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_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)
Пример #4
0
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 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)
Пример #6
0
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
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
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})
Пример #10
0
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))
Пример #12
0
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))
Пример #14
0
    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)