From 1e59b8bc6c9e491222e651837908417fac01142f Mon Sep 17 00:00:00 2001 From: Isahann Hanacleto Date: Tue, 20 Aug 2024 14:23:50 -0300 Subject: [PATCH 1/3] #64 checkpoint --- db.json | 162 ++++++++++++++++-- package.json | 2 +- src/app/app-routing.module.ts | 12 +- src/app/app.module.ts | 8 +- .../icon-text-button.component.html | 7 + .../icon-text-button.component.sass | 13 ++ .../icon-text-button.component.spec.ts | 21 +++ .../icon-text-button.component.ts | 25 +++ .../game-mode-window.component.html | 20 +++ .../game-mode-window.component.sass | 17 ++ .../game-mode-window.component.spec.ts | 21 +++ .../game-mode-window.component.ts | 25 +++ .../main-window/main-window.component.html | 2 +- .../question-trifecta-window.component.html | 84 +++++++++ .../question-trifecta-window.component.sass | 126 ++++++++++++++ ...question-trifecta-window.component.spec.ts | 21 +++ .../question-trifecta-window.component.ts | 129 ++++++++++++++ .../question-window.component.html | 6 +- .../question-window.component.ts | 51 ++---- src/assets/icons/30x30/normal.png | Bin 0 -> 7238 bytes src/assets/icons/30x30/trifecta.png | Bin 0 -> 7647 bytes src/assets/icons/trifecta.png | Bin 0 -> 8800 bytes src/model/enums/GameModesEnum.ts | 21 +++ src/model/enums/PathsEnum.ts | 4 +- src/model/questions/Question.ts | 7 +- src/service/trivia.service.ts | 65 +++++-- 26 files changed, 766 insertions(+), 83 deletions(-) create mode 100644 src/app/common/icon-text-button/icon-text-button.component.html create mode 100644 src/app/common/icon-text-button/icon-text-button.component.sass create mode 100644 src/app/common/icon-text-button/icon-text-button.component.spec.ts create mode 100644 src/app/common/icon-text-button/icon-text-button.component.ts create mode 100644 src/app/game-mode-window/game-mode-window.component.html create mode 100644 src/app/game-mode-window/game-mode-window.component.sass create mode 100644 src/app/game-mode-window/game-mode-window.component.spec.ts create mode 100644 src/app/game-mode-window/game-mode-window.component.ts create mode 100644 src/app/question-trifecta-window/question-trifecta-window.component.html create mode 100644 src/app/question-trifecta-window/question-trifecta-window.component.sass create mode 100644 src/app/question-trifecta-window/question-trifecta-window.component.spec.ts create mode 100644 src/app/question-trifecta-window/question-trifecta-window.component.ts create mode 100644 src/assets/icons/30x30/normal.png create mode 100644 src/assets/icons/30x30/trifecta.png create mode 100644 src/assets/icons/trifecta.png create mode 100644 src/model/enums/GameModesEnum.ts diff --git a/db.json b/db.json index bb690b6..4ca9439 100644 --- a/db.json +++ b/db.json @@ -1,39 +1,106 @@ { "theTriviaApi": [ { - "category": "society_and_culture", - "id": "622a1c367cc59eab6f950408", - "correctAnswer": "Rosa Parks", + "category": "sport_and_leisure", + "id": "62417da50f96c4efe8d773db", + "correctAnswer": "San Francisco 49ers", "incorrectAnswers": [ - "Angela Davis", - "Dorothy Cotton", - "Fanny Lou Hamer" + "San Francisco Jaguars", + "San Francisco Pistons", + "San Francisco Predators" ], "question": { - "text": "Which civil right activist is famous for refusing to give up her seat on a bus to make way for a white person?" + "text": "Which of these is an American Football team based in San Francisco?" }, "tags": [ - "general_knowledge", - "people", - "society_and_culture" + "sport" ], "type": "text_choice", "difficulty": "medium", "regions": [], "isNiche": false + }, + { + "category": "history", + "id": "622a1c367cc59eab6f9503ac", + "correctAnswer": "Germany", + "incorrectAnswers": [ + "Switzerland", + "Denmark", + "France" + ], + "question": { + "text": "Which country was first to operate an old age pension scheme?" + }, + "tags": [ + "history" + ], + "type": "text_choice", + "difficulty": "hard", + "regions": [], + "isNiche": false + }, + { + "category": "arts_and_literature", + "id": "649b4f4f828109028d236251", + "correctAnswer": "A Spider", + "incorrectAnswers": [ + "A Pig", + "A Sheep", + "A Horse" + ], + "question": { + "text": "In E.B. White's classic children's book \"Charlotte's Web\", what kind of animal is Charlotte?" + }, + "tags": [ + "animals", + "childrens_literature", + "arts_and_literature", + "literature" + ], + "type": "text_choice", + "difficulty": "easy", + "regions": [], + "isNiche": false } ], "openTriviaDb": { "response_code": 0, "results": [ { - "type": "Ym9vbGVhbg==", + "type": "bXVsdGlwbGU=", + "difficulty": "bWVkaXVt", + "category": "SGlzdG9yeQ==", + "question": "V2hlbiBkaWQgdGhlIENyaXNpcyBvZiB0aGUgVGhpcmQgQ2VudHVyeSBiZWdpbj8=", + "correct_answer": "MjM1IEFE", + "incorrect_answers": [ + "MjM1IEJD", + "MjQyIEFE", + "MjEwIEFE" + ] + }, + { + "type": "bXVsdGlwbGU=", + "difficulty": "bWVkaXVt", + "category": "RW50ZXJ0YWlubWVudDogVmlkZW8gR2FtZXM=", + "question": "V2hpY2ggb2YgdGhlc2UgQ291bnRlci1TdHJpa2UgbWFwcyBpcyBhIGJvbWIgZGVmdXNlIHNjZW5hcmlvPw==", + "correct_answer": "UHJvZGlneQ==", + "incorrect_answers": [ + "NzQ3", + "SGF2YW5h", + "T2lscmln" + ] + }, + { + "type": "bXVsdGlwbGU=", "difficulty": "bWVkaXVt", - "category": "RW50ZXJ0YWlubWVudDogSmFwYW5lc2UgQW5pbWUgJiBNYW5nYQ==", - "question": "VGhlIGFuaW1hdGVkIGZpbG0gIlNwaXJpdGVkIEF3YXkiIHdvbiB0aGUgQWNhZGVteSBBd2FyZCBmb3IgQmVzdCBBbmltYXRlZCBGZWF0dXJlIGF0IHRoZSA3NXRoIEFjYWRlbXkgQXdhcmRzIGluIDIwMDMu", - "correct_answer": "VHJ1ZQ==", + "category": "RW50ZXJ0YWlubWVudDogVmlkZW8gR2FtZXM=", + "question": "V2hhdCBpcyB0aGUgd29ybGQncyBmaXJzdCB2aWRlbyBnYW1lIGNvbnNvbGU/", + "correct_answer": "TWFnbmF2b3ggT2R5c3NleQ==", "incorrect_answers": [ - "RmFsc2U=" + "Q29sZWNvIFRlbHN0YXI=", + "TmludGVuZG8gQ29sb3IgVFYgR2FtZQ==", + "QXRhcmkgMjYwMA==" ] } ] @@ -70,6 +137,71 @@ ], "category": "Code", "difficulty": "Easy" + }, + { + "id": 1, + "question": "How to delete a directory in Linux?", + "description": "delete folder", + "answers": { + "answer_a": "ls", + "answer_b": "delete", + "answer_c": "remove", + "answer_d": "rmdir", + "answer_e": null, + "answer_f": null + }, + "multiple_correct_answers": "false", + "correct_answers": { + "answer_a_correct": "false", + "answer_b_correct": "false", + "answer_c_correct": "false", + "answer_d_correct": "true", + "answer_e_correct": "false", + "answer_f_correct": "false" + }, + "explanation": "rmdir deletes an empty directory", + "tip": null, + "tags": [], + "category": "linux", + "difficulty": "Easy" + }, + { + "id": 3, + "question": "How to check the current disk usage on Linux?", + "description": "check current disk usage", + "answers": { + "answer_a": "df", + "answer_b": "usage", + "answer_c": "uptime", + "answer_d": "free", + "answer_e": null, + "answer_f": null + }, + "multiple_correct_answers": "false", + "correct_answers": { + "answer_a_correct": "true", + "answer_b_correct": "false", + "answer_c_correct": "false", + "answer_d_correct": "false", + "answer_e_correct": "false", + "answer_f_correct": "false" + }, + "correct_answer": "answer_a", + "explanation": "df shows you the current disk usage", + "tip": "df", + "tags": [ + { + "name": "Linux" + }, + { + "name": "BASH" + }, + { + "name": "cmd" + } + ], + "category": "uncategorized", + "difficulty": "easy" } ] } diff --git a/package.json b/package.json index 0eed12e..4237d7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xpquiz.github.io", - "version": "1.4.1", + "version": "1.5.0", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 4a8fb88..8b9711c 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -7,6 +7,8 @@ import {PathsEnum} from "../model/enums/PathsEnum"; import {CorrectAnswerWindowComponent} from "./correct-answer-window/correct-answer-window.component"; import {WrongAnswerWindowComponent} from "./wrong-answer-window/wrong-answer-window.component"; import {AboutWindowComponent} from "./about-window/about-window.component"; +import {GameModeWindowComponent} from "./game-mode-window/game-mode-window.component"; +import {QuestionTrifectaWindowComponent} from "./question-trifecta-window/question-trifecta-window.component"; const routes: Routes = [ { @@ -27,9 +29,17 @@ const routes: Routes = [ component: ScoreWindowComponent }, { - path: PathsEnum.QUIZ, + path: PathsEnum.GAME_MODE, + component: GameModeWindowComponent, + }, + { + path: `${PathsEnum.QUIZ_NORMAL}`, component: QuestionWindowComponent, }, + { + path: `${PathsEnum.QUIZ_TRIFECTA}`, + component: QuestionTrifectaWindowComponent, + }, { path: `${PathsEnum.CORRECT_ANSWER}/:result`, component: CorrectAnswerWindowComponent, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 220cfc0..b46d839 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -14,6 +14,9 @@ import { CorrectAnswerWindowComponent } from './correct-answer-window/correct-an import { WrongAnswerWindowComponent } from './wrong-answer-window/wrong-answer-window.component'; import { AboutWindowComponent } from './about-window/about-window.component'; import {CopyClipboardDirective} from "./directives/CopyClipboardDirective"; +import { GameModeWindowComponent } from './game-mode-window/game-mode-window.component'; +import { IconTextButtonComponent } from './common/icon-text-button/icon-text-button.component'; +import { QuestionTrifectaWindowComponent } from './question-trifecta-window/question-trifecta-window.component'; @NgModule({ declarations: [ @@ -26,7 +29,10 @@ import {CopyClipboardDirective} from "./directives/CopyClipboardDirective"; CorrectAnswerWindowComponent, WrongAnswerWindowComponent, AboutWindowComponent, - CopyClipboardDirective + CopyClipboardDirective, + GameModeWindowComponent, + IconTextButtonComponent, + QuestionTrifectaWindowComponent ], imports: [ BrowserModule, diff --git a/src/app/common/icon-text-button/icon-text-button.component.html b/src/app/common/icon-text-button/icon-text-button.component.html new file mode 100644 index 0000000..b288d0c --- /dev/null +++ b/src/app/common/icon-text-button/icon-text-button.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/common/icon-text-button/icon-text-button.component.sass b/src/app/common/icon-text-button/icon-text-button.component.sass new file mode 100644 index 0000000..7e310a9 --- /dev/null +++ b/src/app/common/icon-text-button/icon-text-button.component.sass @@ -0,0 +1,13 @@ +button + display: flex + flex-direction: column + align-items: center + justify-content: center + min-height: 100px + width: 170px + + img + margin: 5px + + label + font-weight: bold diff --git a/src/app/common/icon-text-button/icon-text-button.component.spec.ts b/src/app/common/icon-text-button/icon-text-button.component.spec.ts new file mode 100644 index 0000000..753ad7b --- /dev/null +++ b/src/app/common/icon-text-button/icon-text-button.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { IconTextButtonComponent } from './icon-text-button.component'; + +describe('IconTextButtonComponent', () => { + let component: IconTextButtonComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [IconTextButtonComponent] + }); + fixture = TestBed.createComponent(IconTextButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/common/icon-text-button/icon-text-button.component.ts b/src/app/common/icon-text-button/icon-text-button.component.ts new file mode 100644 index 0000000..71e45dc --- /dev/null +++ b/src/app/common/icon-text-button/icon-text-button.component.ts @@ -0,0 +1,25 @@ +import {Component, EventEmitter, Input, Output} from '@angular/core'; + +@Component({ + selector: 'app-icon-text-button', + templateUrl: './icon-text-button.component.html', + styleUrls: ['./icon-text-button.component.sass'] +}) +export class IconTextButtonComponent { + + @Input() + public iconPath: string = ''; + @Input() + public title: string = ''; + @Input() + public description: string = ''; + @Output() + public onButtonClick: EventEmitter = new EventEmitter(); + + public readonly iconSize: number = 30; + + public onClick(): void { + this.onButtonClick.emit(); + } + +} diff --git a/src/app/game-mode-window/game-mode-window.component.html b/src/app/game-mode-window/game-mode-window.component.html new file mode 100644 index 0000000..9cec22d --- /dev/null +++ b/src/app/game-mode-window/game-mode-window.component.html @@ -0,0 +1,20 @@ +
+ +
+ + +
+ + + +
+ + +
+
diff --git a/src/app/game-mode-window/game-mode-window.component.sass b/src/app/game-mode-window/game-mode-window.component.sass new file mode 100644 index 0000000..fa65a9d --- /dev/null +++ b/src/app/game-mode-window/game-mode-window.component.sass @@ -0,0 +1,17 @@ +.window-body + display: flex + flex-direction: column + align-items: center + justify-content: center + + &_modes + display: inherit + flex-direction: row + align-items: center + justify-content: center + + app-icon-text-button + margin: 5px + + app-icon-button + margin: 5px diff --git a/src/app/game-mode-window/game-mode-window.component.spec.ts b/src/app/game-mode-window/game-mode-window.component.spec.ts new file mode 100644 index 0000000..091c4c3 --- /dev/null +++ b/src/app/game-mode-window/game-mode-window.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GameModeWindowComponent } from './game-mode-window.component'; + +describe('GameModeWindowComponent', () => { + let component: GameModeWindowComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [GameModeWindowComponent] + }); + fixture = TestBed.createComponent(GameModeWindowComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/game-mode-window/game-mode-window.component.ts b/src/app/game-mode-window/game-mode-window.component.ts new file mode 100644 index 0000000..14607d9 --- /dev/null +++ b/src/app/game-mode-window/game-mode-window.component.ts @@ -0,0 +1,25 @@ +import {Component} from '@angular/core'; +import {Router} from "@angular/router"; +import {PathsEnum} from "../../model/enums/PathsEnum"; +import {GameMode} from "../../model/enums/GameModesEnum"; + +@Component({ + selector: 'app-game-mode-window', + templateUrl: './game-mode-window.component.html', + styleUrls: ['./game-mode-window.component.sass'] +}) +export class GameModeWindowComponent { + + protected readonly PathsEnum = PathsEnum; + + protected readonly gameModes: GameMode[] = [ + GameMode.NORMAL, + GameMode.TRIFECTA + ]; + + constructor( + protected readonly router: Router + ) { + } + +} diff --git a/src/app/main-window/main-window.component.html b/src/app/main-window/main-window.component.html index 0dcd1a5..8932e2a 100644 --- a/src/app/main-window/main-window.component.html +++ b/src/app/main-window/main-window.component.html @@ -12,7 +12,7 @@
diff --git a/src/app/question-trifecta-window/question-trifecta-window.component.html b/src/app/question-trifecta-window/question-trifecta-window.component.html new file mode 100644 index 0000000..2687f51 --- /dev/null +++ b/src/app/question-trifecta-window/question-trifecta-window.component.html @@ -0,0 +1,84 @@ +
+
+ +
+ +
+ +
+
+ + +
+
+ +
+ + + +
+ +
    +
    + + +
    + + + +
    +
    +
+
+
+ + +
+
+
+ +
+ +
+
+ + + +
+
+ + +
+ + +
+ + + + +
+
+
+
diff --git a/src/app/question-trifecta-window/question-trifecta-window.component.sass b/src/app/question-trifecta-window/question-trifecta-window.component.sass new file mode 100644 index 0000000..a369a02 --- /dev/null +++ b/src/app/question-trifecta-window/question-trifecta-window.component.sass @@ -0,0 +1,126 @@ +.host + display: flex + flex-direction: column + align-items: center + justify-content: center + + .window + margin: 10px + + &_question + &_body + display: flex + flex-direction: column + align-items: center + justify-content: center + + &_questions + display: flex + flex-direction: column + align-items: center + justify-content: center + margin: 5px + + &_total-points + font-weight: bold + + &_sum-points + font-style: italic + + &_tri + display: flex + align-items: stretch + justify-content: center + + @media(200px < width < 1000px) + flex-direction: column + + @media(width > 1000px) + flex-direction: row + + ul + margin: 5px + + &_hint + font-style: italic + + &_loading + display: flex + flex-direction: column + align-items: center + justify-content: center + + &_title + margin: 5px + text-align: center + + &_progress + margin: 5px + + &_image + width: 30% + display: flex + align-items: initial + justify-content: center + + &_loaded + display: flex + flex-direction: column + align-items: center + justify-content: center + + &_title + text-align: center + margin: 15px + font-weight: bold + max-width: 250px + + &_points + font-style: italic + margin: 0px 5px 5px 5px + + &_list + display: flex + flex-direction: column + align-items: center + justify-content: center + width: 100% + + &_option-button + margin: 3px + width: 100% + + &_bold + font-weight: bold + + + &_check-answer + &_body + display: flex + flex-direction: row + align-items: center + justify-content: center + + &_image + width: 30% + display: flex + align-items: initial + justify-content: center + + &_question + display: flex + flex-direction: column + align-items: center + justify-content: center + + &_title + margin: 5px + + &_buttons + display: flex + flex-direction: row + align-items: center + justify-content: center + + app-icon-button + margin: 3px diff --git a/src/app/question-trifecta-window/question-trifecta-window.component.spec.ts b/src/app/question-trifecta-window/question-trifecta-window.component.spec.ts new file mode 100644 index 0000000..d4c9f94 --- /dev/null +++ b/src/app/question-trifecta-window/question-trifecta-window.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { QuestionTrifectaWindowComponent } from './question-trifecta-window.component'; + +describe('QuestionTrifectaWindowComponent', () => { + let component: QuestionTrifectaWindowComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [QuestionTrifectaWindowComponent] + }); + fixture = TestBed.createComponent(QuestionTrifectaWindowComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/question-trifecta-window/question-trifecta-window.component.ts b/src/app/question-trifecta-window/question-trifecta-window.component.ts new file mode 100644 index 0000000..6f82564 --- /dev/null +++ b/src/app/question-trifecta-window/question-trifecta-window.component.ts @@ -0,0 +1,129 @@ +import {Component} from '@angular/core'; +import {Question} from "../../model/questions/Question"; +import {TriviaService} from "../../service/trivia.service"; +import {Router} from "@angular/router"; +import {EncryptionService} from "../../service/encryption.service"; +import {AppStorageService} from "../../service/app-storage.service"; +import {PathsEnum} from "../../model/enums/PathsEnum"; +import {first} from "rxjs"; + +@Component({ + selector: 'app-question-trifecta-window', + templateUrl: './question-trifecta-window.component.html', + styleUrls: ['./question-trifecta-window.component.sass'] +}) +export class QuestionTrifectaWindowComponent { + + public questions: Question[] = []; + public selectedAnswers: string[] | undefined[] = []; + public showQuestions: boolean = false; + public confirmedAnswers: boolean = false; + + private questionLoaded: boolean = false; + private questionAmount: number = 3; + + public loadingProgressBar: number = 0; + public answerProgressBar: number = 0; + public progressBarMax: number = 100; + + private questionReadySound: HTMLAudioElement = new Audio('assets/sounds/logon.wav'); + private confirmAnswerSound: HTMLAudioElement = new Audio('assets/sounds/exclamation.wav'); + + constructor( + private readonly triviaService: TriviaService, + private readonly router: Router, + private readonly encryptionService: EncryptionService, + private readonly appStorageService: AppStorageService + ) { + } + + public async ngOnInit(): Promise { + if (!this.appStorageService.canQuizBeAnswered()) { + await this.router.navigateByUrl(PathsEnum.HOME); + return; + } + + this.startLoadingProgressBar(); + await this.loadQuestions(); + } + + private async loadQuestions(): Promise { + this.questions = await this.triviaService.fetchQuestion(this.questionAmount); + this.questionLoaded = true; + } + + private async startLoadingProgressBar(): Promise { + let revertProgressBar: boolean = false; + + while (true) { + if (this.loadingProgressBar === 100) { + revertProgressBar = true; + + if (this.questionLoaded) { + this.showQuestions = true; + await this.questionReadySound.play(); + break; + } + } else if (this.loadingProgressBar === 0) { + revertProgressBar = false; + } + + this.loadingProgressBar += revertProgressBar ? -10 : 10; + + await new Promise(f => setTimeout(f, 300)); + } + } + + public async onClickAnswer(index: number, answer: string): Promise { + if (this.selectedAnswers[index] !== undefined) + this.selectedAnswers[index] = undefined; + else + this.selectedAnswers[index] = answer; + + if (this.selectedAllAnswers()) + await this.confirmAnswerSound.play(); + } + + public shouldDisableAnswer(index: number, answer: string): boolean { + const selectedAnswer = this.selectedAnswers[index]; + + return (selectedAnswer !== undefined && selectedAnswer !== answer) || this.confirmedAnswers; + } + + public getTotalPointsLabel(): string { + return `This trifecta is worth ${(this.questions[0].points + this.questions[1].points + this.questions[2].points) * 3} points!`; + } + + public getSumPointsLabel(): string { + const firstQuestionPoints: number = this.questions[0].points; + const secondQuestionPoints: number = this.questions[1].points; + const thirdQuestionPoints: number = this.questions[2].points; + const totalPoints: number = firstQuestionPoints + secondQuestionPoints + thirdQuestionPoints; + + return `(${firstQuestionPoints} + ${secondQuestionPoints} + ${thirdQuestionPoints}) = ${totalPoints} * 3 = ${totalPoints * 3}`; + } + + public getAnswerLabel(index: number, answer: string): string { + return this.selectedAnswers[index] === answer ? `> ${answer} <` : answer; + } + + confirmAnswers() { + + } + + public validateAnswers(): void { + this.selectedAnswers = []; + } + + public isSelectingAnswers(): boolean { + return this.selectedAnswers[0] === undefined || + this.selectedAnswers[1] === undefined || + this.selectedAnswers[2] === undefined; + } + + public selectedAllAnswers(): boolean { + return this.selectedAnswers[0] !== undefined && + this.selectedAnswers[1] !== undefined && + this.selectedAnswers[2] !== undefined; + } +} diff --git a/src/app/question-window/question-window.component.html b/src/app/question-window/question-window.component.html index 04fe100..c8cb0f3 100644 --- a/src/app/question-window/question-window.component.html +++ b/src/app/question-window/question-window.component.html @@ -15,10 +15,10 @@
- - + +
- + diff --git a/src/app/question-window/question-window.component.ts b/src/app/question-window/question-window.component.ts index 35cdd59..86d7151 100644 --- a/src/app/question-window/question-window.component.ts +++ b/src/app/question-window/question-window.component.ts @@ -15,20 +15,19 @@ import {Question} from "../../model/questions/Question"; }) export class QuestionWindowComponent implements OnInit, OnDestroy { - public questionLoaded: boolean = false; + public question: Question | undefined; + + private questionLoaded: boolean = false; public showQuestion: boolean = false; - public question: string = ''; - public questionPoints: number = 0; - public answers: string[] = []; public selectedAnswer: string = ''; public confirmedAnswer: boolean = false; + public progressBarMax: number = 100; public answerProgressBar: number = 0; public loadingProgressBar: number = 0; private questionReadySound: HTMLAudioElement = new Audio('assets/sounds/logon.wav'); private confirmAnswerSound: HTMLAudioElement = new Audio('assets/sounds/exclamation.wav'); - private correctAnswer: string = ''; private getQuizzesSubscription: Subscription | undefined; constructor( @@ -41,7 +40,7 @@ export class QuestionWindowComponent implements OnInit, OnDestroy { public async ngOnInit(): Promise { if (!this.appStorageService.canQuizBeAnswered()) { - await this.returnHome(); + await this.router.navigateByUrl(PathsEnum.HOME); return; } @@ -65,17 +64,8 @@ export class QuestionWindowComponent implements OnInit, OnDestroy { } private async loadQuestion(): Promise { - const questions: Question[] = await this.triviaService.fetchQuestion(); - const singleQuestion: Question = questions[0]; - - this.question = singleQuestion.question; - this.correctAnswer = singleQuestion.correctAnswer; - this.answers = [singleQuestion.correctAnswer, ...singleQuestion.incorrectAnswers] - .map((value) => ({value, sort: Math.random()})) - .sort((a, b) => a.sort - b.sort) - .map(({value}) => value); - - this.questionPoints = this.sumQuestionPoints(singleQuestion.difficulty, singleQuestion.isNiche); + const questions: Question[] = await this.triviaService.fetchQuestion(1); + this.question = questions[0]; this.questionLoaded = true; } @@ -99,32 +89,19 @@ export class QuestionWindowComponent implements OnInit, OnDestroy { } private async redirectFromAnswer(): Promise { - const correctAnswer: boolean = this.selectedAnswer === this.correctAnswer; + const correctAnswer: boolean = this.selectedAnswer === this.question!.correctAnswer; const questionResult: QuestionResultTemplateParams = { - question: this.question, - questionPoints: correctAnswer ? this.questionPoints : null, + question: this.question!.question, + questionPoints: correctAnswer ? this.question!.points : null, selectedAnswer: `${correctAnswer ? '🟩' : '🟥'} ${this.selectedAnswer}`, - rightAnswer: this.correctAnswer, - wrongAnswers: this.answers.filter(value => value !== this.correctAnswer) + rightAnswer: this.question!.correctAnswer, + wrongAnswers: this.question!.answers.filter(value => value !== this.question!.correctAnswer) }; const questionResultData: string = this.encryptionService.encrypt(JSON.stringify(questionResult)); await this.router.navigate([correctAnswer ? PathsEnum.CORRECT_ANSWER : PathsEnum.WRONG_ANSWER, questionResultData]); } - private sumQuestionPoints(questionDifficulty: string, isNiche: boolean): number { - const difficultyPointsMap: Map = new Map([ - ['easy', 1], - ['medium', 3], - ['hard', 5] - ]); - - const questionPoints: number = difficultyPointsMap.get(questionDifficulty)!; - const nichePoints: number = isNiche ? 10 : 0; - - return questionPoints + nichePoints; - } - private async startLoadingProgressBar(): Promise { let revertProgressBar: boolean = false; @@ -146,8 +123,4 @@ export class QuestionWindowComponent implements OnInit, OnDestroy { await new Promise(f => setTimeout(f, 300)); } } - - private async returnHome() { - await this.router.navigateByUrl(PathsEnum.HOME); - } } diff --git a/src/assets/icons/30x30/normal.png b/src/assets/icons/30x30/normal.png new file mode 100644 index 0000000000000000000000000000000000000000..88c28b2d7e7174d55ccca55c11f6fee4ca3476a2 GIT binary patch literal 7238 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 literal 0 HcmV?d00001 diff --git a/src/assets/icons/trifecta.png b/src/assets/icons/trifecta.png new file mode 100644 index 0000000000000000000000000000000000000000..b9173b233bce03e98cc0f33ece0bf69e0159faca GIT binary patch literal 8800 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

&U~E@u#&=J>`!yZ7X*#tWbVRN`|edgsX@3^SAa> zn&#D3;=Q%Tx|`o$$tlE|%~Qoaymr`Al@WWh(W>GiGV2;AF)!pB;sy7yVG7Eu45}-R zJ0;Uy)%M2yGAp?zrYWY9x@Xqva55}rzZ{;=qw#8*VVo}v23Wa z`}S+7e)rx+XtO~(`7nIQ1oK9&4z|1dPU;-)cOIT?B)#tgTT1djA{N+hX!>E}^3n{< z6O7$@O$T&P;DIYjapCp54OK<826smy$qS8C#z%X zXP=0y_G~yidTMq9ZUOr4*`+~TkMbuYNqhIEtZ%R^w8NU%82@nWZE;R-?}Ml<`F;a; zL->@P!)Y$!Z`wQ-dC=UJ)o34YOCQGVRg~drprFr;VI>yE{H(f=gcs*x9@NKo+RoV= z>b3cl>e78xaW*#zZEuSGu8!2bK7B2I;DKS<62Be11ly$@`an-2&bBxt>y5=PtgMH6 z-A9rm{kl%bG7x@9!-~!w+ilDod~n6VEib*UdQkLmTI-5~vlp#?op^a9ZR52ztJ7QF zVfkwtzu&=e#GK#noJmMhq;|~qxpg3jv*BR2W8j^}!H5G*XR-sJuQVSJU(fyNaY5_8 z9}gLNBnCHm+$eX$?+(~twyoysW1Y$*wTE5xORc_>&y;bC&`^mg?mCdg(;x@99}lb1 zern-F4svf@OACxlzm@N?KO%I?WaN{9O{L+w&iXl3`HU(}jCRJmpAX`+539P^b;mx} zJz7z8Km1#Eb#IqmQeo_#;8~H6`OE35#lg?p1D(rs`_4~vMdwcBz|HL?T5a~j@RBE zchJ#{LhAUCv}?307ZsVpP!Pi!`!2qs#b4jOBjL8)ntKz+96G-V>R#qMzZ{m&$qbpR zLNV;RAW~nLva6Mw#ZV}ZZDmjN#`SJ3|LCBeilMgmEGJVoh-TR8F zWjlk5?_hC&>=E{Dm`S0ZRuZ$pb?E1#WjABu--K%zIg?b?D4_yB|RWX70{cI~y-GJxu(0$sLtQSZz?= z{+>R$uD5-LXg!0{w1CxPTA>3@C(fbS%?nKGsASz!QRI}^4*d}`rm268!}#XIf-Z7* zk#>7DIhJFcE9!XUT&MGL#h&UCmfWQs7d5setJ(EV!I=T^N=&KBt~-rq)8F1MW-@%L zW;4FEh!|bi@UB=pT2NhA^nwlV|K?^Uv0|Z?$*l4t-Ky`6LOe@e8hCJLm)}wDN$|;2 zz7kCDTpyS56t3b

EC64DfixoO@5{}0%c6(Xo6uUDlmdwfy;-%ZTx+eX+$)dof;{~0zb$;51J)Gi^ zjCxkM@H)4@rH8u^zmc``P)YJ;JC0`T^P5BE^@YMn!?wW>r)-CGf{=!nBZ-J9;HFU93=raV~PfMfJ#O$MoQkMs%Mo94w+)##`Gwb#p#CQs?%|fSM<1 z@}6?XTp#CvF8=!d(!GV(l1sOg-h7kL)I9vYDY|xv(dcl3#$;|olZ|n8&MNDsHWM_@ z(YiLutoP|U^`Ct!3m;mqjJf2s;rlDEtE(c8Rc(7~Dz1_9QW((BGkE7ErWGMx1cpC2 zBkbOQI)S&&YHI!=`sxqDberhVof+9}Wp0=cH_dw;K;R#4>9%?S(?aGa2p+{6G_#HrAT|Ob;+-z1v?a1~~Z4*QFAeJ5PR?n(E!+~1u zolYgqr<686+bnz+S@JZR7@v8iVRQ#EwJ3Z~Z8<%! = new Map([ + ['easy', 1], + ['medium', 3], + ['hard', 5] + ]); + private readonly questionMethods: Function[] = [ this.getQuestionsTheTriviaApi, this.getQuestionsOpenTriviaDB, @@ -28,13 +34,13 @@ export class TriviaService { ) { } - public async fetchQuestion(): Promise { - while(true) { + public async fetchQuestion(questionNumber: number): Promise { + while (true) { const randomNumber: number = this.randomIntFromInterval(0, this.questionMethods.length - 1); const randomQuestionMethod: Function = this.questionMethods[randomNumber]; - const questions: Question[] = await randomQuestionMethod.call(this); + const questions: Question[] = await randomQuestionMethod.call(this, questionNumber); - if(questions.length !== 0) return questions; + if (questions.length !== 0) return questions; } } @@ -42,44 +48,58 @@ export class TriviaService { return Math.floor(Math.random() * (max - min + 1) + min) } - private async getQuestionsTheTriviaApi(): Promise { - const url: string = `${environment.theTriviaApiUrl}?limit=${this.questionLimit}`; - + private async getQuestionsTheTriviaApi(questionNumber: number): Promise { + const url: string = `${environment.theTriviaApiUrl}?limit=${questionNumber}`; const response: TheTriviaApiResponse[] = await firstValueFrom( this.httpClient.get(url) ); return response.map(res => { + const answers = [res.correctAnswer, ...res.incorrectAnswers] + .map((value) => ({value, sort: Math.random()})) + .sort((a, b) => a.sort - b.sort) + .map(({value}) => value); + return { question: res.question.text, + answers, correctAnswer: res.correctAnswer, - incorrectAnswers: res.incorrectAnswers, + points: this.difficultyPointsMap.get(res.difficulty)!, difficulty: res.difficulty, isNiche: res.isNiche, } }); } - private async getQuestionsOpenTriviaDB(): Promise { - const url: string = `${environment.openTriviaDBUrl}?amount=${this.questionLimit}&encode=base64`; + private async getQuestionsOpenTriviaDB(questionNumber: number): Promise { + const url: string = `${environment.openTriviaDBUrl}?amount=${questionNumber}&encode=base64`; const response: OpenTriviaDBResponse = await firstValueFrom( this.httpClient.get(url) ); return response.results.map(res => { + const correctAnswer: string = atob(res.correct_answer) + + const answers = [correctAnswer, ...res.incorrect_answers.map(r => atob(r))] + .map((value) => ({value, sort: Math.random()})) + .sort((a, b) => a.sort - b.sort) + .map(({value}) => value); + const difficulty: DifficultyType = atob(res.difficulty) as DifficultyType; + return { question: atob(res.question), - correctAnswer: atob(res.correct_answer), - incorrectAnswers: res.incorrect_answers.map(r => atob(r)), - difficulty: atob(res.difficulty) as 'easy' | 'medium' | 'hard', + correctAnswer, + answers, + points: this.difficultyPointsMap.get(difficulty)!, + difficulty, isNiche: false, } }); } - private async getQuestionsQuizAPI(): Promise { - const url: string = `${environment.quizAPIUrl}?limit=${this.questionLimit}`; + private async getQuestionsQuizAPI(questionNumber: number): Promise { + const url: string = `${environment.quizAPIUrl}?limit=${questionNumber}`; const response: QuizAPIResponse[] = await firstValueFrom( this.httpClient.get(url, { headers: {'X-Api-Key': environment.quizAPIKey} @@ -87,6 +107,7 @@ export class TriviaService { ); return response.map(res => { + const difficulty: DifficultyType = res.difficulty.toLowerCase() as DifficultyType; let incorrectAnswers: string[] = []; let correctAnswer: string | undefined = undefined; @@ -107,11 +128,17 @@ export class TriviaService { incorrectAnswers.push(answer); } + const answers = [correctAnswer!, ...incorrectAnswers] + .map((value) => ({value, sort: Math.random()})) + .sort((a, b) => a.sort - b.sort) + .map(({value}) => value); + return { question: res.question, correctAnswer: correctAnswer!, - incorrectAnswers: incorrectAnswers, - difficulty: res.difficulty.toLowerCase() as 'easy' | 'medium' | 'hard', + answers, + points: this.difficultyPointsMap.get(difficulty)!, + difficulty, isNiche: false } }); From 8be0b60cf044808297471cd9a66a8060a990ff46 Mon Sep 17 00:00:00 2001 From: Isahann Hanacleto Date: Fri, 23 Aug 2024 09:21:06 -0300 Subject: [PATCH 2/3] #64 checkpoint --- src/app/app-routing.module.ts | 4 +- .../correct-answer-window.component.html | 2 +- .../correct-answer-window.component.ts | 11 ++-- .../question-trifecta-window.component.html | 11 ++-- .../question-trifecta-window.component.sass | 2 +- .../question-trifecta-window.component.ts | 53 +++++++++++++++++-- .../question-window.component.ts | 3 +- .../wrong-answer-window.component.html | 5 +- .../wrong-answer-window.component.ts | 18 ++++--- .../question_result_trifecta.mustache | 19 +++++++ src/model/Template.ts | 22 +++++++- src/model/enums/GameModesEnum.ts | 9 ++-- src/service/app-storage.service.ts | 22 ++------ src/service/storage.service.ts | 1 - 14 files changed, 134 insertions(+), 48 deletions(-) create mode 100644 src/assets/templates/question_result_trifecta.mustache diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 8b9711c..0d41511 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -41,11 +41,11 @@ const routes: Routes = [ component: QuestionTrifectaWindowComponent, }, { - path: `${PathsEnum.CORRECT_ANSWER}/:result`, + path: `${PathsEnum.CORRECT_ANSWER}/:mode/:result`, component: CorrectAnswerWindowComponent, }, { - path: `${PathsEnum.WRONG_ANSWER}/:result`, + path: `${PathsEnum.WRONG_ANSWER}/:mode/:result`, component: WrongAnswerWindowComponent } ] diff --git a/src/app/correct-answer-window/correct-answer-window.component.html b/src/app/correct-answer-window/correct-answer-window.component.html index c2826ee..9ae8083 100644 --- a/src/app/correct-answer-window/correct-answer-window.component.html +++ b/src/app/correct-answer-window/correct-answer-window.component.html @@ -3,7 +3,7 @@
- +
diff --git a/src/app/correct-answer-window/correct-answer-window.component.ts b/src/app/correct-answer-window/correct-answer-window.component.ts index c0bfdbf..6693fb3 100644 --- a/src/app/correct-answer-window/correct-answer-window.component.ts +++ b/src/app/correct-answer-window/correct-answer-window.component.ts @@ -4,7 +4,8 @@ import {PathsEnum} from "../../model/enums/PathsEnum"; import {AppStorageService} from "../../service/app-storage.service"; import {EncryptionService} from "../../service/encryption.service"; import {TemplateService} from "../../service/template.service"; -import {QuestionResultTemplateParams, TemplateEnum} from "../../model/Template"; +import {QuestionResultTemplateParams, QuestionResultTrifectaTemplateParams} from "../../model/Template"; +import {GameMode} from "../../model/enums/GameModesEnum"; @Component({ selector: 'app-correct-answer-window', @@ -53,15 +54,17 @@ export class CorrectAnswerWindowComponent implements OnInit { } private saveCurrentScore(): void { - this.appStorageService.saveAnswer(true, this.questionScore); + this.appStorageService.saveAnswer(true, this.questionScore, 3); } private async retrieveRouteParams(): Promise { + const routeGameModeTitle: string = this.route.snapshot.paramMap.get('mode')!; const encryptedQuestionResult: string = this.route.snapshot.paramMap.get('result')!; const decryptedQuestionResult: string = this.encryptionService.decrypt(encryptedQuestionResult); - const questionResult: QuestionResultTemplateParams = JSON.parse(decryptedQuestionResult); - const questionResultText: string = await this.templateService.render(TemplateEnum.QUESTION_RESULT, questionResult); + const questionResult: QuestionResultTemplateParams | QuestionResultTrifectaTemplateParams = JSON.parse(decryptedQuestionResult); + const mode: GameMode = GameMode.getByTitle(routeGameModeTitle); + const questionResultText: string = await this.templateService.render(mode.templateEnum, questionResult); this.questionScore = questionResult.questionPoints!; this.clipboardText = questionResultText; diff --git a/src/app/question-trifecta-window/question-trifecta-window.component.html b/src/app/question-trifecta-window/question-trifecta-window.component.html index 2687f51..c87a810 100644 --- a/src/app/question-trifecta-window/question-trifecta-window.component.html +++ b/src/app/question-trifecta-window/question-trifecta-window.component.html @@ -53,10 +53,10 @@ - -
@@ -64,17 +64,18 @@ -