Add models, templates on contests
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from TSDMaster.models import Contest, Problem, Try
|
||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
|
|
||||||
|
admin.site.register(Contest)
|
||||||
|
admin.site.register(Problem)
|
||||||
|
admin.site.register(Try)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Definition of forms.
|
|||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
class BootstrapAuthenticationForm(AuthenticationForm):
|
class BootstrapAuthenticationForm(AuthenticationForm):
|
||||||
@@ -16,3 +16,18 @@ class BootstrapAuthenticationForm(AuthenticationForm):
|
|||||||
widget=forms.PasswordInput({
|
widget=forms.PasswordInput({
|
||||||
'class': 'form-control',
|
'class': 'form-control',
|
||||||
'placeholder':'Password'}))
|
'placeholder':'Password'}))
|
||||||
|
|
||||||
|
|
||||||
|
class BootstrapUserCreationForm(UserCreationForm):
|
||||||
|
username = forms.CharField(max_length=254,
|
||||||
|
widget=forms.TextInput({
|
||||||
|
'class': 'form-control',
|
||||||
|
'placeholder': 'User name'}))
|
||||||
|
password1 = forms.CharField(label=_("Password"),
|
||||||
|
widget=forms.PasswordInput({
|
||||||
|
'class': 'form-control',
|
||||||
|
'placeholder':'Password'}))
|
||||||
|
password2 = forms.CharField(label=_("Password confirm"),
|
||||||
|
widget=forms.PasswordInput({
|
||||||
|
'class': 'form-control',
|
||||||
|
'placeholder':'Password confirm'}))
|
||||||
|
|||||||
@@ -1,3 +1,34 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
|
|
||||||
|
class Contest(models.Model):
|
||||||
|
name = models.CharField(max_length=50)
|
||||||
|
date_start = models.DateTimeField()
|
||||||
|
date_stop = models.DateTimeField()
|
||||||
|
problems_file = models.URLField(null=True)
|
||||||
|
opened = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Problem(models.Model):
|
||||||
|
problem_id = models.CharField(max_length=1)
|
||||||
|
name = models.CharField(max_length=100)
|
||||||
|
tests = models.TextField()
|
||||||
|
contest = models.ForeignKey(Contest)
|
||||||
|
|
||||||
|
|
||||||
|
class Try(models.Model):
|
||||||
|
problem = models.ForeignKey(Problem)
|
||||||
|
status = models.CharField(max_length=2)
|
||||||
|
text = models.TextField(null=True)
|
||||||
|
reason = models.CharField(max_length=255, null=True)
|
||||||
|
current_test = models.IntegerField(null=True)
|
||||||
|
owner = models.ForeignKey(User)
|
||||||
|
contest = models.ForeignKey(Contest)
|
||||||
|
|
||||||
|
|
||||||
|
class UserContest(models.Model):
|
||||||
|
user = models.OneToOneField(User)
|
||||||
|
contest = models.ForeignKey(Contest)
|
||||||
|
|||||||
27
TSDMaster/TSDMaster/templates/all_contests.html
Normal file
27
TSDMaster/TSDMaster/templates/all_contests.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{% extends 'layout.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Problems</th>
|
||||||
|
<th>Date Start</th>
|
||||||
|
<th>Date End</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for contest in contests %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{ contest.id }}</th>
|
||||||
|
<td>{{ contest.name }}</td>
|
||||||
|
<td><a href="{{ contest.problems_file }}">View</a></td>
|
||||||
|
<td>{{ contest.date_start }}</td>
|
||||||
|
<td>{{ contest.date_stop }}</td>
|
||||||
|
<td><a class="btn btn-info" href="{% url 'enter_contest' %}?id={{ contest.id }}">Enter</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
23
TSDMaster/TSDMaster/templates/contest.html
Normal file
23
TSDMaster/TSDMaster/templates/contest.html
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{% extends 'layout.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Contest name: {{ contest.name }}</h1>
|
||||||
|
<hr />
|
||||||
|
<h4>Status:</h4>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>User</th>
|
||||||
|
{% for problem in problems %}
|
||||||
|
<th>{{ problem.name }}</th>
|
||||||
|
{% endfor %}
|
||||||
|
<th>Summary</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
<h4>Problem List:</h4>
|
||||||
|
<hr />
|
||||||
|
{% for problem in problems %}
|
||||||
|
<p>{{ problem.problem_id }}: {{ problem.name }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
||||||
@@ -23,15 +23,31 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbar">
|
<div class="collapse navbar-collapse" id="navbar">
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<li class="nav-item active">
|
<!--<li class="nav-item active">
|
||||||
<a class="nav-link" href="{% url 'home' %}">Home</a>
|
<a class="nav-link" href="{% url 'home' %}">Home</a>
|
||||||
</li>
|
</li>-->
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="{ url 'submit' %}">Submit</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{ url 'submissions' %}">Submissions</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'contest' %}">Contest</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'all_contests' %}">All contests</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% include 'loginpartial.html' %}
|
{% include 'loginpartial.html' %}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<main role="main" class="container body-content body-padding">
|
<main role="main" class="container body-content body-padding">
|
||||||
|
{% if messages %}
|
||||||
|
{% for message in messages %}
|
||||||
|
<div class="alert alert-{% if message.tags %}{{ message.tags }}{% else %}info{% endif %}">{{ message }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
<hr class="col-md-12"/>
|
<hr class="col-md-12"/>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<section id="loginForm">
|
<section id="loginForm">
|
||||||
<form action="." method="post" class="form-horizontal">
|
<form action="." method="post" class="form-horizontal">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<h4>Use a local account to log in.</h4>
|
<h4>Use a local account to log in. <a href="{% url 'register' %}">Or register</a></h4>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="id_username" class="col-md-2 control-label">User name</label>
|
<label for="id_username" class="col-md-2 control-label">User name</label>
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<form id="logoutForm" action="{% url 'logout' %}" method="post" class="navbar-right">
|
<form id="logoutForm" action="{% url 'logout' %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<span class="navbar-brand">{{ user }}</span>
|
||||||
<li><span class="navbar-brand">{{ user.name }}</span></li>
|
{% if user.is_staff %}
|
||||||
<li><a href="javascript:document.getElementById('logoutForm').submit()">{% trans "Logout" %}</a></li>
|
<a class="btn btn-outline-success my-2 my-sm-2" href="/admin">Admin</a>
|
||||||
</ul>
|
{% endif %}
|
||||||
|
<a class="btn btn-outline-success my-2 my-sm-0" href="javascript:document.getElementById('logoutForm').submit()">{% trans "Logout" %}</a>
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<a class="btn btn-outline-success my-2 my-sm-0" href="{% url 'login' %}">{% trans "Login" %}</a>
|
||||||
<li><a href="{% url 'login' %}">{% trans "Login" %}</a></li>
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
30
TSDMaster/TSDMaster/templates/register.html
Normal file
30
TSDMaster/TSDMaster/templates/register.html
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{% extends 'layout.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Registration</h1>
|
||||||
|
{% if errors %}
|
||||||
|
<div class="validation-summary-errors">{{ errors }}</div>
|
||||||
|
{% endif %}
|
||||||
|
<hr />
|
||||||
|
<form action="{% url 'register' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="id_name" class="col-md-2">{{ form.username.label }}</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
{{ form.username }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="id_name" class="col-md-2">{{ form.password1.label }}</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
{{ form.password1 }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="id_name" class="col-md-2">{{ form.password2.label }}</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
{{ form.password2 }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="submit" value="Submit" class="btn" />
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -17,11 +17,15 @@ from datetime import datetime
|
|||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
import django.contrib.auth.views
|
import django.contrib.auth.views
|
||||||
|
from django.conf import settings
|
||||||
from TSDMaster import views
|
from TSDMaster import views
|
||||||
from TSDMaster import forms
|
from TSDMaster import forms
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', views.home, name='home'),
|
url(r'^$', views.home, name='home'),
|
||||||
|
url(r'^all_contests$', views.all_contests, name='all_contests'),
|
||||||
|
url(r'^enter_contest$', views.enter_contest, name='enter_contest'),
|
||||||
|
url(r'^contest$', views.contest, name='contest'),
|
||||||
url(r'^login/$',
|
url(r'^login/$',
|
||||||
django.contrib.auth.views.login,
|
django.contrib.auth.views.login,
|
||||||
{
|
{
|
||||||
@@ -30,7 +34,7 @@ urlpatterns = [
|
|||||||
'extra_context':
|
'extra_context':
|
||||||
{
|
{
|
||||||
'title': 'Log in',
|
'title': 'Log in',
|
||||||
'year': datetime.now().year,
|
'company_name': settings.COMPANY_NAME,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
name='login'),
|
name='login'),
|
||||||
@@ -40,5 +44,6 @@ urlpatterns = [
|
|||||||
'next_page': '/',
|
'next_page': '/',
|
||||||
},
|
},
|
||||||
name='logout'),
|
name='logout'),
|
||||||
|
url(r'^register$', views.register, name='register'),
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render, redirect
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.messages import add_message, SUCCESS
|
||||||
|
from TSDMaster import forms
|
||||||
|
from TSDMaster.models import Contest, UserContest, Try, Problem
|
||||||
|
|
||||||
# TestSys views here.
|
# TestSys views here.
|
||||||
|
|
||||||
@@ -10,3 +13,73 @@ def home(request):
|
|||||||
'title': 'Home',
|
'title': 'Home',
|
||||||
'company_name': settings.COMPANY_NAME,
|
'company_name': settings.COMPANY_NAME,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def register(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = forms.BootstrapUserCreationForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
add_message(request, SUCCESS, 'You may login now')
|
||||||
|
return redirect('login')
|
||||||
|
return render(request, 'register.html',
|
||||||
|
{
|
||||||
|
'errors': form.errors,
|
||||||
|
'form': forms.BootstrapUserCreationForm,
|
||||||
|
'title': 'Register',
|
||||||
|
'company_name': settings.COMPANY_NAME,
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return render(request, 'register.html',
|
||||||
|
{
|
||||||
|
'form': forms.BootstrapUserCreationForm,
|
||||||
|
'title': 'Register',
|
||||||
|
'company_name': settings.COMPANY_NAME,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def all_contests(request):
|
||||||
|
return render(request, 'all_contests.html', {
|
||||||
|
'contests': Contest.objects.filter(opened=True),
|
||||||
|
'title': 'All contests',
|
||||||
|
'company_name': settings.COMPANY_NAME,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def enter_contest(request):
|
||||||
|
# TODO: Check contest available
|
||||||
|
try:
|
||||||
|
conq = UserContest.objects.get(user=request.user)
|
||||||
|
conq.contest_id = int(request.GET['id'])
|
||||||
|
conq.save()
|
||||||
|
except Exception:
|
||||||
|
UserContest(user=request.user, contest_id=int(request.GET['id'])).save()
|
||||||
|
return redirect('/contest')
|
||||||
|
|
||||||
|
|
||||||
|
def contest(request):
|
||||||
|
cur_contest = UserContest.objects.get(user=request.user).contest
|
||||||
|
problems = Problem.objects.filter(contest=cur_contest)
|
||||||
|
trys = Try.objects.filter(contest=cur_contest)
|
||||||
|
users = set()
|
||||||
|
problems_trys = {}
|
||||||
|
for tryi in trys:
|
||||||
|
if tryi.owner not in users:
|
||||||
|
users.add(tryi.owner)
|
||||||
|
problems_trys[tryi.owner] = {}
|
||||||
|
for problem in problems:
|
||||||
|
problems_trys[tryi.owner][problem] = [0, False]
|
||||||
|
if not problems_trys[tryi.owner][tryi.problem]:
|
||||||
|
if tryi.status == 'PE' or tryi.status == 'WA' or tryi.status == 'TL' or tryi.status == 'ML' or tryi.status == 'AR':
|
||||||
|
problems_trys[tryi.owner][tryi.problem][0] += 1
|
||||||
|
elif tryi.status == 'OK':
|
||||||
|
problems_trys[tryi.owner][tryi.problem][1] = True
|
||||||
|
# TODO: Presentation
|
||||||
|
return render(request, 'contest.html', {
|
||||||
|
'contest': cur_contest,
|
||||||
|
'problems': problems,
|
||||||
|
'competitors': users,
|
||||||
|
'problem_trys': problems_trys,
|
||||||
|
'title': 'Contest',
|
||||||
|
'company_name': settings.COMPANY_NAME,
|
||||||
|
})
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if os.path.isfile('settings'):
|
if os.path.isfile('settings.py'):
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
|
||||||
else:
|
else:
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings_example")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings_example")
|
||||||
|
|||||||
Reference in New Issue
Block a user