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
64 lines
2.2 KiB
package de.edu.hsfulda.ccip.tdd.purefunction;
|
|
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
public class BowlingCalculator {
|
|
private static final String FOUL = "-";
|
|
private static final int SPLIT_NEXT_ROLL = 2;
|
|
private static final int STRIKE_NEXT_ROLL = 1;
|
|
private static final int MAX_PIN_COUNT = 10;
|
|
|
|
@FunctionalInterface
|
|
interface FrameScorer {
|
|
int score(Matcher frameMatcher);
|
|
}
|
|
|
|
private static final int INITIAL_SCORE = 0;
|
|
private static final Pattern SINGLE_ROLL_PATTERN = Pattern.compile("\\d");
|
|
private static final Pattern SPARE_PATTERN = Pattern.compile("(\\d)/ ([-\\d])");
|
|
private static final Pattern STRIKE_PATTERN = Pattern.compile("X ([-\\d])([-\\d])");
|
|
|
|
public int score(String rolls) {
|
|
int score = INITIAL_SCORE;
|
|
Matcher singleRollMatcher = SINGLE_ROLL_PATTERN.matcher(rolls);
|
|
score = scoreFrameType(score, singleRollMatcher, matcher -> Integer.parseInt(singleRollMatcher.group()));
|
|
|
|
Matcher spareMatcher = SPARE_PATTERN.matcher(rolls);
|
|
score = scoreFrameType(score, spareMatcher, matcher -> scoreSpareFrame(spareMatcher));
|
|
|
|
Matcher strikeMatcher = STRIKE_PATTERN.matcher(rolls);
|
|
score = scoreFrameType(score, strikeMatcher, matcher -> scoreStrike(strikeMatcher));
|
|
|
|
return score;
|
|
}
|
|
|
|
private int scoreStrike(Matcher strikeMatcher) {
|
|
int frameScore = MAX_PIN_COUNT;
|
|
for (int nextRollIndex = STRIKE_NEXT_ROLL; nextRollIndex <= STRIKE_NEXT_ROLL + 1; nextRollIndex++) {
|
|
frameScore = addNextRollToCurrentFrame(strikeMatcher, frameScore, nextRollIndex);
|
|
}
|
|
return frameScore;
|
|
}
|
|
|
|
private int scoreSpareFrame(Matcher spareMatcher) {
|
|
int frameScore = MAX_PIN_COUNT - Integer.parseInt(spareMatcher.group(1));
|
|
int nextRollIndex = SPLIT_NEXT_ROLL;
|
|
return addNextRollToCurrentFrame(spareMatcher, frameScore, nextRollIndex);
|
|
}
|
|
|
|
private int scoreFrameType(int score, Matcher scoreMatcher, FrameScorer frameScorer) {
|
|
while (scoreMatcher.find()) {
|
|
score += frameScorer.score(scoreMatcher);
|
|
}
|
|
return score;
|
|
}
|
|
|
|
private int addNextRollToCurrentFrame(Matcher frameMatcher, int frameScore, int nextRollIndex) {
|
|
String nextRoll = frameMatcher.group(nextRollIndex);
|
|
if (!FOUL.equalsIgnoreCase(nextRoll)) {
|
|
frameScore += Integer.parseInt(nextRoll);
|
|
}
|
|
return frameScore;
|
|
}
|
|
}
|