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", []), }, )
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) } )