def test_get_valid_info():
    info_rows = cur.execute("SELECT * FROM PersonalInfo").fetchall()
    info_row = sample(info_rows, 1)[0]
    student_data = personal_info.get(info_row["matno"])
    student_data["level"] *= [1,-1][student_data["grad_status"]]
    for prop_data, prop_row in zip(info_keys, row_keys):
        if prop_data:
            assert student_data[prop_data] == info_row[prop_row]
Exemple #2
0
def test_symlink_table_to_personal_info():
    for year in range(start, stop + 1):
        session = load_session(year)
        for student in session.SymLink.query.all():
            # Check that symlink DB entry matches Master DB
            assert utils.get_DB(student.mat_no)[:4] == student.database[:4]
            # Check that actual DB entry points back to symlink DB
            assert personal_info.get(
                student.mat_no)["database"][:4] == str(year)
Exemple #3
0
def process_personal_info(mat_no):
    some_personal_info = personal_info.get(mat_no)
    some_personal_info["mode_of_entry_text"] = [
        "PUTME", "DE(200)", "DE(300)"
    ][some_personal_info["mode_of_entry"] - 1]
    if some_personal_info["sex"] == 'F':
        some_personal_info['surname'] += " (Miss)"
    [
        some_personal_info.update({key: ''}) for key in some_personal_info
        if some_personal_info[key] is None
    ]
    return some_personal_info
Exemple #4
0
def test_personal_info_to_symlink_table():
    for student in Master.query.all():
        db_name = student.database
        if not start <= int(db_name[:4]) <= stop:
            continue
        student_info = personal_info.get(student.mat_no)
        # While we're here assert session admitted matches db_name
        # Also ensures the master entry maps to session db
        assert db_name[:4] == str(student_info["session_admitted"])
        if student_info["is_symlink"]:
            new_session = load_session(student_info["database"])
            # Confirm mat no in Symlink table of new_session
            assert new_session.SymLink.query.filter_by(
                mat_no=student.mat_no).first().database == db_name
Exemple #5
0
def get_carryovers(mat_no, level=None, next_level=False):
    """
    Returns a dictionary of the carryover courses for a student for each semester
    :param level: Courses up to but not including this level which are not passed
    :param next_level: Courses up to and including level which are not passed
    """
    level = level or get_level(mat_no)
    first_sem, second_sem = set(), set()
    for course in get_courses(mat_no)[:ltoi(level) + next_level]:
        first_sem |= set(course[0])
        second_sem |= set(course[1])

    person_options = csv_fn(personal_info.get(mat_no)["option"])
    for pair in person_options:
        group, choice = spc_fn(pair, s_int)
        option = course_details.get_options(group)
        idx = option["semester"] - 1
        [first_sem, second_sem][idx] -= set(option["members"])
        [first_sem, second_sem][idx] |= {choice}

    res_stmt = result_statement.get(mat_no)
    results, categories = res_stmt["results"], res_stmt["categories"]
    res_first_sem, res_second_sem = [], []
    if results:
        res_first_sem = reduce(add, [
            result["first_sem"] for idx, result in enumerate(results)
            if not (categories[idx] in "CD" and 200 <= result["level"] <= 400)
        ])
        res_second_sem = reduce(add, [
            result["second_sem"] for idx, result in enumerate(results)
            if not (categories[idx] in "CD" and 200 <= result["level"] <= 400)
        ])
    first_sem -= set([
        record[0] for record in res_first_sem if record[4] not in ("F", "ABS")
    ])
    second_sem -= set([
        record[0] for record in res_second_sem if record[4] not in ("F", "ABS")
    ])

    carryovers = {"first_sem": [], "second_sem": []}
    courses = [("first_sem", course)
               for course in first_sem] + [("second_sem", course)
                                           for course in second_sem]
    for sem, failed_course in courses:
        course = course_details.get(failed_course)
        carryovers[sem].append(
            [failed_course, course["credit"], course["level"]])
    return carryovers
Exemple #6
0
def get_courses(mat_no=None, mode_of_entry=None, session=None, lpad=True):
    "Returns student/session courses list for all levels from sessional DB"
    session = load_session(session or get_DB(mat_no))
    mode_of_entry = mode_of_entry or personal_info.get(mat_no)["mode_of_entry"]
    Courses, CoursesSchema = session.Courses, session.CoursesSchema

    courses = CoursesSchema().dump(
        Courses.query.filter_by(mode_of_entry=mode_of_entry).first())
    level_courses = [
        courses["level{}".format(lvl)].split(" ")
        for lvl in range(mode_of_entry * 100, 600, 100)
    ]
    level_courses = [[csv_fn(x[0]), csv_fn(x[1])] for x in level_courses]
    if lpad:
        return [[[], []] for x in range(mode_of_entry - 1)] + level_courses
    return level_courses
Exemple #7
0
def test_results_table():
    for student in Master.query.all():
        mat_no = student.mat_no
        if not start <= int(student.database[:4]) <= stop:
            continue
        print(mat_no)  # for debugging on failure
        session = load_session(student.database)
        table_blanks = (0, 0)  # for tracking blanks within tables
        # TODO use new col on table to update to verify value is correct
        for level in range(100, 900, 100):
            result_lvl = eval("session.Result{}".format(level))
            result = result_lvl.query.filter_by(mat_no=mat_no).first()
            if result:
                # Assert level for results not higher than present level
                assert personal_info.get(mat_no)["level"] >= min(
                    500, result.level)
                assert table_blanks != (1, 0
                                        )  # assert no blank above this table
                table_blanks = (table_blanks[1], 1)
                expected_TCP = 0  # For verifying Total Credits Passed
                for prop in dir(result):
                    if re.match("[A-Z][A-Z][A-Z][0-9][0-9][0-9]",
                                prop) and result.__getattribute__(prop):
                        score, grade = result.__getattribute__(prop).split(",")
                        # Ensure score matches grade
                        assert utils.compute_grade(int(score),
                                                   student.database) == grade
                        if grade not in ("F", "ABS"):
                            expected_TCP += course_details.get(
                                prop)["course_credit"]
                if result.carryovers:
                    for course, score, grade in [
                            x.split() for x in result.carryovers.split(",")
                    ]:
                        # Assert course isn't from a higher level
                        assert result.level >= course_details.get(
                            course)["course_level"]
                        # Ensure score matches grade
                        assert utils.compute_grade(int(score),
                                                   student.database) == grade
                        if grade not in ("F", "ABS"):
                            expected_TCP += course_details.get(
                                course)["course_credit"]
                assert expected_TCP == result.tcp
            elif table_blanks[1]:
                table_blanks = (table_blanks[1], 0)  # Met a blank
Exemple #8
0
def update_gpa_credits(mat_no, grade, previous_grade, course_credit,
                       course_level):
    gpa_credits = utils.gpa_credits_poll(mat_no)[:-1]
    index = utils.ltoi(course_level)
    level_gpa = gpa_credits[index][0] if gpa_credits[index][0] else 0
    level_credits_passed = gpa_credits[index][1] if gpa_credits[index][1] else 0

    if grade != previous_grade:
        creds = utils.get_credits(mat_no, lpad=True)
        level_credits = creds[index]
        grading_point_rule = utils.get_grading_point(utils.get_DB(mat_no))
        grading_point = grading_point_rule[grade]
        grading_point_old = grading_point_rule[
            previous_grade] if previous_grade else 0

        diff = grading_point - grading_point_old
        level_gpa = level_gpa + ((course_credit * diff) / level_credits)

        sign_multiplier = diff // abs(diff) if diff != 0 else 0
        level_credits_passed += course_credit * sign_multiplier

    gpa_credits[index] = (round(level_gpa, 4), level_credits_passed)
    cgpa = 0
    mode_of_entry = personal_info.get(mat_no)['mode_of_entry']
    weights = utils.get_level_weightings(mode_of_entry)

    for idx in range(len(weights)):
        cgpa += weights[idx] * gpa_credits[idx][0] if gpa_credits[
            idx] and gpa_credits[idx][0] else 0

    gpa_record = {'mat_no': mat_no, 'cgpa': round(cgpa, 4)}
    for key, idx in [('level{}00'.format(lev + 1), lev) for lev in range(5)]:
        gpa_record.update({
            key:
            ','.join(list(map(str, gpa_credits[idx])))
            if gpa_credits[idx][0] else None
        })

    session = utils.load_session(utils.get_DB(mat_no))
    gpa_record = session.GPACreditsSchema().load(gpa_record)
    db_session = session.GPACreditsSchema().Meta.sqla_session
    db_session.add(gpa_record)
    db_session.commit()
    db_session.close()
    return 'Success'
Exemple #9
0
def get_credits(mat_no=None, mode_of_entry=None, session=None, lpad=False):
    "Returns a list of total credits for each level"
    if mat_no:
        session = get_DB(mat_no)
        mode_of_entry = mode_of_entry or personal_info.get(
            mat_no)["mode_of_entry"]
    session = load_session(session)
    Credits, CreditsSchema = session.Credits, session.CreditsSchema

    credits = CreditsSchema().dump(
        Credits.query.filter_by(mode_of_entry=mode_of_entry).first())
    level_credits = [
        credits["level{}".format(lvl)]
        for lvl in range(mode_of_entry * 100, 600, 100)
    ]
    if lpad:
        return [0] * (mode_of_entry - 1) + level_credits
    return level_credits
Exemple #10
0
def rule_1_4():
    bad_mat_1 = set()
    bad_mat_2 = set()
    for session in range(start, stop):
        sess = utils.load_session(session)
        mats = [x.mat_no for x in sess.PersonalInfo.query.all()]
        for mat_no in mats:
            person = personal_info.get(mat_no)
            mode_of_entry = person["mode_of_entry"]
            results = result_statement.get(mat_no)["results"]
            for result in results:
                for record in result["first_sem"] + result["second_sem"]:
                    rec_crs_lvl = crs_lvl[mode_of_entry][record[0]]
                    if rec_crs_lvl // 100 < mode_of_entry:
                        bad_mat_1.add(mat_no)
                    if rec_crs_lvl > result["level"]:
                        bad_mat_2.add(mat_no)

    print("Rule 1 defaulters\n", bad_mat_1)
    print("Rule 4 defaulters\n", bad_mat_2)
Exemple #11
0
def get_students_details(students, entry_session):
    students_details_dict = dict.fromkeys(students)
    for db_name in students:
        for mat_no in students[db_name]:
            bio = personal_info.get(mat_no)
            name = bio['othernames'] + ' ' + bio['surname']
            name += ' (Miss)' if bio['sex'] == 'F' else ''

            *gpa_credits, cgpa = gpa_credits_poll(mat_no)
            details = {
                'mat_no': mat_no,
                'name': name,
                'gpas': list(zip(*gpa_credits))[0],
                'cgpa': float(cgpa)
            }
            if students_details_dict.get(db_name):
                students_details_dict[db_name].append(details)
            else:
                students_details_dict[db_name] = [details]

    ordinary_students = []
    spillover_students = []
    for db_name in students_details_dict:
        details = students_details_dict[db_name]
        if int(db_name[:4]) >= entry_session and details:
            ordinary_students.extend(details)
        elif details:
            spillover_students.extend(details)
    ordinary_students_details = sorted(ordinary_students,
                                       key=lambda x: x['cgpa'],
                                       reverse=True)
    spillover_students_details = sorted(spillover_students,
                                        key=lambda x: x['cgpa'],
                                        reverse=True)

    students_details = ordinary_students_details + spillover_students_details

    return students_details
Exemple #12
0
def _get_single_results_stats(mat_no, level, acad_session):
    info = personal_info.get(mat_no)
    name = info['surname'] + ' ' + info['othernames']
    reg_courses = course_reg_for_session(mat_no, acad_session)
    reg_course_codes = reg_courses.get('courses', [])
    tcr = reg_courses.get('tcr', 0)
    res, _ = res_poll_for_session(acad_session, mat_no=mat_no)
    tce, carryovers_dict, remark = 0, {}, ''

    if res:
        carryovers = res.pop('carryovers')
        carryovers_list = [] if not carryovers else carryovers.split(',')
        for course_dets in carryovers_list:
            code, _, _ = course_dets.split(' ')
            carryovers_dict[code] = True

    for course_code in reg_course_codes:
        if res.get(course_code) not in [
                None, '-1,ABS'
        ] or carryovers_dict.get(course_code) not in [None, '-1,ABS']:
            tce += course_details.get(course_code)['credit']

    return [mat_no, name, tcr, tce, remark], 200
Exemple #13
0
def compute_gpa(mat_no, lpad=True):
    entry_session = get_DB(mat_no)
    grade_weight = get_grading_point(entry_session)
    mode_of_entry = personal_info.get(mat_no)["mode_of_entry"]
    level_credits = get_credits(mode_of_entry=mode_of_entry,
                                session=entry_session,
                                lpad=True)
    gpas = [0] * 5
    courses = course_details.get_all(inactive=True,
                                     mode_of_entry=mode_of_entry)
    course_levels = {x["code"]: x["level"] for x in courses}
    res_stmt = result_statement.get(mat_no)
    categories = res_stmt["categories"]
    for idx, result in enumerate(res_stmt["results"]):
        probated, more = categories[idx] == "C", categories[idx + 1:]
        if not (probated and 200 <= result["level"] <= 400 and more):
            for record in (result["first_sem"] + result["second_sem"]):
                (course, credit, grade) = (record[0], record[2], record[4])
                product = grade_weight[grade] * credit
                lvl_idx = ltoi(course_levels[course])
                gpas[lvl_idx] += (product / level_credits[lvl_idx])
    if lpad:
        return gpas[mode_of_entry - 1:]
    return gpas
Exemple #14
0
def test_course_reg_table():
    for student in Master.query.all():
        mat_no = student.mat_no
        if not start <= int(student.database[:4]) <= stop:
            continue
        print(mat_no)  # for debugging on failure
        session = load_session(student.database)
        table_blanks = (0, 0)  # for tracking blanks within tables
        # TODO use new col on table to update to verify value is correct
        for level in range(100, 900, 100):
            course_reg_lvl = eval("session.CourseReg{}".format(level))
            course_reg = course_reg_lvl.query.filter_by(mat_no=mat_no).first()
            if course_reg:
                # Assert level for registration not higher than present level
                assert personal_info.get(mat_no)["level"] >= min(
                    500, course_reg.level)
                assert table_blanks != (1, 0
                                        )  # assert no blank above this table
                table_blanks = (table_blanks[1], 1)
                expected_TCR = 0  # For verifying Total Credits Registered
                for prop in dir(course_reg):
                    if re.match("[A-Z][A-Z][A-Z][0-9][0-9][0-9]", prop):
                        if int(course_reg.__getattribute__(prop)):
                            expected_TCR += course_details.get(
                                prop)["course_credit"]
                for course in course_reg.carryovers.split(","):
                    # TODO Remove re check after carryover100 set to NULL
                    if re.match("[A-Z][A-Z][A-Z][0-9][0-9][0-9]", course):
                        # Assert course isn't from a higher level
                        assert course_reg.level >= course_details.get(
                            course)["course_level"]
                        expected_TCR += course_details.get(
                            course)["course_credit"]
                assert expected_TCR == course_reg.tcr
            elif table_blanks[1]:
                table_blanks = (table_blanks[1], 0)  # Met a blank
Exemple #15
0
def get(mat_no, sep_carryovers=False):
    person = personal_info.get(mat_no)
    results = utils.result_poll(mat_no)
    student_details = {
        "dept": utils.get_dept(),
        "results": [],
        "credits": [],
        "categories": [],
        "unregd": [],
        "carryovers": [],
        "failed_courses": []
    }
    keys = [
        "date_of_birth", "mode_of_entry", "session_admitted", "surname",
        "grad_status", "session_grad", "is_symlink", "othernames", "sex"
    ]
    student_details.update({key: person[key] for key in keys})
    for idx, result in enumerate(results):
        if result:
            # Handle unregistered results courses
            unregd_result = {
                "first_sem": [],
                "second_sem": [],
                'level': result["level"],
                'session': result["session"],
                "table": itol(idx)
            }
            unregd_arr = [spc_fn(x) for x in csv_fn(result["unregd"])]
            unregd_formatted = format_results(unregd_arr)
            unregd_result["first_sem"] += unregd_formatted[0][0]
            unregd_result["second_sem"] += unregd_formatted[0][1]
            student_details["unregd"].append(unregd_result)
            # Handle registered results courses
            result_arr, lvl_result, co_result = [], deepcopy(
                unregd_result), deepcopy(unregd_result)
            for code in [
                    key for key in result
                    if match("[A-Z][A-Z][A-Z][0-9][0-9][0-9]", key)
                    and result[key]
            ]:
                result_arr.append((code, *csv_fn(result[code])))
            co_arr = [spc_fn(x) for x in csv_fn(result["carryovers"])]
            failed_crs = [[], []]
            if sep_carryovers:
                co_formatted = format_results(co_arr)
                co_result["first_sem"] += co_formatted[0][0]
                co_result["second_sem"] += co_formatted[0][1]
                failed_crs = co_formatted[4]
                student_details["carryovers"].append(co_result)
                formatted = format_results(result_arr, *co_formatted[2:4])
            else:
                formatted = format_results(result_arr + co_arr)
            lvl_result["first_sem"] += formatted[0][0]
            lvl_result["second_sem"] += formatted[0][1]
            student_details["results"].append(lvl_result)
            [failed_crs[ind].extend(formatted[4][ind]) for ind in range(2)]

            student_details["credits"].append(
                (formatted[1], formatted[2], formatted[3]))
            student_details["failed_courses"].append(failed_crs)
            student_details["categories"].append(result["category"])
    return student_details
Exemple #16
0
def test_get_invaid_info():
    mat_no = "INV"+str(time())[-7:]
    assert personal_info.get(mat_no) == None