Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/main/java/bowling/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package bowling;

import bowling.service.BowlingGame;

public class Application {

public static void main(String[] args) {
BowlingGame bowlingGame = new BowlingGame();
bowlingGame.start();
}
}
4 changes: 4 additions & 0 deletions src/main/java/bowling/domain/IllegalPinException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package bowling.domain;

public class IllegalPinException extends RuntimeException {
}
4 changes: 4 additions & 0 deletions src/main/java/bowling/domain/IllegalScoreException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package bowling.domain;

public class IllegalScoreException extends RuntimeException {
}
4 changes: 4 additions & 0 deletions src/main/java/bowling/domain/IllegalSymbolException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package bowling.domain;

public class IllegalSymbolException extends RuntimeException {
}
48 changes: 48 additions & 0 deletions src/main/java/bowling/domain/Pin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package bowling.domain;

public class Pin {

private static final int MAX = 10;
private static final int MIN = 0;

private int pin;

private Pin() {}

private Pin(int pin) {
if (MAX < pin || MIN > pin)
throw new IllegalPinException();

this.pin = pin;
}

public static Pin of(int pin) {
return new Pin(pin);
}

public Pin add(Pin pin) {
return new Pin(this.pin + pin.pin);
}

public int getPin() {
return this.pin;
}

public boolean isStrike() {
return MAX == this.pin;
}

public boolean isSpare(Pin pin) {
return MAX == this.pin + pin.pin;
}

public boolean isMiss(Pin pin) {
return MAX > this.pin + pin.pin;
}

public boolean isGutter() {
return MIN == this.pin;
}

private static class IllegalPinException extends RuntimeException {}
}
26 changes: 26 additions & 0 deletions src/main/java/bowling/domain/Player.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package bowling.domain;

import bowling.domain.service.BowlingService;

public class Player {

private String player;
private BowlingService bowlingService;

private Player(String player) {
this.player = player;
this.bowlingService = new BowlingService();
}

public static Player of(String player) {
return new Player(player);
}

public String getPlayer() {
return player;
}

public BowlingService getBowlingService() {
return bowlingService;
}
}
35 changes: 35 additions & 0 deletions src/main/java/bowling/domain/Score.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package bowling.domain;

public class Score {

private int score;
private int leftBonus;

private Score(int score, int leftBonus) {
this.score = score;
this.leftBonus = leftBonus;
}

public static Score of(int score, int left) {
return new Score(score, left);
}

public Score add(Score score) {
return Score.of(this.score + score.getScore(), this.leftBonus + score.getLeftBonus());
}

public Score addBonusScore(Pin pin) {
if (!isAddable()) return this;
return of(score + pin.getPin(), leftBonus - 1);
}

public boolean isAddable() {
return leftBonus != 0;
}

public int getScore() {
return score;
}

public int getLeftBonus() { return leftBonus; }
}
20 changes: 20 additions & 0 deletions src/main/java/bowling/domain/ScoreResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package bowling.domain;

import java.util.List;

public class ScoreResult {

private List<Score> scores;

private ScoreResult(List<Score> scores) {
this.scores = scores;
}

public static ScoreResult of(List<Score> scores) {
return new ScoreResult(scores);
}

public List<Score> getScores() {
return scores;
}
}
26 changes: 26 additions & 0 deletions src/main/java/bowling/domain/Symbol.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package bowling.domain;

public class Symbol {

private String symbol;

private Symbol(String symbol) {
this.symbol = symbol;
}

public static Symbol of(String symbol) {
return new Symbol(symbol);
}

public static Symbol of(int symbol) {
return Symbol.of(String.valueOf(symbol));
}

public Symbol add(Symbol symbol) {
return Symbol.of(this.symbol + symbol.getSymbol());
}

public String getSymbol() {
return symbol;
}
}
20 changes: 20 additions & 0 deletions src/main/java/bowling/domain/SymbolResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package bowling.domain;

import java.util.List;

public class SymbolResult {

private List<Symbol> symbols;

private SymbolResult(List<Symbol> symbols) {
this.symbols = symbols;
}

public static SymbolResult of(List<Symbol> symbols) {
return new SymbolResult(symbols);
}

public List<Symbol> getSymbols() {
return symbols;
}
}
76 changes: 76 additions & 0 deletions src/main/java/bowling/domain/frame/Final.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package bowling.domain.frame;

import bowling.domain.*;
import bowling.domain.state.State;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

class Final implements Frame {

private LinkedList<State> state;

Final() {
this.state = new LinkedList<>();
this.state.add(State.of());
}

@Override
public Frame bowl(Pin pin) {
if (!isFinished()) {
State nextState = state.getLast().bowl(pin);
state.removeLast();
state.addLast(nextState);
}

if (state.getFirst().getFalledTotalPin().isStrike())
state.addLast(State.of());

return this;
}

@Override
public boolean isFinished() {
if (!state.getFirst().isFinished())
return false;

if (!state.getFirst().getFalledTotalPin().isStrike())
return true;

return getTotalPins().size() >= 3;
}

@Override
public Score getScore() {
return state.stream()
.filter(State::anyBowled)
.map(State::getScore)
.reduce(Score::add).orElseThrow(IllegalScoreException::new);
}

@Override
public List<Pin> getPins() {
return state.stream()
.filter(State::anyBowled)
.flatMap(state -> state.getFalledPins().stream())
.collect(Collectors.toList());
}

@Override
public int getFrameNumber() {
return 10;
}

@Override
public Symbol getSymbol() {
return state.stream()
.filter(State::anyBowled)
.map(State::getSymbol)
.reduce((Symbol::add)).orElseThrow(IllegalSymbolException::new);
}

private List<Pin> getTotalPins() {
return state.stream().filter(State::anyBowled).flatMap(state -> state.getFalledPins().stream()).collect(Collectors.toList());
}
}
26 changes: 26 additions & 0 deletions src/main/java/bowling/domain/frame/Frame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package bowling.domain.frame;

import bowling.domain.Pin;
import bowling.domain.Score;
import bowling.domain.Symbol;

import java.util.List;

public interface Frame {

Frame bowl(Pin pin);

boolean isFinished();

Score getScore();

List<Pin> getPins();

int getFrameNumber();

Symbol getSymbol();

static Frame of() {
return new Normal(1);
}
}
4 changes: 4 additions & 0 deletions src/main/java/bowling/domain/frame/InvalidFrameException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package bowling.domain.frame;

class InvalidFrameException extends RuntimeException {
}
69 changes: 69 additions & 0 deletions src/main/java/bowling/domain/frame/Normal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package bowling.domain.frame;

import bowling.domain.Pin;
import bowling.domain.Score;
import bowling.domain.Symbol;
import bowling.domain.state.State;
import com.google.common.collect.Lists;

import java.util.List;

class Normal implements Frame {

private static final int MAX = 9;
private static final int MIN = 1;

private State state;
private int frameNumber;

Normal(int frameNumber) {
this.frameNumber = frameNumber;
this.state = State.of();

if (!isValid())
throw new InvalidFrameException();
}

@Override
public Frame bowl(Pin pin) {
state = state.bowl(pin);

if (!isFinished()) {
return this;
}

if (MAX == frameNumber)
return new Final();

return new Normal(frameNumber + 1);
}

private boolean isValid() {
return MIN <= frameNumber && frameNumber <= MAX;
}

@Override
public boolean isFinished() {
return state.isFinished();
}

@Override
public Score getScore() {
return state.getScore();
}

@Override
public List<Pin> getPins() {
return Lists.newArrayList(state.getFalledPins());
}

@Override
public int getFrameNumber() {
return frameNumber;
}

@Override
public Symbol getSymbol() {
return state.getSymbol();
}
}
Loading