def list_badges(request): badge_list = Badge.objects.all() for b in badge_list: try: b.check = True if b.held_by( Student.from_request(request) ) else False except exceptions.ObjectDoesNotExist: b.check = False return render( request, "badge_list.html", {"badge_list":badge_list} )
def view_feedback(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() # Now get all of the SOSses related to this user and challenge. feedback = SOS.objects.filter(challenge=challenge, student=me) # Mark feedback as helpful or not. if "helpful" in request.GET or "unhelpful" in request.GET: helpful = True if "unhelpful" in request.GET: helpful = False f_id = request.GET["helpful" if helpful else "unhelpful"] if f_id.isdigit(): try: f = Feedback.objects.get(id=int(f_id)) if f.sos in feedback and f.helpful is None: f.helpful = helpful f.save() LogEntry.log(request, "Marked as %shelpful"%("" if helpful else "un")) except exceptions.ObjectDoesNotExist: LogEntry.log(request, "Feedback voting naughtiness.") return render(request, "feedback.html", {'challenge': challenge, 'feedback': feedback})
def view_feedback(request, name): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append(("alert-error","Please sign in first.")) return redirect("sign-in") # First, try to get the challenge. try: challenge = Challenge.objects.get(slug=name) except exceptions.ObjectDoesNotExist: raise Http404() # Now get all of the SOSses related to this user and challenge. feedback = SOS.objects.filter(challenge=challenge, student=me) # Mark feedback as helpful or not. if "helpful" in request.GET or "unhelpful" in request.GET: helpful = True if "unhelpful" in request.GET: helpful = False f_id = request.GET["helpful" if helpful else "unhelpful"] if f_id.isdigit(): f = Feedback.objects.get(id=int(f_id)) if f.sos in feedback and f.helpful is None: f.helpful = helpful f.save() if helpful: f.author.award_xp(50) me.award_xp(5) LogEntry.log(request, "Marked as %shelpful"%("" if helpful else "un")) return render(request, "feedback.html", {'challenge': challenge, 'feedback': feedback})
def user_profile(request, username): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append(("alert-error","Please sign in first.")) return redirect("sign-in") try: student = Student.objects.get( user=User.objects.get(username=username) ) except: return redirect("user_list") # If we are doing a POST, then let's affect the output a bit. form = ProfileEditForm( {"bio": me.bio, "twitter": me.twitter, "email": me.public_email} ) if request.method == "POST": form = ProfileEditForm(request.POST) if form.is_valid(): data = form.cleaned_data me.bio = data["bio"] me.public_email = data["email"] me.twitter = data["twitter"] me.save() return redirect( "profile", username=me.username ) else: request.session["alerts"].append(("alert-error", "There were some issues with your profile update.")) for e in form.non_field_errors(): alerts.append( ("alert-error", e ) ) # Render the magic. projects = list(me.owns.all())+list(me.works_on.all()) return render(request, "user_profile.html", {"student": student, "collaborators": student.collaborators(), "projects": projects, "form": form, 'alerts': request.session.pop('alerts', []) } )
def view_board(request, category): me = Student.from_request(request) # First, try to get the board. try: board = DiscussionBoard.objects.get(slug=category) except exceptions.ObjectDoesNotExist: raise Http404() if not board.can_read(me): raise Http404() # Get the page number! page = 0 pagination = 50 if "page" in request.GET and request.GET["page"].isdigit(): page = max(0,int(request.GET["page"])-1) # If this is a POST, we are creating a new topic. Redirect when finished. if request.method == "POST": if board.can_write(me): content = str(request.POST.get("content")) title = content[:100]+"..." if "title" in request.POST: title = request.POST["title"] t = DiscussionTopic() t.author = me t.board = board t.title = title t.save() p = DiscussionPost() p.topic = t p.author = me p.content = content p.save() return redirect( "thread", category=board.slug, thread=t.id ) else: return redirect( "board", category=board.slug ) # Get all of the topics, along with the last person who commented on them # and when that was. topic_tuples = [] topics = DiscussionTopic.objects.filter(board=board) if not me.ta: topics = topics.filter(hidden=False) for t in topics[pagination*page:pagination*(page+1)]: posts = DiscussionPost.objects.filter(topic=t, hidden=False).order_by("-timestamp") count = len(posts) new = False if count == 0: posts = [None] else: new = ( posts[0].timestamp > me.unread_since ) topic_tuples.append( (t,count,posts[0],new) ) return render( request, "forum_topics.html", {'board': board, 'topics': topic_tuples, 'alerts': request.session.pop('alerts', []), 'page': page+1, 'pages': (len(topic_tuples)/pagination)+1, 'can_write': board.can_write(me) } )
def view_board(request, name): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append(("alert-error","Please sign in first.")) return redirect("sign-in") # First, try to get the board. try: board = DiscussionBoard.objects.get(slug=name) except exceptions.ObjectDoesNotExist: raise Http404() if board.restricted > me.level: raise Http404() # Get the page number! page = 0 pagination = 200 if "page" in request.GET and request.GET["page"].isdigit(): page = max(0,int(request.GET["page"])-1) # If this is a POST, we are creating a new topic. Redirect when finished. if request.method == "POST" and (me.level >= board.wrestricted or me.ta): content = str(request.POST.get("content")) title = content[:100]+"..." if "title" in request.POST: title = request.POST["title"] t = DiscussionTopic() t.author = me t.board = board t.title = title t.save() p = DiscussionPost() p.topic = t p.author = me p.content = content p.save() return redirect( "thread", name=board.slug, thread=t.id ) # Get all of the topics, along with the last person who commented on them # and when that was. topic_tuples = [] for t in DiscussionTopic.objects.filter(hidden=False, board=board)[pagination*page:pagination*(page+1)]: posts = DiscussionPost.objects.filter(topic=t, hidden=False).order_by("-timestamp") count = len(posts) new = False if count == 0: posts = [None] else: new = ( posts[0].timestamp > me.last_login ) topic_tuples.append( (t,count,posts[0],new) ) return render( request, "forum_topics.html", {'board': board, 'topics': topic_tuples, 'student': me, 'alerts': request.session.pop('alerts', []), 'page': page+1, 'pages': (len(topic_tuples)/pagination)+1 } )
def handle_login(request): me = Student.from_request(request) if me: request.session["alerts"].append(("alert-error","You are already logged in!")) return redirect("index") request.session["secret_state"] = str(random.randint(100000000,999999999)) return redirect("https://github.com/login/oauth/authorize?client_id=%s&state=%s&scope=user:email"% (settings.GITHUB_ID, request.session["secret_state"]))
def view_thread(request, name, thread): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append(("alert-error","Please sign in first.")) return redirect("sign-in") # First, try to get the challenge, then thread. try: board = DiscussionBoard.objects.get(slug=name) topic = DiscussionTopic.objects.get(id=thread, board=board) except exceptions.ObjectDoesNotExist: raise Http404() if not me.ta and (topic.hidden or board.restricted > me.level): raise Http404() # If this is a POST, we are either replying to someone or we are voting. # Manage permissions respectively and redirect. if request.method == "POST": if "thread" in request.POST and (me.level >= board.wrestricted or me.ta): p = DiscussionPost() p.topic = topic p.author = me p.content = str(request.POST.get("content")) p.save() topic.save() elif "upvote" in request.POST or "downvote" in request.POST: upvote = True if "downvote" in request.POST: upvote = False p_id = request.POST["upvote" if upvote else "downvote"] if p_id.isdigit() and (me.modpoints > 0 or me.ta): p = DiscussionPost.objects.get(id=int(p_id)) if upvote: p.upvotes += 1 else: p.downvotes += 1 request.session["alerts"].append(("alert-success","Post %s."%("upvoted" if upvote else "downvoted"))) LogEntry.log(request, "Thread %s"%("upvoted" if upvote else "downvoted")) p.save() me.modpoints -= 1 me.award_xp(1) me.save() return redirect( "thread", name=board.slug, thread=topic.id ) # Get all of the posts. Start on the last page by default. pagination = 20 posts = DiscussionPost.objects.filter(hidden=False, topic=topic) pages = (len(posts)/pagination)+1 page = pages-1 if "page" in request.GET and request.GET["page"].isdigit(): page = max(0,int(request.GET["page"])-1) return render( request, "forum_thread.html", {'board': board, 'topic': topic, 'student': me, 'posts': posts[pagination*page:pagination*(page+1)], 'alerts': request.session.pop('alerts', []), 'page': page+1, 'pages': pages })
def handle_logout(request): me = Student.from_request(request) if me: logout(request) if "alerts" not in request.session: request.session["alerts"] = [] request.session["alerts"].append(("alert-success","Successfully logged out - come back soon!")) return redirect("index") else: request.session["alerts"].append(("alert-error","You're already logged out!")) return redirect("index")
def view_stage(request, world, stage): try: student = Student.from_request(request) except exceptions.ObjectDoesNotExist: return HttpResponse("Redirect to login") here = get_stage(world, stage) go = "lesson" # if in challenge-first group: go = "challenge" # If there is only one choice, then go to that one. if not here.lesson and here.challenge: go = "challenge" if not here.challenge and here.lesson: go = "lesson" return redirect( go, world = world, stage = stage )
def view_lesson(request, world, stage): try: student = Student.from_request(request) except exceptions.ObjectDoesNotExist: return HttpResponse("Redirect to login") here = get_stage(world, stage) if not here.lesson: if here.challenge: return redirect( "challenge", world = world, stage = stage ) else: raise Http404() #TODO log this as read. return render( request, "lessons_lesson.html", {'world': here.world, 'stage': here } )
def view_thread(request, category, thread): me = Student.from_request(request) # First, try to get the challenge, then thread. try: board = DiscussionBoard.objects.get(slug=category) topic = DiscussionTopic.objects.get(id=thread, board=board) except exceptions.ObjectDoesNotExist: raise Http404() if not board.can_read(me): raise Http404() # If this is a POST, we are either replying to someone or we are voting. # Manage permissions respectively and redirect. if request.method == "POST": if "hide" in request.POST and me.ta: try: p = DiscussionPost.objects.get(id=int(request.POST["hide"])) p.hidden = not p.hidden p.save() except: pass elif "topic" in request.POST and me.ta: if "lock" == request.POST.get("topic"): topic.locked = not topic.locked if "hide" == request.POST.get("topic"): topic.hidden = not topic.hidden topic.save() elif "content" in request.POST and board.can_write(me) and (not topic.locked): p = DiscussionPost() p.topic = topic p.author = me p.content = str(request.POST.get("content")) p.save() topic.save() return redirect( "thread", category=board.slug, thread=topic.id ) # Get all of the posts. Start on the last page by default. pagination = 20 posts = DiscussionPost.objects.filter(topic=topic) if not me.ta: post = posts.filter(hidden=False) pages = (len(posts)/pagination)+1 page = pages-1 if "page" in request.GET and request.GET["page"].isdigit(): page = max(0,int(request.GET["page"])-1) return render( request, "forum_thread.html", {'board': board, 'topic': topic, 'posts': posts[pagination*page:pagination*(page+1)], 'alerts': request.session.pop('alerts', []), 'page': page+1, 'pages': pages, 'can_write': board.can_write(me) })
def create_demo_user(request): me = Student.from_request(request) if not settings.DEMO_MODE: request.session["alerts"].append(("alert-error","Demo users are not enabled at this time.")) return redirect("index") username = "******"%len(Student.objects.all()) user = User.objects.create_user(username, username+"@example.com", str(random.randint(100000000,999999999))) user.save() student = Student(user=user) student.save() user.backend = 'django.contrib.auth.backends.ModelBackend' login(request, user) return redirect("index")
def sign_out(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if me: logout(request) if "alerts" not in request.session: request.session["alerts"] = [] request.session["alerts"].append( ("alert-success", "You have successfully signed out.") ) return redirect("index") else: request.session["alerts"].append( ("alert-success", "You are already signed out.") ) return redirect("sign-in")
def project_list(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # Retrieve GET parameters. filt = request.GET.get("filter") page = request.GET.get("page") if page and page.isdigit(): page = max(0, int(page) - 1) else: page = 0 pagination = 50 # If we get a POST request, we create a new project. if request.method == "POST": name = str(request.POST.get("name")) if len(Project.objects.filter(name="name")) > 0: request.session["alerts"].append( ("alert-error", """A project with that name already exists. Please choose a different name.""")) return redirect("project_list") else: p = Project() p.name = name p.owner = me p.save() return redirect("project", id=p.id) # Filter the project list based on the GET filter parameter. project_list = [] if filt == "watch": project_list = list(me.watches.all()) elif filt == "all": project_list = list(Project.objects.all()) else: project_list = list(me.owns.all()) + list(me.works_on.all()) filt = "mine" project_list = project_list[page * pagination:(page + 1) * pagination] # TODO: Create the spotlight. return render( request, "project_list.html", { 'projects': project_list, 'alerts': request.session.pop('alerts', []), 'page': page + 1, 'pages': (len(project_list) / pagination) + 1, 'filter': filt })
def project_list(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append(("alert-error","Please sign in first.")) return redirect("sign-in") # Retrieve GET parameters. filt = request.GET.get("filter") page = request.GET.get("page") if page and page.isdigit(): page = max(0, int(page)-1) else: page = 0 pagination = 50 # If we get a POST request, we create a new project. if request.method == "POST": name = str(request.POST.get("name")) if len(Project.objects.filter(name="name")) > 0: request.session["alerts"].append(("alert-error", """A project with that name already exists. Please choose a different name.""")) return redirect("project_list") else: p = Project() p.name = name p.owner = me p.save() return redirect("project", id=p.id) # Filter the project list based on the GET filter parameter. project_list = [] if filt == "watch": project_list = list(me.watches.all()) elif filt == "all": project_list = list(Project.objects.all()) else: project_list = list(me.owns.all()) + list(me.works_on.all()) filt = "mine" project_list = project_list[page*pagination:(page+1)*pagination] # TODO: Create the spotlight. return render( request, "project_list.html", {'projects':project_list, 'alerts': request.session.pop('alerts', []), 'page': page+1, 'pages': (len(project_list)/pagination)+1, 'filter': filt } )
def view_index(request): me = Student.from_request(request) if me and me.banned: logout(request) if "alerts" not in request.session: request.session["alerts"] = [] request.session["alerts"].append(("alert-error","""This account has been suspended. If you believe this is in error, please contact the site administrator.""")) return redirect("index") elif me and not me.agreed: return redirect("terms") elif me: return view_dashboard(request, me) return render(request, "index.html", {'alerts': request.session.pop('alerts', []) })
def view_challenge(request, world, stage): try: student = Student.from_request(request) except exceptions.ObjectDoesNotExist: return HttpResponse("Redirect to login") here = get_stage(world, stage) if not here.challenge: if here.lesson: return redirect( "lesson", world = world, stage = stage ) else: raise Http404() # TODO log the view # These are all of the types of challenges. c = here.challenge if hasattr(c, "quizchallenge"): return view_quizchallenge(request, world, stage, c.quizchallenge) raise Http404()
def board_list(request): me = Student.from_request(request) # Get all of the boards that this student can read. Store them in the # board_pairs where they are paired with the number of new posts since their # last visit. board_triplets = [] boards = DiscussionBoard.objects.all() for b in boards: if b.can_read(me): last_posts = b.discussiontopic_set.exclude(hidden=True) new_posts = len( last_posts.filter(last_active__gte=me.unread_since) ) if len(last_posts) == 0: last_posts = [None] visible = False board_triplets.append( (b, last_posts[0], new_posts) ) return render( request, "forums.html", {'boards': board_triplets, 'alerts': request.session.pop('alerts', []) })
def terms_of_use(request): me = Student.from_request(request) # A POST request means that the user has agreed to the terms of use. if request.method == "POST" and me: me.agreed = True me.save() request.session["alerts"].append(("alert-success","Thanks! Welcome to #8bitmooc!")) return redirect("index") # If they've already agreed, let them know. if me and me.agreed: request.session["alerts"].append(("alert-success","You have already agreed to the terms of use.")) # Render the page. return render(request, "terms_of_use.html", {'alerts': request.session.pop('alerts', []) })
def sign_up(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if me: return redirect("index") form = RegistrationForm() if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): data = form.cleaned_data u = User.objects.create_user(data['username'], data['email'], data['password1']) u.is_active = False u.is_admin = False u.save() request.session["alerts"].append(("alert-success", "Please check your e-mail for your verification link.")) #TODO move this email to a file so that it's not so darn ugly. email = """ Howdy, %s! You're almost all set for #8bitmooc - all that's left is to verify your e-mail address. Please click on the following link to activate your account! http://%s/sign-up?username=%s&key=%s """%(u.username, settings.SITE_URL, u.username, hashlib.sha256(u.username+settings.REGISTER_SALT).hexdigest()) # Send an alert email to this individual. send_mail('[8bitmooc] Account Registration', email, '*****@*****.**', [u.email], fail_silently=True) return redirect("sign-in") else: request.session["alerts"].append(("alert-failure", "There was an issue registering your account.")) for e in form.non_field_errors(): alerts.append( ("alert-error", e ) ) return render( request, "sign-up.html", { "form":form, 'alerts': request.session.pop('alerts', []) } ) else: return render(request, 'sign-up.html', {"form":form, 'alerts': request.session.pop('alerts', []) })
def do_playground(request): code = request.POST["code"] a = Assembler() rom, errors = a.assemble(code) # Save this in the database. ACR = AssemblyChallengeResponse() try: ACR.student = Student.from_request(request) except exceptions.ObjectDoesNotExist: pass ACR.code = code ACR.save() # Either run the game in the browser or download it. request.session["rom"] = rom if "run" in request.POST or len(errors) > 0: return render(request, "assembler_playground.html", {"source_code": request.POST["code"], "errors": errors}) else: return get_rom(request)
def view_badge(request, badge): # If the badge doesn't exist, take the user to the list. try: badge = Badge.objects.get(shortname=badge) except exceptions.ObjectDoesNotExist: return redirect( "badge_list" ) # Determine if the User has the badge. try: awarded = True if badge.held_by(Student.from_request(request)) else False except exceptions.ObjectDoesNotExist: awarded = False # To embed the add-to-backpack button in your model, use the following # script: be sure you check to see if the user is authenticated. # <script src="http://beta.openbadges.org/issuer.js"></script> # <script type="text/javascript"> # OpenBadges.issue(["{{ domain }}{% url badge_assert user=user.username badge=badge.shortname %}"],function(errors, successes) {}); # </script> return render( request, "badge_details.html", {"badge":badge, "awarded":awarded, "domain":ISSUER_DOMAIN} )
def search(request): me = Student.from_request(request) LogEntry.log(request, "search for %s"%request) if "query" not in request.GET: return redirect("index") query = request.GET["query"] # Filter! pages = Page.objects.filter(content__icontains=query) results = [] for p in pages: i = p.content.lower().index(query.lower()) results.append( (p.name,"..."+p.content[max(0,i-50):min(len(p.content),i+50)]+"...") ) # TODO search through forum posts return render(request, "search.html", {'results': results, 'query': query, 'alerts': request.session.pop('alerts', []) })
def user_profile(request, username): try: student = User.objects.get(username=username).student except exceptions.ObjectDoesNotExist: request.session["alerts"].append(("alert-error","That user does not exist.")) return redirect("index") me = Student.from_request(request) if request.method == "POST": if me.ta and "ban" in request.POST: student.banned = not student.banned student.agreed = False student.save() return redirect("profile", username=username) return render(request, "profile.html", {'student': student, 'challenges': Challenge.show_for(student), 'published': CodeSubmission.objects.filter(published__gt=0, student=student).order_by('-timestamp'), 'alerts': request.session.pop('alerts', []) })
def world_map(request, world): try: student = Student.from_request(request) except exceptions.ObjectDoesNotExist: return HttpResponse("Redirect to login") try: world = World.objects.get(shortname=world) except exceptions.ObjectDoesNotExist: raise Http404() # Here, we go through all of the stages and find out which ones we can see, # which one we can load, and which ones we've completed. stages = [] completed = student.stage_set.all() for s in world.stage_set.all(): available = True for p in s.prereqs.all(): if p not in completed: available = False if available or (not s.hidden): stages.append( ( s, available, s in completed ) ) return render( request, 'lessons_map.html', {'world': world, 'stage_list': stages} )
def board_list(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append(("alert-error","Please sign in first.")) return redirect("sign-in") # Get all of the boards that this student can read. Store them in the # board_pairs where they are paired with the number of new posts since their # last visit. board_triplets = [] boards = DiscussionBoard.objects.all() if not me.ta: boards = boards.filter(restricted__lte=me.level) for b in boards: last_posts = b.discussiontopic_set.exclude(hidden=True) new_posts = len( last_posts.filter(last_active__gte=me.last_login) ) if len(last_posts) == 0: last_posts = [None] board_triplets.append( (b, last_posts[0], new_posts) ) return render( request, "forums.html", {'boards': board_triplets, 'alerts': request.session.pop('alerts', []) })
def user_list(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append(("alert-error","Please sign in first.")) return redirect("sign-in") # Get all of the GET parameters. filt = request.GET.get("filter") page = request.GET.get("page") if page and page.isdigit(): page = max(0, int(page)-1) else: page = 0 pagination = 99 # Get the students student_list = [] if filt == "teachers": student_list += list(Student.objects.filter(ta=True).order_by("-level","-xp")) elif filt == "collab": student_list += list(me.collaborators()) elif filt == "blocked": student_list += list(me.student_set.all()) else: student_list += list(Student.objects.all().order_by("-level","-xp")) filt = "all" # Break the students into three columns l1,l2,l3 = [],[],[] for s in student_list[pagination*page:pagination*(page+1)]: if len(l2) > len(l3): l3.append(s) elif len(l1) > len(l2): l2.append(s) else: l1.append(s) return render(request, "user_list.html", {"user_columns": (l1,l2,l3), "page": page+1, 'pages': (len(student_list)/pagination)+1, "filter": filt } )
def view_feedback(request, name): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # First, try to get the challenge. try: challenge = Challenge.objects.get(slug=name) except exceptions.ObjectDoesNotExist: raise Http404() # Now get all of the SOSses related to this user and challenge. feedback = SOS.objects.filter(challenge=challenge, student=me) # Mark feedback as helpful or not. if "helpful" in request.GET or "unhelpful" in request.GET: helpful = True if "unhelpful" in request.GET: helpful = False f_id = request.GET["helpful" if helpful else "unhelpful"] if f_id.isdigit(): f = Feedback.objects.get(id=int(f_id)) if f.sos in feedback and f.helpful is None: f.helpful = helpful f.save() if helpful: f.author.award_xp(50) me.award_xp(5) LogEntry.log(request, "Marked as %shelpful" % ("" if helpful else "un")) return render(request, "feedback.html", { 'challenge': challenge, 'feedback': feedback })
def view_playground(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] # Compile the code and save it in the database. good = False if request.method == "POST": code = request.POST.get("code") if "code" in request.POST else "" # Save this in the database whether it compiles or not. CR = ChallengeResponse() CR.student = me CR.code = code CR.save() good = assembler.assemble_and_store(request, "playground", code) if "download" in request.POST and good: return redirect("rom") else: return redirect("playground") # Render the page. code = "; put default code here one day" if 'code' in request.POST: code = request.POST['code'] elif 'source' in request.GET: try: code = Game.objects.get(id=int(request.GET['source'])).code except: pass elif me: subs = ChallengeResponse.objects.filter( student=me).order_by('-timestamp') if len(subs) > 0: code = subs[0].code return render(request, "playground.html", { 'alerts': request.session.pop('alerts', []), 'code': code })
def board_list(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # Get all of the boards that this student can read. Store them in the # board_pairs where they are paired with the number of new posts since their # last visit. board_triplets = [] boards = DiscussionBoard.objects.all() if not me.ta: boards = boards.filter(restricted__lte=me.level) for b in boards: last_posts = b.discussiontopic_set.exclude(hidden=True) new_posts = len(last_posts.filter(last_active__gte=me.last_login)) if len(last_posts) == 0: last_posts = [None] board_triplets.append((b, last_posts[0], new_posts)) return render(request, "forums.html", { 'boards': board_triplets, 'alerts': request.session.pop('alerts', []) })
def challenge_list(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # Get GET parameters, pagination and filters filt = request.GET.get("filter") page = request.GET.get("page") if page and page.isdigit(): page = max(0, int(page) - 1) else: page = 0 pagination = 20 #not used # First get all of the challenges that match the user's level. Then create # a challenge list tuple that contains the challenge, whether the challenge # has been successfully completed, the records for size and speed, and the # number of SOSses. challenge_list = [] complete_set = me.challenge_set.all() for c in Challenge.objects.filter(difficulty__lte=me.level): if c in complete_set or (not c.expired and (not c.prereq or c.prereq in complete_set)): complete = c in complete_set size = 0 speed = 0 size_complete = False speed_complete = False best_size, best_speed = None, None my_size, my_speed = None, None if complete: records = ChallengeResponse.objects.filter( challenge=c, 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 sos = len( SOS.objects.filter(active=True, challenge=c).exclude(student=me)) challenge_list.append((c, complete, my_size, my_size == best_size, my_speed, my_speed == best_speed, sos)) # Filter challenges. filtered_list = [] if filt == "all": filtered_list = challenge_list elif filt == "size": filtered_list = [c for c in challenge_list if not c[3]] elif filt == "speed": filtered_list = [c for c in challenge_list if not c[5]] elif filt == "sos": filtered_list = [c for c in challenge_list if c[6]] else: filtered_list = [c for c in challenge_list if not c[1]] filt = "incomplete" # Break the challenges into two columns. If we decide to do pagination, do it # here. l1, l2 = [], [] for c in filtered_list: if len(l1) > len(l2): l2.append(c) else: l1.append(c) return render( request, "challenge_list.html", { 'challenge_columns': (l1, l2), 'alerts': request.session.pop('alerts', []), 'filter': filt })
def view_project(request, id): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # Make sure the game exists and we are allowed to see it. try: project = Project.objects.get(id=id) except exceptions.ObjectDoesNotExist: return redirect("project_list") # If we have a POST request, then we need to save the changes we make. # We need to come up with a way to improve working together on projects. is_owner = (me == project.owner) can_edit = (is_owner or me in project.team.all()) if request.method == "POST": if can_edit: old_code = project.code project.code = str(request.POST.get("code")) commit = ProjectCommit() commit.author = me commit.project = project commit.diff = "" for d in difflib.unified_diff(old_code.splitlines(), project.code.splitlines()): commit.diff += d + "\n" commit.save() try: project.pattern = Pattern.objects.get( name=request.POST.get("pattern")) except exceptions.ObjectDoesNotExist: project.pattern = None project.save() if "watch" in request.POST: if request.POST[ "watch"] == "true" and me not in project.watched_by.all(): project.watched_by.add(me) elif request.POST[ "watch"] == "false" and me in project.watched_by.all(): project.watched_by.remove(me) project.save() if "adduser" in request.POST and is_owner: try: newguy = Student.objects.get(user=User.objects.get( username=request.POST.get("username"))) project.team.add(newguy) project.save() except exceptions.ObjectDoesNotExist: request.session["alerts"].append(( "alert-error", "Could not find the specifed user. Did you type it in wrong?" )) if "removeuser" in request.POST and is_owner: try: newguy = Student.objects.get(user=User.objects.get( username=request.POST.get("username"))) if newguy in project.team.all(): project.team.remove(newguy) project.save() except exceptions.ObjectDoesNotExist: request.session["alerts"].append(( "alert-error", "Could not find the specifed user. Did you type it in wrong?" )) # Now compile, publish, and download, as specified. good = assembler.assemble_and_store(request, slugify(project.name), project.code, project.pattern) if "download" in request.POST: return redirect("rom") elif "publish" in request.POST: project.version += 1 project.save() g = Game() g.title = project.name + (" (version %d)" % project.version if project.version > 1 else "") g.code = project.code g.pattern = project.pattern g.description = str(request.POST.get("description")) g.save() g.authors.add(project.owner) for t in project.team.all(): g.authors.add(t) g.save() return redirect("play", id=g.id) else: return redirect("project", id=project.id) # If we decided we wanted to download the code then we download it. return render( request, "project.html", { 'alerts': request.session.pop('alerts', []), 'project': project, 'patterns': Pattern.objects.all(), 'can_edit': can_edit })
def sign_in(request): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if me: return redirect("index") if request.method == "POST": if request.POST.get("sign-up") == "sign-up": return redirect("sign-up") elif "username" in request.POST and "password" in request.POST: username = request.POST.get("username") password = request.POST.get("password") user = authenticate(username=username, password=password) if user is not None: if Student.objects.filter(user=user).exists(): login(request, user) s = user.student s.last_login = s.this_login s.this_login = timezone.now() if s.last_login is None: s.last_login = s.this_login if s.last_login.day != s.this_login.day: s.modpoints = s.level s.save() return redirect("index") else: request.session["alerts"].append(("alert-error", """This account has not yet been activated. Please check your e-mail for the activation link.""")) return redirect("sign-in") else: request.session["alerts"].append(("alert-error", """Incorrect username or password.""")) return redirect("sign-in") else: return redirect("sign-in") elif "key" in request.GET and "username" in request.GET: key = request.GET["key"] username = request.GET["username"] # Redirect to login if the user account does not exist or has already # been activated. try: user = User.objects.get(username=username) except exceptions.ObjectDoesNotExist: return redirect("sign-in") if Student.objects.filter(user=user).exists(): return redirect("sign-in") # Verify the hash and redirect if it doesn't match. if hashlib.sha256(username+settings.REGISTER_SALT).hexdigest() != key: return redirect("sign-in") # Assuming everything went well... S = Student( user=user ) S.save() user.is_active = True user.save() request.session["alerts"].append(("alert-success", """Verification successful! You may now sign in!.""")) return render(request, "sign-in.html", {'alerts': request.session.pop('alerts', []) }) else: return render(request, "sign-in.html", {'alerts': request.session.pop('alerts', []) })
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_board(request, name): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # First, try to get the board. try: board = DiscussionBoard.objects.get(slug=name) except exceptions.ObjectDoesNotExist: raise Http404() if board.restricted > me.level: raise Http404() # Get the page number! page = 0 pagination = 200 if "page" in request.GET and request.GET["page"].isdigit(): page = max(0, int(request.GET["page"]) - 1) # If this is a POST, we are creating a new topic. Redirect when finished. if request.method == "POST" and (me.level >= board.wrestricted or me.ta): content = str(request.POST.get("content")) title = content[:100] + "..." if "title" in request.POST: title = request.POST["title"] t = DiscussionTopic() t.author = me t.board = board t.title = title t.save() p = DiscussionPost() p.topic = t p.author = me p.content = content p.save() return redirect("thread", name=board.slug, thread=t.id) # Get all of the topics, along with the last person who commented on them # and when that was. topic_tuples = [] for t in DiscussionTopic.objects.filter( hidden=False, board=board)[pagination * page:pagination * (page + 1)]: posts = DiscussionPost.objects.filter( topic=t, hidden=False).order_by("-timestamp") count = len(posts) new = False if count == 0: posts = [None] else: new = (posts[0].timestamp > me.last_login) topic_tuples.append((t, count, posts[0], new)) return render( request, "forum_topics.html", { 'board': board, 'topics': topic_tuples, 'student': me, 'alerts': request.session.pop('alerts', []), 'page': page + 1, 'pages': (len(topic_tuples) / pagination) + 1 })
def view_thread(request, name, thread): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # First, try to get the challenge, then thread. try: board = DiscussionBoard.objects.get(slug=name) topic = DiscussionTopic.objects.get(id=thread, board=board) except exceptions.ObjectDoesNotExist: raise Http404() if not me.ta and (topic.hidden or board.restricted > me.level): raise Http404() # If this is a POST, we are either replying to someone or we are voting. # Manage permissions respectively and redirect. if request.method == "POST": if "thread" in request.POST and (me.level >= board.wrestricted or me.ta): p = DiscussionPost() p.topic = topic p.author = me p.content = str(request.POST.get("content")) p.save() topic.save() elif "upvote" in request.POST or "downvote" in request.POST: upvote = True if "downvote" in request.POST: upvote = False p_id = request.POST["upvote" if upvote else "downvote"] if p_id.isdigit() and (me.modpoints > 0 or me.ta): p = DiscussionPost.objects.get(id=int(p_id)) if upvote: p.upvotes += 1 else: p.downvotes += 1 request.session["alerts"].append( ("alert-success", "Post %s." % ("upvoted" if upvote else "downvoted"))) LogEntry.log( request, "Thread %s" % ("upvoted" if upvote else "downvoted")) p.save() me.modpoints -= 1 me.award_xp(1) me.save() return redirect("thread", name=board.slug, thread=topic.id) # Get all of the posts. Start on the last page by default. pagination = 20 posts = DiscussionPost.objects.filter(hidden=False, topic=topic) pages = (len(posts) / pagination) + 1 page = pages - 1 if "page" in request.GET and request.GET["page"].isdigit(): page = max(0, int(request.GET["page"]) - 1) return render( request, "forum_thread.html", { 'board': board, 'topic': topic, 'student': me, 'posts': posts[pagination * page:pagination * (page + 1)], 'alerts': request.session.pop('alerts', []), 'page': page + 1, 'pages': pages })
def view_challenge(request, name): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # First, try to get the challenge. try: challenge = Challenge.objects.get(slug=name) except exceptions.ObjectDoesNotExist: raise Http404() feedback = len(SOS.objects.filter(challenge=challenge, student=me)) # Now make sure that the student can actually see the challenge before # letting them look at it. They can see expired challenges, but can't # submit to them. if challenge.difficulty > me.level: request.session["alerts"].append( ("alert-error", """You need to reach level %d before you can attempt this challenge.""" % challenge.difficulty)) return redirect("challenge_list") if challenge.prereq and challenge.prereq not in me.challenge_set.all(): request.session["alerts"].append( ("alert-error", """You have not unlocked this challenge yet.""")) return redirect("challenge_list") # 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. if request.method == "POST": if challenge.autograde: do_asm_challenge(request, me, challenge) elif challenge.is_jam: do_jam_challenge(request, me, challenge) if "download" in request.POST: good = True for e in request.session['alerts']: if e[0] == 'alert-error': good = False if good: return redirect("rom") else: return redirect("challenge", name=challenge.slug) # Display the correct challenge page depending on whether it's autograded # or a URL. if challenge.autograde: code = "" subs = ChallengeResponse.objects.filter( student=me, challenge=challenge).order_by('-timestamp') if len(subs) > 0: code = subs[0].code # Get the record speeds and sizes for everything. my_size, my_speed = None, None best_size, best_speed = None, None completed = False records = ChallengeResponse.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 # Try to load up the best submissions by everyone. return render( request, "challenge_asm.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, 'badge_domain': settings.ISSUER_DOMAIN, 'feedback': feedback }) elif challenge.is_jam: # Grey out the submission if the student has already submitted a link for # this challenge or if it's expired. records = ChallengeResponse.objects.filter(challenge=challenge, student=me) url = "" submit_ok = True completed = me in challenge.completed_by.all() if len(records) > 0: url = records[0].code if records[0].is_correct is not None: submit_ok = False if challenge.expired: submit_ok = False return render( request, "challenge_jam.html", { 'challenge': challenge, 'alerts': request.session.pop('alerts', []), 'url': url, 'submit_ok': submit_ok, 'completed': completed, 'badge_domain': settings.ISSUER_DOMAIN, 'feedback': feedback }) else: completed = me in challenge.completed_by.all() return render( request, "challenge_other.html", { 'challenge': challenge, 'alerts': request.session.pop('alerts', []), 'completed': completed, 'badge_domain': settings.ISSUER_DOMAIN, 'feedback': feedback })
def view_sos(request, name): me = Student.from_request(request) if "alerts" not in request.session: request.session["alerts"] = [] if not me: request.session["alerts"].append( ("alert-error", "Please sign in first.")) return redirect("sign-in") # First, try to get the challenge. try: challenge = Challenge.objects.get(slug=name) except exceptions.ObjectDoesNotExist: raise Http404() if challenge not in me.challenge_set.all(): request.session["alerts"].append(( "alert-error", "You must complete this challenge before you can respond to an SOS." )) return redirect("challenge_list") # If this is a POST request, we are responding. if request.method == "POST": if "id" in request.POST and request.POST["id"] == request.session.get( "sos-id"): target = SOS.objects.get(id=int(request.session.pop("sos-id"))) fb = Feedback() fb.author = me fb.sos = target fb.content = str(request.POST.get("response")) fb.confidence = True if request.POST.get("confident") else False fb.good = True if request.POST.get("good") else False fb.save() if (len(target.feedback_set.all()) >= 3): target.active = False target.save() request.session["alerts"].append( ("alert-success", """Thank you for helping your classmates by participating in the SOS system! (+10 XP)""")) me.award_xp(10) LogEntry.log(request, "SOS for %s" % (challenge.slug)) else: request.session["alerts"].append( ("alert-error", """There was an error with your SOS submission.""")) LogEntry.log(request, "Botched SOS job.") return redirect("challenge_list") # Now find out if there are any SOS requests. all_sos = list( SOS.objects.filter(active=True, challenge=challenge).exclude(student=me)) if len(all_sos) == 0: request.session["alerts"].append( ("alert-error", "There are no active SOS requests for this challenge.")) return redirect("challenge_list") # Now find an SOS to respond to. Make sure that we haven't already responded # to it. random.shuffle(all_sos) target = None while len(all_sos) > 0 and target is None: x = all_sos.pop() feedbacks = Feedback.objects.filter(sos=x, author=me) if len(feedbacks) == 0: target = x if target is None: request.session["alerts"].append(( "alert-error", "You have already responded to all active SOS requests for this challenge!" )) return redirect("challenge_list") # Filtering is now over. Time to render. request.session["sos-id"] = str(target.id) if challenge.autograde: assembler.assemble_and_store(request, "challenge", target.submission.code, challenge.pattern, challenge.preamble, challenge.postamble) return render( request, "sos_asm.html", { 'challenge': challenge, 'alerts': request.session.pop('alerts', []), 'sos': target }) elif challenge.is_jam: return redirect("challenge_list") else: return redirect("challenge_list")
def webchat(request): me = Student.from_request(request) LogEntry.log(request, "chat") return render(request, "chat.html")