@researchdatabox/redbox-core 0.0.1-beta.10213 → 0.0.1-beta.10760

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 (287) hide show
  1. package/dist/CoreController.d.ts +8 -0
  2. package/dist/CoreController.d.ts.map +1 -1
  3. package/dist/CoreController.js +87 -52
  4. package/dist/RecordsService.d.ts +2 -0
  5. package/dist/RecordsService.d.ts.map +1 -1
  6. package/dist/SearchService.d.ts +1 -1
  7. package/dist/SearchService.d.ts.map +1 -1
  8. package/dist/StorageService.d.ts +2 -0
  9. package/dist/StorageService.d.ts.map +1 -1
  10. package/dist/api-routes/groups/branding.d.ts +1 -0
  11. package/dist/api-routes/groups/branding.d.ts.map +1 -1
  12. package/dist/api-routes/groups/branding.js +19 -2
  13. package/dist/api-routes/groups/export.js +2 -2
  14. package/dist/api-routes/groups/figshare-crosswalks.d.ts +11 -0
  15. package/dist/api-routes/groups/figshare-crosswalks.d.ts.map +1 -0
  16. package/dist/api-routes/groups/figshare-crosswalks.js +171 -0
  17. package/dist/api-routes/groups/figshare-vocabulary.d.ts +12 -0
  18. package/dist/api-routes/groups/figshare-vocabulary.d.ts.map +1 -0
  19. package/dist/api-routes/groups/figshare-vocabulary.js +248 -0
  20. package/dist/api-routes/groups/search.js +4 -4
  21. package/dist/api-routes/groups/users.js +3 -3
  22. package/dist/api-routes/index.d.ts +2 -0
  23. package/dist/api-routes/index.d.ts.map +1 -1
  24. package/dist/api-routes/index.js +3 -1
  25. package/dist/api-routes/route-registry.d.ts.map +1 -1
  26. package/dist/api-routes/route-registry.js +5 -1
  27. package/dist/api-routes/schemas/common.d.ts +1 -0
  28. package/dist/api-routes/schemas/common.d.ts.map +1 -1
  29. package/dist/api-routes/schemas/common.js +3 -2
  30. package/dist/bootstrap.d.ts.map +1 -1
  31. package/dist/bootstrap.js +5 -1
  32. package/dist/config/agendaQueue.config.d.ts +3 -0
  33. package/dist/config/agendaQueue.config.d.ts.map +1 -1
  34. package/dist/config/agendaQueue.config.js +13 -1
  35. package/dist/config/auth.config.d.ts.map +1 -1
  36. package/dist/config/auth.config.js +4 -1
  37. package/dist/config/brandingConfigurationDefaults.config.d.ts +1 -1
  38. package/dist/config/brandingConfigurationDefaults.config.d.ts.map +1 -1
  39. package/dist/config/brandingConfigurationDefaults.config.js +22 -230
  40. package/dist/config/dashboardtype.config.d.ts +7 -0
  41. package/dist/config/dashboardtype.config.d.ts.map +1 -1
  42. package/dist/config/dashboardtype.config.js +9 -89
  43. package/dist/config/dashboardview.config.d.ts +7 -0
  44. package/dist/config/dashboardview.config.d.ts.map +1 -1
  45. package/dist/config/dashboardview.config.js +9 -134
  46. package/dist/config/http.config.d.ts +2 -0
  47. package/dist/config/http.config.d.ts.map +1 -1
  48. package/dist/config/http.config.js +47 -1
  49. package/dist/config/jsonld.config.d.ts.map +1 -1
  50. package/dist/config/jsonld.config.js +2 -21
  51. package/dist/config/record.config.d.ts.map +1 -1
  52. package/dist/config/record.config.js +2 -9
  53. package/dist/config/recordtype.config.d.ts +8 -0
  54. package/dist/config/recordtype.config.d.ts.map +1 -1
  55. package/dist/config/recordtype.config.js +10 -660
  56. package/dist/config/reusableContributorFormDefinitions.config.d.ts.map +1 -1
  57. package/dist/config/reusableContributorFormDefinitions.config.js +1 -2
  58. package/dist/config/reusableViewFormDefinitions.config.d.ts.map +1 -1
  59. package/dist/config/reusableViewFormDefinitions.config.js +12 -1
  60. package/dist/config/routes.config.d.ts.map +1 -1
  61. package/dist/config/routes.config.js +12 -3
  62. package/dist/config/solr.config.d.ts +1 -0
  63. package/dist/config/solr.config.d.ts.map +1 -1
  64. package/dist/config/solr.config.js +3 -2
  65. package/dist/config/static_assets.config.d.ts +2 -0
  66. package/dist/config/static_assets.config.d.ts.map +1 -1
  67. package/dist/config/static_assets.config.js +4 -2
  68. package/dist/config/storage.config.d.ts.map +1 -1
  69. package/dist/config/storage.config.js +7 -1
  70. package/dist/config/views.config.d.ts.map +1 -1
  71. package/dist/config/views.config.js +2 -6
  72. package/dist/config/vocab.config.d.ts +4 -0
  73. package/dist/config/vocab.config.d.ts.map +1 -1
  74. package/dist/config/vocab.config.js +1 -1
  75. package/dist/config/workflow.config.d.ts +7 -0
  76. package/dist/config/workflow.config.d.ts.map +1 -1
  77. package/dist/config/workflow.config.js +9 -194
  78. package/dist/config/workspacetype.config.d.ts +7 -0
  79. package/dist/config/workspacetype.config.d.ts.map +1 -1
  80. package/dist/config/workspacetype.config.js +9 -10
  81. package/dist/configmodels/DoiPublishing.d.ts +1 -1
  82. package/dist/configmodels/DoiPublishing.d.ts.map +1 -1
  83. package/dist/configmodels/FigsharePublishing.d.ts +746 -217
  84. package/dist/configmodels/FigsharePublishing.d.ts.map +1 -1
  85. package/dist/configmodels/FigsharePublishing.js +181 -190
  86. package/dist/constants/export.d.ts +2 -0
  87. package/dist/constants/export.d.ts.map +1 -0
  88. package/dist/constants/export.js +8 -0
  89. package/dist/controllers/AsynchController.d.ts +4 -1
  90. package/dist/controllers/AsynchController.d.ts.map +1 -1
  91. package/dist/controllers/AsynchController.js +118 -9
  92. package/dist/controllers/BrandingAppController.d.ts +2 -0
  93. package/dist/controllers/BrandingAppController.d.ts.map +1 -1
  94. package/dist/controllers/BrandingAppController.js +40 -2
  95. package/dist/controllers/BrandingController.d.ts +8 -0
  96. package/dist/controllers/BrandingController.d.ts.map +1 -1
  97. package/dist/controllers/BrandingController.js +45 -1
  98. package/dist/controllers/ExportController.d.ts.map +1 -1
  99. package/dist/controllers/ExportController.js +4 -3
  100. package/dist/controllers/RecordController.d.ts +1 -1
  101. package/dist/controllers/RecordController.d.ts.map +1 -1
  102. package/dist/controllers/RecordController.js +47 -21
  103. package/dist/controllers/UserController.d.ts.map +1 -1
  104. package/dist/controllers/UserController.js +3 -2
  105. package/dist/controllers/VocabularyController.js +4 -4
  106. package/dist/controllers/index.d.ts.map +1 -1
  107. package/dist/controllers/index.js +7 -1
  108. package/dist/controllers/webservice/BrandingController.d.ts +1 -0
  109. package/dist/controllers/webservice/BrandingController.d.ts.map +1 -1
  110. package/dist/controllers/webservice/BrandingController.js +69 -10
  111. package/dist/controllers/webservice/ExportController.d.ts.map +1 -1
  112. package/dist/controllers/webservice/ExportController.js +4 -3
  113. package/dist/controllers/webservice/FigshareCrosswalkController.d.ts +20 -0
  114. package/dist/controllers/webservice/FigshareCrosswalkController.d.ts.map +1 -0
  115. package/dist/controllers/webservice/FigshareCrosswalkController.js +184 -0
  116. package/dist/controllers/webservice/FigshareVocabularyController.d.ts +21 -0
  117. package/dist/controllers/webservice/FigshareVocabularyController.d.ts.map +1 -0
  118. package/dist/controllers/webservice/FigshareVocabularyController.js +223 -0
  119. package/dist/controllers/webservice/RecordController.d.ts +2 -0
  120. package/dist/controllers/webservice/RecordController.d.ts.map +1 -1
  121. package/dist/controllers/webservice/RecordController.js +60 -12
  122. package/dist/controllers/webservice/UserManagementController.d.ts +5 -3
  123. package/dist/controllers/webservice/UserManagementController.d.ts.map +1 -1
  124. package/dist/controllers/webservice/UserManagementController.js +140 -9
  125. package/dist/controllers/webservice/figshare-vocabulary-errors.d.ts +14 -0
  126. package/dist/controllers/webservice/figshare-vocabulary-errors.d.ts.map +1 -0
  127. package/dist/controllers/webservice/figshare-vocabulary-errors.js +39 -0
  128. package/dist/form-config/index.d.ts +7 -0
  129. package/dist/form-config/index.d.ts.map +1 -1
  130. package/dist/form-config/index.js +8 -5
  131. package/dist/hooks/hookDiscovery.d.ts +20 -0
  132. package/dist/hooks/hookDiscovery.d.ts.map +1 -0
  133. package/dist/hooks/hookDiscovery.js +186 -0
  134. package/dist/hooks/hookResources.d.ts +23 -0
  135. package/dist/hooks/hookResources.d.ts.map +1 -0
  136. package/dist/hooks/hookResources.js +136 -0
  137. package/dist/hooks/index.d.ts +4 -0
  138. package/dist/hooks/index.d.ts.map +1 -1
  139. package/dist/hooks/index.js +14 -2
  140. package/dist/index.d.ts +4 -0
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +14 -2
  143. package/dist/loader/index.d.ts.map +1 -1
  144. package/dist/loader/index.js +21 -62
  145. package/dist/model/storage/BrandingModel.d.ts +2 -0
  146. package/dist/model/storage/BrandingModel.d.ts.map +1 -1
  147. package/dist/model/storage/BrandingModel.js +3 -1
  148. package/dist/services/AgendaQueueService.d.ts.map +1 -1
  149. package/dist/services/AgendaQueueService.js +6 -2
  150. package/dist/services/BrandingLogoService.d.ts +20 -1
  151. package/dist/services/BrandingLogoService.d.ts.map +1 -1
  152. package/dist/services/BrandingLogoService.js +51 -5
  153. package/dist/services/BrandingThemeTokens.d.ts.map +1 -1
  154. package/dist/services/BrandingThemeTokens.js +2 -1
  155. package/dist/services/EmailService.d.ts +2 -8
  156. package/dist/services/EmailService.d.ts.map +1 -1
  157. package/dist/services/EmailService.js +8 -26
  158. package/dist/services/FigshareService.d.ts.map +1 -1
  159. package/dist/services/FigshareService.js +5 -4
  160. package/dist/services/FigshareVocabularyService.d.ts +442 -0
  161. package/dist/services/FigshareVocabularyService.d.ts.map +1 -0
  162. package/dist/services/FigshareVocabularyService.js +1802 -0
  163. package/dist/services/FormVocabularyService.d.ts.map +1 -1
  164. package/dist/services/FormVocabularyService.js +28 -7
  165. package/dist/services/I18nEntriesService.d.ts.map +1 -1
  166. package/dist/services/I18nEntriesService.js +21 -2
  167. package/dist/services/IntegrationAuditService.js +4 -4
  168. package/dist/services/NamedQueryService.d.ts.map +1 -1
  169. package/dist/services/NamedQueryService.js +3 -16
  170. package/dist/services/RDMPService.d.ts.map +1 -1
  171. package/dist/services/RDMPService.js +9 -1
  172. package/dist/services/RecordsService.d.ts +4 -0
  173. package/dist/services/RecordsService.d.ts.map +1 -1
  174. package/dist/services/RecordsService.js +62 -45
  175. package/dist/services/ReportsService.d.ts +0 -5
  176. package/dist/services/ReportsService.d.ts.map +1 -1
  177. package/dist/services/ReportsService.js +22 -31
  178. package/dist/services/SolrSearchService.d.ts +10 -2
  179. package/dist/services/SolrSearchService.d.ts.map +1 -1
  180. package/dist/services/SolrSearchService.js +110 -52
  181. package/dist/services/StandardDatastreamService.d.ts +7 -0
  182. package/dist/services/StandardDatastreamService.d.ts.map +1 -1
  183. package/dist/services/StandardDatastreamService.js +127 -27
  184. package/dist/services/TemplateService.d.ts +0 -14
  185. package/dist/services/TemplateService.d.ts.map +1 -1
  186. package/dist/services/TemplateService.js +4 -45
  187. package/dist/services/UsersService.d.ts.map +1 -1
  188. package/dist/services/UsersService.js +19 -16
  189. package/dist/services/ViewUtilsService.d.ts +5 -1
  190. package/dist/services/ViewUtilsService.d.ts.map +1 -1
  191. package/dist/services/ViewUtilsService.js +38 -46
  192. package/dist/services/VocabularyService.d.ts +11 -2
  193. package/dist/services/VocabularyService.d.ts.map +1 -1
  194. package/dist/services/VocabularyService.js +46 -20
  195. package/dist/services/doi-v2/bindings.d.ts.map +1 -1
  196. package/dist/services/doi-v2/bindings.js +2 -11
  197. package/dist/services/figshare-v2/assets.d.ts +2 -1
  198. package/dist/services/figshare-v2/assets.d.ts.map +1 -1
  199. package/dist/services/figshare-v2/assets.js +144 -89
  200. package/dist/services/figshare-v2/bindings.d.ts +28 -3
  201. package/dist/services/figshare-v2/bindings.d.ts.map +1 -1
  202. package/dist/services/figshare-v2/bindings.js +75 -17
  203. package/dist/services/figshare-v2/categories.d.ts +142 -0
  204. package/dist/services/figshare-v2/categories.d.ts.map +1 -0
  205. package/dist/services/figshare-v2/categories.js +408 -0
  206. package/dist/services/figshare-v2/config.d.ts +10 -0
  207. package/dist/services/figshare-v2/config.d.ts.map +1 -1
  208. package/dist/services/figshare-v2/config.js +39 -1
  209. package/dist/services/figshare-v2/context.d.ts +18 -1
  210. package/dist/services/figshare-v2/context.d.ts.map +1 -1
  211. package/dist/services/figshare-v2/context.js +34 -2
  212. package/dist/services/figshare-v2/embargo.d.ts.map +1 -1
  213. package/dist/services/figshare-v2/embargo.js +6 -4
  214. package/dist/services/figshare-v2/http.d.ts +3 -1
  215. package/dist/services/figshare-v2/http.d.ts.map +1 -1
  216. package/dist/services/figshare-v2/http.js +26 -4
  217. package/dist/services/figshare-v2/metadata.d.ts.map +1 -1
  218. package/dist/services/figshare-v2/metadata.js +74 -26
  219. package/dist/services/figshare-v2/observability.d.ts +1 -2
  220. package/dist/services/figshare-v2/observability.d.ts.map +1 -1
  221. package/dist/services/figshare-v2/observability.js +7 -47
  222. package/dist/services/figshare-v2/types.d.ts +13 -0
  223. package/dist/services/figshare-v2/types.d.ts.map +1 -1
  224. package/dist/services/figshare-v2/types.js +1 -1
  225. package/dist/services/figshare-v2/vocabulary-errors.d.ts +39 -0
  226. package/dist/services/figshare-v2/vocabulary-errors.d.ts.map +1 -0
  227. package/dist/services/figshare-v2/vocabulary-errors.js +68 -0
  228. package/dist/services/index.d.ts +3 -0
  229. package/dist/services/index.d.ts.map +1 -1
  230. package/dist/services/index.js +8 -3
  231. package/dist/storage/TusStorageManagerDataStore.d.ts.map +1 -1
  232. package/dist/storage/TusStorageManagerDataStore.js +14 -1
  233. package/dist/utilities/ContextVariableUtils.d.ts +3 -1
  234. package/dist/utilities/ContextVariableUtils.d.ts.map +1 -1
  235. package/dist/utilities/ContextVariableUtils.js +25 -7
  236. package/dist/utilities/PromiseUtils.d.ts +9 -0
  237. package/dist/utilities/PromiseUtils.d.ts.map +1 -0
  238. package/dist/utilities/PromiseUtils.js +27 -0
  239. package/dist/utilities/RedactionUtils.d.ts +3 -0
  240. package/dist/utilities/RedactionUtils.d.ts.map +1 -0
  241. package/dist/utilities/RedactionUtils.js +55 -0
  242. package/dist/visitor/client.visitor.d.ts +3 -0
  243. package/dist/visitor/client.visitor.d.ts.map +1 -1
  244. package/dist/visitor/client.visitor.js +102 -17
  245. package/dist/visitor/construct.visitor.d.ts +3 -0
  246. package/dist/visitor/construct.visitor.d.ts.map +1 -1
  247. package/dist/visitor/construct.visitor.js +51 -38
  248. package/dist/visitor/json-type-def.visitor.d.ts +1 -0
  249. package/dist/visitor/json-type-def.visitor.d.ts.map +1 -1
  250. package/dist/visitor/json-type-def.visitor.js +20 -4
  251. package/dist/visitor/migrate-config-v4-v5.visitor.d.ts +6 -3
  252. package/dist/visitor/migrate-config-v4-v5.visitor.d.ts.map +1 -1
  253. package/dist/visitor/migrate-config-v4-v5.visitor.js +94 -44
  254. package/dist/visitor/validator.visitor.d.ts.map +1 -1
  255. package/dist/visitor/validator.visitor.js +1 -1
  256. package/dist/visitor/visitor-helpers.js +2 -2
  257. package/dist/waterline-models/BrandingConfig.d.ts +2 -0
  258. package/dist/waterline-models/BrandingConfig.d.ts.map +1 -1
  259. package/dist/waterline-models/BrandingConfig.js +6 -1
  260. package/dist/waterline-models/FigshareVocabularyCategory.d.ts +38 -0
  261. package/dist/waterline-models/FigshareVocabularyCategory.d.ts.map +1 -0
  262. package/dist/waterline-models/FigshareVocabularyCategory.js +157 -0
  263. package/dist/waterline-models/FigshareVocabularyCrosswalk.d.ts +37 -0
  264. package/dist/waterline-models/FigshareVocabularyCrosswalk.d.ts.map +1 -0
  265. package/dist/waterline-models/FigshareVocabularyCrosswalk.js +153 -0
  266. package/dist/waterline-models/FigshareVocabularyCrosswalkMapping.d.ts +37 -0
  267. package/dist/waterline-models/FigshareVocabularyCrosswalkMapping.d.ts.map +1 -0
  268. package/dist/waterline-models/FigshareVocabularyCrosswalkMapping.js +138 -0
  269. package/dist/waterline-models/FigshareVocabularySource.d.ts +45 -0
  270. package/dist/waterline-models/FigshareVocabularySource.d.ts.map +1 -0
  271. package/dist/waterline-models/FigshareVocabularySource.js +149 -0
  272. package/dist/waterline-models/FigshareVocabularySyncRun.d.ts +70 -0
  273. package/dist/waterline-models/FigshareVocabularySyncRun.d.ts.map +1 -0
  274. package/dist/waterline-models/FigshareVocabularySyncRun.js +237 -0
  275. package/dist/waterline-models/Vocabulary.d.ts +3 -1
  276. package/dist/waterline-models/Vocabulary.d.ts.map +1 -1
  277. package/dist/waterline-models/Vocabulary.js +9 -3
  278. package/dist/waterline-models/index.d.ts +10 -0
  279. package/dist/waterline-models/index.d.ts.map +1 -1
  280. package/dist/waterline-models/index.js +16 -1
  281. package/package.json +19 -19
  282. package/dist/form-config/dataRecord-1.0-draft.d.ts +0 -4
  283. package/dist/form-config/dataRecord-1.0-draft.d.ts.map +0 -1
  284. package/dist/form-config/dataRecord-1.0-draft.js +0 -1042
  285. package/dist/form-config/default-1.0-draft.d.ts +0 -4
  286. package/dist/form-config/default-1.0-draft.d.ts.map +0 -1
  287. package/dist/form-config/default-1.0-draft.js +0 -1156
@@ -0,0 +1,1802 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Services = void 0;
40
+ const CoreService_1 = require("../CoreService");
41
+ const FigshareVocabularySyncRun_1 = require("../waterline-models/FigshareVocabularySyncRun");
42
+ const TransactionUtils_1 = require("../utilities/TransactionUtils");
43
+ const PromiseUtils_1 = require("../utilities/PromiseUtils");
44
+ const fs = __importStar(require("node:fs/promises"));
45
+ const path = __importStar(require("node:path"));
46
+ const lodash_1 = __importDefault(require("lodash"));
47
+ const config_1 = require("./figshare-v2/config");
48
+ const http_1 = require("./figshare-v2/http");
49
+ const categories_1 = require("./figshare-v2/categories");
50
+ const vocabulary_errors_1 = require("./figshare-v2/vocabulary-errors");
51
+ var Services;
52
+ (function (Services) {
53
+ const PREVIEW_TTL_MS = 24 * 60 * 60 * 1000;
54
+ const MAX_MAPPING_BATCH = 2000;
55
+ const MAX_PAGE_SIZE = 200;
56
+ const DEFAULT_BOOTSTRAP_DATA_PATH = 'bootstrap-data';
57
+ const FIGSHARE_IMPORTS_FILE = 'figshare-imports.json';
58
+ const FIGSHARE_IMPORT_TIMEOUT_MS = 120_000;
59
+ const BOOTSTRAP_ACTOR = 'bootstrap-data';
60
+ class FigshareVocabularyService extends CoreService_1.Services.Core.Service {
61
+ _exportedMethods = [
62
+ 'discoverTaxonomies',
63
+ 'createPreview',
64
+ 'getPreview',
65
+ 'applyPreview',
66
+ 'cloneMirror',
67
+ 'listSources',
68
+ 'getSource',
69
+ 'listSourceCategories',
70
+ 'listSyncRuns',
71
+ 'listCrosswalks',
72
+ 'getCrosswalk',
73
+ 'getCrosswalkUsage',
74
+ 'createCrosswalk',
75
+ 'listCrosswalkLocalEntries',
76
+ 'listCrosswalkMappings',
77
+ 'saveMappings',
78
+ 'approveCrosswalk',
79
+ 'deleteCrosswalk',
80
+ 'resolveCategories',
81
+ 'resolveCrosswalkValues',
82
+ 'bootstrapData'
83
+ ];
84
+ // ── Infrastructure helpers ────────────────────────────────────────
85
+ getDatastore() {
86
+ return Vocabulary.getDatastore?.() ?? sails.getDatastore?.() ?? null;
87
+ }
88
+ async runQuery(query, connection) {
89
+ return connection ? query.usingConnection(connection) : query;
90
+ }
91
+ async createOne(query, connection) {
92
+ return this.runQuery(query.fetch(), connection);
93
+ }
94
+ nowIso() {
95
+ return new Date().toISOString();
96
+ }
97
+ resolveBrandName(brandId) {
98
+ const brandingService = typeof BrandingService === 'undefined' ? undefined : BrandingService;
99
+ const brand = brandingService?.getBrandById?.(brandId);
100
+ if (brand?.name != null && String(brand.name).trim() !== '') {
101
+ return String(brand.name);
102
+ }
103
+ return String(brandId);
104
+ }
105
+ buildRunContext(brandId, correlationId) {
106
+ const brandName = this.resolveBrandName(brandId);
107
+ return {
108
+ recordOid: '',
109
+ brandId,
110
+ brandName,
111
+ correlationId,
112
+ triggerSource: 'figshare-vocabulary-admin'
113
+ };
114
+ }
115
+ /**
116
+ * Resolve a Figshare client for catalogue reads. The client is always built from
117
+ * trusted deployment configuration; a request never supplies a base URL or token.
118
+ */
119
+ resolveClient(brandId, scope) {
120
+ const brandName = this.resolveBrandName(brandId);
121
+ const config = (0, config_1.resolveFigshareVocabularyConfig)(brandName);
122
+ if (config == null) {
123
+ throw new vocabulary_errors_1.FigshareTransportError('Figshare is not configured for this brand');
124
+ }
125
+ if (scope === 'account' && String(config.connection.token ?? '').trim() === '' && config.runtime.mode !== 'fixture') {
126
+ throw new vocabulary_errors_1.FigshareTransportError('The Figshare account catalogue requires a configured API token', 401);
127
+ }
128
+ const runContext = this.buildRunContext(brandId, `figshare-vocab-${Date.now()}`);
129
+ return config.runtime.mode === 'fixture'
130
+ ? (0, http_1.makeFixtureClient)(config)
131
+ : (0, http_1.makeLiveClient)(config, runContext);
132
+ }
133
+ async fetchCatalogue(brandId, scope) {
134
+ const client = this.resolveClient(brandId, scope);
135
+ try {
136
+ return scope === 'account' ? await client.listAccountCategories() : await client.listPublicCategories();
137
+ }
138
+ catch (error) {
139
+ if (error instanceof http_1.FigshareHttpError) {
140
+ // FigshareHttpError already strips the axios request config; keep it that way.
141
+ throw new vocabulary_errors_1.FigshareTransportError(`Figshare category catalogue request failed${error.statusCode == null ? '' : ` (status ${error.statusCode})`}`, error.statusCode);
142
+ }
143
+ throw error;
144
+ }
145
+ }
146
+ assertScope(scope) {
147
+ const normalized = String(scope ?? '').trim().toLowerCase();
148
+ if (normalized !== 'public' && normalized !== 'account') {
149
+ throw new vocabulary_errors_1.CatalogueInvalidError("scope must be either 'public' or 'account'");
150
+ }
151
+ return normalized;
152
+ }
153
+ parsePaging(limit, offset, defaultLimit = 50) {
154
+ const parsedLimit = Number.parseInt(String(limit ?? defaultLimit), 10);
155
+ const parsedOffset = Number.parseInt(String(offset ?? 0), 10);
156
+ return {
157
+ limit: Number.isInteger(parsedLimit) && parsedLimit > 0 ? Math.min(MAX_PAGE_SIZE, parsedLimit) : defaultLimit,
158
+ offset: Number.isInteger(parsedOffset) && parsedOffset >= 0 ? parsedOffset : 0
159
+ };
160
+ }
161
+ // ── Brand-scoped resolution ───────────────────────────────────────
162
+ async requireSource(sourceId, brandId) {
163
+ const source = await FigshareVocabularySource.findOne({
164
+ id: String(sourceId ?? '').trim(),
165
+ branding: brandId
166
+ });
167
+ if (!source) {
168
+ throw new vocabulary_errors_1.RelationshipBoundaryError('Figshare source not found');
169
+ }
170
+ return source;
171
+ }
172
+ async requireCrosswalk(crosswalkId, brandId) {
173
+ const crosswalk = await FigshareVocabularyCrosswalk.findOne({
174
+ id: String(crosswalkId ?? '').trim(),
175
+ branding: brandId
176
+ });
177
+ if (!crosswalk) {
178
+ throw new vocabulary_errors_1.RelationshipBoundaryError('Figshare crosswalk not found');
179
+ }
180
+ return crosswalk;
181
+ }
182
+ async requireLocalVocabulary(vocabularyId, brandId) {
183
+ const vocabulary = await Vocabulary.findOne({
184
+ id: String(vocabularyId ?? '').trim(),
185
+ branding: brandId
186
+ });
187
+ if (!vocabulary) {
188
+ throw new vocabulary_errors_1.RelationshipBoundaryError('Local vocabulary not found');
189
+ }
190
+ if (vocabulary.source === 'external') {
191
+ throw new vocabulary_errors_1.RelationshipBoundaryError('A Figshare mirror cannot be used as the local side of a crosswalk');
192
+ }
193
+ return vocabulary;
194
+ }
195
+ async requireRun(runId, brandId) {
196
+ const run = await FigshareVocabularySyncRun.findOne({
197
+ id: String(runId ?? '').trim(),
198
+ branding: brandId
199
+ });
200
+ if (!run) {
201
+ throw new vocabulary_errors_1.RelationshipBoundaryError('Synchronisation preview not found');
202
+ }
203
+ return run;
204
+ }
205
+ /** Expiry is enforced synchronously; no scheduled job is introduced. */
206
+ async pruneExpiredRuns(brandId) {
207
+ const now = this.nowIso();
208
+ await FigshareVocabularySyncRun.update({
209
+ branding: brandId,
210
+ state: ['fetching', 'previewed'],
211
+ expiresAt: { '<': now }
212
+ }).set({ state: 'expired' });
213
+ }
214
+ async transitionRun(runId, from, to, patch = {}, connection) {
215
+ if (!(0, FigshareVocabularySyncRun_1.isAllowedSyncRunTransition)(from, to)) {
216
+ throw new vocabulary_errors_1.StalePreviewError(`Synchronisation run cannot move from '${from}' to '${to}'`);
217
+ }
218
+ const updated = await this.runQuery(FigshareVocabularySyncRun.updateOne({ id: runId, state: from }).set({ ...patch, state: to }), connection);
219
+ if (!updated) {
220
+ throw new vocabulary_errors_1.StalePreviewError(`Synchronisation run is no longer '${from}'`);
221
+ }
222
+ }
223
+ // ── Discovery ─────────────────────────────────────────────────────
224
+ async discoverTaxonomies(input, ctx) {
225
+ const scope = this.assertScope(input?.scope);
226
+ const raw = await this.fetchCatalogue(ctx.brandId, scope);
227
+ return (0, categories_1.groupTaxonomies)((0, categories_1.normalizeFigshareCategories)(raw));
228
+ }
229
+ // ── Preview ───────────────────────────────────────────────────────
230
+ async loadSnapshot(brandId, scope, taxonomyId) {
231
+ const raw = await this.fetchCatalogue(brandId, scope);
232
+ const normalized = (0, categories_1.normalizeFigshareCategories)(raw);
233
+ const filtered = (0, categories_1.filterByTaxonomy)(normalized, taxonomyId);
234
+ if (filtered.rows.length === 0) {
235
+ throw new vocabulary_errors_1.CatalogueInvalidError(`Figshare returned no categories for taxonomy '${taxonomyId}'`);
236
+ }
237
+ (0, categories_1.assertSnapshotWithinLimits)(filtered.rows);
238
+ return { rows: filtered.rows, warnings: filtered.warnings };
239
+ }
240
+ async loadExistingCategories(sourceId) {
241
+ const categories = await FigshareVocabularyCategory.find({ source: sourceId });
242
+ return categories.map((category) => ({
243
+ sourceId: category.sourceId,
244
+ categoryId: category.categoryId,
245
+ title: '',
246
+ contentHash: category.contentHash,
247
+ historical: category.historical === true
248
+ }));
249
+ }
250
+ async loadLocalEntries(vocabularyId) {
251
+ const entries = await VocabularyEntry.find({ vocabulary: vocabularyId });
252
+ return entries.map((entry) => ({
253
+ id: String(entry.id),
254
+ label: String(entry.label ?? ''),
255
+ labelLower: String(entry.labelLower ?? ''),
256
+ value: String(entry.value ?? ''),
257
+ valueLower: String(entry.valueLower ?? ''),
258
+ identifier: entry.identifier
259
+ }));
260
+ }
261
+ /**
262
+ * A brand may only mirror a given catalogue once, so an import that names no explicit
263
+ * source still has to bind the existing mirror instead of creating a second one.
264
+ */
265
+ async findSourceForCatalogue(brandId, scope, taxonomyId) {
266
+ return await FigshareVocabularySource.findOne({
267
+ branding: brandId,
268
+ scope,
269
+ taxonomyId
270
+ });
271
+ }
272
+ /**
273
+ * Likewise, a local vocabulary is crosswalked to a mirror at most once; re-running the
274
+ * wizard for an existing pairing resynchronises that crosswalk rather than forking it.
275
+ */
276
+ async findCrosswalkForPairing(brandId, localVocabularyId, sourceId) {
277
+ return await FigshareVocabularyCrosswalk.findOne({
278
+ branding: brandId,
279
+ localVocabulary: localVocabularyId,
280
+ figshareSource: sourceId
281
+ });
282
+ }
283
+ /**
284
+ * Resolve which of the mutually exclusive preview modes was requested.
285
+ *
286
+ * Four shapes are accepted: an explicit crosswalk resync, a mirror-only resync
287
+ * (`sourceId` with no local target), an existing local vocabulary, and a new clone.
288
+ */
289
+ async resolvePreviewMode(input, brandId, scope) {
290
+ const createLocalClone = input.createLocalClone === true;
291
+ const normalizedScope = scope ?? this.assertScope(input?.scope);
292
+ const crosswalkId = String(input.crosswalkId ?? '').trim();
293
+ const sourceId = String(input.sourceId ?? '').trim();
294
+ const localVocabularyId = String(input.localVocabularyId ?? '').trim();
295
+ if (crosswalkId) {
296
+ if (localVocabularyId || createLocalClone) {
297
+ throw new vocabulary_errors_1.CatalogueInvalidError('A crosswalk resync cannot also select a local vocabulary or request a clone');
298
+ }
299
+ const crosswalk = await this.requireCrosswalk(crosswalkId, brandId);
300
+ const source = await this.requireSource(String(crosswalk.figshareSource), brandId);
301
+ const localVocabulary = await this.requireLocalVocabulary(String(crosswalk.localVocabulary), brandId);
302
+ return { source, crosswalk, localVocabulary, createLocalClone: false };
303
+ }
304
+ if (localVocabularyId && createLocalClone) {
305
+ throw new vocabulary_errors_1.CatalogueInvalidError('Select an existing local vocabulary or create a clone, not both');
306
+ }
307
+ if (createLocalClone && String(input.localCloneName ?? '').trim() === '') {
308
+ throw new vocabulary_errors_1.CatalogueInvalidError('localCloneName is required when creating an editable clone');
309
+ }
310
+ const source = sourceId
311
+ ? await this.requireSource(sourceId, brandId)
312
+ : await this.findSourceForCatalogue(brandId, normalizedScope, String(input.taxonomyId ?? '').trim());
313
+ // Refreshing an existing mirror is a complete request on its own; only a brand new
314
+ // mirror needs to be told what it should be crosswalked to.
315
+ if (!localVocabularyId && !createLocalClone && !source) {
316
+ throw new vocabulary_errors_1.CatalogueInvalidError('Select an existing local vocabulary or request an editable clone');
317
+ }
318
+ const localVocabulary = localVocabularyId ? await this.requireLocalVocabulary(localVocabularyId, brandId) : null;
319
+ const crosswalk = source && localVocabulary
320
+ ? await this.findCrosswalkForPairing(brandId, String(localVocabulary.id), String(source.id))
321
+ : null;
322
+ return { source, crosswalk, localVocabulary, createLocalClone };
323
+ }
324
+ async createPreview(input, ctx) {
325
+ await this.pruneExpiredRuns(ctx.brandId);
326
+ const scope = this.assertScope(input?.scope);
327
+ const taxonomyId = String(input?.taxonomyId ?? '').trim();
328
+ if (!taxonomyId) {
329
+ throw new vocabulary_errors_1.CatalogueInvalidError('taxonomyId is required');
330
+ }
331
+ const mode = await this.resolvePreviewMode(input, ctx.brandId, scope);
332
+ if (mode.source && mode.source.scope !== scope) {
333
+ throw new vocabulary_errors_1.CatalogueInvalidError('The requested scope does not match the existing Figshare source');
334
+ }
335
+ if (mode.source && mode.source.taxonomyId !== taxonomyId) {
336
+ throw new vocabulary_errors_1.CatalogueInvalidError('The requested taxonomy does not match the existing Figshare source');
337
+ }
338
+ const snapshot = await this.loadSnapshot(ctx.brandId, scope, taxonomyId);
339
+ const remoteHash = (0, categories_1.hashSnapshot)(snapshot.rows);
340
+ const existing = mode.source ? await this.loadExistingCategories(String(mode.source.id)) : [];
341
+ const diff = (0, categories_1.classifyChanges)(existing, snapshot.rows);
342
+ const historicalSourceIds = new Set(diff.rows.filter((row) => row.changeClass === 'removed').map((row) => row.sourceId));
343
+ let proposals = [];
344
+ let unresolvedLocalEntryIds = [];
345
+ if (mode.createLocalClone) {
346
+ // Clone entries do not exist yet; propose identity by remote sourceId and let
347
+ // apply bind them to the entry ids created inside the same transaction.
348
+ proposals = snapshot.rows.map((row) => ({
349
+ proposalId: `clone:${row.sourceId}`,
350
+ localEntryId: '',
351
+ localLabel: row.title,
352
+ localValue: row.sourceId,
353
+ targetSourceId: row.sourceId,
354
+ targetCategoryId: row.categoryId,
355
+ targetTitle: row.title,
356
+ matchType: 'identity',
357
+ preselected: true,
358
+ historical: false,
359
+ evidence: { rule: 'clone-identity', normalizerVersion: categories_1.FIGSHARE_NORMALIZER_VERSION }
360
+ }));
361
+ }
362
+ else if (mode.localVocabulary) {
363
+ const localEntries = await this.loadLocalEntries(String(mode.localVocabulary.id));
364
+ const result = (0, categories_1.buildProposals)(localEntries, snapshot.rows, { historicalSourceIds });
365
+ proposals = result.proposals;
366
+ unresolvedLocalEntryIds = result.unresolvedLocalEntryIds;
367
+ }
368
+ const summary = {
369
+ ...diff.summary,
370
+ proposed: proposals.length,
371
+ preselected: proposals.filter((proposal) => proposal.preselected).length,
372
+ unresolved: unresolvedLocalEntryIds.length,
373
+ historicalWarnings: diff.summary.removed
374
+ };
375
+ const expiresAt = new Date(Date.now() + PREVIEW_TTL_MS).toISOString();
376
+ const run = await FigshareVocabularySyncRun.create({
377
+ branding: ctx.brandId,
378
+ source: mode.source ? String(mode.source.id) : null,
379
+ scope,
380
+ taxonomyId,
381
+ localVocabulary: mode.localVocabulary ? String(mode.localVocabulary.id) : null,
382
+ crosswalk: mode.crosswalk ? String(mode.crosswalk.id) : null,
383
+ createLocalClone: mode.createLocalClone,
384
+ localCloneName: String(input.localCloneName ?? '').trim() || undefined,
385
+ localCloneSlug: String(input.localCloneSlug ?? '').trim() || undefined,
386
+ normalizerVersion: categories_1.FIGSHARE_NORMALIZER_VERSION,
387
+ state: 'previewed',
388
+ baseHash: mode.source ? String(mode.source.remoteHash ?? '') : '',
389
+ remoteHash,
390
+ normalizedSnapshot: snapshot.rows,
391
+ diff: { rows: diff.rows, summary: diff.summary },
392
+ proposals,
393
+ summary,
394
+ warnings: [...snapshot.warnings, ...unresolvedLocalEntryIds.map((id) => ({ code: 'unresolved-local-entry', localEntryId: id }))],
395
+ expiresAt,
396
+ requestedBy: ctx.userId
397
+ }).fetch();
398
+ return this.toSyncPreview(run);
399
+ }
400
+ toSyncPreview(run) {
401
+ return {
402
+ runId: String(run.id),
403
+ state: String(run.state),
404
+ scope: run.scope,
405
+ taxonomyId: run.taxonomyId,
406
+ sourceId: run.source == null ? null : String(run.source),
407
+ localVocabularyId: run.localVocabulary == null ? null : String(run.localVocabulary),
408
+ crosswalkId: run.crosswalk == null ? null : String(run.crosswalk),
409
+ createLocalClone: run.createLocalClone === true,
410
+ baseHash: String(run.baseHash ?? ''),
411
+ remoteHash: String(run.remoteHash ?? ''),
412
+ expiresAt: run.expiresAt,
413
+ normalizerVersion: run.normalizerVersion,
414
+ summary: (run.summary ?? {}),
415
+ warnings: (run.warnings ?? [])
416
+ };
417
+ }
418
+ async getPreview(runId, query, ctx) {
419
+ const run = await this.requireRun(runId, ctx.brandId);
420
+ if ((run.state === 'previewed' || run.state === 'fetching') && new Date(run.expiresAt).getTime() <= Date.now()) {
421
+ await this.transitionRun(String(run.id), String(run.state), 'expired');
422
+ throw new vocabulary_errors_1.PreviewExpiredError();
423
+ }
424
+ const view = query?.view === 'diff' ? 'diff' : 'proposals';
425
+ const { limit, offset } = this.parsePaging(query?.limit, query?.offset);
426
+ const search = String(query?.q ?? '').trim().toLowerCase();
427
+ let records;
428
+ if (view === 'diff') {
429
+ const diffRows = (run.diff?.rows ?? []);
430
+ records = diffRows.filter((row) => {
431
+ if (query?.changeClass && row.changeClass !== query.changeClass) {
432
+ return false;
433
+ }
434
+ if (search && !`${row.sourceId} ${row.title}`.toLowerCase().includes(search)) {
435
+ return false;
436
+ }
437
+ return true;
438
+ });
439
+ }
440
+ else {
441
+ const proposals = (run.proposals ?? []);
442
+ records = proposals.filter((proposal) => {
443
+ if (query?.matchType && proposal.matchType !== query.matchType) {
444
+ return false;
445
+ }
446
+ if (query?.historicalOnly === true && !proposal.historical) {
447
+ return false;
448
+ }
449
+ if (query?.unresolvedOnly === true && proposal.preselected) {
450
+ return false;
451
+ }
452
+ if (search) {
453
+ const haystack = `${proposal.localLabel} ${proposal.localValue} ${proposal.targetSourceId} ${proposal.targetTitle}`.toLowerCase();
454
+ if (!haystack.includes(search)) {
455
+ return false;
456
+ }
457
+ }
458
+ return true;
459
+ });
460
+ }
461
+ const unresolvedIds = (run.warnings ?? [])
462
+ .filter((warning) => warning?.code === 'unresolved-local-entry' && warning.localEntryId)
463
+ .map((warning) => String(warning.localEntryId));
464
+ const unresolvedEntries = unresolvedIds.length === 0
465
+ ? []
466
+ : (await VocabularyEntry.find({ id: unresolvedIds })).map((entry) => ({
467
+ localEntryId: String(entry.id),
468
+ localLabel: String(entry.label ?? ''),
469
+ localValue: String(entry.value ?? '')
470
+ }));
471
+ return {
472
+ ...this.toSyncPreview(run),
473
+ page: {
474
+ view,
475
+ records: records.slice(offset, offset + limit),
476
+ total: records.length,
477
+ limit,
478
+ offset
479
+ },
480
+ unresolved: unresolvedEntries
481
+ };
482
+ }
483
+ // ── Apply ─────────────────────────────────────────────────────────
484
+ dedupeLabel(title, sourceId, usedLabels) {
485
+ // VocabularyEntry enforces a unique label per vocabulary while Figshare freely
486
+ // repeats titles across a taxonomy, so collisions are disambiguated by code.
487
+ const base = title.trim() || sourceId;
488
+ if (!usedLabels.has(base.toLowerCase())) {
489
+ usedLabels.add(base.toLowerCase());
490
+ return base;
491
+ }
492
+ let candidate = `${base} (${sourceId})`;
493
+ let suffix = 2;
494
+ while (usedLabels.has(candidate.toLowerCase())) {
495
+ candidate = `${base} (${sourceId}-${suffix})`;
496
+ suffix += 1;
497
+ }
498
+ usedLabels.add(candidate.toLowerCase());
499
+ return candidate;
500
+ }
501
+ async applyPreview(runId, decisions, ctx) {
502
+ const run = await this.requireRun(runId, ctx.brandId);
503
+ if (run.state === 'applied') {
504
+ // A completed run is idempotent: replay the stored result without writing.
505
+ return (run.result ?? {});
506
+ }
507
+ if (run.state === 'applying') {
508
+ throw new vocabulary_errors_1.StalePreviewError('This preview is already being applied');
509
+ }
510
+ if (run.state !== 'previewed') {
511
+ throw new vocabulary_errors_1.StalePreviewError(`This preview is '${run.state}' and can no longer be applied`);
512
+ }
513
+ if (new Date(run.expiresAt).getTime() <= Date.now()) {
514
+ await this.transitionRun(String(run.id), 'previewed', 'expired');
515
+ throw new vocabulary_errors_1.PreviewExpiredError();
516
+ }
517
+ if (String(decisions?.remoteHash ?? '') !== String(run.remoteHash ?? '')) {
518
+ throw new vocabulary_errors_1.StalePreviewError('The reviewed remote snapshot no longer matches this preview');
519
+ }
520
+ const existingSource = run.source ? await this.requireSource(String(run.source), ctx.brandId) : null;
521
+ if (existingSource && String(existingSource.remoteHash ?? '') !== String(run.baseHash ?? '')) {
522
+ throw new vocabulary_errors_1.StalePreviewError('The Figshare mirror changed since this preview was generated');
523
+ }
524
+ const existingCrosswalk = run.crosswalk ? await this.requireCrosswalk(String(run.crosswalk), ctx.brandId) : null;
525
+ if (existingCrosswalk && decisions?.expectedRevision != null
526
+ && Number(decisions.expectedRevision) !== Number(existingCrosswalk.workingRevision)) {
527
+ throw new vocabulary_errors_1.CrosswalkRevisionError();
528
+ }
529
+ await this.transitionRun(String(run.id), 'previewed', 'applying');
530
+ const createdIds = {
531
+ vocabularies: [],
532
+ sources: [],
533
+ crosswalks: []
534
+ };
535
+ try {
536
+ const result = await (0, TransactionUtils_1.runWithOptionalTransaction)(this.getDatastore(), async (connection) => this.applyPreviewWork(run, decisions, ctx, existingSource, existingCrosswalk, createdIds, connection), {
537
+ logger: sails.log,
538
+ unsupportedAdapterWarning: 'Transactions are not supported by this datastore adapter. Falling back to compensating cleanup for Figshare vocabulary apply.'
539
+ });
540
+ await this.transitionRun(String(run.id), 'applying', 'applied', {
541
+ appliedBy: ctx.userId,
542
+ appliedAt: result.appliedAt,
543
+ source: result.sourceId,
544
+ crosswalk: result.crosswalkId ?? null,
545
+ localVocabulary: result.localVocabularyId ?? null,
546
+ result: result
547
+ });
548
+ return result;
549
+ }
550
+ catch (error) {
551
+ await this.compensate(createdIds);
552
+ await this.transitionRun(String(run.id), 'applying', 'failed', {
553
+ errorCode: error?.code ?? 'apply-failed',
554
+ errorDetail: error?.message ?? 'Figshare vocabulary apply failed'
555
+ });
556
+ throw error;
557
+ }
558
+ }
559
+ /** Best-effort cleanup for datastores without transaction support. */
560
+ async compensate(created) {
561
+ try {
562
+ for (const crosswalkId of created.crosswalks) {
563
+ await FigshareVocabularyCrosswalkMapping.destroy({ crosswalk: crosswalkId });
564
+ await FigshareVocabularyCrosswalk.destroyOne({ id: crosswalkId });
565
+ }
566
+ for (const sourceId of created.sources) {
567
+ await FigshareVocabularyCategory.destroy({ source: sourceId });
568
+ await FigshareVocabularySource.destroyOne({ id: sourceId });
569
+ }
570
+ for (const vocabularyId of created.vocabularies) {
571
+ await VocabularyEntry.destroy({ vocabulary: vocabularyId });
572
+ await Vocabulary.destroyOne({ id: vocabularyId });
573
+ }
574
+ }
575
+ catch (cleanupError) {
576
+ sails.log.error('Figshare vocabulary apply compensation failed', cleanupError);
577
+ }
578
+ }
579
+ async applyPreviewWork(run, decisions, ctx, existingSource, existingCrosswalk, createdIds, connection) {
580
+ const snapshot = (run.normalizedSnapshot ?? []);
581
+ const appliedAt = this.nowIso();
582
+ // 1. Source + external mirror vocabulary.
583
+ let source = existingSource;
584
+ let mirrorVocabularyId;
585
+ if (source) {
586
+ mirrorVocabularyId = String(source.vocabulary);
587
+ }
588
+ else {
589
+ const mirrorName = `Figshare ${run.scope} taxonomy ${run.taxonomyId}`;
590
+ const mirror = await this.createOne(Vocabulary.create({
591
+ name: mirrorName,
592
+ description: `Read-only mirror of the Figshare ${run.scope} category catalogue for taxonomy ${run.taxonomyId}`,
593
+ type: 'tree',
594
+ source: 'external',
595
+ sourceId: `${run.scope}:${run.taxonomyId}`,
596
+ figshareSourceKey: `${ctx.brandId}:${run.scope}:${run.taxonomyId}`,
597
+ branding: ctx.brandId
598
+ }), connection);
599
+ mirrorVocabularyId = String(mirror.id);
600
+ createdIds.vocabularies.push(mirrorVocabularyId);
601
+ source = await this.createOne(FigshareVocabularySource.create({
602
+ branding: ctx.brandId,
603
+ vocabulary: mirrorVocabularyId,
604
+ scope: run.scope,
605
+ taxonomyId: run.taxonomyId,
606
+ displayName: mirrorName,
607
+ createdBy: ctx.userId,
608
+ updatedBy: ctx.userId
609
+ }), connection);
610
+ createdIds.sources.push(String(source.id));
611
+ }
612
+ const sourceId = String(source.id);
613
+ // 2/3. Upsert category relationships and mirrored entries, then mark omissions historical.
614
+ const mirrorStats = await this.syncMirror(sourceId, mirrorVocabularyId, snapshot, appliedAt, connection);
615
+ // 4. Optional independent local clone.
616
+ let localVocabularyId = run.localVocabulary == null ? null : String(run.localVocabulary);
617
+ let cloneCreated = false;
618
+ let cloneEntryBySourceId = new Map();
619
+ if (run.createLocalClone === true && !localVocabularyId) {
620
+ const clone = await this.createCloneVocabulary(String(run.localCloneName ?? '').trim(), String(run.localCloneSlug ?? '').trim(), snapshot, ctx, connection);
621
+ localVocabularyId = clone.vocabularyId;
622
+ cloneEntryBySourceId = clone.entryBySourceId;
623
+ cloneCreated = true;
624
+ createdIds.vocabularies.push(localVocabularyId);
625
+ }
626
+ // 5. Crosswalk and mapping edges.
627
+ let crosswalkId = existingCrosswalk ? String(existingCrosswalk.id) : null;
628
+ let crosswalkRevision = existingCrosswalk ? Number(existingCrosswalk.workingRevision) : null;
629
+ let mappingStats = { created: 0, removed: 0 };
630
+ if (localVocabularyId) {
631
+ if (!crosswalkId) {
632
+ // A clone knows its own name up front; an existing local vocabulary has to be
633
+ // read back so the crosswalk is labelled after it rather than a generic stand-in.
634
+ let localLabel = String(run.localCloneName ?? '').trim();
635
+ if (!localLabel) {
636
+ const localVocabulary = await this.runQuery(Vocabulary.findOne({ id: localVocabularyId }), connection);
637
+ localLabel = String(localVocabulary?.name ?? '').trim();
638
+ }
639
+ const crosswalkName = await this.uniqueCrosswalkName(`${localLabel || 'Crosswalk'} → Figshare taxonomy ${run.taxonomyId}`, ctx.brandId, connection);
640
+ const crosswalk = await this.createOne(FigshareVocabularyCrosswalk.create({
641
+ branding: ctx.brandId,
642
+ name: crosswalkName,
643
+ localVocabulary: localVocabularyId,
644
+ figshareSource: sourceId,
645
+ status: 'draft',
646
+ workingRevision: 1,
647
+ updatedBy: ctx.userId
648
+ }), connection);
649
+ crosswalkId = String(crosswalk.id);
650
+ crosswalkRevision = 1;
651
+ createdIds.crosswalks.push(crosswalkId);
652
+ }
653
+ mappingStats = await this.writeMappingEdges(crosswalkId, crosswalkRevision ?? 1, run, decisions, sourceId, localVocabularyId, cloneEntryBySourceId, ctx, connection);
654
+ }
655
+ // 6. Source cursor.
656
+ await this.runQuery(FigshareVocabularySource.updateOne({ id: sourceId }).set({
657
+ remoteHash: String(run.remoteHash ?? ''),
658
+ lastSyncedAt: appliedAt,
659
+ lastSyncRun: String(run.id),
660
+ updatedBy: ctx.userId
661
+ }), connection);
662
+ return {
663
+ runId: String(run.id),
664
+ state: 'applied',
665
+ sourceId,
666
+ vocabularyId: mirrorVocabularyId,
667
+ localVocabularyId,
668
+ crosswalkId,
669
+ crosswalkRevision,
670
+ categories: mirrorStats,
671
+ mappings: mappingStats,
672
+ cloneCreated,
673
+ appliedAt
674
+ };
675
+ }
676
+ async syncMirror(sourceId, mirrorVocabularyId, snapshot, appliedAt, connection) {
677
+ const existingCategories = await this.runQuery(FigshareVocabularyCategory.find({ source: sourceId }), connection);
678
+ const existingBySourceId = new Map(existingCategories.map((category) => [category.sourceId, category]));
679
+ const existingEntries = await this.runQuery(VocabularyEntry.find({ vocabulary: mirrorVocabularyId }), connection);
680
+ const usedLabels = new Set(existingEntries.map((entry) => String(entry.labelLower ?? '')));
681
+ const entryIdByCategoryId = new Map(existingCategories.map((category) => [category.sourceId, String(category.entry)]));
682
+ const stats = { created: 0, updated: 0, historical: 0, reappeared: 0 };
683
+ const entryIdBySourceId = new Map();
684
+ for (const row of snapshot) {
685
+ const existing = existingBySourceId.get(row.sourceId);
686
+ if (!existing) {
687
+ const label = this.dedupeLabel(row.title, row.sourceId, usedLabels);
688
+ const entry = await this.createOne(VocabularyEntry.create({
689
+ vocabulary: mirrorVocabularyId,
690
+ label,
691
+ value: row.sourceId,
692
+ identifier: row.sourceId,
693
+ order: 0,
694
+ historical: false
695
+ }), connection);
696
+ entryIdBySourceId.set(row.sourceId, String(entry.id));
697
+ await this.createOne(FigshareVocabularyCategory.create({
698
+ source: sourceId,
699
+ entry: String(entry.id),
700
+ sourceId: row.sourceId,
701
+ categoryId: row.categoryId,
702
+ taxonomyId: row.taxonomyId,
703
+ parentSourceId: row.parentSourceId ?? undefined,
704
+ path: row.path,
705
+ selectable: row.selectable,
706
+ historical: false,
707
+ firstSeenAt: appliedAt,
708
+ lastSeenAt: appliedAt,
709
+ contentHash: row.contentHash
710
+ }), connection);
711
+ stats.created += 1;
712
+ continue;
713
+ }
714
+ const entryId = String(existing.entry);
715
+ entryIdBySourceId.set(row.sourceId, entryId);
716
+ const wasHistorical = existing.historical === true;
717
+ if (wasHistorical) {
718
+ stats.reappeared += 1;
719
+ }
720
+ else if (existing.contentHash !== row.contentHash) {
721
+ stats.updated += 1;
722
+ }
723
+ if (wasHistorical || existing.contentHash !== row.contentHash) {
724
+ await this.runQuery(VocabularyEntry.updateOne({ id: entryId }).set({
725
+ label: this.relabelExisting(row, existingEntries, entryId, usedLabels),
726
+ historical: false
727
+ }), connection);
728
+ }
729
+ await this.runQuery(FigshareVocabularyCategory.updateOne({ id: String(existing.id) }).set({
730
+ categoryId: row.categoryId,
731
+ taxonomyId: row.taxonomyId,
732
+ parentSourceId: row.parentSourceId ?? undefined,
733
+ path: row.path,
734
+ selectable: row.selectable,
735
+ historical: false,
736
+ lastSeenAt: appliedAt,
737
+ contentHash: row.contentHash
738
+ }), connection);
739
+ }
740
+ // Remote omission never hard-deletes: retain identity and audit evidence.
741
+ const remoteSourceIds = new Set(snapshot.map((row) => row.sourceId));
742
+ for (const existing of existingCategories) {
743
+ if (remoteSourceIds.has(existing.sourceId) || existing.historical === true) {
744
+ continue;
745
+ }
746
+ await this.runQuery(FigshareVocabularyCategory.updateOne({ id: String(existing.id) }).set({ historical: true }), connection);
747
+ await this.runQuery(VocabularyEntry.updateOne({ id: String(existing.entry) }).set({ historical: true }), connection);
748
+ stats.historical += 1;
749
+ }
750
+ // Parents are rebuilt after every entry exists so ordering never matters.
751
+ for (const row of snapshot) {
752
+ const entryId = entryIdBySourceId.get(row.sourceId) ?? entryIdByCategoryId.get(row.sourceId);
753
+ if (!entryId) {
754
+ continue;
755
+ }
756
+ const parentEntryId = row.parentSourceId == null
757
+ ? null
758
+ : entryIdBySourceId.get(row.parentSourceId) ?? entryIdByCategoryId.get(row.parentSourceId) ?? null;
759
+ await this.runQuery(VocabularyEntry.updateOne({ id: entryId }).set({ parent: parentEntryId }), connection);
760
+ }
761
+ return stats;
762
+ }
763
+ relabelExisting(row, existingEntries, entryId, usedLabels) {
764
+ const current = existingEntries.find((entry) => String(entry.id) === entryId);
765
+ const currentLabelLower = String(current?.labelLower ?? '');
766
+ if (currentLabelLower === row.title.toLowerCase()) {
767
+ return row.title;
768
+ }
769
+ usedLabels.delete(currentLabelLower);
770
+ return this.dedupeLabel(row.title, row.sourceId, usedLabels);
771
+ }
772
+ async createCloneVocabulary(name, slug, snapshot, ctx, connection) {
773
+ if (!name) {
774
+ throw new vocabulary_errors_1.CatalogueInvalidError('A clone name is required to create an editable local vocabulary');
775
+ }
776
+ const clone = await this.createOne(Vocabulary.create({
777
+ name,
778
+ ...(slug ? { slug } : {}),
779
+ description: 'Editable local copy of a Figshare category catalogue',
780
+ type: 'tree',
781
+ source: 'local',
782
+ branding: ctx.brandId
783
+ }), connection);
784
+ const vocabularyId = String(clone.id);
785
+ const usedLabels = new Set();
786
+ const entryBySourceId = new Map();
787
+ for (const row of snapshot) {
788
+ const entry = await this.createOne(VocabularyEntry.create({
789
+ vocabulary: vocabularyId,
790
+ label: this.dedupeLabel(row.title, row.sourceId, usedLabels),
791
+ value: row.sourceId,
792
+ identifier: row.sourceId,
793
+ order: 0,
794
+ historical: false
795
+ }), connection);
796
+ entryBySourceId.set(row.sourceId, String(entry.id));
797
+ }
798
+ // Parent references are rebuilt against clone entry ids once all entries exist.
799
+ for (const row of snapshot) {
800
+ const entryId = entryBySourceId.get(row.sourceId);
801
+ const parentId = row.parentSourceId == null ? null : entryBySourceId.get(row.parentSourceId) ?? null;
802
+ if (!entryId || parentId == null) {
803
+ continue;
804
+ }
805
+ await this.runQuery(VocabularyEntry.updateOne({ id: entryId }).set({ parent: parentId }), connection);
806
+ }
807
+ return { vocabularyId, entryBySourceId };
808
+ }
809
+ async uniqueCrosswalkName(base, brandId, connection) {
810
+ let candidate = base;
811
+ let suffix = 2;
812
+ // The unique { branding, name } index makes collisions a hard failure, so probe first.
813
+ while (await this.runQuery(FigshareVocabularyCrosswalk.findOne({ branding: brandId, name: candidate }), connection)) {
814
+ candidate = `${base} (${suffix})`;
815
+ suffix += 1;
816
+ }
817
+ return candidate;
818
+ }
819
+ async writeMappingEdges(crosswalkId, revision, run, decisions, sourceId, localVocabularyId, cloneEntryBySourceId, ctx, connection) {
820
+ const categories = await this.runQuery(FigshareVocabularyCategory.find({ source: sourceId }), connection);
821
+ const categoryBySourceId = new Map(categories.map((category) => [category.sourceId, category]));
822
+ const approvedProposalIds = new Set((decisions?.approvedProposalIds ?? []).map((id) => String(id)));
823
+ const proposals = (run.proposals ?? []);
824
+ const desiredEdges = new Map();
825
+ const addEdge = (localEntryId, categorySourceId, matchType) => {
826
+ const category = categoryBySourceId.get(categorySourceId);
827
+ if (!localEntryId || !category) {
828
+ return;
829
+ }
830
+ desiredEdges.set(`${localEntryId}::${String(category.id)}`, {
831
+ localEntryId,
832
+ categoryId: String(category.id),
833
+ matchType
834
+ });
835
+ };
836
+ for (const proposal of proposals) {
837
+ if (!approvedProposalIds.has(proposal.proposalId)) {
838
+ continue;
839
+ }
840
+ const localEntryId = proposal.localEntryId
841
+ || cloneEntryBySourceId.get(proposal.targetSourceId)
842
+ || '';
843
+ addEdge(localEntryId, proposal.targetSourceId, proposal.matchType);
844
+ }
845
+ const manualMappings = decisions?.manualMappings ?? [];
846
+ if (manualMappings.length > MAX_MAPPING_BATCH) {
847
+ throw new vocabulary_errors_1.CatalogueInvalidError(`manualMappings exceeds the maximum batch size of ${MAX_MAPPING_BATCH}`);
848
+ }
849
+ for (const mapping of manualMappings) {
850
+ const localEntryId = String(mapping.localEntryId ?? '').trim()
851
+ || cloneEntryBySourceId.get(String(mapping.localEntryKey ?? '').trim())
852
+ || '';
853
+ for (const targetSourceId of mapping.figshareSourceIds ?? []) {
854
+ addEdge(localEntryId, String(targetSourceId).trim(), 'manual');
855
+ }
856
+ }
857
+ if (desiredEdges.size > 0) {
858
+ const localEntryIds = Array.from(new Set(Array.from(desiredEdges.values()).map((edge) => edge.localEntryId)));
859
+ const localEntries = await this.runQuery(VocabularyEntry.find({ id: localEntryIds, vocabulary: localVocabularyId }), connection);
860
+ const validLocalEntryIds = new Set(localEntries.map((entry) => String(entry.id)));
861
+ for (const edge of desiredEdges.values()) {
862
+ if (!validLocalEntryIds.has(edge.localEntryId)) {
863
+ throw new vocabulary_errors_1.RelationshipBoundaryError('A mapping references a local entry outside the crosswalk local vocabulary');
864
+ }
865
+ }
866
+ }
867
+ const existingEdges = await this.runQuery(FigshareVocabularyCrosswalkMapping.find({ crosswalk: crosswalkId, revision }), connection);
868
+ const existingKeys = new Set(existingEdges.map((edge) => `${String(edge.localEntry)}::${String(edge.figshareCategory)}`));
869
+ let created = 0;
870
+ for (const [key, edge] of desiredEdges) {
871
+ if (existingKeys.has(key)) {
872
+ continue;
873
+ }
874
+ await this.createOne(FigshareVocabularyCrosswalkMapping.create({
875
+ crosswalk: crosswalkId,
876
+ revision,
877
+ localEntry: edge.localEntryId,
878
+ figshareCategory: edge.categoryId,
879
+ status: 'proposed',
880
+ matchType: edge.matchType
881
+ }), connection);
882
+ created += 1;
883
+ }
884
+ await this.runQuery(FigshareVocabularyCrosswalk.updateOne({ id: crosswalkId }).set({ updatedBy: ctx.userId }), connection);
885
+ return { created, removed: 0 };
886
+ }
887
+ // ── Sources ───────────────────────────────────────────────────────
888
+ async listSources(query, ctx) {
889
+ const { limit, offset } = this.parsePaging(query?.limit, query?.offset, 25);
890
+ const where = { branding: ctx.brandId };
891
+ if (query?.scope === 'public' || query?.scope === 'account') {
892
+ where.scope = query.scope;
893
+ }
894
+ const search = String(query?.q ?? '').trim();
895
+ if (search) {
896
+ where.displayName = { contains: search };
897
+ }
898
+ const total = await FigshareVocabularySource.count(where);
899
+ const sources = await FigshareVocabularySource.find(where)
900
+ .sort('displayName ASC')
901
+ .skip(offset)
902
+ .limit(limit);
903
+ const data = await Promise.all(sources.map((source) => this.describeSource(source)));
904
+ return { data, meta: { total, limit, offset } };
905
+ }
906
+ async getSource(sourceId, ctx) {
907
+ return this.describeSource(await this.requireSource(sourceId, ctx.brandId));
908
+ }
909
+ /**
910
+ * Search the mirrored categories of one source so an operator can pick a manual
911
+ * crosswalk target. Historical targets stay hidden unless explicitly requested:
912
+ * mapping to a retired Figshare category is a deliberate act, not a default.
913
+ */
914
+ async listSourceCategories(sourceId, query, ctx) {
915
+ const source = await this.requireSource(sourceId, ctx.brandId);
916
+ const { limit, offset } = this.parsePaging(query?.limit, query?.offset, 25);
917
+ const where = { source: String(source.id) };
918
+ if (query?.includeHistorical !== true) {
919
+ where.historical = false;
920
+ }
921
+ if (query?.selectableOnly === true) {
922
+ where.selectable = true;
923
+ }
924
+ const categories = await FigshareVocabularyCategory.find(where);
925
+ const titleByEntryId = await this.loadCategoryTitles(categories);
926
+ const search = String(query?.q ?? '').trim().toLowerCase();
927
+ const rows = categories
928
+ .map((category) => ({
929
+ id: String(category.id),
930
+ sourceId: String(category.sourceId),
931
+ categoryId: Number(category.categoryId),
932
+ title: titleByEntryId.get(String(category.entry)) ?? String(category.sourceId),
933
+ parentSourceId: category.parentSourceId,
934
+ selectable: category.selectable !== false,
935
+ historical: category.historical === true
936
+ }))
937
+ .filter((row) => !search
938
+ || `${row.title} ${row.sourceId} ${row.categoryId}`.toLowerCase().includes(search))
939
+ .sort((left, right) => left.sourceId.localeCompare(right.sourceId, undefined, { numeric: true }));
940
+ return {
941
+ data: rows.slice(offset, offset + limit),
942
+ meta: { total: rows.length, limit, offset }
943
+ };
944
+ }
945
+ /** Mirrored category titles live on the linked vocabulary entry, not the category row. */
946
+ async loadCategoryTitles(categories) {
947
+ if (categories.length === 0) {
948
+ return new Map();
949
+ }
950
+ const entryIds = Array.from(new Set(categories.map((category) => String(category.entry))));
951
+ const entries = await VocabularyEntry.find({ id: entryIds });
952
+ return new Map(entries.map((entry) => [String(entry.id), String(entry.label ?? '')]));
953
+ }
954
+ async describeSource(source) {
955
+ const sourceId = String(source.id);
956
+ const [mirroredCount, historicalCount, crosswalkCount] = await Promise.all([
957
+ FigshareVocabularyCategory.count({ source: sourceId, historical: false }),
958
+ FigshareVocabularyCategory.count({ source: sourceId, historical: true }),
959
+ FigshareVocabularyCrosswalk.count({ figshareSource: sourceId })
960
+ ]);
961
+ const vocabulary = await Vocabulary.findOne({ id: String(source.vocabulary) });
962
+ return {
963
+ id: sourceId,
964
+ displayName: source.displayName,
965
+ scope: source.scope,
966
+ taxonomyId: source.taxonomyId,
967
+ vocabularyId: String(source.vocabulary),
968
+ vocabularyName: vocabulary?.name ?? '',
969
+ lastSyncedAt: source.lastSyncedAt ?? null,
970
+ archived: source.archived === true,
971
+ mirroredCount,
972
+ historicalCount,
973
+ crosswalkCount
974
+ };
975
+ }
976
+ async listSyncRuns(query, ctx) {
977
+ const { limit, offset } = this.parsePaging(query?.limit, query?.offset, 25);
978
+ const where = { branding: ctx.brandId };
979
+ const sourceId = String(query?.sourceId ?? '').trim();
980
+ if (sourceId) {
981
+ where.source = sourceId;
982
+ }
983
+ const total = await FigshareVocabularySyncRun.count(where);
984
+ const runs = await FigshareVocabularySyncRun.find(where)
985
+ .sort('createdAt DESC')
986
+ .skip(offset)
987
+ .limit(limit);
988
+ return {
989
+ data: runs.map((run) => ({
990
+ id: String(run.id),
991
+ state: run.state,
992
+ scope: run.scope,
993
+ taxonomyId: run.taxonomyId,
994
+ sourceId: run.source == null ? null : String(run.source),
995
+ summary: run.summary ?? {},
996
+ requestedBy: run.requestedBy,
997
+ appliedBy: run.appliedBy ?? null,
998
+ appliedAt: run.appliedAt ?? null,
999
+ expiresAt: run.expiresAt,
1000
+ errorCode: run.errorCode ?? null
1001
+ })),
1002
+ meta: { total, limit, offset }
1003
+ };
1004
+ }
1005
+ /**
1006
+ * Create an independent editable local vocabulary from an existing mirror plus a
1007
+ * draft identity crosswalk. Later mirror synchronisation never edits clone terms.
1008
+ */
1009
+ async cloneMirror(sourceId, cloneInput, ctx) {
1010
+ const source = await this.requireSource(sourceId, ctx.brandId);
1011
+ const categories = await FigshareVocabularyCategory.find({
1012
+ source: String(source.id),
1013
+ historical: false
1014
+ });
1015
+ if (categories.length === 0) {
1016
+ throw new vocabulary_errors_1.CatalogueInvalidError('The Figshare mirror has no current categories to clone');
1017
+ }
1018
+ const snapshot = categories.map((category) => ({
1019
+ sourceId: category.sourceId,
1020
+ categoryId: category.categoryId,
1021
+ taxonomyId: category.taxonomyId,
1022
+ title: '',
1023
+ parentSourceId: category.parentSourceId ?? null,
1024
+ path: category.path ?? [category.sourceId],
1025
+ selectable: category.selectable !== false,
1026
+ hasChildren: false,
1027
+ contentHash: category.contentHash
1028
+ }));
1029
+ const entries = await VocabularyEntry.find({
1030
+ id: categories.map((category) => String(category.entry))
1031
+ });
1032
+ const labelByEntryId = new Map(entries.map((entry) => [String(entry.id), String(entry.label ?? '')]));
1033
+ for (const [index, category] of categories.entries()) {
1034
+ snapshot[index].title = labelByEntryId.get(String(category.entry)) ?? category.sourceId;
1035
+ }
1036
+ const createdIds = {
1037
+ vocabularies: [],
1038
+ sources: [],
1039
+ crosswalks: []
1040
+ };
1041
+ try {
1042
+ return await (0, TransactionUtils_1.runWithOptionalTransaction)(this.getDatastore(), async (connection) => {
1043
+ const clone = await this.createCloneVocabulary(String(cloneInput?.name ?? '').trim(), String(cloneInput?.slug ?? '').trim(), snapshot, ctx, connection);
1044
+ createdIds.vocabularies.push(clone.vocabularyId);
1045
+ const crosswalkName = await this.uniqueCrosswalkName(`${String(cloneInput.name).trim()} → ${source.displayName}`, ctx.brandId, connection);
1046
+ const crosswalk = await this.createOne(FigshareVocabularyCrosswalk.create({
1047
+ branding: ctx.brandId,
1048
+ name: crosswalkName,
1049
+ localVocabulary: clone.vocabularyId,
1050
+ figshareSource: String(source.id),
1051
+ status: 'draft',
1052
+ workingRevision: 1,
1053
+ updatedBy: ctx.userId
1054
+ }), connection);
1055
+ createdIds.crosswalks.push(String(crosswalk.id));
1056
+ const cloneEntries = Array.from(clone.entryBySourceId.entries()).map(([entrySourceId, entryId]) => ({
1057
+ id: entryId,
1058
+ label: '',
1059
+ labelLower: '',
1060
+ value: entrySourceId,
1061
+ valueLower: entrySourceId.toLowerCase(),
1062
+ sourceId: entrySourceId
1063
+ }));
1064
+ const identity = (0, categories_1.buildIdentityProposals)(cloneEntries, snapshot);
1065
+ const categoryBySourceId = new Map(categories.map((category) => [category.sourceId, category]));
1066
+ for (const proposal of identity.proposals) {
1067
+ const category = categoryBySourceId.get(proposal.targetSourceId);
1068
+ if (!category) {
1069
+ continue;
1070
+ }
1071
+ await this.createOne(FigshareVocabularyCrosswalkMapping.create({
1072
+ crosswalk: String(crosswalk.id),
1073
+ revision: 1,
1074
+ localEntry: proposal.localEntryId,
1075
+ figshareCategory: String(category.id),
1076
+ status: 'proposed',
1077
+ matchType: 'identity'
1078
+ }), connection);
1079
+ }
1080
+ return {
1081
+ localVocabularyId: clone.vocabularyId,
1082
+ crosswalkId: String(crosswalk.id),
1083
+ entries: clone.entryBySourceId.size
1084
+ };
1085
+ }, {
1086
+ logger: sails.log,
1087
+ unsupportedAdapterWarning: 'Transactions are not supported by this datastore adapter. Falling back to compensating cleanup for Figshare clone.'
1088
+ });
1089
+ }
1090
+ catch (error) {
1091
+ await this.compensate(createdIds);
1092
+ throw error;
1093
+ }
1094
+ }
1095
+ // ── Crosswalks ────────────────────────────────────────────────────
1096
+ async listCrosswalks(query, ctx) {
1097
+ const { limit, offset } = this.parsePaging(query?.limit, query?.offset, 25);
1098
+ const where = { branding: ctx.brandId };
1099
+ if (query?.status) {
1100
+ where.status = String(query.status);
1101
+ }
1102
+ if (query?.localVocabularyId) {
1103
+ where.localVocabulary = String(query.localVocabularyId);
1104
+ }
1105
+ if (query?.sourceId) {
1106
+ where.figshareSource = String(query.sourceId);
1107
+ }
1108
+ const search = String(query?.q ?? '').trim();
1109
+ if (search) {
1110
+ where.name = { contains: search };
1111
+ }
1112
+ const total = await FigshareVocabularyCrosswalk.count(where);
1113
+ const crosswalks = await FigshareVocabularyCrosswalk.find(where)
1114
+ .sort('name ASC')
1115
+ .skip(offset)
1116
+ .limit(limit);
1117
+ const data = await Promise.all(crosswalks.map((crosswalk) => this.describeCrosswalk(crosswalk)));
1118
+ return { data, meta: { total, limit, offset } };
1119
+ }
1120
+ async getCrosswalk(crosswalkId, ctx) {
1121
+ return this.describeCrosswalk(await this.requireCrosswalk(crosswalkId, ctx.brandId));
1122
+ }
1123
+ async describeCrosswalk(crosswalk) {
1124
+ const crosswalkId = String(crosswalk.id);
1125
+ const [localVocabulary, source] = await Promise.all([
1126
+ Vocabulary.findOne({ id: String(crosswalk.localVocabulary) }),
1127
+ FigshareVocabularySource.findOne({ id: String(crosswalk.figshareSource) })
1128
+ ]);
1129
+ const [approvedMappingCount, workingMappingCount] = await Promise.all([
1130
+ crosswalk.approvedRevision == null
1131
+ ? Promise.resolve(0)
1132
+ : FigshareVocabularyCrosswalkMapping.count({
1133
+ crosswalk: crosswalkId,
1134
+ revision: Number(crosswalk.approvedRevision),
1135
+ status: 'approved'
1136
+ }),
1137
+ FigshareVocabularyCrosswalkMapping.count({ crosswalk: crosswalkId, revision: Number(crosswalk.workingRevision) })
1138
+ ]);
1139
+ const historicalTargetCount = await this.countHistoricalTargets(crosswalkId, crosswalk);
1140
+ return {
1141
+ id: crosswalkId,
1142
+ name: crosswalk.name,
1143
+ status: String(crosswalk.status),
1144
+ workingRevision: Number(crosswalk.workingRevision),
1145
+ approvedRevision: crosswalk.approvedRevision ?? null,
1146
+ approvedAt: crosswalk.approvedAt,
1147
+ approvedBy: crosswalk.approvedBy,
1148
+ localVocabularyId: String(crosswalk.localVocabulary),
1149
+ localVocabularyName: localVocabulary?.name ?? '',
1150
+ figshareSourceId: String(crosswalk.figshareSource),
1151
+ figshareSourceName: source?.displayName ?? '',
1152
+ scope: String(source?.scope ?? ''),
1153
+ taxonomyId: String(source?.taxonomyId ?? ''),
1154
+ approvedMappingCount,
1155
+ workingMappingCount,
1156
+ historicalTargetCount
1157
+ };
1158
+ }
1159
+ async countHistoricalTargets(crosswalkId, crosswalk) {
1160
+ const revision = Number(crosswalk.approvedRevision ?? crosswalk.workingRevision);
1161
+ const mappings = await FigshareVocabularyCrosswalkMapping.find({
1162
+ crosswalk: crosswalkId,
1163
+ revision
1164
+ });
1165
+ if (mappings.length === 0) {
1166
+ return 0;
1167
+ }
1168
+ const categoryIds = Array.from(new Set(mappings.map((mapping) => String(mapping.figshareCategory))));
1169
+ return FigshareVocabularyCategory.count({ id: categoryIds, historical: true });
1170
+ }
1171
+ async createCrosswalk(input, ctx) {
1172
+ const name = String(input?.name ?? '').trim();
1173
+ if (!name) {
1174
+ throw new vocabulary_errors_1.CatalogueInvalidError('name is required');
1175
+ }
1176
+ const localVocabulary = await this.requireLocalVocabulary(String(input?.localVocabularyId ?? ''), ctx.brandId);
1177
+ const source = await this.requireSource(String(input?.sourceId ?? ''), ctx.brandId);
1178
+ const existing = await FigshareVocabularyCrosswalk.findOne({ branding: ctx.brandId, name });
1179
+ if (existing) {
1180
+ throw new vocabulary_errors_1.RelationshipBoundaryError(`A crosswalk named '${name}' already exists for this brand`);
1181
+ }
1182
+ const crosswalk = await FigshareVocabularyCrosswalk.create({
1183
+ branding: ctx.brandId,
1184
+ name,
1185
+ localVocabulary: String(localVocabulary.id),
1186
+ figshareSource: String(source.id),
1187
+ status: 'draft',
1188
+ workingRevision: 1,
1189
+ updatedBy: ctx.userId
1190
+ }).fetch();
1191
+ return this.describeCrosswalk(crosswalk);
1192
+ }
1193
+ /**
1194
+ * Search the local vocabulary behind a crosswalk, annotated with how many targets
1195
+ * each term already has. Terms with no target never appear in the mapping table,
1196
+ * so this is the only way the manual picker can reach them.
1197
+ */
1198
+ async listCrosswalkLocalEntries(crosswalkId, query, ctx) {
1199
+ const crosswalk = await this.requireCrosswalk(crosswalkId, ctx.brandId);
1200
+ const { limit, offset } = this.parsePaging(query?.limit, query?.offset, 25);
1201
+ const revision = Number(query?.revision ?? crosswalk.workingRevision);
1202
+ const [entries, mappings] = await Promise.all([
1203
+ VocabularyEntry.find({ vocabulary: String(crosswalk.localVocabulary) }),
1204
+ FigshareVocabularyCrosswalkMapping.find({
1205
+ crosswalk: String(crosswalk.id),
1206
+ revision
1207
+ })
1208
+ ]);
1209
+ const targetCountByEntryId = new Map();
1210
+ for (const mapping of mappings) {
1211
+ const key = String(mapping.localEntry);
1212
+ targetCountByEntryId.set(key, (targetCountByEntryId.get(key) ?? 0) + 1);
1213
+ }
1214
+ const search = String(query?.q ?? '').trim().toLowerCase();
1215
+ const mappedFilter = String(query?.mapped ?? '').trim().toLowerCase();
1216
+ const rows = entries
1217
+ .map((entry) => ({
1218
+ id: String(entry.id),
1219
+ label: String(entry.label ?? ''),
1220
+ value: String(entry.value ?? ''),
1221
+ identifier: entry.identifier,
1222
+ historical: entry.historical === true,
1223
+ targetCount: targetCountByEntryId.get(String(entry.id)) ?? 0
1224
+ }))
1225
+ .filter((row) => !search || `${row.label} ${row.value}`.toLowerCase().includes(search))
1226
+ .filter((row) => {
1227
+ if (mappedFilter === 'unmapped') {
1228
+ return row.targetCount === 0;
1229
+ }
1230
+ if (mappedFilter === 'mapped') {
1231
+ return row.targetCount > 0;
1232
+ }
1233
+ return true;
1234
+ })
1235
+ .sort((left, right) => left.label.localeCompare(right.label));
1236
+ return {
1237
+ data: rows.slice(offset, offset + limit),
1238
+ meta: { total: rows.length, limit, offset, revision }
1239
+ };
1240
+ }
1241
+ async listCrosswalkMappings(crosswalkId, query, ctx) {
1242
+ const crosswalk = await this.requireCrosswalk(crosswalkId, ctx.brandId);
1243
+ const { limit, offset } = this.parsePaging(query?.limit, query?.offset);
1244
+ const revision = Number(query?.revision ?? crosswalk.workingRevision);
1245
+ const where = { crosswalk: String(crosswalk.id), revision };
1246
+ if (query?.status) {
1247
+ where.status = String(query.status);
1248
+ }
1249
+ const mappings = await FigshareVocabularyCrosswalkMapping.find(where);
1250
+ const [entries, categories] = await Promise.all([
1251
+ mappings.length === 0
1252
+ ? Promise.resolve([])
1253
+ : VocabularyEntry.find({ id: Array.from(new Set(mappings.map((mapping) => String(mapping.localEntry)))) }),
1254
+ mappings.length === 0
1255
+ ? Promise.resolve([])
1256
+ : FigshareVocabularyCategory.find({ id: Array.from(new Set(mappings.map((mapping) => String(mapping.figshareCategory)))) })
1257
+ ]);
1258
+ const entryById = new Map(entries.map((entry) => [String(entry.id), entry]));
1259
+ const categoryById = new Map(categories.map((category) => [String(category.id), category]));
1260
+ const search = String(query?.q ?? '').trim().toLowerCase();
1261
+ const rows = mappings
1262
+ .map((mapping) => {
1263
+ const entry = entryById.get(String(mapping.localEntry));
1264
+ const category = categoryById.get(String(mapping.figshareCategory));
1265
+ return {
1266
+ id: String(mapping.id),
1267
+ revision: mapping.revision,
1268
+ status: mapping.status,
1269
+ matchType: mapping.matchType,
1270
+ localEntryId: String(mapping.localEntry),
1271
+ localLabel: String(entry?.label ?? ''),
1272
+ localValue: String(entry?.value ?? ''),
1273
+ figshareCategoryId: String(mapping.figshareCategory),
1274
+ figshareSourceId: String(category?.sourceId ?? ''),
1275
+ figshareCategoryNumber: category?.categoryId ?? null,
1276
+ historical: category?.historical === true,
1277
+ approvedAt: mapping.approvedAt ?? null,
1278
+ approvedBy: mapping.approvedBy ?? null
1279
+ };
1280
+ })
1281
+ .filter((row) => !search || `${row.localLabel} ${row.localValue} ${row.figshareSourceId}`.toLowerCase().includes(search))
1282
+ .sort((left, right) => left.localLabel.localeCompare(right.localLabel));
1283
+ return {
1284
+ data: rows.slice(offset, offset + limit),
1285
+ meta: { total: rows.length, limit, offset, revision }
1286
+ };
1287
+ }
1288
+ /**
1289
+ * Batch upsert/delete mapping edges under optimistic revision control. The first
1290
+ * edit of an approved crosswalk copies the approved rows into a new working
1291
+ * revision so publishing continues against the previous approved snapshot.
1292
+ */
1293
+ async saveMappings(crosswalkId, input, ctx) {
1294
+ const crosswalk = await this.requireCrosswalk(crosswalkId, ctx.brandId);
1295
+ const changes = input?.changes ?? [];
1296
+ if (changes.length > MAX_MAPPING_BATCH) {
1297
+ throw new vocabulary_errors_1.CatalogueInvalidError(`changes exceeds the maximum batch size of ${MAX_MAPPING_BATCH}`);
1298
+ }
1299
+ if (Number(input?.revision) !== Number(crosswalk.workingRevision)) {
1300
+ throw new vocabulary_errors_1.CrosswalkRevisionError();
1301
+ }
1302
+ return (0, TransactionUtils_1.runWithOptionalTransaction)(this.getDatastore(), async (connection) => {
1303
+ let workingRevision = Number(crosswalk.workingRevision);
1304
+ if (crosswalk.approvedRevision != null && Number(crosswalk.approvedRevision) === workingRevision) {
1305
+ workingRevision += 1;
1306
+ const approvedRows = await this.runQuery(FigshareVocabularyCrosswalkMapping.find({
1307
+ crosswalk: String(crosswalk.id),
1308
+ revision: Number(crosswalk.approvedRevision)
1309
+ }), connection);
1310
+ for (const row of approvedRows) {
1311
+ await this.createOne(FigshareVocabularyCrosswalkMapping.create({
1312
+ crosswalk: String(crosswalk.id),
1313
+ revision: workingRevision,
1314
+ localEntry: String(row.localEntry),
1315
+ figshareCategory: String(row.figshareCategory),
1316
+ status: row.status,
1317
+ matchType: row.matchType,
1318
+ evidence: row.evidence,
1319
+ approvedAt: row.approvedAt,
1320
+ approvedBy: row.approvedBy
1321
+ }), connection);
1322
+ }
1323
+ await this.runQuery(FigshareVocabularyCrosswalk.updateOne({ id: String(crosswalk.id) }).set({ workingRevision }), connection);
1324
+ }
1325
+ for (const change of changes) {
1326
+ const localEntryId = String(change?.localEntryId ?? '').trim();
1327
+ const figshareCategoryId = String(change?.figshareCategoryId ?? '').trim();
1328
+ if (!localEntryId || !figshareCategoryId) {
1329
+ throw new vocabulary_errors_1.CatalogueInvalidError('Each change requires localEntryId and figshareCategoryId');
1330
+ }
1331
+ await this.assertMappingOwnership(crosswalk, localEntryId, figshareCategoryId, connection);
1332
+ if (change.op === 'remove') {
1333
+ await this.runQuery(FigshareVocabularyCrosswalkMapping.destroy({
1334
+ crosswalk: String(crosswalk.id),
1335
+ revision: workingRevision,
1336
+ localEntry: localEntryId,
1337
+ figshareCategory: figshareCategoryId
1338
+ }), connection);
1339
+ continue;
1340
+ }
1341
+ const existing = await this.runQuery(FigshareVocabularyCrosswalkMapping.findOne({
1342
+ crosswalk: String(crosswalk.id),
1343
+ revision: workingRevision,
1344
+ localEntry: localEntryId,
1345
+ figshareCategory: figshareCategoryId
1346
+ }), connection);
1347
+ const status = change.status ?? 'proposed';
1348
+ const approvalPatch = status === 'approved'
1349
+ ? { approvedAt: this.nowIso(), approvedBy: ctx.userId }
1350
+ : { approvedAt: undefined, approvedBy: undefined };
1351
+ if (existing) {
1352
+ await this.runQuery(FigshareVocabularyCrosswalkMapping.updateOne({ id: String(existing.id) }).set({
1353
+ status,
1354
+ matchType: change.matchType ?? existing.matchType,
1355
+ ...approvalPatch
1356
+ }), connection);
1357
+ continue;
1358
+ }
1359
+ await this.createOne(FigshareVocabularyCrosswalkMapping.create({
1360
+ crosswalk: String(crosswalk.id),
1361
+ revision: workingRevision,
1362
+ localEntry: localEntryId,
1363
+ figshareCategory: figshareCategoryId,
1364
+ status,
1365
+ matchType: change.matchType ?? 'manual',
1366
+ ...approvalPatch
1367
+ }), connection);
1368
+ }
1369
+ await this.runQuery(FigshareVocabularyCrosswalk.updateOne({ id: String(crosswalk.id) }).set({ updatedBy: ctx.userId }), connection);
1370
+ const refreshed = await this.runQuery(FigshareVocabularyCrosswalk.findOne({ id: String(crosswalk.id) }), connection);
1371
+ return this.describeCrosswalk(refreshed ?? crosswalk);
1372
+ }, {
1373
+ logger: sails.log,
1374
+ unsupportedAdapterWarning: 'Transactions are not supported by this datastore adapter. Falling back to non-transactional crosswalk mapping save.'
1375
+ });
1376
+ }
1377
+ async assertMappingOwnership(crosswalk, localEntryId, figshareCategoryId, connection) {
1378
+ const entry = await this.runQuery(VocabularyEntry.findOne({ id: localEntryId, vocabulary: String(crosswalk.localVocabulary) }), connection);
1379
+ if (!entry) {
1380
+ throw new vocabulary_errors_1.RelationshipBoundaryError('The local entry does not belong to the crosswalk local vocabulary');
1381
+ }
1382
+ const category = await this.runQuery(FigshareVocabularyCategory.findOne({ id: figshareCategoryId, source: String(crosswalk.figshareSource) }), connection);
1383
+ if (!category) {
1384
+ throw new vocabulary_errors_1.RelationshipBoundaryError('The Figshare category does not belong to the crosswalk source');
1385
+ }
1386
+ }
1387
+ /**
1388
+ * Promote the working revision to the approved revision. AppConfig keeps its stable
1389
+ * crosswalkId; publishing immediately follows the newly approved revision.
1390
+ */
1391
+ async approveCrosswalk(crosswalkId, revision, ctx) {
1392
+ const crosswalk = await this.requireCrosswalk(crosswalkId, ctx.brandId);
1393
+ if (Number(revision) !== Number(crosswalk.workingRevision)) {
1394
+ throw new vocabulary_errors_1.CrosswalkRevisionError();
1395
+ }
1396
+ const mappings = await FigshareVocabularyCrosswalkMapping.find({
1397
+ crosswalk: String(crosswalk.id),
1398
+ revision: Number(crosswalk.workingRevision)
1399
+ });
1400
+ const approvable = mappings.filter((mapping) => mapping.status !== 'rejected');
1401
+ if (approvable.length === 0) {
1402
+ throw new vocabulary_errors_1.CatalogueInvalidError('A crosswalk revision must contain at least one mapping before it can be approved');
1403
+ }
1404
+ const approvedAt = this.nowIso();
1405
+ return (0, TransactionUtils_1.runWithOptionalTransaction)(this.getDatastore(), async (connection) => {
1406
+ for (const mapping of approvable) {
1407
+ await this.assertMappingOwnership(crosswalk, String(mapping.localEntry), String(mapping.figshareCategory), connection);
1408
+ if (mapping.status === 'approved') {
1409
+ continue;
1410
+ }
1411
+ await this.runQuery(FigshareVocabularyCrosswalkMapping.updateOne({ id: String(mapping.id) }).set({
1412
+ status: 'approved',
1413
+ approvedAt,
1414
+ approvedBy: ctx.userId
1415
+ }), connection);
1416
+ }
1417
+ await this.runQuery(FigshareVocabularyCrosswalk.updateOne({ id: String(crosswalk.id) }).set({
1418
+ status: 'approved',
1419
+ approvedRevision: Number(crosswalk.workingRevision),
1420
+ approvedAt,
1421
+ approvedBy: ctx.userId,
1422
+ updatedBy: ctx.userId
1423
+ }), connection);
1424
+ const refreshed = await this.runQuery(FigshareVocabularyCrosswalk.findOne({ id: String(crosswalk.id) }), connection);
1425
+ return this.describeCrosswalk(refreshed ?? crosswalk);
1426
+ }, {
1427
+ logger: sails.log,
1428
+ unsupportedAdapterWarning: 'Transactions are not supported by this datastore adapter. Falling back to non-transactional crosswalk approval.'
1429
+ });
1430
+ }
1431
+ /**
1432
+ * Collect the dotted paths of every crosswalk binding in a config that selects
1433
+ * `crosswalkId`. A crosswalk can now be referenced by any binding, not just the
1434
+ * categories one, so the whole config tree has to be walked.
1435
+ */
1436
+ collectCrosswalkBindings(node, crosswalkId, pathSegments, found) {
1437
+ if (node == null || typeof node !== 'object') {
1438
+ return;
1439
+ }
1440
+ if (Array.isArray(node)) {
1441
+ node.forEach((item, index) => this.collectCrosswalkBindings(item, crosswalkId, [...pathSegments, String(index)], found));
1442
+ return;
1443
+ }
1444
+ const candidate = node;
1445
+ if (candidate.kind === 'crosswalk' && String(candidate.crosswalkId ?? '') === crosswalkId) {
1446
+ found.push({
1447
+ bindingPath: pathSegments.join('.'),
1448
+ outputs: candidate.outputs == null ? undefined : String(candidate.outputs),
1449
+ sourceVocabularyId: candidate.sourceVocabularyId == null ? undefined : String(candidate.sourceVocabularyId)
1450
+ });
1451
+ }
1452
+ for (const [key, value] of Object.entries(candidate)) {
1453
+ this.collectCrosswalkBindings(value, crosswalkId, [...pathSegments, key], found);
1454
+ }
1455
+ }
1456
+ /** Report the Figshare publishing bindings that select this crosswalk. */
1457
+ async getCrosswalkUsage(crosswalkId, ctx) {
1458
+ const crosswalk = await this.requireCrosswalk(crosswalkId, ctx.brandId);
1459
+ const appConfigService = sails.services?.appconfigservice;
1460
+ const brandName = this.resolveBrandName(ctx.brandId);
1461
+ const brandConfig = appConfigService?.getAppConfigurationForBrand?.(brandName);
1462
+ const figsharePublishing = brandConfig?.figsharePublishing;
1463
+ const found = [];
1464
+ this.collectCrosswalkBindings(figsharePublishing, String(crosswalk.id), [], found);
1465
+ return found.map((binding) => ({
1466
+ brandName,
1467
+ configKey: 'figsharePublishing',
1468
+ bindingPath: binding.bindingPath,
1469
+ outputs: binding.outputs,
1470
+ sourceVocabularyId: binding.sourceVocabularyId
1471
+ }));
1472
+ }
1473
+ /** Draft crosswalks are deleted; approved ones archive to protect AppConfig references. */
1474
+ async deleteCrosswalk(crosswalkId, ctx) {
1475
+ const crosswalk = await this.requireCrosswalk(crosswalkId, ctx.brandId);
1476
+ const usage = await this.getCrosswalkUsage(crosswalkId, ctx);
1477
+ if (usage.length > 0) {
1478
+ throw new vocabulary_errors_1.RelationshipBoundaryError('This crosswalk is selected by a Figshare publishing configuration. Remove or replace the reference first.');
1479
+ }
1480
+ if (crosswalk.status === 'approved') {
1481
+ await FigshareVocabularyCrosswalk.updateOne({ id: String(crosswalk.id) }).set({
1482
+ status: 'archived',
1483
+ updatedBy: ctx.userId
1484
+ });
1485
+ return;
1486
+ }
1487
+ await FigshareVocabularyCrosswalkMapping.destroy({ crosswalk: String(crosswalk.id) });
1488
+ await FigshareVocabularyCrosswalk.destroyOne({ id: String(crosswalk.id) });
1489
+ }
1490
+ // ── Publishing resolution ─────────────────────────────────────────
1491
+ /**
1492
+ * Resolve record codes to the Figshare categories they map to through the
1493
+ * approved revision of a crosswalk. Working revisions are never consulted.
1494
+ *
1495
+ * Shared by every output mode: the caller decides whether to emit the numeric
1496
+ * category ID, the mirrored label, or the Figshare source ID.
1497
+ */
1498
+ async resolveCrosswalkTargets(input) {
1499
+ const crosswalk = await this.requireCrosswalk(String(input?.crosswalkId ?? ''), String(input?.brandId ?? ''));
1500
+ if (crosswalk.status !== 'approved' || crosswalk.approvedRevision == null) {
1501
+ throw new vocabulary_errors_1.RelationshipBoundaryError('The configured Figshare crosswalk has no approved revision');
1502
+ }
1503
+ const sourceVocabularyId = String(input?.sourceVocabularyId ?? '').trim();
1504
+ if (!sourceVocabularyId || String(crosswalk.localVocabulary) !== sourceVocabularyId) {
1505
+ throw new vocabulary_errors_1.RelationshipBoundaryError('The configured Figshare crosswalk maps a different local vocabulary');
1506
+ }
1507
+ const source = await FigshareVocabularySource.findOne({
1508
+ id: String(crosswalk.figshareSource),
1509
+ branding: String(input.brandId)
1510
+ });
1511
+ if (!source || source.archived === true) {
1512
+ throw new vocabulary_errors_1.RelationshipBoundaryError('The Figshare source behind the configured crosswalk is unavailable');
1513
+ }
1514
+ const codes = Array.from(new Set((input?.codes ?? []).map((code) => (0, categories_1.normalizeCategoryCode)(code)).filter((code) => code !== '')));
1515
+ if (codes.length === 0) {
1516
+ return { normalizedCodes: [], matches: [], unresolvedCodes: [], historicalTargets: [] };
1517
+ }
1518
+ const entries = await VocabularyEntry.find({ vocabulary: sourceVocabularyId });
1519
+ const entryByCode = new Map();
1520
+ for (const entry of entries) {
1521
+ const valueCode = (0, categories_1.normalizeCategoryCode)(entry.valueLower ?? entry.value);
1522
+ if (valueCode !== '' && !entryByCode.has(valueCode)) {
1523
+ entryByCode.set(valueCode, entry);
1524
+ }
1525
+ const identifierCode = (0, categories_1.normalizeCategoryCode)(entry.identifier);
1526
+ if (identifierCode !== '' && !entryByCode.has(identifierCode)) {
1527
+ entryByCode.set(identifierCode, entry);
1528
+ }
1529
+ }
1530
+ const unresolvedCodes = [];
1531
+ const matchedEntryIdsByCode = new Map();
1532
+ for (const code of codes) {
1533
+ const entry = entryByCode.get(code);
1534
+ if (!entry) {
1535
+ unresolvedCodes.push(code);
1536
+ continue;
1537
+ }
1538
+ matchedEntryIdsByCode.set(code, String(entry.id));
1539
+ }
1540
+ if (matchedEntryIdsByCode.size === 0) {
1541
+ return { normalizedCodes: codes, matches: [], unresolvedCodes, historicalTargets: [] };
1542
+ }
1543
+ const mappings = await FigshareVocabularyCrosswalkMapping.find({
1544
+ crosswalk: String(crosswalk.id),
1545
+ revision: Number(crosswalk.approvedRevision),
1546
+ status: 'approved',
1547
+ localEntry: Array.from(new Set(matchedEntryIdsByCode.values()))
1548
+ });
1549
+ if (mappings.length === 0) {
1550
+ return {
1551
+ normalizedCodes: codes,
1552
+ matches: [],
1553
+ unresolvedCodes: [...unresolvedCodes, ...matchedEntryIdsByCode.keys()],
1554
+ historicalTargets: []
1555
+ };
1556
+ }
1557
+ const categories = await FigshareVocabularyCategory.find({
1558
+ id: Array.from(new Set(mappings.map((mapping) => String(mapping.figshareCategory))))
1559
+ });
1560
+ const categoryById = new Map(categories.map((category) => [String(category.id), category]));
1561
+ const mappingsByEntryId = new Map();
1562
+ for (const mapping of mappings) {
1563
+ const entryId = String(mapping.localEntry);
1564
+ const bucket = mappingsByEntryId.get(entryId);
1565
+ if (bucket) {
1566
+ bucket.push(mapping);
1567
+ }
1568
+ else {
1569
+ mappingsByEntryId.set(entryId, [mapping]);
1570
+ }
1571
+ }
1572
+ // Walk in code order so every output mode returns a deterministic sequence
1573
+ // that follows the record's own ordering.
1574
+ const matches = [];
1575
+ const historicalTargets = [];
1576
+ for (const [code, entryId] of matchedEntryIdsByCode) {
1577
+ let resolved = false;
1578
+ for (const mapping of mappingsByEntryId.get(entryId) ?? []) {
1579
+ const category = categoryById.get(String(mapping.figshareCategory));
1580
+ if (!category) {
1581
+ continue;
1582
+ }
1583
+ resolved = true;
1584
+ if (category.historical === true) {
1585
+ historicalTargets.push({ code, categoryId: category.categoryId, sourceId: category.sourceId });
1586
+ continue;
1587
+ }
1588
+ matches.push({ code, category });
1589
+ }
1590
+ if (!resolved) {
1591
+ unresolvedCodes.push(code);
1592
+ }
1593
+ }
1594
+ return { normalizedCodes: codes, matches, unresolvedCodes, historicalTargets };
1595
+ }
1596
+ /**
1597
+ * Resolve record category codes to numeric Figshare category IDs. Retained as
1598
+ * the stable narrow surface over {@link resolveCrosswalkValues}.
1599
+ */
1600
+ async resolveCategories(input) {
1601
+ const resolution = await this.resolveCrosswalkTargets(input);
1602
+ const categoryIds = new Set(resolution.matches.map((match) => match.category.categoryId));
1603
+ return {
1604
+ categoryIds: Array.from(categoryIds).sort((left, right) => left - right),
1605
+ unresolvedCodes: resolution.unresolvedCodes,
1606
+ historicalTargets: resolution.historicalTargets
1607
+ };
1608
+ }
1609
+ /**
1610
+ * Resolve record codes through a crosswalk into the values a publishing binding
1611
+ * asks for. Historical targets are excluded from `values` in every mode and
1612
+ * reported separately so the caller can decide whether they are fatal.
1613
+ */
1614
+ async resolveCrosswalkValues(input) {
1615
+ const outputs = input?.outputs || 'categoryId';
1616
+ const resolution = await this.resolveCrosswalkTargets(input);
1617
+ const base = {
1618
+ normalizedCodes: resolution.normalizedCodes,
1619
+ unresolvedCodes: resolution.unresolvedCodes,
1620
+ historicalTargets: resolution.historicalTargets
1621
+ };
1622
+ if (outputs === 'categoryId') {
1623
+ const categoryIds = new Set(resolution.matches.map((match) => match.category.categoryId));
1624
+ return { ...base, values: Array.from(categoryIds).sort((left, right) => left - right) };
1625
+ }
1626
+ if (outputs === 'sourceId') {
1627
+ return { ...base, values: Array.from(new Set(resolution.matches.map((match) => match.category.sourceId))) };
1628
+ }
1629
+ // Labels live on the mirrored VocabularyEntry, not on the category row.
1630
+ const entryIds = Array.from(new Set(resolution.matches.map((match) => String(match.category.entry))));
1631
+ const entries = entryIds.length === 0
1632
+ ? []
1633
+ : await VocabularyEntry.find({ id: entryIds });
1634
+ const labelByEntryId = new Map(entries.map((entry) => [String(entry.id), entry.label]));
1635
+ const labels = new Set();
1636
+ for (const match of resolution.matches) {
1637
+ const label = String(labelByEntryId.get(String(match.category.entry)) ?? '').trim();
1638
+ if (label !== '') {
1639
+ labels.add(label);
1640
+ continue;
1641
+ }
1642
+ // The mapping resolved; only the display label is missing. Falling back to
1643
+ // the source ID keeps the value usable rather than silently dropping it.
1644
+ sails.log.warn(`Figshare crosswalk ${input.crosswalkId}: category ${match.category.sourceId} has no mirrored label, using its source ID`);
1645
+ labels.add(match.category.sourceId);
1646
+ }
1647
+ return { ...base, values: Array.from(labels) };
1648
+ }
1649
+ // ── Bootstrap data ────────────────────────────────────────────────
1650
+ getBootstrapDataPath() {
1651
+ const configuredPath = lodash_1.default.get(sails.config, 'bootstrap.bootstrapDataPath', DEFAULT_BOOTSTRAP_DATA_PATH);
1652
+ return path.resolve(String(configuredPath), 'vocabularies');
1653
+ }
1654
+ /** Overridable seam so unit tests can drive bootstrapData() without touching disk. */
1655
+ getBootstrapFileOps() {
1656
+ return fs;
1657
+ }
1658
+ resolveDefaultBrandingId() {
1659
+ const brandingService = sails.services?.brandingservice;
1660
+ const defaultBrand = brandingService?.getDefault?.();
1661
+ if (defaultBrand && typeof defaultBrand === 'object') {
1662
+ const brand = defaultBrand;
1663
+ const id = brand.id ?? brand._id;
1664
+ if (id != null && String(id).trim() !== '') {
1665
+ return String(id).trim();
1666
+ }
1667
+ }
1668
+ return '';
1669
+ }
1670
+ /**
1671
+ * Declaratively import Figshare taxonomies listed in
1672
+ * `<bootstrapDataPath>/vocabularies/figshare-imports.json` during the Sails lift.
1673
+ *
1674
+ * Each item produces a read-only mirror, an editable local clone, and an approved
1675
+ * identity crosswalk - the state a fresh environment needs for Figshare publishing to
1676
+ * resolve categories without an administrator visiting the admin UI.
1677
+ *
1678
+ * Idempotent: an item whose FigshareVocabularySource already exists is skipped, so a
1679
+ * restart never re-syncs or forks admin-curated crosswalks. Nothing here throws - a
1680
+ * bootstrap importer must not be able to fail the lift.
1681
+ */
1682
+ async bootstrapData() {
1683
+ if (lodash_1.default.get(sails.config, 'vocab.bootstrapFigshareImports') === false) {
1684
+ sails.log.verbose('Skipping Figshare vocabulary bootstrap imports (disabled)');
1685
+ return;
1686
+ }
1687
+ const filePath = path.join(this.getBootstrapDataPath(), FIGSHARE_IMPORTS_FILE);
1688
+ let parsed = null;
1689
+ try {
1690
+ const content = await this.getBootstrapFileOps().readFile(filePath, 'utf8');
1691
+ parsed = JSON.parse(content);
1692
+ }
1693
+ catch (error) {
1694
+ const ioError = error;
1695
+ if (ioError?.code === 'ENOENT') {
1696
+ sails.log.verbose(`Figshare vocabulary bootstrap file not found: ${filePath}`);
1697
+ return;
1698
+ }
1699
+ sails.log.error(`Failed to read Figshare vocabulary bootstrap file: ${FIGSHARE_IMPORTS_FILE}`, error);
1700
+ return;
1701
+ }
1702
+ if (!Array.isArray(parsed?.imports)) {
1703
+ sails.log.error(`Invalid Figshare imports format in bootstrap file: ${FIGSHARE_IMPORTS_FILE}`);
1704
+ return;
1705
+ }
1706
+ const imports = parsed.imports;
1707
+ if (imports.length === 0) {
1708
+ return;
1709
+ }
1710
+ const brandId = this.resolveDefaultBrandingId();
1711
+ if (!brandId) {
1712
+ sails.log.error('Unable to resolve default branding for Figshare vocabulary bootstrap data');
1713
+ return;
1714
+ }
1715
+ // Most deployments have no Figshare configuration at all; resolveClient() would throw
1716
+ // a transport error on every lift, so check first and skip quietly instead.
1717
+ if ((0, config_1.resolveFigshareVocabularyConfig)(this.resolveBrandName(brandId)) == null) {
1718
+ sails.log.verbose('Skipping Figshare vocabulary bootstrap imports: Figshare is not configured for the default brand');
1719
+ return;
1720
+ }
1721
+ const ctx = { brandId, userId: BOOTSTRAP_ACTOR };
1722
+ for (const item of imports) {
1723
+ await this.processBootstrapImport(item, ctx);
1724
+ }
1725
+ }
1726
+ async processBootstrapImport(item, ctx) {
1727
+ const scope = String(item?.scope ?? '').trim().toLowerCase();
1728
+ const taxonomyId = String(item?.taxonomyId ?? '').trim();
1729
+ const localCloneName = String(item?.localCloneName ?? '').trim();
1730
+ const label = `${scope || '?'}:${taxonomyId || '?'}`;
1731
+ if (scope !== 'public' && scope !== 'account') {
1732
+ sails.log.error(`Skipping Figshare bootstrap import with invalid scope '${item?.scope}' (expected 'public' or 'account')`);
1733
+ return;
1734
+ }
1735
+ if (!taxonomyId) {
1736
+ sails.log.error('Skipping Figshare bootstrap import with missing taxonomyId');
1737
+ return;
1738
+ }
1739
+ if (!localCloneName) {
1740
+ sails.log.error(`Skipping Figshare bootstrap import with missing localCloneName: ${label}`);
1741
+ return;
1742
+ }
1743
+ const existing = await FigshareVocabularySource.findOne({
1744
+ branding: ctx.brandId,
1745
+ scope,
1746
+ taxonomyId
1747
+ });
1748
+ if (existing) {
1749
+ sails.log.verbose(`Skipping existing Figshare bootstrap import: ${label}`);
1750
+ return;
1751
+ }
1752
+ try {
1753
+ await (0, PromiseUtils_1.promiseWithTimeout)(this.runBootstrapImport({ scope, taxonomyId, localCloneName, item }, ctx), FIGSHARE_IMPORT_TIMEOUT_MS, `Figshare vocabulary import ${label}`);
1754
+ sails.log.verbose(`Imported Figshare bootstrap vocabulary: ${label}`);
1755
+ }
1756
+ catch (error) {
1757
+ sails.log.error(`Failed Figshare bootstrap import: ${label}`, error);
1758
+ }
1759
+ }
1760
+ async runBootstrapImport(input, ctx) {
1761
+ const localCloneSlug = String(input.item?.localCloneSlug ?? '').trim();
1762
+ const preview = await this.createPreview({
1763
+ scope: input.scope,
1764
+ taxonomyId: input.taxonomyId,
1765
+ createLocalClone: true,
1766
+ localCloneName: input.localCloneName,
1767
+ localCloneSlug: localCloneSlug || undefined
1768
+ }, ctx);
1769
+ // Read the run row directly rather than paging getPreview(), which caps at
1770
+ // MAX_PAGE_SIZE per page - a real taxonomy has thousands of categories. In clone
1771
+ // mode every proposal is an identity match and preselected.
1772
+ const run = await FigshareVocabularySyncRun.findOne({ id: preview.runId });
1773
+ const proposals = (run?.proposals ?? []);
1774
+ const approvedProposalIds = proposals
1775
+ .filter((proposal) => proposal.preselected)
1776
+ .map((proposal) => proposal.proposalId);
1777
+ const result = await this.applyPreview(preview.runId, {
1778
+ remoteHash: preview.remoteHash,
1779
+ approvedProposalIds
1780
+ }, ctx);
1781
+ const crosswalkId = String(result.crosswalkId ?? '');
1782
+ if (!crosswalkId) {
1783
+ throw new Error('Figshare bootstrap import did not produce a crosswalk');
1784
+ }
1785
+ const requestedName = String(input.item?.crosswalkName ?? '').trim();
1786
+ if (requestedName) {
1787
+ // { branding, name } is a unique index, so probe before renaming.
1788
+ const name = await this.uniqueCrosswalkName(requestedName, ctx.brandId);
1789
+ await FigshareVocabularyCrosswalk.updateOne({ id: crosswalkId }).set({
1790
+ name,
1791
+ updatedBy: ctx.userId
1792
+ });
1793
+ }
1794
+ // Mapping edges are written as 'proposed' and resolveCategories() refuses any
1795
+ // crosswalk without an approved revision - approving here is what makes the
1796
+ // bootstrapped crosswalk usable for publishing.
1797
+ await this.approveCrosswalk(crosswalkId, Number(result.crosswalkRevision ?? 1), ctx);
1798
+ }
1799
+ }
1800
+ Services.FigshareVocabularyService = FigshareVocabularyService;
1801
+ })(Services || (exports.Services = Services = {}));
1802
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlnc2hhcmVWb2NhYnVsYXJ5U2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9GaWdzaGFyZVZvY2FidWxhcnlTZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUFzRDtBQVV0RCw2RkFBMkY7QUFDM0Ysb0VBQTJFO0FBQzNFLDREQUErRDtBQUMvRCxxREFBdUM7QUFDdkMsZ0RBQWtDO0FBQ2xDLG9EQUF1QjtBQUN2QixpREFBdUU7QUFFdkUsNkNBQTBGO0FBRTFGLHlEQWtCa0M7QUFDbEMsdUVBT3lDO0FBRXpDLElBQWlCLFFBQVEsQ0FrM0V4QjtBQWwzRUQsV0FBaUIsUUFBUTtJQUN2QixNQUFNLGNBQWMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDM0MsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUM7SUFDL0IsTUFBTSxhQUFhLEdBQUcsR0FBRyxDQUFDO0lBQzFCLE1BQU0sMkJBQTJCLEdBQUcsZ0JBQWdCLENBQUM7SUFDckQsTUFBTSxxQkFBcUIsR0FBRyx1QkFBdUIsQ0FBQztJQUN0RCxNQUFNLDBCQUEwQixHQUFHLE9BQU8sQ0FBQztJQUMzQyxNQUFNLGVBQWUsR0FBRyxnQkFBZ0IsQ0FBQztJQStNekMsTUFBYSx5QkFBMEIsU0FBUSxzQkFBUSxDQUFDLElBQUksQ0FBQyxPQUFPO1FBQy9DLGdCQUFnQixHQUFhO1lBQzlDLG9CQUFvQjtZQUNwQixlQUFlO1lBQ2YsWUFBWTtZQUNaLGNBQWM7WUFDZCxhQUFhO1lBQ2IsYUFBYTtZQUNiLFdBQVc7WUFDWCxzQkFBc0I7WUFDdEIsY0FBYztZQUNkLGdCQUFnQjtZQUNoQixjQUFjO1lBQ2QsbUJBQW1CO1lBQ25CLGlCQUFpQjtZQUNqQiwyQkFBMkI7WUFDM0IsdUJBQXVCO1lBQ3ZCLGNBQWM7WUFDZCxrQkFBa0I7WUFDbEIsaUJBQWlCO1lBQ2pCLG1CQUFtQjtZQUNuQix3QkFBd0I7WUFDeEIsZUFBZTtTQUNoQixDQUFDO1FBRUYscUVBQXFFO1FBRTdELFlBQVk7WUFDbEIsT0FBTyxVQUFVLENBQUMsWUFBWSxFQUFFLEVBQUUsSUFBSSxLQUFLLENBQUMsWUFBWSxFQUFFLEVBQUUsSUFBSSxJQUFJLENBQUM7UUFDdkUsQ0FBQztRQUVPLEtBQUssQ0FBQyxRQUFRLENBQUksS0FBZ0MsRUFBRSxVQUE2QjtZQUN2RixPQUFPLFVBQVUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO1FBQ2hFLENBQUM7UUFFTyxLQUFLLENBQUMsU0FBUyxDQUFJLEtBQWdDLEVBQUUsVUFBNkI7WUFDeEYsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBRU8sTUFBTTtZQUNaLE9BQU8sSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNsQyxDQUFDO1FBRU8sZ0JBQWdCLENBQUMsT0FBZTtZQUN0QyxNQUFNLGVBQWUsR0FBRyxPQUFPLGVBQWUsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDO1lBQzdGLE1BQU0sS0FBSyxHQUFHLGVBQWUsRUFBRSxZQUFZLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN2RCxJQUFJLEtBQUssRUFBRSxJQUFJLElBQUksSUFBSSxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7Z0JBQzVELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM1QixDQUFDO1lBQ0QsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekIsQ0FBQztRQUVPLGVBQWUsQ0FBQyxPQUFlLEVBQUUsYUFBcUI7WUFDNUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2pELE9BQU87Z0JBQ0wsU0FBUyxFQUFFLEVBQUU7Z0JBQ2IsT0FBTztnQkFDUCxTQUFTO2dCQUNULGFBQWE7Z0JBQ2IsYUFBYSxFQUFFLDJCQUEyQjthQUMzQyxDQUFDO1FBQ0osQ0FBQztRQUVEOzs7V0FHRztRQUNLLGFBQWEsQ0FBQyxPQUFlLEVBQUUsS0FBNEI7WUFDakUsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2pELE1BQU0sTUFBTSxHQUFHLElBQUEsd0NBQStCLEVBQUMsU0FBUyxDQUFDLENBQUM7WUFDMUQsSUFBSSxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7Z0JBQ25CLE1BQU0sSUFBSSwwQ0FBc0IsQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1lBQ2hGLENBQUM7WUFDRCxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDcEgsTUFBTSxJQUFJLDBDQUFzQixDQUFDLGdFQUFnRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQzFHLENBQUM7WUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxrQkFBa0IsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNqRixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLFNBQVM7Z0JBQ3RDLENBQUMsQ0FBQyxJQUFBLHdCQUFpQixFQUFDLE1BQU0sQ0FBQztnQkFDM0IsQ0FBQyxDQUFDLElBQUEscUJBQWMsRUFBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDekMsQ0FBQztRQUVPLEtBQUssQ0FBQyxjQUFjLENBQUMsT0FBZSxFQUFFLEtBQTRCO1lBQ3hFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2xELElBQUksQ0FBQztnQkFDSCxPQUFPLEtBQUssS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sTUFBTSxDQUFDLHFCQUFxQixFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sTUFBTSxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDMUcsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxLQUFLLFlBQVksd0JBQWlCLEVBQUUsQ0FBQztvQkFDdkMsK0VBQStFO29CQUMvRSxNQUFNLElBQUksMENBQXNCLENBQzlCLDZDQUE2QyxLQUFLLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLEtBQUssQ0FBQyxVQUFVLEdBQUcsRUFBRSxFQUM5RyxLQUFLLENBQUMsVUFBVSxDQUNqQixDQUFDO2dCQUNKLENBQUM7Z0JBQ0QsTUFBTSxLQUFLLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUVPLFdBQVcsQ0FBQyxLQUFjO1lBQ2hDLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDNUQsSUFBSSxVQUFVLEtBQUssUUFBUSxJQUFJLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDeEQsTUFBTSxJQUFJLHlDQUFxQixDQUFDLDRDQUE0QyxDQUFDLENBQUM7WUFDaEYsQ0FBQztZQUNELE9BQU8sVUFBVSxDQUFDO1FBQ3BCLENBQUM7UUFFTyxXQUFXLENBQUMsS0FBYyxFQUFFLE1BQWUsRUFBRSxZQUFZLEdBQUcsRUFBRTtZQUNwRSxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksWUFBWSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdkUsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzlELE9BQU87Z0JBQ0wsS0FBSyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLElBQUksV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVk7Z0JBQzdHLE1BQU0sRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxJQUFJLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUMvRSxDQUFDO1FBQ0osQ0FBQztRQUVELHFFQUFxRTtRQUU3RCxLQUFLLENBQUMsYUFBYSxDQUFDLFFBQWdCLEVBQUUsT0FBZTtZQUMzRCxNQUFNLE1BQU0sR0FBRyxNQUFNLHdCQUF3QixDQUFDLE9BQU8sQ0FBQztnQkFDcEQsRUFBRSxFQUFFLE1BQU0sQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFO2dCQUNqQyxRQUFRLEVBQUUsT0FBTzthQUNsQixDQUE4QyxDQUFDO1lBQ2hELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDWixNQUFNLElBQUksNkNBQXlCLENBQUMsMkJBQTJCLENBQUMsQ0FBQztZQUNuRSxDQUFDO1lBQ0QsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQztRQUVPLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFtQixFQUFFLE9BQWU7WUFDakUsTUFBTSxTQUFTLEdBQUcsTUFBTSwyQkFBMkIsQ0FBQyxPQUFPLENBQUM7Z0JBQzFELEVBQUUsRUFBRSxNQUFNLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRTtnQkFDcEMsUUFBUSxFQUFFLE9BQU87YUFDbEIsQ0FBaUQsQ0FBQztZQUNuRCxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxJQUFJLDZDQUF5QixDQUFDLDhCQUE4QixDQUFDLENBQUM7WUFDdEUsQ0FBQztZQUNELE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFFTyxLQUFLLENBQUMsc0JBQXNCLENBQUMsWUFBb0IsRUFBRSxPQUFlO1lBQ3hFLE1BQU0sVUFBVSxHQUFHLE1BQU0sVUFBVSxDQUFDLE9BQU8sQ0FBQztnQkFDMUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFO2dCQUNyQyxRQUFRLEVBQUUsT0FBTzthQUNsQixDQUFnQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDaEIsTUFBTSxJQUFJLDZDQUF5QixDQUFDLDRCQUE0QixDQUFDLENBQUM7WUFDcEUsQ0FBQztZQUNELElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDckMsTUFBTSxJQUFJLDZDQUF5QixDQUFDLG1FQUFtRSxDQUFDLENBQUM7WUFDM0csQ0FBQztZQUNELE9BQU8sVUFBVSxDQUFDO1FBQ3BCLENBQUM7UUFFTyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQWEsRUFBRSxPQUFlO1lBQ3JELE1BQU0sR0FBRyxHQUFHLE1BQU0seUJBQXlCLENBQUMsT0FBTyxDQUFDO2dCQUNsRCxFQUFFLEVBQUUsTUFBTSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUU7Z0JBQzlCLFFBQVEsRUFBRSxPQUFPO2FBQ2xCLENBQStDLENBQUM7WUFDakQsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNULE1BQU0sSUFBSSw2Q0FBeUIsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1lBQzNFLENBQUM7WUFDRCxPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUM7UUFFRCx3RUFBd0U7UUFDaEUsS0FBSyxDQUFDLGdCQUFnQixDQUFDLE9BQWU7WUFDNUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzFCLE1BQU0seUJBQXlCLENBQUMsTUFBTSxDQUFDO2dCQUNyQyxRQUFRLEVBQUUsT0FBTztnQkFDakIsS0FBSyxFQUFFLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQztnQkFDaEMsU0FBUyxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRTthQUN4QixDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDL0IsQ0FBQztRQUVPLEtBQUssQ0FBQyxhQUFhLENBQ3pCLEtBQWEsRUFDYixJQUFZLEVBQ1osRUFBVSxFQUNWLFFBQXNELEVBQUUsRUFDeEQsVUFBNkI7WUFFN0IsSUFBSSxDQUFDLElBQUEsc0RBQTBCLEVBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQzFDLE1BQU0sSUFBSSxxQ0FBaUIsQ0FBQyx5Q0FBeUMsSUFBSSxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDM0YsQ0FBQztZQUNELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDakMseUJBQXlCLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQW9DLEVBQy9ILFVBQVUsQ0FDWCxDQUFDO1lBQ0YsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNiLE1BQU0sSUFBSSxxQ0FBaUIsQ0FBQyxxQ0FBcUMsSUFBSSxHQUFHLENBQUMsQ0FBQztZQUM1RSxDQUFDO1FBQ0gsQ0FBQztRQUVELHFFQUFxRTtRQUU5RCxLQUFLLENBQUMsa0JBQWtCLENBQzdCLEtBQXVDLEVBQ3ZDLEdBQWlCO1lBRWpCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzdDLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQzFELE9BQU8sSUFBQSw0QkFBZSxFQUFDLElBQUEsd0NBQTJCLEVBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMzRCxDQUFDO1FBRUQscUVBQXFFO1FBRTdELEtBQUssQ0FBQyxZQUFZLENBQ3hCLE9BQWUsRUFDZixLQUE0QixFQUM1QixVQUFrQjtZQUVsQixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3RELE1BQU0sVUFBVSxHQUFHLElBQUEsd0NBQTJCLEVBQUMsR0FBRyxDQUFDLENBQUM7WUFDcEQsTUFBTSxRQUFRLEdBQUcsSUFBQSw2QkFBZ0IsRUFBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDMUQsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDL0IsTUFBTSxJQUFJLHlDQUFxQixDQUFDLGlEQUFpRCxVQUFVLEdBQUcsQ0FBQyxDQUFDO1lBQ2xHLENBQUM7WUFDRCxJQUFBLHVDQUEwQixFQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMxQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM5RCxDQUFDO1FBRU8sS0FBSyxDQUFDLHNCQUFzQixDQUFDLFFBQWdCO1lBQ25ELE1BQU0sVUFBVSxHQUFHLE1BQU0sMEJBQTBCLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUEyQyxDQUFDO1lBQ3pILE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDbkMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO2dCQUMzQixVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVU7Z0JBQy9CLEtBQUssRUFBRSxFQUFFO2dCQUNULFdBQVcsRUFBRSxRQUFRLENBQUMsV0FBVztnQkFDakMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxVQUFVLEtBQUssSUFBSTthQUN6QyxDQUFDLENBQUMsQ0FBQztRQUNOLENBQUM7UUFFTyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsWUFBb0I7WUFDakQsTUFBTSxPQUFPLEdBQUcsTUFBTSxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxDQUFnQyxDQUFDO1lBQ3hHLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDN0IsRUFBRSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNwQixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUNoQyxVQUFVLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO2dCQUMxQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUNoQyxVQUFVLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO2dCQUMxQyxVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7YUFDN0IsQ0FBQyxDQUFDLENBQUM7UUFDTixDQUFDO1FBRUQ7OztXQUdHO1FBQ0ssS0FBSyxDQUFDLHNCQUFzQixDQUNsQyxPQUFlLEVBQ2YsS0FBNEIsRUFDNUIsVUFBa0I7WUFFbEIsT0FBTyxNQUFNLHdCQUF3QixDQUFDLE9BQU8sQ0FBQztnQkFDNUMsUUFBUSxFQUFFLE9BQU87Z0JBQ2pCLEtBQUs7Z0JBQ0wsVUFBVTthQUNYLENBQThDLENBQUM7UUFDbEQsQ0FBQztRQUVEOzs7V0FHRztRQUNLLEtBQUssQ0FBQyx1QkFBdUIsQ0FDbkMsT0FBZSxFQUNmLGlCQUF5QixFQUN6QixRQUFnQjtZQUVoQixPQUFPLE1BQU0sMkJBQTJCLENBQUMsT0FBTyxDQUFDO2dCQUMvQyxRQUFRLEVBQUUsT0FBTztnQkFDakIsZUFBZSxFQUFFLGlCQUFpQjtnQkFDbEMsY0FBYyxFQUFFLFFBQVE7YUFDekIsQ0FBaUQsQ0FBQztRQUNyRCxDQUFDO1FBRUQ7Ozs7O1dBS0c7UUFDSyxLQUFLLENBQUMsa0JBQWtCLENBQzlCLEtBQXlCLEVBQ3pCLE9BQWUsRUFDZixLQUE2QjtZQU83QixNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsS0FBSyxJQUFJLENBQUM7WUFDekQsTUFBTSxlQUFlLEdBQUcsS0FBSyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2hFLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzNELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3JELE1BQU0saUJBQWlCLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUV2RSxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixJQUFJLGlCQUFpQixJQUFJLGdCQUFnQixFQUFFLENBQUM7b0JBQzFDLE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQyw2RUFBNkUsQ0FBQyxDQUFDO2dCQUNqSCxDQUFDO2dCQUNELE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDcEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ25GLE1BQU0sZUFBZSxHQUFHLE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ3RHLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUN6RSxDQUFDO1lBRUQsSUFBSSxpQkFBaUIsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUMxQyxNQUFNLElBQUkseUNBQXFCLENBQUMsaUVBQWlFLENBQUMsQ0FBQztZQUNyRyxDQUFDO1lBQ0QsSUFBSSxnQkFBZ0IsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDekUsTUFBTSxJQUFJLHlDQUFxQixDQUFDLDREQUE0RCxDQUFDLENBQUM7WUFDaEcsQ0FBQztZQUVELE1BQU0sTUFBTSxHQUFHLFFBQVE7Z0JBQ3JCLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQztnQkFDN0MsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUV2RyxtRkFBbUY7WUFDbkYsNERBQTREO1lBQzVELElBQUksQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLGdCQUFnQixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3ZELE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQyxrRUFBa0UsQ0FBQyxDQUFDO1lBQ3RHLENBQUM7WUFFRCxNQUFNLGVBQWUsR0FBRyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQUMsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUNqSCxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksZUFBZTtnQkFDekMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzVGLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDVCxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQztRQUNsRSxDQUFDO1FBRU0sS0FBSyxDQUFDLGFBQWEsQ0FBQyxLQUF5QixFQUFFLEdBQWlCO1lBQ3JFLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUV6QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztZQUM3QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLFVBQVUsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUMxRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ2hCLE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1lBQzVELENBQUM7WUFFRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN0RSxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFLENBQUM7Z0JBQy9DLE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQyxpRUFBaUUsQ0FBQyxDQUFDO1lBQ3JHLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3pELE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO1lBQ3hHLENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDekUsTUFBTSxVQUFVLEdBQUcsSUFBQSx5QkFBWSxFQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMvQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDOUYsTUFBTSxJQUFJLEdBQXVCLElBQUEsNEJBQWUsRUFBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzFFLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxHQUFHLENBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsV0FBVyxLQUFLLFNBQVMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUNwRixDQUFDO1lBRUYsSUFBSSxTQUFTLEdBQXVCLEVBQUUsQ0FBQztZQUN2QyxJQUFJLHVCQUF1QixHQUFhLEVBQUUsQ0FBQztZQUMzQyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUMxQiw4RUFBOEU7Z0JBQzlFLHdFQUF3RTtnQkFDeEUsU0FBUyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO29CQUN0QyxVQUFVLEVBQUUsU0FBUyxHQUFHLENBQUMsUUFBUSxFQUFFO29CQUNuQyxZQUFZLEVBQUUsRUFBRTtvQkFDaEIsVUFBVSxFQUFFLEdBQUcsQ0FBQyxLQUFLO29CQUNyQixVQUFVLEVBQUUsR0FBRyxDQUFDLFFBQVE7b0JBQ3hCLGNBQWMsRUFBRSxHQUFHLENBQUMsUUFBUTtvQkFDNUIsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLFVBQVU7b0JBQ2hDLFdBQVcsRUFBRSxHQUFHLENBQUMsS0FBSztvQkFDdEIsU0FBUyxFQUFFLFVBQW1CO29CQUM5QixXQUFXLEVBQUUsSUFBSTtvQkFDakIsVUFBVSxFQUFFLEtBQUs7b0JBQ2pCLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBRSx3Q0FBMkIsRUFBRTtpQkFDckYsQ0FBQyxDQUFDLENBQUM7WUFDTixDQUFDO2lCQUFNLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUNoQyxNQUFNLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUNsRixNQUFNLE1BQU0sR0FBRyxJQUFBLDJCQUFjLEVBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxDQUFDLENBQUM7Z0JBQ3BGLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO2dCQUM3Qix1QkFBdUIsR0FBRyxNQUFNLENBQUMsdUJBQXVCLENBQUM7WUFDM0QsQ0FBQztZQUVELE1BQU0sT0FBTyxHQUF1QjtnQkFDbEMsR0FBRyxJQUFJLENBQUMsT0FBTztnQkFDZixRQUFRLEVBQUUsU0FBUyxDQUFDLE1BQU07Z0JBQzFCLFdBQVcsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTTtnQkFDeEUsVUFBVSxFQUFFLHVCQUF1QixDQUFDLE1BQU07Z0JBQzFDLGtCQUFrQixFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTzthQUN6QyxDQUFDO1lBRUYsTUFBTSxTQUFTLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLGNBQWMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3RFLE1BQU0sR0FBRyxHQUFHLE1BQU0seUJBQXlCLENBQUMsTUFBTSxDQUFDO2dCQUNqRCxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU87Z0JBQ3JCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDbkQsS0FBSztnQkFDTCxVQUFVO2dCQUNWLGVBQWUsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDOUUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dCQUM1RCxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO2dCQUN2QyxjQUFjLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksU0FBUztnQkFDdEUsY0FBYyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLFNBQVM7Z0JBQ3RFLGlCQUFpQixFQUFFLHdDQUEyQjtnQkFDOUMsS0FBSyxFQUFFLFdBQVc7Z0JBQ2xCLFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ2pFLFVBQVU7Z0JBQ1Ysa0JBQWtCLEVBQUUsUUFBUSxDQUFDLElBQUk7Z0JBQ2pDLElBQUksRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFO2dCQUNoRCxTQUFTO2dCQUNULE9BQU87Z0JBQ1AsUUFBUSxFQUFFLENBQUMsR0FBRyxRQUFRLENBQUMsUUFBUSxFQUFFLEdBQUcsdUJBQXVCLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLHdCQUF3QixFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hJLFNBQVM7Z0JBQ1QsV0FBVyxFQUFFLEdBQUcsQ0FBQyxNQUFNO2FBQ3hCLENBQUMsQ0FBQyxLQUFLLEVBQXlDLENBQUM7WUFFbEQsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2pDLENBQUM7UUFFTyxhQUFhLENBQUMsR0FBd0M7WUFDNUQsT0FBTztnQkFDTCxLQUFLLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3JCLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztnQkFDeEIsS0FBSyxFQUFFLEdBQUcsQ0FBQyxLQUFLO2dCQUNoQixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7Z0JBQzFCLFFBQVEsRUFBRSxHQUFHLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztnQkFDeEQsaUJBQWlCLEVBQUUsR0FBRyxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUM7Z0JBQ25GLFdBQVcsRUFBRSxHQUFHLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztnQkFDakUsZ0JBQWdCLEVBQUUsR0FBRyxDQUFDLGdCQUFnQixLQUFLLElBQUk7Z0JBQy9DLFFBQVEsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUM7Z0JBQ3BDLFVBQVUsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUM7Z0JBQ3hDLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUztnQkFDeEIsaUJBQWlCLEVBQUUsR0FBRyxDQUFDLGlCQUFpQjtnQkFDeEMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQWtDO2dCQUM3RCxRQUFRLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBYzthQUM1QyxDQUFDO1FBQ0osQ0FBQztRQUVNLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBYSxFQUFFLEtBQXVCLEVBQUUsR0FBaUI7WUFDL0UsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEtBQUssV0FBVyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDO2dCQUMvRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2dCQUN2RSxNQUFNLElBQUksdUNBQW1CLEVBQUUsQ0FBQztZQUNsQyxDQUFDO1lBRUQsTUFBTSxJQUFJLEdBQUcsS0FBSyxFQUFFLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1lBQzNELE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztZQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUUzRCxJQUFJLE9BQWtCLENBQUM7WUFDdkIsSUFBSSxJQUFJLEtBQUssTUFBTSxFQUFFLENBQUM7Z0JBQ3BCLE1BQU0sUUFBUSxHQUFHLENBQUUsR0FBRyxDQUFDLElBQWlELEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUN0RixPQUFPLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO29CQUNoQyxJQUFJLEtBQUssRUFBRSxXQUFXLElBQUksR0FBRyxDQUFDLFdBQVcsS0FBSyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7d0JBQ2hFLE9BQU8sS0FBSyxDQUFDO29CQUNmLENBQUM7b0JBQ0QsSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxRQUFRLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO3dCQUM3RSxPQUFPLEtBQUssQ0FBQztvQkFDZixDQUFDO29CQUNELE9BQU8sSUFBSSxDQUFDO2dCQUNkLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQXVCLENBQUM7Z0JBQzlELE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7b0JBQ3RDLElBQUksS0FBSyxFQUFFLFNBQVMsSUFBSSxRQUFRLENBQUMsU0FBUyxLQUFLLEtBQUssQ0FBQyxTQUFTLEVBQUUsQ0FBQzt3QkFDL0QsT0FBTyxLQUFLLENBQUM7b0JBQ2YsQ0FBQztvQkFDRCxJQUFJLEtBQUssRUFBRSxjQUFjLEtBQUssSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO3dCQUMzRCxPQUFPLEtBQUssQ0FBQztvQkFDZixDQUFDO29CQUNELElBQUksS0FBSyxFQUFFLGNBQWMsS0FBSyxJQUFJLElBQUksUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO3dCQUMzRCxPQUFPLEtBQUssQ0FBQztvQkFDZixDQUFDO29CQUNELElBQUksTUFBTSxFQUFFLENBQUM7d0JBQ1gsTUFBTSxRQUFRLEdBQUcsR0FBRyxRQUFRLENBQUMsVUFBVSxJQUFJLFFBQVEsQ0FBQyxVQUFVLElBQUksUUFBUSxDQUFDLGNBQWMsSUFBSSxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7d0JBQ2xJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7NEJBQy9CLE9BQU8sS0FBSyxDQUFDO3dCQUNmLENBQUM7b0JBQ0gsQ0FBQztvQkFDRCxPQUFPLElBQUksQ0FBQztnQkFDZCxDQUFDLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxNQUFNLGFBQWEsR0FBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFxRDtpQkFDNUYsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxLQUFLLHdCQUF3QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUM7aUJBQ3ZGLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO1lBQ2xELE1BQU0saUJBQWlCLEdBQUcsYUFBYSxDQUFDLE1BQU0sS0FBSyxDQUFDO2dCQUNsRCxDQUFDLENBQUMsRUFBRTtnQkFDSixDQUFDLENBQUMsQ0FBQyxNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLENBQWlDLENBQUEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQ25HLFlBQVksRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDOUIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztvQkFDckMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztpQkFDdEMsQ0FBQyxDQUFDLENBQUM7WUFFTixPQUFPO2dCQUNMLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUM7Z0JBQzFCLElBQUksRUFBRTtvQkFDSixJQUFJO29CQUNKLE9BQU8sRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsS0FBSyxDQUFDO29CQUM5QyxLQUFLLEVBQUUsT0FBTyxDQUFDLE1BQU07b0JBQ3JCLEtBQUs7b0JBQ0wsTUFBTTtpQkFDUDtnQkFDRCxVQUFVLEVBQUUsaUJBQWlCO2FBQzlCLENBQUM7UUFDSixDQUFDO1FBRUQscUVBQXFFO1FBRTdELFdBQVcsQ0FBQyxLQUFhLEVBQUUsUUFBZ0IsRUFBRSxVQUF1QjtZQUMxRSwrRUFBK0U7WUFDL0UsNkVBQTZFO1lBQzdFLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxRQUFRLENBQUM7WUFDdEMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDeEMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDbkMsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1lBQ0QsSUFBSSxTQUFTLEdBQUcsR0FBRyxJQUFJLEtBQUssUUFBUSxHQUFHLENBQUM7WUFDeEMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBQ2YsT0FBTyxVQUFVLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQy9DLFNBQVMsR0FBRyxHQUFHLElBQUksS0FBSyxRQUFRLElBQUksTUFBTSxHQUFHLENBQUM7Z0JBQzlDLE1BQU0sSUFBSSxDQUFDLENBQUM7WUFDZCxDQUFDO1lBQ0QsVUFBVSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUN4QyxPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO1FBRU0sS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFhLEVBQUUsU0FBeUIsRUFBRSxHQUFpQjtZQUNuRixNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUV0RCxJQUFJLEdBQUcsQ0FBQyxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQzVCLDJFQUEyRTtnQkFDM0UsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLElBQUksRUFBRSxDQUEyQixDQUFDO1lBQ3RELENBQUM7WUFDRCxJQUFJLEdBQUcsQ0FBQyxLQUFLLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQzdCLE1BQU0sSUFBSSxxQ0FBaUIsQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO1lBQ3ZFLENBQUM7WUFDRCxJQUFJLEdBQUcsQ0FBQyxLQUFLLEtBQUssV0FBVyxFQUFFLENBQUM7Z0JBQzlCLE1BQU0sSUFBSSxxQ0FBaUIsQ0FBQyxvQkFBb0IsR0FBRyxDQUFDLEtBQUssZ0NBQWdDLENBQUMsQ0FBQztZQUM3RixDQUFDO1lBQ0QsSUFBSSxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7Z0JBQ3BELE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFDakUsTUFBTSxJQUFJLHVDQUFtQixFQUFFLENBQUM7WUFDbEMsQ0FBQztZQUNELElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDLEtBQUssTUFBTSxDQUFDLEdBQUcsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDekUsTUFBTSxJQUFJLHFDQUFpQixDQUFDLDZEQUE2RCxDQUFDLENBQUM7WUFDN0YsQ0FBQztZQUVELE1BQU0sY0FBYyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3JHLElBQUksY0FBYyxJQUFJLE1BQU0sQ0FBQyxjQUFjLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQzdGLE1BQU0sSUFBSSxxQ0FBaUIsQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO1lBQzlGLENBQUM7WUFFRCxNQUFNLGlCQUFpQixHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDakgsSUFBSSxpQkFBaUIsSUFBSSxTQUFTLEVBQUUsZ0JBQWdCLElBQUksSUFBSTttQkFDdkQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO2dCQUN0RixNQUFNLElBQUksMENBQXNCLEVBQUUsQ0FBQztZQUNyQyxDQUFDO1lBRUQsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBRWxFLE1BQU0sVUFBVSxHQUF3RTtnQkFDdEYsWUFBWSxFQUFFLEVBQUU7Z0JBQ2hCLE9BQU8sRUFBRSxFQUFFO2dCQUNYLFVBQVUsRUFBRSxFQUFFO2FBQ2YsQ0FBQztZQUVGLElBQUksQ0FBQztnQkFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUEsNkNBQTBCLEVBQzdDLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFDbkIsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLGNBQWMsRUFBRSxpQkFBaUIsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLEVBQzNIO29CQUNFLE1BQU0sRUFBRSxLQUFLLENBQUMsR0FBRztvQkFDakIseUJBQXlCLEVBQ3ZCLCtIQUErSDtpQkFDbEksQ0FDRixDQUFDO2dCQUNGLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUU7b0JBQzlELFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtvQkFDckIsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTO29CQUMzQixNQUFNLEVBQUUsTUFBTSxDQUFDLFFBQVE7b0JBQ3ZCLFNBQVMsRUFBRSxNQUFNLENBQUMsV0FBVyxJQUFJLElBQUk7b0JBQ3JDLGVBQWUsRUFBRSxNQUFNLENBQUMsaUJBQWlCLElBQUksSUFBSTtvQkFDakQsTUFBTSxFQUFFLE1BQTRDO2lCQUNyRCxDQUFDLENBQUM7Z0JBQ0gsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUNsQyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFO29CQUM3RCxTQUFTLEVBQUcsS0FBMkIsRUFBRSxJQUFJLElBQUksY0FBYztvQkFDL0QsV0FBVyxFQUFHLEtBQWUsRUFBRSxPQUFPLElBQUksa0NBQWtDO2lCQUM3RSxDQUFDLENBQUM7Z0JBQ0gsTUFBTSxLQUFLLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUVELHNFQUFzRTtRQUM5RCxLQUFLLENBQUMsVUFBVSxDQUFDLE9BQTRFO1lBQ25HLElBQUksQ0FBQztnQkFDSCxLQUFLLE1BQU0sV0FBVyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztvQkFDN0MsTUFBTSxrQ0FBa0MsQ0FBQyxPQUFPLENBQUMsRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztvQkFDN0UsTUFBTSwyQkFBMkIsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDcEUsQ0FBQztnQkFDRCxLQUFLLE1BQU0sUUFBUSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDdkMsTUFBTSwwQkFBMEIsQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztvQkFDL0QsTUFBTSx3QkFBd0IsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFDOUQsQ0FBQztnQkFDRCxLQUFLLE1BQU0sWUFBWSxJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQztvQkFDaEQsTUFBTSxlQUFlLENBQUMsT0FBTyxDQUFDLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7b0JBQzVELE1BQU0sVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO2dCQUNwRCxDQUFDO1lBQ0gsQ0FBQztZQUFDLE9BQU8sWUFBWSxFQUFFLENBQUM7Z0JBQ3RCLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLCtDQUErQyxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ2pGLENBQUM7UUFDSCxDQUFDO1FBRU8sS0FBSyxDQUFDLGdCQUFnQixDQUM1QixHQUF3QyxFQUN4QyxTQUF5QixFQUN6QixHQUFpQixFQUNqQixjQUF5RCxFQUN6RCxpQkFBK0QsRUFDL0QsVUFBK0UsRUFDL0UsVUFBNkI7WUFFN0IsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLElBQUksRUFBRSxDQUFpQyxDQUFDO1lBQ2hGLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUVoQywwQ0FBMEM7WUFDMUMsSUFBSSxNQUFNLEdBQUcsY0FBYyxDQUFDO1lBQzVCLElBQUksa0JBQTBCLENBQUM7WUFDL0IsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWCxrQkFBa0IsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ2pELENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLFVBQVUsR0FBRyxZQUFZLEdBQUcsQ0FBQyxLQUFLLGFBQWEsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUN0RSxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQ2pDLFVBQVUsQ0FBQyxNQUFNLENBQUM7b0JBQ2hCLElBQUksRUFBRSxVQUFVO29CQUNoQixXQUFXLEVBQUUsb0NBQW9DLEdBQUcsQ0FBQyxLQUFLLG9DQUFvQyxHQUFHLENBQUMsVUFBVSxFQUFFO29CQUM5RyxJQUFJLEVBQUUsTUFBTTtvQkFDWixNQUFNLEVBQUUsVUFBVTtvQkFDbEIsUUFBUSxFQUFFLEdBQUcsR0FBRyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsVUFBVSxFQUFFO29CQUMxQyxpQkFBaUIsRUFBRSxHQUFHLEdBQUcsQ0FBQyxPQUFPLElBQUksR0FBRyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsVUFBVSxFQUFFO29CQUNsRSxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU87aUJBQ3RCLENBQWlELEVBQ2xELFVBQVUsQ0FDWCxDQUFDO2dCQUNGLGtCQUFrQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ3ZDLFVBQVUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7Z0JBRWpELE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQzNCLHdCQUF3QixDQUFDLE1BQU0sQ0FBQztvQkFDOUIsUUFBUSxFQUFFLEdBQUcsQ0FBQyxPQUFPO29CQUNyQixVQUFVLEVBQUUsa0JBQWtCO29CQUM5QixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7b0JBQ2hCLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVTtvQkFDMUIsV0FBVyxFQUFFLFVBQVU7b0JBQ3ZCLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtvQkFDckIsU0FBUyxFQUFFLEdBQUcsQ0FBQyxNQUFNO2lCQUN0QixDQUErRCxFQUNoRSxVQUFVLENBQ1gsQ0FBQztnQkFDRixVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDN0MsQ0FBQztZQUNELE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFFbkMsMkZBQTJGO1lBQzNGLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQztZQUV6Ryx1Q0FBdUM7WUFDdkMsSUFBSSxpQkFBaUIsR0FBRyxHQUFHLENBQUMsZUFBZSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ3pGLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztZQUN6QixJQUFJLG9CQUFvQixHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1lBQ3JELElBQUksR0FBRyxDQUFDLGdCQUFnQixLQUFLLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQ3hELE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUM1QyxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFDdkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxjQUFjLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQ3ZDLFFBQVEsRUFDUixHQUFHLEVBQ0gsVUFBVSxDQUNYLENBQUM7Z0JBQ0YsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQztnQkFDdkMsb0JBQW9CLEdBQUcsS0FBSyxDQUFDLGVBQWUsQ0FBQztnQkFDN0MsWUFBWSxHQUFHLElBQUksQ0FBQztnQkFDcEIsVUFBVSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNsRCxDQUFDO1lBRUQsa0NBQWtDO1lBQ2xDLElBQUksV0FBVyxHQUFrQixpQkFBaUIsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDekYsSUFBSSxpQkFBaUIsR0FBa0IsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzVHLElBQUksWUFBWSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFFOUMsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO2dCQUN0QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQ2pCLDhFQUE4RTtvQkFDOUUsa0ZBQWtGO29CQUNsRixJQUFJLFVBQVUsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDekQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO3dCQUNoQixNQUFNLGVBQWUsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ3pDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsQ0FBd0QsRUFDcEcsVUFBVSxDQUNYLENBQUM7d0JBQ0YsVUFBVSxHQUFHLE1BQU0sQ0FBQyxlQUFlLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO29CQUMxRCxDQUFDO29CQUNELE1BQU0sYUFBYSxHQUFHLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUNsRCxHQUFHLFVBQVUsSUFBSSxXQUFXLHdCQUF3QixHQUFHLENBQUMsVUFBVSxFQUFFLEVBQ3BFLEdBQUcsQ0FBQyxPQUFPLEVBQ1gsVUFBVSxDQUNYLENBQUM7b0JBQ0YsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUNwQywyQkFBMkIsQ0FBQyxNQUFNLENBQUM7d0JBQ2pDLFFBQVEsRUFBRSxHQUFHLENBQUMsT0FBTzt3QkFDckIsSUFBSSxFQUFFLGFBQWE7d0JBQ25CLGVBQWUsRUFBRSxpQkFBaUI7d0JBQ2xDLGNBQWMsRUFBRSxRQUFRO3dCQUN4QixNQUFNLEVBQUUsT0FBTzt3QkFDZixlQUFlLEVBQUUsQ0FBQzt3QkFDbEIsU0FBUyxFQUFFLEdBQUcsQ0FBQyxNQUFNO3FCQUN0QixDQUFrRSxFQUNuRSxVQUFVLENBQ1gsQ0FBQztvQkFDRixXQUFXLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDbkMsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDO29CQUN0QixVQUFVLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDMUMsQ0FBQztnQkFFRCxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQ3pDLFdBQVcsRUFDWCxpQkFBaUIsSUFBSSxDQUFDLEVBQ3RCLEdBQUcsRUFDSCxTQUFTLEVBQ1QsUUFBUSxFQUNSLGlCQUFpQixFQUNqQixvQkFBb0IsRUFDcEIsR0FBRyxFQUNILFVBQVUsQ0FDWCxDQUFDO1lBQ0osQ0FBQztZQUVELG9CQUFvQjtZQUNwQixNQUFNLElBQUksQ0FBQyxRQUFRLENBQ2pCLHdCQUF3QixDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztnQkFDdkQsVUFBVSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQztnQkFDeEMsWUFBWSxFQUFFLFNBQVM7Z0JBQ3ZCLFdBQVcsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDM0IsU0FBUyxFQUFFLEdBQUcsQ0FBQyxNQUFNO2FBQ3RCLENBQW9DLEVBQ3JDLFVBQVUsQ0FDWCxDQUFDO1lBRUYsT0FBTztnQkFDTCxLQUFLLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3JCLEtBQUssRUFBRSxTQUFTO2dCQUNoQixRQUFRO2dCQUNSLFlBQVksRUFBRSxrQkFBa0I7Z0JBQ2hDLGlCQUFpQjtnQkFDakIsV0FBVztnQkFDWCxpQkFBaUI7Z0JBQ2pCLFVBQVUsRUFBRSxXQUFXO2dCQUN2QixRQUFRLEVBQUUsWUFBWTtnQkFDdEIsWUFBWTtnQkFDWixTQUFTO2FBQ1YsQ0FBQztRQUNKLENBQUM7UUFFTyxLQUFLLENBQUMsVUFBVSxDQUN0QixRQUFnQixFQUNoQixrQkFBMEIsRUFDMUIsUUFBK0MsRUFDL0MsU0FBaUIsRUFDakIsVUFBNkI7WUFFN0IsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQzVDLDBCQUEwQixDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBOEUsRUFDbEksVUFBVSxDQUNYLENBQUM7WUFDRixNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUV4RyxNQUFNLGVBQWUsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ3pDLGVBQWUsQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsa0JBQWtCLEVBQUUsQ0FBbUUsRUFDMUgsVUFBVSxDQUNYLENBQUM7WUFDRixNQUFNLFVBQVUsR0FBRyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDM0YsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRXZILE1BQU0sS0FBSyxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ3ZFLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7WUFFcEQsS0FBSyxNQUFNLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxRQUFRLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDdEQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUNkLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO29CQUNwRSxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQ2hDLGVBQWUsQ0FBQyxNQUFNLENBQUM7d0JBQ3JCLFVBQVUsRUFBRSxrQkFBa0I7d0JBQzlCLEtBQUs7d0JBQ0wsS0FBSyxFQUFFLEdBQUcsQ0FBQyxRQUFRO3dCQUNuQixVQUFVLEVBQUUsR0FBRyxDQUFDLFFBQVE7d0JBQ3hCLEtBQUssRUFBRSxDQUFDO3dCQUNSLFVBQVUsRUFBRSxLQUFLO3FCQUNsQixDQUFzRCxFQUN2RCxVQUFVLENBQ1gsQ0FBQztvQkFDRixpQkFBaUIsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7b0JBQ3RELE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FDbEIsMEJBQTBCLENBQUMsTUFBTSxDQUFDO3dCQUNoQyxNQUFNLEVBQUUsUUFBUTt3QkFDaEIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO3dCQUN2QixRQUFRLEVBQUUsR0FBRyxDQUFDLFFBQVE7d0JBQ3RCLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVTt3QkFDMUIsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVO3dCQUMxQixjQUFjLEVBQUUsR0FBRyxDQUFDLGNBQWMsSUFBSSxTQUFTO3dCQUMvQyxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUk7d0JBQ2QsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVO3dCQUMxQixVQUFVLEVBQUUsS0FBSzt3QkFDakIsV0FBVyxFQUFFLFNBQVM7d0JBQ3RCLFVBQVUsRUFBRSxTQUFTO3dCQUNyQixXQUFXLEVBQUUsR0FBRyxDQUFDLFdBQVc7cUJBQzdCLENBQWlFLEVBQ2xFLFVBQVUsQ0FDWCxDQUFDO29CQUNGLEtBQUssQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDO29CQUNuQixTQUFTO2dCQUNYLENBQUM7Z0JBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDdkMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQzdDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDO2dCQUNuRCxJQUFJLGFBQWEsRUFBRSxDQUFDO29CQUNsQixLQUFLLENBQUMsVUFBVSxJQUFJLENBQUMsQ0FBQztnQkFDeEIsQ0FBQztxQkFBTSxJQUFJLFFBQVEsQ0FBQyxXQUFXLEtBQUssR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO29CQUNwRCxLQUFLLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQztnQkFDckIsQ0FBQztnQkFFRCxJQUFJLGFBQWEsSUFBSSxRQUFRLENBQUMsV0FBVyxLQUFLLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztvQkFDOUQsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUNqQixlQUFlLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDO3dCQUM3QyxLQUFLLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUM7d0JBQ3RFLFVBQVUsRUFBRSxLQUFLO3FCQUNsQixDQUFvQyxFQUNyQyxVQUFVLENBQ1gsQ0FBQztnQkFDSixDQUFDO2dCQUNELE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDakIsMEJBQTBCLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztvQkFDcEUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVO29CQUMxQixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7b0JBQzFCLGNBQWMsRUFBRSxHQUFHLENBQUMsY0FBYyxJQUFJLFNBQVM7b0JBQy9DLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSTtvQkFDZCxVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7b0JBQzFCLFVBQVUsRUFBRSxLQUFLO29CQUNqQixVQUFVLEVBQUUsU0FBUztvQkFDckIsV0FBVyxFQUFFLEdBQUcsQ0FBQyxXQUFXO2lCQUM3QixDQUFvQyxFQUNyQyxVQUFVLENBQ1gsQ0FBQztZQUNKLENBQUM7WUFFRCwwRUFBMEU7WUFDMUUsTUFBTSxlQUFlLEdBQUcsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDckUsS0FBSyxNQUFNLFFBQVEsSUFBSSxrQkFBa0IsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLGVBQWUsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssSUFBSSxFQUFFLENBQUM7b0JBQzNFLFNBQVM7Z0JBQ1gsQ0FBQztnQkFDRCxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ2pCLDBCQUEwQixDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQW9DLEVBQzlILFVBQVUsQ0FDWCxDQUFDO2dCQUNGLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDakIsZUFBZSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQW9DLEVBQ3RILFVBQVUsQ0FDWCxDQUFDO2dCQUNGLEtBQUssQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDO1lBQ3hCLENBQUM7WUFFRCwwRUFBMEU7WUFDMUUsS0FBSyxNQUFNLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUM3RixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ2IsU0FBUztnQkFDWCxDQUFDO2dCQUNELE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQyxjQUFjLElBQUksSUFBSTtvQkFDOUMsQ0FBQyxDQUFDLElBQUk7b0JBQ04sQ0FBQyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLElBQUksbUJBQW1CLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsSUFBSSxJQUFJLENBQUM7Z0JBQ3JHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDakIsZUFBZSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxhQUFhLEVBQUUsQ0FBb0MsRUFDNUcsVUFBVSxDQUNYLENBQUM7WUFDSixDQUFDO1lBRUQsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRU8sZUFBZSxDQUNyQixHQUErQixFQUMvQixlQUFxRCxFQUNyRCxPQUFlLEVBQ2YsVUFBdUI7WUFFdkIsTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxPQUFPLENBQUMsQ0FBQztZQUM5RSxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsVUFBVSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzVELElBQUksaUJBQWlCLEtBQUssR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO2dCQUNsRCxPQUFPLEdBQUcsQ0FBQyxLQUFLLENBQUM7WUFDbkIsQ0FBQztZQUNELFVBQVUsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUNyQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFFTyxLQUFLLENBQUMscUJBQXFCLENBQ2pDLElBQVksRUFDWixJQUFZLEVBQ1osUUFBK0MsRUFDL0MsR0FBaUIsRUFDakIsVUFBNkI7WUFFN0IsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNWLE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQyxpRUFBaUUsQ0FBQyxDQUFDO1lBQ3JHLENBQUM7WUFDRCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQ2hDLFVBQVUsQ0FBQyxNQUFNLENBQUM7Z0JBQ2hCLElBQUk7Z0JBQ0osR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN6QixXQUFXLEVBQUUsc0RBQXNEO2dCQUNuRSxJQUFJLEVBQUUsTUFBTTtnQkFDWixNQUFNLEVBQUUsT0FBTztnQkFDZixRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU87YUFDdEIsQ0FBaUQsRUFDbEQsVUFBVSxDQUNYLENBQUM7WUFDRixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBRXRDLE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7WUFDckMsTUFBTSxlQUFlLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7WUFDbEQsS0FBSyxNQUFNLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUNoQyxlQUFlLENBQUMsTUFBTSxDQUFDO29CQUNyQixVQUFVLEVBQUUsWUFBWTtvQkFDeEIsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQztvQkFDNUQsS0FBSyxFQUFFLEdBQUcsQ0FBQyxRQUFRO29CQUNuQixVQUFVLEVBQUUsR0FBRyxDQUFDLFFBQVE7b0JBQ3hCLEtBQUssRUFBRSxDQUFDO29CQUNSLFVBQVUsRUFBRSxLQUFLO2lCQUNsQixDQUFzRCxFQUN2RCxVQUFVLENBQ1gsQ0FBQztnQkFDRixlQUFlLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RELENBQUM7WUFFRCxnRkFBZ0Y7WUFDaEYsS0FBSyxNQUFNLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ2xELE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQyxjQUFjLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxJQUFJLElBQUksQ0FBQztnQkFDckcsSUFBSSxDQUFDLE9BQU8sSUFBSSxRQUFRLElBQUksSUFBSSxFQUFFLENBQUM7b0JBQ2pDLFNBQVM7Z0JBQ1gsQ0FBQztnQkFDRCxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ2pCLGVBQWUsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQW9DLEVBQ3ZHLFVBQVUsQ0FDWCxDQUFDO1lBQ0osQ0FBQztZQUVELE9BQU8sRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLENBQUM7UUFDM0MsQ0FBQztRQUVPLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxJQUFZLEVBQUUsT0FBZSxFQUFFLFVBQTZCO1lBQzVGLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQztZQUNyQixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7WUFDZix1RkFBdUY7WUFDdkYsT0FBTyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ3hCLDJCQUEyQixDQUFDLE9BQU8sQ0FBQyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFvQyxFQUM5RyxVQUFVLENBQ1gsRUFBRSxDQUFDO2dCQUNGLFNBQVMsR0FBRyxHQUFHLElBQUksS0FBSyxNQUFNLEdBQUcsQ0FBQztnQkFDbEMsTUFBTSxJQUFJLENBQUMsQ0FBQztZQUNkLENBQUM7WUFDRCxPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO1FBRU8sS0FBSyxDQUFDLGlCQUFpQixDQUM3QixXQUFtQixFQUNuQixRQUFnQixFQUNoQixHQUF3QyxFQUN4QyxTQUF5QixFQUN6QixRQUFnQixFQUNoQixpQkFBeUIsRUFDekIsb0JBQXlDLEVBQ3pDLEdBQWlCLEVBQ2pCLFVBQTZCO1lBRTdCLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDcEMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUE4RSxFQUNsSSxVQUFVLENBQ1gsQ0FBQztZQUNGLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVoRyxNQUFNLG1CQUFtQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLG1CQUFtQixJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwRyxNQUFNLFNBQVMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUF1QixDQUFDO1lBQzlELE1BQU0sWUFBWSxHQUFHLElBQUksR0FBRyxFQUEyRSxDQUFDO1lBRXhHLE1BQU0sT0FBTyxHQUFHLENBQUMsWUFBb0IsRUFBRSxnQkFBd0IsRUFBRSxTQUFpQixFQUFRLEVBQUU7Z0JBQzFGLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2dCQUMxRCxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQy9CLE9BQU87Z0JBQ1QsQ0FBQztnQkFDRCxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsWUFBWSxLQUFLLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDMUQsWUFBWTtvQkFDWixVQUFVLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7b0JBQy9CLFNBQVM7aUJBQ1YsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDO1lBRUYsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLEVBQUUsQ0FBQztnQkFDakMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztvQkFDbEQsU0FBUztnQkFDWCxDQUFDO2dCQUNELE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxZQUFZO3VCQUNyQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQzt1QkFDakQsRUFBRSxDQUFDO2dCQUNSLE9BQU8sQ0FBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLGNBQWMsRUFBRSxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDckUsQ0FBQztZQUVELE1BQU0sY0FBYyxHQUFHLFNBQVMsRUFBRSxjQUFjLElBQUksRUFBRSxDQUFDO1lBQ3ZELElBQUksY0FBYyxDQUFDLE1BQU0sR0FBRyxpQkFBaUIsRUFBRSxDQUFDO2dCQUM5QyxNQUFNLElBQUkseUNBQXFCLENBQUMsb0RBQW9ELGlCQUFpQixFQUFFLENBQUMsQ0FBQztZQUMzRyxDQUFDO1lBQ0QsS0FBSyxNQUFNLE9BQU8sSUFBSSxjQUFjLEVBQUUsQ0FBQztnQkFDckMsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFO3VCQUN6RCxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7dUJBQ3BFLEVBQUUsQ0FBQztnQkFDUixLQUFLLE1BQU0sY0FBYyxJQUFJLE9BQU8sQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLEVBQUUsQ0FBQztvQkFDN0QsT0FBTyxDQUFDLFlBQVksRUFBRSxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ2pFLENBQUM7WUFDSCxDQUFDO1lBRUQsSUFBSSxZQUFZLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUMxQixNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUM5RyxNQUFNLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ3RDLGVBQWUsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxDQUFtRSxFQUM1SSxVQUFVLENBQ1gsQ0FBQztnQkFDRixNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNsRixLQUFLLE1BQU0sSUFBSSxJQUFJLFlBQVksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO29CQUN6QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO3dCQUMvQyxNQUFNLElBQUksNkNBQXlCLENBQUMsMkVBQTJFLENBQUMsQ0FBQztvQkFDbkgsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztZQUVELE1BQU0sYUFBYSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDdkMsa0NBQWtDLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsQ0FBc0YsRUFDbEssVUFBVSxDQUNYLENBQUM7WUFDRixNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRTFILElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztZQUNoQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLElBQUksWUFBWSxFQUFFLENBQUM7Z0JBQ3ZDLElBQUksWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUMxQixTQUFTO2dCQUNYLENBQUM7Z0JBQ0QsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUNsQixrQ0FBa0MsQ0FBQyxNQUFNLENBQUM7b0JBQ3hDLFNBQVMsRUFBRSxXQUFXO29CQUN0QixRQUFRO29CQUNSLFVBQVUsRUFBRSxJQUFJLENBQUMsWUFBWTtvQkFDN0IsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFVBQVU7b0JBQ2pDLE1BQU0sRUFBRSxVQUFVO29CQUNsQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7aUJBQzFCLENBQXlFLEVBQzFFLFVBQVUsQ0FDWCxDQUFDO2dCQUNGLE9BQU8sSUFBSSxDQUFDLENBQUM7WUFDZixDQUFDO1lBRUQsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUNqQiwyQkFBMkIsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFvQyxFQUM1SCxVQUFVLENBQ1gsQ0FBQztZQUVGLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQ2pDLENBQUM7UUFFRCxxRUFBcUU7UUFFOUQsS0FBSyxDQUFDLFdBQVcsQ0FDdEIsS0FBc0UsRUFDdEUsR0FBaUI7WUFFakIsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUM1RSxNQUFNLEtBQUssR0FBNEIsRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pFLElBQUksS0FBSyxFQUFFLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxFQUFFLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDNUQsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBQzVCLENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUM3QyxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLEtBQUssQ0FBQyxXQUFXLEdBQUcsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDM0MsQ0FBQztZQUNELE1BQU0sS0FBSyxHQUFHLE1BQU0sd0JBQXdCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzFELE1BQU0sT0FBTyxHQUFHLE1BQU0sd0JBQXdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztpQkFDdkQsSUFBSSxDQUFDLGlCQUFpQixDQUFDO2lCQUN2QixJQUFJLENBQUMsTUFBTSxDQUFDO2lCQUNaLEtBQUssQ0FBQyxLQUFLLENBQXlDLENBQUM7WUFDeEQsTUFBTSxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3JGLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ2xELENBQUM7UUFFTSxLQUFLLENBQUMsU0FBUyxDQUFDLFFBQWdCLEVBQUUsR0FBaUI7WUFDeEQsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDOUUsQ0FBQztRQUVEOzs7O1dBSUc7UUFDSSxLQUFLLENBQUMsb0JBQW9CLENBQy9CLFFBQWdCLEVBQ2hCLEtBQTZHLEVBQzdHLEdBQWlCO1lBRWpCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9ELE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFFNUUsTUFBTSxLQUFLLEdBQTRCLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUNyRSxJQUFJLEtBQUssRUFBRSxpQkFBaUIsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDdEMsS0FBSyxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7WUFDM0IsQ0FBQztZQUNELElBQUksS0FBSyxFQUFFLGNBQWMsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDbkMsS0FBSyxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7WUFDMUIsQ0FBQztZQUNELE1BQU0sVUFBVSxHQUFHLE1BQU0sMEJBQTBCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBMkMsQ0FBQztZQUMxRyxNQUFNLGNBQWMsR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUVqRSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUMzRCxNQUFNLElBQUksR0FBRyxVQUFVO2lCQUNwQixHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ2xCLEVBQUUsRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDdkIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO2dCQUNuQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7Z0JBQ3ZDLEtBQUssRUFBRSxjQUFjLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztnQkFDOUUsY0FBYyxFQUFFLFFBQVEsQ0FBQyxjQUFjO2dCQUN2QyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsS0FBSyxLQUFLO2dCQUN6QyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsS0FBSyxJQUFJO2FBQ3pDLENBQUMsQ0FBQztpQkFDRixNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTTttQkFDbkIsR0FBRyxHQUFHLENBQUMsS0FBSyxJQUFJLEdBQUcsQ0FBQyxRQUFRLElBQUksR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztpQkFDcEYsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRXBHLE9BQU87Z0JBQ0wsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxLQUFLLENBQUM7Z0JBQ3hDLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUU7YUFDNUMsQ0FBQztRQUNKLENBQUM7UUFFRCwwRkFBMEY7UUFDbEYsS0FBSyxDQUFDLGtCQUFrQixDQUM5QixVQUFrRDtZQUVsRCxJQUFJLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQzVCLE9BQU8sSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNuQixDQUFDO1lBQ0QsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNGLE1BQU0sT0FBTyxHQUFHLE1BQU0sZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBZ0MsQ0FBQztZQUM1RixPQUFPLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RixDQUFDO1FBRU8sS0FBSyxDQUFDLGNBQWMsQ0FBQyxNQUEwQztZQUNyRSxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ25DLE1BQU0sQ0FBQyxhQUFhLEVBQUUsZUFBZSxFQUFFLGNBQWMsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztnQkFDekUsMEJBQTBCLENBQUMsS0FBSyxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLENBQUM7Z0JBQ3pFLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO2dCQUN4RSwyQkFBMkIsQ0FBQyxLQUFLLENBQUMsRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLENBQUM7YUFDaEUsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxVQUFVLEdBQUcsTUFBTSxVQUFVLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBZ0MsQ0FBQztZQUM5RyxPQUFPO2dCQUNMLEVBQUUsRUFBRSxRQUFRO2dCQUNaLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztnQkFDL0IsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLO2dCQUNuQixVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVU7Z0JBQzdCLFlBQVksRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQztnQkFDdkMsY0FBYyxFQUFFLFVBQVUsRUFBRSxJQUFJLElBQUksRUFBRTtnQkFDdEMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxZQUFZLElBQUksSUFBSTtnQkFDekMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEtBQUssSUFBSTtnQkFDbEMsYUFBYTtnQkFDYixlQUFlO2dCQUNmLGNBQWM7YUFDZixDQUFDO1FBQ0osQ0FBQztRQUVNLEtBQUssQ0FBQyxZQUFZLENBQ3ZCLEtBQTZELEVBQzdELEdBQWlCO1lBRWpCLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDNUUsTUFBTSxLQUFLLEdBQTRCLEVBQUUsUUFBUSxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNqRSxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN0RCxJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUNiLEtBQUssQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDO1lBQzFCLENBQUM7WUFDRCxNQUFNLEtBQUssR0FBRyxNQUFNLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMzRCxNQUFNLElBQUksR0FBRyxNQUFNLHlCQUF5QixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7aUJBQ3JELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztpQkFDdEIsSUFBSSxDQUFDLE1BQU0sQ0FBQztpQkFDWixLQUFLLENBQUMsS0FBSyxDQUEwQyxDQUFDO1lBQ3pELE9BQU87Z0JBQ0wsSUFBSSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQ3ZCLEVBQUUsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDbEIsS0FBSyxFQUFFLEdBQUcsQ0FBQyxLQUFLO29CQUNoQixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7b0JBQ2hCLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVTtvQkFDMUIsUUFBUSxFQUFFLEdBQUcsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDO29CQUN4RCxPQUFPLEVBQUUsR0FBRyxDQUFDLE9BQU8sSUFBSSxFQUFFO29CQUMxQixXQUFXLEVBQUUsR0FBRyxDQUFDLFdBQVc7b0JBQzVCLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUyxJQUFJLElBQUk7b0JBQ2hDLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUyxJQUFJLElBQUk7b0JBQ2hDLFNBQVMsRUFBRSxHQUFHLENBQUMsU0FBUztvQkFDeEIsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTLElBQUksSUFBSTtpQkFDakMsQ0FBQyxDQUFDO2dCQUNILElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFO2FBQy9CLENBQUM7UUFDSixDQUFDO1FBRUQ7OztXQUdHO1FBQ0ksS0FBSyxDQUFDLFdBQVcsQ0FDdEIsUUFBZ0IsRUFDaEIsVUFBMkMsRUFDM0MsR0FBaUI7WUFFakIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDL0QsTUFBTSxVQUFVLEdBQUcsTUFBTSwwQkFBMEIsQ0FBQyxJQUFJLENBQUM7Z0JBQ3ZELE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztnQkFDekIsVUFBVSxFQUFFLEtBQUs7YUFDbEIsQ0FBMkMsQ0FBQztZQUM3QyxJQUFJLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQzVCLE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1lBQzVGLENBQUM7WUFDRCxNQUFNLFFBQVEsR0FBaUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDM0UsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO2dCQUMzQixVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVU7Z0JBQy9CLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVTtnQkFDL0IsS0FBSyxFQUFFLEVBQUU7Z0JBQ1QsY0FBYyxFQUFFLFFBQVEsQ0FBQyxjQUFjLElBQUksSUFBSTtnQkFDL0MsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO2dCQUMxQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsS0FBSyxLQUFLO2dCQUN6QyxXQUFXLEVBQUUsS0FBSztnQkFDbEIsV0FBVyxFQUFFLFFBQVEsQ0FBQyxXQUFXO2FBQ2xDLENBQUMsQ0FBQyxDQUFDO1lBQ0osTUFBTSxPQUFPLEdBQUcsTUFBTSxlQUFlLENBQUMsSUFBSSxDQUFDO2dCQUN6QyxFQUFFLEVBQUUsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUN6RCxDQUFnQyxDQUFDO1lBQ2xDLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN0RyxLQUFLLE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLElBQUksVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7Z0JBQ3JELFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQztZQUMxRixDQUFDO1lBRUQsTUFBTSxVQUFVLEdBQXdFO2dCQUN0RixZQUFZLEVBQUUsRUFBRTtnQkFDaEIsT0FBTyxFQUFFLEVBQUU7Z0JBQ1gsVUFBVSxFQUFFLEVBQUU7YUFDZixDQUFDO1lBRUYsSUFBSSxDQUFDO2dCQUNILE9BQU8sTUFBTSxJQUFBLDZDQUEwQixFQUNyQyxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQ25CLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRTtvQkFDbkIsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQzVDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUNyQyxNQUFNLENBQUMsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFDckMsUUFBUSxFQUNSLEdBQUcsRUFDSCxVQUFVLENBQ1gsQ0FBQztvQkFDRixVQUFVLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7b0JBRWpELE1BQU0sYUFBYSxHQUFHLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUNsRCxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDLFdBQVcsRUFBRSxFQUMzRCxHQUFHLENBQUMsT0FBTyxFQUNYLFVBQVUsQ0FDWCxDQUFDO29CQUNGLE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FDcEMsMkJBQTJCLENBQUMsTUFBTSxDQUFDO3dCQUNqQyxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU87d0JBQ3JCLElBQUksRUFBRSxhQUFhO3dCQUNuQixlQUFlLEVBQUUsS0FBSyxDQUFDLFlBQVk7d0JBQ25DLGNBQWMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQzt3QkFDakMsTUFBTSxFQUFFLE9BQU87d0JBQ2YsZUFBZSxFQUFFLENBQUM7d0JBQ2xCLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtxQkFDdEIsQ0FBa0UsRUFDbkUsVUFBVSxDQUNYLENBQUM7b0JBQ0YsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO29CQUVqRCxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQzt3QkFDbEcsRUFBRSxFQUFFLE9BQU87d0JBQ1gsS0FBSyxFQUFFLEVBQUU7d0JBQ1QsVUFBVSxFQUFFLEVBQUU7d0JBQ2QsS0FBSyxFQUFFLGFBQWE7d0JBQ3BCLFVBQVUsRUFBRSxhQUFhLENBQUMsV0FBVyxFQUFFO3dCQUN2QyxRQUFRLEVBQUUsYUFBYTtxQkFDeEIsQ0FBQyxDQUFDLENBQUM7b0JBQ0osTUFBTSxRQUFRLEdBQUcsSUFBQSxtQ0FBc0IsRUFBQyxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUM7b0JBQ2hFLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDaEcsS0FBSyxNQUFNLFFBQVEsSUFBSSxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7d0JBQzFDLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLENBQUM7d0JBQ2pFLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQzs0QkFDZCxTQUFTO3dCQUNYLENBQUM7d0JBQ0QsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUNsQixrQ0FBa0MsQ0FBQyxNQUFNLENBQUM7NEJBQ3hDLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQzs0QkFDL0IsUUFBUSxFQUFFLENBQUM7NEJBQ1gsVUFBVSxFQUFFLFFBQVEsQ0FBQyxZQUFZOzRCQUNqQyxnQkFBZ0IsRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQzs0QkFDckMsTUFBTSxFQUFFLFVBQVU7NEJBQ2xCLFNBQVMsRUFBRSxVQUFVO3lCQUN0QixDQUFvQyxFQUNyQyxVQUFVLENBQ1gsQ0FBQztvQkFDSixDQUFDO29CQUVELE9BQU87d0JBQ0wsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLFlBQVk7d0JBQ3JDLFdBQVcsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQzt3QkFDakMsT0FBTyxFQUFFLEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBSTtxQkFDcEMsQ0FBQztnQkFDSixDQUFDLEVBQ0Q7b0JBQ0UsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHO29CQUNqQix5QkFBeUIsRUFDdkIsb0hBQW9IO2lCQUN2SCxDQUNGLENBQUM7WUFDSixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ2xDLE1BQU0sS0FBSyxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUM7UUFFRCxxRUFBcUU7UUFFOUQsS0FBSyxDQUFDLGNBQWMsQ0FDekIsS0FBc0gsRUFDdEgsR0FBaUI7WUFFakIsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztZQUM1RSxNQUFNLEtBQUssR0FBNEIsRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pFLElBQUksS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDO2dCQUNsQixLQUFLLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdEMsQ0FBQztZQUNELElBQUksS0FBSyxFQUFFLGlCQUFpQixFQUFFLENBQUM7Z0JBQzdCLEtBQUssQ0FBQyxlQUFlLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzFELENBQUM7WUFDRCxJQUFJLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FBQztnQkFDcEIsS0FBSyxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2hELENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUM3QyxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLEtBQUssQ0FBQyxJQUFJLEdBQUcsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDcEMsQ0FBQztZQUNELE1BQU0sS0FBSyxHQUFHLE1BQU0sMkJBQTJCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzdELE1BQU0sVUFBVSxHQUFHLE1BQU0sMkJBQTJCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztpQkFDN0QsSUFBSSxDQUFDLFVBQVUsQ0FBQztpQkFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FBQztpQkFDWixLQUFLLENBQUMsS0FBSyxDQUE0QyxDQUFDO1lBQzNELE1BQU0sSUFBSSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pHLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ2xELENBQUM7UUFFTSxLQUFLLENBQUMsWUFBWSxDQUFDLFdBQW1CLEVBQUUsR0FBaUI7WUFDOUQsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3ZGLENBQUM7UUFFTyxLQUFLLENBQUMsaUJBQWlCLENBQUMsU0FBZ0Q7WUFDOUUsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztnQkFDbEQsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQXlDO2dCQUNyRyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUF1RDthQUNqSSxDQUFDLENBQUM7WUFDSCxNQUFNLENBQUMsb0JBQW9CLEVBQUUsbUJBQW1CLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7Z0JBQ3BFLFNBQVMsQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJO29CQUNoQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7b0JBQ3BCLENBQUMsQ0FBQyxrQ0FBa0MsQ0FBQyxLQUFLLENBQUM7d0JBQ3pDLFNBQVMsRUFBRSxXQUFXO3dCQUN0QixRQUFRLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQzt3QkFDNUMsTUFBTSxFQUFFLFVBQVU7cUJBQ25CLENBQUM7Z0JBQ0osa0NBQWtDLENBQUMsS0FBSyxDQUFDLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO2FBQ2xILENBQUMsQ0FBQztZQUVILE1BQU0scUJBQXFCLEdBQUcsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQUMsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBRXhGLE9BQU87Z0JBQ0wsRUFBRSxFQUFFLFdBQVc7Z0JBQ2YsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJO2dCQUNwQixNQUFNLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7Z0JBQ2hDLGVBQWUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQztnQkFDbEQsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLGdCQUFnQixJQUFJLElBQUk7Z0JBQ3BELFVBQVUsRUFBRSxTQUFTLENBQUMsVUFBVTtnQkFDaEMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxVQUFVO2dCQUNoQyxpQkFBaUIsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQztnQkFDcEQsbUJBQW1CLEVBQUUsZUFBZSxFQUFFLElBQUksSUFBSSxFQUFFO2dCQUNoRCxnQkFBZ0IsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQztnQkFDbEQsa0JBQWtCLEVBQUUsTUFBTSxFQUFFLFdBQVcsSUFBSSxFQUFFO2dCQUM3QyxLQUFLLEVBQUUsTUFBTSxDQUFDLE1BQU0sRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUNsQyxVQUFVLEVBQUUsTUFBTSxDQUFDLE1BQU0sRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDO2dCQUM1QyxvQkFBb0I7Z0JBQ3BCLG1CQUFtQjtnQkFDbkIscUJBQXFCO2FBQ3RCLENBQUM7UUFDSixDQUFDO1FBRU8sS0FBSyxDQUFDLHNCQUFzQixDQUNsQyxXQUFtQixFQUNuQixTQUFnRDtZQUVoRCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLGdCQUFnQixJQUFJLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNqRixNQUFNLFFBQVEsR0FBRyxNQUFNLGtDQUFrQyxDQUFDLElBQUksQ0FBQztnQkFDN0QsU0FBUyxFQUFFLFdBQVc7Z0JBQ3RCLFFBQVE7YUFDVCxDQUFtRCxDQUFDO1lBQ3JELElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDMUIsT0FBTyxDQUFDLENBQUM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDckcsT0FBTywwQkFBMEIsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pGLENBQUM7UUFFTSxLQUFLLENBQUMsZUFBZSxDQUMxQixLQUFvRSxFQUNwRSxHQUFpQjtZQUVqQixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUM5QyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ1YsTUFBTSxJQUFJLHlDQUFxQixDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDdEQsQ0FBQztZQUNELE1BQU0sZUFBZSxHQUFHLE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9HLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFFBQVEsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEYsTUFBTSxRQUFRLEdBQUcsTUFBTSwyQkFBMkIsQ0FBQyxPQUFPLENBQUMsRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzVGLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxJQUFJLDZDQUF5QixDQUFDLHNCQUFzQixJQUFJLGlDQUFpQyxDQUFDLENBQUM7WUFDbkcsQ0FBQztZQUNELE1BQU0sU0FBUyxHQUFHLE1BQU0sMkJBQTJCLENBQUMsTUFBTSxDQUFDO2dCQUN6RCxRQUFRLEVBQUUsR0FBRyxDQUFDLE9BQU87Z0JBQ3JCLElBQUk7Z0JBQ0osZUFBZSxFQUFFLE1BQU0sQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO2dCQUMzQyxjQUFjLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQ2pDLE1BQU0sRUFBRSxPQUFPO2dCQUNmLGVBQWUsRUFBRSxDQUFDO2dCQUNsQixTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU07YUFDdEIsQ0FBQyxDQUFDLEtBQUssRUFBMkMsQ0FBQztZQUNwRCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMzQyxDQUFDO1FBRUQ7Ozs7V0FJRztRQUNJLEtBQUssQ0FBQyx5QkFBeUIsQ0FDcEMsV0FBbUIsRUFDbkIsS0FBMEYsRUFDMUYsR0FBaUI7WUFFakIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4RSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzVFLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxJQUFJLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUV0RSxNQUFNLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztnQkFDNUMsZUFBZSxDQUFDLElBQUksQ0FBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQXlDO2dCQUMvRyxrQ0FBa0MsQ0FBQyxJQUFJLENBQUM7b0JBQ3RDLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztvQkFDL0IsUUFBUTtpQkFDVCxDQUE0RDthQUM5RCxDQUFDLENBQUM7WUFFSCxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1lBQ3ZELEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQy9CLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3ZDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDMUUsQ0FBQztZQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzNELE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3RFLE1BQU0sSUFBSSxHQUFHLE9BQU87aUJBQ2pCLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDZixFQUFFLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3BCLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ2hDLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ2hDLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTtnQkFDNUIsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVLEtBQUssSUFBSTtnQkFDckMsV0FBVyxFQUFFLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQzthQUM3RCxDQUFDLENBQUM7aUJBQ0YsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztpQkFDdEYsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ2QsSUFBSSxZQUFZLEtBQUssVUFBVSxFQUFFLENBQUM7b0JBQ2hDLE9BQU8sR0FBRyxDQUFDLFdBQVcsS0FBSyxDQUFDLENBQUM7Z0JBQy9CLENBQUM7Z0JBQ0QsSUFBSSxZQUFZLEtBQUssUUFBUSxFQUFFLENBQUM7b0JBQzlCLE9BQU8sR0FBRyxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7Z0JBQzdCLENBQUM7Z0JBQ0QsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDLENBQUM7aUJBQ0QsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFaEUsT0FBTztnQkFDTCxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLEtBQUssQ0FBQztnQkFDeEMsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUU7YUFDdEQsQ0FBQztRQUNKLENBQUM7UUFFTSxLQUFLLENBQUMscUJBQXFCLENBQ2hDLFdBQW1CLEVBQ25CLEtBQTBGLEVBQzFGLEdBQWlCO1lBRWpCLE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3hFLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxJQUFJLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUV0RSxNQUFNLEtBQUssR0FBNEIsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQztZQUNyRixJQUFJLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQztnQkFDbEIsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RDLENBQUM7WUFDRCxNQUFNLFFBQVEsR0FBRyxNQUFNLGtDQUFrQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQW1ELENBQUM7WUFFeEgsTUFBTSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7Z0JBQzlDLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQztvQkFDbkIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBaUMsQ0FBQztvQkFDcEQsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQXlDO2dCQUNwSixRQUFRLENBQUMsTUFBTSxLQUFLLENBQUM7b0JBQ25CLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQTRDLENBQUM7b0JBQy9ELENBQUMsQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBb0Q7YUFDakwsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxTQUFTLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM3RSxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTVGLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzNELE1BQU0sSUFBSSxHQUFHLFFBQVE7aUJBQ2xCLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUNmLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO2dCQUN4RCxNQUFNLFFBQVEsR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO2dCQUNwRSxPQUFPO29CQUNMLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDdEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO29CQUMxQixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07b0JBQ3RCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztvQkFDNUIsWUFBWSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDO29CQUN4QyxVQUFVLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDO29CQUN0QyxVQUFVLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDO29CQUN0QyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDO29CQUNwRCxnQkFBZ0IsRUFBRSxNQUFNLENBQUMsUUFBUSxFQUFFLFFBQVEsSUFBSSxFQUFFLENBQUM7b0JBQ2xELHNCQUFzQixFQUFFLFFBQVEsRUFBRSxVQUFVLElBQUksSUFBSTtvQkFDcEQsVUFBVSxFQUFFLFFBQVEsRUFBRSxVQUFVLEtBQUssSUFBSTtvQkFDekMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLElBQUksSUFBSTtvQkFDdEMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLElBQUksSUFBSTtpQkFDdkMsQ0FBQztZQUNKLENBQUMsQ0FBQztpQkFDRCxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFVBQVUsSUFBSSxHQUFHLENBQUMsVUFBVSxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztpQkFDeEgsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFFMUUsT0FBTztnQkFDTCxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLEtBQUssQ0FBQztnQkFDeEMsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUU7YUFDdEQsQ0FBQztRQUNKLENBQUM7UUFFRDs7OztXQUlHO1FBQ0ksS0FBSyxDQUFDLFlBQVksQ0FDdkIsV0FBbUIsRUFDbkIsS0FBOEQsRUFDOUQsR0FBaUI7WUFFakIsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4RSxNQUFNLE9BQU8sR0FBRyxLQUFLLEVBQUUsT0FBTyxJQUFJLEVBQUUsQ0FBQztZQUNyQyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsaUJBQWlCLEVBQUUsQ0FBQztnQkFDdkMsTUFBTSxJQUFJLHlDQUFxQixDQUFDLDZDQUE2QyxpQkFBaUIsRUFBRSxDQUFDLENBQUM7WUFDcEcsQ0FBQztZQUNELElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsS0FBSyxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2xFLE1BQU0sSUFBSSwwQ0FBc0IsRUFBRSxDQUFDO1lBQ3JDLENBQUM7WUFFRCxPQUFPLElBQUEsNkNBQTBCLEVBQy9CLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFDbkIsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFO2dCQUNuQixJQUFJLGVBQWUsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUN4RCxJQUFJLFNBQVMsQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLGVBQWUsRUFBRSxDQUFDO29CQUNqRyxlQUFlLElBQUksQ0FBQyxDQUFDO29CQUNyQixNQUFNLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ3RDLGtDQUFrQyxDQUFDLElBQUksQ0FBQzt3QkFDdEMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO3dCQUMvQixRQUFRLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQztxQkFDN0MsQ0FBc0YsRUFDdkYsVUFBVSxDQUNYLENBQUM7b0JBQ0YsS0FBSyxNQUFNLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQzt3QkFDL0IsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUNsQixrQ0FBa0MsQ0FBQyxNQUFNLENBQUM7NEJBQ3hDLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQzs0QkFDL0IsUUFBUSxFQUFFLGVBQWU7NEJBQ3pCLFVBQVUsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQzs0QkFDbEMsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQzs0QkFDOUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNOzRCQUNsQixTQUFTLEVBQUUsR0FBRyxDQUFDLFNBQVM7NEJBQ3hCLFFBQVEsRUFBRSxHQUFHLENBQUMsUUFBUTs0QkFDdEIsVUFBVSxFQUFFLEdBQUcsQ0FBQyxVQUFVOzRCQUMxQixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7eUJBQzNCLENBQW9DLEVBQ3JDLFVBQVUsQ0FDWCxDQUFDO29CQUNKLENBQUM7b0JBQ0QsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUNqQiwyQkFBMkIsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsZUFBZSxFQUFFLENBQW9DLEVBQy9ILFVBQVUsQ0FDWCxDQUFDO2dCQUNKLENBQUM7Z0JBRUQsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztvQkFDN0IsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxZQUFZLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQy9ELE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxrQkFBa0IsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDM0UsSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7d0JBQ3pDLE1BQU0sSUFBSSx5Q0FBcUIsQ0FBQywwREFBMEQsQ0FBQyxDQUFDO29CQUM5RixDQUFDO29CQUNELE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsRUFBRSxZQUFZLEVBQUUsa0JBQWtCLEVBQUUsVUFBVSxDQUFDLENBQUM7b0JBRTNGLElBQUksTUFBTSxDQUFDLEVBQUUsS0FBSyxRQUFRLEVBQUUsQ0FBQzt3QkFDM0IsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUNqQixrQ0FBa0MsQ0FBQyxPQUFPLENBQUM7NEJBQ3pDLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQzs0QkFDL0IsUUFBUSxFQUFFLGVBQWU7NEJBQ3pCLFVBQVUsRUFBRSxZQUFZOzRCQUN4QixnQkFBZ0IsRUFBRSxrQkFBa0I7eUJBQ3JDLENBQStDLEVBQ2hELFVBQVUsQ0FDWCxDQUFDO3dCQUNGLFNBQVM7b0JBQ1gsQ0FBQztvQkFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ2xDLGtDQUFrQyxDQUFDLE9BQU8sQ0FBQzt3QkFDekMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO3dCQUMvQixRQUFRLEVBQUUsZUFBZTt3QkFDekIsVUFBVSxFQUFFLFlBQVk7d0JBQ3hCLGdCQUFnQixFQUFFLGtCQUFrQjtxQkFDckMsQ0FBZ0YsRUFDakYsVUFBVSxDQUNYLENBQUM7b0JBQ0YsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sSUFBSSxVQUFVLENBQUM7b0JBQzNDLE1BQU0sYUFBYSxHQUFHLE1BQU0sS0FBSyxVQUFVO3dCQUN6QyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFO3dCQUN2RCxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsQ0FBQztvQkFDckQsSUFBSSxRQUFRLEVBQUUsQ0FBQzt3QkFDYixNQUFNLElBQUksQ0FBQyxRQUFRLENBQ2pCLGtDQUFrQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUM7NEJBQzVFLE1BQU07NEJBQ04sU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLFNBQVM7NEJBQ2pELEdBQUcsYUFBYTt5QkFDakIsQ0FBb0MsRUFDckMsVUFBVSxDQUNYLENBQUM7d0JBQ0YsU0FBUztvQkFDWCxDQUFDO29CQUNELE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FDbEIsa0NBQWtDLENBQUMsTUFBTSxDQUFDO3dCQUN4QyxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7d0JBQy9CLFFBQVEsRUFBRSxlQUFlO3dCQUN6QixVQUFVLEVBQUUsWUFBWTt3QkFDeEIsZ0JBQWdCLEVBQUUsa0JBQWtCO3dCQUNwQyxNQUFNO3dCQUNOLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxJQUFJLFFBQVE7d0JBQ3ZDLEdBQUcsYUFBYTtxQkFDakIsQ0FBb0MsRUFDckMsVUFBVSxDQUNYLENBQUM7Z0JBQ0osQ0FBQztnQkFFRCxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ2pCLDJCQUEyQixDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFvQyxFQUNySSxVQUFVLENBQ1gsQ0FBQztnQkFFRixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ25DLDJCQUEyQixDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQXlFLEVBQ3pJLFVBQVUsQ0FDWCxDQUFDO2dCQUNGLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsQ0FBQztZQUN4RCxDQUFDLEVBQ0Q7Z0JBQ0UsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHO2dCQUNqQix5QkFBeUIsRUFDdkIscUhBQXFIO2FBQ3hILENBQ0YsQ0FBQztRQUNKLENBQUM7UUFFTyxLQUFLLENBQUMsc0JBQXNCLENBQ2xDLFNBQWdELEVBQ2hELFlBQW9CLEVBQ3BCLGtCQUEwQixFQUMxQixVQUE2QjtZQUU3QixNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQy9CLGVBQWUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQTZELEVBQ3hKLFVBQVUsQ0FDWCxDQUFDO1lBQ0YsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNYLE1BQU0sSUFBSSw2Q0FBeUIsQ0FBQyxtRUFBbUUsQ0FBQyxDQUFDO1lBQzNHLENBQUM7WUFDRCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ2xDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUF3RSxFQUMvSyxVQUFVLENBQ1gsQ0FBQztZQUNGLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDZCxNQUFNLElBQUksNkNBQXlCLENBQUMsK0RBQStELENBQUMsQ0FBQztZQUN2RyxDQUFDO1FBQ0gsQ0FBQztRQUVEOzs7V0FHRztRQUNJLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFtQixFQUFFLFFBQWdCLEVBQUUsR0FBaUI7WUFDcEYsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4RSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxNQUFNLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7Z0JBQzNELE1BQU0sSUFBSSwwQ0FBc0IsRUFBRSxDQUFDO1lBQ3JDLENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLGtDQUFrQyxDQUFDLElBQUksQ0FBQztnQkFDN0QsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUMvQixRQUFRLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUM7YUFDNUMsQ0FBbUQsQ0FBQztZQUNyRCxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxLQUFLLFVBQVUsQ0FBQyxDQUFDO1lBQy9FLElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsTUFBTSxJQUFJLHlDQUFxQixDQUFDLGtGQUFrRixDQUFDLENBQUM7WUFDdEgsQ0FBQztZQUVELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQyxPQUFPLElBQUEsNkNBQTBCLEVBQy9CLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFDbkIsS0FBSyxFQUFFLFVBQVUsRUFBRSxFQUFFO2dCQUNuQixLQUFLLE1BQU0sT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDO29CQUNqQyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7b0JBQ3ZILElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQzt3QkFDbEMsU0FBUztvQkFDWCxDQUFDO29CQUNELE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDakIsa0NBQWtDLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQzt3QkFDM0UsTUFBTSxFQUFFLFVBQVU7d0JBQ2xCLFVBQVU7d0JBQ1YsVUFBVSxFQUFFLEdBQUcsQ0FBQyxNQUFNO3FCQUN2QixDQUFvQyxFQUNyQyxVQUFVLENBQ1gsQ0FBQztnQkFDSixDQUFDO2dCQUNELE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FDakIsMkJBQTJCLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztvQkFDdEUsTUFBTSxFQUFFLFVBQVU7b0JBQ2xCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDO29CQUNuRCxVQUFVO29CQUNWLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTTtvQkFDdEIsU0FBUyxFQUFFLEdBQUcsQ0FBQyxNQUFNO2lCQUN0QixDQUFvQyxFQUNyQyxVQUFVLENBQ1gsQ0FBQztnQkFDRixNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQ25DLDJCQUEyQixDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQXlFLEVBQ3pJLFVBQVUsQ0FDWCxDQUFDO2dCQUNGLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsQ0FBQztZQUN4RCxDQUFDLEVBQ0Q7Z0JBQ0UsTUFBTSxFQUFFLEtBQUssQ0FBQyxHQUFHO2dCQUNqQix5QkFBeUIsRUFDdkIsaUhBQWlIO2FBQ3BILENBQ0YsQ0FBQztRQUNKLENBQUM7UUFFRDs7OztXQUlHO1FBQ0ssd0JBQXdCLENBQzlCLElBQWEsRUFDYixXQUFtQixFQUNuQixZQUFzQixFQUN0QixLQUFvRjtZQUVwRixJQUFJLElBQUksSUFBSSxJQUFJLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQzdDLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ3hCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxDQUFDLEdBQUcsWUFBWSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQ3pILE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBK0IsQ0FBQztZQUNsRCxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssV0FBVyxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQyxLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUMxRixLQUFLLENBQUMsSUFBSSxDQUFDO29CQUNULFdBQVcsRUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQztvQkFDbkMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDO29CQUMxRSxrQkFBa0IsRUFBRSxTQUFTLENBQUMsa0JBQWtCLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsa0JBQWtCLENBQUM7aUJBQzVHLENBQUMsQ0FBQztZQUNMLENBQUM7WUFDRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUNyRCxJQUFJLENBQUMsd0JBQXdCLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxDQUFDLEdBQUcsWUFBWSxFQUFFLEdBQUcsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ25GLENBQUM7UUFDSCxDQUFDO1FBRUQsMEVBQTBFO1FBQ25FLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxXQUFtQixFQUFFLEdBQWlCO1lBQ25FLE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEUsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFFLGdCQUU1QixDQUFDO1lBQ2QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNyRCxNQUFNLFdBQVcsR0FBRyxnQkFBZ0IsRUFBRSwyQkFBMkIsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQy9FLE1BQU0sa0JBQWtCLEdBQUcsV0FBVyxFQUFFLGtCQUFrQixDQUFDO1lBQzNELE1BQU0sS0FBSyxHQUFrRixFQUFFLENBQUM7WUFDaEcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ25GLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDN0IsU0FBUztnQkFDVCxTQUFTLEVBQUUsb0JBQW9CO2dCQUMvQixXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVc7Z0JBQ2hDLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztnQkFDeEIsa0JBQWtCLEVBQUUsT0FBTyxDQUFDLGtCQUFrQjthQUMvQyxDQUFDLENBQUMsQ0FBQztRQUNOLENBQUM7UUFFRCwyRkFBMkY7UUFDcEYsS0FBSyxDQUFDLGVBQWUsQ0FBQyxXQUFtQixFQUFFLEdBQWlCO1lBQ2pFLE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEUsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQzdELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxJQUFJLDZDQUF5QixDQUNqQywyR0FBMkcsQ0FDNUcsQ0FBQztZQUNKLENBQUM7WUFDRCxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3BDLE1BQU0sMkJBQTJCLENBQUMsU0FBUyxDQUFDLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztvQkFDNUUsTUFBTSxFQUFFLFVBQVU7b0JBQ2xCLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTTtpQkFDdEIsQ0FBQyxDQUFDO2dCQUNILE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxrQ0FBa0MsQ0FBQyxPQUFPLENBQUMsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDdEYsTUFBTSwyQkFBMkIsQ0FBQyxVQUFVLENBQUMsRUFBRSxFQUFFLEVBQUUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDN0UsQ0FBQztRQUVELHFFQUFxRTtRQUVyRTs7Ozs7O1dBTUc7UUFDSyxLQUFLLENBQUMsdUJBQXVCLENBQUMsS0FBNkI7WUFDakUsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxXQUFXLElBQUksRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5RyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssVUFBVSxJQUFJLFNBQVMsQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDMUUsTUFBTSxJQUFJLDZDQUF5QixDQUFDLDREQUE0RCxDQUFDLENBQUM7WUFDcEcsQ0FBQztZQUNELE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxrQkFBa0IsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUMxRSxJQUFJLENBQUMsa0JBQWtCLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsS0FBSyxrQkFBa0IsRUFBRSxDQUFDO2dCQUNwRixNQUFNLElBQUksNkNBQXlCLENBQUMscUVBQXFFLENBQUMsQ0FBQztZQUM3RyxDQUFDO1lBQ0QsTUFBTSxNQUFNLEdBQUcsTUFBTSx3QkFBd0IsQ0FBQyxPQUFPLENBQUM7Z0JBQ3BELEVBQUUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQztnQkFDcEMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDO2FBQ2hDLENBQThDLENBQUM7WUFDaEQsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsUUFBUSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUN4QyxNQUFNLElBQUksNkNBQXlCLENBQUMsb0VBQW9FLENBQUMsQ0FBQztZQUM1RyxDQUFDO1lBRUQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFBLGtDQUFxQixFQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pJLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDdkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsRUFBRSxFQUFFLGlCQUFpQixFQUFFLEVBQUUsRUFBRSxDQUFDO1lBQzFGLENBQUM7WUFFRCxNQUFNLE9BQU8sR0FBRyxNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsa0JBQWtCLEVBQUUsQ0FBZ0MsQ0FBQztZQUM5RyxNQUFNLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBcUMsQ0FBQztZQUNqRSxLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUM1QixNQUFNLFNBQVMsR0FBRyxJQUFBLGtDQUFxQixFQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN6RSxJQUFJLFNBQVMsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7b0JBQ3BELFdBQVcsQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNwQyxDQUFDO2dCQUNELE1BQU0sY0FBYyxHQUFHLElBQUEsa0NBQXFCLEVBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUMvRCxJQUFJLGNBQWMsS0FBSyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7b0JBQzlELFdBQVcsQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN6QyxDQUFDO1lBQ0gsQ0FBQztZQUVELE1BQU0sZUFBZSxHQUFhLEVBQUUsQ0FBQztZQUNyQyxNQUFNLHFCQUFxQixHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1lBQ3hELEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3BDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDWCxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUMzQixTQUFTO2dCQUNYLENBQUM7Z0JBQ0QscUJBQXFCLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDcEQsQ0FBQztZQUNELElBQUkscUJBQXFCLENBQUMsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNyQyxPQUFPLEVBQUUsZUFBZSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEVBQUUsQ0FBQztZQUN6RixDQUFDO1lBRUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxrQ0FBa0MsQ0FBQyxJQUFJLENBQUM7Z0JBQzdELFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztnQkFDL0IsUUFBUSxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUM7Z0JBQzVDLE1BQU0sRUFBRSxVQUFVO2dCQUNsQixVQUFVLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO2FBQ2hFLENBQW1ELENBQUM7WUFDckQsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUMxQixPQUFPO29CQUNMLGVBQWUsRUFBRSxLQUFLO29CQUN0QixPQUFPLEVBQUUsRUFBRTtvQkFDWCxlQUFlLEVBQUUsQ0FBQyxHQUFHLGVBQWUsRUFBRSxHQUFHLHFCQUFxQixDQUFDLElBQUksRUFBRSxDQUFDO29CQUN0RSxpQkFBaUIsRUFBRSxFQUFFO2lCQUN0QixDQUFDO1lBQ0osQ0FBQztZQUVELE1BQU0sVUFBVSxHQUFHLE1BQU0sMEJBQTBCLENBQUMsSUFBSSxDQUFDO2dCQUN2RCxFQUFFLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3JGLENBQTJDLENBQUM7WUFDN0MsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUU1RixNQUFNLGlCQUFpQixHQUFHLElBQUksR0FBRyxFQUEwRCxDQUFDO1lBQzVGLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQy9CLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQzNDLE1BQU0sTUFBTSxHQUFHLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDOUMsSUFBSSxNQUFNLEVBQUUsQ0FBQztvQkFDWCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN2QixDQUFDO3FCQUFNLENBQUM7b0JBQ04saUJBQWlCLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQzVDLENBQUM7WUFDSCxDQUFDO1lBRUQsMkVBQTJFO1lBQzNFLDBDQUEwQztZQUMxQyxNQUFNLE9BQU8sR0FBeUMsRUFBRSxDQUFDO1lBQ3pELE1BQU0saUJBQWlCLEdBQW1ELEVBQUUsQ0FBQztZQUM3RSxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUkscUJBQXFCLEVBQUUsQ0FBQztnQkFDcEQsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUNyQixLQUFLLE1BQU0sT0FBTyxJQUFJLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztvQkFDM0QsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztvQkFDcEUsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO3dCQUNkLFNBQVM7b0JBQ1gsQ0FBQztvQkFDRCxRQUFRLEdBQUcsSUFBSSxDQUFDO29CQUNoQixJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssSUFBSSxFQUFFLENBQUM7d0JBQ2pDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7d0JBQy9GLFNBQVM7b0JBQ1gsQ0FBQztvQkFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7Z0JBQ25DLENBQUM7Z0JBQ0QsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUNkLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzdCLENBQUM7WUFDSCxDQUFDO1lBRUQsT0FBTyxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxDQUFDO1FBQ2pGLENBQUM7UUFFRDs7O1dBR0c7UUFDSSxLQUFLLENBQUMsaUJBQWlCLENBQUMsS0FBNkI7WUFDMUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDN0QsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQVMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztZQUNsRyxPQUFPO2dCQUNMLFdBQVcsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUM7Z0JBQ3hFLGVBQWUsRUFBRSxVQUFVLENBQUMsZUFBZTtnQkFDM0MsaUJBQWlCLEVBQUUsVUFBVSxDQUFDLGlCQUFpQjthQUNoRCxDQUFDO1FBQ0osQ0FBQztRQUVEOzs7O1dBSUc7UUFDSSxLQUFLLENBQUMsc0JBQXNCLENBQUMsS0FBa0M7WUFDcEUsTUFBTSxPQUFPLEdBQW9CLEtBQUssRUFBRSxPQUFPLElBQUksWUFBWSxDQUFDO1lBQ2hFLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzdELE1BQU0sSUFBSSxHQUFHO2dCQUNYLGVBQWUsRUFBRSxVQUFVLENBQUMsZUFBZTtnQkFDM0MsZUFBZSxFQUFFLFVBQVUsQ0FBQyxlQUFlO2dCQUMzQyxpQkFBaUIsRUFBRSxVQUFVLENBQUMsaUJBQWlCO2FBQ2hELENBQUM7WUFFRixJQUFJLE9BQU8sS0FBSyxZQUFZLEVBQUUsQ0FBQztnQkFDN0IsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQVMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztnQkFDbEcsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzFGLENBQUM7WUFFRCxJQUFJLE9BQU8sS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDM0IsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzlHLENBQUM7WUFFRCx3RUFBd0U7WUFDeEUsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdEcsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDO2dCQUNuQyxDQUFDLENBQUMsRUFBRTtnQkFDSixDQUFDLENBQUMsTUFBTSxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFnQyxDQUFDO1lBQ2hGLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRXhGLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7WUFDakMsS0FBSyxNQUFNLEtBQUssSUFBSSxVQUFVLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3ZDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ3BGLElBQUksS0FBSyxLQUFLLEVBQUUsRUFBRSxDQUFDO29CQUNqQixNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUNsQixTQUFTO2dCQUNYLENBQUM7Z0JBQ0QsMkVBQTJFO2dCQUMzRSx5RUFBeUU7Z0JBQ3pFLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUNaLHNCQUFzQixLQUFLLENBQUMsV0FBVyxjQUFjLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSw2Q0FBNkMsQ0FDMUgsQ0FBQztnQkFDRixNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdEMsQ0FBQztZQUNELE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2pELENBQUM7UUFFRCxxRUFBcUU7UUFFN0Qsb0JBQW9CO1lBQzFCLE1BQU0sY0FBYyxHQUFHLGdCQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsNkJBQTZCLEVBQUUsMkJBQTJCLENBQUMsQ0FBQztZQUN2RyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFFRCxzRkFBc0Y7UUFDNUUsbUJBQW1CO1lBQzNCLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVPLHdCQUF3QjtZQUM5QixNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFFLGVBQTZELENBQUM7WUFDdEcsTUFBTSxZQUFZLEdBQUcsZUFBZSxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUM7WUFDckQsSUFBSSxZQUFZLElBQUksT0FBTyxZQUFZLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3JELE1BQU0sS0FBSyxHQUFHLFlBQStELENBQUM7Z0JBQzlFLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQztnQkFDakMsSUFBSSxFQUFFLElBQUksSUFBSSxJQUFJLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztvQkFDM0MsT0FBTyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzNCLENBQUM7WUFDSCxDQUFDO1lBQ0QsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQ7Ozs7Ozs7Ozs7O1dBV0c7UUFDSSxLQUFLLENBQUMsYUFBYTtZQUN4QixJQUFJLGdCQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsZ0NBQWdDLENBQUMsS0FBSyxLQUFLLEVBQUUsQ0FBQztnQkFDcEUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsMkRBQTJELENBQUMsQ0FBQztnQkFDL0UsT0FBTztZQUNULENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxFQUFFLHFCQUFxQixDQUFDLENBQUM7WUFDL0UsSUFBSSxNQUFNLEdBQXdDLElBQUksQ0FBQztZQUN2RCxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUM1RSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQWlDLENBQUM7WUFDL0QsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxPQUFPLEdBQUcsS0FBOEIsQ0FBQztnQkFDL0MsSUFBSSxPQUFPLEVBQUUsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUMvQixLQUFLLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxpREFBaUQsUUFBUSxFQUFFLENBQUMsQ0FBQztvQkFDL0UsT0FBTztnQkFDVCxDQUFDO2dCQUNELEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLHNEQUFzRCxxQkFBcUIsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN0RyxPQUFPO1lBQ1QsQ0FBQztZQUVELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNwQyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxzREFBc0QscUJBQXFCLEVBQUUsQ0FBQyxDQUFDO2dCQUMvRixPQUFPO1lBQ1QsQ0FBQztZQUNELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7WUFDL0IsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUN6QixPQUFPO1lBQ1QsQ0FBQztZQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1lBQ2hELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDYixLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQywyRUFBMkUsQ0FBQyxDQUFDO2dCQUM3RixPQUFPO1lBQ1QsQ0FBQztZQUVELHNGQUFzRjtZQUN0Riw0RUFBNEU7WUFDNUUsSUFBSSxJQUFBLHdDQUErQixFQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUM1RSxLQUFLLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxrR0FBa0csQ0FBQyxDQUFDO2dCQUN0SCxPQUFPO1lBQ1QsQ0FBQztZQUVELE1BQU0sR0FBRyxHQUFpQixFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsZUFBZSxFQUFFLENBQUM7WUFDL0QsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQy9DLENBQUM7UUFDSCxDQUFDO1FBRU8sS0FBSyxDQUFDLHNCQUFzQixDQUFDLElBQWlDLEVBQUUsR0FBaUI7WUFDdkYsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDN0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDekQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxjQUFjLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDakUsTUFBTSxLQUFLLEdBQUcsR0FBRyxLQUFLLElBQUksR0FBRyxJQUFJLFVBQVUsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUVyRCxJQUFJLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUM5QyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQywwREFBMEQsSUFBSSxFQUFFLEtBQUssb0NBQW9DLENBQUMsQ0FBQztnQkFDM0gsT0FBTztZQUNULENBQUM7WUFDRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ2hCLEtBQUssQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUM7Z0JBQzlFLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUNwQixLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxtRUFBbUUsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDNUYsT0FBTztZQUNULENBQUM7WUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLHdCQUF3QixDQUFDLE9BQU8sQ0FBQztnQkFDdEQsUUFBUSxFQUFFLEdBQUcsQ0FBQyxPQUFPO2dCQUNyQixLQUFLO2dCQUNMLFVBQVU7YUFDWCxDQUE4QyxDQUFDO1lBQ2hELElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2IsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsZ0RBQWdELEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQzNFLE9BQU87WUFDVCxDQUFDO1lBRUQsSUFBSSxDQUFDO2dCQUNILE1BQU0sSUFBQSxpQ0FBa0IsRUFDdEIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQ3pFLDBCQUEwQixFQUMxQiw4QkFBOEIsS0FBSyxFQUFFLENBQ3RDLENBQUM7Z0JBQ0YsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsMkNBQTJDLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDeEUsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMscUNBQXFDLEtBQUssRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3ZFLENBQUM7UUFDSCxDQUFDO1FBRU8sS0FBSyxDQUFDLGtCQUFrQixDQUM5QixLQUFzSCxFQUN0SCxHQUFpQjtZQUVqQixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxjQUFjLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdkUsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDO2dCQUN2QyxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7Z0JBQ2xCLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTtnQkFDNUIsZ0JBQWdCLEVBQUUsSUFBSTtnQkFDdEIsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjO2dCQUNwQyxjQUFjLEVBQUUsY0FBYyxJQUFJLFNBQVM7YUFDNUMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUVSLDJFQUEyRTtZQUMzRSxpRkFBaUY7WUFDakYsNERBQTREO1lBQzVELE1BQU0sR0FBRyxHQUFHLE1BQU0seUJBQXlCLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBK0MsQ0FBQztZQUN6SCxNQUFNLFNBQVMsR0FBSSxDQUFDLEdBQUcsRUFBRSxTQUFTLElBQUksRUFBRSxDQUF3QixDQUFDO1lBQ2pFLE1BQU0sbUJBQW1CLEdBQUcsU0FBUztpQkFDbEMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDO2lCQUMxQyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUUxQyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRTtnQkFDcEQsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVO2dCQUM5QixtQkFBbUI7YUFDcEIsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUVSLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3JELElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyx1REFBdUQsQ0FBQyxDQUFDO1lBQzNFLENBQUM7WUFFRCxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxhQUFhLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckUsSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDbEIsa0VBQWtFO2dCQUNsRSxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN4RSxNQUFNLDJCQUEyQixDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztvQkFDbkUsSUFBSTtvQkFDSixTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU07aUJBQ3RCLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCw4RUFBOEU7WUFDOUUsNEVBQTRFO1lBQzVFLGdEQUFnRDtZQUNoRCxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN2RixDQUFDO0tBQ0Y7SUEzcEVZLGtDQUF5Qiw0QkEycEVyQyxDQUFBO0FBQ0gsQ0FBQyxFQWwzRWdCLFFBQVEsd0JBQVIsUUFBUSxRQWszRXhCIn0=