From bfbf625f8773e0c73370be6b4c4bc333a365867b Mon Sep 17 00:00:00 2001 From: Lordmau5 Date: Mon, 13 Nov 2023 12:08:48 +0100 Subject: [PATCH] Test code --- package.json | 2 + pnpm-lock.yaml | 14 ++++ src/js/Bingo.ts | 164 +++++++++++++++++++++++++++++++++++++++++ src/main.ts | 2 + src/views/MainPage.vue | 4 + tsconfig.app.json | 7 +- 6 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 src/js/Bingo.ts diff --git a/package.json b/package.json index 2ad6534..4a9fbdb 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,10 @@ }, "dependencies": { "@quasar/extras": "^1.16.8", + "class-transformer": "^0.5.1", "pinia": "^2.1.7", "quasar": "^2.13.1", + "reflect-metadata": "^0.1.13", "vue": "^3.3.4", "vue-router": "^4.2.5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a178784..b00cbdf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,12 +8,18 @@ dependencies: '@quasar/extras': specifier: ^1.16.8 version: 1.16.8 + class-transformer: + specifier: ^0.5.1 + version: 0.5.1 pinia: specifier: ^2.1.7 version: 2.1.7(typescript@5.2.2)(vue@3.3.8) quasar: specifier: ^2.13.1 version: 2.13.1 + reflect-metadata: + specifier: ^0.1.13 + version: 0.1.13 vue: specifier: ^3.3.4 version: 3.3.8(typescript@5.2.2) @@ -1490,6 +1496,10 @@ packages: fsevents: 2.3.3 dev: true + /class-transformer@0.5.1: + resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -2667,6 +2677,10 @@ packages: picomatch: 2.3.1 dev: true + /reflect-metadata@0.1.13: + resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} + dev: false + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: true diff --git a/src/js/Bingo.ts b/src/js/Bingo.ts new file mode 100644 index 0000000..91926c9 --- /dev/null +++ b/src/js/Bingo.ts @@ -0,0 +1,164 @@ +import { + Transform, + Type, + instanceToPlain, plainToInstance +} from 'class-transformer'; + +function stringCompare(a: string, b: string) { + return a.localeCompare(b, undefined, { + sensitivity: 'accent' + }) === 0; +} + +interface IBingoGame { + id: string; + name: string; + description: string; + generator: 'simple' | 'srl_v5' | 'srl_v8'; + goals: IBingoGoal[]; + groups: IBingoGroup[]; +} + +interface IBingoGoal { + name: string; + group?: IBingoGroup; + tags: string[]; + possible_spaces: number[]; +} + +interface IBingoGroup { + name: string; + parent?: IBingoGroup; +} + +class BingoGame implements IBingoGame { + id: string; + + name: string; + + description: string; + + generator: 'simple' | 'srl_v5' | 'srl_v8' = 'simple'; + + @Type(() => BingoGoal) + goals: IBingoGoal[] = []; + + @Type(() => BingoGroup) + groups: IBingoGroup[] = []; + + constructor(id: string, name: string, description: string) { + this.id = id; + this.name = name; + this.description = description; + } + + addGoal(goal: IBingoGoal): void { + if (this.goals.some(_goal => stringCompare(_goal.name, goal.name))) + return; + + this.goals.push(goal); + } + + removeGoal(goal: IBingoGoal): void { + this.goals = this.goals.filter(_goal => !stringCompare(_goal.name, goal.name)); + } + + addGroup(group: IBingoGroup): void { + if (this.groups.some(_group => stringCompare(_group.name, group.name))) + return; + + this.groups.push(group); + } + + removeGroup(group: IBingoGroup): boolean { + // Group has parent, don't delete + if (this.groups.some(_group => _group.parent && stringCompare(_group.parent.name, group.name))) + return false; + + if (this.goals.some(goal => goal.group && stringCompare(goal.group.name, group.name))) + return false; + // TODO: Make sure no goal is still using group; + // boolean override "force_remove" which will remove the group from all goals + console.log('deltee', group); + this.groups = this.groups.filter(_group => !stringCompare(_group.name, group.name)); + console.log(this.groups); + + return true; + } +} + +class BingoGoal implements IBingoGoal { + // id: string; // uuid-by-string maybe? https://www.npmjs.com/package/uuid-by-string + + name: string; + + group?: IBingoGroup; + + tags: string[] = []; + + possible_spaces: number[] = []; + + constructor(name: string, group?: BingoGroup) { + this.name = name; + this.group = group; + } + + addTag(tag: string): IBingoGoal { + if (this.tags.includes(tag)) + return this; + + this.tags.push(tag); + + return this; + } + + removeTag(tag: string): void { + this.tags = this.tags.filter(_tag => !stringCompare(_tag, tag)); + } + + setGroup(group: BingoGroup) { + this.group = group; + } + + setPossibleSpaces(possible_spaces: number[]) { + this.possible_spaces = possible_spaces; + } +} + +class BingoGroup implements IBingoGroup { + name: string; + + @Type(() => BingoGroup) + parent?: IBingoGroup; + + constructor(name: string, parent?: BingoGroup) { + this.name = name; + this.parent = parent; + } +} + +const game = new BingoGame('yakuza_0', 'Yakuza 0', 'The funny game we used for all bingos.'); +const battle_group = new BingoGroup('Battle'); +const defeat_enemies = new BingoGroup('Defeat enemies on the street', battle_group); +game.addGroup(battle_group); +game.addGroup(defeat_enemies); + +const easy = new BingoGoal('Defeat 50 enemies on the street', defeat_enemies).addTag('Easy'); +const normal = new BingoGoal('Defeat 150 enemies on the street', defeat_enemies).addTag('Normal'); +const hard = new BingoGoal('Defeat 300 enemies on the street', defeat_enemies).addTag('Hard'); + +game.addGoal(easy); +game.addGoal(normal); +game.addGoal(hard); + +const jsonifiedInstance = instanceToPlain(game); +// console.log(JSON.stringify(jsonifiedInstance)); +// console.log(JSON.stringify(game)); + +const json_string = '{"id":"yakuza_0","name":"Yakuza 0","description":"The funny game we used for all bingos.","generator":"simple","goals":[{"name":"Defeat 50 enemies on the street","tags":["Easy"],"group":{"name":"Defeat enemies on the street","parent":{"name":"Battle"}},"possible_spaces":[]},{"name":"Defeat 150 enemies on the street","tags":["Normal"],"group":{"name":"Defeat enemies on the street","parent":{"name":"Battle"}},"possible_spaces":[]},{"name":"Defeat 300 enemies on the street","tags":["Hard"],"group":{"name":"Defeat enemies on the street","parent":{"name":"Battle"}},"possible_spaces":[]}],"groups":[{"name":"Battle"},{"name":"Defeat enemies on the street","parent":{"name":"Battle"}}]}'; +const parsed: JSON = JSON.parse(json_string); +const parsed_game = plainToInstance(BingoGame, parsed); +// console.log(JSON.stringify(other_game) === JSON.stringify(jsonifiedInstance)); + +parsed_game.removeGroup(defeat_enemies); +console.log(parsed_game.goals); diff --git a/src/main.ts b/src/main.ts index 83cd36d..99c69a3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -17,6 +17,8 @@ import '@quasar/extras/material-icons/material-icons.css'; // Import Quasar css import 'quasar/src/css/index.sass'; +import 'reflect-metadata'; + import App from './App.vue'; import router from './router'; diff --git a/src/views/MainPage.vue b/src/views/MainPage.vue index 1599c78..2047e41 100644 --- a/src/views/MainPage.vue +++ b/src/views/MainPage.vue @@ -1,3 +1,7 @@ + + diff --git a/tsconfig.app.json b/tsconfig.app.json index 836379c..c04b223 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -17,6 +17,9 @@ "@/*": [ "./src/*" ] - } - } + }, + "target": "ESNext", + "emitDecoratorMetadata": true, + "experimentalDecorators": true + }, } \ No newline at end of file