def gen_course_quizzes_report(ready_course, save_to_s3=False): ### 1- Compose the report file name and instantiate the report writer object dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s-Course-Quizzes.csv" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, course_prefix+'_'+course_suffix) s3_filepath = "%s/%s/reports/course_quizzes/%s" % (course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) ### 2- Write the Report Title rw.write(content = ["Course Quiz Summaries for %s (%s %d)" % (ready_course.title, ready_course.term.title(), ready_course.year)], nl = 1) ### 3- Write problem set reports rw.write(content = ["Problem sets"], nl = 1) problemsets = ProblemSet.objects.getByCourse(course=ready_course).order_by('section__index', 'index') for q in problemsets: WriteQuizSummaryReportContent(q, rw, full=False) ### 4- Write video reports rw.write(content = ["Videos"], nl = 1) videos = Video.objects.getByCourse(course=ready_course).order_by('section__index', 'index') for q in videos: WriteQuizSummaryReportContent(q, rw, full=False) ### 5- Proceed to write out and return report_content = rw.writeout() return {'name': report_name, 'content': report_content, 'path': s3_filepath}
def gen_course_quizzes_report(ready_course, save_to_s3=False): dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] s3_filepath = "%s/%s/reports/course_quizzes/daily/%02d_%02d_%02d__%02d_%02d_%02d-%s-Course-Quizzes.csv" % ( course_prefix, course_suffix, dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, course_prefix + '_' + course_suffix) rw = C2GReportWriter(ready_course, save_to_s3, s3_filepath) # Title rw.write(content=[ "Course Quizzes for %s (%s %d)" % (ready_course.title, ready_course.term.title(), ready_course.year) ], nl=1) # Get a list of Quizzes (Problem sets and videos with exercises) quizzes = [] problemsets = ProblemSet.objects.getByCourse(course=ready_course) for ps in problemsets: quizzes.append(ps) videos = Video.objects.getByCourse(course=ready_course) for vd in videos: quizzes.append(vd) quizzes = sorted(quizzes, key=lambda k: k.live_datetime, reverse=True) for q in quizzes: WriteQuizDataToReport(q, rw) rw.close()
def gen_assessment_student_scores_report(ready_course, save_to_s3=False): ### 1- Compose the report file name and instantiate the report writer object dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] report_name = "%02d_%02d_%02d__%02d_%02d_%02d.csv" % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second) s3_filepath = "%s/%s/reports/assessment_student_scores/%s" % ( course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) ### 2- Write the Report Title rw.write(content=[ "Student Scores for %s (%s %d)" % (ready_course.title, ready_course.term.title(), ready_course.year) ], nl=1) rw.write( content=["All student scores shown are with all penalties included"]) ### 3- Write survey report WriteAssessmentStudentScoresReportContent(ready_course, rw, full=False) ### 4- Proceed to write out and return report_content = rw.writeout() return { 'name': report_name, 'content': report_content, 'path': s3_filepath }
def gen_quiz_summary_report(ready_course, ready_quiz, save_to_s3=False): ### 1- Create the S3 file name and report writer object dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] is_video = isinstance(ready_quiz, Video) is_summative = (not is_video) and (ready_quiz.assessment_type == 'assessive') report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s.csv" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ready_quiz.slug) if is_video: s3_filepath = "%s/%s/reports/videos_summary/%s" % (course_prefix, course_suffix, report_name) else: s3_filepath = "%s/%s/reports/problemsets_summary/%s" % (course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) ### 2- Get the quiz data quiz_data = get_quiz_data(ready_quiz) per_student_data = quiz_data['per_student_data'] exercise_summaries = quiz_data['exercise_summaries'] ### 4- Write out the report content WriteQuizSummaryReportContent(ready_quiz, rw, full=False) ### 5- Proceed to write out and return report_content = rw.writeout() return {'name': report_name, 'content': report_content, 'path': s3_filepath}
def gen_survey_summary_report(ready_course, survey, save_to_s3=False): ### 1- Compose the report file name and instantiate the report writer object dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s.csv" % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, survey.slug) s3_filepath = "%s/%s/reports/survey_summary/%s" % ( course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) ### 2- Write the Report Title rw.write(content=[ "Survey Summary for %s (%s %d)" % (ready_course.title, ready_course.term.title(), ready_course.year) ], nl=1) ### 3- Write survey report WriteSurveySummaryReportContent(survey, rw, full=False) ### 4- Proceed to write out and return report_content = rw.writeout() return { 'name': report_name, 'content': report_content, 'path': s3_filepath }
def gen_class_roster(ready_course, save_to_s3=False): dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s-Class-Roster.csv" % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, course_prefix + '_' + course_suffix) s3_filepath = "%s/%s/reports/class_roster/%s" % ( course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) # Title rw.write(content=[ "Class Roster for %s (%s %d) as of %02d/%02d/%d" % (ready_course.title, ready_course.term.title(), ready_course.year, dt.month, dt.day, dt.year) ], nl=1) # Members students = ready_course.student_group.user_set.order_by( 'username').all().order_by('last_name').values_list( 'first_name', 'last_name', 'email', 'username') rw.write(content=["Num. Students:", "", len(students)], nl=1) rw.write(content=["First namme", "Last name", "Email", "Username"]) for s in students: rw.write(content=[s[0], s[1], s[2], s[3]]) report_content = rw.writeout() return { 'name': "%02d_%02d_%02d__%02d_%02d_%02d-%s-Class-Roster.csv" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, course_prefix + '_' + course_suffix), 'content': report_content, 'path': s3_filepath }
def gen_quiz_data_report(ready_course, ready_quiz, save_to_s3=False): students_ = ready_course.student_group.user_set.all().values_list( 'id', 'username', 'first_name', 'last_name') students = {} for s in students_: students[s[0]] = {"username": s[1], "name": "%s %s" % (s[2], s[3])} mean = lambda k: sum(k) / len(k) dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] is_video = isinstance(ready_quiz, Video) is_summative = (not is_video) and (ready_quiz.assessment_type == 'assessive') is_formative = (is_video) or (ready_quiz.assessment_type == 'formative') if is_summative: submissions_permitted = ready_quiz.submissions_permitted if submissions_permitted == 0: submissions_permitted = 100000 resubmission_penalty = ready_quiz.resubmission_penalty / 100.0 grace_deadline = ready_quiz.grace_period if not grace_deadline: grace_deadline = ready_quiz.due_date partial_credit_deadline = ready_quiz.partial_credit_deadline late_penalty = ready_quiz.late_penalty / 100.0 report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s.csv" % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ready_quiz.slug) if is_video: s3_filepath = "%s/%s/reports/videos/%s" % (course_prefix, course_suffix, report_name) else: s3_filepath = "%s/%s/reports/problemsets/%s" % ( course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) rw.write([ "Activity for %s \"%s\" in %s (%s %d)" % ('Video' if is_video else 'Problem Set', ready_quiz.title, ready_course.title, ready_course.term.title(), ready_course.year) ], nl=1) data = {} if is_video: rlns = VideoToExercise.objects.filter( video=ready_quiz, is_deleted=0).order_by('video_time') else: rlns = ProblemSetToExercise.objects.filter( problemSet=ready_quiz, is_deleted=0).order_by('number') if is_video: video_visits = PageVisitLog.objects.filter( page_type='video', object_id=str(ready_quiz.id)).order_by('user', 'time_created') for vv in video_visits: if not vv.user.username in data: stud_username = vv.user.username stud_fullname = vv.user.first_name + " " + vv.user.last_name data[vv.user.username] = { 'username': stud_username, 'name': stud_fullname, 'visits': [] } data[vv.user.username]['visits'].append( "%s-%s-%s at %s:%s" % (vv.time_created.year, vv.time_created.month, vv.time_created.day, vv.time_created.hour, vv.time_created.minute)) ex_ids = [] for rln in rlns: ex = rln.exercise ex_ids.append(ex.id) if is_video: atts = ProblemActivity.objects.select_related( 'video', 'exercise').filter( video_to_exercise__exercise__fileName=ex.fileName, video_to_exercise__video=ready_quiz).order_by( 'student', 'time_created').values_list('student_id', 'complete', 'time_taken', 'attempt_content', 'time_created') else: atts = ProblemActivity.objects.select_related( 'problemSet', 'exercise').filter( problemset_to_exercise__exercise__fileName=ex.fileName, problemset_to_exercise__problemSet=ready_quiz).order_by( 'student', 'time_created').values_list('student_id', 'complete', 'time_taken', 'attempt_content', 'time_created') submitters = [item[0] for item in atts] completes = [item[1] for item in atts] times_taken = [item[2] for item in atts] attempts_content = [item[3] for item in atts] times_created = [item[4] for item in atts] for i in range(0, len(atts)): if not (submitters[i] in students): continue # Do not include attempts by non-students in the report is_student_first_attempt = (i == 0) or (submitters[i] != submitters[i - 1]) is_student_last_attempt = (i == len(atts) - 1) or ( submitters[i] != submitters[i + 1]) if is_student_first_attempt: stud_username = students[submitters[i]]['username'] if not stud_username in data: stud_fullname = students[submitters[i]]['name'] data[stud_username] = { 'username': stud_username, 'name': stud_fullname, 'visits': [] } attempt_number = 0 completed = False attempt_times = [] attempts = [] num_incorrect_attempts = 0 if not completed: attempt_number += 1 attempt_times.append(times_taken[i]) attempts.append(attempts_content[i].replace("\r", "").replace( "\n", ";")) if completes[i] == 1: completed = True num_incorrect_attempts = attempt_number - 1 first_correct_attempt_time_created = times_created[i] if is_student_last_attempt: score = 0 score_after_late_penalty = 0 if is_summative: if completed and (num_incorrect_attempts + 1 <= submissions_permitted): score = 1.0 - ( num_incorrect_attempts) * resubmission_penalty score_after_late_penalty = score # Apply late penalty if necessary if first_correct_attempt_time_created > partial_credit_deadline: if partial_credit_deadline: score_after_late_penalty = 0 elif first_correct_attempt_time_created > grace_deadline: if grace_deadline: score_after_late_penalty = score * (1 - late_penalty) if score < 0: score = 0 if score_after_late_penalty < 0: score_after_late_penalty = 0 elif is_formative: if completed: score = 1.0 else: score = 0.0 data[stud_username][ex.id] = { 'completed': 'y' if completed else 'n', 'attempts': json.dumps(attempts), 'median_attempt_time': median(attempt_times), 'score': score } if is_summative: data[stud_username][ex.id][ 'score_after_late_penalty'] = score_after_late_penalty ##### Start Write Out ##### # Sort students by username sorted_usernames = sorted(data.keys()) # If not activity, do not type anything unneeded. if len(sorted_usernames) == 0: rw.write(content=[ "No activity yet for this %s" % ('video' if is_video else 'problem set') ], indent=1) report_content = rw.writeout() return { 'name': report_name, 'path': s3_filepath, 'content': report_content } header1 = ["", ""] header2 = ["", ""] if is_video: header1.extend(["", "", "Num video visits", "Visits date/times"]) header2.extend(["", "", "", ""]) for rln in rlns: header1.extend(["", "", rln.exercise.get_slug(), "", "", ""]) header2.extend( ["", "", "Completed", "Attempts", "Median attempt time", "Score"]) if is_summative: header1.append("") header2.append("Score after Late Penalty") header1.extend(["", "Total score / %d" % len(rlns)]) if is_summative: header1.append("Total score after late penalty") rw.write(header1) rw.write(header2) for u in sorted_usernames: r = data[u] stud_score = 0 stud_score_after_late_penalty = 0 content = [u, r['name']] if is_video: visit_dt_string = "" for vvi in range(len(data[u]['visits'])): if vvi > 0: visit_dt_string += ', ' visit_dt_string += data[u]['visits'][vvi] content.extend(["", "", len(data[u]['visits']), visit_dt_string]) for ex_id in ex_ids: if ex_id in r: ex_res = r[ex_id] else: ex_res = { 'completed': '', 'attempts': '', 'median_attempt_time': '', 'score': '', 'score_after_late_penalty': '' } content.extend([ "", "", ex_res['completed'], ex_res['attempts'], ex_res['median_attempt_time'], ex_res['score'] ]) if is_summative: content.append(ex_res['score_after_late_penalty']) stud_score += (ex_res['score'] if isinstance( ex_res['score'], float) else 0) if is_summative: stud_score_after_late_penalty += ( ex_res['score_after_late_penalty'] if isinstance( ex_res['score_after_late_penalty'], float) else 0) content.extend(["", stud_score]) if is_summative: content.append(stud_score_after_late_penalty) rw.write(content) report_content = rw.writeout() return { 'name': report_name, 'content': report_content, 'path': s3_filepath }
def gen_course_dashboard_report(ready_course, save_to_s3=False): dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] s3_filepath = "%s/%s/reports/dashboard/%02d_%02d_%02d__%02d_%02d_%02d-%s-Dashboard.csv" % (course_prefix, course_suffix, dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, course_prefix+'_'+course_suffix) rw = C2GReportWriter(ready_course, save_to_s3, s3_filepath) # Title rw.write(content = ["Dashboard for %s (%s %d)" % (ready_course.title, ready_course.term.title(), ready_course.year)], nl = 1) # Members num_prof = ready_course.instructor_group.user_set.all().count() num_stud = ready_course.student_group.user_set.all().count() num_tas = ready_course.tas_group.user_set.all().count() num_rota = ready_course.readonly_tas_group.user_set.all().count() rw.write(content = ["Members"]) rw.write(content = ["Students", num_stud, "Professors", num_prof, "TAs", num_tas, "Readonly TAs", num_rota], indent = 1, nl = 1) # Content problem_sets = ProblemSet.objects.getByCourse(course=ready_course).order_by('-live_datetime') videos = Video.objects.getByCourse(course=ready_course).order_by('-live_datetime') additional_pages = AdditionalPage.objects.getSectionPagesByCourse(course=ready_course).order_by('-live_datetime') num_all_formative_problem_sets = ProblemSet.objects.getByCourse(course=ready_course.image).filter(assessment_type="formative").count() num_live_formative_problem_sets = problem_sets.filter(assessment_type="formative").count() num_all_summative_problem_sets = ProblemSet.objects.getByCourse(course=ready_course.image).filter(assessment_type="summative").count() num_live_summative_problem_sets = problem_sets.filter(assessment_type="summative").count() num_all_videos = Video.objects.getByCourse(course=ready_course.image).count() num_live_videos = videos.count() num_all_pages = AdditionalPage.objects.getSectionPagesByCourse(course=ready_course.image).count() num_live_pages = additional_pages.count() num_all_files = File.objects.getByCourse(course=ready_course.image).count() num_live_files = File.objects.getByCourse(course=ready_course).count() rw.write(content = ["Content"]) rw.write(content = ["Formative problem sets", "Summative Problem sets", "Videos", "Content Pages", "Files"], indent = 2) rw.write(content = ["All", num_all_formative_problem_sets, num_all_summative_problem_sets, num_all_videos, num_all_pages, num_all_files], indent = 1) rw.write(content = ["Live", num_live_formative_problem_sets, num_live_summative_problem_sets, num_live_videos, num_live_pages, num_live_files], indent = 1, nl = 1) # Activity problem_set_visits = get_visit_information(ready_course, problem_sets, 'problemset') video_visits = get_visit_information(ready_course, videos, 'video') additional_page_visits = get_visit_information(ready_course, additional_pages, 'additional_page') forum_visits = get_visit_information(ready_course, None, 'forum') rw.write(content = ["Page Visits (Only live items are shown)"], nl = 1) rw.write(content = ["Forum"], indent = 1) rw.write(content = ["", "", "", "Past day total", "Past day unique", "", "Past week total", "Past week unique", "", "all_time_total", "all_time_unique"], indent = 1) rw.write(content = ["", "", "", forum_visits[0]['past_day_total'], forum_visits[0]['past_day_unique'], "", forum_visits[0]['past_week_total'], forum_visits[0]['past_week_unique'], "", forum_visits[0]['all_time_total'], forum_visits[0]['all_time_unique']], indent = 1, nl = 1) rw.write([""]) rw.write(content = ["Problem sets"], indent = 1) if len(problem_set_visits) > 0: rw.write(content = ["URL ID", "Title", "", "Past day total", "Past day unique", "", "Past week total", "Past week unique", "", "all_time_total", "all_time_unique"], indent = 1) for item in problem_set_visits: rw.write(content = [item['item'].slug, item['item'].title, "", item['past_day_total'], item['past_day_unique'], "", item['past_week_total'], item['past_week_unique'], "", item['all_time_total'], item['all_time_unique']], indent = 1) else: rw.write(content = ["No live problem sets yet."], indent = 2) rw.write([""]) rw.write(content = ["Videos"], indent = 1) if len(video_visits) > 0: rw.write(content = ["URL ID", "Title", "", "Past day total", "Past day unique", "", "Past week total", "Past week unique", "", "all_time_total", "all_time_unique"], indent = 1) for item in video_visits: rw.write(content = [item['item'].slug, item['item'].title, "", item['past_day_total'], item['past_day_unique'], "", item['past_week_total'], item['past_week_unique'], "", item['all_time_total'], item['all_time_unique']], indent = 1) else: rw.write(content = ["No live videos yet."], indent = 2) rw.write([""]) rw.write(content = ["Content pages"], indent = 1) if len(additional_page_visits) > 0: rw.write(content = ["URL ID", "Title", "", "Past day total", "Past day unique", "", "Past week total", "Past week unique", "", "all_time_total", "all_time_unique"], indent = 1) for item in additional_page_visits: rw.write(content = [item['item'].slug, item['item'].title, "", item['past_day_total'], item['past_day_unique'], "", item['past_week_total'], item['past_week_unique'], "", item['all_time_total'], item['all_time_unique']], indent = 1) else: rw.write(content = ["No live content pages yet."], indent = 2) rw.write([""]) rw.close()
def gen_quiz_data_report(ready_course, ready_quiz, save_to_s3=False): dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] s3_filepath = "%s/%s/reports/quiz_data/%s/%02d_%02d_%02d__%02d_%02d_%02d-%s-Quiz-Data.csv" % ( course_prefix, course_suffix, ready_quiz.slug, dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ready_quiz.slug) rw = C2GReportWriter(ready_course, save_to_s3, s3_filepath) rw.write([ "Quiz Attempts for Quiz \"%s\" in %s (%s %d)" % (ready_quiz.title, ready_course.title, ready_course.term.title(), ready_course.year) ], nl=1) is_summative = isinstance( ready_quiz, ProblemSet) and (ready_quiz.assessment_type == 'summative') data = {} mean = lambda k: sum(k) / len(k) if isinstance(ready_quiz, Video): rlns = VideoToExercise.objects.get( video=ready_quiz).order_by('video_time') else: rlns = ProblemSetToExercise.objects.filter( problemSet=ready_quiz, ).order_by('number') ex_ids = [] for rln in rlns: ex = rln.exercise ex_ids.append(ex.id) if isinstance(ready_quiz, Video): atts = ProblemActivity.objects.filter( video_to_exercise=rln).order_by('student', 'time_created') else: atts = ProblemActivity.objects.filter( problemset_to_exercise=rln).order_by('student', 'time_created') submitters = atts.values_list('student', flat=True) completes = atts.values_list('complete', flat=True) times_taken = atts.values_list('time_taken', flat=True) attempts_content = atts.values_list('attempt_content', flat=True) for i in range(0, len(atts)): is_student_first_attempt = (i == 0) or (submitters[i] != submitters[i - 1]) is_student_last_attempt = (i == len(atts) - 1) or ( submitters[i] != submitters[i + 1]) if is_student_first_attempt: attempt_number = 0 stud_username = atts[i].student.username stud_fullname = atts[i].student.first_name + " " + atts[ i].student.last_name completed = False attempt_times = [] attempts = [] attempt_number += 1 if not completed: attempt_times.append(times_taken[i]) attempts.append(attempts_content[i]) if completes[i] == 1: completed = True if is_student_last_attempt: score = 0 if is_summative: if (attempt_number + 1) <= ready_quiz.submissions_permitted: score = 1 - attempt_number * ready_quiz.resubmission_penalty / 100.0 if score < 0: score = 0 if not stud_username in data: data[stud_username] = { 'username': stud_username, 'name': stud_fullname } data[stud_username][ex.id] = { 'completed': 'y' if completed else 'n', 'attempts': json.dumps(attempts), 'mean_attempt_time': mean(attempt_times) } if is_summative: data[stud_username][ex.id]['score'] = score # Sort students by username sorted_usernames = sorted(data.keys()) header1 = ["", ""] header2 = ["", ""] for rln in rlns: header1.extend(["", "", rln.exercise.get_slug(), "", "", ""]) header2.extend(["", "", "Completed", "attemps"]) if is_summative: header2.append("Score") header2.append("Mean attempt time") if is_summative: header1.extend(["", "Total score / %d" % len(rlns)]) rw.write(header1) rw.write(header2) for u in sorted_usernames: r = data[u] stud_score = 0 content = [u, r['name']] for ex_id in ex_ids: if ex_id in r: ex_res = r[ex_id] else: ex_res = { 'completed': '', 'attempts': '', 'score': '', 'mean_attempt_time': '' } content.extend(["", "", ex_res['completed'], ex_res['attempts']]) if is_summative: content.append(ex_res['score']) stud_score += (ex_res['score'] if isinstance( ex_res['score'], float) else 0) content.append(ex_res['mean_attempt_time']) if is_summative: content.extend(["", stud_score]) rw.write(content) rw.close()
def gen_course_dashboard_report(ready_course, save_to_s3=False): dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s-Dashboard.csv" % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, course_prefix + '_' + course_suffix) s3_filepath = "%s/%s/reports/dashboard/%s" % (course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) # Title rw.write(content=[ "Dashboard for %s (%s %d)" % (ready_course.title, ready_course.term.title(), ready_course.year) ], nl=1) # Members num_prof = ready_course.instructor_group.user_set.all().count() num_stud = ready_course.student_group.user_set.all().count() num_tas = ready_course.tas_group.user_set.all().count() num_rota = ready_course.readonly_tas_group.user_set.all().count() rw.write(content=["Members"]) rw.write(content=[ "Students", num_stud, "Professors", num_prof, "TAs", num_tas, "Readonly TAs", num_rota ], indent=1, nl=1) # Content live_exam_objects = Exam.objects.getByCourse(course=ready_course) all_exam_objects = Exam.objects.getByCourse(course=ready_course.image) exam_types = [li[0] for li in Exam.EXAM_TYPE_CHOICES] exam_content = {} for exam_type in exam_types: content_tuple = (all_exam_objects.filter(exam_type=exam_type), live_exam_objects.filter(exam_type=exam_type)) exam_content[exam_type] = content_tuple num_all_formative_problem_sets = exam_content["problemset"][0].filter( assessment_type="formative").count() num_live_formative_problem_sets = exam_content["problemset"][1].filter( assessment_type="formative").count() num_all_summative_problem_sets = exam_content["problemset"][0].filter( assessment_type="summative").count() num_live_summative_problem_sets = exam_content["problemset"][1].filter( assessment_type="summative").count() num_all_videos = Video.objects.getByCourse( course=ready_course.image).count() live_videos = Video.objects.getByCourse(course=ready_course) num_live_videos = live_videos.count() num_all_pages = AdditionalPage.objects.getByCourse( course=ready_course.image).count() live_additional_pages = AdditionalPage.objects.getByCourse( course=ready_course) num_live_pages = live_additional_pages.count() num_all_files = File.objects.getByCourse(course=ready_course.image).count() num_live_files = File.objects.getByCourse(course=ready_course).count() rw.write(content=["Content"]) rw.write(content=[ "Formative Quizzes", "Summative Quizzes", "Interactive Exercises", "Exams", "Surveys", "Videos", "Content Pages", "Files" ], indent=2) rw.write(content=[ "All", num_all_formative_problem_sets, num_all_summative_problem_sets, exam_content["interactive_exercise"][0].count(), exam_content["exam"][0].count(), exam_content["survey"][0].count(), num_all_videos, num_all_pages, num_all_files ], indent=1) rw.write(content=[ "Live", num_live_formative_problem_sets, num_live_summative_problem_sets, exam_content["interactive_exercise"][1].count(), exam_content["exam"][1].count(), exam_content["survey"][1].count(), num_live_videos, num_live_pages, num_live_files ], indent=1) # Activity rw.write(content=["Page Visits (Only live items are shown)"], nl=1) visits = {} for exam_type in exam_types: visits[ Exam.Exam_HUMAN_TYPES_PLURAL[exam_type]] = get_visit_information( ready_course, exam_content[exam_type][1], exam_type) visits["Videos"] = get_visit_information(ready_course, live_videos, 'video') visits["Content pages"] = get_visit_information(ready_course, live_additional_pages, 'additional_page') visits["Forum"] = get_visit_information(ready_course, None, 'forum') content_types = [ "Forum", "Quizzes", "Interactive Exercises", "Exams", "Surveys", "Videos", "Content pages" ] for content_type in content_types: rw.write(content=[content_type], indent=1) if content_type == "Forum": rw.write(content=[ "", "", "", "Past day total", "Past day unique", "", "Past week total", "Past week unique", "", "all_time_total", "all_time_unique" ], indent=1) rw.write(content=[ "", "", "", visits["Forum"][0]['past_day_total'], visits["Forum"][0]['past_day_unique'], "", visits["Forum"][0]['past_week_total'], visits["Forum"][0]['past_week_unique'], "", visits["Forum"][0]['all_time_total'], visits["Forum"][0]['all_time_unique'] ], indent=1) else: if len(visits[content_type]) > 0: rw.write(content=[ "URL ID", "Title", "", "Past day total", "Past day unique", "", "Past week total", "Past week unique", "", "all_time_total", "all_time_unique" ], indent=1) for item in visits[content_type]: rw.write(content=[ item['item'].slug, item['item'].title, "", item['past_day_total'], item['past_day_unique'], "", item['past_week_total'], item['past_week_unique'], "", item['all_time_total'], item['all_time_unique'] ], indent=1) else: rw.write(content=["No live " + content_type.lower() + " yet."], indent=2) rw.write([""]) report_content = rw.writeout() return { 'name': "%02d_%02d_%02d__%02d_%02d_%02d-%s-Dashboard.csv" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, course_prefix + '_' + course_suffix), 'content': report_content, 'path': s3_filepath }
def gen_quiz_full_report(ready_course, ready_quiz, save_to_s3=False): ### 1- Create the S3 file name and report writer object dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] is_video = isinstance(ready_quiz, Video) is_summative = (not is_video) and (ready_quiz.assessment_type == 'assessive') report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s.csv" % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ready_quiz.slug) if is_video: s3_filepath = "%s/%s/reports/videos/%s" % (course_prefix, course_suffix, report_name) else: s3_filepath = "%s/%s/reports/problemsets/%s" % ( course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) ### 2- Get the quiz data quiz_data = get_quiz_data(ready_quiz, get_visits=True) per_student_data = quiz_data['per_student_data'] exercise_summaries = quiz_data['exercise_summaries'] ex_ids = [ex_summ['id'] for ex_summ in exercise_summaries] ### 3- Writeout rw.write(["Activity for %s" % quiz_data['quiz_summary']['title']], nl=1) # Sort students by username sorted_usernames = sorted(per_student_data.keys()) # If no activity, do not type anything unneeded. if not has_activity(per_student_data): rw.write(content=["No activity yet."], indent=1) report_content = rw.writeout() return { 'name': report_name, 'path': s3_filepath, 'content': report_content } header1 = ["", ""] header2 = ["", ""] header1.extend(["", "Total score / %d" % len(exercise_summaries)]) header2.extend(["", ""]) if is_summative: header1.extend(["Total score after late penalty"]) header2.extend([""]) header1.extend(["", "Num page visits", "Visit date/times"]) header2.extend(["", "", ""]) for ex_summary in exercise_summaries: header1.extend(["", "", ex_summary['slug'], "", "", ""]) header2.extend( ["", "", "Completed", "Attempts", "Score", "Median attempt time"]) if is_summative: header1.extend(["", ""]) header2.extend([ "First correct attempt timestamp", "Score after late penalty" ]) rw.write(header1) rw.write(header2) for u in sorted_usernames: stud_quiz_data = per_student_data[u] if len(stud_quiz_data['visits']) == 0 and len( stud_quiz_data['exercise_activity']) == 0: continue stud_score = 0 stud_score_after_late_penalty = 0 # User- and full name content = [u, stud_quiz_data['name']] # Total scores for ex_id in ex_ids: if ex_id in stud_quiz_data['exercise_activity']: ex_res = stud_quiz_data['exercise_activity'][ex_id] stud_score += (ex_res['score'] if isinstance( ex_res['score'], float) else 0) if is_summative and isinstance( ex_res['score_after_late_penalty'], float): stud_score_after_late_penalty += ex_res[ 'score_after_late_penalty'] content.extend(["", stud_score]) if is_summative: content.append(stud_score_after_late_penalty) # Student visit data content.extend([ "", len(stud_quiz_data['visits']), ", ".join(stud_quiz_data['visits']) ]) for ex_id in ex_ids: if ex_id in stud_quiz_data['exercise_activity']: ex_res = stud_quiz_data['exercise_activity'][ex_id] else: ex_res = { 'completed': '', 'attempts': '', 'score': '', 'last_attempt_timestamp': '', 'score_after_late_penalty': '', 'median_attempt_time': '' } content.extend([ "", "", 'y' if ex_res['completed'] else 'n', ex_res['attempts'], ex_res['score'], ex_res['median_attempt_time'] ]) if is_summative: first_correct_attempt_timestamp = get_friendly_datetime( ex_res['last_attempt_timestamp'] ) if ex_res['completed'] else "" content.extend([ first_correct_attempt_timestamp, ex_res['score_after_late_penalty'] ]) rw.write(content) report_content = rw.writeout() return { 'name': report_name, 'content': report_content, 'path': s3_filepath }
def gen_assessment_full_report(ready_course, ready_exam, save_to_s3=False): ### 1- Create the S3 file name and report writer object dt = datetime.now() course_prefix = ready_course.handle.split('--')[0] course_suffix = ready_course.handle.split('--')[1] is_video = ready_exam.invideo assessment_type = ready_exam.assessment_type report_name = "%02d_%02d_%02d__%02d_%02d_%02d-%s.csv" % ( dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ready_exam.slug) #I'm pretty sure we want to put all the assessment reports in one place and should be classified as problemset reports. # if is_video: # s3_filepath = "%s/%s/reports/videos/%s" % (course_prefix, course_suffix, report_name) # else: s3_filepath = "%s/%s/reports/problemsets/%s" % (course_prefix, course_suffix, report_name) rw = C2GReportWriter(save_to_s3, s3_filepath) ### 2- Get the exam data student_scores, student_field_scores = get_full_assessment_data(ready_exam) ### 3- Writeout rw.write(["Activity for %s" % ready_exam.title], nl=1) content = [] content = [ "", "Field", "Correct", "# Attempts", "Sub score", "Total score", "Max possible score" ] rw.write(content, indent=1) content = [] for student_score in student_scores: name = student_score['student__first_name'] + " " + student_score[ 'student__last_name'] content.extend([ student_score['student__username'], name, "", "", "", "", student_score['score'], ready_exam.total_score ]) rw.write(content) content = [] for student_field_score in student_field_scores: if student_score['student__username'] == student_field_score[ 'parent__record__student__username']: field_name = student_field_score['human_name'] if not field_name: field_name = student_field_score['field_name'] content.extend([ field_name, student_field_score['correct'], student_field_score['total_attempts'], student_field_score['sub_score'] ]) rw.write(content, indent=2) content = [] report_content = rw.writeout() return { 'name': report_name, 'content': report_content, 'path': s3_filepath }