package de.edu.hsfulda.ciip.tdd; import java.util.regex.Matcher; import java.util.regex.Pattern; public class BownlingCalculator { private static final int SINGLE_DIGIT = 0; private static final int STRIKE_SECOND_NEXT_THROW = 2; private static final int STRIKE_NEXT_THROW = 1; private static final String STRIKE = "X (\\d)(\\d)"; private static final int PINS_IN_FRAME = 10; private static final String SPARE = "(\\d)/ (\\d)"; private static final String INCOMPLETE_FRAME = "\\d"; @FunctionalInterface private interface FrameCalculator { int evaluate(Matcher frameStructure); } private static final int SPARE_FRAME_FOLLOWING_THROW = 2; private static final int SPARE_FRAME_FIRST_THROW = 1; public int evaluate(String listOfThrows) { int sum = 0; sum += evaluateFrames(listOfThrows, INCOMPLETE_FRAME, singleDigit -> convertMatchToInt(singleDigit, SINGLE_DIGIT)); sum += evaluateFrames(listOfThrows, SPARE, // trailing line comments for formatting spare -> PINS_IN_FRAME // - convertMatchToInt(spare, SPARE_FRAME_FIRST_THROW) + convertMatchToInt(spare, SPARE_FRAME_FOLLOWING_THROW)); sum += evaluateFrames(listOfThrows, STRIKE, // strike -> PINS_IN_FRAME // + convertMatchToInt(strike, STRIKE_NEXT_THROW) // + convertMatchToInt(strike, STRIKE_SECOND_NEXT_THROW)); return sum; } private int convertMatchToInt(Matcher strike, int groupIndex) { return Integer.parseInt(strike.group(groupIndex)); } private int evaluateFrames(String listOfThrows, String frameStructurePattern, FrameCalculator frameCalculator) { Matcher singleDigit = Pattern.compile(frameStructurePattern).matcher(listOfThrows); int frameValue = 0; while (singleDigit.find()) { frameValue += frameCalculator.evaluate(singleDigit); } return frameValue; } }