Beispiel #1
0
def view_playground(request):
    me = Student.from_request(request)

    # Compile the code and save it in the database.
    good = False
    pattern = None
    name = ""
    if request.method == "POST":
        try:
            old = CodeSubmission.objects.filter(student=me, challenge=None).order_by("-timestamp")[0]
        except:
            old = None

        # Get code from the POST request.
        name = slugify(request.POST.get("name") if request.POST.get("name") else "untitled")[:32]
        code = request.POST.get("code") if request.POST.get("code") else ""
        try:
            pattern = Pattern.objects.get(name=str(request.POST.get("pattern")))
        except:
            pattern = None

        # Save this in the database whether it compiles or not.
        CR = CodeSubmission()
        CR.name = name
        CR.student = me
        CR.code = code
        CR.pattern = pattern
        CR.save()

        good = assembler.assemble_and_store(request, name, code, pattern)
        publish = False
        if "publish" in request.POST and me and not me.banned and good:
            publish = True

        # Convert the last code submission into a diff image, but only save it
        # if the diff is actually smaller than the full code.
        if old and old.published == 0:
            old.parent = CR
            old_code = old.code
            old.code = ""
            for d in difflib.unified_diff(CR.code.splitlines(True), old_code.splitlines(True)):
                old.code += d
            if len(old.code) < len(old_code):
                old.save()

        # Redirect based on which button was clicked.
        if publish:
            CR.published = len(CodeSubmission.objects.filter(published__gt=0)) + 1
            CR.save()
            return redirect("playground")
        elif "download" in request.POST and good:
            return redirect("rom")
        else:
            return redirect("playground")

    # Render the page.
    code = ""
    if "rom_code" in request.session:
        code = request.session["rom_code"]
        pattern = request.session.get("rom_pattern")
        name = str(request.session.get("rom_name"))
    elif me:
        subs = CodeSubmission.objects.filter(student=me, challenge=None).order_by("-timestamp")
        if len(subs) > 0:
            code = subs[0].code
            name = subs[0].name

    # Get recently published games.
    recent = CodeSubmission.objects.filter(published__gt=0).order_by("-timestamp")
    return render(
        request,
        "playground.html",
        {
            "name": name,
            "pattern": pattern,
            "patterns": Pattern.objects.all(),
            "code": code,
            "recently_published": recent[:25],
            "alerts": request.session.pop("alerts", []),
        },
    )
Beispiel #2
0
def view_challenge(request, name):
    me = Student.from_request(request)
    
    # First, try to get the challenge.
    try: challenge = Challenge.objects.get(slug=name)
    except exceptions.ObjectDoesNotExist: raise Http404()
        
    # Find the records for this submission. We need them whether we are viewing
    # or processing.
    my_size, my_speed = 0x10000, 0x10000
    best_size, best_speed = 0x1000000, 0x1000000
    completed = False
    records = CodeSubmission.objects.filter(challenge=challenge, is_correct=True).order_by('rom_size')
    if len(records) > 0:
        best_size = records[0].rom_size
        records = records.order_by('runtime')
        best_speed = records[0].runtime
    records = records.filter(student=me).order_by('rom_size')
    if len(records) > 0:
        my_size = records[0].rom_size
        records = records.order_by('runtime')
        my_speed = records[0].runtime
        completed = True
        
    # If it was a POST request, then we'll take care of that now. This takes
    # care of the side-effects and creates the challenge responses that will be
    # handled below.
    code = ""
    if request.method == "POST":
        try: old = CodeSubmission.objects.filter(student=me, challenge=challenge).order_by('-timestamp')[0]
        except: old = None
        
        code = request.POST.get("code") if "code" in request.POST else ""
        CR = CodeSubmission()
        CR.student = me
        CR.challenge = challenge
        CR.code = code
        CR.is_correct = False if challenge.autograde else None
        CR.save()
        
        # Convert the last code submission into a diff image, but only save it
        # if the diff is actually smaller than the full code.
        if old and len(SOS.objects.filter(submission=old)) == 0:
            old.parent = CR
            old_code = old.code
            old.code = ""
            for d in difflib.unified_diff( CR.code.splitlines(True), old_code.splitlines(True)):
                old.code += d
            if len(old.code) < len(old_code):
                old.save()
        
        # Only try to autograde if the program compiles.
        compiles = assembler.assemble_and_store(request, "challenge%s"%challenge.slug,
                   code, challenge.pattern, challenge.preamble, challenge.postamble)
        if compiles and challenge.autograde:
            completed = me in challenge.completed_by.all()
            results = autograde.grade( challenge, me, code, completed )
            
            # Save its correctness in the database.
            CR.is_correct = True if results else False
            if results: CR.rom_size, CR.runtime = results
            CR.save()
            
            # Award victory if the program is correct.
            if results and not completed:
                challenge.completed_by.add(me)
                challenge.save()
                request.session['alerts'].append(('alert-success',
                                                  '''Congratulations! You completed
                                                  this challenge! Can you make it
                                                  more efficient?'''))
                LogEntry.log(request, "Completed %s"%challenge.slug)
            elif results:
                request.session['alerts'].append(('alert-success',
                                                  '''This solution was %d bytes in
                                                  size and executed %d instructions.'''%results))
                LogEntry.log(request, "%s: %d, %d"%(challenge.slug,results[0],results[1]))
        
        # Is there an SOS involved?
        if "sos" in request.POST and "help" in request.POST:
            for s in SOS.objects.filter(challenge=challenge, student=me):
                s.active = False
                s.save()
        
            s = SOS()
            s.challenge = challenge
            s.submission = CR
            s.content = request.POST["help"]
            s.student = me
            s.save()
        
        # Handle the redirect.
        if "download" in request.POST and compiles:
            return redirect("rom")
        return redirect("challenge", challenge.slug)
    
    # Load the latest submission code to display it on the screen.
    subs = CodeSubmission.objects.filter(student=me, challenge=challenge).order_by('-timestamp')
    if len(subs) > 0: code = subs[0].code
    
    # Try to load up the best submissions by everyone.
    return render(request, "challenge.html", {'challenge': challenge,
                                              'alerts': request.session.pop('alerts', []),
                                              'code': code,
                                              'my_size': my_size,
                                              'my_speed': my_speed,
                                              'best_size': best_size,
                                              'best_speed': best_speed,
                                              'completed': completed,
                                              'feedback': SOS.objects.filter(challenge=challenge, student=me) } )