Merge branch 'master' into '103-verschiedene-lernmodi'
# Conflicts: # django/templates/play/game/question_host.html
This commit is contained in:
@@ -4,12 +4,12 @@ from .models import QivipQuiz, QivipQuestion
|
|||||||
class QuizForm(forms.ModelForm):
|
class QuizForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = QivipQuiz
|
model = QivipQuiz
|
||||||
fields = ['name', 'description','image', 'status', 'category', "difficulty","credits"]
|
fields = ['name', 'description','image', 'status', 'category','difficulty','credits']
|
||||||
|
|
||||||
class QuestionForm(forms.ModelForm):
|
class QuestionForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = QivipQuestion
|
model = QivipQuestion
|
||||||
fields = ['quiz_id', 'data']
|
fields = ['quiz_id', 'data','time_per_question']
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-04-08 14:17
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0032_qivipquiz_average_rating_qivipquiz_rating_count_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='qivipquestion',
|
||||||
|
name='time_per_question',
|
||||||
|
field=models.CharField(choices=[('10', 10), ('15', 15), ('30', 30), ('60', 60), ('90', 90), ('120', 120), ('180', 180), ('nicht gesetzt', 'nicht gesetzt')], default=30, help_text='Zeit pro Frage in Sekunden', max_length=13),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-04-08 14:19
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0033_qivipquestion_time_per_question'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='qivipquestion',
|
||||||
|
name='time_per_question',
|
||||||
|
field=models.CharField(choices=[('10', 10), ('15', 15), ('30', 30), ('60', 60), ('90', 90), ('120', 120), ('180', 180)], default=30, help_text='Zeit pro Frage in Sekunden', max_length=13),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.7 on 2025-04-08 14:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('library', '0034_alter_qivipquestion_time_per_question'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='qivipquestion',
|
||||||
|
name='time_per_question',
|
||||||
|
field=models.CharField(choices=[('10', 10), ('15', 15), ('30', 30), ('60', 60), ('90', 90), ('120', 120), ('180', 180)], default=30, help_text='Zeit pro Frage in Sekunden', max_length=3),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -20,6 +20,9 @@ class QivipQuiz(models.Model):
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def validate_description(value):
|
def validate_description(value):
|
||||||
if value.strip() == "In dem Quiz geht es um ...":
|
if value.strip() == "In dem Quiz geht es um ...":
|
||||||
raise ValidationError("Bitte gib eine aussagekräftige Beschreibung ein.")
|
raise ValidationError("Bitte gib eine aussagekräftige Beschreibung ein.")
|
||||||
@@ -55,12 +58,22 @@ class QivipQuizFavorite(models.Model):
|
|||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
class QivipQuestion(models.Model):
|
class QivipQuestion(models.Model):
|
||||||
|
|
||||||
|
TIME_VALUES = {
|
||||||
|
"10": 10,
|
||||||
|
"15": 15,
|
||||||
|
"30": 30,
|
||||||
|
"60": 60,
|
||||||
|
"90": 90,
|
||||||
|
"120": 120,
|
||||||
|
"180": 180,
|
||||||
|
}
|
||||||
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||||
quiz_id = models.ForeignKey(QivipQuiz, on_delete=models.CASCADE, related_name='questions')
|
quiz_id = models.ForeignKey(QivipQuiz, on_delete=models.CASCADE, related_name='questions')
|
||||||
creation_date = models.DateTimeField(auto_now_add=True)
|
creation_date = models.DateTimeField(auto_now_add=True)
|
||||||
update_date = models.DateTimeField(auto_now=True)
|
update_date = models.DateTimeField(auto_now=True)
|
||||||
data = models.TextField()
|
data = models.TextField()
|
||||||
|
time_per_question = models.CharField(max_length=3, choices=list(TIME_VALUES.items()), default=30, help_text="Zeit pro Frage in Sekunden")
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.data[:50]
|
return self.data[:50]
|
||||||
|
|
||||||
|
|||||||
@@ -387,6 +387,7 @@ def new_question(request):
|
|||||||
question = QivipQuestion()
|
question = QivipQuestion()
|
||||||
question.data = json.dumps(json_data)
|
question.data = json.dumps(json_data)
|
||||||
question.quiz_id = quiz
|
question.quiz_id = quiz
|
||||||
|
question.time_per_question = request.POST.get('time_per_question', '30')
|
||||||
question.save()
|
question.save()
|
||||||
#return modified(request, pk=quiz.pk)
|
#return modified(request, pk=quiz.pk)
|
||||||
return redirect('library:detail_quiz', pk=quiz.pk)
|
return redirect('library:detail_quiz', pk=quiz.pk)
|
||||||
@@ -401,6 +402,7 @@ def new_question(request):
|
|||||||
{'value': 'Falsch', 'is_correct': False}
|
{'value': 'Falsch', 'is_correct': False}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
standard_time_per_question = 30
|
||||||
elif question_type == 'multiple_choice':
|
elif question_type == 'multiple_choice':
|
||||||
question_data = {
|
question_data = {
|
||||||
'type': question_type,
|
'type': question_type,
|
||||||
@@ -410,12 +412,14 @@ def new_question(request):
|
|||||||
{'value': '', 'is_correct': False}
|
{'value': '', 'is_correct': False}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
standard_time_per_question = 30
|
||||||
|
|
||||||
template_name = f'library/question/question_{question_type}.html'
|
template_name = f'library/question/question_{question_type}.html'
|
||||||
context = {
|
context = {
|
||||||
'question': question_data,
|
'question': question_data,
|
||||||
'quiz_id': quiz_id,
|
'quiz_id': quiz_id,
|
||||||
'quiz': quiz
|
'quiz': quiz,
|
||||||
|
'standard_time_per_question': standard_time_per_question,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, template_name, context)
|
return render(request, template_name, context)
|
||||||
@@ -516,6 +520,7 @@ def edit_question(request, pk):
|
|||||||
}
|
}
|
||||||
|
|
||||||
question.data = json.dumps(json_data)
|
question.data = json.dumps(json_data)
|
||||||
|
question.time_per_question = request.POST.get('time_per_question', '30')
|
||||||
question.save()
|
question.save()
|
||||||
#return modified(request, question.quiz_id.pk)
|
#return modified(request, question.quiz_id.pk)
|
||||||
return redirect('library:detail_quiz', pk=question.quiz_id.pk)
|
return redirect('library:detail_quiz', pk=question.quiz_id.pk)
|
||||||
@@ -525,7 +530,8 @@ def edit_question(request, pk):
|
|||||||
context = {
|
context = {
|
||||||
'question': {'data': question_data}, # Wrap in data structure expected by template
|
'question': {'data': question_data}, # Wrap in data structure expected by template
|
||||||
'quiz_id': question.quiz_id.pk,
|
'quiz_id': question.quiz_id.pk,
|
||||||
'quiz': question.quiz_id
|
'quiz': question.quiz_id,
|
||||||
|
'time_per_question': question.time_per_question,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, template_name, context)
|
return render(request, template_name, context)
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ def question(request, join_code):
|
|||||||
return render(request, 'play/game/question_host.html', {
|
return render(request, 'play/game/question_host.html', {
|
||||||
'quiz_game': quiz_game,
|
'quiz_game': quiz_game,
|
||||||
'question_data': question_data,
|
'question_data': question_data,
|
||||||
|
'current_question':current_question,
|
||||||
'host_id': quiz_game.host_id,
|
'host_id': quiz_game.host_id,
|
||||||
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
||||||
'question_index': quiz_game.current_question_index,
|
'question_index': quiz_game.current_question_index,
|
||||||
@@ -265,6 +266,7 @@ def question(request, join_code):
|
|||||||
return render(request, 'play/game/question_participant.html', {
|
return render(request, 'play/game/question_participant.html', {
|
||||||
'quiz_game': quiz_game,
|
'quiz_game': quiz_game,
|
||||||
'question_data': question_data,
|
'question_data': question_data,
|
||||||
|
'current_question':current_question,
|
||||||
'participant': participant,
|
'participant': participant,
|
||||||
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
'start_time': int(quiz_game.question_start_time.timestamp() * 1000),
|
||||||
'question_index': quiz_game.current_question_index,
|
'question_index': quiz_game.current_question_index,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
Zurück zum Quiz
|
Zurück zum Quiz
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-white rounded-lg shadow-md p-6 border-blue-600 border-2 rounded-xl shadow-md">
|
<div class="bg-white rounded-lg shadow-md p-6 border-blue-600 border-2 rounded-xl shadow-md">
|
||||||
<form method="post" class="space-y-6">
|
<form method="post" class="space-y-6">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@@ -92,6 +91,19 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="p-4">
|
||||||
|
<label class="font-bold" for="time_per_question">Zeit pro Frage:</label>
|
||||||
|
<select name="time_per_question" id="time_per_question">
|
||||||
|
<option value="10" {% if standard_time_per_question == "10" or time_per_question == "10" %}selected{% endif %}>10 Sekunden</option>
|
||||||
|
<option value="20" {% if standard_time_per_question == "20" or time_per_question == "20" %}selected{% endif %}>20 Sekunden</option>
|
||||||
|
<option value="30" {% if standard_time_per_question == "30" or time_per_question == "30" %}selected{% endif %}>30 Sekunden</option>
|
||||||
|
<option value="45" {% if standard_time_per_question == "45" or time_per_question == "45" %}selected{% endif %}>45 Sekunden</option>
|
||||||
|
<option value="60" {% if standard_time_per_question == "60" or time_per_question == "60" %}selected{% endif %}>1 Minute</option>
|
||||||
|
<option value="120" {% if standard_time_per_question == "120" or time_per_question == "120" %}selected{% endif %}>2 Minuten</option>
|
||||||
|
<option value="300" {% if standard_time_per_question == "300" or time_per_question == "300" %}selected{% endif %}>5 Minuten</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end space-x-3">
|
<div class="flex justify-end space-x-3">
|
||||||
<a href="{% url 'library:detail_quiz' quiz.id %}"
|
<a href="{% url 'library:detail_quiz' quiz.id %}"
|
||||||
class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
||||||
|
|||||||
@@ -43,6 +43,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="p-4">
|
||||||
|
<label class="font-bold" for="time_per_question">Zeit pro Frage:</label>
|
||||||
|
<select name="time_per_question" id="time_per_question">
|
||||||
|
<option value="10" {% if standard_time_per_question == "10" or time_per_question == "10" %}selected{% endif %}>10 Sekunden</option>
|
||||||
|
<option value="20" {% if standard_time_per_question == "20" or time_per_question == "20" %}selected{% endif %}>20 Sekunden</option>
|
||||||
|
<option value="30" {% if standard_time_per_question == "30" or time_per_question == "30" %}selected{% endif %}>30 Sekunden</option>
|
||||||
|
<option value="45" {% if standard_time_per_question == "45" or time_per_question == "45" %}selected{% endif %}>45 Sekunden</option>
|
||||||
|
<option value="60" {% if standard_time_per_question == "60" or time_per_question == "60" %}selected{% endif %}>1 Minute</option>
|
||||||
|
<option value="120" {% if standard_time_per_question == "120" or time_per_question == "120" %}selected{% endif %}>2 Minuten</option>
|
||||||
|
<option value="300" {% if standard_time_per_question == "300" or time_per_question == "300" %}selected{% endif %}>5 Minuten</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end space-x-3">
|
<div class="flex justify-end space-x-3">
|
||||||
<a href="{% url 'library:detail_quiz' quiz.id %}"
|
<a href="{% url 'library:detail_quiz' quiz.id %}"
|
||||||
class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
const joinCode = '{{ quiz_game.join_code }}';
|
const joinCode = '{{ quiz_game.join_code }}';
|
||||||
const participantId = '{{ participant.participant_id }}';
|
const participantId = '{{ participant.participant_id }}';
|
||||||
const questionStartTime = {{ start_time }};
|
const questionStartTime = {{ start_time }};
|
||||||
const questionDuration = 30000; // 30 seconds in milliseconds
|
const questionDuration = '{{ current_question.time_per_question }}'*1000; //Zeit pro Frage (indviduell eingestellt)
|
||||||
const gameSocket = initializeGameSocket(joinCode);
|
const gameSocket = initializeGameSocket(joinCode);
|
||||||
|
|
||||||
gameSocket.onmessage = function(e) {
|
gameSocket.onmessage = function(e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user