def test_course_is_skippable_ok_course(self): course = CatalogCourse() course.title = 'A valid title' course.instructors = [Instructor()] skippable = ScrapeCatalog.course_is_skippable(course) self.assertFalse(skippable)
def test_course_is_skippable_no_professors(self): course = CatalogCourse() course.title = 'A valid title' course.instructors = [None] skippable = ScrapeCatalog.course_is_skippable(course) self.assertTrue(skippable)
def compute_progress(request, list_id, course_list, progress_overrides, progress_assertions): """Utility function for road_progress and progress that computes and returns the progress on the given requirements list.""" try: req = RequirementsList.objects.get(list_id=list_id + REQUIREMENTS_EXT) except ObjectDoesNotExist: return HttpResponseBadRequest( "the requirements list {} does not exist".format(list_id)) # Get Course objects course_objs = [] #required to give generic courses unique id's so muliple can count towards requirement unique_generic_id = 0 for subject_id in course_list: try: course_objs.append( Course.public_courses().get(subject_id=subject_id)) except ObjectDoesNotExist: try: course_objs.append( Course.make_generic(subject_id, unique_generic_id)) unique_generic_id += 1 except ValueError: print( "Warning: course {} does not exist in the catalog".format( subject_id)) # Create a progress object for the requirements list prog = RequirementsProgress(req, list_id) prog.compute(course_objs, progress_overrides, progress_assertions) # to pretty-print, use these keyword arguments to json.dumps: # sort_keys=True, indent=4, separators=(',', ': ') return HttpResponse(json.dumps(prog.to_json_object(True)), content_type="application/json")
def make_row(requirement): """Returns HTML for displaying the given requirement in a row.""" html = u"<div class=\"course-list\"><div class=\"course-list-inner\">" if requirement.requirements.exists(): reqs = requirement.requirements.all() else: reqs = [requirement] for req in reqs: html += "<div class=\"course-tile-outer\">" desc = req.short_description() tile_classes = "card hoverable white-text course-tile" dept = desc[:desc.find(".")] if "." in desc else "none" if dept not in KNOWN_DEPARTMENTS: dept = "none" html += "<div class=\"{} course-{}\">".format(tile_classes, dept) try: course = Course.public_courses().get(subject_id=desc) html += "<span class=\"course-id\">" + desc + "</span>" html += "<br/>" html += "<span class=\"course-title\">" + course.title + "</span>" except ObjectDoesNotExist: html += "<span class=\"course-id\">" + desc + "</span>" html += "</div></div>" html += "</div></div>" return html
def handle(self, *args, **options): course = Course( **{ 'campus': u'Sydney', 'career': u'Undergraduate', 'code': u'BIOM9028', 'description_markup': u'<div>Fundamentals of producing a medical image, image collection techniques, image reconstruction algorithms. Detailed examination of the four main areas of medical imaging: Nuclear Medicine and Positron Emission Tomography, Diagnostic Radiology, Magnetic Resonance and image analysis methods. Clinical application of each area.</div>', 'eftsl': u'0.12500', 'faculty': u'Faculty of Engineering', 'gened': u'N', 'name': u'Medical Imaging', 'school': u'Graduate School of Biomedical Engineering', 'uoc': u'6', } ) course.save(update_fields=['accessed']) # klass = Class(class_nbr=12123, activity='Lecture', course=course) # klass.save() # self.stdout.write('Course has id: %d' % course.id)
def override_requirement(self, manual_progress): """ Sets the progress fulfillment variables based on a manual progress value, which is expressed in either units or subjects depending on the requirement's threshold. """ self.is_fulfilled = manual_progress >= self.threshold.get_actual_cutoff( ) subjects = 0 units = 0 satisfied_courses = set() if self.threshold.criterion == CRITERION_UNITS: units = manual_progress subjects = manual_progress / DEFAULT_UNIT_COUNT else: units = manual_progress * DEFAULT_UNIT_COUNT subjects = manual_progress subject_progress = ceiling_thresh( subjects, self.threshold.cutoff_for_criterion(CRITERION_SUBJECTS)) unit_progress = ceiling_thresh( units, self.threshold.cutoff_for_criterion(CRITERION_UNITS)) #fill with dummy courses random_ids = random.sample( range(1000, max(10000, subject_progress.progress + 1000)), subject_progress.progress) for rand_id in random_ids: dummy_course = Course( id=self.list_path + "_" + str(rand_id), subject_id="gen_course_" + self.list_path + "_" + str(rand_id), title="Generated Course " + self.list_path + " " + str(rand_id)) satisfied_courses.add(dummy_course) progress_units = CRITERION_SUBJECTS if self.threshold is None else self.threshold.criterion self.subject_fulfillment = subject_progress self.subject_progress = subject_progress.progress self.subject_max = subject_progress.max self.unit_fulfillment = unit_progress self.unit_progress = unit_progress.progress self.unit_max = unit_progress.max progress = unit_progress if self.threshold is not None and self.threshold.criterion == CRITERION_UNITS else subject_progress self.progress = progress.progress self.progress_max = progress.max self.percent_fulfilled = progress.get_percent() self.fraction_fulfilled = progress.get_fraction() self.raw_fraction_fulfilled = progress.get_raw_fraction(progress_units) self.satisfied_courses = list(satisfied_courses)
def view_corrections(request): """Creates the page that displays all current catalog corrections.""" diffs = [] for correction in CatalogCorrection.objects.order_by("subject_id").values(): subject_id = correction["subject_id"] changed_course = Course.public_courses().filter(subject_id=subject_id).values().first() diff = {} if changed_course: for field in changed_course: if field in CORRECTION_DIFF_EXCLUDE or "ptr" in field: continue if field not in correction: continue if correction[field]: diff[field] = (changed_course[field], correction[field]) else: for field in correction: if field in CORRECTION_DIFF_EXCLUDE or "ptr" in field: continue if not correction[field]: continue diff[field] = (None, correction[field]) diffs.append({"subject_id": subject_id, "id": correction["id"], "diff": diff}) return render(request, "courseupdater/corrections.html", {"diffs": diffs})
def initdb(): from catalog.models import User, Category, Course user1 = User(name='Seunghun Lee', email='*****@*****.**') db.session.add(user1) db.session.commit() categories = [ 'Programming Language', 'Math', 'Physics', 'Deep Learning', ] # Add Categories for category_name in categories: new_category = Category(name=category_name, user_id=1) db.session.add(new_category) db.session.flush() course = Course(name='Programming Foundations with Python', level='Beginner', url='https://www.udacity.com/course/programming-foundations-with-python--ud036', image_url='https://s3-us-west-1.amazonaws.com/udacity-content/course/images/ud036-0619766.jpg', description='Learn Object-Oriented Programming', provider='Udacity', category_id=1, user_id=1) db.session.add(course) course = Course(name='Linear Algebra Refresher Course', level='Intermediate', url='https://www.udacity.com/course/linear-algebra-refresher-course--ud953', image_url='https://s3-us-west-1.amazonaws.com/udacity-content/course/images/ud953-d95e68e.jpg', description='A Brief Refresher (with Python!)', provider='Udacity', category_id=2, user_id=1) db.session.add(course) course = Course(name='Intro to Physics', level='Beginner', url='https://www.udacity.com/course/intro-to-physics--ph100', image_url='https://lh6.ggpht.com/9xDuLEr_4CuXcBZVbMQPagaUOvdUOH_T8V4I9Nm9XvDogvR4_yudI60v5_0tWedKx2LInYQiV6KOGqNPXuo=s0#w=436&h=268', description='Landmarks in Physics', provider='Udacity', category_id=3, user_id=1) db.session.add(course) course = Course(name='Deep Learning', level='Advanced', url='https://www.udacity.com/course/deep-learning--ud730', image_url='https://s3-us-west-1.amazonaws.com/udacity-content/course/images/ud730-b3af4bf.jpg', description='Take machine learning to the next level', provider='Udacity', category_id=4, user_id=1) db.session.add(course) db.session.commit() for course in db.session.query(Course).all(): print course.id, course.name, 'in', course.category.name
def test_course_is_skippable_please_register(self): course = CatalogCourse() course.title = 'Please register via AMST0101' course.instructors = [Instructor()] self.assertTrue(ScrapeCatalog.course_is_skippable(course)) course_strange_case = CatalogCourse() course_strange_case.title = 'Please RegisteR via AMST0101' course_strange_case.instructors = [Instructor()] self.assertTrue(ScrapeCatalog.course_is_skippable(course_strange_case)) course_for = CatalogCourse() course_for.title = 'Please register for AMST0101' course_for.instructors = [Instructor()] self.assertTrue(ScrapeCatalog.course_is_skippable(course_for)) course_for_strange_case = CatalogCourse() course_for_strange_case.title = 'Please RegisteR for AMST0101' course_for_strange_case.instructors = [Instructor()] self.assertTrue(ScrapeCatalog.course_is_skippable(course_for_strange_case))
def parse_course(course_dict): course = Course() course.code = course_dict.get('title') course.href = course_dict.get('link') course.description = course_dict.get('description') course.title = course_dict.get('catalog:title') course.type = parse_course_info(course_dict.get('catalog:genustype'), Type) course.location = parse_course_info(course_dict.get('catalog:location'), Location) course.term = parse_course_info(course_dict.get('catalog:term'), Term) course.schedule = parse_schedule(course_dict.get('catalog:schedule')) course.crn = parse_crn(course_dict.get('catalog:property')) # 'catalog:instructor' is a list if there are multiple instructors # and a dict if there is only one instructor instructors_list_or_dict = course_dict.get('catalog:instructor') if type(instructors_list_or_dict) is list: for instructor_dict in instructors_list_or_dict: course.instructors.append(parse_course_info(instructor_dict, Instructor)) else: course.instructors.append(parse_course_info(instructors_list_or_dict, Instructor)) for topic in course_dict.get('catalog:topic'): topic_type = topic.get('@type').split('/')[-1] if topic_type == 'subject': course.subject = parse_course_info(topic, Subject) elif topic_type == 'department': course.department = parse_course_info(topic, Department) elif topic_type == 'requirement': course.requirements.append(parse_course_info(topic, Requirement)) elif topic_type == 'level': course.level = parse_course_info(topic, Level) return course
def test_course_is_skippable_please_register(self): course = CatalogCourse() course.title = 'Please register via AMST0101' course.instructors = [Instructor()] self.assertTrue(ScrapeCatalog.course_is_skippable(course)) course_strange_case = CatalogCourse() course_strange_case.title = 'Please RegisteR via AMST0101' course_strange_case.instructors = [Instructor()] self.assertTrue(ScrapeCatalog.course_is_skippable(course_strange_case)) course_for = CatalogCourse() course_for.title = 'Please register for AMST0101' course_for.instructors = [Instructor()] self.assertTrue(ScrapeCatalog.course_is_skippable(course_for)) course_for_strange_case = CatalogCourse() course_for_strange_case.title = 'Please RegisteR for AMST0101' course_for_strange_case.instructors = [Instructor()] self.assertTrue( ScrapeCatalog.course_is_skippable(course_for_strange_case))
def compute(self, courses, progress_overrides): """Computes and stores the status of the requirements statement using the given list of Course objects.""" # Compute status of children and then self, adapted from mobile apps' computeRequirementsStatus method satisfied_courses = set() if self.list_path in progress_overrides: manual_progress = progress_overrides[self.list_path] else: manual_progress = 0 if self.statement.requirement is not None: #it is a basic requirement if self.statement.is_plain_string and not manual_progress == 0 and self.threshold is not None: #use manual progress is_fulfilled = manual_progress >= self.threshold.get_actual_cutoff( ) subjects = 0 units = 0 if self.threshold.criterion == CRITERION_UNITS: units = manual_progress subjects = manual_progress / DEFAULT_UNIT_COUNT else: units = manual_progress * DEFAULT_UNIT_COUNT subjects = manual_progress subject_progress = ceiling_thresh( subjects, self.threshold.cutoff_for_criterion(CRITERION_SUBJECTS)) unit_progress = ceiling_thresh( units, self.threshold.cutoff_for_criterion(CRITERION_UNITS)) #fill with dummy courses random_ids = random.sample( range(1000, max(10000, subject_progress.progress + 1000)), subject_progress.progress) for rand_id in random_ids: dummy_course = Course( id=self.list_path + "_" + str(rand_id), subject_id="gen_course_" + self.list_path + "_" + str(rand_id), title="Generated Course " + self.list_path + " " + str(rand_id)) satisfied_courses.add(dummy_course) else: #Example: requirement CI-H, we want to show how many have been fulfilled whole_courses, half_courses = self.courses_satisfying_req( courses) satisfied_courses = whole_courses + half_courses if not self.threshold is None: #A specific number of courses is required subject_progress = ceiling_thresh( len(whole_courses) + len(half_courses) // 2, self.threshold.cutoff_for_criterion( CRITERION_SUBJECTS)) unit_progress = ceiling_thresh( total_units(satisfied_courses), self.threshold.cutoff_for_criterion(CRITERION_UNITS)) is_fulfilled = self.threshold.is_satisfied_by( subject_progress.progress, unit_progress.progress) else: #Only one is needed progress_subjects = min(len(satisfied_courses), 1) is_fulfilled = len(satisfied_courses) > 0 subject_progress = ceiling_thresh(progress_subjects, 1) if len(satisfied_courses) > 0: unit_progress = ceiling_thresh( list(satisfied_courses)[0].total_units, DEFAULT_UNIT_COUNT) else: unit_progress = ceiling_thresh(0, DEFAULT_UNIT_COUNT) progress = unit_progress if self.threshold is not None and self.threshold.criterion == CRITERION_UNITS else subject_progress if len(self.children) > 0: #It's a compound requirement num_reqs_satisfied = 0 satisfied_by_category = [] satisfied_courses = set() num_courses_satisfied = 0 for req_progress in self.children: req_progress.compute(courses, progress_overrides) req_satisfied_courses = req_progress.satisfied_courses if req_progress.is_fulfilled and len( req_progress.satisfied_courses) > 0: num_reqs_satisfied += 1 satisfied_courses.update(req_satisfied_courses) satisfied_by_category.append(list(req_satisfied_courses)) # For thresholded ANY statements, children that are ALL statements # count as a single satisfied course. ANY children count for # all of their satisfied courses. if req_progress.statement.connection_type == CONNECTION_TYPE_ALL and req_progress.children: num_courses_satisfied += req_progress.is_fulfilled and len( req_progress.satisfied_courses) > 0 else: num_courses_satisfied += len(req_satisfied_courses) satisfied_by_category = [ sat for prog, sat in sorted( zip(self.children, satisfied_by_category), key=lambda z: z[0].fraction_fulfilled, reverse=True) ] sorted_progresses = sorted(self.children, key=lambda req: req.fraction_fulfilled, reverse=True) if self.threshold is None and self.distinct_threshold is None: is_fulfilled = (num_reqs_satisfied > 0) if self.statement.connection_type == CONNECTION_TYPE_ANY: #Simple "any" statement if len(sorted_progresses) > 0: subject_progress = sorted_progresses[ 0].subject_fulfillment unit_progress = sorted_progresses[0].unit_fulfillment else: subject_progress = Progress(0, 0) unit_progress = Progress(0, 0) else: #"All" statement, will be finalized later subject_progress = sum_progresses(sorted_progresses, CRITERION_SUBJECTS, None) unit_progress = sum_progresses(sorted_progresses, CRITERION_UNITS, None) else: if self.distinct_threshold is not None: #Clip the progresses to the ones which the user is closest to completing num_progresses_to_count = min( self.distinct_threshold.get_actual_cutoff(), len(sorted_progresses)) sorted_progresses = sorted_progresses[: num_progresses_to_count] satisfied_by_category = satisfied_by_category[: num_progresses_to_count] satisfied_courses = set() num_courses_satisfied = 0 for i, child in zip(range(num_progresses_to_count), self.children): satisfied_courses.update(satisfied_by_category[i]) if child.statement.connection_type == CONNECTION_TYPE_ALL: num_courses_satisfied += ( child.is_fulfilled and len(child.satisfied_courses) > 0) else: num_courses_satisfied += len( satisfied_by_category[i]) if self.threshold is None and self.distinct_threshold is not None: #Required number of statements if self.distinct_threshold == THRESHOLD_TYPE_GTE or self.distinct_threshold.type == THRESHOLD_TYPE_GT: is_fulfilled = num_reqs_satisfied >= self.distinct_threshold.get_actual_cutoff( ) else: is_fulfilled = True subject_progress = sum_progresses(sorted_progresses, CRITERION_SUBJECTS, lambda x: max(x, 1)) unit_progress = sum_progresses( sorted_progresses, CRITERION_UNITS, lambda x: (x, DEFAULT_UNIT_COUNT)[x == 0]) elif self.threshold is not None: #Required number of subjects or units subject_progress = Progress( num_courses_satisfied, self.threshold.cutoff_for_criterion( CRITERION_SUBJECTS)) unit_progress = Progress( total_units(satisfied_courses), self.threshold.cutoff_for_criterion(CRITERION_UNITS)) if self.distinct_threshold is not None and ( self.distinct_threshold.type == THRESHOLD_TYPE_GT or self.distinct_threshold.type == THRESHOLD_TYPE_GTE): is_fulfilled = self.threshold.is_satisfied_by( subject_progress.progress, unit_progress.progress ) and num_reqs_satisfied >= self.distinct_threshold.get_actual_cutoff( ) if num_reqs_satisfied < self.distinct_threshold.get_actual_cutoff( ): (subject_progress, unit_progress) = force_unfill_progresses( satisfied_by_category, self.distinct_threshold, self.threshold) else: is_fulfilled = self.threshold.is_satisfied_by( subject_progress.progress, unit_progress.progress) if self.statement.connection_type == CONNECTION_TYPE_ALL: #"All" statement - make above progresses more stringent is_fulfilled = is_fulfilled and (num_reqs_satisfied == len( self.children)) if subject_progress.progress == subject_progress.max and len( self.children) > num_reqs_satisfied: subject_progress.max += len( self.children) - num_reqs_satisfied unit_progress.max += ( len(self.children) - num_reqs_satisfied) * DEFAULT_UNIT_COUNT #Polish up values subject_progress = ceiling_thresh(subject_progress.progress, subject_progress.max) unit_progress = ceiling_thresh(unit_progress.progress, unit_progress.max) progress = unit_progress if self.threshold is not None and self.threshold.criterion == CRITERION_UNITS else subject_progress self.is_fulfilled = is_fulfilled self.subject_fulfillment = subject_progress self.subject_progress = subject_progress.progress self.subject_max = subject_progress.max self.unit_fulfillment = unit_progress self.unit_progress = unit_progress.progress self.unit_max = unit_progress.max self.progress = progress.progress self.progress_max = progress.max self.percent_fulfilled = progress.get_percent() self.fraction_fulfilled = progress.get_fraction() self.satisfied_courses = list(satisfied_courses)