{"action":"created","comment":{"url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/comments/24715077","id":24715077,"diff_hunk":"@@ -17,65 +17,235 @@\n     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n     SOFTWARE.\n     '''\n-\n-from django.http import HttpResponse\n+from django.core.exceptions import PermissionDenied\n+from django.http import HttpResponseRedirect\n+from django.http import Http404\n from django.shortcuts import render,get_object_or_404\n from datetime import datetime\n from index.views import custom_proc\n from django.template import RequestContext\n+from django.forms.models import model_to_dict\n \n-def index(request):\n-    \n-    problem1 = {'id':1,'name':'First Problem','ppl_pass':2,'ppl_not_pass':4}\n-    problem2 = {'id':2,'name':'Second Problem','ppl_pass':1,'ppl_not_pass':8}\n-    problem3 = {'id':3,'name':'third Problem','ppl_pass':5,'ppl_not_pass':1}\n-    problemList = [problem1,problem2,problem3]\n+from contest.models import Contest\n+from contest.models import Contestant\n+from contest.models import Clarification\n \n-    ppl1 = {'name':'naruto'}\n-    ppl2 = {'name':'obama'}\n-    \n-    contestantList = [ppl1,ppl2]\n+from contest.forms import ContestForm\n \n-    ppl3 = {'name':'forest'}\n-    ppl4 = {'name':'gump'}\n+from problem.models import Problem\n+from problem.models import Testcase\n+from problem.models import Submission\n+from problem.models import SubmissionDetail\n \n-    coownerList = [ppl3,ppl4]\n+from utils.log_info import get_logger\n+from utils import user_info\n \n-    contest1 = {'id':1,'name':'First contest','start_time':'2014/11/29 10:11:22','end_time':'2014/12/05 02:12:50',\n-                'contestant_number':200,'owner':'ma in joe','problem_list':problemList,'contestant_list':contestantList,\n-                'coowner_list':coownerList}\n \n-    contestList = [contest1]\n+logger = get_logger()\n \n-    #contest_list = Contest.objects.order_by('-contest_id')\n-    #problem_list = Problem.objects.all()\n-    #contestant_list = {1:'naruto',2:'obama'}\n-    #coowner_list = {1:'teemo',2:'lux',3:'jinx'}\n-    return render(request, 'contest/contestArchive.html',{'contest_list':contestList,'admin':1},\n-                context_instance = RequestContext(request, processors = [custom_proc]))\n+def archive(request):\n+    #to store contest basic info and contestants\n+    contest_list = []\n+    #store contest basic info only\n+    contest_info_list = Contest.objects.order_by('-start_time')\n+    for contest in contest_info_list:\n+        contestants = Contestant.objects.filter(contest = contest)\n+        contest_list.append({'contest':contest,'contestants':contestants})\n \n-def contest(request,contest_id):\n+    user = request.user\n \n-    serverTime = datetime.now().strftime('%Y/%m/%d %H:%M:%S')\n+    return render(request, 'contest/contestArchive.html',\n+        {'contest_list':contest_list,'user':user},\n+        context_instance = RequestContext(request, processors = [custom_proc]))\n \n-    problem1 = {'id':1,'name':'First Problem','ppl_pass':2,'ppl_not_pass':4}\n-    problem2 = {'id':2,'name':'Second Problem','ppl_pass':1,'ppl_not_pass':8}\n-    problem3 = {'id':3,'name':'third Problem','ppl_pass':5,'ppl_not_pass':1}\n-    problemList = [problem1,problem2,problem3]\n+def contest(request,contest_id):\n \n-    ppl1 = {'name':'naruto','score':['0/3','1/2','1/4'],'solved':'2','panalty':'833'}\n-    ppl2 = {'name':'obama','score':['0/2','1/5','1/3'],'solved':'2','panalty':'83'}\n+    serverTime = datetime.now().strftime('%Y/%m/%d %H:%M:%S')\n+    try:\n+        contest = Contest.objects.get(id = contest_id)\n+    except Contest.DoesNotExist: \n+        logger.warning('Contest: Can not find contest %s!' % contest_id)\n+        raise Http404('Contest does not exist')\n     \n-    contestantList = [ppl1,ppl2]\n-\n-    clarification1 = {'id':1,'name':'First Problem','asker':'obama','content':'i have some problem','reply':'shut up'}\n-\n-    clarificationList = [clarification1]\n+    clarification_list = Clarification.objects.filter(contest = contest)\n+    contestant_list = Contestant.objects.filter(contest = contest)\n+    \n+    ### get penalty scoreboard ###\n+\n+    #store contestants' submission dictionary\n+    submission_list = []\n+    #temporary store single contestant submission\n+    contestant_submission_list = []\n+    for contestant in contestant_list:\n+        for problem in contest.problem.all():\n+            submission = Submission.objects.filter(problem = problem , submit_time__lte = contest.end_time,\n+                submit_time__gte = contest.start_time , user = contestant.user)\n+            contestant_submission_list.append(submission)\n+        \n+        submission_list.append({'contestant_submission_list':contestant_submission_list})\n+        contestant_submission_list = []\n+    \n+    #store all contestants' data\n+    scoreboard = []\n+    #store single contestant score\n+    contestant_scoreboard = []\n+    #store single problem status (pass or not)\n+    status = {}\n+    #store single problem submit times\n+    times = {}\n+    #store single problem penalty\n+    penalty = {}\n+\n+    #get single contestant\n+    for contestant_submission_list in submission_list:\n+        times = {}\n+        status = {}\n+        #count penalty\n+        total_penalty = 0\n+        #count solved\n+        solved = 0\n+        contestant = []\n+        #get single contestant's submissions\n+        for submissions in contestant_submission_list['contestant_submission_list']:\n+            #get single contestant's single submission\n+            for submission in submissions:\n+                #count single problem submission times\n+                times[submission.problem.id] = times.get(submission.problem.id,0) + 1  \n+                if submission.status == Submission.ACCEPTED:\n+                    #status[problem name] = 1 if problem is solved\n+                    status[submission.problem.id] = 1\n+                    #get single problem penalty\n+                    penalty[submission.problem.id] = penalty.get(submission.problem.id,0) + (submission.submit_time - contest.start_time).total_seconds()/60\n+                else:\n+                    # 20 is penalty if wrong submission\n+                    penalty[submission.problem.id] = penalty.get(submission.problem.id,0) + 20\n+                contestant = submission.user\n+            #calculate penalty and solved\n+            solved = 0\n+            for problem in contest.problem.all():\n+                if status.get(problem.id,0) == 1:\n+                    solved += 1\n+                    total_penalty += penalty[problem.id]\n+\n+\n+            contestant_scoreboard = {'status':status,'times':times,'penalty':total_penalty,'solved':solved}\n+        scoreboard.append({'contestant':contestant,'contestant_scoreboard':contestant_scoreboard})\n+        contestant_scoreboard = []\n+\n+    #ppl_pass instead of pass to avoid using python reserved word\n+    ppl_pass = {}\n+\n+    not_pass = {}\n+\n+    ### get pass rate ###\n+    for problem in contest.problem.all():\n+        for contestant_data in scoreboard:\n+            status = contestant_data['contestant_scoreboard']['status']\n+            if status.get(problem.id,0) == 1:\n+                ppl_pass[problem.id] = ppl_pass.get(problem.id,0) + 1\n+            else:\n+                not_pass[problem.id] = not_pass.get(problem.id,0) + 1\n+\n+    problem_pass_rate = {'pass':ppl_pass,'not_pass':not_pass}\n+    \n+    ### get testcase scoreboard ###\n+    testcase_scoreboard = {}\n+    # store single contestant testcase-based score\n+    contestant_testcase_scoreboard = {}\n+    # store single problem passed testcase number\n+    testcase_status = {}\n+    # store single problem total testcase number\n+    testcase_number = {}\n+    if submission_list.__len__() != 0:\n+        # single contestant's all submission\n+        for contestant_submission_list in submission_list:\n+            testcase_status = {}\n+            testcase_number = {}\n+            testcase_contestant_name = \"\"\n+            # each problem's submissions\n+            for submissions in contestant_submission_list['contestant_submission_list']:\n+                #each submission\n+                for submission in submissions:\n+                    submission_detail = SubmissionDetail.objects.filter(sid = submission)\n+                    accepted_count = 0\n+                    for testcase in submission_detail.all():\n+                        if testcase.virdect == SubmissionDetail.AC:\n+                            accepted_count += 1\n+                    if accepted_count >= testcase_status.get(submission.problem.id,0):\n+                        testcase_status[submission.problem.id] = accepted_count\n+                    testcase_number[submission.problem.id] = Testcase.objects.filter(problem = submission.problem).__len__()\n+                    testcase_contestant_name = submission.user.username\n+            contestant_testcase_scoreboard = {'status':testcase_status,'number':testcase_number}\n+            testcase_scoreboard[testcase_contestant_name] = {'contestant_scoreboard':contestant_testcase_scoreboard}\n+            contestant_testcase_scoreboard = []\n+\n+    return render(request, 'contest/contest.html',{'contest':contest,'clarification_list':clarification_list,\n+        'contestant_list':contestant_list,'contestant_number':contestant_list.__len__(),\n+        'scoreboard':scoreboard,'testcase_scoreboard':testcase_scoreboard,\n+        'server_time':serverTime,'problem_pass_rate':problem_pass_rate},\n+        context_instance = RequestContext(request, processors = [custom_proc]))\n \n-    contest1 = {'name':'First contest','start_time':'2014/12/27 15:30:00','end_time':'2014/12/27 16:00:00',\n-                    'contest_contestant':200,'contest_owner':'ma in joe','problem_list':problemList,'contestant_list':contestantList\n-                    ,'clarification_list':clarificationList}\n+def new(request):\n+    if request.user.has_judge_auth():\n+        if request.method == 'GET':\n+            form = ContestForm()\n+            return render(request,'contest/editContest.html',{'form':form})\n+        if request.method == 'POST':\n+            form = ContestForm(request.POST)\n+            if form.is_valid():\n+                new_contest = form.save()\n+                logger.info('Contest: Create a new contest %s!' % new_contest.id)\n+                return HttpResponseRedirect('/contest/')\n+    else:\n+        raise PermissionDenied\n+    \n \n-    return render(request, 'contest/contest.html',{'contest':contest1,'problem_list':problemList,\n-        'contestant_list':contestantList,'server_time':serverTime},\n-        context_instance = RequestContext(request, processors = [custom_proc]))\n+def edit(request,contest_id):\n+    contest = get_object_or_404(Contest,id = contest_id)\n+    if user_info.has_c_ownership(request.user,contest):\n+        if request.method == 'GET':        \n+            contest_dic = model_to_dict(contest)\n+            form = ContestForm(initial = contest_dic)\n+            return render(request,'contest/editContest.html',{'form':form})\n+        if request.method == 'POST':\n+            form = ContestForm(request.POST, instance = contest)\n+            if form.is_valid():\n+                modified_contest = form.save()\n+                logger.info('Contest: Modified contest %s!' % modified_contest.id)\n+                return HttpResponseRedirect('/contest/')\n+    else:\n+        raise PermissionDenied\n+\n+def delete(request,contest_id):\n+    try:\n+        contest = Contest.objects.get(id = contest_id)\n+    except Contest.DoesNotExist:\n+        logger.warning('Contest: Can not delete contest %s! Contest not found!' % contest_id)\n+        raise Http404(\"Contest does not exist, can not delete.\")\n+        \n+    if user_info.has_c_ownership(request.user,contest):\n+        deleted_contest_id = contest.id\n+        contest.delete()\n+        logger.info('Contest: Delete contest %s!' % deleted_contest_id)\n+        return HttpResponseRedirect('/contest/')\n+    else:\n+        raise PermissionDenied\n+\n+def register(request,contest_id):\n+    #check contest's existance\n+    try:\n+        contest = Contest.objects.get(id = contest_id)\n+    except Contest.DoesNotExist:\n+        logger.warning('Contest: Can not register contest %s! Contest not found!' % contest_id)\n+        raise Http404(\"Contest does not exist, can not register.\")\n+    #check contestant existance\n+    try:","path":"contest/views.py","position":272,"original_position":270,"commit_id":"54f0280e9edbb384a1175142485299272d7247a9","original_commit_id":"aa0203af5ee2d162c8a644308b837fce40292385","user":{"login":"nickelcheng","id":10057984,"avatar_url":"https://avatars.githubusercontent.com/u/10057984?v=3","gravatar_id":"","url":"https://api.github.com/users/nickelcheng","html_url":"https://github.com/nickelcheng","followers_url":"https://api.github.com/users/nickelcheng/followers","following_url":"https://api.github.com/users/nickelcheng/following{/other_user}","gists_url":"https://api.github.com/users/nickelcheng/gists{/gist_id}","starred_url":"https://api.github.com/users/nickelcheng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nickelcheng/subscriptions","organizations_url":"https://api.github.com/users/nickelcheng/orgs","repos_url":"https://api.github.com/users/nickelcheng/repos","events_url":"https://api.github.com/users/nickelcheng/events{/privacy}","received_events_url":"https://api.github.com/users/nickelcheng/received_events","type":"User","site_admin":false},"body":"I tried the duplicate contestant adding and found that django will raise a  IntegrityError.\r\nSo it should be good to keep this try-except part.\r\nHowever, I prefer contestant.exist() because it is better to read.","created_at":"2015-02-14T15:50:33Z","updated_at":"2015-02-14T15:50:33Z","html_url":"https://github.com/bruce3557/NTHUOJ_web/pull/30#discussion_r24715077","pull_request_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30","_links":{"self":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/comments/24715077"},"html":{"href":"https://github.com/bruce3557/NTHUOJ_web/pull/30#discussion_r24715077"},"pull_request":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30"}}},"pull_request":{"url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30","id":28569038,"html_url":"https://github.com/bruce3557/NTHUOJ_web/pull/30","diff_url":"https://github.com/bruce3557/NTHUOJ_web/pull/30.diff","patch_url":"https://github.com/bruce3557/NTHUOJ_web/pull/30.patch","issue_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/issues/30","number":30,"state":"open","locked":false,"title":"Can add contest. Can show database data","user":{"login":"Changron","id":9431996,"avatar_url":"https://avatars.githubusercontent.com/u/9431996?v=3","gravatar_id":"","url":"https://api.github.com/users/Changron","html_url":"https://github.com/Changron","followers_url":"https://api.github.com/users/Changron/followers","following_url":"https://api.github.com/users/Changron/following{/other_user}","gists_url":"https://api.github.com/users/Changron/gists{/gist_id}","starred_url":"https://api.github.com/users/Changron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Changron/subscriptions","organizations_url":"https://api.github.com/users/Changron/orgs","repos_url":"https://api.github.com/users/Changron/repos","events_url":"https://api.github.com/users/Changron/events{/privacy}","received_events_url":"https://api.github.com/users/Changron/received_events","type":"User","site_admin":false},"body":"Can add/edit contest\r\nCan show contest detail in popup\r\nCan show scoreboard testcase-based and panelty-based","created_at":"2015-02-03T16:57:52Z","updated_at":"2015-02-14T15:50:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d33833f7ec0d0e715dd29399c3065114aee38e31","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30/commits","review_comments_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30/comments","review_comment_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/comments/{number}","comments_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/issues/30/comments","statuses_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/statuses/54f0280e9edbb384a1175142485299272d7247a9","head":{"label":"Changron:dev","ref":"dev","sha":"54f0280e9edbb384a1175142485299272d7247a9","user":{"login":"Changron","id":9431996,"avatar_url":"https://avatars.githubusercontent.com/u/9431996?v=3","gravatar_id":"","url":"https://api.github.com/users/Changron","html_url":"https://github.com/Changron","followers_url":"https://api.github.com/users/Changron/followers","following_url":"https://api.github.com/users/Changron/following{/other_user}","gists_url":"https://api.github.com/users/Changron/gists{/gist_id}","starred_url":"https://api.github.com/users/Changron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Changron/subscriptions","organizations_url":"https://api.github.com/users/Changron/orgs","repos_url":"https://api.github.com/users/Changron/repos","events_url":"https://api.github.com/users/Changron/events{/privacy}","received_events_url":"https://api.github.com/users/Changron/received_events","type":"User","site_admin":false},"repo":{"id":27538510,"name":"NTHUOJ_web","full_name":"Changron/NTHUOJ_web","owner":{"login":"Changron","id":9431996,"avatar_url":"https://avatars.githubusercontent.com/u/9431996?v=3","gravatar_id":"","url":"https://api.github.com/users/Changron","html_url":"https://github.com/Changron","followers_url":"https://api.github.com/users/Changron/followers","following_url":"https://api.github.com/users/Changron/following{/other_user}","gists_url":"https://api.github.com/users/Changron/gists{/gist_id}","starred_url":"https://api.github.com/users/Changron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Changron/subscriptions","organizations_url":"https://api.github.com/users/Changron/orgs","repos_url":"https://api.github.com/users/Changron/repos","events_url":"https://api.github.com/users/Changron/events{/privacy}","received_events_url":"https://api.github.com/users/Changron/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Changron/NTHUOJ_web","description":"","fork":true,"url":"https://api.github.com/repos/Changron/NTHUOJ_web","forks_url":"https://api.github.com/repos/Changron/NTHUOJ_web/forks","keys_url":"https://api.github.com/repos/Changron/NTHUOJ_web/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Changron/NTHUOJ_web/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Changron/NTHUOJ_web/teams","hooks_url":"https://api.github.com/repos/Changron/NTHUOJ_web/hooks","issue_events_url":"https://api.github.com/repos/Changron/NTHUOJ_web/issues/events{/number}","events_url":"https://api.github.com/repos/Changron/NTHUOJ_web/events","assignees_url":"https://api.github.com/repos/Changron/NTHUOJ_web/assignees{/user}","branches_url":"https://api.github.com/repos/Changron/NTHUOJ_web/branches{/branch}","tags_url":"https://api.github.com/repos/Changron/NTHUOJ_web/tags","blobs_url":"https://api.github.com/repos/Changron/NTHUOJ_web/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Changron/NTHUOJ_web/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Changron/NTHUOJ_web/git/refs{/sha}","trees_url":"https://api.github.com/repos/Changron/NTHUOJ_web/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Changron/NTHUOJ_web/statuses/{sha}","languages_url":"https://api.github.com/repos/Changron/NTHUOJ_web/languages","stargazers_url":"https://api.github.com/repos/Changron/NTHUOJ_web/stargazers","contributors_url":"https://api.github.com/repos/Changron/NTHUOJ_web/contributors","subscribers_url":"https://api.github.com/repos/Changron/NTHUOJ_web/subscribers","subscription_url":"https://api.github.com/repos/Changron/NTHUOJ_web/subscription","commits_url":"https://api.github.com/repos/Changron/NTHUOJ_web/commits{/sha}","git_commits_url":"https://api.github.com/repos/Changron/NTHUOJ_web/git/commits{/sha}","comments_url":"https://api.github.com/repos/Changron/NTHUOJ_web/comments{/number}","issue_comment_url":"https://api.github.com/repos/Changron/NTHUOJ_web/issues/comments/{number}","contents_url":"https://api.github.com/repos/Changron/NTHUOJ_web/contents/{+path}","compare_url":"https://api.github.com/repos/Changron/NTHUOJ_web/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Changron/NTHUOJ_web/merges","archive_url":"https://api.github.com/repos/Changron/NTHUOJ_web/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Changron/NTHUOJ_web/downloads","issues_url":"https://api.github.com/repos/Changron/NTHUOJ_web/issues{/number}","pulls_url":"https://api.github.com/repos/Changron/NTHUOJ_web/pulls{/number}","milestones_url":"https://api.github.com/repos/Changron/NTHUOJ_web/milestones{/number}","notifications_url":"https://api.github.com/repos/Changron/NTHUOJ_web/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Changron/NTHUOJ_web/labels{/name}","releases_url":"https://api.github.com/repos/Changron/NTHUOJ_web/releases{/id}","created_at":"2014-12-04T12:00:39Z","updated_at":"2014-12-03T06:37:03Z","pushed_at":"2015-02-13T00:53:48Z","git_url":"git://github.com/Changron/NTHUOJ_web.git","ssh_url":"git@github.com:Changron/NTHUOJ_web.git","clone_url":"https://github.com/Changron/NTHUOJ_web.git","svn_url":"https://github.com/Changron/NTHUOJ_web","homepage":null,"size":2647,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"bruce3557:dev","ref":"dev","sha":"76d71d47aafd4af48097bf96c9c8525d5d91d6c4","user":{"login":"bruce3557","id":4061342,"avatar_url":"https://avatars.githubusercontent.com/u/4061342?v=3","gravatar_id":"","url":"https://api.github.com/users/bruce3557","html_url":"https://github.com/bruce3557","followers_url":"https://api.github.com/users/bruce3557/followers","following_url":"https://api.github.com/users/bruce3557/following{/other_user}","gists_url":"https://api.github.com/users/bruce3557/gists{/gist_id}","starred_url":"https://api.github.com/users/bruce3557/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bruce3557/subscriptions","organizations_url":"https://api.github.com/users/bruce3557/orgs","repos_url":"https://api.github.com/users/bruce3557/repos","events_url":"https://api.github.com/users/bruce3557/events{/privacy}","received_events_url":"https://api.github.com/users/bruce3557/received_events","type":"User","site_admin":false},"repo":{"id":27471538,"name":"NTHUOJ_web","full_name":"bruce3557/NTHUOJ_web","owner":{"login":"bruce3557","id":4061342,"avatar_url":"https://avatars.githubusercontent.com/u/4061342?v=3","gravatar_id":"","url":"https://api.github.com/users/bruce3557","html_url":"https://github.com/bruce3557","followers_url":"https://api.github.com/users/bruce3557/followers","following_url":"https://api.github.com/users/bruce3557/following{/other_user}","gists_url":"https://api.github.com/users/bruce3557/gists{/gist_id}","starred_url":"https://api.github.com/users/bruce3557/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bruce3557/subscriptions","organizations_url":"https://api.github.com/users/bruce3557/orgs","repos_url":"https://api.github.com/users/bruce3557/repos","events_url":"https://api.github.com/users/bruce3557/events{/privacy}","received_events_url":"https://api.github.com/users/bruce3557/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bruce3557/NTHUOJ_web","description":"","fork":false,"url":"https://api.github.com/repos/bruce3557/NTHUOJ_web","forks_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/forks","keys_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/teams","hooks_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/hooks","issue_events_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/issues/events{/number}","events_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/events","assignees_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/assignees{/user}","branches_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/branches{/branch}","tags_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/tags","blobs_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/git/refs{/sha}","trees_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/statuses/{sha}","languages_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/languages","stargazers_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/stargazers","contributors_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/contributors","subscribers_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/subscribers","subscription_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/subscription","commits_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/commits{/sha}","git_commits_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/git/commits{/sha}","comments_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/comments{/number}","issue_comment_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/issues/comments/{number}","contents_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/contents/{+path}","compare_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/merges","archive_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/downloads","issues_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/issues{/number}","pulls_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls{/number}","milestones_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/milestones{/number}","notifications_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/labels{/name}","releases_url":"https://api.github.com/repos/bruce3557/NTHUOJ_web/releases{/id}","created_at":"2014-12-03T05:45:27Z","updated_at":"2014-12-10T14:13:37Z","pushed_at":"2015-02-09T15:11:16Z","git_url":"git://github.com/bruce3557/NTHUOJ_web.git","ssh_url":"git@github.com:bruce3557/NTHUOJ_web.git","clone_url":"https://github.com/bruce3557/NTHUOJ_web.git","svn_url":"https://github.com/bruce3557/NTHUOJ_web","homepage":null,"size":3553,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":6,"forks":7,"open_issues":6,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30"},"html":{"href":"https://github.com/bruce3557/NTHUOJ_web/pull/30"},"issue":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/issues/30"},"comments":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/issues/30/comments"},"review_comments":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30/comments"},"review_comment":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/pulls/30/commits"},"statuses":{"href":"https://api.github.com/repos/bruce3557/NTHUOJ_web/statuses/54f0280e9edbb384a1175142485299272d7247a9"}}}}