Welche Datenstruktur für Multiple-Choice-Fragentrainer

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Man möchte nie etwas global haben, es sei denn es bleibt konstant. Und dann sind das Konstanten und die schreibt man KOMPLETT_GROSS.

Und in diesem Fall möchtest du das ganz bestimmt nicht global haben. Denn es bleibt nicht konstant.
Benutzer Alfons ruft den Trainer auf. Du setzt global, was du als richtige Anwort erwartest.
Benutzer Berta ruft den Trainer auf. Du setzt global, was du als richtige Antwort erwartest.
Benutzer Alfons wird nun keine Chance mehr haben, seine Frage richtig zu beantworten.
Deshalb sind globale Werte böse - und in diesem Fall fällt einem das endlich mal richtig auf die Füße, weil der Zutand eben nicht global sein darf.

Ich habe mit Flask keine Erfahrung, aber wie ich es unter Django lösen würde:

"Frage" ist nachfolgend der Datensatz bestehend aus der Frage und den Antworten.

- Es gibt eine View, der eine Frage auswählt, die Reihenfolge der Antworten shuffelt und für das Frontend ausliefert. Eine ID der Frage wird in der Session des Benutzers gespeichert.

- Es gibt einen View, der die Antwort entgegen nimmt. Der holt sich die ID der Frage, die der Benutzer bekommen hat, aus der Session und damit die passende Frage aus dem Bestand. Er prüft ob die übermittelte Antwort mit der korrekten Antwort überein stimmt.

Das erst einmal zur grundsätzlichen Herangehensweise bei dem Frage/Antwort-Zyklus.
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Morgen,

Danke für die Antwort.
Ja Mist, dass das zwei (oder im allgemeinen Fall, mehrere) gleichzeitig benutzen können, habe ich ja noch gar nicht bedacht. Das leuchtet natürlich voll und ganz ein, dass das so nicht geht.

Ich schau mal ob ich im Netz was finde, wie ich jedem Benutzer eine Session zuweisen kann.
und in diesem Fall fällt einem das endlich mal richtig auf die Füße, weil der Zutand eben nicht global sein darf.
Immerhin dient es als schlechtes Beispiel. Ich hatte was im Hinterkopf, das es wohl spezielle Gründe gibt, in denen ein globaler Zustand von änderlichen Objekten okay sei, aber ich weis nicht mehr um was es dabei ging und ob das wirklich so war oder ob ich das einfach falsch im Hinterkopf habe.

Grüße und schönen Sonntag
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Dennis89: so kompliziert mußt Du es Dir gar nicht machen. Ich hatte Dir ja schon gezeigt, dass es nötig ist, die Fragennummer (z.B. per hidden-input) mit ins Formular zu packen.
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Danke für den Hinweis.

Das heißt, das ich mein 'active_question' gar nicht brauche, weil ich die Fragennummer mit der Antwort geliefert bekomme. Dann würde ich die Klasse nur noch benötigen, um mir die zufällige Reihenfolge der Antworten zu merken.
Die Reihenfolge der Antwort merke ich mir nur, weil ich die Frage + Antworten + den Hinweise ob die gewählte Antwort richtig war auf einmal angezeigt haben will. Und mit 'submit' lädt die ganze Seite noch einmal neu. Eventuell geht es, wenn ich den den Typ von 'submit' auf 'button' wechsle.

Ich teste das heute Nachmittag mal aus. Wollte meine Gedanken dazu nur gleich mal aufschreiben, in der Hoffnung sie werden bestätigt/verbessert.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

get_right_answer braucht doch die gewürfelten Antworten gar nicht.
Das Attribut answers_random_order war in deiner ursprünglichen Implementierung überflüssig und ist es immer noch.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

In diesem Fall vielleicht unnötig, aber: Wenn du das auf die Weise löst, dass du Frage und Antwort schickst, könntest du jede Frage korrekt beantworten, indem du den request einer richtig beantworteten Frage für jede Frage sendest.
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Danke für eure Antworten.

@Sirius3 Ich hatte schon einen Post geschrieben, in dem ich dir erklären wollte, das ich 'answers_random_order' brauche, weil ich sonst beim neuladen der Seite eine andere Reihenfolge der Antworten habe. Dann wurde mir klar, dass du das bestimmt schon verstanden hast und ich eher noch einmal überlegen sollte.

Ich hätte jetzt eine Lösung ohne Klasse, aber es hackt noch an einer Stelle.
Ich schicke ja die Liste mit den Antworten, an den Server. Dann könnte ich doch einfach, ein 'input' erstellen, das ich einfach mit auslesen, wenn man auf eine Antwort geklickt hat.
Leider erhalte ich hier nicht die ganze Liste zurück, sondern immer nur eine Antwort. Wenn ich in meinen Testfragen zum Beispiel auf die Antwort 'Hans' klicke, dann bekomme ich anstatt eine Liste mit allen vier Namen nur

Code: Alles auswählen

['Hans',
zurück.

Dabei habe ich es versucht mit

Code: Alles auswählen

requestform['answers']
request.form.get('answers')
request.form.get('answers, default=false, type=list)
request.data
request.get_data()
request.get_data('answers')
Entweder kommt die angefangene Liste zurück oder nichts.

Ist meine Denkweise hier wieder falsch oder "nur" ein Fehler in meinem Code?

Der Code sieht aktuell so aus

Code: Alles auswählen

from json import loads
from pathlib import Path
from random import sample

from flask import Flask, render_template, request
from werkzeug.exceptions import abort

QUESTIONS_PATH = Path("/home/dennis/Question_Trainer/questions.json")
QUESTIONS = loads(QUESTIONS_PATH.read_bytes())
app = Flask(__name__)


def number_of_questions():
    return [number for number, _ in enumerate(QUESTIONS)]


def get_question(question_id):
    return QUESTIONS[question_id]["question"]


def get_answers_in_random_order(question_id):
    return sample(QUESTIONS[question_id]["answers"], 4)


def get_right_answer(question_id, answer):
    return answer == QUESTIONS[question_id]["answers"][0]


@app.route("/question", methods=["GET", "POST"])
def chose_question():
    question_id = int(request.form["answer"]) - 1
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=get_answers_in_random_order(question_id),
    )


@app.route("/answer", methods=["GET", "POST"])
def check_answer():
    question_id = int(request.form["id"])
    answer = str(request.form["answer"])
    answers = request.get_data('answers')
    rating = "Richtig!" if get_right_answer(question_id, answer) else "Falsch!"
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=answers,
        rating=rating,
    )


@app.route("/next", methods=["GET", "POST"])
def next_question():
    try:
        question_id = int(request.form["id"])
        question = get_question(question_id)
        return render_template(
            "question.html",
            question=question,
            id=question_id,
            answers=get_answers_in_random_order(question_id),
        )
    except IndexError:
        return render_template("finish.html")


@app.route("/back", methods=["GET", "POST"])
def previous_question():
    question_id = int(request.form["id"])
    if question_id < 0:
        return index()
    question = get_question(question_id)
    return render_template(
        "question.html",
        question=question,
        id=question_id,
        answers=get_answers_in_random_order(question_id),
    )


@app.route("/")
def index():
    return render_template("index.html", questions=number_of_questions())
Und die question.html

Code: Alles auswählen

{% extends 'base.html' %}

<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="{{ url_for('static', filename= 'css/style.css') }}">
    <title>Fragetrainer</title>
</head>

{% block content %}
    <h1>{% block title %} Wähle weise! {% endblock %}</h1>
    
    {{ question }}
    <form action="/answer" method="POST">    
    <input type="hidden" name="id" value={{ id }}>
    {% for answer in answers %}
    <p><input type="submit" name="answer" value={{ answer }}></p>
    {% endfor %}
    <input type="hidden" name="answers" value={{ answers }}>
   
 </form>

{{ rating }}


        <form action="/back" method="POST">  
        <input type="hidden" name="id" value={{ id - 1 }}>
        <p><input type="submit" name="back" value="Zurück"></p>
        </form>
   
        <form action="/next" method="POST">
         <input type="hidden" name="id" value={{ id + 1 }}>
        <p><input type="submit" name="next" value="Weiter"></p>
        </form>

{% endblock %}
@sparrow Dieses mal verstehe ich leider nur Bahnhof. Ich habe den letzten Satzteil wirklich oft gelesen, weis aber nicht was das bedeutet. Sorry.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Das mit `answers` ist ein Problem hier. Ein Attribut kann *einen* Wert haben und der muss in Anführungszeichen eingeschlossen sein, das hast Du auch an den anderen Stellen falsch. Browser schlucken auch eine Menge falsches Zeug und versuchen da irgendwas sinnvolles draus zu machen.

Die Werte von Attributen sind a) Zeichenketten und b) wird in denen „whitespace“ normalisiert. Das heisst man muss so etwas wie Datenstrukturen wegen a) irgendwie serialisieren, beispielsweise als JSON, und b) darf dabei nicht zum Problem werden. Warum gibt es denn überhaupt `answers` als <input>? Die Antworten hat doch der Server und kann über die ID der Frage darauf zugreifen‽
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@Dennis89: Warum willst du die Antworten überhaupt zurück schicken? Die hast du doch schon auf dem Server im Bestand. Welchen Mehrwert hast du, dass du noch einmal dorthin sendest?
Dennis89 hat geschrieben: Sonntag 5. Februar 2023, 17:04@sparrow Dieses mal verstehe ich leider nur Bahnhof. Ich habe den letzten Satzteil wirklich oft gelesen, weis aber nicht was das bedeutet. Sorry.
Ich versuche es mit einem praktischen Beispiel.

Wir nehmen mal an, das ist kein Spaßprojekt sondern das ist eine Frageapp, mit der du tatsächlich das Wissen der Benutzer abfragen willst. Zum Beispiel damit die ein Zertifikat bekommen.

(Nachfolgend ist das Senden an den Server als Python dict geschrieben. Das ist eigentlich der post-Request mit form-data. Es soll nur das Problem veranschaulichen.)

Die erste Frage (mit der internen ID 21) ist:
Welche Farbe hat eine Ampel oben?
1) Blau
2) Grün
3) Rot

Ich klicke "Rot".
Deine Lösung sendet jetzt quasi {"id": 21, "answer": "Rot") an den Server. Der sagt völlig zu recht: "Das ist richtig."

Jetzt kommt die zweite Frage (interne ID 14):
Schneewittchen und die ... Zwerge.
1) grünen
2) 7
3) vielen
Ich klicke gar nichts aber sage dem Client, er soll mal {"id": 21, "answer": "Rot") senden. Der Server sagt: "Das ist richtig."

Wenn es jetzt reicht x Mal "Das ist richtig." vom Server zu erhalten ist das Zertifikat also eher einfach zu bekommen.
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Vielen Dank für eure Antworten.

Da ihr beide die gleichen Fragen gestellt habt, beantworte ich das als erstes.
Kurz gesagt, wenn ich die schon im Bestand habe, dann weis ich nicht wie ich darauf zugreife.
Wenn ich über die ID der Frage, die Antworten hole, dann sind die nicht mehr in der gleichen Reihenfolge, wie sie waren, bevor eine Antwort ausgewählt wurde.
Ich beschreibe mal meine Gedanken, wie ich mir den Ablauf vorstelle.
Ausgewählt wird eine Frage, die erscheint und anhand ihrer ID werden die Antworten "ausgesucht" und mit 'sample' wird die Reihenfolge der Antwortmöglichkeiten beliebig getauscht. Dann wird die Frage, die ID und die Liste mit den Antworten, die in einer beliebigen Reihenfolge sind, an den Server gesendet und ich kann das im Browser sehen.
Dann klicke ich auf eine Antwort, ich lese den Wert des geklickten Buttons aus, anhand der ID ermittle ich die richtige Antwort und sende das zurück. Jetzt wird die Seite neu geladen und wenn ich jetzt nicht die gleiche Liste mit den Antworten wieder an den Server sende, dann sind entweder keine Antworten da oder wenn ich mir die Antworten wieder über die ID der Frage hole, dann sind sie in einer anderen Reihenfolge.
Weil ich das verwirrend finde, wenn sich die Reihenfolge ändert, wollte ich die beibehalten und irgendwie "speichern" und wieder senden.

So glaube ich, dass das was ich da mache funktioniert. Dass das falsch ist, kann natürlich gut sein und dass ich eine Möglichkeit übersehe ist auch sehr wahrscheinlich. Aber vielleicht könnt ihr nachvollziehen, wieso ich den Code so geschrieben habe und mich hoffentlich an der richtigen Stelle, wieder vom Holzweg schicken.

@__blakjack__ Durch das setzen der Anführungszeichen, bekomme ich jetzt die ganze Liste zurück. Aber, da das womöglich falsch ist, habe ich in die Richtung noch nicht weiter gemacht.

@sparrow Das Beispiel leuchtet mir vollkommen ein. Aber wie du sagst, das ist hier eher weniger von Bedeutung. Falls ich doch mal irgendwann Langeweile habe, weis ich über was ich grübeln könnte.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@sparrow: dein Beispiel hinkt in sofern, dass Du nicht beschreibst, wie denn die Anzahl richtiger Antworten auf dem Server gezählt werden.
Im einfachsten Fall, wenn man für Frage 5 die Antwort von Frage 1 schickt, landet man wieder bei Frage 2. Der Schummlerin ist damit nicht geholfen.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@Sirius3: Doch beschreibe ich. Ich habe explizit geschrieben: 'Wenn es jetzt reicht x Mal "Das ist richtig." vom Server zu erhalten [...]'
Klar kann es anderweitig augeschlossen sein. Ich wollte trotzdem darauf hinweisen, dass man eingehenden Daten nicht ungeprüft vertrauen sollte.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Dennis89: jetzt sehe ich erst, dass Du beim Senden von "richtig" nochmal alle Antworten anzeigst. Ja, da wäre die einfachste Möglichkeit, die Antworten in einem input-Feld json-kodiert mitzuschicken
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@sparrow: ich schrieb nur, dass dann noch so einiges fehlt. Eine Benutzerverwaltung, Sessions, eine Datenbank im Hintergrund.
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Dann muss ich die Liste mit den Antworten schon das "erste" mal als json schicke, damit ich sie mit 'request.json' wieder zurück schicken kann? Weil wenn ich es nur mit 'request.json' versuche, bekomme ich die Meldung das nur json-Objekte so abgeholt werden können. Mit 'request.form' bekomme ich jedes Zeichen ink. der eckigen Klammern einzeln als String zurück, mal mit einem, mal mit zwei Leerzeilen dazwischen. Dass ist vermutlich das angesprochene Thema von @__blackjack__

Wenn ich im Netz schaue wie ich eine Liste in json wandle, dann stoße ich auf 'dumps'
Das Problem dabei ist dann aber folgendes:

Code: Alles auswählen

>>>import json
>>>answers = ["hallo", "Ciao"]
>>>print(json.dumps(answers))
["hallo", "Ciao"]
>>>for word in json.dumps(answers):
>>>    print(word)
    
[
"
h
a
l
l
o
"
,
 
"
C
i
a
o
"
]
Und so sehen dann natürlich auch meine Buttons aus.

So langsam qualmt mir auch ganz schön der Kopf.

Danke und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: `word` ist da als Name falsch. JSON ist *eine* Zeichenkette und die Elemente sind keine Worte, sondern einzelne Zeichen. Das `print()` vor der Schleife führt Dich in die Irre, denn da sieht man ja keinen Unterschied mehr zwischen einer Zeichenkette mit einer Liste und einer Liste die nicht in einer Zeichenkette steht.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Oh, das wird ja immer besser 🤯

Ich glaube da passiert heute nicht mehr viel. Ich habe gerade noch die Python-Doku zu JSON angeschaut und zwar so Sachen wie 'encode', 'JSONEncoder' gefunden, aber gerade weis ich allgemein nicht so recht, nach was ich eigentlich suche.

Wenn ich meine Antworten als JSON sende, dann passt meine 'for'-Schleife im HTML-Code gar nicht mehr, das mit der Liste war da schon angenehm. Oder wie geht man dann in HTML mit dem JSON um?

Vielen Dank und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@Dennis89: Ich glaube, du denkst zu kompliziert, was das JSON angeht.
So wie ich das sehe, kannst du das mit der Liste beibehalten. Nur dass an der Stelle die Liste als JSON-Array steht (und das bekommst du mit json.dumps()) und beim Lesen musst du mit json.loads(request.get_data('answers')) dann daraus wieder eine Liste machen.
Benutzeravatar
__blackjack__
User
Beiträge: 13003
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Es ging einzig und allein um den Punkt wo das als *ein* Wert in ein <input> gesteckt wurde. Die Schleife über die einzelnen Antworten muss weiterhin über die Liste passieren. Wobei ich wie gesagt nicht weiss warum man die Antworten überhaupt alle noch mal in einem versteckten <input> brauchen sollte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Dennis89
User
Beiträge: 1123
Registriert: Freitag 11. Dezember 2020, 15:13

Vielen Dank für eure Geduld und Hilfe.

Mit 'request.get_data('answers')' kommt leider nichts zurück.
Mit 'request.form['answers']' bekomme ich zwar Daten, wenn ich dann 'json.loads' mit den Daten als Argument aufrufe, dann bekomme ich die Meldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 2548, in __call__
    return self.wsgi_app(environ, start_response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 2528, in wsgi_app
    response = self.handle_exception(e)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/Question_Trainer/app.py", line 44, in check_answer
    answers = loads(request.form['answers'])
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 2 (char 1)
Es scheint als werden da wohl irgendwelche Leerzeichen/Leerzeilen mit gesendet? Ich habe erfolglos versucht mit replace('" ", "") die Leerzeichen zu entfernen.
Oder ist das hier ein anderes Probelm?

@__blackjack__ Ich denke das ich die Daten noch einmal brauche, weil ich mit den Programmablauf so vorstelle:
Kurz gesagt, wenn ich die schon im Bestand habe, dann weis ich nicht wie ich darauf zugreife.
Wenn ich über die ID der Frage, die Antworten hole, dann sind die nicht mehr in der gleichen Reihenfolge, wie sie waren, bevor eine Antwort ausgewählt wurde.
Ich beschreibe mal meine Gedanken, wie ich mir den Ablauf vorstelle.
Ausgewählt wird eine Frage, die erscheint und anhand ihrer ID werden die Antworten "ausgesucht" und mit 'sample' wird die Reihenfolge der Antwortmöglichkeiten beliebig getauscht. Dann wird die Frage, die ID und die Liste mit den Antworten, die in einer beliebigen Reihenfolge sind, an den Server gesendet und ich kann das im Browser sehen.
Dann klicke ich auf eine Antwort, ich lese den Wert des geklickten Buttons aus, anhand der ID ermittle ich die richtige Antwort und sende das zurück. Jetzt wird die Seite neu geladen und wenn ich jetzt nicht die gleiche Liste mit den Antworten wieder an den Server sende, dann sind entweder keine Antworten da oder wenn ich mir die Antworten wieder über die ID der Frage hole, dann sind sie in einer anderen Reihenfolge.
Weil ich das verwirrend finde, wenn sich die Reihenfolge ändert, wollte ich die beibehalten und irgendwie "speichern" und wieder senden.
Wie könnte ich das denn sonst noch umsetzen?

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten