vEnhance / helium

Subtree of Helium grader used for Harvard-MIT Math Tournament
Other
6 stars 0 forks source link

Babbage #1

Open circosine opened 5 years ago

circosine commented 5 years ago

Do you have a link to the Babbage software?

vEnhance commented 5 years ago

No, I don't think that's published anywhere.

circosine commented 5 years ago

How would one create a Guts scoreboard to mimic the one found in Babbage?

vEnhance commented 5 years ago

Heh, the actual version that runs for HMMT isn't the best code in the world, but I'll try to describe it. The scoreboard itself is just an HTML file that will periodically query an AJAX hook and then display the results. The AJAX hook will look something like:

guts_exam = He.models.Exam.objects.get(name="Guts") # or however you want to identify it
num_problems = guts_exam.problem_set.count()

data = He.models.Verdict.objects.filter(problem__exam = guts_exam, score__isnull=False)\
        .order_by().values("entity__shortname", "entity__name", "entity__id",
                "problem__allow_partial", "problem__weight", "score")
class GutsTeam:
    def __init__(self, name):
        self.name = name
    score = 0
    progress = 0
    @property
    def progress_width(self):
        return 100 * self.progress / num_problems

score_dict = {} # id -> GutsTeam object
for d in data:
    eid = d['entity__id']
    t = score_dict.get(eid, GutsTeam(d['entity__shortname'] or d['entity__name']))
    t.progress += 1
    if d['problem__allow_partial']:
        t.score += int(d['score'])
    else: # all-or-nothing
        t.score += int(d['problem__weight'] * d['score'])
    score_dict[eid] = t

teams_s = list(score_dict.values())
# Add empty teams
for team in He.models.Entity.teams.all():
    if team.id not in score_dict:
        teams_s.append(GutsTeam(team.shortname or unicode(team)))
teams_s.sort(key=lambda t: -t.score) # sort teams in descending order

That will give you a sorted list of GutsTeam objects. You can then format that into a JSON however you see fit, send it back to the client, which should then (by javascript/jquery) format and display the results.

circosine commented 5 years ago

Thank you for the code! However, I am having some problems implementing this. So far, I have added a few line to import the json and helium modules and attempted to format the GutsTeam objects into a JSON.

import json
import helium as He

guts_exam = He.models.Exam.objects.get(name="Guts") # or however you want to identify it
num_problems = guts_exam.problem_set.count()

data = He.models.Verdict.objects.filter(problem__exam = guts_exam, score__isnull=False)\
        .order_by().values("entity__shortname", "entity__name", "entity__id",
                "problem__allow_partial", "problem__weight", "score")
class GutsTeam:
    def __init__(self, name):
        self.name = name
    score = 0
    progress = 0
    @property
    def progress_width(self):
        return 100 * self.progress / num_problems

score_dict = {} # id -> GutsTeam object
for d in data:
    eid = d['entity__id']
    t = score_dict.get(eid, GutsTeam(d['entity__shortname'] or d['entity__name']))
    t.progress += 1
    if d['problem__allow_partial']:
        t.score += int(d['score'])
    else: # all-or-nothing
        t.score += int(d['problem__weight'] * d['score'])
    score_dict[eid] = t

teams_s = list(score_dict.values())
# Add empty teams
for team in He.models.Entity.teams.all():
    if team.id not in score_dict:
        teams_s.append(GutsTeam(team.shortname or unicode(team)))
teams_s.sort(key=lambda t: -t.score) # sort teams in descending order

GutsDump = json.dumps(GutsTeam.__dict__)
print GutsDump

I executed this python script in the ./manage.py shell of Django using execfile(helium/GutsTeam.py) and got this message: TypeError: <function __init__ at 0x7f227fc6cd70> is not JSON serializable Any clue on how to fix this issue?

vEnhance commented 5 years ago

If you print GutsTeam.__dict__, you'll see why it's not working... this is a bunch of information about the class itself (not even about its objects), which in particular is not something you can JSON-ify. ;)

Maybe you would want to JSON-ify something like [(t.name, t.progress, t.score) for t in teams_s] instead.