Add tournaments
This commit is contained in:
parent
acd1906c30
commit
9867281dd8
@ -1,14 +1,19 @@
|
||||
{% extends "base.html" %}
|
||||
{% load rest_framework %}
|
||||
|
||||
{% block title %}Stwórz turniej{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Stwórz turniej</h1>
|
||||
<form method="post" novalidate>
|
||||
<span>name:<input id="name" type="text" name="name" value="{{ tournament.name }}"></span><br>
|
||||
<span>passing score:<input id="passing_score" type="text" name="passing_score" value="{{ tournament.passing_score }}"></span>
|
||||
{% for question in questions %}
|
||||
|
||||
<div class="mainTestName">
|
||||
<div class="question_title" style="padding-top:15px; padding-bottom:10px; padding-left:5px;">
|
||||
<input class="form-check-input me-1" type="radio" value={{ question.id }}>
|
||||
<input class="form-check-input me-1" type="radio" name={{ question.id }} value={{ question.id }}>
|
||||
|
||||
{{ question.description }}
|
||||
</div>
|
||||
<div class="list-group">
|
||||
@ -20,9 +25,10 @@
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</form>
|
||||
<div class="testContent">
|
||||
<input type="submit" value="Wyślij odpowiedzi">
|
||||
<input type="submit" value="Stwórz turniej">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
54
templates/generic_tournament.html
Normal file
54
templates/generic_tournament.html
Normal file
@ -0,0 +1,54 @@
|
||||
{% extends "base.html" %}
|
||||
{% load rest_framework %}
|
||||
|
||||
{% block title %}{{ test.name }}{% endblock %}
|
||||
|
||||
{% block additional_head %}
|
||||
<meta charset="UTF-8">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||
<style>
|
||||
|
||||
.test_title {
|
||||
font-size: 40px;
|
||||
}
|
||||
.test_body {
|
||||
width: 50%;
|
||||
}
|
||||
.question_title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card" style="border: none;">
|
||||
<div class="card-body test_body">
|
||||
<div class="card-header test_title" style="background:#00916E; color: #FFF;">
|
||||
{{ tournament.name }}
|
||||
</div>
|
||||
<form method="post" novalidate>
|
||||
{% for question in questions %}
|
||||
<div class="question_title" style="padding-top:15px; padding-bottom:10px; padding-left:5px;">
|
||||
{{ question.description }}
|
||||
</div>
|
||||
<div class="list-group">
|
||||
{% for answer in question.answers.all %}
|
||||
<label class="list-group-item">
|
||||
<input class="form-check-input me-1" type="radio" name={{ question.id }} value={{ answer.id }}>
|
||||
{{ answer.description }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="testContent">
|
||||
<input type="submit" value="Wyślij odpowiedzi">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
56
templates/tournament_result.html
Normal file
56
templates/tournament_result.html
Normal file
@ -0,0 +1,56 @@
|
||||
{% extends "base.html" %}
|
||||
{% load social_share %}
|
||||
|
||||
{% block title %}Test result{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="resultContainer ">
|
||||
<img class="resultImage" src="http://kmit.in/emagazine/wp-content/uploads/2018/02/karnataka-results.jpg" alt="Card image cap">
|
||||
<div class="resultBody">
|
||||
<h5 class="resultMsg">
|
||||
<!-- Quite good! All the best for next quiz!-->
|
||||
{% if request.session.percentage == 100 %}
|
||||
Idealnie, widzę że ten temat nie ma dla ciebie tajemnic!
|
||||
{% elif request.session.percentage >= 75 %}
|
||||
Bardzo dobrze, ale są jeszcze pewne braki ;)
|
||||
{% elif request.session.percentage >= 50 %}
|
||||
Nie jest źle, wiedziałeś więcej niż mniej
|
||||
{% elif request.session.percentage >= 25 %}
|
||||
Masz spore braki, powinieneś trochę więcej się pouczyć
|
||||
{% else %}
|
||||
Słabiutko, ale następnym razem będzie lepiej
|
||||
{% endif %}
|
||||
</h5>
|
||||
<h5 class="resultScore">Rezultat: {{ request.session.status }}</h5>
|
||||
<h5 class="resultText">Twój wynik: {{ request.session.points }}</h5>
|
||||
<h5 class="resultText">Próg zaliczenia: {{ request.session.passing }}</h5>
|
||||
<h5 class="resultText">Maksymalny wynik: {{ request.session.max }}</h5>
|
||||
<h5 class="resultText">Wynik procentowy: {{ request.session.percentage }}%</h5>
|
||||
|
||||
<div class="resultContainerSapce"><br></div>
|
||||
<span><label for="rate"><h5>Jak oceniasz test:</h5></label></span>
|
||||
<select name="rate" id="rate">
|
||||
<option value="1">Tragiczny</option>
|
||||
<option value="2">Słaby</option>
|
||||
<option value="3">Przeciętny</option>
|
||||
<option value="4">Dobry</option>
|
||||
<option value="5">Genialny</option>
|
||||
</select>
|
||||
<span><button class="defaultButton">
|
||||
<a href='' onclick="this.href='rateTest?rate='+document.getElementById('rate').value">Oceń</a>
|
||||
</button></span>
|
||||
<div class="resultContainerSapce"><br></div>
|
||||
|
||||
{% if request.session.password == "" %}
|
||||
<h5>Udostępnij:</h5>
|
||||
{% post_to_facebook object_or_url %}
|
||||
{% post_to_linkedin object_or_url %}
|
||||
{% endif %}
|
||||
|
||||
<div class="resultContainerSapce"><br></div>
|
||||
<button class="defaultButton"><a href="{% url 'home' %}">Strona główna</a></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -3,8 +3,8 @@
|
||||
{% block title %}Turnieje{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Twoje testy</h1>
|
||||
{% for test in tests %}
|
||||
<h1>Turnieje</h1>
|
||||
{% for tournament in tournaments %}
|
||||
<div class="mainTestContainer">
|
||||
<div class="mainTestName">
|
||||
{{tournament.name}}
|
||||
@ -15,7 +15,7 @@
|
||||
<!-- <div class="mainTestDesc">-->
|
||||
<!-- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus volutpat scelerisque tortor, id sodales leo finibus id. Vivamus id viverra nunc, ac faucibus metus. Nulla a mauris imperdiet sapien lobortis dapibus. Quisque ornare posuere pulvinar.-->
|
||||
<!-- </div>-->
|
||||
<button><a href="/tests/{{tournament.id}}/show">Rozwiąż</a></button>
|
||||
<button><a href="/tests/{{tournament.id}}/tournament/show">Rozwiąż</a></button>
|
||||
</div>
|
||||
<br>
|
||||
{% endfor %}
|
||||
|
@ -38,3 +38,24 @@ class TestManager(Manager):
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class TournamentManager(Manager):
|
||||
|
||||
def create(
|
||||
self, *,
|
||||
name="",
|
||||
questions=[],
|
||||
passing_score=0,
|
||||
**kwargs
|
||||
):
|
||||
Question = apps.get_model("questions", "Question")
|
||||
|
||||
instance = super().create(
|
||||
name=name,
|
||||
passing_score=passing_score
|
||||
)
|
||||
for q in questions:
|
||||
qq = Question.objects.get(id=q)
|
||||
qq.tournament.add(instance.id)
|
||||
return instance
|
||||
|
18
trials/migrations/0024_alter_tournament_password.py
Normal file
18
trials/migrations/0024_alter_tournament_password.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.9 on 2022-05-24 20:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('trials', '0023_tournament'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tournament',
|
||||
name='password',
|
||||
field=models.CharField(default='', max_length=100),
|
||||
),
|
||||
]
|
18
trials/migrations/0025_tournament_passing_score.py
Normal file
18
trials/migrations/0025_tournament_passing_score.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.9 on 2022-05-24 21:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('trials', '0024_alter_tournament_password'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='passing_score',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
),
|
||||
]
|
18
trials/migrations/0026_tournament_completions.py
Normal file
18
trials/migrations/0026_tournament_completions.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.9 on 2022-05-24 21:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('trials', '0025_tournament_passing_score'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='completions',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
]
|
43
trials/migrations/0027_auto_20220524_2354.py
Normal file
43
trials/migrations/0027_auto_20220524_2354.py
Normal file
@ -0,0 +1,43 @@
|
||||
# Generated by Django 3.2.9 on 2022-05-24 21:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('trials', '0026_tournament_completions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='avg_difficulty',
|
||||
field=models.FloatField(default=0.0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='avg_rating',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='difficulty_label',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='rates_amount',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='total_percentage_scored_by_users',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tournament',
|
||||
name='total_rating',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
]
|
@ -2,7 +2,7 @@ from django.db import models
|
||||
|
||||
from questions.models import Question
|
||||
from users.models import User
|
||||
from .managers import TestManager
|
||||
from .managers import TestManager, TournamentManager
|
||||
|
||||
|
||||
class Test(models.Model):
|
||||
@ -114,4 +114,70 @@ class Tournament(models.Model):
|
||||
related_name="tournaments",
|
||||
on_delete=models.CASCADE
|
||||
)
|
||||
password = models.CharField(max_length=100)
|
||||
password = models.CharField(max_length=100, default="")
|
||||
passing_score = models.PositiveSmallIntegerField(default=0)
|
||||
completions = models.IntegerField(default=0)
|
||||
total_percentage_scored_by_users = models.IntegerField(default=0)
|
||||
total_rating = models.IntegerField(default=0)
|
||||
avg_rating = models.IntegerField(default=0)
|
||||
rates_amount = models.IntegerField(default=0)
|
||||
difficulty_label = models.IntegerField(default=0)
|
||||
avg_difficulty = models.FloatField(default=0.0)
|
||||
|
||||
objects = TournamentManager()
|
||||
|
||||
|
||||
def get_score(self, answers):
|
||||
"""
|
||||
[
|
||||
{
|
||||
"question": 1,
|
||||
"answer": 1
|
||||
},
|
||||
{
|
||||
"question": 2,
|
||||
"answer": 1
|
||||
}
|
||||
]
|
||||
"""
|
||||
points = 0
|
||||
for answer in answers:
|
||||
question = Question.objects.filter(tournament=self.id).get(id=answer["question"])
|
||||
if question.answers.get(id=answer["answer"]).is_correct:
|
||||
points += question.points
|
||||
return points
|
||||
|
||||
def get_maxscore(self):
|
||||
"""
|
||||
[
|
||||
{
|
||||
"question": 1,
|
||||
"answer": 1
|
||||
},
|
||||
{
|
||||
"question": 2,
|
||||
"answer": 1
|
||||
}
|
||||
]
|
||||
"""
|
||||
points = 0
|
||||
for question in Question.objects.filter(tournament=self.id):
|
||||
points += question.points
|
||||
return points
|
||||
|
||||
def question_count(self):
|
||||
return Question.objects.filter(tournament=self.id).count()
|
||||
|
||||
def get_author_name(self):
|
||||
if self.created_by:
|
||||
user = User.objects.get(email=self.created_by)
|
||||
user_fullname = user.first_name + " " + user.last_name
|
||||
else:
|
||||
user_fullname = "SOITA"
|
||||
return user_fullname
|
||||
|
||||
def name_and_passing_score(self):
|
||||
return {
|
||||
"name": self.name,
|
||||
"passing_score": self.passing_score
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
from django.urls import path
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from trials.views import TestModelViewSet, TestTemplateView, TestValidateAPIView, TestResultView, rateTest, addTest, addQuestions, myTests, solvedTests, solvedTestsDetailed, EditTestTemplateView, deleteTest, AddQuestionToExistingTest, RemoveQuestionFromExistingTest, EditQuestionTemplateView, editName, editVisible, editPassword, TestPasswordTemplateView, TournamentView, CreateTournamentView
|
||||
from trials.views import TestModelViewSet, TestTemplateView, TestValidateAPIView, TestResultView, rateTest, addTest, addQuestions, myTests, solvedTests, solvedTestsDetailed, EditTestTemplateView, deleteTest, AddQuestionToExistingTest, RemoveQuestionFromExistingTest, EditQuestionTemplateView, editName, editVisible, editPassword, TestPasswordTemplateView, TournamentView, CreateTournamentView, TournamentTemplateView, TournamentResultView
|
||||
|
||||
router = DefaultRouter(trailing_slash=False)
|
||||
router.register("items", TestModelViewSet)
|
||||
@ -26,7 +26,9 @@ urlpatterns = [
|
||||
path('solved', solvedTests, name="solvedTests"),
|
||||
path('solved/<int:test_id>', solvedTestsDetailed, name="solvedTests"),
|
||||
path('tournamets', TournamentView, name="tournaments"),
|
||||
path('add/tournament', CreateTournamentView, name="CreateTournament")
|
||||
path('add/tournament', CreateTournamentView, name="CreateTournament"),
|
||||
path('<int:tournament_id>/tournament/show', TournamentTemplateView.as_view()),
|
||||
path('<int:tournament_id>/tournament/result', TournamentResultView.as_view())
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
||||
|
107
trials/views.py
107
trials/views.py
@ -85,14 +85,28 @@ def addQuestions(request, **kwargs):
|
||||
|
||||
def TournamentView(request):
|
||||
context = {}
|
||||
context['tournament'] = Tournament.objects.all()
|
||||
context['tournaments'] = Tournament.objects.all()
|
||||
return render(request, 'tournaments.html', context)
|
||||
|
||||
def CreateTournamentView(request):
|
||||
def CreateTournamentView(request, **kwargs):
|
||||
if request.POST:
|
||||
question_ids = []
|
||||
dictt = dict(request.POST)
|
||||
pyk = dictt.pop("name")
|
||||
pyk2 = dictt.pop("passing_score")
|
||||
name = request.POST.get("name")
|
||||
passing_score = request.POST.get("passing_score")
|
||||
for k, v in dictt.items():
|
||||
question_ids.append(k)
|
||||
Tournament.objects.create(name=name, questions=question_ids, passing_score=passing_score)
|
||||
return render(request, 'home.html')
|
||||
context = {}
|
||||
context['questions'] = Question.objects.all()
|
||||
return render(request, 'createTournament.html', context)
|
||||
|
||||
|
||||
|
||||
|
||||
class AddQuestionToExistingTest(TemplateView):
|
||||
template_name = settings.BASE_DIR + f"/templates/addQuestionToExistingTest.html"
|
||||
|
||||
@ -411,6 +425,91 @@ class TestTemplateView(TemplateView):
|
||||
return HttpResponseRedirect(f'result')
|
||||
|
||||
|
||||
class TournamentTemplateView(TemplateView):
|
||||
PASSED = "Zaliczony"
|
||||
FAILED = "Niezaliczony"
|
||||
UNKNOWN = "nieznany"
|
||||
|
||||
PASSED = {
|
||||
True: PASSED,
|
||||
False: FAILED
|
||||
}
|
||||
|
||||
permission_classes = []
|
||||
template_name = settings.BASE_DIR + f"/templates/generic_tournament.html"
|
||||
test_id = None
|
||||
|
||||
def get_queryset(self):
|
||||
return Tournament.objects.all()
|
||||
|
||||
def get_context_data(self, tournament_id, **kwargs):
|
||||
self.test_id = tournament_id
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["tournament"] = self.get_queryset().filter(id=tournament_id)
|
||||
context["questions"] = Question.objects.filter(tournament=tournament_id)
|
||||
return context
|
||||
|
||||
def get_score(self, tournament: Tournament, answers):
|
||||
return tournament.get_score(answers)
|
||||
|
||||
def get_maxscore(self, tournament: Tournament):
|
||||
return tournament.get_maxscore()
|
||||
|
||||
def formatted_responses(self, unformatted_json):
|
||||
formatted_response = list()
|
||||
for question, answer in unformatted_json.items():
|
||||
formatted_response.append(
|
||||
{
|
||||
"question": question,
|
||||
"answer": answer
|
||||
}
|
||||
)
|
||||
return formatted_response
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
tournament = Tournament.objects.get(id=kwargs.get("tournament_id"))
|
||||
score = self.get_score(tournament, self.formatted_responses(request.POST))
|
||||
max = self.get_maxscore(tournament)
|
||||
status = score >= tournament.passing_score
|
||||
# context = {
|
||||
# "status": self.PASSED.get(status, self.UNKNOWN),
|
||||
# "points": score,
|
||||
# "max": max,
|
||||
# "passing": test.passing_score,
|
||||
# "percentage": int(score / max * 100),
|
||||
# "password": test.password
|
||||
# }
|
||||
request.session["status"] = self.PASSED.get(status, self.UNKNOWN)
|
||||
request.session["points"] = score
|
||||
request.session["max"] = max
|
||||
request.session["passing"] = tournament.passing_score
|
||||
request.session["percentage"] = int(score / max * 100)
|
||||
request.session["password"] = tournament.password
|
||||
# SolvedTest.objects.create(
|
||||
# score=score,
|
||||
# max=max,
|
||||
# percentage=int(score / max * 100),
|
||||
# user=request.user,
|
||||
# test=test
|
||||
# )
|
||||
tournament.completions += 1
|
||||
tournament.total_percentage_scored_by_users += int(score / max * 100)
|
||||
if tournament.completions >= 5:
|
||||
tournament.avg_difficulty = float(tournament.total_percentage_scored_by_users) / float(tournament.completions)
|
||||
if tournament.avg_difficulty > 90.0:
|
||||
tournament.difficulty_label = 1
|
||||
elif tournament.avg_difficulty > 75.0:
|
||||
tournament.difficulty_label = 2
|
||||
elif tournament.avg_difficulty > 50.0:
|
||||
tournament.difficulty_label = 3
|
||||
elif tournament.avg_difficulty > 25.0:
|
||||
tournament.difficulty_label = 4
|
||||
else:
|
||||
tournament.difficulty_label = 5
|
||||
tournament.save()
|
||||
return HttpResponseRedirect(f'result')
|
||||
|
||||
|
||||
@login_required
|
||||
def TestPasswordTemplateView(request, test_id):
|
||||
test = Test.objects.get(id=test_id)
|
||||
@ -471,3 +570,7 @@ class TestValidateAPIView(views.APIView):
|
||||
class TestResultView(TemplateView):
|
||||
permission_classes = []
|
||||
template_name = settings.BASE_DIR + f"/templates/result.html"
|
||||
|
||||
class TournamentResultView(TemplateView):
|
||||
permission_classes = []
|
||||
template_name = settings.BASE_DIR + f"/templates/tournament_result.html"
|
||||
|
Loading…
Reference in New Issue
Block a user