further description and improved point system
This commit is contained in:
parent
b3d4f4a198
commit
93f8563807
46
app.py
46
app.py
@ -70,32 +70,42 @@ def upload():
|
||||
secret = session.get('secret')
|
||||
if not secret or secret not in games:
|
||||
return redirect(url_for('host'))
|
||||
|
||||
game = games[secret]
|
||||
|
||||
# retrieve uploaded file
|
||||
file = request.files.get('file')
|
||||
if not file:
|
||||
return render_template('upload.html', error='Keine Datei ausgewählt')
|
||||
|
||||
# try to read Excel
|
||||
try:
|
||||
df = pd.read_excel(file)
|
||||
except Exception:
|
||||
return render_template('upload.html', error='Ungültige Excel-Datei')
|
||||
|
||||
# enforce maximum of 100 questions
|
||||
max_questions = 100
|
||||
if df.shape[0] > max_questions:
|
||||
return render_template(
|
||||
'upload.html',
|
||||
error=f'Maximal dürfen {max_questions} Fragen hochgeladen werden. Ihre Datei enthält {df.shape[0]}.')
|
||||
|
||||
# mandatory columns
|
||||
required = ['question', 'answer1', 'answer2', 'answer3', 'answer4', 'correct']
|
||||
# ermittelt, welche der benötigten Spalten nicht im DataFrame sind
|
||||
missing = [col for col in required if col not in df.columns]
|
||||
if missing:
|
||||
return render_template(
|
||||
'upload.html',
|
||||
error=f"Fehler in Datei: Fehlende Spalte(n): {', '.join(missing)}"
|
||||
)
|
||||
|
||||
# validate that 'correct' references one of the answer columns
|
||||
valid_keys = ['answer1', 'answer2', 'answer3', 'answer4']
|
||||
invalid_mask = ~df['correct'].isin(valid_keys)
|
||||
if invalid_mask.any():
|
||||
# finde den ersten Invalid-Eintrag
|
||||
idx = invalid_mask.idxmax() # DataFrame-Index
|
||||
excel_line = idx + 2 # Header ist Zeile 1
|
||||
idx = invalid_mask.idxmax()
|
||||
excel_line = idx + 2 # Header is line 1
|
||||
bad_value = df.at[idx, 'correct']
|
||||
return render_template(
|
||||
'upload.html',
|
||||
@ -104,19 +114,23 @@ def upload():
|
||||
f'"correct" enthält "{bad_value}", '
|
||||
f'muss einer der Werte {valid_keys} sein.'
|
||||
)
|
||||
) # build per-game question list
|
||||
)
|
||||
|
||||
# build per-game question list
|
||||
questions = []
|
||||
for _, row in df.iterrows():
|
||||
col = row['correct']
|
||||
questions.append({
|
||||
'question': row['question'],
|
||||
'options': [row[f'answer{i}'] for i in range(1,5)],
|
||||
'correct': row[col]
|
||||
'question': str(row['question']),
|
||||
'options': [str(row[f'answer{i}']) for i in range(1, 5)],
|
||||
'correct': str(row[col])
|
||||
})
|
||||
|
||||
game['questions'] = questions
|
||||
# once upload and validation succeeds, redirect to host view (which will show the QR)
|
||||
# redirect to host view, which will show the QR code
|
||||
return redirect(url_for('host'))
|
||||
|
||||
|
||||
@app.route('/new_game', methods=['POST'])
|
||||
def new_game():
|
||||
if session.get('role') != 'host':
|
||||
@ -419,7 +433,12 @@ def _send_question(secret):
|
||||
|
||||
def _score_and_emit(secret):
|
||||
game = games[secret]
|
||||
score_map = {1: 4, 2: 3, 3: 2, 4: 1}
|
||||
# Punkteverteilung:
|
||||
# 1. richtige Antwort → 5 Punkte
|
||||
# 2. richtige Antwort → 4 Punkte
|
||||
# 3. richtige Antwort → 3 Punkte
|
||||
# alle weiteren richtigen Antworten → 1 Punkt
|
||||
score_map = {1: 5, 2: 4, 3: 3}
|
||||
per_q = []
|
||||
|
||||
# grab the current question’s correct answer
|
||||
@ -431,9 +450,10 @@ def _score_and_emit(secret):
|
||||
prev_correct = sum(1 for p, a in game['answered'][:-1] if a == correct)
|
||||
rank = prev_correct + 1
|
||||
|
||||
# assign points only if this one is correct and within top‐4
|
||||
if ans == correct and rank <= 4:
|
||||
pts = score_map[rank]
|
||||
# assign points only if korrekt
|
||||
if ans == correct:
|
||||
# für Platz 1–3 nach Mapping, ab Platz 4 immer 1 Punkt
|
||||
pts = score_map.get(rank, 1)
|
||||
game['players'][pid]['score'] += pts
|
||||
per_q.append({
|
||||
'name': game['players'][pid]['name'],
|
||||
|
||||
@ -4,27 +4,43 @@
|
||||
|
||||
<!-- Einführung -->
|
||||
<p class="lead">
|
||||
Willkommen beim interaktiven Gruppen-Quiz! Lade hier deinen eigenen Fragebogen hoch,
|
||||
um ein spannendes Live-Quiz zu starten. Deine Teilnehmer bearbeiten die Fragen schnell
|
||||
und wettbewerbsorientiert, direkt über ihre Smartphones.
|
||||
Willkommen zum interaktiven Gruppenquiz! Lade deinen eigenen Fragebogen hoch und starte ein spannendes Live-Quiz.
|
||||
Deine Teilnehmer beantworten die Fragen schnell und wettbewerbsorientiert direkt über ihre Smartphones.
|
||||
</p>
|
||||
|
||||
<!-- Beschreibung -->
|
||||
<!-- Punktevergabe -->
|
||||
<p>
|
||||
Verwende die <strong>Beispieldatei</strong> als Vorlage und trage deine Fragen und Antwortoptionen
|
||||
ein. Achte darauf, dass deine Excel-Datei folgende Spalten enthält:
|
||||
Schnelle und richtige Antworten werden mit mehr Punkten belohnt. Jeder Spieler hat pro Frage nur einen Versuch.
|
||||
Ein guter Mix aus Schnelligkeit und Genauigkeit zahlt sich aus!
|
||||
</p>
|
||||
<p class="text-muted">
|
||||
<strong>Hinweis:</strong> Die ersten drei richtigen Antworten erhalten höhere Punktwerte, alle weiteren richtigen Antworten bringen jeweils 1 Punkt.
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>question</code>: Der Fragentext (z.B. "Wer baute die Arche?")</li>
|
||||
<li><code>answer1</code> bis <code>answer4</code>: Vier mögliche Antworten</li>
|
||||
<li><code>correct</code>: Name der richtigen Spalte (<code>answer1</code>–<code>answer4</code>)</li>
|
||||
<li>erste richtige Antwort → 5 Punkte</li>
|
||||
<li>zweite richtige Antwort → 4 Punkte</li>
|
||||
<li>dritte richtige Antwort → 3 Punkte</li>
|
||||
<li>jeder weitere richtige Antwort → 1 Punkt</li>
|
||||
</ul>
|
||||
|
||||
<p>Sobald die richtige Antwort für alle anzeigt wird, werden keine weiteren Punkte verteilt.</p>
|
||||
|
||||
<!-- Dateivorlage -->
|
||||
<h2 class="mb-4">Fragebogen erstellen</h2>
|
||||
<p>
|
||||
Nutze die <strong>Beispieldatei</strong> als Vorlage und trage deine Fragen sowie die Antwortoptionen ein.
|
||||
Deine Excel-Datei sollte folgende Spalten enthalten:
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>question</code>: Text der Frage (z. B. „Wer baute die Arche?“)</li>
|
||||
<li><code>answer1</code> bis <code>answer4</code>: Vier Antwortmöglichkeiten</li>
|
||||
<li><code>correct</code>: Spaltenname der richtigen Antwort (<code>answer1</code>-<code>answer4</code>)</li>
|
||||
</ul>
|
||||
<p class="text-muted">
|
||||
Unterstützte Formate: <code>.xlsx</code>, <code>.xls</code>. Maximal 100 Fragen empfohlen.
|
||||
Unterstützte Formate: <code>.xlsx</code>, <code>.xls</code>
|
||||
Maximal 100 Fragen!
|
||||
</p>
|
||||
|
||||
<h2 class="mb-4">Fragebogen:</h2>
|
||||
|
||||
<!-- Download-Link zur Beispiel-Datei -->
|
||||
<div class="mb-4">
|
||||
<a href="{{ url_for('static', filename='questions_example.xlsx') }}" class="btn btn-warning">
|
||||
@ -45,7 +61,7 @@
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success">Fragebogen hochladen</button>
|
||||
<button type="submit" class="btn btn-success">Spiel beginnen</button>
|
||||
</form>
|
||||
|
||||
<!-- Fehlermeldung -->
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user