You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
2.2 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package de.edu.hsfulda.ccip.tdd.purefunction;
  2. import java.util.regex.Matcher;
  3. import java.util.regex.Pattern;
  4. public class BowlingCalculator {
  5. private static final String FOUL = "-";
  6. private static final int SPLIT_NEXT_ROLL = 2;
  7. private static final int STRIKE_NEXT_ROLL = 1;
  8. private static final int MAX_PIN_COUNT = 10;
  9. @FunctionalInterface
  10. interface FrameScorer {
  11. int score(Matcher frameMatcher);
  12. }
  13. private static final int INITIAL_SCORE = 0;
  14. private static final Pattern SINGLE_ROLL_PATTERN = Pattern.compile("\\d");
  15. private static final Pattern SPARE_PATTERN = Pattern.compile("(\\d)/ ([-\\d])");
  16. private static final Pattern STRIKE_PATTERN = Pattern.compile("X ([-\\d])([-\\d])");
  17. public int score(String rolls) {
  18. int score = INITIAL_SCORE;
  19. Matcher singleRollMatcher = SINGLE_ROLL_PATTERN.matcher(rolls);
  20. score = scoreFrameType(score, singleRollMatcher, matcher -> Integer.parseInt(singleRollMatcher.group()));
  21. Matcher spareMatcher = SPARE_PATTERN.matcher(rolls);
  22. score = scoreFrameType(score, spareMatcher, matcher -> scoreSpareFrame(spareMatcher));
  23. Matcher strikeMatcher = STRIKE_PATTERN.matcher(rolls);
  24. score = scoreFrameType(score, strikeMatcher, matcher -> scoreStrike(strikeMatcher));
  25. return score;
  26. }
  27. private int scoreStrike(Matcher strikeMatcher) {
  28. int frameScore = MAX_PIN_COUNT;
  29. for (int nextRollIndex = STRIKE_NEXT_ROLL; nextRollIndex <= STRIKE_NEXT_ROLL + 1; nextRollIndex++) {
  30. frameScore = addNextRollToCurrentFrame(strikeMatcher, frameScore, nextRollIndex);
  31. }
  32. return frameScore;
  33. }
  34. private int scoreSpareFrame(Matcher spareMatcher) {
  35. int frameScore = MAX_PIN_COUNT - Integer.parseInt(spareMatcher.group(1));
  36. int nextRollIndex = SPLIT_NEXT_ROLL;
  37. return addNextRollToCurrentFrame(spareMatcher, frameScore, nextRollIndex);
  38. }
  39. private int scoreFrameType(int score, Matcher scoreMatcher, FrameScorer frameScorer) {
  40. while (scoreMatcher.find()) {
  41. score += frameScorer.score(scoreMatcher);
  42. }
  43. return score;
  44. }
  45. private int addNextRollToCurrentFrame(Matcher frameMatcher, int frameScore, int nextRollIndex) {
  46. String nextRoll = frameMatcher.group(nextRollIndex);
  47. if (!FOUL.equalsIgnoreCase(nextRoll)) {
  48. frameScore += Integer.parseInt(nextRoll);
  49. }
  50. return frameScore;
  51. }
  52. }