diff --git a/package-lock.json b/package-lock.json index b61e99ad..982312a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "bootstrap": "^5.3.0", "echarts": "^5.4.1", "echarts-wordcloud": "^2.0.0", + "howler": "^2.2.4", "html2canvas": "^1.4.1", "jspdf": "^2.5.1", "katex": "^0.16.0", @@ -48,6 +49,7 @@ "@angular/cli": "^16.1.4", "@angular/compiler-cli": "^16.1.4", "@types/echarts": "^4.9.16", + "@types/howler": "^2.2.11", "@types/jasmine": "^4.3.0", "@types/marked": "^4.0.8", "@types/node": "^18.14.0", @@ -4408,6 +4410,12 @@ "@types/send": "*" } }, + "node_modules/@types/howler": { + "version": "2.2.11", + "resolved": "https://registry.npmmirror.com/@types/howler/-/howler-2.2.11.tgz", + "integrity": "sha512-7aBoUL6RbSIrqKnpEgfa1wSNUBK06mn08siP2QI0zYk7MXfEJAaORc4tohamQYqCqVESoDyRWSdQn2BOKWj2Qw==", + "dev": true + }, "node_modules/@types/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.1.tgz", @@ -8973,6 +8981,11 @@ "node": ">=12" } }, + "node_modules/howler": { + "version": "2.2.4", + "resolved": "https://registry.npmmirror.com/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==" + }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmmirror.com/hpack.js/-/hpack.js-2.1.6.tgz", @@ -18477,6 +18490,12 @@ "@types/send": "*" } }, + "@types/howler": { + "version": "2.2.11", + "resolved": "https://registry.npmmirror.com/@types/howler/-/howler-2.2.11.tgz", + "integrity": "sha512-7aBoUL6RbSIrqKnpEgfa1wSNUBK06mn08siP2QI0zYk7MXfEJAaORc4tohamQYqCqVESoDyRWSdQn2BOKWj2Qw==", + "dev": true + }, "@types/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/@types/http-errors/-/http-errors-2.0.1.tgz", @@ -22244,6 +22263,11 @@ } } }, + "howler": { + "version": "2.2.4", + "resolved": "https://registry.npmmirror.com/howler/-/howler-2.2.4.tgz", + "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==" + }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmmirror.com/hpack.js/-/hpack.js-2.1.6.tgz", diff --git a/package.json b/package.json index b9671234..7a7387e3 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "bootstrap": "^5.3.0", "echarts": "^5.4.1", "echarts-wordcloud": "^2.0.0", + "howler": "^2.2.4", "html2canvas": "^1.4.1", "jspdf": "^2.5.1", "katex": "^0.16.0", @@ -66,6 +67,7 @@ "@angular/cli": "^16.1.4", "@angular/compiler-cli": "^16.1.4", "@types/echarts": "^4.9.16", + "@types/howler": "^2.2.11", "@types/jasmine": "^4.3.0", "@types/marked": "^4.0.8", "@types/node": "^18.14.0", diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 66d2a4f6..5d68bbed 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -15,7 +15,7 @@ import { NgxEchartsModule } from 'ngx-echarts'; import * as echarts from 'echarts'; import { NuMonacoEditorModule } from '@ng-util/monaco-editor'; -import { ODataService, QuizService, UIUtilityService, AuthGuardService, EnglishLearningService } from './services'; +import { ODataService, QuizService, UIUtilityService, AuthGuardService, EnglishLearningService, AudioService } from './services'; import { environment } from 'src/environments/environment'; import { NavItemFilterPipe } from './pipes'; import { QuizFailureDailogComponent } from './pages/quiz-failure-dailog'; @@ -59,6 +59,7 @@ import { AuthConfigModule } from './auth/auth-config.module'; UIUtilityService, QuizService, EnglishLearningService, + AudioService, AuthGuardService, { provide: TRANSLOCO_CONFIG, diff --git a/src/app/pages/puzzle-game/typing-game/typing-game.component.html b/src/app/pages/puzzle-game/typing-game/typing-game.component.html index 2db72f40..4e75afec 100644 --- a/src/app/pages/puzzle-game/typing-game/typing-game.component.html +++ b/src/app/pages/puzzle-game/typing-game/typing-game.component.html @@ -1,3 +1,5 @@ -
- +
+ + {{echar.visible ? echar.letter : '_'}} +
diff --git a/src/app/pages/puzzle-game/typing-game/typing-game.component.scss b/src/app/pages/puzzle-game/typing-game/typing-game.component.scss index e69de29b..d1b0a722 100644 --- a/src/app/pages/puzzle-game/typing-game/typing-game.component.scss +++ b/src/app/pages/puzzle-game/typing-game/typing-game.component.scss @@ -0,0 +1,7 @@ +.typing-container { + font-size: 72px; + display: flex; + justify-content: center; + height: 250px; + align-items: center; +} diff --git a/src/app/pages/puzzle-game/typing-game/typing-game.component.ts b/src/app/pages/puzzle-game/typing-game/typing-game.component.ts index c08cfd1b..15409817 100644 --- a/src/app/pages/puzzle-game/typing-game/typing-game.component.ts +++ b/src/app/pages/puzzle-game/typing-game/typing-game.component.ts @@ -8,27 +8,82 @@ import { Output, ViewChild, } from '@angular/core'; +import { AudioService } from 'src/app/services'; export interface typingCompare { expected: string; inputted: string; } +interface typingWord { + visible: boolean; + letter: string; +} + @Component({ selector: 'khb-typing-game', templateUrl: './typing-game.component.html', styleUrls: ['./typing-game.component.scss'], }) export class TypingGameComponent implements OnInit, AfterViewInit { - // @ViewChild('type-game-canvas', { static: true }) canvasTypeGame!: ElementRef; + srcstring = 'fighter'; + private _arwords: typingWord[] = []; + private _keyidx = -1; + + get chararray(): typingWord[] { + return this._arwords; + } - constructor() { + @HostListener('document:keyup', ['$event']) + handleKeyboardEvent(event: KeyboardEvent) { + // if (event.key == 'Tab' && this.lastField == 'subject') { + // var el: any = document.querySelectorAll('.ql-editor') + + // if (el && el.length == 1) { + // el[0].focus(); + // this.lastField = 'body'; + // } + // } + console.log(event.key); + if (this._keyidx >= 0 && this._keyidx < this._arwords.length) { + if (event.key === 'Backspace') { + this._keyidx--; + if (this._keyidx >= 0) { + this._arwords[this._keyidx].visible = false; + } else { + this._keyidx = 0; + } + } else { + if (event.key === this._arwords[this._keyidx].letter) { + this._arwords[this._keyidx].visible = true; + this._keyidx++; + } else { + // Sending the error indicator. + this.audiosrv.playSound('beep.wav'); + } + } + } + } + + constructor(private audiosrv: AudioService) { + // Constructor } ngOnInit(): void { + // On Init. + const archars = this.srcstring.split(''); + archars.forEach((val) => { + this._arwords.push({ + visible: false, + letter: val, + }); + }); } ngAfterViewInit(): void { + // After view init. + if (this._arwords.length > 0) { + this._keyidx = 0; + } } - } diff --git a/src/app/services/audio-service.spec.ts b/src/app/services/audio-service.spec.ts new file mode 100644 index 00000000..85c3d9a4 --- /dev/null +++ b/src/app/services/audio-service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; +import { of } from 'rxjs'; + +import { AudioService } from './audio-service'; + +describe('AudioService', () => { + let service: AudioService; + + beforeEach(() => { + service = TestBed.inject(AudioService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/audio-service.ts b/src/app/services/audio-service.ts new file mode 100644 index 00000000..d1e42d94 --- /dev/null +++ b/src/app/services/audio-service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { Howl, Howler } from 'howler'; + +const TYPING_SOUND_URL = 'assets/typing/sounds/'; + +@Injectable({ + providedIn: 'root', +}) +export class AudioService { + playSound(filename: string): void { + const path = TYPING_SOUND_URL + filename; + const sound = new Howl({ + src: path, + format: ['wav'], + }); + Howler.volume(1); + sound.play(); + } +} diff --git a/src/app/services/index.ts b/src/app/services/index.ts index 1931b4cb..7df7656d 100644 --- a/src/app/services/index.ts +++ b/src/app/services/index.ts @@ -6,3 +6,4 @@ export * from './uiutility.service'; export * from './auth-guard.service'; export * from './auth.service'; export * from './english-learning.service'; +export * from './audio-service'; diff --git a/src/assets/typing/sounds/beep.wav b/src/assets/typing/sounds/beep.wav new file mode 100644 index 00000000..26df295f Binary files /dev/null and b/src/assets/typing/sounds/beep.wav differ diff --git a/src/assets/typing/sounds/click.wav b/src/assets/typing/sounds/click.wav new file mode 100644 index 00000000..0fc69c85 Binary files /dev/null and b/src/assets/typing/sounds/click.wav differ diff --git a/src/assets/typing/sounds/correct.wav b/src/assets/typing/sounds/correct.wav new file mode 100644 index 00000000..06806051 Binary files /dev/null and b/src/assets/typing/sounds/correct.wav differ diff --git a/src/assets/typing/sounds/key-sound/Alpacas.mp3 b/src/assets/typing/sounds/key-sound/Alpacas.mp3 new file mode 100644 index 00000000..22482a4e Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Alpacas.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Buckling Spring.mp3 b/src/assets/typing/sounds/key-sound/Buckling Spring.mp3 new file mode 100644 index 00000000..6a80d56a Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Buckling Spring.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Cherry MX Blacks.mp3 b/src/assets/typing/sounds/key-sound/Cherry MX Blacks.mp3 new file mode 100644 index 00000000..a3c64046 Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Cherry MX Blacks.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Cherry MX Blues.mp3 b/src/assets/typing/sounds/key-sound/Cherry MX Blues.mp3 new file mode 100644 index 00000000..edd0abbe Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Cherry MX Blues.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Cherry MX Browns.mp3 b/src/assets/typing/sounds/key-sound/Cherry MX Browns.mp3 new file mode 100644 index 00000000..4f8114fd Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Cherry MX Browns.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Default.wav b/src/assets/typing/sounds/key-sound/Default.wav new file mode 100644 index 00000000..0fc69c85 Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Default.wav differ diff --git a/src/assets/typing/sounds/key-sound/Gateron Black Inks.mp3 b/src/assets/typing/sounds/key-sound/Gateron Black Inks.mp3 new file mode 100644 index 00000000..663cb469 Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Gateron Black Inks.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Gateron Red Inks.mp3 b/src/assets/typing/sounds/key-sound/Gateron Red Inks.mp3 new file mode 100644 index 00000000..c802221c Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Gateron Red Inks.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Holy Pandas.mp3 b/src/assets/typing/sounds/key-sound/Holy Pandas.mp3 new file mode 100644 index 00000000..3897e0da Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Holy Pandas.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Kailh Box Navies.mp3 b/src/assets/typing/sounds/key-sound/Kailh Box Navies.mp3 new file mode 100644 index 00000000..26b7c0ef Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Kailh Box Navies.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/NovelKeys Creams.mp3 b/src/assets/typing/sounds/key-sound/NovelKeys Creams.mp3 new file mode 100644 index 00000000..4da558aa Binary files /dev/null and b/src/assets/typing/sounds/key-sound/NovelKeys Creams.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/SKCM Blue Alps.mp3 b/src/assets/typing/sounds/key-sound/SKCM Blue Alps.mp3 new file mode 100644 index 00000000..a85adb34 Binary files /dev/null and b/src/assets/typing/sounds/key-sound/SKCM Blue Alps.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Topre.mp3 b/src/assets/typing/sounds/key-sound/Topre.mp3 new file mode 100644 index 00000000..536b7a0f Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Topre.mp3 differ diff --git a/src/assets/typing/sounds/key-sound/Turquoise Tealios.mp3 b/src/assets/typing/sounds/key-sound/Turquoise Tealios.mp3 new file mode 100644 index 00000000..7df554bf Binary files /dev/null and b/src/assets/typing/sounds/key-sound/Turquoise Tealios.mp3 differ