347 lines
11 KiB
Vue

<template>
<div>
<div class="md-layout" v-if="error" @click="error = null">
<div class="md-layout-item">
<md-app>
<md-app-content>
Error: <br>
{{ error }}
</md-app-content>
</md-app>
</div>
</div>
<br>
<div class="md-layout">
<div class="md-layout-item">
<md-app>
<md-app-content>
<md-field>
<label>Name</label>
<md-input v-model="name" :readonly="gameJoined"></md-input>
</md-field>
<md-field v-if="!gameStarted">
<label>Game code</label>
<md-input v-model="code" :readonly="gameJoined"></md-input>
</md-field>
<template v-if="!gameJoined">
<md-button @click="createGame" class="md-raised">Create</md-button>
<md-button @click="joinGame" class="md-raised">Join</md-button>
</template>
<template v-if="gameJoined && !gameStarted && owner">
<md-button @click="startGame" class="md-raised md-primary">Start</md-button>
</template>
<template v-if="myTurn && !gameEnded">
It is your turn, make a guess: <br>
<md-field>
<label>Dice count</label>
<md-input type="number" v-model="diceCount"></md-input>
</md-field>
Die value: <br>
<span v-for="n in 6" :key="'v'+n" @click="dieValue = n">
<die :number="n" :selected="dieValue === n"></die>
</span> <br><br>
<md-button @click="makeGuess" class="md-raised md-primary">Guess</md-button>
<md-button @click="callBluff" class="md-raised md-accent">Call</md-button>
</template>
</md-app-content>
</md-app>
</div>
<div class="md-layout-item">
<md-app>
<md-app-content>
<template v-if="gameJoined && !gameStarted">
<span v-if="owner">Game created!</span>
<span v-else>Game joined, now waiting or game to start</span>
<br>
PlayerId: {{ playerId }} <br>
<template v-if="gameStateObject">
Players: <br>
<template v-for="player in gameStateObject.players">
- {{ player.name }}<br>
</template>
<br/>
<game-rules-editor v-model="rules" :readonly="!owner"/>
</template>
</template>
<template v-if="gameRunning">
The game has started, lets go! <br>
</template>
<template v-if="gameStateObject && gameRunning">
<span
v-if="previousRound && previousRound.loser.hash === playerHash">You lost the previous round!<br></span>
Round: {{ currentRound.number + 1 }} <br>
Turn: {{ lastTurn ? lastTurn.number + 2 : 1 }} <br>
Your throw: <br>
<template v-for="(count, number) in currentRound.myRolls">
<die v-for="n in count" :number="number" :key="'t'+n+number"></die>
</template>
<br><br>
<template v-if="lastTurn">
Last guesses: <br>
<round-turns :round="currentRound"/>
</template>
<br>
<template v-if="!myTurn">Someone else is playing, waiting for your turn<br></template>
Players: <br>
<template v-for="player in gameStateObject.players">
-{{ player.hash === gameStateObject.currentPlayer.hash ? '>' : '-' }}{{ player.name }}<br>
</template>
<br>
</template>
<template v-if="gameEnded">
The game is over, the winner is: {{ gameStateObject.currentPlayer.name }}<br>
</template>
</md-app-content>
</md-app>
</div>
</div>
<br>
<template v-if="gameStateObject && gameStarted">
History: <br>
<template v-for="round in gameStateObject.rounds.slice().reverse()">
<round :round="round" :players="playersKeyedById"/>
<br>
</template>
</template>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import PerudoApi from "@/services/PerudoApi";
import Die from "@/components/Die.vue";
import {
ApiObject,
GameState,
GameStateObject,
IsStartedObject,
JoinCreateGameObject,
MyTurnObject,
RoundObject,
TurnObject,
GameStateState,
PlayerObject,
GameRules
} from "@/objects/objects";
import Round from "@/components/Round.vue";
import RoundTurns from "@/components/RoundTurns.vue";
import GameRulesEditor from "@/components/GameRulesEditor.vue";
@Component({
components: {GameRulesEditor, RoundTurns, Round, Die}
})
export default class Home extends Vue {
private gameState: GameState = GameState.Setup;
private gameStateObject: GameStateObject | null = null;
private error: string | null = null;
private name: string = process.env.VUE_APP_NAME;
private code: string = '';
private owner: boolean = false;
private playerId: string | null = null;
private playerHash: string | null = null;
private gameTimer: number | null = null;
private diceCount: string = '1';
private dieValue: number = 2;
private get gameJoined (): boolean {
return this.gameState >= GameState.Joined;
}
private get gameStarted (): boolean {
return this.gameState >= GameState.Started;
}
private get gameRunning (): boolean {
return this.gameStarted && !this.gameEnded;
}
private get gameEnded (): boolean {
return this.gameState === GameState.Ended;
}
private get myTurn (): boolean {
return this.gameState === GameState.MyTurn;
}
private get playersKeyedById (): Record<string, PlayerObject> | undefined {
let newPlayers: Record<string, PlayerObject> = {};
if (this.gameStateObject) {
let players = this.gameStateObject.players;
for (let key in players) {
newPlayers[players[key].hash] = players[key];
}
}
return newPlayers;
}
private get previousRound (): RoundObject | undefined {
let rounds = this.gameStateObject?.rounds;
return rounds ? (rounds[rounds.length - 2] ?? undefined) : undefined;
}
private get currentRound (): RoundObject | undefined {
let rounds = this.gameStateObject?.rounds;
return rounds ? rounds[rounds.length - 1] : undefined;
}
private get lastTurn (): TurnObject | undefined {
let turns = this.currentRound?.turns;
return turns ? turns[turns.length - 1] : undefined;
}
private get rules (): GameRules | undefined {
return this.gameStateObject?.rules;
}
private set rules (gameRules: GameRules | undefined) {
console.log(gameRules);
if (this.playerId && gameRules) {
PerudoApi.instance.setGameRules(this.playerId, gameRules);
}
}
private createGame (): void {
if (this.name === '') {
this.error = "Name cannot be empty";
return;
}
PerudoApi.instance.createGame(this.name).then((response: JoinCreateGameObject) => {
this.playerId = response.player.id;
this.playerHash = response.player.hash;
this.code = response.code;
this.owner = true;
this.gameState = GameState.Joined;
this.gameTimer = setInterval(() => {
this.checkStarted();
}, 1000);
}).catch((reason => {
this.error = reason;
}));
}
private joinGame (): void {
if (this.code === '') {
this.error = "Game code cannot be empty when joining a game";
return;
}
if (this.name === '') {
this.error = "Name cannot be empty";
return;
}
PerudoApi.instance.joinGame(this.name, this.code).then((response: JoinCreateGameObject) => {
this.playerId = response.player.id;
this.playerHash = response.player.hash;
this.gameTimer = setInterval(() => {
this.checkStarted();
}, 1000);
this.gameState = GameState.Joined;
}).catch((reason => {
this.error = reason;
}));
}
private startGame (): void {
if (this.gameJoined && this.playerId) {
PerudoApi.instance.startGame(this.playerId).then((response: ApiObject) => {
this.gameState = GameState.Started;
this.gameStateObject = null; // Bug fix because checkStarted gameStateObject misses some properties
this.checkTurn();
}).catch((reason => {
this.error = reason;
}));
}
}
private makeGuess (): void {
if (this.myTurn && this.playerId) {
PerudoApi.instance.makeGuess(this.playerId, {
diceCount: parseInt(this.diceCount),
dieValue: this.dieValue,
}).then((response: MyTurnObject) => {
this.gameState = GameState.Started;
this.gameTimer = setInterval(() => {
this.checkTurn();
}, 1000);
this.checkTurn();
}).catch((reason => {
this.error = reason;
}));
}
}
private callBluff (): void {
if (this.myTurn && this.playerId) {
PerudoApi.instance.callBluff(this.playerId).then((response: MyTurnObject) => {
this.gameState = GameState.Started;
this.gameTimer = setInterval(() => {
this.checkTurn();
}, 1000);
this.checkTurn();
}).catch((reason => {
this.error = reason;
}));
}
}
private checkStarted (): void {
console.log("Check started");
if (this.gameJoined && this.playerId) {
PerudoApi.instance.gameStarted(this.playerId).then((response: IsStartedObject) => {
this.gameStateObject = response.gameState;
console.log(this.gameStateObject.rules);
if (response.started) {
this.gameState = GameState.Started;
this.clearGameTimer();
this.gameTimer = setInterval(() => {
this.checkTurn();
}, 1000);
}
}).catch((reason => {
this.error = reason;
}));
}
}
private checkTurn (): void {
console.log("Check turn");
if (this.gameStarted && this.playerId) {
PerudoApi.instance.myTurn(this.playerId).then((response: MyTurnObject) => {
this.gameStateObject = response.gameState;
if (this.gameStateObject.state === GameStateState.Ended) {
this.gameState = GameState.Ended;
this.clearGameTimer();
}
if (response.turn) {
this.gameState = GameState.MyTurn;
this.diceCount = this.lastTurn?.diceCount.toString() ?? this.diceCount;
this.dieValue = this.lastTurn?.dieValue ?? this.dieValue;
this.clearGameTimer();
console.log(this.gameStateObject);
}
});
}
}
private clearGameTimer (): void {
if (this.gameTimer) {
clearInterval(this.gameTimer);
this.gameTimer = null;
}
}
}
</script>