def get_course_data_for_users(cls, courseid, users=None): """ Returns data of users for a specific course. users is a list of username. If users is none, data from all users will be returned. The returned value is a dict: {"username": {"task_tried": 0, "total_tries": 0, "task_succeeded": 0, "task_grades":{"task_1": 100.0, "task_2": 0.0, ...}}} Please note that only the task already seen at least one time will be present in the dict task_grades. """ from frontend.custom.courses import FrontendCourse course = FrontendCourse(courseid) match = {"courseid": courseid} if users is not None: match["username"] = {"$in": users} tasks = course.get_tasks() taskids = tasks.keys() match["taskid"] = {"$in": taskids} data = list(get_database().user_tasks.aggregate( [ {"$match": match}, {"$group": { "_id": "$username", "task_tried": {"$sum": {"$cond": [{"$ne": ["$tried", 0]}, 1, 0]}}, "total_tries": {"$sum": "$tried"}, "task_succeeded": {"$addToSet": {"$cond": ["$succeeded", "$taskid", False]}}, "task_grades": {"$addToSet": {"taskid": "$taskid", "grade": "$grade"}} }} ])) if len(data) != 0: return_data = {} for result in data: username = result["_id"] user_tasks = set([taskid for taskid, task in tasks.iteritems() if task.is_visible_by_user(username)]) result["total_tasks"] = len(user_tasks) result["task_succeeded"] = len(set(result["task_succeeded"]).intersection(user_tasks)) result["task_grades"] = {dg["taskid"]: dg["grade"] for dg in result["task_grades"] if dg["taskid"] in user_tasks} del result["_id"] return_data[username] = result return return_data else: return {}
def GET(self, courseid): # try: course = FrontendCourse(courseid) contest_data = get_contest_data(course) if not contest_data['enabled']: raise web.notfound() start = datetime.strptime(contest_data['start'], "%Y-%m-%d %H:%M:%S") end = datetime.strptime(contest_data['end'], "%Y-%m-%d %H:%M:%S") blackout = end - timedelta(hours=contest_data['blackout']) users = course.get_registered_users(True) tasks = course.get_tasks().keys() db_results = get_database().submissions.find({ "username": {"$in": users}, "courseid": courseid, "submitted_on": {"$gte": start, "$lt": blackout}, "status": "done"}, {"username": True, "_id": False, "taskid": True, "result": True, "submitted_on": True}).sort([("submitted_on", pymongo.ASCENDING)]) task_status = {taskid: {"status": "NA", "tries": 0} for taskid in tasks} results = {username: {"name": UserData(username).get_data()['realname'], "tasks": copy.deepcopy(task_status)} for username in users} activity = [] # Compute stats for each submission task_succeeded = {taskid: False for taskid in tasks} for submission in db_results: if submission['taskid'] not in tasks: continue if submission['username'] not in users: continue status = results[submission['username']]["tasks"][submission['taskid']] if status["status"] == "AC" or status["status"] == "ACF": continue else: if submission['result'] == "success": if not task_succeeded[submission['taskid']]: status["status"] = "ACF" task_succeeded[submission['taskid']] = True else: status["status"] = "AC" status["tries"] += 1 status["time"] = submission['submitted_on'] status["score"] = ((submission['submitted_on'] + ( timedelta(minutes=contest_data["penalty"]) * (status["tries"] - 1))) - start).total_seconds() / 60 elif submission['result'] == "failed": status["status"] = "WA" status["tries"] += 1 elif submission['result'] == "timeout": status["status"] = "TLE" status["tries"] += 1 else: # other internal error continue activity.append({"user": results[submission['username']]["name"], "when": submission['submitted_on'], "result": (status["status"] == 'AC' or status["status"] == 'ACF'), "taskid": submission['taskid']}) activity.reverse() # Compute current score for user in results: score = [0, 0] for data in results[user]["tasks"].values(): if "score" in data: score[0] += 1 score[1] += data["score"] results[user]["score"] = tuple(score) # Sort everybody results = OrderedDict(sorted(results.items(), key=lambda t: (-t[1]["score"][0], t[1]["score"][1]))) # Compute ranking old = None current_rank = 0 for cid, user in enumerate(results.keys()): if results[user]["score"] != old: old = results[user]["score"] current_rank = cid + 1 results[user]["rank"] = current_rank results[user]["displayed_rank"] = str(current_rank) else: results[user]["rank"] = current_rank results[user]["displayed_rank"] = "" return get_template_renderer('plugins/contests', '../../templates/layout').scoreboard(course, start, end, blackout, tasks, results, activity)