@sbb-esta/lyne-elements-experimental-dev 0.0.0 → 4.0.0-dev.1775550888

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 (331) hide show
  1. package/README.md +55 -0
  2. package/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.js +67 -0
  3. package/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.js +73 -0
  4. package/autocomplete-grid/autocomplete-grid-button.js +4 -0
  5. package/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.js +2 -0
  6. package/autocomplete-grid/autocomplete-grid-cell.js +4 -0
  7. package/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.js +21 -0
  8. package/autocomplete-grid/autocomplete-grid-optgroup.js +4 -0
  9. package/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.js +2 -0
  10. package/autocomplete-grid/autocomplete-grid-option.js +4 -0
  11. package/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.js +2 -0
  12. package/autocomplete-grid/autocomplete-grid-row.js +4 -0
  13. package/autocomplete-grid/autocomplete-grid.js +4 -0
  14. package/autocomplete-grid-cell.component-DkD9aFKc.js +24 -0
  15. package/autocomplete-grid-option.component-CtATJy7n.js +37 -0
  16. package/autocomplete-grid-row.component-6nJv5PMj.js +27 -0
  17. package/autocomplete-grid.js +10 -0
  18. package/autocomplete-grid.pure.js +7 -0
  19. package/core/datetime/date-helper.js +2 -0
  20. package/core/datetime.js +2 -0
  21. package/core/styles/core.scss +13 -0
  22. package/core/styles/lean-theme.scss +3 -0
  23. package/core/styles/off-brand-theme.scss +3 -0
  24. package/core/styles/safety-theme.scss +3 -0
  25. package/core/styles/standard-theme.scss +3 -0
  26. package/core/styles/theme.scss +5 -0
  27. package/core/timetable/access-leg-helper.js +96 -0
  28. package/core/timetable/timetable-helper.js +10 -0
  29. package/core/timetable/timetable-properties.js +0 -0
  30. package/core/timetable.js +4 -0
  31. package/core.css +13 -0
  32. package/custom-elements.json +8629 -0
  33. package/date-helper-CGproP5d.js +185 -0
  34. package/development/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.d.ts +40 -0
  35. package/development/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.d.ts.map +1 -0
  36. package/development/autocomplete-grid/autocomplete-grid/autocomplete-grid.component.js +120 -0
  37. package/development/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.d.ts +32 -0
  38. package/development/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.d.ts.map +1 -0
  39. package/development/autocomplete-grid/autocomplete-grid-button/autocomplete-grid-button.component.js +103 -0
  40. package/development/autocomplete-grid/autocomplete-grid-button.d.ts +2 -0
  41. package/development/autocomplete-grid/autocomplete-grid-button.d.ts.map +1 -0
  42. package/development/autocomplete-grid/autocomplete-grid-button.js +10 -0
  43. package/development/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.d.ts +19 -0
  44. package/development/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.d.ts.map +1 -0
  45. package/development/autocomplete-grid/autocomplete-grid-cell/autocomplete-grid-cell.component.js +2 -0
  46. package/development/autocomplete-grid/autocomplete-grid-cell.d.ts +2 -0
  47. package/development/autocomplete-grid/autocomplete-grid-cell.d.ts.map +1 -0
  48. package/development/autocomplete-grid/autocomplete-grid-cell.js +10 -0
  49. package/development/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.d.ts +20 -0
  50. package/development/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.d.ts.map +1 -0
  51. package/development/autocomplete-grid/autocomplete-grid-optgroup/autocomplete-grid-optgroup.component.js +30 -0
  52. package/development/autocomplete-grid/autocomplete-grid-optgroup.d.ts +2 -0
  53. package/development/autocomplete-grid/autocomplete-grid-optgroup.d.ts.map +1 -0
  54. package/development/autocomplete-grid/autocomplete-grid-optgroup.js +10 -0
  55. package/development/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.d.ts +27 -0
  56. package/development/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.d.ts.map +1 -0
  57. package/development/autocomplete-grid/autocomplete-grid-option/autocomplete-grid-option.component.js +2 -0
  58. package/development/autocomplete-grid/autocomplete-grid-option.d.ts +2 -0
  59. package/development/autocomplete-grid/autocomplete-grid-option.d.ts.map +1 -0
  60. package/development/autocomplete-grid/autocomplete-grid-option.js +10 -0
  61. package/development/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.d.ts +20 -0
  62. package/development/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.d.ts.map +1 -0
  63. package/development/autocomplete-grid/autocomplete-grid-row/autocomplete-grid-row.component.js +2 -0
  64. package/development/autocomplete-grid/autocomplete-grid-row.d.ts +2 -0
  65. package/development/autocomplete-grid/autocomplete-grid-row.d.ts.map +1 -0
  66. package/development/autocomplete-grid/autocomplete-grid-row.js +10 -0
  67. package/development/autocomplete-grid/autocomplete-grid.d.ts +2 -0
  68. package/development/autocomplete-grid/autocomplete-grid.d.ts.map +1 -0
  69. package/development/autocomplete-grid/autocomplete-grid.js +10 -0
  70. package/development/autocomplete-grid-cell.component-BxkWGaX0.js +34 -0
  71. package/development/autocomplete-grid-option.component-5mPGswUO.js +61 -0
  72. package/development/autocomplete-grid-row.component-DEm6zyHZ.js +39 -0
  73. package/development/autocomplete-grid.d.ts +2 -0
  74. package/development/autocomplete-grid.d.ts.map +1 -0
  75. package/development/autocomplete-grid.js +19 -0
  76. package/development/autocomplete-grid.pure.d.ts +8 -0
  77. package/development/autocomplete-grid.pure.d.ts.map +1 -0
  78. package/development/autocomplete-grid.pure.js +7 -0
  79. package/development/core/datetime/date-helper.d.ts +27 -0
  80. package/development/core/datetime/date-helper.d.ts.map +1 -0
  81. package/development/core/datetime/date-helper.js +2 -0
  82. package/development/core/datetime.d.ts +3 -0
  83. package/development/core/datetime.d.ts.map +1 -0
  84. package/development/core/datetime.js +2 -0
  85. package/development/core/timetable/access-leg-helper.d.ts +26 -0
  86. package/development/core/timetable/access-leg-helper.d.ts.map +1 -0
  87. package/development/core/timetable/access-leg-helper.js +147 -0
  88. package/development/core/timetable/timetable-helper.d.ts +12 -0
  89. package/development/core/timetable/timetable-helper.d.ts.map +1 -0
  90. package/development/core/timetable/timetable-helper.js +19 -0
  91. package/development/core/timetable/timetable-properties.d.ts +308 -0
  92. package/development/core/timetable/timetable-properties.d.ts.map +1 -0
  93. package/development/core/timetable/timetable-properties.js +0 -0
  94. package/development/core/timetable.d.ts +5 -0
  95. package/development/core/timetable.d.ts.map +1 -0
  96. package/development/core/timetable.js +4 -0
  97. package/development/date-helper-qNdwgC9O.js +520 -0
  98. package/development/differenceInMinutes-B7_GTDq7.js +110 -0
  99. package/development/format-DFx4997p.js +1848 -0
  100. package/development/isValid-JpZ7FphI.js +178 -0
  101. package/development/journey-summary/journey-summary.component.d.ts +67 -0
  102. package/development/journey-summary/journey-summary.component.d.ts.map +1 -0
  103. package/development/journey-summary/journey-summary.component.js +2 -0
  104. package/development/journey-summary.component-BZwgD4im.js +340 -0
  105. package/development/journey-summary.d.ts +2 -0
  106. package/development/journey-summary.d.ts.map +1 -0
  107. package/development/journey-summary.js +9 -0
  108. package/development/journey-summary.pure.d.ts +3 -0
  109. package/development/journey-summary.pure.d.ts.map +1 -0
  110. package/development/journey-summary.pure.js +2 -0
  111. package/development/mapper-hWWm7Uke.js +11454 -0
  112. package/development/pearl-chain/pearl-chain.component.d.ts +44 -0
  113. package/development/pearl-chain/pearl-chain.component.d.ts.map +1 -0
  114. package/development/pearl-chain/pearl-chain.component.js +2 -0
  115. package/development/pearl-chain-time/pearl-chain-time.component.d.ts +49 -0
  116. package/development/pearl-chain-time/pearl-chain-time.component.d.ts.map +1 -0
  117. package/development/pearl-chain-time/pearl-chain-time.component.js +2 -0
  118. package/development/pearl-chain-time.component-B2_BI6E_.js +319 -0
  119. package/development/pearl-chain-time.d.ts +2 -0
  120. package/development/pearl-chain-time.d.ts.map +1 -0
  121. package/development/pearl-chain-time.js +9 -0
  122. package/development/pearl-chain-time.pure.d.ts +3 -0
  123. package/development/pearl-chain-time.pure.d.ts.map +1 -0
  124. package/development/pearl-chain-time.pure.js +2 -0
  125. package/development/pearl-chain-vertical/pearl-chain-vertical.component.d.ts +18 -0
  126. package/development/pearl-chain-vertical/pearl-chain-vertical.component.d.ts.map +1 -0
  127. package/development/pearl-chain-vertical/pearl-chain-vertical.component.js +2 -0
  128. package/development/pearl-chain-vertical-item/pearl-chain-vertical-item.component.d.ts +36 -0
  129. package/development/pearl-chain-vertical-item/pearl-chain-vertical-item.component.d.ts.map +1 -0
  130. package/development/pearl-chain-vertical-item/pearl-chain-vertical-item.component.js +2 -0
  131. package/development/pearl-chain-vertical-item.component-DcmH13Vb.js +133 -0
  132. package/development/pearl-chain-vertical-item.d.ts +2 -0
  133. package/development/pearl-chain-vertical-item.d.ts.map +1 -0
  134. package/development/pearl-chain-vertical-item.js +9 -0
  135. package/development/pearl-chain-vertical-item.pure.d.ts +3 -0
  136. package/development/pearl-chain-vertical-item.pure.d.ts.map +1 -0
  137. package/development/pearl-chain-vertical-item.pure.js +2 -0
  138. package/development/pearl-chain-vertical.component-CpcNFl-x.js +31 -0
  139. package/development/pearl-chain-vertical.d.ts +2 -0
  140. package/development/pearl-chain-vertical.d.ts.map +1 -0
  141. package/development/pearl-chain-vertical.js +9 -0
  142. package/development/pearl-chain-vertical.pure.d.ts +3 -0
  143. package/development/pearl-chain-vertical.pure.d.ts.map +1 -0
  144. package/development/pearl-chain-vertical.pure.js +2 -0
  145. package/development/pearl-chain.component-oQZUzsyW.js +316 -0
  146. package/development/pearl-chain.d.ts +2 -0
  147. package/development/pearl-chain.d.ts.map +1 -0
  148. package/development/pearl-chain.js +9 -0
  149. package/development/pearl-chain.pure.d.ts +3 -0
  150. package/development/pearl-chain.pure.d.ts.map +1 -0
  151. package/development/pearl-chain.pure.js +2 -0
  152. package/development/seat-reservation/common/mapper/icon-mapper.d.ts +106 -0
  153. package/development/seat-reservation/common/mapper/icon-mapper.d.ts.map +1 -0
  154. package/development/seat-reservation/common/mapper/icon-mapper.js +170 -0
  155. package/development/seat-reservation/common/mapper/mapper.d.ts +34 -0
  156. package/development/seat-reservation/common/mapper/mapper.d.ts.map +1 -0
  157. package/development/seat-reservation/common/mapper/mapper.js +2 -0
  158. package/development/seat-reservation/common/mapper.d.ts +3 -0
  159. package/development/seat-reservation/common/mapper.d.ts.map +1 -0
  160. package/development/seat-reservation/common/mapper.js +3 -0
  161. package/development/seat-reservation/common/svgs.d.ts +24 -0
  162. package/development/seat-reservation/common/svgs.d.ts.map +1 -0
  163. package/development/seat-reservation/common/svgs.js +2 -0
  164. package/development/seat-reservation/common/translations/i18n.d.ts +28 -0
  165. package/development/seat-reservation/common/translations/i18n.d.ts.map +1 -0
  166. package/development/seat-reservation/common/translations/i18n.js +1120 -0
  167. package/development/seat-reservation/common/translations.d.ts +2 -0
  168. package/development/seat-reservation/common/translations.d.ts.map +1 -0
  169. package/development/seat-reservation/common/translations.js +2 -0
  170. package/development/seat-reservation/common/types.d.ts +102 -0
  171. package/development/seat-reservation/common/types.d.ts.map +1 -0
  172. package/development/seat-reservation/common/types.js +0 -0
  173. package/development/seat-reservation/common.d.ts +6 -0
  174. package/development/seat-reservation/common.d.ts.map +1 -0
  175. package/development/seat-reservation/common.js +12 -0
  176. package/development/seat-reservation/seat-reservation/seat-reservation-base-element.d.ts +294 -0
  177. package/development/seat-reservation/seat-reservation/seat-reservation-base-element.d.ts.map +1 -0
  178. package/development/seat-reservation/seat-reservation/seat-reservation-base-element.js +1350 -0
  179. package/development/seat-reservation/seat-reservation/seat-reservation.component.d.ts +77 -0
  180. package/development/seat-reservation/seat-reservation/seat-reservation.component.d.ts.map +1 -0
  181. package/development/seat-reservation/seat-reservation/seat-reservation.component.js +2 -0
  182. package/development/seat-reservation/seat-reservation-area/seat-reservation-area.component.d.ts +20 -0
  183. package/development/seat-reservation/seat-reservation-area/seat-reservation-area.component.d.ts.map +1 -0
  184. package/development/seat-reservation/seat-reservation-area/seat-reservation-area.component.js +2 -0
  185. package/development/seat-reservation/seat-reservation-area.d.ts +2 -0
  186. package/development/seat-reservation/seat-reservation-area.d.ts.map +1 -0
  187. package/development/seat-reservation/seat-reservation-area.js +10 -0
  188. package/development/seat-reservation/seat-reservation-graphic/seat-reservation-assets.d.ts +9 -0
  189. package/development/seat-reservation/seat-reservation-graphic/seat-reservation-assets.d.ts.map +1 -0
  190. package/development/seat-reservation/seat-reservation-graphic/seat-reservation-assets.js +306 -0
  191. package/development/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.d.ts +22 -0
  192. package/development/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.d.ts.map +1 -0
  193. package/development/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.js +2 -0
  194. package/development/seat-reservation/seat-reservation-graphic.d.ts +2 -0
  195. package/development/seat-reservation/seat-reservation-graphic.d.ts.map +1 -0
  196. package/development/seat-reservation/seat-reservation-graphic.js +10 -0
  197. package/development/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.d.ts +56 -0
  198. package/development/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.d.ts.map +1 -0
  199. package/development/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.js +2 -0
  200. package/development/seat-reservation/seat-reservation-navigation-coach.d.ts +2 -0
  201. package/development/seat-reservation/seat-reservation-navigation-coach.d.ts.map +1 -0
  202. package/development/seat-reservation/seat-reservation-navigation-coach.js +10 -0
  203. package/development/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.d.ts +25 -0
  204. package/development/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.d.ts.map +1 -0
  205. package/development/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.js +2 -0
  206. package/development/seat-reservation/seat-reservation-navigation-services.d.ts +2 -0
  207. package/development/seat-reservation/seat-reservation-navigation-services.d.ts.map +1 -0
  208. package/development/seat-reservation/seat-reservation-navigation-services.js +10 -0
  209. package/development/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.d.ts +49 -0
  210. package/development/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.d.ts.map +1 -0
  211. package/development/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.js +2 -0
  212. package/development/seat-reservation/seat-reservation-place-control.d.ts +2 -0
  213. package/development/seat-reservation/seat-reservation-place-control.d.ts.map +1 -0
  214. package/development/seat-reservation/seat-reservation-place-control.js +10 -0
  215. package/development/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.d.ts +16 -0
  216. package/development/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.d.ts.map +1 -0
  217. package/development/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.js +2 -0
  218. package/development/seat-reservation/seat-reservation-scoped.d.ts +2 -0
  219. package/development/seat-reservation/seat-reservation-scoped.d.ts.map +1 -0
  220. package/development/seat-reservation/seat-reservation-scoped.js +10 -0
  221. package/development/seat-reservation/seat-reservation.d.ts +3 -0
  222. package/development/seat-reservation/seat-reservation.d.ts.map +1 -0
  223. package/development/seat-reservation/seat-reservation.js +11 -0
  224. package/development/seat-reservation-area.component-DbeuTnXT.js +96 -0
  225. package/development/seat-reservation-graphic.component-DlrHtlia.js +129 -0
  226. package/development/seat-reservation-navigation-coach.component-CjoDkcVU.js +428 -0
  227. package/development/seat-reservation-navigation-services.component-CGel7__P.js +159 -0
  228. package/development/seat-reservation-place-control.component-CM9efId7.js +429 -0
  229. package/development/seat-reservation-scoped.component-CFA_bJ3o.js +25 -0
  230. package/development/seat-reservation.component-DFJVFmrI.js +510 -0
  231. package/development/seat-reservation.d.ts +2 -0
  232. package/development/seat-reservation.d.ts.map +1 -0
  233. package/development/seat-reservation.js +27 -0
  234. package/development/seat-reservation.pure.d.ts +15 -0
  235. package/development/seat-reservation.pure.d.ts.map +1 -0
  236. package/development/seat-reservation.pure.js +15 -0
  237. package/development/svgs-kDpBCto5.js +28 -0
  238. package/development/timetable-duration/timetable-duration.component.d.ts +24 -0
  239. package/development/timetable-duration/timetable-duration.component.d.ts.map +1 -0
  240. package/development/timetable-duration/timetable-duration.component.js +2 -0
  241. package/development/timetable-duration.component-BhFlqYbV.js +100 -0
  242. package/development/timetable-duration.d.ts +2 -0
  243. package/development/timetable-duration.d.ts.map +1 -0
  244. package/development/timetable-duration.js +9 -0
  245. package/development/timetable-duration.pure.d.ts +3 -0
  246. package/development/timetable-duration.pure.d.ts.map +1 -0
  247. package/development/timetable-duration.pure.js +2 -0
  248. package/development/timetable-row/timetable-row.component.d.ts +89 -0
  249. package/development/timetable-row/timetable-row.component.d.ts.map +1 -0
  250. package/development/timetable-row/timetable-row.component.js +2 -0
  251. package/development/timetable-row.component-Dko8laRT.js +729 -0
  252. package/development/timetable-row.d.ts +2 -0
  253. package/development/timetable-row.d.ts.map +1 -0
  254. package/development/timetable-row.js +9 -0
  255. package/development/timetable-row.pure.d.ts +3 -0
  256. package/development/timetable-row.pure.d.ts.map +1 -0
  257. package/development/timetable-row.pure.js +2 -0
  258. package/development/toDate-DOFAOjP-.js +150 -0
  259. package/differenceInMinutes-Dr9gRqtu.js +27 -0
  260. package/format-CM5exOsN.js +1103 -0
  261. package/index.d.ts +33 -0
  262. package/index.js +32 -0
  263. package/isValid-B9oVW3lA.js +36 -0
  264. package/journey-summary/journey-summary.component.js +2 -0
  265. package/journey-summary.component-DC7-qPHY.js +264 -0
  266. package/journey-summary.js +6 -0
  267. package/journey-summary.pure.js +2 -0
  268. package/mapper-DkiDDseD.js +11382 -0
  269. package/off-brand-theme.css +13 -0
  270. package/package.json +222 -1
  271. package/pearl-chain/pearl-chain.component.js +2 -0
  272. package/pearl-chain-time/pearl-chain-time.component.js +2 -0
  273. package/pearl-chain-time.component-CkKsrbgQ.js +239 -0
  274. package/pearl-chain-time.js +6 -0
  275. package/pearl-chain-time.pure.js +2 -0
  276. package/pearl-chain-vertical/pearl-chain-vertical.component.js +2 -0
  277. package/pearl-chain-vertical-item/pearl-chain-vertical-item.component.js +2 -0
  278. package/pearl-chain-vertical-item.component-BUqZ-3Ay.js +108 -0
  279. package/pearl-chain-vertical-item.js +6 -0
  280. package/pearl-chain-vertical-item.pure.js +2 -0
  281. package/pearl-chain-vertical.component-Df9CvRxo.js +21 -0
  282. package/pearl-chain-vertical.js +6 -0
  283. package/pearl-chain-vertical.pure.js +2 -0
  284. package/pearl-chain.component-CpISVoAu.js +194 -0
  285. package/pearl-chain.js +6 -0
  286. package/pearl-chain.pure.js +2 -0
  287. package/safety-theme.css +13 -0
  288. package/seat-reservation/common/mapper/icon-mapper.js +72 -0
  289. package/seat-reservation/common/mapper/mapper.js +2 -0
  290. package/seat-reservation/common/mapper.js +3 -0
  291. package/seat-reservation/common/svgs.js +2 -0
  292. package/seat-reservation/common/translations/i18n.js +1085 -0
  293. package/seat-reservation/common/translations.js +2 -0
  294. package/seat-reservation/common/types.js +0 -0
  295. package/seat-reservation/common.js +9 -0
  296. package/seat-reservation/seat-reservation/seat-reservation-base-element.js +861 -0
  297. package/seat-reservation/seat-reservation/seat-reservation.component.js +2 -0
  298. package/seat-reservation/seat-reservation-area/seat-reservation-area.component.js +2 -0
  299. package/seat-reservation/seat-reservation-area.js +4 -0
  300. package/seat-reservation/seat-reservation-graphic/seat-reservation-assets.js +291 -0
  301. package/seat-reservation/seat-reservation-graphic/seat-reservation-graphic.component.js +2 -0
  302. package/seat-reservation/seat-reservation-graphic.js +4 -0
  303. package/seat-reservation/seat-reservation-navigation-coach/seat-reservation-navigation-coach.component.js +2 -0
  304. package/seat-reservation/seat-reservation-navigation-coach.js +4 -0
  305. package/seat-reservation/seat-reservation-navigation-services/seat-reservation-navigation-services.component.js +2 -0
  306. package/seat-reservation/seat-reservation-navigation-services.js +4 -0
  307. package/seat-reservation/seat-reservation-place-control/seat-reservation-place-control.component.js +2 -0
  308. package/seat-reservation/seat-reservation-place-control.js +4 -0
  309. package/seat-reservation/seat-reservation-scoped/seat-reservation-scoped.component.js +2 -0
  310. package/seat-reservation/seat-reservation-scoped.js +4 -0
  311. package/seat-reservation/seat-reservation.js +5 -0
  312. package/seat-reservation-area.component-CtYawDjE.js +75 -0
  313. package/seat-reservation-graphic.component-Cm_pVxaB.js +102 -0
  314. package/seat-reservation-navigation-coach.component-sug9IBTH.js +333 -0
  315. package/seat-reservation-navigation-services.component-C9dDYD_M.js +127 -0
  316. package/seat-reservation-place-control.component-CE7d9M2b.js +322 -0
  317. package/seat-reservation-scoped.component-DVyP2JGE.js +17 -0
  318. package/seat-reservation.component-DajC6fqU.js +367 -0
  319. package/seat-reservation.js +17 -0
  320. package/seat-reservation.pure.js +15 -0
  321. package/standard-theme.css +13 -0
  322. package/svgs-D5DhLHxC.js +26 -0
  323. package/timetable-duration/timetable-duration.component.js +2 -0
  324. package/timetable-duration.component-BnJA8wSb.js +65 -0
  325. package/timetable-duration.js +6 -0
  326. package/timetable-duration.pure.js +2 -0
  327. package/timetable-row/timetable-row.component.js +2 -0
  328. package/timetable-row.component-DbzBCpKR.js +559 -0
  329. package/timetable-row.js +6 -0
  330. package/timetable-row.pure.js +2 -0
  331. package/toDate-p-Tpkb7t.js +16 -0
@@ -0,0 +1,1350 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { SbbElement } from "@sbb-esta/lyne-elements/core/base-elements.js";
3
+ import { forceType } from "@sbb-esta/lyne-elements/core/decorators.js";
4
+ import { isServer } from "lit";
5
+ import { isArrowKeyOrPageKeysPressed } from "@sbb-esta/lyne-elements/core/a11y.js";
6
+ import { eventOptions, property, state } from "lit/decorators.js";
7
+ import { mapCoachInfosToCoachSelection, mapIconToSvg, mapPlaceAndCoachToSeatReservationPlaceSelection, mapPlaceInfosToPlaceSelection } from "../common/mapper.js";
8
+ //#region src/elements-experimental/seat-reservation/seat-reservation/seat-reservation-base-element.ts
9
+ var ScrollDirection;
10
+ (function(ScrollDirection) {
11
+ ScrollDirection["right"] = "right";
12
+ ScrollDirection["left"] = "left";
13
+ })(ScrollDirection || (ScrollDirection = {}));
14
+ var MAX_SERVICE_PROPERTIES = 3;
15
+ var ALLOWED_SERVICE_ICONS = [
16
+ "sa-vo",
17
+ "sa-rs",
18
+ "sa-abteilkinderwagen",
19
+ "sa-wr",
20
+ "sa-fa",
21
+ "sa-bz",
22
+ "sa-rz"
23
+ ];
24
+ var SeatReservationBaseElement = (() => {
25
+ let _classSuper = SbbElement;
26
+ let _instanceExtraInitializers = [];
27
+ let _seatReservations_decorators;
28
+ let _seatReservations_initializers = [];
29
+ let _seatReservations_extraInitializers = [];
30
+ let _travelDirection_decorators;
31
+ let _travelDirection_initializers = [];
32
+ let _travelDirection_extraInitializers = [];
33
+ let _hasNavigation_decorators;
34
+ let _hasNavigation_initializers = [];
35
+ let _hasNavigation_extraInitializers = [];
36
+ let _alignVertical_decorators;
37
+ let _alignVertical_initializers = [];
38
+ let _alignVertical_extraInitializers = [];
39
+ let _baseGridSize_decorators;
40
+ let _baseGridSize_initializers = [];
41
+ let _baseGridSize_extraInitializers = [];
42
+ let _height_decorators;
43
+ let _height_initializers = [];
44
+ let _height_extraInitializers = [];
45
+ let _maxSeatReservations_decorators;
46
+ let _maxSeatReservations_initializers = [];
47
+ let _maxSeatReservations_extraInitializers = [];
48
+ let _maxBicycleReservations_decorators;
49
+ let _maxBicycleReservations_initializers = [];
50
+ let _maxBicycleReservations_extraInitializers = [];
51
+ let _preventPlaceClick_decorators;
52
+ let _preventPlaceClick_initializers = [];
53
+ let _preventPlaceClick_extraInitializers = [];
54
+ let _preselectCoachIndex_decorators;
55
+ let _preselectCoachIndex_initializers = [];
56
+ let _preselectCoachIndex_extraInitializers = [];
57
+ let _showTitleInfo_decorators;
58
+ let _showTitleInfo_initializers = [];
59
+ let _showTitleInfo_extraInitializers = [];
60
+ let _selectedCoachIndex_decorators;
61
+ let _selectedCoachIndex_initializers = [];
62
+ let _selectedCoachIndex_extraInitializers = [];
63
+ let _focusedCoachIndex_decorators;
64
+ let _focusedCoachIndex_initializers = [];
65
+ let _focusedCoachIndex_extraInitializers = [];
66
+ let _hoveredCoachIndex_decorators;
67
+ let _hoveredCoachIndex_initializers = [];
68
+ let _hoveredCoachIndex_extraInitializers = [];
69
+ let _coachAreaScrollend_decorators;
70
+ return class SeatReservationBaseElement extends _classSuper {
71
+ static {
72
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
73
+ _seatReservations_decorators = [property({
74
+ attribute: "seat-reservations",
75
+ type: Array
76
+ })];
77
+ _travelDirection_decorators = [property({
78
+ attribute: "travel-direction",
79
+ type: String
80
+ })];
81
+ _hasNavigation_decorators = [forceType(), property({
82
+ attribute: "has-navigation",
83
+ type: Boolean
84
+ })];
85
+ _alignVertical_decorators = [forceType(), property({
86
+ attribute: "align-vertical",
87
+ type: Boolean,
88
+ reflect: true,
89
+ useDefault: true
90
+ })];
91
+ _baseGridSize_decorators = [forceType(), property({
92
+ attribute: "base-grid-size",
93
+ type: Number
94
+ })];
95
+ _height_decorators = [forceType(), property({
96
+ attribute: "height",
97
+ type: Number
98
+ })];
99
+ _maxSeatReservations_decorators = [forceType(), property({
100
+ attribute: "max-seat-reservations",
101
+ type: Number
102
+ })];
103
+ _maxBicycleReservations_decorators = [forceType(), property({
104
+ attribute: "max-bicycle-reservations",
105
+ type: Number
106
+ })];
107
+ _preventPlaceClick_decorators = [forceType(), property({
108
+ attribute: "prevent-place-click",
109
+ type: Boolean
110
+ })];
111
+ _preselectCoachIndex_decorators = [forceType(), property({
112
+ attribute: "preselect-coach-index",
113
+ type: Number
114
+ })];
115
+ _showTitleInfo_decorators = [forceType(), property({
116
+ attribute: "show-title-info",
117
+ type: Boolean
118
+ })];
119
+ _selectedCoachIndex_decorators = [state()];
120
+ _focusedCoachIndex_decorators = [state()];
121
+ _hoveredCoachIndex_decorators = [state()];
122
+ _coachAreaScrollend_decorators = [eventOptions({ passive: true })];
123
+ __esDecorate(this, null, _seatReservations_decorators, {
124
+ kind: "accessor",
125
+ name: "seatReservations",
126
+ static: false,
127
+ private: false,
128
+ access: {
129
+ has: (obj) => "seatReservations" in obj,
130
+ get: (obj) => obj.seatReservations,
131
+ set: (obj, value) => {
132
+ obj.seatReservations = value;
133
+ }
134
+ },
135
+ metadata: _metadata
136
+ }, _seatReservations_initializers, _seatReservations_extraInitializers);
137
+ __esDecorate(this, null, _travelDirection_decorators, {
138
+ kind: "accessor",
139
+ name: "travelDirection",
140
+ static: false,
141
+ private: false,
142
+ access: {
143
+ has: (obj) => "travelDirection" in obj,
144
+ get: (obj) => obj.travelDirection,
145
+ set: (obj, value) => {
146
+ obj.travelDirection = value;
147
+ }
148
+ },
149
+ metadata: _metadata
150
+ }, _travelDirection_initializers, _travelDirection_extraInitializers);
151
+ __esDecorate(this, null, _hasNavigation_decorators, {
152
+ kind: "accessor",
153
+ name: "hasNavigation",
154
+ static: false,
155
+ private: false,
156
+ access: {
157
+ has: (obj) => "hasNavigation" in obj,
158
+ get: (obj) => obj.hasNavigation,
159
+ set: (obj, value) => {
160
+ obj.hasNavigation = value;
161
+ }
162
+ },
163
+ metadata: _metadata
164
+ }, _hasNavigation_initializers, _hasNavigation_extraInitializers);
165
+ __esDecorate(this, null, _alignVertical_decorators, {
166
+ kind: "accessor",
167
+ name: "alignVertical",
168
+ static: false,
169
+ private: false,
170
+ access: {
171
+ has: (obj) => "alignVertical" in obj,
172
+ get: (obj) => obj.alignVertical,
173
+ set: (obj, value) => {
174
+ obj.alignVertical = value;
175
+ }
176
+ },
177
+ metadata: _metadata
178
+ }, _alignVertical_initializers, _alignVertical_extraInitializers);
179
+ __esDecorate(this, null, _baseGridSize_decorators, {
180
+ kind: "accessor",
181
+ name: "baseGridSize",
182
+ static: false,
183
+ private: false,
184
+ access: {
185
+ has: (obj) => "baseGridSize" in obj,
186
+ get: (obj) => obj.baseGridSize,
187
+ set: (obj, value) => {
188
+ obj.baseGridSize = value;
189
+ }
190
+ },
191
+ metadata: _metadata
192
+ }, _baseGridSize_initializers, _baseGridSize_extraInitializers);
193
+ __esDecorate(this, null, _height_decorators, {
194
+ kind: "accessor",
195
+ name: "height",
196
+ static: false,
197
+ private: false,
198
+ access: {
199
+ has: (obj) => "height" in obj,
200
+ get: (obj) => obj.height,
201
+ set: (obj, value) => {
202
+ obj.height = value;
203
+ }
204
+ },
205
+ metadata: _metadata
206
+ }, _height_initializers, _height_extraInitializers);
207
+ __esDecorate(this, null, _maxSeatReservations_decorators, {
208
+ kind: "accessor",
209
+ name: "maxSeatReservations",
210
+ static: false,
211
+ private: false,
212
+ access: {
213
+ has: (obj) => "maxSeatReservations" in obj,
214
+ get: (obj) => obj.maxSeatReservations,
215
+ set: (obj, value) => {
216
+ obj.maxSeatReservations = value;
217
+ }
218
+ },
219
+ metadata: _metadata
220
+ }, _maxSeatReservations_initializers, _maxSeatReservations_extraInitializers);
221
+ __esDecorate(this, null, _maxBicycleReservations_decorators, {
222
+ kind: "accessor",
223
+ name: "maxBicycleReservations",
224
+ static: false,
225
+ private: false,
226
+ access: {
227
+ has: (obj) => "maxBicycleReservations" in obj,
228
+ get: (obj) => obj.maxBicycleReservations,
229
+ set: (obj, value) => {
230
+ obj.maxBicycleReservations = value;
231
+ }
232
+ },
233
+ metadata: _metadata
234
+ }, _maxBicycleReservations_initializers, _maxBicycleReservations_extraInitializers);
235
+ __esDecorate(this, null, _preventPlaceClick_decorators, {
236
+ kind: "accessor",
237
+ name: "preventPlaceClick",
238
+ static: false,
239
+ private: false,
240
+ access: {
241
+ has: (obj) => "preventPlaceClick" in obj,
242
+ get: (obj) => obj.preventPlaceClick,
243
+ set: (obj, value) => {
244
+ obj.preventPlaceClick = value;
245
+ }
246
+ },
247
+ metadata: _metadata
248
+ }, _preventPlaceClick_initializers, _preventPlaceClick_extraInitializers);
249
+ __esDecorate(this, null, _preselectCoachIndex_decorators, {
250
+ kind: "accessor",
251
+ name: "preselectCoachIndex",
252
+ static: false,
253
+ private: false,
254
+ access: {
255
+ has: (obj) => "preselectCoachIndex" in obj,
256
+ get: (obj) => obj.preselectCoachIndex,
257
+ set: (obj, value) => {
258
+ obj.preselectCoachIndex = value;
259
+ }
260
+ },
261
+ metadata: _metadata
262
+ }, _preselectCoachIndex_initializers, _preselectCoachIndex_extraInitializers);
263
+ __esDecorate(this, null, _showTitleInfo_decorators, {
264
+ kind: "accessor",
265
+ name: "showTitleInfo",
266
+ static: false,
267
+ private: false,
268
+ access: {
269
+ has: (obj) => "showTitleInfo" in obj,
270
+ get: (obj) => obj.showTitleInfo,
271
+ set: (obj, value) => {
272
+ obj.showTitleInfo = value;
273
+ }
274
+ },
275
+ metadata: _metadata
276
+ }, _showTitleInfo_initializers, _showTitleInfo_extraInitializers);
277
+ __esDecorate(this, null, _selectedCoachIndex_decorators, {
278
+ kind: "accessor",
279
+ name: "selectedCoachIndex",
280
+ static: false,
281
+ private: false,
282
+ access: {
283
+ has: (obj) => "selectedCoachIndex" in obj,
284
+ get: (obj) => obj.selectedCoachIndex,
285
+ set: (obj, value) => {
286
+ obj.selectedCoachIndex = value;
287
+ }
288
+ },
289
+ metadata: _metadata
290
+ }, _selectedCoachIndex_initializers, _selectedCoachIndex_extraInitializers);
291
+ __esDecorate(this, null, _focusedCoachIndex_decorators, {
292
+ kind: "accessor",
293
+ name: "focusedCoachIndex",
294
+ static: false,
295
+ private: false,
296
+ access: {
297
+ has: (obj) => "focusedCoachIndex" in obj,
298
+ get: (obj) => obj.focusedCoachIndex,
299
+ set: (obj, value) => {
300
+ obj.focusedCoachIndex = value;
301
+ }
302
+ },
303
+ metadata: _metadata
304
+ }, _focusedCoachIndex_initializers, _focusedCoachIndex_extraInitializers);
305
+ __esDecorate(this, null, _hoveredCoachIndex_decorators, {
306
+ kind: "accessor",
307
+ name: "hoveredCoachIndex",
308
+ static: false,
309
+ private: false,
310
+ access: {
311
+ has: (obj) => "hoveredCoachIndex" in obj,
312
+ get: (obj) => obj.hoveredCoachIndex,
313
+ set: (obj, value) => {
314
+ obj.hoveredCoachIndex = value;
315
+ }
316
+ },
317
+ metadata: _metadata
318
+ }, _hoveredCoachIndex_initializers, _hoveredCoachIndex_extraInitializers);
319
+ __esDecorate(this, null, _coachAreaScrollend_decorators, {
320
+ kind: "method",
321
+ name: "coachAreaScrollend",
322
+ static: false,
323
+ private: false,
324
+ access: {
325
+ has: (obj) => "coachAreaScrollend" in obj,
326
+ get: (obj) => obj.coachAreaScrollend
327
+ },
328
+ metadata: _metadata
329
+ }, null, _instanceExtraInitializers);
330
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, {
331
+ enumerable: true,
332
+ configurable: true,
333
+ writable: true,
334
+ value: _metadata
335
+ });
336
+ }
337
+ static {
338
+ this.events = {
339
+ selectedplaces: "selectedplaces",
340
+ selectedcoach: "selectedcoach"
341
+ };
342
+ }
343
+ #seatReservations_accessor_storage;
344
+ /** The seat reservations array contains all coaches and places */
345
+ get seatReservations() {
346
+ return this.#seatReservations_accessor_storage;
347
+ }
348
+ set seatReservations(value) {
349
+ this.#seatReservations_accessor_storage = value;
350
+ }
351
+ #travelDirection_accessor_storage;
352
+ /** Displays an arrow showing what direction does train drive*/
353
+ get travelDirection() {
354
+ return this.#travelDirection_accessor_storage;
355
+ }
356
+ set travelDirection(value) {
357
+ this.#travelDirection_accessor_storage = value;
358
+ }
359
+ #hasNavigation_accessor_storage;
360
+ /** The seat reservation navigation can be toggled by this property */
361
+ get hasNavigation() {
362
+ return this.#hasNavigation_accessor_storage;
363
+ }
364
+ set hasNavigation(value) {
365
+ this.#hasNavigation_accessor_storage = value;
366
+ }
367
+ #alignVertical_accessor_storage;
368
+ /** The seat reservation area is aligned vertically */
369
+ get alignVertical() {
370
+ return this.#alignVertical_accessor_storage;
371
+ }
372
+ set alignVertical(value) {
373
+ this.#alignVertical_accessor_storage = value;
374
+ }
375
+ #baseGridSize_accessor_storage;
376
+ /** The seat reservation area's base grid size */
377
+ get baseGridSize() {
378
+ return this.#baseGridSize_accessor_storage;
379
+ }
380
+ set baseGridSize(value) {
381
+ this.#baseGridSize_accessor_storage = value;
382
+ }
383
+ #height_accessor_storage;
384
+ /** The seat reservation area's width */
385
+ get height() {
386
+ return this.#height_accessor_storage;
387
+ }
388
+ set height(value) {
389
+ this.#height_accessor_storage = value;
390
+ }
391
+ #maxSeatReservations_accessor_storage;
392
+ /** Maximal number of possible clickable seats */
393
+ get maxSeatReservations() {
394
+ return this.#maxSeatReservations_accessor_storage;
395
+ }
396
+ set maxSeatReservations(value) {
397
+ this.#maxSeatReservations_accessor_storage = value;
398
+ }
399
+ #maxBicycleReservations_accessor_storage;
400
+ /** Maximal number of possible clickable bicycle places */
401
+ get maxBicycleReservations() {
402
+ return this.#maxBicycleReservations_accessor_storage;
403
+ }
404
+ set maxBicycleReservations(value) {
405
+ this.#maxBicycleReservations_accessor_storage = value;
406
+ }
407
+ #preventPlaceClick_accessor_storage;
408
+ /** Any click functionality is prevented */
409
+ get preventPlaceClick() {
410
+ return this.#preventPlaceClick_accessor_storage;
411
+ }
412
+ set preventPlaceClick(value) {
413
+ this.#preventPlaceClick_accessor_storage = value;
414
+ }
415
+ #preselectCoachIndex_accessor_storage;
416
+ get preselectCoachIndex() {
417
+ return this.#preselectCoachIndex_accessor_storage;
418
+ }
419
+ set preselectCoachIndex(value) {
420
+ this.#preselectCoachIndex_accessor_storage = value;
421
+ }
422
+ #showTitleInfo_accessor_storage;
423
+ /** The seat reservation title information at place-controls, navigation-coaches and navigation-services can be toggled by this property */
424
+ get showTitleInfo() {
425
+ return this.#showTitleInfo_accessor_storage;
426
+ }
427
+ set showTitleInfo(value) {
428
+ this.#showTitleInfo_accessor_storage = value;
429
+ }
430
+ #selectedCoachIndex_accessor_storage;
431
+ get selectedCoachIndex() {
432
+ return this.#selectedCoachIndex_accessor_storage;
433
+ }
434
+ set selectedCoachIndex(value) {
435
+ this.#selectedCoachIndex_accessor_storage = value;
436
+ }
437
+ #focusedCoachIndex_accessor_storage;
438
+ get focusedCoachIndex() {
439
+ return this.#focusedCoachIndex_accessor_storage;
440
+ }
441
+ set focusedCoachIndex(value) {
442
+ this.#focusedCoachIndex_accessor_storage = value;
443
+ }
444
+ #hoveredCoachIndex_accessor_storage;
445
+ get hoveredCoachIndex() {
446
+ return this.#hoveredCoachIndex_accessor_storage;
447
+ }
448
+ set hoveredCoachIndex(value) {
449
+ this.#hoveredCoachIndex_accessor_storage = value;
450
+ }
451
+ constructor() {
452
+ super();
453
+ this.#seatReservations_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _seatReservations_initializers, null));
454
+ this.#travelDirection_accessor_storage = (__runInitializers(this, _seatReservations_extraInitializers), __runInitializers(this, _travelDirection_initializers, "NONE"));
455
+ this.#hasNavigation_accessor_storage = (__runInitializers(this, _travelDirection_extraInitializers), __runInitializers(this, _hasNavigation_initializers, true));
456
+ this.#alignVertical_accessor_storage = (__runInitializers(this, _hasNavigation_extraInitializers), __runInitializers(this, _alignVertical_initializers, false));
457
+ this.#baseGridSize_accessor_storage = (__runInitializers(this, _alignVertical_extraInitializers), __runInitializers(this, _baseGridSize_initializers, 16));
458
+ this.#height_accessor_storage = (__runInitializers(this, _baseGridSize_extraInitializers), __runInitializers(this, _height_initializers, null));
459
+ this.#maxSeatReservations_accessor_storage = (__runInitializers(this, _height_extraInitializers), __runInitializers(this, _maxSeatReservations_initializers, -1));
460
+ this.#maxBicycleReservations_accessor_storage = (__runInitializers(this, _maxSeatReservations_extraInitializers), __runInitializers(this, _maxBicycleReservations_initializers, -1));
461
+ this.#preventPlaceClick_accessor_storage = (__runInitializers(this, _maxBicycleReservations_extraInitializers), __runInitializers(this, _preventPlaceClick_initializers, false));
462
+ this.#preselectCoachIndex_accessor_storage = (__runInitializers(this, _preventPlaceClick_extraInitializers), __runInitializers(this, _preselectCoachIndex_initializers, -1));
463
+ this.#showTitleInfo_accessor_storage = (__runInitializers(this, _preselectCoachIndex_extraInitializers), __runInitializers(this, _showTitleInfo_initializers, false));
464
+ this.#selectedCoachIndex_accessor_storage = (__runInitializers(this, _showTitleInfo_extraInitializers), __runInitializers(this, _selectedCoachIndex_initializers, -1));
465
+ this.#focusedCoachIndex_accessor_storage = (__runInitializers(this, _selectedCoachIndex_extraInitializers), __runInitializers(this, _focusedCoachIndex_initializers, -1));
466
+ this.#hoveredCoachIndex_accessor_storage = (__runInitializers(this, _focusedCoachIndex_extraInitializers), __runInitializers(this, _hoveredCoachIndex_initializers, -1));
467
+ this.coachBorderPadding = (__runInitializers(this, _hoveredCoachIndex_extraInitializers), 6);
468
+ this.gapBetweenCoaches = 4;
469
+ this.coachBorderOffset = this.coachBorderPadding / this.baseGridSize;
470
+ this.gapBetweenCoachDecks = 48;
471
+ this.coachNavButtonDim = 0;
472
+ this.globalAreaIconDim = {
473
+ w: 2,
474
+ h: 2
475
+ };
476
+ this.globalAreaIconPadding = .8;
477
+ this.coachItemDetailsElements = [];
478
+ this.currScrollDirection = ScrollDirection.right;
479
+ this.maxCalcCoachesWidth = 0;
480
+ this.scrollCoachesAreaWidth = 0;
481
+ this.scrollNavigationAreaDim = 0;
482
+ this.triggerCoachPositionsCollection = [];
483
+ this.navigationScrollArea = null;
484
+ this.coachScrollArea = null;
485
+ this.currSelectedPlace = null;
486
+ this.currSelectedPlaceElementId = null;
487
+ this.currSelectedCoachIndex = -1;
488
+ this.currSelectedDeckIndex = 0;
489
+ this.preventCoachScrollByPlaceClick = false;
490
+ this.selectedSeatReservationPlaces = {
491
+ seats: [],
492
+ bicycles: []
493
+ };
494
+ this.seatReservationWithoutNavigationHasFocus = false;
495
+ this.isCoachGridFocusable = false;
496
+ this.isAutoScrolling = false;
497
+ this.isKeyboardNavigation = false;
498
+ this.hasMultipleDecks = false;
499
+ this.hasSeatReservationNativeFocus = false;
500
+ this.keyboardNavigationEvents = {
501
+ ArrowLeft: "ArrowLeft",
502
+ ArrowRight: "ArrowRight",
503
+ ArrowUp: "ArrowUp",
504
+ ArrowDown: "ArrowDown",
505
+ Tab: "Tab",
506
+ Enter: "Enter"
507
+ };
508
+ this.notAreaElements = [
509
+ "DRIVER_AREA",
510
+ "DRIVER_AREA_NO_VERTICAL_WALL",
511
+ "COACH_PASSAGE",
512
+ "COACH_WALL_NO_PASSAGE",
513
+ "COMPARTMENT_PASSAGE",
514
+ "COMPARTMENT_PASSAGE_HIGH",
515
+ "COMPARTMENT_PASSAGE_MIDDLE",
516
+ "COMPARTMENT_PASSAGE_LOW",
517
+ "COMPARTMENT_WALL"
518
+ ];
519
+ this.overHangingElementInformation = [];
520
+ this._isRunningInitPreselectCoachIndex = false;
521
+ this._lastStartScrollPos = -1;
522
+ this._prepareServiceIconsNavigation = (propertyIds) => {
523
+ if (!propertyIds) return [];
524
+ const shrunkPropertyIds = propertyIds?.map(function(propertyId) {
525
+ return {
526
+ pId: propertyId,
527
+ svgName: mapIconToSvg[propertyId]?.svgName ? mapIconToSvg[propertyId]?.svgName : ""
528
+ };
529
+ }).filter((propertyToSvg) => ALLOWED_SERVICE_ICONS.indexOf(propertyToSvg.svgName) !== -1).filter((value, index, self) => self.map((propSvg) => propSvg.svgName).indexOf(value.svgName) === index).map((propertyToSvg) => propertyToSvg.pId).slice(0, MAX_SERVICE_PROPERTIES);
530
+ return shrunkPropertyIds ? shrunkPropertyIds : [];
531
+ };
532
+ this.addEventListener("blur", () => this._onLeaveSeatReservationComponent());
533
+ }
534
+ willUpdate(changedProperties) {
535
+ super.willUpdate(changedProperties);
536
+ if (changedProperties.has("seatReservations")) {
537
+ this.hasMultipleDecks = this.seatReservations?.length > 1;
538
+ this._initPrepareSeatReservationData();
539
+ this._prepareCoachWidthAndGapCalculations();
540
+ this._initSeatReservationPlaceSelection();
541
+ this.initNavigationSelectionByScrollEvent();
542
+ }
543
+ if (changedProperties.has("baseGridSize")) {
544
+ this.coachBorderOffset = this.coachBorderPadding / this.baseGridSize;
545
+ this.style?.setProperty("--sbb-seat-reservation-grid-size", `${this.baseGridSize}px`);
546
+ this.initNavigationSelectionByScrollEvent();
547
+ }
548
+ if (changedProperties.has("height") && !!this.height) {
549
+ const seatReservationLayer = this.seatReservations[this.currSelectedDeckIndex] || null;
550
+ if (seatReservationLayer?.coachItems.length) {
551
+ this.baseGridSize = this.height / seatReservationLayer.coachItems[0].dimension.h;
552
+ this.coachBorderOffset = this.coachBorderPadding / this.baseGridSize;
553
+ this.style?.setProperty("--sbb-seat-reservation-grid-size", `${this.baseGridSize}px`);
554
+ this._initPrepareSeatReservationData();
555
+ this.initNavigationSelectionByScrollEvent();
556
+ }
557
+ }
558
+ if (changedProperties.has("alignVertical") && this.alignVertical) this.initNavigationSelectionByScrollEvent();
559
+ if (changedProperties.has("preselectCoachIndex")) {
560
+ this._isRunningInitPreselectCoachIndex = true;
561
+ setTimeout(() => this.scrollToSelectedNavCoach(this.preselectCoachIndex), 1);
562
+ }
563
+ }
564
+ navigateByDirectionBtn(btnDirection) {
565
+ this.unfocusPlaceElement();
566
+ let navigateToCoachIndex = this.currSelectedCoachIndex;
567
+ if (btnDirection == "DIRECTION_LEFT" && navigateToCoachIndex > 0) navigateToCoachIndex = this.currSelectedCoachIndex != -1 ? this.currSelectedCoachIndex - 1 : 0;
568
+ else if (btnDirection == "DIRECTION_RIGHT" && navigateToCoachIndex < this.seatReservations[this.currSelectedDeckIndex]?.coachItems.length - 1) navigateToCoachIndex = this.currSelectedCoachIndex != -1 ? this.currSelectedCoachIndex + 1 : 0;
569
+ this.scrollToSelectedNavCoach(navigateToCoachIndex);
570
+ }
571
+ /**
572
+ * Data can be prepared once for the entire component
573
+ * in order to avoid recurring iteration processes in rendering.
574
+ */
575
+ _initPrepareSeatReservationData() {
576
+ this._determineBaseFontSize();
577
+ if (this.hasMultipleDecks) this._initEmptyCoachDeckOffsets();
578
+ this._prepareCoachItemDetailsData();
579
+ this._prepareOptimizeAreaIconDimensionByMedian();
580
+ }
581
+ /** Init scroll event handling for coach navigation */
582
+ initNavigationSelectionByScrollEvent() {
583
+ this.coachScrollArea = this.shadowRoot?.querySelector("#sbb-sr__wrapper-scrollarea");
584
+ this.navigationScrollArea = this.shadowRoot?.querySelector("#sbb-sr__navigation-list-coaches");
585
+ const seatReservationDeck = this.seatReservations ? this.seatReservations[this.currSelectedDeckIndex] : null;
586
+ if (seatReservationDeck && seatReservationDeck.coachItems.length > 0) {
587
+ const coachHeightWithBorderPadding = seatReservationDeck.coachItems[0].dimension.h * this.baseGridSize + this.coachBorderPadding;
588
+ const gapBetweenCoachDecks = (this.seatReservations.length - 1) * this.gapBetweenCoachDecks;
589
+ this.style?.setProperty("--sbb-seat-reservation-height", `${coachHeightWithBorderPadding * this.seatReservations.length + gapBetweenCoachDecks}`);
590
+ this.style?.setProperty("--sbb-seat-reservation-decks", `${this.seatReservations.length}`);
591
+ }
592
+ if (this.navigationScrollArea) {
593
+ this.scrollNavigationAreaDim = this.alignVertical ? this.navigationScrollArea.getBoundingClientRect().height : this.navigationScrollArea.getBoundingClientRect().width;
594
+ const navCoachesList = this.navigationScrollArea.querySelector("ul > li");
595
+ if (navCoachesList) {
596
+ const firstLiEleDimension = navCoachesList?.getBoundingClientRect();
597
+ this.coachNavButtonDim = this.alignVertical ? firstLiEleDimension.height : firstLiEleDimension.width;
598
+ }
599
+ }
600
+ if (this.coachScrollArea && seatReservationDeck) {
601
+ let currCalcTriggerPos = 0;
602
+ this.scrollCoachesAreaWidth = this.alignVertical ? this.coachScrollArea.getBoundingClientRect().height : this.coachScrollArea.getBoundingClientRect().width;
603
+ this.triggerCoachPositionsCollection = seatReservationDeck.coachItems.map((coach) => {
604
+ const startPosX = currCalcTriggerPos;
605
+ const coachWidth = this.getCalculatedDimension(coach.dimension).w;
606
+ const currentCoachOverhangingInfo = this.overHangingElementInformation.find((e) => e.coachId === coach.id);
607
+ const overhangingElementsPresent = currentCoachOverhangingInfo?.overhangingPlaces || currentCoachOverhangingInfo?.overhangingGraphicAreas;
608
+ currCalcTriggerPos += coachWidth + (!overhangingElementsPresent ? this.gapBetweenCoaches : 2 * this.gapBetweenCoaches);
609
+ return {
610
+ start: startPosX,
611
+ end: currCalcTriggerPos,
612
+ width: coachWidth
613
+ };
614
+ });
615
+ this.maxCalcCoachesWidth = currCalcTriggerPos - this.gapBetweenCoaches;
616
+ }
617
+ }
618
+ /**
619
+ * Scroll event handler managed the end of scrolling inside the coach scroll area.
620
+ * Timeout event handling to check if the scrolling has been completed.
621
+ * It is required because the Safari browser does not handle scrollend event,
622
+ * and we therefore imitate this event -> scrollend.
623
+ */
624
+ coachAreaScrollend() {
625
+ if (this._scrollTimeout) clearTimeout(this._scrollTimeout);
626
+ this._scrollTimeout = setTimeout(() => this._handleCoachAreaScrollendEvent(), 150);
627
+ }
628
+ /**
629
+ * If no navigation exists (property setting -> hasNavigation) and a table coach gets the focus,
630
+ * the first place in the coach must be automatically preselected to control the place navigation via keyboard
631
+ *
632
+ * @param focusCoachIndex
633
+ */
634
+ onFocusTableCoachAndPreselectPlace(focusCoachIndex) {
635
+ if (!this.seatReservationWithoutNavigationHasFocus && !this.hasNavigation) {
636
+ this.seatReservationWithoutNavigationHasFocus = true;
637
+ this.currSelectedCoachIndex = focusCoachIndex === 0 ? this.getNextAvailableCoachIndex(-1) : this.getPrevAvailableCoachIndex(focusCoachIndex);
638
+ this.preselectPlaceInCoach();
639
+ }
640
+ }
641
+ /** Will be triggered by focus navigation direction */
642
+ onFocusNavDirectionButton() {
643
+ this.focusedCoachIndex = -1;
644
+ }
645
+ /** TAB Key Event handling for Coach Navigation */
646
+ onKeyNavigationNavCoachButton(event, currNavCoachButtonIndex) {
647
+ if (event.key === this.keyboardNavigationEvents.Tab) {
648
+ this._handleTabKeyNavigation(event, "navigation", currNavCoachButtonIndex);
649
+ return;
650
+ }
651
+ if (isArrowKeyOrPageKeysPressed(event)) this.keyboardSeatmapEventHandling(event);
652
+ }
653
+ /** General TAB Key Event handling for tab navigation inside the coach navigation area and the seatmap area */
654
+ _handleTabKeyNavigation(event, eventArea, currTabIndex) {
655
+ const pressedKey = event.key;
656
+ const pressedShiftTab = event.shiftKey;
657
+ if (pressedKey === this.keyboardNavigationEvents.Tab) {
658
+ if (eventArea == "navigation") {
659
+ if (currTabIndex == this.currSelectedCoachIndex) {
660
+ if (!this.currSelectedPlace || !pressedShiftTab || this.coachItemDetailsElements[currTabIndex].isDriverArea || this.focusedCoachIndex == -1) this.focusedCoachIndex = currTabIndex;
661
+ else if (pressedShiftTab && this.currSelectedPlace) {
662
+ this.focusedCoachIndex = -1;
663
+ this.focusPlaceElement(this.currSelectedPlace);
664
+ }
665
+ } else this.focusedCoachIndex = currTabIndex;
666
+ this._scrollToSelectedNavigationButton(currTabIndex);
667
+ } else if (eventArea == "seatmap") {
668
+ event.preventDefault();
669
+ if (pressedShiftTab) this._navigateCoachNavigationByKeyboard("PREV_TAB");
670
+ else this._navigateCoachNavigationByKeyboard("NEXT_TAB");
671
+ }
672
+ }
673
+ }
674
+ /**
675
+ * Initialisation of Keyboard Seatmap event handling to navigation between each places inside a selected coach by using [arrow] keys.
676
+ * With the [TAB] key the user navigation goes to the next coach navigation element and the currently selected place is automatically reset.
677
+ */
678
+ keyboardSeatmapEventHandling(event) {
679
+ const isTabNext = event.key === this.keyboardNavigationEvents.Tab;
680
+ const isTabPrev = event.shiftKey && isTabNext;
681
+ if (!this.hasNavigation && this.currSelectedCoachIndex === 0 && isTabPrev || this.currSelectedCoachIndex === this.coachItemDetailsElements.length - 1 && isTabNext) return;
682
+ const pressedKey = event.key;
683
+ this.preventCoachScrollByPlaceClick = false;
684
+ if (!this.hasSeatReservationNativeFocus && (isTabNext || isTabPrev)) this.hasSeatReservationNativeFocus = true;
685
+ if (isTabNext) {
686
+ this._handleTabKeyNavigation(event, "seatmap");
687
+ return;
688
+ }
689
+ if (this.currSelectedCoachIndex !== -1 && isArrowKeyOrPageKeysPressed(event)) {
690
+ event.preventDefault();
691
+ switch (pressedKey) {
692
+ case this.keyboardNavigationEvents.ArrowLeft:
693
+ {
694
+ const pressedLeftKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowDown : pressedKey;
695
+ this._navigateToPlaceByKeyboard(pressedLeftKeyMapping);
696
+ }
697
+ break;
698
+ case this.keyboardNavigationEvents.ArrowRight:
699
+ {
700
+ const pressedRightKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowUp : pressedKey;
701
+ this._navigateToPlaceByKeyboard(pressedRightKeyMapping);
702
+ }
703
+ break;
704
+ case this.keyboardNavigationEvents.ArrowUp:
705
+ {
706
+ const pressedUpKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowLeft : pressedKey;
707
+ this._navigateToPlaceByKeyboard(pressedUpKeyMapping);
708
+ }
709
+ break;
710
+ case this.keyboardNavigationEvents.ArrowDown:
711
+ {
712
+ const pressedDownKeyMapping = this.alignVertical ? this.keyboardNavigationEvents.ArrowRight : pressedKey;
713
+ this._navigateToPlaceByKeyboard(pressedDownKeyMapping);
714
+ }
715
+ break;
716
+ default: break;
717
+ }
718
+ }
719
+ }
720
+ /**
721
+ * Selects a place inside the coach if navigated via keyboard,
722
+ * otherwise the coach grid is selected (necessary for ScreenReader)
723
+ */
724
+ preselectPlaceInCoach() {
725
+ if (!this.isAutoScrolling) return;
726
+ if (this._isRunningInitPreselectCoachIndex) {
727
+ this._isRunningInitPreselectCoachIndex = false;
728
+ return;
729
+ }
730
+ if (this.coachItemDetailsElements[this.currSelectedCoachIndex] && this.coachItemDetailsElements[this.currSelectedCoachIndex].isDriverArea) {
731
+ this._setFocusToSelectedCoachGrid();
732
+ return;
733
+ }
734
+ if (this.isKeyboardNavigation && this.isAutoScrolling) {
735
+ const closestPlace = this._getClosestPlaceByKeyDirection();
736
+ if (closestPlace) {
737
+ this.unfocusPlaceElement();
738
+ this.focusPlaceElement(closestPlace);
739
+ this.focusedCoachIndex = -1;
740
+ } else this._setFocusToSelectedCoachGrid();
741
+ } else {
742
+ this.unfocusPlaceElement();
743
+ this.isCoachGridFocusable = true;
744
+ this._setFocusToSelectedCoachGrid();
745
+ }
746
+ }
747
+ scrollToSelectedNavCoach(selectedNavCoachIndex) {
748
+ if (this._isValidCoachIndex(selectedNavCoachIndex) && selectedNavCoachIndex !== this.currSelectedCoachIndex) {
749
+ this.hoveredCoachIndex = selectedNavCoachIndex;
750
+ this.isAutoScrolling = true;
751
+ this.isCoachGridFocusable = true;
752
+ this.currSelectedCoachIndex = selectedNavCoachIndex;
753
+ this.currSelectedDeckIndex = this._getExistingCoachDeckIndex();
754
+ this._setScrollDirectionByCoachIndex();
755
+ const scrollToCoachPosX = this._getCoachScrollPositionX();
756
+ if ((this.selectedCoachIndex !== -1 || this.currSelectedCoachIndex > 0) && this._isScrollableToSelectedCoach()) {
757
+ this._lastStartScrollPos = this.coachScrollArea.scrollLeft;
758
+ this.coachScrollArea.scrollTo({
759
+ top: this.alignVertical ? scrollToCoachPosX : 0,
760
+ left: this.alignVertical ? 0 : scrollToCoachPosX,
761
+ behavior: "smooth"
762
+ });
763
+ } else this.updateCurrentSelectedCoach();
764
+ this._scrollToSelectedNavigationButton(selectedNavCoachIndex);
765
+ }
766
+ }
767
+ focusPlaceElement(place) {
768
+ this.unfocusPlaceElement();
769
+ if (place) {
770
+ this.currSelectedPlace = place;
771
+ this._setCurrSelectedPlaceElementId(place);
772
+ const selectedPlaceElement = this._getPlaceHtmlElement();
773
+ if (selectedPlaceElement) {
774
+ selectedPlaceElement.setAttribute("keyfocus", "focus");
775
+ const delayScrollInViewport = setTimeout(() => {
776
+ const placeId = this.getPlaceElementId(this.currSelectedDeckIndex, this.currSelectedCoachIndex, place.number);
777
+ this._scrollPlaceIntoNearestViewport(placeId);
778
+ clearTimeout(delayScrollInViewport);
779
+ }, 0);
780
+ }
781
+ }
782
+ }
783
+ unfocusPlaceElement() {
784
+ const selectedPlaceElement = this._getPlaceHtmlElement();
785
+ if (selectedPlaceElement) {
786
+ selectedPlaceElement.setAttribute("keyfocus", "unfocus");
787
+ this._setCurrSelectedPlaceElementId(null);
788
+ this.currSelectedPlace = null;
789
+ }
790
+ }
791
+ getCalculatedDimension(elementDimension, coachDimension, isOriginHeight, isStretchHeight) {
792
+ if (coachDimension && !isOriginHeight) elementDimension.h += this.coachBorderOffset * 2;
793
+ if (isStretchHeight) elementDimension.h += this.coachBorderOffset;
794
+ return {
795
+ w: this.baseGridSize * elementDimension.w,
796
+ h: this.baseGridSize * elementDimension.h
797
+ };
798
+ }
799
+ getCalculatedPosition(elementPosition, elementDimension, coachDimension, isOriginHeight) {
800
+ if (coachDimension && elementDimension) {
801
+ const endPosHeight = isOriginHeight ? coachDimension.h : coachDimension.h + this.coachBorderOffset;
802
+ if (elementPosition.y === 0) elementPosition.y -= this.coachBorderOffset;
803
+ else if (elementPosition.y + elementDimension.h === endPosHeight) elementPosition.y += this.coachBorderOffset;
804
+ }
805
+ return {
806
+ x: this.baseGridSize * elementPosition.x,
807
+ y: this.baseGridSize * elementPosition.y,
808
+ z: elementPosition.z
809
+ };
810
+ }
811
+ /**
812
+ * detects if a (graphical) element is on the border with its position (upper or lower border).
813
+ * @param baseElement
814
+ * @param coachDimension
815
+ * @protected
816
+ */
817
+ isElementDirectlyOnBorder(baseElement, coachDimension) {
818
+ return baseElement.position.y === 0 || baseElement.position.y + baseElement.dimension.h === coachDimension.h;
819
+ }
820
+ /**
821
+ * Counts all available seats together depending on the seat type
822
+ *
823
+ * @param places
824
+ * @returns An Object with count of free seats and free bicycle places
825
+ */
826
+ getAvailableFreePlacesNumFromCoach(places) {
827
+ const accumulator = {
828
+ seats: 0,
829
+ bicycles: 0
830
+ };
831
+ const freePlaces = places?.reduce((accumulator, currPlace) => {
832
+ if (currPlace.state !== "FREE") return accumulator;
833
+ if (currPlace.type === "SEAT") accumulator.seats++;
834
+ else accumulator.bicycles++;
835
+ return accumulator;
836
+ }, accumulator);
837
+ return freePlaces ? freePlaces : accumulator;
838
+ }
839
+ /**
840
+ * At the end of a scroll Event from the coach scrollable area,
841
+ * the reached coach is marked as selected
842
+ */
843
+ _handleCoachAreaScrollendEvent() {
844
+ const findScrollCoachIndex = this.isAutoScrolling ? this.currSelectedCoachIndex : this._getCoachIndexByScrollTriggerPosition();
845
+ if (this.preventCoachScrollByPlaceClick) {
846
+ if (Math.abs(this._lastStartScrollPos - this.coachScrollArea.scrollLeft) > this.baseGridSize * 2) this.selectedCoachIndex = findScrollCoachIndex;
847
+ this.preventCoachScrollByPlaceClick = false;
848
+ return;
849
+ }
850
+ this._lastStartScrollPos = this.coachScrollArea.scrollLeft;
851
+ this.hoveredCoachIndex = -1;
852
+ if (this.currSelectedCoachIndex === -1) this.currSelectedCoachIndex = findScrollCoachIndex;
853
+ if (this._isScrollableToSelectedCoach()) this.currSelectedCoachIndex = findScrollCoachIndex;
854
+ else this.currSelectedCoachIndex = findScrollCoachIndex < this.currSelectedCoachIndex ? this.currSelectedCoachIndex : findScrollCoachIndex;
855
+ if (!this.isAutoScrolling) this._scrollToSelectedNavigationButton(findScrollCoachIndex);
856
+ this.preventCoachScrollByPlaceClick = false;
857
+ this.updateCurrentSelectedCoach();
858
+ if (!this.hasNavigation) {
859
+ this.preselectPlaceInCoach();
860
+ this.isAutoScrolling = false;
861
+ }
862
+ }
863
+ /**
864
+ * Performs an automatic main navigation scroll to the specified selectedNavCoachIndex.
865
+ * Calculates the central scroll offset of the nav coach to be selected.
866
+ * @param selectedNavCoachIndex
867
+ */
868
+ _scrollToSelectedNavigationButton(selectedNavCoachIndex) {
869
+ setTimeout(() => {
870
+ if (this.hasNavigation && this.navigationScrollArea) {
871
+ const navigationAreaCenteredPosX = this.scrollNavigationAreaDim / 2;
872
+ const scrollOffsetX = selectedNavCoachIndex * this.coachNavButtonDim - navigationAreaCenteredPosX + this.coachNavButtonDim;
873
+ this.navigationScrollArea.scrollTo({
874
+ top: this.alignVertical ? scrollOffsetX : 0,
875
+ left: this.alignVertical ? 0 : scrollOffsetX,
876
+ behavior: "smooth"
877
+ });
878
+ }
879
+ }, 10);
880
+ }
881
+ /**
882
+ * Sets the new ScrollDirection by the new given target coach index.
883
+ */
884
+ _setScrollDirectionByCoachIndex() {
885
+ this.currScrollDirection = this.currSelectedCoachIndex > this.selectedCoachIndex ? ScrollDirection.right : ScrollDirection.left;
886
+ }
887
+ /**
888
+ * Returns the scroll start or end position X from the selected coach.
889
+ * In case the user is currently navigating through places by keyboard and goes to previous coach,
890
+ * then we return the end position of the coach to get the closest scroll position of the next focus place.
891
+ * @returns number
892
+ */
893
+ _getCoachScrollPositionX() {
894
+ const coachTriggerPoint = this.triggerCoachPositionsCollection[this.currSelectedCoachIndex];
895
+ return this.isKeyboardNavigation && this.currScrollDirection === ScrollDirection.left && coachTriggerPoint.width > this.scrollCoachesAreaWidth ? coachTriggerPoint.end - this.scrollCoachesAreaWidth : coachTriggerPoint.start;
896
+ }
897
+ /**
898
+ * Sets the focus on the HTML table (grid) caption element so that the heading is read out when using a ScreenReader.
899
+ */
900
+ _setFocusToSelectedCoachGrid() {
901
+ if (this.isCoachGridFocusable && this.hasSeatReservationNativeFocus) {
902
+ this.isCoachGridFocusable = false;
903
+ const coachTableCaptionElement = this.shadowRoot?.querySelector("#sbb-sr-coach-caption-" + this.currSelectedCoachIndex);
904
+ if (coachTableCaptionElement) coachTableCaptionElement.focus();
905
+ }
906
+ }
907
+ /**
908
+ * Returns whether the current scrolled position can be used to scroll to the selected wagon
909
+ * @returns boolean
910
+ */
911
+ _isScrollableToSelectedCoach() {
912
+ const currScrollPosX = this.alignVertical ? this.coachScrollArea.scrollTop : this.coachScrollArea.scrollLeft;
913
+ const coachScrollWindowWidth = this.alignVertical ? this.coachScrollArea.getBoundingClientRect().height : this.coachScrollArea.getBoundingClientRect().width;
914
+ const maxScrollWidthArea = this.maxCalcCoachesWidth - coachScrollWindowWidth;
915
+ const currCoachTrigger = this.triggerCoachPositionsCollection[this.currSelectedCoachIndex];
916
+ const isScrollPosSameToCurrCoachPos = currScrollPosX === this.triggerCoachPositionsCollection[this.currSelectedCoachIndex].start;
917
+ return (currScrollPosX < maxScrollWidthArea || currScrollPosX > currCoachTrigger.start) && !isScrollPosSameToCurrCoachPos;
918
+ }
919
+ /**
920
+ * Returns the coach index which is currently visible in the scroll area
921
+ * @returns number
922
+ */
923
+ _getCoachIndexByScrollTriggerPosition() {
924
+ const scrollOffsetX = (this.alignVertical ? this.coachScrollArea.scrollTop : this.coachScrollArea.scrollLeft) + this.scrollCoachesAreaWidth / 2;
925
+ return this.triggerCoachPositionsCollection.findIndex((coachTrigger) => scrollOffsetX >= coachTrigger.start && scrollOffsetX <= coachTrigger.end);
926
+ }
927
+ /**
928
+ * Get the first place of current selected coach by table cell coordinate 0-0 id.
929
+ * @returns Place or null
930
+ */
931
+ _getFirstPlaceInSelectedCoach() {
932
+ let firstPlace = null;
933
+ const coach = this.seatReservations[this.currSelectedDeckIndex].coachItems[this.currSelectedCoachIndex];
934
+ const firstCellId = "cell-" + this.currSelectedDeckIndex + "-" + this.currSelectedCoachIndex + "-0-0";
935
+ const placeNumber = this.shadowRoot?.querySelector("#" + firstCellId)?.querySelector("sbb-seat-reservation-place-control")?.getAttribute("text") || null;
936
+ if (coach && placeNumber) firstPlace = coach.places?.find((place) => place.number === placeNumber) || null;
937
+ return firstPlace;
938
+ }
939
+ _getSwitchedCoachDeckIndexByKeyNavigation(pressedKey, coach) {
940
+ if (!this.currSelectedPlace || pressedKey === this.keyboardNavigationEvents.ArrowRight || pressedKey === this.keyboardNavigationEvents.ArrowLeft) return null;
941
+ if (pressedKey === this.keyboardNavigationEvents.ArrowDown && this.currSelectedPlace.position.y + 2 === coach.dimension.h && !!this.seatReservations[this.currSelectedDeckIndex + 1]) return this.currSelectedDeckIndex + 1;
942
+ else if (pressedKey === this.keyboardNavigationEvents.ArrowUp && this.currSelectedPlace.position.y === 0 && !!this.seatReservations[this.currSelectedDeckIndex - 1]) return this.currSelectedDeckIndex - 1;
943
+ return null;
944
+ }
945
+ /**
946
+ * To get the correct closest place of current pressed key and the current selected place,
947
+ * we have to investigate the coordinates of each place to find the closest place of the currSelectedPlaceElementId.
948
+ * @param pressedKey
949
+ * @returns Place or null
950
+ */
951
+ _getClosestPlaceByKeyDirection(pressedKey) {
952
+ const coach = this.seatReservations[this.currSelectedDeckIndex].coachItems[this.currSelectedCoachIndex];
953
+ let closestPlace = null;
954
+ let coachPlaces = coach.places;
955
+ let switchedCoachDeckIndex = null;
956
+ if (coachPlaces) {
957
+ if (!this.currSelectedPlaceElementId) return this._getFirstPlaceInSelectedCoach();
958
+ else if (this.currSelectedPlace) {
959
+ const currSelectedPlacePosition = { ...this.currSelectedPlace.position };
960
+ if (pressedKey) {
961
+ switchedCoachDeckIndex = this._getSwitchedCoachDeckIndexByKeyNavigation(pressedKey, coach);
962
+ if (switchedCoachDeckIndex !== null) {
963
+ coachPlaces = this.seatReservations[switchedCoachDeckIndex].coachItems[this.currSelectedCoachIndex].places || [];
964
+ currSelectedPlacePosition.y = switchedCoachDeckIndex < this.currSelectedDeckIndex ? coach.dimension.h : -1;
965
+ }
966
+ }
967
+ for (const place of coachPlaces) if (!pressedKey) {
968
+ if (this.currScrollDirection === ScrollDirection.right && place.position.y === currSelectedPlacePosition.y && (!closestPlace || place.position.x < closestPlace.position.x)) closestPlace = place;
969
+ else if (this.currScrollDirection === ScrollDirection.left && place.position.y === currSelectedPlacePosition.y && (!closestPlace || place.position.x > closestPlace.position.x)) closestPlace = place;
970
+ } else if (place.number !== this.currSelectedPlace?.number) {
971
+ if (pressedKey === this.keyboardNavigationEvents.ArrowRight && (place.position.y === currSelectedPlacePosition.y || place.position.y === currSelectedPlacePosition.y - 1) && place.position.x > currSelectedPlacePosition.x && (!closestPlace || place.position.x < closestPlace.position.x)) closestPlace = place;
972
+ else if (pressedKey === this.keyboardNavigationEvents.ArrowDown && (place.position.x === currSelectedPlacePosition.x || place.position.x === currSelectedPlacePosition.x + 1) && place.position.y > currSelectedPlacePosition.y && (!closestPlace || place.position.y < closestPlace.position.y)) closestPlace = place;
973
+ else if (pressedKey === this.keyboardNavigationEvents.ArrowLeft && (place.position.y === currSelectedPlacePosition.y || place.position.y === currSelectedPlacePosition.y + 1) && place.position.x < currSelectedPlacePosition.x && (!closestPlace || place.position.x > closestPlace.position.x)) closestPlace = place;
974
+ else if (pressedKey === this.keyboardNavigationEvents.ArrowUp && (place.position.x === currSelectedPlacePosition.x || place.position.x === currSelectedPlacePosition.x - 1) && place.position.y < currSelectedPlacePosition.y && (!closestPlace || place.position.y > closestPlace.position.y)) closestPlace = place;
975
+ }
976
+ if (switchedCoachDeckIndex !== null && closestPlace) this.currSelectedDeckIndex = switchedCoachDeckIndex;
977
+ }
978
+ }
979
+ return closestPlace;
980
+ }
981
+ _navigateCoachNavigationByKeyboard(tabDirection) {
982
+ const currFocusIndex = this.focusedCoachIndex === -1 ? this.currSelectedCoachIndex === -1 ? 0 : this.currSelectedCoachIndex : this.focusedCoachIndex;
983
+ const newFocusableIndex = tabDirection === "NEXT_TAB" ? this.getNextAvailableCoachIndex(currFocusIndex) : this.getPrevAvailableCoachIndex(currFocusIndex);
984
+ if (this.hasNavigation) {
985
+ const selectedPlaceElement = this._getPlaceHtmlElement();
986
+ const placeInCoachHasFocus = selectedPlaceElement ? selectedPlaceElement.getAttribute("keyfocus") === "focus" : false;
987
+ if (tabDirection === "PREV_TAB" && this.selectedCoachIndex === currFocusIndex) if (placeInCoachHasFocus || this.currSelectedPlace !== null) {
988
+ this.focusedCoachIndex = currFocusIndex;
989
+ this.unfocusPlaceElement();
990
+ return;
991
+ } else if (currFocusIndex === 0) this._refocusCurrentFocusedNavCoach(currFocusIndex);
992
+ else this.focusedCoachIndex = newFocusableIndex;
993
+ else if (newFocusableIndex !== this.currSelectedCoachIndex) this.focusedCoachIndex = newFocusableIndex;
994
+ else if (tabDirection === "NEXT_TAB" && newFocusableIndex === this.coachItemDetailsElements.length - 1) this._refocusCurrentFocusedNavCoach(currFocusIndex);
995
+ else {
996
+ this.focusedCoachIndex = -1;
997
+ this.selectedCoachIndex = newFocusableIndex;
998
+ if (placeInCoachHasFocus) this.focusPlaceElement(this.currSelectedPlace);
999
+ else {
1000
+ this.isCoachGridFocusable = true;
1001
+ this._setFocusToSelectedCoachGrid();
1002
+ }
1003
+ }
1004
+ this._scrollToSelectedNavigationButton(newFocusableIndex);
1005
+ } else this.scrollToSelectedNavCoach(newFocusableIndex);
1006
+ }
1007
+ _refocusCurrentFocusedNavCoach(focusIndex) {
1008
+ this.focusedCoachIndex = -1;
1009
+ setTimeout(() => this.focusedCoachIndex = focusIndex, 0);
1010
+ }
1011
+ _navigateToPlaceByKeyboard(pressedKey) {
1012
+ this.isKeyboardNavigation = true;
1013
+ if (this.focusedCoachIndex !== -1) this.focusedCoachIndex = -1;
1014
+ if (!this.preventPlaceClick) {
1015
+ const findClosestPlace = this._getClosestPlaceByKeyDirection(pressedKey);
1016
+ if (findClosestPlace) this.focusPlaceElement(findClosestPlace);
1017
+ else if (pressedKey === this.keyboardNavigationEvents.ArrowRight || pressedKey === this.keyboardNavigationEvents.ArrowLeft || this.alignVertical && (pressedKey === this.keyboardNavigationEvents.ArrowUp || pressedKey === this.keyboardNavigationEvents.ArrowDown)) {
1018
+ const newSelectedCoachIndex = pressedKey === this.keyboardNavigationEvents.ArrowRight ? this.getNextAvailableCoachIndex() : this.getPrevAvailableCoachIndex();
1019
+ this.scrollToSelectedNavCoach(newSelectedCoachIndex);
1020
+ }
1021
+ }
1022
+ }
1023
+ getNextAvailableCoachIndex(currentIndex) {
1024
+ const startIndex = currentIndex ?? this.currSelectedCoachIndex;
1025
+ return startIndex < this.seatReservations[this.currSelectedDeckIndex].coachItems.length - 1 ? startIndex + 1 : startIndex;
1026
+ }
1027
+ getPrevAvailableCoachIndex(currentIndex) {
1028
+ const startIndex = currentIndex ?? this.currSelectedCoachIndex;
1029
+ return startIndex > 0 ? startIndex - 1 : startIndex;
1030
+ }
1031
+ updateSelectedSeatReservationPlaces(placeSelection) {
1032
+ const placeTypeProp = placeSelection.placeType === "SEAT" ? "seats" : "bicycles";
1033
+ const maxReservations = placeSelection.placeType === "SEAT" ? this.maxSeatReservations : this.maxBicycleReservations;
1034
+ const currSelectedPlaces = this.selectedSeatReservationPlaces[placeTypeProp];
1035
+ this.selectedSeatReservationPlaces[placeTypeProp] = this._updateSelectedSeatReservationPlaces(currSelectedPlaces, maxReservations, placeSelection);
1036
+ /**
1037
+ * @type {CustomEvent<SeatReservationSelectedPlaces>}
1038
+ * Emits when a place was selected and returns a Place array with all selected places.
1039
+ */
1040
+ this.dispatchEvent(new CustomEvent("selectedplaces", {
1041
+ bubbles: true,
1042
+ composed: true,
1043
+ detail: this.selectedSeatReservationPlaces
1044
+ }));
1045
+ }
1046
+ _updateSelectedSeatReservationPlaces(selectedSeatReservationPlaces, maxReservations, placeSelection) {
1047
+ if (placeSelection.state === "SELECTED") {
1048
+ const selectedPlaceDeckIndex = this._getDeckIndexByPlaceId(placeSelection.id);
1049
+ const seatReservationSelection = this._getSeatReservationPlaceSelection(placeSelection, selectedPlaceDeckIndex);
1050
+ if (seatReservationSelection) selectedSeatReservationPlaces.push(seatReservationSelection);
1051
+ } else selectedSeatReservationPlaces = selectedSeatReservationPlaces.filter((_selectedPlace) => _selectedPlace.id !== placeSelection.id);
1052
+ if (maxReservations > -1 && selectedSeatReservationPlaces.length > maxReservations) {
1053
+ const resetWithPlaceSelection = maxReservations > 0 ? placeSelection : void 0;
1054
+ selectedSeatReservationPlaces = this._resetAllPlaceSelections(selectedSeatReservationPlaces, resetWithPlaceSelection);
1055
+ }
1056
+ return selectedSeatReservationPlaces;
1057
+ }
1058
+ updateCurrentSelectedPlaceInCoach(placeSelection) {
1059
+ const placeDeckIndex = this._getDeckIndexByPlaceId(placeSelection.id);
1060
+ const coachIndex = placeSelection.coachIndex;
1061
+ if (placeDeckIndex === null) return;
1062
+ const place = this.seatReservations[placeDeckIndex].coachItems[coachIndex].places?.find((place) => place.number == placeSelection.number);
1063
+ if (!place) return;
1064
+ this.currSelectedDeckIndex = placeDeckIndex;
1065
+ this.currSelectedCoachIndex = coachIndex;
1066
+ this.currSelectedPlace = place;
1067
+ if (this.currSelectedCoachIndex !== this.selectedCoachIndex) this.updateCurrentSelectedCoach();
1068
+ this._setCurrSelectedPlaceElementId(place);
1069
+ const delayScrollInViewport = setTimeout(() => {
1070
+ this._scrollPlaceIntoNearestViewport(placeSelection.id);
1071
+ clearTimeout(delayScrollInViewport);
1072
+ }, 0);
1073
+ }
1074
+ updateCurrentSelectedCoach() {
1075
+ if (this.currSelectedCoachIndex == this.selectedCoachIndex) return;
1076
+ if (this.focusedCoachIndex != -1) this.focusedCoachIndex = this.currSelectedCoachIndex;
1077
+ this.selectedCoachIndex = this.currSelectedCoachIndex;
1078
+ const coachSelection = this._getSeatReservationSelectedCoach(this.selectedCoachIndex);
1079
+ if (coachSelection)
1080
+ /**
1081
+ * @type {CustomEvent<SeatReservationSelectedCoach>}
1082
+ * Emits when a coach was selected and returns a CoachSelection
1083
+ */
1084
+ this.dispatchEvent(new CustomEvent("selectedcoach", {
1085
+ bubbles: true,
1086
+ composed: true,
1087
+ detail: coachSelection
1088
+ }));
1089
+ }
1090
+ getPlaceElementId(coachDeckIndex, coachIndex, placeNumber) {
1091
+ return "seat-reservation__place-button-" + coachDeckIndex + "-" + coachIndex + "-" + placeNumber;
1092
+ }
1093
+ /**
1094
+ * In the case of coach layouts with different decks,
1095
+ * it is necessary to extend the offset with empty coaches
1096
+ * in order to create a stable vehicle layout.
1097
+ *
1098
+ * [ooo]-[ooo]-[ooo]
1099
+ * [ooo]-[ooo]-[ooo]-[ooo]-[ooo]
1100
+ */
1101
+ _initEmptyCoachDeckOffsets() {
1102
+ const coachOffsetIndexCounter = Array(this.seatReservations.length - 1).fill(0);
1103
+ this.seatReservations[this.seatReservations.length - 1].coachItems.forEach((lowerCoachItem) => {
1104
+ for (let i = 0; i < this.seatReservations.length - 1; i++) {
1105
+ const deckCoachItem = this.seatReservations[i].coachItems[coachOffsetIndexCounter[i]];
1106
+ if (lowerCoachItem.id != deckCoachItem?.id) {
1107
+ const emptyOffsetCoach = {
1108
+ ...lowerCoachItem,
1109
+ places: void 0,
1110
+ propertyIds: void 0,
1111
+ graphicElements: void 0,
1112
+ serviceElements: void 0,
1113
+ travelClass: []
1114
+ };
1115
+ this.seatReservations[i].coachItems.splice(coachOffsetIndexCounter[i], 0, emptyOffsetCoach);
1116
+ }
1117
+ coachOffsetIndexCounter[i]++;
1118
+ }
1119
+ });
1120
+ }
1121
+ /**
1122
+ * Initialization of SeatReservationPlaceSelection Array based on the transferred places
1123
+ * that have the state SELECTED within the seatReservation object
1124
+ */
1125
+ _initSeatReservationPlaceSelection() {
1126
+ this.selectedSeatReservationPlaces.seats = [];
1127
+ this.selectedSeatReservationPlaces.bicycles = [];
1128
+ this.seatReservations?.forEach((seatReservation, coachDeckIndex) => seatReservation.coachItems.map((coach, coachIndex) => {
1129
+ coach.places?.filter((place) => place.state === "SELECTED")?.forEach((place) => {
1130
+ const preselectedPlaceSelection = mapPlaceInfosToPlaceSelection(place, this.getPlaceElementId(coachDeckIndex, coachIndex, place.number), seatReservation.deckCoachIndex, coachIndex);
1131
+ const seatReservationPlaceSelection = this._getSeatReservationPlaceSelection(preselectedPlaceSelection, coachDeckIndex);
1132
+ if (seatReservationPlaceSelection) if (seatReservationPlaceSelection.placeType === "SEAT") this.selectedSeatReservationPlaces.seats.push(seatReservationPlaceSelection);
1133
+ else this.selectedSeatReservationPlaces.bicycles.push(seatReservationPlaceSelection);
1134
+ });
1135
+ }));
1136
+ }
1137
+ /**
1138
+ * All selected places will be reset or the currentSelectedPlace was given, then we reset all except currentSelectedPlace
1139
+ * @param reservationPlaceSelections
1140
+ * @param currSelectedPlace
1141
+ */
1142
+ _resetAllPlaceSelections(reservationPlaceSelections, currSelectedPlace) {
1143
+ for (const placeSelection of reservationPlaceSelections) if (!currSelectedPlace || currSelectedPlace.id !== placeSelection.id) {
1144
+ const placeElement = this.shadowRoot?.getElementById(placeSelection.id);
1145
+ if (placeElement) placeElement.setAttribute("state", "FREE");
1146
+ }
1147
+ if (currSelectedPlace) reservationPlaceSelections = reservationPlaceSelections.filter((_selectedPlace) => _selectedPlace.id === currSelectedPlace.id);
1148
+ else reservationPlaceSelections = [];
1149
+ return reservationPlaceSelections;
1150
+ }
1151
+ _getSeatReservationPlaceSelection(currSelectedPlace, coachDeckIndex) {
1152
+ if (coachDeckIndex === null) return null;
1153
+ const coach = this.seatReservations[coachDeckIndex].coachItems[currSelectedPlace.coachIndex];
1154
+ const place = coach.places?.find((place) => place.number === currSelectedPlace.number);
1155
+ return place ? mapPlaceAndCoachToSeatReservationPlaceSelection(place, coach, currSelectedPlace.id, currSelectedPlace.deckIndex, currSelectedPlace.coachIndex) : null;
1156
+ }
1157
+ _getSeatReservationSelectedCoach(coachIndex) {
1158
+ if (!this.seatReservations[this.currSelectedDeckIndex].coachItems[coachIndex]) return null;
1159
+ const coach = this.seatReservations[this.currSelectedDeckIndex].coachItems[coachIndex];
1160
+ return mapCoachInfosToCoachSelection(coachIndex, coach, this.getAvailableFreePlacesNumFromCoach(coach.places));
1161
+ }
1162
+ _setCurrSelectedPlaceElementId(place) {
1163
+ this.currSelectedPlaceElementId = place ? this.getPlaceElementId(this.currSelectedDeckIndex, this.currSelectedCoachIndex, place.number) : null;
1164
+ }
1165
+ /**
1166
+ * Preparation of the used documents font-size which needs
1167
+ * to be determined in order to correctly calculate CSS values with rem
1168
+ * */
1169
+ _determineBaseFontSize() {
1170
+ if (!isServer) {
1171
+ const onePixelInRem = 1 / parseInt(window.getComputedStyle(document.body).fontSize, 10);
1172
+ this.style?.setProperty("--sbb-seat-reservation-one-px-rem", `${onePixelInRem + "rem"}`);
1173
+ }
1174
+ }
1175
+ /**
1176
+ * Prepares data for displaying navigation area.
1177
+ * Calculates the values which are not going to change during use of a component:
1178
+ * - coach id
1179
+ * - list of service icons
1180
+ * - class (first, second, any)
1181
+ * - whether there is a driver area left or right
1182
+ * */
1183
+ _prepareCoachItemDetailsData() {
1184
+ if (this.seatReservations) {
1185
+ const lowerDeck = this.seatReservations[this.seatReservations.length - 1].coachItems;
1186
+ this.coachItemDetailsElements = [];
1187
+ lowerDeck.forEach((coach, index) => {
1188
+ const travelClasses = [];
1189
+ const propertyIds = [];
1190
+ const places = [];
1191
+ this.seatReservations.map((sr) => {
1192
+ return sr.coachItems[index];
1193
+ }).forEach((coach) => {
1194
+ travelClasses.push(...coach.travelClass);
1195
+ propertyIds.push(...coach.propertyIds ? coach.propertyIds : []);
1196
+ places.push(...coach.places ? coach.places : []);
1197
+ });
1198
+ this.coachItemDetailsElements.push({
1199
+ id: coach.id,
1200
+ travelClass: this._prepareTravelClassNavigation(travelClasses),
1201
+ propertyIds: this._prepareServiceIconsNavigation(propertyIds),
1202
+ isDriverArea: coach.places ? coach.places.length === 0 : true,
1203
+ driverAreaSide: this._prepareDriverAreaSideNavigation(coach),
1204
+ freePlaces: this.getAvailableFreePlacesNumFromCoach(places),
1205
+ driverAreaElements: this._setDriverAreasElements(coach)
1206
+ });
1207
+ });
1208
+ }
1209
+ }
1210
+ _prepareOptimizeAreaIconDimensionByMedian() {
1211
+ if (this.seatReservations) {
1212
+ const allServiceDimensions = [];
1213
+ this.seatReservations.forEach((deck) => deck.coachItems.forEach((coach) => coach.serviceElements?.forEach((icon) => allServiceDimensions.push(icon.dimension))));
1214
+ if (allServiceDimensions.length) {
1215
+ allServiceDimensions.sort((dim1, dim2) => {
1216
+ if (dim1 && dim2) {
1217
+ const maxDim1 = dim1.w + dim1.h;
1218
+ const maxDim2 = dim2.w + dim2.h;
1219
+ if (maxDim1 > maxDim2) return 1;
1220
+ else if (maxDim1 < maxDim2) return -1;
1221
+ else return 0;
1222
+ }
1223
+ return 0;
1224
+ });
1225
+ const medianIconSize = allServiceDimensions[Math.floor(allServiceDimensions.length / 2)];
1226
+ this.globalAreaIconDim = this.getCalculatedDimension(medianIconSize);
1227
+ } else {
1228
+ const maxCoachHeight = this.seatReservations.flatMap((deck) => deck.coachItems.map((coach) => coach.dimension.h)).reduce((max, height) => Math.max(max, height), 0);
1229
+ const iconDimension = Math.floor(maxCoachHeight * .2);
1230
+ this.globalAreaIconDim = this.getCalculatedDimension({
1231
+ w: iconDimension,
1232
+ h: iconDimension
1233
+ });
1234
+ }
1235
+ }
1236
+ }
1237
+ _prepareTravelClassNavigation(travelClasses) {
1238
+ if (travelClasses.indexOf("FIRST") !== -1) return "FIRST";
1239
+ if (travelClasses.indexOf("SECOND") !== -1) return "SECOND";
1240
+ return "ANY_CLASS";
1241
+ }
1242
+ _prepareDriverAreaSideNavigation(coachItem) {
1243
+ const coachDriverAreas = coachItem.graphicElements?.filter((graphicalElements) => graphicalElements.icon === "DRIVER_AREA");
1244
+ if (coachDriverAreas && coachDriverAreas.length > 0) {
1245
+ const hasLeftDriverArea = coachDriverAreas.find((driverAreaElement) => driverAreaElement.position.x === 0) || false;
1246
+ const hasRightDriverArea = coachDriverAreas.find((driverAreaElement) => driverAreaElement.position.x > 0) || false;
1247
+ return {
1248
+ left: !!hasLeftDriverArea,
1249
+ right: !!hasRightDriverArea
1250
+ };
1251
+ }
1252
+ }
1253
+ _prepareCoachWidthAndGapCalculations() {
1254
+ if (this.seatReservations) this.seatReservations.forEach((seatReservation) => {
1255
+ seatReservation?.coachItems?.forEach((coachItem) => {
1256
+ const hasOverhangingPlaces = this._isOverhangingElementsPresent(coachItem.dimension.w, coachItem.places);
1257
+ const filteredElements = coachItem.graphicElements?.filter((e) => e.icon && !this.notAreaElements.includes(e.icon));
1258
+ const hasOverhangingGraphicAreas = this._isOverhangingElementsPresent(coachItem.dimension.w, filteredElements);
1259
+ this.overHangingElementInformation.push({
1260
+ coachId: coachItem.id,
1261
+ overhangingPlaces: hasOverhangingPlaces,
1262
+ overhangingGraphicAreas: hasOverhangingGraphicAreas
1263
+ });
1264
+ });
1265
+ });
1266
+ }
1267
+ /**
1268
+ * Returns the current selected place HTML element by currSelectedPlaceElementId.
1269
+ * @returns HTMLElement or null
1270
+ */
1271
+ _getPlaceHtmlElement() {
1272
+ return this.currSelectedPlaceElementId ? this.shadowRoot?.getElementById(this.currSelectedPlaceElementId) || null : null;
1273
+ }
1274
+ /**
1275
+ * Returns the extracted coach deck index from place id
1276
+ * @returns number
1277
+ */
1278
+ _getDeckIndexByPlaceId(placeId) {
1279
+ const deckIndex = this.shadowRoot?.querySelector("#" + placeId)?.getAttribute("data-deck-index");
1280
+ if (deckIndex && !isNaN(+deckIndex)) return +deckIndex;
1281
+ return null;
1282
+ }
1283
+ _isValidCoachIndex(coachIndex) {
1284
+ return coachIndex >= 0 && coachIndex <= this.seatReservations[this.seatReservations.length - 1].coachItems.length;
1285
+ }
1286
+ /**
1287
+ * Returns existing coach deck index depending on the selected coach.
1288
+ * This method is necessary to get an available coach deck index during keyboard navigation, which can vary between coaches with different decks.
1289
+ * For example, when navigating from a coach with two decks to a coach with one deck.
1290
+ *
1291
+ * [ooo]-[ooo]-[ooo]
1292
+ * [ooo]-[ooo]-[ooo]-[ooo]-[ooo]
1293
+ *
1294
+ * @returns number
1295
+ */
1296
+ _getExistingCoachDeckIndex() {
1297
+ if (this.seatReservations[this.currSelectedDeckIndex].coachItems[this.currSelectedCoachIndex].places !== void 0) return this.currSelectedDeckIndex;
1298
+ const nextAvailableDeckCoachIndex = this.seatReservations.findIndex((seatReservation) => seatReservation.coachItems[this.currSelectedCoachIndex].places !== void 0);
1299
+ return this.currSelectedDeckIndex >= nextAvailableDeckCoachIndex ? this.currSelectedDeckIndex : nextAvailableDeckCoachIndex;
1300
+ }
1301
+ /**
1302
+ * If a selected place is slightly hidden by the overflow scroll content and is still clicked,
1303
+ * the method tries to scroll the selected place into the nearest viewport, so that it is completely visible.
1304
+ *
1305
+ * @param placeId
1306
+ */
1307
+ _scrollPlaceIntoNearestViewport(placeId) {
1308
+ this.shadowRoot?.getElementById(placeId)?.scrollIntoView({
1309
+ behavior: "smooth",
1310
+ block: "nearest",
1311
+ inline: "nearest"
1312
+ });
1313
+ }
1314
+ /**
1315
+ * checks if any places or graphical elements (e.g. toilet area, etc.) are overhanging the coach borders
1316
+ * @param coachItemWidth
1317
+ * @param elements
1318
+ */
1319
+ _isOverhangingElementsPresent(coachItemWidth, elements) {
1320
+ return elements?.some((element) => element.position.x === 0 || element.position.x + element.dimension.w >= coachItemWidth) ?? false;
1321
+ }
1322
+ /**
1323
+ * collect information about the driverAreas for one coach
1324
+ * @param coachItem
1325
+ * @private
1326
+ */
1327
+ _setDriverAreasElements(coachItem) {
1328
+ if (coachItem) return {
1329
+ driverArea: coachItem.graphicElements?.find((element) => element.icon === "DRIVER_AREA"),
1330
+ driverAreaNoVerticalWall: coachItem.type === "LOCOMOTIVE_COACH" ? coachItem.graphicElements?.find((element) => element.icon === "DRIVER_AREA_NO_VERTICAL_WALL") : void 0
1331
+ };
1332
+ return {
1333
+ driverArea: void 0,
1334
+ driverAreaNoVerticalWall: void 0
1335
+ };
1336
+ }
1337
+ /**
1338
+ * Is called when the SeatReservation loses focus, what happens when the user tabs out or clicks somewhere else.
1339
+ * Then we reset the focused elements.
1340
+ */
1341
+ _onLeaveSeatReservationComponent() {
1342
+ if (this.hasNavigation) this.focusedCoachIndex = -1;
1343
+ this.unfocusPlaceElement();
1344
+ }
1345
+ };
1346
+ })();
1347
+ //#endregion
1348
+ export { SeatReservationBaseElement };
1349
+
1350
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VhdC1yZXNlcnZhdGlvbi1iYXNlLWVsZW1lbnQuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2VsZW1lbnRzLWV4cGVyaW1lbnRhbC9zZWF0LXJlc2VydmF0aW9uL3NlYXQtcmVzZXJ2YXRpb24vc2VhdC1yZXNlcnZhdGlvbi1iYXNlLWVsZW1lbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNBcnJvd0tleU9yUGFnZUtleXNQcmVzc2VkIH0gZnJvbSAnQHNiYi1lc3RhL2x5bmUtZWxlbWVudHMvY29yZS9hMTF5LmpzJztcbmltcG9ydCB7IFNiYkVsZW1lbnQgfSBmcm9tICdAc2JiLWVzdGEvbHluZS1lbGVtZW50cy9jb3JlL2Jhc2UtZWxlbWVudHMuanMnO1xuaW1wb3J0IHsgZm9yY2VUeXBlIH0gZnJvbSAnQHNiYi1lc3RhL2x5bmUtZWxlbWVudHMvY29yZS9kZWNvcmF0b3JzLmpzJztcbmltcG9ydCB7IGlzU2VydmVyLCB0eXBlIFByb3BlcnR5VmFsdWVzIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IGV2ZW50T3B0aW9ucywgcHJvcGVydHksIHN0YXRlIH0gZnJvbSAnbGl0L2RlY29yYXRvcnMuanMnO1xuXG5pbXBvcnQge1xuICBtYXBDb2FjaEluZm9zVG9Db2FjaFNlbGVjdGlvbixcbiAgbWFwSWNvblRvU3ZnLFxuICBtYXBQbGFjZUFuZENvYWNoVG9TZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbixcbiAgbWFwUGxhY2VJbmZvc1RvUGxhY2VTZWxlY3Rpb24sXG59IGZyb20gJy4uL2NvbW1vbi9tYXBwZXIudHMnO1xuaW1wb3J0IHR5cGUge1xuICBCYXNlRWxlbWVudCxcbiAgQ29hY2hJdGVtLFxuICBDb2FjaE51bWJlck9mRnJlZVBsYWNlcyxcbiAgRWxlbWVudERpbWVuc2lvbixcbiAgRWxlbWVudFBvc2l0aW9uLFxuICBDb2FjaEl0ZW1EZXRhaWxzLFxuICBQbGFjZSxcbiAgUGxhY2VTZWxlY3Rpb24sXG4gIFBsYWNlVHJhdmVsQ2xhc3MsXG4gIFNlYXRSZXNlcnZhdGlvbixcbiAgU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24sXG4gIFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkQ29hY2gsXG4gIFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkUGxhY2VzLFxuICBUcmF2ZWxEaXJlY3Rpb24sXG59IGZyb20gJy4uL2NvbW1vbi90eXBlcy50cyc7XG5pbXBvcnQgdHlwZSB7IFNiYlNlYXRSZXNlcnZhdGlvblBsYWNlQ29udHJvbEVsZW1lbnQgfSBmcm9tICcuLi9zZWF0LXJlc2VydmF0aW9uLXBsYWNlLWNvbnRyb2wvc2VhdC1yZXNlcnZhdGlvbi1wbGFjZS1jb250cm9sLmNvbXBvbmVudC50cyc7XG5cbmVudW0gU2Nyb2xsRGlyZWN0aW9uIHtcbiAgcmlnaHQgPSAncmlnaHQnLFxuICBsZWZ0ID0gJ2xlZnQnLFxufVxuXG5pbnRlcmZhY2UgQ29hY2hTY3JvbGxUcmlnZ2VyUG9pbnQge1xuICBzdGFydDogbnVtYmVyO1xuICBlbmQ6IG51bWJlcjtcbiAgd2lkdGg6IG51bWJlcjtcbn1cblxuY29uc3QgTUFYX1NFUlZJQ0VfUFJPUEVSVElFUyA9IDM7XG5jb25zdCBBTExPV0VEX1NFUlZJQ0VfSUNPTlM6IHN0cmluZ1tdID0gW1xuICAnc2Etdm8nLFxuICAnc2EtcnMnLFxuICAnc2EtYWJ0ZWlsa2luZGVyd2FnZW4nLFxuICAnc2Etd3InLFxuICAnc2EtZmEnLFxuICAnc2EtYnonLFxuICAnc2EtcnonLFxuXTtcblxuZXhwb3J0IGNsYXNzIFNlYXRSZXNlcnZhdGlvbkJhc2VFbGVtZW50IGV4dGVuZHMgU2JiRWxlbWVudCB7XG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgZXZlbnRzID0ge1xuICAgIHNlbGVjdGVkcGxhY2VzOiAnc2VsZWN0ZWRwbGFjZXMnLFxuICAgIHNlbGVjdGVkY29hY2g6ICdzZWxlY3RlZGNvYWNoJyxcbiAgfSBhcyBjb25zdDtcblxuICAvKiogVGhlIHNlYXQgcmVzZXJ2YXRpb25zIGFycmF5IGNvbnRhaW5zIGFsbCBjb2FjaGVzIGFuZCBwbGFjZXMgKi9cbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAnc2VhdC1yZXNlcnZhdGlvbnMnLCB0eXBlOiBBcnJheSB9KVxuICBwdWJsaWMgYWNjZXNzb3Igc2VhdFJlc2VydmF0aW9uczogU2VhdFJlc2VydmF0aW9uW10gPSBudWxsITtcblxuICAvKiogRGlzcGxheXMgYW4gYXJyb3cgc2hvd2luZyB3aGF0IGRpcmVjdGlvbiBkb2VzIHRyYWluIGRyaXZlKi9cbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAndHJhdmVsLWRpcmVjdGlvbicsIHR5cGU6IFN0cmluZyB9KVxuICBwdWJsaWMgYWNjZXNzb3IgdHJhdmVsRGlyZWN0aW9uOiBUcmF2ZWxEaXJlY3Rpb24gPSAnTk9ORSc7XG5cbiAgLyoqIFRoZSBzZWF0IHJlc2VydmF0aW9uIG5hdmlnYXRpb24gY2FuIGJlIHRvZ2dsZWQgYnkgdGhpcyBwcm9wZXJ0eSAqL1xuICBAZm9yY2VUeXBlKClcbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAnaGFzLW5hdmlnYXRpb24nLCB0eXBlOiBCb29sZWFuIH0pXG4gIHB1YmxpYyBhY2Nlc3NvciBoYXNOYXZpZ2F0aW9uOiBib29sZWFuID0gdHJ1ZTtcblxuICAvKiogVGhlIHNlYXQgcmVzZXJ2YXRpb24gYXJlYSBpcyBhbGlnbmVkIHZlcnRpY2FsbHkgKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2FsaWduLXZlcnRpY2FsJywgdHlwZTogQm9vbGVhbiwgcmVmbGVjdDogdHJ1ZSwgdXNlRGVmYXVsdDogdHJ1ZSB9KVxuICBwdWJsaWMgYWNjZXNzb3IgYWxpZ25WZXJ0aWNhbDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBUaGUgc2VhdCByZXNlcnZhdGlvbiBhcmVhJ3MgYmFzZSBncmlkIHNpemUgKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2Jhc2UtZ3JpZC1zaXplJywgdHlwZTogTnVtYmVyIH0pXG4gIHB1YmxpYyBhY2Nlc3NvciBiYXNlR3JpZFNpemU6IG51bWJlciA9IDE2O1xuXG4gIC8qKiBUaGUgc2VhdCByZXNlcnZhdGlvbiBhcmVhJ3Mgd2lkdGggKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2hlaWdodCcsIHR5cGU6IE51bWJlciB9KVxuICBwdWJsaWMgYWNjZXNzb3IgaGVpZ2h0OiBudW1iZXIgPSBudWxsITtcblxuICAvKiogTWF4aW1hbCBudW1iZXIgb2YgcG9zc2libGUgY2xpY2thYmxlIHNlYXRzICovXG4gIEBmb3JjZVR5cGUoKVxuICBAcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICdtYXgtc2VhdC1yZXNlcnZhdGlvbnMnLCB0eXBlOiBOdW1iZXIgfSlcbiAgcHVibGljIGFjY2Vzc29yIG1heFNlYXRSZXNlcnZhdGlvbnM6IG51bWJlciA9IC0xO1xuXG4gIC8qKiBNYXhpbWFsIG51bWJlciBvZiBwb3NzaWJsZSBjbGlja2FibGUgYmljeWNsZSBwbGFjZXMgKi9cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ21heC1iaWN5Y2xlLXJlc2VydmF0aW9ucycsIHR5cGU6IE51bWJlciB9KVxuICBwdWJsaWMgYWNjZXNzb3IgbWF4QmljeWNsZVJlc2VydmF0aW9uczogbnVtYmVyID0gLTE7XG5cbiAgLyoqIEFueSBjbGljayBmdW5jdGlvbmFsaXR5IGlzIHByZXZlbnRlZCAqL1xuICBAZm9yY2VUeXBlKClcbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAncHJldmVudC1wbGFjZS1jbGljaycsIHR5cGU6IEJvb2xlYW4gfSlcbiAgcHVibGljIGFjY2Vzc29yIHByZXZlbnRQbGFjZUNsaWNrOiBib29sZWFuID0gZmFsc2U7XG5cbiAgQGZvcmNlVHlwZSgpXG4gIEBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ3ByZXNlbGVjdC1jb2FjaC1pbmRleCcsIHR5cGU6IE51bWJlciB9KVxuICBwdWJsaWMgYWNjZXNzb3IgcHJlc2VsZWN0Q29hY2hJbmRleDogbnVtYmVyID0gLTE7XG5cbiAgLyoqIFRoZSBzZWF0IHJlc2VydmF0aW9uIHRpdGxlIGluZm9ybWF0aW9uIGF0IHBsYWNlLWNvbnRyb2xzLCBuYXZpZ2F0aW9uLWNvYWNoZXMgYW5kIG5hdmlnYXRpb24tc2VydmljZXMgY2FuIGJlIHRvZ2dsZWQgYnkgdGhpcyBwcm9wZXJ0eSAqL1xuICBAZm9yY2VUeXBlKClcbiAgQHByb3BlcnR5KHsgYXR0cmlidXRlOiAnc2hvdy10aXRsZS1pbmZvJywgdHlwZTogQm9vbGVhbiB9KVxuICBwdWJsaWMgYWNjZXNzb3Igc2hvd1RpdGxlSW5mbzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBzdGF0ZSgpIHByb3RlY3RlZCBhY2Nlc3NvciBzZWxlY3RlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuICBAc3RhdGUoKSBwcm90ZWN0ZWQgYWNjZXNzb3IgZm9jdXNlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuICBAc3RhdGUoKSBwcm90ZWN0ZWQgYWNjZXNzb3IgaG92ZXJlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuXG4gIC8vIERlc2NyaWJlcyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgYm9yZGVyIG9mIHRoZSBjb2FjaCBhbmQgdGhlIHBsYWNlcyBpbiBwaXhlbHNcbiAgcHJvdGVjdGVkIGNvYWNoQm9yZGVyUGFkZGluZyA9IDY7XG4gIC8vIERlc2NyaWJlcyB0aGUgZ2FwIGJldHdlZW4gdGhlIGNvYWNoZXMgaW4gcGl4ZWxzXG4gIHByb3RlY3RlZCBnYXBCZXR3ZWVuQ29hY2hlcyA9IDQ7XG4gIC8vIFRoZSBjYWxjdWxhdGVkIGNvYWNoQm9yZGVyT2Zmc2V0IGlzIHVzZWQgdG8gY2FsY3VsYXRlIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIGNvYWNoIGJvcmRlciBncmFwaGljLFxuICAvLyBidXQgYWxzbyB0byBwb3NpdGlvbiBvdGhlciBncmFwaGljcyB0aGF0IGFyZSBhbGlnbmVkIGRpcmVjdGx5IHRvIHRoZSBjb2FjaCBib3JkZXIuXG4gIHByb3RlY3RlZCBjb2FjaEJvcmRlck9mZnNldCA9IHRoaXMuY29hY2hCb3JkZXJQYWRkaW5nIC8gdGhpcy5iYXNlR3JpZFNpemU7XG4gIC8vIERlc2NyaWJlcyB0aGUgZ2FwIGJldHdlZW4gdGhlIGNvYWNoZXMgZGVja3MgYnkgbXVsdGlwbGUgZGVjayB2aXN1YWxpemF0aW9uXG4gIHByb3RlY3RlZCBnYXBCZXR3ZWVuQ29hY2hEZWNrcyA9IDQ4O1xuICAvLyBEZXNjcmliZXMgdGhlIGZpeCB3aWR0aCBvZiBjb2FjaCBuYXZpZ2F0aW9uIGJ1dHRvblxuICBwcm90ZWN0ZWQgY29hY2hOYXZCdXR0b25EaW06IG51bWJlciA9IDA7XG4gIC8vIERlc2NyaWJlcyB0aGUgY2FsY3VsYXRlZCBkaW1lbnNpb24gZm9yIHRoZSBhcmVhIGljb25zLCB3aGljaCBpcyB1c2VkIHRvIHNldCB0aGUgbWF4IHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIGFyZWEgaWNvbnNcbiAgcHJvdGVjdGVkIGdsb2JhbEFyZWFJY29uRGltOiBFbGVtZW50RGltZW5zaW9uID0geyB3OiAyLCBoOiAyIH07XG4gIC8vICNUSU1PLTQ1ODU4XG4gIC8vIERlc2NyaWJlcyB0aGUgcGFkZGluZyBmb3IgdGhlIGljb24gd2l0aGluIHRoZSBhcmVhIGFzIGEgcGVyY2VudGFnZSBzaXplIG9mIHRoZSBhcmVhIHNlbGYuIDgwJSAoMC44IHBlcmNlbnQpIGNvcnJlc3BvbmRzXG4gIC8vIHRvIGEgZ29vZCBvcHRpY2FsIHNpemUgYW5kIGNyZWF0ZXMgYSBnb29kIHBhZGRpbmcgZnJvbSB0aGUgYXJlYSB0aSBpY29uXG4gIHByb3RlY3RlZCBnbG9iYWxBcmVhSWNvblBhZGRpbmc6IG51bWJlciA9IDAuODtcbiAgcHJvdGVjdGVkIGNvYWNoSXRlbURldGFpbHNFbGVtZW50czogQ29hY2hJdGVtRGV0YWlsc1tdID0gW107XG4gIHByb3RlY3RlZCBjdXJyU2Nyb2xsRGlyZWN0aW9uOiBTY3JvbGxEaXJlY3Rpb24gPSBTY3JvbGxEaXJlY3Rpb24ucmlnaHQ7XG4gIHByb3RlY3RlZCBtYXhDYWxjQ29hY2hlc1dpZHRoOiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgc2Nyb2xsQ29hY2hlc0FyZWFXaWR0aDogbnVtYmVyID0gMDtcbiAgcHJvdGVjdGVkIHNjcm9sbE5hdmlnYXRpb25BcmVhRGltOiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgdHJpZ2dlckNvYWNoUG9zaXRpb25zQ29sbGVjdGlvbjogQ29hY2hTY3JvbGxUcmlnZ2VyUG9pbnRbXSA9IFtdO1xuICBwcm90ZWN0ZWQgbmF2aWdhdGlvblNjcm9sbEFyZWE6IEhUTUxFbGVtZW50ID0gbnVsbCE7XG4gIHByb3RlY3RlZCBjb2FjaFNjcm9sbEFyZWE6IEhUTUxFbGVtZW50ID0gbnVsbCE7XG4gIHByb3RlY3RlZCBjdXJyU2VsZWN0ZWRQbGFjZTogUGxhY2UgfCBudWxsID0gbnVsbDtcbiAgcHJvdGVjdGVkIGN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJvdGVjdGVkIGN1cnJTZWxlY3RlZENvYWNoSW5kZXg6IG51bWJlciA9IC0xO1xuICBwcm90ZWN0ZWQgY3VyclNlbGVjdGVkRGVja0luZGV4OiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgcHJldmVudENvYWNoU2Nyb2xsQnlQbGFjZUNsaWNrOiBib29sZWFuID0gZmFsc2U7XG4gIHByb3RlY3RlZCBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlczogU2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRQbGFjZXMgPSB7XG4gICAgc2VhdHM6IFtdLFxuICAgIGJpY3ljbGVzOiBbXSxcbiAgfTtcbiAgcHJvdGVjdGVkIHNlYXRSZXNlcnZhdGlvbldpdGhvdXROYXZpZ2F0aW9uSGFzRm9jdXMgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGlzQ29hY2hHcmlkRm9jdXNhYmxlID0gZmFsc2U7XG4gIHByb3RlY3RlZCBpc0F1dG9TY3JvbGxpbmcgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIGlzS2V5Ym9hcmROYXZpZ2F0aW9uID0gZmFsc2U7XG4gIHByb3RlY3RlZCBoYXNNdWx0aXBsZURlY2tzID0gZmFsc2U7XG4gIHByb3RlY3RlZCBoYXNTZWF0UmVzZXJ2YXRpb25OYXRpdmVGb2N1cyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQga2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzID0ge1xuICAgIEFycm93TGVmdDogJ0Fycm93TGVmdCcsXG4gICAgQXJyb3dSaWdodDogJ0Fycm93UmlnaHQnLFxuICAgIEFycm93VXA6ICdBcnJvd1VwJyxcbiAgICBBcnJvd0Rvd246ICdBcnJvd0Rvd24nLFxuICAgIFRhYjogJ1RhYicsXG4gICAgRW50ZXI6ICdFbnRlcicsXG4gIH0gYXMgY29uc3Q7XG5cbiAgLy8gR3JhcGhpY3MgdGhhdCBzaG91bGQgbm90IGJlIHJlbmRlcmVkIHdpdGggYW4gYXJlYVxuICBwcm90ZWN0ZWQgbm90QXJlYUVsZW1lbnRzID0gW1xuICAgICdEUklWRVJfQVJFQScsXG4gICAgJ0RSSVZFUl9BUkVBX05PX1ZFUlRJQ0FMX1dBTEwnLFxuICAgICdDT0FDSF9QQVNTQUdFJyxcbiAgICAnQ09BQ0hfV0FMTF9OT19QQVNTQUdFJyxcbiAgICAnQ09NUEFSVE1FTlRfUEFTU0FHRScsXG4gICAgJ0NPTVBBUlRNRU5UX1BBU1NBR0VfSElHSCcsXG4gICAgJ0NPTVBBUlRNRU5UX1BBU1NBR0VfTUlERExFJyxcbiAgICAnQ09NUEFSVE1FTlRfUEFTU0FHRV9MT1cnLFxuICAgICdDT01QQVJUTUVOVF9XQUxMJyxcbiAgXTtcblxuICBwcm90ZWN0ZWQgb3ZlckhhbmdpbmdFbGVtZW50SW5mb3JtYXRpb246IHtcbiAgICBjb2FjaElkOiBzdHJpbmc7XG4gICAgb3ZlcmhhbmdpbmdQbGFjZXM6IGJvb2xlYW47XG4gICAgb3ZlcmhhbmdpbmdHcmFwaGljQXJlYXM6IGJvb2xlYW47XG4gIH1bXSA9IFtdO1xuXG4gIHByaXZhdGUgX2lzUnVubmluZ0luaXRQcmVzZWxlY3RDb2FjaEluZGV4ID0gZmFsc2U7XG4gIHByaXZhdGUgX3Njcm9sbFRpbWVvdXQ6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF9sYXN0U3RhcnRTY3JvbGxQb3MgPSAtMTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgICAvLyBBZGQgYmx1ciBldmVudCBsaXN0ZW5lciBvbiB0aGUgZW50aXJlIGNvbXBvbmVudCB0byBkZXRlY3Qgd2hlbiB0aGUgdXNlciBsZWF2ZXMgdGhlIGNvbXBvbmVudFxuICAgIC8vIGJ5IHVzaW5nIHRhYiBuYXZpZ2F0aW9uIG9yIGNsaWNraW5nIG91dHNpZGUgb2YgdGhlIGNvbXBvbmVudC4gSW4gdGhpcyBjYXNlLCB3ZSBjYW4gcmVzZXQgdGhlIHNlbGVjdGVkIGNvYWNoIGFuZCBwbGFjZS5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCAoKSA9PiB0aGlzLl9vbkxlYXZlU2VhdFJlc2VydmF0aW9uQ29tcG9uZW50KCkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIHdpbGxVcGRhdGUoY2hhbmdlZFByb3BlcnRpZXM6IFByb3BlcnR5VmFsdWVzPHRoaXM+KTogdm9pZCB7XG4gICAgc3VwZXIud2lsbFVwZGF0ZShjaGFuZ2VkUHJvcGVydGllcyk7XG5cbiAgICBpZiAoY2hhbmdlZFByb3BlcnRpZXMuaGFzKCdzZWF0UmVzZXJ2YXRpb25zJykpIHtcbiAgICAgIHRoaXMuaGFzTXVsdGlwbGVEZWNrcyA9IHRoaXMuc2VhdFJlc2VydmF0aW9ucz8ubGVuZ3RoID4gMTtcblxuICAgICAgdGhpcy5faW5pdFByZXBhcmVTZWF0UmVzZXJ2YXRpb25EYXRhKCk7XG4gICAgICB0aGlzLl9wcmVwYXJlQ29hY2hXaWR0aEFuZEdhcENhbGN1bGF0aW9ucygpO1xuICAgICAgdGhpcy5faW5pdFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uKCk7XG4gICAgICB0aGlzLmluaXROYXZpZ2F0aW9uU2VsZWN0aW9uQnlTY3JvbGxFdmVudCgpO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VkUHJvcGVydGllcy5oYXMoJ2Jhc2VHcmlkU2l6ZScpKSB7XG4gICAgICB0aGlzLmNvYWNoQm9yZGVyT2Zmc2V0ID0gdGhpcy5jb2FjaEJvcmRlclBhZGRpbmcgLyB0aGlzLmJhc2VHcmlkU2l6ZTtcbiAgICAgIHRoaXMuc3R5bGU/LnNldFByb3BlcnR5KCctLXNiYi1zZWF0LXJlc2VydmF0aW9uLWdyaWQtc2l6ZScsIGAke3RoaXMuYmFzZUdyaWRTaXplfXB4YCk7XG5cbiAgICAgIHRoaXMuaW5pdE5hdmlnYXRpb25TZWxlY3Rpb25CeVNjcm9sbEV2ZW50KCk7XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlIGhlaWdodCBpcyB1c2VkLCB0aGUgYmFzZUdyaWRTaXplIG11c3QgYmUgcmVjYWxjdWxhdGVkXG4gICAgaWYgKGNoYW5nZWRQcm9wZXJ0aWVzLmhhcygnaGVpZ2h0JykgJiYgISF0aGlzLmhlaWdodCkge1xuICAgICAgY29uc3Qgc2VhdFJlc2VydmF0aW9uTGF5ZXIgPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdIHx8IG51bGw7XG4gICAgICBpZiAoc2VhdFJlc2VydmF0aW9uTGF5ZXI/LmNvYWNoSXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuYmFzZUdyaWRTaXplID0gdGhpcy5oZWlnaHQgLyBzZWF0UmVzZXJ2YXRpb25MYXllci5jb2FjaEl0ZW1zWzBdLmRpbWVuc2lvbi5oO1xuICAgICAgICB0aGlzLmNvYWNoQm9yZGVyT2Zmc2V0ID0gdGhpcy5jb2FjaEJvcmRlclBhZGRpbmcgLyB0aGlzLmJhc2VHcmlkU2l6ZTtcbiAgICAgICAgdGhpcy5zdHlsZT8uc2V0UHJvcGVydHkoJy0tc2JiLXNlYXQtcmVzZXJ2YXRpb24tZ3JpZC1zaXplJywgYCR7dGhpcy5iYXNlR3JpZFNpemV9cHhgKTtcblxuICAgICAgICB0aGlzLl9pbml0UHJlcGFyZVNlYXRSZXNlcnZhdGlvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5pbml0TmF2aWdhdGlvblNlbGVjdGlvbkJ5U2Nyb2xsRXZlbnQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2hhbmdlZFByb3BlcnRpZXMuaGFzKCdhbGlnblZlcnRpY2FsJykgJiYgdGhpcy5hbGlnblZlcnRpY2FsKSB7XG4gICAgICB0aGlzLmluaXROYXZpZ2F0aW9uU2VsZWN0aW9uQnlTY3JvbGxFdmVudCgpO1xuICAgIH1cblxuICAgIGlmIChjaGFuZ2VkUHJvcGVydGllcy5oYXMoJ3ByZXNlbGVjdENvYWNoSW5kZXgnKSkge1xuICAgICAgLy8gc2V0VGltZW91dCBpcyBuZWNlc3NhcnkgYmVjYXVzZSB3aXRob3V0LCBfZ2V0Q29hY2hTY3JvbGxQb3NpdGlvblgoKSB3b3VsZCBmYWlsIHdpdGggTlBFIGJlY2F1c2VcbiAgICAgIC8vIHRoZSBjb2FjaFNjcm9sbEFyZWEgaXMgbm90IHlldCBpbml0aWFsaXplZFxuICAgICAgdGhpcy5faXNSdW5uaW5nSW5pdFByZXNlbGVjdENvYWNoSW5kZXggPSB0cnVlO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnNjcm9sbFRvU2VsZWN0ZWROYXZDb2FjaCh0aGlzLnByZXNlbGVjdENvYWNoSW5kZXgpLCAxKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgbmF2aWdhdGVCeURpcmVjdGlvbkJ0bihidG5EaXJlY3Rpb246IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudW5mb2N1c1BsYWNlRWxlbWVudCgpO1xuICAgIGxldCBuYXZpZ2F0ZVRvQ29hY2hJbmRleCA9IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICBpZiAoYnRuRGlyZWN0aW9uID09ICdESVJFQ1RJT05fTEVGVCcgJiYgbmF2aWdhdGVUb0NvYWNoSW5kZXggPiAwKSB7XG4gICAgICBuYXZpZ2F0ZVRvQ29hY2hJbmRleCA9XG4gICAgICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAhPSAtMSA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAtIDEgOiAwO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICBidG5EaXJlY3Rpb24gPT0gJ0RJUkVDVElPTl9SSUdIVCcgJiZcbiAgICAgIG5hdmlnYXRlVG9Db2FjaEluZGV4IDxcbiAgICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zW3RoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4XT8uY29hY2hJdGVtcy5sZW5ndGggLSAxXG4gICAgKSB7XG4gICAgICBuYXZpZ2F0ZVRvQ29hY2hJbmRleCA9XG4gICAgICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAhPSAtMSA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCArIDEgOiAwO1xuICAgIH1cblxuICAgIHRoaXMuc2Nyb2xsVG9TZWxlY3RlZE5hdkNvYWNoKG5hdmlnYXRlVG9Db2FjaEluZGV4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEYXRhIGNhbiBiZSBwcmVwYXJlZCBvbmNlIGZvciB0aGUgZW50aXJlIGNvbXBvbmVudFxuICAgKiBpbiBvcmRlciB0byBhdm9pZCByZWN1cnJpbmcgaXRlcmF0aW9uIHByb2Nlc3NlcyBpbiByZW5kZXJpbmcuXG4gICAqL1xuICBwcml2YXRlIF9pbml0UHJlcGFyZVNlYXRSZXNlcnZhdGlvbkRhdGEoKTogdm9pZCB7XG4gICAgdGhpcy5fZGV0ZXJtaW5lQmFzZUZvbnRTaXplKCk7XG5cbiAgICBpZiAodGhpcy5oYXNNdWx0aXBsZURlY2tzKSB7XG4gICAgICAvLyBJZiB0aGVyZSBhcmUgbXVsdGlwbGUgZGVja3MsIHdlIG5lZWQgdG8gY2hlY2tcbiAgICAgIC8vIHdoZXRoZXIgZW1wdHkgY29hY2hlcyBuZWVkIHRvIGJlIGFkZGVkIG9uIGRpZmZlcmVudCBkZWNrIGxldmVsc1xuICAgICAgdGhpcy5faW5pdEVtcHR5Q29hY2hEZWNrT2Zmc2V0cygpO1xuICAgIH1cblxuICAgIHRoaXMuX3ByZXBhcmVDb2FjaEl0ZW1EZXRhaWxzRGF0YSgpO1xuICAgIHRoaXMuX3ByZXBhcmVPcHRpbWl6ZUFyZWFJY29uRGltZW5zaW9uQnlNZWRpYW4oKTtcbiAgfVxuXG4gIC8qKiBJbml0IHNjcm9sbCBldmVudCBoYW5kbGluZyBmb3IgY29hY2ggbmF2aWdhdGlvbiAqL1xuICBwcm90ZWN0ZWQgaW5pdE5hdmlnYXRpb25TZWxlY3Rpb25CeVNjcm9sbEV2ZW50KCk6IHZvaWQge1xuICAgIHRoaXMuY29hY2hTY3JvbGxBcmVhID0gdGhpcy5zaGFkb3dSb290Py5xdWVyeVNlbGVjdG9yKFxuICAgICAgJyNzYmItc3JfX3dyYXBwZXItc2Nyb2xsYXJlYScsXG4gICAgKSBhcyBIVE1MRWxlbWVudDtcbiAgICB0aGlzLm5hdmlnYXRpb25TY3JvbGxBcmVhID0gdGhpcy5zaGFkb3dSb290Py5xdWVyeVNlbGVjdG9yKFxuICAgICAgJyNzYmItc3JfX25hdmlnYXRpb24tbGlzdC1jb2FjaGVzJyxcbiAgICApIGFzIEhUTUxFbGVtZW50O1xuXG4gICAgY29uc3Qgc2VhdFJlc2VydmF0aW9uRGVjayA9IHRoaXMuc2VhdFJlc2VydmF0aW9uc1xuICAgICAgPyB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdXG4gICAgICA6IG51bGw7XG4gICAgaWYgKHNlYXRSZXNlcnZhdGlvbkRlY2sgJiYgc2VhdFJlc2VydmF0aW9uRGVjay5jb2FjaEl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENhbGN1bGF0ZXMgdGhlIGFic29sdXRlIGhlaWdodCBvZiBvbmUgY29hY2ggaW5jbHVkaW5nIGJvcmRlciBwYWRkaW5nXG4gICAgICBjb25zdCBjb2FjaEhlaWdodFdpdGhCb3JkZXJQYWRkaW5nID1cbiAgICAgICAgc2VhdFJlc2VydmF0aW9uRGVjay5jb2FjaEl0ZW1zWzBdLmRpbWVuc2lvbi5oICogdGhpcy5iYXNlR3JpZFNpemUgKyB0aGlzLmNvYWNoQm9yZGVyUGFkZGluZztcblxuICAgICAgLy8gQ2FsY3VsYXRlIGVhY2ggZ2FwIGJldHdlZW4gbXVsdGlwbGUgY29hY2ggdGhlIGRlY2tzLlxuICAgICAgLy8gTm8gZ2FwIGV4aXN0IGlmIGp1c3Qgb25lIGNvYWNoIGRlY2sgZXhpc3QuXG4gICAgICBjb25zdCBnYXBCZXR3ZWVuQ29hY2hEZWNrcyA9ICh0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMSkgKiB0aGlzLmdhcEJldHdlZW5Db2FjaERlY2tzO1xuXG4gICAgICB0aGlzLnN0eWxlPy5zZXRQcm9wZXJ0eShcbiAgICAgICAgJy0tc2JiLXNlYXQtcmVzZXJ2YXRpb24taGVpZ2h0JyxcbiAgICAgICAgYCR7Y29hY2hIZWlnaHRXaXRoQm9yZGVyUGFkZGluZyAqIHRoaXMuc2VhdFJlc2VydmF0aW9ucy5sZW5ndGggKyBnYXBCZXR3ZWVuQ29hY2hEZWNrc31gLFxuICAgICAgKTtcbiAgICAgIHRoaXMuc3R5bGU/LnNldFByb3BlcnR5KCctLXNiYi1zZWF0LXJlc2VydmF0aW9uLWRlY2tzJywgYCR7dGhpcy5zZWF0UmVzZXJ2YXRpb25zLmxlbmd0aH1gKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5uYXZpZ2F0aW9uU2Nyb2xsQXJlYSkge1xuICAgICAgdGhpcy5zY3JvbGxOYXZpZ2F0aW9uQXJlYURpbSA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICA/IHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0XG4gICAgICAgIDogdGhpcy5uYXZpZ2F0aW9uU2Nyb2xsQXJlYS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aDtcblxuICAgICAgLy8gSW5pdCB0aGUgY29hY2hOYXZCdXR0b25EaW0gZGltZW5zaW9uLCB3aGljaCBpcyBuZWVkZWQgdG8gY2FsY3VsYXRlIHRoZSBjb3JyZWN0IHNjcm9sbCBuYXZpZ2F0aW9uIGxhdGVyXG4gICAgICBjb25zdCBuYXZDb2FjaGVzTGlzdCA9IHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEucXVlcnlTZWxlY3RvcigndWwgPiBsaScpIGFzIEhUTUxVTGlzdEVsZW1lbnQ7XG4gICAgICBpZiAobmF2Q29hY2hlc0xpc3QpIHtcbiAgICAgICAgY29uc3QgZmlyc3RMaUVsZURpbWVuc2lvbiA9IG5hdkNvYWNoZXNMaXN0Py5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdGhpcy5jb2FjaE5hdkJ1dHRvbkRpbSA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICAgID8gZmlyc3RMaUVsZURpbWVuc2lvbi5oZWlnaHRcbiAgICAgICAgICA6IGZpcnN0TGlFbGVEaW1lbnNpb24ud2lkdGg7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY29hY2hTY3JvbGxBcmVhICYmIHNlYXRSZXNlcnZhdGlvbkRlY2spIHtcbiAgICAgIC8vIEluaXQgdGhlIHN0YXJ0IG9mZnNldCBmb3IgdGhlIGNhbGN1bGF0aW9uIG9mIHRoZSBjb2FjaCBzY3JvbGwgdHJpZ2dlciBwb3NpdGlvbnNcbiAgICAgIGxldCBjdXJyQ2FsY1RyaWdnZXJQb3MgPSAwO1xuICAgICAgdGhpcy5zY3JvbGxDb2FjaGVzQXJlYVdpZHRoID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICAgID8gdGhpcy5jb2FjaFNjcm9sbEFyZWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkuaGVpZ2h0XG4gICAgICAgIDogdGhpcy5jb2FjaFNjcm9sbEFyZWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7XG5cbiAgICAgIC8vIFByZWNhbGN1bGF0ZSB0cmlnZ2VyIHNjcm9sbCBwb3NpdGlvbiBhcnJheSBkZXBlbmRzIG9uIGNvYWNoIHdpZHRoXG4gICAgICB0aGlzLnRyaWdnZXJDb2FjaFBvc2l0aW9uc0NvbGxlY3Rpb24gPSBzZWF0UmVzZXJ2YXRpb25EZWNrLmNvYWNoSXRlbXMubWFwKChjb2FjaCkgPT4ge1xuICAgICAgICBjb25zdCBzdGFydFBvc1ggPSBjdXJyQ2FsY1RyaWdnZXJQb3M7XG4gICAgICAgIGNvbnN0IGNvYWNoV2lkdGggPSB0aGlzLmdldENhbGN1bGF0ZWREaW1lbnNpb24oY29hY2guZGltZW5zaW9uKS53O1xuXG4gICAgICAgIC8vIENhbGN1bGF0aW9uIG9mIHRoZSBlbmQgc2Nyb2xsIHRyaWdnZXIgcG9zaXRpb24gb2YgYSBjb2FjaCwgaW5jbHVkaW5nIHRoZSBnYXAgYmV0d2VlbiB0aGUgY29hY2hlc1xuICAgICAgICAvLyBUaGUgZ2FwIGlzIG1heWJlIGFkanVzdGVkIGlmIG92ZXJoYW5naW5nIHBsYWNlcyBvciBncmFwaGljcyBleGlzdFxuICAgICAgICBjb25zdCBjdXJyZW50Q29hY2hPdmVyaGFuZ2luZ0luZm8gPSB0aGlzLm92ZXJIYW5naW5nRWxlbWVudEluZm9ybWF0aW9uLmZpbmQoXG4gICAgICAgICAgKGUpID0+IGUuY29hY2hJZCA9PT0gY29hY2guaWQsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IG92ZXJoYW5naW5nRWxlbWVudHNQcmVzZW50ID1cbiAgICAgICAgICBjdXJyZW50Q29hY2hPdmVyaGFuZ2luZ0luZm8/Lm92ZXJoYW5naW5nUGxhY2VzIHx8XG4gICAgICAgICAgY3VycmVudENvYWNoT3ZlcmhhbmdpbmdJbmZvPy5vdmVyaGFuZ2luZ0dyYXBoaWNBcmVhcztcbiAgICAgICAgY3VyckNhbGNUcmlnZ2VyUG9zICs9XG4gICAgICAgICAgY29hY2hXaWR0aCArXG4gICAgICAgICAgKCFvdmVyaGFuZ2luZ0VsZW1lbnRzUHJlc2VudCA/IHRoaXMuZ2FwQmV0d2VlbkNvYWNoZXMgOiAyICogdGhpcy5nYXBCZXR3ZWVuQ29hY2hlcyk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzdGFydDogc3RhcnRQb3NYLFxuICAgICAgICAgIGVuZDogY3VyckNhbGNUcmlnZ2VyUG9zLFxuICAgICAgICAgIHdpZHRoOiBjb2FjaFdpZHRoLFxuICAgICAgICB9IGFzIENvYWNoU2Nyb2xsVHJpZ2dlclBvaW50O1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFNldCBtYXhpbXVtIGNhbGN1bGF0ZWQgY29hY2ggd2lkdGhcbiAgICAgIHRoaXMubWF4Q2FsY0NvYWNoZXNXaWR0aCA9IGN1cnJDYWxjVHJpZ2dlclBvcyAtIHRoaXMuZ2FwQmV0d2VlbkNvYWNoZXM7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNjcm9sbCBldmVudCBoYW5kbGVyIG1hbmFnZWQgdGhlIGVuZCBvZiBzY3JvbGxpbmcgaW5zaWRlIHRoZSBjb2FjaCBzY3JvbGwgYXJlYS5cbiAgICogVGltZW91dCBldmVudCBoYW5kbGluZyB0byBjaGVjayBpZiB0aGUgc2Nyb2xsaW5nIGhhcyBiZWVuIGNvbXBsZXRlZC5cbiAgICogSXQgaXMgcmVxdWlyZWQgYmVjYXVzZSB0aGUgU2FmYXJpIGJyb3dzZXIgZG9lcyBub3QgaGFuZGxlIHNjcm9sbGVuZCBldmVudCxcbiAgICogYW5kIHdlIHRoZXJlZm9yZSBpbWl0YXRlIHRoaXMgZXZlbnQgLT4gc2Nyb2xsZW5kLlxuICAgKi9cbiAgQGV2ZW50T3B0aW9ucyh7IHBhc3NpdmU6IHRydWUgfSlcbiAgcHJvdGVjdGVkIGNvYWNoQXJlYVNjcm9sbGVuZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fc2Nyb2xsVGltZW91dCkge1xuICAgICAgLy8gRmlyc3QsIHdlIGNsZWFyZWQgdGhlIHJlZ2lzdGVyZWQgdGltZW91dCwgYXMgdGhlIHNjcm9sbGluZyBpcyBzdGlsbCBydW5uaW5nXG4gICAgICAvLyBhbmQgdGh1cyB3ZSBwcmV2ZW50IHRoZSBleGVjdXRpb24gb2YgdGhlIF9oYW5kbGVDb2FjaEFyZWFTY3JvbGxlbmRFdmVudCBmdW5jdGlvblxuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuX3Njcm9sbFRpbWVvdXQpO1xuICAgIH1cbiAgICAvLyBJZiBubyBmdXJ0aGVyIHNjcm9sbCBldmVudCBpcyBmaXJlZCwgdGhlIG5leHQgdGltZW91dCBjYW4gZXhlY3V0ZSB0aGUgaW5uZXIgZnVuY3Rpb24gX2hhbmRsZUNvYWNoQXJlYVNjcm9sbGVuZEV2ZW50IHdpdGhvdXQgY2xlYXJpbmdcbiAgICB0aGlzLl9zY3JvbGxUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB0aGlzLl9oYW5kbGVDb2FjaEFyZWFTY3JvbGxlbmRFdmVudCgpLCAxNTApO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIG5vIG5hdmlnYXRpb24gZXhpc3RzIChwcm9wZXJ0eSBzZXR0aW5nIC0+IGhhc05hdmlnYXRpb24pIGFuZCBhIHRhYmxlIGNvYWNoIGdldHMgdGhlIGZvY3VzLFxuICAgKiB0aGUgZmlyc3QgcGxhY2UgaW4gdGhlIGNvYWNoIG11c3QgYmUgYXV0b21hdGljYWxseSBwcmVzZWxlY3RlZCB0byBjb250cm9sIHRoZSBwbGFjZSBuYXZpZ2F0aW9uIHZpYSBrZXlib2FyZFxuICAgKlxuICAgKiBAcGFyYW0gZm9jdXNDb2FjaEluZGV4XG4gICAqL1xuICBwcm90ZWN0ZWQgb25Gb2N1c1RhYmxlQ29hY2hBbmRQcmVzZWxlY3RQbGFjZShmb2N1c0NvYWNoSW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghdGhpcy5zZWF0UmVzZXJ2YXRpb25XaXRob3V0TmF2aWdhdGlvbkhhc0ZvY3VzICYmICF0aGlzLmhhc05hdmlnYXRpb24pIHtcbiAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uV2l0aG91dE5hdmlnYXRpb25IYXNGb2N1cyA9IHRydWU7XG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPVxuICAgICAgICBmb2N1c0NvYWNoSW5kZXggPT09IDBcbiAgICAgICAgICA/IHRoaXMuZ2V0TmV4dEF2YWlsYWJsZUNvYWNoSW5kZXgoLTEpXG4gICAgICAgICAgOiB0aGlzLmdldFByZXZBdmFpbGFibGVDb2FjaEluZGV4KGZvY3VzQ29hY2hJbmRleCk7XG4gICAgICB0aGlzLnByZXNlbGVjdFBsYWNlSW5Db2FjaCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBXaWxsIGJlIHRyaWdnZXJlZCBieSBmb2N1cyBuYXZpZ2F0aW9uIGRpcmVjdGlvbiAqL1xuICBwcm90ZWN0ZWQgb25Gb2N1c05hdkRpcmVjdGlvbkJ1dHRvbigpOiB2b2lkIHtcbiAgICAvLyBJZiBhbnkgbmF2aWdhdGlvbiBkaXJlY3Rpb24gYnV0dG9uIChyaWdodHxsZWZ0KSBnZXQgdGhlIGZvY3VzLCBzbyB3ZSBoYXZlIG1hbnVhbCByZXNldCB0aGUgcHJldmlvdXMgZm9jdXNDb2FjaEluZGV4LlxuICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSAtMTtcbiAgfVxuXG4gIC8qKiBUQUIgS2V5IEV2ZW50IGhhbmRsaW5nIGZvciBDb2FjaCBOYXZpZ2F0aW9uICovXG4gIHByb3RlY3RlZCBvbktleU5hdmlnYXRpb25OYXZDb2FjaEJ1dHRvbihcbiAgICBldmVudDogS2V5Ym9hcmRFdmVudCxcbiAgICBjdXJyTmF2Q29hY2hCdXR0b25JbmRleDogbnVtYmVyLFxuICApOiB2b2lkIHtcbiAgICBpZiAoZXZlbnQua2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5UYWIpIHtcbiAgICAgIHRoaXMuX2hhbmRsZVRhYktleU5hdmlnYXRpb24oZXZlbnQsICduYXZpZ2F0aW9uJywgY3Vyck5hdkNvYWNoQnV0dG9uSW5kZXgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEJ5IHVzaW5nIGFueSBvdGhlciBrZXkgKG5vIFRBQikgaW5zaWRlIHRoZSBOYXZpZ2F0aW9uIGFyZWEsIHNvIHdlIGNhbiBoYW5kbGUgdGhpcyBieSB1c2luZyB0aGUgbG9naWMgZnJvbSBrZXlib2FyZFNlYXRtYXBFdmVudEhhbmRsaW5nXG4gICAgaWYgKGlzQXJyb3dLZXlPclBhZ2VLZXlzUHJlc3NlZChldmVudCkpIHtcbiAgICAgIHRoaXMua2V5Ym9hcmRTZWF0bWFwRXZlbnRIYW5kbGluZyhldmVudCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEdlbmVyYWwgVEFCIEtleSBFdmVudCBoYW5kbGluZyBmb3IgdGFiIG5hdmlnYXRpb24gaW5zaWRlIHRoZSBjb2FjaCBuYXZpZ2F0aW9uIGFyZWEgYW5kIHRoZSBzZWF0bWFwIGFyZWEgKi9cbiAgcHJpdmF0ZSBfaGFuZGxlVGFiS2V5TmF2aWdhdGlvbihcbiAgICBldmVudDogS2V5Ym9hcmRFdmVudCxcbiAgICBldmVudEFyZWE6IHN0cmluZyxcbiAgICBjdXJyVGFiSW5kZXg/OiBudW1iZXIsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IHByZXNzZWRLZXkgPSBldmVudC5rZXk7XG4gICAgY29uc3QgcHJlc3NlZFNoaWZ0VGFiID0gZXZlbnQuc2hpZnRLZXk7XG5cbiAgICBpZiAocHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuVGFiKSB7XG4gICAgICAvLyBIYW5kbGUgVEFCIGtleSBldmVudCBuYXZpZ2F0aW9uIGZvciBjb2FjaCBuYXZpZ2F0aW9uIGFyZWEuXG4gICAgICAvLyBGcHIgY29hY2ggbmF2aWdhdGlvbiB3ZSBqdXN0IGNvbnRyb2wgdGhlIGZvY3VzIGluZGV4IHRvIHZpc3VhbGl6ZSBmb2N1cyBzdHlsZSBmb3IgbmF2IGNvYWNoIGJ1dHRvblxuICAgICAgaWYgKGV2ZW50QXJlYSA9PSAnbmF2aWdhdGlvbicpIHtcbiAgICAgICAgaWYgKGN1cnJUYWJJbmRleCA9PSB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXgpIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAhdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZSB8fFxuICAgICAgICAgICAgIXByZXNzZWRTaGlmdFRhYiB8fFxuICAgICAgICAgICAgdGhpcy5jb2FjaEl0ZW1EZXRhaWxzRWxlbWVudHNbY3VyclRhYkluZGV4XS5pc0RyaXZlckFyZWEgfHxcbiAgICAgICAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPT0gLTFcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSBjdXJyVGFiSW5kZXg7XG4gICAgICAgICAgfSBlbHNlIGlmIChwcmVzc2VkU2hpZnRUYWIgJiYgdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZSkge1xuICAgICAgICAgICAgLy9JZiB0aGUgRm9yIGJhY2sgdGFiYmluZywgd2UganVtcFxuICAgICAgICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IC0xO1xuICAgICAgICAgICAgdGhpcy5mb2N1c1BsYWNlRWxlbWVudCh0aGlzLmN1cnJTZWxlY3RlZFBsYWNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IGN1cnJUYWJJbmRleCE7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zY3JvbGxUb1NlbGVjdGVkTmF2aWdhdGlvbkJ1dHRvbihjdXJyVGFiSW5kZXghKTtcbiAgICAgIH1cbiAgICAgIC8vIEhhbmRsZSBUQUIga2V5IGV2ZW50IG5hdmlnYXRpb24gZm9yIHNlYXRtYXAgYXJlYVxuICAgICAgZWxzZSBpZiAoZXZlbnRBcmVhID09ICdzZWF0bWFwJykge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBpZiAocHJlc3NlZFNoaWZ0VGFiKSB7XG4gICAgICAgICAgdGhpcy5fbmF2aWdhdGVDb2FjaE5hdmlnYXRpb25CeUtleWJvYXJkKCdQUkVWX1RBQicpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuX25hdmlnYXRlQ29hY2hOYXZpZ2F0aW9uQnlLZXlib2FyZCgnTkVYVF9UQUInKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXNhdGlvbiBvZiBLZXlib2FyZCBTZWF0bWFwIGV2ZW50IGhhbmRsaW5nIHRvIG5hdmlnYXRpb24gYmV0d2VlbiBlYWNoIHBsYWNlcyBpbnNpZGUgYSBzZWxlY3RlZCBjb2FjaCBieSB1c2luZyBbYXJyb3ddIGtleXMuXG4gICAqIFdpdGggdGhlIFtUQUJdIGtleSB0aGUgdXNlciBuYXZpZ2F0aW9uIGdvZXMgdG8gdGhlIG5leHQgY29hY2ggbmF2aWdhdGlvbiBlbGVtZW50IGFuZCB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHBsYWNlIGlzIGF1dG9tYXRpY2FsbHkgcmVzZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQga2V5Ym9hcmRTZWF0bWFwRXZlbnRIYW5kbGluZyhldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGlzVGFiTmV4dCA9IGV2ZW50LmtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuVGFiO1xuICAgIGNvbnN0IGlzVGFiUHJldiA9IGV2ZW50LnNoaWZ0S2V5ICYmIGlzVGFiTmV4dDtcblxuICAgIC8vIElmIG5vIG5hdmlnYXRpb24gZXhpc3QgYW5kIHRoZSBmaXJzdCBvciBsYXN0IGNvYWNoIGlzIHNlbGVjdGVkLCB0aGUgdGhlIHVzZSB0cmllcyB0byBsZWF2ZSB0aGUgc2VhdCByZXNlcnZhdGlvbiBjb21wb25lbnQgYnkgdXNpbmcgdGFiLFxuICAgIC8vIHNvIHdlIGNhbiByZXR1cm4gaGVyZSBhbmQgYWxsb3cgdGhlIG5hdGl2ZSBmb2N1cyB0byBsZWF2ZSB0aGUgY29tcG9uZW50LlxuICAgIGlmIChcbiAgICAgICghdGhpcy5oYXNOYXZpZ2F0aW9uICYmIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9PT0gMCAmJiBpc1RhYlByZXYpIHx8XG4gICAgICAodGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4ID09PSB0aGlzLmNvYWNoSXRlbURldGFpbHNFbGVtZW50cy5sZW5ndGggLSAxICYmIGlzVGFiTmV4dClcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwcmVzc2VkS2V5ID0gZXZlbnQua2V5O1xuICAgIHRoaXMucHJldmVudENvYWNoU2Nyb2xsQnlQbGFjZUNsaWNrID0gZmFsc2U7XG4gICAgLy8gQ2hlY2sgYW55IGtleWJvYXJkIGV2ZW50IHdhcyB0cmlnZ2VyZWQgaW5zaWRlIHRoZSBzZWF0IHJlc2VydmF0aW9uIGNvbXBvbmVudCxcbiAgICAvLyBzbyB3ZSBjYW4gc2F5IHRoZSBuYXRpdmUgYnJvd3NlciBmb2N1cyBsaWVzIG9uIHRoZSBjb21wb25lbnRcbiAgICBpZiAoIXRoaXMuaGFzU2VhdFJlc2VydmF0aW9uTmF0aXZlRm9jdXMgJiYgKGlzVGFiTmV4dCB8fCBpc1RhYlByZXYpKSB7XG4gICAgICB0aGlzLmhhc1NlYXRSZXNlcnZhdGlvbk5hdGl2ZUZvY3VzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBJZiBhbnkgcGxhY2UgaXMgc2VsZWN0ZWQgYW5kIFRBQiBLZXkgY29tYmluYXRpb24gaXN0IHByZXNzZWQsXG4gICAgLy8gdGhlbiB3ZSBoYW5kbGUgdGhlIG5leHQgb3IgcHJldmlvdXMgY29hY2ggc2VsZWN0aW9uXG4gICAgaWYgKGlzVGFiTmV4dCkge1xuICAgICAgdGhpcy5faGFuZGxlVGFiS2V5TmF2aWdhdGlvbihldmVudCwgJ3NlYXRtYXAnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBBcnJvdyBLZXlib2FyZCBuYXZpZ2F0aW9uIHRvIGNvbnRyb2wgcGxhY2VzIGluc2lkZSB0aGUgc2VhdG1hcFxuICAgIGlmICh0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggIT09IC0xICYmIGlzQXJyb3dLZXlPclBhZ2VLZXlzUHJlc3NlZChldmVudCkpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgIHN3aXRjaCAocHJlc3NlZEtleSkge1xuICAgICAgICBjYXNlIHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdDpcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb25zdCBwcmVzc2VkTGVmdEtleU1hcHBpbmc6IHN0cmluZyA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICAgICAgICA/IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93RG93blxuICAgICAgICAgICAgICA6IHByZXNzZWRLZXk7XG4gICAgICAgICAgICB0aGlzLl9uYXZpZ2F0ZVRvUGxhY2VCeUtleWJvYXJkKHByZXNzZWRMZWZ0S2V5TWFwcGluZyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93UmlnaHQ6XG4gICAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgcHJlc3NlZFJpZ2h0S2V5TWFwcGluZzogc3RyaW5nID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICAgICAgICAgID8gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dVcFxuICAgICAgICAgICAgICA6IHByZXNzZWRLZXk7XG4gICAgICAgICAgICB0aGlzLl9uYXZpZ2F0ZVRvUGxhY2VCeUtleWJvYXJkKHByZXNzZWRSaWdodEtleU1hcHBpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1VwOlxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGNvbnN0IHByZXNzZWRVcEtleU1hcHBpbmc6IHN0cmluZyA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgICAgICAgICA/IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdFxuICAgICAgICAgICAgICA6IHByZXNzZWRLZXk7XG4gICAgICAgICAgICB0aGlzLl9uYXZpZ2F0ZVRvUGxhY2VCeUtleWJvYXJkKHByZXNzZWRVcEtleU1hcHBpbmcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd0Rvd246XG4gICAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgcHJlc3NlZERvd25LZXlNYXBwaW5nOiBzdHJpbmcgPSB0aGlzLmFsaWduVmVydGljYWxcbiAgICAgICAgICAgICAgPyB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1JpZ2h0XG4gICAgICAgICAgICAgIDogcHJlc3NlZEtleTtcbiAgICAgICAgICAgIHRoaXMuX25hdmlnYXRlVG9QbGFjZUJ5S2V5Ym9hcmQocHJlc3NlZERvd25LZXlNYXBwaW5nKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNlbGVjdHMgYSBwbGFjZSBpbnNpZGUgdGhlIGNvYWNoIGlmIG5hdmlnYXRlZCB2aWEga2V5Ym9hcmQsXG4gICAqIG90aGVyd2lzZSB0aGUgY29hY2ggZ3JpZCBpcyBzZWxlY3RlZCAobmVjZXNzYXJ5IGZvciBTY3JlZW5SZWFkZXIpXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlc2VsZWN0UGxhY2VJbkNvYWNoKCk6IHZvaWQge1xuICAgIC8vIE5vIHByZXNlbGVjdCBwbGFjZSBieSBtYW51YWwgc2VhdG1hcCBzY3JvbGxpbmdcbiAgICBpZiAoIXRoaXMuaXNBdXRvU2Nyb2xsaW5nKSByZXR1cm47XG5cbiAgICAvLyBObyBhdXRvIHBsYWNlIHByZXNlbGVjdGlvbiBieSBydW5uaW5nIHRoZSBwcmVzZWxlY3QgY29hY2ggaW5kZXhcbiAgICBpZiAodGhpcy5faXNSdW5uaW5nSW5pdFByZXNlbGVjdENvYWNoSW5kZXgpIHtcbiAgICAgIHRoaXMuX2lzUnVubmluZ0luaXRQcmVzZWxlY3RDb2FjaEluZGV4ID0gZmFsc2U7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gRm9yIERyaXZlckFyZWEgb3IgRW1wdHkgY29hY2ggKG5vIHBsYWNlcyksIG5vIHBsYWNlIGlzIHNlbGVjdGFibGUsIHNvIHdlIHJldHVybiBkaXJlY3RseVxuICAgIGlmIChcbiAgICAgIHRoaXMuY29hY2hJdGVtRGV0YWlsc0VsZW1lbnRzW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF0gJiZcbiAgICAgIHRoaXMuY29hY2hJdGVtRGV0YWlsc0VsZW1lbnRzW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF0uaXNEcml2ZXJBcmVhXG4gICAgKSB7XG4gICAgICB0aGlzLl9zZXRGb2N1c1RvU2VsZWN0ZWRDb2FjaEdyaWQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBPbmx5IHdoZW4ga2V5Ym9hcmQgbmF2aWdhdGlvbiBpcyB1c2VkIGFuZCBjb2FjaGVzIGFyZSBzY3JvbGxlZCBieSBhdXRvIHNjcm9sbGluZyxcbiAgICAvLyB0aGVuIHdlIGNhbiBzZXQgdGhlIGZvY3VzIG9uIHRoZSBmaXJzdCBwbGFjZSBpbiB0aGUgY29hY2guXG4gICAgaWYgKHRoaXMuaXNLZXlib2FyZE5hdmlnYXRpb24gJiYgdGhpcy5pc0F1dG9TY3JvbGxpbmcpIHtcbiAgICAgIGNvbnN0IGNsb3Nlc3RQbGFjZSA9IHRoaXMuX2dldENsb3Nlc3RQbGFjZUJ5S2V5RGlyZWN0aW9uKCk7XG4gICAgICAvL0lmIGNsb3Nlc3RQbGFjZSBleGlzdCwgd2UgaGF2ZSB0byB1bmZvY3VzIHByZXZpb3VzIGZvY3VzZWQgcGxhY2VcbiAgICAgIGlmIChjbG9zZXN0UGxhY2UpIHtcbiAgICAgICAgdGhpcy51bmZvY3VzUGxhY2VFbGVtZW50KCk7XG4gICAgICAgIHRoaXMuZm9jdXNQbGFjZUVsZW1lbnQoY2xvc2VzdFBsYWNlKTtcbiAgICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IC0xO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgYSBjb2FjaCB3YXMgc2VsZWN0ZWQgd2l0aCBubyBwbGFjZXMsIHRoZW4gd2UgaGF2ZSB0byBmb2N1cyB0aGUgY29hY2hHcmlkXG4gICAgICAgIHRoaXMuX3NldEZvY3VzVG9TZWxlY3RlZENvYWNoR3JpZCgpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBJbiBjYXNlcyB3aGVyZSB0aGUgcHJlc2VsZWN0aW9uIGZ1bmN0aW9uIGlzIHRyaWdnZXJlZCBieSBub3JtYWwgY2xpY2tpbmcgb3IgdmlhIHNjcmVlbiByZWFkZXIgdmlhIHRhYixcbiAgICAvLyB3ZSBvbmx5IGZvY3VzIHRoZSB0YWJsZSB3aXRob3V0IGRpcmVjdGx5IGZvY3VzaW5nIHRoZSBwbGFjZS5cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMudW5mb2N1c1BsYWNlRWxlbWVudCgpO1xuXG4gICAgICB0aGlzLmlzQ29hY2hHcmlkRm9jdXNhYmxlID0gdHJ1ZTtcbiAgICAgIHRoaXMuX3NldEZvY3VzVG9TZWxlY3RlZENvYWNoR3JpZCgpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBzY3JvbGxUb1NlbGVjdGVkTmF2Q29hY2goc2VsZWN0ZWROYXZDb2FjaEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLl9pc1ZhbGlkQ29hY2hJbmRleChzZWxlY3RlZE5hdkNvYWNoSW5kZXgpICYmXG4gICAgICBzZWxlY3RlZE5hdkNvYWNoSW5kZXggIT09IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICkge1xuICAgICAgdGhpcy5ob3ZlcmVkQ29hY2hJbmRleCA9IHNlbGVjdGVkTmF2Q29hY2hJbmRleDtcbiAgICAgIHRoaXMuaXNBdXRvU2Nyb2xsaW5nID0gdHJ1ZTtcbiAgICAgIHRoaXMuaXNDb2FjaEdyaWRGb2N1c2FibGUgPSB0cnVlO1xuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4ID0gc2VsZWN0ZWROYXZDb2FjaEluZGV4O1xuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggPSB0aGlzLl9nZXRFeGlzdGluZ0NvYWNoRGVja0luZGV4KCk7XG4gICAgICB0aGlzLl9zZXRTY3JvbGxEaXJlY3Rpb25CeUNvYWNoSW5kZXgoKTtcblxuICAgICAgY29uc3Qgc2Nyb2xsVG9Db2FjaFBvc1ggPSB0aGlzLl9nZXRDb2FjaFNjcm9sbFBvc2l0aW9uWCgpO1xuICAgICAgY29uc3QgaXNTZWxlY3RlZENvYWNoSW5kZXhTY3JvbGxhYmxlID1cbiAgICAgICAgdGhpcy5zZWxlY3RlZENvYWNoSW5kZXggIT09IC0xIHx8IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA+IDA7XG5cbiAgICAgIC8vIENoZWNrcyB3aGV0aGVyIHRoZSBjdXJyZW50IHNjcm9sbCBwb3NpdGlvbiBhbGxvd3Mgc2Nyb2xsaW5nIHRvIHRoZSBuZXh0IHdhZ29uIG9yIG5vdFxuICAgICAgaWYgKGlzU2VsZWN0ZWRDb2FjaEluZGV4U2Nyb2xsYWJsZSAmJiB0aGlzLl9pc1Njcm9sbGFibGVUb1NlbGVjdGVkQ29hY2goKSkge1xuICAgICAgICB0aGlzLl9sYXN0U3RhcnRTY3JvbGxQb3MgPSB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxMZWZ0O1xuICAgICAgICB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxUbyh7XG4gICAgICAgICAgdG9wOiB0aGlzLmFsaWduVmVydGljYWwgPyBzY3JvbGxUb0NvYWNoUG9zWCA6IDAsXG4gICAgICAgICAgbGVmdDogdGhpcy5hbGlnblZlcnRpY2FsID8gMCA6IHNjcm9sbFRvQ29hY2hQb3NYLFxuICAgICAgICAgIGJlaGF2aW9yOiAnc21vb3RoJyxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnVwZGF0ZUN1cnJlbnRTZWxlY3RlZENvYWNoKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEF1dG9tYXRpYyBzY3JvbGxpbmcgdG8gdGhlIHNlbGVjdGVkIGNvYWNoIGluIHRoZSBtYWluIG5hdmlnYXRpb25cbiAgICAgIHRoaXMuX3Njcm9sbFRvU2VsZWN0ZWROYXZpZ2F0aW9uQnV0dG9uKHNlbGVjdGVkTmF2Q29hY2hJbmRleCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGZvY3VzUGxhY2VFbGVtZW50KHBsYWNlOiBQbGFjZSB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLnVuZm9jdXNQbGFjZUVsZW1lbnQoKTtcbiAgICBpZiAocGxhY2UpIHtcbiAgICAgIHRoaXMuY3VyclNlbGVjdGVkUGxhY2UgPSBwbGFjZTtcbiAgICAgIHRoaXMuX3NldEN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkKHBsYWNlKTtcblxuICAgICAgY29uc3Qgc2VsZWN0ZWRQbGFjZUVsZW1lbnQgPSB0aGlzLl9nZXRQbGFjZUh0bWxFbGVtZW50KCk7XG4gICAgICBpZiAoc2VsZWN0ZWRQbGFjZUVsZW1lbnQpIHtcbiAgICAgICAgc2VsZWN0ZWRQbGFjZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdrZXlmb2N1cycsICdmb2N1cycpO1xuXG4gICAgICAgIC8vVHJ5IHRvIHNjcm9sbCBmb2N1c2VkIHBsYWNlIGludG8gdGhlIHZpZXdwb3J0XG4gICAgICAgIGNvbnN0IGRlbGF5U2Nyb2xsSW5WaWV3cG9ydCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHBsYWNlSWQgPSB0aGlzLmdldFBsYWNlRWxlbWVudElkKFxuICAgICAgICAgICAgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXgsXG4gICAgICAgICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXgsXG4gICAgICAgICAgICBwbGFjZS5udW1iZXIsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLl9zY3JvbGxQbGFjZUludG9OZWFyZXN0Vmlld3BvcnQocGxhY2VJZCk7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KGRlbGF5U2Nyb2xsSW5WaWV3cG9ydCk7XG4gICAgICAgIH0sIDApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCB1bmZvY3VzUGxhY2VFbGVtZW50KCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbGVjdGVkUGxhY2VFbGVtZW50ID0gdGhpcy5fZ2V0UGxhY2VIdG1sRWxlbWVudCgpO1xuICAgIGlmIChzZWxlY3RlZFBsYWNlRWxlbWVudCkge1xuICAgICAgc2VsZWN0ZWRQbGFjZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdrZXlmb2N1cycsICd1bmZvY3VzJyk7XG4gICAgICB0aGlzLl9zZXRDdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZChudWxsKTtcbiAgICAgIHRoaXMuY3VyclNlbGVjdGVkUGxhY2UgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRDYWxjdWxhdGVkRGltZW5zaW9uKFxuICAgIGVsZW1lbnREaW1lbnNpb246IEVsZW1lbnREaW1lbnNpb24sXG4gICAgY29hY2hEaW1lbnNpb24/OiBFbGVtZW50RGltZW5zaW9uLFxuICAgIGlzT3JpZ2luSGVpZ2h0PzogYm9vbGVhbixcbiAgICBpc1N0cmV0Y2hIZWlnaHQ/OiBib29sZWFuLFxuICApOiBFbGVtZW50RGltZW5zaW9uIHtcbiAgICBpZiAoY29hY2hEaW1lbnNpb24gJiYgIWlzT3JpZ2luSGVpZ2h0KSB7XG4gICAgICAvLyBTaW5jZSB0aGUgaGVpZ2h0IG9mIHRoZSBjb2FjaCBoYXMgYmVlbiB2aXN1YWxseSBleHBhbmRlZCB0byBtYWludGFpbiBhIGRpc3RhbmNlIGJldHdlZW4gdGhlIGJvcmRlciBvZiB0aGUgY29hY2ggYW5kIHRoZSBwbGFjZXMsXG4gICAgICAvLyBzb21lIGdyYXBoaWNzIG11c3QgYWxzbyBiZSBhZGFwdGVkIHRvIHRoZSBoZWlnaHQsIHdoaWNoIGVuZCB3aXRoIHRoZSBib3JkZXJzIG9mIHRoZSBjb2FjaFxuICAgICAgZWxlbWVudERpbWVuc2lvbi5oICs9IHRoaXMuY29hY2hCb3JkZXJPZmZzZXQgKiAyO1xuICAgIH1cblxuICAgIGlmIChpc1N0cmV0Y2hIZWlnaHQpIHtcbiAgICAgIC8vIEluIHRoZSBjYXNlIG9mIGdyYXBoaWNzIGFyZSBhc3NpZ25lZCBkaXJlY3RseSBhdCB0aGUgYm9yZGVyIG9mIHRoZSBjb2FjaCxcbiAgICAgIC8vIHRoZXNlIGdyYXBoaWNzIG11c3QgYmUgZXhwYW5kZWQgaW4gaGVpZ2h0IGJ5IGEgY29hY2hCb3JkZXJPZmZzZXQgaW4gb3JkZXIgdG8gcmVhY2ggdGhlaXIgb3JpZ2luYWwgdmlzdWFsIHBvc2l0aW9uXG4gICAgICBlbGVtZW50RGltZW5zaW9uLmggKz0gdGhpcy5jb2FjaEJvcmRlck9mZnNldDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdzogdGhpcy5iYXNlR3JpZFNpemUgKiBlbGVtZW50RGltZW5zaW9uLncsXG4gICAgICBoOiB0aGlzLmJhc2VHcmlkU2l6ZSAqIGVsZW1lbnREaW1lbnNpb24uaCxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldENhbGN1bGF0ZWRQb3NpdGlvbihcbiAgICBlbGVtZW50UG9zaXRpb246IEVsZW1lbnRQb3NpdGlvbixcbiAgICBlbGVtZW50RGltZW5zaW9uPzogRWxlbWVudERpbWVuc2lvbixcbiAgICBjb2FjaERpbWVuc2lvbj86IEVsZW1lbnREaW1lbnNpb24sXG4gICAgaXNPcmlnaW5IZWlnaHQ/OiBib29sZWFuLFxuICApOiBFbGVtZW50UG9zaXRpb24ge1xuICAgIGlmIChjb2FjaERpbWVuc2lvbiAmJiBlbGVtZW50RGltZW5zaW9uKSB7XG4gICAgICBjb25zdCBlbmRQb3NIZWlnaHQgPSBpc09yaWdpbkhlaWdodFxuICAgICAgICA/IGNvYWNoRGltZW5zaW9uLmhcbiAgICAgICAgOiBjb2FjaERpbWVuc2lvbi5oICsgdGhpcy5jb2FjaEJvcmRlck9mZnNldDtcbiAgICAgIC8vIElmIHRoZSBvcmlnaW5hbCBlbGVtZW50IGlzIHBvc2l0aW9uZWQgYXQgdGhlIHRvcCBvciBib3R0b20gb2YgdGhlIGNvYWNoLCB3ZSBuZWVkIHRvIHJlY2FsY3VsYXRlIHRoZSBZIGNvb3JkaW5hdGUgd2l0aCB0aGUgYWRkaXRpb25hbCBib3JkZXIgcGFkZGluZ1xuICAgICAgaWYgKGVsZW1lbnRQb3NpdGlvbi55ID09PSAwKSB7XG4gICAgICAgIGVsZW1lbnRQb3NpdGlvbi55IC09IHRoaXMuY29hY2hCb3JkZXJPZmZzZXQ7XG4gICAgICB9IGVsc2UgaWYgKGVsZW1lbnRQb3NpdGlvbi55ICsgZWxlbWVudERpbWVuc2lvbi5oID09PSBlbmRQb3NIZWlnaHQpIHtcbiAgICAgICAgZWxlbWVudFBvc2l0aW9uLnkgKz0gdGhpcy5jb2FjaEJvcmRlck9mZnNldDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgeDogdGhpcy5iYXNlR3JpZFNpemUgKiBlbGVtZW50UG9zaXRpb24ueCxcbiAgICAgIHk6IHRoaXMuYmFzZUdyaWRTaXplICogZWxlbWVudFBvc2l0aW9uLnksXG4gICAgICB6OiBlbGVtZW50UG9zaXRpb24ueixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIGRldGVjdHMgaWYgYSAoZ3JhcGhpY2FsKSBlbGVtZW50IGlzIG9uIHRoZSBib3JkZXIgd2l0aCBpdHMgcG9zaXRpb24gKHVwcGVyIG9yIGxvd2VyIGJvcmRlcikuXG4gICAqIEBwYXJhbSBiYXNlRWxlbWVudFxuICAgKiBAcGFyYW0gY29hY2hEaW1lbnNpb25cbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcHJvdGVjdGVkIGlzRWxlbWVudERpcmVjdGx5T25Cb3JkZXIoXG4gICAgYmFzZUVsZW1lbnQ6IEJhc2VFbGVtZW50LFxuICAgIGNvYWNoRGltZW5zaW9uOiBFbGVtZW50RGltZW5zaW9uLFxuICApOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgYmFzZUVsZW1lbnQucG9zaXRpb24ueSA9PT0gMCB8fFxuICAgICAgYmFzZUVsZW1lbnQucG9zaXRpb24ueSArIGJhc2VFbGVtZW50LmRpbWVuc2lvbi5oID09PSBjb2FjaERpbWVuc2lvbi5oXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3VudHMgYWxsIGF2YWlsYWJsZSBzZWF0cyB0b2dldGhlciBkZXBlbmRpbmcgb24gdGhlIHNlYXQgdHlwZVxuICAgKlxuICAgKiBAcGFyYW0gcGxhY2VzXG4gICAqIEByZXR1cm5zIEFuIE9iamVjdCB3aXRoIGNvdW50IG9mIGZyZWUgc2VhdHMgYW5kIGZyZWUgYmljeWNsZSBwbGFjZXNcbiAgICovXG4gIHByb3RlY3RlZCBnZXRBdmFpbGFibGVGcmVlUGxhY2VzTnVtRnJvbUNvYWNoKFxuICAgIHBsYWNlczogUGxhY2VbXSB8IHVuZGVmaW5lZCxcbiAgKTogQ29hY2hOdW1iZXJPZkZyZWVQbGFjZXMge1xuICAgIGNvbnN0IGFjY3VtdWxhdG9yOiBDb2FjaE51bWJlck9mRnJlZVBsYWNlcyA9IHsgc2VhdHM6IDAsIGJpY3ljbGVzOiAwIH07XG4gICAgY29uc3QgZnJlZVBsYWNlcyA9IHBsYWNlcz8ucmVkdWNlKChhY2N1bXVsYXRvciwgY3VyclBsYWNlOiBQbGFjZSkgPT4ge1xuICAgICAgaWYgKGN1cnJQbGFjZS5zdGF0ZSAhPT0gJ0ZSRUUnKSB7XG4gICAgICAgIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgICAgIH1cbiAgICAgIC8vIENvdW50IHVwIGRlcGVuZGluZyBvbiBzZWF0IHR5cGVcbiAgICAgIGlmIChjdXJyUGxhY2UudHlwZSA9PT0gJ1NFQVQnKSB7XG4gICAgICAgIGFjY3VtdWxhdG9yLnNlYXRzKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY2N1bXVsYXRvci5iaWN5Y2xlcysrO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAgIH0sIGFjY3VtdWxhdG9yKTtcbiAgICByZXR1cm4gZnJlZVBsYWNlcyA/IGZyZWVQbGFjZXMgOiBhY2N1bXVsYXRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdCB0aGUgZW5kIG9mIGEgc2Nyb2xsIEV2ZW50IGZyb20gdGhlIGNvYWNoIHNjcm9sbGFibGUgYXJlYSxcbiAgICogdGhlIHJlYWNoZWQgY29hY2ggaXMgbWFya2VkIGFzIHNlbGVjdGVkXG4gICAqL1xuICBwcml2YXRlIF9oYW5kbGVDb2FjaEFyZWFTY3JvbGxlbmRFdmVudCgpOiB2b2lkIHtcbiAgICBjb25zdCBmaW5kU2Nyb2xsQ29hY2hJbmRleCA9IHRoaXMuaXNBdXRvU2Nyb2xsaW5nXG4gICAgICA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICAgOiB0aGlzLl9nZXRDb2FjaEluZGV4QnlTY3JvbGxUcmlnZ2VyUG9zaXRpb24oKTtcblxuICAgIC8vIFRJTU8tNDM3MDVcbiAgICAvLyBJZiBhIHBsYWNlIHdhcyBzZWxlY3RlZCBieSBtb3VzZSBjbGljayAocHJldmVudENvYWNoU2Nyb2xsQnlQbGFjZUNsaWNrKSBiZWZvcmUgdHJpZ2dlcmluZyB0aGlzIHNjcm9sbGVuZCBtZXRob2QsXG4gICAgLy8gdGhlbiB0aGlzIHNjcm9sbGluZyB3YXMgdHJpZ2dlcmVkIGJ5IHRoZSBtZXRob2QgX3Njcm9sbFBsYWNlSW50b05lYXJlc3RWaWV3cG9ydCwgYW5kIGl0IGlzIG9ubHkgYSBwbGFjZSBhZGp1c3RtZW50IHNjcm9sbCAoc2Nyb2xsSW50b1ZpZXcpLFxuICAgIC8vIHdoZXJlIGEgbGVzcyB2aXNpYmxlIHBsYWNlIGhhcyBiZWVuIHNjcm9sbGVkIGludG8gdGhlIHZpZXdwb3J0LiBJbiBjYXNlIG9mIGEgcGxhY2UgYWRqdXN0bWVudCBieSBjbGljaywgd2UgY2FuIHJldHVybiBoZXJlLlxuICAgIGlmICh0aGlzLnByZXZlbnRDb2FjaFNjcm9sbEJ5UGxhY2VDbGljaykge1xuICAgICAgLy8gQ2hlY2sgd2hldGhlciB0aGUgZW5kc2Nyb2xsaW5nIGlzIGp1c3QgYSBwbGFjZSBhZGp1c3RtZW50IHNjcm9sbGluZyAocGxhY2UgaGFzIDIgZ3JpZCBzaXplIHVuaXRzKVxuICAgICAgY29uc3QgaXNDb2FjaFNjcm9sbGluZyA9XG4gICAgICAgIE1hdGguYWJzKHRoaXMuX2xhc3RTdGFydFNjcm9sbFBvcyAtIHRoaXMuY29hY2hTY3JvbGxBcmVhLnNjcm9sbExlZnQpID5cbiAgICAgICAgdGhpcy5iYXNlR3JpZFNpemUgKiAyO1xuICAgICAgaWYgKGlzQ29hY2hTY3JvbGxpbmcpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZENvYWNoSW5kZXggPSBmaW5kU2Nyb2xsQ29hY2hJbmRleDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5wcmV2ZW50Q29hY2hTY3JvbGxCeVBsYWNlQ2xpY2sgPSBmYWxzZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9sYXN0U3RhcnRTY3JvbGxQb3MgPSB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxMZWZ0O1xuXG4gICAgLy8gQWZ0ZXIgY29hY2ggc2Nyb2xsZW5kIGV2ZW50IHdlIGNhbiByZXNldCB0aGUgaG92ZXJlZCBjb2FjaCBpbmRleFxuICAgIHRoaXMuaG92ZXJlZENvYWNoSW5kZXggPSAtMTtcblxuICAgIC8vIEluIGNhc2UgdGhlIHVzZXIgdXNlcyB0aGUgc2Nyb2xsYmFyIHdpdGhvdXQgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgc2VhdCByZXNlcnZhdGlvbixcbiAgICAvLyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIGluZGV4IGlzIC0xLCBhbmQgd2UgaGF2ZSB0byBzZXQgdGhpcyB2YWx1ZSB3aXRoIGZpbmRTY3JvbGxDb2FjaEluZGV4LlxuICAgIGlmICh0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPT09IC0xKSB7XG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPSBmaW5kU2Nyb2xsQ29hY2hJbmRleDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5faXNTY3JvbGxhYmxlVG9TZWxlY3RlZENvYWNoKCkpIHtcbiAgICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9IGZpbmRTY3JvbGxDb2FjaEluZGV4O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPVxuICAgICAgICBmaW5kU2Nyb2xsQ29hY2hJbmRleCA8IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICAgICAgID8gdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XG4gICAgICAgICAgOiBmaW5kU2Nyb2xsQ29hY2hJbmRleDtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNBdXRvU2Nyb2xsaW5nKSB7XG4gICAgICAvL1doZW4gdXNlciBpcyBzY3JvbGxpbmcgdmlhIHNjcm9sbGJhciwgaXQgYXV0b21hdGljYWxseSBzY3JvbGxzIHRvIHRoZSBmb2N1c2VkIGNvYWNoIGluIHRoZSBtYWluIG5hdmlnYXRpb25cbiAgICAgIHRoaXMuX3Njcm9sbFRvU2VsZWN0ZWROYXZpZ2F0aW9uQnV0dG9uKGZpbmRTY3JvbGxDb2FjaEluZGV4KTtcbiAgICB9XG4gICAgdGhpcy5wcmV2ZW50Q29hY2hTY3JvbGxCeVBsYWNlQ2xpY2sgPSBmYWxzZTtcbiAgICB0aGlzLnVwZGF0ZUN1cnJlbnRTZWxlY3RlZENvYWNoKCk7XG5cbiAgICBpZiAoIXRoaXMuaGFzTmF2aWdhdGlvbikge1xuICAgICAgdGhpcy5wcmVzZWxlY3RQbGFjZUluQ29hY2goKTtcbiAgICAgIHRoaXMuaXNBdXRvU2Nyb2xsaW5nID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGFuIGF1dG9tYXRpYyBtYWluIG5hdmlnYXRpb24gc2Nyb2xsIHRvIHRoZSBzcGVjaWZpZWQgc2VsZWN0ZWROYXZDb2FjaEluZGV4LlxuICAgKiBDYWxjdWxhdGVzIHRoZSBjZW50cmFsIHNjcm9sbCBvZmZzZXQgb2YgdGhlIG5hdiBjb2FjaCB0byBiZSBzZWxlY3RlZC5cbiAgICogQHBhcmFtIHNlbGVjdGVkTmF2Q29hY2hJbmRleFxuICAgKi9cbiAgcHJpdmF0ZSBfc2Nyb2xsVG9TZWxlY3RlZE5hdmlnYXRpb25CdXR0b24oc2VsZWN0ZWROYXZDb2FjaEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvL1RpbWUgZGVsYXkgdG8gbm90IGludGVyZmVyZSB3aXRoIG90aGVyIGV4ZWN1dGluZyBjYWxsaW5nIHNjcm9sbFRvIGZ1bmN0aW9ucyAoY29hY2hlcyBzY3JvbGxpbmcpXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5oYXNOYXZpZ2F0aW9uICYmIHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEpIHtcbiAgICAgICAgY29uc3QgbmF2aWdhdGlvbkFyZWFDZW50ZXJlZFBvc1ggPSB0aGlzLnNjcm9sbE5hdmlnYXRpb25BcmVhRGltIC8gMjtcbiAgICAgICAgY29uc3Qgc2Nyb2xsQnV0dG9uT2Zmc2V0WCA9IHNlbGVjdGVkTmF2Q29hY2hJbmRleCAqIHRoaXMuY29hY2hOYXZCdXR0b25EaW07XG4gICAgICAgIGNvbnN0IHNjcm9sbE9mZnNldFggPVxuICAgICAgICAgIHNjcm9sbEJ1dHRvbk9mZnNldFggLSBuYXZpZ2F0aW9uQXJlYUNlbnRlcmVkUG9zWCArIHRoaXMuY29hY2hOYXZCdXR0b25EaW07XG4gICAgICAgIHRoaXMubmF2aWdhdGlvblNjcm9sbEFyZWEuc2Nyb2xsVG8oe1xuICAgICAgICAgIHRvcDogdGhpcy5hbGlnblZlcnRpY2FsID8gc2Nyb2xsT2Zmc2V0WCA6IDAsXG4gICAgICAgICAgbGVmdDogdGhpcy5hbGlnblZlcnRpY2FsID8gMCA6IHNjcm9sbE9mZnNldFgsXG4gICAgICAgICAgYmVoYXZpb3I6ICdzbW9vdGgnLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LCAxMCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgbmV3IFNjcm9sbERpcmVjdGlvbiBieSB0aGUgbmV3IGdpdmVuIHRhcmdldCBjb2FjaCBpbmRleC5cbiAgICovXG4gIHByaXZhdGUgX3NldFNjcm9sbERpcmVjdGlvbkJ5Q29hY2hJbmRleCgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJTY3JvbGxEaXJlY3Rpb24gPVxuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4ID4gdGhpcy5zZWxlY3RlZENvYWNoSW5kZXhcbiAgICAgICAgPyBTY3JvbGxEaXJlY3Rpb24ucmlnaHRcbiAgICAgICAgOiBTY3JvbGxEaXJlY3Rpb24ubGVmdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzY3JvbGwgc3RhcnQgb3IgZW5kIHBvc2l0aW9uIFggZnJvbSB0aGUgc2VsZWN0ZWQgY29hY2guXG4gICAqIEluIGNhc2UgdGhlIHVzZXIgaXMgY3VycmVudGx5IG5hdmlnYXRpbmcgdGhyb3VnaCBwbGFjZXMgYnkga2V5Ym9hcmQgYW5kIGdvZXMgdG8gcHJldmlvdXMgY29hY2gsXG4gICAqIHRoZW4gd2UgcmV0dXJuIHRoZSBlbmQgcG9zaXRpb24gb2YgdGhlIGNvYWNoIHRvIGdldCB0aGUgY2xvc2VzdCBzY3JvbGwgcG9zaXRpb24gb2YgdGhlIG5leHQgZm9jdXMgcGxhY2UuXG4gICAqIEByZXR1cm5zIG51bWJlclxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0Q29hY2hTY3JvbGxQb3NpdGlvblgoKTogbnVtYmVyIHtcbiAgICBjb25zdCBjb2FjaFRyaWdnZXJQb2ludCA9IHRoaXMudHJpZ2dlckNvYWNoUG9zaXRpb25zQ29sbGVjdGlvblt0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXhdO1xuICAgIGNvbnN0IGlzRm9jdXNQbGFjZUZyb21QcmV2aW91c0NvYWNoUG9zaXRpb24gPVxuICAgICAgdGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbiAmJlxuICAgICAgdGhpcy5jdXJyU2Nyb2xsRGlyZWN0aW9uID09PSBTY3JvbGxEaXJlY3Rpb24ubGVmdCAmJlxuICAgICAgY29hY2hUcmlnZ2VyUG9pbnQud2lkdGggPiB0aGlzLnNjcm9sbENvYWNoZXNBcmVhV2lkdGg7XG5cbiAgICByZXR1cm4gaXNGb2N1c1BsYWNlRnJvbVByZXZpb3VzQ29hY2hQb3NpdGlvblxuICAgICAgPyBjb2FjaFRyaWdnZXJQb2ludC5lbmQgLSB0aGlzLnNjcm9sbENvYWNoZXNBcmVhV2lkdGhcbiAgICAgIDogY29hY2hUcmlnZ2VyUG9pbnQuc3RhcnQ7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZm9jdXMgb24gdGhlIEhUTUwgdGFibGUgKGdyaWQpIGNhcHRpb24gZWxlbWVudCBzbyB0aGF0IHRoZSBoZWFkaW5nIGlzIHJlYWQgb3V0IHdoZW4gdXNpbmcgYSBTY3JlZW5SZWFkZXIuXG4gICAqL1xuICBwcml2YXRlIF9zZXRGb2N1c1RvU2VsZWN0ZWRDb2FjaEdyaWQoKTogdm9pZCB7XG4gICAgLy8gV2hlbiB0aGUgdXNlciBwZXJmb3JtcyBhbiBhY3Rpb24gdGhhdCBhZmZlY3RzIHRoZSBjb2FjaCBuYXZpZ2F0aW9uLCB0aGVuIHRoZSBuYXZpZ2F0ZWQgdGFibGUgaXMgZm9jdXNhYmxlLlxuICAgIGlmICh0aGlzLmlzQ29hY2hHcmlkRm9jdXNhYmxlICYmIHRoaXMuaGFzU2VhdFJlc2VydmF0aW9uTmF0aXZlRm9jdXMpIHtcbiAgICAgIHRoaXMuaXNDb2FjaEdyaWRGb2N1c2FibGUgPSBmYWxzZTtcbiAgICAgIGNvbnN0IGNvYWNoVGFibGVDYXB0aW9uRWxlbWVudCA9IHRoaXMuc2hhZG93Um9vdD8ucXVlcnlTZWxlY3RvcihcbiAgICAgICAgJyNzYmItc3ItY29hY2gtY2FwdGlvbi0nICsgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4LFxuICAgICAgKSBhcyBIVE1MVGFibGVDYXB0aW9uRWxlbWVudDtcbiAgICAgIGlmIChjb2FjaFRhYmxlQ2FwdGlvbkVsZW1lbnQpIHtcbiAgICAgICAgY29hY2hUYWJsZUNhcHRpb25FbGVtZW50LmZvY3VzKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgd2hldGhlciB0aGUgY3VycmVudCBzY3JvbGxlZCBwb3NpdGlvbiBjYW4gYmUgdXNlZCB0byBzY3JvbGwgdG8gdGhlIHNlbGVjdGVkIHdhZ29uXG4gICAqIEByZXR1cm5zIGJvb2xlYW5cbiAgICovXG4gIHByaXZhdGUgX2lzU2Nyb2xsYWJsZVRvU2VsZWN0ZWRDb2FjaCgpOiBib29sZWFuIHtcbiAgICBjb25zdCBjdXJyU2Nyb2xsUG9zWCA9IHRoaXMuYWxpZ25WZXJ0aWNhbFxuICAgICAgPyB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxUb3BcbiAgICAgIDogdGhpcy5jb2FjaFNjcm9sbEFyZWEuc2Nyb2xsTGVmdDtcbiAgICBjb25zdCBjb2FjaFNjcm9sbFdpbmRvd1dpZHRoID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICA/IHRoaXMuY29hY2hTY3JvbGxBcmVhLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodFxuICAgICAgOiB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aDtcbiAgICBjb25zdCBtYXhTY3JvbGxXaWR0aEFyZWEgPSB0aGlzLm1heENhbGNDb2FjaGVzV2lkdGggLSBjb2FjaFNjcm9sbFdpbmRvd1dpZHRoO1xuICAgIGNvbnN0IGN1cnJDb2FjaFRyaWdnZXIgPSB0aGlzLnRyaWdnZXJDb2FjaFBvc2l0aW9uc0NvbGxlY3Rpb25bdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XTtcbiAgICBjb25zdCBpc1Njcm9sbFBvc1NhbWVUb0N1cnJDb2FjaFBvcyA9XG4gICAgICBjdXJyU2Nyb2xsUG9zWCA9PT0gdGhpcy50cmlnZ2VyQ29hY2hQb3NpdGlvbnNDb2xsZWN0aW9uW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF0uc3RhcnQ7XG5cbiAgICByZXR1cm4gKFxuICAgICAgKGN1cnJTY3JvbGxQb3NYIDwgbWF4U2Nyb2xsV2lkdGhBcmVhIHx8IGN1cnJTY3JvbGxQb3NYID4gY3VyckNvYWNoVHJpZ2dlci5zdGFydCkgJiZcbiAgICAgICFpc1Njcm9sbFBvc1NhbWVUb0N1cnJDb2FjaFBvc1xuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29hY2ggaW5kZXggd2hpY2ggaXMgY3VycmVudGx5IHZpc2libGUgaW4gdGhlIHNjcm9sbCBhcmVhXG4gICAqIEByZXR1cm5zIG51bWJlclxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0Q29hY2hJbmRleEJ5U2Nyb2xsVHJpZ2dlclBvc2l0aW9uKCk6IG51bWJlciB7XG4gICAgY29uc3Qgc2Nyb2xsUG9zID0gdGhpcy5hbGlnblZlcnRpY2FsXG4gICAgICA/IHRoaXMuY29hY2hTY3JvbGxBcmVhLnNjcm9sbFRvcFxuICAgICAgOiB0aGlzLmNvYWNoU2Nyb2xsQXJlYS5zY3JvbGxMZWZ0O1xuICAgIGNvbnN0IHNjcm9sbE9mZnNldFggPSBzY3JvbGxQb3MgKyB0aGlzLnNjcm9sbENvYWNoZXNBcmVhV2lkdGggLyAyO1xuICAgIHJldHVybiB0aGlzLnRyaWdnZXJDb2FjaFBvc2l0aW9uc0NvbGxlY3Rpb24uZmluZEluZGV4KFxuICAgICAgKGNvYWNoVHJpZ2dlcikgPT4gc2Nyb2xsT2Zmc2V0WCA+PSBjb2FjaFRyaWdnZXIuc3RhcnQgJiYgc2Nyb2xsT2Zmc2V0WCA8PSBjb2FjaFRyaWdnZXIuZW5kLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBmaXJzdCBwbGFjZSBvZiBjdXJyZW50IHNlbGVjdGVkIGNvYWNoIGJ5IHRhYmxlIGNlbGwgY29vcmRpbmF0ZSAwLTAgaWQuXG4gICAqIEByZXR1cm5zIFBsYWNlIG9yIG51bGxcbiAgICovXG4gIHByaXZhdGUgX2dldEZpcnN0UGxhY2VJblNlbGVjdGVkQ29hY2goKTogUGxhY2UgfCBudWxsIHtcbiAgICBsZXQgZmlyc3RQbGFjZTogUGxhY2UgfCBudWxsID0gbnVsbDtcbiAgICBjb25zdCBjb2FjaCA9XG4gICAgICB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdLmNvYWNoSXRlbXNbdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XTtcbiAgICBjb25zdCBmaXJzdENlbGxJZCA9XG4gICAgICAnY2VsbC0nICsgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggKyAnLScgKyB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggKyAnLTAtMCc7XG4gICAgY29uc3QgcGxhY2VOdW1iZXIgPVxuICAgICAgdGhpcy5zaGFkb3dSb290XG4gICAgICAgID8ucXVlcnlTZWxlY3RvcjxIVE1MVGFibGVDZWxsRWxlbWVudD4oJyMnICsgZmlyc3RDZWxsSWQpXG4gICAgICAgID8ucXVlcnlTZWxlY3RvcjxTYmJTZWF0UmVzZXJ2YXRpb25QbGFjZUNvbnRyb2xFbGVtZW50Pignc2JiLXNlYXQtcmVzZXJ2YXRpb24tcGxhY2UtY29udHJvbCcpXG4gICAgICAgID8uZ2V0QXR0cmlidXRlKCd0ZXh0JykgfHwgbnVsbDtcblxuICAgIGlmIChjb2FjaCAmJiBwbGFjZU51bWJlcikge1xuICAgICAgZmlyc3RQbGFjZSA9IGNvYWNoLnBsYWNlcz8uZmluZCgocGxhY2UpID0+IHBsYWNlLm51bWJlciA9PT0gcGxhY2VOdW1iZXIpIHx8IG51bGw7XG4gICAgfVxuICAgIHJldHVybiBmaXJzdFBsYWNlO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0U3dpdGNoZWRDb2FjaERlY2tJbmRleEJ5S2V5TmF2aWdhdGlvbihcbiAgICBwcmVzc2VkS2V5OiBzdHJpbmcsXG4gICAgY29hY2g6IENvYWNoSXRlbSxcbiAgKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgaWYgKFxuICAgICAgIXRoaXMuY3VyclNlbGVjdGVkUGxhY2UgfHxcbiAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93UmlnaHQgfHxcbiAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdFxuICAgIClcbiAgICAgIHJldHVybiBudWxsO1xuXG4gICAgLy9DSEVDSyBERUNLIFNXSVRDSCBET1dOXG4gICAgaWYgKFxuICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dEb3duICYmXG4gICAgICB0aGlzLmN1cnJTZWxlY3RlZFBsYWNlLnBvc2l0aW9uLnkgKyAyID09PSBjb2FjaC5kaW1lbnNpb24uaCAmJlxuICAgICAgISF0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggKyAxXVxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4ICsgMTtcbiAgICB9XG4gICAgLy9DSEVDSyBERUNLIFNXSVRDSCBVUFxuICAgIGVsc2UgaWYgKFxuICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dVcCAmJlxuICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZS5wb3NpdGlvbi55ID09PSAwICYmXG4gICAgICAhIXRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCAtIDFdXG4gICAgKSB7XG4gICAgICByZXR1cm4gdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggLSAxO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUbyBnZXQgdGhlIGNvcnJlY3QgY2xvc2VzdCBwbGFjZSBvZiBjdXJyZW50IHByZXNzZWQga2V5IGFuZCB0aGUgY3VycmVudCBzZWxlY3RlZCBwbGFjZSxcbiAgICogd2UgaGF2ZSB0byBpbnZlc3RpZ2F0ZSB0aGUgY29vcmRpbmF0ZXMgb2YgZWFjaCBwbGFjZSB0byBmaW5kIHRoZSBjbG9zZXN0IHBsYWNlIG9mIHRoZSBjdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZC5cbiAgICogQHBhcmFtIHByZXNzZWRLZXlcbiAgICogQHJldHVybnMgUGxhY2Ugb3IgbnVsbFxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0Q2xvc2VzdFBsYWNlQnlLZXlEaXJlY3Rpb24ocHJlc3NlZEtleT86IHN0cmluZyk6IFBsYWNlIHwgbnVsbCB7XG4gICAgY29uc3QgY29hY2ggPVxuICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zW3RoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4XS5jb2FjaEl0ZW1zW3RoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleF07XG4gICAgbGV0IGNsb3Nlc3RQbGFjZSA9IG51bGw7XG4gICAgbGV0IGNvYWNoUGxhY2VzID0gY29hY2gucGxhY2VzO1xuICAgIGxldCBzd2l0Y2hlZENvYWNoRGVja0luZGV4ID0gbnVsbDtcblxuICAgIGlmIChjb2FjaFBsYWNlcykge1xuICAgICAgLy8gSWYgbm8gcGxhY2Ugc2V0LCB0aGVuIHdlIHVzZSBpbml0aWFsIHRoZSBsZWZ0LXRvcCBwbGFjZSBvbiB0aGUgY29hY2hcbiAgICAgIGlmICghdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0Rmlyc3RQbGFjZUluU2VsZWN0ZWRDb2FjaCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuY3VyclNlbGVjdGVkUGxhY2UpIHtcbiAgICAgICAgICBjb25zdCBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uID0geyAuLi50aGlzLmN1cnJTZWxlY3RlZFBsYWNlLnBvc2l0aW9uIH07XG5cbiAgICAgICAgICBpZiAocHJlc3NlZEtleSkge1xuICAgICAgICAgICAgLy8gQ2hlY2sgd2hldGhlciB0aGUga2V5Ym9hcmQgbmF2aWdhdGlvbiBpcyB1c2VkIHRvIHN3aXRjaCB0byBhbm90aGVyIGNvYWNoIGRlY2sgKFVwIC0+IERvd24gfCBEb3duIC0+IFVwKS5cbiAgICAgICAgICAgIC8vIEluIHRoaXMgY2FzZSwgd2UgdGFrZSB0aGUgY29hY2ggcGxhY2VzIHdlIGhhdmUgdG8gY2hlY2tlZCBmcm9tIHRoZSB0YXJnZXQgZGVjayBub3cuXG4gICAgICAgICAgICBzd2l0Y2hlZENvYWNoRGVja0luZGV4ID0gdGhpcy5fZ2V0U3dpdGNoZWRDb2FjaERlY2tJbmRleEJ5S2V5TmF2aWdhdGlvbihcbiAgICAgICAgICAgICAgcHJlc3NlZEtleSxcbiAgICAgICAgICAgICAgY29hY2gsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKHN3aXRjaGVkQ29hY2hEZWNrSW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgLy8gQXNzaWduIGNoZWNrIHBsYWNlcyBmcm9tIHRoZSB0YXJnZXQgc3dpdGNoIGRlY2tcbiAgICAgICAgICAgICAgY29hY2hQbGFjZXMgPVxuICAgICAgICAgICAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uc1tzd2l0Y2hlZENvYWNoRGVja0luZGV4XS5jb2FjaEl0ZW1zW1xuICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4XG4gICAgICAgICAgICAgICAgXS5wbGFjZXMgfHwgW107XG4gICAgICAgICAgICAgIC8vIFdlIGhhdmUgdG8gdXBkYXRlIHkgY29vcmRpbmF0ZVxuICAgICAgICAgICAgICBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgPVxuICAgICAgICAgICAgICAgIHN3aXRjaGVkQ29hY2hEZWNrSW5kZXggPCB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCA/IGNvYWNoLmRpbWVuc2lvbi5oIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZm9yIChjb25zdCBwbGFjZSBvZiBjb2FjaFBsYWNlcykge1xuICAgICAgICAgICAgLy8gSWYgbm8ga2V5IHByZXNzZWQsIHRoZW4gd2UgdHJ5IHRvIGZpbmQgdGhlIHBsYWNlIG9mIHRoZSBjdXJyZW50IGN1cnJTY3JvbGxEaXJlY3Rpb25cbiAgICAgICAgICAgIGlmICghcHJlc3NlZEtleSkge1xuICAgICAgICAgICAgICAvLyBGaW5kIHBsYWNlIGZyb20gdGhlIGxlZnQgc2lkZSBvZiBjb2FjaCBieSB5IGNvb3JkaW5hdGUuIEN1cnJlbnQgY3VyclNjcm9sbERpcmVjdGlvbiBpcyBSSUdIVFxuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyU2Nyb2xsRGlyZWN0aW9uID09PSBTY3JvbGxEaXJlY3Rpb24ucmlnaHQgJiZcbiAgICAgICAgICAgICAgICBwbGFjZS5wb3NpdGlvbi55ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgJiZcbiAgICAgICAgICAgICAgICAoIWNsb3Nlc3RQbGFjZSB8fCBwbGFjZS5wb3NpdGlvbi54IDwgY2xvc2VzdFBsYWNlLnBvc2l0aW9uLngpXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGNsb3Nlc3RQbGFjZSA9IHBsYWNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vRmluZCBwbGFjZSBmcm9tIHRoZSByaWdodCBzaWRlIG9mIGNvYWNoIGJ5IHkgY29vcmRpbmF0ZS4gQ3VycmVudCBjdXJyU2Nyb2xsRGlyZWN0aW9uIGlzIExFRlRcbiAgICAgICAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyU2Nyb2xsRGlyZWN0aW9uID09PSBTY3JvbGxEaXJlY3Rpb24ubGVmdCAmJlxuICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnkgPT09IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueSAmJlxuICAgICAgICAgICAgICAgICghY2xvc2VzdFBsYWNlIHx8IHBsYWNlLnBvc2l0aW9uLnggPiBjbG9zZXN0UGxhY2UucG9zaXRpb24ueClcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgY2xvc2VzdFBsYWNlID0gcGxhY2U7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGlmIChwbGFjZS5udW1iZXIgIT09IHRoaXMuY3VyclNlbGVjdGVkUGxhY2U/Lm51bWJlcikge1xuICAgICAgICAgICAgICAgIC8vS2V5IFtSaWdodF0gbmF2aWdhdGlvbiwgd2UgY2hlY2sgdGhlIHBsYWNlIGNvb3JkaW5hdGVzIG9mIHRoZSB4LWF4aXMgdG8gZ2V0IHRoZSBzbWFsbGVzdCBsYXJnZXIgeCBwbGFjZSBjb29yZGluYXRlIG9mIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcGxhY2VcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1JpZ2h0ICYmXG4gICAgICAgICAgICAgICAgICAocGxhY2UucG9zaXRpb24ueSA9PT0gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi55IHx8XG4gICAgICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnkgPT09IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueSAtIDEpICYmXG4gICAgICAgICAgICAgICAgICBwbGFjZS5wb3NpdGlvbi54ID4gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi54ICYmXG4gICAgICAgICAgICAgICAgICAoIWNsb3Nlc3RQbGFjZSB8fCBwbGFjZS5wb3NpdGlvbi54IDwgY2xvc2VzdFBsYWNlLnBvc2l0aW9uLngpXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICBjbG9zZXN0UGxhY2UgPSBwbGFjZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy9LZXkgW0Rvd25dIG5hdmlnYXRpb24sIHdlIGNoZWNrIHRoZSBwbGFjZSBjb29yZGluYXRlcyBvZiB0aGUgeS1heGlzIHRvIGdldCB0aGUgc21hbGxlc3QgbGFyZ2VyIHkgcGxhY2UgY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHBsYWNlXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd0Rvd24gJiZcbiAgICAgICAgICAgICAgICAgIChwbGFjZS5wb3NpdGlvbi54ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnggfHxcbiAgICAgICAgICAgICAgICAgICAgcGxhY2UucG9zaXRpb24ueCA9PT0gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi54ICsgMSkgJiZcbiAgICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnkgPiBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgJiZcbiAgICAgICAgICAgICAgICAgICghY2xvc2VzdFBsYWNlIHx8IHBsYWNlLnBvc2l0aW9uLnkgPCBjbG9zZXN0UGxhY2UucG9zaXRpb24ueSlcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIGNsb3Nlc3RQbGFjZSA9IHBsYWNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvL0tleSBbTGVmdF0gbmF2aWdhdGlvbiwgd2UgY2hlY2sgdGhlIHBsYWNlIGNvb3JkaW5hdGVzIG9mIHRoZSB4LWF4aXMgdG8gZ2V0IHRoZSBncmVhdGVzdCBzbWFsbGVyIHggcGxhY2UgY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHBsYWNlXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd0xlZnQgJiZcbiAgICAgICAgICAgICAgICAgIChwbGFjZS5wb3NpdGlvbi55ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnkgfHxcbiAgICAgICAgICAgICAgICAgICAgcGxhY2UucG9zaXRpb24ueSA9PT0gY3VyclNlbGVjdGVkUGxhY2VQb3NpdGlvbi55ICsgMSkgJiZcbiAgICAgICAgICAgICAgICAgIHBsYWNlLnBvc2l0aW9uLnggPCBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnggJiZcbiAgICAgICAgICAgICAgICAgICghY2xvc2VzdFBsYWNlIHx8IHBsYWNlLnBvc2l0aW9uLnggPiBjbG9zZXN0UGxhY2UucG9zaXRpb24ueClcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgIGNsb3Nlc3RQbGFjZSA9IHBsYWNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvL0tleSBbVXBdIG5hdmlnYXRpb24sIHdlIGNoZWNrIHRoZSBwbGFjZSBjb29yZGluYXRlcyBvZiB0aGUgeS1heGlzIHRvIGdldCB0aGUgZ3JlYXRlc3Qgc21hbGxlciB5IHBsYWNlIGNvb3JkaW5hdGUgb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBwbGFjZVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKFxuICAgICAgICAgICAgICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dVcCAmJlxuICAgICAgICAgICAgICAgICAgKHBsYWNlLnBvc2l0aW9uLnggPT09IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueCB8fFxuICAgICAgICAgICAgICAgICAgICBwbGFjZS5wb3NpdGlvbi54ID09PSBjdXJyU2VsZWN0ZWRQbGFjZVBvc2l0aW9uLnggLSAxKSAmJlxuICAgICAgICAgICAgICAgICAgcGxhY2UucG9zaXRpb24ueSA8IGN1cnJTZWxlY3RlZFBsYWNlUG9zaXRpb24ueSAmJlxuICAgICAgICAgICAgICAgICAgKCFjbG9zZXN0UGxhY2UgfHwgcGxhY2UucG9zaXRpb24ueSA+IGNsb3Nlc3RQbGFjZS5wb3NpdGlvbi55KVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgY2xvc2VzdFBsYWNlID0gcGxhY2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gSWYgYSBwbGFjZSBoYXMgYmVlbiBmb3VuZCBpbiB0aGUgY2hhbmdpbmcgc3dpdGNoIGNvYWNoLFxuICAgICAgICAgIC8vIHdlIGNhbiB1cGRhdGUgdGhlIGN1cnJTZWxlY3RlZERlY2tJbmRleFxuICAgICAgICAgIGlmIChzd2l0Y2hlZENvYWNoRGVja0luZGV4ICE9PSBudWxsICYmIGNsb3Nlc3RQbGFjZSkge1xuICAgICAgICAgICAgdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXggPSBzd2l0Y2hlZENvYWNoRGVja0luZGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY2xvc2VzdFBsYWNlO1xuICB9XG5cbiAgLy8gSGFuZGxpbmcgZm9yIFRhYiBuYXZpZ2F0aW9uIGlmIGEgcGxhY2UgaXMgc2VsZWN0ZWQgaW5zaWRlIHRoZSBjb2FjaC5cbiAgLy8gVGhpcyBjb250cm9scyB0aGUgZm9jdXNlZCBjb2FjaCBmcm9tIHRoZSBjdXJyZW50IHNlbGVjdGVkIGNvYWNoLlxuICBwcml2YXRlIF9uYXZpZ2F0ZUNvYWNoTmF2aWdhdGlvbkJ5S2V5Ym9hcmQodGFiRGlyZWN0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyRm9jdXNJbmRleCA9XG4gICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID09PSAtMVxuICAgICAgICA/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9PT0gLTFcbiAgICAgICAgICA/IDBcbiAgICAgICAgICA6IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleFxuICAgICAgICA6IHRoaXMuZm9jdXNlZENvYWNoSW5kZXg7XG5cbiAgICAvLyBDaGVjayBuZXh0IG9yIHByZXYgdGFiIGlzIHByZXNzZWQsIHRoZW4gd2UgbmVlZCB0byBmaW5kIHRoZSBuZXh0IGF2YWlsYWJsZSBjb2FjaCBpbmRleCB0aGF0IHNob3VsZCByZWNlaXZlIHRoZSBmb2N1c1xuICAgIGNvbnN0IG5ld0ZvY3VzYWJsZUluZGV4OiBudW1iZXIgPVxuICAgICAgdGFiRGlyZWN0aW9uID09PSAnTkVYVF9UQUInXG4gICAgICAgID8gdGhpcy5nZXROZXh0QXZhaWxhYmxlQ29hY2hJbmRleChjdXJyRm9jdXNJbmRleClcbiAgICAgICAgOiB0aGlzLmdldFByZXZBdmFpbGFibGVDb2FjaEluZGV4KGN1cnJGb2N1c0luZGV4KTtcblxuICAgIGlmICh0aGlzLmhhc05hdmlnYXRpb24pIHtcbiAgICAgIGNvbnN0IHNlbGVjdGVkUGxhY2VFbGVtZW50ID0gdGhpcy5fZ2V0UGxhY2VIdG1sRWxlbWVudCgpO1xuICAgICAgY29uc3QgcGxhY2VJbkNvYWNoSGFzRm9jdXMgPSBzZWxlY3RlZFBsYWNlRWxlbWVudFxuICAgICAgICA/IHNlbGVjdGVkUGxhY2VFbGVtZW50LmdldEF0dHJpYnV0ZSgna2V5Zm9jdXMnKSA9PT0gJ2ZvY3VzJ1xuICAgICAgICA6IGZhbHNlO1xuXG4gICAgICAvLyBJZiB3ZSB0YWIgYmFjayAoUFJFVl9UQUIpIGFuZCB0aGUgZm9jdXMgaXMgY3VycmVudGx5IG9uIHBsYWNlLFxuICAgICAgLy8gd2UgcmVtb3ZlIHRoZSBzZWxlY3RlZCBzdGF0ZSBmcm9tIHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgbmF2aWdhdGlvbiBjb2FjaCBhbmQgb25seSBzZXQgdGhlIGZvY3VzIHN0YXR1cyB0byBpdFxuICAgICAgaWYgKHRhYkRpcmVjdGlvbiA9PT0gJ1BSRVZfVEFCJyAmJiB0aGlzLnNlbGVjdGVkQ29hY2hJbmRleCA9PT0gY3VyckZvY3VzSW5kZXgpIHtcbiAgICAgICAgLy8gSWYgd2UgVEFCIGJhY2sgYW5kIGhhdmUgYSBzZWxlY3RlZCBwbGFjZXMgaW5zaWRlIHRoZSBjdXJyZW50IGNvYWNoLCB0aGVuIHdlIG1vdmUgb3V0IGZyb20gdGhlIHNlYXRtYXAgYW5kIHNldCB0aGUgZm9jdXMgdG8gdGhlIGN1cnJlbnQgc2VsZWN0ZWQgY29hY2hcbiAgICAgICAgaWYgKHBsYWNlSW5Db2FjaEhhc0ZvY3VzIHx8IHRoaXMuY3VyclNlbGVjdGVkUGxhY2UgIT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gY3VyckZvY3VzSW5kZXg7XG4gICAgICAgICAgdGhpcy51bmZvY3VzUGxhY2VFbGVtZW50KCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdoZW4gdGhlIGZpcnN0IGNvYWNoIGlzIHNlbGVjdGVkIGFuZCB3ZSBUQUIgYmFjaywgd2UgaGF2ZSB0byBzZXQgdGhlIG5hdGl2ZSBmb2N1cyBvbiB0aGUgZmlyc3QgY29hY2ggaW4gdGhlIG5hdmlnYXRpb24gdG8gZ2V0IGJhY2sgdG8gdGhlIG5vcm1hbCB0YWIgbmF2aWdhdGlvbi5cbiAgICAgICAgLy8gVG8gZG8gdGhpcywgd2UgaGF2ZSB0byByZW1vdmUgdGhlIGZvY3VzZWRJbmRleCBmcm9tIHRoZSBmaXJzdCBjb2FjaCBhbmQgc2V0IGl0IGFnYWluIGFmdGVyIGEgc2hvcnQgZGVsYXlcbiAgICAgICAgZWxzZSBpZiAoY3VyckZvY3VzSW5kZXggPT09IDApIHtcbiAgICAgICAgICAvLyBSZWZvY3VzIHRoZSBmaXJzdCBjb2FjaFxuICAgICAgICAgIHRoaXMuX3JlZm9jdXNDdXJyZW50Rm9jdXNlZE5hdkNvYWNoKGN1cnJGb2N1c0luZGV4KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gbmV3Rm9jdXNhYmxlSW5kZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIE9ubHkgc2V0cyB0aGUgZm9jdXMgb24gdGhlIG5ldyBuYXZpZ2F0aW9uIGNvYWNoXG4gICAgICBlbHNlIGlmIChuZXdGb2N1c2FibGVJbmRleCAhPT0gdGhpcy5jdXJyU2VsZWN0ZWRDb2FjaEluZGV4KSB7XG4gICAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSBuZXdGb2N1c2FibGVJbmRleDtcbiAgICAgIH1cbiAgICAgIC8vIFdoZW4gdGhlIGxhc3QgY29hY2ggaXMgc2VsZWN0ZWQgYW5kIHdlIFRBQiwgd2UgaGF2ZSB0byBzZXQgdGhlIG5hdGl2ZSBmb2N1cyBvbiB0aGUgbGFzdCBjb2FjaCBpbiB0aGUgbmF2aWdhdGlvbiB0byBnZXQgYmFjayB0byB0aGUgbm9ybWFsIHRhYiBuYXZpZ2F0aW9uLlxuICAgICAgLy8gVG8gZG8gdGhpcywgd2UgaGF2ZSAgdG8gcmVtb3ZlIHRoZSBmb2N1c2VkSW5kZXggZnJvbSB0aGUgZmlyc3QgY29hY2ggYW5kIHNldCBpdCBhZ2FpbiBhZnRlciBhIHNob3J0IGRlbGF5XG4gICAgICBlbHNlIGlmIChcbiAgICAgICAgdGFiRGlyZWN0aW9uID09PSAnTkVYVF9UQUInICYmXG4gICAgICAgIG5ld0ZvY3VzYWJsZUluZGV4ID09PSB0aGlzLmNvYWNoSXRlbURldGFpbHNFbGVtZW50cy5sZW5ndGggLSAxXG4gICAgICApIHtcbiAgICAgICAgLy8gUmVmb2N1cyB0aGUgbGFzdCBjb2FjaFxuICAgICAgICB0aGlzLl9yZWZvY3VzQ3VycmVudEZvY3VzZWROYXZDb2FjaChjdXJyRm9jdXNJbmRleCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gLTE7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRDb2FjaEluZGV4ID0gbmV3Rm9jdXNhYmxlSW5kZXg7XG4gICAgICAgIC8vIElmIGFueSBwbGFjZSB3YXMgZm9jdXNlZCBpbiBjb2FjaCwgc28gd2Ugc2V0IGZvY3VzZWQgYWdhaW5cbiAgICAgICAgaWYgKHBsYWNlSW5Db2FjaEhhc0ZvY3VzKSB7XG4gICAgICAgICAgdGhpcy5mb2N1c1BsYWNlRWxlbWVudCh0aGlzLmN1cnJTZWxlY3RlZFBsYWNlKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBJZiBubyBwbGFjZSB3YXMgc2VsZWN0ZWQsIHRoZW4gd2Ugc2VsZWN0IHRoZSBjb2FjaCBncmlkXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHRoaXMuaXNDb2FjaEdyaWRGb2N1c2FibGUgPSB0cnVlO1xuICAgICAgICAgIHRoaXMuX3NldEZvY3VzVG9TZWxlY3RlZENvYWNoR3JpZCgpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEJ5IFRhYiBOYXZpZ2F0aW9uLCBwZXJmb3JtIGF1dG9tYXRpYyBzY3JvbGxpbmcgdG8gdGhlIGZvY3VzZWQgd2Fnb25cbiAgICAgIHRoaXMuX3Njcm9sbFRvU2VsZWN0ZWROYXZpZ2F0aW9uQnV0dG9uKG5ld0ZvY3VzYWJsZUluZGV4KTtcbiAgICB9XG4gICAgLy8gSWYgbm8gbmF2aWdhdGlvbiBleGlzdCwgd2Ugc2Nyb2xsIGRpcmVjdGx5IHRvIHRoZSBuZXh0IHRhYmFibGUgY29hY2hcbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuc2Nyb2xsVG9TZWxlY3RlZE5hdkNvYWNoKG5ld0ZvY3VzYWJsZUluZGV4KTtcbiAgICB9XG4gIH1cblxuICAvLyBSZWZvY3VzZWQgdGhlIGN1cnJlbnQgZm9jdXNlZCAodmlzdWFsKSBuYXYgY29hY2ggdG8gZ2V0IHRoZSBuYXRpdmUgZm9jdXMgYmFjayB0byB0aGUgbmF2aWdhdGlvblxuICBwcml2YXRlIF9yZWZvY3VzQ3VycmVudEZvY3VzZWROYXZDb2FjaChmb2N1c0luZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmZvY3VzZWRDb2FjaEluZGV4ID0gLTE7XG4gICAgc2V0VGltZW91dCgoKSA9PiAodGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IGZvY3VzSW5kZXgpLCAwKTtcbiAgfVxuXG4gIHByaXZhdGUgX25hdmlnYXRlVG9QbGFjZUJ5S2V5Ym9hcmQocHJlc3NlZEtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbiA9IHRydWU7XG5cbiAgICBpZiAodGhpcy5mb2N1c2VkQ29hY2hJbmRleCAhPT0gLTEpIHtcbiAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSAtMTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMucHJldmVudFBsYWNlQ2xpY2spIHtcbiAgICAgIGNvbnN0IGZpbmRDbG9zZXN0UGxhY2UgPSB0aGlzLl9nZXRDbG9zZXN0UGxhY2VCeUtleURpcmVjdGlvbihwcmVzc2VkS2V5KTtcblxuICAgICAgaWYgKGZpbmRDbG9zZXN0UGxhY2UpIHtcbiAgICAgICAgdGhpcy5mb2N1c1BsYWNlRWxlbWVudChmaW5kQ2xvc2VzdFBsYWNlKTtcbiAgICAgIH1cbiAgICAgIC8vIE5vIGNsb3Nlc3QgcGxhY2UgZm91bmQgYnkga2V5IG5hdmlnYXRpb25cbiAgICAgIGVsc2Uge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dSaWdodCB8fFxuICAgICAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93TGVmdCB8fFxuICAgICAgICAgICh0aGlzLmFsaWduVmVydGljYWwgJiZcbiAgICAgICAgICAgIChwcmVzc2VkS2V5ID09PSB0aGlzLmtleWJvYXJkTmF2aWdhdGlvbkV2ZW50cy5BcnJvd1VwIHx8XG4gICAgICAgICAgICAgIHByZXNzZWRLZXkgPT09IHRoaXMua2V5Ym9hcmROYXZpZ2F0aW9uRXZlbnRzLkFycm93RG93bikpXG4gICAgICAgICkge1xuICAgICAgICAgIC8vIENoZWNrIHRoZSBjdXJyZW50IHByZXNzZWQga2V5IHRvIGdldCB0aGUgbmV4dCBhdmFpbGFibGUgY29hY2ggaW5kZXhcbiAgICAgICAgICBjb25zdCBuZXdTZWxlY3RlZENvYWNoSW5kZXggPVxuICAgICAgICAgICAgcHJlc3NlZEtleSA9PT0gdGhpcy5rZXlib2FyZE5hdmlnYXRpb25FdmVudHMuQXJyb3dSaWdodFxuICAgICAgICAgICAgICA/IHRoaXMuZ2V0TmV4dEF2YWlsYWJsZUNvYWNoSW5kZXgoKVxuICAgICAgICAgICAgICA6IHRoaXMuZ2V0UHJldkF2YWlsYWJsZUNvYWNoSW5kZXgoKTtcblxuICAgICAgICAgIHRoaXMuc2Nyb2xsVG9TZWxlY3RlZE5hdkNvYWNoKG5ld1NlbGVjdGVkQ29hY2hJbmRleCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0TmV4dEF2YWlsYWJsZUNvYWNoSW5kZXgoY3VycmVudEluZGV4PzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBzdGFydEluZGV4ID0gY3VycmVudEluZGV4ID8/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICByZXR1cm4gc3RhcnRJbmRleCA8IHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleF0uY29hY2hJdGVtcy5sZW5ndGggLSAxXG4gICAgICA/IHN0YXJ0SW5kZXggKyAxXG4gICAgICA6IHN0YXJ0SW5kZXg7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0UHJldkF2YWlsYWJsZUNvYWNoSW5kZXgoY3VycmVudEluZGV4PzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBzdGFydEluZGV4ID0gY3VycmVudEluZGV4ID8/IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICByZXR1cm4gc3RhcnRJbmRleCA+IDAgPyBzdGFydEluZGV4IC0gMSA6IHN0YXJ0SW5kZXg7XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlU2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXMocGxhY2VTZWxlY3Rpb246IFBsYWNlU2VsZWN0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgcGxhY2VUeXBlUHJvcCA9IHBsYWNlU2VsZWN0aW9uLnBsYWNlVHlwZSA9PT0gJ1NFQVQnID8gJ3NlYXRzJyA6ICdiaWN5Y2xlcyc7XG4gICAgY29uc3QgbWF4UmVzZXJ2YXRpb25zID1cbiAgICAgIHBsYWNlU2VsZWN0aW9uLnBsYWNlVHlwZSA9PT0gJ1NFQVQnID8gdGhpcy5tYXhTZWF0UmVzZXJ2YXRpb25zIDogdGhpcy5tYXhCaWN5Y2xlUmVzZXJ2YXRpb25zO1xuICAgIGNvbnN0IGN1cnJTZWxlY3RlZFBsYWNlcyA9IHRoaXMuc2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXNbcGxhY2VUeXBlUHJvcF07XG5cbiAgICB0aGlzLnNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzW3BsYWNlVHlwZVByb3BdID0gdGhpcy5fdXBkYXRlU2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXMoXG4gICAgICBjdXJyU2VsZWN0ZWRQbGFjZXMsXG4gICAgICBtYXhSZXNlcnZhdGlvbnMsXG4gICAgICBwbGFjZVNlbGVjdGlvbixcbiAgICApO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtDdXN0b21FdmVudDxTZWF0UmVzZXJ2YXRpb25TZWxlY3RlZFBsYWNlcz59XG4gICAgICogRW1pdHMgd2hlbiBhIHBsYWNlIHdhcyBzZWxlY3RlZCBhbmQgcmV0dXJucyBhIFBsYWNlIGFycmF5IHdpdGggYWxsIHNlbGVjdGVkIHBsYWNlcy5cbiAgICAgKi9cbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQoXG4gICAgICBuZXcgQ3VzdG9tRXZlbnQ8U2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRQbGFjZXM+KCdzZWxlY3RlZHBsYWNlcycsIHtcbiAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgY29tcG9zZWQ6IHRydWUsXG4gICAgICAgIGRldGFpbDogdGhpcy5zZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVTZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyhcbiAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlczogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25bXSxcbiAgICBtYXhSZXNlcnZhdGlvbnM6IG51bWJlcixcbiAgICBwbGFjZVNlbGVjdGlvbjogUGxhY2VTZWxlY3Rpb24sXG4gICk6IFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uW10ge1xuICAgIC8vIEFkZCBzZWxlY3RlZCBwbGFjZSB0byBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlc1xuICAgIGlmIChwbGFjZVNlbGVjdGlvbi5zdGF0ZSA9PT0gJ1NFTEVDVEVEJykge1xuICAgICAgY29uc3Qgc2VsZWN0ZWRQbGFjZURlY2tJbmRleCA9IHRoaXMuX2dldERlY2tJbmRleEJ5UGxhY2VJZChwbGFjZVNlbGVjdGlvbi5pZCk7XG4gICAgICBjb25zdCBzZWF0UmVzZXJ2YXRpb25TZWxlY3Rpb24gPSB0aGlzLl9nZXRTZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbihcbiAgICAgICAgcGxhY2VTZWxlY3Rpb24sXG4gICAgICAgIHNlbGVjdGVkUGxhY2VEZWNrSW5kZXgsXG4gICAgICApO1xuICAgICAgaWYgKHNlYXRSZXNlcnZhdGlvblNlbGVjdGlvbikge1xuICAgICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcy5wdXNoKHNlYXRSZXNlcnZhdGlvblNlbGVjdGlvbik7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFJlbW92ZSBzZWxlY3RlZCBwbGFjZSBmcm9tIHNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzXG4gICAgZWxzZSB7XG4gICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyA9IHNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzLmZpbHRlcihcbiAgICAgICAgKF9zZWxlY3RlZFBsYWNlKSA9PiBfc2VsZWN0ZWRQbGFjZS5pZCAhPT0gcGxhY2VTZWxlY3Rpb24uaWQsXG4gICAgICApO1xuICAgIH1cbiAgICAvLyBDaGVja3Mgd2hldGhlciBtYXhSZXNlcnZhdGlvbiBpcyBhY3RpdmF0ZWQgYW5kIHRoZSBtYXhpbXVtIG51bWJlciBvZiBzZWxlY3RlZCBwbGFjZXMgaXMgcmVhY2hlZFxuICAgIGlmIChtYXhSZXNlcnZhdGlvbnMgPiAtMSAmJiBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcy5sZW5ndGggPiBtYXhSZXNlcnZhdGlvbnMpIHtcbiAgICAgIGNvbnN0IHJlc2V0V2l0aFBsYWNlU2VsZWN0aW9uID0gbWF4UmVzZXJ2YXRpb25zID4gMCA/IHBsYWNlU2VsZWN0aW9uIDogdW5kZWZpbmVkO1xuXG4gICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyA9IHRoaXMuX3Jlc2V0QWxsUGxhY2VTZWxlY3Rpb25zKFxuICAgICAgICBzZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcyxcbiAgICAgICAgcmVzZXRXaXRoUGxhY2VTZWxlY3Rpb24sXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gc2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXM7XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlQ3VycmVudFNlbGVjdGVkUGxhY2VJbkNvYWNoKHBsYWNlU2VsZWN0aW9uOiBQbGFjZVNlbGVjdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IHBsYWNlRGVja0luZGV4ID0gdGhpcy5fZ2V0RGVja0luZGV4QnlQbGFjZUlkKHBsYWNlU2VsZWN0aW9uLmlkKTtcbiAgICBjb25zdCBjb2FjaEluZGV4ID0gcGxhY2VTZWxlY3Rpb24uY29hY2hJbmRleDtcblxuICAgIGlmIChwbGFjZURlY2tJbmRleCA9PT0gbnVsbCkgcmV0dXJuO1xuXG4gICAgY29uc3QgcGxhY2UgPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbcGxhY2VEZWNrSW5kZXhdLmNvYWNoSXRlbXNbY29hY2hJbmRleF0ucGxhY2VzPy5maW5kKFxuICAgICAgKHBsYWNlKSA9PiBwbGFjZS5udW1iZXIgPT0gcGxhY2VTZWxlY3Rpb24ubnVtYmVyLFxuICAgICk7XG5cbiAgICBpZiAoIXBsYWNlKSByZXR1cm47XG5cbiAgICB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCA9IHBsYWNlRGVja0luZGV4O1xuICAgIHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCA9IGNvYWNoSW5kZXg7XG4gICAgdGhpcy5jdXJyU2VsZWN0ZWRQbGFjZSA9IHBsYWNlO1xuXG4gICAgaWYgKHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleCAhPT0gdGhpcy5zZWxlY3RlZENvYWNoSW5kZXgpIHtcbiAgICAgIHRoaXMudXBkYXRlQ3VycmVudFNlbGVjdGVkQ29hY2goKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zZXRDdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZChwbGFjZSk7XG5cbiAgICAvLyBUaW1lIGRlbGF5IHRvIHdhaXQgZm9yIHN0YXR1cyB1cGRhdGUgcHJvY2VzcyBhdCBjbGlja2VkIHBsYWNlXG4gICAgY29uc3QgZGVsYXlTY3JvbGxJblZpZXdwb3J0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLl9zY3JvbGxQbGFjZUludG9OZWFyZXN0Vmlld3BvcnQocGxhY2VTZWxlY3Rpb24uaWQpO1xuICAgICAgY2xlYXJUaW1lb3V0KGRlbGF5U2Nyb2xsSW5WaWV3cG9ydCk7XG4gICAgfSwgMCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgdXBkYXRlQ3VycmVudFNlbGVjdGVkQ29hY2goKTogdm9pZCB7XG4gICAgLy9Pbmx5IGlmIHRoZSBzZWxlY3RlZENvYWNoSW5kZXggaGFzIGNoYW5nZWQsIGFuIHVwZGF0ZSBuZWVkcyB0byBiZSBjYXJyaWVkIG91dFxuICAgIGlmICh0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXggPT0gdGhpcy5zZWxlY3RlZENvYWNoSW5kZXgpIHJldHVybjtcblxuICAgIC8vIElmIGEgZm9jdXNpbmRleCBoYXMgYmVlbiBzZXQgKCE9IC0xKSwgaXQgY2FuIGJlIHVwZGF0ZWQgd2l0aCB0aGUgY3VycmVudCBzZWxlY3RlZENvYWNoSW5kZXhcbiAgICBpZiAodGhpcy5mb2N1c2VkQ29hY2hJbmRleCAhPSAtMSkge1xuICAgICAgdGhpcy5mb2N1c2VkQ29hY2hJbmRleCA9IHRoaXMuY3VyclNlbGVjdGVkQ29hY2hJbmRleDtcbiAgICB9XG4gICAgdGhpcy5zZWxlY3RlZENvYWNoSW5kZXggPSB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXg7XG5cbiAgICBjb25zdCBjb2FjaFNlbGVjdGlvbiA9IHRoaXMuX2dldFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkQ29hY2godGhpcy5zZWxlY3RlZENvYWNoSW5kZXgpO1xuICAgIGlmIChjb2FjaFNlbGVjdGlvbikge1xuICAgICAgLyoqXG4gICAgICAgKiBAdHlwZSB7Q3VzdG9tRXZlbnQ8U2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRDb2FjaD59XG4gICAgICAgKiBFbWl0cyB3aGVuIGEgY29hY2ggd2FzIHNlbGVjdGVkIGFuZCByZXR1cm5zIGEgQ29hY2hTZWxlY3Rpb25cbiAgICAgICAqL1xuICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICBuZXcgQ3VzdG9tRXZlbnQ8U2VhdFJlc2VydmF0aW9uU2VsZWN0ZWRDb2FjaD4oJ3NlbGVjdGVkY29hY2gnLCB7XG4gICAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgICBjb21wb3NlZDogdHJ1ZSxcbiAgICAgICAgICBkZXRhaWw6IGNvYWNoU2VsZWN0aW9uLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGdldFBsYWNlRWxlbWVudElkKFxuICAgIGNvYWNoRGVja0luZGV4OiBudW1iZXIsXG4gICAgY29hY2hJbmRleDogbnVtYmVyLFxuICAgIHBsYWNlTnVtYmVyOiBzdHJpbmcsXG4gICk6IHN0cmluZyB7XG4gICAgcmV0dXJuIChcbiAgICAgICdzZWF0LXJlc2VydmF0aW9uX19wbGFjZS1idXR0b24tJyArIGNvYWNoRGVja0luZGV4ICsgJy0nICsgY29hY2hJbmRleCArICctJyArIHBsYWNlTnVtYmVyXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbiB0aGUgY2FzZSBvZiBjb2FjaCBsYXlvdXRzIHdpdGggZGlmZmVyZW50IGRlY2tzLFxuICAgKiBpdCBpcyBuZWNlc3NhcnkgdG8gZXh0ZW5kIHRoZSBvZmZzZXQgd2l0aCBlbXB0eSBjb2FjaGVzXG4gICAqIGluIG9yZGVyIHRvIGNyZWF0ZSBhIHN0YWJsZSB2ZWhpY2xlIGxheW91dC5cbiAgICpcbiAgICogICAgICAgICAgICAgW29vb10tW29vb10tW29vb11cbiAgICogW29vb10tW29vb10tW29vb10tW29vb10tW29vb11cbiAgICovXG4gIHByaXZhdGUgX2luaXRFbXB0eUNvYWNoRGVja09mZnNldHMoKTogdm9pZCB7XG4gICAgLy8gUHJlZmlsbCBvZmZzZXQgY291bnRlcnMgd2l0aCAwIHN0YXJ0IGluZGV4XG4gICAgY29uc3QgY29hY2hPZmZzZXRJbmRleENvdW50ZXIgPSBBcnJheSh0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMSkuZmlsbCgwKTtcbiAgICAvLyBUYWtlcyB0aGUgbG93ZXIgZGVjayB3aGljaCBjb250YWlucyB0aGUgbWF4IG51bWJlcnMgb2YgY29hY2hlc1xuICAgIGNvbnN0IGxvd2VyRGVjayA9IHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMV07XG5cbiAgICBsb3dlckRlY2suY29hY2hJdGVtcy5mb3JFYWNoKChsb3dlckNvYWNoSXRlbTogQ29hY2hJdGVtKSA9PiB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2VhdFJlc2VydmF0aW9ucy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgY29uc3QgZGVja0NvYWNoSXRlbSA9IHRoaXMuc2VhdFJlc2VydmF0aW9uc1tpXS5jb2FjaEl0ZW1zW2NvYWNoT2Zmc2V0SW5kZXhDb3VudGVyW2ldXTtcbiAgICAgICAgaWYgKGxvd2VyQ29hY2hJdGVtLmlkICE9IGRlY2tDb2FjaEl0ZW0/LmlkKSB7XG4gICAgICAgICAgLy8gQWRkIEVtcHR5IG9mZnNldCBjb2FjaCB0byBzcGVjaWZpZWQgaW5kZXggcG9zaXRpb25cbiAgICAgICAgICBjb25zdCBlbXB0eU9mZnNldENvYWNoID0ge1xuICAgICAgICAgICAgLi4ubG93ZXJDb2FjaEl0ZW0sXG4gICAgICAgICAgICBwbGFjZXM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHByb3BlcnR5SWRzOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBncmFwaGljRWxlbWVudHM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHNlcnZpY2VFbGVtZW50czogdW5kZWZpbmVkLFxuICAgICAgICAgICAgdHJhdmVsQ2xhc3M6IFtdLFxuICAgICAgICAgIH07XG4gICAgICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zW2ldLmNvYWNoSXRlbXMuc3BsaWNlKFxuICAgICAgICAgICAgY29hY2hPZmZzZXRJbmRleENvdW50ZXJbaV0sXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgZW1wdHlPZmZzZXRDb2FjaCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29hY2hPZmZzZXRJbmRleENvdW50ZXJbaV0rKztcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXphdGlvbiBvZiBTZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbiBBcnJheSBiYXNlZCBvbiB0aGUgdHJhbnNmZXJyZWQgcGxhY2VzXG4gICAqIHRoYXQgaGF2ZSB0aGUgc3RhdGUgU0VMRUNURUQgd2l0aGluIHRoZSBzZWF0UmVzZXJ2YXRpb24gb2JqZWN0XG4gICAqL1xuICBwcml2YXRlIF9pbml0U2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgLy8gUmVzZXQgcGxhY2Ugc2VsZWN0aW9uc1xuICAgIHRoaXMuc2VsZWN0ZWRTZWF0UmVzZXJ2YXRpb25QbGFjZXMuc2VhdHMgPSBbXTtcbiAgICB0aGlzLnNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzLmJpY3ljbGVzID0gW107XG5cbiAgICB0aGlzLnNlYXRSZXNlcnZhdGlvbnM/LmZvckVhY2goKHNlYXRSZXNlcnZhdGlvbjogU2VhdFJlc2VydmF0aW9uLCBjb2FjaERlY2tJbmRleDogbnVtYmVyKSA9PlxuICAgICAgc2VhdFJlc2VydmF0aW9uLmNvYWNoSXRlbXMubWFwKChjb2FjaDogQ29hY2hJdGVtLCBjb2FjaEluZGV4OiBudW1iZXIpID0+IHtcbiAgICAgICAgY29hY2gucGxhY2VzXG4gICAgICAgICAgPy5maWx0ZXIoKHBsYWNlKSA9PiBwbGFjZS5zdGF0ZSA9PT0gJ1NFTEVDVEVEJylcbiAgICAgICAgICA/LmZvckVhY2goKHBsYWNlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwbGFjZUlkID0gdGhpcy5nZXRQbGFjZUVsZW1lbnRJZChjb2FjaERlY2tJbmRleCwgY29hY2hJbmRleCwgcGxhY2UubnVtYmVyKTtcbiAgICAgICAgICAgIGNvbnN0IHByZXNlbGVjdGVkUGxhY2VTZWxlY3Rpb246IFBsYWNlU2VsZWN0aW9uID0gbWFwUGxhY2VJbmZvc1RvUGxhY2VTZWxlY3Rpb24oXG4gICAgICAgICAgICAgIHBsYWNlLFxuICAgICAgICAgICAgICBwbGFjZUlkLFxuICAgICAgICAgICAgICBzZWF0UmVzZXJ2YXRpb24uZGVja0NvYWNoSW5kZXgsXG4gICAgICAgICAgICAgIGNvYWNoSW5kZXgsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBjb25zdCBzZWF0UmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbjogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24gfCBudWxsID1cbiAgICAgICAgICAgICAgdGhpcy5fZ2V0U2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24ocHJlc2VsZWN0ZWRQbGFjZVNlbGVjdGlvbiwgY29hY2hEZWNrSW5kZXgpO1xuXG4gICAgICAgICAgICBpZiAoc2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgaWYgKHNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uLnBsYWNlVHlwZSA9PT0gJ1NFQVQnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3RlZFNlYXRSZXNlcnZhdGlvblBsYWNlcy5zZWF0cy5wdXNoKHNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkU2VhdFJlc2VydmF0aW9uUGxhY2VzLmJpY3ljbGVzLnB1c2goc2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFsbCBzZWxlY3RlZCBwbGFjZXMgd2lsbCBiZSByZXNldCBvciB0aGUgY3VycmVudFNlbGVjdGVkUGxhY2Ugd2FzIGdpdmVuLCB0aGVuIHdlIHJlc2V0IGFsbCBleGNlcHQgY3VycmVudFNlbGVjdGVkUGxhY2VcbiAgICogQHBhcmFtIHJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25zXG4gICAqIEBwYXJhbSBjdXJyU2VsZWN0ZWRQbGFjZVxuICAgKi9cbiAgcHJpdmF0ZSBfcmVzZXRBbGxQbGFjZVNlbGVjdGlvbnMoXG4gICAgcmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbnM6IFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uW10sXG4gICAgY3VyclNlbGVjdGVkUGxhY2U/OiBQbGFjZVNlbGVjdGlvbixcbiAgKTogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25bXSB7XG4gICAgLy9GaW5kIGFsbCBwbGFjZXMgdG8gYmUgbmVlZGVkIHVuc2VsZWN0XG4gICAgZm9yIChjb25zdCBwbGFjZVNlbGVjdGlvbiBvZiByZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9ucykge1xuICAgICAgaWYgKCFjdXJyU2VsZWN0ZWRQbGFjZSB8fCBjdXJyU2VsZWN0ZWRQbGFjZS5pZCAhPT0gcGxhY2VTZWxlY3Rpb24uaWQpIHtcbiAgICAgICAgY29uc3QgcGxhY2VFbGVtZW50ID0gdGhpcy5zaGFkb3dSb290Py5nZXRFbGVtZW50QnlJZChwbGFjZVNlbGVjdGlvbi5pZCkgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGlmIChwbGFjZUVsZW1lbnQpIHtcbiAgICAgICAgICBwbGFjZUVsZW1lbnQuc2V0QXR0cmlidXRlKCdzdGF0ZScsICdGUkVFJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgLy9SZW1vdmVzIGFsbCBzZWxlY3RlZCBwbGFjZXMgZXhjZXB0IHRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcGxhY2VcbiAgICBpZiAoY3VyclNlbGVjdGVkUGxhY2UpIHtcbiAgICAgIHJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25zID0gcmVzZXJ2YXRpb25QbGFjZVNlbGVjdGlvbnMuZmlsdGVyKFxuICAgICAgICAoX3NlbGVjdGVkUGxhY2UpID0+IF9zZWxlY3RlZFBsYWNlLmlkID09PSBjdXJyU2VsZWN0ZWRQbGFjZS5pZCxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb25zID0gW107XG4gICAgfVxuICAgIHJldHVybiByZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9ucztcbiAgfVxuXG4gIHByaXZhdGUgX2dldFNlYXRSZXNlcnZhdGlvblBsYWNlU2VsZWN0aW9uKFxuICAgIGN1cnJTZWxlY3RlZFBsYWNlOiBQbGFjZVNlbGVjdGlvbixcbiAgICBjb2FjaERlY2tJbmRleDogbnVtYmVyIHwgbnVsbCxcbiAgKTogU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24gfCBudWxsIHtcbiAgICBpZiAoY29hY2hEZWNrSW5kZXggPT09IG51bGwpIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgY29hY2ggPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbY29hY2hEZWNrSW5kZXhdLmNvYWNoSXRlbXNbY3VyclNlbGVjdGVkUGxhY2UuY29hY2hJbmRleF07XG4gICAgY29uc3QgcGxhY2UgPSBjb2FjaC5wbGFjZXM/LmZpbmQoKHBsYWNlKSA9PiBwbGFjZS5udW1iZXIgPT09IGN1cnJTZWxlY3RlZFBsYWNlLm51bWJlcik7XG5cbiAgICByZXR1cm4gcGxhY2VcbiAgICAgID8gbWFwUGxhY2VBbmRDb2FjaFRvU2VhdFJlc2VydmF0aW9uUGxhY2VTZWxlY3Rpb24oXG4gICAgICAgICAgcGxhY2UsXG4gICAgICAgICAgY29hY2gsXG4gICAgICAgICAgY3VyclNlbGVjdGVkUGxhY2UuaWQsXG4gICAgICAgICAgY3VyclNlbGVjdGVkUGxhY2UuZGVja0luZGV4LFxuICAgICAgICAgIGN1cnJTZWxlY3RlZFBsYWNlLmNvYWNoSW5kZXgsXG4gICAgICAgIClcbiAgICAgIDogbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgX2dldFNlYXRSZXNlcnZhdGlvblNlbGVjdGVkQ29hY2goXG4gICAgY29hY2hJbmRleDogbnVtYmVyLFxuICApOiBTZWF0UmVzZXJ2YXRpb25TZWxlY3RlZENvYWNoIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdLmNvYWNoSXRlbXNbY29hY2hJbmRleF0pIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgY29hY2ggPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5jdXJyU2VsZWN0ZWREZWNrSW5kZXhdLmNvYWNoSXRlbXNbY29hY2hJbmRleF07XG4gICAgY29uc3QgY29hY2hOdW1iZXJPZkZyZWVQbGFjZXMgPSB0aGlzLmdldEF2YWlsYWJsZUZyZWVQbGFjZXNOdW1Gcm9tQ29hY2goY29hY2gucGxhY2VzKTtcbiAgICByZXR1cm4gbWFwQ29hY2hJbmZvc1RvQ29hY2hTZWxlY3Rpb24oY29hY2hJbmRleCwgY29hY2gsIGNvYWNoTnVtYmVyT2ZGcmVlUGxhY2VzKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NldEN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkKHBsYWNlOiBQbGFjZSB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkID0gcGxhY2VcbiAgICAgID8gdGhpcy5nZXRQbGFjZUVsZW1lbnRJZChcbiAgICAgICAgICB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleCxcbiAgICAgICAgICB0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXgsXG4gICAgICAgICAgcGxhY2UubnVtYmVyLFxuICAgICAgICApXG4gICAgICA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyYXRpb24gb2YgdGhlIHVzZWQgZG9jdW1lbnRzIGZvbnQtc2l6ZSB3aGljaCBuZWVkc1xuICAgKiB0byBiZSBkZXRlcm1pbmVkIGluIG9yZGVyIHRvIGNvcnJlY3RseSBjYWxjdWxhdGUgQ1NTIHZhbHVlcyB3aXRoIHJlbVxuICAgKiAqL1xuICBwcml2YXRlIF9kZXRlcm1pbmVCYXNlRm9udFNpemUoKTogdm9pZCB7XG4gICAgaWYgKCFpc1NlcnZlcikge1xuICAgICAgY29uc3QgYmFzZUZvbnRTaXplID0gcGFyc2VJbnQod2luZG93LmdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQuYm9keSkuZm9udFNpemUsIDEwKTtcbiAgICAgIC8vY2FsY3VsYXRlIHJlbSBvZiAxcHhcbiAgICAgIGNvbnN0IG9uZVBpeGVsSW5SZW0gPSAxIC8gYmFzZUZvbnRTaXplO1xuICAgICAgdGhpcy5zdHlsZT8uc2V0UHJvcGVydHkoJy0tc2JiLXNlYXQtcmVzZXJ2YXRpb24tb25lLXB4LXJlbScsIGAke29uZVBpeGVsSW5SZW0gKyAncmVtJ31gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgZGF0YSBmb3IgZGlzcGxheWluZyBuYXZpZ2F0aW9uIGFyZWEuXG4gICAqIENhbGN1bGF0ZXMgdGhlIHZhbHVlcyB3aGljaCBhcmUgbm90IGdvaW5nIHRvIGNoYW5nZSBkdXJpbmcgdXNlIG9mIGEgY29tcG9uZW50OlxuICAgKiAgICAtIGNvYWNoIGlkXG4gICAqICAgIC0gbGlzdCBvZiBzZXJ2aWNlIGljb25zXG4gICAqICAgIC0gY2xhc3MgKGZpcnN0LCBzZWNvbmQsIGFueSlcbiAgICogICAgLSB3aGV0aGVyIHRoZXJlIGlzIGEgZHJpdmVyIGFyZWEgbGVmdCBvciByaWdodFxuICAgKiAqL1xuICBwcml2YXRlIF9wcmVwYXJlQ29hY2hJdGVtRGV0YWlsc0RhdGEoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2VhdFJlc2VydmF0aW9ucykge1xuICAgICAgY29uc3QgbG93ZXJEZWNrOiBDb2FjaEl0ZW1bXSA9XG4gICAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLnNlYXRSZXNlcnZhdGlvbnMubGVuZ3RoIC0gMV0uY29hY2hJdGVtcztcblxuICAgICAgdGhpcy5jb2FjaEl0ZW1EZXRhaWxzRWxlbWVudHMgPSBbXTtcblxuICAgICAgbG93ZXJEZWNrLmZvckVhY2goKGNvYWNoLCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB0cmF2ZWxDbGFzc2VzOiBQbGFjZVRyYXZlbENsYXNzW10gPSBbXTtcbiAgICAgICAgY29uc3QgcHJvcGVydHlJZHM6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGNvbnN0IHBsYWNlczogUGxhY2VbXSA9IFtdO1xuXG4gICAgICAgIC8vIENvbGxlY3QgYWxsIGltcG9ydGFudCBuYXZpZ2F0aW9uIGRhdGEgdG8gYmUgcmVuZGVyZWRcbiAgICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zXG4gICAgICAgICAgLm1hcCgoc3IpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBzci5jb2FjaEl0ZW1zW2luZGV4XTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5mb3JFYWNoKChjb2FjaDogQ29hY2hJdGVtKSA9PiB7XG4gICAgICAgICAgICB0cmF2ZWxDbGFzc2VzLnB1c2goLi4uY29hY2gudHJhdmVsQ2xhc3MpO1xuICAgICAgICAgICAgcHJvcGVydHlJZHMucHVzaCguLi4oY29hY2gucHJvcGVydHlJZHMgPyBjb2FjaC5wcm9wZXJ0eUlkcyA6IFtdKSk7XG4gICAgICAgICAgICBwbGFjZXMucHVzaCguLi4oY29hY2gucGxhY2VzID8gY29hY2gucGxhY2VzIDogW10pKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmNvYWNoSXRlbURldGFpbHNFbGVtZW50cy5wdXNoKHtcbiAgICAgICAgICBpZDogY29hY2guaWQsXG4gICAgICAgICAgdHJhdmVsQ2xhc3M6IHRoaXMuX3ByZXBhcmVUcmF2ZWxDbGFzc05hdmlnYXRpb24odHJhdmVsQ2xhc3NlcyksXG4gICAgICAgICAgcHJvcGVydHlJZHM6IHRoaXMuX3ByZXBhcmVTZXJ2aWNlSWNvbnNOYXZpZ2F0aW9uKHByb3BlcnR5SWRzKSxcbiAgICAgICAgICBpc0RyaXZlckFyZWE6IGNvYWNoLnBsYWNlcyA/IGNvYWNoLnBsYWNlcy5sZW5ndGggPT09IDAgOiB0cnVlLFxuICAgICAgICAgIGRyaXZlckFyZWFTaWRlOiB0aGlzLl9wcmVwYXJlRHJpdmVyQXJlYVNpZGVOYXZpZ2F0aW9uKGNvYWNoKSxcbiAgICAgICAgICBmcmVlUGxhY2VzOiB0aGlzLmdldEF2YWlsYWJsZUZyZWVQbGFjZXNOdW1Gcm9tQ29hY2gocGxhY2VzKSxcbiAgICAgICAgICBkcml2ZXJBcmVhRWxlbWVudHM6IHRoaXMuX3NldERyaXZlckFyZWFzRWxlbWVudHMoY29hY2gpLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vICNUSU1PLTQ1ODU4XG4gIC8vIEZpbmRzIHRoZSBvcHRpbWFsIGljb24gc2l6ZSBiYXNlZCBvbiBhbGwgc2VydmljZUVsZW1lbnRzIGFuZCB0aGVpciBkaW1lbnNpb24uXG4gIC8vIFRoaXMgc2V0cyB0aGUgZ2xvYmFsQXJlYUljb25EaW0gYW5kIGlzIHVzZWQgd2hlbiBjcmVhdGluZyB0aGUgc2VhdCByZXNlcnZhdGlvbiBhcmVhIGVsZW1lbnRzLlxuICAvLyBUaGlzIGdpdmVzIHVzIGEgbWF4aW11bSB1bmlmb3JtIGljb24gc2l6ZSB3aXRoaW4gdGhlIGFyZWEgZWxlbWVudHNcbiAgcHJpdmF0ZSBfcHJlcGFyZU9wdGltaXplQXJlYUljb25EaW1lbnNpb25CeU1lZGlhbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZWF0UmVzZXJ2YXRpb25zKSB7XG4gICAgICBjb25zdCBhbGxTZXJ2aWNlRGltZW5zaW9uczogRWxlbWVudERpbWVuc2lvbltdID0gW107XG4gICAgICB0aGlzLnNlYXRSZXNlcnZhdGlvbnMuZm9yRWFjaCgoZGVjaykgPT5cbiAgICAgICAgZGVjay5jb2FjaEl0ZW1zLmZvckVhY2goKGNvYWNoKSA9PlxuICAgICAgICAgIGNvYWNoLnNlcnZpY2VFbGVtZW50cz8uZm9yRWFjaCgoaWNvbikgPT4gYWxsU2VydmljZURpbWVuc2lvbnMucHVzaChpY29uLmRpbWVuc2lvbikpLFxuICAgICAgICApLFxuICAgICAgKTtcblxuICAgICAgaWYgKGFsbFNlcnZpY2VEaW1lbnNpb25zLmxlbmd0aCkge1xuICAgICAgICBhbGxTZXJ2aWNlRGltZW5zaW9ucy5zb3J0KFxuICAgICAgICAgIChkaW0xOiBFbGVtZW50RGltZW5zaW9uIHwgdW5kZWZpbmVkLCBkaW0yOiBFbGVtZW50RGltZW5zaW9uIHwgdW5kZWZpbmVkKSA9PiB7XG4gICAgICAgICAgICBpZiAoZGltMSAmJiBkaW0yKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG1heERpbTEgPSBkaW0xLncgKyBkaW0xLmg7XG4gICAgICAgICAgICAgIGNvbnN0IG1heERpbTIgPSBkaW0yLncgKyBkaW0yLmg7XG4gICAgICAgICAgICAgIGlmIChtYXhEaW0xID4gbWF4RGltMikgcmV0dXJuIDE7XG4gICAgICAgICAgICAgIGVsc2UgaWYgKG1heERpbTEgPCBtYXhEaW0yKSByZXR1cm4gLTE7XG4gICAgICAgICAgICAgIGVsc2UgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9LFxuICAgICAgICApO1xuICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIGJlc3QgaWNvbiBzaXplIGJ5IG1lZGlhblxuICAgICAgICBjb25zdCBtZWRpYW5JY29uU2l6ZSA9IGFsbFNlcnZpY2VEaW1lbnNpb25zW01hdGguZmxvb3IoYWxsU2VydmljZURpbWVuc2lvbnMubGVuZ3RoIC8gMildITtcblxuICAgICAgICAvLyBTZXQgdGhlIGRldGVybWluZWQgbWVkaWFuIGljb24gc2l6ZSBhcyBnbG9iYWwgY2FsY3VsYXRlZCBhcmVhIGljb24gZGltZW5zaW9uXG4gICAgICAgIHRoaXMuZ2xvYmFsQXJlYUljb25EaW0gPSB0aGlzLmdldENhbGN1bGF0ZWREaW1lbnNpb24obWVkaWFuSWNvblNpemUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZmluZCB0aGUgbWF4aW11bSBjb2FjaCBoZWlnaHQgZnJvbSBhbGwgZGVja3NcbiAgICAgICAgY29uc3QgbWF4Q29hY2hIZWlnaHQgPSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNcbiAgICAgICAgICAuZmxhdE1hcCgoZGVjaykgPT4gZGVjay5jb2FjaEl0ZW1zLm1hcCgoY29hY2gpID0+IGNvYWNoLmRpbWVuc2lvbi5oKSlcbiAgICAgICAgICAucmVkdWNlKChtYXgsIGhlaWdodCkgPT4gTWF0aC5tYXgobWF4LCBoZWlnaHQpLCAwKTtcblxuICAgICAgICAvL2NhbGN1bGF0ZSAyMCUgb2YgbWF4aW11bSBoZWlnaHQgYXMgaWNvbiBkaW1lbnNpb25cbiAgICAgICAgY29uc3QgaWNvbkRpbWVuc2lvbiA9IE1hdGguZmxvb3IobWF4Q29hY2hIZWlnaHQgKiAwLjIpO1xuICAgICAgICB0aGlzLmdsb2JhbEFyZWFJY29uRGltID0gdGhpcy5nZXRDYWxjdWxhdGVkRGltZW5zaW9uKHtcbiAgICAgICAgICB3OiBpY29uRGltZW5zaW9uLFxuICAgICAgICAgIGg6IGljb25EaW1lbnNpb24sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3ByZXBhcmVUcmF2ZWxDbGFzc05hdmlnYXRpb24odHJhdmVsQ2xhc3NlczogUGxhY2VUcmF2ZWxDbGFzc1tdKTogUGxhY2VUcmF2ZWxDbGFzcyB7XG4gICAgaWYgKHRyYXZlbENsYXNzZXMuaW5kZXhPZignRklSU1QnKSAhPT0gLTEpIHJldHVybiAnRklSU1QnO1xuICAgIGlmICh0cmF2ZWxDbGFzc2VzLmluZGV4T2YoJ1NFQ09ORCcpICE9PSAtMSkgcmV0dXJuICdTRUNPTkQnO1xuICAgIHJldHVybiAnQU5ZX0NMQVNTJztcbiAgfVxuXG4gIHByaXZhdGUgX3ByZXBhcmVEcml2ZXJBcmVhU2lkZU5hdmlnYXRpb24oXG4gICAgY29hY2hJdGVtOiBDb2FjaEl0ZW0sXG4gICk6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjb2FjaERyaXZlckFyZWFzID0gY29hY2hJdGVtLmdyYXBoaWNFbGVtZW50cz8uZmlsdGVyKFxuICAgICAgKGdyYXBoaWNhbEVsZW1lbnRzKSA9PiBncmFwaGljYWxFbGVtZW50cy5pY29uID09PSAnRFJJVkVSX0FSRUEnLFxuICAgICk7XG5cbiAgICBpZiAoY29hY2hEcml2ZXJBcmVhcyAmJiBjb2FjaERyaXZlckFyZWFzLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENoZWNraW5nIHRoZSBkcml2ZXIgYXJlYSBwb3NpdGlvbiB3aGV0aGVyIGl0IGlzIHByZXNlbnQgb24gdGhlIGxlZnQgb3IgcmlnaHQgc2lkZSBpbiBhIGNvYWNoXG4gICAgICBjb25zdCBoYXNMZWZ0RHJpdmVyQXJlYSA9XG4gICAgICAgIGNvYWNoRHJpdmVyQXJlYXMuZmluZCgoZHJpdmVyQXJlYUVsZW1lbnQpID0+IGRyaXZlckFyZWFFbGVtZW50LnBvc2l0aW9uLnggPT09IDApIHx8IGZhbHNlO1xuICAgICAgY29uc3QgaGFzUmlnaHREcml2ZXJBcmVhID1cbiAgICAgICAgY29hY2hEcml2ZXJBcmVhcy5maW5kKChkcml2ZXJBcmVhRWxlbWVudCkgPT4gZHJpdmVyQXJlYUVsZW1lbnQucG9zaXRpb24ueCA+IDApIHx8IGZhbHNlO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBsZWZ0OiAhIWhhc0xlZnREcml2ZXJBcmVhLFxuICAgICAgICByaWdodDogISFoYXNSaWdodERyaXZlckFyZWEsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBfcHJlcGFyZVNlcnZpY2VJY29uc05hdmlnYXRpb24gPSAocHJvcGVydHlJZHM6IHN0cmluZ1tdKTogc3RyaW5nW10gPT4ge1xuICAgIGlmICghcHJvcGVydHlJZHMpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBjb25zdCBzaHJ1bmtQcm9wZXJ0eUlkcyA9IHByb3BlcnR5SWRzXG4gICAgICA/Lm1hcChmdW5jdGlvbiAocHJvcGVydHlJZDogc3RyaW5nKToge1xuICAgICAgICBwSWQ6IHN0cmluZztcbiAgICAgICAgc3ZnTmFtZTogc3RyaW5nO1xuICAgICAgfSB7XG4gICAgICAgIC8vIHByZXBhcmUgdGVtcG9yYXJ5IG9iamVjdCBtYXBwaW5nIHByb3BlcnR5IGlkIHRvIGl0J3Mgc3ZnTmFtZSBzbyB0aGF0IHdlIGNhbiBjb21wYXJlIGl0IHRvIHRoZSBsaXN0IG9mIGFsbG93ZWQgaWNvbnNcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwSWQ6IHByb3BlcnR5SWQsXG4gICAgICAgICAgc3ZnTmFtZTogbWFwSWNvblRvU3ZnW3Byb3BlcnR5SWRdPy5zdmdOYW1lID8gbWFwSWNvblRvU3ZnW3Byb3BlcnR5SWRdPy5zdmdOYW1lIDogJycsXG4gICAgICAgIH07XG4gICAgICB9KVxuICAgICAgLy9maWx0ZXIgb3V0IG9iamVjdHMgc2VydmljZSBpY29ucyB3aGljaCBhcmUgbm90IGluIEFMTE9XRURfU0VSVklDRV9JQ09OU1xuICAgICAgLmZpbHRlcigocHJvcGVydHlUb1N2ZykgPT4gQUxMT1dFRF9TRVJWSUNFX0lDT05TLmluZGV4T2YocHJvcGVydHlUb1N2Zy5zdmdOYW1lKSAhPT0gLTEpXG4gICAgICAvL21ha2UgaXQgZGlzdGluY3QgYnkgc3ZnTmFtZVxuICAgICAgLmZpbHRlcihcbiAgICAgICAgKHZhbHVlLCBpbmRleCwgc2VsZikgPT5cbiAgICAgICAgICBzZWxmLm1hcCgocHJvcFN2ZykgPT4gcHJvcFN2Zy5zdmdOYW1lKS5pbmRleE9mKHZhbHVlLnN2Z05hbWUpID09PSBpbmRleCxcbiAgICAgIClcbiAgICAgIC8vIGdvIGJhY2sgdG8gcHJvcGVydHlJZCBzdHJpbmcgZnJvbSB0ZW1wb3Jhcnkgb2JqZWN0XG4gICAgICAubWFwKChwcm9wZXJ0eVRvU3ZnKSA9PiBwcm9wZXJ0eVRvU3ZnLnBJZClcbiAgICAgIC8vIHRha2UgZmlyc3QgTUFYX1NFUlZJQ0VfUFJPUEVSVElFUyByZWdhcmRsZXNzIG9mIHRoZSBpbnB1dCBmcm9tIEJhY2tlbmQsIG90aGVyd2lzZSB0aGUgbGF5b3V0IGNvdWxkIGJlIGRlc3Ryb3llZFxuICAgICAgLnNsaWNlKDAsIE1BWF9TRVJWSUNFX1BST1BFUlRJRVMpO1xuICAgIHJldHVybiBzaHJ1bmtQcm9wZXJ0eUlkcyA/IHNocnVua1Byb3BlcnR5SWRzIDogW107XG4gIH07XG5cbiAgcHJpdmF0ZSBfcHJlcGFyZUNvYWNoV2lkdGhBbmRHYXBDYWxjdWxhdGlvbnMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2VhdFJlc2VydmF0aW9ucykge1xuICAgICAgdGhpcy5zZWF0UmVzZXJ2YXRpb25zLmZvckVhY2goKHNlYXRSZXNlcnZhdGlvbjogU2VhdFJlc2VydmF0aW9uKSA9PiB7XG4gICAgICAgIHNlYXRSZXNlcnZhdGlvbj8uY29hY2hJdGVtcz8uZm9yRWFjaCgoY29hY2hJdGVtOiBDb2FjaEl0ZW0pID0+IHtcbiAgICAgICAgICBjb25zdCBoYXNPdmVyaGFuZ2luZ1BsYWNlcyA9IHRoaXMuX2lzT3ZlcmhhbmdpbmdFbGVtZW50c1ByZXNlbnQoXG4gICAgICAgICAgICBjb2FjaEl0ZW0uZGltZW5zaW9uLncsXG4gICAgICAgICAgICBjb2FjaEl0ZW0ucGxhY2VzLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICAvL011c3QgIGJlIGRvbmUgYWxzbyBmb3IgZ3JhcGhpY2FsIGVsZW1lbnRzLCBhcyB0aGV5IGNhbiBhbHNvIHByb3RydWRlIHRoZSBjb2FjaCBib3JkZXJcbiAgICAgICAgICAvLyBDaGVjayBvbmx5IGdyYXBoaWNhbCBlbGVtZW50cyB0aGF0IGFyZSBub3QgYXJlYSBlbGVtZW50c1xuICAgICAgICAgIGNvbnN0IGZpbHRlcmVkRWxlbWVudHMgPSBjb2FjaEl0ZW0uZ3JhcGhpY0VsZW1lbnRzPy5maWx0ZXIoXG4gICAgICAgICAgICAoZSkgPT4gZS5pY29uICYmICF0aGlzLm5vdEFyZWFFbGVtZW50cy5pbmNsdWRlcyhlLmljb24pLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBoYXNPdmVyaGFuZ2luZ0dyYXBoaWNBcmVhcyA9IHRoaXMuX2lzT3ZlcmhhbmdpbmdFbGVtZW50c1ByZXNlbnQoXG4gICAgICAgICAgICBjb2FjaEl0ZW0uZGltZW5zaW9uLncsXG4gICAgICAgICAgICBmaWx0ZXJlZEVsZW1lbnRzLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLm92ZXJIYW5naW5nRWxlbWVudEluZm9ybWF0aW9uLnB1c2goe1xuICAgICAgICAgICAgY29hY2hJZDogY29hY2hJdGVtLmlkLFxuICAgICAgICAgICAgb3ZlcmhhbmdpbmdQbGFjZXM6IGhhc092ZXJoYW5naW5nUGxhY2VzLFxuICAgICAgICAgICAgb3ZlcmhhbmdpbmdHcmFwaGljQXJlYXM6IGhhc092ZXJoYW5naW5nR3JhcGhpY0FyZWFzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHNlbGVjdGVkIHBsYWNlIEhUTUwgZWxlbWVudCBieSBjdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZC5cbiAgICogQHJldHVybnMgSFRNTEVsZW1lbnQgb3IgbnVsbFxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0UGxhY2VIdG1sRWxlbWVudCgpOiBIVE1MRWxlbWVudCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLmN1cnJTZWxlY3RlZFBsYWNlRWxlbWVudElkXG4gICAgICA/IHRoaXMuc2hhZG93Um9vdD8uZ2V0RWxlbWVudEJ5SWQodGhpcy5jdXJyU2VsZWN0ZWRQbGFjZUVsZW1lbnRJZCkgfHwgbnVsbFxuICAgICAgOiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGV4dHJhY3RlZCBjb2FjaCBkZWNrIGluZGV4IGZyb20gcGxhY2UgaWRcbiAgICogQHJldHVybnMgbnVtYmVyXG4gICAqL1xuICBwcml2YXRlIF9nZXREZWNrSW5kZXhCeVBsYWNlSWQocGxhY2VJZDogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgY29uc3QgZGVja0luZGV4ID0gdGhpcy5zaGFkb3dSb290XG4gICAgICA/LnF1ZXJ5U2VsZWN0b3IoJyMnICsgcGxhY2VJZClcbiAgICAgID8uZ2V0QXR0cmlidXRlKCdkYXRhLWRlY2staW5kZXgnKTtcbiAgICBpZiAoZGVja0luZGV4ICYmICFpc05hTigrZGVja0luZGV4KSkge1xuICAgICAgcmV0dXJuICtkZWNrSW5kZXg7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSBfaXNWYWxpZENvYWNoSW5kZXgoY29hY2hJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIGNvYWNoSW5kZXggPj0gMCAmJlxuICAgICAgY29hY2hJbmRleCA8PSB0aGlzLnNlYXRSZXNlcnZhdGlvbnNbdGhpcy5zZWF0UmVzZXJ2YXRpb25zLmxlbmd0aCAtIDFdLmNvYWNoSXRlbXMubGVuZ3RoXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGV4aXN0aW5nIGNvYWNoIGRlY2sgaW5kZXggZGVwZW5kaW5nIG9uIHRoZSBzZWxlY3RlZCBjb2FjaC5cbiAgICogVGhpcyBtZXRob2QgaXMgbmVjZXNzYXJ5IHRvIGdldCBhbiBhdmFpbGFibGUgY29hY2ggZGVjayBpbmRleCBkdXJpbmcga2V5Ym9hcmQgbmF2aWdhdGlvbiwgd2hpY2ggY2FuIHZhcnkgYmV0d2VlbiBjb2FjaGVzIHdpdGggZGlmZmVyZW50IGRlY2tzLlxuICAgKiBGb3IgZXhhbXBsZSwgd2hlbiBuYXZpZ2F0aW5nIGZyb20gYSBjb2FjaCB3aXRoIHR3byBkZWNrcyB0byBhIGNvYWNoIHdpdGggb25lIGRlY2suXG4gICAqXG4gICAqICAgICAgIFtvb29dLVtvb29dLVtvb29dXG4gICAqIFtvb29dLVtvb29dLVtvb29dLVtvb29dLVtvb29dXG4gICAqXG4gICAqIEByZXR1cm5zIG51bWJlclxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0RXhpc3RpbmdDb2FjaERlY2tJbmRleCgpOiBudW1iZXIge1xuICAgIGlmIChcbiAgICAgIHRoaXMuc2VhdFJlc2VydmF0aW9uc1t0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleF0uY29hY2hJdGVtc1t0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXhdXG4gICAgICAgIC5wbGFjZXMgIT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgcmV0dXJuIHRoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4O1xuICAgIH1cblxuICAgIC8vIEZpbmQgbmV4dCBwb3NzaWJsZSBjb2FjaCBkZWNrIGluZGV4IHdoZXJlIHBsYWNlcyBleGlzdFxuICAgIGNvbnN0IG5leHRBdmFpbGFibGVEZWNrQ29hY2hJbmRleCA9IHRoaXMuc2VhdFJlc2VydmF0aW9ucy5maW5kSW5kZXgoXG4gICAgICAoc2VhdFJlc2VydmF0aW9uKSA9PlxuICAgICAgICBzZWF0UmVzZXJ2YXRpb24uY29hY2hJdGVtc1t0aGlzLmN1cnJTZWxlY3RlZENvYWNoSW5kZXhdLnBsYWNlcyAhPT0gdW5kZWZpbmVkLFxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMuY3VyclNlbGVjdGVkRGVja0luZGV4ID49IG5leHRBdmFpbGFibGVEZWNrQ29hY2hJbmRleFxuICAgICAgPyB0aGlzLmN1cnJTZWxlY3RlZERlY2tJbmRleFxuICAgICAgOiBuZXh0QXZhaWxhYmxlRGVja0NvYWNoSW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogSWYgYSBzZWxlY3RlZCBwbGFjZSBpcyBzbGlnaHRseSBoaWRkZW4gYnkgdGhlIG92ZXJmbG93IHNjcm9sbCBjb250ZW50IGFuZCBpcyBzdGlsbCBjbGlja2VkLFxuICAgKiB0aGUgbWV0aG9kIHRyaWVzIHRvIHNjcm9sbCB0aGUgc2VsZWN0ZWQgcGxhY2UgaW50byB0aGUgbmVhcmVzdCB2aWV3cG9ydCwgc28gdGhhdCBpdCBpcyBjb21wbGV0ZWx5IHZpc2libGUuXG4gICAqXG4gICAqIEBwYXJhbSBwbGFjZUlkXG4gICAqL1xuICBwcml2YXRlIF9zY3JvbGxQbGFjZUludG9OZWFyZXN0Vmlld3BvcnQocGxhY2VJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5zaGFkb3dSb290XG4gICAgICA/LmdldEVsZW1lbnRCeUlkKHBsYWNlSWQpXG4gICAgICA/LnNjcm9sbEludG9WaWV3KHsgYmVoYXZpb3I6ICdzbW9vdGgnLCBibG9jazogJ25lYXJlc3QnLCBpbmxpbmU6ICduZWFyZXN0JyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjaGVja3MgaWYgYW55IHBsYWNlcyBvciBncmFwaGljYWwgZWxlbWVudHMgKGUuZy4gdG9pbGV0IGFyZWEsIGV0Yy4pIGFyZSBvdmVyaGFuZ2luZyB0aGUgY29hY2ggYm9yZGVyc1xuICAgKiBAcGFyYW0gY29hY2hJdGVtV2lkdGhcbiAgICogQHBhcmFtIGVsZW1lbnRzXG4gICAqL1xuICBwcml2YXRlIF9pc092ZXJoYW5naW5nRWxlbWVudHNQcmVzZW50KFxuICAgIGNvYWNoSXRlbVdpZHRoOiBudW1iZXIsXG4gICAgZWxlbWVudHM6IChQbGFjZSB8IEJhc2VFbGVtZW50KVtdIHwgdW5kZWZpbmVkLFxuICApOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgZWxlbWVudHM/LnNvbWUoXG4gICAgICAgIChlbGVtZW50KSA9PlxuICAgICAgICAgIGVsZW1lbnQucG9zaXRpb24ueCA9PT0gMCB8fCBlbGVtZW50LnBvc2l0aW9uLnggKyBlbGVtZW50LmRpbWVuc2lvbi53ID49IGNvYWNoSXRlbVdpZHRoLFxuICAgICAgKSA/PyBmYWxzZVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogY29sbGVjdCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZHJpdmVyQXJlYXMgZm9yIG9uZSBjb2FjaFxuICAgKiBAcGFyYW0gY29hY2hJdGVtXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIF9zZXREcml2ZXJBcmVhc0VsZW1lbnRzKGNvYWNoSXRlbTogQ29hY2hJdGVtKToge1xuICAgIGRyaXZlckFyZWE6IEJhc2VFbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgIGRyaXZlckFyZWFOb1ZlcnRpY2FsV2FsbDogQmFzZUVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gIH0ge1xuICAgIGlmIChjb2FjaEl0ZW0pIHtcbiAgICAgIGNvbnN0IGRyaXZlckFyZWEgPSBjb2FjaEl0ZW0uZ3JhcGhpY0VsZW1lbnRzPy5maW5kKFxuICAgICAgICAoZWxlbWVudDogQmFzZUVsZW1lbnQpID0+IGVsZW1lbnQuaWNvbiA9PT0gJ0RSSVZFUl9BUkVBJyxcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRyaXZlckFyZWFOb1ZlcnRpY2FsV2FsbCA9XG4gICAgICAgIGNvYWNoSXRlbS50eXBlID09PSAnTE9DT01PVElWRV9DT0FDSCdcbiAgICAgICAgICA/IGNvYWNoSXRlbS5ncmFwaGljRWxlbWVudHM/LmZpbmQoXG4gICAgICAgICAgICAgIChlbGVtZW50OiBCYXNlRWxlbWVudCkgPT4gZWxlbWVudC5pY29uID09PSAnRFJJVkVSX0FSRUFfTk9fVkVSVElDQUxfV0FMTCcsXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRyaXZlckFyZWE6IGRyaXZlckFyZWEsXG4gICAgICAgIGRyaXZlckFyZWFOb1ZlcnRpY2FsV2FsbDogZHJpdmVyQXJlYU5vVmVydGljYWxXYWxsLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZHJpdmVyQXJlYTogdW5kZWZpbmVkLFxuICAgICAgZHJpdmVyQXJlYU5vVmVydGljYWxXYWxsOiB1bmRlZmluZWQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJcyBjYWxsZWQgd2hlbiB0aGUgU2VhdFJlc2VydmF0aW9uIGxvc2VzIGZvY3VzLCB3aGF0IGhhcHBlbnMgd2hlbiB0aGUgdXNlciB0YWJzIG91dCBvciBjbGlja3Mgc29tZXdoZXJlIGVsc2UuXG4gICAqIFRoZW4gd2UgcmVzZXQgdGhlIGZvY3VzZWQgZWxlbWVudHMuXG4gICAqL1xuICBwcml2YXRlIF9vbkxlYXZlU2VhdFJlc2VydmF0aW9uQ29tcG9uZW50KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmhhc05hdmlnYXRpb24pIHtcbiAgICAgIHRoaXMuZm9jdXNlZENvYWNoSW5kZXggPSAtMTtcbiAgICB9XG4gICAgdGhpcy51bmZvY3VzUGxhY2VFbGVtZW50KCk7XG4gIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUE4QkEsSUFBSztDQUFMLFNBQUssaUJBQWU7QUFDbEIsaUJBQUEsV0FBQTtBQUNBLGlCQUFBLFVBQUE7R0FGRyxvQkFBQSxrQkFBZSxFQUFBLEVBQUE7QUFXcEIsSUFBTSx5QkFBeUI7QUFDL0IsSUFBTSx3QkFBa0M7Q0FDdEM7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDRDtJQUVZLG9DQUEwQjttQkFBUzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2NBQW5DLG1DQUFtQyxZQUFVOzs7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