@testgorilla/tgo-coding-test 0.0.1 → 1.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 (354) hide show
  1. package/README.md +49 -2
  2. package/esm2022/index.mjs +12 -0
  3. package/esm2022/lib/components/code-editor/code-editor.component.mjs +335 -0
  4. package/esm2022/lib/components/code-editor/code-editor.service.mjs +72 -0
  5. package/esm2022/lib/components/code-editor/helpers/c-helper.mjs +40 -0
  6. package/esm2022/lib/components/code-editor/helpers/code-editor-helper.base.mjs +11 -0
  7. package/esm2022/lib/components/code-editor/helpers/code-editor-helper.model.mjs +2 -0
  8. package/esm2022/lib/components/code-editor/helpers/cpp-helper.mjs +41 -0
  9. package/esm2022/lib/components/code-editor/helpers/csharp-helper.mjs +42 -0
  10. package/esm2022/lib/components/code-editor/helpers/go-helper.mjs +42 -0
  11. package/esm2022/lib/components/code-editor/helpers/index.mjs +16 -0
  12. package/esm2022/lib/components/code-editor/helpers/java-helper.mjs +42 -0
  13. package/esm2022/lib/components/code-editor/helpers/javascript-helper.mjs +26 -0
  14. package/esm2022/lib/components/code-editor/helpers/kotlin-helper.mjs +42 -0
  15. package/esm2022/lib/components/code-editor/helpers/php-helper.mjs +26 -0
  16. package/esm2022/lib/components/code-editor/helpers/python-helper.mjs +26 -0
  17. package/esm2022/lib/components/code-editor/helpers/r-helper.mjs +26 -0
  18. package/esm2022/lib/components/code-editor/helpers/ruby-helper.mjs +26 -0
  19. package/esm2022/lib/components/code-editor/helpers/scala-helper.mjs +41 -0
  20. package/esm2022/lib/components/code-editor/helpers/sql-helper.mjs +34 -0
  21. package/esm2022/lib/components/code-editor/helpers/swift-helper.mjs +40 -0
  22. package/esm2022/lib/components/code-editor/helpers/typescript-helper.mjs +41 -0
  23. package/esm2022/lib/components/code-editor/models/code-editor.model.mjs +2 -0
  24. package/esm2022/lib/components/code-editor/models/coding-snapshot.model.mjs +2 -0
  25. package/esm2022/lib/components/coding-question/coding-question.component.mjs +126 -0
  26. package/esm2022/lib/components/coding-section/coding-section.component.mjs +188 -0
  27. package/esm2022/lib/components/common/truncated-text/truncated-text.component.mjs +38 -0
  28. package/esm2022/lib/components/configurations/configurations.component.mjs +97 -0
  29. package/esm2022/lib/components/instructions/instructions.component.mjs +139 -0
  30. package/esm2022/lib/components/panel/panel.component.mjs +34 -0
  31. package/esm2022/lib/components/runnable-editor/runnable-editor.component.mjs +169 -0
  32. package/esm2022/lib/components/tests/test-cases/test-cases.component.mjs +198 -0
  33. package/esm2022/lib/components/tests/test-cases-content/test-cases-content.component.mjs +96 -0
  34. package/esm2022/lib/components/tests/test-cases-status/test-cases-status.component.mjs +21 -0
  35. package/esm2022/lib/components/tests/test-results.component.mjs +127 -0
  36. package/esm2022/lib/components/tgo-coding-test/tgo-coding-test.component.mjs +280 -0
  37. package/esm2022/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.mjs +476 -0
  38. package/esm2022/lib/config/index.mjs +2 -0
  39. package/esm2022/lib/config/tgo-coding-test.config.mjs +2 -0
  40. package/esm2022/lib/config/tgo-coding-test.provider.mjs +34 -0
  41. package/esm2022/lib/config/tgo-coding-test.token.mjs +14 -0
  42. package/esm2022/lib/models/auto-saved-data.mjs +2 -0
  43. package/esm2022/lib/models/code-event.mjs +2 -0
  44. package/esm2022/lib/models/coderunner-execution-results.mjs +2 -0
  45. package/esm2022/lib/models/configs.mjs +2 -0
  46. package/esm2022/lib/models/language-change-action.mjs +2 -0
  47. package/esm2022/lib/models/lat-languages.mjs +3 -0
  48. package/esm2022/lib/models/mixpanel-events.mjs +2 -0
  49. package/esm2022/lib/models/mode.mjs +2 -0
  50. package/esm2022/lib/models/paste-data.mjs +2 -0
  51. package/esm2022/lib/models/programming-language.mjs +2 -0
  52. package/esm2022/lib/models/test-cases.mjs +7 -0
  53. package/esm2022/lib/models/theme.mjs +2 -0
  54. package/esm2022/lib/models/translations.mjs +2 -0
  55. package/esm2022/lib/models/view-mode.mjs +8 -0
  56. package/esm2022/lib/pipes/memoize-func.pipe.mjs +39 -0
  57. package/esm2022/lib/services/candidate-coding-test-services/candidature-api.service.mjs +19 -0
  58. package/esm2022/lib/services/candidate-coding-test-services/coderunner-api.service.mjs +58 -0
  59. package/esm2022/lib/services/candidate-coding-test-services/coding-test-tour.service.mjs +89 -0
  60. package/esm2022/lib/services/candidate-coding-test-services/coding-test.service.mjs +490 -0
  61. package/esm2022/lib/services/candidate-coding-test-services/index.mjs +5 -0
  62. package/esm2022/lib/services/coding-test-config.service.mjs +51 -0
  63. package/esm2022/lib/services/configurations.service.mjs +89 -0
  64. package/esm2022/lib/services/lib-coding-test.service.mjs +106 -0
  65. package/esm2022/lib/services/storage.service.mjs +624 -0
  66. package/esm2022/lib/services/test-cases.service.mjs +30 -0
  67. package/esm2022/lib/services/theme.service.mjs +36 -0
  68. package/esm2022/lib/utils/additional-languages/erlang.mjs +103 -0
  69. package/esm2022/lib/utils/resize-element.mjs +13 -0
  70. package/esm2022/lib/utils/time-to-ms.util.mjs +11 -0
  71. package/esm2022/shared/index.mjs +5 -0
  72. package/esm2022/shared/lib/components/audio-animation/audio-animation.component.mjs +114 -0
  73. package/esm2022/shared/lib/components/audio-animation/index.mjs +2 -0
  74. package/esm2022/shared/lib/components/index.mjs +3 -0
  75. package/esm2022/shared/lib/components/vimeo-video/index.mjs +2 -0
  76. package/esm2022/shared/lib/components/vimeo-video/vimeo-video.component.mjs +101 -0
  77. package/esm2022/shared/lib/models/answer.mjs +2 -0
  78. package/esm2022/shared/lib/models/assessment.mjs +2 -0
  79. package/esm2022/shared/lib/models/environment.mjs +2 -0
  80. package/esm2022/shared/lib/models/index.mjs +9 -0
  81. package/esm2022/shared/lib/models/question-component.mjs +2 -0
  82. package/esm2022/shared/lib/models/question.mjs +2 -0
  83. package/esm2022/shared/lib/models/test.mjs +2 -0
  84. package/esm2022/shared/lib/models/translations.mjs +2 -0
  85. package/esm2022/shared/lib/models/window.mjs +2 -0
  86. package/esm2022/shared/lib/services/api/api.service.mjs +97 -0
  87. package/esm2022/shared/lib/services/api/mocked-api.service.mjs +131 -0
  88. package/esm2022/shared/lib/services/environment/environment.service.mjs +13 -0
  89. package/esm2022/shared/lib/services/index.mjs +10 -0
  90. package/esm2022/shared/lib/services/localization/languages.model.mjs +19 -0
  91. package/esm2022/shared/lib/services/localization/transloco-lazy-module-utils.mjs +27 -0
  92. package/esm2022/shared/lib/services/localization/transloco-testing.module.mjs +11 -0
  93. package/esm2022/shared/lib/services/media/media.service.mjs +129 -0
  94. package/esm2022/shared/lib/services/mixpanel/mixpanel.service.mjs +30 -0
  95. package/esm2022/shared/lib/services/theme/theme.service.mjs +24 -0
  96. package/esm2022/shared/test-mocks/assessment-test.mock.mjs +112 -0
  97. package/esm2022/shared/test-mocks/index.mjs +3 -0
  98. package/esm2022/shared/test-mocks/tgo-ui.mock.mjs +39 -0
  99. package/esm2022/testgorilla-tgo-coding-test.mjs +5 -0
  100. package/fesm2022/testgorilla-tgo-coding-test.mjs +4526 -0
  101. package/fesm2022/testgorilla-tgo-coding-test.mjs.map +1 -0
  102. package/{src/index.ts → index.d.ts} +2 -19
  103. package/lib/components/code-editor/code-editor.component.d.ts +54 -0
  104. package/lib/components/code-editor/code-editor.service.d.ts +12 -0
  105. package/lib/components/code-editor/helpers/c-helper.d.ts +11 -0
  106. package/lib/components/code-editor/helpers/code-editor-helper.base.d.ts +8 -0
  107. package/lib/components/code-editor/helpers/code-editor-helper.model.d.ts +62 -0
  108. package/lib/components/code-editor/helpers/cpp-helper.d.ts +11 -0
  109. package/lib/components/code-editor/helpers/csharp-helper.d.ts +12 -0
  110. package/lib/components/code-editor/helpers/go-helper.d.ts +12 -0
  111. package/lib/components/code-editor/helpers/java-helper.d.ts +12 -0
  112. package/lib/components/code-editor/helpers/javascript-helper.d.ts +10 -0
  113. package/lib/components/code-editor/helpers/kotlin-helper.d.ts +12 -0
  114. package/lib/components/code-editor/helpers/php-helper.d.ts +10 -0
  115. package/lib/components/code-editor/helpers/python-helper.d.ts +10 -0
  116. package/lib/components/code-editor/helpers/r-helper.d.ts +10 -0
  117. package/lib/components/code-editor/helpers/ruby-helper.d.ts +10 -0
  118. package/lib/components/code-editor/helpers/scala-helper.d.ts +12 -0
  119. package/lib/components/code-editor/helpers/sql-helper.d.ts +10 -0
  120. package/lib/components/code-editor/helpers/swift-helper.d.ts +11 -0
  121. package/lib/components/code-editor/helpers/typescript-helper.d.ts +11 -0
  122. package/lib/components/code-editor/models/code-editor.model.d.ts +8 -0
  123. package/lib/components/code-editor/models/coding-snapshot.model.d.ts +4 -0
  124. package/lib/components/coding-question/coding-question.component.d.ts +45 -0
  125. package/lib/components/coding-section/coding-section.component.d.ts +52 -0
  126. package/lib/components/common/truncated-text/truncated-text.component.d.ts +13 -0
  127. package/lib/components/configurations/configurations.component.d.ts +40 -0
  128. package/lib/components/instructions/instructions.component.d.ts +48 -0
  129. package/lib/components/panel/panel.component.d.ts +12 -0
  130. package/lib/components/runnable-editor/runnable-editor.component.d.ts +53 -0
  131. package/lib/components/tests/test-cases/test-cases.component.d.ts +46 -0
  132. package/lib/components/tests/test-cases-content/test-cases-content.component.d.ts +26 -0
  133. package/lib/components/tests/test-cases-status/test-cases-status.component.d.ts +9 -0
  134. package/lib/components/tests/test-results.component.d.ts +33 -0
  135. package/lib/components/tgo-coding-test/tgo-coding-test.component.d.ts +69 -0
  136. package/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.d.ts +101 -0
  137. package/{src/lib/config/index.ts → lib/config/index.d.ts} +0 -1
  138. package/lib/config/tgo-coding-test.config.d.ts +24 -0
  139. package/{src/lib/config/tgo-coding-test.provider.ts → lib/config/tgo-coding-test.provider.d.ts} +6 -18
  140. package/lib/config/tgo-coding-test.token.d.ts +9 -0
  141. package/lib/models/auto-saved-data.d.ts +42 -0
  142. package/lib/models/code-event.d.ts +15 -0
  143. package/lib/models/coderunner-execution-results.d.ts +51 -0
  144. package/lib/models/configs.d.ts +15 -0
  145. package/lib/models/language-change-action.d.ts +4 -0
  146. package/lib/models/lat-languages.d.ts +8 -0
  147. package/lib/models/mixpanel-events.d.ts +3 -0
  148. package/lib/models/mode.d.ts +5 -0
  149. package/lib/models/paste-data.d.ts +4 -0
  150. package/lib/models/programming-language.d.ts +8 -0
  151. package/lib/models/test-cases.d.ts +67 -0
  152. package/lib/models/theme.d.ts +4 -0
  153. package/lib/models/translations.d.ts +1 -0
  154. package/lib/models/view-mode.d.ts +6 -0
  155. package/{src/lib/pipes/memoize-func.pipe.ts → lib/pipes/memoize-func.pipe.d.ts} +6 -14
  156. package/lib/services/candidate-coding-test-services/candidature-api.service.d.ts +10 -0
  157. package/lib/services/candidate-coding-test-services/coderunner-api.service.d.ts +18 -0
  158. package/lib/services/candidate-coding-test-services/coding-test-tour.service.d.ts +22 -0
  159. package/lib/services/candidate-coding-test-services/coding-test.service.d.ts +68 -0
  160. package/{src/lib/services/candidate-coding-test-services/index.ts → lib/services/candidate-coding-test-services/index.d.ts} +1 -1
  161. package/lib/services/coding-test-config.service.d.ts +38 -0
  162. package/lib/services/configurations.service.d.ts +37 -0
  163. package/lib/services/lib-coding-test.service.d.ts +69 -0
  164. package/lib/services/storage.service.d.ts +83 -0
  165. package/lib/services/test-cases.service.d.ts +12 -0
  166. package/lib/services/theme.service.d.ts +17 -0
  167. package/lib/utils/additional-languages/erlang.d.ts +37 -0
  168. package/lib/utils/resize-element.d.ts +2 -0
  169. package/lib/utils/time-to-ms.util.d.ts +1 -0
  170. package/package.json +18 -7
  171. package/shared/index.d.ts +4 -0
  172. package/shared/lib/components/audio-animation/audio-animation.component.d.ts +27 -0
  173. package/shared/lib/components/audio-animation/index.d.ts +1 -0
  174. package/shared/lib/components/index.d.ts +2 -0
  175. package/shared/lib/components/vimeo-video/index.d.ts +1 -0
  176. package/shared/lib/components/vimeo-video/vimeo-video.component.d.ts +24 -0
  177. package/shared/lib/models/answer.d.ts +17 -0
  178. package/shared/lib/models/assessment.d.ts +80 -0
  179. package/shared/lib/models/environment.d.ts +1 -0
  180. package/shared/lib/models/index.d.ts +8 -0
  181. package/shared/lib/models/question-component.d.ts +54 -0
  182. package/shared/lib/models/question.d.ts +102 -0
  183. package/shared/lib/models/test.d.ts +81 -0
  184. package/shared/lib/models/translations.d.ts +1 -0
  185. package/shared/lib/models/window.d.ts +6 -0
  186. package/shared/lib/services/api/api.service.d.ts +25 -0
  187. package/shared/lib/services/api/mocked-api.service.d.ts +35 -0
  188. package/shared/lib/services/environment/environment.service.d.ts +6 -0
  189. package/shared/lib/services/index.d.ts +9 -0
  190. package/shared/lib/services/localization/languages.model.d.ts +15 -0
  191. package/shared/lib/services/localization/transloco-lazy-module-utils.d.ts +11 -0
  192. package/shared/lib/services/localization/transloco-testing.module.d.ts +2 -0
  193. package/shared/lib/services/media/media.service.d.ts +29 -0
  194. package/shared/lib/services/mixpanel/mixpanel.service.d.ts +10 -0
  195. package/shared/lib/services/theme/theme.service.d.ts +8 -0
  196. package/shared/test-mocks/assessment-test.mock.d.ts +21 -0
  197. package/shared/test-mocks/index.d.ts +2 -0
  198. package/shared/test-mocks/tgo-ui.mock.d.ts +21 -0
  199. package/.eslintrc.json +0 -45
  200. package/jest.config.ts +0 -21
  201. package/ng-package.json +0 -14
  202. package/project.json +0 -36
  203. package/src/lib/components/.gitkeep +0 -0
  204. package/src/lib/components/code-editor/code-editor.component.html +0 -10
  205. package/src/lib/components/code-editor/code-editor.component.scss +0 -21
  206. package/src/lib/components/code-editor/code-editor.component.spec.ts +0 -136
  207. package/src/lib/components/code-editor/code-editor.component.ts +0 -369
  208. package/src/lib/components/code-editor/code-editor.mocks.ts +0 -28
  209. package/src/lib/components/code-editor/code-editor.service.spec.ts +0 -160
  210. package/src/lib/components/code-editor/code-editor.service.ts +0 -94
  211. package/src/lib/components/code-editor/helpers/c-helper.spec.ts +0 -39
  212. package/src/lib/components/code-editor/helpers/c-helper.ts +0 -51
  213. package/src/lib/components/code-editor/helpers/code-editor-helper.base.spec.ts +0 -30
  214. package/src/lib/components/code-editor/helpers/code-editor-helper.base.ts +0 -16
  215. package/src/lib/components/code-editor/helpers/code-editor-helper.mocks.ts +0 -24
  216. package/src/lib/components/code-editor/helpers/code-editor-helper.model.ts +0 -67
  217. package/src/lib/components/code-editor/helpers/cpp-helper.spec.ts +0 -40
  218. package/src/lib/components/code-editor/helpers/cpp-helper.ts +0 -52
  219. package/src/lib/components/code-editor/helpers/csharp-helper.spec.ts +0 -42
  220. package/src/lib/components/code-editor/helpers/csharp-helper.ts +0 -55
  221. package/src/lib/components/code-editor/helpers/go-helper.spec.ts +0 -41
  222. package/src/lib/components/code-editor/helpers/go-helper.ts +0 -54
  223. package/src/lib/components/code-editor/helpers/java-helper.spec.ts +0 -41
  224. package/src/lib/components/code-editor/helpers/java-helper.ts +0 -54
  225. package/src/lib/components/code-editor/helpers/javascript-helper.spec.ts +0 -39
  226. package/src/lib/components/code-editor/helpers/javascript-helper.ts +0 -32
  227. package/src/lib/components/code-editor/helpers/kotlin-helper.spec.ts +0 -41
  228. package/src/lib/components/code-editor/helpers/kotlin-helper.ts +0 -54
  229. package/src/lib/components/code-editor/helpers/php-helper.spec.ts +0 -39
  230. package/src/lib/components/code-editor/helpers/php-helper.ts +0 -32
  231. package/src/lib/components/code-editor/helpers/python-helper.spec.ts +0 -39
  232. package/src/lib/components/code-editor/helpers/python-helper.ts +0 -32
  233. package/src/lib/components/code-editor/helpers/r-helper.spec.ts +0 -39
  234. package/src/lib/components/code-editor/helpers/r-helper.ts +0 -32
  235. package/src/lib/components/code-editor/helpers/ruby-helper.spec.ts +0 -39
  236. package/src/lib/components/code-editor/helpers/ruby-helper.ts +0 -32
  237. package/src/lib/components/code-editor/helpers/scala-helper.spec.ts +0 -41
  238. package/src/lib/components/code-editor/helpers/scala-helper.ts +0 -53
  239. package/src/lib/components/code-editor/helpers/sql-helper.spec.ts +0 -87
  240. package/src/lib/components/code-editor/helpers/sql-helper.ts +0 -44
  241. package/src/lib/components/code-editor/helpers/swift-helper.spec.ts +0 -40
  242. package/src/lib/components/code-editor/helpers/swift-helper.ts +0 -51
  243. package/src/lib/components/code-editor/helpers/typescript-helper.spec.ts +0 -40
  244. package/src/lib/components/code-editor/helpers/typescript-helper.ts +0 -52
  245. package/src/lib/components/code-editor/models/code-editor.model.ts +0 -9
  246. package/src/lib/components/code-editor/models/coding-snapshot.model.ts +0 -4
  247. package/src/lib/components/coding-question/coding-question.component.html +0 -78
  248. package/src/lib/components/coding-question/coding-question.component.scss +0 -76
  249. package/src/lib/components/coding-question/coding-question.component.spec.ts +0 -85
  250. package/src/lib/components/coding-question/coding-question.component.ts +0 -102
  251. package/src/lib/components/coding-section/coding-section.component.html +0 -82
  252. package/src/lib/components/coding-section/coding-section.component.scss +0 -64
  253. package/src/lib/components/coding-section/coding-section.component.spec.ts +0 -257
  254. package/src/lib/components/coding-section/coding-section.component.ts +0 -187
  255. package/src/lib/components/coding-test.module.ts +0 -124
  256. package/src/lib/components/common/truncated-text/truncated-text.component.html +0 -6
  257. package/src/lib/components/common/truncated-text/truncated-text.component.scss +0 -18
  258. package/src/lib/components/common/truncated-text/truncated-text.component.spec.ts +0 -84
  259. package/src/lib/components/common/truncated-text/truncated-text.component.ts +0 -37
  260. package/src/lib/components/configurations/configurations.component.html +0 -57
  261. package/src/lib/components/configurations/configurations.component.scss +0 -42
  262. package/src/lib/components/configurations/configurations.component.spec.ts +0 -186
  263. package/src/lib/components/configurations/configurations.component.ts +0 -98
  264. package/src/lib/components/instructions/instructions.component.html +0 -41
  265. package/src/lib/components/instructions/instructions.component.scss +0 -167
  266. package/src/lib/components/instructions/instructions.component.spec.ts +0 -106
  267. package/src/lib/components/instructions/instructions.component.ts +0 -138
  268. package/src/lib/components/panel/panel.component.html +0 -19
  269. package/src/lib/components/panel/panel.component.scss +0 -41
  270. package/src/lib/components/panel/panel.component.spec.ts +0 -40
  271. package/src/lib/components/panel/panel.component.ts +0 -34
  272. package/src/lib/components/runnable-editor/runnable-editor.component.html +0 -75
  273. package/src/lib/components/runnable-editor/runnable-editor.component.scss +0 -55
  274. package/src/lib/components/runnable-editor/runnable-editor.component.spec.ts +0 -124
  275. package/src/lib/components/runnable-editor/runnable-editor.component.ts +0 -155
  276. package/src/lib/components/tests/test-cases/test-cases.component.html +0 -135
  277. package/src/lib/components/tests/test-cases/test-cases.component.scss +0 -220
  278. package/src/lib/components/tests/test-cases/test-cases.component.spec.ts +0 -401
  279. package/src/lib/components/tests/test-cases/test-cases.component.ts +0 -205
  280. package/src/lib/components/tests/test-cases-content/test-cases-content.component.html +0 -94
  281. package/src/lib/components/tests/test-cases-content/test-cases-content.component.scss +0 -103
  282. package/src/lib/components/tests/test-cases-content/test-cases-content.component.spec.ts +0 -122
  283. package/src/lib/components/tests/test-cases-content/test-cases-content.component.ts +0 -102
  284. package/src/lib/components/tests/test-cases-status/test-cases-status.component.html +0 -16
  285. package/src/lib/components/tests/test-cases-status/test-cases-status.component.scss +0 -49
  286. package/src/lib/components/tests/test-cases-status/test-cases-status.component.spec.ts +0 -22
  287. package/src/lib/components/tests/test-cases-status/test-cases-status.component.ts +0 -18
  288. package/src/lib/components/tests/test-results.component.html +0 -119
  289. package/src/lib/components/tests/test-results.component.scss +0 -189
  290. package/src/lib/components/tests/test-results.component.spec.ts +0 -140
  291. package/src/lib/components/tests/test-results.component.ts +0 -98
  292. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.html +0 -96
  293. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.scss +0 -6
  294. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.spec.ts +0 -599
  295. package/src/lib/components/tgo-coding-test/tgo-coding-test.component.ts +0 -279
  296. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.html +0 -36
  297. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.scss +0 -183
  298. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.spec.ts +0 -883
  299. package/src/lib/components/tgo-coding-test-candidate-view/tgo-coding-test-candidate-view.component.ts +0 -575
  300. package/src/lib/config/tgo-coding-test.config.ts +0 -26
  301. package/src/lib/config/tgo-coding-test.token.ts +0 -21
  302. package/src/lib/models/.gitkeep +0 -0
  303. package/src/lib/models/auto-saved-data.ts +0 -51
  304. package/src/lib/models/code-event.ts +0 -17
  305. package/src/lib/models/coderunner-execution-results.ts +0 -58
  306. package/src/lib/models/coding-lib.mocks.ts +0 -246
  307. package/src/lib/models/configs.ts +0 -18
  308. package/src/lib/models/language-change-action.ts +0 -4
  309. package/src/lib/models/lat-languages.ts +0 -12
  310. package/src/lib/models/mixpanel-events.ts +0 -3
  311. package/src/lib/models/mode.ts +0 -5
  312. package/src/lib/models/paste-data.ts +0 -4
  313. package/src/lib/models/programming-language.ts +0 -9
  314. package/src/lib/models/test-cases.ts +0 -74
  315. package/src/lib/models/theme.ts +0 -5
  316. package/src/lib/models/translations.ts +0 -1
  317. package/src/lib/models/view-mode.ts +0 -6
  318. package/src/lib/services/.gitkeep +0 -0
  319. package/src/lib/services/candidate-coding-test-services/candidature-api.service.spec.ts +0 -40
  320. package/src/lib/services/candidate-coding-test-services/candidature-api.service.ts +0 -15
  321. package/src/lib/services/candidate-coding-test-services/coderunner-api.service.spec.ts +0 -134
  322. package/src/lib/services/candidate-coding-test-services/coderunner-api.service.ts +0 -105
  323. package/src/lib/services/candidate-coding-test-services/coding-test-tour.service.spec.ts +0 -161
  324. package/src/lib/services/candidate-coding-test-services/coding-test-tour.service.ts +0 -100
  325. package/src/lib/services/candidate-coding-test-services/coding-test.service.spec.ts +0 -1524
  326. package/src/lib/services/candidate-coding-test-services/coding-test.service.ts +0 -843
  327. package/src/lib/services/coding-test-config.service.ts +0 -48
  328. package/src/lib/services/configurations.service.mocks.ts +0 -77
  329. package/src/lib/services/configurations.service.spec.ts +0 -79
  330. package/src/lib/services/configurations.service.ts +0 -111
  331. package/src/lib/services/index.ts +0 -0
  332. package/src/lib/services/lib-coding-test.service.spec.ts +0 -265
  333. package/src/lib/services/lib-coding-test.service.ts +0 -157
  334. package/src/lib/services/local-storage.service.mocks.ts +0 -22
  335. package/src/lib/services/storage.service.spec.ts +0 -1120
  336. package/src/lib/services/storage.service.ts +0 -729
  337. package/src/lib/services/test-cases.service.spec.ts +0 -53
  338. package/src/lib/services/test-cases.service.ts +0 -29
  339. package/src/lib/services/theme.service.spec.ts +0 -76
  340. package/src/lib/services/theme.service.ts +0 -34
  341. package/src/lib/styles/mixins.scss +0 -86
  342. package/src/lib/styles/styles.scss +0 -112
  343. package/src/lib/styles/variables.scss +0 -105
  344. package/src/lib/utils/.gitkeep +0 -0
  345. package/src/lib/utils/additional-languages/erlang.ts +0 -115
  346. package/src/lib/utils/resize-element.ts +0 -15
  347. package/src/lib/utils/time-to-ms.util.ts +0 -10
  348. package/src/test-setup.ts +0 -1
  349. package/tsconfig.json +0 -16
  350. package/tsconfig.lib.json +0 -12
  351. package/tsconfig.lib.prod.json +0 -9
  352. package/tsconfig.spec.json +0 -13
  353. /package/{src/assets → assets}/i18n/en.json +0 -0
  354. /package/{src/lib/components/code-editor/helpers/index.ts → lib/components/code-editor/helpers/index.d.ts} +0 -0
@@ -0,0 +1,624 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { LocalStorageService } from 'ngx-webstorage';
3
+ import { filter } from 'rxjs';
4
+ import { AssessmentIdPreview } from '../models/lat-languages';
5
+ import { ConfigurationsService } from './configurations.service';
6
+ import { LibCodingTestService } from './lib-coding-test.service';
7
+ import { timeToMs } from '../utils/time-to-ms.util';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "ngx-webstorage";
10
+ import * as i2 from "./lib-coding-test.service";
11
+ import * as i3 from "./configurations.service";
12
+ export class StorageCodingService {
13
+ storage;
14
+ libCodingTestService;
15
+ configurationsService;
16
+ CURRENT_STORAGE_VERSION = 2;
17
+ autoSavedData = {
18
+ version: this.CURRENT_STORAGE_VERSION,
19
+ config: {},
20
+ isFullscreen: false,
21
+ assessments: {},
22
+ lastModified: Date.now(),
23
+ };
24
+ key = 'savedData';
25
+ assessmentId;
26
+ questionId;
27
+ language;
28
+ codeSaveEnabled;
29
+ testCasesSaveEnabled;
30
+ isLAT;
31
+ currentMode;
32
+ isPreview;
33
+ codeChangeSubscription;
34
+ configSubscription;
35
+ isFullscreenSubscription;
36
+ currentLanguageSubscription;
37
+ isCodeComponentAlive = filter(() => !this.configurationsService.getCodeComponentDestroyed());
38
+ // Maximum age of entire storage data in days
39
+ MAX_STORAGE_AGE_DAYS = 7;
40
+ // Maximum age for assessment inner data in days
41
+ MAX_QUESTION_DATA_AGE_DAYS = 1;
42
+ // Maximum number of assessments to keep
43
+ MAX_ASSESSMENTS = 10;
44
+ // The default question ID used for migrated v1 data
45
+ DEFAULT_MIGRATION_QUESTION_ID = 'default-question';
46
+ // todo: remove
47
+ // storage = {
48
+ // retrieve: (key: string) => {
49
+ // return {} as any;
50
+ // },
51
+ // store: (key: string, value: any) => {
52
+ // return {} as any;
53
+ // },
54
+ // clear: (key: string) => {
55
+ // return {} as any;
56
+ // },
57
+ // };
58
+ constructor(
59
+ // todo
60
+ storage, libCodingTestService, configurationsService) {
61
+ this.storage = storage;
62
+ this.libCodingTestService = libCodingTestService;
63
+ this.configurationsService = configurationsService;
64
+ // Perform safety check on localStorage data
65
+ this.performStorageSafetyCheck();
66
+ }
67
+ /**
68
+ * Performs a safety check on localStorage data.
69
+ * This is called at service initialization to ensure data integrity.
70
+ */
71
+ performStorageSafetyCheck() {
72
+ try {
73
+ const savedData = this.storage.retrieve(this.key);
74
+ // If no data, nothing to check
75
+ if (!savedData) {
76
+ return;
77
+ }
78
+ // Check storage format and migrate if needed
79
+ if (!('version' in savedData)) {
80
+ // It's v1 format, so we'll migrate it when it's actually needed
81
+ // No need to do anything right now
82
+ }
83
+ else {
84
+ // It's v2 format, so we can perform cleanup right away
85
+ this.autoSavedData = savedData;
86
+ }
87
+ }
88
+ catch (error) {
89
+ // If any error occurs during safety check, reset storage to avoid issues
90
+ console.error('Error during storage safety check, resetting storage:', error);
91
+ this.autoSavedData = {
92
+ version: this.CURRENT_STORAGE_VERSION,
93
+ config: {},
94
+ isFullscreen: false,
95
+ assessments: {},
96
+ lastModified: Date.now(),
97
+ };
98
+ this.storeData();
99
+ }
100
+ }
101
+ initializeSaving() {
102
+ if (!this.codeChangeSubscription) {
103
+ this.codeChangeSubscription = this.libCodingTestService.codeChange$
104
+ .pipe(this.isCodeComponentAlive)
105
+ .subscribe((code) => {
106
+ if (this.codeSaveEnabled && this.assessmentId && this.questionId) {
107
+ this.ensureDataStructure();
108
+ const questionData = this.autoSavedData.assessments[this.assessmentId][this.questionId];
109
+ const targetTestData = this.isPreview ? questionData.preview : questionData.actual;
110
+ targetTestData.code[this.language] = code;
111
+ this.updateLastModified(targetTestData);
112
+ this.storeData();
113
+ }
114
+ });
115
+ }
116
+ if (!this.configSubscription) {
117
+ this.configSubscription = this.configurationsService.config$
118
+ .pipe(this.isCodeComponentAlive)
119
+ .subscribe((config) => {
120
+ this.autoSavedData.config = { ...config };
121
+ this.updateLastModified(this.autoSavedData);
122
+ this.storeData();
123
+ });
124
+ }
125
+ if (!this.isFullscreenSubscription) {
126
+ this.isFullscreenSubscription = this.libCodingTestService.isFullscreen$
127
+ .pipe(this.isCodeComponentAlive)
128
+ .subscribe((isFullscreen) => {
129
+ this.autoSavedData.isFullscreen = isFullscreen;
130
+ this.updateLastModified(this.autoSavedData);
131
+ this.storeData();
132
+ });
133
+ }
134
+ if (!this.currentLanguageSubscription && this.isLAT) {
135
+ this.currentLanguageSubscription = this.libCodingTestService.currentLanguage$
136
+ .pipe(this.isCodeComponentAlive)
137
+ .subscribe((language) => {
138
+ this.autoSavedData.lastLanguageLAT = {
139
+ value: language,
140
+ version: this.libCodingTestService.getVersion(),
141
+ };
142
+ this.updateLastModified(this.autoSavedData);
143
+ this.storeData();
144
+ });
145
+ }
146
+ }
147
+ setupAutoSavedData(language, assessmentId, questionId, codeSaveEnabled, testCasesSaveEnabled, isLAT, mode) {
148
+ this.language = language;
149
+ this.assessmentId = assessmentId;
150
+ this.questionId = questionId;
151
+ this.codeSaveEnabled = codeSaveEnabled;
152
+ this.testCasesSaveEnabled = testCasesSaveEnabled;
153
+ this.isLAT = isLAT;
154
+ this.currentMode = mode;
155
+ this.isPreview = mode === "preview" /* Modes.Preview */ || mode === "non-assessment-preview" /* Modes.NonAssessmentPreview */;
156
+ // Get saved data
157
+ const savedData = this.storage.retrieve(this.key);
158
+ // Handle migration if needed
159
+ if (savedData) {
160
+ // Check if it's v1 schema (no version field)
161
+ if (!('version' in savedData)) {
162
+ this.migrateFromV1ToV2(savedData);
163
+ }
164
+ else {
165
+ this.autoSavedData = savedData;
166
+ }
167
+ // Apply loaded config and fullscreen setting
168
+ this.configurationsService.setConfig(this.autoSavedData.config);
169
+ this.libCodingTestService.setFullscreen(this.autoSavedData.isFullscreen);
170
+ }
171
+ }
172
+ migrateFromV1ToV2(v1Data) {
173
+ // Create a new v2 data structure
174
+ const v2Data = {
175
+ version: this.CURRENT_STORAGE_VERSION,
176
+ config: v1Data.config,
177
+ isFullscreen: v1Data.isFullscreen,
178
+ lastLanguageLAT: v1Data.lastLanguageLAT,
179
+ assessments: {},
180
+ lastModified: Date.now(),
181
+ };
182
+ // Migrate assessment data
183
+ // In v1, assessments were directly mapped to TestData
184
+ // In v2, we need to organize by questionId
185
+ for (const [assessmentId, testData] of Object.entries(v1Data.assessments)) {
186
+ if (assessmentId === AssessmentIdPreview) {
187
+ continue;
188
+ }
189
+ // We use a consistent default questionId for migration to ensure backward compatibility
190
+ const defaultQuestionId = this.DEFAULT_MIGRATION_QUESTION_ID;
191
+ // Initialize the assessment entry if it doesn't exist
192
+ if (!v2Data.assessments[assessmentId]) {
193
+ v2Data.assessments[assessmentId] = {};
194
+ }
195
+ // Create question data with the migrated test data
196
+ const questionData = {};
197
+ questionData.actual = {
198
+ ...testData,
199
+ lastModified: Date.now(),
200
+ };
201
+ // Set last modified time for the question data
202
+ questionData.lastModified = Date.now();
203
+ // Add to the v2 structure
204
+ v2Data.assessments[assessmentId][defaultQuestionId] = questionData;
205
+ }
206
+ // Update our instance with migrated data
207
+ this.autoSavedData = { ...v2Data };
208
+ // Save the migrated data
209
+ this.storeData();
210
+ }
211
+ ensureDataStructure() {
212
+ // Make sure assessment exists
213
+ if (!this.autoSavedData.assessments[this.assessmentId]) {
214
+ this.autoSavedData.assessments[this.assessmentId] = {};
215
+ }
216
+ // Make sure question exists
217
+ if (!this.autoSavedData.assessments[this.assessmentId][this.questionId]) {
218
+ this.autoSavedData.assessments[this.assessmentId][this.questionId] = {
219
+ lastModified: Date.now(),
220
+ };
221
+ }
222
+ const questionData = this.autoSavedData.assessments[this.assessmentId][this.questionId];
223
+ // Ensure preview or actual exists based on current mode
224
+ if (this.isPreview && !questionData.preview) {
225
+ questionData.preview = {
226
+ code: {},
227
+ testCasesLAT: [],
228
+ lastModified: Date.now(),
229
+ };
230
+ }
231
+ else if (!this.isPreview && !questionData.actual) {
232
+ questionData.actual = {
233
+ code: {},
234
+ testCasesLAT: [],
235
+ lastModified: Date.now(),
236
+ };
237
+ }
238
+ }
239
+ updateLastModified(data) {
240
+ const now = Date.now();
241
+ data.lastModified = now;
242
+ // If updating a TestData, also update its parent QuestionData
243
+ if ('code' in data && this.assessmentId && this.questionId) {
244
+ this.autoSavedData.assessments[this.assessmentId][this.questionId].lastModified = now;
245
+ }
246
+ // Always update root timestamp regardless of the object being modified
247
+ this.autoSavedData.lastModified = now;
248
+ }
249
+ /**
250
+ * Cleanup with a temporary age threshold
251
+ * @param maxAgeDays Maximum age in days for data to be considered valid
252
+ */
253
+ cleanupWithReducedThreshold(maxAgeDays) {
254
+ // Call the unified cleanup method with more aggressive parameters
255
+ this.cleanupStorageData({
256
+ storageAgeMultiplier: 2, // More aggressive multiplier
257
+ customStorageAgeDays: maxAgeDays, // Use the provided custom age
258
+ minQuestionDataAgeDays: 0.5, // 12 hours minimum
259
+ assessmentLimitMultiplier: 0.5, // Half the normal assessment limit
260
+ });
261
+ }
262
+ /**
263
+ * Unified method to clean up localStorage data with configurable intensity
264
+ * @param options Cleanup options to control the aggressiveness of the cleanup
265
+ */
266
+ cleanupStorageData(options) {
267
+ const now = Date.now();
268
+ // Determine the storage age threshold
269
+ const storageAgeDays = options.customStorageAgeDays ?? this.MAX_STORAGE_AGE_DAYS;
270
+ const storageAgeThreshold = timeToMs(storageAgeDays); // Convert days to milliseconds
271
+ const multiplier = options.storageAgeMultiplier ?? 1;
272
+ // Check if the entire storage is too old and needs cleanup
273
+ if (this.autoSavedData.lastModified && now - this.autoSavedData.lastModified > storageAgeThreshold * multiplier) {
274
+ // If the entire storage is very old, just reset everything
275
+ this.autoSavedData = {
276
+ version: this.CURRENT_STORAGE_VERSION,
277
+ config: this.autoSavedData.config, // Keep the config settings
278
+ isFullscreen: this.autoSavedData.isFullscreen, // Keep fullscreen setting
279
+ assessments: {},
280
+ lastModified: now,
281
+ };
282
+ this.storeData();
283
+ return;
284
+ }
285
+ const assessmentMetadata = [];
286
+ // Determine the question data age threshold
287
+ let questionDataAgeThreshold;
288
+ if (options.useStandardQuestionDataAge) {
289
+ // Use the standard threshold for normal cleanup
290
+ questionDataAgeThreshold = timeToMs(this.MAX_QUESTION_DATA_AGE_DAYS);
291
+ }
292
+ else {
293
+ // For maintenance/aggressive cleanup, use a custom threshold
294
+ const minAgeHours = (options.minQuestionDataAgeDays ?? 0.5) * 24; // Convert days to hours
295
+ questionDataAgeThreshold = Math.max(timeToMs(this.MAX_QUESTION_DATA_AGE_DAYS), // Standard age in milliseconds
296
+ timeToMs(minAgeHours, 'hours') // Minimum age in milliseconds
297
+ );
298
+ }
299
+ // Collect assessments with their latest modification times
300
+ for (const [assessmentId, questions] of Object.entries(this.autoSavedData.assessments)) {
301
+ let assessmentLastModified = 0;
302
+ // Check all questions in this assessment
303
+ let hasValidQuestions = false;
304
+ for (const [questionId, questionData] of Object.entries(questions)) {
305
+ // Skip if undefined
306
+ if (!questionData) {
307
+ continue;
308
+ }
309
+ // Get the latest modification time from preview and actual
310
+ const previewTime = questionData.preview?.lastModified || 0;
311
+ const actualTime = questionData.actual?.lastModified || 0;
312
+ const questionLastModified = Math.max(previewTime, actualTime, questionData.lastModified || 0);
313
+ // Check if data is too old - using configured threshold
314
+ const isPreviewTooOld = previewTime > 0 && now - previewTime > questionDataAgeThreshold;
315
+ const isActualTooOld = actualTime > 0 && now - actualTime > questionDataAgeThreshold;
316
+ // Clean up old data within the question
317
+ if (isPreviewTooOld && questionData.preview) {
318
+ delete questionData.preview;
319
+ }
320
+ if (isActualTooOld && questionData.actual) {
321
+ delete questionData.actual;
322
+ }
323
+ // If neither preview nor actual exists, remove the question
324
+ if (!questionData.preview && !questionData.actual) {
325
+ delete questions[questionId];
326
+ }
327
+ else {
328
+ hasValidQuestions = true;
329
+ assessmentLastModified = Math.max(assessmentLastModified, questionLastModified);
330
+ }
331
+ }
332
+ // If no valid questions, remove the assessment
333
+ if (!hasValidQuestions) {
334
+ delete this.autoSavedData.assessments[assessmentId];
335
+ }
336
+ else {
337
+ // Add to our list for potential size-based cleanup
338
+ assessmentMetadata.push({
339
+ id: assessmentId,
340
+ lastModified: assessmentLastModified,
341
+ });
342
+ }
343
+ }
344
+ // Determine the assessment limit based on the multiplier
345
+ const limitMultiplier = options.assessmentLimitMultiplier ?? 1;
346
+ const assessmentLimit = Math.ceil(this.MAX_ASSESSMENTS * limitMultiplier);
347
+ // If we have too many assessments, remove the oldest ones
348
+ if (assessmentMetadata.length > assessmentLimit) {
349
+ // Sort by lastModified (most recent first)
350
+ assessmentMetadata.sort((a, b) => b.lastModified - a.lastModified);
351
+ // Remove oldest assessments that exceed our limit
352
+ for (let i = assessmentLimit; i < assessmentMetadata.length; i++) {
353
+ delete this.autoSavedData.assessments[assessmentMetadata[i].id];
354
+ }
355
+ }
356
+ // Save the cleaned data
357
+ this.storeData();
358
+ }
359
+ changeLanguage(language) {
360
+ this.language = language;
361
+ }
362
+ /**
363
+ * Gets data from v1 schema format
364
+ * Used for backward compatibility when retrieving data
365
+ */
366
+ getDataFromV1Schema(retrievedData) {
367
+ // For v1, we need to handle the case where we don't have questionId
368
+ // We're now using questionId in the app, but stored data might still be in v1 format
369
+ // For preview data, the assessment ID would be AssessmentIdPreview
370
+ if (this.assessmentId === AssessmentIdPreview) {
371
+ if (this.isPreview) {
372
+ // For preview mode on preview assessment, get the code directly
373
+ const code = retrievedData.assessments[this.assessmentId]?.code;
374
+ if (code && this.language in code) {
375
+ return code[this.language];
376
+ }
377
+ }
378
+ // We don't expect actual/non-preview data for AssessmentIdPreview
379
+ return null;
380
+ }
381
+ else {
382
+ // For regular assessments, v1 only had code in the "actual" section
383
+ if (!this.isPreview) {
384
+ const code = retrievedData.assessments[this.assessmentId]?.code;
385
+ if (code && this.language in code) {
386
+ return code[this.language];
387
+ }
388
+ }
389
+ // We don't have preview data for regular assessments in v1
390
+ return null;
391
+ }
392
+ }
393
+ getSavedCode() {
394
+ const retrievedData = this.retrieveData();
395
+ if (!retrievedData) {
396
+ return null;
397
+ }
398
+ // Check if using v2 schema
399
+ if ('version' in retrievedData) {
400
+ // Handle v2 schema
401
+ const v2Data = retrievedData;
402
+ const assessmentData = v2Data.assessments[this.assessmentId];
403
+ if (!assessmentData) {
404
+ return null;
405
+ }
406
+ // First try with provided questionId
407
+ if (this.questionId && assessmentData[this.questionId]) {
408
+ const questionData = assessmentData[this.questionId];
409
+ const testData = this.isPreview ? questionData.preview : questionData.actual;
410
+ if (testData?.code && this.language in testData.code) {
411
+ return testData.code[this.language];
412
+ }
413
+ }
414
+ if (this.questionId !== this.DEFAULT_MIGRATION_QUESTION_ID &&
415
+ assessmentData[this.DEFAULT_MIGRATION_QUESTION_ID]) {
416
+ const questionData = assessmentData[this.DEFAULT_MIGRATION_QUESTION_ID];
417
+ const testData = this.isPreview ? questionData.preview : questionData.actual;
418
+ if (testData?.code && this.language in testData.code) {
419
+ return testData.code[this.language];
420
+ }
421
+ }
422
+ return null;
423
+ }
424
+ else {
425
+ // Handle v1 schema for backward compatibility
426
+ return this.getDataFromV1Schema(retrievedData);
427
+ }
428
+ }
429
+ getLastLanguageLAT() {
430
+ const retrievedData = this.retrieveData();
431
+ if (!retrievedData) {
432
+ return null;
433
+ }
434
+ return retrievedData.lastLanguageLAT || null;
435
+ }
436
+ getSavedTestCases() {
437
+ const retrievedData = this.retrieveData();
438
+ if (!retrievedData) {
439
+ return null;
440
+ }
441
+ // Check if using v2 schema
442
+ if ('version' in retrievedData) {
443
+ // Handle v2 schema
444
+ const v2Data = retrievedData;
445
+ const assessmentData = v2Data.assessments[this.assessmentId];
446
+ if (!assessmentData) {
447
+ return null;
448
+ }
449
+ // First try with provided questionId
450
+ if (this.questionId && assessmentData[this.questionId]) {
451
+ const questionData = assessmentData[this.questionId];
452
+ const testData = this.isPreview ? questionData.preview : questionData.actual;
453
+ if (testData?.testCasesLAT) {
454
+ return testData.testCasesLAT;
455
+ }
456
+ }
457
+ // If not found and questionId != DEFAULT_MIGRATION_QUESTION_ID,
458
+ // also try with the default migration ID as a fallback
459
+ if (this.questionId !== this.DEFAULT_MIGRATION_QUESTION_ID &&
460
+ assessmentData[this.DEFAULT_MIGRATION_QUESTION_ID]) {
461
+ const questionData = assessmentData[this.DEFAULT_MIGRATION_QUESTION_ID];
462
+ const testData = this.isPreview ? questionData.preview : questionData.actual;
463
+ if (testData?.testCasesLAT) {
464
+ return testData.testCasesLAT;
465
+ }
466
+ }
467
+ return null;
468
+ }
469
+ else {
470
+ // Handle v1 schema test cases (test cases were only in the actual mode)
471
+ const v1Data = retrievedData;
472
+ if (!this.isPreview && v1Data.assessments[this.assessmentId]?.testCasesLAT) {
473
+ return v1Data.assessments[this.assessmentId].testCasesLAT;
474
+ }
475
+ return null;
476
+ }
477
+ }
478
+ getSavedConfig() {
479
+ const retrievedData = this.retrieveData();
480
+ return retrievedData?.config ? { ...retrievedData.config } : null;
481
+ }
482
+ getSavedFullScreenMode() {
483
+ const retrievedData = this.retrieveData();
484
+ return retrievedData?.isFullscreen !== undefined ? retrievedData.isFullscreen : null;
485
+ }
486
+ clearSavedCode() {
487
+ this.ensureDataStructure();
488
+ const questionData = this.autoSavedData.assessments[this.assessmentId][this.questionId];
489
+ const targetTestData = this.isPreview ? [questionData.preview] : [questionData.preview, questionData.actual];
490
+ let hasChanged = false;
491
+ targetTestData.forEach(testData => {
492
+ if (testData) {
493
+ testData.code = {};
494
+ this.updateLastModified(testData);
495
+ hasChanged = true;
496
+ }
497
+ });
498
+ if (hasChanged) {
499
+ this.storeData();
500
+ }
501
+ }
502
+ clearLastLang() {
503
+ this.autoSavedData.lastLanguageLAT = null;
504
+ this.updateLastModified(this.autoSavedData);
505
+ this.storeData();
506
+ }
507
+ clearSavedTestCases() {
508
+ this.ensureDataStructure();
509
+ const questionData = this.autoSavedData.assessments[this.assessmentId][this.questionId];
510
+ const targetTestData = this.isPreview ? questionData.preview : questionData.actual;
511
+ if (targetTestData) {
512
+ const hasNoCode = !Object.keys(targetTestData.code ?? {}).length;
513
+ if (this.isPreview) {
514
+ targetTestData.testCasesLAT = [];
515
+ this.updateLastModified(targetTestData);
516
+ }
517
+ else if (hasNoCode) {
518
+ const allQuestions = this.autoSavedData.assessments[this.assessmentId];
519
+ delete allQuestions[this.questionId];
520
+ this.autoSavedData.assessments[this.assessmentId] = { ...allQuestions };
521
+ this.updateLastModified(this.autoSavedData);
522
+ }
523
+ this.storeData();
524
+ }
525
+ }
526
+ updateVersion(version) {
527
+ if (this.autoSavedData.lastLanguageLAT) {
528
+ this.autoSavedData.lastLanguageLAT.version = version;
529
+ this.updateLastModified(this.autoSavedData);
530
+ this.storeData();
531
+ }
532
+ }
533
+ updateTestCases(testCases) {
534
+ if (this.assessmentId && this.questionId && this.testCasesSaveEnabled) {
535
+ this.ensureDataStructure();
536
+ const questionData = this.autoSavedData.assessments[this.assessmentId][this.questionId];
537
+ const targetTestData = this.isPreview ? questionData.preview : questionData.actual;
538
+ if (targetTestData) {
539
+ targetTestData.testCasesLAT = testCases;
540
+ this.updateLastModified(targetTestData);
541
+ this.storeData();
542
+ }
543
+ }
544
+ }
545
+ storeData() {
546
+ this.storage.store(this.key, this.autoSavedData);
547
+ }
548
+ retrieveData() {
549
+ return this.storage.retrieve(this.key);
550
+ }
551
+ /**
552
+ * Manually triggers data cleanup and migration.
553
+ * Useful for handling large localStorage or migration when needed.
554
+ * This can be called from application startup or after major events.
555
+ */
556
+ performMaintenanceAndCleanup() {
557
+ // Get current data
558
+ const savedData = this.storage.retrieve(this.key);
559
+ // If no data, nothing to do
560
+ if (!savedData) {
561
+ return;
562
+ }
563
+ // Check if migration needed
564
+ if (!('version' in savedData)) {
565
+ this.migrateFromV1ToV2(savedData);
566
+ }
567
+ else {
568
+ // Already migrated, just perform cleanup
569
+ this.autoSavedData = savedData;
570
+ // Perform a more aggressive cleanup for manual maintenance
571
+ // by temporarily modifying the cleanup thresholds
572
+ const originalMaxAge = this.MAX_STORAGE_AGE_DAYS;
573
+ const halfAge = Math.floor(originalMaxAge / 2); // Cut threshold in half
574
+ // Create a custom cleanup function with reduced threshold
575
+ this.cleanupWithReducedThreshold(halfAge);
576
+ }
577
+ // Verify localStorage size is manageable
578
+ try {
579
+ const serializedData = JSON.stringify(this.autoSavedData);
580
+ const sizeInKB = Math.round(serializedData.length / 1024);
581
+ // If data is too large (over 2MB), perform more aggressive cleanup
582
+ if (sizeInKB > 2048) {
583
+ console.warn(`Local storage data is large (${sizeInKB}KB), performing deep cleanup`);
584
+ // Use extremely aggressive cleanup settings
585
+ this.cleanupStorageData({
586
+ storageAgeMultiplier: 0.5, // Even more aggressive - half the normal age
587
+ minQuestionDataAgeDays: 0.25, // 6 hours minimum
588
+ assessmentLimitMultiplier: 0.2, // Keep only 20% of assessments
589
+ });
590
+ // If still too large, keep only a few most recent assessments
591
+ const newSerializedData = JSON.stringify(this.autoSavedData);
592
+ const newSizeInKB = Math.round(newSerializedData.length / 1024);
593
+ if (newSizeInKB > 1024) {
594
+ // Keep only recent assessments
595
+ const assessments = this.autoSavedData.assessments;
596
+ // Find the newest timestamp in each assessment
597
+ const getNewestTimestamp = (obj) => Object.values(obj).reduce((max, questionData) => Math.max(max, questionData?.lastModified || 0), 0);
598
+ const entries = Object.entries(assessments).sort(([, a], [, b]) => getNewestTimestamp(b) -
599
+ getNewestTimestamp(a));
600
+ // Keep only the 5 most recent assessments
601
+ const keepCount = Math.min(5, entries.length);
602
+ this.autoSavedData.assessments = {};
603
+ for (let i = 0; i < keepCount; i++) {
604
+ const [id, data] = entries[i];
605
+ this.autoSavedData.assessments[id] = data;
606
+ }
607
+ this.storeData();
608
+ }
609
+ }
610
+ }
611
+ catch (error) {
612
+ console.error('Error checking localStorage size', error);
613
+ }
614
+ }
615
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StorageCodingService, deps: [{ token: i1.LocalStorageService }, { token: i2.LibCodingTestService }, { token: i3.ConfigurationsService }], target: i0.ɵɵFactoryTarget.Injectable });
616
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StorageCodingService, providedIn: 'root' });
617
+ }
618
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StorageCodingService, decorators: [{
619
+ type: Injectable,
620
+ args: [{
621
+ providedIn: 'root',
622
+ }]
623
+ }], ctorParameters: () => [{ type: i1.LocalStorageService }, { type: i2.LibCodingTestService }, { type: i3.ConfigurationsService }] });
624
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvdGdvLWNvZGluZy10ZXN0L3NyYy9saWIvc2VydmljZXMvc3RvcmFnZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckQsT0FBTyxFQUFFLE1BQU0sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFJNUMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHOUQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDakUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDakUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDOzs7OztBQUtwRCxNQUFNLE9BQU8sb0JBQW9CO0lBZ0RyQjtJQUNBO0lBQ0E7SUFqRE8sdUJBQXVCLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLGFBQWEsR0FBa0I7UUFDckMsT0FBTyxFQUFFLElBQUksQ0FBQyx1QkFBdUI7UUFDckMsTUFBTSxFQUFFLEVBQVk7UUFDcEIsWUFBWSxFQUFFLEtBQUs7UUFDbkIsV0FBVyxFQUFFLEVBQUU7UUFDZixZQUFZLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtLQUN6QixDQUFDO0lBQ2UsR0FBRyxHQUFHLFdBQVcsQ0FBQztJQUMzQixZQUFZLENBQVM7SUFDckIsVUFBVSxDQUFTO0lBQ25CLFFBQVEsQ0FBc0I7SUFDOUIsZUFBZSxDQUFVO0lBQ3pCLG9CQUFvQixDQUFVO0lBQzlCLEtBQUssQ0FBVTtJQUNmLFdBQVcsQ0FBUTtJQUNuQixTQUFTLENBQVU7SUFDbkIsc0JBQXNCLENBQWU7SUFDckMsa0JBQWtCLENBQWU7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LENBQUMsYUFBYSxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUM7b0JBRXBDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQzt3QkFDbkMsTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQzlCLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQW9DLENBQUM7b0JBQzVFLENBQUM7b0JBRUQsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNuQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyxrQ0FBa0MsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUMzRCxDQUFDO0lBQ0gsQ0FBQzt3R0F2c0JVLG9CQUFvQjs0R0FBcEIsb0JBQW9CLGNBRm5CLE1BQU07OzRGQUVQLG9CQUFvQjtrQkFIaEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBMb2NhbFN0b3JhZ2VTZXJ2aWNlIH0gZnJvbSAnbmd4LXdlYnN0b3JhZ2UnO1xuaW1wb3J0IHsgZmlsdGVyLCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IENvZGVFZGl0b3JMYW5ndWFnZXMgfSBmcm9tICcuLi9jb21wb25lbnRzL2NvZGUtZWRpdG9yL2hlbHBlcnMvY29kZS1lZGl0b3ItaGVscGVyLm1vZGVsJztcbmltcG9ydCB7IEF1dG9TYXZlZERhdGEsIEF1dG9TYXZlZERhdGFWMSwgQXV0b1NhdmVkRGF0YVYyLCBRdWVzdGlvbkRhdGEsIFRlc3REYXRhIH0gZnJvbSAnLi4vbW9kZWxzL2F1dG8tc2F2ZWQtZGF0YSc7XG5pbXBvcnQgeyBDb25maWcgfSBmcm9tICcuLi9tb2RlbHMvY29uZmlncyc7XG5pbXBvcnQgeyBBc3Nlc3NtZW50SWRQcmV2aWV3IH0gZnJvbSAnLi4vbW9kZWxzL2xhdC1sYW5ndWFnZXMnO1xuaW1wb3J0IHsgTW9kZXMgfSBmcm9tICcuLi9tb2RlbHMvbW9kZSc7XG5pbXBvcnQgeyBDdXN0b21UZXN0Q2FzZSwgRXhhbXBsZVRlc3RDYXNlIH0gZnJvbSAnLi4vbW9kZWxzL3Rlc3QtY2FzZXMnO1xuaW1wb3J0IHsgQ29uZmlndXJhdGlvbnNTZXJ2aWNlIH0gZnJvbSAnLi9jb25maWd1cmF0aW9ucy5zZXJ2aWNlJztcbmltcG9ydCB7IExpYkNvZGluZ1Rlc3RTZXJ2aWNlIH0gZnJvbSAnLi9saWItY29kaW5nLXRlc3Quc2VydmljZSc7XG5pbXBvcnQgeyB0aW1lVG9NcyB9IGZyb20gJy4uL3V0aWxzL3RpbWUtdG8tbXMudXRpbCc7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBTdG9yYWdlQ29kaW5nU2VydmljZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgQ1VSUkVOVF9TVE9SQUdFX1ZFUlNJT04gPSAyO1xuICBwcml2YXRlIGF1dG9TYXZlZERhdGE6IEF1dG9TYXZlZERhdGEgPSB7XG4gICAgdmVyc2lvbjogdGhpcy5DVVJSRU5UX1NUT1JBR0VfVkVSU0lPTixcbiAgICBjb25maWc6IHt9IGFzIENvbmZpZyxcbiAgICBpc0Z1bGxzY3JlZW46IGZhbHNlLFxuICAgIGFzc2Vzc21lbnRzOiB7fSxcbiAgICBsYXN0TW9kaWZpZWQ6IERhdGUubm93KCksXG4gIH07XG4gIHByaXZhdGUgcmVhZG9ubHkga2V5ID0gJ3NhdmVkRGF0YSc7XG4gIHByaXZhdGUgYXNzZXNzbWVudElkOiBzdHJpbmc7XG4gIHByaXZhdGUgcXVlc3Rpb25JZDogc3RyaW5nO1xuICBwcml2YXRlIGxhbmd1YWdlOiBDb2RlRWRpdG9yTGFuZ3VhZ2VzO1xuICBwcml2YXRlIGNvZGVTYXZlRW5hYmxlZDogYm9vbGVhbjtcbiAgcHJpdmF0ZSB0ZXN0Q2FzZXNTYXZlRW5hYmxlZDogYm9vbGVhbjtcbiAgcHJpdmF0ZSBpc0xBVDogYm9vbGVhbjtcbiAgcHJpdmF0ZSBjdXJyZW50TW9kZTogTW9kZXM7XG4gIHByaXZhdGUgaXNQcmV2aWV3OiBib29sZWFuO1xuICBwcml2YXRlIGNvZGVDaGFuZ2VTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBjb25maWdTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBpc0Z1bGxzY3JlZW5TdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBjdXJyZW50TGFuZ3VhZ2VTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBpc0NvZGVDb21wb25lbnRBbGl2ZSA9IGZpbHRlcigoKSA9PiAhdGhpcy5jb25maWd1cmF0aW9uc1NlcnZpY2UuZ2V0Q29kZUNvbXBvbmVudERlc3Ryb3llZCgpKTtcblxuICAvLyBNYXhpbXVtIGFnZSBvZiBlbnRpcmUgc3RvcmFnZSBkYXRhIGluIGRheXNcbiAgcHJpdmF0ZSByZWFkb25seSBNQVhfU1RPUkFHRV9BR0VfREFZUyA9IDc7XG4gIC8vIE1heGltdW0gYWdlIGZvciBhc3Nlc3NtZW50IGlubmVyIGRhdGEgaW4gZGF5c1xuICBwcml2YXRlIHJlYWRvbmx5IE1BWF9RVUVTVElPTl9EQVRBX0FHRV9EQVlTID0gMTtcbiAgLy8gTWF4aW11bSBudW1iZXIgb2YgYXNzZXNzbWVudHMgdG8ga2VlcFxuICBwcml2YXRlIHJlYWRvbmx5IE1BWF9BU1NFU1NNRU5UUyA9IDEwO1xuICAvLyBUaGUgZGVmYXVsdCBxdWVzdGlvbiBJRCB1c2VkIGZvciBtaWdyYXRlZCB2MSBkYXRhXG4gIHByaXZhdGUgcmVhZG9ubHkgREVGQVVMVF9NSUdSQVRJT05fUVVFU1RJT05fSUQgPSAnZGVmYXVsdC1xdWVzdGlvbic7XG5cbiAgLy8gdG9kbzogcmVtb3ZlXG4gIC8vIHN0b3JhZ2UgPSB7XG4gIC8vICAgcmV0cmlldmU6IChrZXk6IHN0cmluZykgPT4ge1xuICAvLyAgICAgcmV0dXJuIHt9IGFzIGFueTtcbiAgLy8gICB9LFxuICAvLyAgIHN0b3JlOiAoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpID0+IHtcbiAgLy8gICAgIHJldHVybiB7fSBhcyBhbnk7XG4gIC8vICAgfSxcbiAgLy8gICBjbGVhcjogKGtleTogc3RyaW5nKSA9PiB7XG4gIC8vICAgICByZXR1cm4ge30gYXMgYW55O1xuICAvLyAgIH0sXG4gIC8vIH07XG5cbiAgY29uc3RydWN0b3IoXG4gICAgLy8gdG9kb1xuICAgIHByaXZhdGUgc3RvcmFnZTogTG9jYWxTdG9yYWdlU2VydmljZSxcbiAgICBwcml2YXRlIGxpYkNvZGluZ1Rlc3RTZXJ2aWNlOiBMaWJDb2RpbmdUZXN0U2VydmljZSxcbiAgICBwcml2YXRlIGNvbmZpZ3VyYXRpb25zU2VydmljZTogQ29uZmlndXJhdGlvbnNTZXJ2aWNlXG4gICkge1xuICAgIC8vIFBlcmZvcm0gc2FmZXR5IGNoZWNrIG9uIGxvY2FsU3RvcmFnZSBkYXRhXG4gICAgdGhpcy5wZXJmb3JtU3RvcmFnZVNhZmV0eUNoZWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgYSBzYWZldHkgY2hlY2sgb24gbG9jYWxTdG9yYWdlIGRhdGEuXG4gICAqIFRoaXMgaXMgY2FsbGVkIGF0IHNlcnZpY2UgaW5pdGlhbGl6YXRpb24gdG8gZW5zdXJlIGRhdGEgaW50ZWdyaXR5LlxuICAgKi9cbiAgcHJpdmF0ZSBwZXJmb3JtU3RvcmFnZVNhZmV0eUNoZWNrKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzYXZlZERhdGEgPSB0aGlzLnN0b3JhZ2UucmV0cmlldmUodGhpcy5rZXkpO1xuXG4gICAgICAvLyBJZiBubyBkYXRhLCBub3RoaW5nIHRvIGNoZWNrXG4gICAgICBpZiAoIXNhdmVkRGF0YSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIENoZWNrIHN0b3JhZ2UgZm9ybWF0IGFuZCBtaWdyYXRlIGlmIG5lZWRlZFxuICAgICAgaWYgKCEoJ3ZlcnNpb24nIGluIHNhdmVkRGF0YSkpIHtcbiAgICAgICAgLy8gSXQncyB2MSBmb3JtYXQsIHNvIHdlJ2xsIG1pZ3JhdGUgaXQgd2hlbiBpdCdzIGFjdHVhbGx5IG5lZWRlZFxuICAgICAgICAvLyBObyBuZWVkIHRvIGRvIGFueXRoaW5nIHJpZ2h0IG5vd1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSXQncyB2MiBmb3JtYXQsIHNvIHdlIGNhbiBwZXJmb3JtIGNsZWFudXAgcmlnaHQgYXdheVxuICAgICAgICB0aGlzLmF1dG9TYXZlZERhdGEgPSBzYXZlZERhdGEgYXMgQXV0b1NhdmVkRGF0YTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gSWYgYW55IGVycm9yIG9jY3VycyBkdXJpbmcgc2FmZXR5IGNoZWNrLCByZXNldCBzdG9yYWdlIHRvIGF2b2lkIGlzc3Vlc1xuICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZHVyaW5nIHN0b3JhZ2Ugc2FmZXR5IGNoZWNrLCByZXNldHRpbmcgc3RvcmFnZTonLCBlcnJvcik7XG4gICAgICB0aGlzLmF1dG9TYXZlZERhdGEgPSB7XG4gICAgICAgIHZlcnNpb246IHRoaXMuQ1VSUkVOVF9TVE9SQUdFX1ZFUlNJT04sXG4gICAgICAgIGNvbmZpZzoge30gYXMgQ29uZmlnLFxuICAgICAgICBpc0Z1bGxzY3JlZW46IGZhbHNlLFxuICAgICAgICBhc3Nlc3NtZW50czoge30sXG4gICAgICAgIGxhc3RNb2RpZmllZDogRGF0ZS5ub3coKSxcbiAgICAgIH07XG4gICAgICB0aGlzLnN0b3JlRGF0YSgpO1xuICAgIH1cbiAgfVxuXG4gIGluaXRpYWxpemVTYXZpbmcoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvZGVDaGFuZ2VTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuY29kZUNoYW5nZVN1YnNjcmlwdGlvbiA9IHRoaXMubGliQ29kaW5nVGVzdFNlcnZpY2UuY29kZUNoYW5nZSRcbiAgICAgICAgLnBpcGUodGhpcy5pc0NvZGVDb21wb25lbnRBbGl2ZSlcbiAgICAgICAgLnN1YnNjcmliZSgoY29kZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuY29kZVNhdmVFbmFibGVkICYmIHRoaXMuYXNzZXNzbWVudElkICYmIHRoaXMucXVlc3Rpb25JZCkge1xuICAgICAgICAgICAgdGhpcy5lbnN1cmVEYXRhU3RydWN0dXJlKCk7XG4gICAgICAgICAgICBjb25zdCBxdWVzdGlvbkRhdGEgPSB0aGlzLmF1dG9TYXZlZERhdGEuYXNzZXNzbWVudHNbdGhpcy5hc3Nlc3NtZW50SWRdW3RoaXMucXVlc3Rpb25JZF07XG4gICAgICAgICAgICBjb25zdCB0YXJnZXRUZXN0RGF0YSA9IHRoaXMuaXNQcmV2aWV3ID8gcXVlc3Rpb25EYXRhLnByZXZpZXcgOiBxdWVzdGlvbkRhdGEuYWN0dWFsO1xuICAgICAgICAgICAgdGFyZ2V0VGVzdERhdGEuY29kZVt0aGlzLmxhbmd1YWdlXSA9IGNvZGUhO1xuICAgICAgICAgICAgdGhpcy51cGRhdGVMYXN0TW9kaWZpZWQodGFyZ2V0VGVzdERhdGEpO1xuICAgICAgICAgICAgdGhpcy5zdG9yZURhdGEoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5jb25maWdTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuY29uZmlnU3Vic2NyaXB0aW9uID0gdGhpcy5jb25maWd1cmF0aW9uc1NlcnZpY2UuY29uZmlnJFxuICAgICAgICAucGlwZSh0aGlzLmlzQ29kZUNvbXBvbmVudEFsaXZlKVxuICAgICAgICAuc3Vic2NyaWJlKChjb25maWc6IENvbmZpZykgPT4ge1xuICAgICAgICAgIHRoaXMuYXV0b1NhdmVkRGF0YS5jb25maWcgPSB7IC4uLmNvbmZpZyB9O1xuICAgICAgICAgIHRoaXMudXBkYXRlTGFzdE1vZGlmaWVkKHRoaXMuYXV0b1NhdmVkRGF0YSk7XG4gICAgICAgICAgdGhpcy5zdG9yZURhdGEoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzRnVsbHNjcmVlblN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5pc0Z1bGxzY3JlZW5TdWJzY3JpcHRpb24gPSB0aGlzLmxpYkNvZGluZ1Rlc3RTZXJ2aWNlLmlzRnVsbHNjcmVlbiRcbiAgICAgICAgLnBpcGUodGhpcy5pc0NvZGVDb21wb25lbnRBbGl2ZSlcbiAgICAgICAgLnN1YnNjcmliZSgoaXNGdWxsc2NyZWVuOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgdGhpcy5hdXRvU2F2ZWREYXRhLmlzRnVsbHNjcmVlbiA9IGlzRnVsbHNjcmVlbjtcbiAgICAgICAgICB0aGlzLnVwZGF0ZUxhc3RNb2RpZmllZCh0aGlzLmF1dG9TYXZlZERhdGEpO1xuICAgICAgICAgIHRoaXMuc3RvcmVEYXRhKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5jdXJyZW50TGFuZ3VhZ2VTdWJzY3JpcHRpb24gJiYgdGhpcy5pc0xBVCkge1xuICAgICAgdGhpcy5jdXJyZW50TGFuZ3VhZ2VTdWJzY3JpcHRpb24gPSB0aGlzLmxpYkNvZGluZ1Rlc3RTZXJ2aWNlLmN1cnJlbnRMYW5ndWFnZSRcbiAgICAgICAgLnBpcGUodGhpcy5pc0NvZGVDb21wb25lbnRBbGl2ZSlcbiAgICAgICAgLnN1YnNjcmliZSgobGFuZ3VhZ2U6IENvZGVFZGl0b3JMYW5ndWFnZXMpID0+IHtcbiAgICAgICAgICB0aGlzLmF1dG9TYXZlZERhdGEubGFzdExhbmd1YWdlTEFUID0ge1xuICAgICAgICAgICAgdmFsdWU6IGxhbmd1YWdlLFxuICAgICAgICAgICAgdmVyc2lvbjogdGhpcy5saWJDb2RpbmdUZXN0U2VydmljZS5nZXRWZXJzaW9uKCksXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZUxhc3RNb2RpZmllZCh0aGlzLmF1dG9TYXZlZERhdGEpO1xuICAgICAgICAgIHRoaXMuc3RvcmVEYXRhKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHNldHVwQXV0b1NhdmVkRGF0YShcbiAgICBsYW5ndWFnZTogQ29kZUVkaXRvckxhbmd1YWdlcyxcbiAgICBhc3Nlc3NtZW50SWQ6IHN0cmluZyxcbiAgICBxdWVzdGlvbklkOiBzdHJpbmcsXG4gICAgY29kZVNhdmVFbmFibGVkOiBib29sZWFuLFxuICAgIHRlc3RDYXNlc1NhdmVFbmFibGVkOiBib29sZWFuLFxuICAgIGlzTEFUOiBib29sZWFuLFxuICAgIG1vZGU6IE1vZGVzXG4gICkge1xuICAgIHRoaXMubGFuZ3VhZ2UgPSBsYW5ndWFnZTtcbiAgICB0aGlzLmFzc2Vzc21lbnRJZCA9IGFzc2Vzc21lbnRJZDtcbiAgICB0aGlzLnF1ZXN0aW9uSWQgPSBxdWVzdGlvbklkO1xuICAgIHRoaXMuY29kZVNhdmVFbmFibGVkID0gY29kZVNhdmVFbmFibGVkO1xuICAgIHRoaXMudGVzdENhc2VzU2F2ZUVuYWJsZWQgPSB0ZXN0Q2FzZXNTYXZlRW5hYmxlZDtcbiAgICB0aGlzLmlzTEFUID0gaXNMQVQ7XG4gICAgdGhpcy5jdXJyZW50TW9kZSA9IG1vZGU7XG4gICAgdGhpcy5pc1ByZXZpZXcgPSBtb2RlID09PSBNb2Rlcy5QcmV2aWV3IHx8IG1vZGUgPT09IE1vZGVzLk5vbkFzc2Vzc21lbnRQcmV2aWV3O1xuXG4gICAgLy8gR2V0IHNhdmVkIGRhdGFcbiAgICBjb25zdCBzYXZlZERhdGEgPSB0aGlzLnN0b3JhZ2UucmV0cmlldmUodGhpcy5rZXkpO1xuXG4gICAgLy8gSGFuZGxlIG1pZ3JhdGlvbiBpZiBuZWVkZWRcbiAgICBpZiAoc2F2ZWREYXRhKSB7XG4gICAgICAvLyBDaGVjayBpZiBpdCdzIHYxIHNjaGVtYSAobm8gdmVyc2lvbiBmaWVsZClcbiAgICAgIGlmICghKCd2ZXJzaW9uJyBpbiBzYXZlZERhdGEpKSB7XG4gICAgICAgIHRoaXMubWlncmF0ZUZyb21WMVRvVjIoc2F2ZWREYXRhIGFzIEF1dG9TYXZlZERhdGFWMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmF1dG9TYXZlZERhdGEgPSBzYXZlZERhdGEgYXMgQXV0b1NhdmVkRGF0YTtcbiAgICAgIH1cblxuICAgICAgLy8gQXBwbHkgbG9hZGVkIGNvbmZpZyBhbmQgZnVsbHNjcmVlbiBzZXR0aW5nXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb25zU2VydmljZS5zZXRDb25maWcodGhpcy5hdXRvU2F2ZWREYXRhLmNvbmZpZyk7XG4gICAgICB0aGlzLmxpYkNvZGluZ1Rlc3RTZXJ2aWNlLnNldEZ1bGxzY3JlZW4odGhpcy5hdXRvU2F2ZWREYXRhLmlzRnVsbHNjcmVlbik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtaWdyYXRlRnJvbVYxVG9WMih2MURhdGE6IEF1dG9TYXZlZERhdGFWMSk6IHZvaWQge1xuICAgIC8vIENyZWF0ZSBhIG5ldyB2MiBkYXRhIHN0cnVjdHVyZVxuICAgIGNvbnN0IHYyRGF0YTogQXV0b1NhdmVkRGF0YVYyID0ge1xuICAgICAgdmVyc2lvbjogdGhpcy5DVVJSRU5UX1NUT1JBR0VfVkVSU0lPTixcbiAgICAgIGNvbmZpZzogdjFEYXRhLmNvbmZpZyxcbiAgICAgIGlzRnVsbHNjcmVlbjogdjFEYXRhLmlzRnVsbHNjcmVlbixcbiAgICAgIGxhc3RMYW5ndWFnZUxBVDogdjFEYXRhLmxhc3RMYW5ndWFnZUxBVCxcbiAgICAgIGFzc2Vzc21lbnRzOiB7fSxcbiAgICAgIGxhc3RNb2RpZmllZDogRGF0ZS5ub3coKSxcbiAgICB9O1xuXG4gICAgLy8gTWlncmF0ZSBhc3Nlc3NtZW50IGRhdGFcbiAgICAvLyBJbiB2MSwgYXNzZXNzbWVudHMgd2VyZSBkaXJlY3RseSBtYXBwZWQgdG8gVGVzdERhdGFcbiAgICAvLyBJbiB2Miwgd2UgbmVlZCB0byBvcmdhbml6ZSBieSBxdWVzdGlvbklkXG4gICAgZm9yIChjb25zdCBbYXNzZXNzbWVudElkLCB0ZXN0RGF0YV0gb2YgT2JqZWN0LmVudHJpZXModjFEYXRhLmFzc2Vzc21lbnRzKSkge1xuICAgICAgaWYgKGFzc2Vzc21lbnRJZCA9PT0gQXNzZXNzbWVudElkUHJldmlldykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gV2UgdXNlIGEgY29uc2lzdGVudCBkZWZhdWx0IHF1ZXN0aW9uSWQgZm9yIG1pZ3JhdGlvbiB0byBlbnN1cmUgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxuICAgICAgY29uc3QgZGVmYXVsdFF1ZXN0aW9uSWQgPSB0aGlzLkRFRkFVTFRfTUlHUkFUSU9OX1FVRVNUSU9OX0lEO1xuXG4gICAgICAvLyBJbml0aWFsaXplIHRoZSBhc3Nlc3NtZW50IGVudHJ5IGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICAgIGlmICghdjJEYXRhLmFzc2Vzc21lbnRzW2Fzc2Vzc21lbnRJZF0pIHtcbiAgICAgICAgdjJEYXRhLmFzc2Vzc21lbnRzW2Fzc2Vzc21lbnRJZF0gPSB7fTtcbiAgICAgIH1cblxuICAgICAgLy8gQ3JlYXRlIHF1ZXN0aW9uIGRhdGEgd2l0aCB0aGUgbWlncmF0ZWQgdGVzdCBkYXRhXG4gICAgICBjb25zdCBxdWVzdGlvbkRhdGE6IFF1ZXN0aW9uRGF0YSA9IHt9O1xuXG4gICAgICBxdWVzdGlvbkRhdGEuYWN0dWFsID0ge1xuICAgICAgICAuLi50ZXN0RGF0YSxcbiAgICAgICAgbGFzdE1vZGlmaWVkOiBEYXRlLm5vdygpLFxuICAgICAgfTtcblxuICAgICAgLy8gU2V0IGxhc3QgbW9kaWZpZWQgdGltZSBmb3IgdGhlIHF1ZXN0aW9uIGRhdGFcbiAgICAgIHF1ZXN0aW9uRGF0YS5sYXN0TW9kaWZpZWQgPSBEYXRlLm5vdygpO1xuXG4gICAgICAvLyBBZGQgdG8gdGhlIHYyIHN0cnVjdHVyZVxuICAgICAgdjJEYXRhLmFzc2Vzc21lbnRzW2Fzc2Vzc21lbnRJZF1bZGVmYXVsdFF1ZXN0aW9uSWRdID0gcXVlc3Rpb25EYXRhO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSBvdXIgaW5zdGFuY2Ugd2l0aCBtaWdyYXRlZCBkYXRhXG4gICAgdGhpcy5hdXRvU2F2ZWREYXRhID0geyAuLi52MkRhdGEgfTtcblxuICAgIC8vIFNhdmUgdGhlIG1pZ3JhdGVkIGRhdGFcbiAgICB0aGlzLnN0b3JlRGF0YSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbnN1cmVEYXRhU3RydWN0dXJlKCk6IHZvaWQge1xuICAgIC8vIE1ha2Ugc3VyZSBhc3Nlc3NtZW50IGV4aXN0c1xuICAgIGlmICghdGhpcy5hdXRvU2F2ZWREYXRhLmFzc2Vzc21lbnRzW3RoaXMuYXNzZXNzbWVudElkXSkge1xuICAgICAgdGhpcy5hdXRvU2F2ZWREYXRhLmFzc2Vzc21lbnRzW3RoaXMuYXNzZXNzbWVudElkXSA9IHt9O1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSBxdWVzdGlvbiBleGlzdHNcbiAgICBpZiAoIXRoaXMuYXV0b1NhdmVkRGF0YS5hc3Nlc3NtZW50c1t0aGlzLmFzc2Vzc21lbnRJZF1bdGhpcy5xdWVzdGlvbklkXSkge1xuICAgICAgdGhpcy5hdXRvU2F2ZWREYXRhLmFzc2Vzc21lbnRzW3RoaXMuYXNzZXNzbWVudElkXVt0aGlzLnF1ZXN0aW9uSWRdID0ge1xuICAgICAgICBsYXN0TW9kaWZpZWQ6IERhdGUubm93KCksXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHF1ZXN0aW9uRGF0YSA9IHRoaXMuYXV0b1NhdmVkRGF0YS5hc3Nlc3NtZW50c1t0aGlzLmFzc2Vzc21lbnRJZF1bdGhpcy5xdWVzdGlvbklkXTtcblxuICAgIC8vIEVuc3VyZSBwcmV2aWV3IG9yIGFjdHVhbCBleGlzdHMgYmFzZWQgb24gY3VycmVudCBtb2RlXG4gICAgaWYgKHRoaXMuaXNQcmV2aWV3ICYmICFxdWVzdGlvbkRhdGEucHJldmlldykge1xuICAgICAgcXVlc3Rpb25EYXRhLnByZXZpZXcgPSB7XG4gICAgICAgIGNvZGU6IHt9LFxuICAgICAgICB0ZXN0Q2FzZXNMQVQ6IFtdLFxuICAgICAgICBsYXN0TW9kaWZpZWQ6IERhdGUubm93KCksXG4gICAgICB9O1xuICAgIH0gZWxzZSBpZiAoIXRoaXMuaXNQcmV2aWV3ICYmICFxdWVzdGlvbkRhdGEuYWN0dWFsKSB7XG4gICAgICBxdWVzdGlvbkRhdGEuYWN0dWFsID0ge1xuICAgICAgICBjb2RlOiB7fSxcbiAgICAgICAgdGVzdENhc2VzTEFUOiBbXSxcbiAgICAgICAgbGFzdE1vZGlmaWVkOiBEYXRlLm5vdygpLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUxhc3RNb2RpZmllZChkYXRhOiBUZXN0RGF0YSB8IFF1ZXN0aW9uRGF0YSB8IEF1dG9TYXZlZERhdGEpOiB2b2lkIHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGRhdGEubGFzdE1vZGlmaWVkID0gbm93O1xuXG4gICAgLy8gSWYgdXBkYXRpbmcgYSBUZXN0RGF0YSwgYWxzbyB1cGRhdGUgaXRzIHBhcmVudCBRdWVzdGlvbkRhdGFcbiAgICBpZiAoJ2NvZGUnIGluIGRhdGEgJiYgdGhpcy5hc3Nlc3NtZW50SWQgJiYgdGhpcy5xdWVzdGlvbklkKSB7XG4gICAgICB0aGlzLmF1dG9TYXZlZERhdGEuYXNzZXNzbWVudHNbdGhpcy5hc3Nlc3NtZW50SWRdW3RoaXMucXVlc3Rpb25JZF0ubGFzdE1vZGlmaWVkID0gbm93O1xuICAgIH1cblxuICAgIC8vIEFsd2F5cyB1cGRhdGUgcm9vdCB0aW1lc3RhbXAgcmVnYXJkbGVzcyBvZiB0aGUgb2JqZWN0IGJlaW5nIG1vZGlmaWVkXG4gICAgdGhpcy5hdXRvU2F2ZWREYXRhLmxhc3RNb2RpZmllZCA9IG5vdztcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbnVwIHdpdGggYSB0ZW1wb3JhcnkgYWdlIHRocmVzaG9sZFxuICAgKiBAcGFyYW0gbWF4QWdlRGF5cyBNYXhpbXVtIGFnZSBpbiBkYXlzIGZvciBkYXRhIHRvIGJlIGNvbnNpZGVyZWQgdmFsaWRcbiAgICovXG4gIHByaXZhdGUgY2xlYW51cFdpdGhSZWR1Y2VkVGhyZXNob2xkKG1heEFnZURheXM6IG51bWJlcik6IHZvaWQge1xuICAgIC8vIENhbGwgdGhlIHVuaWZpZWQgY2xlYW51cCBtZXRob2Qgd2l0aCBtb3JlIGFnZ3Jlc3NpdmUgcGFyYW1ldGVyc1xuICAgIHRoaXMuY2xlYW51cFN0b3JhZ2VEYXRhKHtcbiAgICAgIHN0b3JhZ2VBZ2VNdWx0aXBsaWVyOiAyLCAvLyBNb3JlIGFnZ3Jlc3NpdmUgbXVsdGlwbGllclxuICAgICAgY3VzdG9tU3RvcmFnZUFnZURheXM6IG1heEFnZURheXMsIC8vIFVzZSB0aGUgcHJvdmlkZWQgY3VzdG9tIGFnZVxuICAgICAgbWluUXVlc3Rpb25EYXRhQWdlRGF5czogMC41LCAvLyAxMiBob3VycyBtaW5pbXVtXG4gICAgICBhc3Nlc3NtZW50TGltaXRNdWx0aXBsaWVyOiAwLjUsIC8vIEhhbGYgdGhlIG5vcm1hbCBhc3Nlc3NtZW50IGxpbWl0XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVW5pZmllZCBtZXRob2QgdG8gY2xlYW4gdXAgbG9jYWxTdG9yYWdlIGRhdGEgd2l0aCBjb25maWd1cmFibGUgaW50ZW5zaXR5XG4gICAqIEBwYXJhbSBvcHRpb25zIENsZWFudXAgb3B0aW9ucyB0byBjb250cm9sIHRoZSBhZ2dyZXNzaXZlbmVzcyBvZiB0aGUgY2xlYW51cFxuICAgKi9cbiAgcHJpdmF0ZSBjbGVhbnVwU3RvcmFnZURhdGEob3B0aW9uczoge1xuICAgIHN0b3JhZ2VBZ2VNdWx0aXBsaWVyPzogbnVtYmVyOyAvLyBNdWx0aXBsaWVyIGZvciBzdG9yYWdlIGFnZSB0aHJlc2hvbGQgKGRlZmF1bHQ6IDEpXG4gICAgY3VzdG9tU3RvcmFnZUFnZURheXM/OiBudW1iZXI7IC8vIEN1c3RvbSBzdG9yYWdlIGFnZSBpbiBkYXlzIChvdmVycmlkZXMgTUFYX1NUT1JBR0VfQUdFX0RBWVMgaWYgcHJvdmlkZWQpXG4gICAgdXNlU3RhbmRhcmRRdWVzdGlvbkRhdGFBZ2U/OiBib29sZWFuOyAvLyBXaGV0aGVyIHRvIHVzZSBzdGFuZGFyZCBxdWVzdGlvbiBkYXRhIGFnZSAoZGVmYXVsdDogZmFsc2UpXG4gICAgbWluUXVlc3Rpb25EYXRhQWdlRGF5cz86IG51bWJlcjsgLy8gTWluaW11bSBhZ2UgZm9yIHF1ZXN0aW9uIGRhdGEgaW4gZGF5cyAoZGVmYXVsdDogMC41IC0gMTIgaG91cnMpXG4gICAgYXNzZXNzbWVudExpbWl0TXVsdGlwbGllcj86IG51bWJlcjsgLy8gTXVsdGlwbGllciBmb3IgbWF4aW11bSBhc3Nlc3NtZW50cyAoZGVmYXVsdDogMSlcbiAgfSk6IHZvaWQge1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG5cbiAgICAvLyBEZXRlcm1pbmUgdGhlIHN0b3JhZ2UgYWdlIHRocmVzaG9sZFxuICAgIGNvbnN0IHN0b3JhZ2VBZ2VEYXlzID0gb3B0aW9ucy5jdXN0b21TdG9yYWdlQWdlRGF5cyA/PyB0aGlzLk1BWF9TVE9SQUdFX0FHRV9EQVlTO1xuICAgIGNvbnN0IHN0b3JhZ2VBZ2VUaHJlc2hvbGQgPSB0aW1lVG9NcyhzdG9yYWdlQWdlRGF5cyk7IC8vIENvbnZlcnQgZGF5cyB0byBtaWxsaXNlY29uZHNcbiAgICBjb25zdCBtdWx0aXBsaWVyID0gb3B0aW9ucy5zdG9yYWdlQWdlTXVsdGlwbGllciA/PyAxO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIGVudGlyZSBzdG9yYWdlIGlzIHRvbyBvbGQgYW5kIG5lZWRzIGNsZWFudXBcbiAgICBpZiAodGhpcy5hdXRvU2F2ZWREYXRhLmxhc3RNb2RpZmllZCAmJiBub3cgLSB0aGlzLmF1dG9TYXZlZERhdGEubGFzdE1vZGlmaWVkID4gc3RvcmFnZUFnZVRocmVzaG9sZCAqIG11bHRpcGxpZXIpIHtcbiAgICAgIC8vIElmIHRoZSBlbnRpcmUgc3RvcmFnZSBpcyB2ZXJ5IG9sZCwganVzdCByZXNldCBldmVyeXRoaW5nXG4gICAgICB0aGlzLmF1dG9TYXZlZERhdGEgPSB7XG4gICAgICAgIHZlcnNpb246IHRoaXMuQ1VSUkVOVF9TVE9SQUdFX1ZFUlNJT04sXG4gICAgICAgIGNvbmZpZzogdGhpcy5hdXRvU2F2ZWREYXRhLmNvbmZpZywgLy8gS2VlcCB0aGUgY29uZmlnIHNldHRpbmdzXG4gICAgICAgIGlzRnVsbHNjcmVlbjogdGhpcy5hdXRvU2F2ZWREYXRhLmlzRnVsbHNjcmVlbiwgLy8gS2VlcCBmdWxsc2NyZWVuIHNldHRpbmdcbiAgICAgICAgYXNzZXNzbWVudHM6IHt9LFxuICAgICAgICBsYXN0TW9kaWZpZWQ6IG5vdyxcbiAgICAgIH07XG4gICAgICB0aGlzLnN0b3JlRGF0YSgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFN0cnVjdHVyZSBmb3IgY29sbGVjdGluZyBhc3Nlc3NtZW50IGRhdGEgd2l0aCBtZXRhZGF0YVxuICAgIGludGVyZmFjZSBBc3Nlc3NtZW50TWV0YWRhdGEge1xuICAgICAgaWQ6IHN0cmluZztcbiAgICAgIGxhc3RNb2RpZmllZDogbnVtYmVyO1xuICAgIH1cblxuICAgIGNvbnN0IGFzc2Vzc21lbnRNZXRhZGF0YTogQXNzZXNzbWVudE1ldGFkYXRhW10gPSBbXTtcblxuICAgIC8vIERldGVybWluZSB0aGUgcXVlc3Rpb24gZGF0YSBhZ2UgdGhyZXNob2xkXG4gICAgbGV0IHF1ZXN0aW9uRGF0YUFnZVRocmVzaG9sZDogbnVtYmVyO1xuICAgIGlmIChvcHRpb25zLnVzZVN0YW5kYXJkUXVlc3Rpb25EYXRhQWdlKSB7XG4gICAgICAvLyBVc2UgdGhlIHN0YW5kYXJkIHRocmVzaG9sZCBmb3Igbm9ybWFsIGNsZWFudXBcbiAgICAgIHF1ZXN0aW9uRGF0YUFnZVRocmVzaG9sZCA9IHRpbWVUb01zKHRoaXMuTUFYX1FVRVNUSU9OX0RBVEFfQUdFX0RBWVMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBGb3IgbWFpbnRlbmFuY2UvYWdncmVzc2l2ZSBjbGVhbnVwLCB1c2UgYSBjdXN0b20gdGhyZXNob2xkXG4gICAgICBjb25zdCBtaW5BZ2VIb3VycyA9IChvcHRpb25zLm1pblF1ZXN0aW9uRGF0YUFnZURheXMgPz8gMC41KSAqIDI0OyAvLyBDb252ZXJ0IGRheXMgdG8gaG91cnNcbiAgICAgIHF1ZXN0aW9uRGF0YUFnZVRocmVzaG9sZCA9IE1hdGgubWF4KFxuICAgICAgICB0aW1lVG9Ncyh0aGlzLk1BWF9RVUVTVElPTl9EQVRBX0FHRV9EQVlTKSwgLy8gU3RhbmRhcmQgYWdlIGluIG1pbGxpc2Vjb25kc1xuICAgICAgICB0aW1lVG9NcyhtaW5BZ2VIb3VycywgJ2hvdXJzJykgLy8gTWluaW11bSBhZ2UgaW4gbWlsbGlzZWNvbmRzXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIENvbGxlY3QgYXNzZXNzbWVudHMgd2l0aCB0aGVpciBsYXRlc3QgbW9kaWZpY2F0aW9uIHRpbWVzXG4gICAgZm9yIChjb25zdCBbYXNzZXNzbWVudElkLCBxdWVzdGlvbnNdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMuYXV0b1NhdmVkRGF0YS5hc3Nlc3NtZW50cykpIHtcbiAgICAgIGxldCBhc3Nlc3NtZW50TGFzdE1vZGlmaWVkID0gMDtcblxuICAgICAgLy8gQ2hlY2sgYWxsIHF1ZXN0aW9ucyBpbiB0aGlzIGFzc2Vzc21lbnRcbiAgICAgIGxldCBoYXNWYWxpZFF1ZXN0aW9ucyA9IGZhbHNlO1xuXG4gICAgICBmb3IgKGNvbnN0IFtxdWVzdGlvbklkLCBxdWVzdGlvbkRhdGFdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXN0aW9ucykpIHtcbiAgICAgICAgLy8gU2tpcCBpZiB1bmRlZmluZWRcbiAgICAgICAgaWYgKCFxdWVzdGlvbkRhdGEpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCB0aGUgbGF0ZXN0IG1vZGlmaWNhdGlvbiB0aW1lIGZyb20gcHJldmlldyBhbmQgYWN0dWFsXG4gICAgICAgIGNvbnN0IHByZXZpZXdUaW1lID0gcXVlc3Rpb25EYXRhLnByZXZpZXc/Lmxhc3RNb2RpZmllZCB8fCAwO1xuICAgICAgICBjb25zdCBhY3R1YWxUaW1lID0gcXVlc3Rpb25EYXRhLmFjdHVhbD8ubGFzdE1vZGlmaWVkIHx8IDA7XG4gICAgICAgIGNvbnN0IHF1ZXN0aW9uTGFzdE1vZGlmaWVkID0gTWF0aC5tYXgocHJldmlld1RpbWUsIGFjdHVhbFRpbWUsIHF1ZXN0aW9uRGF0YS5sYXN0TW9kaWZpZWQgfHwgMCk7XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgZGF0YSBpcyB0b28gb2xkIC0gdXNpbmcgY29uZmlndXJlZCB0aHJlc2hvbGRcbiAgICAgICAgY29uc3QgaXNQcmV2aWV3VG9vT2xkID0gcHJldmlld1RpbWUgPiAwICYmIG5vdyAtIHByZXZpZXdUaW1lID4gcXVlc3Rpb25EYXRhQWdlVGhyZXNob2xkO1xuICAgICAgICBjb25zdCBpc0FjdHVhbFRvb09sZCA9IGFjdHVhbFRpbWUgPiAwICYmIG5vdyAtIGFjdHVhbFRpbWUgPiBxdWVzdGlvbkRhdGFBZ2VUaHJlc2hvbGQ7XG5cbiAgICAgICAgLy8gQ2xlYW4gdXAgb2xkIGRhdGEgd2l0aGluIHRoZSBxdWVzdGlvblxuICAgICAgICBpZiAoaXNQcmV2aWV3VG9vT2xkICYmIHF1ZXN0aW9uRGF0YS5wcmV2aWV3KSB7XG4gICAgICAgICAgZGVsZXRlIHF1ZXN0aW9uRGF0YS5wcmV2aWV3O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzQWN0dWFsVG9vT2xkICYmIHF1ZXN0aW9uRGF0YS5hY3R1YWwpIHtcbiAgICAgICAgICBkZWxldGUgcXVlc3Rpb25EYXRhLmFjdHVhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIG5laXRoZXIgcHJldmlldyBub3IgYWN0dWFsIGV4aXN0cywgcmVtb3ZlIHRoZSBxdWVzdGlvblxuICAgICAgICBpZiAoIXF1ZXN0aW9uRGF0YS5wcmV2aWV3ICYmICFxdWVzdGlvbkRhdGEuYWN0dWFsKSB7XG4gICAgICAgICAgZGVsZXRlIHF1ZXN0aW9uc1txdWVzdGlvbklkXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBoYXNWYWxpZFF1ZXN0aW9ucyA9IHRydWU7XG4gICAgICAgICAgYXNzZXNzbWVudExhc3RNb2RpZmllZCA9IE1hdGgubWF4KGFzc2Vzc21lbnRMYXN0TW9kaWZpZWQsIHF1ZXN0aW9uTGFzdE1vZGlmaWVkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBJZiBubyB2YWxpZCBxdWVzdGlvbnMsIHJlbW92ZSB0aGUgYXNzZXNzbWVudFxuICAgICAgaWYgKCFoYXNWYWxpZFF1ZXN0aW9ucykge1xuICAgICAgICBkZWxldGUgdGhpcy5hdXRvU2F2ZWREYXRhLmFzc2Vzc21lbnRzW2Fzc2Vzc21lbnRJZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBZGQgdG8gb3VyIGxpc3QgZm9yIHBvdGVudGlhbCBzaXplLWJhc2VkIGNsZWFudXBcbiAgICAgICAgYXNzZXNzbWVudE1ldGFkYXRhLnB1c2goe1xuICAgICAgICAgIGlkOiBhc3Nlc3NtZW50SWQsXG4gICAgICAgICAgbGFzdE1vZGlmaWVkOiBhc3Nlc3NtZW50TGFzdE1vZGlmaWVkLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEZXRlcm1pbmUgdGhlIGFzc2Vzc21lbnQgbGltaXQgYmFzZWQgb24gdGhlIG11bHRpcGxpZXJcbiAgICBjb25zdCBsaW1pdE11bHRpcGxpZXIgPSBvcHRpb25zLmFzc2Vzc21lbnRMaW1pdE11bHRpcGxpZXIgPz8gMTtcbiAgICBjb25zdCBhc3Nlc3NtZW50TGltaXQgPSBNYXRoLmNlaWwodGhpcy5NQVhfQVNTRVNTTUVOVFMgKiBsaW1pdE11bHRpcGxpZXIpO1xuXG4gICAgLy8gSWYgd2UgaGF2ZSB0b28gbWFueSBhc3Nlc3NtZW50cywgcmVtb3ZlIHRoZSBvbGRlc3Qgb25lc1xuICAgIGlmIChhc3Nlc3NtZW50TWV0YWRhdGEubGVuZ3RoID4gYXNzZXNzbWVudExpbWl0KSB7XG4gICAgICAvLyBTb3J0IGJ5IGxhc3RNb2RpZmllZCAobW9zdCByZWNlbnQgZmlyc3QpXG4gICAgICBhc3Nlc3NtZW50TWV0YWRhdGEuc29ydCgoYSwgYikgPT4gYi5sYXN0TW9kaWZpZWQgLSBhLmxhc3RNb2RpZmllZCk7XG5cbiAgICAgIC8vIFJlbW92ZSBvbGRlc3QgYXNzZXNzbWVudHMgdGhhdCBleGNlZWQgb3VyIGxpbWl0XG4gICAgICBmb3IgKGxldCBpID0gYXNzZXNzbWVudExpbWl0OyBpIDwgYXNzZXNzbWVudE1ldGFkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLmF1dG9TYXZlZERhdGEuYXNzZXNzbWVudHNbYXNzZXNzbWVudE1ldGFkYXRhW2ldLmlkXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTYXZlIHRoZSBjbGVhbmVkIGRhdGFcbiAgICB0aGlzLnN0b3JlRGF0YSgpO1xuICB9XG5cbiAgY2hhbmdlTGFuZ3VhZ2UobGFuZ3VhZ2U6IENvZGVFZGl0b3JMYW5ndWFnZXMpIHtcbiAgICB0aGlzLmxhbmd1YWdlID0gbGFuZ3VhZ2U7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBkYXRhIGZyb20gdjEgc2NoZW1hIGZvcm1hdFxuICAgKiBVc2VkIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IHdoZW4gcmV0cmlldmluZyBkYXRhXG4gICAqL1xuICBwcml2YXRlIGdldERhdGFGcm9tVjFTY2hlbWEocmV0cmlldmVkRGF0YTogQXV0b1NhdmVkRGF0YVYxKTogc3RyaW5nIHwgKEV4YW1wbGVUZXN0Q2FzZSB8IEN1c3RvbVRlc3RDYXNlKVtdIHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgLy8gRm9yIHYxLCB3ZSBuZWVkIHRvIGhhbmRsZSB0aGUgY2FzZSB3aGVyZSB3ZSBkb24ndCBoYXZlIHF1ZXN0aW9uSWRcbiAgICAvLyBXZSdyZSBub3cgdXNpbmcgcXVlc3Rpb25JZCBpbiB0aGUgYXBwLCBidXQgc3RvcmVkIGRhdGEgbWlnaHQgc3RpbGwgYmUgaW4gdjEgZm9ybWF0XG5cbiAgICAvLyBGb3IgcHJldmlldyBkYXRhLCB0aGUgYXNzZXNzbWVudCBJRCB3b3VsZCBiZSBBc3Nlc3NtZW50SWRQcmV2aWV3XG4gICAgaWYgKHRoaXMuYXNzZXNzbWVudElkID09PSBBc3Nlc3NtZW50SWRQcmV2aWV3KSB7XG4gICAgICBpZiAodGhpcy5pc1ByZXZpZXcpIHtcbiAgICAgICAgLy8gRm9yIHByZXZpZXcgbW9kZSBvbiBwcmV2aWV3IGFzc2Vzc21lbnQsIGdldCB0aGUgY29kZSBkaXJlY3RseVxuICAgICAgICBjb25zdCBjb2RlID0gcmV0cmlldmVkRGF0YS5hc3Nlc3NtZW50c1t0aGlzLmFzc2Vzc21lbnRJZF0/LmNvZGU7XG4gICAgICAgIGlmIChjb2RlICYmIHRoaXMubGFuZ3VhZ2UgaW4gY29kZSkge1xuICAgICAgICAgIHJldHVybiBjb2RlW3RoaXMubGFuZ3VhZ2VdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBXZSBkb24ndCBleHBlY3QgYWN0dWFsL25vbi1wcmV2aWV3IGRhdGEgZm9yIEFzc2Vzc21lbnRJZFByZXZpZXdcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBGb3IgcmVndWxhciBhc3Nlc3NtZW50cywgdjEgb25seSBoYWQgY29kZSBpbiB0aGUgXCJhY3R1YWxcIiBzZWN0aW9uXG4gICAgICBpZiAoIXRoaXMuaXNQcmV2aWV3KSB7XG4gICAgICAgIGNvbnN0IGNvZGUgPSByZXRyaWV2ZWREYXRhLmFzc2Vzc21lbnRzW3RoaXMuYXNzZXNzbWVudElkXT8uY29kZTtcbiAgICAgICAgaWYgKGNvZGUgJiYgdGhpcy5sYW5ndWFnZSBpbiBjb2RlKSB7XG4gICAgICAgICAgcmV0dXJuIGNvZGVbdGhpcy5sYW5ndWFnZV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIFdlIGRvbid0IGhhdmUgcHJldmlldyBkYXRhIGZvciByZWd1bGFyIGFzc2Vzc21lbnRzIGluIHYxXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBnZXRTYXZlZENvZGUoKTogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgcmV0cmlldmVkRGF0YSA9IHRoaXMucmV0cmlldmVEYXRhKCk7XG4gICAgaWYgKCFyZXRyaWV2ZWREYXRhKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB1c2luZyB2MiBzY2hlbWFcbiAgICBpZiAoJ3ZlcnNpb24nIGluIHJldHJpZXZlZERhdGEpIHtcbiAgICAgIC8vIEhhbmRsZSB2MiBzY2hlbWFcbiAgICAgIGNvbnN0IHYyRGF0YSA9IHJldHJpZXZlZERhdGE7XG4gICAgICBjb25zdCBhc3Nlc3NtZW50RGF0YSA9IHYyRGF0YS5hc3Nlc3NtZW50c1t0aGlzLmFzc2Vzc21lbnRJZF07XG5cbiAgICAgIGlmICghYXNzZXNzbWVudERhdGEpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG5cbiAgICAgIC8vIEZpcnN0IHRyeSB3aXRoIHByb3ZpZGVkIHF1ZXN0aW9uSWRcbiAgICAgIGlmICh0aGlzLnF1ZXN0aW9uSWQgJiYgYXNzZXNzbWVudERhdGFbdGhpcy5xdWVzdGlvbklkXSkge1xuICAgICAgICBjb25zdCBxdWVzdGlvbkRhdGEgPSBhc3Nlc3NtZW50RGF0YVt0aGlzLnF1ZXN0aW9uSWRdO1xuICAgICAgICBjb25zdCB0ZXN0RGF0YSA9IHRoaXMuaXNQcmV2aWV3ID8gcXVlc3Rpb25EYXRhLnByZXZpZXcgOiBxdWVzdGlvbkRhdGEuYWN0dWFsO1xuICAgICAgICBpZiAodGVzdERhdGE/LmNvZGUgJiYgdGhpcy5sYW5ndWFnZSBpbiB0ZXN0RGF0YS5jb2RlKSB7XG4gICAgICAgICAgcmV0dXJuIHRlc3REYXRhLmNvZGVbdGhpcy5sYW5ndWFnZV07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICB0aGlzLnF1ZXN0aW9uSWQgIT09IHRoaXMuREVGQVVMVF9NSUdSQVRJT05fUVVFU1RJT05fSUQgJiZcbiAgICAgICAgYXNzZXNzbWVudERhdGFbdGhpcy5ERUZBVUxUX01JR1JBVElPTl9RVUVTVElPTl9JRF1cbiAgICAgICkge1xuICAgICAgICBjb25zdCBxdWVzdGlvbkRhdGEgPSBhc3Nlc3NtZW50RGF0YVt0aGlzLkRFRkFVTFRfTUlHUkFUSU9OX1FVRVNUSU9OX0lEXTtcbiAgICAgICAgY29uc3QgdGVzdERhdGEgPSB0aGlzLmlzUHJldmlldyA/IHF1ZXN0aW9uRGF0YS5wcmV2aWV3IDogcXVlc3Rpb25EYXRhLmFjdHVhbDtcbiAgICAgICAgaWYgKHRlc3REYXRhPy5jb2RlICYmIHRoaXMubGFuZ3VhZ2UgaW4gdGVzdERhdGEuY29kZSkge1xuICAgICAgICAgIHJldHVybiB0ZXN0RGF0YS5jb2RlW3RoaXMubGFuZ3VhZ2VdO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBIYW5kbGUgdjEgc2NoZW1hIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICByZXR1cm4gdGhpcy5nZXREYXRhRnJvbVYxU2NoZW1hKHJldHJpZXZlZERhdGEpIGFzIHN0cmluZztcbiAgICB9XG4gIH1cblxuICBnZXRMYXN0TGFuZ3VhZ2VMQVQoKToge1xuICAgIHZhbHVlOiBDb2RlRWRpdG9yTGFuZ3VhZ2VzO1xuICAgIHZlcnNpb246IHN0cmluZztcbiAgfSB8IG51bGwge1xuICAgIGNvbnN0IHJldHJpZXZlZERhdGEgPSB0aGlzLnJldHJpZXZlRGF0YSgpO1xuICAgIGlmICghcmV0cmlldmVkRGF0YSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldHJpZXZlZERhdGEubGFzdExhbmd1YWdlTEFUIHx8IG51bGw7XG4gIH1cblxuICBnZXRTYXZlZFRlc3RDYXNlcygpOiAoRXhhbXBsZVRlc3RDYXNlIHwgQ3VzdG9tVGVzdENhc2UpW10gfCBudWxsIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCByZXRyaWV2ZWREYXRhID0gdGhpcy5yZXRyaWV2ZURhdGEoKTtcbiAgICBpZiAoIXJldHJpZXZlZERhdGEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIHVzaW5nIHYyIHNjaGVtYVxuICAgIGlmICgndmVyc2lvbicgaW4gcmV0cmlldmVkRGF0YSkge1xuICAgICAgLy8gSGFuZGxlIHYyIHNjaGVtYVxuICAgICAgY29uc3QgdjJEYXRhID0gcmV0cmlldmVkRGF0YTtcbiAgICAgIGNvbnN0IGFzc2Vzc21lbnREYXRhID0gdjJEYXRhLmFzc2Vzc21lbnRzW3RoaXMuYXNzZXNzbWVudElkXTtcblxuICAgICAgaWYgKCFhc3Nlc3NtZW50RGF0YSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgLy8gRmlyc3QgdHJ5IHdpdGggcHJvdmlkZWQgcXVlc3Rpb25JZFxuICAgICAgaWYgKHRoaXMucXVlc3Rpb25JZCAmJiBhc3Nlc3NtZW50RGF0YVt0aGlzLnF1ZXN0aW9uSWRdKSB7XG4gICAgICAgIGNvbnN0IHF1ZXN0aW9uRGF0YSA9IGFzc2Vzc21lbnREYXRhW3RoaXMucXVlc3Rpb25JZF07XG4gICAgICAgIGNvbnN0IHRlc3REYXRhID0gdGhpcy5pc1ByZXZpZXcgPyBxdWVzdGlvbkRhdGEucHJldmlldyA6IHF1ZXN0aW9uRGF0YS5hY3R1YWw7XG4gICAgICAgIGlmICh0ZXN0RGF0YT8udGVzdENhc2VzTEFUKSB7XG4gICAgICAgICAgcmV0dXJuIHRlc3REYXRhLnRlc3RDYXNlc0xBVDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBJZiBub3QgZm91bmQgYW5kIHF1ZXN0aW9uSWQgIT0gREVGQVVMVF9NSUdSQVRJT05fUVVFU1RJT05fSUQsXG4gICAgICAvLyBhbHNvIHRyeSB3aXRoIHRoZSBkZWZhdWx0IG1pZ3JhdGlvbiBJRCBhcyBhIGZhbGxiYWNrXG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMucXVlc3Rpb25JZCAhPT0gdGhpcy5ERUZBVUxUX01JR1JBVElPTl9RVUVTVElPTl9JRCAmJlxuICAgICAgICBhc3Nlc3NtZW50RGF0YVt0aGlzLkRFRkFVTFRfTUlHUkFUSU9OX1FVRVNUSU9OX0lEXVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IHF1ZXN0aW9uRGF0YSA9IGFzc2Vzc21lbnREYXRhW3RoaXMuREVGQVVMVF9NSUdSQVRJT05fUVVFU1RJT05fSURdO1xuICAgICAgICBjb25zdCB0ZXN0RGF0YSA9IHRoaXMuaXNQcmV2aWV3ID8gcXVlc3Rpb25EYXRhLnByZXZpZXcgOiBxdWVzdGlvbkRhdGEuYWN0dWFsO1xuICAgICAgICBpZiAodGVzdERhdGE/LnRlc3RDYXNlc0xBVCkge1xuICAgICAgICAgIHJldHVybiB0ZXN0RGF0YS50ZXN0Q2FzZXNMQVQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEhhbmRsZSB2MSBzY2hlbWEgdGVzdCBjYXNlcyAodGVzdCBjYXNlcyB3ZXJlIG9ubHkgaW4gdGhlIGFjdHVhbCBtb2RlKVxuICAgICAgY29uc3QgdjFEYXRhID0gcmV0cmlldmVkRGF0YTtcbiAgICAgIGlmICghdGhpcy5pc1ByZXZpZXcgJiYgdjFEYXRhLmFzc2Vzc21lbnRzW3RoaXMuYXNzZXNzbWVudElkXT8udGVzdENhc2VzTEFUKSB7XG4gICAgICAgIHJldHVybiB2MURhdGEuYXNzZXNzbWVudHNbdGhpcy5hc3Nlc3NtZW50SWRdLnRlc3RDYXNlc0xBVDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGdldFNhdmVkQ29uZmlnKCk6IENvbmZpZyB8IG51bGwge1xuICAgIGNvbnN0IHJldHJpZXZlZERhdGEgPSB0aGlzLnJldHJpZXZlRGF0YSgpO1xuICAgIHJldHVybiByZXRyaWV2ZWREYXRhPy5jb25maWcgPyB7IC4uLnJldHJpZXZlZERhdGEuY29uZmlnIH0gOiBudWxsO1xuICB9XG5cbiAgZ2V0U2F2ZWRGdWxsU2NyZWVuTW9kZSgpOiBib29sZWFuIHwgbnVsbCB7XG4gICAgY29uc3QgcmV0cmlldmVkRGF0YSA9IHRoaXMucmV0cmlldmVEYXRhKCk7XG4gICAgcmV0dXJuIHJldHJpZXZlZERhdGE/LmlzRnVsbHNjcmVlbiAhPT0gdW5kZWZpbmVkID8gcmV0cmlldmVkRGF0YS5pc0Z1bGxzY3JlZW4gOiBudWxsO1xuICB9XG5cbiAgY2xlYXJTYXZlZENvZGUoKTogdm9pZCB7XG4gICAgdGhpcy5lbnN1cmVEYXRhU3RydWN0dXJlKCk7XG4gICAgY29uc3QgcXVlc3Rpb25EYXRhID0gdGhpcy5hdXRvU2F2ZWREYXRhLmFzc2Vzc21lbnRzW3RoaXMuYXNzZXNzbWVudElkXVt0aGlzLnF1ZXN0aW9uSWRdO1xuICAgIGNvbnN0IHRhcmdldFRlc3REYXRhID0gdGhpcy5pc1ByZXZpZXcgPyBbcXVlc3Rpb25EYXRhLnByZXZpZXddIDogW3F1ZXN0aW9uRGF0YS5wcmV2aWV3LCBxdWVzdGlvbkRhdGEuYWN0dWFsXTtcblxuICAgIGxldCBoYXNDaGFuZ2VkID0gZmFsc2U7XG4gICAgdGFyZ2V0VGVzdERhdGEuZm9yRWFjaCh0ZXN0RGF0YSA9PiB7XG4gICAgICBpZiAodGVzdERhdGEpIHtcbiAgICAgICAgdGVzdERhdGEuY29kZSA9IHt9O1xuICAgICAgICB0aGlzLnVwZGF0ZUxhc3RNb2RpZmllZCh0ZXN0RGF0YSk7XG4gICAgICAgIGhhc0NoYW5nZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChoYXNDaGFuZ2VkKSB7XG4gICAgICB0aGlzLnN0b3JlRGF0YSgpO1xuICAgIH1cbiAgfVxuXG4gIGNsZWFyTGFzdExhbmcoKTogdm9pZCB7XG4gICAgdGhpcy5hdXRvU2F2ZWREYXRhLmxhc3RMYW5ndWFnZUxBVCA9IG51bGw7XG4gICAgdGhpcy51cGRhdGVMYXN0TW9kaWZpZWQodGhpcy5hdXRvU2F2ZWREYXRhKTtcbiAgICB0aGlzLnN0b3JlRGF0YSgpO1xuICB9XG5cbiAgY2xlYXJTYXZlZFRlc3RDYXNlcygpOiB2b2lkIHtcbiAgICB0aGlzLmVuc3VyZURhdGFTdHJ1Y3R1cmUoKTtcbiAgICBjb25zdCBxdWVzdGlvbkRhdGEgPSB0aGlzLmF1dG9TYXZlZERhdGEuYXNzZXNzbWVudHNbdGhpcy5hc3Nlc3NtZW50SWRdW3RoaXMucXVlc3Rpb25JZF07XG4gICAgY29uc3QgdGFyZ2V0VGVzdERhdGEgPSB0aGlzLmlzUHJldmlldyA/IHF1ZXN0aW9uRGF0YS5wcmV2aWV3IDogcXVlc3Rpb25EYXRhLmFjdHVhbDtcblxuICAgIGlmICh0YXJnZXRUZXN0RGF0YSkge1xuICAgICAgY29uc3QgaGFzTm9Db2RlID0gIU9iamVjdC5rZXlzKHRhcmdldFRlc3REYXRhLmNvZGUgPz8ge30pLmxlbmd0aDtcblxuICAgICAgaWYgKHRoaXMuaXNQcmV2aWV3KSB7XG4gICAgICAgIHRhcmdldFRlc3REYXRhLnRlc3RDYXNlc0xBVCA9IFtdO1xuICAgICAgICB0aGlzLnVwZGF0ZUxhc3RNb2RpZmllZCh0YXJnZXRUZXN0RGF0YSk7XG4gICAgICB9IGVsc2UgaWYgKGhhc05vQ29kZSkge1xuICAgICAgICBjb25zdCBhbGxRdWVzdGlvbnMgPSB0aGlzLmF1dG9TYXZlZERhdGEuYXNzZXNzbWVudHNbdGhpcy5hc3Nlc3NtZW50SWRdO1xuICAgICAgICBkZWxldGUgYWxsUXVlc3Rpb25zW3RoaXMucXVlc3Rpb25JZF07XG4gICAgICAgIHRoaXMuYXV0b1NhdmVkRGF0YS5hc3Nlc3NtZW50c1t0aGlzLmFzc2Vzc21lbnRJZF0gPSB7IC4uLmFsbFF1ZXN0aW9ucyB9O1xuICAgICAgICB0aGlzLnVwZGF0ZUxhc3RNb2RpZmllZCh0aGlzLmF1dG9TYXZlZERhdGEpO1xuICAgICAgfVxuICAgICAgdGhpcy5zdG9yZURhdGEoKTtcbiAgICB9XG4gIH1cblxuICB1cGRhdGVWZXJzaW9uKHZlcnNpb246IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLmF1dG9TYXZlZERhdGEubGFzdExhbmd1YWdlTEFUKSB7XG4gICAgICB0aGlzLmF1dG9TYXZlZERhdGEubGFzdExhbmd1YWdlTEFULnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgdGhpcy51cGRhdGVMYXN0TW9kaWZpZWQodGhpcy5hdXRvU2F2ZWREYXRhKTtcbiAgICAgIHRoaXMuc3RvcmVEYXRhKCk7XG4gICAgfVxuICB9XG5cbiAgdXBkYXRlVGVzdENhc2VzKHRlc3RDYXNlczogKEV4YW1wbGVUZXN0Q2FzZSB8IEN1c3RvbVRlc3RDYXNlKVtdKSB7XG4gICAgaWYgKHRoaXMuYXNzZXNzbWVudElkICYmIHRoaXMucXVlc3Rpb25JZCAmJiB0aGlzLnRlc3RDYXNlc1NhdmVFbmFibGVkKSB7XG4gICAgICB0aGlzLmVuc3VyZURhdGFTdHJ1Y3R1cmUoKTtcbiAgICAgIGNvbnN0IHF1ZXN0aW9uRGF0YSA9IHRoaXMuYXV0b1NhdmVkRGF0YS5hc3Nlc3NtZW50c1t0aGlzLmFzc2Vzc21lbnRJZF1bdGhpcy5xdWVzdGlvbklkXTtcbiAgICAgIGNvbnN0IHRhcmdldFRlc3REYXRhID0gdGhpcy5pc1ByZXZpZXcgPyBxdWVzdGlvbkRhdGEucHJldmlldyA6IHF1ZXN0aW9uRGF0YS5hY3R1YWw7XG5cbiAgICAgIGlmICh0YXJnZXRUZXN0RGF0YSkge1xuICAgICAgICB0YXJnZXRUZXN0RGF0YS50ZXN0Q2FzZXNMQVQgPSB0ZXN0Q2FzZXM7XG4gICAgICAgIHRoaXMudXBkYXRlTGFzdE1vZGlmaWVkKHRhcmdldFRlc3REYXRhKTtcbiAgICAgICAgdGhpcy5zdG9yZURhdGEoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN0b3JlRGF0YSgpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JhZ2Uuc3RvcmUodGhpcy5rZXksIHRoaXMuYXV0b1NhdmVkRGF0YSk7XG4gIH1cblxuICBwcml2YXRlIHJldHJpZXZlRGF0YSgpOiBBdXRvU2F2ZWREYXRhIHwgQXV0b1NhdmVkRGF0YVYxIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLnJldHJpZXZlKHRoaXMua2V5KSBhcyBBdXRvU2F2ZWREYXRhIHwgQXV0b1NhdmVkRGF0YVYxO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hbnVhbGx5IHRyaWdnZXJzIGRhdGEgY2xlYW51cCBhbmQgbWlncmF0aW9uLlxuICAgKiBVc2VmdWwgZm9yIGhhbmRsaW5nIGxhcmdlIGxvY2FsU3RvcmFnZSBvciBtaWdyYXRpb24gd2hlbiBuZWVkZWQuXG4gICAqIFRoaXMgY2FuIGJlIGNhbGxlZCBmcm9tIGFwcGxpY2F0aW9uIHN0YXJ0dXAgb3IgYWZ0ZXIgbWFqb3IgZXZlbnRzLlxuICAgKi9cbiAgcGVyZm9ybU1haW50ZW5hbmNlQW5kQ2xlYW51cCgpOiB2b2lkIHtcbiAgICAvLyBHZXQgY3VycmVudCBkYXRhXG4gICAgY29uc3Qgc2F2ZWREYXRhID0gdGhpcy5zdG9yYWdlLnJldHJpZXZlKHRoaXMua2V5KTtcblxuICAgIC8vIElmIG5vIGRhdGEsIG5vdGhpbmcgdG8gZG9cbiAgICBpZiAoIXNhdmVkRGF0YSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIG1pZ3JhdGlvbiBuZWVkZWRcbiAgICBpZiAoISgndmVyc2lvbicgaW4gc2F2ZWREYXRhKSkge1xuICAgICAgdGhpcy5taWdyYXRlRnJvbVYxVG9WMihzYXZlZERhdGEgYXMgQXV0b1NhdmVkRGF0YVYxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQWxyZWFkeSBtaWdyYXRlZCwganVzdCBwZXJmb3JtIGNsZWFudXBcbiAgICAgIHRoaXMuYXV0b1NhdmVkRGF0YSA9IHNhdmVkRGF0YSBhcyBBdXRvU2F2ZWREYXRhO1xuXG4gICAgICAvLyBQZXJmb3JtIGEgbW9yZSBhZ2dyZXNzaXZlIGNsZWFudXAgZm9yIG1hbnVhbCBtYWludGVuYW5jZVxuICAgICAgLy8gYnkgdGVtcG9yYXJpbHkgbW9kaWZ5aW5nIHRoZSBjbGVhbnVwIHRocmVzaG9sZHNcbiAgICAgIGNvbnN0IG9yaWdpbmFsTWF4QWdlID0gdGhpcy5NQVhfU1RPUkFHRV9BR0VfREFZUztcbiAgICAgIGNvbnN0IGhhbGZBZ2UgPSBNYXRoLmZsb29yKG9yaWdpbmFsTWF4QWdlIC8gMik7IC8vIEN1dCB0aHJlc2hvbGQgaW4gaGFsZlxuXG4gICAgICAvLyBDcmVhdGUgYSBjdXN0b20gY2xlYW51cCBmdW5jdGlvbiB3aXRoIHJlZHVjZWQgdGhyZXNob2xkXG4gICAgICB0aGlzLmNsZWFudXBXaXRoUmVkdWNlZFRocmVzaG9sZChoYWxmQWdlKTtcbiAgICB9XG5cbiAgICAvLyBWZXJpZnkgbG9jYWxTdG9yYWdlIHNpemUgaXMgbWFuYWdlYWJsZVxuICAgIHRyeSB7XG4gICAgICBjb25zdCBzZXJpYWxpemVkRGF0YSA9IEpTT04uc3RyaW5naWZ5KHRoaXMuYXV0b1NhdmVkRGF0YSk7XG4gICAgICBjb25zdCBzaXplSW5LQiA9IE1hdGgucm91bmQoc2VyaWFsaXplZERhdGEubGVuZ3RoIC8gMTAyNCk7XG5cbiAgICAgIC8vIElmIGRhdGEgaXMgdG9vIGxhcmdlIChvdmVyIDJNQiksIHBlcmZvcm0gbW9yZSBhZ2dyZXNzaXZlIGNsZWFudXBcbiAgICAgIGlmIChzaXplSW5LQiA+IDIwNDgpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBMb2NhbCBzdG9yYWdlIGRhdGEgaXMgbGFyZ2UgKCR7c2l6ZUluS0J9S0IpLCBwZXJmb3JtaW5nIGRlZXAgY2xlYW51cGApO1xuXG4gICAgICAgIC8vIFVzZSBleHRyZW1lbHkgYWdncmVzc2l2ZSBjbGVhbnVwIHNldHRpbmdzXG4gICAgICAgIHRoaXMuY2xlYW51cFN0b3JhZ2VEYXRhKHtcbiAgICAgICAgICBzdG9yYWdlQWdlTXVsdGlwbGllcjogMC41LCAvLyBFdmVuIG1vcmUgYWdncmVzc2l2ZSAtIGhhbGYgdGhlIG5vcm1hbCBhZ2VcbiAgICAgICAgICBtaW5RdWVzdGlvbkRhdGFBZ2VEYXlzOiAwLjI1LCAvLyA2IGhvdXJzIG1pbmltdW1cbiAgICAgICAgICBhc3Nlc3NtZW50TGltaXRNdWx0aXBsaWVyOiAwLjIsIC8vIEtlZXAgb25seSAyMCUgb2YgYXNzZXNzbWVudHNcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gSWYgc3RpbGwgdG9vIGxhcmdlLCBrZWVwIG9ubHkgYSBmZXcgbW9zdCByZWNlbnQgYXNzZXNzbWVudHNcbiAgICAgICAgY29uc3QgbmV3U2VyaWFsaXplZERhdGEgPSBKU09OLnN0cmluZ2lmeSh0aGlzLmF1dG9TYXZlZERhdGEpO1xuICAgICAgICBjb25zdCBuZXdTaXplSW5LQiA9IE1hdGgucm91bmQobmV3U2VyaWFsaXplZERhdGEubGVuZ3RoIC8gMTAyNCk7XG5cbiAgICAgICAgaWYgKG5ld1NpemVJbktCID4gMTAyNCkge1xuICAgICAgICAgIC8vIEtlZXAgb25seSByZWNlbnQgYXNzZXNzbWVudHNcbiAgICAgICAgICBjb25zdCBhc3Nlc3NtZW50cyA9IHRoaXMuYXV0b1NhdmVkRGF0YS5hc3Nlc3NtZW50cztcbiAgICAgICAgICAvLyBGaW5kIHRoZSBuZXdlc3QgdGltZXN0YW1wIGluIGVhY2ggYXNzZXNzbWVudFxuICAgICAgICAgIGNvbnN0IGdldE5ld2VzdFRpbWVzdGFtcCA9IChvYmo6IFJlY29yZDxzdHJpbmcsIFF1ZXN0aW9uRGF0YT4pID0+XG4gICAgICAgICAgICBPYmplY3QudmFsdWVzKG9iaikucmVkdWNlKChtYXgsIHF1ZXN0aW9uRGF0YSkgPT4gTWF0aC5tYXgobWF4LCBxdWVzdGlvbkRhdGE/Lmxhc3RNb2RpZmllZCB8fCAwKSwgMCk7XG4gICAgICAgICAgY29uc3QgZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKGFzc2Vzc21lbnRzKS5zb3J0KFxuICAgICAgICAgICAgKFssIGFdLCBbLCBiXSkgPT5cbiAgICAgICAgICAgICAgZ2V0TmV3ZXN0VGltZXN0YW1wKGIgYXMgUmVjb3JkPHN0cmluZywgUXVlc3Rpb25EYXRhPikgLVxuICAgICAgICAgICAgICBnZXROZXdlc3RUaW1lc3RhbXAoYSBhcyBSZWNvcmQ8c3RyaW5nLCBRdWVzdGlvbkRhdGE+KVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICAvLyBLZWVwIG9ubHkgdGhlIDUgbW9zdCByZWNlbnQgYXNzZXNzbWVudHNcbiAgICAgICAgICBjb25zdCBrZWVwQ291bnQgPSBNYXRoLm1pbig1LCBlbnRyaWVzLmxlbmd0aCk7XG4gICAgICAgICAgdGhpcy5hdXRvU2F2ZWREYXRhLmFzc2Vzc21lbnRzID0ge307XG5cbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGtlZXBDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBbaWQsIGRhdGFdID0gZW50cmllc1tpXTtcbiAgICAgICAgICAgIHRoaXMuYXV0b1NhdmVkRGF0YS5hc3Nlc3NtZW50c1tpZF0gPSBkYXRhIGFzIFJlY29yZDxzdHJpbmcsIFF1ZXN0aW9uRGF0YT47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5zdG9yZURhdGEoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBjaGVja2luZyBsb2NhbFN0b3JhZ2Ugc2l6ZScsIGVycm9yKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==