Commit 9fc19c5c authored by Colin DAMON's avatar Colin DAMON

Merge branch '63-puissance-4' into 'master'

Resolve "Puissance 4"

Closes #63

See merge request !47
parents 691c6692 a2cf6e42
......@@ -18,3 +18,4 @@ include:
- local: "/java-h2g2/.gitlab-ci.yml"
- local: "/factory-patterns/.gitlab-ci.yml"
- local: "/exceptions/.gitlab-ci.yml"
- local: "/puissance-4/.gitlab-ci.yml"
......@@ -41,3 +41,4 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
| [Back from GDCR avec Maxime, Séraphin, Anthony et Colin](https://www.youtube.com/watch?v=CHfUGdnSX6I) | Discussion | |
| [Factory patterns](/factory-patterns) | Code&coffee | Facile |
| [Exceptions](/exceptions) | Code&coffee | Facile |
| [Puissance 4](/puissance-4) | Kata | Moyenne |
......@@ -4,14 +4,14 @@ class GildedRose {
private static final String SULFURAS_NAME = "Sulfuras, Hand of Ragnaros";
private static final String BACKSTAGE_PASSES_NAME = "Backstage passes to a TAFKAL80ETC concert";
private static final String AGED_BRIE_NAME = "Aged Brie";
Item[] items;
private Item[] items;
public GildedRose(Item[] items) {
this.items = items;
this.setItems(items);
}
public void updateQuality() {
for (Item item : items) {
for (Item item : getItems()) {
if (SULFURAS_NAME.equals(item.name)) {
continue;
}
......@@ -71,4 +71,12 @@ class GildedRose {
item.quality = item.quality - 1;
}
}
public Item[] getItems() {
return items;
}
public void setItems(Item[] items) {
this.items = items;
}
}
package com.gildedrose;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.*;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
class GildedRoseTest {
@Test
void shouldUpdateForOneDay() {
GildedRose rose = new GildedRose(ItemsProvider.get());
rose.updateQuality();
assertThat(rose.items).extracting(item -> item.sellIn).containsExactly(9, 1, 4, 0, -1, 14, 9, 4);
assertThat(rose.items).extracting(item -> item.quality).containsExactly(19, 1, 6, 80, 80, 21, 50, 50);
}
@Test
void shouldUpdateForTwoDays() {
GildedRose rose = new GildedRose(ItemsProvider.get());
rose.updateQuality();
rose.updateQuality();
assertThat(rose.items).extracting(item -> item.sellIn).containsExactly(8, 0, 3, 0, -1, 13, 8, 3);
assertThat(rose.items).extracting(item -> item.quality).containsExactly(18, 2, 5, 80, 80, 22, 50, 50);
}
@Test
void shouldBehaveLikeGoldenMaster() {
GildedRose rose = new GildedRose(ItemsProvider.get());
......@@ -37,10 +16,10 @@ class GildedRoseTest {
rose.updateQuality();
golden.updateQuality();
assertThat(rose.items)
assertThat(rose.getItems())
.extracting(item -> item.sellIn)
.containsExactly(Arrays.stream(golden.items).map(item -> item.sellIn).toArray(Integer[]::new));
assertThat(rose.items)
assertThat(rose.getItems())
.extracting(item -> item.quality)
.containsExactly(Arrays.stream(golden.items).map(item -> item.quality).toArray(Integer[]::new));
}
......
package-puissance-4:
variables:
PROJECT_FOLDER: "puissance-4"
extends: .java
only:
refs:
- master
- merge_requests
changes:
- ".gitlab-common-ci.yml"
- "puissance-4/**/*"
# Puissance IV
Refactoring, en live, d'un code de puissance 4 fait en première année d'études
- **Auteurs** : Colin DAMON & Cyril DUPONT
- **Date** : 22/12/2020
- **Langage** : Java
- **Niveau** : Moyen
- **Replay** : TODO
<?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>puissance-4</artifactId>
<name>Puissance4</name>
<developers>
<developer>
<email>cdamon@ippon.fr</email>
<name>Colin DAMON</name>
</developer>
<developer>
<email>cdupont@ippon.fr</email>
<name>Cyril DUPONT</name>
</developer>
</developers>
<dependencies>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package fr.ippon.kata.puissance4;
public enum Joueur {
JOUEUR_1('X'),
JOUEUR_2('O');
private final char pion;
private Joueur(char pion) {
this.pion = pion;
}
public char getPion() {
return pion;
}
}
This diff is collapsed.
package fr.ippon.kata.puissance4;
import static org.assertj.core.api.Assertions.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class Puissance4Test {
private PrintStream systemOut;
private InputStream systemIn;
private ByteArrayOutputStream out;
private SystemInMock in = new SystemInMock();
private Thread runner;
@BeforeEach
void changeOutput() {
systemOut = System.out;
systemIn = System.in;
out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));
System.setIn(in);
}
@AfterEach
void resetOutput() {
System.setOut(systemOut);
System.setIn(systemIn);
}
@AfterEach
void stopGame() {
runner.interrupt();
}
@Test
void shouldDisplayMenu() {
play();
assertGameOrder("Puissance 4", "[3] Regle du jeu");
}
@Test
void shouldDisplayRules() throws InterruptedException {
play("3", "1");
assertGameOrder("[3] Regle du jeu", "Le but du jeu", "la partie est déclarée nulle", "[3] Regle du jeu");
}
@Test
void shouldPlayTwoPlayerGame() {
play("2", "Colin", "Cyril", "1", "2", "1", "2", "1", "2", "1");
assertGameOrder("Colin a gagné !");
}
@Test
void shouldAskMenuAgainForOutOfBoundOption() {
play("5", "0", "3");
assertGameOrder("[3] Regle du jeu");
}
@Test
void shouldAskColumnAgainForBadPlayerOneInput() {
play("2", "Colin", "Cyril", "0", "9", "1");
assertGameOrder(
"Choix incorrect, entrez un nombre entre 1 et 8",
"Choix incorrect, entrez un nombre entre 1 et 8",
"| X| *| *| *| *| *| *| *|"
);
}
@Test
void shouldAskColumnAgainForBadPlayerTwoInput() {
play("2", "Colin", "Cyril", "1", "9", "0", "2");
assertGameOrder(
"Choix incorrect, entrez un nombre entre 1 et 8",
"Choix incorrect, entrez un nombre entre 1 et 8",
"| X| O| *| *| *| *| *| *|"
);
}
@Test
void shouldPlayAgainsIA() {
play("1", "Colin", "4", "5", "6", "7", "8");
assertGameOrder(
"| *| *| *| X| *| *| *| *|",
"| *| *| *| X| O| *| *| *|",
"| *| *| *| *| X| *| *| *|",
"| *| *| *| O| X| *| *| *|",
"| *| *| *| X| O| X| *| *|",
"| *| *| *| O| *| *| *| *|",
"L'ordinateur a gagné !"
);
}
private void play(String... inputs) {
in.provideText(Arrays.stream(inputs).collect(Collectors.joining("\n")));
runner = startGame();
}
private Thread startGame() {
Thread runner = new Thread(
() -> {
try {
Puissance4.main(null);
} catch (NoSuchElementException e) {
// Nothing to do
}
}
);
runner.start();
return runner;
}
private void assertGameOrder(String... elements) {
Awaitility
.await()
.pollDelay(5, TimeUnit.MILLISECONDS)
.atMost(1000, TimeUnit.MILLISECONDS)
.untilAsserted(
() -> {
String message = new String(out.toByteArray()).intern();
for (String element : elements) {
assertThat(message).contains(element);
message = message.substring(message.indexOf(element) + element.length());
}
}
);
}
private static class SystemInMock extends InputStream {
private StringReader currentReader;
private IOException ioException;
private RuntimeException runtimeException;
void provideText(String text) {
currentReader = new StringReader(text);
}
@Override
public int read() throws IOException {
if (currentReader == null) {
return 0;
}
int character = currentReader.read();
if (character == -1) handleEmptyReader();
return character;
}
private void handleEmptyReader() throws IOException {
if (ioException != null) throw ioException; else if (runtimeException != null) throw runtimeException;
}
@Override
public int read(byte[] buffer, int offset, int len) throws IOException {
if (buffer == null) throw new NullPointerException(); else if (
offset < 0 || len < 0 || len > buffer.length - offset
) throw new IndexOutOfBoundsException(); else if (len == 0) return 0; else return readNextLine(buffer, offset, len);
}
private int readNextLine(byte[] buffer, int offset, int len) throws IOException {
int c = read();
if (c == -1) return -1;
buffer[offset] = (byte) c;
int i = 1;
for (; (i < len) && !isCompleteLineWritten(buffer, i - 1); ++i) {
byte read = (byte) read();
if (read == -1) break; else buffer[offset + i] = read;
}
return i;
}
private boolean isCompleteLineWritten(byte[] buffer, int indexLastByteWritten) {
byte[] separator = System.lineSeparator().getBytes();
int indexFirstByteOfSeparator = indexLastByteWritten - separator.length + 1;
return indexFirstByteOfSeparator >= 0 && contains(buffer, separator, indexFirstByteOfSeparator);
}
private boolean contains(byte[] array, byte[] pattern, int indexStart) {
for (int i = 0; i < pattern.length; ++i) if (array[indexStart + i] != pattern[i]) return false;
return true;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment