def exercisemetrics(): if "chapter" not in request.vars: logger.error( "It Appears exercisemetrics was called without any request vars") session.flash = "Cannot call exercisemetrics directly" redirect(URL("dashboard", "index")) chapter = request.vars["chapter"] base_course = (db(db.courses.course_name == auth.user.course_name).select().first().base_course) chapter = (db(((db.chapters.course_id == auth.user.course_name) | (db.chapters.course_id == base_course)) & (db.chapters.chapter_label == chapter)).select().first()) if not chapter: logger.error("Error -- No Chapter information for {} and {}".format( auth.user.course_name, request.vars["chapter"])) session.flash = "No Chapter information for {} and {}".format( auth.user.course_name, request.vars["chapter"]) redirect(URL("dashboard", "index")) # TODO: When all old style courses were gone this can be just a base course data_analyzer = DashboardDataAnalyzer(auth.user.course_id, chapter) data_analyzer.load_exercise_metrics(request.vars["id"]) problem_metrics = data_analyzer.problem_metrics prob_id = request.vars["id"] answers = [] attempt_histogram = [] logger.debug(problem_metrics.problems) try: problem_metric = problem_metrics.problems[prob_id] except KeyError: session.flash = f"Not enough data for {prob_id}" redirect(request.env.http_referer) response_frequency = problem_metric.aggregate_responses for username, user_responses in six.iteritems( problem_metric.user_responses): responses = user_responses.responses[:4] responses += [""] * (4 - len(responses)) answers.append({ "user": user_responses.user, "username": user_responses.username, "answers": responses, }) for attempts, count in six.iteritems( problem_metric.user_number_responses()): attempt_histogram.append({"attempts": attempts, "frequency": count}) return dict( course=get_course_row(db.courses.ALL), answers=answers, response_frequency=response_frequency, attempt_histogram=attempt_histogram, exercise_label=problem_metric.problem_text, )
def studentreport(): data_analyzer = DashboardDataAnalyzer(auth.user.course_id) # todo: Test to see if vars.id is there -- if its not then load_user_metrics will crash # todo: This seems redundant with assignments/index -- should use this one... id should be text sid data_analyzer.load_user_metrics(request.vars.id) data_analyzer.load_assignment_metrics(request.vars.id) chapters = [] for chapter_label, chapter in six.iteritems( data_analyzer.chapter_progress.chapters): chapters.append({ "label": chapter.chapter_label, "status": chapter.status_text(), "subchapters": chapter.get_sub_chapter_progress(), }) activity = data_analyzer.formatted_activity.activities logger.debug("GRADES = %s", data_analyzer.grades) return dict( course=get_course_row(db.courses.ALL), user=data_analyzer.user, chapters=chapters, activity=activity, assignments=data_analyzer.grades, )
def exercisemetrics(): if 'chapter' not in request.vars: logger.error( "It Appears exercisemetrics was called without any request vars") session.flash = "Cannot call exercisemetrics directly" redirect(URL('dashboard', 'index')) chapter = request.get_vars['chapter'] chapter = db((db.chapters.course_id == auth.user.course_name) & (db.chapters.chapter_label == chapter)).select().first() data_analyzer = DashboardDataAnalyzer(auth.user.course_id, chapter) data_analyzer.load_exercise_metrics(request.get_vars["id"]) problem_metrics = data_analyzer.problem_metrics prob_id = request.get_vars["id"] answers = [] attempt_histogram = [] logger.debug(problem_metrics.problems) problem_metric = problem_metrics.problems[prob_id] response_frequency = problem_metric.aggregate_responses for username, user_responses in six.iteritems( problem_metric.user_responses): responses = user_responses.responses[:4] responses += [''] * (4 - len(responses)) answers.append({ "user": user_responses.user, "username": user_responses.username, "answers": responses }) for attempts, count in six.iteritems( problem_metric.user_number_responses()): attempt_histogram.append({"attempts": attempts, "frequency": count}) return dict(course=get_course_row(db.courses.ALL), answers=answers, response_frequency=response_frequency, attempt_histogram=attempt_histogram, exercise_label=problem_metric.problem_text)
def index(): if not auth.user: session.flash = "Please Login" return redirect(URL('default', 'index')) if 'sid' not in request.vars: #return redirect(URL('assignments','index') + '?sid=%s' % (auth.user.username)) request.vars.sid = auth.user.username student = db(db.auth_user.username == request.vars.sid).select( db.auth_user.id, db.auth_user.username, db.auth_user.first_name, db.auth_user.last_name, db.auth_user.email, ).first() if not student: return redirect(URL('assignments', 'index')) if auth.user.course_name in ['thinkcspy', 'pythonds', 'JavaReview', 'webfundamentals', 'StudentCSP', 'apcsareview']: session.flash = "{} is not a graded course".format(auth.user.course_name) return redirect(URL('default', 'user')) data_analyzer = DashboardDataAnalyzer(auth.user.course_id) data_analyzer.load_user_metrics(request.vars.sid) data_analyzer.load_assignment_metrics(request.vars.sid, studentView=True) chapters = [] for chapter_label, chapter in six.iteritems(data_analyzer.chapter_progress.chapters): chapters.append({ "label": chapter.chapter_label, "status": chapter.status_text(), "subchapters": chapter.get_sub_chapter_progress() }) activity = data_analyzer.formatted_activity.activities (now, now_local, message1, message2, practice_graded, spacing, interleaving, practice_completion_count, remaining_days, max_days, max_questions, day_points, question_points, presentable_flashcards, available_flashcards_num, practiced_today_count, questions_to_complete_day, practice_today_left, points_received, total_possible_points, flashcard_creation_method) = _get_practice_data(auth.user, float(session.timezoneoffset) if 'timezoneoffset' in session else 0) return dict(student=student, course_id=auth.user.course_id, course_name=auth.user.course_name, user=data_analyzer.user, chapters=chapters, activity=activity, assignments=data_analyzer.grades, practice_message1=message1, practice_message2=message2, practice_graded=practice_graded, flashcard_count=available_flashcards_num, # The number of days the student has completed their practice. practice_completion_count=practice_completion_count, remaining_days=remaining_days, max_questions=max_questions, max_days=max_days, total_today_count=min(practice_today_left + practiced_today_count, questions_to_complete_day), # The number of times remaining to practice today to get the completion point. practice_today_left=practice_today_left, # The number of times this user has submitted their practice from the beginning of today (12:00 am) # till now. practiced_today_count=practiced_today_count, points_received=points_received, total_possible_points=total_possible_points, spacing=spacing, interleaving=interleaving )
def index(): selected_chapter = None questions = [] sections = [] if settings.academy_mode and not settings.docker_institution_mode: if auth.user.course_name in [ "thinkcspy", "pythonds", "JavaReview", "JavaReview-RU", "StudentCSP", "csawesome", "fopp", ]: session.flash = "Student Progress page not available for {}".format( auth.user.course_name) return redirect(URL("admin", "admin")) course = db(db.courses.id == auth.user.course_id).select().first() assignments = db(db.assignments.course == course.id).select( db.assignments.ALL, orderby=db.assignments.name) chapters = db(db.chapters.course_id == course.base_course).select( orderby=db.chapters.chapter_num) logger.debug("getting chapters for {}".format(auth.user.course_name)) chapget = ChapterGet(chapters) for chapter in chapters.find( lambda chapter: chapter.chapter_label == request.vars["chapter"]): selected_chapter = chapter if selected_chapter is None: selected_chapter = chapters.first() logger.debug("making an analyzer") data_analyzer = DashboardDataAnalyzer(auth.user.course_id, selected_chapter) logger.debug("loading chapter metrics for course {}".format( auth.user.course_name)) data_analyzer.load_chapter_metrics(selected_chapter) logger.debug("loading problem metrics") problem_metrics = data_analyzer.problem_metrics logger.debug("loading progress_metrics metrics") progress_metrics = data_analyzer.progress_metrics logger.debug("starting problem_id, metric loop") for problem_id, metric in six.iteritems(problem_metrics.problems): stats = metric.user_response_stats() if data_analyzer.questions[problem_id]: chtmp = data_analyzer.questions[problem_id].chapter schtmp = data_analyzer.questions[problem_id].subchapter entry = { "id": problem_id, "text": metric.problem_text, "chapter": chtmp, "chapter_title": chapget.ChapterName(chtmp), "chapter_number": chapget.ChapterNumber(chtmp), "sub_chapter": schtmp, "sub_chapter_number": chapget.SectionNumber(chtmp, schtmp), "sub_chapter_title": chapget.SectionName(chtmp, schtmp), "correct": stats[2], "correct_mult_attempt": stats[3], "incomplete": stats[1], "not_attempted": stats[0], "attemptedBy": stats[1] + stats[2] + stats[3], } else: entry = { "id": problem_id, "text": metric.problem_text, "chapter": "unknown", "sub_chapter": "unknown", "sub_chapter_number": 0, "sub_chapter_title": "unknown", "chapter_title": "unknown", "correct": stats[2], "correct_mult_attempt": stats[3], "incomplete": stats[1], "not_attempted": stats[0], "attemptedBy": stats[1] + stats[2] + stats[3], } questions.append(entry) logger.debug("ADDING QUESTION %s ", entry["chapter"]) logger.debug("getting questions") try: questions = sorted(questions, key=itemgetter("chapter", "sub_chapter_number")) except Exception as e: logger.error("FAILED TO SORT {} Error detail: {}".format(questions, e)) logger.debug("starting sub_chapter loop") for sub_chapter, metric in six.iteritems(progress_metrics.sub_chapters): sections.append({ "id": metric.sub_chapter_label, "text": metric.sub_chapter_text, "name": metric.sub_chapter_name, "number": chapget.SectionNumber(selected_chapter.chapter_label, metric.sub_chapter_label), # FIX: Using selected_chapter here might be a kludge # Better if metric contained chapter numbers associated with sub_chapters "readPercent": metric.get_completed_percent(), "startedPercent": metric.get_started_percent(), "unreadPercent": metric.get_not_started_percent(), }) read_data = [] correct_data = [] missed_data = [] recent_data = [] recent_correct = [] recent_missed = [] daily_data = [] daily_correct = [] daily_missed = [] logger.debug("getting user activity") user_activity = data_analyzer.user_activity # All of this can be replaced by a nice crosstab call # See UserActivityCrosstab.ipynb for user, activity in six.iteritems(user_activity.user_activities): read_data.append({ "student": activity. name, # causes username instead of full name to show in the report, but it works ?? how to display the name but use the username on click?? "sid": activity.username, "count": activity.get_page_views(), }) correct_data.append({ "student": activity. name, # causes username instead of full name to show in the report, but it works ?? how to display the name but use the username on click?? "sid": activity.username, "count": activity.get_correct_count(), }) missed_data.append({ "student": activity. name, # causes username instead of full name to show in the report, but it works ?? how to display the name but use the username on click?? "sid": activity.username, "count": activity.get_missed_count(), }) recent_data.append({ "student": activity.name, "sid": activity.username, "count": activity.get_recent_page_views(), }) recent_correct.append({ "student": activity.name, "sid": activity.username, "count": activity.get_recent_correct(), }) recent_missed.append({ "student": activity.name, "sid": activity.username, "count": activity.get_recent_missed(), }) daily_data.append({ "student": activity.name, "sid": activity.username, "count": activity.get_daily_page_views(), }) daily_correct.append({ "student": activity.name, "sid": activity.username, "count": activity.get_daily_correct(), }) daily_missed.append({ "student": activity.name, "sid": activity.username, "count": activity.get_daily_missed(), }) logger.debug("finishing") # TODO -- this is not right and explains why all are the same!! studentactivity = [ { "data": read_data, "name": "Sections Read" }, { "data": correct_data, "name": "Exercises Correct" }, { "data": missed_data, "name": "Exercises Missed" }, ] recentactivity = [ { "data": recent_data, "name": "Sections Read" }, { "data": recent_correct, "name": "Exercises Correct" }, { "data": recent_missed, "name": "Exercises Missed" }, ] dailyactivity = [ { "data": daily_data, "name": "Sections Read" }, { "data": daily_correct, "name": "Exercises Correct" }, { "data": daily_missed, "name": "Exercises Missed" }, ] return dict( assignments=assignments, course=course, questions=questions, sections=sections, chapters=chapters, selected_chapter=selected_chapter, studentactivity=studentactivity, recentactivity=recentactivity, dailyactivity=dailyactivity, )
def studentreport(): data_analyzer = DashboardDataAnalyzer(auth.user.course_id) for_dashboard = verifyInstructorStatus(auth.user.course_id, auth.user.id) if "id" in request.vars and for_dashboard: sid = request.vars.id else: sid = auth.user.username response.view = "assignments/index.html" data_analyzer.load_user_metrics(sid) data_analyzer.load_assignment_metrics(sid, not for_dashboard) chapters = [] for chapter_label, chapter in six.iteritems( data_analyzer.chapter_progress.chapters): chapters.append({ "label": chapter.chapter_label, "status": chapter.status_text(), "subchapters": chapter.get_sub_chapter_progress(), }) activity = data_analyzer.formatted_activity logger.debug("GRADES = %s", data_analyzer.grades) pd_dict = dict() if response.view == "assignments/index.html": ( pd_dict["now"], pd_dict["now_local"], pd_dict["practice_message1"], pd_dict["practice_message2"], pd_dict["practice_graded"], pd_dict["spacing"], pd_dict["interleaving"], pd_dict["practice_completion_count"], pd_dict["remaining_days"], pd_dict["max_days"], pd_dict["max_questions"], pd_dict["day_points"], pd_dict["question_points"], pd_dict["presentable_flashcards"], pd_dict["flashcard_count"], pd_dict["practiced_today_count"], pd_dict["questions_to_complete_day"], pd_dict["practice_today_left"], pd_dict["points_received"], pd_dict["total_possible_points"], pd_dict["flashcard_creation_method"], ) = _get_practice_data( auth.user, float(session.timezoneoffset) if "timezoneoffset" in session else 0, db, ) pd_dict["total_today_count"] = min( pd_dict["practice_today_left"] + pd_dict["practiced_today_count"], pd_dict["questions_to_complete_day"], ) if request.vars.action == "dlcsv": mtbl = pd.read_sql_query( """ select * from useinfo where sid = %(sid)s and course_id = %(course)s """, settings.database_uri, params={ "sid": sid, "course": auth.user.course_name }, ) response.headers["Content-Type"] = "application/vnd.ms-excel" response.headers[ "Content-Disposition"] = "attachment; filename=data_for_{}.csv".format( sid) session.flash = f"Downloading to data_for_{sid}.csv" return mtbl.to_csv(na_rep=" ") if request.vars.action == "dlcode": mtbl = pd.read_sql_query( """ select * from code where sid = %(sid)s and course_id = %(course)s """, settings.database_uri, params={ "sid": auth.user.username, "course": auth.user.course_id }, ) response.headers["Content-Type"] = "application/vnd.ms-excel" response.headers[ "Content-Disposition"] = "attachment; filename=code_for_{}.csv".format( sid) session.flash = f"Downloading to code_for_{sid}.csv" return mtbl.to_csv(na_rep=" ") return dict( course=get_course_row(db.courses.ALL), user=data_analyzer.user, chapters=chapters, activity=activity, assignments=data_analyzer.grades, **pd_dict, )
def studentreport(): data_analyzer = DashboardDataAnalyzer(auth.user.course_id) for_dashboard = verifyInstructorStatus(auth.user.course_id, auth.user.id) if "id" in request.vars and for_dashboard: sid = request.vars.id else: sid = auth.user.username response.view = "assignments/index.html" data_analyzer.load_user_metrics(sid) data_analyzer.load_assignment_metrics(sid) chapters = [] for chapter_label, chapter in six.iteritems( data_analyzer.chapter_progress.chapters): chapters.append({ "label": chapter.chapter_label, "status": chapter.status_text(), "subchapters": chapter.get_sub_chapter_progress(), }) activity = data_analyzer.formatted_activity logger.debug("GRADES = %s", data_analyzer.grades) pd = dict() if response.view == "assignments/index.html": ( pd["now"], pd["now_local"], pd["practice_message1"], pd["practice_message2"], pd["practice_graded"], pd["spacing"], pd["interleaving"], pd["practice_completion_count"], pd["remaining_days"], pd["max_days"], pd["max_questions"], pd["day_points"], pd["question_points"], pd["presentable_flashcards"], pd["flashcard_count"], pd["practiced_today_count"], pd["questions_to_complete_day"], pd["practice_today_left"], pd["points_received"], pd["total_possible_points"], pd["flashcard_creation_method"], ) = _get_practice_data( auth.user, float(session.timezoneoffset) if "timezoneoffset" in session else 0, db, ) pd["total_today_count"] = min( pd["practice_today_left"] + pd["practiced_today_count"], pd["questions_to_complete_day"], ) return dict(course=get_course_row(db.courses.ALL), user=data_analyzer.user, chapters=chapters, activity=activity, assignments=data_analyzer.grades, **pd)
def index(): selected_chapter = None questions = [] sections = [] if settings.academy_mode and not settings.docker_institution_mode: if auth.user.course_name in ['thinkcspy','pythonds','JavaReview','JavaReview-RU', 'StudentCSP']: session.flash = "Student Progress page not available for {}".format(auth.user.course_name) return redirect(URL('admin','admin')) course = db(db.courses.id == auth.user.course_id).select().first() assignments = db(db.assignments.course == course.id).select(db.assignments.ALL, orderby=db.assignments.name) logger.debug("getting chapters for {}".format(auth.user.course_name)) chapters = db(db.chapters.course_id == course.base_course).select() chap_map = {} for chapter in chapters: chap_map[chapter.chapter_label] = chapter.chapter_name for chapter in chapters.find(lambda chapter: chapter.chapter_label==request.vars['chapter']): selected_chapter = chapter if selected_chapter is None: selected_chapter = chapters.first() logger.debug("making an analyzer") data_analyzer = DashboardDataAnalyzer(auth.user.course_id,selected_chapter) logger.debug("loading chapter metrics for course {}".format(auth.user.course_name)) data_analyzer.load_chapter_metrics(selected_chapter) logger.debug("loading problem metrics") problem_metrics = data_analyzer.problem_metrics logger.debug("loading progress_metrics metrics") progress_metrics = data_analyzer.progress_metrics logger.debug("starting problem_id, metric loop") for problem_id, metric in six.iteritems(problem_metrics.problems): stats = metric.user_response_stats() if data_analyzer.questions[problem_id]: chtmp = data_analyzer.questions[problem_id].chapter entry = { "id": problem_id, "text": metric.problem_text, "chapter": chtmp, "chapter_title": chap_map.get(chtmp,chtmp), "sub_chapter": data_analyzer.questions[problem_id].subchapter, "correct": stats[2], "correct_mult_attempt": stats[3], "incomplete": stats[1], "not_attempted": stats[0], "attemptedBy": stats[1] + stats[2] + stats[3] } else: entry = { "id": problem_id, "text": metric.problem_text, "chapter": "unknown", "sub_chapter": "unknown", "chapter_title": "unknown", "correct": stats[2], "correct_mult_attempt": stats[3], "incomplete": stats[1], "not_attempted": stats[0], "attemptedBy": stats[1] + stats[2] + stats[3] } questions.append(entry) logger.debug("ADDING QUESTION %s ", entry["chapter"]) logger.debug("getting questsions") questions = sorted(questions, key=itemgetter("chapter")) logger.debug("starting sub_chapter loop") for sub_chapter, metric in six.iteritems(progress_metrics.sub_chapters): sections.append({ "id": metric.sub_chapter_label, "text": metric.sub_chapter_text, "name": metric.sub_chapter_name, "readPercent": metric.get_completed_percent(), "startedPercent": metric.get_started_percent(), "unreadPercent": metric.get_not_started_percent() }) read_data = [] recent_data = [] logger.debug("getting user activity") user_activity = data_analyzer.user_activity for user, activity in six.iteritems(user_activity.user_activities): read_data.append({ "student":activity.name, # causes username instead of full name to show in the report, but it works ?? how to display the name but use the username on click?? "sid":activity.username, "count":activity.get_page_views() }) recent_data.append({ "student":activity.name, "sid":activity.username, "count":activity.get_recent_page_views() }) logger.debug("finishing") studentactivity = [{ "data":read_data, "name":"Sections Read" },{ "data":read_data, "name":"Exercises Correct" },{ "data":read_data, "name":"Exercises Missed" }] recentactivity = [{ "data":recent_data, "name":"Sections Read" },{ "data":recent_data, "name":"Exercises Correct" },{ "data":recent_data, "name":"Exercises Missed" }] return dict(assignments=assignments, course=course, questions=questions, sections=sections, chapters=chapters, selected_chapter=selected_chapter, studentactivity=studentactivity, recentactivity=recentactivity)