Quiz mit Javascript erstellt - bitte um Code-Beurteilung

  • Ich konnte pointerEventsOn() komplett aus diesem Eventlistener entfernen, denn ich hatte diese Funktion schon in die Funktion startTimer() integriert. Jetzt scheint alles zu funktionieren.


    Wie schützt sich der Profi vor solchen unsinnigen Doppelungen und überflüssigem Code, der später zu Problemen führen kann?

  • Heute Morgen ist mir noch was eingefallen …


    Ursprünglich war es mal mein Ziel, dass ein User die richtigen Antworten nicht vorm Spiel auslesen kann. Das war in einer älteren Version auch der Fall. Und jetzt habe ich im Eifer des Gefechts die Datei http://music-quiz.bplaced.net/mq05/giveTrueNumbers.php eingeführt und mir dabei selbst ein Bein gestellt.


    Ich meine, hier geht es um nichts, aber es ärgert mich trotzdem. Gibt es denn eine Möglichkeit, dass auch für erfahrene User solche „Betrugsmöglichkeiten“ nicht im Quelltext erkennbar sind?

  • Wenn ich mich richtig erinnere, hatten wir früher den Index der gewählten Antwort als POST-Parameter an ein PHP-Skript geschickt und ein boolean, das angibt, ob die Antwort richtig war, zurück bekommen. Das macht es zwar nicht völlig unmöglich, die richtige Antwort heraus zu bekommen aber ein ganzes Stück schwerer.

    Du könntest dieses Verfahren auf alle Antworten erweitern, d. h. die Indizes der gewählten Antworten wieder als POST-Parameter an das Skript schicken und ein Array mit booleans zurück bekommen.


    Zitat

    Wie schützt sich der Profi vor solchen unsinnigen Doppelungen und überflüssigem Code, der später zu Problemen führen kann?

    Dafür kenne ich leider kein Patentrezept. Generell haben Programme oder Skripts die Tendenz, zu wachsen und zu wachsen und es wird dann immer schwerer, den Überblick zu behalten und zu erkennen, ob mehrfacher Code drin ist oder Ungereimtheiten. Eine Möglichkeit vorzubeugen ist, nach dem Prinzip KISS vorzugehen "keep it simple and stupid", anstatt den Code unnötig kompliziert zu machen.

  • Ich müsste also, nachdem eine Antwort gegeben worden ist, die jeweilige richtige Antwort per ID aus der Datenbank holen und in ein Array speichern, wenn ich es richtig sehe. Dann hätte man nur Zugriff auf die Antworten, für die man schon eine Entscheidung getroffen hat.


    Was den Code angeht: Ich hatte ab und zu das Gefühl, dass ich langsam den Überblick verliere. ;) Für mich ist das Ganze schon ziemlich komplex, habe versucht, es durch Kommentare und größere Abstände zwischen den einzelnen Bereichen übersichtlicher zu machen. Dass sich da allerdings eine Funktion doppelt versteckt, wurde mir dadurch auch nicht verraten. Und nur durch ständiges Testen kriegt man die Bugs dann wirklich zu fassen.


    Ich wünsche Dir einen schönen Sonntag … und natürlich danke für Deine wie immer superschnelle Antwort!

  • So, ich habe es geschafft. Jetzt wird die Ziffer der richtigen Antwort erst nach Beantwortung der jeweiligen Frage aus der DB geholt und in ein Array gespeichert. Ist also doch etwas bei mir hängengeblieben. :)


    Der Link ist noch derselbe: http://music-quiz.bplaced.net/mq05/


    Falls ich sonst noch etwas übersehen habe oder andere Bugs auftauchen, bin ich für eine Info dankbar. Schönen Abend und einen guten Start in die Woche!

  • Ich bastle gerade an einer Version meines Spiels, bei der die nächste Frage geladen wird, sobald man eine Antwort gegeben hat, ohne dass man einen Weiter-Button drücken muss. Aber ich habe ein Problem mit der dabei verwendeten Timeout-Funktion. Hier der entsprechende Code-Schnipsel:



    Solange die Gesamtzahl der Fragen nicht erreicht ist, soll nach dem Klick auf einen Antwortbutton (Eventlistener hier im Codebeispiel nicht enthalten) der Bereich des Spiels gedreht und eine Transparenz gesetzt werden. Diese Transition hat eine Verzögerung von 2 Sekunden und dauert 1,5 Sekunden.


    Sind diese 3,5 Sekunden vorüber, startet der Inhalt der Timeout-Funktion. Drehung und Transparenz werden zurückgesetzt, die neue Frage wird geladen, der Timer zurückgesetzt und die Pointerevents eingeschaltet.


    Das funktioniert theoretisch sehr gut und praktisch nur in 70, 80 % der Fälle. Ab und zu – unregelmäßig – kommt das Timing durcheinander. Dann werden die Elemente aus der Timeout-Funktion geladen, bevor die erste Transition abgeschlossen ist.


    Ich ahnte irgendwie beim Erstellen bereits, dass diese Konstruktion ziemlich fragil aussieht. Die zeitliche Abstimmung der einzelnen Events scheint so nicht zu funktionieren. Wie kann man das auf sichere Füße stellen?


    ---


    Nachtrag: Ich habe gerade die Verzögerung von 2 Sekunden aus der CSS-Transition entfernt und in ein JavaScript-Timeout gesetzt. Hier der geänderte Code:



    Der Effekt ist das Gegenteil dessen, was ich gehofft hatte. Die Abläufe haben sich nicht verbessert, sondern verschlechtert – die Fehlfunktion tritt jetzt noch häufiger auf, der zweite Timer startet, bevor der erste beendet ist. Ich wäre wirklich für Hilfe sehr dankbar, da mein Konzept offensichtlich falsch ist.

  • Gilt der Link von früher (Posting #186) noch? Ohne das Ganze im Zusammenhang zu sehen, kann man die Frage wahrscheinlich nicht beantworten.

    Und gibt es noch einen Link für die vorige Version mit dem Next-Button?


    Mein spontaner erster Eindruck: Zu viele Timer :)

  • Guten Morgen und wie immer danke für die schnelle Reaktion! :)


    Der Link von #186 funktioniert noch und verweist auf die ältere Version mit Next-Button.


    Habe die neue Version jetzt online gestellt:

    http://music-quiz.bplaced.net/test06/

    http://music-quiz.bplaced.net/test06/musicQuiz.js


    Inzwischen hatte ich noch einiges versucht, z. B. auch eine Verschachtelung der Timer, aber es wurde eher schlimmer …


    Wichtig wäre mir aber hier wirklich die exakte zeitliche Abstimmung der Ereignisse. Danke!

  • Ich bin da noch nicht in die Details eingestiegen, aber schon Mal zwei Hinweise:

    1. Die nächste Frage anzuzeigen erfordert ja die selbe Aktion wie ein Klick auf den next-Button in der früheren Version. Also den betr. Code aus dem Eventlistener in eine Funktion schreiben.
    2. Es gibt in Javascript auch ein Event für das Ende einer Transition, siehe hier:
      https://developer.mozilla.org/…ement/transitionend_event
      Wenn Du das verwendest, um das Ende der Transitions abzuwarten, brauchst Du die Zeiten für die Timer nicht abzugleichen und brauchst wahrscheinlich überhaupt keine Timer mehr. Das Event feuert präzise dann wenn die Transition beendet ist.
  • Danke Dir!


    Die Funktionen für die nächste Frage habe ich vom Next-Button übernommen, das war mein erster Schritt und das funktioniert ja auch einwandfrei.


    Danach wollte ich die Effekte und Verzögerungen einsetzen und bekam o. g. Probleme. Jetzt schaue ich mir natürlich den von Dir genannten Link an und versuche, alles dementsprechend umzubauen.


    Mir scheint, es gibt generell Probleme mit Timeouts in JavaScript, oder? Man kann sich nicht darauf verlassen, dass die Timer exakt hintereinander ablaufen, wie mein Beispiel zeigt. Aber was ist die Ursache dafür?

  • An sich funktionieren die Timer in Javascript schon zuverlässig, natürlich nicht auf die Millisekunde genau. Probleme können jedoch dann auftreten, wenn Du auf etwas anderes wartest, wie in deinem Fall das Ende einer Transition. Dann kann man natürlich eine Art Reserve einplanen um sicher zu gehen, dass die Transition auch beendet ist. Was aber nicht wirklich befriedigend ist. Besser ist in dem Fall ein Event für den originalen Vorgang zu verwenden, was bei einer Transition ja möglich ist.

    Was die Timer betrifft, ist es außerdem nicht ganz ausgeschlossen, dass man sich bei der Berechnung der Verzögerung verkalkuliert.

  • Dass die Verzögerung aus der CSS-Transition sich nicht exakt auf das Timeout von JS abstimmen lässt, hatte ich bereits im Vorfeld geahnt. Sehr erstaunt war ich allerdings, dass die ausschließliche Verwendung von JS-Timeouts (zweites Codebeispiel in #187) zu noch größeren Problemen führt.


    Eine Zeitreserve ist in meinem Fall nicht machbar, da sie sich optisch auswirken würde. Und deshalb habe ich auch genau kalkuliert – wenn der Effekt korrekt funktioniert, funktioniert er wunderbar. Aber „wenn“ ist halt nicht die Bedingung, mit der ich zufrieden bin. ;)

  • Hm, ich komme mit den Events für das Ende einer Transition nicht klar:


    http://music-quiz.bplaced.net/test07/

    http://music-quiz.bplaced.net/test07/musicQuiz.js


    Auf Zeile 381 startet die Transition für das Element playpart. Dann gibt die Konsole die verschiedenen Events aus, und es sind etliche. Vor allem werden transitionstart und transitionend zweimal ausgegeben. Mir scheint, da wird auch das Ende der Verzögerung als transitionendangesehen.


    Und deshalb funktioniert auch die folgende Transition absolut nicht. Was habe ich hier wieder falsch gemacht?


    ---


    Nachtrag: Das Problem liegt offensichtlich in den beiden Transitions, die auf den Zeilen 347 und 350 ablaufen. Die hier veränderten Elemente liegen im Element playpart und bringen wohl dadurch den Ablauf durcheinander. Entferne ich diese beiden Transitions (was natürlich eigentlich nicht gewollt ist), funktioniert der Eventlistener für playpart wie gewünscht.


    Muss ich mich jetzt von dieser ganzen Vorgehensweise verabschieden? Sieht nach einer Sackgasse aus.

  • Da geht ja wirklich die Post ab in der Console! Möglicher Weise muss ich da doch mal bis in die Details einsteigen, um dir weitere Hinweise zu geben.

    Aber bevor ich das tue, zunächst diese zwei Hinweise:

    1. Du hast die Eventlistener für die Transitions innerhalb des Listeners für einen Klick auf eine Antwort registriert. Dadurch kommen bei jedem Schritt neue dazu.
    2. Javascript übergibt bei jedem Listener den Parameter target. Füge das mal hinzu und sieh dir das target bei transitionend an. Möglicher Weise bekommst Du dort Hinweise über den Status der Transition und um welches Element es sich handelt.
    Code
              playpart.addEventListener('transitionstart', function (event) {
                console.log('transitionstart', event);
              });
  • Unsere beiden Postings (mein Nachtrag gerade in #194 und Dein #195) haben sich überschnitten. Der Parameter target sagt so ungefähr das, was ich vermutet habe.


    Die Transition für playpart selbst ist in der Konsole von Firefox gar nicht zu sehen, in Chrome schon. Das nächste Rätsel …


    Online-Beispiel ist aktualisiert.

  • Ich erwarte eher nicht, dass das eine Sackgasse ist.

    Ich habe mal rasch einen Test gemacht mit folgendem Ergebnis:

    Animiert man zwei Eigenschaften, feuert das "transitionend" zwei Mal, d. h. einmal für jede Eigenschaft.

    Unter event.propertyName findest Du die Eigenschaft, auf die sich das Event bezieht.

    Versuche zunächst, ob die diese Infos weiter helfen.

  • Hm, warum sehe ich dann (im Firefox) nur das:


    12:07:51.324 transitionend

    transitionend { target: button#1

    , propertyName: "opacity", pseudoElement: "" }

    musicQuiz.js:392:21


    12:07:51.329 transitionend

    transitionend { target: button#2

    , propertyName: "opacity", pseudoElement: "" }

    musicQuiz.js:392:21


    12:07:51.330 transitionend

    transitionend { target: button#4

    , propertyName: "opacity", pseudoElement: "" }

    musicQuiz.js:392:21


    12:07:51.330 transitionend

    transitionend { target: div#countPlayTime

    , propertyName: "opacity", pseudoElement: "" }

    musicQuiz.js:392:21


    12:07:52.341 transitionend

    transitionend { target: div#countPlayTime

    , propertyName: "opacity", pseudoElement: "" }

    musicQuiz.js:392:21


    Kein div#playpart. Und kein transform, nur opacity. Ich kapiere es gerade gar nicht mehr.

  • Zitat

    Kein div#playpart. Und kein transform, nur opacity.

    Da bin ich auch noch nicht dahinter gekommen.


    Aber ich habe inzwischen ein wenig weiter getestet und verstehe jetzt die Abläufe mit deinen Animationen besser. Hier mein Testcode:

    Ziehe als erste das Registrieren des Eventlisteners für "transitionend" aus dem anderen Listener heraus wie ich es in dem Code beschrieben habe.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!