@testgorilla/tgo-typing-test 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/.eslintrc.json +45 -0
  2. package/README.md +95 -0
  3. package/jest.config.ts +21 -0
  4. package/ng-package.json +15 -0
  5. package/package.json +20 -0
  6. package/project.json +36 -0
  7. package/src/assets/typing-test-languages/english.json +207 -0
  8. package/src/assets/typing-test-languages/english_punctuation.json +18 -0
  9. package/src/assets/typing-test-languages/quotes/english_version_1.json +35291 -0
  10. package/src/assets/typing-test-languages/quotes/english_version_2.json +720 -0
  11. package/src/assets/typing-test-languages/quotes/filtered_sources.json +79 -0
  12. package/src/index.ts +2 -0
  13. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +30 -0
  14. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +250 -0
  15. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +48 -0
  16. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +72 -0
  17. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +699 -0
  18. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +294 -0
  19. package/src/lib/helpers/config.ts +28 -0
  20. package/src/lib/helpers/constants/default-config.ts +103 -0
  21. package/src/lib/helpers/controllers/input-controller.ts +710 -0
  22. package/src/lib/helpers/controllers/quotes-controller.ts +183 -0
  23. package/src/lib/helpers/observables/banner-event.ts +18 -0
  24. package/src/lib/helpers/observables/config-event.ts +31 -0
  25. package/src/lib/helpers/observables/timer-event.ts +18 -0
  26. package/src/lib/helpers/states/active-page.ts +9 -0
  27. package/src/lib/helpers/states/composition.ts +29 -0
  28. package/src/lib/helpers/states/page-transition.ts +9 -0
  29. package/src/lib/helpers/states/slow-timer.ts +16 -0
  30. package/src/lib/helpers/states/test-active.ts +9 -0
  31. package/src/lib/helpers/states/time.ts +13 -0
  32. package/src/lib/helpers/test/caps-warning.ts +50 -0
  33. package/src/lib/helpers/test/caret.ts +92 -0
  34. package/src/lib/helpers/test/custom-text.ts +73 -0
  35. package/src/lib/helpers/test/english-punctuation.ts +38 -0
  36. package/src/lib/helpers/test/focus.ts +39 -0
  37. package/src/lib/helpers/test/manual-restart-tracker.ts +13 -0
  38. package/src/lib/helpers/test/out-of-focus.ts +19 -0
  39. package/src/lib/helpers/test/replay.ts +265 -0
  40. package/src/lib/helpers/test/test-input.ts +320 -0
  41. package/src/lib/helpers/test/test-logic.ts +1039 -0
  42. package/src/lib/helpers/test/test-state.ts +17 -0
  43. package/src/lib/helpers/test/test-stats.ts +442 -0
  44. package/src/lib/helpers/test/test-timer.ts +209 -0
  45. package/src/lib/helpers/test/test-ui.ts +370 -0
  46. package/src/lib/helpers/test/test-words.ts +72 -0
  47. package/src/lib/helpers/test/timer-progress.ts +16 -0
  48. package/src/lib/helpers/test/tts.ts +42 -0
  49. package/src/lib/helpers/test/weak-spot.ts +74 -0
  50. package/src/lib/helpers/test/wordset.ts +109 -0
  51. package/src/lib/styles/animations.scss +101 -0
  52. package/src/lib/styles/caret.scss +108 -0
  53. package/src/lib/styles/core.scss +498 -0
  54. package/src/lib/styles/index.scss +19 -0
  55. package/src/lib/styles/inputs.scss +290 -0
  56. package/src/lib/styles/popups.scss +1311 -0
  57. package/src/lib/styles/test.scss +1008 -0
  58. package/src/lib/styles/z_media-queries.scss +848 -0
  59. package/src/lib/types/types.d.ts +731 -0
  60. package/src/lib/utils/misc.ts +776 -0
  61. package/src/test-setup.ts +1 -0
  62. package/tsconfig.json +16 -0
  63. package/tsconfig.lib.json +14 -0
  64. package/tsconfig.lib.prod.json +9 -0
  65. package/tsconfig.spec.json +11 -0
@@ -0,0 +1,294 @@
1
+ import { animate, state, style, transition, trigger } from '@angular/animations';
2
+ import {
3
+ AfterViewInit,
4
+ Component,
5
+ ElementRef,
6
+ EventEmitter,
7
+ HostListener,
8
+ Input,
9
+ OnChanges,
10
+ OnDestroy,
11
+ OnInit,
12
+ Output,
13
+ SimpleChanges,
14
+ ViewChild,
15
+ } from '@angular/core';
16
+ import { BehaviorSubject, Observable, Subscription } from 'rxjs';
17
+ import {
18
+ setCustomTGQuotes,
19
+ setFunbox,
20
+ setNumbers,
21
+ setPunctuation,
22
+ setTestVersionForSentences,
23
+ setTime,
24
+ } from '../../helpers/config';
25
+ import {
26
+ inputKeydown,
27
+ setWordsInputElement,
28
+ wordsInputBeforeinput,
29
+ wordsInputCompositionend,
30
+ wordsInputCompositionstart,
31
+ wordsInputCopy,
32
+ wordsInputFocus,
33
+ wordsInputInput,
34
+ wordsInputKeyup,
35
+ wordsInputPaste,
36
+ } from '../../helpers/controllers/input-controller';
37
+ import { capsKeydown, capsKeyup, showCaps } from '../../helpers/test/caps-warning';
38
+ import { caretAnimation, caretLeft, caretShow, caretTop } from '../../helpers/test/caret';
39
+ import { mousemove, setCapsWarningElement, setMiddleElement } from '../../helpers/test/focus';
40
+ import { outOfFocusShow } from '../../helpers/test/out-of-focus';
41
+ import { getReplayExport } from '../../helpers/test/replay';
42
+ import * as TestLogic from '../../helpers/test/test-logic';
43
+ import * as TestUI from '../../helpers/test/test-ui';
44
+ import {
45
+ setWordsElement,
46
+ setWordsInputElementTestUI,
47
+ setWordsWrapperElement,
48
+ wordsInputFocusOut,
49
+ wordsInputFocusTestUI,
50
+ wordsWrapperClick,
51
+ } from '../../helpers/test/test-ui';
52
+ import { timeLeft } from '../../helpers/test/timer-progress';
53
+ import { QuoteNetworkError$ } from '../../utils/misc';
54
+ import * as TestActive from '../../helpers/states/test-active';
55
+ import quoteController from '../../helpers/controllers/quotes-controller';
56
+ import { disableCheckIfTimeIsUp } from '../../helpers/test/test-timer';
57
+ import { CommonModule } from '@angular/common';
58
+
59
+ @Component({
60
+ selector: 'tgo-typing-test',
61
+ standalone: true,
62
+ imports: [CommonModule],
63
+ templateUrl: './tgo-typing-test.component.html',
64
+ styleUrl: '../../styles/index.scss',
65
+ animations: [
66
+ trigger('fadeIn', [
67
+ state('show', style({opacity: 1})),
68
+ state('hide', style({opacity: 0})),
69
+ transition('show => hide', [
70
+ animate('125ms')
71
+ ]),
72
+ transition('hide => show', [
73
+ animate('125ms')
74
+ ])
75
+ ]),
76
+ trigger('updatePositionCaret', [
77
+ state('true',
78
+ style({
79
+ top: '{{caretTopPos}}px',
80
+ left: '{{caretLeftPos}}px'
81
+ }),
82
+ {
83
+ params: {caretTopPos: 0, caretLeftPos: 0}
84
+ }
85
+ ),
86
+ state('false',
87
+ style({
88
+ top: '{{caretTopPos}}px',
89
+ left: '{{caretLeftPos}}px'
90
+ }),
91
+ {
92
+ params: {caretTopPos: 0, caretLeftPos: 0}
93
+ }
94
+ ),
95
+ transition('true => false', [
96
+ animate('100ms')
97
+ ]),
98
+ transition('false => true', [
99
+ animate('100ms')
100
+ ])
101
+ ])
102
+ ]
103
+ })
104
+ export class TgoTypingTestComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
105
+ showCaps$: BehaviorSubject<boolean>;
106
+ showCaret$: BehaviorSubject<boolean>;
107
+ caretAnimation$: BehaviorSubject<string>;
108
+ showTimer$: BehaviorSubject<boolean>;
109
+ timeLeft$: BehaviorSubject<string>;
110
+ caretLeft = 0;
111
+ caretTop = 0;
112
+ state = 'true';
113
+ outOfFocusShow$: BehaviorSubject<boolean>;
114
+
115
+ subscriptions: Subscription[] = [];
116
+ replayIntervalID: any;
117
+
118
+ @Output() resultEvent = new EventEmitter<any>();
119
+ @Output() replayExport = new EventEmitter<any>();
120
+ @Output() errorEvent = new EventEmitter<string>();
121
+
122
+ @Input() time = 180;
123
+ @Input() punctuation = false;
124
+ @Input() numbers = false;
125
+ @Input() funbox = 'none';
126
+ @Input() customTGQuotes = false;
127
+ @Input() showMiniTimerAndLiveWpm = true;
128
+ @Input() restartTest = false;
129
+ @Input() testVersion = 1;
130
+ @Input() testExpiration$?: Observable<void>;
131
+
132
+ constructor() {
133
+ this.showCaps$ = showCaps;
134
+ this.showCaret$ = caretShow;
135
+ this.caretAnimation$ = caretAnimation;
136
+ this.showTimer$ = TestLogic.startTestSubject;
137
+ this.outOfFocusShow$ = outOfFocusShow;
138
+ this.timeLeft$ = timeLeft;
139
+ }
140
+
141
+ @ViewChild('wordsInput') wordsInput!: ElementRef;
142
+ @ViewChild('wordsWrapper') wordsWrapper!: ElementRef;
143
+ @ViewChild('words') words!: ElementRef;
144
+ @ViewChild('middle') middle!: ElementRef;
145
+ @ViewChild('capsWarning') capsWarning!: ElementRef;
146
+
147
+ ngOnInit() {
148
+ TestUI.setResultCalculating(false);
149
+ TestUI.setResultVisible(false);
150
+ this.caretLeft = 0;
151
+ this.caretTop = 0;
152
+ setTime(this.time);
153
+ setPunctuation(this.punctuation);
154
+ setNumbers(this.numbers);
155
+ setFunbox(this.funbox);
156
+ setCustomTGQuotes(this.customTGQuotes);
157
+ setTestVersionForSentences(this.testVersion);
158
+ const caretLeftSub = caretLeft.subscribe(res => {
159
+ if (res !== this.caretLeft) {
160
+ this.caretLeft = res;
161
+ if (this.state == 'true') {
162
+ this.state = 'false';
163
+ } else {
164
+ this.state = 'true';
165
+ }
166
+ }
167
+ });
168
+
169
+ const caretTopSub = caretTop.subscribe(res => {
170
+ this.caretTop = res;
171
+ });
172
+
173
+ const testResultSub = TestLogic.resultSub.subscribe(res => {
174
+ this.replayExport.emit(getReplayExport());
175
+ this.resultEvent.emit(res);
176
+ });
177
+
178
+ const errorSub = QuoteNetworkError$.subscribe({
179
+ next: e => {
180
+ if (!e) return;
181
+ this.errorEvent.emit(e);
182
+ TestLogic.stopTest();
183
+ },
184
+ });
185
+
186
+ this.replayIntervalID = setInterval(() => {
187
+ this.replayExport.emit(getReplayExport());
188
+ }, 20000);
189
+
190
+ this.subscriptions.push(caretLeftSub, caretTopSub, testResultSub, errorSub);
191
+
192
+ if (this.testExpiration$) {
193
+ disableCheckIfTimeIsUp();
194
+ this.subscriptions.push(
195
+ this.testExpiration$.subscribe(() => {
196
+ TestLogic.finish();
197
+ })
198
+ );
199
+ }
200
+ }
201
+
202
+ ngOnChanges(changes: SimpleChanges) {
203
+ if (changes['restartTest']) {
204
+ if (!changes['restartTest'].isFirstChange()) {
205
+ this.restart();
206
+ }
207
+ }
208
+ }
209
+
210
+ wordsInputKeyup(event: any) {
211
+ wordsInputKeyup(event);
212
+ }
213
+
214
+ wordsInputBeforeinput(event: any) {
215
+ wordsInputBeforeinput(event);
216
+ }
217
+
218
+ wordsInputInput(event: any) {
219
+ wordsInputInput(event);
220
+ }
221
+
222
+ wordsInputFocus(event: any) {
223
+ if (!TestActive.get()) return;
224
+ wordsInputFocus(event);
225
+ wordsInputFocusTestUI();
226
+ }
227
+
228
+ wordsInputFocusOut() {
229
+ if (!TestActive.get()) return;
230
+ wordsInputFocusOut();
231
+ }
232
+
233
+ wordsInputCopy(event: any) {
234
+ wordsInputCopy(event);
235
+ }
236
+
237
+ wordsInputPaste(event: any) {
238
+ wordsInputPaste(event);
239
+ }
240
+
241
+ wordsInputCompositionstart() {
242
+ wordsInputCompositionstart();
243
+ }
244
+
245
+ wordsInputCompositionend() {
246
+ wordsInputCompositionend();
247
+ }
248
+
249
+ wordsWrapperClick() {
250
+ wordsWrapperClick();
251
+ }
252
+
253
+ ngAfterViewInit() {
254
+ setWordsInputElement(this.wordsInput.nativeElement);
255
+ setWordsInputElementTestUI(this.wordsInput.nativeElement);
256
+ TestLogic.setWordsInputElementTestLogic(this.wordsInput.nativeElement);
257
+ setWordsWrapperElement(this.wordsWrapper.nativeElement);
258
+ setWordsElement(this.words.nativeElement);
259
+ setMiddleElement(this.middle.nativeElement);
260
+ setCapsWarningElement(this.capsWarning.nativeElement);
261
+ TestLogic.restart();
262
+ }
263
+
264
+ restart() {
265
+ TestUI.setResultCalculating(false);
266
+ TestUI.setResultVisible(false);
267
+ this.caretLeft = 0;
268
+ this.caretTop = 0;
269
+ TestLogic.restart();
270
+ }
271
+
272
+ @HostListener('document:keydown', ['$event'])
273
+ handleKeyboardDown(event: KeyboardEvent) {
274
+ capsKeydown(event);
275
+ inputKeydown(event, document.activeElement === this.wordsInput.nativeElement);
276
+ }
277
+
278
+ @HostListener('document:keyup', ['$event'])
279
+ handleKeyboardUp(event: KeyboardEvent) {
280
+ capsKeyup(event);
281
+ }
282
+
283
+ @HostListener('document:mousemove', ['$event'])
284
+ handleMouseMove(event: MouseEvent) {
285
+ mousemove(event);
286
+ }
287
+
288
+ ngOnDestroy(): void {
289
+ TestLogic.stopTest();
290
+ quoteController.resetQuotes();
291
+ clearInterval(this.replayIntervalID);
292
+ this.subscriptions.forEach(sub => sub.unsubscribe());
293
+ }
294
+ }
@@ -0,0 +1,28 @@
1
+ import DefaultConfig from "./constants/default-config";
2
+ const config = {
3
+ ...DefaultConfig,
4
+ };
5
+
6
+ export function setNumbers(numb: boolean) {
7
+ config.numbers = numb;
8
+ }
9
+ export function setPunctuation(punc: boolean) {
10
+ config.punctuation = punc;
11
+ }
12
+ export function setTime(time: number) {
13
+ config.time = time;
14
+ }
15
+
16
+ export function setFunbox(funbox: string) {
17
+ config.funbox = funbox;
18
+ }
19
+
20
+ export function setCustomTGQuotes(customTGQuotes: boolean) {
21
+ config.customTGQuotes = customTGQuotes;
22
+ }
23
+
24
+ export function setTestVersionForSentences(testVersion: number) {
25
+ config.testVersion = testVersion;
26
+ }
27
+
28
+ export default config;
@@ -0,0 +1,103 @@
1
+ import { MonkeyTypes } from '../../types/types';
2
+ export default <MonkeyTypes.Config>{
3
+ theme: 'serika_dark',
4
+ themeLight: 'serika',
5
+ themeDark: 'serika_dark',
6
+ autoSwitchTheme: false,
7
+ customTheme: false,
8
+ customThemeColors: [
9
+ '#323437',
10
+ '#e2b714',
11
+ '#e2b714',
12
+ '#646669',
13
+ '#2c2e31',
14
+ '#d1d0c5',
15
+ '#ca4754',
16
+ '#7e2a33',
17
+ '#ca4754',
18
+ '#7e2a33',
19
+ ],
20
+ favThemes: [],
21
+ showKeyTips: true,
22
+ showLiveWpm: false,
23
+ showTimerProgress: true,
24
+ smoothCaret: true,
25
+ quickRestart: 'off',
26
+ punctuation: false,
27
+ numbers: false,
28
+ words: 50,
29
+ time: 15,
30
+ mode: 'time',
31
+ quoteLength: [2],
32
+ language: 'english',
33
+ fontSize: '15',
34
+ freedomMode: false,
35
+ resultFilters: null,
36
+ difficulty: 'normal',
37
+ blindMode: false,
38
+ quickEnd: false,
39
+ caretStyle: 'default',
40
+ paceCaretStyle: 'default',
41
+ flipTestColors: false,
42
+ layout: 'default',
43
+ funbox: 'none',
44
+ confidenceMode: 'on',
45
+ indicateTypos: 'below',
46
+ timerStyle: 'mini',
47
+ colorfulMode: false,
48
+ randomTheme: 'off',
49
+ timerColor: 'main',
50
+ timerOpacity: '1',
51
+ stopOnError: 'off',
52
+ showAllLines: false,
53
+ keymapMode: 'off',
54
+ keymapStyle: 'staggered',
55
+ keymapLegendStyle: 'lowercase',
56
+ keymapLayout: 'overrideSync',
57
+ keymapShowTopRow: 'layout',
58
+ fontFamily: 'Roboto_Mono',
59
+ smoothLineScroll: false,
60
+ alwaysShowDecimalPlaces: false,
61
+ alwaysShowWordsHistory: false,
62
+ singleListCommandLine: 'manual',
63
+ capsLockWarning: true,
64
+ playSoundOnError: false,
65
+ playSoundOnClick: 'off',
66
+ soundVolume: '0.5',
67
+ startGraphsAtZero: true,
68
+ showOutOfFocusWarning: true,
69
+ paceCaret: 'off',
70
+ paceCaretCustomSpeed: 100,
71
+ repeatedPace: true,
72
+ pageWidth: '125',
73
+ chartAccuracy: true,
74
+ chartStyle: 'line',
75
+ minWpm: 'off',
76
+ minWpmCustomSpeed: 100,
77
+ highlightMode: 'letter',
78
+ alwaysShowCPM: false,
79
+ ads: 'result',
80
+ hideExtraLetters: false,
81
+ strictSpace: false,
82
+ minAcc: 'off',
83
+ minAccCustom: 90,
84
+ showLiveAcc: false,
85
+ showLiveBurst: false,
86
+ monkey: false,
87
+ repeatQuotes: 'off',
88
+ oppositeShiftMode: 'off',
89
+ customBackground: '',
90
+ customBackgroundSize: 'cover',
91
+ customBackgroundFilter: [0, 1, 1, 1, 1],
92
+ customLayoutfluid: 'qwerty#dvorak#colemak',
93
+ monkeyPowerLevel: 'off',
94
+ minBurst: 'off',
95
+ minBurstCustomSpeed: 100,
96
+ burstHeatmap: false,
97
+ britishEnglish: false,
98
+ lazyMode: false,
99
+ showAverage: 'off',
100
+ tapeMode: 'off',
101
+ customTGQuotes: false,
102
+ testVersion: 1,
103
+ };