@igo2/geo 1.14.3 → 1.14.4

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 (876) hide show
  1. package/assets/icons/cross_black_18px.svg +88 -88
  2. package/assets/icons/place_blue_36px.svg +55 -55
  3. package/assets/icons/place_green_36px.svg +55 -55
  4. package/assets/icons/place_red_36px.svg +55 -55
  5. package/assets/icons/place_yellow_36px.svg +55 -55
  6. package/esm2020/igo2-geo.mjs +4 -4
  7. package/esm2020/lib/catalog/catalog-browser/catalog-browser-group.component.mjs +300 -300
  8. package/esm2020/lib/catalog/catalog-browser/catalog-browser-layer.component.mjs +305 -305
  9. package/esm2020/lib/catalog/catalog-browser/catalog-browser.component.mjs +246 -246
  10. package/esm2020/lib/catalog/catalog-browser/catalog-browser.module.mjs +79 -79
  11. package/esm2020/lib/catalog/catalog-library/add-catalog-dialog.component.mjs +208 -208
  12. package/esm2020/lib/catalog/catalog-library/catalog-library-item.component.mjs +78 -78
  13. package/esm2020/lib/catalog/catalog-library/catalog-library.component.mjs +216 -216
  14. package/esm2020/lib/catalog/catalog-library/catalog-library.module.mjs +94 -94
  15. package/esm2020/lib/catalog/catalog.module.mjs +52 -52
  16. package/esm2020/lib/catalog/index.mjs +4 -4
  17. package/esm2020/lib/catalog/shared/catalog.abstract.mjs +94 -94
  18. package/esm2020/lib/catalog/shared/catalog.enum.mjs +15 -15
  19. package/esm2020/lib/catalog/shared/catalog.interface.mjs +1 -1
  20. package/esm2020/lib/catalog/shared/catalog.service.mjs +605 -605
  21. package/esm2020/lib/catalog/shared/index.mjs +5 -5
  22. package/esm2020/lib/datasource/datasource.module.mjs +21 -21
  23. package/esm2020/lib/datasource/index.mjs +3 -3
  24. package/esm2020/lib/datasource/shared/capabilities.service.mjs +431 -431
  25. package/esm2020/lib/datasource/shared/datasource.service.mjs +235 -235
  26. package/esm2020/lib/datasource/shared/datasources/any-datasource.interface.mjs +1 -1
  27. package/esm2020/lib/datasource/shared/datasources/any-datasource.mjs +1 -1
  28. package/esm2020/lib/datasource/shared/datasources/arcgisrest-datasource.interface.mjs +1 -1
  29. package/esm2020/lib/datasource/shared/datasources/arcgisrest-datasource.mjs +144 -144
  30. package/esm2020/lib/datasource/shared/datasources/carto-datasource.interface.mjs +1 -1
  31. package/esm2020/lib/datasource/shared/datasources/carto-datasource.mjs +108 -108
  32. package/esm2020/lib/datasource/shared/datasources/cluster-datasource.interface.mjs +1 -1
  33. package/esm2020/lib/datasource/shared/datasources/cluster-datasource.mjs +14 -14
  34. package/esm2020/lib/datasource/shared/datasources/data.service.mjs +2 -2
  35. package/esm2020/lib/datasource/shared/datasources/datasource.interface.mjs +1 -1
  36. package/esm2020/lib/datasource/shared/datasources/datasource.mjs +28 -28
  37. package/esm2020/lib/datasource/shared/datasources/feature-datasource.interface.mjs +1 -1
  38. package/esm2020/lib/datasource/shared/datasources/feature-datasource.mjs +42 -42
  39. package/esm2020/lib/datasource/shared/datasources/imagearcgisrest-datasource.interface.mjs +1 -1
  40. package/esm2020/lib/datasource/shared/datasources/imagearcgisrest-datasource.mjs +56 -56
  41. package/esm2020/lib/datasource/shared/datasources/index.mjs +36 -36
  42. package/esm2020/lib/datasource/shared/datasources/mvt-datasource.interface.mjs +1 -1
  43. package/esm2020/lib/datasource/shared/datasources/mvt-datasource.mjs +27 -27
  44. package/esm2020/lib/datasource/shared/datasources/osm-datasource.interface.mjs +1 -1
  45. package/esm2020/lib/datasource/shared/datasources/osm-datasource.mjs +11 -11
  46. package/esm2020/lib/datasource/shared/datasources/tilearcgisrest-datasource.interface.mjs +1 -1
  47. package/esm2020/lib/datasource/shared/datasources/tilearcgisrest-datasource.mjs +48 -48
  48. package/esm2020/lib/datasource/shared/datasources/tiledebug-datasource.interface.mjs +1 -1
  49. package/esm2020/lib/datasource/shared/datasources/tiledebug-datasource.mjs +14 -14
  50. package/esm2020/lib/datasource/shared/datasources/websocket-datasource.interface.mjs +1 -1
  51. package/esm2020/lib/datasource/shared/datasources/websocket-datasource.mjs +53 -53
  52. package/esm2020/lib/datasource/shared/datasources/wfs-datasource.interface.mjs +1 -1
  53. package/esm2020/lib/datasource/shared/datasources/wfs-datasource.mjs +71 -71
  54. package/esm2020/lib/datasource/shared/datasources/wfs.service.mjs +151 -151
  55. package/esm2020/lib/datasource/shared/datasources/wms-datasource.interface.mjs +1 -1
  56. package/esm2020/lib/datasource/shared/datasources/wms-datasource.mjs +205 -205
  57. package/esm2020/lib/datasource/shared/datasources/wms-wfs.utils.mjs +206 -206
  58. package/esm2020/lib/datasource/shared/datasources/wmts-datasource.interface.mjs +1 -1
  59. package/esm2020/lib/datasource/shared/datasources/wmts-datasource.mjs +15 -15
  60. package/esm2020/lib/datasource/shared/datasources/xyz-datasource.interface.mjs +1 -1
  61. package/esm2020/lib/datasource/shared/datasources/xyz-datasource.mjs +8 -8
  62. package/esm2020/lib/datasource/shared/index.mjs +4 -4
  63. package/esm2020/lib/datasource/shared/options/index.mjs +4 -4
  64. package/esm2020/lib/datasource/shared/options/options-api.interface.mjs +1 -1
  65. package/esm2020/lib/datasource/shared/options/options-api.providers.mjs +14 -14
  66. package/esm2020/lib/datasource/shared/options/options-api.service.mjs +80 -80
  67. package/esm2020/lib/datasource/shared/options/options.service.mjs +2 -2
  68. package/esm2020/lib/datasource/utils/esri-style-generator.mjs +356 -356
  69. package/esm2020/lib/datasource/utils/index.mjs +2 -2
  70. package/esm2020/lib/datasource/utils/tilegrid.mjs +19 -19
  71. package/esm2020/lib/directions/directions-buttons/directions-buttons.component.mjs +223 -223
  72. package/esm2020/lib/directions/directions-buttons/index.mjs +2 -2
  73. package/esm2020/lib/directions/directions-inputs/directions-inputs.component.mjs +289 -289
  74. package/esm2020/lib/directions/directions-inputs/index.mjs +2 -2
  75. package/esm2020/lib/directions/directions-results/directions-results.component.mjs +195 -195
  76. package/esm2020/lib/directions/directions-results/index.mjs +2 -2
  77. package/esm2020/lib/directions/directions-sources/directions-source.interface.mjs +1 -1
  78. package/esm2020/lib/directions/directions-sources/directions-source.mjs +2 -2
  79. package/esm2020/lib/directions/directions-sources/directions-source.provider.mjs +15 -15
  80. package/esm2020/lib/directions/directions-sources/index.mjs +5 -5
  81. package/esm2020/lib/directions/directions-sources/osrm-directions-source.mjs +99 -99
  82. package/esm2020/lib/directions/directions.component.mjs +310 -310
  83. package/esm2020/lib/directions/directions.module.mjs +101 -101
  84. package/esm2020/lib/directions/index.mjs +7 -7
  85. package/esm2020/lib/directions/shared/directions-source.service.mjs +17 -17
  86. package/esm2020/lib/directions/shared/directions.enum.mjs +28 -28
  87. package/esm2020/lib/directions/shared/directions.interface.mjs +1 -1
  88. package/esm2020/lib/directions/shared/directions.service.mjs +28 -28
  89. package/esm2020/lib/directions/shared/directions.utils.mjs +508 -508
  90. package/esm2020/lib/directions/shared/index.mjs +6 -6
  91. package/esm2020/lib/directions/shared/store.mjs +23 -23
  92. package/esm2020/lib/download/download-button/download-button.component.mjs +60 -60
  93. package/esm2020/lib/download/download-button/index.mjs +2 -2
  94. package/esm2020/lib/download/download.module.mjs +41 -41
  95. package/esm2020/lib/download/index.mjs +3 -3
  96. package/esm2020/lib/download/shared/download.interface.mjs +2 -2
  97. package/esm2020/lib/download/shared/download.service.mjs +64 -64
  98. package/esm2020/lib/download/shared/index.mjs +3 -3
  99. package/esm2020/lib/draw/draw/draw-layer-popup.component.mjs +54 -54
  100. package/esm2020/lib/draw/draw/draw-popup.component.mjs +590 -590
  101. package/esm2020/lib/draw/draw/draw-shorcuts.component.mjs +47 -47
  102. package/esm2020/lib/draw/draw/draw.component.mjs +1298 -1298
  103. package/esm2020/lib/draw/draw/draw.module.mjs +112 -112
  104. package/esm2020/lib/draw/drawingTool.module.mjs +19 -19
  105. package/esm2020/lib/draw/index.mjs +3 -3
  106. package/esm2020/lib/draw/shared/draw-icon.service.mjs +26 -26
  107. package/esm2020/lib/draw/shared/draw-style.service.mjs +189 -189
  108. package/esm2020/lib/draw/shared/draw.enum.mjs +36 -36
  109. package/esm2020/lib/draw/shared/draw.interface.mjs +1 -1
  110. package/esm2020/lib/draw/shared/draw.utils.mjs +121 -121
  111. package/esm2020/lib/draw/shared/index.mjs +5 -5
  112. package/esm2020/lib/feature/feature-details/feature-details.component.mjs +404 -404
  113. package/esm2020/lib/feature/feature-details/feature-details.directive.mjs +53 -53
  114. package/esm2020/lib/feature/feature-details/feature-details.module.mjs +47 -47
  115. package/esm2020/lib/feature/feature-form/feature-form.component.mjs +111 -111
  116. package/esm2020/lib/feature/feature-form/feature-form.module.mjs +33 -33
  117. package/esm2020/lib/feature/feature.module.mjs +27 -27
  118. package/esm2020/lib/feature/index.mjs +3 -3
  119. package/esm2020/lib/feature/shared/feature.enums.mjs +9 -9
  120. package/esm2020/lib/feature/shared/feature.interfaces.mjs +1 -1
  121. package/esm2020/lib/feature/shared/feature.utils.mjs +346 -346
  122. package/esm2020/lib/feature/shared/index.mjs +6 -6
  123. package/esm2020/lib/feature/shared/store.mjs +123 -123
  124. package/esm2020/lib/feature/shared/strategies/in-map-extent.mjs +112 -112
  125. package/esm2020/lib/feature/shared/strategies/in-map-resolution.mjs +93 -93
  126. package/esm2020/lib/feature/shared/strategies/index.mjs +5 -5
  127. package/esm2020/lib/feature/shared/strategies/loading-layer.mjs +103 -103
  128. package/esm2020/lib/feature/shared/strategies/loading.mjs +132 -132
  129. package/esm2020/lib/feature/shared/strategies/selection.mjs +369 -369
  130. package/esm2020/lib/feature/shared/strategies.utils.mjs +36 -36
  131. package/esm2020/lib/filter/filter.module.mjs +288 -288
  132. package/esm2020/lib/filter/index.mjs +15 -15
  133. package/esm2020/lib/filter/ogc-filter-button/index.mjs +1 -1
  134. package/esm2020/lib/filter/ogc-filter-button/ogc-filter-button.component.mjs +139 -139
  135. package/esm2020/lib/filter/ogc-filter-form/index.mjs +1 -1
  136. package/esm2020/lib/filter/ogc-filter-form/ogc-filter-form.component.mjs +644 -644
  137. package/esm2020/lib/filter/ogc-filter-selection/index.mjs +1 -1
  138. package/esm2020/lib/filter/ogc-filter-selection/ogc-filter-selection.component.mjs +1301 -1301
  139. package/esm2020/lib/filter/ogc-filter-time/index.mjs +2 -2
  140. package/esm2020/lib/filter/ogc-filter-time/ogc-filter-time-slider.component.mjs +176 -176
  141. package/esm2020/lib/filter/ogc-filter-time/ogc-filter-time.component.mjs +897 -897
  142. package/esm2020/lib/filter/ogc-filterable-form/index.mjs +1 -1
  143. package/esm2020/lib/filter/ogc-filterable-form/ogc-filterable-form.component.mjs +58 -58
  144. package/esm2020/lib/filter/ogc-filterable-item/index.mjs +1 -1
  145. package/esm2020/lib/filter/ogc-filterable-item/ogc-filterable-item.component.mjs +306 -306
  146. package/esm2020/lib/filter/ogc-filterable-list/index.mjs +2 -2
  147. package/esm2020/lib/filter/ogc-filterable-list/ogc-filterable-list-binding.directive.mjs +30 -30
  148. package/esm2020/lib/filter/ogc-filterable-list/ogc-filterable-list.component.mjs +43 -43
  149. package/esm2020/lib/filter/shared/filterable-datasource.pipe.mjs +54 -54
  150. package/esm2020/lib/filter/shared/index.mjs +11 -11
  151. package/esm2020/lib/filter/shared/ogc-filter-time.service.mjs +71 -71
  152. package/esm2020/lib/filter/shared/ogc-filter.enum.mjs +29 -29
  153. package/esm2020/lib/filter/shared/ogc-filter.interface.mjs +1 -1
  154. package/esm2020/lib/filter/shared/ogc-filter.mjs +691 -691
  155. package/esm2020/lib/filter/shared/ogc-filter.service.mjs +45 -45
  156. package/esm2020/lib/filter/shared/spatial-filter.enum.mjs +22 -22
  157. package/esm2020/lib/filter/shared/spatial-filter.interface.mjs +1 -1
  158. package/esm2020/lib/filter/shared/spatial-filter.service.mjs +268 -268
  159. package/esm2020/lib/filter/shared/time-filter.enum.mjs +12 -12
  160. package/esm2020/lib/filter/shared/time-filter.interface.mjs +1 -1
  161. package/esm2020/lib/filter/shared/time-filter.service.mjs +106 -106
  162. package/esm2020/lib/filter/spatial-filter/spatial-filter-item/index.mjs +1 -1
  163. package/esm2020/lib/filter/spatial-filter/spatial-filter-item/spatial-filter-item.component.mjs +1088 -1088
  164. package/esm2020/lib/filter/spatial-filter/spatial-filter-list/index.mjs +1 -1
  165. package/esm2020/lib/filter/spatial-filter/spatial-filter-list/spatial-filter-list.component.mjs +207 -207
  166. package/esm2020/lib/filter/spatial-filter/spatial-filter-type/index.mjs +1 -1
  167. package/esm2020/lib/filter/spatial-filter/spatial-filter-type/spatial-filter-type.component.mjs +143 -143
  168. package/esm2020/lib/filter/time-filter-button/index.mjs +1 -1
  169. package/esm2020/lib/filter/time-filter-button/time-filter-button.component.mjs +77 -77
  170. package/esm2020/lib/filter/time-filter-form/index.mjs +1 -1
  171. package/esm2020/lib/filter/time-filter-form/time-filter-form.component.mjs +733 -733
  172. package/esm2020/lib/filter/time-filter-item/index.mjs +1 -1
  173. package/esm2020/lib/filter/time-filter-item/time-filter-item.component.mjs +118 -118
  174. package/esm2020/lib/filter/time-filter-list/index.mjs +2 -2
  175. package/esm2020/lib/filter/time-filter-list/time-filter-list-binding.directive.mjs +30 -30
  176. package/esm2020/lib/filter/time-filter-list/time-filter-list.component.mjs +38 -38
  177. package/esm2020/lib/geo.module.mjs +101 -101
  178. package/esm2020/lib/geometry/geometry-form-field/geometry-form-field-input.component.mjs +520 -520
  179. package/esm2020/lib/geometry/geometry-form-field/geometry-form-field.component.mjs +188 -188
  180. package/esm2020/lib/geometry/geometry-form-field/geometry-form-field.module.mjs +63 -63
  181. package/esm2020/lib/geometry/geometry.module.mjs +26 -26
  182. package/esm2020/lib/geometry/index.mjs +3 -3
  183. package/esm2020/lib/geometry/shared/controls/draw.mjs +313 -313
  184. package/esm2020/lib/geometry/shared/controls/index.mjs +4 -4
  185. package/esm2020/lib/geometry/shared/controls/modify.mjs +520 -520
  186. package/esm2020/lib/geometry/shared/controls/slice.mjs +176 -176
  187. package/esm2020/lib/geometry/shared/geometry.errors.mjs +25 -25
  188. package/esm2020/lib/geometry/shared/geometry.interfaces.mjs +1 -1
  189. package/esm2020/lib/geometry/shared/geometry.utils.mjs +121 -121
  190. package/esm2020/lib/geometry/shared/index.mjs +5 -5
  191. package/esm2020/lib/import-export/export-button/export-button.component.mjs +63 -63
  192. package/esm2020/lib/import-export/export-button/index.mjs +2 -2
  193. package/esm2020/lib/import-export/import-export/import-export.component.mjs +1219 -1219
  194. package/esm2020/lib/import-export/import-export/index.mjs +2 -2
  195. package/esm2020/lib/import-export/import-export.module.mjs +95 -95
  196. package/esm2020/lib/import-export/index.mjs +4 -4
  197. package/esm2020/lib/import-export/shared/drop-geo-file.directive.mjs +134 -134
  198. package/esm2020/lib/import-export/shared/export.errors.mjs +15 -15
  199. package/esm2020/lib/import-export/shared/export.interface.mjs +1 -1
  200. package/esm2020/lib/import-export/shared/export.service.mjs +194 -194
  201. package/esm2020/lib/import-export/shared/export.type.mjs +3 -3
  202. package/esm2020/lib/import-export/shared/export.utils.mjs +54 -54
  203. package/esm2020/lib/import-export/shared/import.errors.mjs +38 -38
  204. package/esm2020/lib/import-export/shared/import.interface.mjs +1 -1
  205. package/esm2020/lib/import-export/shared/import.service.mjs +214 -214
  206. package/esm2020/lib/import-export/shared/import.utils.mjs +234 -234
  207. package/esm2020/lib/import-export/shared/index.mjs +11 -11
  208. package/esm2020/lib/import-export/style-list/index.mjs +4 -4
  209. package/esm2020/lib/import-export/style-list/style-list.interface.mjs +1 -1
  210. package/esm2020/lib/import-export/style-list/style-list.module.mjs +22 -22
  211. package/esm2020/lib/import-export/style-list/style-list.provider.mjs +20 -20
  212. package/esm2020/lib/import-export/style-list/style-list.service.mjs +50 -50
  213. package/esm2020/lib/layer/index.mjs +10 -10
  214. package/esm2020/lib/layer/layer-item/index.mjs +1 -1
  215. package/esm2020/lib/layer/layer-item/layer-item.component.mjs +299 -299
  216. package/esm2020/lib/layer/layer-legend/index.mjs +1 -1
  217. package/esm2020/lib/layer/layer-legend/layer-legend.component.mjs +387 -387
  218. package/esm2020/lib/layer/layer-legend-item/index.mjs +1 -1
  219. package/esm2020/lib/layer/layer-legend-item/layer-legend-item.component.mjs +83 -83
  220. package/esm2020/lib/layer/layer-legend-list/index.mjs +2 -2
  221. package/esm2020/lib/layer/layer-legend-list/layer-legend-list-binding.directive.mjs +47 -47
  222. package/esm2020/lib/layer/layer-legend-list/layer-legend-list.component.mjs +194 -194
  223. package/esm2020/lib/layer/layer-list/index.mjs +3 -3
  224. package/esm2020/lib/layer/layer-list/layer-list-binding.directive.mjs +58 -58
  225. package/esm2020/lib/layer/layer-list/layer-list.component.mjs +1008 -1008
  226. package/esm2020/lib/layer/layer-list/layer-list.enum.mjs +18 -18
  227. package/esm2020/lib/layer/layer-list-tool/index.mjs +4 -4
  228. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.component.mjs +164 -164
  229. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.enum.mjs +6 -6
  230. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.interface.mjs +1 -1
  231. package/esm2020/lib/layer/layer-list-tool/layer-list-tool.service.mjs +21 -21
  232. package/esm2020/lib/layer/layer.module.mjs +184 -184
  233. package/esm2020/lib/layer/shared/clusterParam.mjs +1 -1
  234. package/esm2020/lib/layer/shared/index.mjs +6 -6
  235. package/esm2020/lib/layer/shared/layer.enums.mjs +1 -1
  236. package/esm2020/lib/layer/shared/layer.service.mjs +185 -185
  237. package/esm2020/lib/layer/shared/layers/any-layer.interface.mjs +1 -1
  238. package/esm2020/lib/layer/shared/layers/any-layer.mjs +1 -1
  239. package/esm2020/lib/layer/shared/layers/image-layer.interface.mjs +1 -1
  240. package/esm2020/lib/layer/shared/layers/image-layer.mjs +67 -67
  241. package/esm2020/lib/layer/shared/layers/index.mjs +13 -13
  242. package/esm2020/lib/layer/shared/layers/layer.interface.mjs +16 -16
  243. package/esm2020/lib/layer/shared/layers/layer.mjs +163 -163
  244. package/esm2020/lib/layer/shared/layers/tile-layer.interface.mjs +1 -1
  245. package/esm2020/lib/layer/shared/layers/tile-layer.mjs +46 -46
  246. package/esm2020/lib/layer/shared/layers/vector-layer.interface.mjs +1 -1
  247. package/esm2020/lib/layer/shared/layers/vector-layer.mjs +377 -377
  248. package/esm2020/lib/layer/shared/layers/vectortile-layer.interface.mjs +1 -1
  249. package/esm2020/lib/layer/shared/layers/vectortile-layer.mjs +103 -103
  250. package/esm2020/lib/layer/shared/style.service.mjs +355 -355
  251. package/esm2020/lib/layer/shared/vector-style.interface.mjs +1 -1
  252. package/esm2020/lib/layer/style-modal/index.mjs +1 -1
  253. package/esm2020/lib/layer/style-modal/style-modal.component.mjs +287 -287
  254. package/esm2020/lib/layer/track-feature-button/index.mjs +1 -1
  255. package/esm2020/lib/layer/track-feature-button/track-feature-button.component.mjs +58 -58
  256. package/esm2020/lib/layer/utils/image-watcher.mjs +61 -61
  257. package/esm2020/lib/layer/utils/index.mjs +5 -5
  258. package/esm2020/lib/layer/utils/layer.utils.mjs +9 -9
  259. package/esm2020/lib/layer/utils/outputLegend.mjs +26 -26
  260. package/esm2020/lib/layer/utils/tile-watcher.mjs +49 -49
  261. package/esm2020/lib/layer/utils/vector-watcher.mjs +47 -47
  262. package/esm2020/lib/map/baselayers-switcher/baselayers-switcher.animation.mjs +19 -19
  263. package/esm2020/lib/map/baselayers-switcher/baselayers-switcher.component.mjs +96 -96
  264. package/esm2020/lib/map/baselayers-switcher/index.mjs +2 -2
  265. package/esm2020/lib/map/baselayers-switcher/mini-basemap.component.mjs +140 -140
  266. package/esm2020/lib/map/geolocate-button/geolocate-button.component.mjs +78 -78
  267. package/esm2020/lib/map/geolocate-button/index.mjs +1 -1
  268. package/esm2020/lib/map/home-extent-button/home-extent-button.component.mjs +62 -62
  269. package/esm2020/lib/map/home-extent-button/index.mjs +1 -1
  270. package/esm2020/lib/map/index.mjs +13 -13
  271. package/esm2020/lib/map/info-section/index.mjs +1 -1
  272. package/esm2020/lib/map/info-section/info-section.component.mjs +29 -29
  273. package/esm2020/lib/map/map-browser/index.mjs +1 -1
  274. package/esm2020/lib/map/map-browser/map-browser.component.mjs +65 -65
  275. package/esm2020/lib/map/map-center/index.mjs +1 -1
  276. package/esm2020/lib/map/map-center/map-center.component.mjs +49 -49
  277. package/esm2020/lib/map/map.module.mjs +126 -126
  278. package/esm2020/lib/map/menu-button/index.mjs +1 -1
  279. package/esm2020/lib/map/menu-button/menu-button.component.mjs +61 -61
  280. package/esm2020/lib/map/offline-button/index.mjs +1 -1
  281. package/esm2020/lib/map/offline-button/offline-button.component.mjs +75 -75
  282. package/esm2020/lib/map/rotation-button/index.mjs +1 -1
  283. package/esm2020/lib/map/rotation-button/rotation-button.component.mjs +69 -69
  284. package/esm2020/lib/map/shared/controllers/controller.mjs +41 -41
  285. package/esm2020/lib/map/shared/controllers/geolocation.mjs +307 -307
  286. package/esm2020/lib/map/shared/controllers/index.mjs +3 -3
  287. package/esm2020/lib/map/shared/controllers/view.mjs +350 -350
  288. package/esm2020/lib/map/shared/hover-feature.directive.mjs +502 -502
  289. package/esm2020/lib/map/shared/index.mjs +13 -13
  290. package/esm2020/lib/map/shared/linkedLayers.utils.mjs +237 -237
  291. package/esm2020/lib/map/shared/map-pointer-position.directive.mjs +106 -106
  292. package/esm2020/lib/map/shared/map.enums.mjs +5 -5
  293. package/esm2020/lib/map/shared/map.interface.mjs +1 -1
  294. package/esm2020/lib/map/shared/map.mjs +412 -407
  295. package/esm2020/lib/map/shared/map.service.mjs +28 -28
  296. package/esm2020/lib/map/shared/map.utils.mjs +462 -462
  297. package/esm2020/lib/map/shared/mapOffline.directive.mjs +162 -162
  298. package/esm2020/lib/map/shared/projection.interfaces.mjs +1 -1
  299. package/esm2020/lib/map/shared/projection.service.mjs +64 -64
  300. package/esm2020/lib/map/shared/projection.utils.mjs +63 -63
  301. package/esm2020/lib/map/swipe-control/index.mjs +1 -1
  302. package/esm2020/lib/map/swipe-control/swipe-control.component.mjs +192 -192
  303. package/esm2020/lib/map/utils/layer-watcher.mjs +78 -78
  304. package/esm2020/lib/map/wake-lock-button/index.mjs +1 -1
  305. package/esm2020/lib/map/wake-lock-button/wake-lock-button.component.mjs +113 -113
  306. package/esm2020/lib/map/zoom-button/index.mjs +1 -1
  307. package/esm2020/lib/map/zoom-button/zoom-button.component.mjs +39 -39
  308. package/esm2020/lib/measure/index.mjs +3 -3
  309. package/esm2020/lib/measure/measure.module.mjs +19 -19
  310. package/esm2020/lib/measure/measurer/measure-format.pipe.mjs +36 -36
  311. package/esm2020/lib/measure/measurer/measurer-dialog.component.mjs +179 -179
  312. package/esm2020/lib/measure/measurer/measurer-item.component.mjs +139 -139
  313. package/esm2020/lib/measure/measurer/measurer.component.mjs +1041 -1041
  314. package/esm2020/lib/measure/measurer/measurer.module.mjs +93 -93
  315. package/esm2020/lib/measure/shared/index.mjs +4 -4
  316. package/esm2020/lib/measure/shared/measure.enum.mjs +36 -36
  317. package/esm2020/lib/measure/shared/measure.interfaces.mjs +1 -1
  318. package/esm2020/lib/measure/shared/measure.utils.mjs +488 -488
  319. package/esm2020/lib/metadata/index.mjs +2 -2
  320. package/esm2020/lib/metadata/metadata-button/index.mjs +2 -2
  321. package/esm2020/lib/metadata/metadata-button/metadata-button.component.mjs +134 -134
  322. package/esm2020/lib/metadata/metadata.module.mjs +54 -54
  323. package/esm2020/lib/metadata/shared/index.mjs +3 -3
  324. package/esm2020/lib/metadata/shared/metadata.interface.mjs +1 -1
  325. package/esm2020/lib/metadata/shared/metadata.service.mjs +19 -19
  326. package/esm2020/lib/offline/geoDB/configFileToGeoDB.service.mjs +104 -104
  327. package/esm2020/lib/offline/geoDB/geoDB.enums.mjs +5 -5
  328. package/esm2020/lib/offline/geoDB/geoDB.interface.mjs +1 -1
  329. package/esm2020/lib/offline/geoDB/geoDB.service.mjs +166 -166
  330. package/esm2020/lib/offline/geoDB/index.mjs +5 -5
  331. package/esm2020/lib/offline/index.mjs +2 -2
  332. package/esm2020/lib/offline/shared/geo-network.service.mjs +65 -65
  333. package/esm2020/lib/offline/shared/index.mjs +2 -2
  334. package/esm2020/lib/overlay/index.mjs +2 -2
  335. package/esm2020/lib/overlay/overlay.module.mjs +22 -22
  336. package/esm2020/lib/overlay/shared/index.mjs +6 -6
  337. package/esm2020/lib/overlay/shared/overlay-marker-style.utils.mjs +68 -68
  338. package/esm2020/lib/overlay/shared/overlay.directive.mjs +32 -32
  339. package/esm2020/lib/overlay/shared/overlay.enum.mjs +7 -7
  340. package/esm2020/lib/overlay/shared/overlay.mjs +129 -129
  341. package/esm2020/lib/overlay/shared/overlay.service.mjs +26 -26
  342. package/esm2020/lib/overlay/shared/overlay.utils.mjs +102 -102
  343. package/esm2020/lib/print/index.mjs +4 -4
  344. package/esm2020/lib/print/print/print.component.mjs +125 -125
  345. package/esm2020/lib/print/print-form/index.mjs +2 -2
  346. package/esm2020/lib/print/print-form/print-form.component.mjs +427 -427
  347. package/esm2020/lib/print/print.module.mjs +64 -64
  348. package/esm2020/lib/print/shared/geopdf.mjs +57 -57
  349. package/esm2020/lib/print/shared/index.mjs +5 -5
  350. package/esm2020/lib/print/shared/print.interface.mjs +1 -1
  351. package/esm2020/lib/print/shared/print.service.mjs +933 -933
  352. package/esm2020/lib/print/shared/print.type.mjs +29 -29
  353. package/esm2020/lib/query/index.mjs +2 -2
  354. package/esm2020/lib/query/query.module.mjs +28 -28
  355. package/esm2020/lib/query/shared/index.mjs +7 -7
  356. package/esm2020/lib/query/shared/query-search-source.mjs +34 -34
  357. package/esm2020/lib/query/shared/query-search-source.providers.mjs +21 -21
  358. package/esm2020/lib/query/shared/query.directive.mjs +260 -260
  359. package/esm2020/lib/query/shared/query.enums.mjs +30 -30
  360. package/esm2020/lib/query/shared/query.interfaces.mjs +1 -1
  361. package/esm2020/lib/query/shared/query.service.mjs +732 -732
  362. package/esm2020/lib/query/shared/query.utils.mjs +36 -36
  363. package/esm2020/lib/search/index.mjs +11 -11
  364. package/esm2020/lib/search/search-bar/search-bar.component.mjs +511 -511
  365. package/esm2020/lib/search/search-bar/search-bar.module.mjs +74 -74
  366. package/esm2020/lib/search/search-bar/search-url-param.directive.mjs +34 -34
  367. package/esm2020/lib/search/search-results/save-feature-dialog.component.mjs +117 -117
  368. package/esm2020/lib/search/search-results/search-results-add-button.component.mjs +370 -370
  369. package/esm2020/lib/search/search-results/search-results-item.component.mjs +123 -123
  370. package/esm2020/lib/search/search-results/search-results.component.mjs +339 -339
  371. package/esm2020/lib/search/search-results/search-results.module.mjs +103 -103
  372. package/esm2020/lib/search/search-selector/search-selector.component.mjs +122 -122
  373. package/esm2020/lib/search/search-selector/search-selector.module.mjs +55 -55
  374. package/esm2020/lib/search/search-settings/search-settings.component.mjs +441 -441
  375. package/esm2020/lib/search/search-settings/search-settings.module.mjs +59 -59
  376. package/esm2020/lib/search/search.module.mjs +66 -66
  377. package/esm2020/lib/search/shared/index.mjs +9 -9
  378. package/esm2020/lib/search/shared/search-pointer-summary.directive.mjs +321 -321
  379. package/esm2020/lib/search/shared/search-source-service.providers.mjs +19 -19
  380. package/esm2020/lib/search/shared/search-source.service.mjs +46 -46
  381. package/esm2020/lib/search/shared/search.enums.mjs +3 -3
  382. package/esm2020/lib/search/shared/search.interfaces.mjs +1 -1
  383. package/esm2020/lib/search/shared/search.service.mjs +120 -120
  384. package/esm2020/lib/search/shared/search.utils.mjs +90 -90
  385. package/esm2020/lib/search/shared/sources/coordinates.interfaces.mjs +1 -1
  386. package/esm2020/lib/search/shared/sources/coordinates.mjs +153 -153
  387. package/esm2020/lib/search/shared/sources/coordinates.providers.mjs +39 -39
  388. package/esm2020/lib/search/shared/sources/icherche.interfaces.mjs +1 -1
  389. package/esm2020/lib/search/shared/sources/icherche.mjs +767 -767
  390. package/esm2020/lib/search/shared/sources/icherche.providers.mjs +65 -65
  391. package/esm2020/lib/search/shared/sources/ilayer.interfaces.mjs +1 -1
  392. package/esm2020/lib/search/shared/sources/ilayer.mjs +320 -320
  393. package/esm2020/lib/search/shared/sources/ilayer.providers.mjs +39 -39
  394. package/esm2020/lib/search/shared/sources/index.mjs +17 -17
  395. package/esm2020/lib/search/shared/sources/nominatim.interfaces.mjs +2 -2
  396. package/esm2020/lib/search/shared/sources/nominatim.mjs +252 -252
  397. package/esm2020/lib/search/shared/sources/nominatim.providers.mjs +22 -22
  398. package/esm2020/lib/search/shared/sources/source.interfaces.mjs +1 -1
  399. package/esm2020/lib/search/shared/sources/source.mjs +178 -178
  400. package/esm2020/lib/search/shared/sources/storedqueries.interfaces.mjs +1 -1
  401. package/esm2020/lib/search/shared/sources/storedqueries.mjs +425 -425
  402. package/esm2020/lib/search/shared/sources/storedqueries.providers.mjs +40 -40
  403. package/esm2020/lib/toast/index.mjs +2 -2
  404. package/esm2020/lib/toast/toast.component.mjs +112 -112
  405. package/esm2020/lib/toast/toast.module.mjs +44 -44
  406. package/esm2020/lib/utils/commonVectorStyle.interface.mjs +1 -1
  407. package/esm2020/lib/utils/commonVectorStyle.mjs +74 -74
  408. package/esm2020/lib/utils/googleLinks.mjs +12 -12
  409. package/esm2020/lib/utils/id-generator.mjs +109 -109
  410. package/esm2020/lib/utils/index.mjs +5 -5
  411. package/esm2020/lib/utils/osmLinks.mjs +9 -9
  412. package/esm2020/lib/wkt/index.mjs +2 -2
  413. package/esm2020/lib/wkt/shared/index.mjs +2 -2
  414. package/esm2020/lib/wkt/shared/wkt.service.mjs +224 -224
  415. package/esm2020/lib/wkt/wkt.module.mjs +21 -21
  416. package/esm2020/lib/workspace/confirmation-popup/confirmation-popup.component.mjs +47 -47
  417. package/esm2020/lib/workspace/confirmation-popup/confirmation-popup.module.mjs +35 -35
  418. package/esm2020/lib/workspace/confirmation-popup/index.mjs +2 -2
  419. package/esm2020/lib/workspace/index.mjs +8 -8
  420. package/esm2020/lib/workspace/shared/edition-workspace.mjs +279 -279
  421. package/esm2020/lib/workspace/shared/edition-workspace.service.mjs +656 -656
  422. package/esm2020/lib/workspace/shared/feature-workspace.mjs +34 -34
  423. package/esm2020/lib/workspace/shared/feature-workspace.service.mjs +149 -149
  424. package/esm2020/lib/workspace/shared/index.mjs +8 -8
  425. package/esm2020/lib/workspace/shared/wfs-workspace.mjs +34 -34
  426. package/esm2020/lib/workspace/shared/wfs-workspace.service.mjs +149 -149
  427. package/esm2020/lib/workspace/shared/wms-workspace.service.mjs +259 -259
  428. package/esm2020/lib/workspace/shared/workspace.utils.mjs +23 -23
  429. package/esm2020/lib/workspace/widgets/index.mjs +4 -4
  430. package/esm2020/lib/workspace/widgets/ogc-filter/ogc-filter.component.mjs +46 -46
  431. package/esm2020/lib/workspace/widgets/ogc-filter/ogc-filter.module.mjs +35 -35
  432. package/esm2020/lib/workspace/widgets/widgets.mjs +15 -15
  433. package/esm2020/lib/workspace/workspace-selector/workspace-selector.directive.mjs +132 -132
  434. package/esm2020/lib/workspace/workspace-selector/workspace-selector.module.mjs +27 -27
  435. package/esm2020/lib/workspace/workspace-updator/workspace-updator.directive.mjs +112 -112
  436. package/esm2020/lib/workspace/workspace-updator/workspace-updator.module.mjs +27 -27
  437. package/esm2020/lib/workspace/workspace.module.mjs +61 -61
  438. package/esm2020/public_api.mjs +54 -54
  439. package/fesm2015/igo2-geo.mjs +44992 -44987
  440. package/fesm2015/igo2-geo.mjs.map +1 -1
  441. package/fesm2020/igo2-geo.mjs +43034 -43029
  442. package/fesm2020/igo2-geo.mjs.map +1 -1
  443. package/index.d.ts +5 -5
  444. package/lib/catalog/catalog-browser/catalog-browser-group.component.d.ts +126 -126
  445. package/lib/catalog/catalog-browser/catalog-browser-layer.component.d.ts +80 -80
  446. package/lib/catalog/catalog-browser/catalog-browser.component.d.ts +105 -105
  447. package/lib/catalog/catalog-browser/catalog-browser.module.d.ts +22 -22
  448. package/lib/catalog/catalog-library/add-catalog-dialog.component.d.ts +45 -45
  449. package/lib/catalog/catalog-library/catalog-library-item.component.d.ts +25 -25
  450. package/lib/catalog/catalog-library/catalog-library.component.d.ts +65 -65
  451. package/lib/catalog/catalog-library/catalog-library.module.d.ts +26 -26
  452. package/lib/catalog/catalog.module.d.ts +14 -14
  453. package/lib/catalog/index.d.ts +4 -4
  454. package/lib/catalog/shared/catalog.abstract.d.ts +50 -50
  455. package/lib/catalog/shared/catalog.enum.d.ts +14 -14
  456. package/lib/catalog/shared/catalog.interface.d.ts +66 -66
  457. package/lib/catalog/shared/catalog.service.d.ts +36 -36
  458. package/lib/catalog/shared/index.d.ts +4 -4
  459. package/lib/datasource/datasource.module.d.ts +8 -8
  460. package/lib/datasource/index.d.ts +2 -2
  461. package/lib/datasource/shared/capabilities.service.d.ts +37 -37
  462. package/lib/datasource/shared/datasource.service.d.ts +37 -37
  463. package/lib/datasource/shared/datasources/any-datasource.d.ts +16 -16
  464. package/lib/datasource/shared/datasources/any-datasource.interface.d.ts +15 -15
  465. package/lib/datasource/shared/datasources/arcgisrest-datasource.d.ts +14 -14
  466. package/lib/datasource/shared/datasources/arcgisrest-datasource.interface.d.ts +14 -14
  467. package/lib/datasource/shared/datasources/carto-datasource.d.ts +15 -15
  468. package/lib/datasource/shared/datasources/carto-datasource.interface.d.ts +13 -13
  469. package/lib/datasource/shared/datasources/cluster-datasource.d.ts +10 -10
  470. package/lib/datasource/shared/datasources/cluster-datasource.interface.d.ts +11 -11
  471. package/lib/datasource/shared/datasources/data.service.d.ts +3 -3
  472. package/lib/datasource/shared/datasources/datasource.d.ts +20 -20
  473. package/lib/datasource/shared/datasources/datasource.interface.d.ts +100 -100
  474. package/lib/datasource/shared/datasources/feature-datasource.d.ts +12 -12
  475. package/lib/datasource/shared/datasources/feature-datasource.interface.d.ts +18 -18
  476. package/lib/datasource/shared/datasources/imagearcgisrest-datasource.d.ts +15 -15
  477. package/lib/datasource/shared/datasources/imagearcgisrest-datasource.interface.d.ts +15 -15
  478. package/lib/datasource/shared/datasources/index.d.ts +35 -35
  479. package/lib/datasource/shared/datasources/mvt-datasource.d.ts +10 -10
  480. package/lib/datasource/shared/datasources/mvt-datasource.interface.d.ts +13 -13
  481. package/lib/datasource/shared/datasources/osm-datasource.d.ts +9 -9
  482. package/lib/datasource/shared/datasources/osm-datasource.interface.d.ts +7 -7
  483. package/lib/datasource/shared/datasources/tilearcgisrest-datasource.d.ts +15 -15
  484. package/lib/datasource/shared/datasources/tilearcgisrest-datasource.interface.d.ts +14 -14
  485. package/lib/datasource/shared/datasources/tiledebug-datasource.d.ts +9 -9
  486. package/lib/datasource/shared/datasources/tiledebug-datasource.interface.d.ts +9 -9
  487. package/lib/datasource/shared/datasources/websocket-datasource.d.ts +15 -15
  488. package/lib/datasource/shared/datasources/websocket-datasource.interface.d.ts +7 -7
  489. package/lib/datasource/shared/datasources/wfs-datasource.d.ts +20 -20
  490. package/lib/datasource/shared/datasources/wfs-datasource.interface.d.ts +20 -20
  491. package/lib/datasource/shared/datasources/wfs.service.d.ts +17 -17
  492. package/lib/datasource/shared/datasources/wms-datasource.d.ts +31 -31
  493. package/lib/datasource/shared/datasources/wms-datasource.interface.d.ts +32 -32
  494. package/lib/datasource/shared/datasources/wms-wfs.utils.d.ts +41 -41
  495. package/lib/datasource/shared/datasources/wmts-datasource.d.ts +10 -10
  496. package/lib/datasource/shared/datasources/wmts-datasource.interface.d.ts +13 -13
  497. package/lib/datasource/shared/datasources/xyz-datasource.d.ts +9 -9
  498. package/lib/datasource/shared/datasources/xyz-datasource.interface.d.ts +11 -11
  499. package/lib/datasource/shared/index.d.ts +4 -4
  500. package/lib/datasource/shared/options/index.d.ts +4 -4
  501. package/lib/datasource/shared/options/options-api.interface.d.ts +4 -4
  502. package/lib/datasource/shared/options/options-api.providers.d.ts +10 -10
  503. package/lib/datasource/shared/options/options-api.service.d.ts +16 -16
  504. package/lib/datasource/shared/options/options.service.d.ts +6 -6
  505. package/lib/datasource/utils/esri-style-generator.d.ts +21 -21
  506. package/lib/datasource/utils/index.d.ts +2 -2
  507. package/lib/datasource/utils/tilegrid.d.ts +2 -2
  508. package/lib/directions/directions-buttons/directions-buttons.component.d.ts +30 -30
  509. package/lib/directions/directions-buttons/index.d.ts +1 -1
  510. package/lib/directions/directions-inputs/directions-inputs.component.d.ts +45 -45
  511. package/lib/directions/directions-inputs/index.d.ts +1 -1
  512. package/lib/directions/directions-results/directions-results.component.d.ts +30 -30
  513. package/lib/directions/directions-results/index.d.ts +1 -1
  514. package/lib/directions/directions-sources/directions-source.d.ts +7 -7
  515. package/lib/directions/directions-sources/directions-source.interface.d.ts +11 -11
  516. package/lib/directions/directions-sources/directions-source.provider.d.ts +11 -11
  517. package/lib/directions/directions-sources/index.d.ts +4 -4
  518. package/lib/directions/directions-sources/osrm-directions-source.d.ts +23 -23
  519. package/lib/directions/directions.component.d.ts +56 -56
  520. package/lib/directions/directions.module.d.ts +26 -26
  521. package/lib/directions/index.d.ts +6 -6
  522. package/lib/directions/shared/directions-source.service.d.ts +11 -11
  523. package/lib/directions/shared/directions.enum.d.ts +22 -22
  524. package/lib/directions/shared/directions.interface.d.ts +126 -126
  525. package/lib/directions/shared/directions.service.d.ts +13 -13
  526. package/lib/directions/shared/directions.utils.d.ts +42 -42
  527. package/lib/directions/shared/index.d.ts +5 -5
  528. package/lib/directions/shared/store.d.ts +18 -18
  529. package/lib/download/download-button/download-button.component.d.ts +18 -18
  530. package/lib/download/download-button/index.d.ts +1 -1
  531. package/lib/download/download.module.d.ts +14 -14
  532. package/lib/download/index.d.ts +2 -2
  533. package/lib/download/shared/download.interface.d.ts +10 -10
  534. package/lib/download/shared/download.service.d.ts +11 -11
  535. package/lib/download/shared/index.d.ts +2 -2
  536. package/lib/draw/draw/draw-layer-popup.component.d.ts +14 -14
  537. package/lib/draw/draw/draw-popup.component.d.ts +63 -63
  538. package/lib/draw/draw/draw-shorcuts.component.d.ts +5 -5
  539. package/lib/draw/draw/draw.component.d.ts +239 -239
  540. package/lib/draw/draw/draw.module.d.ts +34 -34
  541. package/lib/draw/drawingTool.module.d.ts +7 -7
  542. package/lib/draw/index.d.ts +2 -2
  543. package/lib/draw/shared/draw-icon.service.d.ts +12 -12
  544. package/lib/draw/shared/draw-style.service.d.ts +36 -36
  545. package/lib/draw/shared/draw.enum.d.ts +32 -32
  546. package/lib/draw/shared/draw.interface.d.ts +40 -40
  547. package/lib/draw/shared/draw.utils.d.ts +35 -35
  548. package/lib/draw/shared/index.d.ts +5 -5
  549. package/lib/feature/feature-details/feature-details.component.d.ts +60 -60
  550. package/lib/feature/feature-details/feature-details.directive.d.ts +19 -19
  551. package/lib/feature/feature-details/feature-details.module.d.ts +15 -15
  552. package/lib/feature/feature-form/feature-form.component.d.ts +50 -50
  553. package/lib/feature/feature-form/feature-form.module.d.ts +12 -12
  554. package/lib/feature/feature.module.d.ts +9 -9
  555. package/lib/feature/index.d.ts +3 -3
  556. package/lib/feature/shared/feature.enums.d.ts +7 -7
  557. package/lib/feature/shared/feature.interfaces.d.ts +74 -74
  558. package/lib/feature/shared/feature.utils.d.ts +104 -104
  559. package/lib/feature/shared/index.d.ts +6 -6
  560. package/lib/feature/shared/store.d.ts +71 -71
  561. package/lib/feature/shared/strategies/in-map-extent.d.ts +52 -52
  562. package/lib/feature/shared/strategies/in-map-resolution.d.ts +52 -52
  563. package/lib/feature/shared/strategies/index.d.ts +5 -5
  564. package/lib/feature/shared/strategies/loading-layer.d.ts +59 -59
  565. package/lib/feature/shared/strategies/loading.d.ts +75 -75
  566. package/lib/feature/shared/strategies/selection.d.ts +176 -176
  567. package/lib/feature/shared/strategies.utils.d.ts +17 -17
  568. package/lib/filter/filter.module.d.ts +53 -53
  569. package/lib/filter/index.d.ts +15 -15
  570. package/lib/filter/ogc-filter-button/index.d.ts +1 -1
  571. package/lib/filter/ogc-filter-button/ogc-filter-button.component.d.ts +20 -20
  572. package/lib/filter/ogc-filter-form/index.d.ts +1 -1
  573. package/lib/filter/ogc-filter-form/ogc-filter-form.component.d.ts +65 -65
  574. package/lib/filter/ogc-filter-selection/index.d.ts +1 -1
  575. package/lib/filter/ogc-filter-selection/ogc-filter-selection.component.d.ts +93 -93
  576. package/lib/filter/ogc-filter-time/index.d.ts +2 -2
  577. package/lib/filter/ogc-filter-time/ogc-filter-time-slider.component.d.ts +39 -39
  578. package/lib/filter/ogc-filter-time/ogc-filter-time.component.d.ts +86 -86
  579. package/lib/filter/ogc-filterable-form/index.d.ts +1 -1
  580. package/lib/filter/ogc-filterable-form/ogc-filterable-form.component.d.ts +15 -15
  581. package/lib/filter/ogc-filterable-item/index.d.ts +1 -1
  582. package/lib/filter/ogc-filterable-item/ogc-filterable-item.component.d.ts +41 -41
  583. package/lib/filter/ogc-filterable-list/index.d.ts +2 -2
  584. package/lib/filter/ogc-filterable-list/ogc-filterable-list-binding.directive.d.ts +14 -14
  585. package/lib/filter/ogc-filterable-list/ogc-filterable-list.component.d.ts +10 -10
  586. package/lib/filter/shared/filterable-datasource.pipe.d.ts +10 -10
  587. package/lib/filter/shared/index.d.ts +11 -11
  588. package/lib/filter/shared/ogc-filter-time.service.d.ts +19 -19
  589. package/lib/filter/shared/ogc-filter.d.ts +29 -29
  590. package/lib/filter/shared/ogc-filter.enum.d.ts +27 -27
  591. package/lib/filter/shared/ogc-filter.interface.d.ts +200 -200
  592. package/lib/filter/shared/ogc-filter.service.d.ts +11 -11
  593. package/lib/filter/shared/spatial-filter.enum.d.ts +19 -19
  594. package/lib/filter/shared/spatial-filter.interface.d.ts +10 -10
  595. package/lib/filter/shared/spatial-filter.service.d.ts +37 -37
  596. package/lib/filter/shared/time-filter.enum.d.ts +10 -10
  597. package/lib/filter/shared/time-filter.interface.d.ts +29 -29
  598. package/lib/filter/shared/time-filter.service.d.ts +11 -11
  599. package/lib/filter/spatial-filter/spatial-filter-item/index.d.ts +1 -1
  600. package/lib/filter/spatial-filter/spatial-filter-item/spatial-filter-item.component.d.ts +166 -166
  601. package/lib/filter/spatial-filter/spatial-filter-list/index.d.ts +1 -1
  602. package/lib/filter/spatial-filter/spatial-filter-list/spatial-filter-list.component.d.ts +58 -58
  603. package/lib/filter/spatial-filter/spatial-filter-type/index.d.ts +1 -1
  604. package/lib/filter/spatial-filter/spatial-filter-type/spatial-filter-type.component.d.ts +45 -45
  605. package/lib/filter/time-filter-button/index.d.ts +1 -1
  606. package/lib/filter/time-filter-button/time-filter-button.component.d.ts +20 -20
  607. package/lib/filter/time-filter-form/index.d.ts +1 -1
  608. package/lib/filter/time-filter-form/time-filter-form.component.d.ts +77 -77
  609. package/lib/filter/time-filter-item/index.d.ts +1 -1
  610. package/lib/filter/time-filter-item/time-filter-item.component.d.ts +28 -28
  611. package/lib/filter/time-filter-list/index.d.ts +2 -2
  612. package/lib/filter/time-filter-list/time-filter-list-binding.directive.d.ts +14 -14
  613. package/lib/filter/time-filter-list/time-filter-list.component.d.ts +12 -12
  614. package/lib/geo.module.d.ts +28 -28
  615. package/lib/geometry/geometry-form-field/geometry-form-field-input.component.d.ts +206 -206
  616. package/lib/geometry/geometry-form-field/geometry-form-field.component.d.ts +88 -88
  617. package/lib/geometry/geometry-form-field/geometry-form-field.module.d.ts +19 -19
  618. package/lib/geometry/geometry.module.d.ts +8 -8
  619. package/lib/geometry/index.d.ts +3 -3
  620. package/lib/geometry/shared/controls/draw.d.ts +150 -150
  621. package/lib/geometry/shared/controls/index.d.ts +3 -3
  622. package/lib/geometry/shared/controls/modify.d.ts +228 -228
  623. package/lib/geometry/shared/controls/slice.d.ts +99 -99
  624. package/lib/geometry/shared/geometry.errors.d.ts +11 -11
  625. package/lib/geometry/shared/geometry.interfaces.d.ts +13 -13
  626. package/lib/geometry/shared/geometry.utils.d.ts +45 -45
  627. package/lib/geometry/shared/index.d.ts +4 -4
  628. package/lib/import-export/export-button/export-button.component.d.ts +16 -16
  629. package/lib/import-export/export-button/index.d.ts +1 -1
  630. package/lib/import-export/import-export/import-export.component.d.ts +104 -104
  631. package/lib/import-export/import-export/index.d.ts +1 -1
  632. package/lib/import-export/import-export.module.d.ts +26 -26
  633. package/lib/import-export/index.d.ts +4 -4
  634. package/lib/import-export/shared/drop-geo-file.directive.d.ts +36 -36
  635. package/lib/import-export/shared/export.errors.d.ts +8 -8
  636. package/lib/import-export/shared/export.interface.d.ts +11 -11
  637. package/lib/import-export/shared/export.service.d.ts +30 -30
  638. package/lib/import-export/shared/export.type.d.ts +16 -16
  639. package/lib/import-export/shared/export.utils.d.ts +19 -19
  640. package/lib/import-export/shared/import.errors.d.ts +20 -20
  641. package/lib/import-export/shared/import.interface.d.ts +8 -8
  642. package/lib/import-export/shared/import.service.d.ts +31 -31
  643. package/lib/import-export/shared/import.utils.d.ts +18 -18
  644. package/lib/import-export/shared/index.d.ts +10 -10
  645. package/lib/import-export/style-list/index.d.ts +4 -4
  646. package/lib/import-export/style-list/style-list.interface.d.ts +6 -6
  647. package/lib/import-export/style-list/style-list.module.d.ts +8 -8
  648. package/lib/import-export/style-list/style-list.provider.d.ts +15 -15
  649. package/lib/import-export/style-list/style-list.service.d.ts +18 -18
  650. package/lib/layer/index.d.ts +10 -10
  651. package/lib/layer/layer-item/index.d.ts +1 -1
  652. package/lib/layer/layer-item/layer-item.component.d.ts +62 -62
  653. package/lib/layer/layer-legend/index.d.ts +1 -1
  654. package/lib/layer/layer-legend/layer-legend.component.d.ts +90 -90
  655. package/lib/layer/layer-legend-item/index.d.ts +1 -1
  656. package/lib/layer/layer-legend-item/layer-legend-item.component.d.ts +22 -22
  657. package/lib/layer/layer-legend-list/index.d.ts +2 -2
  658. package/lib/layer/layer-legend-list/layer-legend-list-binding.directive.d.ts +16 -16
  659. package/lib/layer/layer-legend-list/layer-legend-list.component.d.ts +31 -31
  660. package/lib/layer/layer-list/index.d.ts +3 -3
  661. package/lib/layer/layer-list/layer-list-binding.directive.d.ts +19 -19
  662. package/lib/layer/layer-list/layer-list.component.d.ts +127 -127
  663. package/lib/layer/layer-list/layer-list.enum.d.ts +15 -15
  664. package/lib/layer/layer-list-tool/index.d.ts +4 -4
  665. package/lib/layer/layer-list-tool/layer-list-tool.component.d.ts +32 -32
  666. package/lib/layer/layer-list-tool/layer-list-tool.enum.d.ts +5 -5
  667. package/lib/layer/layer-list-tool/layer-list-tool.interface.d.ts +8 -8
  668. package/lib/layer/layer-list-tool/layer-list-tool.service.d.ts +14 -14
  669. package/lib/layer/layer.module.d.ts +36 -36
  670. package/lib/layer/shared/clusterParam.d.ts +13 -13
  671. package/lib/layer/shared/index.d.ts +6 -6
  672. package/lib/layer/shared/layer.enums.d.ts +1 -1
  673. package/lib/layer/shared/layer.service.d.ts +30 -30
  674. package/lib/layer/shared/layers/any-layer.d.ts +6 -6
  675. package/lib/layer/shared/layers/any-layer.interface.d.ts +6 -6
  676. package/lib/layer/shared/layers/image-layer.d.ts +22 -22
  677. package/lib/layer/shared/layers/image-layer.interface.d.ts +19 -19
  678. package/lib/layer/shared/layers/index.d.ts +12 -12
  679. package/lib/layer/shared/layers/layer.d.ts +62 -62
  680. package/lib/layer/shared/layers/layer.interface.d.ts +109 -109
  681. package/lib/layer/shared/layers/tile-layer.d.ts +31 -31
  682. package/lib/layer/shared/layers/tile-layer.interface.d.ts +20 -20
  683. package/lib/layer/shared/layers/vector-layer.d.ts +78 -78
  684. package/lib/layer/shared/layers/vector-layer.interface.d.ts +41 -41
  685. package/lib/layer/shared/layers/vectortile-layer.d.ts +28 -28
  686. package/lib/layer/shared/layers/vectortile-layer.interface.d.ts +18 -18
  687. package/lib/layer/shared/style.service.d.ts +57 -57
  688. package/lib/layer/shared/vector-style.interface.d.ts +38 -38
  689. package/lib/layer/style-modal/index.d.ts +1 -1
  690. package/lib/layer/style-modal/style-modal.component.d.ts +42 -42
  691. package/lib/layer/track-feature-button/index.d.ts +1 -1
  692. package/lib/layer/track-feature-button/track-feature-button.component.d.ts +15 -15
  693. package/lib/layer/utils/image-watcher.d.ts +17 -17
  694. package/lib/layer/utils/index.d.ts +5 -5
  695. package/lib/layer/utils/layer.utils.d.ts +2 -2
  696. package/lib/layer/utils/outputLegend.d.ts +7 -7
  697. package/lib/layer/utils/tile-watcher.d.ts +14 -14
  698. package/lib/layer/utils/vector-watcher.d.ts +13 -13
  699. package/lib/map/baselayers-switcher/baselayers-switcher.animation.d.ts +2 -2
  700. package/lib/map/baselayers-switcher/baselayers-switcher.component.d.ts +21 -21
  701. package/lib/map/baselayers-switcher/index.d.ts +2 -2
  702. package/lib/map/baselayers-switcher/mini-basemap.component.d.ts +29 -29
  703. package/lib/map/geolocate-button/geolocate-button.component.d.ts +22 -22
  704. package/lib/map/geolocate-button/index.d.ts +1 -1
  705. package/lib/map/home-extent-button/home-extent-button.component.d.ts +20 -20
  706. package/lib/map/home-extent-button/index.d.ts +1 -1
  707. package/lib/map/index.d.ts +13 -13
  708. package/lib/map/info-section/index.d.ts +1 -1
  709. package/lib/map/info-section/info-section.component.d.ts +7 -7
  710. package/lib/map/map-browser/index.d.ts +1 -1
  711. package/lib/map/map-browser/map-browser.component.d.ts +25 -25
  712. package/lib/map/map-center/index.d.ts +1 -1
  713. package/lib/map/map-center/map-center.component.d.ts +31 -31
  714. package/lib/map/map.module.d.ts +28 -28
  715. package/lib/map/menu-button/index.d.ts +1 -1
  716. package/lib/map/menu-button/menu-button.component.d.ts +17 -17
  717. package/lib/map/offline-button/index.d.ts +1 -1
  718. package/lib/map/offline-button/offline-button.component.d.ts +23 -23
  719. package/lib/map/rotation-button/index.d.ts +1 -1
  720. package/lib/map/rotation-button/rotation-button.component.d.ts +17 -17
  721. package/lib/map/shared/controllers/controller.d.ts +29 -29
  722. package/lib/map/shared/controllers/geolocation.d.ts +112 -112
  723. package/lib/map/shared/controllers/index.d.ts +3 -3
  724. package/lib/map/shared/controllers/view.d.ts +200 -200
  725. package/lib/map/shared/hover-feature.directive.d.ts +132 -132
  726. package/lib/map/shared/index.d.ts +13 -13
  727. package/lib/map/shared/linkedLayers.utils.d.ts +17 -17
  728. package/lib/map/shared/map-pointer-position.directive.d.ts +71 -71
  729. package/lib/map/shared/map.d.ts +135 -135
  730. package/lib/map/shared/map.enums.d.ts +4 -4
  731. package/lib/map/shared/map.interface.d.ts +57 -57
  732. package/lib/map/shared/map.service.d.ts +19 -19
  733. package/lib/map/shared/map.utils.d.ts +90 -90
  734. package/lib/map/shared/mapOffline.directive.d.ts +21 -21
  735. package/lib/map/shared/projection.interfaces.d.ts +29 -29
  736. package/lib/map/shared/projection.service.d.ts +19 -19
  737. package/lib/map/shared/projection.utils.d.ts +19 -19
  738. package/lib/map/swipe-control/index.d.ts +1 -1
  739. package/lib/map/swipe-control/swipe-control.component.d.ts +97 -97
  740. package/lib/map/utils/layer-watcher.d.ts +20 -20
  741. package/lib/map/wake-lock-button/index.d.ts +1 -1
  742. package/lib/map/wake-lock-button/wake-lock-button.component.d.ts +30 -30
  743. package/lib/map/zoom-button/index.d.ts +1 -1
  744. package/lib/map/zoom-button/zoom-button.component.d.ts +12 -12
  745. package/lib/measure/index.d.ts +3 -3
  746. package/lib/measure/measure.module.d.ts +7 -7
  747. package/lib/measure/measurer/measure-format.pipe.d.ts +15 -15
  748. package/lib/measure/measurer/measurer-dialog.component.d.ts +14 -14
  749. package/lib/measure/measurer/measurer-item.component.d.ts +66 -66
  750. package/lib/measure/measurer/measurer.component.d.ts +405 -405
  751. package/lib/measure/measurer/measurer.module.d.ts +25 -25
  752. package/lib/measure/shared/index.d.ts +3 -3
  753. package/lib/measure/shared/measure.enum.d.ts +33 -33
  754. package/lib/measure/shared/measure.interfaces.d.ts +21 -21
  755. package/lib/measure/shared/measure.utils.d.ts +180 -180
  756. package/lib/metadata/index.d.ts +2 -2
  757. package/lib/metadata/metadata-button/index.d.ts +1 -1
  758. package/lib/metadata/metadata-button/metadata-button.component.d.ts +26 -26
  759. package/lib/metadata/metadata.module.d.ts +15 -15
  760. package/lib/metadata/shared/index.d.ts +2 -2
  761. package/lib/metadata/shared/metadata.interface.d.ts +13 -13
  762. package/lib/metadata/shared/metadata.service.d.ts +8 -8
  763. package/lib/offline/geoDB/configFileToGeoDB.service.d.ts +14 -14
  764. package/lib/offline/geoDB/geoDB.enums.d.ts +4 -4
  765. package/lib/offline/geoDB/geoDB.interface.d.ts +19 -19
  766. package/lib/offline/geoDB/geoDB.service.d.ts +37 -37
  767. package/lib/offline/geoDB/index.d.ts +4 -4
  768. package/lib/offline/index.d.ts +2 -2
  769. package/lib/offline/shared/geo-network.service.d.ts +28 -28
  770. package/lib/offline/shared/index.d.ts +1 -1
  771. package/lib/overlay/index.d.ts +1 -1
  772. package/lib/overlay/overlay.module.d.ts +9 -9
  773. package/lib/overlay/shared/index.d.ts +6 -6
  774. package/lib/overlay/shared/overlay-marker-style.utils.d.ts +11 -11
  775. package/lib/overlay/shared/overlay.d.ts +81 -81
  776. package/lib/overlay/shared/overlay.directive.d.ts +18 -18
  777. package/lib/overlay/shared/overlay.enum.d.ts +6 -6
  778. package/lib/overlay/shared/overlay.service.d.ts +14 -14
  779. package/lib/overlay/shared/overlay.utils.d.ts +17 -17
  780. package/lib/print/index.d.ts +3 -3
  781. package/lib/print/print/print.component.d.ts +35 -35
  782. package/lib/print/print-form/index.d.ts +1 -1
  783. package/lib/print/print-form/print-form.component.d.ts +97 -97
  784. package/lib/print/print.module.d.ts +19 -19
  785. package/lib/print/shared/geopdf.d.ts +1 -1
  786. package/lib/print/shared/index.d.ts +4 -4
  787. package/lib/print/shared/print.interface.d.ts +22 -22
  788. package/lib/print/shared/print.service.d.ts +168 -168
  789. package/lib/print/shared/print.type.d.ts +45 -45
  790. package/lib/query/index.d.ts +1 -1
  791. package/lib/query/query.module.d.ts +11 -11
  792. package/lib/query/shared/index.d.ts +6 -6
  793. package/lib/query/shared/query-search-source.d.ts +17 -17
  794. package/lib/query/shared/query-search-source.providers.d.ts +17 -17
  795. package/lib/query/shared/query.directive.d.ts +105 -105
  796. package/lib/query/shared/query.enums.d.ts +26 -26
  797. package/lib/query/shared/query.interfaces.d.ts +35 -35
  798. package/lib/query/shared/query.service.d.ts +56 -56
  799. package/lib/query/shared/query.utils.d.ts +27 -27
  800. package/lib/search/index.d.ts +11 -11
  801. package/lib/search/search-bar/search-bar.component.d.ts +230 -230
  802. package/lib/search/search-bar/search-bar.module.d.ts +23 -23
  803. package/lib/search/search-bar/search-url-param.directive.d.ts +13 -13
  804. package/lib/search/search-results/save-feature-dialog.component.d.ts +32 -32
  805. package/lib/search/search-results/search-results-add-button.component.d.ts +76 -76
  806. package/lib/search/search-results/search-results-item.component.d.ts +47 -47
  807. package/lib/search/search-results/search-results.component.d.ts +161 -161
  808. package/lib/search/search-results/search-results.module.d.ts +28 -28
  809. package/lib/search/search-selector/search-selector.component.d.ts +58 -58
  810. package/lib/search/search-selector/search-selector.module.d.ts +19 -19
  811. package/lib/search/search-settings/search-settings.component.d.ts +102 -102
  812. package/lib/search/search-settings/search-settings.module.d.ts +20 -20
  813. package/lib/search/search.module.d.ts +14 -14
  814. package/lib/search/shared/index.d.ts +8 -8
  815. package/lib/search/shared/search-pointer-summary.directive.d.ts +133 -133
  816. package/lib/search/shared/search-source-service.providers.d.ts +15 -15
  817. package/lib/search/shared/search-source.service.d.ts +32 -32
  818. package/lib/search/shared/search.enums.d.ts +1 -1
  819. package/lib/search/shared/search.interfaces.d.ts +29 -29
  820. package/lib/search/shared/search.service.d.ts +53 -53
  821. package/lib/search/shared/search.utils.d.ts +39 -39
  822. package/lib/search/shared/sources/coordinates.d.ts +40 -40
  823. package/lib/search/shared/sources/coordinates.interfaces.d.ts +12 -12
  824. package/lib/search/shared/sources/coordinates.providers.d.ts +31 -31
  825. package/lib/search/shared/sources/icherche.d.ts +96 -96
  826. package/lib/search/shared/sources/icherche.interfaces.d.ts +30 -30
  827. package/lib/search/shared/sources/icherche.providers.d.ts +46 -46
  828. package/lib/search/shared/sources/ilayer.d.ts +55 -55
  829. package/lib/search/shared/sources/ilayer.interfaces.d.ts +47 -47
  830. package/lib/search/shared/sources/ilayer.providers.d.ts +31 -31
  831. package/lib/search/shared/sources/index.d.ts +17 -17
  832. package/lib/search/shared/sources/nominatim.d.ts +45 -45
  833. package/lib/search/shared/sources/nominatim.interfaces.d.ts +10 -10
  834. package/lib/search/shared/sources/nominatim.providers.d.ts +18 -18
  835. package/lib/search/shared/sources/source.d.ts +108 -108
  836. package/lib/search/shared/sources/source.interfaces.d.ts +47 -47
  837. package/lib/search/shared/sources/storedqueries.d.ts +73 -73
  838. package/lib/search/shared/sources/storedqueries.interfaces.d.ts +42 -42
  839. package/lib/search/shared/sources/storedqueries.providers.d.ts +32 -32
  840. package/lib/toast/index.d.ts +1 -1
  841. package/lib/toast/toast.component.d.ts +33 -33
  842. package/lib/toast/toast.module.d.ts +14 -14
  843. package/lib/utils/commonVectorStyle.d.ts +14 -14
  844. package/lib/utils/commonVectorStyle.interface.d.ts +16 -16
  845. package/lib/utils/googleLinks.d.ts +5 -5
  846. package/lib/utils/id-generator.d.ts +54 -54
  847. package/lib/utils/index.d.ts +5 -5
  848. package/lib/utils/osmLinks.d.ts +4 -4
  849. package/lib/wkt/index.d.ts +1 -1
  850. package/lib/wkt/shared/index.d.ts +1 -1
  851. package/lib/wkt/shared/wkt.service.d.ts +19 -19
  852. package/lib/wkt/wkt.module.d.ts +8 -8
  853. package/lib/workspace/confirmation-popup/confirmation-popup.component.d.ts +23 -23
  854. package/lib/workspace/confirmation-popup/confirmation-popup.module.d.ts +14 -14
  855. package/lib/workspace/confirmation-popup/index.d.ts +2 -2
  856. package/lib/workspace/index.d.ts +7 -7
  857. package/lib/workspace/shared/edition-workspace.d.ts +82 -82
  858. package/lib/workspace/shared/edition-workspace.service.d.ts +52 -52
  859. package/lib/workspace/shared/feature-workspace.d.ts +18 -18
  860. package/lib/workspace/shared/feature-workspace.service.d.ts +19 -19
  861. package/lib/workspace/shared/index.d.ts +7 -7
  862. package/lib/workspace/shared/wfs-workspace.d.ts +18 -18
  863. package/lib/workspace/shared/wfs-workspace.service.d.ts +19 -19
  864. package/lib/workspace/shared/wms-workspace.service.d.ts +22 -22
  865. package/lib/workspace/shared/workspace.utils.d.ts +10 -10
  866. package/lib/workspace/widgets/index.d.ts +3 -3
  867. package/lib/workspace/widgets/ogc-filter/ogc-filter.component.d.ts +29 -29
  868. package/lib/workspace/widgets/ogc-filter/ogc-filter.module.d.ts +14 -14
  869. package/lib/workspace/widgets/widgets.d.ts +9 -9
  870. package/lib/workspace/workspace-selector/workspace-selector.directive.d.ts +32 -32
  871. package/lib/workspace/workspace-selector/workspace-selector.module.d.ts +11 -11
  872. package/lib/workspace/workspace-updator/workspace-updator.directive.d.ts +26 -26
  873. package/lib/workspace/workspace-updator/workspace-updator.module.d.ts +11 -11
  874. package/lib/workspace/workspace.module.d.ts +14 -14
  875. package/package.json +4 -4
  876. package/public_api.d.ts +51 -51
@@ -1,934 +1,934 @@
1
- import { Injectable } from '@angular/core';
2
- import { Observable, Subject, forkJoin } from 'rxjs';
3
- import { map as rxMap } from 'rxjs/operators';
4
- import { saveAs } from 'file-saver';
5
- import jsPDF from 'jspdf';
6
- import html2canvas from 'html2canvas';
7
- import { default as JSZip } from 'jszip';
8
- import { SubjectStatus } from '@igo2/utils';
9
- import { SecureImagePipe } from '@igo2/common';
10
- import { formatScale } from '../../map/shared/map.utils';
11
- import { getLayersLegends } from '../../layer/utils/outputLegend';
12
- import GeoPdfPlugin from './geopdf';
13
- import * as i0 from "@angular/core";
14
- import * as i1 from "@angular/common/http";
15
- import * as i2 from "@igo2/core";
16
- export class PrintService {
17
- constructor(http, messageService, activityService, languageService, configService) {
18
- this.http = http;
19
- this.messageService = messageService;
20
- this.activityService = activityService;
21
- this.languageService = languageService;
22
- this.configService = configService;
23
- this.TEXTPDFFONT = {
24
- titleFont: 'Times',
25
- titleFontStyle: 'bold',
26
- subtitleFont: 'Times',
27
- subtitleFontStyle: 'bold',
28
- commentFont: 'courier',
29
- commentFontStyle: 'normal',
30
- commentFontSize: 16
31
- };
32
- }
33
- print(map, options) {
34
- const status$ = new Subject();
35
- const paperFormat = options.paperFormat;
36
- const resolution = +options.resolution; // Default is 96
37
- const orientation = options.orientation;
38
- const legendPostion = options.legendPosition;
39
- this.activityId = this.activityService.register();
40
- GeoPdfPlugin(jsPDF.API);
41
- const doc = new jsPDF({
42
- orientation,
43
- format: paperFormat.toLowerCase(),
44
- unit: 'mm' // default
45
- });
46
- const dimensions = [
47
- doc.internal.pageSize.width,
48
- doc.internal.pageSize.height
49
- ];
50
- const margins = [10, 10, 10, 10];
51
- const width = dimensions[0] - margins[3] - margins[1];
52
- const height = dimensions[1] - margins[0] - margins[2];
53
- const size = [width, height];
54
- let titleSizes;
55
- let subtitleSizes;
56
- // PDF title
57
- if (options.title !== undefined) {
58
- const fontSizeInPt = Math.round(2 * (height + 145) * 0.05) / 2; //calculate the fontSize title from the page height.
59
- titleSizes = this.getTextPdfObjectSizeAndMarg(options.title, margins, this.TEXTPDFFONT.titleFont, fontSizeInPt, this.TEXTPDFFONT.titleFontStyle, doc);
60
- this.addTextInPdfDoc(doc, options.title, this.TEXTPDFFONT.titleFont, this.TEXTPDFFONT.titleFontStyle, titleSizes.fontSize, titleSizes.marginLeft + margins[3], margins[0]);
61
- margins[0] = titleSizes.height + margins[0]; // cumulative margin top for next elem to place in pdf doc
62
- }
63
- // PDF subtitle
64
- if (options.subtitle !== undefined) {
65
- subtitleSizes = this.getTextPdfObjectSizeAndMarg(options.subtitle, margins, this.TEXTPDFFONT.subtitleFont, titleSizes.fontSize * 0.7, // 70% size of title
66
- this.TEXTPDFFONT.subtitleFontStyle, doc);
67
- this.addTextInPdfDoc(doc, options.subtitle, this.TEXTPDFFONT.subtitleFont, this.TEXTPDFFONT.subtitleFontStyle, subtitleSizes.fontSize, subtitleSizes.marginLeft + margins[3], margins[0]);
68
- margins[0] += 5; // cumulative marg top for next elem to place in pdf doc. 5 is a fix it could be adjust
69
- }
70
- if (options.showProjection === true || options.showScale === true) {
71
- this.addProjScale(doc, map, resolution, options.showProjection, options.showScale);
72
- }
73
- if (options.comment !== '') {
74
- this.addComment(doc, options.comment);
75
- }
76
- this.addMap(doc, map, resolution, size, margins).subscribe(async (status) => {
77
- if (status === SubjectStatus.Done) {
78
- await this.addScale(doc, map, margins);
79
- await this.handleMeasureLayer(doc, map, margins);
80
- const width = this.imgSizeAdded[0];
81
- const height = this.imgSizeAdded[1];
82
- const res = 1;
83
- this.addGeoRef(doc, map, width, height, res, margins);
84
- if (options.legendPosition !== 'none') {
85
- if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(options.legendPosition) > -1) {
86
- await this.addLegendSamePage(doc, map, margins, resolution, options.legendPosition);
87
- }
88
- else if (options.legendPosition === 'newpage') {
89
- await this.addLegend(doc, map, margins, resolution);
90
- }
91
- }
92
- else {
93
- await this.saveDoc(doc);
94
- }
95
- }
96
- if (status === SubjectStatus.Done || status === SubjectStatus.Error) {
97
- this.activityService.unregister(this.activityId);
98
- status$.next(SubjectStatus.Done);
99
- }
100
- });
101
- return status$;
102
- }
103
- // ref GeoMoose https://github.com/geomoose/gm3/tree/main/src/gm3/components/print
104
- addGeoRef(doc, map, width, height, resolution, margins) {
105
- const unit = 'mm';
106
- const docHeight = doc.internal.pageSize.getHeight();
107
- // x,y = margin left-bottom corner for img in pdf doc
108
- const x = margins[3];
109
- const y = docHeight - margins[0] - height;
110
- let pdf_extents = [x, y, x + width, y + height];
111
- for (let i = 0; i < pdf_extents.length; i++) {
112
- pdf_extents[i] = this.pdf_units2points(pdf_extents[i], unit);
113
- }
114
- const mapExtent = map.viewController.getExtent('EPSG:3857');
115
- doc.setGeoArea(pdf_extents, mapExtent);
116
- }
117
- /**
118
- * Add measure overlay on the map on the document when the measure layer is present
119
- * @param doc - Pdf document where measure tooltip will be added
120
- * @param map - Map of the app
121
- * @param margins - Page margins
122
- */
123
- async handleMeasureLayer(doc, map, margins) {
124
- if (map.layers.find(layer => layer.visible && layer.id.startsWith('igo-measures-'))) {
125
- let canvasOverlayHTMLMeasures;
126
- const mapOverlayMeasuresHTML = map.ol.getOverlayContainer();
127
- await html2canvas(mapOverlayMeasuresHTML, {
128
- scale: 1,
129
- backgroundColor: null
130
- }).then(e => {
131
- canvasOverlayHTMLMeasures = e;
132
- });
133
- this.addCanvas(doc, canvasOverlayHTMLMeasures, margins); // this adds measure overlays
134
- }
135
- }
136
- /**
137
- * Get html code for all layers legend
138
- * @param map IgoMap
139
- * @param width The width that the legend need to be
140
- * @return Html code for the legend
141
- */
142
- getLayersLegendHtml(map, width, resolution) {
143
- return new Observable((observer) => {
144
- let html = '';
145
- const legends = getLayersLegends(map.layers, {
146
- resolution: map.viewController.getResolution(),
147
- extent: map.viewController.getExtent(),
148
- projection: map.viewController.getOlProjection().getCode(),
149
- // scale: map.viewController.getScale(resolution),
150
- size: map.ol.getSize()
151
- });
152
- if (legends.filter(l => l.display === true).length === 0) {
153
- observer.next(html);
154
- observer.complete();
155
- return;
156
- }
157
- // Define important style to be sure that all container is convert
158
- // to image not just visible part
159
- html += '<style media="screen" type="text/css">';
160
- html += '.html2canvas-container { width: ' + width + 'mm !important; height: 2000px !important; }';
161
- html += 'table.tableLegend {table-layout: auto;}';
162
- html += 'div.styleLegend {padding-top: 5px; padding-right:5px;padding-left:5px;padding-bottom:5px;}';
163
- html += '</style>';
164
- // The font size will also be lowered afterwards (globally along the legend size)
165
- // this allows having a good relative font size here and to keep ajusting the legend size
166
- // while keeping good relative font size
167
- html += '<font size="3" face="Times" >';
168
- html += '<div class="styleLegend">';
169
- html += '<table class="tableLegend" >';
170
- // For each legend, define an html table cell
171
- const images$ = legends.filter(l => l.display).map((legend) => this.getDataImage(legend.url).pipe(rxMap((dataImage) => {
172
- let htmlImg = '<tr><td>' + legend.title.toUpperCase() + '</td></tr>';
173
- htmlImg += '<tr><td><img src="' + dataImage + '"></td></tr>';
174
- return htmlImg;
175
- })));
176
- forkJoin(images$).subscribe((dataImages) => {
177
- html = dataImages.reduce((acc, current) => (acc += current), html);
178
- html += '</table>';
179
- html += '</div>';
180
- observer.next(html);
181
- observer.complete();
182
- });
183
- });
184
- }
185
- getDataImage(url) {
186
- const secureIMG = new SecureImagePipe(this.http, this.configService);
187
- return secureIMG.transform(url);
188
- }
189
- /**
190
- * Get all the legend in a single image
191
- * * @param format - Image format. default value to "png"
192
- * @return The image of the legend
193
- */
194
- async getLayersLegendImage(map, format = 'png', doZipFile, resolution) {
195
- const status$ = new Subject();
196
- // Get html code for the legend
197
- const width = 200; // milimeters unit, originally define for document pdf
198
- let html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
199
- format = format.toLowerCase();
200
- // If no legend show No LEGEND in an image
201
- if (html.length === 0) {
202
- html = '<font size="12" face="Courier New" >';
203
- html += '<div align="center"><b>NO LEGEND</b></div>';
204
- }
205
- // Create div to contain html code for legend
206
- const div = window.document.createElement('div');
207
- div.style.position = 'absolute';
208
- div.style.top = '0';
209
- // Add html code to convert in the new window
210
- window.document.body.appendChild(div);
211
- div.innerHTML = html;
212
- await this.timeout(1);
213
- const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
214
- console.log(e);
215
- });
216
- if (canvas) {
217
- let status = SubjectStatus.Done;
218
- try {
219
- if (!doZipFile) {
220
- // Save the canvas as file
221
- this.saveCanvasImageAsFile(canvas, 'legendImage', format);
222
- }
223
- else {
224
- // Add the canvas to zip
225
- this.generateCanvaFileToZip(canvas, 'legendImage' + '.' + format);
226
- }
227
- div.parentNode.removeChild(div); // remove temp div (IE)
228
- }
229
- catch (err) {
230
- status = SubjectStatus.Error;
231
- }
232
- status$.next(status);
233
- }
234
- return status$;
235
- }
236
- getTextPdfObjectSizeAndMarg(text, margins, font, fontSizeInPt, fontStyle, doc) {
237
- const pdfResolution = 96;
238
- const docWidth = doc.internal.pageSize.getWidth();
239
- const pageWidth = docWidth - margins[1] - margins[3];
240
- // important to set it first, the textDimension change when font change!
241
- doc.setFont(font, fontStyle);
242
- doc.setFontSize(fontSizeInPt);
243
- let textDimensions = doc.getTextDimensions(text);
244
- let textMarginLeft;
245
- if (textDimensions.w > pageWidth) {
246
- // if the text is to long, reduce fontSize 70% and the overflow with be cut in print...
247
- textMarginLeft = 0;
248
- fontSizeInPt = fontSizeInPt * 0.7;
249
- doc.setFontSize(fontSizeInPt);
250
- textDimensions = doc.getTextDimensions(text);
251
- }
252
- else {
253
- textMarginLeft = (pageWidth - textDimensions.w) / 2;
254
- }
255
- return {
256
- 'fontSize': fontSizeInPt,
257
- 'marginLeft': textMarginLeft,
258
- 'height': textDimensions.h
259
- };
260
- }
261
- /**
262
- * Add comment to the document
263
- * * @param doc - pdf document
264
- * * @param comment - Comment to add in the document
265
- */
266
- addComment(doc, comment) {
267
- const commentMarginLeft = 20; //margin left and bottom is fix
268
- const commentMarginBottom = 5;
269
- const marginTop = doc.internal.pageSize.height - commentMarginBottom;
270
- this.addTextInPdfDoc(doc, comment, this.TEXTPDFFONT.commentFont, this.TEXTPDFFONT.commentFontStyle, this.TEXTPDFFONT.commentFontSize, commentMarginLeft, marginTop);
271
- }
272
- addTextInPdfDoc(doc, textToAdd, textFont, textFontStyle, textFontSize, textMarginLeft, textMarginTop) {
273
- doc.setFont(textFont, textFontStyle);
274
- doc.setFontSize(textFontSize);
275
- doc.text(textToAdd, textMarginLeft, textMarginTop);
276
- }
277
- /**
278
- * Add projection and/or scale to the document
279
- * @param doc - pdf document
280
- * @param map - Map of the app
281
- * @param dpi - DPI resolution of the document
282
- * @param projection - Bool to indicate if projection need to be added
283
- * @param scale - Bool to indicate if scale need to be added
284
- */
285
- addProjScale(doc, map, dpi, projection, scale) {
286
- const translate = this.languageService.translate;
287
- const projScaleSize = 16;
288
- const projScaleMarginLeft = 20;
289
- const marginBottom = 15;
290
- const heightPixels = doc.internal.pageSize.height - marginBottom;
291
- let textProjScale = '';
292
- if (projection === true) {
293
- const projText = translate.instant('igo.geo.printForm.projection');
294
- textProjScale += projText + ': ' + map.projection;
295
- }
296
- if (scale === true) {
297
- if (projection === true) {
298
- textProjScale += ' ';
299
- }
300
- const scaleText = translate.instant('igo.geo.printForm.scale');
301
- const mapScale = map.viewController.getScale(dpi);
302
- textProjScale += scaleText + ': ~ 1 / ' + formatScale(mapScale);
303
- }
304
- doc.setFont('courier');
305
- doc.setFontSize(projScaleSize);
306
- doc.text(textProjScale, projScaleMarginLeft, heightPixels);
307
- }
308
- /**
309
- * Add the legend to the document
310
- * @param doc - Pdf document where legend will be added
311
- * @param map - Map of the app
312
- * @param margins - Page margins
313
- */
314
- async addLegend(doc, map, margins, resolution) {
315
- // Get html code for the legend
316
- const width = doc.internal.pageSize.width;
317
- const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
318
- // If no legend, save the map directly
319
- if (html === '') {
320
- await this.saveDoc(doc);
321
- return true;
322
- }
323
- // Create div to contain html code for legend
324
- const div = window.document.createElement('div');
325
- div.style.position = 'absolute';
326
- div.style.top = '0';
327
- // Add html code to convert in the new window
328
- window.document.body.appendChild(div);
329
- div.innerHTML = html;
330
- await this.timeout(1);
331
- const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
332
- console.log(e);
333
- });
334
- if (canvas) {
335
- const pourcentageReduction = 0.85;
336
- const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution, pourcentageReduction
337
- * (25.4 * canvas.height) / resolution];
338
- let imgData;
339
- doc.addPage();
340
- imgData = canvas.toDataURL('image/png');
341
- doc.addImage(imgData, 'PNG', 10, 10, imageSize[0], imageSize[1]);
342
- div.parentNode.removeChild(div); // remove temp div (IE style)
343
- }
344
- await this.saveDoc(doc);
345
- }
346
- /**
347
- * Add the legend to the document
348
- * @param doc - Pdf document where legend will be added
349
- * @param map - Map of the app
350
- * @param margins - Page margins
351
- */
352
- async addLegendSamePage(doc, map, margins, resolution, legendPosition) {
353
- // Get html code for the legend
354
- const width = doc.internal.pageSize.width;
355
- const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
356
- // If no legend, save the map directly
357
- if (html === '') {
358
- await this.saveDoc(doc);
359
- return true;
360
- }
361
- // Create div to contain html code for legend
362
- const div = window.document.createElement('div');
363
- div.style.position = 'absolute';
364
- div.style.top = '0';
365
- // Add html code to convert in the new window
366
- window.document.body.appendChild(div);
367
- div.innerHTML = html;
368
- await this.timeout(1);
369
- const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
370
- console.log(e);
371
- });
372
- let marginsLegend;
373
- if (canvas) {
374
- const pourcentageReduction = 0.85;
375
- const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution,
376
- pourcentageReduction * (25.4 * canvas.height) / resolution];
377
- // Move the legend to the correct position on the page
378
- if (legendPosition === 'bottomright') {
379
- marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1], margins[1],
380
- margins[2], doc.internal.pageSize.width - margins[1] - imageSize[0]];
381
- }
382
- else if (legendPosition === 'topright') {
383
- marginsLegend = [margins[0], margins[1], doc.internal.pageSize.height - margins[0] - imageSize[1],
384
- doc.internal.pageSize.width - margins[1] - imageSize[0]];
385
- }
386
- else if (legendPosition === 'bottomleft') {
387
- // When the legend is in the bottom left, raise the legend slightly upward so that attributions are visible
388
- marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1] - 15,
389
- doc.internal.pageSize.width - margins[3] - imageSize[0], margins[2] + 15, margins[3]];
390
- }
391
- else if (legendPosition === 'topleft') {
392
- marginsLegend = [margins[0], doc.internal.pageSize.width - margins[3] - imageSize[0],
393
- doc.internal.pageSize.height - margins[0] - imageSize[1], margins[3]];
394
- }
395
- this.addCanvas(doc, canvas, marginsLegend); // this adds the legend
396
- div.parentNode.removeChild(div); // remove temp div (IE style)
397
- await this.saveDoc(doc);
398
- }
399
- }
400
- /**
401
- * Add scale and attributions on the map on the document
402
- * @param doc - Pdf document where legend will be added
403
- * @param map - Map of the app
404
- * @param margins - Page margins
405
- */
406
- async addScale(doc, map, margins) {
407
- const mapSize = map.ol.getSize();
408
- const extent = map.ol.getView().calculateExtent(mapSize);
409
- // Get the scale and attribution
410
- // we use cloneNode to modify the nodes to print without modifying it on the page, using deep:true to get children
411
- let canvasOverlayHTML;
412
- const mapOverlayHTML = map.ol.getOverlayContainerStopEvent();
413
- // Remove the UI buttons from the nodes
414
- const OverlayHTMLButtons = mapOverlayHTML.getElementsByTagName('button');
415
- const OverlayHTMLButtonsarr = Array.from(OverlayHTMLButtons);
416
- for (const OverlayHTMLButton of OverlayHTMLButtonsarr) {
417
- OverlayHTMLButton.setAttribute('data-html2canvas-ignore', 'true');
418
- }
419
- // Change the styles of hyperlink in the printed version
420
- // Transform the Overlay into a canvas
421
- // scale is necessary to make it in google chrome
422
- // background as null because otherwise it is white and cover the map
423
- // allowtaint is to allow rendering images in the attributions
424
- // useCORS: true pour permettre de renderer les images (ne marche pas en local)
425
- const canvas = await html2canvas(mapOverlayHTML, {
426
- scale: 1,
427
- backgroundColor: null,
428
- allowTaint: true,
429
- useCORS: true,
430
- }).then(e => {
431
- canvasOverlayHTML = e;
432
- });
433
- this.addCanvas(doc, canvasOverlayHTML, margins); // this adds scales and attributions
434
- }
435
- defineNbFileToProcess(nbFileToProcess) {
436
- this.nbFileToProcess = nbFileToProcess;
437
- }
438
- timeout(ms) {
439
- return new Promise((resolve) => setTimeout(resolve, ms));
440
- }
441
- addCanvas(doc, canvas, margins) {
442
- let image;
443
- if (canvas) {
444
- image = canvas.toDataURL('image/png');
445
- }
446
- if (image !== undefined) {
447
- if (image.length < 20) { // img is corrupt todo: fix addScale in mobile make a corrupt img
448
- console.log('Warning: An image cannot be print in pdf file');
449
- return;
450
- }
451
- const imageSize = this.getImageSizeToFitPdf(doc, canvas, margins);
452
- doc.addImage(image, 'PNG', margins[3], margins[0], imageSize[0], imageSize[1]);
453
- doc.rect(margins[3], margins[0], imageSize[0], imageSize[1]);
454
- this.imgSizeAdded = imageSize; // keep img size for georef later
455
- }
456
- }
457
- // TODO fix printing with image resolution
458
- addMap(doc, map, resolution, size, margins) {
459
- const status$ = new Subject();
460
- const mapSize = map.ol.getSize();
461
- const extent = map.ol.getView().calculateExtent(mapSize);
462
- const widthPixels = Math.round((size[0] * resolution) / 25.4);
463
- const heightPixels = Math.round((size[1] * resolution) / 25.4);
464
- let timeout;
465
- map.ol.once('rendercomplete', (event) => {
466
- const canvases = event.target.getViewport().getElementsByTagName('canvas');
467
- const mapStatus$$ = map.status$.subscribe((mapStatus) => {
468
- clearTimeout(timeout);
469
- if (mapStatus !== SubjectStatus.Done) {
470
- return;
471
- }
472
- mapStatus$$.unsubscribe();
473
- let status = SubjectStatus.Done;
474
- try {
475
- for (const canvas of canvases) {
476
- if (canvas.width !== 0) {
477
- this.addCanvas(doc, canvas, margins);
478
- }
479
- }
480
- }
481
- catch (err) {
482
- status = SubjectStatus.Error;
483
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
484
- }
485
- this.renderMap(map, mapSize, extent);
486
- status$.next(status);
487
- });
488
- // If no loading as started after 200ms, then probably no loading
489
- // is required.
490
- timeout = window.setTimeout(() => {
491
- mapStatus$$.unsubscribe();
492
- let status = SubjectStatus.Done;
493
- try {
494
- for (const canvas of canvases) {
495
- if (canvas.width !== 0) {
496
- this.addCanvas(doc, canvas, margins);
497
- }
498
- }
499
- }
500
- catch (err) {
501
- status = SubjectStatus.Error;
502
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
503
- }
504
- this.renderMap(map, mapSize, extent);
505
- status$.next(status);
506
- }, 200);
507
- });
508
- this.renderMap(map, [widthPixels, heightPixels], extent);
509
- return status$;
510
- }
511
- /**
512
- * Download an image of the map with addition of informations
513
- * @param map - Map of the app
514
- * @param format - Image format. default value to "png"
515
- * @param projection - Indicate if projection need to be add. Default to false
516
- * @param scale - Indicate if scale need to be add. Default to false
517
- * @param legend - Indicate if the legend of layers need to be download. Default to false
518
- * @param title - Title to add for the map - Default to blank
519
- * @param subtitle - Subtitle to add for the map - Default to blank
520
- * @param comment - Comment to add for the map - Default to blank
521
- * @param doZipFile - Indicate if we do a zip with the file
522
- * @return Image file of the map with extension format given as parameter
523
- */
524
- downloadMapImage(map, resolution, format = 'png', projection = false, scale = false, title = '', subtitle = '', comment = '', doZipFile = true, legendPosition) {
525
- const status$ = new Subject();
526
- // const resolution = map.ol.getView().getResolution();
527
- this.activityId = this.activityService.register();
528
- const translate = this.languageService.translate;
529
- map.ol.once('rendercomplete', async (event) => {
530
- format = format.toLowerCase();
531
- const oldCanvas = event.target
532
- .getViewport()
533
- .getElementsByTagName('canvas')[0];
534
- const newCanvas = document.createElement('canvas');
535
- const newContext = newCanvas.getContext('2d');
536
- // Postion in height to set the canvas in new canvas
537
- let positionHCanvas = 0;
538
- // Get height/width of map canvas
539
- const width = oldCanvas.width;
540
- let height = oldCanvas.height;
541
- // Set Font to calculate comment width
542
- newContext.font = '20px Calibri';
543
- const commentWidth = newContext.measureText(comment).width;
544
- // Add height for title if defined
545
- height = title !== '' ? height + 30 : height;
546
- // Add height for title if defined
547
- height = subtitle !== '' ? height + 30 : height;
548
- // Add height for projection or scale (same line) if defined
549
- height = projection !== false || scale !== false ? height + 30 : height;
550
- const positionHProjScale = height - 10;
551
- // Define number of line depending of the comment length
552
- const commentNbLine = Math.ceil(commentWidth / width);
553
- // Add height for multiline comment if defined
554
- height = comment !== '' ? height + commentNbLine * 30 : height;
555
- let positionHComment = height - commentNbLine * 20 + 5;
556
- // Set the new canvas with the new calculated size
557
- newCanvas.width = width;
558
- newCanvas.height = height;
559
- if (['bmp', 'gif', 'jpeg', 'png', 'tiff'].indexOf(format) > -1) {
560
- // Patch Jpeg default black background to white
561
- if (format === 'jpeg') {
562
- newContext.fillStyle = '#ffffff';
563
- newContext.fillRect(0, 0, width, height);
564
- newContext.fillStyle = '#000000';
565
- }
566
- else if (title !== '' || subtitle !== '' || comment !== '' ||
567
- projection !== false || scale !== false) {
568
- newContext.fillStyle = '#ffffff';
569
- newContext.fillRect(0, 0, width, height);
570
- newContext.fillStyle = '#000000';
571
- }
572
- }
573
- // If a title need to be added to canvas
574
- if (title !== '') {
575
- // Set font for title
576
- // Adjust according to title length
577
- newContext.font = '26px Calibri';
578
- positionHCanvas = 30;
579
- newContext.textAlign = 'center';
580
- newContext.fillText(title, width / 2, 20, width * 0.9);
581
- }
582
- if (subtitle !== '') {
583
- // Set font for subtitle
584
- // Adjust according to title length
585
- newContext.font = '26px Calibri';
586
- positionHCanvas = 60;
587
- newContext.textAlign = 'center';
588
- newContext.fillText(subtitle, width / 2, 50, width * 0.9);
589
- }
590
- // Set font for next section
591
- newContext.font = '20px Calibri';
592
- // If projection or/end scale need to be added to canvas
593
- if ((projection !== false) || (scale !== false)) {
594
- let projectionScaleText = '';
595
- if (projection !== false) {
596
- const projText = translate.instant('igo.geo.printForm.projection');
597
- projectionScaleText = projText + ': ' + map.projection + ' ';
598
- }
599
- if (scale !== false) {
600
- const scaleText = translate.instant('igo.geo.printForm.scale');
601
- const mapScale = map.viewController.getScale(resolution);
602
- projectionScaleText += scaleText + ': ~ 1 / ' + formatScale(mapScale);
603
- }
604
- newContext.textAlign = 'center';
605
- newContext.fillText(projectionScaleText, width / 2, positionHProjScale, width * 0.9);
606
- }
607
- // If a comment need to be added to canvas
608
- if (comment !== '') {
609
- newContext.textAlign = 'center';
610
- // If only one line, no need to multiline the comment
611
- if (commentNbLine === 1) {
612
- newContext.fillText(comment, width / 2, positionHComment);
613
- }
614
- else {
615
- // Separate the setenses to be approx. the same length
616
- const nbCommentChar = comment.length;
617
- const CommentLengthToCut = Math.floor(nbCommentChar / commentNbLine);
618
- let commentCurrentLine = '';
619
- let positionFirstCutChar = 0;
620
- let positionLastBlank;
621
- // Loop for the number of line calculated
622
- for (let i = 0; i < commentNbLine; i++) {
623
- // For all line except last
624
- if (commentNbLine - 1 > i) {
625
- // Get comment current line to find the right place tu cut comment
626
- commentCurrentLine = comment.substr(positionFirstCutChar, CommentLengthToCut);
627
- // Cut the setence at blank
628
- positionLastBlank = commentCurrentLine.lastIndexOf(' ');
629
- newContext.fillText(commentCurrentLine.substr(0, positionLastBlank), width / 2, positionHComment);
630
- positionFirstCutChar += positionLastBlank;
631
- // Go to next line for insertion
632
- positionHComment += 20;
633
- }
634
- else {
635
- // Don't cut last part
636
- newContext.fillText(comment.substr(positionFirstCutChar), width / 2, positionHComment);
637
- }
638
- }
639
- }
640
- }
641
- // Add map to new canvas
642
- newContext.drawImage(oldCanvas, 0, positionHCanvas);
643
- // Check the legendPosition
644
- if (legendPosition !== 'none') {
645
- if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(legendPosition) > -1) {
646
- await this.addLegendToImage(newCanvas, map, resolution, legendPosition, format);
647
- }
648
- }
649
- let status = SubjectStatus.Done;
650
- let fileNameWithExt = 'map.' + format;
651
- if (format.toLowerCase() === 'tiff') {
652
- fileNameWithExt = 'map' + map.projection.replace(':', '_') + '.' + format;
653
- }
654
- try {
655
- // Save the canvas as file
656
- if (!doZipFile) {
657
- this.saveCanvasImageAsFile(newCanvas, fileNameWithExt, format);
658
- }
659
- else if (format.toLowerCase() === 'tiff') {
660
- // Add the canvas to zip
661
- this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
662
- }
663
- else {
664
- // Add the canvas to zip
665
- this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
666
- }
667
- }
668
- catch (err) {
669
- status = SubjectStatus.Error;
670
- }
671
- status$.next(status);
672
- if (format.toLowerCase() === 'tiff') {
673
- const tfwFileNameWithExt = fileNameWithExt.substring(0, fileNameWithExt.toLowerCase().indexOf('.tiff')) + '.tfw';
674
- const tiwContent = this.getWorldFileInformation(map);
675
- const blob = new Blob([tiwContent], {
676
- type: 'text/plain;charset=utf-8'
677
- });
678
- if (!doZipFile) {
679
- // saveAs automaticly replace ':' for '_'
680
- saveAs(blob, tfwFileNameWithExt);
681
- this.saveFileProcessing();
682
- }
683
- else {
684
- // Add the canvas to zip
685
- this.addFileToZip(tfwFileNameWithExt, blob);
686
- }
687
- }
688
- });
689
- map.ol.renderSync();
690
- return status$;
691
- }
692
- /**
693
- * Create and Add Legend to the map canvas
694
- * @param canvas Canvas of the map
695
- * @param map Map of the app
696
- * @param resolution Resolution of map
697
- * @param legendPosition Legend position
698
- * @param format Image format
699
- */
700
- async addLegendToImage(canvas, map, resolution, legendPosition, format) {
701
- const fileNameWithExt = 'map.' + format;
702
- const context = canvas.getContext('2d');
703
- // Get html code for the legend
704
- const html = await this.getLayersLegendHtml(map, canvas.width, resolution).toPromise();
705
- // If no legend, save the map directly
706
- if (html === '') {
707
- await this.saveCanvasImageAsFile(canvas, fileNameWithExt, format);
708
- return true;
709
- }
710
- // Create div to contain html code for legend
711
- const div = window.document.createElement('div');
712
- div.style.position = 'absolute';
713
- div.style.top = '0';
714
- // Add html code to convert in the new window
715
- window.document.body.appendChild(div);
716
- div.innerHTML = html;
717
- await this.timeout(1);
718
- const canvasLegend = await html2canvas(div, { useCORS: true }).catch((e) => {
719
- console.log(e);
720
- });
721
- if (canvasLegend) {
722
- const canvasHeight = canvas.height;
723
- const canvasWidth = canvas.width;
724
- const legendHeight = canvasLegend.height;
725
- const legendWidth = canvasLegend.width;
726
- // Move the legend to the correct position on the page
727
- const offset = canvasHeight * 0.01;
728
- let legendX;
729
- let legendY;
730
- if (legendPosition === 'bottomright') {
731
- legendX = canvasWidth - legendWidth - offset;
732
- legendY = canvasHeight - legendHeight - offset;
733
- }
734
- else if (legendPosition === 'topright') {
735
- legendX = canvasWidth - legendWidth - offset;
736
- legendY = offset;
737
- }
738
- else if (legendPosition === 'bottomleft') {
739
- legendX = offset;
740
- legendY = canvasHeight - legendHeight - offset;
741
- }
742
- else if (legendPosition === 'topleft') {
743
- legendX = offset;
744
- legendY = offset;
745
- }
746
- context.drawImage(canvasLegend, legendX, legendY, legendWidth, legendHeight);
747
- context.strokeRect(legendX, legendY, legendWidth, legendHeight);
748
- div.parentNode.removeChild(div); // remove temp div (IE style)
749
- return true;
750
- }
751
- }
752
- renderMap(map, size, extent) {
753
- map.ol.updateSize();
754
- map.ol.renderSync();
755
- }
756
- /**
757
- * Save document
758
- * @param doc - Document to save
759
- */
760
- async saveDoc(doc) {
761
- await doc.save('map_georef.pdf', { returnPromise: true });
762
- }
763
- /**
764
- * Calculate the best Image size to fit in pdf
765
- * @param doc - Pdf Document
766
- * @param canvas - Canvas of image
767
- * @param margins - Page margins
768
- */
769
- getImageSizeToFitPdf(doc, canvas, margins) {
770
- // Define variable to calculate best size to fit in one page
771
- const pageHeight = doc.internal.pageSize.getHeight() - (margins[0] + margins[2]);
772
- const pageWidth = doc.internal.pageSize.getWidth() - (margins[1] + margins[3]);
773
- const canHeight = this.pdf_units2points(canvas.height, 'mm');
774
- const canWidth = this.pdf_units2points(canvas.width, 'mm');
775
- const heightRatio = canHeight / pageHeight;
776
- const widthRatio = canWidth / pageWidth;
777
- const maxRatio = heightRatio > widthRatio ? heightRatio : widthRatio;
778
- const imgHeigh = maxRatio > 1 ? canHeight / maxRatio : canHeight;
779
- const imgWidth = maxRatio > 1 ? canWidth / maxRatio : canWidth;
780
- return [imgWidth, imgHeigh];
781
- }
782
- /**
783
- * Get a world file information for tiff
784
- * @param map - Map of the app
785
- */
786
- getWorldFileInformation(map) {
787
- const currentResolution = map.viewController.getResolution();
788
- const currentExtent = map.viewController.getExtent(); // Return [minx, miny, maxx, maxy]
789
- return [
790
- currentResolution,
791
- 0,
792
- 0,
793
- -currentResolution,
794
- currentExtent[0] + currentResolution / 0.5,
795
- currentExtent[3] - currentResolution / 0.5
796
- ].join('\n');
797
- }
798
- /**
799
- * Save canvas image as file
800
- * @param canvas - Canvas to save
801
- * @param name - Name of the file
802
- * @param format - file format
803
- */
804
- saveCanvasImageAsFile(canvas, nameWithExt, format) {
805
- const blobFormat = 'image/' + format;
806
- const that = this;
807
- try {
808
- canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
809
- // If navigator is Internet Explorer
810
- if (navigator.msSaveBlob) {
811
- navigator.msSaveBlob(canvas.msToBlob(), nameWithExt);
812
- this.saveFileProcessing();
813
- }
814
- else {
815
- canvas.toBlob((blob) => {
816
- // download image
817
- saveAs(blob, nameWithExt);
818
- that.saveFileProcessing();
819
- }, blobFormat);
820
- }
821
- }
822
- catch (err) {
823
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
824
- }
825
- }
826
- /**
827
- * Add file to a zip
828
- * @param canvas - File to add to the zip
829
- * @param name -Name of the fileoverview
830
- */
831
- generateCanvaFileToZip(canvas, name) {
832
- const blobFormat = 'image/' + 'jpeg';
833
- const that = this;
834
- if (!this.hasOwnProperty('zipFile') ||
835
- typeof this.zipFile === 'undefined') {
836
- this.zipFile = new JSZip();
837
- }
838
- try {
839
- canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
840
- if (navigator.msSaveBlob) {
841
- this.addFileToZip(name, canvas.msToBlob());
842
- }
843
- else {
844
- canvas.toBlob((blob) => {
845
- that.addFileToZip(name, blob);
846
- }, blobFormat);
847
- }
848
- }
849
- catch (err) {
850
- this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
851
- }
852
- }
853
- /**
854
- * Add file to zip, if all file are zipped, download
855
- * @param name - Name of the files
856
- * @param blob - Contain of file
857
- */
858
- addFileToZip(name, blob) {
859
- // add file to zip
860
- this.zipFile.file(name, blob);
861
- this.nbFileToProcess--;
862
- // If all files are proccessed
863
- if (this.nbFileToProcess === 0) {
864
- // Download zip file
865
- this.getZipFile();
866
- // Stop loading
867
- this.activityService.unregister(this.activityId);
868
- }
869
- }
870
- saveFileProcessing() {
871
- this.nbFileToProcess--;
872
- // If all files are proccessed
873
- if (this.nbFileToProcess === 0) {
874
- // Stop loading
875
- this.activityService.unregister(this.activityId);
876
- }
877
- }
878
- /**
879
- * Get the zipped file
880
- * @return Retun a zip file
881
- */
882
- getZipFile() {
883
- const that = this;
884
- this.zipFile.generateAsync({ type: 'blob' }).then((blob) => {
885
- // 1) generate the zip file
886
- saveAs(blob, 'map.zip');
887
- delete that.zipFile;
888
- });
889
- }
890
- pdf_units2points(n, unit) {
891
- let k = 1;
892
- // this code is borrowed from jsPDF
893
- // as it does not expose a public API
894
- // for converting units to points.
895
- switch (unit) {
896
- case 'pt':
897
- k = 1;
898
- break;
899
- case 'mm':
900
- k = 72 / 25.4;
901
- break;
902
- case 'cm':
903
- k = 72 / 2.54;
904
- break;
905
- case 'in':
906
- k = 72;
907
- break;
908
- case 'px':
909
- k = 96 / 72;
910
- break;
911
- case 'pc':
912
- k = 12;
913
- break;
914
- case 'em':
915
- k = 12;
916
- break;
917
- case 'ex':
918
- k = 6;
919
- break;
920
- default:
921
- throw new Error('Invalid unit: ' + unit);
922
- }
923
- return n * k;
924
- }
925
- }
926
- PrintService.ɵfac = function PrintService_Factory(t) { return new (t || PrintService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(i2.MessageService), i0.ɵɵinject(i2.ActivityService), i0.ɵɵinject(i2.LanguageService), i0.ɵɵinject(i2.ConfigService)); };
927
- PrintService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PrintService, factory: PrintService.ɵfac, providedIn: 'root' });
928
- (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrintService, [{
929
- type: Injectable,
930
- args: [{
931
- providedIn: 'root'
932
- }]
933
- }], function () { return [{ type: i1.HttpClient }, { type: i2.MessageService }, { type: i2.ActivityService }, { type: i2.LanguageService }, { type: i2.ConfigService }]; }, null); })();
1
+ import { Injectable } from '@angular/core';
2
+ import { Observable, Subject, forkJoin } from 'rxjs';
3
+ import { map as rxMap } from 'rxjs/operators';
4
+ import { saveAs } from 'file-saver';
5
+ import jsPDF from 'jspdf';
6
+ import html2canvas from 'html2canvas';
7
+ import { default as JSZip } from 'jszip';
8
+ import { SubjectStatus } from '@igo2/utils';
9
+ import { SecureImagePipe } from '@igo2/common';
10
+ import { formatScale } from '../../map/shared/map.utils';
11
+ import { getLayersLegends } from '../../layer/utils/outputLegend';
12
+ import GeoPdfPlugin from './geopdf';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@angular/common/http";
15
+ import * as i2 from "@igo2/core";
16
+ export class PrintService {
17
+ constructor(http, messageService, activityService, languageService, configService) {
18
+ this.http = http;
19
+ this.messageService = messageService;
20
+ this.activityService = activityService;
21
+ this.languageService = languageService;
22
+ this.configService = configService;
23
+ this.TEXTPDFFONT = {
24
+ titleFont: 'Times',
25
+ titleFontStyle: 'bold',
26
+ subtitleFont: 'Times',
27
+ subtitleFontStyle: 'bold',
28
+ commentFont: 'courier',
29
+ commentFontStyle: 'normal',
30
+ commentFontSize: 16
31
+ };
32
+ }
33
+ print(map, options) {
34
+ const status$ = new Subject();
35
+ const paperFormat = options.paperFormat;
36
+ const resolution = +options.resolution; // Default is 96
37
+ const orientation = options.orientation;
38
+ const legendPostion = options.legendPosition;
39
+ this.activityId = this.activityService.register();
40
+ GeoPdfPlugin(jsPDF.API);
41
+ const doc = new jsPDF({
42
+ orientation,
43
+ format: paperFormat.toLowerCase(),
44
+ unit: 'mm' // default
45
+ });
46
+ const dimensions = [
47
+ doc.internal.pageSize.width,
48
+ doc.internal.pageSize.height
49
+ ];
50
+ const margins = [10, 10, 10, 10];
51
+ const width = dimensions[0] - margins[3] - margins[1];
52
+ const height = dimensions[1] - margins[0] - margins[2];
53
+ const size = [width, height];
54
+ let titleSizes;
55
+ let subtitleSizes;
56
+ // PDF title
57
+ if (options.title !== undefined) {
58
+ const fontSizeInPt = Math.round(2 * (height + 145) * 0.05) / 2; //calculate the fontSize title from the page height.
59
+ titleSizes = this.getTextPdfObjectSizeAndMarg(options.title, margins, this.TEXTPDFFONT.titleFont, fontSizeInPt, this.TEXTPDFFONT.titleFontStyle, doc);
60
+ this.addTextInPdfDoc(doc, options.title, this.TEXTPDFFONT.titleFont, this.TEXTPDFFONT.titleFontStyle, titleSizes.fontSize, titleSizes.marginLeft + margins[3], margins[0]);
61
+ margins[0] = titleSizes.height + margins[0]; // cumulative margin top for next elem to place in pdf doc
62
+ }
63
+ // PDF subtitle
64
+ if (options.subtitle !== undefined) {
65
+ subtitleSizes = this.getTextPdfObjectSizeAndMarg(options.subtitle, margins, this.TEXTPDFFONT.subtitleFont, titleSizes.fontSize * 0.7, // 70% size of title
66
+ this.TEXTPDFFONT.subtitleFontStyle, doc);
67
+ this.addTextInPdfDoc(doc, options.subtitle, this.TEXTPDFFONT.subtitleFont, this.TEXTPDFFONT.subtitleFontStyle, subtitleSizes.fontSize, subtitleSizes.marginLeft + margins[3], margins[0]);
68
+ margins[0] += 5; // cumulative marg top for next elem to place in pdf doc. 5 is a fix it could be adjust
69
+ }
70
+ if (options.showProjection === true || options.showScale === true) {
71
+ this.addProjScale(doc, map, resolution, options.showProjection, options.showScale);
72
+ }
73
+ if (options.comment !== '') {
74
+ this.addComment(doc, options.comment);
75
+ }
76
+ this.addMap(doc, map, resolution, size, margins).subscribe(async (status) => {
77
+ if (status === SubjectStatus.Done) {
78
+ await this.addScale(doc, map, margins);
79
+ await this.handleMeasureLayer(doc, map, margins);
80
+ const width = this.imgSizeAdded[0];
81
+ const height = this.imgSizeAdded[1];
82
+ const res = 1;
83
+ this.addGeoRef(doc, map, width, height, res, margins);
84
+ if (options.legendPosition !== 'none') {
85
+ if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(options.legendPosition) > -1) {
86
+ await this.addLegendSamePage(doc, map, margins, resolution, options.legendPosition);
87
+ }
88
+ else if (options.legendPosition === 'newpage') {
89
+ await this.addLegend(doc, map, margins, resolution);
90
+ }
91
+ }
92
+ else {
93
+ await this.saveDoc(doc);
94
+ }
95
+ }
96
+ if (status === SubjectStatus.Done || status === SubjectStatus.Error) {
97
+ this.activityService.unregister(this.activityId);
98
+ status$.next(SubjectStatus.Done);
99
+ }
100
+ });
101
+ return status$;
102
+ }
103
+ // ref GeoMoose https://github.com/geomoose/gm3/tree/main/src/gm3/components/print
104
+ addGeoRef(doc, map, width, height, resolution, margins) {
105
+ const unit = 'mm';
106
+ const docHeight = doc.internal.pageSize.getHeight();
107
+ // x,y = margin left-bottom corner for img in pdf doc
108
+ const x = margins[3];
109
+ const y = docHeight - margins[0] - height;
110
+ let pdf_extents = [x, y, x + width, y + height];
111
+ for (let i = 0; i < pdf_extents.length; i++) {
112
+ pdf_extents[i] = this.pdf_units2points(pdf_extents[i], unit);
113
+ }
114
+ const mapExtent = map.viewController.getExtent('EPSG:3857');
115
+ doc.setGeoArea(pdf_extents, mapExtent);
116
+ }
117
+ /**
118
+ * Add measure overlay on the map on the document when the measure layer is present
119
+ * @param doc - Pdf document where measure tooltip will be added
120
+ * @param map - Map of the app
121
+ * @param margins - Page margins
122
+ */
123
+ async handleMeasureLayer(doc, map, margins) {
124
+ if (map.layers.find(layer => layer.visible && layer.id.startsWith('igo-measures-'))) {
125
+ let canvasOverlayHTMLMeasures;
126
+ const mapOverlayMeasuresHTML = map.ol.getOverlayContainer();
127
+ await html2canvas(mapOverlayMeasuresHTML, {
128
+ scale: 1,
129
+ backgroundColor: null
130
+ }).then(e => {
131
+ canvasOverlayHTMLMeasures = e;
132
+ });
133
+ this.addCanvas(doc, canvasOverlayHTMLMeasures, margins); // this adds measure overlays
134
+ }
135
+ }
136
+ /**
137
+ * Get html code for all layers legend
138
+ * @param map IgoMap
139
+ * @param width The width that the legend need to be
140
+ * @return Html code for the legend
141
+ */
142
+ getLayersLegendHtml(map, width, resolution) {
143
+ return new Observable((observer) => {
144
+ let html = '';
145
+ const legends = getLayersLegends(map.layers, {
146
+ resolution: map.viewController.getResolution(),
147
+ extent: map.viewController.getExtent(),
148
+ projection: map.viewController.getOlProjection().getCode(),
149
+ // scale: map.viewController.getScale(resolution),
150
+ size: map.ol.getSize()
151
+ });
152
+ if (legends.filter(l => l.display === true).length === 0) {
153
+ observer.next(html);
154
+ observer.complete();
155
+ return;
156
+ }
157
+ // Define important style to be sure that all container is convert
158
+ // to image not just visible part
159
+ html += '<style media="screen" type="text/css">';
160
+ html += '.html2canvas-container { width: ' + width + 'mm !important; height: 2000px !important; }';
161
+ html += 'table.tableLegend {table-layout: auto;}';
162
+ html += 'div.styleLegend {padding-top: 5px; padding-right:5px;padding-left:5px;padding-bottom:5px;}';
163
+ html += '</style>';
164
+ // The font size will also be lowered afterwards (globally along the legend size)
165
+ // this allows having a good relative font size here and to keep ajusting the legend size
166
+ // while keeping good relative font size
167
+ html += '<font size="3" face="Times" >';
168
+ html += '<div class="styleLegend">';
169
+ html += '<table class="tableLegend" >';
170
+ // For each legend, define an html table cell
171
+ const images$ = legends.filter(l => l.display).map((legend) => this.getDataImage(legend.url).pipe(rxMap((dataImage) => {
172
+ let htmlImg = '<tr><td>' + legend.title.toUpperCase() + '</td></tr>';
173
+ htmlImg += '<tr><td><img src="' + dataImage + '"></td></tr>';
174
+ return htmlImg;
175
+ })));
176
+ forkJoin(images$).subscribe((dataImages) => {
177
+ html = dataImages.reduce((acc, current) => (acc += current), html);
178
+ html += '</table>';
179
+ html += '</div>';
180
+ observer.next(html);
181
+ observer.complete();
182
+ });
183
+ });
184
+ }
185
+ getDataImage(url) {
186
+ const secureIMG = new SecureImagePipe(this.http, this.configService);
187
+ return secureIMG.transform(url);
188
+ }
189
+ /**
190
+ * Get all the legend in a single image
191
+ * * @param format - Image format. default value to "png"
192
+ * @return The image of the legend
193
+ */
194
+ async getLayersLegendImage(map, format = 'png', doZipFile, resolution) {
195
+ const status$ = new Subject();
196
+ // Get html code for the legend
197
+ const width = 200; // milimeters unit, originally define for document pdf
198
+ let html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
199
+ format = format.toLowerCase();
200
+ // If no legend show No LEGEND in an image
201
+ if (html.length === 0) {
202
+ html = '<font size="12" face="Courier New" >';
203
+ html += '<div align="center"><b>NO LEGEND</b></div>';
204
+ }
205
+ // Create div to contain html code for legend
206
+ const div = window.document.createElement('div');
207
+ div.style.position = 'absolute';
208
+ div.style.top = '0';
209
+ // Add html code to convert in the new window
210
+ window.document.body.appendChild(div);
211
+ div.innerHTML = html;
212
+ await this.timeout(1);
213
+ const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
214
+ console.log(e);
215
+ });
216
+ if (canvas) {
217
+ let status = SubjectStatus.Done;
218
+ try {
219
+ if (!doZipFile) {
220
+ // Save the canvas as file
221
+ this.saveCanvasImageAsFile(canvas, 'legendImage', format);
222
+ }
223
+ else {
224
+ // Add the canvas to zip
225
+ this.generateCanvaFileToZip(canvas, 'legendImage' + '.' + format);
226
+ }
227
+ div.parentNode.removeChild(div); // remove temp div (IE)
228
+ }
229
+ catch (err) {
230
+ status = SubjectStatus.Error;
231
+ }
232
+ status$.next(status);
233
+ }
234
+ return status$;
235
+ }
236
+ getTextPdfObjectSizeAndMarg(text, margins, font, fontSizeInPt, fontStyle, doc) {
237
+ const pdfResolution = 96;
238
+ const docWidth = doc.internal.pageSize.getWidth();
239
+ const pageWidth = docWidth - margins[1] - margins[3];
240
+ // important to set it first, the textDimension change when font change!
241
+ doc.setFont(font, fontStyle);
242
+ doc.setFontSize(fontSizeInPt);
243
+ let textDimensions = doc.getTextDimensions(text);
244
+ let textMarginLeft;
245
+ if (textDimensions.w > pageWidth) {
246
+ // if the text is to long, reduce fontSize 70% and the overflow with be cut in print...
247
+ textMarginLeft = 0;
248
+ fontSizeInPt = fontSizeInPt * 0.7;
249
+ doc.setFontSize(fontSizeInPt);
250
+ textDimensions = doc.getTextDimensions(text);
251
+ }
252
+ else {
253
+ textMarginLeft = (pageWidth - textDimensions.w) / 2;
254
+ }
255
+ return {
256
+ 'fontSize': fontSizeInPt,
257
+ 'marginLeft': textMarginLeft,
258
+ 'height': textDimensions.h
259
+ };
260
+ }
261
+ /**
262
+ * Add comment to the document
263
+ * * @param doc - pdf document
264
+ * * @param comment - Comment to add in the document
265
+ */
266
+ addComment(doc, comment) {
267
+ const commentMarginLeft = 20; //margin left and bottom is fix
268
+ const commentMarginBottom = 5;
269
+ const marginTop = doc.internal.pageSize.height - commentMarginBottom;
270
+ this.addTextInPdfDoc(doc, comment, this.TEXTPDFFONT.commentFont, this.TEXTPDFFONT.commentFontStyle, this.TEXTPDFFONT.commentFontSize, commentMarginLeft, marginTop);
271
+ }
272
+ addTextInPdfDoc(doc, textToAdd, textFont, textFontStyle, textFontSize, textMarginLeft, textMarginTop) {
273
+ doc.setFont(textFont, textFontStyle);
274
+ doc.setFontSize(textFontSize);
275
+ doc.text(textToAdd, textMarginLeft, textMarginTop);
276
+ }
277
+ /**
278
+ * Add projection and/or scale to the document
279
+ * @param doc - pdf document
280
+ * @param map - Map of the app
281
+ * @param dpi - DPI resolution of the document
282
+ * @param projection - Bool to indicate if projection need to be added
283
+ * @param scale - Bool to indicate if scale need to be added
284
+ */
285
+ addProjScale(doc, map, dpi, projection, scale) {
286
+ const translate = this.languageService.translate;
287
+ const projScaleSize = 16;
288
+ const projScaleMarginLeft = 20;
289
+ const marginBottom = 15;
290
+ const heightPixels = doc.internal.pageSize.height - marginBottom;
291
+ let textProjScale = '';
292
+ if (projection === true) {
293
+ const projText = translate.instant('igo.geo.printForm.projection');
294
+ textProjScale += projText + ': ' + map.projection;
295
+ }
296
+ if (scale === true) {
297
+ if (projection === true) {
298
+ textProjScale += ' ';
299
+ }
300
+ const scaleText = translate.instant('igo.geo.printForm.scale');
301
+ const mapScale = map.viewController.getScale(dpi);
302
+ textProjScale += scaleText + ': ~ 1 / ' + formatScale(mapScale);
303
+ }
304
+ doc.setFont('courier');
305
+ doc.setFontSize(projScaleSize);
306
+ doc.text(textProjScale, projScaleMarginLeft, heightPixels);
307
+ }
308
+ /**
309
+ * Add the legend to the document
310
+ * @param doc - Pdf document where legend will be added
311
+ * @param map - Map of the app
312
+ * @param margins - Page margins
313
+ */
314
+ async addLegend(doc, map, margins, resolution) {
315
+ // Get html code for the legend
316
+ const width = doc.internal.pageSize.width;
317
+ const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
318
+ // If no legend, save the map directly
319
+ if (html === '') {
320
+ await this.saveDoc(doc);
321
+ return true;
322
+ }
323
+ // Create div to contain html code for legend
324
+ const div = window.document.createElement('div');
325
+ div.style.position = 'absolute';
326
+ div.style.top = '0';
327
+ // Add html code to convert in the new window
328
+ window.document.body.appendChild(div);
329
+ div.innerHTML = html;
330
+ await this.timeout(1);
331
+ const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
332
+ console.log(e);
333
+ });
334
+ if (canvas) {
335
+ const pourcentageReduction = 0.85;
336
+ const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution, pourcentageReduction
337
+ * (25.4 * canvas.height) / resolution];
338
+ let imgData;
339
+ doc.addPage();
340
+ imgData = canvas.toDataURL('image/png');
341
+ doc.addImage(imgData, 'PNG', 10, 10, imageSize[0], imageSize[1]);
342
+ div.parentNode.removeChild(div); // remove temp div (IE style)
343
+ }
344
+ await this.saveDoc(doc);
345
+ }
346
+ /**
347
+ * Add the legend to the document
348
+ * @param doc - Pdf document where legend will be added
349
+ * @param map - Map of the app
350
+ * @param margins - Page margins
351
+ */
352
+ async addLegendSamePage(doc, map, margins, resolution, legendPosition) {
353
+ // Get html code for the legend
354
+ const width = doc.internal.pageSize.width;
355
+ const html = await this.getLayersLegendHtml(map, width, resolution).toPromise();
356
+ // If no legend, save the map directly
357
+ if (html === '') {
358
+ await this.saveDoc(doc);
359
+ return true;
360
+ }
361
+ // Create div to contain html code for legend
362
+ const div = window.document.createElement('div');
363
+ div.style.position = 'absolute';
364
+ div.style.top = '0';
365
+ // Add html code to convert in the new window
366
+ window.document.body.appendChild(div);
367
+ div.innerHTML = html;
368
+ await this.timeout(1);
369
+ const canvas = await html2canvas(div, { useCORS: true }).catch((e) => {
370
+ console.log(e);
371
+ });
372
+ let marginsLegend;
373
+ if (canvas) {
374
+ const pourcentageReduction = 0.85;
375
+ const imageSize = [pourcentageReduction * (25.4 * canvas.width) / resolution,
376
+ pourcentageReduction * (25.4 * canvas.height) / resolution];
377
+ // Move the legend to the correct position on the page
378
+ if (legendPosition === 'bottomright') {
379
+ marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1], margins[1],
380
+ margins[2], doc.internal.pageSize.width - margins[1] - imageSize[0]];
381
+ }
382
+ else if (legendPosition === 'topright') {
383
+ marginsLegend = [margins[0], margins[1], doc.internal.pageSize.height - margins[0] - imageSize[1],
384
+ doc.internal.pageSize.width - margins[1] - imageSize[0]];
385
+ }
386
+ else if (legendPosition === 'bottomleft') {
387
+ // When the legend is in the bottom left, raise the legend slightly upward so that attributions are visible
388
+ marginsLegend = [doc.internal.pageSize.height - margins[2] - imageSize[1] - 15,
389
+ doc.internal.pageSize.width - margins[3] - imageSize[0], margins[2] + 15, margins[3]];
390
+ }
391
+ else if (legendPosition === 'topleft') {
392
+ marginsLegend = [margins[0], doc.internal.pageSize.width - margins[3] - imageSize[0],
393
+ doc.internal.pageSize.height - margins[0] - imageSize[1], margins[3]];
394
+ }
395
+ this.addCanvas(doc, canvas, marginsLegend); // this adds the legend
396
+ div.parentNode.removeChild(div); // remove temp div (IE style)
397
+ await this.saveDoc(doc);
398
+ }
399
+ }
400
+ /**
401
+ * Add scale and attributions on the map on the document
402
+ * @param doc - Pdf document where legend will be added
403
+ * @param map - Map of the app
404
+ * @param margins - Page margins
405
+ */
406
+ async addScale(doc, map, margins) {
407
+ const mapSize = map.ol.getSize();
408
+ const extent = map.ol.getView().calculateExtent(mapSize);
409
+ // Get the scale and attribution
410
+ // we use cloneNode to modify the nodes to print without modifying it on the page, using deep:true to get children
411
+ let canvasOverlayHTML;
412
+ const mapOverlayHTML = map.ol.getOverlayContainerStopEvent();
413
+ // Remove the UI buttons from the nodes
414
+ const OverlayHTMLButtons = mapOverlayHTML.getElementsByTagName('button');
415
+ const OverlayHTMLButtonsarr = Array.from(OverlayHTMLButtons);
416
+ for (const OverlayHTMLButton of OverlayHTMLButtonsarr) {
417
+ OverlayHTMLButton.setAttribute('data-html2canvas-ignore', 'true');
418
+ }
419
+ // Change the styles of hyperlink in the printed version
420
+ // Transform the Overlay into a canvas
421
+ // scale is necessary to make it in google chrome
422
+ // background as null because otherwise it is white and cover the map
423
+ // allowtaint is to allow rendering images in the attributions
424
+ // useCORS: true pour permettre de renderer les images (ne marche pas en local)
425
+ const canvas = await html2canvas(mapOverlayHTML, {
426
+ scale: 1,
427
+ backgroundColor: null,
428
+ allowTaint: true,
429
+ useCORS: true,
430
+ }).then(e => {
431
+ canvasOverlayHTML = e;
432
+ });
433
+ this.addCanvas(doc, canvasOverlayHTML, margins); // this adds scales and attributions
434
+ }
435
+ defineNbFileToProcess(nbFileToProcess) {
436
+ this.nbFileToProcess = nbFileToProcess;
437
+ }
438
+ timeout(ms) {
439
+ return new Promise((resolve) => setTimeout(resolve, ms));
440
+ }
441
+ addCanvas(doc, canvas, margins) {
442
+ let image;
443
+ if (canvas) {
444
+ image = canvas.toDataURL('image/png');
445
+ }
446
+ if (image !== undefined) {
447
+ if (image.length < 20) { // img is corrupt todo: fix addScale in mobile make a corrupt img
448
+ console.log('Warning: An image cannot be print in pdf file');
449
+ return;
450
+ }
451
+ const imageSize = this.getImageSizeToFitPdf(doc, canvas, margins);
452
+ doc.addImage(image, 'PNG', margins[3], margins[0], imageSize[0], imageSize[1]);
453
+ doc.rect(margins[3], margins[0], imageSize[0], imageSize[1]);
454
+ this.imgSizeAdded = imageSize; // keep img size for georef later
455
+ }
456
+ }
457
+ // TODO fix printing with image resolution
458
+ addMap(doc, map, resolution, size, margins) {
459
+ const status$ = new Subject();
460
+ const mapSize = map.ol.getSize();
461
+ const extent = map.ol.getView().calculateExtent(mapSize);
462
+ const widthPixels = Math.round((size[0] * resolution) / 25.4);
463
+ const heightPixels = Math.round((size[1] * resolution) / 25.4);
464
+ let timeout;
465
+ map.ol.once('rendercomplete', (event) => {
466
+ const canvases = event.target.getViewport().getElementsByTagName('canvas');
467
+ const mapStatus$$ = map.status$.subscribe((mapStatus) => {
468
+ clearTimeout(timeout);
469
+ if (mapStatus !== SubjectStatus.Done) {
470
+ return;
471
+ }
472
+ mapStatus$$.unsubscribe();
473
+ let status = SubjectStatus.Done;
474
+ try {
475
+ for (const canvas of canvases) {
476
+ if (canvas.width !== 0) {
477
+ this.addCanvas(doc, canvas, margins);
478
+ }
479
+ }
480
+ }
481
+ catch (err) {
482
+ status = SubjectStatus.Error;
483
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
484
+ }
485
+ this.renderMap(map, mapSize, extent);
486
+ status$.next(status);
487
+ });
488
+ // If no loading as started after 200ms, then probably no loading
489
+ // is required.
490
+ timeout = window.setTimeout(() => {
491
+ mapStatus$$.unsubscribe();
492
+ let status = SubjectStatus.Done;
493
+ try {
494
+ for (const canvas of canvases) {
495
+ if (canvas.width !== 0) {
496
+ this.addCanvas(doc, canvas, margins);
497
+ }
498
+ }
499
+ }
500
+ catch (err) {
501
+ status = SubjectStatus.Error;
502
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
503
+ }
504
+ this.renderMap(map, mapSize, extent);
505
+ status$.next(status);
506
+ }, 200);
507
+ });
508
+ this.renderMap(map, [widthPixels, heightPixels], extent);
509
+ return status$;
510
+ }
511
+ /**
512
+ * Download an image of the map with addition of informations
513
+ * @param map - Map of the app
514
+ * @param format - Image format. default value to "png"
515
+ * @param projection - Indicate if projection need to be add. Default to false
516
+ * @param scale - Indicate if scale need to be add. Default to false
517
+ * @param legend - Indicate if the legend of layers need to be download. Default to false
518
+ * @param title - Title to add for the map - Default to blank
519
+ * @param subtitle - Subtitle to add for the map - Default to blank
520
+ * @param comment - Comment to add for the map - Default to blank
521
+ * @param doZipFile - Indicate if we do a zip with the file
522
+ * @return Image file of the map with extension format given as parameter
523
+ */
524
+ downloadMapImage(map, resolution, format = 'png', projection = false, scale = false, title = '', subtitle = '', comment = '', doZipFile = true, legendPosition) {
525
+ const status$ = new Subject();
526
+ // const resolution = map.ol.getView().getResolution();
527
+ this.activityId = this.activityService.register();
528
+ const translate = this.languageService.translate;
529
+ map.ol.once('rendercomplete', async (event) => {
530
+ format = format.toLowerCase();
531
+ const oldCanvas = event.target
532
+ .getViewport()
533
+ .getElementsByTagName('canvas')[0];
534
+ const newCanvas = document.createElement('canvas');
535
+ const newContext = newCanvas.getContext('2d');
536
+ // Postion in height to set the canvas in new canvas
537
+ let positionHCanvas = 0;
538
+ // Get height/width of map canvas
539
+ const width = oldCanvas.width;
540
+ let height = oldCanvas.height;
541
+ // Set Font to calculate comment width
542
+ newContext.font = '20px Calibri';
543
+ const commentWidth = newContext.measureText(comment).width;
544
+ // Add height for title if defined
545
+ height = title !== '' ? height + 30 : height;
546
+ // Add height for title if defined
547
+ height = subtitle !== '' ? height + 30 : height;
548
+ // Add height for projection or scale (same line) if defined
549
+ height = projection !== false || scale !== false ? height + 30 : height;
550
+ const positionHProjScale = height - 10;
551
+ // Define number of line depending of the comment length
552
+ const commentNbLine = Math.ceil(commentWidth / width);
553
+ // Add height for multiline comment if defined
554
+ height = comment !== '' ? height + commentNbLine * 30 : height;
555
+ let positionHComment = height - commentNbLine * 20 + 5;
556
+ // Set the new canvas with the new calculated size
557
+ newCanvas.width = width;
558
+ newCanvas.height = height;
559
+ if (['bmp', 'gif', 'jpeg', 'png', 'tiff'].indexOf(format) > -1) {
560
+ // Patch Jpeg default black background to white
561
+ if (format === 'jpeg') {
562
+ newContext.fillStyle = '#ffffff';
563
+ newContext.fillRect(0, 0, width, height);
564
+ newContext.fillStyle = '#000000';
565
+ }
566
+ else if (title !== '' || subtitle !== '' || comment !== '' ||
567
+ projection !== false || scale !== false) {
568
+ newContext.fillStyle = '#ffffff';
569
+ newContext.fillRect(0, 0, width, height);
570
+ newContext.fillStyle = '#000000';
571
+ }
572
+ }
573
+ // If a title need to be added to canvas
574
+ if (title !== '') {
575
+ // Set font for title
576
+ // Adjust according to title length
577
+ newContext.font = '26px Calibri';
578
+ positionHCanvas = 30;
579
+ newContext.textAlign = 'center';
580
+ newContext.fillText(title, width / 2, 20, width * 0.9);
581
+ }
582
+ if (subtitle !== '') {
583
+ // Set font for subtitle
584
+ // Adjust according to title length
585
+ newContext.font = '26px Calibri';
586
+ positionHCanvas = 60;
587
+ newContext.textAlign = 'center';
588
+ newContext.fillText(subtitle, width / 2, 50, width * 0.9);
589
+ }
590
+ // Set font for next section
591
+ newContext.font = '20px Calibri';
592
+ // If projection or/end scale need to be added to canvas
593
+ if ((projection !== false) || (scale !== false)) {
594
+ let projectionScaleText = '';
595
+ if (projection !== false) {
596
+ const projText = translate.instant('igo.geo.printForm.projection');
597
+ projectionScaleText = projText + ': ' + map.projection + ' ';
598
+ }
599
+ if (scale !== false) {
600
+ const scaleText = translate.instant('igo.geo.printForm.scale');
601
+ const mapScale = map.viewController.getScale(resolution);
602
+ projectionScaleText += scaleText + ': ~ 1 / ' + formatScale(mapScale);
603
+ }
604
+ newContext.textAlign = 'center';
605
+ newContext.fillText(projectionScaleText, width / 2, positionHProjScale, width * 0.9);
606
+ }
607
+ // If a comment need to be added to canvas
608
+ if (comment !== '') {
609
+ newContext.textAlign = 'center';
610
+ // If only one line, no need to multiline the comment
611
+ if (commentNbLine === 1) {
612
+ newContext.fillText(comment, width / 2, positionHComment);
613
+ }
614
+ else {
615
+ // Separate the setenses to be approx. the same length
616
+ const nbCommentChar = comment.length;
617
+ const CommentLengthToCut = Math.floor(nbCommentChar / commentNbLine);
618
+ let commentCurrentLine = '';
619
+ let positionFirstCutChar = 0;
620
+ let positionLastBlank;
621
+ // Loop for the number of line calculated
622
+ for (let i = 0; i < commentNbLine; i++) {
623
+ // For all line except last
624
+ if (commentNbLine - 1 > i) {
625
+ // Get comment current line to find the right place tu cut comment
626
+ commentCurrentLine = comment.substr(positionFirstCutChar, CommentLengthToCut);
627
+ // Cut the setence at blank
628
+ positionLastBlank = commentCurrentLine.lastIndexOf(' ');
629
+ newContext.fillText(commentCurrentLine.substr(0, positionLastBlank), width / 2, positionHComment);
630
+ positionFirstCutChar += positionLastBlank;
631
+ // Go to next line for insertion
632
+ positionHComment += 20;
633
+ }
634
+ else {
635
+ // Don't cut last part
636
+ newContext.fillText(comment.substr(positionFirstCutChar), width / 2, positionHComment);
637
+ }
638
+ }
639
+ }
640
+ }
641
+ // Add map to new canvas
642
+ newContext.drawImage(oldCanvas, 0, positionHCanvas);
643
+ // Check the legendPosition
644
+ if (legendPosition !== 'none') {
645
+ if (['topleft', 'topright', 'bottomleft', 'bottomright'].indexOf(legendPosition) > -1) {
646
+ await this.addLegendToImage(newCanvas, map, resolution, legendPosition, format);
647
+ }
648
+ }
649
+ let status = SubjectStatus.Done;
650
+ let fileNameWithExt = 'map.' + format;
651
+ if (format.toLowerCase() === 'tiff') {
652
+ fileNameWithExt = 'map' + map.projection.replace(':', '_') + '.' + format;
653
+ }
654
+ try {
655
+ // Save the canvas as file
656
+ if (!doZipFile) {
657
+ this.saveCanvasImageAsFile(newCanvas, fileNameWithExt, format);
658
+ }
659
+ else if (format.toLowerCase() === 'tiff') {
660
+ // Add the canvas to zip
661
+ this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
662
+ }
663
+ else {
664
+ // Add the canvas to zip
665
+ this.generateCanvaFileToZip(newCanvas, fileNameWithExt);
666
+ }
667
+ }
668
+ catch (err) {
669
+ status = SubjectStatus.Error;
670
+ }
671
+ status$.next(status);
672
+ if (format.toLowerCase() === 'tiff') {
673
+ const tfwFileNameWithExt = fileNameWithExt.substring(0, fileNameWithExt.toLowerCase().indexOf('.tiff')) + '.tfw';
674
+ const tiwContent = this.getWorldFileInformation(map);
675
+ const blob = new Blob([tiwContent], {
676
+ type: 'text/plain;charset=utf-8'
677
+ });
678
+ if (!doZipFile) {
679
+ // saveAs automaticly replace ':' for '_'
680
+ saveAs(blob, tfwFileNameWithExt);
681
+ this.saveFileProcessing();
682
+ }
683
+ else {
684
+ // Add the canvas to zip
685
+ this.addFileToZip(tfwFileNameWithExt, blob);
686
+ }
687
+ }
688
+ });
689
+ map.ol.renderSync();
690
+ return status$;
691
+ }
692
+ /**
693
+ * Create and Add Legend to the map canvas
694
+ * @param canvas Canvas of the map
695
+ * @param map Map of the app
696
+ * @param resolution Resolution of map
697
+ * @param legendPosition Legend position
698
+ * @param format Image format
699
+ */
700
+ async addLegendToImage(canvas, map, resolution, legendPosition, format) {
701
+ const fileNameWithExt = 'map.' + format;
702
+ const context = canvas.getContext('2d');
703
+ // Get html code for the legend
704
+ const html = await this.getLayersLegendHtml(map, canvas.width, resolution).toPromise();
705
+ // If no legend, save the map directly
706
+ if (html === '') {
707
+ await this.saveCanvasImageAsFile(canvas, fileNameWithExt, format);
708
+ return true;
709
+ }
710
+ // Create div to contain html code for legend
711
+ const div = window.document.createElement('div');
712
+ div.style.position = 'absolute';
713
+ div.style.top = '0';
714
+ // Add html code to convert in the new window
715
+ window.document.body.appendChild(div);
716
+ div.innerHTML = html;
717
+ await this.timeout(1);
718
+ const canvasLegend = await html2canvas(div, { useCORS: true }).catch((e) => {
719
+ console.log(e);
720
+ });
721
+ if (canvasLegend) {
722
+ const canvasHeight = canvas.height;
723
+ const canvasWidth = canvas.width;
724
+ const legendHeight = canvasLegend.height;
725
+ const legendWidth = canvasLegend.width;
726
+ // Move the legend to the correct position on the page
727
+ const offset = canvasHeight * 0.01;
728
+ let legendX;
729
+ let legendY;
730
+ if (legendPosition === 'bottomright') {
731
+ legendX = canvasWidth - legendWidth - offset;
732
+ legendY = canvasHeight - legendHeight - offset;
733
+ }
734
+ else if (legendPosition === 'topright') {
735
+ legendX = canvasWidth - legendWidth - offset;
736
+ legendY = offset;
737
+ }
738
+ else if (legendPosition === 'bottomleft') {
739
+ legendX = offset;
740
+ legendY = canvasHeight - legendHeight - offset;
741
+ }
742
+ else if (legendPosition === 'topleft') {
743
+ legendX = offset;
744
+ legendY = offset;
745
+ }
746
+ context.drawImage(canvasLegend, legendX, legendY, legendWidth, legendHeight);
747
+ context.strokeRect(legendX, legendY, legendWidth, legendHeight);
748
+ div.parentNode.removeChild(div); // remove temp div (IE style)
749
+ return true;
750
+ }
751
+ }
752
+ renderMap(map, size, extent) {
753
+ map.ol.updateSize();
754
+ map.ol.renderSync();
755
+ }
756
+ /**
757
+ * Save document
758
+ * @param doc - Document to save
759
+ */
760
+ async saveDoc(doc) {
761
+ await doc.save('map_georef.pdf', { returnPromise: true });
762
+ }
763
+ /**
764
+ * Calculate the best Image size to fit in pdf
765
+ * @param doc - Pdf Document
766
+ * @param canvas - Canvas of image
767
+ * @param margins - Page margins
768
+ */
769
+ getImageSizeToFitPdf(doc, canvas, margins) {
770
+ // Define variable to calculate best size to fit in one page
771
+ const pageHeight = doc.internal.pageSize.getHeight() - (margins[0] + margins[2]);
772
+ const pageWidth = doc.internal.pageSize.getWidth() - (margins[1] + margins[3]);
773
+ const canHeight = this.pdf_units2points(canvas.height, 'mm');
774
+ const canWidth = this.pdf_units2points(canvas.width, 'mm');
775
+ const heightRatio = canHeight / pageHeight;
776
+ const widthRatio = canWidth / pageWidth;
777
+ const maxRatio = heightRatio > widthRatio ? heightRatio : widthRatio;
778
+ const imgHeigh = maxRatio > 1 ? canHeight / maxRatio : canHeight;
779
+ const imgWidth = maxRatio > 1 ? canWidth / maxRatio : canWidth;
780
+ return [imgWidth, imgHeigh];
781
+ }
782
+ /**
783
+ * Get a world file information for tiff
784
+ * @param map - Map of the app
785
+ */
786
+ getWorldFileInformation(map) {
787
+ const currentResolution = map.viewController.getResolution();
788
+ const currentExtent = map.viewController.getExtent(); // Return [minx, miny, maxx, maxy]
789
+ return [
790
+ currentResolution,
791
+ 0,
792
+ 0,
793
+ -currentResolution,
794
+ currentExtent[0] + currentResolution / 0.5,
795
+ currentExtent[3] - currentResolution / 0.5
796
+ ].join('\n');
797
+ }
798
+ /**
799
+ * Save canvas image as file
800
+ * @param canvas - Canvas to save
801
+ * @param name - Name of the file
802
+ * @param format - file format
803
+ */
804
+ saveCanvasImageAsFile(canvas, nameWithExt, format) {
805
+ const blobFormat = 'image/' + format;
806
+ const that = this;
807
+ try {
808
+ canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
809
+ // If navigator is Internet Explorer
810
+ if (navigator.msSaveBlob) {
811
+ navigator.msSaveBlob(canvas.msToBlob(), nameWithExt);
812
+ this.saveFileProcessing();
813
+ }
814
+ else {
815
+ canvas.toBlob((blob) => {
816
+ // download image
817
+ saveAs(blob, nameWithExt);
818
+ that.saveFileProcessing();
819
+ }, blobFormat);
820
+ }
821
+ }
822
+ catch (err) {
823
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
824
+ }
825
+ }
826
+ /**
827
+ * Add file to a zip
828
+ * @param canvas - File to add to the zip
829
+ * @param name -Name of the fileoverview
830
+ */
831
+ generateCanvaFileToZip(canvas, name) {
832
+ const blobFormat = 'image/' + 'jpeg';
833
+ const that = this;
834
+ if (!this.hasOwnProperty('zipFile') ||
835
+ typeof this.zipFile === 'undefined') {
836
+ this.zipFile = new JSZip();
837
+ }
838
+ try {
839
+ canvas.toDataURL(); // Just to make the catch trigger wihtout toBlob Error throw not catched
840
+ if (navigator.msSaveBlob) {
841
+ this.addFileToZip(name, canvas.msToBlob());
842
+ }
843
+ else {
844
+ canvas.toBlob((blob) => {
845
+ that.addFileToZip(name, blob);
846
+ }, blobFormat);
847
+ }
848
+ }
849
+ catch (err) {
850
+ this.messageService.error(this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageBody'), this.languageService.translate.instant('igo.geo.printForm.corsErrorMessageHeader'));
851
+ }
852
+ }
853
+ /**
854
+ * Add file to zip, if all file are zipped, download
855
+ * @param name - Name of the files
856
+ * @param blob - Contain of file
857
+ */
858
+ addFileToZip(name, blob) {
859
+ // add file to zip
860
+ this.zipFile.file(name, blob);
861
+ this.nbFileToProcess--;
862
+ // If all files are proccessed
863
+ if (this.nbFileToProcess === 0) {
864
+ // Download zip file
865
+ this.getZipFile();
866
+ // Stop loading
867
+ this.activityService.unregister(this.activityId);
868
+ }
869
+ }
870
+ saveFileProcessing() {
871
+ this.nbFileToProcess--;
872
+ // If all files are proccessed
873
+ if (this.nbFileToProcess === 0) {
874
+ // Stop loading
875
+ this.activityService.unregister(this.activityId);
876
+ }
877
+ }
878
+ /**
879
+ * Get the zipped file
880
+ * @return Retun a zip file
881
+ */
882
+ getZipFile() {
883
+ const that = this;
884
+ this.zipFile.generateAsync({ type: 'blob' }).then((blob) => {
885
+ // 1) generate the zip file
886
+ saveAs(blob, 'map.zip');
887
+ delete that.zipFile;
888
+ });
889
+ }
890
+ pdf_units2points(n, unit) {
891
+ let k = 1;
892
+ // this code is borrowed from jsPDF
893
+ // as it does not expose a public API
894
+ // for converting units to points.
895
+ switch (unit) {
896
+ case 'pt':
897
+ k = 1;
898
+ break;
899
+ case 'mm':
900
+ k = 72 / 25.4;
901
+ break;
902
+ case 'cm':
903
+ k = 72 / 2.54;
904
+ break;
905
+ case 'in':
906
+ k = 72;
907
+ break;
908
+ case 'px':
909
+ k = 96 / 72;
910
+ break;
911
+ case 'pc':
912
+ k = 12;
913
+ break;
914
+ case 'em':
915
+ k = 12;
916
+ break;
917
+ case 'ex':
918
+ k = 6;
919
+ break;
920
+ default:
921
+ throw new Error('Invalid unit: ' + unit);
922
+ }
923
+ return n * k;
924
+ }
925
+ }
926
+ PrintService.ɵfac = function PrintService_Factory(t) { return new (t || PrintService)(i0.ɵɵinject(i1.HttpClient), i0.ɵɵinject(i2.MessageService), i0.ɵɵinject(i2.ActivityService), i0.ɵɵinject(i2.LanguageService), i0.ɵɵinject(i2.ConfigService)); };
927
+ PrintService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PrintService, factory: PrintService.ɵfac, providedIn: 'root' });
928
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PrintService, [{
929
+ type: Injectable,
930
+ args: [{
931
+ providedIn: 'root'
932
+ }]
933
+ }], function () { return [{ type: i1.HttpClient }, { type: i2.MessageService }, { type: i2.ActivityService }, { type: i2.LanguageService }, { type: i2.ConfigService }]; }, null); })();
934
934
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbnQuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2dlby9zcmMvbGliL3ByaW50L3NoYXJlZC9wcmludC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxHQUFHLElBQUksS0FBSyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNwQyxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyxXQUFXLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxPQUFPLElBQUksS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBRXpDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUkvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFekQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHbEUsT0FBTyxZQUFZLE1BQU0sVUFBVSxDQUFDOzs7O0FBV3BDLE1BQU0sT0FBTyxZQUFZO0lBZ0J2QixZQUNVLElBQWdCLEVBQ2hCLGNBQThCLEVBQzlCLGVBQWdDLEVBQ2hDLGVBQWdDLEVBQ2hDLGFBQTRCO1FBSjVCLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNoQyxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUFDaEMsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFmdEMsZ0JBQVcsR0FBRztZQUNaLFNBQVMsRUFBRSxPQUFPO1lBQ2xCLGNBQWMsRUFBRSxNQUFNO1lBQ3RCLFlBQVksRUFBRSxPQUFPO1lBQ3JCLGlCQUFpQixFQUFFLE1BQU07WUFDekIsV0FBVyxFQUFFLFNBQVM7WUFDdEIsZ0JBQWdCLEVBQUUsUUFBUTtZQUMxQixlQUFlLEVBQUUsRUFBRTtTQUNwQixDQUFDO0lBUUMsQ0FBQztJQUVKLEtBQUssQ0FBQyxHQUFXLEVBQUUsT0FBcUI7UUFDdEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM5QixNQUFNLFdBQVcsR0FBVyxPQUFPLENBQUMsV0FBVyxDQUFDO1FBQ2hELE1BQU0sVUFBVSxHQUFHLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGdCQUFnQjtRQUN4RCxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDO1FBQ3hDLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUM7UUFDN0MsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBRWxELFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFeEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxLQUFLLENBQUM7WUFDcEIsV0FBVztZQUNYLE1BQU0sRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFO1lBQ2pDLElBQUksRUFBRSxJQUFJLENBQUMsVUFBVTtTQUN0QixDQUFDLENBQUM7UUFFSCxNQUFNLFVBQVUsR0FBRztZQUNqQixHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLO1lBQzNCLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU07U0FDN0IsQ0FBQztRQUVGLE1BQU0sT0FBTyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakMsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEQsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0IsSUFBSSxVQUFnQyxDQUFDO1FBQ3JDLElBQUksYUFBbUMsQ0FBQztRQUV4QyxZQUFZO1FBQ1osSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLFNBQVMsRUFBRztZQUNoQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxvREFBb0Q7WUFDcEgsVUFBVSxHQUFHLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUN6RCxPQUFPLEVBQ1AsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQzFCLFlBQVksRUFDWixJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFDL0IsR0FBRyxDQUFDLENBQUM7WUFFUCxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFDdEIsT0FBTyxDQUFDLEtBQUssRUFDYixJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsRUFDMUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQy9CLFVBQVUsQ0FBQyxRQUFRLEVBQ25CLFVBQVUsQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUNsQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVkLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLDBEQUEwRDtTQUV4RztRQUVELGVBQWU7UUFDZixJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssU0FBUyxFQUFFO1lBQ2xDLGFBQWEsR0FBRyxJQUFJLENBQUMsMkJBQTJCLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFDL0QsT0FBTyxFQUNQLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUM3QixVQUFVLENBQUMsUUFBUSxHQUFHLEdBQUcsRUFBRSxvQkFBb0I7WUFDL0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsRUFDbEMsR0FBRyxDQUFDLENBQUM7WUFFTixJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFDdkIsT0FBTyxDQUFDLFFBQVEsRUFDaEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLEVBQzdCLElBQUksQ0FBQyxXQUFXLENBQUMsaUJBQWlCLEVBQ2xDLGFBQWEsQ0FBQyxRQUFRLEVBQ3RCLGFBQWEsQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUNyQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQ1gsQ0FBQztZQUVGLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyx1RkFBdUY7U0FDekc7UUFFRCxJQUFJLE9BQU8sQ0FBQyxjQUFjLEtBQUssSUFBSSxJQUFJLE9BQU8sQ0FBQyxTQUFTLEtBQUssSUFBSSxFQUFFO1lBQ2pFLElBQUksQ0FBQyxZQUFZLENBQ2YsR0FBRyxFQUNILEdBQUcsRUFDSCxVQUFVLEVBQ1YsT0FBTyxDQUFDLGNBQWMsRUFDdEIsT0FBTyxDQUFDLFNBQVMsQ0FDaEIsQ0FBQztTQUNMO1FBQ0QsSUFBSSxPQUFPLENBQUMsT0FBTyxLQUFLLEVBQUUsRUFBRTtZQUMxQixJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDdkM7UUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxTQUFTLENBQ3hELEtBQUssRUFBRSxNQUFxQixFQUFFLEVBQUU7WUFDOUIsSUFBSSxNQUFNLEtBQUssYUFBYSxDQUFDLElBQUksRUFBRTtnQkFDakMsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ3ZDLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBRWpELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ25DLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BDLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQztnQkFDZCxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBRXRELElBQUksT0FBTyxDQUFDLGNBQWMsS0FBSyxNQUFNLEVBQUU7b0JBQ3JDLElBQUksQ0FBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxhQUFhLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFHO3dCQUM5RixNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO3FCQUNyRjt5QkFBTSxJQUFJLE9BQU8sQ0FBQyxjQUFjLEtBQUssU0FBUyxFQUFFO3dCQUMvQyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7cUJBQ3JEO2lCQUNGO3FCQUFNO29CQUNMLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDekI7YUFDRjtZQUVELElBQUksTUFBTSxLQUFLLGFBQWEsQ0FBQyxJQUFJLElBQUksTUFBTSxLQUFLLGFBQWEsQ0FBQyxLQUFLLEVBQUU7Z0JBQ25FLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDakQsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDbEM7UUFDSCxDQUFDLENBQ0YsQ0FBQztRQUVGLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFDRCxrRkFBa0Y7SUFDbEYsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsT0FBTztRQUNwRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7UUFDbEIsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7UUFFcEQscURBQXFEO1FBQ3JELE1BQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyQixNQUFNLENBQUMsR0FBRyxTQUFTLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQztRQUUxQyxJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7UUFDaEQsS0FBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDMUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDOUQ7UUFFRCxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1RCxHQUFHLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztJQUV6QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxLQUFLLENBQUMsa0JBQWtCLENBQzlCLEdBQVUsRUFDVixHQUFXLEVBQ1gsT0FBc0I7UUFFdEIsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksS0FBSyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLENBQUMsRUFBRTtZQUNuRixJQUFJLHlCQUF5QixDQUFDO1lBQzlCLE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQzVELE1BQU0sV0FBVyxDQUFDLHNCQUFzQixFQUFFO2dCQUN4QyxLQUFLLEVBQUUsQ0FBQztnQkFDUixlQUFlLEVBQUUsSUFBSTthQUN0QixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUNWLHlCQUF5QixHQUFHLENBQUMsQ0FBQztZQUNoQyxDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLHlCQUF5QixFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsNkJBQTZCO1NBQ3ZGO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsbUJBQW1CLENBQ2pCLEdBQVcsRUFDWCxLQUFhLEVBQ2IsVUFBa0I7UUFFbEIsT0FBTyxJQUFJLFVBQVUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO1lBQ2pDLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNkLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixDQUM5QixHQUFHLENBQUMsTUFBTSxFQUNWO2dCQUNFLFVBQVUsRUFBRSxHQUFHLENBQUMsY0FBYyxDQUFDLGFBQWEsRUFBRTtnQkFDOUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxjQUFjLENBQUMsU0FBUyxFQUFFO2dCQUN0QyxVQUFVLEVBQUUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxPQUFPLEVBQUU7Z0JBQzFELGtEQUFrRDtnQkFDbEQsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFO2FBQ0MsQ0FDMUIsQ0FBQztZQUNGLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDeEQsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDcEIsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNwQixPQUFPO2FBQ1I7WUFDRCxrRUFBa0U7WUFDbEUsaUNBQWlDO1lBQ2pDLElBQUksSUFBSSx3Q0FBd0MsQ0FBQztZQUNqRCxJQUFJLElBQUksa0NBQWtDLEdBQUcsS0FBSyxHQUFHLDZDQUE2QyxDQUFDO1lBQ25HLElBQUksSUFBSSx5Q0FBeUMsQ0FBQztZQUNsRCxJQUFJLElBQUksNEZBQTRGLENBQUM7WUFDckcsSUFBSSxJQUFJLFVBQVUsQ0FBQztZQUNuQixpRkFBaUY7WUFDakYseUZBQXlGO1lBQ3pGLHdDQUF3QztZQUN4QyxJQUFJLElBQUksK0JBQStCLENBQUM7WUFDeEMsSUFBSSxJQUFJLDJCQUEyQixDQUFDO1lBQ3BDLElBQUksSUFBSSw4QkFBOEIsQ0FBQztZQUV2Qyw2Q0FBNkM7WUFDN0MsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUM1RCxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQ2hDLEtBQUssQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO2dCQUNsQixJQUFJLE9BQU8sR0FBRyxVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsR0FBRyxZQUFZLENBQUM7Z0JBQ3JFLE9BQU8sSUFBSSxvQkFBb0IsR0FBRyxTQUFTLEdBQUcsY0FBYyxDQUFDO2dCQUM3RCxPQUFPLE9BQU8sQ0FBQztZQUNqQixDQUFDLENBQUMsQ0FDSCxDQUNGLENBQUM7WUFDRixRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7Z0JBQ3pDLElBQUksR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksT0FBTyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ25FLElBQUksSUFBSSxVQUFVLENBQUM7Z0JBQ25CLElBQUksSUFBSSxRQUFRLENBQUM7Z0JBQ2pCLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3BCLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFlBQVksQ0FBQyxHQUFXO1FBQ3RCLE1BQU0sU0FBUyxHQUFHLElBQUksZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3JFLE9BQU8sU0FBUyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxvQkFBb0IsQ0FDeEIsR0FBRyxFQUNILFNBQWlCLEtBQUssRUFDdEIsU0FBa0IsRUFDbEIsVUFBa0I7UUFFbEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM5QiwrQkFBK0I7UUFDL0IsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUMsc0RBQXNEO1FBQ3pFLElBQUksSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUN2QyxHQUFHLEVBQ0gsS0FBSyxFQUNMLFVBQVUsQ0FDWCxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2QsTUFBTSxHQUFHLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUU5QiwwQ0FBMEM7UUFDMUMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUNyQixJQUFJLEdBQUcsc0NBQXNDLENBQUM7WUFDOUMsSUFBSSxJQUFJLDRDQUE0QyxDQUFDO1NBQ3REO1FBQ0QsNkNBQTZDO1FBQzdDLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLFVBQVUsQ0FBQztRQUNoQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFFcEIsNkNBQTZDO1FBQzdDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0QyxHQUFHLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUVyQixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxXQUFXLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDbkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqQixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksTUFBTSxFQUFFO1lBQ1YsSUFBSSxNQUFNLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FBQztZQUNoQyxJQUFJO2dCQUNGLElBQUksQ0FBQyxTQUFTLEVBQUU7b0JBQ2QsMEJBQTBCO29CQUMxQixJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxFQUFFLGFBQWEsRUFBRSxNQUFNLENBQUMsQ0FBQztpQkFDM0Q7cUJBQU07b0JBQ0wsd0JBQXdCO29CQUN4QixJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxFQUFFLGFBQWEsR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUM7aUJBQ25FO2dCQUNELEdBQUcsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsdUJBQXVCO2FBQ3pEO1lBQUMsT0FBTyxHQUFHLEVBQUU7Z0JBQ1osTUFBTSxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUM7YUFDOUI7WUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3RCO1FBRUQsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUdELDJCQUEyQixDQUFDLElBQVksRUFBRSxPQUFPLEVBQUUsSUFBVyxFQUFFLFlBQW9CLEVBQUUsU0FBZ0IsRUFBRSxHQUFVO1FBRWhILE1BQU0sYUFBYSxHQUFHLEVBQUUsQ0FBQztRQUN6QixNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNsRCxNQUFNLFNBQVMsR0FBRyxRQUFRLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVyRCx3RUFBd0U7UUFDeEUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDN0IsR0FBRyxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUU5QixJQUFJLGNBQWMsR0FBRyxHQUFHLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakQsSUFBSSxjQUFzQixDQUFDO1FBRTNCLElBQUksY0FBYyxDQUFDLENBQUMsR0FBRyxTQUFTLEVBQUU7WUFDaEMsdUZBQXVGO1lBQ3ZGLGNBQWMsR0FBRyxDQUFDLENBQUM7WUFDbkIsWUFBWSxHQUFHLFlBQVksR0FBRyxHQUFHLENBQUM7WUFDbEMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUM5QixjQUFjLEdBQUcsR0FBRyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO1NBRTlDO2FBQU07WUFDTCxjQUFjLEdBQUcsQ0FBQyxTQUFTLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBRSxHQUFHLENBQUMsQ0FBRTtTQUN2RDtRQUVELE9BQU87WUFDTCxVQUFVLEVBQUUsWUFBWTtZQUN4QixZQUFZLEVBQUUsY0FBYztZQUM1QixRQUFRLEVBQUUsY0FBYyxDQUFDLENBQUM7U0FDM0IsQ0FBQztJQUNKLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssVUFBVSxDQUFDLEdBQVUsRUFBRSxPQUFlO1FBQzVDLE1BQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFDLENBQUMsK0JBQStCO1FBQzdELE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO1FBQzlCLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxtQkFBbUIsQ0FBQztRQUNyRSxJQUFJLENBQUUsZUFBZSxDQUFDLEdBQUcsRUFBQyxPQUFPLEVBQy9CLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUM1QixJQUFJLENBQUMsV0FBVyxDQUFDLGdCQUFnQixFQUNqQyxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsRUFDaEMsaUJBQWlCLEVBQ2pCLFNBQVMsQ0FDVixDQUFDO0lBQ0osQ0FBQztJQUVPLGVBQWUsQ0FBQyxHQUFVLEVBQ2hDLFNBQWlCLEVBQ2pCLFFBQWdCLEVBQ2hCLGFBQXFCLEVBQ3JCLFlBQW9CLEVBQ3BCLGNBQXNCLEVBQ3RCLGFBQXFCO1FBRW5CLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ3JDLEdBQUcsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDOUIsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsY0FBYyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFFSDs7Ozs7OztPQU9HO0lBQ0ssWUFBWSxDQUNsQixHQUFVLEVBQ1YsR0FBVyxFQUNYLEdBQVcsRUFDWCxVQUFtQixFQUNuQixLQUFjO1FBRWQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUM7UUFDakQsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBQy9CLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN4QixNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsWUFBWSxDQUFDO1FBRWpFLElBQUksYUFBYSxHQUFXLEVBQUUsQ0FBQztRQUMvQixJQUFJLFVBQVUsS0FBSyxJQUFJLEVBQUU7WUFDdkIsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1lBQ25FLGFBQWEsSUFBSSxRQUFRLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUM7U0FDbkQ7UUFDRCxJQUFJLEtBQUssS0FBSyxJQUFJLEVBQUU7WUFDbEIsSUFBSSxVQUFVLEtBQUssSUFBSSxFQUFFO2dCQUN2QixhQUFhLElBQUksS0FBSyxDQUFDO2FBQ3hCO1lBQ0QsTUFBTSxTQUFTLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1lBQy9ELE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2xELGFBQWEsSUFBSSxTQUFTLEdBQUcsVUFBVSxHQUFHLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNqRTtRQUNELEdBQUcsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkIsR0FBRyxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUMvQixHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxtQkFBbUIsRUFBRSxZQUFZLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxLQUFLLENBQUMsU0FBUyxDQUNyQixHQUFVLEVBQ1YsR0FBVyxFQUNYLE9BQXNCLEVBQ3RCLFVBQWtCO1FBRWxCLCtCQUErQjtRQUMvQixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7UUFDMUMsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQ3pDLEdBQUcsRUFDSCxLQUFLLEVBQ0wsVUFBVSxDQUNYLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDZCxzQ0FBc0M7UUFDdEMsSUFBSSxJQUFJLEtBQUssRUFBRSxFQUFFO1lBQ2YsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFDRCw2Q0FBNkM7UUFDN0MsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakQsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO1FBQ2hDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUVwQiw2Q0FBNkM7UUFDN0MsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLEdBQUcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBRXJCLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0QixNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pCLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxNQUFNLEVBQUU7WUFDVixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQztZQUNsQyxNQUFNLFNBQVMsR0FBRyxDQUFDLG9CQUFvQixHQUFHLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxVQUFVLEVBQUUsb0JBQW9CO3NCQUM5RixDQUFDLElBQUksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUM7WUFDekMsSUFBSSxPQUFPLENBQUM7WUFDWixHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDZCxPQUFPLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4QyxHQUFHLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDakUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyw2QkFBNkI7U0FDL0Q7UUFFRCxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFMUIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ1EsS0FBSyxDQUFDLGlCQUFpQixDQUM5QixHQUFVLEVBQ1YsR0FBVyxFQUNYLE9BQXNCLEVBQ3RCLFVBQWtCLEVBQ2xCLGNBQXNCO1FBRXRCLCtCQUErQjtRQUMvQixNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7UUFDMUMsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQ3pDLEdBQUcsRUFDSCxLQUFLLEVBQ0wsVUFBVSxDQUNYLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDZCxzQ0FBc0M7UUFDdEMsSUFBSSxJQUFJLEtBQUssRUFBRSxFQUFFO1lBQ2YsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFDRCw2Q0FBNkM7UUFDN0MsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakQsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDO1FBQ2hDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNwQiw2Q0FBNkM7UUFDN0MsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLEdBQUcsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0QixNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxhQUFhLENBQUM7UUFDbEIsSUFBSSxNQUFNLEVBQUU7WUFDVixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQztZQUNsQyxNQUFNLFNBQVMsR0FBRyxDQUFDLG9CQUFvQixHQUFHLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxVQUFVO2dCQUN6RSxvQkFBb0IsR0FBRyxDQUFDLElBQUksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsVUFBVSxDQUFDLENBQUM7WUFDL0Qsc0RBQXNEO1lBQ3RELElBQUssY0FBYyxLQUFLLGFBQWEsRUFBRTtnQkFDckMsYUFBYSxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztvQkFDcEYsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDdkU7aUJBQU0sSUFBSSxjQUFjLEtBQUssVUFBVSxFQUFFO2dCQUN4QyxhQUFhLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQztvQkFDakcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUUsQ0FBQzthQUMzRDtpQkFBTSxJQUFJLGNBQWMsS0FBSyxZQUFZLEVBQUU7Z0JBQzFDLDJHQUEyRztnQkFDM0csYUFBYSxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRTtvQkFDOUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUUsQ0FBQzthQUN4RjtpQkFBTSxJQUFJLGNBQWMsS0FBSyxTQUFTLEVBQUU7Z0JBQ3ZDLGFBQWEsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQ25GLEdBQUcsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFDO2FBQ3pFO1lBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUMsdUJBQXVCO1lBQ25FLEdBQUcsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsNkJBQTZCO1lBQzlELE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUN6QjtJQUNILENBQUM7SUFFSDs7Ozs7T0FLRztJQUNLLEtBQUssQ0FBQyxRQUFRLENBQ3BCLEdBQVUsRUFDVixHQUFXLEVBQ1gsT0FBc0I7UUFFcEIsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqQyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN6RCxnQ0FBZ0M7UUFDaEMsa0hBQWtIO1FBQ2xILElBQUksaUJBQWlCLENBQUM7UUFDdEIsTUFBTSxjQUFjLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxDQUFDO1FBQzdELHVDQUF1QztRQUN2QyxNQUFNLGtCQUFrQixHQUFHLGNBQWMsQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN6RSxNQUFNLHFCQUFxQixHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUM3RCxLQUFLLE1BQU0saUJBQWlCLElBQUkscUJBQXFCLEVBQUU7WUFDckQsaUJBQWlCLENBQUMsWUFBWSxDQUFDLHlCQUF5QixFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ25FO1FBQ0Qsd0RBQXdEO1FBQ3hELHNDQUFzQztRQUN0QyxpREFBaUQ7UUFDakQscUVBQXFFO1FBQ3JFLDhEQUE4RDtRQUM5RCwrRUFBK0U7UUFDL0UsTUFBTSxNQUFNLEdBQUcsTUFBTSxXQUFXLENBQUMsY0FBYyxFQUFFO1lBQy9DLEtBQUssRUFBRSxDQUFDO1lBQ1IsZUFBZSxFQUFFLElBQUk7WUFDckIsVUFBVSxFQUFFLElBQUk7WUFDaEIsT0FBTyxFQUFFLElBQUk7U0FDZCxDQUFDLENBQUMsSUFBSSxDQUFFLENBQUMsQ0FBQyxFQUFFO1lBQ1gsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxvQ0FBb0M7SUFDMUYsQ0FBQztJQUVBLHFCQUFxQixDQUFDLGVBQWU7UUFDbkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7SUFDekMsQ0FBQztJQUVPLE9BQU8sQ0FBQyxFQUFFO1FBQ2hCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRU8sU0FBUyxDQUNmLEdBQVUsRUFDVixNQUF5QixFQUN6QixPQUFzQjtRQUV0QixJQUFJLEtBQUssQ0FBQztRQUNWLElBQUksTUFBTSxFQUFFO1lBQ1YsS0FBSyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDdkM7UUFFRCxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUU7WUFDdkIsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLEVBQUUsRUFBRyxFQUFFLHFFQUFxRTtnQkFDN0YsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO2dCQUM3RCxPQUFPO2FBQ1I7WUFDRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNsRSxHQUFHLENBQUMsUUFBUSxDQUNWLEtBQUssRUFDTCxLQUFLLEVBQ0wsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUNWLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFDVixTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQ1osU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUNiLENBQUM7WUFDRixHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdELElBQUksQ0FBQyxZQUFZLEdBQUcsU0FBUyxDQUFDLENBQUMsaUNBQWlDO1NBQ2pFO0lBQ0gsQ0FBQztJQUVELDBDQUEwQztJQUNsQyxNQUFNLENBQ1osR0FBVSxFQUNWLEdBQVcsRUFDWCxVQUFrQixFQUNsQixJQUFtQixFQUNuQixPQUFzQjtRQUV0QixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBRTlCLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFekQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztRQUM5RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1FBRS9ELElBQUksT0FBTyxDQUFDO1FBRVosR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxLQUFVLEVBQUUsRUFBRTtZQUMzQyxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzNFLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBd0IsRUFBRSxFQUFFO2dCQUNyRSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBRXRCLElBQUksU0FBUyxLQUFLLGFBQWEsQ0FBQyxJQUFJLEVBQUU7b0JBQ3BDLE9BQU87aUJBQ1I7Z0JBRUQsV0FBVyxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUUxQixJQUFJLE1BQU0sR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDO2dCQUNoQyxJQUFJO29CQUNGLEtBQUssTUFBTSxNQUFNLElBQUksUUFBUSxFQUFFO3dCQUM3QixJQUFJLE1BQU0sQ0FBQyxLQUFLLEtBQUssQ0FBQyxFQUFFOzRCQUN0QixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7eUJBQ3RDO3FCQUNGO2lCQUNGO2dCQUFDLE9BQU8sR0FBRyxFQUFFO29CQUNaLE1BQU0sR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDO29CQUM3QixJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FDdkIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUNwQyx3Q0FBd0MsQ0FDekMsRUFDRCxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQ3BDLDBDQUEwQyxDQUMzQyxDQUNGLENBQUM7aUJBQ0g7Z0JBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUNyQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3ZCLENBQUMsQ0FBQyxDQUFDO1lBRUgsaUVBQWlFO1lBQ2pFLGVBQWU7WUFDZixPQUFPLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQy9CLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFFMUIsSUFBSSxNQUFNLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FBQztnQkFDaEMsSUFBSTtvQkFDRixLQUFLLE1BQU0sTUFBTSxJQUFJLFFBQVEsRUFBRTt3QkFDN0IsSUFBSSxNQUFNLENBQUMsS0FBSyxLQUFLLENBQUMsRUFBRTs0QkFDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO3lCQUN0QztxQkFDRjtpQkFDRjtnQkFBQyxPQUFPLEdBQUcsRUFBRTtvQkFDWixNQUFNLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQztvQkFDN0IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQ3ZCLElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FDcEMsd0NBQXdDLENBQ3pDLEVBQ0QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUNwQywwQ0FBMEMsQ0FDM0MsQ0FDRixDQUFDO2lCQUNIO2dCQUNELElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDckMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN2QixDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDVixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsV0FBVyxFQUFFLFlBQVksQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBRXpELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxnQkFBZ0IsQ0FDZCxHQUFXLEVBQ1gsVUFBa0IsRUFDbEIsTUFBTSxHQUFHLEtBQUssRUFDZCxVQUFVLEdBQUcsS0FBSyxFQUNsQixLQUFLLEdBQUcsS0FBSyxFQUNiLEtBQUssR0FBRyxFQUFFLEVBQ1YsUUFBUSxHQUFHLEVBQUUsRUFDYixPQUFPLEdBQUcsRUFBRSxFQUNaLFNBQVMsR0FBRyxJQUFJLEVBQ2hCLGNBQXNCO1FBRXRCLE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFDOUIsdURBQXVEO1FBQ3ZELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNsRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQztRQUNqRCxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsS0FBVSxFQUFFLEVBQUU7WUFDakQsTUFBTSxHQUFHLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUM5QixNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsTUFBTTtpQkFDM0IsV0FBVyxFQUFFO2lCQUNiLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3JDLE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbkQsTUFBTSxVQUFVLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM5QyxvREFBb0Q7WUFDcEQsSUFBSSxlQUFlLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLGlDQUFpQztZQUNqQyxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO1lBQzlCLElBQUksTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDOUIsc0NBQXNDO1lBQ3RDLFVBQVUsQ0FBQyxJQUFJLEdBQUcsY0FBYyxDQUFDO1lBQ2pDLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDO1lBQzNELGtDQUFrQztZQUNsQyxNQUFNLEdBQUcsS0FBSyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1lBQzdDLGtDQUFrQztZQUNsQyxNQUFNLEdBQUcsUUFBUSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1lBQ2hELDREQUE0RDtZQUM1RCxNQUFNLEdBQUcsVUFBVSxLQUFLLEtBQUssSUFBSSxLQUFLLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDeEUsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLEdBQUcsRUFBRSxDQUFDO1lBQ3ZDLHdEQUF3RDtZQUN4RCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUMsQ0FBQztZQUN0RCw4Q0FBOEM7WUFDOUMsTUFBTSxHQUFHLE9BQU8sS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxhQUFhLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDL0QsSUFBSSxnQkFBZ0IsR0FBRyxNQUFNLEdBQUcsYUFBYSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDdkQsa0RBQWtEO1lBQ2xELFNBQVMsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1lBQ3hCLFNBQVMsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1lBQzFCLElBQUksQ0FBQyxLQUFLLEVBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFO2dCQUM3RCwrQ0FBK0M7Z0JBQy9DLElBQUksTUFBTSxLQUFLLE1BQU0sRUFBRTtvQkFDckIsVUFBVSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7b0JBQ2pDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7b0JBQ3pDLFVBQVUsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO2lCQUNsQztxQkFBTSxJQUFJLEtBQUssS0FBSyxFQUFFLElBQUksUUFBUSxLQUFLLEVBQUUsSUFBSSxPQUFPLEtBQUssRUFBRTtvQkFDeEQsVUFBVSxLQUFLLEtBQUssSUFBSSxLQUFLLEtBQUssS0FBSyxFQUFFO29CQUN2QyxVQUFVLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztvQkFDakMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztvQkFDekMsVUFBVSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7aUJBQ3RDO2FBQ0Y7WUFFRCx3Q0FBd0M7WUFDeEMsSUFBSSxLQUFLLEtBQUssRUFBRSxFQUFFO2dCQUNoQixxQkFBcUI7Z0JBQ3JCLG1DQUFtQztnQkFDbkMsVUFBVSxDQUFDLElBQUksR0FBRyxjQUFjLENBQUM7Z0JBQ2pDLGVBQWUsR0FBRyxFQUFFLENBQUM7Z0JBQ3JCLFVBQVUsQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDO2dCQUNoQyxVQUFVLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLEdBQUcsR0FBRyxDQUFDLENBQUM7YUFDeEQ7WUFDRCxJQUFJLFFBQVEsS0FBSyxFQUFFLEVBQUU7Z0JBQ25CLHdCQUF3QjtnQkFDeEIsbUNBQW1DO2dCQUNuQyxVQUFVLENBQUMsSUFBSSxHQUFHLGNBQWMsQ0FBQztnQkFDakMsZUFBZSxHQUFHLEVBQUUsQ0FBQztnQkFDckIsVUFBVSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUM7Z0JBQ2hDLFVBQVUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLEtBQUssR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQzthQUMzRDtZQUNELDRCQUE0QjtZQUM1QixVQUFVLENBQUMsSUFBSSxHQUFHLGNBQWMsQ0FBQztZQUNqQyx3REFBd0Q7WUFDeEQsSUFBRyxDQUFDLFVBQVUsS0FBSyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxLQUFLLENBQUMsRUFBRTtnQkFDOUMsSUFBSSxtQkFBbUIsR0FBRyxFQUFFLENBQUM7Z0JBQzdCLElBQUksVUFBVSxLQUFLLEtBQUssRUFBRTtvQkFDeEIsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO29CQUNuRSxtQkFBbUIsR0FBRyxRQUFRLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQyxVQUFVLEdBQUcsV0FBVyxDQUFDO2lCQUN0RTtnQkFFRCxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUU7b0JBQ25CLE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FBQztvQkFDL0QsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ3pELG1CQUFtQixJQUFJLFNBQVMsR0FBRyxVQUFVLEdBQUcsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2lCQUN2RTtnQkFDRCxVQUFVLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQztnQkFDaEMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLGtCQUFrQixFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQzthQUN0RjtZQUVELDBDQUEwQztZQUMxQyxJQUFJLE9BQU8sS0FBSyxFQUFFLEVBQUU7Z0JBQ2xCLFVBQVUsQ0FBQyxTQUFTLEdBQUcsUUFBUSxDQUFDO2dCQUNoQyxxREFBcUQ7Z0JBQ3JELElBQUksYUFBYSxLQUFLLENBQUMsRUFBRTtvQkFDdkIsVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO2lCQUMzRDtxQkFBTTtvQkFDTCxzREFBc0Q7b0JBQ3RELE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7b0JBQ3JDLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDLENBQUM7b0JBQ3JFLElBQUksa0JBQWtCLEdBQUcsRUFBRSxDQUFDO29CQUM1QixJQUFJLG9CQUFvQixHQUFHLENBQUMsQ0FBQztvQkFDN0IsSUFBSSxpQkFBaUIsQ0FBQztvQkFDdEIseUNBQXlDO29CQUN6QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxFQUFFLENBQUMsRUFBRSxFQUFFO3dCQUN0QywyQkFBMkI7d0JBQzNCLElBQUksYUFBYSxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7NEJBQ3pCLGtFQUFrRTs0QkFDbEUsa0JBQWtCLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FDakMsb0JBQW9CLEVBQ3BCLGtCQUFrQixDQUNuQixDQUFDOzRCQUNGLDJCQUEyQjs0QkFDM0IsaUJBQWlCLEdBQUcsa0JBQWtCLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDOzRCQUN4RCxVQUFVLENBQUMsUUFBUSxDQUNqQixrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLGlCQUFpQixDQUFDLEVBQy9DLEtBQUssR0FBRyxDQUFDLEVBQ1QsZ0JBQWdCLENBQ2pCLENBQUM7NEJBQ0Ysb0JBQW9CLElBQUksaUJBQWlCLENBQUM7NEJBQzFDLGdDQUFnQzs0QkFDaEMsZ0JBQWdCLElBQUksRUFBRSxDQUFDO3lCQUN4Qjs2QkFBTTs0QkFDTCxzQkFBc0I7NEJBQ3RCLFVBQVUsQ0FBQyxRQUFRLENBQ2pCLE9BQU8sQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsRUFDcEMsS0FBSyxHQUFHLENBQUMsRUFDVCxnQkFBZ0IsQ0FDakIsQ0FBQzt5QkFDSDtxQkFDRjtpQkFDRjthQUNGO1lBRUQsd0JBQXdCO1lBQ3hCLFVBQVUsQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQztZQUVwRCwyQkFBMkI7WUFDM0IsSUFBSSxjQUFjLEtBQUssTUFBTSxFQUFFO2dCQUM3QixJQUFJLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsYUFBYSxDQUFDLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFO29CQUNyRixNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FDekIsU0FBUyxFQUNULEdBQUcsRUFDSCxVQUFVLEVBQ1YsY0FBYyxFQUNkLE1BQU0sQ0FDUCxDQUFDO2lCQUNIO2FBQ0Y7WUFFRCxJQUFJLE1BQU0sR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDO1lBQ2hDLElBQUksZUFBZSxHQUFHLE1BQU0sR0FBRyxNQUFNLENBQUM7WUFDdEMsSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFLEtBQUssTUFBTSxFQUFFO2dCQUNuQyxlQUFlLEdBQUcsS0FBSyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDO2FBQzNFO1lBRUQsSUFBSTtnQkFDRiwwQkFBMEI7Z0JBQzFCLElBQUksQ0FBQyxTQUFTLEVBQUU7b0JBQ2QsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFNBQVMsRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUM7aUJBQ2hFO3FCQUFNLElBQUksTUFBTSxDQUFDLFdBQVcsRUFBRSxLQUFLLE1BQU0sRUFBRTtvQkFDMUMsd0JBQXdCO29CQUN4QixJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxFQUFFLGVBQWUsQ0FBQyxDQUFDO2lCQUN6RDtxQkFBTTtvQkFDTCx3QkFBd0I7b0JBQ3hCLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLEVBQUUsZUFBZSxDQUFDLENBQUM7aUJBQ3pEO2FBQ0Y7WUFBQyxPQUFPLEdBQUcsRUFBRTtnQkFDWixNQUFNLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQzthQUM5QjtZQUVELE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7WUFFckIsSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFLEtBQUssTUFBTSxFQUFFO2dCQUNuQyxNQUFNLGtCQUFrQixHQUFHLGVBQWUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLGVBQWUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUM7Z0JBQ2pILE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDckQsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRTtvQkFDbEMsSUFBSSxFQUFFLDBCQUEwQjtpQkFDakMsQ0FBQyxDQUFDO2dCQUNILElBQUksQ0FBQyxTQUFTLEVBQUU7b0JBQ2QseUNBQXlDO29CQUN6QyxNQUFNLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLENBQUM7b0JBQ2pDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO2lCQUMzQjtxQkFBTTtvQkFDTCx3QkFBd0I7b0JBQ3hCLElBQUksQ0FBQyxZQUFZLENBQUMsa0JBQWtCLEVBQUMsSUFBSSxDQUFDLENBQUM7aUJBQzVDO2FBQ0Y7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILEdBQUcsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUM7UUFFcEIsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSyxLQUFLLENBQUMsZ0JBQWdCLENBQzFCLE1BQXlCLEVBQ3pCLEdBQVcsRUFDWCxVQUFrQixFQUNsQixjQUFzQixFQUN0QixNQUFjO1FBRWhCLE1BQU0sZUFBZSxHQUFHLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDeEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUV4QywrQkFBK0I7UUFDL0IsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQ3pDLEdBQUcsRUFDSCxNQUFNLENBQUMsS0FBSyxFQUNaLFVBQVUsQ0FDWCxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2Qsc0NBQXNDO1FBQ3RDLElBQUksSUFBSSxLQUFLLEVBQUUsRUFBRTtZQUNmLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDbEUsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUNELDZDQUE2QztRQUM3QyxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqRCxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUM7UUFDaEMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO1FBQ3BCLDZDQUE2QztRQUM3QyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEMsR0FBRyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDckIsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RCLE1BQU0sWUFBWSxHQUFHLE1BQU0sV0FBVyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQ3pFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakIsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLFlBQVksRUFBRTtZQUNoQixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO1lBQ25DLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7WUFDakMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQztZQUN6QyxNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDO1lBQ3ZDLHNEQUFzRDtZQUN0RCxNQUFNLE1BQU0sR0FBRyxZQUFZLEdBQUcsSUFBSSxDQUFDO1lBQ25DLElBQUksT0FBZSxDQUFDO1lBQ3BCLElBQUksT0FBZSxDQUFDO1lBRXBCLElBQUksY0FBYyxLQUFLLGFBQWEsRUFBRTtnQkFDcEMsT0FBTyxHQUFHLFdBQVcsR0FBRyxXQUFXLEdBQUcsTUFBTSxDQUFDO2dCQUM3QyxPQUFPLEdBQUcsWUFBWSxHQUFHLFlBQVksR0FBRyxNQUFNLENBQUM7YUFDaEQ7aUJBQU0sSUFBSSxjQUFjLEtBQUssVUFBVSxFQUFFO2dCQUN4QyxPQUFPLEdBQUcsV0FBVyxHQUFHLFdBQVcsR0FBRyxNQUFNLENBQUM7Z0JBQzdDLE9BQU8sR0FBRyxNQUFNLENBQUM7YUFDbEI7aUJBQU0sSUFBSSxjQUFjLEtBQUssWUFBWSxFQUFFO2dCQUMxQyxPQUFPLEdBQUcsTUFBTSxDQUFDO2dCQUNqQixPQUFPLEdBQUcsWUFBWSxHQUFHLFlBQVksR0FBRyxNQUFNLENBQUM7YUFDaEQ7aUJBQU0sSUFBSSxjQUFjLEtBQUssU0FBUyxFQUFFO2dCQUN2QyxPQUFPLEdBQUcsTUFBTSxDQUFDO2dCQUNqQixPQUFPLEdBQUcsTUFBTSxDQUFDO2FBQ2xCO1lBRUQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsWUFBWSxDQUFDLENBQUM7WUFDN0UsT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUNoRSxHQUFHLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLDZCQUE2QjtZQUM5RCxPQUFPLElBQUksQ0FBQztTQUNiO0lBQ0gsQ0FBQztJQUVPLFNBQVMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU07UUFDakMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNwQixHQUFHLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7O09BR0c7SUFDTyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQVU7UUFDaEMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssb0JBQW9CLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxPQUFPO1FBQy9DLDREQUE0RDtRQUM1RCxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRixNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvRSxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM3RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUUzRCxNQUFNLFdBQVcsR0FBRyxTQUFTLEdBQUcsVUFBVSxDQUFDO1FBQzNDLE1BQU0sVUFBVSxHQUFHLFFBQVEsR0FBRyxTQUFTLENBQUM7UUFDeEMsTUFBTSxRQUFRLEdBQUcsV0FBVyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7UUFDckUsTUFBTSxRQUFRLEdBQUcsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ2pFLE1BQU0sUUFBUSxHQUFHLFFBQVEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUUvRCxPQUFPLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7O09BR0c7SUFDSyx1QkFBdUIsQ0FBQyxHQUFHO1FBQ2pDLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxDQUFDLGNBQWMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUM3RCxNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUMsY0FBYyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsa0NBQWtDO1FBQ3hGLE9BQU87WUFDTCxpQkFBaUI7WUFDakIsQ0FBQztZQUNELENBQUM7WUFDRCxDQUFDLGlCQUFpQjtZQUNsQixhQUFhLENBQUMsQ0FBQyxDQUFDLEdBQUcsaUJBQWlCLEdBQUcsR0FBRztZQUMxQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEdBQUcsaUJBQWlCLEdBQUcsR0FBRztTQUMzQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNmLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLHFCQUFxQixDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTTtRQUN2RCxNQUFNLFVBQVUsR0FBRyxRQUFRLEdBQUcsTUFBTSxDQUFDO1FBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQztRQUVsQixJQUFJO1lBQ0YsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsd0VBQXdFO1lBQzVGLG9DQUFvQztZQUNwQyxJQUFJLFNBQVMsQ0FBQyxVQUFVLEVBQUU7Z0JBQ3hCLFNBQVMsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxFQUFFLFdBQVcsQ0FBQyxDQUFDO2dCQUNyRCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQzthQUMzQjtpQkFBTTtnQkFDTCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7b0JBQ3JCLGlCQUFpQjtvQkFDakIsTUFBTSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztvQkFDMUIsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7Z0JBQzVCLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQzthQUNoQjtTQUNGO1FBQUMsT0FBTyxHQUFHLEVBQUU7WUFDWixJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FDdkIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUNwQyx3Q0FBd0MsQ0FDekMsRUFDRCxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQ3BDLDBDQUEwQyxDQUMzQyxDQUNGLENBQUM7U0FDSDtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssc0JBQXNCLENBQUMsTUFBTSxFQUFFLElBQUk7UUFDekMsTUFBTSxVQUFVLEdBQUcsUUFBUSxHQUFHLE1BQU0sQ0FBQztRQUNyQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7UUFDbEIsSUFDRSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDO1lBQy9CLE9BQU8sSUFBSSxDQUFDLE9BQU8sS0FBSyxXQUFXLEVBQ25DO1lBQ0EsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDO1NBQzVCO1FBRUQsSUFBSTtZQUNGLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLHdFQUF3RTtZQUM1RixJQUFJLFNBQVMsQ0FBQyxVQUFVLEVBQUU7Z0JBQ3hCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO2FBQzVDO2lCQUFNO2dCQUNMLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtvQkFDckIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ2hDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQzthQUNoQjtTQUNGO1FBQUMsT0FBTyxHQUFHLEVBQUU7WUFDWixJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FDdkIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUNwQyx3Q0FBd0MsQ0FDekMsRUFDRCxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQ3BDLDBDQUEwQyxDQUMzQyxDQUNGLENBQUM7U0FDSDtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssWUFBWSxDQUFDLElBQUksRUFBRSxJQUFJO1FBQzdCLGtCQUFrQjtRQUNsQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRXZCLDhCQUE4QjtRQUM5QixJQUFJLElBQUksQ0FBQyxlQUFlLEtBQUssQ0FBQyxFQUFFO1lBQzlCLG9CQUFvQjtZQUNwQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbEIsZUFBZTtZQUNmLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztTQUNsRDtJQUNILENBQUM7SUFFTyxrQkFBa0I7UUFDeEIsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRXZCLDhCQUE4QjtRQUM5QixJQUFJLElBQUksQ0FBQyxlQUFlLEtBQUssQ0FBQyxFQUFFO1lBQzlCLGVBQWU7WUFDZixJQUFJLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDbEQ7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssVUFBVTtRQUNoQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUM7UUFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUN6RCwyQkFBMkI7WUFDM0IsTUFBTSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDdEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBR08sZ0JBQWdCLENBQUMsQ0FBQyxFQUFFLElBQUk7UUFDOUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRVYsbUNBQW1DO1FBQ25DLHNDQUFzQztRQUN0QyxtQ0FBbUM7UUFDbkMsUUFBUSxJQUFJLEVBQUU7WUFDVixLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDTixNQUFNO1lBQ1YsS0FBSyxJQUFJO2dCQUNMLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO2dCQUNkLE1BQU07WUFDVixLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7Z0JBQ2QsTUFBTTtZQUNWLEtBQUssSUFBSTtnQkFDTCxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNQLE1BQU07WUFDVixLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7Z0JBQ1osTUFBTTtZQUNWLEtBQUssSUFBSTtnQkFDTCxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNQLE1BQU07WUFDVixLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDUCxNQUFNO1lBQ1YsS0FBSyxJQUFJO2dCQUNMLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ04sTUFBTTtZQUNWO2dCQUNJLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLENBQUM7U0FDaEQ7UUFFRCxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDZixDQUFDOzt3RUF0cENVLFlBQVk7a0VBQVosWUFBWSxXQUFaLFlBQVksbUJBRlgsTUFBTTt1RkFFUCxZQUFZO2NBSHhCLFVBQVU7ZUFBQztnQkFDVixVQUFVLEVBQUUsTUFBTTthQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QsIGZvcmtKb2luIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAgYXMgcnhNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IHNhdmVBcyB9IGZyb20gJ2ZpbGUtc2F2ZXInO1xuaW1wb3J0IGpzUERGIGZyb20gJ2pzcGRmJztcbmltcG9ydCBodG1sMmNhbnZhcyBmcm9tICdodG1sMmNhbnZhcyc7XG5pbXBvcnQgeyBkZWZhdWx0IGFzIEpTWmlwIH0gZnJvbSAnanN6aXAnO1xuXG5pbXBvcnQgeyBTdWJqZWN0U3RhdHVzIH0gZnJvbSAnQGlnbzIvdXRpbHMnO1xuaW1wb3J0IHsgU2VjdXJlSW1hZ2VQaXBlIH0gZnJvbSAnQGlnbzIvY29tbW9uJztcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlLCBBY3Rpdml0eVNlcnZpY2UsIExhbmd1YWdlU2VydmljZSwgQ29uZmlnU2VydmljZSB9IGZyb20gJ0BpZ28yL2NvcmUnO1xuXG5pbXBvcnQgeyBJZ29NYXAgfSBmcm9tICcuLi8uLi9tYXAvc2hhcmVkL21hcCc7XG5pbXBvcnQgeyBmb3JtYXRTY2FsZSB9IGZyb20gJy4uLy4uL21hcC9zaGFyZWQvbWFwLnV0aWxzJztcbmltcG9ydCB7IExlZ2VuZE1hcFZpZXdPcHRpb25zIH0gZnJvbSAnLi4vLi4vbGF5ZXIvc2hhcmVkL2xheWVycy9sYXllci5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgZ2V0TGF5ZXJzTGVnZW5kcyB9IGZyb20gJy4uLy4uL2xheWVyL3V0aWxzL291dHB1dExlZ2VuZCc7XG5cbmltcG9ydCB7IFByaW50T3B0aW9ucywgVGV4dFBkZlNpemVBbmRNYXJnaW4gfSBmcm9tICcuL3ByaW50LmludGVyZmFjZSc7XG5pbXBvcnQgR2VvUGRmUGx1Z2luIGZyb20gJy4vZ2VvcGRmJztcblxuZGVjbGFyZSBnbG9iYWwge1xuICBpbnRlcmZhY2UgTmF2aWdhdG9yIHtcbiAgICBtc1NhdmVCbG9iPzogKGJsb2I6IGFueSwgZGVmYXVsdE5hbWU/OiBzdHJpbmcpID0+IGJvb2xlYW5cbiAgfVxufVxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBQcmludFNlcnZpY2Uge1xuICB6aXBGaWxlOiBKU1ppcDtcbiAgbmJGaWxlVG9Qcm9jZXNzOiBudW1iZXI7XG4gIGFjdGl2aXR5SWQ6IHN0cmluZztcbiAgaW1nU2l6ZUFkZGVkOiBBcnJheTxudW1iZXI+O1xuXG4gIFRFWFRQREZGT05UID0ge1xuICAgIHRpdGxlRm9udDogJ1RpbWVzJyxcbiAgICB0aXRsZUZvbnRTdHlsZTogJ2JvbGQnLFxuICAgIHN1YnRpdGxlRm9udDogJ1RpbWVzJyxcbiAgICBzdWJ0aXRsZUZvbnRTdHlsZTogJ2JvbGQnLFxuICAgIGNvbW1lbnRGb250OiAnY291cmllcicsXG4gICAgY29tbWVudEZvbnRTdHlsZTogJ25vcm1hbCcsXG4gICAgY29tbWVudEZvbnRTaXplOiAxNlxuICB9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcbiAgICBwcml2YXRlIG1lc3NhZ2VTZXJ2aWNlOiBNZXNzYWdlU2VydmljZSxcbiAgICBwcml2YXRlIGFjdGl2aXR5U2VydmljZTogQWN0aXZpdHlTZXJ2aWNlLFxuICAgIHByaXZhdGUgbGFuZ3VhZ2VTZXJ2aWNlOiBMYW5ndWFnZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBjb25maWdTZXJ2aWNlOiBDb25maWdTZXJ2aWNlXG4gICkge31cblxuICBwcmludChtYXA6IElnb01hcCwgb3B0aW9uczogUHJpbnRPcHRpb25zKTogU3ViamVjdDxhbnk+IHtcbiAgICBjb25zdCBzdGF0dXMkID0gbmV3IFN1YmplY3QoKTtcbiAgICBjb25zdCBwYXBlckZvcm1hdDogc3RyaW5nID0gb3B0aW9ucy5wYXBlckZvcm1hdDtcbiAgICBjb25zdCByZXNvbHV0aW9uID0gK29wdGlvbnMucmVzb2x1dGlvbjsgLy8gRGVmYXVsdCBpcyA5NlxuICAgIGNvbnN0IG9yaWVudGF0aW9uID0gb3B0aW9ucy5vcmllbnRhdGlvbjtcbiAgICBjb25zdCBsZWdlbmRQb3N0aW9uID0gb3B0aW9ucy5sZWdlbmRQb3NpdGlvbjtcbiAgICB0aGlzLmFjdGl2aXR5SWQgPSB0aGlzLmFjdGl2aXR5U2VydmljZS5yZWdpc3RlcigpO1xuXG4gICAgR2VvUGRmUGx1Z2luKGpzUERGLkFQSSk7XG5cbiAgICBjb25zdCBkb2MgPSBuZXcganNQREYoe1xuICAgICAgb3JpZW50YXRpb24sXG4gICAgICBmb3JtYXQ6IHBhcGVyRm9ybWF0LnRvTG93ZXJDYXNlKCksXG4gICAgICB1bml0OiAnbW0nIC8vIGRlZmF1bHRcbiAgICB9KTtcblxuICAgIGNvbnN0IGRpbWVuc2lvbnMgPSBbXG4gICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGgsXG4gICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUuaGVpZ2h0XG4gICAgXTtcblxuICAgIGNvbnN0IG1hcmdpbnMgPSBbMTAsIDEwLCAxMCwgMTBdO1xuICAgIGNvbnN0IHdpZHRoID0gZGltZW5zaW9uc1swXSAtIG1hcmdpbnNbM10gLSBtYXJnaW5zWzFdO1xuICAgIGNvbnN0IGhlaWdodCA9IGRpbWVuc2lvbnNbMV0gLSBtYXJnaW5zWzBdIC0gbWFyZ2luc1syXTtcbiAgICBjb25zdCBzaXplID0gW3dpZHRoLCBoZWlnaHRdO1xuICAgIGxldCB0aXRsZVNpemVzOiBUZXh0UGRmU2l6ZUFuZE1hcmdpbjtcbiAgICBsZXQgc3VidGl0bGVTaXplczogVGV4dFBkZlNpemVBbmRNYXJnaW47XG5cbiAgICAvLyBQREYgdGl0bGVcbiAgICBpZiAob3B0aW9ucy50aXRsZSAhPT0gdW5kZWZpbmVkICkge1xuICAgICAgY29uc3QgZm9udFNpemVJblB0ID0gTWF0aC5yb3VuZCgyICogKGhlaWdodCArIDE0NSkgKiAwLjA1KSAvIDI7IC8vY2FsY3VsYXRlIHRoZSBmb250U2l6ZSB0aXRsZSBmcm9tIHRoZSBwYWdlIGhlaWdodC5cbiAgICAgIHRpdGxlU2l6ZXMgPSB0aGlzLmdldFRleHRQZGZPYmplY3RTaXplQW5kTWFyZyhvcHRpb25zLnRpdGxlLFxuICAgICAgICBtYXJnaW5zLFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnRpdGxlRm9udCxcbiAgICAgICAgZm9udFNpemVJblB0LFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnRpdGxlRm9udFN0eWxlLFxuICAgICAgICBkb2MpO1xuXG4gICAgICB0aGlzLmFkZFRleHRJblBkZkRvYyhkb2MsXG4gICAgICAgIG9wdGlvbnMudGl0bGUsXG4gICAgICAgIHRoaXMuVEVYVFBERkZPTlQudGl0bGVGb250LFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnRpdGxlRm9udFN0eWxlLFxuICAgICAgICB0aXRsZVNpemVzLmZvbnRTaXplLFxuICAgICAgICB0aXRsZVNpemVzLm1hcmdpbkxlZnQgKyBtYXJnaW5zWzNdLFxuICAgICAgICBtYXJnaW5zWzBdKTtcblxuICAgICAgbWFyZ2luc1swXSA9IHRpdGxlU2l6ZXMuaGVpZ2h0ICsgbWFyZ2luc1swXTsgLy8gY3VtdWxhdGl2ZSBtYXJnaW4gdG9wIGZvciBuZXh0IGVsZW0gdG8gcGxhY2UgaW4gcGRmIGRvY1xuXG4gICAgfVxuXG4gICAgLy8gUERGIHN1YnRpdGxlXG4gICAgaWYgKG9wdGlvbnMuc3VidGl0bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc3VidGl0bGVTaXplcyA9IHRoaXMuZ2V0VGV4dFBkZk9iamVjdFNpemVBbmRNYXJnKG9wdGlvbnMuc3VidGl0bGUsXG4gICAgICAgIG1hcmdpbnMsXG4gICAgICAgIHRoaXMuVEVYVFBERkZPTlQuc3VidGl0bGVGb250LFxuICAgICAgICB0aXRsZVNpemVzLmZvbnRTaXplICogMC43LCAvLyA3MCUgc2l6ZSBvZiB0aXRsZVxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnN1YnRpdGxlRm9udFN0eWxlLFxuICAgICAgICBkb2MpO1xuXG4gICAgICAgdGhpcy5hZGRUZXh0SW5QZGZEb2MoZG9jLFxuICAgICAgICBvcHRpb25zLnN1YnRpdGxlLFxuICAgICAgICB0aGlzLlRFWFRQREZGT05ULnN1YnRpdGxlRm9udCxcbiAgICAgICAgdGhpcy5URVhUUERGRk9OVC5zdWJ0aXRsZUZvbnRTdHlsZSxcbiAgICAgICAgc3VidGl0bGVTaXplcy5mb250U2l6ZSxcbiAgICAgICAgc3VidGl0bGVTaXplcy5tYXJnaW5MZWZ0ICsgbWFyZ2luc1szXSxcbiAgICAgICAgbWFyZ2luc1swXVxuICAgICAgKTtcblxuICAgICAgbWFyZ2luc1swXSArPSA1OyAvLyBjdW11bGF0aXZlIG1hcmcgdG9wIGZvciBuZXh0IGVsZW0gdG8gcGxhY2UgaW4gcGRmIGRvYy4gNSBpcyBhIGZpeCBpdCBjb3VsZCBiZSBhZGp1c3RcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5zaG93UHJvamVjdGlvbiA9PT0gdHJ1ZSB8fCBvcHRpb25zLnNob3dTY2FsZSA9PT0gdHJ1ZSkge1xuICAgICAgdGhpcy5hZGRQcm9qU2NhbGUoXG4gICAgICAgIGRvYyxcbiAgICAgICAgbWFwLFxuICAgICAgICByZXNvbHV0aW9uLFxuICAgICAgICBvcHRpb25zLnNob3dQcm9qZWN0aW9uLFxuICAgICAgICBvcHRpb25zLnNob3dTY2FsZVxuICAgICAgICApO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5jb21tZW50ICE9PSAnJykge1xuICAgICAgdGhpcy5hZGRDb21tZW50KGRvYywgb3B0aW9ucy5jb21tZW50KTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZE1hcChkb2MsIG1hcCwgcmVzb2x1dGlvbiwgc2l6ZSwgbWFyZ2lucykuc3Vic2NyaWJlKFxuICAgICAgYXN5bmMgKHN0YXR1czogU3ViamVjdFN0YXR1cykgPT4ge1xuICAgICAgICBpZiAoc3RhdHVzID09PSBTdWJqZWN0U3RhdHVzLkRvbmUpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmFkZFNjYWxlKGRvYywgbWFwLCBtYXJnaW5zKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZU1lYXN1cmVMYXllcihkb2MsIG1hcCwgbWFyZ2lucyk7XG5cbiAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuaW1nU2l6ZUFkZGVkWzBdO1xuICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaW1nU2l6ZUFkZGVkWzFdO1xuICAgICAgICAgIGNvbnN0IHJlcyA9IDE7XG4gICAgICAgICAgdGhpcy5hZGRHZW9SZWYoZG9jLCBtYXAsIHdpZHRoLCBoZWlnaHQsIHJlcywgbWFyZ2lucyk7XG5cbiAgICAgICAgICBpZiAob3B0aW9ucy5sZWdlbmRQb3NpdGlvbiAhPT0gJ25vbmUnKSB7XG4gICAgICAgICAgICBpZiAoWyd0b3BsZWZ0JywgJ3RvcHJpZ2h0JywgJ2JvdHRvbWxlZnQnLCAnYm90dG9tcmlnaHQnXS5pbmRleE9mKG9wdGlvbnMubGVnZW5kUG9zaXRpb24pID4gLTEgKSB7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMuYWRkTGVnZW5kU2FtZVBhZ2UoZG9jLCBtYXAsIG1hcmdpbnMsIHJlc29sdXRpb24sIG9wdGlvbnMubGVnZW5kUG9zaXRpb24pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmxlZ2VuZFBvc2l0aW9uID09PSAnbmV3cGFnZScpIHtcbiAgICAgICAgICAgICAgYXdhaXQgdGhpcy5hZGRMZWdlbmQoZG9jLCBtYXAsIG1hcmdpbnMsIHJlc29sdXRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNhdmVEb2MoZG9jKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhdHVzID09PSBTdWJqZWN0U3RhdHVzLkRvbmUgfHwgc3RhdHVzID09PSBTdWJqZWN0U3RhdHVzLkVycm9yKSB7XG4gICAgICAgICAgdGhpcy5hY3Rpdml0eVNlcnZpY2UudW5yZWdpc3Rlcih0aGlzLmFjdGl2aXR5SWQpO1xuICAgICAgICAgIHN0YXR1cyQubmV4dChTdWJqZWN0U3RhdHVzLkRvbmUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgKTtcblxuICAgIHJldHVybiBzdGF0dXMkO1xuICB9XG4gIC8vIHJlZiBHZW9Nb29zZSBodHRwczovL2dpdGh1Yi5jb20vZ2VvbW9vc2UvZ20zL3RyZWUvbWFpbi9zcmMvZ20zL2NvbXBvbmVudHMvcHJpbnRcbiAgYWRkR2VvUmVmKGRvYywgbWFwLCB3aWR0aCwgaGVpZ2h0LCByZXNvbHV0aW9uLCBtYXJnaW5zKSB7XG4gICAgY29uc3QgdW5pdCA9ICdtbSc7XG4gICAgY29uc3QgZG9jSGVpZ2h0ID0gZG9jLmludGVybmFsLnBhZ2VTaXplLmdldEhlaWdodCgpO1xuXG4gICAgLy8geCx5ID0gbWFyZ2luIGxlZnQtYm90dG9tIGNvcm5lciBmb3IgaW1nIGluIHBkZiBkb2NcbiAgICBjb25zdCB4ID0gbWFyZ2luc1szXTtcbiAgICBjb25zdCB5ID0gZG9jSGVpZ2h0IC0gbWFyZ2luc1swXSAtIGhlaWdodDtcblxuICAgIGxldCBwZGZfZXh0ZW50cyA9IFt4LCB5LCB4ICsgd2lkdGgsIHkgKyBoZWlnaHRdO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBwZGZfZXh0ZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgcGRmX2V4dGVudHNbaV0gPSB0aGlzLnBkZl91bml0czJwb2ludHMocGRmX2V4dGVudHNbaV0sIHVuaXQpO1xuICAgIH1cblxuICAgIGNvbnN0IG1hcEV4dGVudCA9IG1hcC52aWV3Q29udHJvbGxlci5nZXRFeHRlbnQoJ0VQU0c6Mzg1NycpO1xuICAgIGRvYy5zZXRHZW9BcmVhKHBkZl9leHRlbnRzLCBtYXBFeHRlbnQpO1xuXG4gIH1cblxuICAvKipcbiAgICogQWRkIG1lYXN1cmUgb3ZlcmxheSBvbiB0aGUgbWFwIG9uIHRoZSBkb2N1bWVudCB3aGVuIHRoZSBtZWFzdXJlIGxheWVyIGlzIHByZXNlbnRcbiAgICogQHBhcmFtICBkb2MgLSBQZGYgZG9jdW1lbnQgd2hlcmUgbWVhc3VyZSB0b29sdGlwIHdpbGwgYmUgYWRkZWRcbiAgICogQHBhcmFtICBtYXAgLSBNYXAgb2YgdGhlIGFwcFxuICAgKiBAcGFyYW0gIG1hcmdpbnMgLSBQYWdlIG1hcmdpbnNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgaGFuZGxlTWVhc3VyZUxheWVyKFxuICAgIGRvYzoganNQREYsXG4gICAgbWFwOiBJZ29NYXAsXG4gICAgbWFyZ2luczogQXJyYXk8bnVtYmVyPlxuICApIHtcbiAgICBpZiAobWFwLmxheWVycy5maW5kKGxheWVyID0+IGxheWVyLnZpc2libGUgJiYgbGF5ZXIuaWQuc3RhcnRzV2l0aCgnaWdvLW1lYXN1cmVzLScpKSkge1xuICAgICAgbGV0IGNhbnZhc092ZXJsYXlIVE1MTWVhc3VyZXM7XG4gICAgICBjb25zdCBtYXBPdmVybGF5TWVhc3VyZXNIVE1MID0gbWFwLm9sLmdldE92ZXJsYXlDb250YWluZXIoKTtcbiAgICAgIGF3YWl0IGh0bWwyY2FudmFzKG1hcE92ZXJsYXlNZWFzdXJlc0hUTUwsIHtcbiAgICAgICAgc2NhbGU6IDEsXG4gICAgICAgIGJhY2tncm91bmRDb2xvcjogbnVsbFxuICAgICAgfSkudGhlbihlID0+IHtcbiAgICAgICAgY2FudmFzT3ZlcmxheUhUTUxNZWFzdXJlcyA9IGU7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuYWRkQ2FudmFzKGRvYywgY2FudmFzT3ZlcmxheUhUTUxNZWFzdXJlcywgbWFyZ2lucyk7IC8vIHRoaXMgYWRkcyBtZWFzdXJlIG92ZXJsYXlzXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBodG1sIGNvZGUgZm9yIGFsbCBsYXllcnMgbGVnZW5kXG4gICAqIEBwYXJhbSAgbWFwIElnb01hcFxuICAgKiBAcGFyYW0gIHdpZHRoIFRoZSB3aWR0aCB0aGF0IHRoZSBsZWdlbmQgbmVlZCB0byBiZVxuICAgKiBAcmV0dXJuIEh0bWwgY29kZSBmb3IgdGhlIGxlZ2VuZFxuICAgKi9cbiAgZ2V0TGF5ZXJzTGVnZW5kSHRtbChcbiAgICBtYXA6IElnb01hcCxcbiAgICB3aWR0aDogbnVtYmVyLFxuICAgIHJlc29sdXRpb246IG51bWJlclxuICApOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcbiAgICAgIGxldCBodG1sID0gJyc7XG4gICAgICBjb25zdCBsZWdlbmRzID0gZ2V0TGF5ZXJzTGVnZW5kcyhcbiAgICAgICAgbWFwLmxheWVycyxcbiAgICAgICAge1xuICAgICAgICAgIHJlc29sdXRpb246IG1hcC52aWV3Q29udHJvbGxlci5nZXRSZXNvbHV0aW9uKCksXG4gICAgICAgICAgZXh0ZW50OiBtYXAudmlld0NvbnRyb2xsZXIuZ2V0RXh0ZW50KCksXG4gICAgICAgICAgcHJvamVjdGlvbjogbWFwLnZpZXdDb250cm9sbGVyLmdldE9sUHJvamVjdGlvbigpLmdldENvZGUoKSxcbiAgICAgICAgICAvLyBzY2FsZTogbWFwLnZpZXdDb250cm9sbGVyLmdldFNjYWxlKHJlc29sdXRpb24pLFxuICAgICAgICAgIHNpemU6IG1hcC5vbC5nZXRTaXplKClcbiAgICAgICAgfSBhcyBMZWdlbmRNYXBWaWV3T3B0aW9uc1xuICAgICAgKTtcbiAgICAgIGlmIChsZWdlbmRzLmZpbHRlcihsID0+IGwuZGlzcGxheSA9PT0gdHJ1ZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIG9ic2VydmVyLm5leHQoaHRtbCk7XG4gICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIERlZmluZSBpbXBvcnRhbnQgc3R5bGUgdG8gYmUgc3VyZSB0aGF0IGFsbCBjb250YWluZXIgaXMgY29udmVydFxuICAgICAgLy8gdG8gaW1hZ2Ugbm90IGp1c3QgdmlzaWJsZSBwYXJ0XG4gICAgICBodG1sICs9ICc8c3R5bGUgbWVkaWE9XCJzY3JlZW5cIiB0eXBlPVwidGV4dC9jc3NcIj4nO1xuICAgICAgaHRtbCArPSAnLmh0bWwyY2FudmFzLWNvbnRhaW5lciB7IHdpZHRoOiAnICsgd2lkdGggKyAnbW0gIWltcG9ydGFudDsgaGVpZ2h0OiAyMDAwcHggIWltcG9ydGFudDsgfSc7XG4gICAgICBodG1sICs9ICd0YWJsZS50YWJsZUxlZ2VuZCB7dGFibGUtbGF5b3V0OiBhdXRvO30nO1xuICAgICAgaHRtbCArPSAnZGl2LnN0eWxlTGVnZW5kIHtwYWRkaW5nLXRvcDogNXB4OyBwYWRkaW5nLXJpZ2h0OjVweDtwYWRkaW5nLWxlZnQ6NXB4O3BhZGRpbmctYm90dG9tOjVweDt9JztcbiAgICAgIGh0bWwgKz0gJzwvc3R5bGU+JztcbiAgICAgIC8vIFRoZSBmb250IHNpemUgd2lsbCBhbHNvIGJlIGxvd2VyZWQgYWZ0ZXJ3YXJkcyAoZ2xvYmFsbHkgYWxvbmcgdGhlIGxlZ2VuZCBzaXplKVxuICAgICAgLy8gdGhpcyBhbGxvd3MgaGF2aW5nIGEgZ29vZCByZWxhdGl2ZSBmb250IHNpemUgaGVyZSBhbmQgdG8ga2VlcCBhanVzdGluZyB0aGUgbGVnZW5kIHNpemVcbiAgICAgIC8vIHdoaWxlIGtlZXBpbmcgZ29vZCByZWxhdGl2ZSBmb250IHNpemVcbiAgICAgIGh0bWwgKz0gJzxmb250IHNpemU9XCIzXCIgZmFjZT1cIlRpbWVzXCIgPic7XG4gICAgICBodG1sICs9ICc8ZGl2IGNsYXNzPVwic3R5bGVMZWdlbmRcIj4nO1xuICAgICAgaHRtbCArPSAnPHRhYmxlIGNsYXNzPVwidGFibGVMZWdlbmRcIiA+JztcblxuICAgICAgLy8gRm9yIGVhY2ggbGVnZW5kLCBkZWZpbmUgYW4gaHRtbCB0YWJsZSBjZWxsXG4gICAgICBjb25zdCBpbWFnZXMkID0gbGVnZW5kcy5maWx0ZXIobCA9PiBsLmRpc3BsYXkpLm1hcCgobGVnZW5kKSA9PlxuICAgICAgICB0aGlzLmdldERhdGFJbWFnZShsZWdlbmQudXJsKS5waXBlKFxuICAgICAgICAgIHJ4TWFwKChkYXRhSW1hZ2UpID0+IHtcbiAgICAgICAgICAgIGxldCBodG1sSW1nID0gJzx0cj48dGQ+JyArIGxlZ2VuZC50aXRsZS50b1VwcGVyQ2FzZSgpICsgJzwvdGQ+PC90cj4nO1xuICAgICAgICAgICAgaHRtbEltZyArPSAnPHRyPjx0ZD48aW1nIHNyYz1cIicgKyBkYXRhSW1hZ2UgKyAnXCI+PC90ZD48L3RyPic7XG4gICAgICAgICAgICByZXR1cm4gaHRtbEltZztcbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICApO1xuICAgICAgZm9ya0pvaW4oaW1hZ2VzJCkuc3Vic2NyaWJlKChkYXRhSW1hZ2VzKSA9PiB7XG4gICAgICAgIGh0bWwgPSBkYXRhSW1hZ2VzLnJlZHVjZSgoYWNjLCBjdXJyZW50KSA9PiAoYWNjICs9IGN1cnJlbnQpLCBodG1sKTtcbiAgICAgICAgaHRtbCArPSAnPC90YWJsZT4nO1xuICAgICAgICBodG1sICs9ICc8L2Rpdj4nO1xuICAgICAgICBvYnNlcnZlci5uZXh0KGh0bWwpO1xuICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXREYXRhSW1hZ2UodXJsOiBzdHJpbmcpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIGNvbnN0IHNlY3VyZUlNRyA9IG5ldyBTZWN1cmVJbWFnZVBpcGUodGhpcy5odHRwLCB0aGlzLmNvbmZpZ1NlcnZpY2UpO1xuICAgIHJldHVybiBzZWN1cmVJTUcudHJhbnNmb3JtKHVybCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCB0aGUgbGVnZW5kIGluIGEgc2luZ2xlIGltYWdlXG4gICAqICogQHBhcmFtICBmb3JtYXQgLSBJbWFnZSBmb3JtYXQuIGRlZmF1bHQgdmFsdWUgdG8gXCJwbmdcIlxuICAgKiBAcmV0dXJuIFRoZSBpbWFnZSBvZiB0aGUgbGVnZW5kXG4gICAqL1xuICBhc3luYyBnZXRMYXllcnNMZWdlbmRJbWFnZShcbiAgICBtYXAsXG4gICAgZm9ybWF0OiBzdHJpbmcgPSAncG5nJyxcbiAgICBkb1ppcEZpbGU6IGJvb2xlYW4sXG4gICAgcmVzb2x1dGlvbjogbnVtYmVyXG4gICkge1xuICAgIGNvbnN0IHN0YXR1cyQgPSBuZXcgU3ViamVjdCgpO1xuICAgIC8vIEdldCBodG1sIGNvZGUgZm9yIHRoZSBsZWdlbmRcbiAgICBjb25zdCB3aWR0aCA9IDIwMDsgLy8gbWlsaW1ldGVycyB1bml0LCBvcmlnaW5hbGx5IGRlZmluZSBmb3IgZG9jdW1lbnQgcGRmXG4gICAgbGV0IGh0bWwgPSBhd2FpdCB0aGlzLmdldExheWVyc0xlZ2VuZEh0bWwoXG4gICAgICBtYXAsXG4gICAgICB3aWR0aCxcbiAgICAgIHJlc29sdXRpb25cbiAgICApLnRvUHJvbWlzZSgpO1xuICAgIGZvcm1hdCA9IGZvcm1hdC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgLy8gSWYgbm8gbGVnZW5kIHNob3cgTm8gTEVHRU5EIGluIGFuIGltYWdlXG4gICAgaWYgKGh0bWwubGVuZ3RoID09PSAwKSB7XG4gICAgICBodG1sID0gJzxmb250IHNpemU9XCIxMlwiIGZhY2U9XCJDb3VyaWVyIE5ld1wiID4nO1xuICAgICAgaHRtbCArPSAnPGRpdiBhbGlnbj1cImNlbnRlclwiPjxiPk5PIExFR0VORDwvYj48L2Rpdj4nO1xuICAgIH1cbiAgICAvLyBDcmVhdGUgZGl2IHRvIGNvbnRhaW4gaHRtbCBjb2RlIGZvciBsZWdlbmRcbiAgICBjb25zdCBkaXYgPSB3aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBkaXYuc3R5bGUudG9wID0gJzAnO1xuXG4gICAgLy8gQWRkIGh0bWwgY29kZSB0byBjb252ZXJ0IGluIHRoZSBuZXcgd2luZG93XG4gICAgd2luZG93LmRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZGl2KTtcbiAgICBkaXYuaW5uZXJIVE1MID0gaHRtbDtcblxuICAgIGF3YWl0IHRoaXMudGltZW91dCgxKTtcbiAgICBjb25zdCBjYW52YXMgPSBhd2FpdCBodG1sMmNhbnZhcyhkaXYsIHsgdXNlQ09SUzogdHJ1ZSB9KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgfSk7XG5cbiAgICBpZiAoY2FudmFzKSB7XG4gICAgICBsZXQgc3RhdHVzID0gU3ViamVjdFN0YXR1cy5Eb25lO1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCFkb1ppcEZpbGUpIHtcbiAgICAgICAgICAvLyBTYXZlIHRoZSBjYW52YXMgYXMgZmlsZVxuICAgICAgICAgIHRoaXMuc2F2ZUNhbnZhc0ltYWdlQXNGaWxlKGNhbnZhcywgJ2xlZ2VuZEltYWdlJywgZm9ybWF0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBBZGQgdGhlIGNhbnZhcyB0byB6aXBcbiAgICAgICAgICB0aGlzLmdlbmVyYXRlQ2FudmFGaWxlVG9aaXAoY2FudmFzLCAnbGVnZW5kSW1hZ2UnICsgJy4nICsgZm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgICBkaXYucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkaXYpOyAvLyByZW1vdmUgdGVtcCBkaXYgKElFKVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRXJyb3I7XG4gICAgICB9XG4gICAgICBzdGF0dXMkLm5leHQoc3RhdHVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3RhdHVzJDtcbiAgfVxuXG5cbiAgZ2V0VGV4dFBkZk9iamVjdFNpemVBbmRNYXJnKHRleHQ6IHN0cmluZywgbWFyZ2lucywgZm9udDpzdHJpbmcsIGZvbnRTaXplSW5QdDogbnVtYmVyLCBmb250U3R5bGU6c3RyaW5nLCBkb2M6IGpzUERGKVxuICA6IFRleHRQZGZTaXplQW5kTWFyZ2luIHtcbiAgICBjb25zdCBwZGZSZXNvbHV0aW9uID0gOTY7XG4gICAgY29uc3QgZG9jV2lkdGggPSBkb2MuaW50ZXJuYWwucGFnZVNpemUuZ2V0V2lkdGgoKTtcbiAgICBjb25zdCBwYWdlV2lkdGggPSBkb2NXaWR0aCAtIG1hcmdpbnNbMV0gLSBtYXJnaW5zWzNdO1xuXG4gICAgLy8gaW1wb3J0YW50IHRvIHNldCBpdCBmaXJzdCwgdGhlIHRleHREaW1lbnNpb24gY2hhbmdlIHdoZW4gZm9udCBjaGFuZ2UhXG4gICAgZG9jLnNldEZvbnQoZm9udCwgZm9udFN0eWxlKTtcbiAgICBkb2Muc2V0Rm9udFNpemUoZm9udFNpemVJblB0KTtcblxuICAgIGxldCB0ZXh0RGltZW5zaW9ucyA9IGRvYy5nZXRUZXh0RGltZW5zaW9ucyh0ZXh0KTtcbiAgICBsZXQgdGV4dE1hcmdpbkxlZnQ6IG51bWJlcjtcblxuICAgIGlmICh0ZXh0RGltZW5zaW9ucy53ID4gcGFnZVdpZHRoKSB7XG4gICAgICAvLyBpZiB0aGUgdGV4dCBpcyB0byBsb25nLCByZWR1Y2UgZm9udFNpemUgNzAlIGFuZCB0aGUgb3ZlcmZsb3cgd2l0aCBiZSBjdXQgaW4gcHJpbnQuLi5cbiAgICAgIHRleHRNYXJnaW5MZWZ0ID0gMDtcbiAgICAgIGZvbnRTaXplSW5QdCA9IGZvbnRTaXplSW5QdCAqIDAuNztcbiAgICAgIGRvYy5zZXRGb250U2l6ZShmb250U2l6ZUluUHQpO1xuICAgICAgdGV4dERpbWVuc2lvbnMgPSBkb2MuZ2V0VGV4dERpbWVuc2lvbnModGV4dCk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgdGV4dE1hcmdpbkxlZnQgPSAocGFnZVdpZHRoIC0gdGV4dERpbWVuc2lvbnMudyApIC8gMiA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICdmb250U2l6ZSc6IGZvbnRTaXplSW5QdCxcbiAgICAgICdtYXJnaW5MZWZ0JzogdGV4dE1hcmdpbkxlZnQsXG4gICAgICAnaGVpZ2h0JzogdGV4dERpbWVuc2lvbnMuaFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQWRkIGNvbW1lbnQgdG8gdGhlIGRvY3VtZW50XG4gICAqICogQHBhcmFtICBkb2MgLSBwZGYgZG9jdW1lbnRcbiAgICogKiBAcGFyYW0gIGNvbW1lbnQgLSBDb21tZW50IHRvIGFkZCBpbiB0aGUgZG9jdW1lbnRcbiAgICovXG4gIHByaXZhdGUgYWRkQ29tbWVudChkb2M6IGpzUERGLCBjb21tZW50OiBzdHJpbmcpIHtcbiAgICBjb25zdCBjb21tZW50TWFyZ2luTGVmdCA9IDIwOyAvL21hcmdpbiBsZWZ0IGFuZCBib3R0b20gaXMgZml4XG4gICAgY29uc3QgY29tbWVudE1hcmdpbkJvdHRvbSA9IDU7XG4gICAgY29uc3QgbWFyZ2luVG9wID0gZG9jLmludGVybmFsLnBhZ2VTaXplLmhlaWdodCAtIGNvbW1lbnRNYXJnaW5Cb3R0b207XG4gICAgdGhpcy4gYWRkVGV4dEluUGRmRG9jKGRvYyxjb21tZW50LFxuICAgICAgdGhpcy5URVhUUERGRk9OVC5jb21tZW50Rm9udCxcbiAgICAgIHRoaXMuVEVYVFBERkZPTlQuY29tbWVudEZvbnRTdHlsZSxcbiAgICAgIHRoaXMuVEVYVFBERkZPTlQuY29tbWVudEZvbnRTaXplLFxuICAgICAgY29tbWVudE1hcmdpbkxlZnQsXG4gICAgICBtYXJnaW5Ub3BcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRUZXh0SW5QZGZEb2MoZG9jOiBqc1BERixcbiAgICB0ZXh0VG9BZGQ6IHN0cmluZyxcbiAgICB0ZXh0Rm9udDogc3RyaW5nLFxuICAgIHRleHRGb250U3R5bGU6IHN0cmluZyxcbiAgICB0ZXh0Rm9udFNpemU6IG51bWJlcixcbiAgICB0ZXh0TWFyZ2luTGVmdDogbnVtYmVyLFxuICAgIHRleHRNYXJnaW5Ub3A6IG51bWJlcilcbiAgICB7XG4gICAgICBkb2Muc2V0Rm9udCh0ZXh0Rm9udCwgdGV4dEZvbnRTdHlsZSk7XG4gICAgICBkb2Muc2V0Rm9udFNpemUodGV4dEZvbnRTaXplKTtcbiAgICAgIGRvYy50ZXh0KHRleHRUb0FkZCwgdGV4dE1hcmdpbkxlZnQsIHRleHRNYXJnaW5Ub3ApO1xuICAgIH1cblxuICAvKipcbiAgICogQWRkIHByb2plY3Rpb24gYW5kL29yIHNjYWxlIHRvIHRoZSBkb2N1bWVudFxuICAgKiBAcGFyYW0gIGRvYyAtIHBkZiBkb2N1bWVudFxuICAgKiBAcGFyYW0gIG1hcCAtIE1hcCBvZiB0aGUgYXBwXG4gICAqIEBwYXJhbSAgZHBpIC0gRFBJIHJlc29sdXRpb24gb2YgdGhlIGRvY3VtZW50XG4gICAqIEBwYXJhbSAgcHJvamVjdGlvbiAtIEJvb2wgdG8gaW5kaWNhdGUgaWYgcHJvamVjdGlvbiBuZWVkIHRvIGJlIGFkZGVkXG4gICAqIEBwYXJhbSAgc2NhbGUgLSBCb29sIHRvIGluZGljYXRlIGlmIHNjYWxlIG5lZWQgdG8gYmUgYWRkZWRcbiAgICovXG4gIHByaXZhdGUgYWRkUHJvalNjYWxlKFxuICAgIGRvYzoganNQREYsXG4gICAgbWFwOiBJZ29NYXAsXG4gICAgZHBpOiBudW1iZXIsXG4gICAgcHJvamVjdGlvbjogYm9vbGVhbixcbiAgICBzY2FsZTogYm9vbGVhblxuICApIHtcbiAgICBjb25zdCB0cmFuc2xhdGUgPSB0aGlzLmxhbmd1YWdlU2VydmljZS50cmFuc2xhdGU7XG4gICAgY29uc3QgcHJvalNjYWxlU2l6ZSA9IDE2O1xuICAgIGNvbnN0IHByb2pTY2FsZU1hcmdpbkxlZnQgPSAyMDtcbiAgICBjb25zdCBtYXJnaW5Cb3R0b20gPSAxNTtcbiAgICBjb25zdCBoZWlnaHRQaXhlbHMgPSBkb2MuaW50ZXJuYWwucGFnZVNpemUuaGVpZ2h0IC0gbWFyZ2luQm90dG9tO1xuXG4gICAgbGV0IHRleHRQcm9qU2NhbGU6IHN0cmluZyA9ICcnO1xuICAgIGlmIChwcm9qZWN0aW9uID09PSB0cnVlKSB7XG4gICAgICBjb25zdCBwcm9qVGV4dCA9IHRyYW5zbGF0ZS5pbnN0YW50KCdpZ28uZ2VvLnByaW50Rm9ybS5wcm9qZWN0aW9uJyk7XG4gICAgICB0ZXh0UHJvalNjYWxlICs9IHByb2pUZXh0ICsgJzogJyArIG1hcC5wcm9qZWN0aW9uO1xuICAgIH1cbiAgICBpZiAoc2NhbGUgPT09IHRydWUpIHtcbiAgICAgIGlmIChwcm9qZWN0aW9uID09PSB0cnVlKSB7XG4gICAgICAgIHRleHRQcm9qU2NhbGUgKz0gJyAgICc7XG4gICAgICB9XG4gICAgICBjb25zdCBzY2FsZVRleHQgPSB0cmFuc2xhdGUuaW5zdGFudCgnaWdvLmdlby5wcmludEZvcm0uc2NhbGUnKTtcbiAgICAgIGNvbnN0IG1hcFNjYWxlID0gbWFwLnZpZXdDb250cm9sbGVyLmdldFNjYWxlKGRwaSk7XG4gICAgICB0ZXh0UHJvalNjYWxlICs9IHNjYWxlVGV4dCArICc6IH4gMSAvICcgKyBmb3JtYXRTY2FsZShtYXBTY2FsZSk7XG4gICAgfVxuICAgIGRvYy5zZXRGb250KCdjb3VyaWVyJyk7XG4gICAgZG9jLnNldEZvbnRTaXplKHByb2pTY2FsZVNpemUpO1xuICAgIGRvYy50ZXh0KHRleHRQcm9qU2NhbGUsIHByb2pTY2FsZU1hcmdpbkxlZnQsIGhlaWdodFBpeGVscyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHRoZSBsZWdlbmQgdG8gdGhlIGRvY3VtZW50XG4gICAqIEBwYXJhbSAgZG9jIC0gUGRmIGRvY3VtZW50IHdoZXJlIGxlZ2VuZCB3aWxsIGJlIGFkZGVkXG4gICAqIEBwYXJhbSAgbWFwIC0gTWFwIG9mIHRoZSBhcHBcbiAgICogQHBhcmFtICBtYXJnaW5zIC0gUGFnZSBtYXJnaW5zXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGFkZExlZ2VuZChcbiAgICBkb2M6IGpzUERGLFxuICAgIG1hcDogSWdvTWFwLFxuICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj4sXG4gICAgcmVzb2x1dGlvbjogbnVtYmVyXG4gICkge1xuICAgIC8vIEdldCBodG1sIGNvZGUgZm9yIHRoZSBsZWdlbmRcbiAgICBjb25zdCB3aWR0aCA9IGRvYy5pbnRlcm5hbC5wYWdlU2l6ZS53aWR0aDtcbiAgICBjb25zdCBodG1sID0gYXdhaXQgdGhpcy5nZXRMYXllcnNMZWdlbmRIdG1sKFxuICAgICAgbWFwLFxuICAgICAgd2lkdGgsXG4gICAgICByZXNvbHV0aW9uXG4gICAgKS50b1Byb21pc2UoKTtcbiAgICAvLyBJZiBubyBsZWdlbmQsIHNhdmUgdGhlIG1hcCBkaXJlY3RseVxuICAgIGlmIChodG1sID09PSAnJykge1xuICAgICAgYXdhaXQgdGhpcy5zYXZlRG9jKGRvYyk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgLy8gQ3JlYXRlIGRpdiB0byBjb250YWluIGh0bWwgY29kZSBmb3IgbGVnZW5kXG4gICAgY29uc3QgZGl2ID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGRpdi5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgZGl2LnN0eWxlLnRvcCA9ICcwJztcblxuICAgIC8vIEFkZCBodG1sIGNvZGUgdG8gY29udmVydCBpbiB0aGUgbmV3IHdpbmRvd1xuICAgIHdpbmRvdy5kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgZGl2LmlubmVySFRNTCA9IGh0bWw7XG5cbiAgICBhd2FpdCB0aGlzLnRpbWVvdXQoMSk7XG4gICAgY29uc3QgY2FudmFzID0gYXdhaXQgaHRtbDJjYW52YXMoZGl2LCB7IHVzZUNPUlM6IHRydWUgfSkuY2F0Y2goKGUpID0+IHtcbiAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgIH0pO1xuXG4gICAgaWYgKGNhbnZhcykge1xuICAgICAgY29uc3QgcG91cmNlbnRhZ2VSZWR1Y3Rpb24gPSAwLjg1O1xuICAgICAgY29uc3QgaW1hZ2VTaXplID0gW3BvdXJjZW50YWdlUmVkdWN0aW9uICogKDI1LjQgKiBjYW52YXMud2lkdGgpIC8gcmVzb2x1dGlvbiwgcG91cmNlbnRhZ2VSZWR1Y3Rpb25cbiAgICAgICAgKiAoMjUuNCAqIGNhbnZhcy5oZWlnaHQpIC8gcmVzb2x1dGlvbl07XG4gICAgICBsZXQgaW1nRGF0YTtcbiAgICAgIGRvYy5hZGRQYWdlKCk7XG4gICAgICBpbWdEYXRhID0gY2FudmFzLnRvRGF0YVVSTCgnaW1hZ2UvcG5nJyk7XG4gICAgICBkb2MuYWRkSW1hZ2UoaW1nRGF0YSwgJ1BORycsIDEwLCAxMCwgaW1hZ2VTaXplWzBdLCBpbWFnZVNpemVbMV0pO1xuICAgICAgZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGl2KTsgLy8gcmVtb3ZlIHRlbXAgZGl2IChJRSBzdHlsZSlcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnNhdmVEb2MoZG9jKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCB0aGUgbGVnZW5kIHRvIHRoZSBkb2N1bWVudFxuICAgKiBAcGFyYW0gIGRvYyAtIFBkZiBkb2N1bWVudCB3aGVyZSBsZWdlbmQgd2lsbCBiZSBhZGRlZFxuICAgKiBAcGFyYW0gIG1hcCAtIE1hcCBvZiB0aGUgYXBwXG4gICAqIEBwYXJhbSAgbWFyZ2lucyAtIFBhZ2UgbWFyZ2luc1xuICAgKi9cbiAgICAgcHJpdmF0ZSBhc3luYyBhZGRMZWdlbmRTYW1lUGFnZShcbiAgICAgIGRvYzoganNQREYsXG4gICAgICBtYXA6IElnb01hcCxcbiAgICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj4sXG4gICAgICByZXNvbHV0aW9uOiBudW1iZXIsXG4gICAgICBsZWdlbmRQb3NpdGlvbjogc3RyaW5nXG4gICAgKSB7XG4gICAgICAvLyBHZXQgaHRtbCBjb2RlIGZvciB0aGUgbGVnZW5kXG4gICAgICBjb25zdCB3aWR0aCA9IGRvYy5pbnRlcm5hbC5wYWdlU2l6ZS53aWR0aDtcbiAgICAgIGNvbnN0IGh0bWwgPSBhd2FpdCB0aGlzLmdldExheWVyc0xlZ2VuZEh0bWwoXG4gICAgICAgIG1hcCxcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIHJlc29sdXRpb25cbiAgICAgICkudG9Qcm9taXNlKCk7XG4gICAgICAvLyBJZiBubyBsZWdlbmQsIHNhdmUgdGhlIG1hcCBkaXJlY3RseVxuICAgICAgaWYgKGh0bWwgPT09ICcnKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2F2ZURvYyhkb2MpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIC8vIENyZWF0ZSBkaXYgdG8gY29udGFpbiBodG1sIGNvZGUgZm9yIGxlZ2VuZFxuICAgICAgY29uc3QgZGl2ID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgIGRpdi5zdHlsZS50b3AgPSAnMCc7XG4gICAgICAvLyBBZGQgaHRtbCBjb2RlIHRvIGNvbnZlcnQgaW4gdGhlIG5ldyB3aW5kb3dcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICBkaXYuaW5uZXJIVE1MID0gaHRtbDtcbiAgICAgIGF3YWl0IHRoaXMudGltZW91dCgxKTtcbiAgICAgIGNvbnN0IGNhbnZhcyA9IGF3YWl0IGh0bWwyY2FudmFzKGRpdiwgeyB1c2VDT1JTOiB0cnVlIH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgfSk7XG4gICAgICBsZXQgbWFyZ2luc0xlZ2VuZDtcbiAgICAgIGlmIChjYW52YXMpIHtcbiAgICAgICAgY29uc3QgcG91cmNlbnRhZ2VSZWR1Y3Rpb24gPSAwLjg1O1xuICAgICAgICBjb25zdCBpbWFnZVNpemUgPSBbcG91cmNlbnRhZ2VSZWR1Y3Rpb24gKiAoMjUuNCAqIGNhbnZhcy53aWR0aCkgLyByZXNvbHV0aW9uLFxuICAgICAgICAgICBwb3VyY2VudGFnZVJlZHVjdGlvbiAqICgyNS40ICogY2FudmFzLmhlaWdodCkgLyByZXNvbHV0aW9uXTtcbiAgICAgICAgLy8gTW92ZSB0aGUgbGVnZW5kIHRvIHRoZSBjb3JyZWN0IHBvc2l0aW9uIG9uIHRoZSBwYWdlXG4gICAgICAgIGlmICggbGVnZW5kUG9zaXRpb24gPT09ICdib3R0b21yaWdodCcpIHtcbiAgICAgICAgICBtYXJnaW5zTGVnZW5kID0gW2RvYy5pbnRlcm5hbC5wYWdlU2l6ZS5oZWlnaHQgLSBtYXJnaW5zWzJdIC0gaW1hZ2VTaXplWzFdLCBtYXJnaW5zWzFdLFxuICAgICAgICAgICBtYXJnaW5zWzJdLCBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGggLSBtYXJnaW5zWzFdIC0gaW1hZ2VTaXplWzBdXTtcbiAgICAgICAgfSBlbHNlIGlmIChsZWdlbmRQb3NpdGlvbiA9PT0gJ3RvcHJpZ2h0Jykge1xuICAgICAgICAgIG1hcmdpbnNMZWdlbmQgPSBbbWFyZ2luc1swXSwgbWFyZ2luc1sxXSwgZG9jLmludGVybmFsLnBhZ2VTaXplLmhlaWdodCAtIG1hcmdpbnNbMF0gLSBpbWFnZVNpemVbMV0sXG4gICAgICAgICAgZG9jLmludGVybmFsLnBhZ2VTaXplLndpZHRoIC0gbWFyZ2luc1sxXSAtIGltYWdlU2l6ZVswXSBdO1xuICAgICAgICB9IGVsc2UgaWYgKGxlZ2VuZFBvc2l0aW9uID09PSAnYm90dG9tbGVmdCcpIHtcbiAgICAgICAgICAvLyBXaGVuIHRoZSBsZWdlbmQgaXMgaW4gdGhlIGJvdHRvbSBsZWZ0LCByYWlzZSB0aGUgbGVnZW5kIHNsaWdodGx5IHVwd2FyZCBzbyB0aGF0IGF0dHJpYnV0aW9ucyBhcmUgdmlzaWJsZVxuICAgICAgICAgIG1hcmdpbnNMZWdlbmQgPSBbZG9jLmludGVybmFsLnBhZ2VTaXplLmhlaWdodCAtIG1hcmdpbnNbMl0gLSBpbWFnZVNpemVbMV0gLSAxNSxcbiAgICAgICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGggLSBtYXJnaW5zWzNdIC0gaW1hZ2VTaXplWzBdLCBtYXJnaW5zWzJdICsgMTUsIG1hcmdpbnNbM10gXTtcbiAgICAgICAgfSBlbHNlIGlmIChsZWdlbmRQb3NpdGlvbiA9PT0gJ3RvcGxlZnQnKSB7XG4gICAgICAgICAgbWFyZ2luc0xlZ2VuZCA9IFttYXJnaW5zWzBdLCBkb2MuaW50ZXJuYWwucGFnZVNpemUud2lkdGggLSBtYXJnaW5zWzNdIC0gaW1hZ2VTaXplWzBdLFxuICAgICAgICAgICBkb2MuaW50ZXJuYWwucGFnZVNpemUuaGVpZ2h0IC0gbWFyZ2luc1swXSAtIGltYWdlU2l6ZVsxXSwgbWFyZ2luc1szXSBdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkQ2FudmFzKGRvYywgY2FudmFzLCBtYXJnaW5zTGVnZW5kKTsgLy8gdGhpcyBhZGRzIHRoZSBsZWdlbmRcbiAgICAgICAgZGl2LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZGl2KTsgLy8gcmVtb3ZlIHRlbXAgZGl2IChJRSBzdHlsZSlcbiAgICAgICAgYXdhaXQgdGhpcy5zYXZlRG9jKGRvYyk7XG4gICAgICB9XG4gICAgfVxuXG4gIC8qKlxuICAgKiBBZGQgc2NhbGUgYW5kIGF0dHJpYnV0aW9ucyBvbiB0aGUgbWFwIG9uIHRoZSBkb2N1bWVudFxuICAgKiBAcGFyYW0gIGRvYyAtIFBkZiBkb2N1bWVudCB3aGVyZSBsZWdlbmQgd2lsbCBiZSBhZGRlZFxuICAgKiBAcGFyYW0gIG1hcCAtIE1hcCBvZiB0aGUgYXBwXG4gICAqIEBwYXJhbSAgbWFyZ2lucyAtIFBhZ2UgbWFyZ2luc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBhZGRTY2FsZShcbiAgICBkb2M6IGpzUERGLFxuICAgIG1hcDogSWdvTWFwLFxuICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj5cbiAgICApIHtcbiAgICAgIGNvbnN0IG1hcFNpemUgPSBtYXAub2wuZ2V0U2l6ZSgpO1xuICAgICAgY29uc3QgZXh0ZW50ID0gbWFwLm9sLmdldFZpZXcoKS5jYWxjdWxhdGVFeHRlbnQobWFwU2l6ZSk7XG4gICAgICAvLyBHZXQgdGhlIHNjYWxlIGFuZCBhdHRyaWJ1dGlvblxuICAgICAgLy8gd2UgdXNlIGNsb25lTm9kZSB0byBtb2RpZnkgdGhlIG5vZGVzIHRvIHByaW50IHdpdGhvdXQgbW9kaWZ5aW5nIGl0IG9uIHRoZSBwYWdlLCB1c2luZyBkZWVwOnRydWUgdG8gZ2V0IGNoaWxkcmVuXG4gICAgICBsZXQgY2FudmFzT3ZlcmxheUhUTUw7XG4gICAgICBjb25zdCBtYXBPdmVybGF5SFRNTCA9IG1hcC5vbC5nZXRPdmVybGF5Q29udGFpbmVyU3RvcEV2ZW50KCk7XG4gICAgICAvLyBSZW1vdmUgdGhlIFVJIGJ1dHRvbnMgZnJvbSB0aGUgbm9kZXNcbiAgICAgIGNvbnN0IE92ZXJsYXlIVE1MQnV0dG9ucyA9IG1hcE92ZXJsYXlIVE1MLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdidXR0b24nKTtcbiAgICAgIGNvbnN0IE92ZXJsYXlIVE1MQnV0dG9uc2FyciA9IEFycmF5LmZyb20oT3ZlcmxheUhUTUxCdXR0b25zKTtcbiAgICAgIGZvciAoY29uc3QgT3ZlcmxheUhUTUxCdXR0b24gb2YgT3ZlcmxheUhUTUxCdXR0b25zYXJyKSB7XG4gICAgICAgIE92ZXJsYXlIVE1MQnV0dG9uLnNldEF0dHJpYnV0ZSgnZGF0YS1odG1sMmNhbnZhcy1pZ25vcmUnLCAndHJ1ZScpO1xuICAgICAgfVxuICAgICAgLy8gQ2hhbmdlIHRoZSBzdHlsZXMgb2YgaHlwZXJsaW5rIGluIHRoZSBwcmludGVkIHZlcnNpb25cbiAgICAgIC8vIFRyYW5zZm9ybSB0aGUgT3ZlcmxheSBpbnRvIGEgY2FudmFzXG4gICAgICAvLyBzY2FsZSBpcyBuZWNlc3NhcnkgdG8gbWFrZSBpdCBpbiBnb29nbGUgY2hyb21lXG4gICAgICAvLyBiYWNrZ3JvdW5kIGFzIG51bGwgYmVjYXVzZSBvdGhlcndpc2UgaXQgaXMgd2hpdGUgYW5kIGNvdmVyIHRoZSBtYXBcbiAgICAgIC8vIGFsbG93dGFpbnQgaXMgdG8gYWxsb3cgcmVuZGVyaW5nIGltYWdlcyBpbiB0aGUgYXR0cmlidXRpb25zXG4gICAgICAvLyB1c2VDT1JTOiB0cnVlIHBvdXIgcGVybWV0dHJlIGRlIHJlbmRlcmVyIGxlcyBpbWFnZXMgKG5lIG1hcmNoZSBwYXMgZW4gbG9jYWwpXG4gICAgICBjb25zdCBjYW52YXMgPSBhd2FpdCBodG1sMmNhbnZhcyhtYXBPdmVybGF5SFRNTCwge1xuICAgICAgICBzY2FsZTogMSxcbiAgICAgICAgYmFja2dyb3VuZENvbG9yOiBudWxsLFxuICAgICAgICBhbGxvd1RhaW50OiB0cnVlLFxuICAgICAgICB1c2VDT1JTOiB0cnVlLFxuICAgICAgfSkudGhlbiggZSA9PiB7XG4gICAgICAgIGNhbnZhc092ZXJsYXlIVE1MID0gZTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5hZGRDYW52YXMoZG9jLCBjYW52YXNPdmVybGF5SFRNTCwgbWFyZ2lucyk7IC8vIHRoaXMgYWRkcyBzY2FsZXMgYW5kIGF0dHJpYnV0aW9uc1xuIH1cblxuICBkZWZpbmVOYkZpbGVUb1Byb2Nlc3MobmJGaWxlVG9Qcm9jZXNzKSB7XG4gICAgdGhpcy5uYkZpbGVUb1Byb2Nlc3MgPSBuYkZpbGVUb1Byb2Nlc3M7XG4gIH1cblxuICBwcml2YXRlIHRpbWVvdXQobXMpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQ2FudmFzKFxuICAgIGRvYzoganNQREYsXG4gICAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCxcbiAgICBtYXJnaW5zOiBBcnJheTxudW1iZXI+XG4gICkge1xuICAgIGxldCBpbWFnZTtcbiAgICBpZiAoY2FudmFzKSB7XG4gICAgICBpbWFnZSA9IGNhbnZhcy50b0RhdGFVUkwoJ2ltYWdlL3BuZycpO1xuICAgIH1cblxuICAgIGlmIChpbWFnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAoaW1hZ2UubGVuZ3RoIDwgMjAgKSB7IC8vICBpbWcgaXMgY29ycnVwdCAgICB0b2RvOiBmaXggYWRkU2NhbGUgaW4gbW9iaWxlIG1ha2UgYSBjb3JydXB0IGltZ1xuICAgICAgICBjb25zb2xlLmxvZygnV2FybmluZzogQW4gaW1hZ2UgY2Fubm90IGJlIHByaW50IGluIHBkZiBmaWxlJyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGltYWdlU2l6ZSA9IHRoaXMuZ2V0SW1hZ2VTaXplVG9GaXRQZGYoZG9jLCBjYW52YXMsIG1hcmdpbnMpO1xuICAgICAgZG9jLmFkZEltYWdlKFxuICAgICAgICBpbWFnZSxcbiAgICAgICAgJ1BORycsXG4gICAgICAgIG1hcmdpbnNbM10sXG4gICAgICAgIG1hcmdpbnNbMF0sXG4gICAgICAgIGltYWdlU2l6ZVswXSxcbiAgICAgICAgaW1hZ2VTaXplWzFdXG4gICAgICApO1xuICAgICAgZG9jLnJlY3QobWFyZ2luc1szXSwgbWFyZ2luc1swXSwgaW1hZ2VTaXplWzBdLCBpbWFnZVNpemVbMV0pO1xuICAgICAgdGhpcy5pbWdTaXplQWRkZWQgPSBpbWFnZVNpemU7IC8vIGtlZXAgaW1nIHNpemUgZm9yIGdlb3JlZiBsYXRlclxuICAgIH1cbiAgfVxuXG4gIC8vIFRPRE8gZml4IHByaW50aW5nIHdpdGggaW1hZ2UgcmVzb2x1dGlvblxuICBwcml2YXRlIGFkZE1hcChcbiAgICBkb2M6IGpzUERGLFxuICAgIG1hcDogSWdvTWFwLFxuICAgIHJlc29sdXRpb246IG51bWJlcixcbiAgICBzaXplOiBBcnJheTxudW1iZXI+LFxuICAgIG1hcmdpbnM6IEFycmF5PG51bWJlcj5cbiAgKSB7XG4gICAgY29uc3Qgc3RhdHVzJCA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgICBjb25zdCBtYXBTaXplID0gbWFwLm9sLmdldFNpemUoKTtcbiAgICBjb25zdCBleHRlbnQgPSBtYXAub2wuZ2V0VmlldygpLmNhbGN1bGF0ZUV4dGVudChtYXBTaXplKTtcblxuICAgIGNvbnN0IHdpZHRoUGl4ZWxzID0gTWF0aC5yb3VuZCgoc2l6ZVswXSAqIHJlc29sdXRpb24pIC8gMjUuNCk7XG4gICAgY29uc3QgaGVpZ2h0UGl4ZWxzID0gTWF0aC5yb3VuZCgoc2l6ZVsxXSAqIHJlc29sdXRpb24pIC8gMjUuNCk7XG5cbiAgICBsZXQgdGltZW91dDtcblxuICAgIG1hcC5vbC5vbmNlKCdyZW5kZXJjb21wbGV0ZScsIChldmVudDogYW55KSA9PiB7XG4gICAgICBjb25zdCBjYW52YXNlcyA9IGV2ZW50LnRhcmdldC5nZXRWaWV3cG9ydCgpLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdjYW52YXMnKTtcbiAgICAgIGNvbnN0IG1hcFN0YXR1cyQkID0gbWFwLnN0YXR1cyQuc3Vic2NyaWJlKChtYXBTdGF0dXM6IFN1YmplY3RTdGF0dXMpID0+IHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgIGlmIChtYXBTdGF0dXMgIT09IFN1YmplY3RTdGF0dXMuRG9uZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIG1hcFN0YXR1cyQkLnVuc3Vic2NyaWJlKCk7XG5cbiAgICAgICAgbGV0IHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRG9uZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBmb3IgKGNvbnN0IGNhbnZhcyBvZiBjYW52YXNlcykge1xuICAgICAgICAgICAgaWYgKGNhbnZhcy53aWR0aCAhPT0gMCkge1xuICAgICAgICAgICAgICB0aGlzLmFkZENhbnZhcyhkb2MsIGNhbnZhcywgbWFyZ2lucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBzdGF0dXMgPSBTdWJqZWN0U3RhdHVzLkVycm9yO1xuICAgICAgICAgIHRoaXMubWVzc2FnZVNlcnZpY2UuZXJyb3IoXG4gICAgICAgICAgICB0aGlzLmxhbmd1YWdlU2VydmljZS50cmFuc2xhdGUuaW5zdGFudChcbiAgICAgICAgICAgICAgJ2lnby5nZW8ucHJpbnRGb3JtLmNvcnNFcnJvck1lc3NhZ2VCb2R5J1xuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICAgICAgICAnaWdvLmdlby5wcmludEZvcm0uY29yc0Vycm9yTWVzc2FnZUhlYWRlcidcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVuZGVyTWFwKG1hcCwgbWFwU2l6ZSwgZXh0ZW50KTtcbiAgICAgICAgc3RhdHVzJC5uZXh0KHN0YXR1cyk7XG4gICAgICB9KTtcblxuICAgICAgLy8gSWYgbm8gbG9hZGluZyBhcyBzdGFydGVkIGFmdGVyIDIwMG1zLCB0aGVuIHByb2JhYmx5IG5vIGxvYWRpbmdcbiAgICAgIC8vIGlzIHJlcXVpcmVkLlxuICAgICAgdGltZW91dCA9IHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgbWFwU3RhdHVzJCQudW5zdWJzY3JpYmUoKTtcblxuICAgICAgICBsZXQgc3RhdHVzID0gU3ViamVjdFN0YXR1cy5Eb25lO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGZvciAoY29uc3QgY2FudmFzIG9mIGNhbnZhc2VzKSB7XG4gICAgICAgICAgICBpZiAoY2FudmFzLndpZHRoICE9PSAwKSB7XG4gICAgICAgICAgICAgIHRoaXMuYWRkQ2FudmFzKGRvYywgY2FudmFzLCBtYXJnaW5zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRXJyb3I7XG4gICAgICAgICAgdGhpcy5tZXNzYWdlU2VydmljZS5lcnJvcihcbiAgICAgICAgICAgIHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICAgICAgICAnaWdvLmdlby5wcmludEZvcm0uY29yc0Vycm9yTWVzc2FnZUJvZHknXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgdGhpcy5sYW5ndWFnZVNlcnZpY2UudHJhbnNsYXRlLmluc3RhbnQoXG4gICAgICAgICAgICAgICdpZ28uZ2VvLnByaW50Rm9ybS5jb3JzRXJyb3JNZXNzYWdlSGVhZGVyJ1xuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJNYXAobWFwLCBtYXBTaXplLCBleHRlbnQpO1xuICAgICAgICBzdGF0dXMkLm5leHQoc3RhdHVzKTtcbiAgICAgIH0sIDIwMCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnJlbmRlck1hcChtYXAsIFt3aWR0aFBpeGVscywgaGVpZ2h0UGl4ZWxzXSwgZXh0ZW50KTtcblxuICAgIHJldHVybiBzdGF0dXMkO1xuICB9XG5cbiAgLyoqXG4gICAqIERvd25sb2FkIGFuIGltYWdlIG9mIHRoZSBtYXAgd2l0aCBhZGRpdGlvbiBvZiBpbmZvcm1hdGlvbnNcbiAgICogQHBhcmFtICBtYXAgLSBNYXAgb2YgdGhlIGFwcFxuICAgKiBAcGFyYW0gIGZvcm1hdCAtIEltYWdlIGZvcm1hdC4gZGVmYXVsdCB2YWx1ZSB0byBcInBuZ1wiXG4gICAqIEBwYXJhbSAgcHJvamVjdGlvbiAtIEluZGljYXRlIGlmIHByb2plY3Rpb24gbmVlZCB0byBiZSBhZGQuIERlZmF1bHQgdG8gZmFsc2VcbiAgICogQHBhcmFtICBzY2FsZSAtIEluZGljYXRlIGlmIHNjYWxlIG5lZWQgdG8gYmUgYWRkLiBEZWZhdWx0IHRvIGZhbHNlXG4gICAqIEBwYXJhbSAgbGVnZW5kIC0gSW5kaWNhdGUgaWYgdGhlIGxlZ2VuZCBvZiBsYXllcnMgbmVlZCB0byBiZSBkb3dubG9hZC4gRGVmYXVsdCB0byBmYWxzZVxuICAgKiBAcGFyYW0gIHRpdGxlIC0gVGl0bGUgdG8gYWRkIGZvciB0aGUgbWFwIC0gRGVmYXVsdCB0byBibGFua1xuICAgKiBAcGFyYW0gIHN1YnRpdGxlIC0gU3VidGl0bGUgdG8gYWRkIGZvciB0aGUgbWFwIC0gRGVmYXVsdCB0byBibGFua1xuICAgKiBAcGFyYW0gIGNvbW1lbnQgLSBDb21tZW50IHRvIGFkZCBmb3IgdGhlIG1hcCAtIERlZmF1bHQgdG8gYmxhbmtcbiAgICogQHBhcmFtICBkb1ppcEZpbGUgLSBJbmRpY2F0ZSBpZiB3ZSBkbyBhIHppcCB3aXRoIHRoZSBmaWxlXG4gICAqIEByZXR1cm4gSW1hZ2UgZmlsZSBvZiB0aGUgbWFwIHdpdGggZXh0ZW5zaW9uIGZvcm1hdCBnaXZlbiBhcyBwYXJhbWV0ZXJcbiAgICovXG4gIGRvd25sb2FkTWFwSW1hZ2UoXG4gICAgbWFwOiBJZ29NYXAsXG4gICAgcmVzb2x1dGlvbjogbnVtYmVyLFxuICAgIGZvcm1hdCA9ICdwbmcnLFxuICAgIHByb2plY3Rpb24gPSBmYWxzZSxcbiAgICBzY2FsZSA9IGZhbHNlLFxuICAgIHRpdGxlID0gJycsXG4gICAgc3VidGl0bGUgPSAnJyxcbiAgICBjb21tZW50ID0gJycsXG4gICAgZG9aaXBGaWxlID0gdHJ1ZSxcbiAgICBsZWdlbmRQb3NpdGlvbjogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IHN0YXR1cyQgPSBuZXcgU3ViamVjdCgpO1xuICAgIC8vIGNvbnN0IHJlc29sdXRpb24gPSBtYXAub2wuZ2V0VmlldygpLmdldFJlc29sdXRpb24oKTtcbiAgICB0aGlzLmFjdGl2aXR5SWQgPSB0aGlzLmFjdGl2aXR5U2VydmljZS5yZWdpc3RlcigpO1xuICAgIGNvbnN0IHRyYW5zbGF0ZSA9IHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZTtcbiAgICBtYXAub2wub25jZSgncmVuZGVyY29tcGxldGUnLCBhc3luYyAoZXZlbnQ6IGFueSkgPT4ge1xuICAgICAgZm9ybWF0ID0gZm9ybWF0LnRvTG93ZXJDYXNlKCk7XG4gICAgICBjb25zdCBvbGRDYW52YXMgPSBldmVudC50YXJnZXRcbiAgICAgICAgLmdldFZpZXdwb3J0KClcbiAgICAgICAgLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdjYW52YXMnKVswXTtcbiAgICAgIGNvbnN0IG5ld0NhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgY29uc3QgbmV3Q29udGV4dCA9IG5ld0NhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgLy8gUG9zdGlvbiBpbiBoZWlnaHQgdG8gc2V0IHRoZSBjYW52YXMgaW4gbmV3IGNhbnZhc1xuICAgICAgbGV0IHBvc2l0aW9uSENhbnZhcyA9IDA7XG4gICAgICAvLyBHZXQgaGVpZ2h0L3dpZHRoIG9mIG1hcCBjYW52YXNcbiAgICAgIGNvbnN0IHdpZHRoID0gb2xkQ2FudmFzLndpZHRoO1xuICAgICAgbGV0IGhlaWdodCA9IG9sZENhbnZhcy5oZWlnaHQ7XG4gICAgICAvLyBTZXQgRm9udCB0byBjYWxjdWxhdGUgY29tbWVudCB3aWR0aFxuICAgICAgbmV3Q29udGV4dC5mb250ID0gJzIwcHggQ2FsaWJyaSc7XG4gICAgICBjb25zdCBjb21tZW50V2lkdGggPSBuZXdDb250ZXh0Lm1lYXN1cmVUZXh0KGNvbW1lbnQpLndpZHRoO1xuICAgICAgLy8gQWRkIGhlaWdodCBmb3IgdGl0bGUgaWYgZGVmaW5lZFxuICAgICAgaGVpZ2h0ID0gdGl0bGUgIT09ICcnID8gaGVpZ2h0ICsgMzAgOiBoZWlnaHQ7XG4gICAgICAvLyBBZGQgaGVpZ2h0IGZvciB0aXRsZSBpZiBkZWZpbmVkXG4gICAgICBoZWlnaHQgPSBzdWJ0aXRsZSAhPT0gJycgPyBoZWlnaHQgKyAzMCA6IGhlaWdodDtcbiAgICAgIC8vIEFkZCBoZWlnaHQgZm9yIHByb2plY3Rpb24gb3Igc2NhbGUgKHNhbWUgbGluZSkgaWYgZGVmaW5lZFxuICAgICAgaGVpZ2h0ID0gcHJvamVjdGlvbiAhPT0gZmFsc2UgfHwgc2NhbGUgIT09IGZhbHNlID8gaGVpZ2h0ICsgMzAgOiBoZWlnaHQ7XG4gICAgICBjb25zdCBwb3NpdGlvbkhQcm9qU2NhbGUgPSBoZWlnaHQgLSAxMDtcbiAgICAgIC8vIERlZmluZSBudW1iZXIgb2YgbGluZSBkZXBlbmRpbmcgb2YgdGhlIGNvbW1lbnQgbGVuZ3RoXG4gICAgICBjb25zdCBjb21tZW50TmJMaW5lID0gTWF0aC5jZWlsKGNvbW1lbnRXaWR0aCAvIHdpZHRoKTtcbiAgICAgIC8vIEFkZCBoZWlnaHQgZm9yIG11bHRpbGluZSBjb21tZW50IGlmIGRlZmluZWRcbiAgICAgIGhlaWdodCA9IGNvbW1lbnQgIT09ICcnID8gaGVpZ2h0ICsgY29tbWVudE5iTGluZSAqIDMwIDogaGVpZ2h0O1xuICAgICAgbGV0IHBvc2l0aW9uSENvbW1lbnQgPSBoZWlnaHQgLSBjb21tZW50TmJMaW5lICogMjAgKyA1O1xuICAgICAgLy8gU2V0IHRoZSBuZXcgY2FudmFzIHdpdGggdGhlIG5ldyBjYWxjdWxhdGVkIHNpemVcbiAgICAgIG5ld0NhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgbmV3Q2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICAgIGlmIChbJ2JtcCcsJ2dpZicsICdqcGVnJywgJ3BuZycsICd0aWZmJ10uaW5kZXhPZihmb3JtYXQpID4gLTEpIHtcbiAgICAgICAgLy8gUGF0Y2ggSnBlZyBkZWZhdWx0IGJsYWNrIGJhY2tncm91bmQgdG8gd2hpdGVcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ2pwZWcnKSB7XG4gICAgICAgICAgbmV3Q29udGV4dC5maWxsU3R5bGUgPSAnI2ZmZmZmZic7XG4gICAgICAgICAgbmV3Q29udGV4dC5maWxsUmVjdCgwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICBuZXdDb250ZXh0LmZpbGxTdHlsZSA9ICcjMDAwMDAwJztcbiAgICAgICAgfSBlbHNlIGlmICh0aXRsZSAhPT0gJycgfHwgc3VidGl0bGUgIT09ICcnIHx8IGNvbW1lbnQgIT09ICcnIHx8XG4gICAgICAgICAgICBwcm9qZWN0aW9uICE9PSBmYWxzZSB8fCBzY2FsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgbmV3Q29udGV4dC5maWxsU3R5bGUgPSAnI2ZmZmZmZic7XG4gICAgICAgICAgICAgIG5ld0NvbnRleHQuZmlsbFJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICAgIG5ld0NvbnRleHQuZmlsbFN0eWxlID0gJyMwMDAwMDAnO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIElmIGEgdGl0bGUgbmVlZCB0byBiZSBhZGRlZCB0byBjYW52YXNcbiAgICAgIGlmICh0aXRsZSAhPT0gJycpIHtcbiAgICAgICAgLy8gU2V0IGZvbnQgZm9yIHRpdGxlXG4gICAgICAgIC8vIEFkanVzdCBhY2NvcmRpbmcgdG8gdGl0bGUgbGVuZ3RoXG4gICAgICAgIG5ld0NvbnRleHQuZm9udCA9ICcyNnB4IENhbGlicmknO1xuICAgICAgICBwb3NpdGlvbkhDYW52YXMgPSAzMDtcbiAgICAgICAgbmV3Q29udGV4dC50ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgbmV3Q29udGV4dC5maWxsVGV4dCh0aXRsZSwgd2lkdGggLyAyLCAyMCwgd2lkdGggKiAwLjkpO1xuICAgICAgfVxuICAgICAgaWYgKHN1YnRpdGxlICE9PSAnJykge1xuICAgICAgICAvLyBTZXQgZm9udCBmb3Igc3VidGl0bGVcbiAgICAgICAgLy8gQWRqdXN0IGFjY29yZGluZyB0byB0aXRsZSBsZW5ndGhcbiAgICAgICAgbmV3Q29udGV4dC5mb250ID0gJzI2cHggQ2FsaWJyaSc7XG4gICAgICAgIHBvc2l0aW9uSENhbnZhcyA9IDYwO1xuICAgICAgICBuZXdDb250ZXh0LnRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICBuZXdDb250ZXh0LmZpbGxUZXh0KHN1YnRpdGxlLCB3aWR0aCAvIDIsIDUwLCB3aWR0aCAqIDAuOSk7XG4gICAgICB9XG4gICAgICAvLyBTZXQgZm9udCBmb3IgbmV4dCBzZWN0aW9uXG4gICAgICBuZXdDb250ZXh0LmZvbnQgPSAnMjBweCBDYWxpYnJpJztcbiAgICAgIC8vIElmIHByb2plY3Rpb24gb3IvZW5kIHNjYWxlIG5lZWQgdG8gYmUgYWRkZWQgdG8gY2FudmFzXG4gICAgICBpZigocHJvamVjdGlvbiAhPT0gZmFsc2UpIHx8IChzY2FsZSAhPT0gZmFsc2UpKSB7XG4gICAgICAgIGxldCBwcm9qZWN0aW9uU2NhbGVUZXh0ID0gJyc7XG4gICAgICAgIGlmIChwcm9qZWN0aW9uICE9PSBmYWxzZSkge1xuICAgICAgICAgIGNvbnN0IHByb2pUZXh0ID0gdHJhbnNsYXRlLmluc3RhbnQoJ2lnby5nZW8ucHJpbnRGb3JtLnByb2plY3Rpb24nKTtcbiAgICAgICAgICBwcm9qZWN0aW9uU2NhbGVUZXh0ID0gcHJvalRleHQgKyAnOiAnICsgbWFwLnByb2plY3Rpb24gKyAnICAgICAgICAgJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY2FsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICBjb25zdCBzY2FsZVRleHQgPSB0cmFuc2xhdGUuaW5zdGFudCgnaWdvLmdlby5wcmludEZvcm0uc2NhbGUnKTtcbiAgICAgICAgICBjb25zdCBtYXBTY2FsZSA9IG1hcC52aWV3Q29udHJvbGxlci5nZXRTY2FsZShyZXNvbHV0aW9uKTtcbiAgICAgICAgICBwcm9qZWN0aW9uU2NhbGVUZXh0ICs9IHNjYWxlVGV4dCArICc6IH4gMSAvICcgKyBmb3JtYXRTY2FsZShtYXBTY2FsZSk7XG4gICAgICAgIH1cbiAgICAgICAgbmV3Q29udGV4dC50ZXh0QWxpZ24gPSAnY2VudGVyJztcbiAgICAgICAgbmV3Q29udGV4dC5maWxsVGV4dChwcm9qZWN0aW9uU2NhbGVUZXh0LCB3aWR0aCAvIDIsIHBvc2l0aW9uSFByb2pTY2FsZSwgd2lkdGggKiAwLjkpO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiBhIGNvbW1lbnQgbmVlZCB0byBiZSBhZGRlZCB0byBjYW52YXNcbiAgICAgIGlmIChjb21tZW50ICE9PSAnJykge1xuICAgICAgICBuZXdDb250ZXh0LnRleHRBbGlnbiA9ICdjZW50ZXInO1xuICAgICAgICAvLyBJZiBvbmx5IG9uZSBsaW5lLCBubyBuZWVkIHRvIG11bHRpbGluZSB0aGUgY29tbWVudFxuICAgICAgICBpZiAoY29tbWVudE5iTGluZSA9PT0gMSkge1xuICAgICAgICAgIG5ld0NvbnRleHQuZmlsbFRleHQoY29tbWVudCwgd2lkdGggLyAyLCBwb3NpdGlvbkhDb21tZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBTZXBhcmF0ZSB0aGUgc2V0ZW5zZXMgdG8gYmUgYXBwcm94LiB0aGUgc2FtZSBsZW5ndGhcbiAgICAgICAgICBjb25zdCBuYkNvbW1lbnRDaGFyID0gY29tbWVudC5sZW5ndGg7XG4gICAgICAgICAgY29uc3QgQ29tbWVudExlbmd0aFRvQ3V0ID0gTWF0aC5mbG9vcihuYkNvbW1lbnRDaGFyIC8gY29tbWVudE5iTGluZSk7XG4gICAgICAgICAgbGV0IGNvbW1lbnRDdXJyZW50TGluZSA9ICcnO1xuICAgICAgICAgIGxldCBwb3NpdGlvbkZpcnN0Q3V0Q2hhciA9IDA7XG4gICAgICAgICAgbGV0IHBvc2l0aW9uTGFzdEJsYW5rO1xuICAgICAgICAgIC8vIExvb3AgZm9yIHRoZSBudW1iZXIgb2YgbGluZSBjYWxjdWxhdGVkXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb21tZW50TmJMaW5lOyBpKyspIHtcbiAgICAgICAgICAgIC8vIEZvciBhbGwgbGluZSBleGNlcHQgbGFzdFxuICAgICAgICAgICAgaWYgKGNvbW1lbnROYkxpbmUgLSAxID4gaSkge1xuICAgICAgICAgICAgICAvLyBHZXQgY29tbWVudCBjdXJyZW50IGxpbmUgdG8gZmluZCB0aGUgcmlnaHQgcGxhY2UgdHUgY3V0IGNvbW1lbnRcbiAgICAgICAgICAgICAgY29tbWVudEN1cnJlbnRMaW5lID0gY29tbWVudC5zdWJzdHIoXG4gICAgICAgICAgICAgICAgcG9zaXRpb25GaXJzdEN1dENoYXIsXG4gICAgICAgICAgICAgICAgQ29tbWVudExlbmd0aFRvQ3V0XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIC8vIEN1dCB0aGUgc2V0ZW5jZSBhdCBibGFua1xuICAgICAgICAgICAgICBwb3NpdGlvbkxhc3RCbGFuayA9IGNvbW1lbnRDdXJyZW50TGluZS5sYXN0SW5kZXhPZignICcpO1xuICAgICAgICAgICAgICBuZXdDb250ZXh0LmZpbGxUZXh0KFxuICAgICAgICAgICAgICAgIGNvbW1lbnRDdXJyZW50TGluZS5zdWJzdHIoMCwgcG9zaXRpb25MYXN0QmxhbmspLFxuICAgICAgICAgICAgICAgIHdpZHRoIC8gMixcbiAgICAgICAgICAgICAgICBwb3NpdGlvbkhDb21tZW50XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHBvc2l0aW9uRmlyc3RDdXRDaGFyICs9IHBvc2l0aW9uTGFzdEJsYW5rO1xuICAgICAgICAgICAgICAvLyBHbyB0byBuZXh0IGxpbmUgZm9yIGluc2VydGlvblxuICAgICAgICAgICAgICBwb3NpdGlvbkhDb21tZW50ICs9IDIwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gRG9uJ3QgY3V0IGxhc3QgcGFydFxuICAgICAgICAgICAgICBuZXdDb250ZXh0LmZpbGxUZXh0KFxuICAgICAgICAgICAgICAgIGNvbW1lbnQuc3Vic3RyKHBvc2l0aW9uRmlyc3RDdXRDaGFyKSxcbiAgICAgICAgICAgICAgICB3aWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgcG9zaXRpb25IQ29tbWVudFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBBZGQgbWFwIHRvIG5ldyBjYW52YXNcbiAgICAgIG5ld0NvbnRleHQuZHJhd0ltYWdlKG9sZENhbnZhcywgMCwgcG9zaXRpb25IQ2FudmFzKTtcblxuICAgICAgLy8gQ2hlY2sgdGhlIGxlZ2VuZFBvc2l0aW9uXG4gICAgICBpZiAobGVnZW5kUG9zaXRpb24gIT09ICdub25lJykge1xuICAgICAgICBpZiAoWyd0b3BsZWZ0JywgJ3RvcHJpZ2h0JywgJ2JvdHRvbWxlZnQnLCAnYm90dG9tcmlnaHQnXS5pbmRleE9mKGxlZ2VuZFBvc2l0aW9uKSA+IC0xKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5hZGRMZWdlbmRUb0ltYWdlKFxuICAgICAgICAgICAgbmV3Q2FudmFzLFxuICAgICAgICAgICAgbWFwLFxuICAgICAgICAgICAgcmVzb2x1dGlvbixcbiAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uLFxuICAgICAgICAgICAgZm9ybWF0XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBsZXQgc3RhdHVzID0gU3ViamVjdFN0YXR1cy5Eb25lO1xuICAgICAgbGV0IGZpbGVOYW1lV2l0aEV4dCA9ICdtYXAuJyArIGZvcm1hdDtcbiAgICAgIGlmIChmb3JtYXQudG9Mb3dlckNhc2UoKSA9PT0gJ3RpZmYnKSB7XG4gICAgICAgIGZpbGVOYW1lV2l0aEV4dCA9ICdtYXAnICsgbWFwLnByb2plY3Rpb24ucmVwbGFjZSgnOicsICdfJykgKyAnLicgKyBmb3JtYXQ7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFNhdmUgdGhlIGNhbnZhcyBhcyBmaWxlXG4gICAgICAgIGlmICghZG9aaXBGaWxlKSB7XG4gICAgICAgICAgdGhpcy5zYXZlQ2FudmFzSW1hZ2VBc0ZpbGUobmV3Q2FudmFzLCBmaWxlTmFtZVdpdGhFeHQsIGZvcm1hdCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZm9ybWF0LnRvTG93ZXJDYXNlKCkgPT09ICd0aWZmJykge1xuICAgICAgICAgIC8vIEFkZCB0aGUgY2FudmFzIHRvIHppcFxuICAgICAgICAgIHRoaXMuZ2VuZXJhdGVDYW52YUZpbGVUb1ppcChuZXdDYW52YXMsIGZpbGVOYW1lV2l0aEV4dCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gQWRkIHRoZSBjYW52YXMgdG8gemlwXG4gICAgICAgICAgdGhpcy5nZW5lcmF0ZUNhbnZhRmlsZVRvWmlwKG5ld0NhbnZhcywgZmlsZU5hbWVXaXRoRXh0KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHN0YXR1cyA9IFN1YmplY3RTdGF0dXMuRXJyb3I7XG4gICAgICB9XG5cbiAgICAgIHN0YXR1cyQubmV4dChzdGF0dXMpO1xuXG4gICAgICBpZiAoZm9ybWF0LnRvTG93ZXJDYXNlKCkgPT09ICd0aWZmJykge1xuICAgICAgICBjb25zdCB0ZndGaWxlTmFtZVdpdGhFeHQgPSBmaWxlTmFtZVdpdGhFeHQuc3Vic3RyaW5nKDAsIGZpbGVOYW1lV2l0aEV4dC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJy50aWZmJykpICsgJy50ZncnO1xuICAgICAgICBjb25zdCB0aXdDb250ZW50ID0gdGhpcy5nZXRXb3JsZEZpbGVJbmZvcm1hdGlvbihtYXApO1xuICAgICAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW3Rpd0NvbnRlbnRdLCB7XG4gICAgICAgICAgdHlwZTogJ3RleHQvcGxhaW47Y2hhcnNldD11dGYtOCdcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghZG9aaXBGaWxlKSB7XG4gICAgICAgICAgLy8gc2F2ZUFzIGF1dG9tYXRpY2x5IHJlcGxhY2UgJzonIGZvciAnXydcbiAgICAgICAgICBzYXZlQXMoYmxvYiwgdGZ3RmlsZU5hbWVXaXRoRXh0KTtcbiAgICAgICAgICB0aGlzLnNhdmVGaWxlUHJvY2Vzc2luZygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEFkZCB0aGUgY2FudmFzIHRvIHppcFxuICAgICAgICAgIHRoaXMuYWRkRmlsZVRvWmlwKHRmd0ZpbGVOYW1lV2l0aEV4dCxibG9iKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIG1hcC5vbC5yZW5kZXJTeW5jKCk7XG5cbiAgICByZXR1cm4gc3RhdHVzJDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW5kIEFkZCBMZWdlbmQgdG8gdGhlIG1hcCBjYW52YXNcbiAgICogQHBhcmFtICBjYW52YXMgQ2FudmFzIG9mIHRoZSBtYXBcbiAgICogQHBhcmFtICBtYXAgTWFwIG9mIHRoZSBhcHBcbiAgICogQHBhcmFtICByZXNvbHV0aW9uIFJlc29sdXRpb24gb2YgbWFwXG4gICAqIEBwYXJhbSAgbGVnZW5kUG9zaXRpb24gTGVnZW5kIHBvc2l0aW9uXG4gICAqIEBwYXJhbSAgZm9ybWF0IEltYWdlIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBhZGRMZWdlbmRUb0ltYWdlKFxuICAgICAgY2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCxcbiAgICAgIG1hcDogSWdvTWFwLFxuICAgICAgcmVzb2x1dGlvbjogbnVtYmVyLFxuICAgICAgbGVnZW5kUG9zaXRpb246IHN0cmluZyxcbiAgICAgIGZvcm1hdDogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IGZpbGVOYW1lV2l0aEV4dCA9ICdtYXAuJyArIGZvcm1hdDtcbiAgICBjb25zdCBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICAvLyBHZXQgaHRtbCBjb2RlIGZvciB0aGUgbGVnZW5kXG4gICAgY29uc3QgaHRtbCA9IGF3YWl0IHRoaXMuZ2V0TGF5ZXJzTGVnZW5kSHRtbChcbiAgICAgIG1hcCxcbiAgICAgIGNhbnZhcy53aWR0aCxcbiAgICAgIHJlc29sdXRpb25cbiAgICApLnRvUHJvbWlzZSgpO1xuICAgIC8vIElmIG5vIGxlZ2VuZCwgc2F2ZSB0aGUgbWFwIGRpcmVjdGx5XG4gICAgaWYgKGh0bWwgPT09ICcnKSB7XG4gICAgICBhd2FpdCB0aGlzLnNhdmVDYW52YXNJbWFnZUFzRmlsZShjYW52YXMsIGZpbGVOYW1lV2l0aEV4dCwgZm9ybWF0KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICAvLyBDcmVhdGUgZGl2IHRvIGNvbnRhaW4gaHRtbCBjb2RlIGZvciBsZWdlbmRcbiAgICBjb25zdCBkaXYgPSB3aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBkaXYuc3R5bGUudG9wID0gJzAnO1xuICAgIC8vIEFkZCBodG1sIGNvZGUgdG8gY29udmVydCBpbiB0aGUgbmV3IHdpbmRvd1xuICAgIHdpbmRvdy5kb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgZGl2LmlubmVySFRNTCA9IGh0bWw7XG4gICAgYXdhaXQgdGhpcy50aW1lb3V0KDEpO1xuICAgIGNvbnN0IGNhbnZhc0xlZ2VuZCA9IGF3YWl0IGh0bWwyY2FudmFzKGRpdiwgeyB1c2VDT1JTOiB0cnVlIH0pLmNhdGNoKChlKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICB9KTtcblxuICAgIGlmIChjYW52YXNMZWdlbmQpIHtcbiAgICAgIGNvbnN0IGNhbnZhc0hlaWdodCA9IGNhbnZhcy5oZWlnaHQ7XG4gICAgICBjb25zdCBjYW52YXNXaWR0aCA9IGNhbnZhcy53aWR0aDtcbiAgICAgIGNvbnN0IGxlZ2VuZEhlaWdodCA9IGNhbnZhc0xlZ2VuZC5oZWlnaHQ7XG4gICAgICBjb25zdCBsZWdlbmRXaWR0aCA9IGNhbnZhc0xlZ2VuZC53aWR0aDtcbiAgICAgIC8vIE1vdmUgdGhlIGxlZ2VuZCB0byB0aGUgY29ycmVjdCBwb3NpdGlvbiBvbiB0aGUgcGFnZVxuICAgICAgY29uc3Qgb2Zmc2V0ID0gY2FudmFzSGVpZ2h0ICogMC4wMTtcbiAgICAgIGxldCBsZWdlbmRYOiBudW1iZXI7XG4gICAgICBsZXQgbGVnZW5kWTogbnVtYmVyO1xuXG4gICAgICBpZiAobGVnZW5kUG9zaXRpb24gPT09ICdib3R0b21yaWdodCcpIHtcbiAgICAgICAgbGVnZW5kWCA9IGNhbnZhc1dpZHRoIC0gbGVnZW5kV2lkdGggLSBvZmZzZXQ7XG4gICAgICAgIGxlZ2VuZFkgPSBjYW52YXNIZWlnaHQgLSBsZWdlbmRIZWlnaHQgLSBvZmZzZXQ7XG4gICAgICB9IGVsc2UgaWYgKGxlZ2VuZFBvc2l0aW9uID09PSAndG9wcmlnaHQnKSB7XG4gICAgICAgIGxlZ2VuZFggPSBjYW52YXNXaWR0aCAtIGxlZ2VuZFdpZHRoIC0gb2Zmc2V0O1xuICAgICAgICBsZWdlbmRZID0gb2Zmc2V0O1xuICAgICAgfSBlbHNlIGlmIChsZWdlbmRQb3NpdGlvbiA9PT0gJ2JvdHRvbWxlZnQnKSB7XG4gICAgICAgIGxlZ2VuZFggPSBvZmZzZXQ7XG4gICAgICAgIGxlZ2VuZFkgPSBjYW52YXNIZWlnaHQgLSBsZWdlbmRIZWlnaHQgLSBvZmZzZXQ7XG4gICAgICB9IGVsc2UgaWYgKGxlZ2VuZFBvc2l0aW9uID09PSAndG9wbGVmdCcpIHtcbiAgICAgICAgbGVnZW5kWCA9IG9mZnNldDtcbiAgICAgICAgbGVnZW5kWSA9IG9mZnNldDtcbiAgICAgIH1cblxuICAgICAgY29udGV4dC5kcmF3SW1hZ2UoY2FudmFzTGVnZW5kLCBsZWdlbmRYLCBsZWdlbmRZLCBsZWdlbmRXaWR0aCwgbGVnZW5kSGVpZ2h0KTtcbiAgICAgIGNvbnRleHQuc3Ryb2tlUmVjdChsZWdlbmRYLCBsZWdlbmRZLCBsZWdlbmRXaWR0aCwgbGVnZW5kSGVpZ2h0KTtcbiAgICAgIGRpdi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRpdik7IC8vIHJlbW92ZSB0ZW1wIGRpdiAoSUUgc3R5bGUpXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbmRlck1hcChtYXAsIHNpemUsIGV4dGVudCkge1xuICAgIG1hcC5vbC51cGRhdGVTaXplKCk7XG4gICAgbWFwLm9sLnJlbmRlclN5bmMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlIGRvY3VtZW50XG4gICAqIEBwYXJhbSAgZG9jIC0gRG9jdW1lbnQgdG8gc2F2ZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHNhdmVEb2MoZG9jOiBqc1BERikge1xuICAgIGF3YWl0IGRvYy5zYXZlKCdtYXBfZ2VvcmVmLnBkZicsIHsgcmV0dXJuUHJvbWlzZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGJlc3QgSW1hZ2Ugc2l6ZSB0byBmaXQgaW4gcGRmXG4gICAqIEBwYXJhbSBkb2MgLSBQZGYgRG9jdW1lbnRcbiAgICogQHBhcmFtIGNhbnZhcyAtIENhbnZhcyBvZiBpbWFnZVxuICAgKiBAcGFyYW0gbWFyZ2lucyAtIFBhZ2UgbWFyZ2luc1xuICAgKi9cbiAgcHJpdmF0ZSBnZXRJbWFnZVNpemVUb0ZpdFBkZihkb2MsIGNhbnZhcywgbWFyZ2lucykge1xuICAgIC8vIERlZmluZSB2YXJpYWJsZSB0byBjYWxjdWxhdGUgYmVzdCBzaXplIHRvIGZpdCBpbiBvbmUgcGFnZVxuICAgIGNvbnN0IHBhZ2VIZWlnaHQgPSBkb2MuaW50ZXJuYWwucGFnZVNpemUuZ2V0SGVpZ2h0KCkgLSAobWFyZ2luc1swXSArIG1hcmdpbnNbMl0pO1xuICAgIGNvbnN0IHBhZ2VXaWR0aCA9IGRvYy5pbnRlcm5hbC5wYWdlU2l6ZS5nZXRXaWR0aCgpIC0gKG1hcmdpbnNbMV0gKyBtYXJnaW5zWzNdKTtcbiAgICBjb25zdCBjYW5IZWlnaHQgPSB0aGlzLnBkZl91bml0czJwb2ludHMoY2FudmFzLmhlaWdodCwgJ21tJyk7XG4gICAgY29uc3QgY2FuV2lkdGggPSB0aGlzLnBkZl91bml0czJwb2ludHMoY2FudmFzLndpZHRoLCAnbW0nKTtcblxuICAgIGNvbnN0IGhlaWdodFJhdGlvID0gY2FuSGVpZ2h0IC8gcGFnZUhlaWdodDtcbiAgICBjb25zdCB3aWR0aFJhdGlvID0gY2FuV2lkdGggLyBwYWdlV2lkdGg7XG4gICAgY29uc3QgbWF4UmF0aW8gPSBoZWlnaHRSYXRpbyA+IHdpZHRoUmF0aW8gPyBoZWlnaHRSYXRpbyA6IHdpZHRoUmF0aW87XG4gICAgY29uc3QgaW1nSGVpZ2ggPSBtYXhSYXRpbyA+IDEgPyBjYW5IZWlnaHQgLyBtYXhSYXRpbyA6IGNhbkhlaWdodDtcbiAgICBjb25zdCBpbWdXaWR0aCA9IG1heFJhdGlvID4gMSA/IGNhbldpZHRoIC8gbWF4UmF0aW8gOiBjYW5XaWR0aDtcblxuICAgIHJldHVybiBbaW1nV2lkdGgsIGltZ0hlaWdoXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYSB3b3JsZCBmaWxlIGluZm9ybWF0aW9uIGZvciB0aWZmXG4gICAqIEBwYXJhbSAgbWFwIC0gTWFwIG9mIHRoZSBhcHBcbiAgICovXG4gIHByaXZhdGUgZ2V0V29ybGRGaWxlSW5mb3JtYXRpb24obWFwKSB7XG4gICAgY29uc3QgY3VycmVudFJlc29sdXRpb24gPSBtYXAudmlld0NvbnRyb2xsZXIuZ2V0UmVzb2x1dGlvbigpO1xuICAgIGNvbnN0IGN1cnJlbnRFeHRlbnQgPSBtYXAudmlld0NvbnRyb2xsZXIuZ2V0RXh0ZW50KCk7IC8vIFJldHVybiBbbWlueCwgbWlueSwgbWF4eCwgbWF4eV1cbiAgICByZXR1cm4gW1xuICAgICAgY3VycmVudFJlc29sdXRpb24sXG4gICAgICAwLFxuICAgICAgMCxcbiAgICAgIC1jdXJyZW50UmVzb2x1dGlvbixcbiAgICAgIGN1cnJlbnRFeHRlbnRbMF0gKyBjdXJyZW50UmVzb2x1dGlvbiAvIDAuNSxcbiAgICAgIGN1cnJlbnRFeHRlbnRbM10gLSBjdXJyZW50UmVzb2x1dGlvbiAvIDAuNVxuICAgIF0uam9pbignXFxuJyk7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSBjYW52YXMgaW1hZ2UgYXMgZmlsZVxuICAgKiBAcGFyYW0gY2FudmFzIC0gQ2FudmFzIHRvIHNhdmVcbiAgICogQHBhcmFtIG5hbWUgLSBOYW1lIG9mIHRoZSBmaWxlXG4gICAqIEBwYXJhbSBmb3JtYXQgLSBmaWxlIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSBzYXZlQ2FudmFzSW1hZ2VBc0ZpbGUoY2FudmFzLCBuYW1lV2l0aEV4dCwgZm9ybWF0KSB7XG4gICAgY29uc3QgYmxvYkZvcm1hdCA9ICdpbWFnZS8nICsgZm9ybWF0O1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNhbnZhcy50b0RhdGFVUkwoKTsgLy8gSnVzdCB0byBtYWtlIHRoZSBjYXRjaCB0cmlnZ2VyIHdpaHRvdXQgdG9CbG9iIEVycm9yIHRocm93IG5vdCBjYXRjaGVkXG4gICAgICAvLyBJZiBuYXZpZ2F0b3IgaXMgSW50ZXJuZXQgRXhwbG9yZXJcbiAgICAgIGlmIChuYXZpZ2F0b3IubXNTYXZlQmxvYikge1xuICAgICAgICBuYXZpZ2F0b3IubXNTYXZlQmxvYihjYW52YXMubXNUb0Jsb2IoKSwgbmFtZVdpdGhFeHQpO1xuICAgICAgICB0aGlzLnNhdmVGaWxlUHJvY2Vzc2luZygpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FudmFzLnRvQmxvYigoYmxvYikgPT4ge1xuICAgICAgICAgIC8vIGRvd25sb2FkIGltYWdlXG4gICAgICAgICAgc2F2ZUFzKGJsb2IsIG5hbWVXaXRoRXh0KTtcbiAgICAgICAgICB0aGF0LnNhdmVGaWxlUHJvY2Vzc2luZygpO1xuICAgICAgICB9LCBibG9iRm9ybWF0KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMubWVzc2FnZVNlcnZpY2UuZXJyb3IoXG4gICAgICAgIHRoaXMubGFuZ3VhZ2VTZXJ2aWNlLnRyYW5zbGF0ZS5pbnN0YW50KFxuICAgICAgICAgICdpZ28uZ2VvLnByaW50Rm9ybS5jb3JzRXJyb3JNZXNzYWdlQm9keSdcbiAgICAgICAgKSxcbiAgICAgICAgdGhpcy5sYW5ndWFnZVNlcnZpY2UudHJhbnNsYXRlLmluc3RhbnQoXG4gICAgICAgICAgJ2lnby5nZW8ucHJpbnRGb3JtLmNvcnNFcnJvck1lc3NhZ2VIZWFkZXInXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBmaWxlIHRvIGEgemlwXG4gICAqIEBwYXJhbSBjYW52YXMgLSBGaWxlIHRvIGFkZCB0byB0aGUgemlwXG4gICAqIEBwYXJhbSAgbmFtZSAtTmFtZSBvZiB0aGUgZmlsZW92ZXJ2aWV3XG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlQ2FudmFGaWxlVG9aaXAoY2FudmFzLCBuYW1lKSB7XG4gICAgY29uc3QgYmxvYkZvcm1hdCA9ICdpbWFnZS8nICsgJ2pwZWcnO1xuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgIGlmIChcbiAgICAgICF0aGlzLmhhc093blByb3BlcnR5KCd6aXBGaWxlJykgfHxcbiAgICAgIHR5cGVvZiB0aGlzLnppcEZpbGUgPT09ICd1bmRlZmluZWQnXG4gICAgKSB7XG4gICAgICB0aGlzLnppcEZpbGUgPSBuZXcgSlNaaXAoKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY2FudmFzLnRvRGF0YVVSTCgpOyAvLyBKdXN0IHRvIG1ha2UgdGhlIGNhdGNoIHRyaWdnZXIgd2lodG91dCB0b0Jsb2IgRXJyb3IgdGhyb3cgbm90IGNhdGNoZWRcbiAgICAgIGlmIChuYXZpZ2F0b3IubXNTYXZlQmxvYikge1xuICAgICAgICB0aGlzLmFkZEZpbGVUb1ppcChuYW1lLCBjYW52YXMubXNUb0Jsb2IoKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYW52YXMudG9CbG9iKChibG9iKSA9PiB7XG4gICAgICAgICAgdGhhdC5hZGRGaWxlVG9aaXAobmFtZSwgYmxvYik7XG4gICAgICAgIH0sIGJsb2JGb3JtYXQpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5tZXNzYWdlU2VydmljZS5lcnJvcihcbiAgICAgICAgdGhpcy5sYW5ndWFnZVNlcnZpY2UudHJhbnNsYXRlLmluc3RhbnQoXG4gICAgICAgICAgJ2lnby5nZW8ucHJpbnRGb3JtLmNvcnNFcnJvck1lc3NhZ2VCb2R5J1xuICAgICAgICApLFxuICAgICAgICB0aGlzLmxhbmd1YWdlU2VydmljZS50cmFuc2xhdGUuaW5zdGFudChcbiAgICAgICAgICAnaWdvLmdlby5wcmludEZvcm0uY29yc0Vycm9yTWVzc2FnZUhlYWRlcidcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIGZpbGUgdG8gemlwLCBpZiBhbGwgZmlsZSBhcmUgemlwcGVkLCBkb3dubG9hZFxuICAgKiBAcGFyYW0gbmFtZSAtIE5hbWUgb2YgdGhlIGZpbGVzXG4gICAqIEBwYXJhbSBibG9iIC0gQ29udGFpbiBvZiBmaWxlXG4gICAqL1xuICBwcml2YXRlIGFkZEZpbGVUb1ppcChuYW1lLCBibG9iKSB7XG4gICAgLy8gYWRkIGZpbGUgdG8gemlwXG4gICAgdGhpcy56aXBGaWxlLmZpbGUobmFtZSwgYmxvYik7XG4gICAgdGhpcy5uYkZpbGVUb1Byb2Nlc3MtLTtcblxuICAgIC8vIElmIGFsbCBmaWxlcyBhcmUgcHJvY2Nlc3NlZFxuICAgIGlmICh0aGlzLm5iRmlsZVRvUHJvY2VzcyA9PT0gMCkge1xuICAgICAgLy8gRG93bmxvYWQgemlwIGZpbGVcbiAgICAgIHRoaXMuZ2V0WmlwRmlsZSgpO1xuICAgICAgLy8gU3RvcCBsb2FkaW5nXG4gICAgICB0aGlzLmFjdGl2aXR5U2VydmljZS51bnJlZ2lzdGVyKHRoaXMuYWN0aXZpdHlJZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzYXZlRmlsZVByb2Nlc3NpbmcoKSB7XG4gICAgdGhpcy5uYkZpbGVUb1Byb2Nlc3MtLTtcblxuICAgIC8vIElmIGFsbCBmaWxlcyBhcmUgcHJvY2Nlc3NlZFxuICAgIGlmICh0aGlzLm5iRmlsZVRvUHJvY2VzcyA9PT0gMCkge1xuICAgICAgLy8gU3RvcCBsb2FkaW5nXG4gICAgICB0aGlzLmFjdGl2aXR5U2VydmljZS51bnJlZ2lzdGVyKHRoaXMuYWN0aXZpdHlJZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgemlwcGVkIGZpbGVcbiAgICogQHJldHVybiBSZXR1biBhIHppcCBmaWxlXG4gICAqL1xuICBwcml2YXRlIGdldFppcEZpbGUoKSB7XG4gICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgdGhpcy56aXBGaWxlLmdlbmVyYXRlQXN5bmMoeyB0eXBlOiAnYmxvYicgfSkudGhlbigoYmxvYikgPT4ge1xuICAgICAgLy8gMSkgZ2VuZXJhdGUgdGhlIHppcCBmaWxlXG4gICAgICBzYXZlQXMoYmxvYiwgJ21hcC56aXAnKTtcbiAgICAgIGRlbGV0ZSB0aGF0LnppcEZpbGU7XG4gICAgfSk7XG4gIH1cblxuXG4gIHByaXZhdGUgcGRmX3VuaXRzMnBvaW50cyhuLCB1bml0KTogbnVtYmVyIHtcbiAgICBsZXQgayA9IDE7XG5cbiAgICAvLyB0aGlzIGNvZGUgaXMgYm9ycm93ZWQgZnJvbSBqc1BERlxuICAgIC8vICBhcyBpdCBkb2VzIG5vdCBleHBvc2UgYSBwdWJsaWMgQVBJXG4gICAgLy8gIGZvciBjb252ZXJ0aW5nIHVuaXRzIHRvIHBvaW50cy5cbiAgICBzd2l0Y2ggKHVuaXQpIHtcbiAgICAgICAgY2FzZSAncHQnOlxuICAgICAgICAgICAgayA9IDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgayA9IDcyIC8gMjUuNDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdjbSc6XG4gICAgICAgICAgICBrID0gNzIgLyAyLjU0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2luJzpcbiAgICAgICAgICAgIGsgPSA3MjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdweCc6XG4gICAgICAgICAgICBrID0gOTYgLyA3MjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdwYyc6XG4gICAgICAgICAgICBrID0gMTI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZW0nOlxuICAgICAgICAgICAgayA9IDEyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2V4JzpcbiAgICAgICAgICAgIGsgPSA2O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgdW5pdDogJyArIHVuaXQpO1xuICAgIH1cblxuICAgIHJldHVybiBuICogaztcbiAgfVxuXG59XG4iXX0=