@testgorilla/tgo-typing-test 1.0.0 → 2.0.0

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 (134) hide show
  1. package/.eslintrc.json +46 -0
  2. package/jest.config.ts +21 -0
  3. package/ng-package.json +15 -0
  4. package/package.json +7 -22
  5. package/project.json +36 -0
  6. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +30 -0
  7. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +250 -0
  8. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +47 -0
  9. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +72 -0
  10. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +699 -0
  11. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +287 -0
  12. package/src/lib/helpers/config.ts +28 -0
  13. package/src/lib/helpers/constants/default-config.ts +103 -0
  14. package/src/lib/helpers/controllers/input-controller.ts +710 -0
  15. package/src/lib/helpers/controllers/quotes-controller.ts +183 -0
  16. package/src/lib/helpers/observables/banner-event.ts +18 -0
  17. package/src/lib/helpers/observables/config-event.ts +31 -0
  18. package/src/lib/helpers/observables/timer-event.ts +18 -0
  19. package/src/lib/helpers/states/active-page.ts +9 -0
  20. package/src/lib/helpers/states/composition.ts +29 -0
  21. package/src/lib/helpers/states/page-transition.ts +9 -0
  22. package/src/lib/helpers/states/slow-timer.ts +16 -0
  23. package/src/lib/helpers/states/test-active.ts +9 -0
  24. package/src/lib/helpers/states/time.ts +13 -0
  25. package/src/lib/helpers/test/caps-warning.ts +50 -0
  26. package/src/lib/helpers/test/caret.ts +92 -0
  27. package/src/lib/helpers/test/custom-text.ts +73 -0
  28. package/src/lib/helpers/test/english-punctuation.ts +38 -0
  29. package/src/lib/helpers/test/focus.ts +39 -0
  30. package/src/lib/helpers/test/manual-restart-tracker.ts +13 -0
  31. package/src/lib/helpers/test/out-of-focus.ts +19 -0
  32. package/src/lib/helpers/test/replay.ts +265 -0
  33. package/src/lib/helpers/test/test-input.ts +320 -0
  34. package/src/lib/helpers/test/test-logic.ts +1039 -0
  35. package/src/lib/helpers/test/test-state.ts +17 -0
  36. package/src/lib/helpers/test/test-stats.ts +442 -0
  37. package/src/lib/helpers/test/test-timer.ts +209 -0
  38. package/src/lib/helpers/test/test-ui.ts +370 -0
  39. package/src/lib/helpers/test/test-words.ts +72 -0
  40. package/src/lib/helpers/test/timer-progress.ts +16 -0
  41. package/src/lib/helpers/test/tts.ts +42 -0
  42. package/src/lib/helpers/test/weak-spot.ts +74 -0
  43. package/src/lib/helpers/test/wordset.ts +109 -0
  44. package/src/lib/styles/animations.scss +101 -0
  45. package/src/lib/styles/caret.scss +108 -0
  46. package/src/lib/styles/core.scss +498 -0
  47. package/src/lib/styles/index.scss +19 -0
  48. package/src/lib/styles/inputs.scss +290 -0
  49. package/src/lib/styles/popups.scss +1311 -0
  50. package/src/lib/styles/test.scss +1008 -0
  51. package/src/lib/styles/z_media-queries.scss +848 -0
  52. package/src/lib/types/types.d.ts +731 -0
  53. package/src/lib/utils/misc.ts +776 -0
  54. package/src/test-setup.ts +20 -0
  55. package/tsconfig.json +16 -0
  56. package/tsconfig.lib.json +14 -0
  57. package/tsconfig.lib.prod.json +9 -0
  58. package/tsconfig.spec.json +11 -0
  59. package/esm2022/index.mjs +0 -3
  60. package/esm2022/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.mjs +0 -45
  61. package/esm2022/lib/components/tgo-typing-test/tgo-typing-test.component.mjs +0 -299
  62. package/esm2022/lib/helpers/config.mjs +0 -24
  63. package/esm2022/lib/helpers/constants/default-config.mjs +0 -103
  64. package/esm2022/lib/helpers/controllers/input-controller.mjs +0 -586
  65. package/esm2022/lib/helpers/controllers/quotes-controller.mjs +0 -118
  66. package/esm2022/lib/helpers/observables/config-event.mjs +0 -16
  67. package/esm2022/lib/helpers/observables/timer-event.mjs +0 -16
  68. package/esm2022/lib/helpers/states/active-page.mjs +0 -8
  69. package/esm2022/lib/helpers/states/composition.mjs +0 -20
  70. package/esm2022/lib/helpers/states/page-transition.mjs +0 -8
  71. package/esm2022/lib/helpers/states/slow-timer.mjs +0 -15
  72. package/esm2022/lib/helpers/states/test-active.mjs +0 -8
  73. package/esm2022/lib/helpers/states/time.mjs +0 -11
  74. package/esm2022/lib/helpers/test/caps-warning.mjs +0 -50
  75. package/esm2022/lib/helpers/test/caret.mjs +0 -80
  76. package/esm2022/lib/helpers/test/custom-text.mjs +0 -59
  77. package/esm2022/lib/helpers/test/english-punctuation.mjs +0 -29
  78. package/esm2022/lib/helpers/test/focus.mjs +0 -35
  79. package/esm2022/lib/helpers/test/manual-restart-tracker.mjs +0 -11
  80. package/esm2022/lib/helpers/test/out-of-focus.mjs +0 -14
  81. package/esm2022/lib/helpers/test/replay.mjs +0 -217
  82. package/esm2022/lib/helpers/test/test-input.mjs +0 -264
  83. package/esm2022/lib/helpers/test/test-logic.mjs +0 -927
  84. package/esm2022/lib/helpers/test/test-state.mjs +0 -13
  85. package/esm2022/lib/helpers/test/test-stats.mjs +0 -342
  86. package/esm2022/lib/helpers/test/test-timer.mjs +0 -207
  87. package/esm2022/lib/helpers/test/test-ui.mjs +0 -341
  88. package/esm2022/lib/helpers/test/test-words.mjs +0 -69
  89. package/esm2022/lib/helpers/test/timer-progress.mjs +0 -15
  90. package/esm2022/lib/helpers/test/weak-spot.mjs +0 -65
  91. package/esm2022/lib/helpers/test/wordset.mjs +0 -100
  92. package/esm2022/lib/utils/misc.mjs +0 -673
  93. package/esm2022/testgorilla-tgo-typing-test.mjs +0 -5
  94. package/fesm2022/testgorilla-tgo-typing-test.mjs +0 -4707
  95. package/fesm2022/testgorilla-tgo-typing-test.mjs.map +0 -1
  96. package/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.d.ts +0 -14
  97. package/lib/components/tgo-typing-test/tgo-typing-test.component.d.ts +0 -54
  98. package/lib/helpers/config.d.ts +0 -98
  99. package/lib/helpers/constants/default-config.d.ts +0 -3
  100. package/lib/helpers/controllers/input-controller.d.ts +0 -16
  101. package/lib/helpers/controllers/quotes-controller.d.ts +0 -20
  102. package/lib/helpers/observables/config-event.d.ts +0 -5
  103. package/lib/helpers/observables/timer-event.d.ts +0 -4
  104. package/lib/helpers/states/active-page.d.ts +0 -2
  105. package/lib/helpers/states/composition.d.ts +0 -10
  106. package/lib/helpers/states/page-transition.d.ts +0 -2
  107. package/lib/helpers/states/slow-timer.d.ts +0 -3
  108. package/lib/helpers/states/test-active.d.ts +0 -2
  109. package/lib/helpers/states/time.d.ts +0 -3
  110. package/lib/helpers/test/caps-warning.d.ts +0 -5
  111. package/lib/helpers/test/caret.d.ts +0 -11
  112. package/lib/helpers/test/custom-text.d.ts +0 -16
  113. package/lib/helpers/test/english-punctuation.d.ts +0 -3
  114. package/lib/helpers/test/focus.d.ts +0 -7
  115. package/lib/helpers/test/manual-restart-tracker.d.ts +0 -3
  116. package/lib/helpers/test/out-of-focus.d.ts +0 -4
  117. package/lib/helpers/test/replay.d.ts +0 -20
  118. package/lib/helpers/test/test-input.d.ts +0 -86
  119. package/lib/helpers/test/test-logic.d.ts +0 -25
  120. package/lib/helpers/test/test-state.d.ts +0 -7
  121. package/lib/helpers/test/test-stats.d.ts +0 -92
  122. package/lib/helpers/test/test-timer.d.ts +0 -6
  123. package/lib/helpers/test/test-ui.d.ts +0 -27
  124. package/lib/helpers/test/test-words.d.ts +0 -23
  125. package/lib/helpers/test/timer-progress.d.ts +0 -3
  126. package/lib/helpers/test/weak-spot.d.ts +0 -3
  127. package/lib/helpers/test/wordset.d.ts +0 -7
  128. package/lib/utils/misc.d.ts +0 -81
  129. /package/{assets → src/assets}/typing-test-languages/english.json +0 -0
  130. /package/{assets → src/assets}/typing-test-languages/english_punctuation.json +0 -0
  131. /package/{assets → src/assets}/typing-test-languages/quotes/english_version_1.json +0 -0
  132. /package/{assets → src/assets}/typing-test-languages/quotes/english_version_2.json +0 -0
  133. /package/{assets → src/assets}/typing-test-languages/quotes/filtered_sources.json +0 -0
  134. /package/{index.d.ts → src/index.ts} +0 -0
@@ -1,100 +0,0 @@
1
- import { randomElementFromArray, randomIntFromRange } from '../../utils/misc';
2
- let currentWordset = null;
3
- let currentWordGenerator = null;
4
- export class Wordset {
5
- words;
6
- length;
7
- constructor(words) {
8
- this.words = words;
9
- this.length = this.words.length;
10
- }
11
- randomWord() {
12
- return randomElementFromArray(this.words);
13
- }
14
- }
15
- const prefixSize = 2;
16
- class CharDistribution {
17
- chars;
18
- count;
19
- constructor() {
20
- this.chars = {};
21
- this.count = 0;
22
- }
23
- addChar(char) {
24
- this.count++;
25
- if (char in this.chars) {
26
- this.chars[char]++;
27
- }
28
- else {
29
- this.chars[char] = 1;
30
- }
31
- }
32
- randomChar() {
33
- const randomIndex = randomIntFromRange(0, this.count - 1);
34
- let runningCount = 0;
35
- for (const [char, charCount] of Object.entries(this.chars)) {
36
- runningCount += charCount;
37
- if (runningCount > randomIndex) {
38
- return char;
39
- }
40
- }
41
- return Object.keys(this.chars)[0];
42
- }
43
- }
44
- class WordGenerator extends Wordset {
45
- ngrams = {};
46
- constructor(words) {
47
- super(words);
48
- // Can generate an unbounded number of words in theory.
49
- this.length = Infinity;
50
- for (let word of words) {
51
- // Mark the end of each word with a space.
52
- word += " ";
53
- let prefix = "";
54
- for (const c of word) {
55
- // Add `c` to the distribution of chars that can come after `prefix`.
56
- if (!(prefix in this.ngrams)) {
57
- this.ngrams[prefix] = new CharDistribution();
58
- }
59
- this.ngrams[prefix].addChar(c);
60
- prefix = (prefix + c).substr(-prefixSize);
61
- }
62
- }
63
- }
64
- randomWord() {
65
- let word = "";
66
- for (;;) {
67
- const prefix = word.substr(-prefixSize);
68
- const charDistribution = this.ngrams[prefix];
69
- if (!charDistribution) {
70
- // This shouldn't happen if this.ngrams is complete. If it does
71
- // somehow, start generating a new word.
72
- word = "";
73
- continue;
74
- }
75
- // Pick a random char from the distribution that comes after `prefix`.
76
- const nextChar = charDistribution.randomChar();
77
- if (nextChar == " ") {
78
- // A space marks the end of the word, so stop generating and return.
79
- break;
80
- }
81
- word += nextChar;
82
- }
83
- return word;
84
- }
85
- }
86
- export function withWords(words, funbox) {
87
- if (funbox == "pseudolang") {
88
- if (currentWordGenerator == null || words !== currentWordGenerator.words) {
89
- currentWordGenerator = new WordGenerator(words);
90
- }
91
- return currentWordGenerator;
92
- }
93
- else {
94
- if (currentWordset == null || words !== currentWordset.words) {
95
- currentWordset = new Wordset(words);
96
- }
97
- return currentWordset;
98
- }
99
- }
100
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29yZHNldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvdGVzdC93b3Jkc2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTlFLElBQUksY0FBYyxHQUFtQixJQUFJLENBQUM7QUFDMUMsSUFBSSxvQkFBb0IsR0FBeUIsSUFBSSxDQUFDO0FBRXRELE1BQU0sT0FBTyxPQUFPO0lBQ1gsS0FBSyxDQUFXO0lBQ2hCLE1BQU0sQ0FBUztJQUN0QixZQUFZLEtBQWU7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUNsQyxDQUFDO0lBRU0sVUFBVTtRQUNmLE9BQU8sc0JBQXNCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVDLENBQUM7Q0FDRjtBQUVELE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQztBQUVyQixNQUFNLGdCQUFnQjtJQUNiLEtBQUssQ0FBNkI7SUFDbEMsS0FBSyxDQUFTO0lBQ3JCO1FBQ0UsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDaEIsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDakIsQ0FBQztJQUVNLE9BQU8sQ0FBQyxJQUFZO1FBQ3pCLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNiLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDckIsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFH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QUFJLGNBQWMsSUFBSSxJQUFJLElBQUksS0FBSyxLQUFLLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM3RCxjQUFjLEdBQUcsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEMsQ0FBQztRQUNELE9BQU8sY0FBYyxDQUFDO0lBQ3hCLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tRWxlbWVudEZyb21BcnJheSwgcmFuZG9tSW50RnJvbVJhbmdlIH0gZnJvbSAnLi4vLi4vdXRpbHMvbWlzYyc7XG5cbmxldCBjdXJyZW50V29yZHNldDogV29yZHNldCB8IG51bGwgPSBudWxsO1xubGV0IGN1cnJlbnRXb3JkR2VuZXJhdG9yOiBXb3JkR2VuZXJhdG9yIHwgbnVsbCA9IG51bGw7XG5cbmV4cG9ydCBjbGFzcyBXb3Jkc2V0IHtcbiAgcHVibGljIHdvcmRzOiBzdHJpbmdbXTtcbiAgcHVibGljIGxlbmd0aDogbnVtYmVyO1xuICBjb25zdHJ1Y3Rvcih3b3Jkczogc3RyaW5nW10pIHtcbiAgICB0aGlzLndvcmRzID0gd29yZHM7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLndvcmRzLmxlbmd0aDtcbiAgfVxuXG4gIHB1YmxpYyByYW5kb21Xb3JkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHJhbmRvbUVsZW1lbnRGcm9tQXJyYXkodGhpcy53b3Jkcyk7XG4gIH1cbn1cblxuY29uc3QgcHJlZml4U2l6ZSA9IDI7XG5cbmNsYXNzIENoYXJEaXN0cmlidXRpb24ge1xuICBwdWJsaWMgY2hhcnM6IHsgW2NoYXI6IHN0cmluZ106IG51bWJlciB9O1xuICBwdWJsaWMgY291bnQ6IG51bWJlcjtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5jaGFycyA9IHt9O1xuICAgIHRoaXMuY291bnQgPSAwO1xuICB9XG5cbiAgcHVibGljIGFkZENoYXIoY2hhcjogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jb3VudCsrO1xuICAgIGlmIChjaGFyIGluIHRoaXMuY2hhcnMpIHtcbiAgICAgIHRoaXMuY2hhcnNbY2hhcl0rKztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5jaGFyc1tjaGFyXSA9IDE7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHJhbmRvbUNoYXIoKTogc3RyaW5nIHtcbiAgICBjb25zdCByYW5kb21JbmRleCA9IHJhbmRvbUludEZyb21SYW5nZSgwLCB0aGlzLmNvdW50IC0gMSk7XG4gICAgbGV0IHJ1bm5pbmdDb3VudCA9IDA7XG4gICAgZm9yIChjb25zdCBbY2hhciwgY2hhckNvdW50XSBvZiBPYmplY3QuZW50cmllcyh0aGlzLmNoYXJzKSkge1xuICAgICAgcnVubmluZ0NvdW50ICs9IGNoYXJDb3VudDtcbiAgICAgIGlmIChydW5uaW5nQ291bnQgPiByYW5kb21JbmRleCkge1xuICAgICAgICByZXR1cm4gY2hhcjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5jaGFycylbMF07XG4gIH1cbn1cblxuY2xhc3MgV29yZEdlbmVyYXRvciBleHRlbmRzIFdvcmRzZXQge1xuICBwdWJsaWMgbmdyYW1zOiB7IFtwcmVmaXg6IHN0cmluZ106IENoYXJEaXN0cmlidXRpb24gfSA9IHt9O1xuICBjb25zdHJ1Y3Rvcih3b3Jkczogc3RyaW5nW10pIHtcbiAgICBzdXBlcih3b3Jkcyk7XG4gICAgLy8gQ2FuIGdlbmVyYXRlIGFuIHVuYm91bmRlZCBudW1iZXIgb2Ygd29yZHMgaW4gdGhlb3J5LlxuICAgIHRoaXMubGVuZ3RoID0gSW5maW5pdHk7XG5cbiAgICBmb3IgKGxldCB3b3JkIG9mIHdvcmRzKSB7XG4gICAgICAvLyBNYXJrIHRoZSBlbmQgb2YgZWFjaCB3b3JkIHdpdGggYSBzcGFjZS5cbiAgICAgIHdvcmQgKz0gXCIgXCI7XG4gICAgICBsZXQgcHJlZml4ID0gXCJcIjtcbiAgICAgIGZvciAoY29uc3QgYyBvZiB3b3JkKSB7XG4gICAgICAgIC8vIEFkZCBgY2AgdG8gdGhlIGRpc3RyaWJ1dGlvbiBvZiBjaGFycyB0aGF0IGNhbiBjb21lIGFmdGVyIGBwcmVmaXhgLlxuICAgICAgICBpZiAoIShwcmVmaXggaW4gdGhpcy5uZ3JhbXMpKSB7XG4gICAgICAgICAgdGhpcy5uZ3JhbXNbcHJlZml4XSA9IG5ldyBDaGFyRGlzdHJpYnV0aW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5uZ3JhbXNbcHJlZml4XS5hZGRDaGFyKGMpO1xuICAgICAgICBwcmVmaXggPSAocHJlZml4ICsgYykuc3Vic3RyKC1wcmVmaXhTaXplKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgcmFuZG9tV29yZCgpOiBzdHJpbmcge1xuICAgIGxldCB3b3JkID0gXCJcIjtcbiAgICBmb3IgKDs7KSB7XG4gICAgICBjb25zdCBwcmVmaXggPSB3b3JkLnN1YnN0cigtcHJlZml4U2l6ZSk7XG4gICAgICBjb25zdCBjaGFyRGlzdHJpYnV0aW9uID0gdGhpcy5uZ3JhbXNbcHJlZml4XTtcbiAgICAgIGlmICghY2hhckRpc3RyaWJ1dGlvbikge1xuICAgICAgICAvLyBUaGlzIHNob3VsZG4ndCBoYXBwZW4gaWYgdGhpcy5uZ3JhbXMgaXMgY29tcGxldGUuIElmIGl0IGRvZXNcbiAgICAgICAgLy8gc29tZWhvdywgc3RhcnQgZ2VuZXJhdGluZyBhIG5ldyB3b3JkLlxuICAgICAgICB3b3JkID0gXCJcIjtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICAvLyBQaWNrIGEgcmFuZG9tIGNoYXIgZnJvbSB0aGUgZGlzdHJpYnV0aW9uIHRoYXQgY29tZXMgYWZ0ZXIgYHByZWZpeGAuXG4gICAgICBjb25zdCBuZXh0Q2hhciA9IGNoYXJEaXN0cmlidXRpb24ucmFuZG9tQ2hhcigpO1xuICAgICAgaWYgKG5leHRDaGFyID09IFwiIFwiKSB7XG4gICAgICAgIC8vIEEgc3BhY2UgbWFya3MgdGhlIGVuZCBvZiB0aGUgd29yZCwgc28gc3RvcCBnZW5lcmF0aW5nIGFuZCByZXR1cm4uXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgd29yZCArPSBuZXh0Q2hhcjtcbiAgICB9XG4gICAgcmV0dXJuIHdvcmQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpdGhXb3Jkcyh3b3Jkczogc3RyaW5nW10sIGZ1bmJveDogc3RyaW5nKTogV29yZHNldCB7XG4gIGlmIChmdW5ib3ggPT0gXCJwc2V1ZG9sYW5nXCIpIHtcbiAgICBpZiAoY3VycmVudFdvcmRHZW5lcmF0b3IgPT0gbnVsbCB8fCB3b3JkcyAhPT0gY3VycmVudFdvcmRHZW5lcmF0b3Iud29yZHMpIHtcbiAgICAgIGN1cnJlbnRXb3JkR2VuZXJhdG9yID0gbmV3IFdvcmRHZW5lcmF0b3Iod29yZHMpO1xuICAgIH1cbiAgICByZXR1cm4gY3VycmVudFdvcmRHZW5lcmF0b3I7XG4gIH0gZWxzZSB7XG4gICAgaWYgKGN1cnJlbnRXb3Jkc2V0ID09IG51bGwgfHwgd29yZHMgIT09IGN1cnJlbnRXb3Jkc2V0LndvcmRzKSB7XG4gICAgICBjdXJyZW50V29yZHNldCA9IG5ldyBXb3Jkc2V0KHdvcmRzKTtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnJlbnRXb3Jkc2V0O1xuICB9XG59XG4iXX0=