19 changed files with 344 additions and 10 deletions
@ -1,6 +1,5 @@ |
|||||||
from django.apps import AppConfig |
from django.apps import AppConfig |
||||||
|
|
||||||
|
|
||||||
class QuizConfig(AppConfig): |
class QuizConfig(AppConfig): |
||||||
default_auto_field = 'django.db.models.BigAutoField' |
default_auto_field = 'django.db.models.BigAutoField' |
||||||
name = 'quiz' |
name = 'quiz' |
||||||
|
|||||||
@ -1,3 +1,10 @@ |
|||||||
from django.contrib import admin |
from django.contrib import admin |
||||||
|
|
||||||
# Register your models here. |
# Register your models here. |
||||||
|
from .models import Atome, Score |
||||||
|
|
||||||
|
class AtomeAdmin(admin.ModelAdmin): |
||||||
|
list_display = ('pk','nom', 'symbole') |
||||||
|
|
||||||
|
admin.site.register(Atome, AtomeAdmin) |
||||||
|
admin.site.register(Score) |
||||||
|
|||||||
@ -1,6 +1,5 @@ |
|||||||
from django.apps import AppConfig |
from django.apps import AppConfig |
||||||
|
|
||||||
|
|
||||||
class QuizAtomesConfig(AppConfig): |
class QuizAtomesConfig(AppConfig): |
||||||
default_auto_field = 'django.db.models.BigAutoField' |
default_auto_field = 'django.db.models.BigAutoField' |
||||||
name = 'quiz_atomes' |
name = 'quiz_atomes' |
||||||
|
|||||||
@ -0,0 +1,31 @@ |
|||||||
|
# Generated by Django 4.0.1 on 2022-03-28 13:37 |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
initial = True |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.CreateModel( |
||||||
|
name='Atome', |
||||||
|
fields=[ |
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('nom', models.CharField(max_length=20)), |
||||||
|
('symbole', models.CharField(max_length=3)), |
||||||
|
], |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='Score', |
||||||
|
fields=[ |
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('pseudo', models.CharField(max_length=20)), |
||||||
|
('score', models.IntegerField(default=0)), |
||||||
|
('score_date', models.DateTimeField(verbose_name='Date du score')), |
||||||
|
], |
||||||
|
), |
||||||
|
] |
||||||
@ -1,3 +1,14 @@ |
|||||||
from django.db import models |
from django.db import models |
||||||
|
|
||||||
# Create your models here. |
class Atome(models.Model): |
||||||
|
nom = models.CharField(max_length=20) |
||||||
|
symbole = models.CharField(max_length=3) |
||||||
|
def __str__(self): |
||||||
|
return self.nom+" ("+self.symbole+")" |
||||||
|
|
||||||
|
class Score(models.Model): |
||||||
|
pseudo = models.CharField(max_length=20) |
||||||
|
score = models.IntegerField(default=0) |
||||||
|
score_date = models.DateTimeField('Date du score') |
||||||
|
def __str__(self): |
||||||
|
return self.pseudo+" - "+str(self.score)+" - "+self.score_date.strftime("%Y-%m-%d %H:%M") |
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 640 B |
@ -0,0 +1,24 @@ |
|||||||
|
{% extends 'basic_template.html' %}{% block 'body' %}{% load static %} |
||||||
|
<nav class="navbar navbar-light"> |
||||||
|
<div class="container"> |
||||||
|
<a class="navbar-brand text-primary" href="/"> |
||||||
|
<i class="fa fa-university"></i> |
||||||
|
<b>Edu.apps</b> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</nav> |
||||||
|
<div id="scoring" class="d-flex justify-content-center align-items-center"> |
||||||
|
<div class="py-3 d-flex flex-column align-items-center"> |
||||||
|
<h1 class="display-4"><b>LE QUIZ DES ATOMES</b> <i class="fa fa-vial"></i></h1> |
||||||
|
<p class="py-3 w-50">Ta mission pour ce jeu ?<br/> |
||||||
|
Connaître les symboles chimiques des atomes qui constituent l'univers. Chaque bonne réponse te rapporte 20 points. Une mauvaise t'en enlève 10 et une absence de réponse t'en enlève 5. Attention au temps ! Chaque seconde passée sur la partie t'enlèvera un point au moment de calculer ton score.<br/>Pour t'entraîner, aide toi de <a href="{% static 'quiz_atomes/tableau_periodique-couleur.png' %}">ce tableau</a>. Bon courage !</p> |
||||||
|
<div class="d-inline"> |
||||||
|
<a href="{% url "quiz_atomes" %}"> |
||||||
|
<input type="button" value="JOUER" href=> |
||||||
|
</a> |
||||||
|
<a href="{% url "scores" %}"> |
||||||
|
<input type="button" value="Scores"> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div>{% endblock %} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
{% extends 'basic_template.html' %}{% block 'body' %} |
||||||
|
<nav class="navbar navbar-light"> |
||||||
|
<div class="container"> |
||||||
|
<a class="navbar-brand text-primary" href="{% url "home" %}"> |
||||||
|
<i class="fa fa-home"></i> |
||||||
|
</a> |
||||||
|
<div class="navbar-brand text-primary"> |
||||||
|
<b>{{pseudo}}</b> |
||||||
|
</div> |
||||||
|
<a class="navbar-brand text-primary" href="{% url "settings" %}"> |
||||||
|
<i class="fa fa-gear"></i> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</nav> |
||||||
|
<div class="d-flex justify-content-center align-items-center"> |
||||||
|
<form action="{% url "quiz_atomes" %}" method="POST" id="quiz" name="quiz"> |
||||||
|
{% csrf_token %} |
||||||
|
<table class="table table-striped w-auto table-responsive-lg"> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th scope="col">Atome</th> |
||||||
|
<th scope="col">Symbole</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody>{% if atome_list %}{% for atome in atome_list %} |
||||||
|
<tr> |
||||||
|
<td>{{atome.nom}}</td> |
||||||
|
<td><input name="input{{ forloop.counter }}" maxlength="3" value=""></td> |
||||||
|
</tr>{% endfor %}{% endif %} |
||||||
|
<tr> |
||||||
|
<td colspan="2"><input type="submit" name="ok" value="OK"></td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</form> |
||||||
|
</div>{% endblock %} |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
{% extends 'basic_template.html' %}{% block 'body' %} |
||||||
|
<nav class="navbar navbar-light"> |
||||||
|
<div class="container"> |
||||||
|
<a class="navbar-brand text-primary" href="{% url "home" %}"> |
||||||
|
<i class="fa fa-home"></i> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</nav> |
||||||
|
<div id="scoring" class="d-flex justify-content-center align-items-center"> |
||||||
|
<div class="py-2 d-flex flex-column align-items-center"> |
||||||
|
<h4 id="points"><b>POINTS : {{points}}</b></h4> |
||||||
|
<h4 id="dt"><b>TEMPS : {{dt}}</b></h4> |
||||||
|
<h1 id="score"><b>SCORE : {{score}}</b></h1>{% if best_score %} |
||||||
|
<h4><i class="fa-solid fa-star"></i><b> Nouveau <i class="fa-solid fa-star"></i><br/>meilleur score !</b> </h4>{% else %} |
||||||
|
<h4><b>Essaie encore !</b></h4> |
||||||
|
{% endif %} |
||||||
|
<div class="d-inline"> |
||||||
|
<a href="{% url "scores" %}"> |
||||||
|
<input type="button" value="Scores"> |
||||||
|
</a> |
||||||
|
<a href="{% url "quiz_atomes" %}"> |
||||||
|
<input type="button" value="Rejouer"> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div>{% endblock %} |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
{% extends 'basic_template.html' %}{% block 'body' %} |
||||||
|
<nav class="navbar navbar-light"> |
||||||
|
<div class="container"> |
||||||
|
<a class="navbar-brand text-primary" href="{% url "home" %}"> |
||||||
|
<i class="fa fa-home"></i> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</nav> |
||||||
|
<div class="d-flex justify-content-center align-items-center"> |
||||||
|
<table class="table table-striped w-auto table-responsive-lg"> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th scope="col">Rang</th> |
||||||
|
<th scope="col">Score</th> |
||||||
|
<th scope="col">Pseudo</th> |
||||||
|
<th scope="col">Date</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody>{% if score_list %}{% for score in score_list %} |
||||||
|
<tr> |
||||||
|
<td>{{ forloop.counter }}</td> |
||||||
|
<td>{{ score.score }}</td> |
||||||
|
<td>{{ score.pseudo }}</td> |
||||||
|
<td>{{ score.score_date }}</td> |
||||||
|
</tr>{% endfor %}{% endif %} |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div>{% endblock %} |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
{% extends 'basic_template.html' %}{% block 'body' %} |
||||||
|
<nav class="navbar navbar-light"> |
||||||
|
<div class="container"> <a class="navbar-brand text-primary" href="{% url "quiz_atomes" %}"> |
||||||
|
<i class="fa fa-arrow-left"></i> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</nav> |
||||||
|
<div class="d-flex justify-content-center align-items-center"> |
||||||
|
<div class="py-2 d-flex flex-column align-items-center"> |
||||||
|
<h2><b>Paramètres du quiz</b></h2> |
||||||
|
<form action="{% url "settings" %}" method="POST" name="settings">{% csrf_token %} |
||||||
|
<table class="table w-auto table-responsive-lg"> |
||||||
|
<tr> |
||||||
|
<td>NOM :</td> |
||||||
|
<td><input id="nom" name="nom" maxlength="20"></td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>Prénom :</td> |
||||||
|
<td><input id="prenom" name="prenom" maxlength="20"></td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td>Nombre<br/>d'atomes :</td> |
||||||
|
<td class="align-middle"> |
||||||
|
<div class="form-check form-check-inline"> |
||||||
|
<input class="form-check-input" type="radio" name="nb" id="inlineRadio1" value="10" checked> |
||||||
|
<label class="form-check-label" for="inlineRadio1">10</label> |
||||||
|
</div> |
||||||
|
<div class="form-check form-check-inline"> |
||||||
|
<input class="form-check-input" type="radio" name="nb" id="inlineRadio1" value="20"> |
||||||
|
<label class="form-check-label" for="inlineRadio2">20</label> |
||||||
|
</div> |
||||||
|
<div class="form-check form-check-inline"> |
||||||
|
<input class="form-check-input" type="radio" name="nb" id="inlineRadio1" value="30"> |
||||||
|
<label class="form-check-label" for="inlineRadio1">30</label> |
||||||
|
</div> |
||||||
|
<div class="form-check form-check-inline"> |
||||||
|
<input class="form-check-input" type="radio" name="nb" id="inlineRadio1" value="40"> |
||||||
|
<label class="form-check-label" for="inlineRadio2">40</label> |
||||||
|
</div> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td colspan="2"><input type="submit" value="OK"></td> |
||||||
|
</tr> |
||||||
|
</table> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div>{% endblock %} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
from django.urls import path |
||||||
|
|
||||||
|
from . import views |
||||||
|
|
||||||
|
urlpatterns = [ |
||||||
|
path('', views.home, name='home'), |
||||||
|
path('quiz_atomes/', views.quiz_atomes, name='quiz_atomes'), |
||||||
|
path('settings/', views.settings, name='settings'), |
||||||
|
path('scores/', views.scores, name='scores'), |
||||||
|
] |
||||||
@ -1,3 +1,99 @@ |
|||||||
from django.shortcuts import render |
from django.http import HttpResponse |
||||||
|
from django.template.response import TemplateResponse |
||||||
|
from django.template import loader |
||||||
|
from .models import Atome, Score |
||||||
|
from random import shuffle |
||||||
|
from datetime import datetime |
||||||
|
from django.shortcuts import redirect |
||||||
|
import time |
||||||
|
from django.views.decorators.cache import never_cache |
||||||
|
from django.db.models import Min |
||||||
|
|
||||||
# Create your views here. |
def home(request): |
||||||
|
return TemplateResponse(request, 'quiz_atomes/home.html', {'favicon':'vial-solid.svg'}) |
||||||
|
|
||||||
|
def settings(request): |
||||||
|
if request.method =='POST': |
||||||
|
if not request.POST.get('prenom') or not request.POST.get('nom'): |
||||||
|
request.session['pseudo'] = "Anonyme" |
||||||
|
else: |
||||||
|
request.session['pseudo'] = request.POST.get('prenom')[0].upper()+". "+request.POST.get('nom').upper() |
||||||
|
request.session['difficulte'] = request.POST.get('nb') |
||||||
|
return redirect('quiz_atomes') |
||||||
|
else: |
||||||
|
return TemplateResponse(request, 'quiz_atomes/settings.html', {'favicon':'vial-solid.svg'}) |
||||||
|
|
||||||
|
@never_cache |
||||||
|
def quiz_atomes(request): |
||||||
|
|
||||||
|
if request.POST.get('ok'): |
||||||
|
return resultats(request) |
||||||
|
|
||||||
|
if 'pseudo' not in request.session or 'difficulte' not in request.session: |
||||||
|
return redirect('settings') |
||||||
|
|
||||||
|
atome_list = Atome.objects.all() |
||||||
|
random_list = list(atome_list) |
||||||
|
shuffle(random_list) |
||||||
|
random_list = random_list[:int(request.session['difficulte'])] |
||||||
|
|
||||||
|
symbole_list = [] |
||||||
|
for x in random_list: |
||||||
|
symbole_list.append(x.symbole) |
||||||
|
|
||||||
|
request.session['quiz'] = symbole_list |
||||||
|
request.session['time'] = time.time() |
||||||
|
|
||||||
|
template = loader.get_template('quiz_atomes/quiz_atomes.html') |
||||||
|
context = { |
||||||
|
'pseudo': request.session['pseudo'], |
||||||
|
'diff': request.session['difficulte'], |
||||||
|
'atome_list': random_list, |
||||||
|
'favicon':'vial-solid.svg' |
||||||
|
} |
||||||
|
return HttpResponse(template.render(context, request)) |
||||||
|
|
||||||
|
def resultats(request): |
||||||
|
|
||||||
|
points = 0 |
||||||
|
dt = round(time.time()-request.session['time'])*-1 |
||||||
|
|
||||||
|
for i in range(int(request.session['difficulte'])): |
||||||
|
if request.POST.get('input'+str(i+1)).casefold()==request.session['quiz'][i].casefold(): |
||||||
|
points+=20 |
||||||
|
elif request.POST.get('input'+str(i+1)).casefold()=="": |
||||||
|
points-=5 |
||||||
|
else: |
||||||
|
points-=10 |
||||||
|
|
||||||
|
points=points*10 |
||||||
|
score=points+dt |
||||||
|
|
||||||
|
best_score=0 |
||||||
|
if score>0: |
||||||
|
score_list = Score.objects.all().order_by('-score')[:10] |
||||||
|
min_selection_score = score_list.aggregate(Min("score")).get('score__min') |
||||||
|
if score>=min_selection_score: |
||||||
|
new_score = Score(pseudo=request.session['pseudo'], score=int(score), score_date=datetime.now()) |
||||||
|
new_score.save() |
||||||
|
best_score=1 |
||||||
|
|
||||||
|
template = loader.get_template('quiz_atomes/resultats.html') |
||||||
|
context = { |
||||||
|
'points': points, |
||||||
|
'dt': dt, |
||||||
|
'score': score, |
||||||
|
'best_score': best_score, |
||||||
|
'favicon':'vial-solid.svg' |
||||||
|
} |
||||||
|
return HttpResponse(template.render(context, request)) |
||||||
|
|
||||||
|
def scores(request): |
||||||
|
|
||||||
|
score_list = Score.objects.all().order_by('-score')[:10] |
||||||
|
template = loader.get_template('quiz_atomes/scores.html') |
||||||
|
context = { |
||||||
|
'score_list': score_list, |
||||||
|
'favicon':'vial-solid.svg' |
||||||
|
} |
||||||
|
return HttpResponse(template.render(context, request)) |
||||||
|
|||||||
Loading…
Reference in new issue