def _initialize(self): self._initialize_db() self.pairingsRepo = AssociationRepository(self.dao, self.graded_activity) self.review_repo = WorkRepositoryLoaderFactory.make( course=environment.CONFIG.course, activity=self.review_activity, rest_timeout=5)
def setUp(self): dao = SqliteDAO() self.session = dao.session # self.student_ids = [i for i in range(0,5)] self.create_new_and_preexisting_students() self.unit = unit_factory() self.activity = self.unit.initial_work self.activity_id = self.activity.id self.obj = AssociationRepository(dao, self.activity)
def _initialize(self, unit): self.data = [] self.unit = unit # The activity whose id is used to store review pairings for the whole SKAA self.activity_for_review_pairings = self.unit.discussion_review self.components = [ c for c in self.unit.components if isinstance(c, DiscussionGroup) ] self.studentRepo = StudentRepository(environment.CONFIG.course) self.studentRepo.download() self._initialize_db() self.assignRepo = AssociationRepository( self.dao, self.activity_for_review_pairings)
def _initialize(self, unit): self.data = [] self.unit = unit # The activity whose id is used to store review pairings for the whole SKAA self.activity_for_review_pairings = self.unit.initial_work self.components = [ c for c in self.unit.components if isinstance(c, SkaaReviewGroup) ] self._initialize_db() self.assignRepo = AssociationRepository( self.dao, self.activity_for_review_pairings)
def _initialize(self): """ Handle instantiating and loading repositories :return: """ self.workRepo = WorkRepositoryLoaderFactory.make( course=environment.CONFIG.course, activity=self.activity, rest_timeout=self.wait) self.assignment = environment.CONFIG.course.get_assignment( self.activity.id) self.subRepo = AssignmentSubmissionRepository(self.assignment) # shove the activity onto a sub repo so it will resemble # a quizrepo for the grader self.subRepo.activity = self.activity # Filter previously graded self.subRepo.data = [ s for s in self.subRepo.data if s.workflow_state != 'complete' ] self.workRepo.data = self.workRepo.data[ self.workRepo.data.workflow_state != 'complete'].copy(deep=True) self.workRepo.data.reset_index(inplace=True) # We will need the association repo if the activity can be # blocked or graded by another student self.association_repo = None if isinstance(self.activity, BlockableActivity): dao = SqliteDAO() self.association_repo = AssociationRepository(dao, self.activity)
def _initialize( self ): """Creates and populates all relevant repositories and db access points""" self.studentRepo = StudentRepository( self.course ) self.studentRepo.download() self._initialize_db() self.associationRepo = AssociationRepository( self.dao, self.activity_for_review_pairings) self.display_manager = DisplayManager(self.activity)
class ReviewBased(IGradingMethod, StoreMixin, DaoMixin): def __init__(self, graded_activity: Activity, review_activity: Activity, review_columns: list, pct_of_score=1, **kwargs): """ :param graded_activity: Activity whose grade depends on review :param review_activity: Activity where the reviewer gave scores :param review_columns: Columns in the review activity to use """ self.pct_of_score = pct_of_score self.graded_activity = graded_activity self.activity = graded_activity self.review_columns = review_columns self.review_activity = review_activity # todo make this a param or variable... self.valmap = { 'strongly agree': 1, 'agree': 0.9, 'disagree': 0.5, 'strongly disagree': 0.1 } self.handle_kwargs(**kwargs) self._initialize() def _initialize(self): self._initialize_db() self.pairingsRepo = AssociationRepository(self.dao, self.graded_activity) self.review_repo = WorkRepositoryLoaderFactory.make( course=environment.CONFIG.course, activity=self.review_activity, rest_timeout=5) def grade(self, student_id): # todo assume only one column for now col = self.review_columns[0] ra = self.pairingsRepo.get_by_author(student_id) reviewer_work = self.review_repo.get_student_work(ra.assessor_id) v = reviewer_work[col] #.value # reformat so don't blow up if i use different caps v = v.strip().lower() return self.valmap.get(v)
def _initialize(self): """ Handle instantiating and loading repositories :return: """ self.workRepo = WorkRepositoryLoaderFactory.make( course=environment.CONFIG.course, activity=self.activity, rest_timeout=self.wait) try: self.quiz = environment.CONFIG.course.get_quiz( self.activity.quiz_id) except AttributeError: # todo dev hope this doesn't cause problems! self.quiz = environment.CONFIG.course.get_quiz(self.activity.id) self.subRepo = QuizSubmissionRepository(self.quiz) # If this is a quiz type assignment, we need to get the quiz submission objects # not the regular submission object so we can use them for uploading self.qsubs = [s for s in self.quiz.get_submissions()] # Filter previously graded self.subRepo.data = [ s for s in self.subRepo.data if s.workflow_state != 'complete' ] self.workRepo.data = self.workRepo.data[ self.workRepo.data.workflow_state != 'complete'].copy(deep=True) self.workRepo.data.reset_index(inplace=True) # We will need the association repo if the activity can be # blocked or graded by another student self.association_repo = None if isinstance(self.activity, BlockableActivity): dao = SqliteDAO() self.association_repo = AssociationRepository(dao, self.activity)
class TestAssociationRepository( TestingBase ): def setUp(self): dao = SqliteDAO() self.session = dao.session # self.student_ids = [i for i in range(0,5)] self.create_new_and_preexisting_students() self.unit = unit_factory() self.activity = self.unit.initial_work self.activity_id = self.activity.id self.obj = AssociationRepository(dao, self.activity) def test__make_associations_single_submissions( self ): # Students only submit once # id case assoc = self.obj._make_associations(self.student_ids) self.assertEqual(len(self.students), len(assoc) , "single submission; ids") # obj case assoc = self.obj._make_associations(self.students) self.assertEqual(len(self.students), len(assoc) , "single submission; objects" ) def test__make_associations_3_submissions( self ): # Students only submit once # id case self.student_ids = [i for i in range(0,3)] assoc = self.obj._make_associations(self.student_ids) self.assertEqual(3, len(assoc) , "single submission; ids") # obj case self.students = [student_factory() for i in range(0,3)] assoc = self.obj._make_associations(self.students) self.assertEqual(3, len(assoc) , "single submission; objects" ) def test__make_associations_double_submissions( self ): # Students only submit twice adjacent s = [] for so in self.students: s.append(so) s.append(so) # obj case assoc = self.obj._make_associations(s) for a, b in assoc: self.assertNotEqual(a, b, "self-unit multi submission; objects" ) def test__make_associations_double_submissions_ids( self ): s = [] for so in self.student_ids: s.append(so) s.append(so) # obj case assoc = self.obj._make_associations(s) for a, b in assoc: self.assertNotEqual(a, b, "self-unit multi submission; objects" ) def test_assign_reviewer_raises_when_all_submitters_already_assigned( self ): preexisting_pairings = self.create_preexisting_review_pairings(self.activity_id, self.preexisting_students) with self.assertRaises(AllAssigned): self.obj.assign_reviewers(self.preexisting_students) def test_assign_reviewer_raises_when_only_one_submitter( self ): with self.assertRaises(NoAvailablePartner): self.obj.assign_reviewers(self.preexisting_students[:1])
class SkaaOverviewRepository(DaoMixin): """ Holds consolidated information about statuses etc for Skaa assignments Other classes like dashboard.skaaDashboard are in charge of displaying the information """ def __init__(self, unit=None): self.unit = unit self.studentRepo = StudentRepository(environment.CONFIG.course) self.studentRepo.download() if unit is not None: # Load and display counts self.load(unit) def _initialize(self, unit): self.data = [] self.unit = unit # The activity whose id is used to store review pairings for the whole SKAA self.activity_for_review_pairings = self.unit.initial_work self.components = [ c for c in self.unit.components if isinstance(c, SkaaReviewGroup) ] self._initialize_db() self.assignRepo = AssociationRepository( self.dao, self.activity_for_review_pairings) def load(self, unit): """ Main called method which initializes and loads data Often will have to be called later than initialization so that we can have the object existing and then specify which unit to load. :param unit: :return: """ self._initialize(unit) for sid, obj in self.studentRepo.data.items(): d = { 'student': obj.name, 'canvas_id': sid, 'csun_id': obj.sis_user_id } for c in self.components: if len(self.assignRepo.get_associations()) > 0: try: # get the record where the student is the reviwer a = self.assignRepo.get_by_reviewer(sid) # get the name of the student being assessed d['reviewing'] = self.studentRepo.get_student_name( a.assessee_id) d['reviewing_id'] = a.assessee_id # get the record where the student is the author b = self.assignRepo.get_by_author(sid) # get the name d['reviewed_by'] = self.studentRepo.get_student_name( b.assessor_id) d['reviewed_by_id'] = b.assessor_id except AttributeError: pass self.add_invites(d, c, sid) self.add_reviews(d, c, sid) self.data.append(d) self.data = pd.DataFrame(self.data) def add_invites(self, data_dict, component, student_id): invite_fields = { Review: 'invited_to_review', MetaReview: 'invited_to_metareview', DiscussionReview: 'invited_to_discussion_review' } invite_fieldname = invite_fields.get(type(component)) if invite_fieldname is not None: inv = InvitationStatusRepository(self.dao, component) data_dict[invite_fieldname] = pd.to_datetime( inv.received_at(student_id)) def add_reviews(self, data_dict, component, student_id): # Note: can't do in similar way to invitations since invited to metareview and received ca feedback # use different activities. The invitation is for the upcoming one which provides feedback # on the previous one # set to none so won't overwrite on next time through fb_fieldname = None if isinstance(component, InitialWork): # we can't use the review object because feedback on the review # comes from the metareview fb_fieldname = 'received_feedback_on_essay' if isinstance(component, Review): fb_fieldname = 'received_feedback_on_review' if isinstance(component, DiscussionForum): fb_fieldname = 'received_discussion_feedback' if fb_fieldname is not None: fr = FeedbackStatusRepository(self.dao, component) data_dict[fb_fieldname] = pd.to_datetime( fr.received_at(student_id)) @property def essay(self): """ Return students who have done initial work and been assigned a reviewer :return: DataFrame """ return self.data[~self.data.reviewing.isnull()] @property def no_essay(self): """ Students who have not submitted the initial work :return: DataFrame """ return self.data[self.data.reviewing.isnull()] @property def reviewed(self): """ Returns the subset of students who have turned in the initial work whose reviewer has turned in the review :return: DataFrame """ # Students whose reviewer has and has not turned in review return self.essay[~self.essay.received_feedback_on_essay.isnull()] @property def non_reviewed(self): """ Returns the subset of students who have turned in the initial work whose reviewer has NOT turned in the review :return: DataFrame """ return self.essay[ self.essay.received_feedback_on_essay.isnull() ]\ # .drop( [ 'reviewing' ], axis=1 ) @property def metareviewed(self): """ Returns the subset of students who have turned in the initial work whose author has turned in the metareview :return: DataFrame """ return self.essay[~self.essay.received_feedback_on_review.isnull()] @property def non_metareviewed(self): """ Returns the subset of students who have turned in the initial work whose author has turned in the metareview :return: DataFrame """ return self.essay[self.essay.received_feedback_on_review.isnull()]
class DiscussionOverviewRepository(DaoMixin): """ Holds information about the discussion and discussion review for a unit Other classes like dashboard.discussionDashboard are in charge of displaying the information """ def __init__(self, unit=None): """ Initializes and loads all data or waits to have load called :return: """ self.unit = unit self.studentRepo = StudentRepository(environment.CONFIG.course) self.studentRepo.download() if unit is not None: # Load and display counts self.load(unit) def _initialize(self, unit): self.data = [] self.unit = unit # The activity whose id is used to store review pairings for the whole SKAA self.activity_for_review_pairings = self.unit.discussion_review self.components = [ c for c in self.unit.components if isinstance(c, DiscussionGroup) ] self.studentRepo = StudentRepository(environment.CONFIG.course) self.studentRepo.download() self._initialize_db() self.assignRepo = AssociationRepository( self.dao, self.activity_for_review_pairings) def load(self, unit): self._initialize(unit) for sid, obj in self.studentRepo.data.items(): d = { 'student': obj.name, 'canvas_id': sid, 'csun_id': obj.sis_user_id } for c in self.components: if len(self.assignRepo.get_associations()) > 0: try: # get the record where the student is the reviwer a = self.assignRepo.get_by_reviewer(sid) # get the name of the student being assessed d['reviewing'] = self.studentRepo.get_student_name( a.assessee_id) d['reviewing_id'] = a.assessee_id # get the record where the student is the author b = self.assignRepo.get_by_author(sid) # get the name d['reviewed_by'] = self.studentRepo.get_student_name( b.assessor_id) d['reviewed_by_id'] = b.assessor_id except AttributeError: pass self.add_invites(d, c, sid) self.add_reviews(d, c, sid) self.data.append(d) self.data = pd.DataFrame(self.data) def add_invites(self, data_dict, component, student_id): invite_fields = {DiscussionReview: 'invited_to_discussion_review'} invite_fieldname = invite_fields.get(type(component)) if invite_fieldname is not None: inv = InvitationStatusRepository(self.dao, component) data_dict[invite_fieldname] = pd.to_datetime( inv.received_at(student_id)) def add_reviews(self, data_dict, component, student_id): # Note: can't do in similar way to invitations since invited to metareview and received ca feedback # use different activities. The invitation is for the upcoming one which provides feedback # on the previous one # set to none so won't overwrite on next time through fb_fieldname = None if isinstance(component, DiscussionForum): fb_fieldname = 'received_discussion_feedback' if fb_fieldname is not None: fr = FeedbackStatusRepository(self.dao, component) data_dict[fb_fieldname] = pd.to_datetime( fr.received_at(student_id)) @property def posters(self): """ Students who have posted and been assigned reviewers todo Consider whether should be using the assignment of reviewers or a status object :return: DataFrame """ return self.data[~self.data.reviewing.isnull()] @property def non_posters(self): """ Students who have not posted and thus not been assigned a reviewer :return: DataFrame """ return self.data[self.data.reviewing.isnull()] @property def reviewed(self): """ Students whose reviewer has turned in the review :return: DataFrame """ return self.posters[~self.posters.received_discussion_feedback.isnull( )] @property def non_reviewed(self): """ Students whose reviewer has NOT turned in the review :return: DataFrame """ return self.posters[self.posters.received_discussion_feedback.isnull()] def add_invites(self, data_dict, component, student_id): invite_fields = {DiscussionReview: 'invited_to_discussion_review'} invite_fieldname = invite_fields.get(type(component)) if invite_fieldname is not None: inv = InvitationStatusRepository(self.dao, component) data_dict[invite_fieldname] = pd.to_datetime( inv.received_at(student_id)) def add_reviews(self, data_dict, component, student_id): # Note: can't do in similar way to invitations since invited to metareview and received ca feedback # use different activities. The invitation is for the upcoming one which provides feedback # on the previous one # set to none so won't overwrite on next time through fb_fieldname = None # todo this probably should be changed to discussion forum everywhere if isinstance(component, DiscussionReview): fb_fieldname = 'received_discussion_feedback' if fb_fieldname is not None: fr = FeedbackStatusRepository(self.dao, component) data_dict[fb_fieldname] = pd.to_datetime( fr.received_at(student_id))