|
@ -4,6 +4,11 @@ import java.util.regex.Matcher; |
|
|
import java.util.regex.Pattern; |
|
|
import java.util.regex.Pattern; |
|
|
|
|
|
|
|
|
public class BowlingCalculator { |
|
|
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 |
|
|
@FunctionalInterface |
|
|
interface FrameScorer { |
|
|
interface FrameScorer { |
|
|
int score(Matcher frameMatcher); |
|
|
int score(Matcher frameMatcher); |
|
@ -12,6 +17,7 @@ public class BowlingCalculator { |
|
|
private static final int INITIAL_SCORE = 0; |
|
|
private static final int INITIAL_SCORE = 0; |
|
|
private static final Pattern SINGLE_ROLL_PATTERN = Pattern.compile("\\d"); |
|
|
private static final Pattern SINGLE_ROLL_PATTERN = Pattern.compile("\\d"); |
|
|
private static final Pattern SPARE_PATTERN = Pattern.compile("(\\d)/ ([-\\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) { |
|
|
public int score(String rolls) { |
|
|
int score = INITIAL_SCORE; |
|
|
int score = INITIAL_SCORE; |
|
@ -21,18 +27,26 @@ public class BowlingCalculator { |
|
|
Matcher spareMatcher = SPARE_PATTERN.matcher(rolls); |
|
|
Matcher spareMatcher = SPARE_PATTERN.matcher(rolls); |
|
|
score = scoreFrameType(score, spareMatcher, matcher -> scoreSpareFrame(spareMatcher)); |
|
|
score = scoreFrameType(score, spareMatcher, matcher -> scoreSpareFrame(spareMatcher)); |
|
|
|
|
|
|
|
|
|
|
|
Matcher strikeMatcher = STRIKE_PATTERN.matcher(rolls); |
|
|
|
|
|
score = scoreFrameType(score, strikeMatcher, matcher -> scoreStrike(strikeMatcher)); |
|
|
|
|
|
|
|
|
return score; |
|
|
return score; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private int scoreSpareFrame(Matcher spareMatcher) { |
|
|
|
|
|
int frameScore = 10 - Integer.parseInt(spareMatcher.group(1)); |
|
|
|
|
|
String nextRoll = spareMatcher.group(2); |
|
|
|
|
|
if(!"-".equalsIgnoreCase(nextRoll)) { |
|
|
|
|
|
frameScore += Integer.parseInt(spareMatcher.group(1)); |
|
|
|
|
|
|
|
|
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; |
|
|
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) { |
|
|
private int scoreFrameType(int score, Matcher scoreMatcher, FrameScorer frameScorer) { |
|
|
while (scoreMatcher.find()) { |
|
|
while (scoreMatcher.find()) { |
|
|
score += frameScorer.score(scoreMatcher); |
|
|
score += frameScorer.score(scoreMatcher); |
|
@ -40,4 +54,11 @@ public class BowlingCalculator { |
|
|
return score; |
|
|
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; |
|
|
|
|
|
} |
|
|
} |
|
|
} |