Erstelle zuerst einen Fork von diesem Repository und klone diesen. Führe den Befehl npm install im geklonten Verzeichnis aus.
Bearbeite die Aufgaben nach dem folgenden Vorgehen:
- Schreibe keinen Produktivcode, bis es einen Test gibt, der aufgrund dieses fehlenden Produktivcodes scheitert.
- Schreibe nicht mehr Testcode, als nötig ist, um den Test zum Scheitern zu bringen.
- Schreibe nicht mehr Produktivcode, als nötig ist, um den Test zum Laufen zu bringen.
Erstelle mindestens nach jeder Aufgabe einen Commit!
Betrachte den Testcode in src/calc.test.ts, welcher die beiden Funktionen sum und sub von src/calc.ts überprüft.
Pro Funktion gibt es mehrere Testfälle. Mithilfe von describe werden die Testfälle gruppiert.
Der obere Test ("adding up numbers") testet die Funktion sum und verwendet dazu gruppierte Tests mit einer manuell definierten Beschreibung.
Der untere Test ("subtracting numbers") testet die Funktion sub und verwendet dazu parametrisierte Tests mit einer generierten Beschreibung.
Bei der oberen Variante ist im Code besser erkennbar, was der einzelne Testfall ausdrücken soll. Bei der unteren Variante ist die Erweiterung um weitere Testfälle wesentlich weniger aufwändig, solange alle Testfälle nach dem gleichen Schema funktionieren.
In der Praxis verwendet man eine Kombination der beiden Varianten: Parametrisierte Tests für reguläre Fälle, die laufend erweitert werden (z.B. im Zuge der Korrektur von Fehlern) und gruppierte Tests mit einer präzisen Beschreibung für Spezialfälle.
Probiere in den folgenden Aufgaben beide Varianten aus (z.B. einzelne Tests in Aufgabe 1, parametrisierte Tests in Aufgabe 2 und eine Kombination davon in Aufgabe 3).
Bearbeite diese Aufgabe in src/duration.test.ts (Testcode) und src/duration.ts (Produktivcode).
In dieser Aufgabe soll die Funktion formatDuration in src/duration.ts implementiert werden. Anhand einer gegebenen Anzahl Sekunden soll eine Zeitdauerangabe nach der Form XXhYYmZZs zurückgegeben werden. Beispiele:
33wird zu33s.123wird zu2m3s.500wird zu8m20s.3600wird zu1h.3999wird zu1h6m30s.
Schreibe Tests und Produktivcode gemäss TDD-Vorgehen, indem du die obigen Fälle und folgende Spezialfälle testest und implementierst:
0wird zu0s.- Negative Zahlen führen zu einem
Errormit aussagekräftiger Beschreibung. (Teste auf eine geworfene Exception!) - Nachkommastellen von Sekundenangaben werden durch Rundung eliminiert (siehe
Math.round).
Bearbeite diese Aufgabe in src/rock-paper-scissors.test.ts (Testcode) und src/rock-paper-scissors.ts (Produktivcode).
Implementiere das Spiel Schere, Stein, Papier bzw. Rock, Paper, Scissors in der Funktion play.
Die Funktion erwartet als Parameter die Spielzüge zweier Spieler als Zeichenkette:
"rock": Stein"paper": Papier"scissors": Schere
Die Gross- und Kleinschreibung sowie führende und anschliessende Leerzeichen sollen ignoriert werden.
Die Funktion soll den folgenden Wert zurückgeben:
1wenn Spieler 1 gewinnt.2wenn Spieler 2 gewinnt.0bei einem Unentschieden.
Für ungültige Spielzüge wird eine Exception mit sprechender Fehlermeldung geworfen.
Schreibe die Testfälle und implementiere die Funktion play gemäss TDD-Vorgehen.
Bearbeite diese Aufgabe in src/isbn13.test.ts (Testcode) und src/isbn13.ts (Produktivcode).
Bücher werden anhand einer ISBN (internationale Standardbuchnummer) identifiziert. Früher war dies eine zehnstellige Zahl (ISBN-10). Heutzutage verwendet man die dreizehnstellige ISBN-13, um mit EAN (European Article Number) kompatibel zu sein. (Als Landespräfix wird die Zahl 978 oder 979 verwendet, welche für das fiktive Land Buchland steht.)
Die letzte Stelle einer ISBN-13 ist eine sogenannte Prüfsumme, mithilfe welcher man mögliche Fehler beim Übermitteln einer ISBN-13 bzw. Fehler beim Scanvorgang des Barcodes erkennen kann. Der Algorithmus zur Berechnung der ISBN-13-Prüfsumme soll gemäss TDD-Vorgehen in src/isbn13.ts in der Funktion isValid umgesetzt werden.
Schreibe die Testfälle und implementiere die Funktion isValid gemäss TDD-Vorgehen.
Dieses mal musst du selber sinnvolle Testdaten und -fälle zusammenstellen.
Bearbeite diese Aufgabe in src/darts.test.ts (Testcode) und src/darts.ts (Produktivcode).
Bei der Darts-Spielvariante 501 geht es darum, mit möglichst wenig Würfen von 501 auf null Punkte zu kommen. Das Spiel funktioniert (vereinfacht für einen Spieler) folgendermassen:
- Der Spieler wirft dreimal mit je einem Pfeil auf das Brett.
- Die Anzahl Punkte für die Runde wird berchnet und vom Zwischenstand (zu Beginn: 501) abgezogen.
- Bei einem Treffer in einen bestimmten Sektor erhält der Spieler die einfache Punktzahl (z.B. Single 18: 18).
- Wird der Double Ring getroffen, erhält der Spieler die doppelte Punktzahl des Sektors (z.B. Double 17: 34).
- Wird der Triple Ring getroffen, erhält der Spieler die dreifache Punktzahl des Sektors (z.B. Triple 20: 60).
- Die Runde ist zu Ende, wenn der Spieler auf null Punkten ist.
- Die Punktzahl 0 muss exakt erreicht werden. Wird die Punktzahl 0 unterschritten (bust), gibt es keine Punkte. Der Zwischenstand wird auf denjenigen vor dem Wurf zurückgesetzt. (Beispiel: Bei 37 offenen Punkten trifft der Spieler zuerst die 20 und dann die 18 ‒ bust. Der Spieler ist wieder bei 37 Punkten.)
- Die Punktzahl 0 muss über einen Double Checkout erreicht werden, d.h. mit dem letzten Wurf muss man den Double Ring treffen. (D.h. man kann die Runde nur beenden, wenn beim letzten Wurf eine gerade Punktzahl verbleibt.)
Zur Illustration eine Dartscheibe mit den Sektoren, Ringen und dem Bull's Eye in der Mitte:
In dieser Aufgabe geht es um zwei Berechnungen:
- Berechnung der Punktezahl aus einer Runde anhand einer Zeichenkette: Funktion
calcPoints.- Der Spieler gibt seine Treffer im folgenden Format ein (Beispiele):
3 20 1 17 2 4: Triple 20, Single 17, Double 4:3*20+1*17+2*4=852 15 1 18 3 19: Double 15, Single 18, Triple 19:2*15+1*18+3*19=1053 20 1 5: Triple 20, Single 5, [einmal daneben]:3*20+1*5=65- D.h. Ring-Multiplikator und Sektor wechseln sich jeweils ab.
- Eine Funktion soll aus der Zeichenkette die Punktezahl berechnen.
- Der Spieler gibt seine Treffer im folgenden Format ein (Beispiele):
- Ermittlung eines Treffers für den Double Checkout bei gegebener Punktzahl: Funktion
possibleCheckout.- Der Spieler hat bisher eine bestimmte Punktezahl
xgeworfen. - Es verbleiben noch eine bestimmte Anzahl Punkte (
501-x). - Es soll berechnet werden, mit welchem Wurf die Runde mittels Double Checkout beendet werden kann.
- Beispiel:
x=477,501-477=24,24:2=12,"Double 12" - Beispiel:
x=480,501-480=31,31:2=15.5, [unmöglich, da ungerade] - Beispiel:
x=441,501-441=60,60:2=30, [unmöglich, da30>20]
- Der Spieler hat bisher eine bestimmte Punktezahl
Implementiere die beiden Funktionen, indem du dich wiederum ans TDD-Vorgehen hälst. Wenn dir unklar ist, wie die API genau funktionieren soll (z.B. was possibleCheckout zurückgeben soll, wenn kein Checkout möglich ist), entscheide dich selber für eine Lösung!
