From f5ed700dda29b5d1b58a9226a416e1a23a2629cc Mon Sep 17 00:00:00 2001 From: Tobias Heine Date: Wed, 10 Jan 2018 16:23:07 +0100 Subject: [PATCH 1/5] Add rx java as dependency to implement the JVM GameLoop --- game-of-life-multiplatform/game-of-life-jvm/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/game-of-life-multiplatform/game-of-life-jvm/build.gradle b/game-of-life-multiplatform/game-of-life-jvm/build.gradle index e5a92a99e..a8823d60d 100644 --- a/game-of-life-multiplatform/game-of-life-jvm/build.gradle +++ b/game-of-life-multiplatform/game-of-life-jvm/build.gradle @@ -2,6 +2,7 @@ apply plugin: 'kotlin-platform-jvm' dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.1.1' expectedBy project(":common") testCompile "junit:junit:4.12" testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" From 9c9a7e0ef87b8ee0c845ac315c99b815374db466 Mon Sep 17 00:00:00 2001 From: Tobias Heine Date: Wed, 10 Jan 2018 16:29:24 +0100 Subject: [PATCH 2/5] Implement JVM GameLoop based on Flowable.interval --- .../main/kotlin/com/novoda/gol/GameLoop.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/GameLoop.kt diff --git a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/GameLoop.kt b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/GameLoop.kt new file mode 100644 index 000000000..54536f42a --- /dev/null +++ b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/GameLoop.kt @@ -0,0 +1,27 @@ +package com.novoda.gol + +import io.reactivex.Flowable +import io.reactivex.disposables.Disposable +import java.util.concurrent.TimeUnit + +actual class GameLoop actual constructor() { + + private var gameLoop: Disposable? = null + + actual var onTick: () -> Unit = {} + + actual fun startWith(intervalMs: Int) { + gameLoop = Flowable.interval(intervalMs.toLong(), TimeUnit.MILLISECONDS).subscribe { + onTick() + } + } + + actual fun stop() { + gameLoop?.dispose() + gameLoop = null + + } + + actual fun isLooping() = gameLoop != null + +} From 616374e9ed7eb6cfc59f98c19a164960f7ab99a7 Mon Sep 17 00:00:00 2001 From: Tobias Heine Date: Wed, 10 Jan 2018 17:17:41 +0100 Subject: [PATCH 3/5] Reuse width and height from the previous board --- .../kotlin/com/novoda/gol/data/SimulationBoardEntity.kt | 2 +- .../com/novoda/gol/presentation/AppTerminalView.kt | 9 +++++++++ .../com/novoda/gol/presentation/BoardTerminalView.kt | 9 +++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt create mode 100644 game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt diff --git a/game-of-life-multiplatform/common/src/main/kotlin/com/novoda/gol/data/SimulationBoardEntity.kt b/game-of-life-multiplatform/common/src/main/kotlin/com/novoda/gol/data/SimulationBoardEntity.kt index 3929d9914..f1b72ad7f 100644 --- a/game-of-life-multiplatform/common/src/main/kotlin/com/novoda/gol/data/SimulationBoardEntity.kt +++ b/game-of-life-multiplatform/common/src/main/kotlin/com/novoda/gol/data/SimulationBoardEntity.kt @@ -8,7 +8,7 @@ data class SimulationBoardEntity(private val cellMatrix: CellMatrix) : BoardEnti val seeds = this.cellMatrix.getSeeds().toMutableList() seeds.addAll(patternEntity.getSeeds()) - val cellMatrix = ListBasedMatrix(width = 50, height = 50, seeds = seeds) + val cellMatrix = ListBasedMatrix(width = cellMatrix.getWidth(), height = cellMatrix.getHeight(), seeds = seeds) return SimulationBoardEntity(cellMatrix) } diff --git a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt new file mode 100644 index 000000000..7af5657ea --- /dev/null +++ b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt @@ -0,0 +1,9 @@ +package com.novoda.gol.presentation + +/** + * User: tobiasheine + * Date: 10.01.18 + * Time: 16:31 + */ +class AppTerminalView { +} diff --git a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt new file mode 100644 index 000000000..dd31abe3a --- /dev/null +++ b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt @@ -0,0 +1,9 @@ +package com.novoda.gol.presentation + +/** + * User: tobiasheine + * Date: 10.01.18 + * Time: 16:42 + */ +class BoardTerminalView { +} From ea46164b83b963f37606670436248851817f7f85 Mon Sep 17 00:00:00 2001 From: Tobias Heine Date: Wed, 10 Jan 2018 17:18:56 +0100 Subject: [PATCH 4/5] Implement first iteration of Terminal AppView and BoardView --- .../gol/presentation/AppTerminalView.kt | 52 ++++++++++++++++--- .../gol/presentation/BoardTerminalView.kt | 41 ++++++++++++--- .../kotlin/com/novoda/gol/terminal/Main.kt | 50 ++---------------- 3 files changed, 84 insertions(+), 59 deletions(-) diff --git a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt index 7af5657ea..9ef14d8ef 100644 --- a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt +++ b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt @@ -1,9 +1,49 @@ package com.novoda.gol.presentation -/** - * User: tobiasheine - * Date: 10.01.18 - * Time: 16:31 - */ -class AppTerminalView { +import com.novoda.gol.patterns.Glider +import com.novoda.gol.patterns.PatternEntity +import io.reactivex.Observable +import io.reactivex.schedulers.Schedulers +import java.io.BufferedReader +import java.io.InputStreamReader + +class AppTerminalView : AppView { + + override var onControlButtonClicked: () -> Unit = {} + + override var onPatternSelected: (pattern: PatternEntity) -> Unit = {} + + private val presenter = AppPresenter() + + fun onCreate() { + presenter.bind(this) + + Observable + .fromCallable { + readString() + } + .filter { it == "yes" } + .subscribeOn(Schedulers.io()) + .subscribe { + onPatternSelected(Glider.create()) + onControlButtonClicked() + } + } + + override fun renderControlButtonLabel(controlButtonLabel: String) { + print("$controlButtonLabel\n") + } + + private fun readString(): String { + val bufferedReader = BufferedReader(InputStreamReader(System.`in`)) + return bufferedReader.readLine().toString() + } + + override fun renderPatternSelectionVisibility(visibility: Boolean) { + //TODO: pattern selection ignored in first iteration + } + + override fun renderBoard(boardViewState: BoardViewState) { + BoardTerminalView().onCreate(boardViewState) + } } diff --git a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt index dd31abe3a..952e1b6f3 100644 --- a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt +++ b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/BoardTerminalView.kt @@ -1,9 +1,38 @@ package com.novoda.gol.presentation -/** - * User: tobiasheine - * Date: 10.01.18 - * Time: 16:42 - */ -class BoardTerminalView { +import com.novoda.gol.data.BoardEntity +import com.novoda.gol.data.PositionEntity +import com.novoda.gol.patterns.PatternEntity + +class BoardTerminalView : BoardView { + + override var onPatternSelected: (pattern: PatternEntity) -> Unit = {} + override var onCellClicked: (position: PositionEntity) -> Unit = {} + override var onStartSimulationClicked: () -> Unit = {} + override var onStopSimulationClicked: () -> Unit = {} + + private var presenter = BoardPresenter(width = 20, height = 20) + + fun onCreate(boardViewState: BoardViewState) { + presenter.bind(this) + if (boardViewState.selectedPattern != null) { + onPatternSelected(boardViewState.selectedPattern!!) + onStartSimulationClicked() + } + } + + override fun renderBoard(boardEntity: BoardEntity) { + for (y in 0 until boardEntity.getHeight()) { + for (x in 0 until boardEntity.getWidth()) { + val cellAtPosition = boardEntity.cellAtPosition(x, y) + if (cellAtPosition.isAlive) { + print("X") + } else { + print(" ") + } + + } + print("\n") + } + } } diff --git a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/terminal/Main.kt b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/terminal/Main.kt index 85374737d..cd43ca538 100644 --- a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/terminal/Main.kt +++ b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/terminal/Main.kt @@ -1,58 +1,14 @@ package com.novoda.gol.terminal -import com.novoda.gol.data.BoardEntity -import com.novoda.gol.data.ListBasedMatrix -import com.novoda.gol.data.PositionEntity -import com.novoda.gol.data.SimulationBoardEntity -import java.io.BufferedReader -import java.io.InputStreamReader - -const val EXIT = "exit" +import com.novoda.gol.presentation.AppTerminalView fun main(args: Array) { + AppTerminalView().onCreate() - var keepLooping = true - val br = BufferedReader(InputStreamReader(System.`in`)) - - print("enter width: ") - val width = br.readLine().toInt() - - print("enter height: ") - val height = br.readLine().toInt() - - val cellMatrix = ListBasedMatrix(width = width, height = height, seeds = listOf(PositionEntity(2, 1), PositionEntity(2, 2), PositionEntity(2, 3))) - - var boardEntity: BoardEntity = SimulationBoardEntity(cellMatrix) - + while (true){ - while (keepLooping) { - val input = br.readLine() - keepLooping = input != EXIT - - render(boardEntity) - - if (keepLooping) { - boardEntity = boardEntity.nextIteration() - } } } -fun render(boardEntity: BoardEntity) { - for (y in 0 until boardEntity.getHeight()) { - for (x in 0 until boardEntity.getWidth()) { - val cellAtPosition = boardEntity.cellAtPosition(x, y) - if (cellAtPosition.isAlive) { - print("X") - } else { - print(" ") - } - - } - print("\n") - } - - print("exit: Stop Simulation\n") - print("next: Next Iteration\n") -} From c69c51b55b4bb0b9640546b90bbf15aee2cc80c3 Mon Sep 17 00:00:00 2001 From: Tobias Heine Date: Wed, 10 Jan 2018 17:31:23 +0100 Subject: [PATCH 5/5] Fix typo in comment --- .../main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt index 9ef14d8ef..68f7feae5 100644 --- a/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt +++ b/game-of-life-multiplatform/game-of-life-jvm/src/main/kotlin/com/novoda/gol/presentation/AppTerminalView.kt @@ -40,7 +40,7 @@ class AppTerminalView : AppView { } override fun renderPatternSelectionVisibility(visibility: Boolean) { - //TODO: pattern selection ignored in first iteration + //TODO: pattern selection is ignored in first iteration } override fun renderBoard(boardViewState: BoardViewState) {