ex-oop-02-horse-race/readme.adoc
github-classroom[bot] ced8bcdb46
add deadline
2024-10-17 13:32:13 +00:00

114 lines
No EOL
3.5 KiB
Text

[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/Z4IuCC1c)
:sectnums:
:nofooter:
:toc: left
:icons: font
:data-uri:
= OOB.02 -- Horse Race
This time you are going to read horse data from a CSV file and then simulate races between those horses, including output to the terminal.
[plantuml]
----
@startuml
class HorseRace {
+HorseRace(Horse[])
+int MaxSteps [const]
-int DelayMilliseconds [const]
-Horse[] _horses [readonly]
-bool IsFinished
+void PrintStartList()
+void PerformRace()
+void PrintResults()
-void MoveHorses()
-void DrawHorses()
-void AssignRanks()
-void SortByPosition()
}
class Horse {
+Horse(string, int, int)
+int Age [readonly]
+string Name [readonly]
+int Position [private set]
+int Rank
+int StartNumber [readonly]
+int CompareTo(Horse other)
+void Draw()
+void Move()
{static} +bool TryParse(string, int, out Horse?)
}
HorseRace "1" -r- "n" Horse: has
@enduml
----
== The `Horse` class
The `Horse` class, unsurprisingly, represents a horse.
Each horse has:
* A name
* An age
* An assigned starting number
During the race and based on the race results each horse gets assigned:
* A varying position
* A final rank
=== Method Requirements
Additional specifications for some methods -- primarily rely on the XML Doc.
* `CompareTo`
** Subtract _from_ the `other` value to get the correct `int` value
* `Move`
** The probability of moving one position ('field') forward is ~33%
*** Make sure to use the `Random` instance in `RandomProvider`
* `TryParse`
** The name cannot be empty
** The age of a horse has to be in the stem:[0 < x <= 20] range
** The starting number may not be negative
== Importing Data with the `HorseImporter` class
The `Horse` class provides a `TryParse` _factory method_, yet it still needs to be called for each CSV line which in turn needs to be read from a file.
That is the job of the `_static_` `HorseImporter` class.
Consider the usual rules for reading CSV files:
* The file has to exist
* It has to have a header and _at least one_ valid data row
* Invalid data rows are skipped
* If no data could be parsed an _empty_ array is returned
* Make sure the returned array does not contain any `null` values
NOTE: This is a `static` class providing a single, _stateless_ method
== Performing the race with the `HorseRace` class
A race can only happen when the horses are present.
Thus, it is _dependent_ on the array of horses => required to construct an instance of the `HorseRace` class.
* The `IsFinished` property is set to `true` once the first horse reaches the finish line
** Subsequent move operations are ignored
** The finish line is reached when the horse's `Position` equals `MAX_STEPS`
* `MoveHorses` applies a 'move order' to _each_ of the horses in the race
* Make sure to print in the expected format
** => see sample run below
** Remember that the `Horse` class already provides a `Draw` method!
* Ranks are assigned based on the position (at the end of the race), thus, horses with the same position also have the same rank
** Ranks start at 1 (not 0)
* When sorting make sure to use the `CompareTo` method of the `Horse` class
** Horses know how to compare to each other _themselves_!
NOTE: Do not worry about (already implemented) the delay between horse movements. We'll discuss various methods for adding delays to a program in a few months
=== Sample Run
video::pics/sample_run.mp4[width=480,opts=autoplay]