Skip to content

Instantly share code, notes, and snippets.

@saantiaguilera
Created November 5, 2019 03:41
Show Gist options
  • Save saantiaguilera/bd0241a9a4cfd97842f4682abbaa61ac to your computer and use it in GitHub Desktop.
Save saantiaguilera/bd0241a9a4cfd97842f4682abbaa61ac to your computer and use it in GitHub Desktop.
Tennis BrownBag
package com.mercadolibre.dojo
import org.junit.Assert
import org.junit.Before
import org.junit.Test
class IntegrationTests {
lateinit var player1: Player
lateinit var player2: Player
@Before
fun setup() {
val (player1, player2) = createPlayers("fulana", "fulano")
this.player1 = player1
this.player2 = player2
}
fun provideGamePoint(name: String) = Game(name)
fun provideFourtyPoint(game: Game) = Fourty(game)
fun provideAdvantagePoint(name: String, game: Game) = Advantage(name, game)
fun provideDeucePoint(advantage: Advantage, oponentAdvantage: Advantage) = Deuce(advantage, oponentAdvantage)
fun provideThirtyPoint(fourty: Fourty, deuceProvider: DeuceProvider) = Thirty(fourty, deuceProvider)
fun provideFifteenPoint(thirty: Thirty) = Fifteen(thirty)
fun provideZero(fifteen: Fifteen) = Zero(fifteen)
private fun createPlayers(name1: String, name2: String): Pair<Player, Player> {
val scoreGame1 = provideGamePoint(name1)
val scoreFourty1 = provideFourtyPoint(scoreGame1)
val scoreAdvantage1 = provideAdvantagePoint(name1, scoreGame1)
val scoreGame2 = provideGamePoint(name2)
val scoreFourty2 = provideFourtyPoint(scoreGame2)
val scoreAdvantage2 = provideAdvantagePoint(name2, scoreGame2)
val scoreDeuce1 = provideDeucePoint(scoreAdvantage1, scoreAdvantage2)
val scoreDeuce2 = provideDeucePoint(scoreAdvantage2, scoreAdvantage1)
val scoreThirty1 = provideThirtyPoint(scoreFourty1) {
Pair(scoreDeuce1, scoreDeuce2)
}
val scoreThirty2 = provideThirtyPoint(scoreFourty2) {
Pair(scoreDeuce2, scoreDeuce1)
}
val scoreFifteen1 = provideFifteenPoint(scoreThirty1)
val scoreFifteen2 = provideFifteenPoint(scoreThirty2)
val scoreZero1 = provideZero(scoreFifteen1)
val scoreZero2 = provideZero(scoreFifteen2)
return Pair(Player(scoreZero1), Player(scoreZero2))
}
fun getMessageWhen(player1: Player,
player2: Player,
numberOfScoresPlayer1: Int,
numberOfScoresPlayer2: Int): String {
repeat(numberOfScoresPlayer1) {
player1 scoreAgainst player2
}
repeat(numberOfScoresPlayer2) {
player2 scoreAgainst player1
}
return Logger(player1, player2).getCurrentScore()
}
@Test
fun `test game start`() {
Assert.assertEquals("Game Start", getMessageWhen(player1, player2, 0, 0))
}
@Test
fun `test game 0 - 15`() {
Assert.assertEquals("0 - 15", getMessageWhen(player1, player2, 0, 1))
}
@Test
fun `test game 15 - 0`() {
Assert.assertEquals("15 - 0", getMessageWhen(player1, player2, 1, 0))
}
@Test
fun `test game 30 - 0`() {
Assert.assertEquals("30 - 0", getMessageWhen(player1, player2, 2, 0))
}
@Test
fun `test game 0 - 30`() {
Assert.assertEquals("0 - 30", getMessageWhen(player1, player2, 0, 2))
}
@Test
fun `test game 40 - 0`() {
Assert.assertEquals("40 - 0", getMessageWhen(player1, player2, 3, 0))
}
@Test
fun `test game 0 - 40`() {
Assert.assertEquals("0 - 40", getMessageWhen(player1, player2, 0, 3))
}
@Test
fun `test game wins player 1`() {
Assert.assertEquals("Game fulano", getMessageWhen(player1, player2, 0, 4))
}
@Test
fun `test game wins player 2`() {
Assert.assertEquals("Game fulana", getMessageWhen(player1, player2, 4, 0))
}
@Test
fun `test game 15 - 30`() {
Assert.assertEquals("15 - 30", getMessageWhen(player1, player2, 1, 2))
}
@Test
fun `test game 30 - 15`() {
Assert.assertEquals("30 - 15", getMessageWhen(player1, player2, 2, 1))
}
@Test
fun `test game 40 - 15`() {
Assert.assertEquals("40 - 15", getMessageWhen(player1, player2, 3, 1))
}
@Test
fun `test game 15 - 40`() {
Assert.assertEquals("15 - 40", getMessageWhen(player1, player2, 1, 3))
}
@Test
fun `test game 40 - 30`() {
Assert.assertEquals("40 - 30", getMessageWhen(player1, player2, 3, 2))
}
@Test
fun `test game 30 - 40`() {
Assert.assertEquals("30 - 40", getMessageWhen(player1, player2, 2, 3))
}
@Test
fun `test game 40 - 40 deuce`() {
Assert.assertEquals("Deuce", getMessageWhen(player1, player2, 3, 3))
}
@Test
fun `test game advantage player 1`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player1 scoreAgainst player2
Assert.assertEquals("Advantage fulano", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game advantage player 2`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
Assert.assertEquals("Advantage fulana", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game wins player 1 after advantage`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player1 scoreAgainst player2
player1 scoreAgainst player2
Assert.assertEquals("Game fulano", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game wins player 2 after advantage`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
Assert.assertEquals("Game fulana", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game deuce after advantage`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player1 scoreAgainst player2
Assert.assertEquals("Deuce", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game advantage player 1 after deuce`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player1 scoreAgainst player2
player1 scoreAgainst player2
Assert.assertEquals("Advantage fulano", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game advantage player 2 after deuce`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player1 scoreAgainst player2
player2 scoreAgainst player1
Assert.assertEquals("Advantage fulana", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game wins player 1 after advantage and deuce`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
Assert.assertEquals("Game fulano", Logger(player1, player2).getCurrentScore())
}
@Test
fun `test game wins player 2 after advantage and deuce`() {
val (player1, player2) = createPlayers("fulano", "fulana")
player1 scoreAgainst player2
player1 scoreAgainst player2
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player2 scoreAgainst player1
player1 scoreAgainst player2
player2 scoreAgainst player1
player2 scoreAgainst player1
Assert.assertEquals("Game fulana", Logger(player1, player2).getCurrentScore())
}
}
package com.mercadolibre.dojo
interface Scorer<S : Scorer<S>> {
var score: Score
infix fun scoreAgainst(scorer: S)
}
class Player(initialScore: Score) : Scorer<Player> {
override var score: Score = initialScore
override infix fun scoreAgainst(scorer: Player) {
val (score1, score2) = score.nextPoint(scorer.score)
score = score1
scorer.score = score2
}
}
class Logger<S: Scorer<S>>(private val scorer1: S,
private val scorer2: S) {
fun getCurrentScore(): String {
return scorer1.score.asMessage(scorer2.score)
}
}
package com.mercadolibre.dojo
interface Score {
fun nextPoint(otherPoint: Score): Pair<Score, Score>
fun asMessage(otherPoint: Score): String {
return "${toString()} - $otherPoint"
}
}
typealias DeuceProvider = () -> Pair<Deuce, Deuce>
data class Zero(val nextPoint: Score) : Score {
override fun nextPoint(otherPoint: Score) = Pair(nextPoint, otherPoint)
override fun toString() = "0"
override fun asMessage(otherPoint: Score): String {
if (otherPoint is Zero) {
return "Game Start"
}
return super.asMessage(otherPoint)
}
}
data class Fifteen(val nextPoint: Score) : Score {
override fun nextPoint(otherPoint: Score) = Pair(nextPoint, otherPoint)
override fun toString() = "15"
}
data class Thirty(val fourtyPoint: Score,
val deuceProvider: DeuceProvider) : Score {
override fun nextPoint(otherPoint: Score): Pair<Score, Score> {
if (otherPoint::class == fourtyPoint::class) {
return deuceProvider()
}
return Pair(fourtyPoint, otherPoint)
}
override fun toString() = "30"
}
data class Fourty(val gamePoint: Score) : Score {
override fun toString() = "40"
override fun nextPoint(otherPoint: Score): Pair<Score, Score> {
return Pair(gamePoint, gamePoint)
}
}
data class Advantage(val name: String,
val gamePoint: Score) : Score {
override fun asMessage(otherPoint: Score) = "Advantage $name"
override fun nextPoint(otherPoint: Score): Pair<Score, Score> {
return Pair(gamePoint, gamePoint)
}
}
data class Deuce(val advantagePoint: Score,
val oponentAdvantagePoint: Score) : Score {
override fun asMessage(otherPoint: Score): String {
if (otherPoint is Deuce) {
return "Deuce"
}
return otherPoint.asMessage(this) // Probably he's an advantage. Double-dispatch us
}
override fun nextPoint(otherPoint: Score): Pair<Score, Score> {
if (otherPoint::class == advantagePoint::class) {
// Create a deuce for the oponent with inverted values for advantages!
return Pair(this, Deuce(oponentAdvantagePoint, advantagePoint))
}
return Pair(advantagePoint, otherPoint)
}
}
data class Game(val winner: String) : Score {
override fun asMessage(otherPoint: Score) = "Game $winner"
override fun nextPoint(otherPoint: Score): Pair<Score, Score> {
throw IllegalStateException("Game has already ended.")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment