@sbb-esta/lyne-elements-experimental 4.7.0 → 4.8.0

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