Skip to content

Commit

Permalink
refactor(pages): splitting component and page. some were doing both l…
Browse files Browse the repository at this point in the history
…ogic
  • Loading branch information
mJehanno committed Mar 5, 2024
1 parent 165a646 commit cdd91ec
Show file tree
Hide file tree
Showing 23 changed files with 417 additions and 326 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ The game is supposed to be able to update itself on launch.

More features are to come :

- [ ] live score display
- [ ] new difficulty mode (easier than the existing one)
- [X] live score display
- [X] new difficulty mode (easier than the existing one)
- [ ] might add some other mod later
5 changes: 4 additions & 1 deletion frontend/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@ declare module 'vue' {
Column: typeof import('primevue/column')['default']
DataTable: typeof import('primevue/datatable')['default']
Game: typeof import('./src/components/Game.vue')['default']
Home: typeof import('./src/components/Home.vue')['default']
GameOverDialog: typeof import('./src/components/GameOverDialog.vue')['default']
InputText: typeof import('primevue/inputtext')['default']
LifeBar: typeof import('./src/components/LifeBar.vue')['default']
Prompter: typeof import('./src/components/Prompter.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
ScoreBoard: typeof import('./src/components/ScoreBoard.vue')['default']
Streak: typeof import('./src/components/Streak.vue')['default']
Timer: typeof import('./src/components/Timer.vue')['default']
Update: typeof import('./src/components/Update.vue')['default']
VersionDisplayer: typeof import('./src/components/VersionDisplayer.vue')['default']
}
}
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
"version": "1.3.2",
"version": "1.4.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
b2b66add8c5579eb021ae243c0424edd
4a7c841e55cbdbc32f4fa1d10eb002ec
147 changes: 18 additions & 129 deletions frontend/src/components/Game.vue
Original file line number Diff line number Diff line change
@@ -1,159 +1,52 @@
<script setup lang="ts">
import { computed, reactive, ref} from 'vue';
import { onMounted } from 'vue'
import InputNumber from 'primevue/inputnumber';
import FloatLabel from 'primevue/floatlabel';
import Dialog from 'primevue/dialog';
import InlineMessage from 'primevue/inlinemessage';
import Prompter from '@/components/Prompter.vue';
import Timer from '@/components/Timer.vue';
import ScoreBoard from '@/components/ScoreBoard.vue';
import { useRouter } from 'vue-router';
import { AddScore } from '../../wailsjs/go/score/ScoreService';
import { DifficultyLevel } from '@/models/game';
import type {GamePrompt, GameState} from '@/models/game';
import {score} from '../../wailsjs/go/models';
import { useRoute } from 'vue-router';
import {Mode} from '@/models/scoreboard';
onMounted(() => {
generatePrompt();
});
const route = useRoute()
const router = useRouter();
const props = defineProps<{
prompt: string;
expected: number
}>()
const prompt = computed<string>(() => game_prompt.x + " X " + game_prompt.y + " = ");
const result = computed<number>(() => game_prompt.x * game_prompt.y);
const timer = ref<typeof Timer | null>(null)
const gameState: GameState = reactive({
streak: 0,
endingDialogVisible : false,
level: route.params.difficultyLevel as DifficultyLevel,
currentlife: route.params.difficultyLevel == 'medium' ? 3 : 0,
maxSec: 20
})
const emit = defineEmits<{
succeed: []
failed: []
}>()
const game_prompt: GamePrompt = reactive({
x : 0,
y : 0,
result: result,
prompt: prompt,
})
const current: score.Score = reactive(
{id: -1,username: 'xxx', score: 0, difficulty: gameState.level, created_at: new Date()} as score.Score
)
function generateRandom(): number{
return Math.ceil(Math.random() * 10);
}
function openEndingDialog() {
gameState.endingDialogVisible = true;
function handleInput(event: Event) {
const v = (event.target as HTMLInputElement).value;
check(parseInt(v));
//(event.target as HTMLInputElement).value = null;
}
function gameOver(){
if (gameState.user && gameState.user?.length > 0 && gameState.user?.length <=3) {
AddScore(score.Score.createFrom({username: gameState.user, score: gameState.streak, difficulty: gameState.level}))
router.push('/');
}else if (gameState.user && gameState.user?.length > 3){
gameState.err = "username should contains max 3 characters"
function check(val: number | undefined){
if (val === props.expected) {
emit("succeed")
}else {
gameState.err = "username is required"
emit("failed")
}
}
function generatePrompt() {
game_prompt.x = generateRandom();
game_prompt.y = generateRandom();
}
function check(val: number | undefined, timeout: boolean) {
if (val == game_prompt.result) {
gameState.streak ++;
current.score ++;
if (gameState.level == DifficultyLevel.Hard && timer.value && gameState.streak %5 == 0 && gameState.maxSec > 4) {
gameState.maxSec -= 4;
generatePrompt()
//timer.value?.resetWithoutSec(4)
return
}
}else {
switch(gameState.level) {
case DifficultyLevel.Easy:
if (!timeout) {
return;
}
break;
case DifficultyLevel.Medium:
gameState.currentlife --;
if (gameState.currentlife == 0) {
openEndingDialog()
}
if (!timeout) {
return;
}
break;
case DifficultyLevel.Hard:
openEndingDialog();
return;
}
}
if (timeout) {
openEndingDialog();
return;
}
generatePrompt();
timer.value?.reset();
}
</script>
<template>
<div>
<div class="flex flex-column align-items-center">
<Timer :seconds="gameState.maxSec" @timeout="check(gameState.answer, true)" ref="timer"/>
<div class="flex flex-row align-items-center w-full justify-content-evenly">
<span id="streak">Current streak : {{ gameState.streak }}</span>
<div v-if="gameState.level == DifficultyLevel.Medium">
<i class="pi pi-heart-fill text-red-700 text-2xl" v-for="n in gameState.currentlife"></i>
<i class="pi pi-heart text-red-700 text-2xl" v-for="n in (3- gameState.currentlife)"></i>
</div>
</div>

<div class="flex flex-row align-items-center">
<ScoreBoard class="align-self-start" :current="current" :mode="Mode.Live" :level="gameState.level"/>
<div id="game">
<Prompter id="prompt" :prompt="game_prompt.prompt" />
<Prompter id="prompt" :prompt="props.prompt" />
<FloatLabel id="input" >
<InputNumber :model-value="gameState.answer" :input-props="{'autofocus': true}" id="answer-input" @keyup.enter="check($event.target.value, false); $event.target.value = null;" />
<InputNumber :input-props="{'autofocus': true}" id="answer-input" @keyup.enter="handleInput($event); $event.target.value=null;" />
<label for="answer-input">Answer</label>
</FloatLabel>
</div>
</div>
</div>

<Dialog v-model:visible="gameState.endingDialogVisible" :content-style="{padding: '0 1em', height: '100%'}" modal header="Game Over" :closable="false" v-on:hide="gameOver">
<div class="flex flex-column w-full">
<span class="p-text-secondary block ">The answer to {{ game_prompt.prompt }} was : {{ game_prompt.result }}</span>
<div class="flex flex-column m-2 flex-wrap">
<span class="m-2">Register your score !</span>
<FloatLabel class="m-2">
<InputText id="username" v-model="gameState.user" mask="aaa" placeholder="aaa" aria-describedby="username-help"/>
<label for="username">Username</label>
</FloatLabel>
<small id="username-help">Can't contain more than 3 characters.</small>
<InlineMessage class="m-1" v-if="gameState.err" severity="error">{{ gameState.err }}</InlineMessage>
</div>
</div>
<template #footer>
<div class="flex flex-row justify-content-center w-full" >
<Button label="Submit" class="m-2" severity="success" @click="gameOver"/>
</div>
</template>
</Dialog>
</div>
</template>
<style>
Expand All @@ -167,10 +60,6 @@ function check(val: number | undefined, timeout: boolean) {
#prompt{
font-size: 5em;
}
#streak{
font-size: 3em;
}
.p-dialog-header, .p-dialog-footer{
padding: 1em;
}
Expand Down
52 changes: 52 additions & 0 deletions frontend/src/components/GameOverDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script setup lang="ts">
import Dialog from 'primevue/dialog';
import InlineMessage from 'primevue/inlinemessage';
import FloatLabel from 'primevue/floatlabel';
import { reactive } from 'vue';
const props = defineProps<{
visible: boolean;
prompt?: string;
answer?: number;
}>()
const dialogState = reactive<{
user?: string,
err ?: string,
}>({})
const emit = defineEmits<{
userCreated: [username: string]
}>()
function gameOver(){
if (dialogState.user && dialogState.user?.length > 0 && dialogState.user?.length <=3) {
emit("userCreated", dialogState.user)
}else if (dialogState.user && dialogState.user?.length > 3){
dialogState.err = "username should contains max 3 characters"
}else {
dialogState.err = "username is required"
}
}
</script>
<template>
<Dialog v-model:visible="props.visible" :content-style="{padding: '0 1em', height: '100%'}" modal header="Game Over" :closable="false" v-on:hide="gameOver">
<div class="flex flex-column w-full">
<span class="p-text-secondary block ">The answer to {{ props.prompt }} was : {{ props.answer }}</span>
<div class="flex flex-column m-2 flex-wrap">
<span class="m-2">Register your score !</span>
<FloatLabel class="m-2">
<InputText id="username" v-model="dialogState.user" mask="aaa" placeholder="aaa" aria-describedby="username-help"/>
<label for="username">Username</label>
</FloatLabel>
<small id="username-help">Can't contain more than 3 characters.</small>
<InlineMessage class="m-1" v-if="dialogState.err" severity="error">{{ dialogState.err }}</InlineMessage>
</div>
</div>
<template #footer>
<div class="flex flex-row justify-content-center w-full" >
<Button label="Submit" class="m-2" severity="success" @click="gameOver"/>
</div>
</template>
</Dialog>
</template>
82 changes: 0 additions & 82 deletions frontend/src/components/Home.vue

This file was deleted.

12 changes: 12 additions & 0 deletions frontend/src/components/LifeBar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script setup lang="ts">
const props = defineProps<{
maxHealth: number;
current: number;
}>()
</script>
<template>
<div>
<i class="pi pi-heart-fill text-red-700 text-2xl" :key="n" v-for="n in props.current"></i>
<i class="pi pi-heart text-red-700 text-2xl" :key="n" v-for="n in (props.maxHealth -props.current)"></i>
</div>
</template>
Loading

0 comments on commit cdd91ec

Please sign in to comment.