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]
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)
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
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
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
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
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
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'
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
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)
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
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
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
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
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
def test_get_invaid_info(): mat_no = "INV"+str(time())[-7:] assert personal_info.get(mat_no) == None