diff --git a/.gitignore b/.gitignore index 91dfed8..e6b1219 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store -node_modules \ No newline at end of file +node_modules +js/ \ No newline at end of file diff --git a/game.html b/game.html index a8c9a21..9f88c10 100644 --- a/game.html +++ b/game.html @@ -68,11 +68,8 @@ Processor icons created by kerismaker - Flaticon --> - diff --git a/game.js b/game.js deleted file mode 100644 index bcaee6c..0000000 --- a/game.js +++ /dev/null @@ -1,115 +0,0 @@ -import { CountUp } from "https://cdnjs.cloudflare.com/ajax/libs/countup.js/2.6.0/countUp.min.js"; - -var cpuList; -var currentCpu; -var nextCpu; - -// current user score -var score; -var highScore; - -function setHighScore(score) { - const currHighScore = localStorage.getItem("highScore_cpu") - if (currHighScore < score) { - localStorage.setItem("highScore_cpu", score) - highScore = score - } -} - -export async function main() { - await (fetch('./data.json') - .then((response) => response.json()) - .then((json) => cpuList = json)); - - currentCpu = getRandomCpu(); - nextCpu = getRandomCpu(); - score = 0; - highScore = localStorage.getItem("highScore_cpu") ?? 0 - updateLayout(); -} - -function getRandomCpu() { - let randomIndex = getRandomInt(0, cpuList.length) - return { - name: cpuList[randomIndex]["name"].split('@')[0], - score: cpuList[randomIndex]["cpuScore"] - } -} - -export function btnLowerClick() { - nextCpu.score < currentCpu.score ? showResult(true) : showResult(false); -} - -export function btnHigherClick() { - nextCpu.score > currentCpu.score ? showResult(true) : showResult(false); -} - -function showResult(isCorrect) { - document.getElementById("btnHigher").setAttribute("disabled", ""); - document.getElementById("btnLower").setAttribute("disabled", ""); - - document.getElementById("col2").style.backgroundColor = isCorrect ? "lightgreen" : "#FF4444"; - if (!isCorrect) { - setHighScore(score) - } - score = isCorrect ? score + 1 : 0; - if (score > highScore) { - highScore = score; - document.getElementById("highScore").innerText = highScore; - } - document.getElementById("score").innerText = score; - - countUp(); -} - -// updates view based on the cpu objects -function updateLayout() { - document.getElementById("highScore").innerText = highScore; - - document.getElementById("currentCpuTitle").innerText = currentCpu.name; - // add "." to large numbers - document.getElementById("currentCpuScore").innerText = new Intl.NumberFormat().format(currentCpu.score) - document.getElementById("nextCpuTitle").innerText = nextCpu.name; - - document.getElementById("nextCpuScore").innerText = "?"; - - document.getElementById("col2").style.backgroundColor = ""; -} - -function delay(time) { - return new Promise(resolve => setTimeout(resolve, time)); -} - -async function countUp() { - const options = { - startVal: nextCpu.score / 2, - separator: '.', - decimal: ',', - duration: 2 - }; - let counter = new CountUp('nextCpuScore', nextCpu.score, options); - if (!counter.error) { - counter.start(); - } else { - counter.error(demo.error); - } - - await delay(2500) - nextRound(); - - document.getElementById("btnHigher").removeAttribute("disabled"); - document.getElementById("btnLower").removeAttribute("disabled"); -} - -function nextRound() { - currentCpu = nextCpu; - nextCpu = getRandomCpu(); - - updateLayout(); -} - -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive -} \ No newline at end of file diff --git a/gst.html b/gst.html index d8c42f6..742a0ba 100644 --- a/gst.html +++ b/gst.html @@ -32,7 +32,7 @@ + @@ -68,8 +68,7 @@ diff --git a/gst.js b/gst.js deleted file mode 100644 index 61ebc0c..0000000 --- a/gst.js +++ /dev/null @@ -1,124 +0,0 @@ -var cpuList; -var currentCpu; - -var score; -var highScore; - -export async function main() { - // init cpu list - await (fetch('./data.json') - .then((response) => response.json()) - .then((json) => cpuList = json)); - - highScore = localStorage.getItem("highScore_socket") ?? 0 - score = 0; - updateScores(); - - nextRound(); -} - -function nextRound() { - currentCpu = getRandomCpu(); - - document.getElementById("cpuName").innerText = currentCpu.name; - - document.getElementById("mainCol").style.backgroundColor = ""; -} - -function getRandomCpu() { - let randomIndex; - do { - randomIndex = getRandomInt(0, cpuList.length) - } while (typeof(cpuList[randomIndex]["type"]) == null || cpuList[randomIndex]["type"] == "null" || cpuList[randomIndex]["type"] == null); - - - return { - name: cpuList[randomIndex]["name"].split('@')[0], - type: cpuList[randomIndex]["type"] - } -} - -function delay(time) { - return new Promise(resolve => setTimeout(resolve, time)); -} - -export async function btnClick(typ) { - // 0 -> Desktop - // 1 -> Laptop - // 2 -> Mobile/Embedded - // 3 -> Server - - let btnDesktop = document.getElementById("btnDesktop"); - let btnLaptop = document.getElementById("btnLaptop"); - let btnMobile = document.getElementById("btnMobile"); - let btnServer = document.getElementById("btnServer"); - - let btns = [btnDesktop, btnLaptop, btnMobile, btnServer]; - - btns.forEach((el) => { - el.setAttribute("disabled", ""); - }) - - switch (typ) { - case 0: - btnDesktop.style.backgroundColor = "#FF4444"; - break; - case 1: - btnLaptop.style.backgroundColor = "#FF4444"; - break; - case 2: - btnMobile.style.backgroundColor = "#FF4444"; - break; - case 3: - btnServer.style.backgroundColor = "#FF4444"; - break; - } - - if(currentCpu.type.includes("Desktop")) { - btnDesktop.style.backgroundColor = "lightgreen"; - } - if(currentCpu.type.includes("Laptop")) { - btnLaptop.style.backgroundColor = "lightgreen"; - } - if(currentCpu.type.includes("Mobile/Embedded")) { - btnMobile.style.backgroundColor = "lightgreen"; - } - if(currentCpu.type.includes("Server")) { - btnServer.style.backgroundColor = "lightgreen"; - } - - // Score - if (btns[typ].style.backgroundColor == "lightgreen") { - score++; - } else { - score = 0; - } - // Highscore - if (score > highScore) { - highScore = score; - localStorage.setItem("highScore_socket", highScore); - } - updateScores(); - - await delay(1000); - - btns.forEach( (el) => { - el.style.backgroundColor = "#3CC3FA"; - el.removeAttribute("disabled"); - }) - - nextRound(); -} - -function updateScores() { - document.getElementById("score").innerText = score; - document.getElementById("highScore").innerText = highScore; -} - -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive -} - -main(); \ No newline at end of file diff --git a/src/cpuRepository.ts b/src/cpuRepository.ts new file mode 100644 index 0000000..2d4eb7f --- /dev/null +++ b/src/cpuRepository.ts @@ -0,0 +1,46 @@ +export class CpuRepository { + #cpuList; + + #currentCPU; + #nextCPU; + + async init() { + const fetchResult = await fetch("../data.json"); + this.#cpuList = await fetchResult.json(); + + this.reset(); + } + + get currentCpu() { + return this.#currentCPU; + } + + get nextCpu() { + return this.#nextCPU; + } + + getRandomCpu() { + let randomIndex: number; + do { + randomIndex = this.#getRandomInt(0, this.#cpuList.length); + } while (this.#cpuList[randomIndex]["value"] == null || this.#cpuList[randomIndex]["type"] == null) + this.#cpuList[randomIndex]["name"] = this.#cpuList[randomIndex]["name"].split('@')[0]; + return this.#cpuList[randomIndex]; + } + + #getRandomInt(min, max): number { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive + } + + nextRound(): void { + this.#currentCPU = this.#nextCPU + this.#nextCPU = this.getRandomCpu(); + } + + reset(): void { + this.#currentCPU = this.getRandomCpu(); + this.#nextCPU = this.getRandomCpu(); + } +} \ No newline at end of file diff --git a/src/game.ts b/src/game.ts new file mode 100644 index 0000000..5ca8743 --- /dev/null +++ b/src/game.ts @@ -0,0 +1,168 @@ +// @ts-ignore +import { CountUp } from "https://cdnjs.cloudflare.com/ajax/libs/countup.js/2.6.0/countUp.min.js"; +import { Stats } from "./statistics.js"; +import { CpuRepository } from "./cpuRepository.js" + +class UI { + #model: ViewModel; + + #btnLower: HTMLElement; + #btnHigher: HTMLElement; + #btnScore: HTMLElement; + #btnHighScore: HTMLElement; + + #curCpuTitle: HTMLElement; + #curCpuScore: HTMLElement; + #nextCpuTitle: HTMLElement; + #nextCpuScore: HTMLElement; + + #background: HTMLElement; + + constructor() { + this.#model = new ViewModel(); + } + + async init() { + await this.#model.init(); + + this.#btnLower = document.getElementById("btnLower"); + this.#btnHigher = document.getElementById("btnHigher"); + this.#btnScore = document.getElementById("score"); + this.#btnHighScore = document.getElementById("highScore"); + + this.#curCpuTitle = document.getElementById("currentCpuTitle"); + this.#curCpuScore = document.getElementById("currentCpuScore"); + this.#nextCpuTitle = document.getElementById("nextCpuTitle"); + this.#nextCpuScore = document.getElementById("nextCpuScore"); + + this.#background = document.getElementById("col2"); + + this.#btnLower.onclick = () => this.handleButtonLowerClick(); + this.#btnHigher.onclick = () => this.handleButtonHigherClick(); + + this.updateLayout(); + } + + updateLayout() { + this.#btnHighScore.innerText = this.#model.highScore.toString(); + + this.#curCpuTitle.innerText = this.#model.currentCpu.name; + // add "." to large numbers + this.#curCpuScore.innerText = new Intl.NumberFormat().format(this.#model.currentCpu.cpuScore); + this.#nextCpuTitle.innerText = this.#model.nextCpu.name; + + this.#nextCpuScore.innerText = "?"; + + this.#background.style.backgroundColor = ""; + } + + handleButtonLowerClick() { + let result = this.#model.buttonClicked("lower"); + this.#showResult(result); + } + + handleButtonHigherClick() { + let result = this.#model.buttonClicked("higher"); + this.#showResult(result); + } + + #showResult(isCorrect) { + this.#btnHigher.setAttribute("disabled", ""); + this.#btnLower.setAttribute("disabled", ""); + + this.#background.style.backgroundColor = isCorrect ? "lightgreen" : "#FF4444"; + + isCorrect ? this.#model.incrementScore() : this.#model.resetScore(); + + this.#btnHighScore.innerText = this.#model.highScore.toString(); + this.#btnScore.innerText = this.#model.score.toString(); + + this.#countUp(); + } + + #delay(time) { + return new Promise(resolve => setTimeout(resolve, time)); + } + + async #countUp() { + const options = { + startVal: this.#model.nextCpu.cpuScore / 2, + separator: '.', + decimal: ',', + duration: 2 + }; + let counter = new CountUp('nextCpuScore', this.#model.nextCpu.cpuScore, options); + if (!counter.error) { + counter.start(); + } else { + console.log(counter.error); + } + + await this.#delay(2500) + this.#model.nextRound(); + + this.#btnHigher.removeAttribute("disabled"); + this.#btnLower.removeAttribute("disabled"); + + this.updateLayout(); + } +} + +class ViewModel { + #repo: CpuRepository; + #localStats: Stats; + + constructor() { + this.#repo = new CpuRepository(); + this.#localStats = new Stats("highScore_cpu"); + } + + async init() { + await this.#repo.init(); + } + + nextRound(): void { + this.#repo.nextRound(); + } + + // "lower" and "higher" + buttonClicked(value: string): boolean { + if (value == "higher") { + return this.#repo.nextCpu.cpuScore > this.#repo.currentCpu.cpuScore; + } + if (value == "lower") { + return this.#repo.nextCpu.cpuScore < this.#repo.currentCpu.cpuScore; + } + console.log("nothing found for '" + value + "'"); + return false; + } + + incrementScore() { + this.#localStats.incrementScore(); + } + + resetScore() { + this.#localStats.resetScore(); + } + + get currentCpu() { + return this.#repo.currentCpu; + } + + get nextCpu() { + return this.#repo.nextCpu; + } + + get highScore() { + return this.#localStats.highScore; + } + + get score() { + return this.#localStats.score; + } +} + +export async function main() { + const ui = new UI(); + await ui.init(); +} \ No newline at end of file diff --git a/src/gst.ts b/src/gst.ts new file mode 100644 index 0000000..f57ecae --- /dev/null +++ b/src/gst.ts @@ -0,0 +1,166 @@ +import { CpuRepository } from "./cpuRepository.js"; +import { Stats } from "./statistics.js"; + +type CPU = { + name: string; + type: string; +} + +class UI { + #model: ViewModel; + + #btnDesktop: HTMLElement; + #btnLaptop: HTMLElement; + #btnServer: HTMLElement; + #btnMobile: HTMLElement; + + #btns: HTMLElement[]; + + #cpuName: HTMLElement; + #score: HTMLElement; + #highScore: HTMLElement; + #mainCol: HTMLElement; + + constructor() { + this.#model = new ViewModel(); + + this.#btnDesktop = document.getElementById("btnDesktop"); + this.#btnDesktop.onclick = () => this.btnClick(0); + this.#btnLaptop = document.getElementById("btnLaptop"); + this.#btnLaptop.onclick = () => this.btnClick(1); + this.#btnMobile = document.getElementById("btnMobile"); + this.#btnMobile.onclick = () => this.btnClick(2); + this.#btnServer = document.getElementById("btnServer"); + this.#btnServer.onclick = () => this.btnClick(3); + + this.#btns = [this.#btnDesktop, this.#btnLaptop, this.#btnMobile, this.#btnServer]; + + this.#cpuName = document.getElementById("cpuName"); + this.#score = document.getElementById("score"); + this.#highScore = document.getElementById("highScore"); + this.#mainCol = document.getElementById("mainCol"); + } + + async init() { + await this.#model.init(); + + this.#nextRound(); + } + + #updateScores() { + this.#score.innerText = this.#model.score.toString(); + this.#highScore.innerText = this.#model.highScore.toString(); + } + + async #delay(time) { + return new Promise(resolve => setTimeout(resolve, time)); + } + + #nextRound() { + this.#model.nextRound(); + + this.#cpuName.innerText = this.#model.currentCpu.name; + + this.#mainCol.style.backgroundColor = ""; + } + + async btnClick(typ) { + // 0 -> Desktop + // 1 -> Laptop + // 2 -> Mobile/Embedded + // 3 -> Server + + this.#btns.forEach((el) => { + el.setAttribute("disabled", ""); + }) + + switch (typ) { + case 0: + this.#btnDesktop.style.backgroundColor = "#FF4444"; + break; + case 1: + this.#btnLaptop.style.backgroundColor = "#FF4444"; + break; + case 2: + this.#btnMobile.style.backgroundColor = "#FF4444"; + break; + case 3: + this.#btnServer.style.backgroundColor = "#FF4444"; + break; + } + + const currentType = this.#model.currentCpu.type; + if(currentType.includes("Desktop")) { + this.#btnDesktop.style.backgroundColor = "lightgreen"; + } + if(currentType.includes("Laptop")) { + this.#btnLaptop.style.backgroundColor = "lightgreen"; + } + if(currentType.includes("Mobile/Embedded")) { + this.#btnMobile.style.backgroundColor = "lightgreen"; + } + if(currentType.includes("Server")) { + this.#btnServer.style.backgroundColor = "lightgreen"; + } + + // Score + if (this.#btns[typ].style.backgroundColor == "lightgreen") { + this.#model.incrementScore(); + } else { + this.#model.resetScore(); + } + this.#updateScores(); + + await this.#delay(1000); + + this.#btns.forEach( (el) => { + el.style.backgroundColor = "#3CC3FA"; + el.removeAttribute("disabled"); + }) + + this.#nextRound(); + } +} + +class ViewModel { + #repo: CpuRepository; + #stats: Stats; + + constructor() { + this.#stats = new Stats("highScore_socket"); + this.#repo = new CpuRepository(); + } + + async init() { + await this.#repo.init(); + } + + nextRound() { + this.#repo.reset(); + } + + incrementScore() { + this.#stats.incrementScore(); + } + + resetScore() { + this.#stats.resetScore(); + } + + get currentCpu(): CPU { + return this.#repo.currentCpu; + } + + get score(): number { + return this.#stats.score; + } + + get highScore(): number { + return this.#stats.highScore; + } +} + +export async function main() { + const ui = new UI(); + await ui.init(); +} \ No newline at end of file diff --git a/src/statistics.ts b/src/statistics.ts new file mode 100644 index 0000000..f320c64 --- /dev/null +++ b/src/statistics.ts @@ -0,0 +1,34 @@ +export class Stats { + #score: number; + #highScore: number; + #highScoreStorageKey: string; + + constructor(highScoreStorageKey) { + // used as key for localStorage + this.#highScoreStorageKey = highScoreStorageKey; + + this.#score = 0; + this.#highScore = Number(localStorage.getItem(this.#highScoreStorageKey)) ?? 0; + } + + incrementScore(value = 1) { + this.#score += value; + + if (this.#highScore < this.#score) { + this.#highScore = this.#score; + localStorage.setItem(this.#highScoreStorageKey, this.#highScore.toString()); + } + } + + resetScore(): void { + this.#score = 0; + } + + get highScore(): number { + return this.#highScore; + } + + get score(): number { + return this.#score; + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..17a2a90 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "outDir": "./js", + "allowJs": true, + "target": "ES2017", + "lib": ["es2018", "dom"], + }, + "include": ["./src/**/*"] +} + \ No newline at end of file