def page(self, course, username): """ Get all data and display the page """ data = list(self.database.user_tasks.find({"username": username, "courseid": course.get_id()})) tasks = course.get_tasks() result = dict([(taskid, {"taskid": taskid, "name": tasks[taskid].get_name(self.user_manager.session_language()), "tried": 0, "status": "notviewed", "grade": 0, "url": self.submission_url_generator(username, taskid)}) for taskid in tasks]) for taskdata in data: if taskdata["taskid"] in result: result[taskdata["taskid"]]["tried"] = taskdata["tried"] if taskdata["tried"] == 0: result[taskdata["taskid"]]["status"] = "notattempted" elif taskdata["succeeded"]: result[taskdata["taskid"]]["status"] = "succeeded" else: result[taskdata["taskid"]]["status"] = "failed" result[taskdata["taskid"]]["grade"] = taskdata["grade"] result[taskdata["taskid"]]["submissionid"] = str(taskdata["submissionid"]) if "csv" in web.input(): return make_csv(result) results = sorted(list(result.values()), key=lambda result: (tasks[result["taskid"]].get_order(), result["taskid"])) return self.template_helper.get_renderer().course_admin.student_info(course, username, results)
def page(self, course): """ Get all data and display the page """ data = list(self.database.user_tasks.aggregate( [ { "$match": { "courseid": course.get_id(), "username": {"$in": self.user_manager.get_course_registered_users(course, False)} } }, { "$group": { "_id": "$taskid", "viewed": {"$sum": 1}, "attempted": {"$sum": {"$cond": [{"$ne": ["$tried", 0]}, 1, 0]}}, "attempts": {"$sum": "$tried"}, "succeeded": {"$sum": {"$cond": ["$succeeded", 1, 0]}} } } ])) # Load tasks and verify exceptions files = self.task_factory.get_readable_tasks(course) output = {} errors = [] for task in files: try: output[task] = course.get_task(task) except Exception as inst: errors.append({"taskid": task, "error": str(inst)}) tasks = OrderedDict(sorted(list(output.items()), key=lambda t: (t[1].get_order(), t[1].get_id()))) # Now load additional informations result = OrderedDict() for taskid in tasks: result[taskid] = {"name": tasks[taskid].get_name(self.user_manager.session_language()), "viewed": 0, "attempted": 0, "attempts": 0, "succeeded": 0, "url": self.submission_url_generator(taskid)} for entry in data: if entry["_id"] in result: result[entry["_id"]]["viewed"] = entry["viewed"] result[entry["_id"]]["attempted"] = entry["attempted"] result[entry["_id"]]["attempts"] = entry["attempts"] result[entry["_id"]]["succeeded"] = entry["succeeded"] if "csv" in web.input(): return make_csv(result) return self.template_helper.get_renderer().course_admin.task_list(course, result, errors)
def page(self, course, msg="", error=False): """ Get all data and display the page """ aggregations = OrderedDict() taskids = list(course.get_tasks().keys()) for aggregation in self.user_manager.get_course_aggregations(course): aggregations[aggregation['_id']] = dict(list(aggregation.items()) + [("tried", 0), ("done", 0), ("url", self.submission_url_generator(aggregation['_id'])) ]) data = list(self.database.submissions.aggregate( [ { "$match": { "courseid": course.get_id(), "taskid": {"$in": taskids}, "username": {"$in": aggregation["students"]} } }, { "$group": { "_id": "$taskid", "tried": {"$sum": 1}, "done": {"$sum": {"$cond": [{"$eq": ["$result", "success"]}, 1, 0]}} } }, ])) for c in data: aggregations[aggregation['_id']]["tried"] += 1 if c["tried"] else 0 aggregations[aggregation['_id']]["done"] += 1 if c["done"] else 0 my_aggregations, other_aggregations = [], [] for aggregation in aggregations.values(): if self.user_manager.session_username() in aggregation["tutors"]: my_aggregations.append(aggregation) else: other_aggregations.append(aggregation) if "csv" in web.input(): return make_csv(data) return self.template_helper.get_renderer().course_admin.aggregation_list(course, [my_aggregations, other_aggregations], msg, error)
def page(self, course, aggregationid): """ Get all data and display the page """ aggregation = self.database.aggregations.find_one({"_id": ObjectId(aggregationid)}) data = list(self.database.submissions.aggregate( [ { "$match": { "courseid": course.get_id(), "username": {"$in": aggregation["students"]} } }, { "$group": { "_id": "$taskid", "tried": {"$sum": 1}, "succeeded": {"$sum": {"$cond": [{"$eq": ["$result", "success"]}, 1, 0]}}, "grade": {"$max": "$grade"} } } ])) tasks = course.get_tasks() result = dict([(taskid, {"taskid": taskid, "name": tasks[taskid].get_name(self.user_manager.session_language()), "tried": 0, "status": "notviewed", "grade": 0, "url": self.submission_url_generator(aggregationid, taskid)}) for taskid in tasks]) for taskdata in data: if taskdata["_id"] in result: result[taskdata["_id"]]["tried"] = taskdata["tried"] if taskdata["tried"] == 0: result[taskdata["_id"]]["status"] = "notattempted" elif taskdata["succeeded"]: result[taskdata["_id"]]["status"] = "succeeded" else: result[taskdata["_id"]]["status"] = "failed" result[taskdata["_id"]]["grade"] = taskdata["grade"] if "csv" in web.input(): return make_csv(result) results = sorted(list(result.values()), key=lambda result: (tasks[result["taskid"]].get_order(), result["taskid"])) return self.template_helper.get_renderer().course_admin.aggregation_info(course, aggregation, results)
def page(self, course, msgs=None): """ Get all data and display the page """ msgs = msgs if msgs else [] user_input = self.get_input() data, classroom = self.get_submissions(course, user_input) # ONLY classrooms user wants to query if len(data) == 0 and not self.show_collapse(user_input): msgs.append(_("No submissions found")) classrooms = self.user_manager.get_course_aggregations(course) # ALL classrooms of the course users = self.get_users(course) # All users of the course tasks = course.get_tasks() # All tasks of the course statistics = None if user_input.stat != "no_stat": statistics = compute_statistics(tasks, data, True if "with_pond_stat" == user_input.stat else False) if "csv" in web.input(): return make_csv(data) if "download" in web.input(): # self._logger.info("Downloading %d submissions from course %s", len(data), course.get_id()) web.header('Content-Type', 'application/x-gzip', unique=True) web.header('Content-Disposition', 'attachment; filename="submissions.tgz"', unique=True) # Tweak if not using classrooms : classroom['students'] may content ungrouped users aggregations = dict([(username, aggregation if course.use_classrooms() or ( username in aggregation['groups'][0]["students"]) else None ) for aggregation in classroom for username in aggregation["students"]]) download_type = web.input(download_type=self._valid_formats[0]).download_type if download_type not in self._valid_formats: download_type = self._valid_formats[0] return self.submission_manager.get_submission_archive(data, list(reversed(download_type.split('/'))), aggregations) if user_input.limit != '' and user_input.limit.isdigit(): data = data[:int(user_input.limit)] if len(data) > self._trunc_limit: msgs.append(_("The result contains more than {0} submissions. The displayed submissions are truncated.\n").format(self._trunc_limit)) data = data[:self._trunc_limit] return self.template_helper.get_renderer().course_admin.submissions(course, tasks, users, classrooms, data, statistics, user_input, self._allowed_sort, self._allowed_sort_name, self._valid_formats, msgs, self.show_collapse(user_input))
def page(self, course, msgs=None): """ Get all data and display the page """ msgs = msgs if msgs else [] user_input = self.get_input() # Retrieve submissions data required for display the table fields_for_table = [ "username", "best", "result", "submitted_on", "grade", "status", "taskid" ] data_table, classroom = self.get_submissions(course, user_input, fields_for_table) if len(data_table) == 0 and not self.show_collapse(user_input): msgs.append(_("No submissions found")) classrooms = self.user_manager.get_course_aggregations( course) # ALL classrooms of the course users = self.get_users(course) # All users of the course tasks = course.get_tasks() # All tasks of the course statistics = None if user_input.stat != "no_stat": # Retrieve submissions data required for display stats fields_for_stats = [ "taskid", "username", "tests", "best", "result" ] data_stats, classroom = self.get_submissions( course, user_input, fields_for_stats) statistics = compute_statistics( tasks, data_stats, True if "with_pond_stat" == user_input.stat else False) #Get csv with all the submissions info in the query if "csv" in web.input(): #We get the all info of that submissions data, classroom = self.get_submissions(course, user_input) return make_csv(data) #Download all the submissions in the query if "download" in web.input(): #We get the all info of that submissions data, classroom = self.get_submissions(course, user_input) # self._logger.info("Downloading %d submissions from course %s", len(data), course.get_id()) web.header('Content-Type', 'application/x-gzip', unique=True) web.header('Content-Disposition', 'attachment; filename="submissions.tgz"', unique=True) # Tweak if not using classrooms : classroom['students'] may content ungrouped users aggregations = dict([ (username, aggregation if course.use_classrooms() or (username in aggregation['groups'][0]["students"]) else None) for aggregation in classroom for username in aggregation["students"] ]) download_type = web.input( download_type=self._valid_formats[0]).download_type if download_type not in self._valid_formats: download_type = self._valid_formats[0] return self.submission_manager.get_submission_archive( data, list(reversed(download_type.split('/'))), aggregations) if user_input.limit != '' and user_input.limit.isdigit(): data_table = data_table[:int(user_input.limit)] if len(data_table) > self._trunc_limit: msgs.append( _("The result contains more than ") + "{0}".format(self._trunc_limit) + _(" submissions. The displayed submissions are truncated.\n")) data_table = data_table[:self._trunc_limit] return self.template_helper.get_renderer().course_admin.submissions( course, tasks, users, classrooms, data_table, statistics, user_input, self._allowed_sort, self._allowed_sort_name, self._valid_formats, msgs, self.show_collapse(user_input))
def page(self, course, task): """ Get all data and display the page """ user_list = self.user_manager.get_course_registered_users(course, False) users = OrderedDict(sorted(list(self.user_manager.get_users_info(user_list).items()), key=lambda k: k[1][0] if k[1] is not None else "")) individual_results = list(self.database.user_tasks.find({"courseid": course.get_id(), "taskid": task.get_id(), "username": {"$in": user_list}})) individual_data = OrderedDict([(username, {"username": username, "realname": user[0] if user is not None else "", "email": user[1] if user is not None else "", "url": self.individual_submission_url_generator(task, username), "tried": 0, "grade": 0, "status": "notviewed"}) for username, user in users.items()]) for user in individual_results: individual_data[user["username"]]["tried"] = user["tried"] if user["tried"] == 0: individual_data[user["username"]]["status"] = "notattempted" elif user["succeeded"]: individual_data[user["username"]]["status"] = "succeeded" else: individual_data[user["username"]]["status"] = "failed" individual_data[user["username"]]["grade"] = user["grade"] aggregation_data = OrderedDict() for aggregation in self.user_manager.get_course_aggregations(course): aggregation_data[aggregation['_id']] = {"_id": aggregation['_id'], "description": aggregation['description'], "url": self.aggregation_submission_url_generator(task, aggregation), "tried": 0, "grade": 0, "status": "notviewed", "tutors": aggregation["tutors"], "groups": aggregation["groups"]} aggregation_results = list(self.database.submissions.aggregate( [ { "$match": { "courseid": course.get_id(), "taskid": task.get_id(), "username": {"$in": aggregation["students"]} } }, { "$group": { "_id": "$taskid", "tried": {"$sum": 1}, "succeeded": {"$sum": {"$cond": [{"$eq": ["$result", "success"]}, 1, 0]}}, "grade": {"$max": "$grade"} } } ])) for g in aggregation_results: aggregation_data[aggregation['_id']]["tried"] = g["tried"] if g["tried"] == 0: aggregation_data[aggregation['_id']]["status"] = "notattempted" elif g["succeeded"]: aggregation_data[aggregation['_id']]["status"] = "succeeded" else: aggregation_data[aggregation['_id']]["status"] = "failed" aggregation_data[aggregation['_id']]["grade"] = g["grade"] my_aggregations, other_aggregations = [], [] for aggregation in aggregation_data.values(): if self.user_manager.session_username() in aggregation["tutors"]: my_aggregations.append(aggregation) else: other_aggregations.append(aggregation) if "csv" in web.input() and web.input()["csv"] == "students": return make_csv(list(individual_data.values())) elif "csv" in web.input() and web.input()["csv"] == "aggregations": return make_csv(list(aggregation_data.values())) return self.template_helper.get_renderer().course_admin.task_info(course, task, individual_data.values(), [my_aggregations, other_aggregations])
def page(self, course, msg="", error=False): """ Get all data and display the page """ aggregations = OrderedDict() taskids = list(course.get_tasks().keys()) for aggregation in self.user_manager.get_course_aggregations(course): aggregations[aggregation['_id']] = dict( list(aggregation.items()) + [("tried", 0), ("done", 0), ("url", self.submission_url_generator(aggregation['_id']))]) data = list( self.database.submissions.aggregate([ { "$match": { "courseid": course.get_id(), "taskid": { "$in": taskids }, "username": { "$in": aggregation["students"] } } }, { "$group": { "_id": "$taskid", "tried": { "$sum": 1 }, "done": { "$sum": { "$cond": [{ "$eq": ["$result", "success"] }, 1, 0] } } } }, ])) for c in data: aggregations[ aggregation['_id']]["tried"] += 1 if c["tried"] else 0 aggregations[ aggregation['_id']]["done"] += 1 if c["done"] else 0 my_aggregations, other_aggregations = [], [] for aggregation in aggregations.values(): if self.user_manager.session_username() in aggregation["tutors"]: my_aggregations.append(aggregation) else: other_aggregations.append(aggregation) if "csv" in web.input(): return make_csv(data) return self.template_helper.get_renderer( ).course_admin.aggregation_list(course, [my_aggregations, other_aggregations], msg, error)
def page(self, course, msgs=None): """ Get all data and display the page """ msgs = msgs if msgs else [] user_input = self.get_input() data, audience = self.get_submissions( course, user_input) # ONLY audiences user wants to query if len(data) == 0 and not self.show_collapse(user_input): msgs.append(_("No submissions found")) course_audiences = self.user_manager.get_course_audiences( course) # ALL audiences of the course audiences_id = [audience["_id"] for audience in course_audiences] audiences_list = list( self.database.audiences.aggregate([{ "$match": { "_id": { "$in": audiences_id } } }, { "$unwind": "$students" }, { "$project": { "audience": "$_id", "students": 1 } }])) audiences = { audience["_id"]: audience for audience in course_audiences } audiences = { d["students"]: audiences[d["audience"]] for d in audiences_list } users = self.get_users(course) # All users of the course tasks = course.get_tasks() # All tasks of the course statistics = None if user_input.stat != "no_stat": statistics = compute_statistics( tasks, data, True if "with_pond_stat" == user_input.stat else False) if "csv" in web.input(): return make_csv(data) if "download" in web.input(): download_type = web.input( download_type=self._valid_formats[0]).download_type if download_type not in self._valid_formats: download_type = self._valid_formats[0] archive, error = self.submission_manager.get_submission_archive( data, list(reversed(download_type.split('/'))), audiences) if not error: # self._logger.info("Downloading %d submissions from course %s", len(data), course.get_id()) web.header('Content-Type', 'application/x-gzip', unique=True) web.header('Content-Disposition', 'attachment; filename="submissions.tgz"', unique=True) return archive else: msgs.append( _("The following submission could not be prepared for download: {}" ).format(error)) if user_input.limit != '' and user_input.limit.isdigit(): data = data[:int(user_input.limit)] if len(data) > self._trunc_limit: msgs.append( _("The result contains more than {0} submissions. The displayed submissions are truncated.\n" ).format(self._trunc_limit)) data = data[:self._trunc_limit] return self.template_helper.get_renderer().course_admin.submissions( course, tasks, users, course_audiences, data, statistics, user_input, self._allowed_sort, self._allowed_sort_name, self._valid_formats, msgs, self.show_collapse(user_input))
def POST_AUTH(self, courseid): # pylint: disable=arguments-differ """ POST request """ course, __ = self.get_course_and_check_rights(courseid) msgs = [] user_input = web.input(users=[], audiences=[], tasks=[], org_tags=[]) if "replay_submission" in user_input: # Replay a unique submission submission = self.database.submissions.find_one( {"_id": ObjectId(user_input["replay_submission"])}) if submission is None: raise web.notfound() web.header('Content-Type', 'application/json') self.submission_manager.replay_job( course.get_task(submission["taskid"]), submission) return json.dumps({"status": "waiting"}) elif "csv" in user_input or "download" in user_input or "replay" in user_input: best_only = "eval_dl" in user_input and "download" in user_input params = self.get_input_params( json.loads(user_input.get("displayed_selection", "")), course) data = self.submissions_from_user_input(course, params, msgs, best_only=best_only) if "csv" in user_input: return make_csv(data) elif "download" in user_input: download_type = user_input.get("download_type", "") if download_type not in [ "taskid/username", "taskid/audience", "username/taskid", "audience/taskid" ]: download_type = "taskid/username" if (best_only or "eval" in params) and "simplify" in user_input: sub_folders = list(download_type.split('/')) else: sub_folders = list( download_type.split('/')) + ["submissiondateid"] archive, error = self.submission_manager.get_submission_archive( course, data, sub_folders, simplify="simplify" in user_input) if not error: # self._logger.info("Downloading %d submissions from course %s", len(data), course.get_id()) web.header('Content-Type', 'application/x-gzip', unique=True) web.header('Content-Disposition', 'attachment; filename="submissions.tgz"', unique=True) return archive else: msgs.append( _("The following submission could not be prepared for download: {}" ).format(error)) return self.page(course, params, msgs=msgs) elif "replay" in user_input: if not self.user_manager.has_admin_rights_on_course(course): raise web.notfound() tasks = course.get_tasks() for submission in data: self.submission_manager.replay_job( tasks[submission["taskid"]], submission) msgs.append( _("{0} selected submissions were set for replay.").format( str(len(data)))) return self.page(course, params, msgs=msgs) elif "page" in user_input: params = self.get_input_params( json.loads(user_input["displayed_selection"]), course) try: page = int(user_input["page"]) except TypeError: page = 1 return self.page(course, params, page=page, msgs=msgs) else: params = self.get_input_params(user_input, course) return self.page(course, params, msgs=msgs)
def POST_AUTH(self, courseid): # pylint: disable=arguments-differ """ POST request """ course, __ = self.get_course_and_check_rights(courseid) msgs = [] user_input = flask.request.form.copy() user_input["users"] = flask.request.form.getlist("users") user_input["audiences"] = flask.request.form.getlist("audiences") user_input["tasks"] = flask.request.form.getlist("tasks") user_input["org_tags"] = flask.request.form.getlist("org_tasks") if "replay_submission" in user_input: # Replay a unique submission submission = self.database.submissions.find_one( {"_id": ObjectId(user_input["replay_submission"])}) if submission is None: raise NotFound(description=_("This submission doesn't exist.")) self.submission_manager.replay_job( course.get_task(submission["taskid"]), submission) return Response(response=json.dumps({"status": "waiting"}), content_type='application/json') elif "csv" in user_input or "download" in user_input or "replay" in user_input: best_only = "eval_dl" in user_input and "download" in user_input params = self.get_input_params( json.loads(user_input.get("displayed_selection", "")), course) data = self.submissions_from_user_input(course, params, msgs, best_only=best_only) if "csv" in user_input: return make_csv(data) elif "download" in user_input: download_type = user_input.get("download_type", "") if download_type not in [ "taskid/username", "taskid/audience", "username/taskid", "audience/taskid" ]: download_type = "taskid/username" if (best_only or "eval" in params) and "simplify" in user_input: sub_folders = list(download_type.split('/')) else: sub_folders = list( download_type.split('/')) + ["submissiondateid"] archive, error = self.submission_manager.get_submission_archive( course, data, sub_folders, simplify="simplify" in user_input) if not error: response = Response(response=archive, content_type='application/x-gzip') response.headers[ 'Content-Disposition'] = 'attachment; filename="submissions.tgz"' return response else: msgs.append( _("The following submission could not be prepared for download: {}" ).format(error)) return self.page(course, params, msgs=msgs) elif "replay" in user_input: if not self.user_manager.has_admin_rights_on_course(course): raise Forbidden(description=_( "You don't have admin rights on this course.")) tasks = course.get_tasks() for submission in data: self.submission_manager.replay_job( tasks[submission["taskid"]], submission) msgs.append( _("{0} selected submissions were set for replay.").format( str(len(data)))) return self.page(course, params, msgs=msgs) elif "page" in user_input: params = self.get_input_params( json.loads(user_input["displayed_selection"]), course) try: page = int(user_input["page"]) except TypeError: page = 1 return self.page(course, params, page=page, msgs=msgs) else: params = self.get_input_params(user_input, course) return self.page(course, params, msgs=msgs)
def page(self, course, params): msgs = [] daterange = [None, None] try: if params.get('date_before', ''): daterange[1] = datetime.strptime(params["date_before"], "%Y-%m-%d %H:%M:%S") if params.get('date_after', ''): daterange[0] = datetime.strptime(params["date_after"], "%Y-%m-%d %H:%M:%S") except ValueError: # If match of datetime.strptime() fails msgs.append(_("Invalid dates")) if daterange[0] is None or daterange[1] is None: now = datetime.now().replace(minute=0, second=0, microsecond=0) daterange = [now - timedelta(days=14), now] params["date_before"] = daterange[1].strftime("%Y-%m-%d %H:%M:%S") params["date_after"] = daterange[0].strftime("%Y-%m-%d %H:%M:%S") display_hours = (daterange[1] - daterange[0]).days < 4 users, tutored_users, audiences, tutored_audiences, tasks, limit = self.get_course_params( course, params) filter, best_submissions_list = self.get_submissions_filter( course, only_tasks=params["tasks"], only_tasks_with_categories=params["org_tags"], only_users=params["users"], only_audiences=params["audiences"], grade_between=[ float(params["grade_min"]) if params.get('grade_min', '') else None, float(params["grade_max"]) if params.get('grade_max', '') else None ], submit_time_between=[ x.strftime("%Y-%m-%d %H:%M:%S") for x in daterange ], keep_only_crashes="crashes_only" in params) stats_tasks = self._tasks_stats(tasks, filter, limit) stats_users = self._users_stats(filter, limit) stats_graph = self._graph_stats(daterange, filter, limit) stats_progress = self._progress_stats(course) stats_global = self._global_stats( tasks, filter, limit, best_submissions_list, params.get('stat', 'normal') == 'pond_stat') if "progress_csv" in flask.request.args: return make_csv(stats_progress) return self.template_helper.render("course_admin/stats.html", course=course, users=users, tutored_users=tutored_users, audiences=audiences, tutored_audiences=tutored_audiences, tasks=tasks, old_params=params, stats_graph=stats_graph, stats_tasks=stats_tasks, stats_users=stats_users, stats_progress=stats_progress, stats_global=stats_global, display_hour=display_hours, msgs=msgs)
def page(self, course, aggregationid): """ Get all data and display the page """ aggregation = self.database.aggregations.find_one( {"_id": ObjectId(aggregationid)}) data = list( self.database.submissions.aggregate([{ "$match": { "courseid": course.get_id(), "username": { "$in": aggregation["students"] } } }, { "$group": { "_id": "$taskid", "tried": { "$sum": 1 }, "succeeded": { "$sum": { "$cond": [{ "$eq": ["$result", "success"] }, 1, 0] } }, "grade": { "$max": "$grade" } } }])) tasks = course.get_tasks() result = dict([(taskid, { "taskid": taskid, "name": tasks[taskid].get_name(self.user_manager.session_language()), "tried": 0, "status": "notviewed", "grade": 0, "url": self.submission_url_generator(aggregationid, taskid) }) for taskid in tasks]) for taskdata in data: if taskdata["_id"] in result: result[taskdata["_id"]]["tried"] = taskdata["tried"] if taskdata["tried"] == 0: result[taskdata["_id"]]["status"] = "notattempted" elif taskdata["succeeded"]: result[taskdata["_id"]]["status"] = "succeeded" else: result[taskdata["_id"]]["status"] = "failed" result[taskdata["_id"]]["grade"] = taskdata["grade"] if "csv" in web.input(): return make_csv(result) results = sorted( list(result.values()), key=lambda result: (tasks[result["taskid"]].get_order(), result["taskid"])) return self.template_helper.get_renderer( ).course_admin.aggregation_info(course, aggregation, results)
def page(self, course, task): """ Get all data and display the page """ user_list = self.user_manager.get_course_registered_users( course, False) users = OrderedDict( sorted(list(self.user_manager.get_users_info(user_list).items()), key=lambda k: k[1][0] if k[1] is not None else "")) individual_results = list( self.database.user_tasks.find({ "courseid": course.get_id(), "taskid": task.get_id(), "username": { "$in": user_list } })) individual_data = OrderedDict([(username, { "username": username, "realname": user[0] if user is not None else "", "email": user[1] if user is not None else "", "url": self.individual_submission_url_generator(task, username), "tried": 0, "grade": 0, "status": "notviewed" }) for username, user in users.items()]) for user in individual_results: individual_data[user["username"]]["tried"] = user["tried"] if user["tried"] == 0: individual_data[user["username"]]["status"] = "notattempted" elif user["succeeded"]: individual_data[user["username"]]["status"] = "succeeded" else: individual_data[user["username"]]["status"] = "failed" individual_data[user["username"]]["grade"] = user["grade"] aggregation_data = OrderedDict() for aggregation in self.user_manager.get_course_aggregations(course): aggregation_data[aggregation['_id']] = { "_id": aggregation['_id'], "description": aggregation['description'], "url": self.aggregation_submission_url_generator(task, aggregation), "tried": 0, "grade": 0, "status": "notviewed", "tutors": aggregation["tutors"], "groups": aggregation["groups"] } aggregation_results = list( self.database.submissions.aggregate([{ "$match": { "courseid": course.get_id(), "taskid": task.get_id(), "username": { "$in": aggregation["students"] } } }, { "$group": { "_id": "$taskid", "tried": { "$sum": 1 }, "succeeded": { "$sum": { "$cond": [{ "$eq": ["$result", "success"] }, 1, 0] } }, "grade": { "$max": "$grade" } } }])) for g in aggregation_results: aggregation_data[aggregation['_id']]["tried"] = g["tried"] if g["tried"] == 0: aggregation_data[ aggregation['_id']]["status"] = "notattempted" elif g["succeeded"]: aggregation_data[ aggregation['_id']]["status"] = "succeeded" else: aggregation_data[aggregation['_id']]["status"] = "failed" aggregation_data[aggregation['_id']]["grade"] = g["grade"] my_aggregations, other_aggregations = [], [] for aggregation in aggregation_data.values(): if self.user_manager.session_username() in aggregation["tutors"]: my_aggregations.append(aggregation) else: other_aggregations.append(aggregation) if "csv" in web.input() and web.input()["csv"] == "students": return make_csv(list(individual_data.values())) elif "csv" in web.input() and web.input()["csv"] == "aggregations": return make_csv(list(aggregation_data.values())) return self.template_helper.get_renderer().course_admin.task_info( course, task, individual_data.values(), [my_aggregations, other_aggregations])
def page(self, course): """ Get all data and display the page """ data = list( self.database.user_tasks.aggregate([{ "$match": { "courseid": course.get_id(), "username": { "$in": self.user_manager.get_course_registered_users( course, False) } } }, { "$group": { "_id": "$taskid", "viewed": { "$sum": 1 }, "attempted": { "$sum": { "$cond": [{ "$ne": ["$tried", 0] }, 1, 0] } }, "attempts": { "$sum": "$tried" }, "succeeded": { "$sum": { "$cond": ["$succeeded", 1, 0] } } } }])) # Load tasks and verify exceptions files = self.task_factory.get_readable_tasks(course) output = {} errors = [] for task in files: try: output[task] = course.get_task(task) except Exception as inst: errors.append({"taskid": task, "error": str(inst)}) tasks = OrderedDict( sorted(list(output.items()), key=lambda t: (t[1].get_order(), t[1].get_id()))) # Now load additional informations result = OrderedDict() for taskid in tasks: result[taskid] = { "name": tasks[taskid].get_name_or_id( self.user_manager.session_language()), "viewed": 0, "attempted": 0, "attempts": 0, "succeeded": 0, "url": self.submission_url_generator(taskid) } for entry in data: if entry["_id"] in result: result[entry["_id"]]["viewed"] = entry["viewed"] result[entry["_id"]]["attempted"] = entry["attempted"] result[entry["_id"]]["attempts"] = entry["attempts"] result[entry["_id"]]["succeeded"] = entry["succeeded"] if "csv" in web.input(): return make_csv(result) return self.template_helper.get_renderer().course_admin.task_list( course, result, errors)