Added game state to all components, renamed timeout to timeoutMilliseconds, removed score from savegame.

This commit is contained in:
2020-12-21 15:48:20 +01:00
parent 639fcf8c6e
commit c4b914ccfd
11 changed files with 128 additions and 91 deletions

View File

@@ -1,18 +1,19 @@
<template> <template>
<main> <main>
<Level :level="level" /> <Level :level="level" />
<Timer :time="time" /> <Timer />
<Buffer :slots="slots" :codes="codes" /> <Buffer />
<Matrix :size="size" :matrix="matrix" /> <Matrix />
</main> </main>
</template> </template>
<script lang="ts"> <script lang="ts">
import {defineComponent} from "vue"; import {defineComponent, provide, ref, readonly} from "vue";
import Level from "./components/Level.vue"; import Level from "./components/Level.vue";
import Timer from "./components/Timer.vue"; import Timer from "./components/Timer.vue";
import Buffer from "./components/Buffer.vue"; import Buffer from "./components/Buffer.vue";
import Matrix from "./components/Matrix.vue"; import Matrix from "./components/Matrix.vue";
import { Game } from "./game/Game";
export default defineComponent({ export default defineComponent({
components: { components: {
@@ -22,31 +23,36 @@
Matrix Matrix
}, },
setup() { setup() {
const time = new Date(); const game = new Game({
time.setSeconds(time.getSeconds()+60); matrix: [
"AA", "BB", "CC",
"DD", "AA", "BB",
"CC", "DD", "AA",
],
sequences: [
["AA", "CC", "DD"],
],
maxBufferLength: 3,
timeoutMilliseconds: 60_000,
});
const level = ref(1);
const remainingMilliseconds = ref(game.remainingMilliseconds);
const timeoutMilliseconds = ref(game.timeoutMilliseconds);
const maxBufferLength = ref(game.maxBufferLength);
const buffer = ref(game.buffer);
const sequences = ref(game.sequences);
const size = ref(game.size);
const matrix = ref(game.matrix);
provide("remainingMilliseconds", readonly(remainingMilliseconds));
provide("timeoutMilliseconds", readonly(timeoutMilliseconds));
provide("maxBufferLength", readonly(maxBufferLength));
provide("buffer", readonly(buffer));
provide("sequences", readonly(sequences));
provide("size", readonly(size));
provide("matrix", readonly(matrix));
return { return {
level: 5, level
time,
slots: ["99", "E7", "AD", ""],
codes: [
{
code: ["", "E7", "AD", "BD"],
points: 100
},
{
code: ["99", "E7", "AD"],
points: 50
}
],
size: 5,
matrix: [
"99", "E7", "AD", "99", "BD",
"99", "BD", "99", "E7", "AD",
"AD", "E7", "BD", "AD", "99",
"99", "99", "BD", "E7", "AD",
"E7", "AD", "99", "BD", "99"
]
} }
} }
}); });

View File

@@ -2,31 +2,30 @@
<div class="buffer"> <div class="buffer">
<h2>Buffer</h2> <h2>Buffer</h2>
<div class="buffer-slots"> <div class="buffer-slots">
<div class="buffer-slots-slot buffer-slots-border" v-for="(slot, i) in slots" :key="i"> <div class="buffer-slots-slot buffer-slots-border" v-for="(slot, i) in maxBufferLength" :key="i">
{{slot}} <span v-if="buffer.length > i">{{buffer[i]}}</span>
</div>
</div>
<h2>Sequences</h2>
<div class="buffer-codes" v-for="(code, i) in codes" :key="i">
<div class="buffer-slots">
<div class="buffer-slots-slot" v-for="(digit, j) in code.code" :key="j">
{{digit}}
</div>
</div>
<div class="buffer-points">
{{code.points}} Pts
</div> </div>
</div> </div>
<Sequences />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import {defineComponent} from "vue"; import {defineComponent, inject} from "vue";
import Sequences from "./Sequences.vue";
export default defineComponent({ export default defineComponent({
props: { components: {
slots: {type: Array, required: true}, Sequences
codes: {type: Array, required: true} },
setup() {
const maxBufferLength = inject("maxBufferLength");
const buffer = inject("buffer");
return {
maxBufferLength,
buffer
}
} }
}); });
</script> </script>

View File

@@ -3,19 +3,24 @@
<h2>Code-Matrix</h2> <h2>Code-Matrix</h2>
<div class="matrix-row" v-for="i in size" :key="i"> <div class="matrix-row" v-for="i in size" :key="i">
<div class="matrix-column" v-for="j in size" :key="j"> <div class="matrix-column" v-for="j in size" :key="j">
{{matrix[(i - 1)*5 + (j - 1)]}} {{matrix[(i - 1)*size + (j - 1)]}}
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import {defineComponent} from "vue"; import {defineComponent, inject} from "vue";
export default defineComponent({ export default defineComponent({
props: { setup() {
size: {type: Number, required: true}, const size = inject("size");
matrix: {type: Array, required: true}, const matrix = inject("matrix");
return {
size,
matrix
}
} }
}); });
</script> </script>

View File

@@ -0,0 +1,24 @@
<template>
<h2>Sequences</h2>
<div class="buffer-codes" v-for="(sequence, i) in sequences" :key="i">
<div class="buffer-slots">
<div class="buffer-slots-slot" v-for="(digit, j) in sequence" :key="j">
{{digit}}
</div>
</div>
</div>
</template>
<script lang="ts">
import {defineComponent, inject} from "vue";
export default defineComponent({
setup() {
const sequences = inject("sequences");
return {
sequences
}
}
});
</script>

View File

@@ -6,18 +6,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import {defineComponent, ref, computed} from "vue"; import {defineComponent, computed, inject, Ref} from "vue";
export default defineComponent({ export default defineComponent({
props: { setup() {
time: {type: Object, required: true} const remainingTime = inject("remainingMilliseconds") as Ref<number>;
}, const timeoutMilliseconds = inject("timeoutMilliseconds") as Ref<number>;
setup(props) { const progress = computed(() => remainingTime.value/timeoutMilliseconds.value*100);
const remainingTime = ref(60) const countdown = computed(() => (remainingTime.value/1000).toFixed(2));
const progress = computed(() => remainingTime.value/60*100);
const countdown = computed(() => remainingTime.value.toFixed(2));
const updateTime = () => { /*const updateTime = () => {
remainingTime.value = Math.max(0, (props.time.getTime() - new Date().getTime()) / 1000); remainingTime.value = Math.max(0, (props.time.getTime() - new Date().getTime()) / 1000);
if (remainingTime.value > 0) { if (remainingTime.value > 0) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
@@ -28,7 +26,7 @@
requestAnimationFrame(() => { requestAnimationFrame(() => {
updateTime(); updateTime();
}); });*/
return { return {
countdown, countdown,

View File

@@ -12,7 +12,7 @@ describe("GameState", () => {
const unlimitedTime = 999 * 1000 const unlimitedTime = 999 * 1000
test("getting size works", () => { test("getting size works", () => {
expect((new Game({ matrix: ["00"], sequences: [["AA"]], maxBufferLength: unrestrictedBuffer, timeout: unlimitedTime })).size).toEqual(1) expect((new Game({ matrix: ["00"], sequences: [["AA"]], maxBufferLength: unrestrictedBuffer, timeoutMilliseconds: unlimitedTime })).size).toEqual(1)
expect((new Game({ expect((new Game({
matrix: [ matrix: [
"00", "01", "00", "01",
@@ -20,7 +20,7 @@ describe("GameState", () => {
], ],
sequences: [], sequences: [],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
})).size).toEqual(2) })).size).toEqual(2)
}); });
@@ -29,14 +29,14 @@ describe("GameState", () => {
matrix: threeByThreeMatrix, matrix: threeByThreeMatrix,
sequences: [["AA"]], sequences: [["AA"]],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}); });
expect(game.getCell(0, 2)).toEqual({ value: "02", isUsed: false }) expect(game.getCell(0, 2)).toEqual({ value: "02", isUsed: false })
}); });
describe("picking", () => { describe("picking", () => {
test("starts with free pick", () => { test("starts with free pick", () => {
const game = new Game({ matrix: [], sequences: [["AA"]], maxBufferLength: 1, timeout: unlimitedTime }); const game = new Game({ matrix: [], sequences: [["AA"]], maxBufferLength: 1, timeoutMilliseconds: unlimitedTime });
expect(game.state).toEqual({ selectionMode: SelectionMode.FreePick }) expect(game.state).toEqual({ selectionMode: SelectionMode.FreePick })
}); });
@@ -45,7 +45,7 @@ describe("GameState", () => {
matrix: threeByThreeMatrix, matrix: threeByThreeMatrix,
sequences: [["AA"]], sequences: [["AA"]],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}); });
game.pick(0, 0); game.pick(0, 0);
expect(game.state).toEqual({ selectionMode: SelectionMode.RowPick, column: 0 }); expect(game.state).toEqual({ selectionMode: SelectionMode.RowPick, column: 0 });
@@ -60,7 +60,7 @@ describe("GameState", () => {
matrix: threeByThreeMatrix, matrix: threeByThreeMatrix,
sequences: [["AA"]], sequences: [["AA"]],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}); });
game.pick(0, 0); game.pick(0, 0);
expect(() => game.pick(0, 0)).toThrow(); expect(() => game.pick(0, 0)).toThrow();
@@ -71,7 +71,7 @@ describe("GameState", () => {
matrix: threeByThreeMatrix, matrix: threeByThreeMatrix,
sequences: [], sequences: [],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}); });
expect(() => game.pick(-1, 0)).toThrow(); expect(() => game.pick(-1, 0)).toThrow();
expect(() => game.pick(0, -1)).toThrow(); expect(() => game.pick(0, -1)).toThrow();
@@ -85,7 +85,7 @@ describe("GameState", () => {
matrix: threeByThreeMatrix, matrix: threeByThreeMatrix,
sequences: [simpleSequence], sequences: [simpleSequence],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}); });
expect(game.getSequences()).toEqual([{ sequence: simpleSequence, numberOfFulfilled: 0 }]) expect(game.getSequences()).toEqual([{ sequence: simpleSequence, numberOfFulfilled: 0 }])
game.pick(0, 0); game.pick(0, 0);
@@ -107,7 +107,7 @@ describe("GameState", () => {
], ],
sequences: [sequence], sequences: [sequence],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}); });
expect(game.getSequences()).toEqual([{ sequence: sequence, numberOfFulfilled: 0 }]) expect(game.getSequences()).toEqual([{ sequence: sequence, numberOfFulfilled: 0 }])
game.pick(0, 0); game.pick(0, 0);
@@ -133,7 +133,7 @@ describe("GameState", () => {
], ],
sequences: [["AA", "BB", "CC"]], sequences: [["AA", "BB", "CC"]],
maxBufferLength: 3, maxBufferLength: 3,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}) })
game.pick(0, 0) game.pick(0, 0)
game.pick(2, 0) game.pick(2, 0)
@@ -151,7 +151,7 @@ describe("GameState", () => {
], ],
sequences: [["AA", "BB", "CC"]], sequences: [["AA", "BB", "CC"]],
maxBufferLength: 3, maxBufferLength: 3,
timeout: unlimitedTime, timeoutMilliseconds: unlimitedTime,
}) })
game.pick(0, 0) game.pick(0, 0)
game.pick(1, 0) game.pick(1, 0)
@@ -186,7 +186,7 @@ describe("GameState", () => {
], ],
sequences: [["AA"]], sequences: [["AA"]],
maxBufferLength: 3, maxBufferLength: 3,
timeout: 10_000, timeoutMilliseconds: 10_000,
}) })
fakeTimeProgress(1_000) fakeTimeProgress(1_000)
expect(game.remainingMilliseconds).toEqual(9_000) expect(game.remainingMilliseconds).toEqual(9_000)
@@ -208,7 +208,7 @@ describe("GameState", () => {
], ],
sequences: [["AA"]], sequences: [["AA"]],
maxBufferLength: unrestrictedBuffer, maxBufferLength: unrestrictedBuffer,
timeout: 10_000, timeoutMilliseconds: 10_000,
} }
) )
fakeTimeProgress(1_000) fakeTimeProgress(1_000)

View File

@@ -102,16 +102,15 @@ export class Game {
this.timeoutInterval = setTimeout(() => { this.timeoutInterval = setTimeout(() => {
this.state = EndState.Lost this.state = EndState.Lost
this.stopClock() this.stopClock()
}, }, this.config.timeoutMilliseconds)
this.config.timeout)
this.startTimeTimeStamp = Date.now() this.startTimeTimeStamp = Date.now()
} }
get remainingMilliseconds(): number { get remainingMilliseconds(): number {
if (this.endTimestamp) { if (this.endTimestamp) {
return this.config.timeout - (this.endTimestamp - this.startTimeTimeStamp) return this.config.timeoutMilliseconds - (this.endTimestamp - this.startTimeTimeStamp)
} }
return this.config.timeout - (Date.now() - this.startTimeTimeStamp) return this.config.timeoutMilliseconds - (Date.now() - this.startTimeTimeStamp)
} }
getCell(row: number, column: number): Cell { getCell(row: number, column: number): Cell {
@@ -218,4 +217,20 @@ export class Game {
this.checkEndGame(); this.checkEndGame();
} }
get maxBufferLength(): number {
return this.config.maxBufferLength
}
get sequences(): string[][] {
return this.config.sequences
}
get matrix(): string[] {
return this.config.matrix
}
get timeoutMilliseconds(): number {
return this.config.timeoutMilliseconds
}
} }

View File

@@ -2,5 +2,5 @@ export default interface GameConfiguration {
matrix: string[] matrix: string[]
sequences: string[][] sequences: string[][]
maxBufferLength: number maxBufferLength: number
timeout: number timeoutMilliseconds: number
} }

View File

@@ -4,7 +4,6 @@ import { saveGameKey, saveGame, loadGame } from './SaveGame';
describe("SaveGame", () => { describe("SaveGame", () => {
const state = { const state = {
level: 42, level: 42,
score: 89,
}; };
beforeEach(() => { beforeEach(() => {

View File

@@ -2,7 +2,6 @@ export const saveGameKey = "save_game";
export interface SaveGame { export interface SaveGame {
level: number level: number
score: number
} }
export function saveGame(saveGame: SaveGame): void { export function saveGame(saveGame: SaveGame): void {

View File

@@ -84,14 +84,6 @@ main {
margin: 0 5px 0 0; margin: 0 5px 0 0;
} }
&-points {
display: flex;
justify-content: center;
align-items: center;
width: 64px;
height: 32px;
}
&-border { &-border {
border: 1px solid $yellow; border: 1px solid $yellow;
} }