I am creating a scoring system for a competition that is somewhat obscure, but it resembles the Olympics in terms of its high-level structure. Therefore, I will ask my question in terms of an abstracted, fictional version of the Olympics, since everyone can relate to that to some degree.
Assume the following hierarchy of classes and score rollups:
- Event class has one or more Sports (e.g., the 2012 Olympics has Decathlon, IndividualMedley, etc.) and one or more EventScores (one EventScore per Team per Event calculated by adding up the team's SportScores for a particular Event)
- Sport class has one or more Elements (e.g., Decathlon has Shotput, Javelin, etc.) and one or more SportScores (one SportScore per Team per Sport calculated by adding up the team's ElementScores for a particular Sport)
- Element class has one or more Rounds (e.g., Shotput has Throw1, Throw2, etc.) and one or more ElementScores (one ElementScore per Team per Element calculated by adding up the team's RoundScores for a particular Element)
The scoring algorithm (let's call it the CalculateRoundScore() method) of a particular RoundScore depends on the Element to which the Round belongs. Examples:
- Shotput element: CalculateRoundScore(double ThrowDuration, double ThrowDistance, double GruntVolume) { algorithm; }
- Javelin element: CalculateRoundScore(double ThrowDuration, double ThrowDistance, double GruntVolume) { algorithm (different from Shotput algorithm even though parameters are the same, which would seem to eliminate overloading as a viable option); }
- 100MeterDash element: CalculateRoundScore(double Time, bool FalseStart) { algorithm; }
Although I am seeking general architecture guidance, here are some of my specific questions:
- How do I associate different CalculateRoundScore methods to different Elements?
- Should I use interfaces, inheritance, overloading, or some other approach?
- In which class(es) should the various CalculateRoundScore methods be located?
Conceptually, I can imagine each Element being an ICalculateRoundScore interface. However, that only makes sense if I create a different class for each different element, which doesn't seem right. It feels like I need some kind of a lookup in which the Round class picks its particular CalculateRoundScore method depending on the Element to which it belongs, but I'm not sure what would be the correct object-oriented way to do this.