Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

=== Module Description === This file contains classes that describe a survey as well as classes that described different types of questions that can be

=== Module Description ===

This file contains classes that describe a survey as well as classes that described different types of questions that can be asked in a given survey.

from __future__ import annotations from typing import TYPE_CHECKING, Union, Dict, List from criterion import HomogeneousCriterion, InvalidAnswerError if TYPE_CHECKING: from criterion import Criterion from grouper import Grouping from course import Student

class Question: """ An abstract class representing a question used in a survey

=== Public Attributes === id: the id of this question text: the text of this question

=== Representation Invariants === text is not the empty string """

id: int text: str

def __init__(self, id_: int, text: str) -> None: """ Initialize a question with the text """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a string representation of this question that contains both the text of this question and a description of all possible answers to this question.

You can choose the precise format of this string. """ raise NotImplementedError

def validate_answer(self, answer: Answer) -> bool: """ Return True iff is a valid answer to this question. """ raise NotImplementedError

def get_similarity(self, answer1: Answer, answer2: Answer) -> float: """ Return a float between 0.0 and 1.0 indicating how similar two answers are.

=== Precondition === and are both valid answers to this question """ raise NotImplementedError

class MultipleChoiceQuestion: # TODO: make this a child class of another class defined in this file """ A question whose answers can be one of several options

=== Public Attributes === id: the id of this question text: the text of this question

=== Representation Invariants === text is not the empty string """

id: int text: str

def __init__(self, id_: int, text: str, options: List[str]) -> None: """ Initialize a question with the text and id and possible answers .

=== Precondition === No two elements in are the same string contains at least two elements """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a string representation of this question including the text of the question and a description of the possible answers.

You can choose the precise format of this string. """ # TODO: complete the body of this method

def validate_answer(self, answer: Answer) -> bool: """ Return True iff is a valid answer to this question.

An answer is valid if its content is one of the possible answers to this question. """ # TODO: complete the body of this method

def get_similarity(self, answer1: Answer, answer2: Answer) -> float: """ Return 1.0 iff .content and .content are equal and 0.0 otherwise.

=== Precondition === and are both valid answers to this question. """ # TODO: complete the body of this method

class NumericQuestion: # TODO: make this a child class of another class defined in this file """ A question whose answer can be an integer between some minimum and maximum value (inclusive).

=== Public Attributes === id: the id of this question text: the text of this question

=== Representation Invariants === text is not the empty string """

id: int text: str

def __init__(self, id_: int, text: str, min_: int, max_: int) -> None: """ Initialize a question with id and text whose possible answers can be any integer between and (inclusive)

=== Precondition === min_ < max_ """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a string representation of this question including the text of the question and a description of the possible answers.

You can choose the precise format of this string. """ # TODO: complete the body of this method

def validate_answer(self, answer: Answer) -> bool: """ Return True iff the content of is an integer between the minimum and maximum (inclusive) possible answers to this question. """ # TODO: complete the body of this method

def get_similarity(self, answer1: Answer, answer2: Answer) -> float: """ Return the similarity between and over the range of possible answers to this question.

Similarity calculated by:

1. first find the absolute difference between .content and .content. 2. divide the value from step 1 by the difference between the maximimum and minimum possible answers. 3. subtract the value from step 2 from 1.0

Hint: this is the same calculation from the worksheet in lecture!

For example: - Maximum similarity is 1.0 and occurs when == - Minimum similarity is 0.0 and occurs when is the minimum possible answer and is the maximum possible answer (or vice versa).

=== Precondition === and are both valid answers to this question """ # TODO: complete the body of this method

class YesNoQuestion: # TODO: make this a child class of another class defined in this file """ A question whose answer is either yes (represented by True) or no (represented by False).

=== Public Attributes === id: the id of this question text: the text of this question

=== Representation Invariants === text is not the empty string """ id: int text: str

def __init__(self, id_: int, text: str) -> None: """ Initialize a question with the text and id . """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a string representation of this question including the text of the question and a description of the possible answers.

You can choose the precise format of this string. """ # TODO: complete the body of this method

def validate_answer(self, answer: Answer) -> bool: """ Return True iff 's content is a boolean. """ # TODO: complete the body of this method

def get_similarity(self, answer1: Answer, answer2: Answer) -> float: """ Return 1.0 iff .content is equal to .content and return 0.0 otherwise.

=== Precondition === and are both valid answers to this question """ # TODO: complete the body of this method

class CheckboxQuestion: # TODO: make this a child class of another class defined in this file """ A question whose answers can be one or more of several options

=== Public Attributes === id: the id of this question text: the text of this question

=== Representation Invariants === text is not the empty string """

id: int text: str

def __init__(self, id_: int, text: str, options: List[str]) -> None: """ Initialize a question with the text and id and possible answers .

=== Precondition === No two elements in are the same string contains at least two elements """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a string representation of this question including the text of the question and a description of the possible answers.

You can choose the precise format of this string. """ # TODO: complete the body of this method

def validate_answer(self, answer: Answer) -> bool: """ Return True iff is a valid answer to this question.

An answer is valid iff its content is a non-empty list containing unique possible answers to this question. """ # TODO: complete the body of this method

def get_similarity(self, answer1: Answer, answer2: Answer) -> float: """ Return the similarity between and .

Similarity is defined as the ratio between the number of strings that are common to both .content and .content over the total number of unique strings that appear in both .content and .content

For example, if .content == ['a', 'b', 'c'] and .content == ['c', 'b', 'd'], the strings that are common to both are ['c', 'b'] and the unique strings that appear in both are ['a', 'b', 'c', 'd'].

=== Precondition === and are both valid answers to this question """ # TODO: complete the body of this method

class Answer: """ An answer to a question used in a survey

=== Public Attributes === content: an answer to a single question """ content: Union[str, bool, int, List[str]]

def __init__(self, content: Union[str, bool, int, List[Union[str]]]) -> None: """Initialize an answer with content """ # TODO: complete the body of this method

def is_valid(self, question: Question) -> bool: """Return True iff self.content is a valid answer to """ # TODO: complete the body of this method

class Survey: """ A survey containing questions as well as criteria and weights used to evaluate the quality of a group based on their answers to the survey questions.

=== Private Attributes === _questions: a dictionary mapping each question's id to the question itself _criteria: a dictionary mapping a question's id to its associated criterion _weights: a dictionary mapping a question's id to a weight; an integer representing the importance of this criteria. _default_criterion: a criterion to use to evaluate a question if the question does not have an associated criterion in _criteria _default_weight: a weight to use to evaluate a question if the question does not have an associated weight in _weights

=== Representation Invariants === No two questions on this survey have the same id Each key in _questions equals the id attribute of its value Each key in _criteria occurs as a key in _questions Each key in _weights occurs as a key in _questions Each value in _weights is greater than 0 _default_weight > 0 """

_questions: Dict[int, Question] _criteria: Dict[int, Criterion] _weights: Dict[int, int] _default_criterion: Criterion _default_weight: int

def __init__(self, questions: List[Question]) -> None: """ Initialize a new survey that contains every question in . This new survey should use a HomogeneousCriterion as a default criterion and should use 1 as a default weight. """ # TODO: complete the body of this method

def __len__(self) -> int: """ Return the number of questions in this survey """ # TODO: complete the body of this method

def __contains__(self, question: Question) -> bool: """ Return True iff there is a question in this survey with the same id as . """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a string containing the string representation of all questions in this survey

You can choose the precise format of this string. """ # TODO: complete the body of this method

def get_questions(self) -> List[Question]: """ Return a list of all questions in this survey """ # TODO: complete the body of this method

def _get_criterion(self, question: Question) -> Criterion: """ Return the criterion associated with in this survey.

Iff .id does not appear in self._criteria, return the default criterion for this survey instead.

=== Precondition === .id occurs in this survey """ # TODO: complete the body of this method

def _get_weight(self, question: Question) -> int: """ Return the weight associated with in this survey.

Iff .id does not appear in self._weights, return the default weight for this survey instead.

=== Precondition === .id occurs in this survey """ # TODO: complete the body of this method

def set_weight(self, weight: int, question: Question) -> bool: """ Set the weight associated with to and return True.

If .id does not occur in this survey, do not set the and return False instead. """ # TODO: complete the body of this method

def set_criterion(self, criterion: Criterion, question: Question) -> bool: """ Set the criterion associated with to and return True.

If .id does not occur in this survey, do not set the and return False instead. """ # TODO: complete the body of this method

def score_students(self, students: List[Student]) -> float: """ Return a quality score for calculated based on their answers to the questions in this survey, and the associated criterion and weight for each question .

This score is determined using the following algorithm:

1. For each question in , find its associated criterion, weight, and answers to this question. Use the score_answers method for this criterion to calculate a quality score. Multiply this quality score by the associated weight. 2. Find the average of all quality scores from step 1.

If an InvalidAnswerError would be raised by calling this method, or if there are no questions in , this method should return zero.

=== Precondition === All students in have an answer to all questions in this survey """ # TODO: complete the body of this method

def score_grouping(self, grouping: Grouping) -> float: """ Return a score for calculated based on the answers of each student in each group in to the questions in .

If there are no groups in this score is 0.0. Otherwise, this score is determined using the following algorithm:

1. For each group in , get the score for the members of this group calculated based on their answers to the questions in this survey. 2. Return the average of all the scores calculated in step 1.

=== Precondition === All students in the groups in have an answer to all questions in this survey """ # TODO: complete the body of this method

if __name__ == '__main__': import python_ta python_ta.check_all(config={'extra-imports': ['typing', 'criterion', 'course', 'grouper']})

=== Module Description ===

This file contains classes that describe a university course and the students who are enrolled in these courses. """ from __future__ import annotations from typing import TYPE_CHECKING, List, Tuple, Optional if TYPE_CHECKING: from survey import Answer, Survey, Question

def sort_students(lst: List[Student], attribute: str) -> List[Student]: """ Return a shallow copy of sorted by

=== Precondition === is a attribute name for the Student class

>>> s1 = Student(1, 'Misha') >>> s2 = Student(2, 'Diane') >>> s3 = Student(3, 'Mario') >>> sort_students([s1, s3, s2], 'id') == [s1, s2, s3] True >>> sort_students([s1, s2, s3], 'name') == [s2, s3, s1] True """ return sorted(lst, key=lambda s: getattr(s, attribute))

class Student: """ A Student who can be enrolled in a university course.

=== Public Attributes === id: the id of the student name: the name of the student

=== Representation Invariants === name is not the empty string """

id: int name: str

def __init__(self, id_: int, name: str) -> None: """ Initialize a student with name and id """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return the name of this student """ # TODO: complete the body of this method

def has_answer(self, question: Question) -> bool: """ Return True iff this student has an answer for a question with the same id as and that answer is a valid answer for . """ # TODO: complete the body of this method

def set_answer(self, question: Question, answer: Answer) -> None: """ Record this student's answer to the question . """ # TODO: complete the body of this method

def get_answer(self, question: Question) -> Optional[Answer]: """ Return this student's answer to the question . Return None if this student does not have an answer to """ # TODO: complete the body of this method

class Course: """ A University Course

=== Public Attributes === name: the name of the course students: a list of students enrolled in the course

=== Representation Invariants === - No two students in this course have the same id - name is not the empty string """

name: str students: List[Student]

def __init__(self, name: str) -> None: """ Initialize a course with the name of . """ # TODO: complete the body of this method

def enroll_students(self, students: List[Student]) -> None: """ Enroll all students in in this course.

If adding any student would violate a representation invariant, do not add any of the students in to the course. """ # TODO: complete the body of this method

def all_answered(self, survey: Survey) -> bool: """ Return True iff all the students enrolled in this course have a valid answer for every question in . """ # TODO: complete the body of this method

def get_students(self) -> Tuple[Student, ...]: """ Return a tuple of all students enrolled in this course.

The students in this tuple should be in order according to their id from lowest id to highest id.

Hint: the sort_students function might be useful """ # TODO: complete the body of this method

if __name__ == '__main__': import python_ta python_ta.check_all(config={'extra-imports': ['typing', 'survey']})

=== Module Description ===

This file contains classes that describe different types of criteria used to evaluate a group of answers to a survey question. """ from __future__ import annotations from typing import TYPE_CHECKING, List if TYPE_CHECKING: from survey import Question, Answer

class InvalidAnswerError(Exception): """ Error that should be raised when an answer is invalid for a given question. """

class Criterion: """ An abstract class representing a criterion used to evaluate the quality of a group based on the group members' answers for a given question. """

def score_answers(self, question: Question, answers: List[Answer]) -> float: """ Return score between 0.0 and 1.0 indicating the quality of the group of to the question .

Raise InvalidAnswerError if any answer in is not a valid answer to .

Each implementation of this abstract class will measure quality differently. """ raise NotImplementedError

class HomogeneousCriterion: # TODO: make this a child class of another class defined in this file """ A criterion used to evaluate the quality of a group based on the group members' answers for a given question.

This criterion gives a higher score to answers that are more similar. """

def score_answers(self, question: Question, answers: List[Answer]) -> float: """ Return a score between 0.0 and 1.0 indicating how similar the answers in are.

This score is calculated by finding the similarity of every combination of two answers in and taking the average of all of these similarity scores.

If there is only one answer in and it is valid return 1.0 since a single answer is always identical to itself.

Raise InvalidAnswerError if any answer in is not a valid answer to .

=== Precondition === len(answers) > 0 """ # TODO: complete the body of this method

class HeterogeneousCriterion: # TODO: make this a child class of another class defined in this file """ A criterion used to evaluate the quality of a group based on the group members' answers for a given question.

This criterion gives a higher score to answers that are more different. """

def score_answers(self, question: Question, answers: List[Answer]) -> float: """ Return a score between 0.0 and 1.0 indicating how similar the answers in are.

This score is calculated by finding the similarity of every combination of two answers in , finding the average of all of these similarity scores, and then subtracting this average from 1.0

If there is only one answer in and it is valid, return 0.0 since a single answer is never identical to itself.

Raise InvalidAnswerError if any answer in is not a valid answer to .

=== Precondition === len(answers) > 0 """ # TODO: complete the body of this method

class LonelyMemberCriterion: # TODO: make this a child class of another class defined in this file """ A criterion used to measure the quality of a group of students according to the group members' answers to a question. This criterion assumes that a group is of high quality if no member of the group gives a unique answer to a question. """

def score_answers(self, question: Question, answers: List[Answer]) -> float: """ Return score between 0.0 and 1.0 indicating the quality of the group of to the question .

The score returned will be zero iff there are any unique answers in and will be 1.0 otherwise.

An answer is not unique if there is at least one other answer in with identical content.

Raise InvalidAnswerError if any answer in is not a valid answer to .

=== Precondition === len(answers) > 0 """ # TODO: complete the body of this method

if __name__ == '__main__': import python_ta python_ta.check_all(config={'extra-imports': ['typing', 'survey']})

=== Module Description ===

This file contains classes that define different algorithms for grouping students according to chosen criteria and the group members' answers to survey questions. This file also contain a classe that describes a group of students as well as a grouping (a group of groups). """ from __future__ import annotations import random from typing import TYPE_CHECKING, List, Any from course import sort_students if TYPE_CHECKING: from survey import Survey from course import Course, Student

def slice_list(lst: List[Any], n: int) -> List[List[Any]]: """ Return a list containing slices of in order. Each slice is a list of size containing the next elements in .

The last slice may contain fewer than elements in order to make sure that the returned list contains all elements in .

=== Precondition === n <= len(lst)

>>> slice_list([3, 4, 6, 2, 3], 2) == [[3, 4], [6, 2], [3]] True >>> slice_list(['a', 1, 6.0, False], 3) == [['a', 1, 6.0], [False]] True """ # TODO: complete the body of this function

def windows(lst: List[Any], n: int) -> List[List[Any]]: """ Return a list containing windows of in order. Each window is a list of size containing the elements with index i through index i+ in the original list where i is the index of window in the returned list.

=== Precondition === n <= len(lst)

>>> windows([3, 4, 6, 2, 3], 2) == [[3, 4], [4, 6], [6, 2], [2, 3]] True >>> windows(['a', 1, 6.0, False], 3) == [['a', 1, 6.0], [1, 6.0, False]] True """ # TODO: complete the body of this function

class Grouper: """ An abstract class representing a grouper used to create a grouping of students according to their answers to a survey.

=== Public Attributes === group_size: the ideal number of students that should be in each group

=== Representation Invariants === group_size > 1 """

group_size: int

def __init__(self, group_size: int) -> None: """ Initialize a grouper that creates groups of size

=== Precondition === group_size > 1 """ # TODO: complete the body of this method

def make_grouping(self, course: Course, survey: Survey) -> Grouping: """ Return a grouping for all students in using the questions in to create the grouping. """ raise NotImplementedError

class AlphaGrouper(Grouper): """ A grouper that groups students in a given course according to the alphabetical order of their names.

=== Public Attributes === group_size: the ideal number of students that should be in each group

=== Representation Invariants === group_size > 1 """

group_size: int

def make_grouping(self, course: Course, survey: Survey) -> Grouping: """ Return a grouping for all students in .

The first group should contain the students in whose names come first when sorted alphabetically, the second group should contain the next students in that order, etc.

All groups in this grouping should have exactly self.group_size members except for the last group which may have fewer than self.group_size members if that is required to make sure all students in are members of a group.

Hint: the sort_students function might be useful """ # TODO: complete the body of this method

class RandomGrouper(Grouper): """ A grouper used to create a grouping of students by randomly assigning them to groups.

=== Public Attributes === group_size: the ideal number of students that should be in each group

=== Representation Invariants === group_size > 1 """

group_size: int

def make_grouping(self, course: Course, survey: Survey) -> Grouping: """ Return a grouping for all students in .

Students should be assigned to groups randomly.

All groups in this grouping should have exactly self.group_size members except for one group which may have fewer than self.group_size members if that is required to make sure all students in are members of a group. """ # TODO: complete the body of this method

class GreedyGrouper(Grouper): """ A grouper used to create a grouping of students according to their answers to a survey. This grouper uses a greedy algorithm to create groups.

=== Public Attributes === group_size: the ideal number of students that should be in each group

=== Representation Invariants === group_size > 1 """

group_size: int

def make_grouping(self, course: Course, survey: Survey) -> Grouping: """ Return a grouping for all students in .

Starting with a tuple of all students in obtained by calling the .get_students() method, create groups of students using the following algorithm:

1. select the first student in the tuple that hasn't already been put into a group and put this student in a new group. 2. select the student in the tuple that hasn't already been put into a group that, if added to the new group, would increase the group's score the most (or reduce it the least), add that student to the new group. 3. repeat step 2 until there are N students in the new group where N is equal to self.group_size. 4. repeat steps 1-3 until all students have been placed in a group.

In step 2 above, use the .score_students method to determine the score of each group of students.

The final group created may have fewer than N members if that is required to make sure all students in are members of a group. """ # TODO: complete the body of this method

class WindowGrouper(Grouper): """ A grouper used to create a grouping of students according to their answers to a survey. This grouper uses a window search algorithm to create groups.

=== Public Attributes === group_size: the ideal number of students that should be in each group

=== Representation Invariants === group_size > 1 """

group_size: int

def make_grouping(self, course: Course, survey: Survey) -> Grouping: """ Return a grouping for all students in .

Starting with a tuple of all students in obtained by calling the .get_students() method, create groups of students using the following algorithm:

1. Get the windows of the list of students who have not already been put in a group. 2. For each window in order, calculate the current window's score as well as the score of the next window in the list. If the current window's score is greater than or equal to the next window's score, make a group out of the students in current window and start again at step 1. If the current window is the last window, compare it to the first window instead.

In step 2 above, use the .score_students to determine the score of each window (list of students).

In step 1 and 2 above, use the windows function to get the windows of the list of students.

If there are any remaining students who have not been put in a group after repeating steps 1 and 2 above, put the remaining students into a new group. """ # TODO: complete the body of this method

class Group: """ A group of one or more students

=== Private Attributes === _members: a list of unique students in this group

=== Representation Invariants === No two students in _members have the same id """

_members: List[Student]

def __init__(self, members: List[Student]) -> None: """ Initialize a group with members """ # TODO: complete the body of this method

def __len__(self) -> int: """ Return the number of members in this group """ # TODO: complete the body of this method

def __contains__(self, member: Student) -> bool: """ Return True iff this group contains a member with the same id as . """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a string containing the names of all members in this group on a single line.

You can choose the precise format of this string. """ # TODO: complete the body of this method

def get_members(self) -> List[Student]: """ Return a list of members in this group. This list should be a shallow copy of the self._members attribute. """ # TODO: complete the body of this method

class Grouping: """ A collection of groups

=== Private Attributes === _groups: a list of Groups

=== Representation Invariants === No group in _groups contains zero members No student appears in more than one group in _groups """

_groups: List[Group]

def __init__(self) -> None: """ Initialize a Grouping that contains zero groups """ # TODO: complete the body of this method

def __len__(self) -> int: """ Return the number of groups in this grouping """ # TODO: complete the body of this method

def __str__(self) -> str: """ Return a multi-line string that includes the names of all of the members of all of the groups in . Each line should contain the names of members for a single group.

You can choose the precise format of this string. """ # TODO: complete the body of this method

def add_group(self, group: Group) -> bool: """ Add to this grouping and return True.

Iff adding to this grouping would violate a representation invariant don't add it and return False instead. """ # TODO: complete the body of this method

def get_groups(self) -> List[Group]: """ Return a list of all groups in this grouping. This list should be a shallow copy of the self._groups attribute. """ # TODO: complete the body of this method

if __name__ == '__main__': import python_ta python_ta.check_all(config={'extra-imports': ['typing', 'random', 'survey', 'course']})

plz use python and i paste on survey-course-criterion-grouper order and each one has one simple intro atbeginning thx

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Genomes And Databases On The Internet A Practical Guide To Functions And Applications

Authors: Paul Rangel

1st Edition

189848631X, 978-1898486312

More Books

Students also viewed these Databases questions

Question

Distinguish between a renal corpuscle and a renal tubule.

Answered: 1 week ago