Stream Three-Projekt: Datenzentrierte Entwicklung – Code Institute.
Dieses Projekt wurde mit dem Flask Microframework erstellt und konnte als manuelle Stoppuhr verwendet werden, um die Zeit mehrerer Athleten beim Schwimmen und Leichtathletik zu messen. Das Ziel dieser Anwendung besteht darin, die Effizienz bei der Zeitmessung im Sport zu verbessern, indem die Anzahl der Personen, die die Zeitnahme separat messen, verringert und die Zeiten direkt gespeichert werden, anstatt eine schriftliche Dokumentation zu führen.
DIESE ANWENDUNG IST NUR FÜR BILDUNGSZWECKE BESTIMMT. DIESE ANWENDUNG IST NICHT FÜR KOMMERZIELLE NUTZUNGEN BESTIMMT.
Eine Live-Demo dieses Projekts finden Sie hier. Diese App wird auf Heroku gehostet. Die Zeiten werden in MongoDB gespeichert.
Die Idee für diese Timing Assistant-App entstand, als ich in meiner Kindheit mit dem Schwimmen in Kontakt kam. Mir ist aufgefallen, dass am Zeitmessungsprozess mehrere Personen beteiligt sein müssen, da die Touchpads im Pool aus verschiedenen Gründen nicht immer genaue oder lesbare Zeiten liefern. Darüber hinaus können der Trainer und die Athleten die endgültigen Zeiten oder Zwischenzeiten erst nach Ende des Wettkampfs sehen, es sei denn, es sind mehrere Personen an Deck für jede Bahn, die die Zeiten auf einem Klemmbrett notieren.
Ich sah die Gelegenheit, eine Anwendung zu entwickeln, die die Anzahl der am Timing-Prozess beteiligten Personen reduzieren würde, in der Hoffnung, die Effizienz der Treffen und das Feedback an die Athleten und Trainer zu verbessern. Diese Anwendung kann für jede zeitgesteuerte Sportart optimiert werden und diese Version funktioniert sowohl beim Schwimmen als auch bei der Leichtathletik.
Sowohl Trainer als auch Zeitnehmer können eine Sportart, ein Treffen, ein Ereignis, einen Lauf und Bahnnummern auswählen, die ihnen dabei helfen, den Überblick über das Geschehen bei einem Wettkampf zu behalten. Außerdem können sie ihren Athleten nach einem Rennen sofort Feedback geben, da die Zeiten angezeigt werden, nachdem Sie sie gespeichert und dann auf „Zeiten anzeigen“ geklickt haben. Ich wollte außerdem sicherstellen, dass sie kumulierte Ergebnisse für das Treffen sehen können, anstatt nur jeweils eine Veranstaltung.
Für dieses Design wurde kein Thema verwendet, das moderne Design wurde gewählt, da eine Seite mit vielen Timern und Daten unordentlich und unorganisiert wirken kann. Ich wollte das nicht, also wollte ich zwar die Timer, Zeiten und Ereignisoptionen auf einer Seite haben, dachte aber, dass die vertikale Aufteilung der Seite in Drittel der beste Weg wäre, dies zu erreichen und einen spürbaren Unterschied zwischen den einzelnen Dritteln zu erzeugen.
Timing Assistant wurde mit dem Flask Microframework in Python mit einer NoSQL-Datenbank (MongoDB) im Backend, mit HTML, CSS, Javascript und jQuery im Frontend und für die Stoppuhrfunktionalität erstellt, die über AJAX mit dem Backend verbunden ist.
Auf der Startseite der App gibt der Benutzer die Sportart, für die er Zeit nehmen möchte, seinen Teamnamen, seinen Benutzernamen und den Namen des Wettkampfs ein. Durch diese Aktion gelangen sie zur Stoppuhr-Seite, wo sie dann das Ereignis und den Lauf auswählen können, für den sie sich die Zeit nehmen möchten. Der Benutzer kann bis zu drei Bahnen messen und Teilungen für alle drei Bahnen vornehmen. Der Benutzer muss den Haupttimer manuell stoppen, nachdem alle drei kleinen Timer gestoppt wurden, da diese einzeln eingestellt werden. Dies könnte jedoch besonders nützlich sein, wenn der Trainer wissen möchte, wie lange das Rennen dauert, und die Zeiten seiner Schwimmer mit der Zeit des letzten Finishers vergleichen möchte. Die Zeit des Haupttimers wird nicht in der Datenbank gespeichert.
Sobald sie auf „Senden“ klicken, werden das Ereignis und der Lauf angezeigt. Anschließend können sie die Zeitmessung für bis zu drei Bahnen starten, indem sie auf der Hauptstoppuhr „START“ drücken. Dadurch werden alle vier Stoppuhren gestartet, allerdings werden nur die letzten drei in der Datenbank gespeichert. Über die Schaltfläche „SPLIT“ besteht die Möglichkeit, Zwischenzeiten für jede Bahn einzeln zu erfassen. Jeder Timer kann einzeln gestoppt und gestartet werden, wobei der Haupttimer alle Stoppuhren steuert (Starten, Stoppen und Zurücksetzen).
Durch Klicken auf „ZEITEN SPEICHERN“ werden die Zeiten gespeichert, indem der AJAX-Aufruf in der Javascript-Datei verwendet wird, um die Zeiten an Flask zu übertragen, wobei Flask mit MongoDB verbunden ist. Sobald die Zeiten gespeichert wurden, werden die Zeiten durch Klicken auf „ZEITEN ANZEIGEN“ unter den Stoppuhren angezeigt.
Die Daten werden auch ohne Angabe eines Ereignisses oder Laufs gespeichert (diese Felder sind leer, wenn die Zeiten angezeigt werden). Dies könnte nützlich sein, wenn ein Trainer die Stoppuhren im Training und nicht bei einem Wettkampf verwenden möchte.
Ich möchte den Trainern die Möglichkeit geben, die Daten im PDF-Format oder einem anderen Dateiformat herunterzuladen. Auf lange Sicht würde es ihnen ermöglichen, die gesamte manuelle Zeitmessung für ihre Aufzeichnungen beizubehalten, ohne sich jedes Mal auf handschriftliche Daten oder diese Website verlassen zu müssen, wenn sie zurückgehen und sich alte Treffen ansehen möchten.
Ich möchte dem Trainer auch erlauben, die Anzahl der Stoppuhren, die er sehen möchte, basierend auf der Anzahl der Athleten in jedem Lauf auszuwählen. Derzeit können Sie nur für drei Athleten gleichzeitig eine Zeit nehmen, und Sie können sich nicht für weniger als drei Athleten entscheiden.
Ich würde auch gerne einen „Übungsmodus“ und einen „Meeting-Modus“ implementieren, die eine genauere Zeitplanung für Treffen und Übungen ermöglichen würden. Der Meet-Modus würde mehr Einschränkungen bei der Auswahl einer Veranstaltung oder eines Laufs mit sich bringen und es dem Trainer ermöglichen, zu entscheiden, für wie viele Bahnen er Zeit haben möchte. Der Übungsmodus würde es dem Trainer ermöglichen, sich Notizen zu den eingesparten Zeiten zu machen (für eine bestimmte Übung usw.), ohne ein Ereignis oder einen Lauf angeben zu müssen.
Alle Tests für dieses Projekt wurden manuell durchgeführt. Das Formular auf der Zielseite verfügt über erforderliche Attribute für die Eingabe-Tags, um zu verhindern, dass der Benutzer ein Feld im Formular nicht ausfüllt, da dies zu einem 400-Fehler führt, da die Flask-App-Route von diesen Eingaben abhängt.
Die Ajax-Funktion und die Schaltfläche „Zeiten speichern“ wurden über die Konsole getestet und überprüft, ob die Daten in MongoDB korrekt formatiert angezeigt wurden. Auch die von den Timern gesammelten Daten und die vorgesehene Datenstruktur wurden getestet.
Zeitersparnis individuell mit einem Dokument pro Spur:
Zeiten für die Anzeige von Spuren im selben Dokument (Hinweis: Zu Testzwecken wurden hier nur zwei Spuren gespeichert, um sicherzustellen, dass zwei Spuren im selben Dokument angezeigt werden.):
Richtige Datenstruktur:
Die Tests der Stoppuhren wurden ebenfalls manuell durchgeführt, um sicherzustellen, dass die Haupt-Reset-Taste die Stoppuhr zurücksetzte und die Zwischenzeiten aller Timer löschte, während jede einzelne Stoppuhr nur ihre eigene Zeit und Zwischenzeiten löschte. Darüber hinaus wurde dies auch für die Start-/Stoppfunktion getestet, da die Hauptstoppuhr alle Stoppuhren steuert, während die einzelnen nur ihre eigenen Start-/Stoppfunktionen steuern sollten.
Alle Flask-Pfade wurden außerdem getestet, um sicherzustellen, dass alle Links funktionierten, ungewöhnliche Werte in der Eingabe verarbeitet werden konnten und Eingaben über Jinja in der HTML-Datei ordnungsgemäß angezeigt wurden.
Während des Testprozesses wurde mir klar, dass es möglich sein könnte, dass zwei Benutzer denselben Meet-Namen oder denselben Clubnamen haben, wodurch es für den Benutzer möglich wäre, auf die Daten einer anderen Person zu stoßen. Um die Zeiten in der Vorlage anzuzeigen, habe ich Folgendes eingefügt, um sicherzustellen, dass drei Eingabefelder auf der Zielseite übereinstimmen müssen, damit die entsprechenden Zeiten angezeigt werden. Dazu müssen der korrekte Teamname, der Benutzername und der Name des Treffens übereinstimmen, um ein gegenseitiges Speichern oder gegenseitige Anzeigen von Zeiten zu verhindern.
{% if time.team == team %}
{% if time.username == username %}
{% if time.meet == meets %}
Die Aufteilungen für jede Spur wurden ursprünglich im folgenden Format angezeigt:
split: ["00:02.2300:01.45"]
Ich wollte jedoch, dass sie in einer Liste wie dieser angezeigt werden:
split: ["00:02.23", "00:01.45"]
Daher musste ich ein Listenverständnis implementieren, um diese Zeichenfolge alle 9 Zeichen in mehrere Zeichenfolgen in einer Liste aufzuteilen (wenn mehr als eine Aufteilung für eine Spur vorgenommen wurde).
In der HTML-Datei „timer_page.html“ sieht das Formular, das Daten für die AJAX-Funktion sendet, so aus, als hätte es ein verirrtes End-Tag, das jedoch alle Endzeiten, Split- und Lane-Daten umfassen musste, um die Zeiten in MongoDB zu speichern . Aufgrund des Stils und anderer Elemente, die angezeigt werden müssen, sieht es so aus, als ob das Formular nicht mit den anderen Elementen übereinstimmt. Auch wenn man sich den HTML-Code ansieht, gibt es leere Tags, allerdings werden hier die Zwischenzeiten mit jQuery in den HTML-Code eingefügt.
Wenn Sie beim Speichern der Zeiten für jeden Timer dieselbe Spur auswählen (z. B. Spur 1), wird nur eine der Zeiten von Spur 1 in den Ansichtszeiten angezeigt. Sie müssen jedoch eine Spur auswählen, da Sie aufgrund der Art der Datenstruktur ohne diese Spur die von Ihnen gespeicherten Zeiten nicht anzeigen können. Das Spur-Dropdown-Menü ist standardmäßig auf Spur 1, Land 2 und Land 3 eingestellt, falls der Benutzer keine Spur angibt. Ich hoffe, eine Validierung implementieren zu können, die verhindert, dass die Zeiten gespeichert werden, wenn der Benutzer in einem Lauf für zwei Spuren dieselbe Spurnummer wählt.
Die Javascript-Funktionen, die die Stoppuhr ausführen, wurden aus dem Stoppuhr-Tutorial von Coding with Sara für diese Anwendung geändert. Ein Teil des HTML-Codes wurde ebenfalls nach ihrem Beispiel modelliert, jedoch an den Stil, mehrere Schaltflächen, Teilungen und Spuren angepasst.
Für das JavaScript wurden die Reset-Funktionen für die Reset-Schaltfläche geändert, um alle Stoppuhren zurückzusetzen, anstatt die Seite zu aktualisieren, und einzelne Reset-Schaltflächen für jede kleine Stoppuhr wurden entfernt, da es sich um eine unnötige Funktion für die UX dieses Projekts handelte. Außerdem wurden Split-Funktionen hinzugefügt. Die Start-/Stopp-Funktionen wurden für eine Stiländerung bei Schaltflächen mithilfe von jQuery geändert. Für UX wurde eine Hauptstoppuhr hinzugefügt, sodass der Trainer die verstrichene Gesamtzeit zusammen mit den Einzelzeiten sehen konnte, ähnlich einer Schwimm-Anzeigetafel. Die Schaltfläche „Speichern“ zum Übergeben von Werten an Flask und an MongoDB wurde mithilfe von Ajax hinzugefügt.
Die Ajax-Funktion wurde diesem Beitrag von Stack Overflow nachempfunden und durch Betrachtung von Mustern anderer Ajax-Verwendungen und -Syntax an dieses Projekt angepasst. Ein „preventDefault“ wurde hinzugefügt, um zu verhindern, dass die Seite neu geladen wird, wenn der AJAX-Aufruf erfolgt.
Die Rekursion in Jinja wurde verwendet, um über die verschachtelten Wörterbücher in Python zu iterieren, um die Zeiten und Daten richtig darzustellen, indem sichergestellt wurde, dass alle Spuren durchlaufen und angezeigt wurden. Diese Methode von Stack Overflow wurde als Richtlinie befolgt und an die Art meiner Datenstruktur angepasst.
Es wurde versucht, die Javascript-Funktion für die Stoppuhren umzugestalten, damit der Benutzer basierend auf der Anzahl der ausgewählten Bahnen entscheiden kann, wie viele Stoppuhren auf dem Bildschirm angezeigt werden sollen.
var stopwatches = [ ] ;
var i ;
for ( i = 0 ; i <= 1 ; i ++ ) {
var stopwatch = new timing ( "timerLabel" + i , "start" + i , "splitLabel" + i ) ;
stopwatches . push ( stopwatch ) ;
console . log ( i ) ;
document . getElementById ( "start" + i ) . onclick = function ( ) {
stopwatches [ i ] . start ( ) ;
}
document . getElementById ( "reset" + i ) . onclick = function ( ) {
stopwatches [ i ] . reset ( ) ;
}
document . getElementById ( "split" + i ) . onclick = function ( ) {
stopwatches [ i ] . split ( ) ;
}
console . log ( stopwatches ) ;
}
Beim Versuch, diese in eine for-Schleife wie diese zu schreiben, liest stopwatches[i].start() i
nicht als eine Variable, die sich ändern kann. Bei fester Codierung gab es jedoch kein Problem:
document . getElementById ( "reset" + i ) . onclick = function ( ) {
stopwatches [ 0 ] . reset ( ) ;
}
document . getElementById ( "split" + i ) . onclick = function ( ) {
stopwatches [ 0 ] . split ( ) ;
}
Ich habe versucht, es anders anzugehen, indem ich if-Anweisungen verwendet habe, um die entsprechenden Stoppuhren anzuzeigen.
Es wurde versucht, das i
stattdessen als Argument aus der obigen for-Schleife durch eine Funktion zu übergeben, war jedoch erfolglos:
function chooseNumberOfStopwatches ( i ) {
if ( i == 1 ) {
stopwatches_one . start ( ) ;
}
else if ( i == 2 ) {
stopwatches_one . start ( ) ;
stopwatches_two . start ( ) ;
} else {
console . log ( 'else' ) ;
}
}
Wenn Sie daran interessiert sind, dieses Repository zu klonen, führen Sie den folgenden Befehl im Terminal aus, um alles in der Datei „requirements.txt“ einzurichten und zu installieren:
$ sudo pip3 -r install requirements.txt
Bitte beachten Sie, dass ich für dieses Projekt Cloud9 verwendet habe. Wenn Sie also einen anderen Editor verwenden, können die Terminalbefehle abweichen. Weitere Informationen zu editorspezifischen Terminalbefehlen finden Sie in der Dokumentation des von Ihnen verwendeten Editors. Alle geheimen Schlüssel für MongoDB müssen einzeln beschafft werden, da sie versteckt und spezifisch für mich sind.