From 9303276a3631795a0f3e173ccb899c3b8a855fe8 Mon Sep 17 00:00:00 2001
From: Colin DAMON <cdamon@ippon.fr>
Date: Mon, 22 Mar 2021 14:08:14 +0100
Subject: [PATCH] Bowling game resolution

---
 .gitlab-ci.yml                                |  1 +
 README.md                                     |  1 +
 bowling-game/.gitlab-ci.yml                   | 11 +++
 bowling-game/pom.xml                          | 29 ++++++++
 bowling-game/readme.md                        |  9 +++
 .../src/main/java/fr/craft/kata/Game.java     | 73 +++++++++++++++++++
 .../src/test/java/fr/craft/kata/GameTest.java | 57 +++++++++++++++
 7 files changed, 181 insertions(+)
 create mode 100644 bowling-game/.gitlab-ci.yml
 create mode 100644 bowling-game/pom.xml
 create mode 100644 bowling-game/readme.md
 create mode 100644 bowling-game/src/main/java/fr/craft/kata/Game.java
 create mode 100644 bowling-game/src/test/java/fr/craft/kata/GameTest.java

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fe4e9f35..cc25dcfd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -29,3 +29,4 @@ include:
   - local: "/leap-years/.gitlab-ci.yml"
   - local: "/employee-report/.gitlab-ci.yml"
   - local: "/java-concurrence/.gitlab-ci.yml"
+  - local: "/bowling-game/.gitlab-ci.yml"
diff --git a/README.md b/README.md
index 51ea161b..6bbf1136 100644
--- a/README.md
+++ b/README.md
@@ -58,3 +58,4 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
 | [Gilded rose without flow control](/gilded-rose-without-flow-control)                                                 | Kata        | Enervé     |
 | [Retour sur les 3 jours de conférences de DDD Europe](https://youtu.be/sDUuDpnLWXs)                                   | Discussion  |            |
 | [Concurrence en Java](/java-concurrence)                                                                              | Code&coffee | Enervé     |
+| [Bowling Game](/bowling-game)                                                                                         | Kata        | Moyen      |
diff --git a/bowling-game/.gitlab-ci.yml b/bowling-game/.gitlab-ci.yml
new file mode 100644
index 00000000..476500c0
--- /dev/null
+++ b/bowling-game/.gitlab-ci.yml
@@ -0,0 +1,11 @@
+package-bowling-game:
+  variables:
+    PROJECT_FOLDER: "bowling-game"
+  extends: .java
+  only:
+    refs:
+      - master
+      - merge_requests
+    changes:
+      - ".gitlab-common-ci.yml"
+      - "bowling-game/**/*"
diff --git a/bowling-game/pom.xml b/bowling-game/pom.xml
new file mode 100644
index 00000000..fed2ee18
--- /dev/null
+++ b/bowling-game/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <version>1.0.0</version>
+    <groupId>fr.ippon.kata</groupId>
+    <artifactId>java-parent</artifactId>
+    <relativePath>../java-parent</relativePath>
+  </parent>
+
+  <version>1.0.0-SNAPSHOT</version>
+  <artifactId>bowling-game</artifactId>
+
+  <name>BowlingGame</name>
+
+  <developers>
+    <developer>
+      <email>jlfernandes@ippon.fr</email>
+      <name>Jean-Luc FERNANDES</name>
+    </developer>
+    <developer>
+      <email>cdamon@ippon.fr</email>
+      <name>Colin DAMON</name>
+    </developer>
+  </developers>
+</project>
diff --git a/bowling-game/readme.md b/bowling-game/readme.md
new file mode 100644
index 00000000..01c8a31b
--- /dev/null
+++ b/bowling-game/readme.md
@@ -0,0 +1,9 @@
+# Bowling game
+
+Résolution en TDD et en Java du kata [BowlingGame](https://codingdojo.org/kata/Bowling/).
+
+-   **Auteurs** : Jean-Luc FERNANDES et Colin DAMON
+-   **Date** : 22/03/2021
+-   **Langage** : Java
+-   **Niveau** : Moyen
+-   **Replay** : TODO
diff --git a/bowling-game/src/main/java/fr/craft/kata/Game.java b/bowling-game/src/main/java/fr/craft/kata/Game.java
new file mode 100644
index 00000000..f0836a7b
--- /dev/null
+++ b/bowling-game/src/main/java/fr/craft/kata/Game.java
@@ -0,0 +1,73 @@
+package fr.craft.kata;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Game {
+  private final List<Integer> rolls = new ArrayList<>();
+
+  public void roll(int pinsDown) {
+    rolls.add(pinsDown);
+  }
+
+  public int score() {
+    int score = 0;
+    int frameIndex = 0;
+
+    for (int frame = 0; frame < 10; frame++) {
+      score += frameScore(frameIndex);
+
+      frameIndex = nextFrameIndex(frameIndex);
+    }
+
+    return score;
+  }
+
+  private int frameScore(int frameIndex) {
+    if (isStrike(frameIndex)) {
+      return strikeScore(frameIndex);
+    }
+
+    if (isSpare(frameIndex)) {
+      return spareScore(frameIndex);
+    }
+
+    return normalFrameScore(frameIndex);
+  }
+
+  private int nextFrameIndex(int frameIndex) {
+    if (isStrike(frameIndex)) {
+      return frameIndex + 1;
+    }
+
+    return frameIndex + 2;
+  }
+
+  private boolean isStrike(int frameIndex) {
+    return rolls.get(frameIndex) == 10;
+  }
+
+  private int strikeScore(int frameIndex) {
+    return 10 + strikeBonus(frameIndex);
+  }
+
+  private int strikeBonus(int frameIndex) {
+    return rolls.get(frameIndex + 1) + rolls.get(frameIndex + 2);
+  }
+
+  private boolean isSpare(int frameIndex) {
+    return normalFrameScore(frameIndex) == 10;
+  }
+
+  private int spareScore(int frameIndex) {
+    return 10 + spareBonus(frameIndex);
+  }
+
+  private Integer spareBonus(int frameIndex) {
+    return rolls.get(frameIndex + 2);
+  }
+
+  private int normalFrameScore(int frameIndex) {
+    return rolls.get(frameIndex) + rolls.get(frameIndex + 1);
+  }
+}
diff --git a/bowling-game/src/test/java/fr/craft/kata/GameTest.java b/bowling-game/src/test/java/fr/craft/kata/GameTest.java
new file mode 100644
index 00000000..fa38e4ff
--- /dev/null
+++ b/bowling-game/src/test/java/fr/craft/kata/GameTest.java
@@ -0,0 +1,57 @@
+package fr.craft.kata;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class GameTest {
+  private final Game game = new Game();
+
+  @Test
+  void shouldScoreGutterGame() {
+    rolls(20, 0);
+
+    assertThat(game.score()).isEqualTo(0);
+  }
+
+  @Test
+  void shouldScoreGameOfOnes() {
+    rolls(20, 1);
+
+    assertThat(game.score()).isEqualTo(20);
+  }
+
+  @Test
+  void shouldScoreSpare() {
+    game.roll(7);
+    game.roll(3);
+    game.roll(4);
+
+    rolls(17, 0);
+
+    assertThat(game.score()).isEqualTo((7 + 3) + 4 + 4);
+  }
+
+  @Test
+  void shouldScoreStrike() {
+    game.roll(10);
+    game.roll(3);
+    game.roll(4);
+    rolls(16, 0);
+
+    assertThat(game.score()).isEqualTo(10 + (3 + 4) + (3 + 4));
+  }
+
+  @Test
+  void shouldScorePerfectGame() {
+    rolls(12, 10);
+
+    assertThat(game.score()).isEqualTo(300);
+  }
+
+  private void rolls(int rolls, int pinsDown) {
+    for (int roll = 0; roll < rolls; roll++) {
+      game.roll(pinsDown);
+    }
+  }
+}
-- 
GitLab