riksdagsmonitor 0.8.14 → 0.8.17

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 (663) hide show
  1. package/dist/lib/cia/dashboard-init.d.ts +26 -0
  2. package/dist/lib/cia/dashboard-init.d.ts.map +1 -0
  3. package/dist/lib/cia/dashboard-init.js +108 -0
  4. package/dist/lib/cia/dashboard-init.js.map +1 -0
  5. package/dist/lib/cia/data-loader.d.ts +408 -0
  6. package/dist/lib/cia/data-loader.d.ts.map +1 -0
  7. package/dist/lib/cia/data-loader.js +867 -0
  8. package/dist/lib/cia/data-loader.js.map +1 -0
  9. package/dist/lib/cia/election-predictions.d.ts +78 -0
  10. package/dist/lib/cia/election-predictions.d.ts.map +1 -0
  11. package/dist/lib/cia/election-predictions.js +259 -0
  12. package/dist/lib/cia/election-predictions.js.map +1 -0
  13. package/dist/lib/cia/i18n-translations.d.ts +111 -0
  14. package/dist/lib/cia/i18n-translations.d.ts.map +1 -0
  15. package/dist/lib/cia/i18n-translations.js +619 -0
  16. package/dist/lib/cia/i18n-translations.js.map +1 -0
  17. package/dist/lib/cia/visualizations.d.ts +64 -0
  18. package/dist/lib/cia/visualizations.d.ts.map +1 -0
  19. package/dist/lib/cia/visualizations.js +662 -0
  20. package/dist/lib/cia/visualizations.js.map +1 -0
  21. package/dist/lib/dashboards/anomaly-detection.d.ts +44 -0
  22. package/dist/lib/dashboards/anomaly-detection.d.ts.map +1 -0
  23. package/dist/lib/dashboards/anomaly-detection.js +1017 -0
  24. package/dist/lib/dashboards/anomaly-detection.js.map +1 -0
  25. package/dist/lib/dashboards/coalition-dashboard.d.ts +36 -0
  26. package/dist/lib/dashboards/coalition-dashboard.d.ts.map +1 -0
  27. package/dist/lib/dashboards/coalition-dashboard.js +645 -0
  28. package/dist/lib/dashboards/coalition-dashboard.js.map +1 -0
  29. package/dist/lib/dashboards/coalition-loader.d.ts +43 -0
  30. package/dist/lib/dashboards/coalition-loader.d.ts.map +1 -0
  31. package/dist/lib/dashboards/coalition-loader.js +701 -0
  32. package/dist/lib/dashboards/coalition-loader.js.map +1 -0
  33. package/dist/lib/dashboards/committees-dashboard.d.ts +23 -0
  34. package/dist/lib/dashboards/committees-dashboard.d.ts.map +1 -0
  35. package/dist/lib/dashboards/committees-dashboard.js +886 -0
  36. package/dist/lib/dashboards/committees-dashboard.js.map +1 -0
  37. package/dist/lib/dashboards/election-cycle.d.ts +62 -0
  38. package/dist/lib/dashboards/election-cycle.d.ts.map +1 -0
  39. package/dist/lib/dashboards/election-cycle.js +484 -0
  40. package/dist/lib/dashboards/election-cycle.js.map +1 -0
  41. package/dist/lib/dashboards/ministry-dashboard.d.ts +46 -0
  42. package/dist/lib/dashboards/ministry-dashboard.d.ts.map +1 -0
  43. package/dist/lib/dashboards/ministry-dashboard.js +1114 -0
  44. package/dist/lib/dashboards/ministry-dashboard.js.map +1 -0
  45. package/dist/lib/dashboards/party-dashboard.d.ts +56 -0
  46. package/dist/lib/dashboards/party-dashboard.d.ts.map +1 -0
  47. package/dist/lib/dashboards/party-dashboard.js +981 -0
  48. package/dist/lib/dashboards/party-dashboard.js.map +1 -0
  49. package/dist/lib/dashboards/politician-dashboard.d.ts +41 -0
  50. package/dist/lib/dashboards/politician-dashboard.d.ts.map +1 -0
  51. package/dist/lib/dashboards/politician-dashboard.js +611 -0
  52. package/dist/lib/dashboards/politician-dashboard.js.map +1 -0
  53. package/dist/lib/dashboards/pre-election.d.ts +64 -0
  54. package/dist/lib/dashboards/pre-election.d.ts.map +1 -0
  55. package/dist/lib/dashboards/pre-election.js +604 -0
  56. package/dist/lib/dashboards/pre-election.js.map +1 -0
  57. package/dist/lib/dashboards/risk-dashboard.d.ts +37 -0
  58. package/dist/lib/dashboards/risk-dashboard.d.ts.map +1 -0
  59. package/dist/lib/dashboards/risk-dashboard.js +863 -0
  60. package/dist/lib/dashboards/risk-dashboard.js.map +1 -0
  61. package/dist/lib/dashboards/seasonal-patterns.d.ts +24 -0
  62. package/dist/lib/dashboards/seasonal-patterns.d.ts.map +1 -0
  63. package/dist/lib/dashboards/seasonal-patterns.js +535 -0
  64. package/dist/lib/dashboards/seasonal-patterns.js.map +1 -0
  65. package/dist/lib/dashboards/stats-loader.d.ts +35 -0
  66. package/dist/lib/dashboards/stats-loader.d.ts.map +1 -0
  67. package/dist/lib/dashboards/stats-loader.js +145 -0
  68. package/dist/lib/dashboards/stats-loader.js.map +1 -0
  69. package/dist/lib/{chart-factory.d.ts → shared/chart-factory.d.ts} +9 -2
  70. package/dist/lib/shared/chart-factory.d.ts.map +1 -0
  71. package/dist/lib/{chart-factory.js → shared/chart-factory.js} +9 -2
  72. package/dist/lib/shared/chart-factory.js.map +1 -0
  73. package/dist/lib/shared/data-loader.d.ts.map +1 -0
  74. package/dist/lib/shared/data-loader.js.map +1 -0
  75. package/dist/lib/shared/dom-utils.d.ts.map +1 -0
  76. package/dist/lib/shared/dom-utils.js.map +1 -0
  77. package/dist/lib/shared/error-boundary.d.ts.map +1 -0
  78. package/dist/lib/shared/error-boundary.js.map +1 -0
  79. package/dist/lib/shared/fallback-ui.d.ts.map +1 -0
  80. package/dist/lib/shared/fallback-ui.js.map +1 -0
  81. package/dist/lib/shared/index.d.ts.map +1 -0
  82. package/dist/lib/shared/index.js.map +1 -0
  83. package/dist/lib/shared/logger.d.ts.map +1 -0
  84. package/dist/lib/shared/logger.js.map +1 -0
  85. package/dist/lib/shared/register-globals.d.ts +14 -0
  86. package/dist/lib/shared/register-globals.d.ts.map +1 -0
  87. package/dist/lib/shared/register-globals.js +21 -0
  88. package/dist/lib/shared/register-globals.js.map +1 -0
  89. package/dist/lib/{theme.d.ts → shared/theme.d.ts} +1 -18
  90. package/dist/lib/shared/theme.d.ts.map +1 -0
  91. package/dist/lib/{theme.js → shared/theme.js} +1 -18
  92. package/dist/lib/shared/theme.js.map +1 -0
  93. package/dist/lib/shared/types.d.ts.map +1 -0
  94. package/dist/lib/shared/types.js.map +1 -0
  95. package/dist/lib/ui/back-to-top.d.ts +13 -0
  96. package/dist/lib/ui/back-to-top.d.ts.map +1 -0
  97. package/dist/lib/ui/back-to-top.js +48 -0
  98. package/dist/lib/ui/back-to-top.js.map +1 -0
  99. package/dist/scripts/analysis-reader.d.ts +241 -0
  100. package/dist/scripts/analysis-reader.d.ts.map +1 -0
  101. package/dist/scripts/analysis-reader.js +495 -0
  102. package/dist/scripts/analysis-reader.js.map +1 -0
  103. package/dist/scripts/article-quality-enhancer.d.ts +148 -0
  104. package/dist/scripts/article-quality-enhancer.d.ts.map +1 -0
  105. package/dist/scripts/article-quality-enhancer.js +430 -0
  106. package/dist/scripts/article-quality-enhancer.js.map +1 -0
  107. package/dist/scripts/article-template/constants.d.ts +104 -0
  108. package/dist/scripts/article-template/constants.d.ts.map +1 -0
  109. package/dist/scripts/article-template/constants.js +225 -0
  110. package/dist/scripts/article-template/constants.js.map +1 -0
  111. package/dist/scripts/article-template/helpers.d.ts +83 -0
  112. package/dist/scripts/article-template/helpers.d.ts.map +1 -0
  113. package/dist/scripts/article-template/helpers.js +236 -0
  114. package/dist/scripts/article-template/helpers.js.map +1 -0
  115. package/dist/scripts/article-template/index.d.ts +39 -0
  116. package/dist/scripts/article-template/index.d.ts.map +1 -0
  117. package/dist/scripts/article-template/index.js +37 -0
  118. package/dist/scripts/article-template/index.js.map +1 -0
  119. package/dist/scripts/article-template/registry.d.ts +64 -0
  120. package/dist/scripts/article-template/registry.d.ts.map +1 -0
  121. package/dist/scripts/article-template/registry.js +405 -0
  122. package/dist/scripts/article-template/registry.js.map +1 -0
  123. package/dist/scripts/article-template/template.d.ts +18 -0
  124. package/dist/scripts/article-template/template.d.ts.map +1 -0
  125. package/dist/scripts/article-template/template.js +359 -0
  126. package/dist/scripts/article-template/template.js.map +1 -0
  127. package/dist/scripts/article-template/types.d.ts +90 -0
  128. package/dist/scripts/article-template/types.d.ts.map +1 -0
  129. package/dist/scripts/article-template/types.js +96 -0
  130. package/dist/scripts/article-template/types.js.map +1 -0
  131. package/dist/scripts/article-template.d.ts +18 -0
  132. package/dist/scripts/article-template.d.ts.map +1 -0
  133. package/dist/scripts/article-template.js +18 -0
  134. package/dist/scripts/article-template.js.map +1 -0
  135. package/dist/scripts/catalog-downloaded-data.d.ts +66 -0
  136. package/dist/scripts/catalog-downloaded-data.d.ts.map +1 -0
  137. package/dist/scripts/catalog-downloaded-data.js +239 -0
  138. package/dist/scripts/catalog-downloaded-data.js.map +1 -0
  139. package/dist/scripts/check-cia-schema-updates.d.ts +186 -0
  140. package/dist/scripts/check-cia-schema-updates.d.ts.map +1 -0
  141. package/dist/scripts/check-cia-schema-updates.js +363 -0
  142. package/dist/scripts/check-cia-schema-updates.js.map +1 -0
  143. package/dist/scripts/data-transformers/calendar.d.ts +16 -0
  144. package/dist/scripts/data-transformers/calendar.d.ts.map +1 -0
  145. package/dist/scripts/data-transformers/calendar.js +137 -0
  146. package/dist/scripts/data-transformers/calendar.js.map +1 -0
  147. package/dist/scripts/data-transformers/constants/committee-names.d.ts +15 -0
  148. package/dist/scripts/data-transformers/constants/committee-names.d.ts.map +1 -0
  149. package/dist/scripts/data-transformers/constants/committee-names.js +30 -0
  150. package/dist/scripts/data-transformers/constants/committee-names.js.map +1 -0
  151. package/dist/scripts/data-transformers/constants/content-labels-part1.d.ts +11 -0
  152. package/dist/scripts/data-transformers/constants/content-labels-part1.d.ts.map +1 -0
  153. package/dist/scripts/data-transformers/constants/content-labels-part1.js +900 -0
  154. package/dist/scripts/data-transformers/constants/content-labels-part1.js.map +1 -0
  155. package/dist/scripts/data-transformers/constants/content-labels-part2.d.ts +11 -0
  156. package/dist/scripts/data-transformers/constants/content-labels-part2.d.ts.map +1 -0
  157. package/dist/scripts/data-transformers/constants/content-labels-part2.js +900 -0
  158. package/dist/scripts/data-transformers/constants/content-labels-part2.js.map +1 -0
  159. package/dist/scripts/data-transformers/constants/content-labels.d.ts +13 -0
  160. package/dist/scripts/data-transformers/constants/content-labels.d.ts.map +1 -0
  161. package/dist/scripts/data-transformers/constants/content-labels.js +18 -0
  162. package/dist/scripts/data-transformers/constants/content-labels.js.map +1 -0
  163. package/dist/scripts/data-transformers/constants/index.d.ts +15 -0
  164. package/dist/scripts/data-transformers/constants/index.d.ts.map +1 -0
  165. package/dist/scripts/data-transformers/constants/index.js +15 -0
  166. package/dist/scripts/data-transformers/constants/index.js.map +1 -0
  167. package/dist/scripts/data-transformers/constants/locale-map.d.ts +13 -0
  168. package/dist/scripts/data-transformers/constants/locale-map.d.ts.map +1 -0
  169. package/dist/scripts/data-transformers/constants/locale-map.js +17 -0
  170. package/dist/scripts/data-transformers/constants/locale-map.js.map +1 -0
  171. package/dist/scripts/data-transformers/constants.d.ts +14 -0
  172. package/dist/scripts/data-transformers/constants.d.ts.map +1 -0
  173. package/dist/scripts/data-transformers/constants.js +14 -0
  174. package/dist/scripts/data-transformers/constants.js.map +1 -0
  175. package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.d.ts +64 -0
  176. package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.d.ts.map +1 -0
  177. package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.js +805 -0
  178. package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.js.map +1 -0
  179. package/dist/scripts/data-transformers/content-generators/cia-overview-section.d.ts +50 -0
  180. package/dist/scripts/data-transformers/content-generators/cia-overview-section.d.ts.map +1 -0
  181. package/dist/scripts/data-transformers/content-generators/cia-overview-section.js +310 -0
  182. package/dist/scripts/data-transformers/content-generators/cia-overview-section.js.map +1 -0
  183. package/dist/scripts/data-transformers/content-generators/committee.d.ts +12 -0
  184. package/dist/scripts/data-transformers/content-generators/committee.d.ts.map +1 -0
  185. package/dist/scripts/data-transformers/content-generators/committee.js +247 -0
  186. package/dist/scripts/data-transformers/content-generators/committee.js.map +1 -0
  187. package/dist/scripts/data-transformers/content-generators/dashboard-section.d.ts +124 -0
  188. package/dist/scripts/data-transformers/content-generators/dashboard-section.d.ts.map +1 -0
  189. package/dist/scripts/data-transformers/content-generators/dashboard-section.js +564 -0
  190. package/dist/scripts/data-transformers/content-generators/dashboard-section.js.map +1 -0
  191. package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.d.ts +82 -0
  192. package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.d.ts.map +1 -0
  193. package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.js +321 -0
  194. package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.js.map +1 -0
  195. package/dist/scripts/data-transformers/content-generators/generic.d.ts +12 -0
  196. package/dist/scripts/data-transformers/content-generators/generic.d.ts.map +1 -0
  197. package/dist/scripts/data-transformers/content-generators/generic.js +295 -0
  198. package/dist/scripts/data-transformers/content-generators/generic.js.map +1 -0
  199. package/dist/scripts/data-transformers/content-generators/index.d.ts +84 -0
  200. package/dist/scripts/data-transformers/content-generators/index.d.ts.map +1 -0
  201. package/dist/scripts/data-transformers/content-generators/index.js +47 -0
  202. package/dist/scripts/data-transformers/content-generators/index.js.map +1 -0
  203. package/dist/scripts/data-transformers/content-generators/interpellations.d.ts +12 -0
  204. package/dist/scripts/data-transformers/content-generators/interpellations.d.ts.map +1 -0
  205. package/dist/scripts/data-transformers/content-generators/interpellations.js +124 -0
  206. package/dist/scripts/data-transformers/content-generators/interpellations.js.map +1 -0
  207. package/dist/scripts/data-transformers/content-generators/mindmap-section.d.ts +137 -0
  208. package/dist/scripts/data-transformers/content-generators/mindmap-section.d.ts.map +1 -0
  209. package/dist/scripts/data-transformers/content-generators/mindmap-section.js +286 -0
  210. package/dist/scripts/data-transformers/content-generators/mindmap-section.js.map +1 -0
  211. package/dist/scripts/data-transformers/content-generators/month-ahead.d.ts +17 -0
  212. package/dist/scripts/data-transformers/content-generators/month-ahead.d.ts.map +1 -0
  213. package/dist/scripts/data-transformers/content-generators/month-ahead.js +212 -0
  214. package/dist/scripts/data-transformers/content-generators/month-ahead.js.map +1 -0
  215. package/dist/scripts/data-transformers/content-generators/monthly-review.d.ts +17 -0
  216. package/dist/scripts/data-transformers/content-generators/monthly-review.d.ts.map +1 -0
  217. package/dist/scripts/data-transformers/content-generators/monthly-review.js +173 -0
  218. package/dist/scripts/data-transformers/content-generators/monthly-review.js.map +1 -0
  219. package/dist/scripts/data-transformers/content-generators/motions.d.ts +12 -0
  220. package/dist/scripts/data-transformers/content-generators/motions.d.ts.map +1 -0
  221. package/dist/scripts/data-transformers/content-generators/motions.js +158 -0
  222. package/dist/scripts/data-transformers/content-generators/motions.js.map +1 -0
  223. package/dist/scripts/data-transformers/content-generators/newsworthiness.d.ts +52 -0
  224. package/dist/scripts/data-transformers/content-generators/newsworthiness.d.ts.map +1 -0
  225. package/dist/scripts/data-transformers/content-generators/newsworthiness.js +244 -0
  226. package/dist/scripts/data-transformers/content-generators/newsworthiness.js.map +1 -0
  227. package/dist/scripts/data-transformers/content-generators/propositions.d.ts +12 -0
  228. package/dist/scripts/data-transformers/content-generators/propositions.d.ts.map +1 -0
  229. package/dist/scripts/data-transformers/content-generators/propositions.js +263 -0
  230. package/dist/scripts/data-transformers/content-generators/propositions.js.map +1 -0
  231. package/dist/scripts/data-transformers/content-generators/sankey-section.d.ts +92 -0
  232. package/dist/scripts/data-transformers/content-generators/sankey-section.d.ts.map +1 -0
  233. package/dist/scripts/data-transformers/content-generators/sankey-section.js +257 -0
  234. package/dist/scripts/data-transformers/content-generators/sankey-section.js.map +1 -0
  235. package/dist/scripts/data-transformers/content-generators/shared.d.ts +123 -0
  236. package/dist/scripts/data-transformers/content-generators/shared.d.ts.map +1 -0
  237. package/dist/scripts/data-transformers/content-generators/shared.js +919 -0
  238. package/dist/scripts/data-transformers/content-generators/shared.js.map +1 -0
  239. package/dist/scripts/data-transformers/content-generators/swot-section.d.ts +50 -0
  240. package/dist/scripts/data-transformers/content-generators/swot-section.d.ts.map +1 -0
  241. package/dist/scripts/data-transformers/content-generators/swot-section.js +177 -0
  242. package/dist/scripts/data-transformers/content-generators/swot-section.js.map +1 -0
  243. package/dist/scripts/data-transformers/content-generators/week-ahead.d.ts +12 -0
  244. package/dist/scripts/data-transformers/content-generators/week-ahead.d.ts.map +1 -0
  245. package/dist/scripts/data-transformers/content-generators/week-ahead.js +332 -0
  246. package/dist/scripts/data-transformers/content-generators/week-ahead.js.map +1 -0
  247. package/dist/scripts/data-transformers/content-generators.d.ts +15 -0
  248. package/dist/scripts/data-transformers/content-generators.d.ts.map +1 -0
  249. package/dist/scripts/data-transformers/content-generators.js +14 -0
  250. package/dist/scripts/data-transformers/content-generators.js.map +1 -0
  251. package/dist/scripts/data-transformers/document-analysis.d.ts +58 -0
  252. package/dist/scripts/data-transformers/document-analysis.d.ts.map +1 -0
  253. package/dist/scripts/data-transformers/document-analysis.js +396 -0
  254. package/dist/scripts/data-transformers/document-analysis.js.map +1 -0
  255. package/dist/scripts/data-transformers/helpers.d.ts +144 -0
  256. package/dist/scripts/data-transformers/helpers.d.ts.map +1 -0
  257. package/dist/scripts/data-transformers/helpers.js +408 -0
  258. package/dist/scripts/data-transformers/helpers.js.map +1 -0
  259. package/dist/scripts/data-transformers/index.d.ts +45 -0
  260. package/dist/scripts/data-transformers/index.d.ts.map +1 -0
  261. package/dist/scripts/data-transformers/index.js +66 -0
  262. package/dist/scripts/data-transformers/index.js.map +1 -0
  263. package/dist/scripts/data-transformers/metadata.d.ts +42 -0
  264. package/dist/scripts/data-transformers/metadata.d.ts.map +1 -0
  265. package/dist/scripts/data-transformers/metadata.js +385 -0
  266. package/dist/scripts/data-transformers/metadata.js.map +1 -0
  267. package/dist/scripts/data-transformers/policy-analysis.d.ts +105 -0
  268. package/dist/scripts/data-transformers/policy-analysis.d.ts.map +1 -0
  269. package/dist/scripts/data-transformers/policy-analysis.js +686 -0
  270. package/dist/scripts/data-transformers/policy-analysis.js.map +1 -0
  271. package/dist/scripts/data-transformers/risk-analysis.d.ts +104 -0
  272. package/dist/scripts/data-transformers/risk-analysis.d.ts.map +1 -0
  273. package/dist/scripts/data-transformers/risk-analysis.js +279 -0
  274. package/dist/scripts/data-transformers/risk-analysis.js.map +1 -0
  275. package/dist/scripts/data-transformers/types.d.ts +260 -0
  276. package/dist/scripts/data-transformers/types.d.ts.map +1 -0
  277. package/dist/scripts/data-transformers/types.js +11 -0
  278. package/dist/scripts/data-transformers/types.js.map +1 -0
  279. package/dist/scripts/data-transformers.d.ts +23 -0
  280. package/dist/scripts/data-transformers.d.ts.map +1 -0
  281. package/dist/scripts/data-transformers.js +35 -0
  282. package/dist/scripts/data-transformers.js.map +1 -0
  283. package/dist/scripts/deep-inspection/index.d.ts +55 -0
  284. package/dist/scripts/deep-inspection/index.d.ts.map +1 -0
  285. package/dist/scripts/deep-inspection/index.js +66 -0
  286. package/dist/scripts/deep-inspection/index.js.map +1 -0
  287. package/dist/scripts/detect-swedish-leakage.d.ts +69 -0
  288. package/dist/scripts/detect-swedish-leakage.d.ts.map +1 -0
  289. package/dist/scripts/detect-swedish-leakage.js +417 -0
  290. package/dist/scripts/detect-swedish-leakage.js.map +1 -0
  291. package/dist/scripts/editorial-framework.d.ts +121 -0
  292. package/dist/scripts/editorial-framework.d.ts.map +1 -0
  293. package/dist/scripts/editorial-framework.js +364 -0
  294. package/dist/scripts/editorial-framework.js.map +1 -0
  295. package/dist/scripts/editorial-pillars.d.ts +43 -0
  296. package/dist/scripts/editorial-pillars.d.ts.map +1 -0
  297. package/dist/scripts/editorial-pillars.js +215 -0
  298. package/dist/scripts/editorial-pillars.js.map +1 -0
  299. package/dist/scripts/extract-news-metadata.d.ts +12 -0
  300. package/dist/scripts/extract-news-metadata.d.ts.map +1 -0
  301. package/dist/scripts/extract-news-metadata.js +107 -0
  302. package/dist/scripts/extract-news-metadata.js.map +1 -0
  303. package/dist/scripts/extract-vocabulary.d.ts +15 -0
  304. package/dist/scripts/extract-vocabulary.d.ts.map +1 -0
  305. package/dist/scripts/extract-vocabulary.js +255 -0
  306. package/dist/scripts/extract-vocabulary.js.map +1 -0
  307. package/dist/scripts/fix-article-navigation.d.ts +37 -0
  308. package/dist/scripts/fix-article-navigation.d.ts.map +1 -0
  309. package/dist/scripts/fix-article-navigation.js +198 -0
  310. package/dist/scripts/fix-article-navigation.js.map +1 -0
  311. package/dist/scripts/fix-keywords-localization.d.ts +18 -0
  312. package/dist/scripts/fix-keywords-localization.d.ts.map +1 -0
  313. package/dist/scripts/fix-keywords-localization.js +270 -0
  314. package/dist/scripts/fix-keywords-localization.js.map +1 -0
  315. package/dist/scripts/fix-old-articles-branding.d.ts +17 -0
  316. package/dist/scripts/fix-old-articles-branding.d.ts.map +1 -0
  317. package/dist/scripts/fix-old-articles-branding.js +229 -0
  318. package/dist/scripts/fix-old-articles-branding.js.map +1 -0
  319. package/dist/scripts/generate-news-backport.d.ts +16 -0
  320. package/dist/scripts/generate-news-backport.d.ts.map +1 -0
  321. package/dist/scripts/generate-news-backport.js +379 -0
  322. package/dist/scripts/generate-news-backport.js.map +1 -0
  323. package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.d.ts +124 -0
  324. package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.d.ts.map +1 -0
  325. package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.js +529 -0
  326. package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.js.map +1 -0
  327. package/dist/scripts/generate-news-enhanced/analysis-cache.d.ts +59 -0
  328. package/dist/scripts/generate-news-enhanced/analysis-cache.d.ts.map +1 -0
  329. package/dist/scripts/generate-news-enhanced/analysis-cache.js +116 -0
  330. package/dist/scripts/generate-news-enhanced/analysis-cache.js.map +1 -0
  331. package/dist/scripts/generate-news-enhanced/analysis-labels.d.ts +58 -0
  332. package/dist/scripts/generate-news-enhanced/analysis-labels.d.ts.map +1 -0
  333. package/dist/scripts/generate-news-enhanced/analysis-labels.js +144 -0
  334. package/dist/scripts/generate-news-enhanced/analysis-labels.js.map +1 -0
  335. package/dist/scripts/generate-news-enhanced/config.d.ts +58 -0
  336. package/dist/scripts/generate-news-enhanced/config.d.ts.map +1 -0
  337. package/dist/scripts/generate-news-enhanced/config.js +286 -0
  338. package/dist/scripts/generate-news-enhanced/config.js.map +1 -0
  339. package/dist/scripts/generate-news-enhanced/generators.d.ts +119 -0
  340. package/dist/scripts/generate-news-enhanced/generators.d.ts.map +1 -0
  341. package/dist/scripts/generate-news-enhanced/generators.js +2131 -0
  342. package/dist/scripts/generate-news-enhanced/generators.js.map +1 -0
  343. package/dist/scripts/generate-news-enhanced/helpers.d.ts +122 -0
  344. package/dist/scripts/generate-news-enhanced/helpers.d.ts.map +1 -0
  345. package/dist/scripts/generate-news-enhanced/helpers.js +468 -0
  346. package/dist/scripts/generate-news-enhanced/helpers.js.map +1 -0
  347. package/dist/scripts/generate-news-enhanced/index.d.ts +19 -0
  348. package/dist/scripts/generate-news-enhanced/index.d.ts.map +1 -0
  349. package/dist/scripts/generate-news-enhanced/index.js +221 -0
  350. package/dist/scripts/generate-news-enhanced/index.js.map +1 -0
  351. package/dist/scripts/generate-news-enhanced/swot-analyzer.d.ts +46 -0
  352. package/dist/scripts/generate-news-enhanced/swot-analyzer.d.ts.map +1 -0
  353. package/dist/scripts/generate-news-enhanced/swot-analyzer.js +1227 -0
  354. package/dist/scripts/generate-news-enhanced/swot-analyzer.js.map +1 -0
  355. package/dist/scripts/generate-news-enhanced/types.d.ts +34 -0
  356. package/dist/scripts/generate-news-enhanced/types.d.ts.map +1 -0
  357. package/dist/scripts/generate-news-enhanced/types.js +9 -0
  358. package/dist/scripts/generate-news-enhanced/types.js.map +1 -0
  359. package/dist/scripts/generate-news-enhanced.d.ts +25 -0
  360. package/dist/scripts/generate-news-enhanced.d.ts.map +1 -0
  361. package/dist/scripts/generate-news-enhanced.js +37 -0
  362. package/dist/scripts/generate-news-enhanced.js.map +1 -0
  363. package/dist/scripts/generate-news-indexes/constants.d.ts +20 -0
  364. package/dist/scripts/generate-news-indexes/constants.d.ts.map +1 -0
  365. package/dist/scripts/generate-news-indexes/constants.js +308 -0
  366. package/dist/scripts/generate-news-indexes/constants.js.map +1 -0
  367. package/dist/scripts/generate-news-indexes/helpers.d.ts +73 -0
  368. package/dist/scripts/generate-news-indexes/helpers.d.ts.map +1 -0
  369. package/dist/scripts/generate-news-indexes/helpers.js +352 -0
  370. package/dist/scripts/generate-news-indexes/helpers.js.map +1 -0
  371. package/dist/scripts/generate-news-indexes/index.d.ts +20 -0
  372. package/dist/scripts/generate-news-indexes/index.d.ts.map +1 -0
  373. package/dist/scripts/generate-news-indexes/index.js +75 -0
  374. package/dist/scripts/generate-news-indexes/index.js.map +1 -0
  375. package/dist/scripts/generate-news-indexes/template.d.ts +25 -0
  376. package/dist/scripts/generate-news-indexes/template.d.ts.map +1 -0
  377. package/dist/scripts/generate-news-indexes/template.js +644 -0
  378. package/dist/scripts/generate-news-indexes/template.js.map +1 -0
  379. package/dist/scripts/generate-news-indexes/types.d.ts +96 -0
  380. package/dist/scripts/generate-news-indexes/types.d.ts.map +1 -0
  381. package/dist/scripts/generate-news-indexes/types.js +9 -0
  382. package/dist/scripts/generate-news-indexes/types.js.map +1 -0
  383. package/dist/scripts/generate-news-indexes.d.ts +20 -0
  384. package/dist/scripts/generate-news-indexes.d.ts.map +1 -0
  385. package/dist/scripts/generate-news-indexes.js +19 -0
  386. package/dist/scripts/generate-news-indexes.js.map +1 -0
  387. package/dist/scripts/generate-rss.d.ts +48 -0
  388. package/dist/scripts/generate-rss.d.ts.map +1 -0
  389. package/dist/scripts/generate-rss.js +299 -0
  390. package/dist/scripts/generate-rss.js.map +1 -0
  391. package/dist/scripts/generate-sitemap-html.d.ts +79 -0
  392. package/dist/scripts/generate-sitemap-html.d.ts.map +1 -0
  393. package/dist/scripts/generate-sitemap-html.js +878 -0
  394. package/dist/scripts/generate-sitemap-html.js.map +1 -0
  395. package/dist/scripts/generate-sitemap.d.ts +23 -0
  396. package/dist/scripts/generate-sitemap.d.ts.map +1 -0
  397. package/dist/scripts/generate-sitemap.js +476 -0
  398. package/dist/scripts/generate-sitemap.js.map +1 -0
  399. package/dist/scripts/generate-types-from-cia-schemas.d.ts +176 -0
  400. package/dist/scripts/generate-types-from-cia-schemas.d.ts.map +1 -0
  401. package/dist/scripts/generate-types-from-cia-schemas.js +318 -0
  402. package/dist/scripts/generate-types-from-cia-schemas.js.map +1 -0
  403. package/dist/scripts/government-role-validator.d.ts +65 -0
  404. package/dist/scripts/government-role-validator.d.ts.map +1 -0
  405. package/dist/scripts/government-role-validator.js +217 -0
  406. package/dist/scripts/government-role-validator.js.map +1 -0
  407. package/dist/scripts/html-utils.d.ts +17 -0
  408. package/dist/scripts/html-utils.d.ts.map +1 -0
  409. package/dist/scripts/html-utils.js +29 -0
  410. package/dist/scripts/html-utils.js.map +1 -0
  411. package/dist/scripts/load-cia-stats.d.ts +89 -0
  412. package/dist/scripts/load-cia-stats.d.ts.map +1 -0
  413. package/dist/scripts/load-cia-stats.js +400 -0
  414. package/dist/scripts/load-cia-stats.js.map +1 -0
  415. package/dist/scripts/mcp-client/client.d.ts +73 -0
  416. package/dist/scripts/mcp-client/client.d.ts.map +1 -0
  417. package/dist/scripts/mcp-client/client.js +526 -0
  418. package/dist/scripts/mcp-client/client.js.map +1 -0
  419. package/dist/scripts/mcp-client/document-types.d.ts +23 -0
  420. package/dist/scripts/mcp-client/document-types.d.ts.map +1 -0
  421. package/dist/scripts/mcp-client/document-types.js +62 -0
  422. package/dist/scripts/mcp-client/document-types.js.map +1 -0
  423. package/dist/scripts/mcp-client/index.d.ts +34 -0
  424. package/dist/scripts/mcp-client/index.d.ts.map +1 -0
  425. package/dist/scripts/mcp-client/index.js +67 -0
  426. package/dist/scripts/mcp-client/index.js.map +1 -0
  427. package/dist/scripts/mcp-client/transport.d.ts +32 -0
  428. package/dist/scripts/mcp-client/transport.d.ts.map +1 -0
  429. package/dist/scripts/mcp-client/transport.js +102 -0
  430. package/dist/scripts/mcp-client/transport.js.map +1 -0
  431. package/dist/scripts/mcp-client.d.ts +18 -0
  432. package/dist/scripts/mcp-client.d.ts.map +1 -0
  433. package/dist/scripts/mcp-client.js +18 -0
  434. package/dist/scripts/mcp-client.js.map +1 -0
  435. package/dist/scripts/mcp-query-cli.d.ts +25 -0
  436. package/dist/scripts/mcp-query-cli.d.ts.map +1 -0
  437. package/dist/scripts/mcp-query-cli.js +66 -0
  438. package/dist/scripts/mcp-query-cli.js.map +1 -0
  439. package/dist/scripts/news-types/breaking-news.d.ts +178 -0
  440. package/dist/scripts/news-types/breaking-news.d.ts.map +1 -0
  441. package/dist/scripts/news-types/breaking-news.js +432 -0
  442. package/dist/scripts/news-types/breaking-news.js.map +1 -0
  443. package/dist/scripts/news-types/committee-reports.d.ts +212 -0
  444. package/dist/scripts/news-types/committee-reports.d.ts.map +1 -0
  445. package/dist/scripts/news-types/committee-reports.js +404 -0
  446. package/dist/scripts/news-types/committee-reports.js.map +1 -0
  447. package/dist/scripts/news-types/month-ahead.d.ts +71 -0
  448. package/dist/scripts/news-types/month-ahead.d.ts.map +1 -0
  449. package/dist/scripts/news-types/month-ahead.js +392 -0
  450. package/dist/scripts/news-types/month-ahead.js.map +1 -0
  451. package/dist/scripts/news-types/monthly-review.d.ts +61 -0
  452. package/dist/scripts/news-types/monthly-review.d.ts.map +1 -0
  453. package/dist/scripts/news-types/monthly-review.js +417 -0
  454. package/dist/scripts/news-types/monthly-review.js.map +1 -0
  455. package/dist/scripts/news-types/motions.d.ts +214 -0
  456. package/dist/scripts/news-types/motions.d.ts.map +1 -0
  457. package/dist/scripts/news-types/motions.js +447 -0
  458. package/dist/scripts/news-types/motions.js.map +1 -0
  459. package/dist/scripts/news-types/propositions.d.ts +204 -0
  460. package/dist/scripts/news-types/propositions.d.ts.map +1 -0
  461. package/dist/scripts/news-types/propositions.js +401 -0
  462. package/dist/scripts/news-types/propositions.js.map +1 -0
  463. package/dist/scripts/news-types/week-ahead.d.ts +231 -0
  464. package/dist/scripts/news-types/week-ahead.d.ts.map +1 -0
  465. package/dist/scripts/news-types/week-ahead.js +441 -0
  466. package/dist/scripts/news-types/week-ahead.js.map +1 -0
  467. package/dist/scripts/news-types/weekly-review/analysis.d.ts +47 -0
  468. package/dist/scripts/news-types/weekly-review/analysis.d.ts.map +1 -0
  469. package/dist/scripts/news-types/weekly-review/analysis.js +276 -0
  470. package/dist/scripts/news-types/weekly-review/analysis.js.map +1 -0
  471. package/dist/scripts/news-types/weekly-review/data-loader.d.ts +51 -0
  472. package/dist/scripts/news-types/weekly-review/data-loader.d.ts.map +1 -0
  473. package/dist/scripts/news-types/weekly-review/data-loader.js +298 -0
  474. package/dist/scripts/news-types/weekly-review/data-loader.js.map +1 -0
  475. package/dist/scripts/news-types/weekly-review/generator.d.ts +18 -0
  476. package/dist/scripts/news-types/weekly-review/generator.d.ts.map +1 -0
  477. package/dist/scripts/news-types/weekly-review/generator.js +284 -0
  478. package/dist/scripts/news-types/weekly-review/generator.js.map +1 -0
  479. package/dist/scripts/news-types/weekly-review/index.d.ts +20 -0
  480. package/dist/scripts/news-types/weekly-review/index.d.ts.map +1 -0
  481. package/dist/scripts/news-types/weekly-review/index.js +23 -0
  482. package/dist/scripts/news-types/weekly-review/index.js.map +1 -0
  483. package/dist/scripts/news-types/weekly-review/types.d.ts +72 -0
  484. package/dist/scripts/news-types/weekly-review/types.d.ts.map +1 -0
  485. package/dist/scripts/news-types/weekly-review/types.js +20 -0
  486. package/dist/scripts/news-types/weekly-review/types.js.map +1 -0
  487. package/dist/scripts/news-types/weekly-review/validation.d.ts +10 -0
  488. package/dist/scripts/news-types/weekly-review/validation.d.ts.map +1 -0
  489. package/dist/scripts/news-types/weekly-review/validation.js +95 -0
  490. package/dist/scripts/news-types/weekly-review/validation.js.map +1 -0
  491. package/dist/scripts/news-types/weekly-review.d.ts +15 -0
  492. package/dist/scripts/news-types/weekly-review.d.ts.map +1 -0
  493. package/dist/scripts/news-types/weekly-review.js +14 -0
  494. package/dist/scripts/news-types/weekly-review.js.map +1 -0
  495. package/dist/scripts/party-variants.d.ts +23 -0
  496. package/dist/scripts/party-variants.d.ts.map +1 -0
  497. package/dist/scripts/party-variants.js +50 -0
  498. package/dist/scripts/party-variants.js.map +1 -0
  499. package/dist/scripts/pipeline/index.d.ts +19 -0
  500. package/dist/scripts/pipeline/index.d.ts.map +1 -0
  501. package/dist/scripts/pipeline/index.js +17 -0
  502. package/dist/scripts/pipeline/index.js.map +1 -0
  503. package/dist/scripts/pipeline/orchestrator.d.ts +56 -0
  504. package/dist/scripts/pipeline/orchestrator.d.ts.map +1 -0
  505. package/dist/scripts/pipeline/orchestrator.js +147 -0
  506. package/dist/scripts/pipeline/orchestrator.js.map +1 -0
  507. package/dist/scripts/pipeline/types.d.ts +117 -0
  508. package/dist/scripts/pipeline/types.d.ts.map +1 -0
  509. package/dist/scripts/pipeline/types.js +13 -0
  510. package/dist/scripts/pipeline/types.js.map +1 -0
  511. package/dist/scripts/pipeline/validation.d.ts +66 -0
  512. package/dist/scripts/pipeline/validation.d.ts.map +1 -0
  513. package/dist/scripts/pipeline/validation.js +129 -0
  514. package/dist/scripts/pipeline/validation.js.map +1 -0
  515. package/dist/scripts/populate-analysis-data.d.ts +41 -0
  516. package/dist/scripts/populate-analysis-data.d.ts.map +1 -0
  517. package/dist/scripts/populate-analysis-data.js +255 -0
  518. package/dist/scripts/populate-analysis-data.js.map +1 -0
  519. package/dist/scripts/pre-article-analysis/data-downloader.d.ts +80 -0
  520. package/dist/scripts/pre-article-analysis/data-downloader.d.ts.map +1 -0
  521. package/dist/scripts/pre-article-analysis/data-downloader.js +230 -0
  522. package/dist/scripts/pre-article-analysis/data-downloader.js.map +1 -0
  523. package/dist/scripts/pre-article-analysis/data-persistence.d.ts +141 -0
  524. package/dist/scripts/pre-article-analysis/data-persistence.d.ts.map +1 -0
  525. package/dist/scripts/pre-article-analysis/data-persistence.js +345 -0
  526. package/dist/scripts/pre-article-analysis/data-persistence.js.map +1 -0
  527. package/dist/scripts/pre-article-analysis/markdown-serializer.d.ts +158 -0
  528. package/dist/scripts/pre-article-analysis/markdown-serializer.d.ts.map +1 -0
  529. package/dist/scripts/pre-article-analysis/markdown-serializer.js +648 -0
  530. package/dist/scripts/pre-article-analysis/markdown-serializer.js.map +1 -0
  531. package/dist/scripts/pre-article-analysis/pdf-converter.d.ts +58 -0
  532. package/dist/scripts/pre-article-analysis/pdf-converter.d.ts.map +1 -0
  533. package/dist/scripts/pre-article-analysis/pdf-converter.js +142 -0
  534. package/dist/scripts/pre-article-analysis/pdf-converter.js.map +1 -0
  535. package/dist/scripts/pre-article-analysis.d.ts +41 -0
  536. package/dist/scripts/pre-article-analysis.d.ts.map +1 -0
  537. package/dist/scripts/pre-article-analysis.js +591 -0
  538. package/dist/scripts/pre-article-analysis.js.map +1 -0
  539. package/dist/scripts/scb-client.d.ts +104 -0
  540. package/dist/scripts/scb-client.d.ts.map +1 -0
  541. package/dist/scripts/scb-client.js +286 -0
  542. package/dist/scripts/scb-client.js.map +1 -0
  543. package/dist/scripts/scb-context.d.ts +88 -0
  544. package/dist/scripts/scb-context.d.ts.map +1 -0
  545. package/dist/scripts/scb-context.js +307 -0
  546. package/dist/scripts/scb-context.js.map +1 -0
  547. package/dist/scripts/shared/version.d.ts +9 -0
  548. package/dist/scripts/shared/version.d.ts.map +1 -0
  549. package/dist/scripts/shared/version.js +28 -0
  550. package/dist/scripts/shared/version.js.map +1 -0
  551. package/dist/scripts/statistical-claims-detector.d.ts +119 -0
  552. package/dist/scripts/statistical-claims-detector.d.ts.map +1 -0
  553. package/dist/scripts/statistical-claims-detector.js +391 -0
  554. package/dist/scripts/statistical-claims-detector.js.map +1 -0
  555. package/dist/scripts/sync-cia-schemas.d.ts +52 -0
  556. package/dist/scripts/sync-cia-schemas.d.ts.map +1 -0
  557. package/dist/scripts/sync-cia-schemas.js +195 -0
  558. package/dist/scripts/sync-cia-schemas.js.map +1 -0
  559. package/dist/scripts/translation-dictionary.d.ts +45 -0
  560. package/dist/scripts/translation-dictionary.d.ts.map +1 -0
  561. package/dist/scripts/translation-dictionary.js +3642 -0
  562. package/dist/scripts/translation-dictionary.js.map +1 -0
  563. package/dist/scripts/types/article.d.ts +392 -0
  564. package/dist/scripts/types/article.d.ts.map +1 -0
  565. package/dist/scripts/types/article.js +6 -0
  566. package/dist/scripts/types/article.js.map +1 -0
  567. package/dist/scripts/types/content.d.ts +167 -0
  568. package/dist/scripts/types/content.d.ts.map +1 -0
  569. package/dist/scripts/types/content.js +6 -0
  570. package/dist/scripts/types/content.js.map +1 -0
  571. package/dist/scripts/types/editorial.d.ts +17 -0
  572. package/dist/scripts/types/editorial.d.ts.map +1 -0
  573. package/dist/scripts/types/editorial.js +6 -0
  574. package/dist/scripts/types/editorial.js.map +1 -0
  575. package/dist/scripts/types/language.d.ts +7 -0
  576. package/dist/scripts/types/language.d.ts.map +1 -0
  577. package/dist/scripts/types/language.js +6 -0
  578. package/dist/scripts/types/language.js.map +1 -0
  579. package/dist/scripts/types/mcp.d.ts +117 -0
  580. package/dist/scripts/types/mcp.d.ts.map +1 -0
  581. package/dist/scripts/types/mcp.js +6 -0
  582. package/dist/scripts/types/mcp.js.map +1 -0
  583. package/dist/scripts/types/party.d.ts +9 -0
  584. package/dist/scripts/types/party.d.ts.map +1 -0
  585. package/dist/scripts/types/party.js +6 -0
  586. package/dist/scripts/types/party.js.map +1 -0
  587. package/dist/scripts/types/validation.d.ts +136 -0
  588. package/dist/scripts/types/validation.d.ts.map +1 -0
  589. package/dist/scripts/types/validation.js +6 -0
  590. package/dist/scripts/types/validation.js.map +1 -0
  591. package/dist/scripts/types/workflow.d.ts +78 -0
  592. package/dist/scripts/types/workflow.d.ts.map +1 -0
  593. package/dist/scripts/types/workflow.js +6 -0
  594. package/dist/scripts/types/workflow.js.map +1 -0
  595. package/dist/scripts/update-stats-from-cia.d.ts +44 -0
  596. package/dist/scripts/update-stats-from-cia.d.ts.map +1 -0
  597. package/dist/scripts/update-stats-from-cia.js +310 -0
  598. package/dist/scripts/update-stats-from-cia.js.map +1 -0
  599. package/dist/scripts/validate-against-cia-schemas.d.ts +126 -0
  600. package/dist/scripts/validate-against-cia-schemas.d.ts.map +1 -0
  601. package/dist/scripts/validate-against-cia-schemas.js +299 -0
  602. package/dist/scripts/validate-against-cia-schemas.js.map +1 -0
  603. package/dist/scripts/validate-cross-references.d.ts +49 -0
  604. package/dist/scripts/validate-cross-references.d.ts.map +1 -0
  605. package/dist/scripts/validate-cross-references.js +183 -0
  606. package/dist/scripts/validate-cross-references.js.map +1 -0
  607. package/dist/scripts/validate-file-ownership.d.ts +68 -0
  608. package/dist/scripts/validate-file-ownership.d.ts.map +1 -0
  609. package/dist/scripts/validate-file-ownership.js +135 -0
  610. package/dist/scripts/validate-file-ownership.js.map +1 -0
  611. package/dist/scripts/validate-news-translations.d.ts +27 -0
  612. package/dist/scripts/validate-news-translations.d.ts.map +1 -0
  613. package/dist/scripts/validate-news-translations.js +258 -0
  614. package/dist/scripts/validate-news-translations.js.map +1 -0
  615. package/dist/scripts/validate-translations.d.ts +162 -0
  616. package/dist/scripts/validate-translations.d.ts.map +1 -0
  617. package/dist/scripts/validate-translations.js +378 -0
  618. package/dist/scripts/validate-translations.js.map +1 -0
  619. package/dist/scripts/workflow-state-coordinator.d.ts +354 -0
  620. package/dist/scripts/workflow-state-coordinator.d.ts.map +1 -0
  621. package/dist/scripts/workflow-state-coordinator.js +876 -0
  622. package/dist/scripts/workflow-state-coordinator.js.map +1 -0
  623. package/dist/scripts/world-bank-client.d.ts +122 -0
  624. package/dist/scripts/world-bank-client.d.ts.map +1 -0
  625. package/dist/scripts/world-bank-client.js +192 -0
  626. package/dist/scripts/world-bank-client.js.map +1 -0
  627. package/dist/scripts/world-bank-context.d.ts +88 -0
  628. package/dist/scripts/world-bank-context.d.ts.map +1 -0
  629. package/dist/scripts/world-bank-context.js +331 -0
  630. package/dist/scripts/world-bank-context.js.map +1 -0
  631. package/package.json +33 -8
  632. package/dist/lib/chart-factory.d.ts.map +0 -1
  633. package/dist/lib/chart-factory.js.map +0 -1
  634. package/dist/lib/data-loader.d.ts.map +0 -1
  635. package/dist/lib/data-loader.js.map +0 -1
  636. package/dist/lib/dom-utils.d.ts.map +0 -1
  637. package/dist/lib/dom-utils.js.map +0 -1
  638. package/dist/lib/error-boundary.d.ts.map +0 -1
  639. package/dist/lib/error-boundary.js.map +0 -1
  640. package/dist/lib/fallback-ui.d.ts.map +0 -1
  641. package/dist/lib/fallback-ui.js.map +0 -1
  642. package/dist/lib/index.d.ts.map +0 -1
  643. package/dist/lib/index.js.map +0 -1
  644. package/dist/lib/logger.d.ts.map +0 -1
  645. package/dist/lib/logger.js.map +0 -1
  646. package/dist/lib/theme.d.ts.map +0 -1
  647. package/dist/lib/theme.js.map +0 -1
  648. package/dist/lib/types.d.ts.map +0 -1
  649. package/dist/lib/types.js.map +0 -1
  650. /package/dist/lib/{data-loader.d.ts → shared/data-loader.d.ts} +0 -0
  651. /package/dist/lib/{data-loader.js → shared/data-loader.js} +0 -0
  652. /package/dist/lib/{dom-utils.d.ts → shared/dom-utils.d.ts} +0 -0
  653. /package/dist/lib/{dom-utils.js → shared/dom-utils.js} +0 -0
  654. /package/dist/lib/{error-boundary.d.ts → shared/error-boundary.d.ts} +0 -0
  655. /package/dist/lib/{error-boundary.js → shared/error-boundary.js} +0 -0
  656. /package/dist/lib/{fallback-ui.d.ts → shared/fallback-ui.d.ts} +0 -0
  657. /package/dist/lib/{fallback-ui.js → shared/fallback-ui.js} +0 -0
  658. /package/dist/lib/{index.d.ts → shared/index.d.ts} +0 -0
  659. /package/dist/lib/{index.js → shared/index.js} +0 -0
  660. /package/dist/lib/{logger.d.ts → shared/logger.d.ts} +0 -0
  661. /package/dist/lib/{logger.js → shared/logger.js} +0 -0
  662. /package/dist/lib/{types.d.ts → shared/types.d.ts} +0 -0
  663. /package/dist/lib/{types.js → shared/types.js} +0 -0
@@ -0,0 +1,1017 @@
1
+ /**
2
+ * @module Dashboards/AnomalyDetection
3
+ * @category Intelligence Analysis - Statistical Outlier Detection & Early Warning
4
+ *
5
+ * Anomaly Detection & Early Warning Intelligence Dashboard.
6
+ *
7
+ * Advanced statistical intelligence module implementing Z-score analysis for
8
+ * behavioral anomaly detection across Swedish Parliament activity (2002-2025).
9
+ * Provides real-time early warning capability for unusual patterns in voting,
10
+ * document production, and attendance metrics.
11
+ *
12
+ * ## Intelligence Methodology
13
+ *
14
+ * - Detection Threshold: |Z| >= 2.0 (2 standard deviations)
15
+ * - Severity Classification: CRITICAL (>3σ), HIGH (2-3σ), MODERATE (1-2σ), LOW (<1σ)
16
+ * - Direction Detection: UNUSUALLY_HIGH, UNUSUALLY_LOW, WITHIN_NORMAL_RANGE
17
+ * - Temporal Coverage: 23 years × 4 quarters = 92 time periods
18
+ *
19
+ * ## Data Source
20
+ *
21
+ * - `view_riksdagen_seasonal_anomaly_detection_sample.csv`
22
+ *
23
+ * @author Hack23 AB - Political Intelligence Team
24
+ * @license Apache-2.0
25
+ * @version 2.0.0
26
+ * @since 2024
27
+ * @see {@link https://github.com/Hack23/cia|CIA Platform Data Pipeline}
28
+
29
+ *
30
+ * @intelligence Statistical Outlier Detection & Early Warning System — advanced Z-score analysis (threshold |Z| >= 2.0) for behavioral anomaly detection across 23 years × 4 quarters = 92 time periods of Swedish Parliament activity. Severity classification: CRITICAL (>3σ), HIGH (2-3σ), MODERATE (1-2σ). Direction detection: UNUSUALLY_HIGH, UNUSUALLY_LOW, WITHIN_NORMAL_RANGE.
31
+ *
32
+ * @business Algorithmic intelligence differentiator — statistical anomaly detection represents the most technically sophisticated product capability. Demonstrates platform as an AI/ML-adjacent intelligence tool. Highest perceived value for enterprise and institutional clients. Foundation for automated anomaly alerting subscription.
33
+ *
34
+ * @marketing Alert-driven content generation — each detected anomaly is an automatically generated content opportunity: push notifications, email alerts, social media posts, and newsletter items. Anomaly alerts create FOMO (fear of missing out) driving subscription growth and daily active usage.
35
+ * */
36
+ import { logger, detectLanguage, showDataSourceDisclaimer, } from '../shared/index.js';
37
+ const d3 = globalThis.d3;
38
+ const Chart = globalThis.Chart;
39
+ // ============================================================================
40
+ // CONFIGURATION
41
+ // ============================================================================
42
+ const CONFIG = {
43
+ dataUrls: [
44
+ 'cia-data/seasonal/view_riksdagen_seasonal_anomaly_detection_sample.csv',
45
+ 'https://raw.githubusercontent.com/Hack23/cia/master/service.data.impl/sample-data/view_riksdagen_seasonal_anomaly_detection_sample.csv',
46
+ ],
47
+ cacheKey: 'riksdag_anomaly_detection',
48
+ cacheDuration: 60 * 60 * 1000,
49
+ alertDismissKey: 'anomaly_alert_dismissed',
50
+ alertDismissDuration: 24 * 60 * 60 * 1000,
51
+ };
52
+ const ALERT_CONFIG = {
53
+ CRITICAL: { color: '#d32f2f', icon: '🔴', notify: true },
54
+ HIGH: { color: '#f57c00', icon: '🟠', notify: true },
55
+ MODERATE: { color: '#fbc02d', icon: '🟡', notify: false },
56
+ LOW: { color: '#388e3c', icon: '🟢', notify: false },
57
+ };
58
+ // ============================================================================
59
+ // TRANSLATIONS
60
+ // ============================================================================
61
+ const TRANSLATIONS = {
62
+ en: {
63
+ title: 'Anomaly Detection & Early Warning System',
64
+ severityLabel: 'Severity',
65
+ typeLabel: 'Type',
66
+ directionLabel: 'Direction',
67
+ yearLabel: 'Year',
68
+ allSeverities: 'All Severities',
69
+ allTypes: 'All Types',
70
+ allDirections: 'All Directions',
71
+ allYears: 'All Years',
72
+ severity: { CRITICAL: 'Critical', HIGH: 'High', MODERATE: 'Moderate', LOW: 'Low' },
73
+ type: {
74
+ BALLOT_ANOMALY: 'Ballot Anomaly',
75
+ DOCUMENT_ANOMALY: 'Document Anomaly',
76
+ ATTENDANCE_ANOMALY: 'Attendance Anomaly',
77
+ NO_ANOMALY: 'No Anomaly',
78
+ },
79
+ direction: {
80
+ UNUSUALLY_HIGH: 'Unusually High',
81
+ UNUSUALLY_LOW: 'Unusually Low',
82
+ WITHIN_NORMAL_RANGE: 'Within Normal Range',
83
+ },
84
+ alertPrefix: 'CRITICAL ANOMALY DETECTED',
85
+ dismissAlert: 'Dismiss',
86
+ loading: 'Loading anomaly data...',
87
+ error: 'Error loading data',
88
+ noData: 'No anomaly data available',
89
+ chartTitles: {
90
+ timeline: 'Anomaly Timeline (2002-2025)',
91
+ distribution: 'Z-Score Distribution',
92
+ typeBreakdown: 'Anomaly Type Distribution',
93
+ heatmap: 'Severity Heat Map (Year × Quarter)',
94
+ quarterly: 'Anomaly Frequency by Quarter',
95
+ recent: 'Recent Anomalies (Last 5)',
96
+ },
97
+ chartDescriptions: {
98
+ timeline: 'Chronological view of detected anomalies with severity coding',
99
+ distribution: 'Normal curve with outlier markers (|Z| ≥ 2.0)',
100
+ typeBreakdown: 'Ballot vs. Document anomaly distribution',
101
+ heatmap: 'Grid showing anomaly severity by year and quarter',
102
+ quarterly: 'Q1-Q4 anomaly counts across all years',
103
+ recent: 'Most recent anomalies with details',
104
+ },
105
+ quarters: {
106
+ Q1: 'Q1 (Jan-Mar)',
107
+ Q2: 'Q2 (Apr-Jun)',
108
+ Q3: 'Q3 (Jul-Sep)',
109
+ Q4: 'Q4 (Oct-Dec)',
110
+ },
111
+ },
112
+ sv: {
113
+ title: 'Anomalidetektering och Tidig Varning',
114
+ severityLabel: 'Allvarlighetsgrad',
115
+ typeLabel: 'Typ',
116
+ directionLabel: 'Riktning',
117
+ yearLabel: 'År',
118
+ allSeverities: 'Alla allvarlighetsgrader',
119
+ allTypes: 'Alla typer',
120
+ allDirections: 'Alla riktningar',
121
+ allYears: 'Alla år',
122
+ severity: { CRITICAL: 'Kritisk', HIGH: 'Hög', MODERATE: 'Måttlig', LOW: 'Låg' },
123
+ type: {
124
+ BALLOT_ANOMALY: 'Omröstningsanomali',
125
+ DOCUMENT_ANOMALY: 'Dokumentanomali',
126
+ ATTENDANCE_ANOMALY: 'Närvaroanomali',
127
+ NO_ANOMALY: 'Ingen anomali',
128
+ },
129
+ direction: {
130
+ UNUSUALLY_HIGH: 'Ovanligt hög',
131
+ UNUSUALLY_LOW: 'Ovanligt låg',
132
+ WITHIN_NORMAL_RANGE: 'Inom normalintervall',
133
+ },
134
+ alertPrefix: 'KRITISK ANOMALI UPPTÄCKT',
135
+ dismissAlert: 'Avvisa',
136
+ loading: 'Laddar anomalidata...',
137
+ error: 'Fel vid laddning av data',
138
+ noData: 'Ingen anomalidata tillgänglig',
139
+ chartTitles: {
140
+ timeline: 'Anomalitidslinje (2002-2025)',
141
+ distribution: 'Z-poängfördelning',
142
+ typeBreakdown: 'Anomalitypfördelning',
143
+ heatmap: 'Allvarlighetsvärmekartan (År × Kvartal)',
144
+ quarterly: 'Anomalifrekvens per kvartal',
145
+ recent: 'Senaste anomalierna (Senaste 5)',
146
+ },
147
+ chartDescriptions: {
148
+ timeline: 'Kronologisk vy av upptäckta anomalier med allvarlighetskodning',
149
+ distribution: 'Normalkurva med utliggare (|Z| ≥ 2.0)',
150
+ typeBreakdown: 'Omröstnings- vs. dokumentanomalier',
151
+ heatmap: 'Rutnät som visar anomalins allvarlighetsgrad per år och kvartal',
152
+ quarterly: 'Q1-Q4 anomaliräkning över alla år',
153
+ recent: 'Senaste anomalier med detaljer',
154
+ },
155
+ quarters: {
156
+ Q1: 'Q1 (Jan-Mar)',
157
+ Q2: 'Q2 (Apr-Jun)',
158
+ Q3: 'Q3 (Jul-Sep)',
159
+ Q4: 'Q4 (Okt-Dec)',
160
+ },
161
+ },
162
+ da: { title: 'Anomalidetektering og Tidlig Advarsel', severity: { CRITICAL: 'Kritisk', HIGH: 'Høj', MODERATE: 'Moderat', LOW: 'Lav' } },
163
+ no: { title: 'Anomalideteksjon og Tidlig Varsel', severity: { CRITICAL: 'Kritisk', HIGH: 'Høy', MODERATE: 'Moderat', LOW: 'Lav' } },
164
+ fi: { title: 'Poikkeavuuksien havaitseminen ja varhainen varoitus', severity: { CRITICAL: 'Kriittinen', HIGH: 'Korkea', MODERATE: 'Kohtalainen', LOW: 'Matala' } },
165
+ de: { title: 'Anomalieerkennung und Frühwarnsystem', severity: { CRITICAL: 'Kritisch', HIGH: 'Hoch', MODERATE: 'Mäßig', LOW: 'Niedrig' } },
166
+ fr: { title: "Détection d'anomalies et alerte précoce", severity: { CRITICAL: 'Critique', HIGH: 'Élevé', MODERATE: 'Modéré', LOW: 'Faible' } },
167
+ es: { title: 'Detección de anomalías y alerta temprana', severity: { CRITICAL: 'Crítico', HIGH: 'Alto', MODERATE: 'Moderado', LOW: 'Bajo' } },
168
+ nl: { title: 'Anomaliedetectie en vroegtijdige waarschuwing', severity: { CRITICAL: 'Kritiek', HIGH: 'Hoog', MODERATE: 'Gematigd', LOW: 'Laag' } },
169
+ ar: { title: 'اكتشاف الشذوذ والإنذار المبكر', severity: { CRITICAL: 'حرج', HIGH: 'عالي', MODERATE: 'معتدل', LOW: 'منخفض' } },
170
+ he: { title: 'זיהוי חריגות והתרעה מוקדמת', severity: { CRITICAL: 'קריטי', HIGH: 'גבוה', MODERATE: 'בינוני', LOW: 'נמוך' } },
171
+ ja: { title: '異常検知と早期警告', severity: { CRITICAL: '重大', HIGH: '高', MODERATE: '中', LOW: '低' } },
172
+ ko: { title: '이상 탐지 및 조기 경보', severity: { CRITICAL: '치명적', HIGH: '높음', MODERATE: '보통', LOW: '낮음' } },
173
+ zh: { title: '异常检测与预警', severity: { CRITICAL: '严重', HIGH: '高', MODERATE: '中等', LOW: '低' } },
174
+ };
175
+ // ============================================================================
176
+ // HELPERS
177
+ // ============================================================================
178
+ function getTranslations() {
179
+ const lang = detectLanguage();
180
+ const t = TRANSLATIONS[lang] || TRANSLATIONS.en;
181
+ // Merge minimal translations over the English defaults
182
+ if (!('loading' in t)) {
183
+ return { ...TRANSLATIONS.en, ...t };
184
+ }
185
+ return t;
186
+ }
187
+ /**
188
+ * Generate synthetic fallback data when all CSV sources are unavailable.
189
+ * Ensures charts render with representative sample data rather than showing
190
+ * an error state, consistent with how other dashboards handle data failures.
191
+ */
192
+ function generateFallbackData() {
193
+ const data = [];
194
+ const quarterLabels = ['Q1_JAN_MAR', 'Q2_APR_JUN', 'Q3_JUL_SEP', 'Q4_OCT_DEC'];
195
+ const periods = ['Winter Session', 'Spring Session', 'Summer Recess/Election', 'Autumn Session'];
196
+ for (let year = 2018; year <= 2025; year++) {
197
+ for (let quarter = 1; quarter <= 4; quarter++) {
198
+ // Deterministic, bounded z-scores to avoid random HIGH/CRITICAL anomalies in fallback data
199
+ const ballotZRaw = (((year * 31 + quarter * 17) % 300) / 100) - 1.5;
200
+ const docZRaw = (((year * 19 + quarter * 23) % 300) / 100) - 1.5;
201
+ const ballotZ = ballotZRaw.toFixed(4);
202
+ const docZ = docZRaw.toFixed(4);
203
+ const absBallotZ = Math.abs(ballotZRaw);
204
+ const absDocZ = Math.abs(docZRaw);
205
+ const maxZ = Math.max(absBallotZ, absDocZ);
206
+ let severity = 'LOW';
207
+ let anomalyType = 'NO_ANOMALY';
208
+ let direction = 'WITHIN_NORMAL_RANGE';
209
+ const dominantZ = absBallotZ >= absDocZ ? ballotZRaw : docZRaw;
210
+ if (maxZ >= 3.0) {
211
+ severity = 'CRITICAL';
212
+ anomalyType = absBallotZ >= absDocZ ? 'BALLOT_ANOMALY' : 'DOCUMENT_ANOMALY';
213
+ direction = dominantZ > 0 ? 'UNUSUALLY_HIGH' : 'UNUSUALLY_LOW';
214
+ }
215
+ else if (maxZ >= 2.0) {
216
+ severity = 'HIGH';
217
+ anomalyType = absBallotZ >= absDocZ ? 'BALLOT_ANOMALY' : 'DOCUMENT_ANOMALY';
218
+ direction = dominantZ > 0 ? 'UNUSUALLY_HIGH' : 'UNUSUALLY_LOW';
219
+ }
220
+ else if (maxZ >= 1.0) {
221
+ severity = 'MODERATE';
222
+ }
223
+ data.push({
224
+ year: String(year),
225
+ quarter: String(quarter),
226
+ is_election_year: (year === 2022) ? 't' : 'f',
227
+ // Deterministic synthetic counts for reproducible fallback data
228
+ total_ballots: String(100 + ((year * 13 + quarter * 7) % 200)),
229
+ active_politicians: '349',
230
+ attendance_rate: '100.00',
231
+ documents_produced: String(200 + ((year * 29 + quarter * 11) % 500)),
232
+ q_baseline_ballots: '150.00',
233
+ q_stddev_ballots: '40.00',
234
+ ballot_z_score: ballotZ,
235
+ q_baseline_docs: '300.00',
236
+ q_stddev_docs: '100.00',
237
+ doc_z_score: docZ,
238
+ q_baseline_attendance: '100.00',
239
+ q_stddev_attendance: '0',
240
+ attendance_z_score: '0',
241
+ activity_classification: maxZ >= 2 ? 'ANOMALY_DETECTED' : 'NORMAL_ACTIVITY',
242
+ quarter_label: quarterLabels[quarter - 1],
243
+ parliamentary_period: periods[quarter - 1],
244
+ anomaly_type: anomalyType,
245
+ anomaly_direction: direction,
246
+ max_z_score: maxZ.toFixed(4),
247
+ anomaly_severity: severity,
248
+ });
249
+ }
250
+ }
251
+ data.sort((a, b) => {
252
+ const yearDiff = parseInt(b.year, 10) - parseInt(a.year, 10);
253
+ if (yearDiff !== 0)
254
+ return yearDiff;
255
+ return parseInt(b.quarter, 10) - parseInt(a.quarter, 10);
256
+ });
257
+ return data;
258
+ }
259
+ // ============================================================================
260
+ // DATA MANAGER
261
+ // ============================================================================
262
+ class AnomalyDetectionDataManager {
263
+ data = null;
264
+ dataSourceType = 'live';
265
+ getTranslations() {
266
+ return getTranslations();
267
+ }
268
+ async fetchData() {
269
+ // Check cache first
270
+ const cached = this.getCachedData();
271
+ if (cached) {
272
+ logger.debug('Using cached anomaly data');
273
+ this.data = cached;
274
+ return cached;
275
+ }
276
+ logger.debug('Fetching fresh anomaly data from CIA...');
277
+ let response = null;
278
+ for (const url of CONFIG.dataUrls) {
279
+ try {
280
+ logger.debug(`Attempting to fetch from: ${url}`);
281
+ response = await fetch(url);
282
+ if (response.ok) {
283
+ logger.debug(`✓ Successfully fetched from: ${url}`);
284
+ break;
285
+ }
286
+ else {
287
+ logger.warn(`⚠ Failed to fetch from ${url}: HTTP ${response.status}`);
288
+ response = null;
289
+ }
290
+ }
291
+ catch (error) {
292
+ logger.warn(`⚠ Error fetching from ${url}:`, error.message);
293
+ response = null;
294
+ }
295
+ }
296
+ if (!response) {
297
+ logger.warn('All data sources failed, using synthetic fallback data');
298
+ const fallback = generateFallbackData();
299
+ this.data = fallback;
300
+ this.dataSourceType = 'synthetic';
301
+ return fallback;
302
+ }
303
+ const csvText = await response.text();
304
+ const parsedData = this.parseCSV(csvText);
305
+ this.setCachedData(parsedData);
306
+ this.data = parsedData;
307
+ logger.debug(`Loaded ${parsedData.length} anomaly records`);
308
+ return parsedData;
309
+ }
310
+ parseCSV(csvText) {
311
+ const lines = csvText.trim().split('\n');
312
+ const headers = lines[0].split(',').map((h) => h.trim());
313
+ const data = [];
314
+ for (let i = 1; i < lines.length; i++) {
315
+ const values = this.parseCSVLine(lines[i]);
316
+ if (values.length === headers.length) {
317
+ const record = {};
318
+ headers.forEach((header, index) => {
319
+ record[header] = values[index];
320
+ });
321
+ data.push(record);
322
+ }
323
+ }
324
+ data.sort((a, b) => {
325
+ const yearDiff = parseInt(b.year, 10) - parseInt(a.year, 10);
326
+ if (yearDiff !== 0)
327
+ return yearDiff;
328
+ return parseInt(b.quarter, 10) - parseInt(a.quarter, 10);
329
+ });
330
+ return data;
331
+ }
332
+ parseCSVLine(line) {
333
+ const values = [];
334
+ let current = '';
335
+ let inQuotes = false;
336
+ for (let i = 0; i < line.length; i++) {
337
+ const char = line[i];
338
+ if (char === '"') {
339
+ inQuotes = !inQuotes;
340
+ }
341
+ else if (char === ',' && !inQuotes) {
342
+ values.push(current.trim());
343
+ current = '';
344
+ }
345
+ else {
346
+ current += char;
347
+ }
348
+ }
349
+ values.push(current.trim());
350
+ return values;
351
+ }
352
+ getCachedData() {
353
+ try {
354
+ const cached = localStorage.getItem(CONFIG.cacheKey);
355
+ if (!cached)
356
+ return null;
357
+ const { data, timestamp } = JSON.parse(cached);
358
+ const age = Date.now() - timestamp;
359
+ if (age < CONFIG.cacheDuration)
360
+ return data;
361
+ localStorage.removeItem(CONFIG.cacheKey);
362
+ return null;
363
+ }
364
+ catch {
365
+ return null;
366
+ }
367
+ }
368
+ setCachedData(data) {
369
+ try {
370
+ localStorage.setItem(CONFIG.cacheKey, JSON.stringify({ data, timestamp: Date.now() }));
371
+ }
372
+ catch (error) {
373
+ logger.error('Error setting cache:', error);
374
+ }
375
+ }
376
+ identifyActiveAnomalies() {
377
+ if (!this.data)
378
+ return [];
379
+ return this.data
380
+ .filter((record) => record.anomaly_type !== 'NO_ANOMALY')
381
+ .sort((a, b) => Math.abs(parseFloat(b.max_z_score)) -
382
+ Math.abs(parseFloat(a.max_z_score)));
383
+ }
384
+ calculateAnomalyStats() {
385
+ if (!this.data)
386
+ return null;
387
+ const anomalies = this.identifyActiveAnomalies();
388
+ const total = this.data.length;
389
+ const anomalyCount = anomalies.length;
390
+ const criticalCount = anomalies.filter((a) => a.anomaly_severity === 'CRITICAL').length;
391
+ const highCount = anomalies.filter((a) => a.anomaly_severity === 'HIGH').length;
392
+ const moderateCount = anomalies.filter((a) => a.anomaly_severity === 'MODERATE').length;
393
+ const ballotAnomalies = anomalies.filter((a) => a.anomaly_type === 'BALLOT_ANOMALY').length;
394
+ const documentAnomalies = anomalies.filter((a) => a.anomaly_type === 'DOCUMENT_ANOMALY').length;
395
+ const attendanceAnomalies = anomalies.filter((a) => a.anomaly_type === 'ATTENDANCE_ANOMALY').length;
396
+ const avgZScore = anomalies.length > 0
397
+ ? anomalies.reduce((sum, a) => sum + Math.abs(parseFloat(a.max_z_score)), 0) /
398
+ anomalies.length
399
+ : 0;
400
+ return {
401
+ total,
402
+ anomalyCount,
403
+ anomalyRate: ((anomalyCount / total) * 100).toFixed(1),
404
+ criticalCount,
405
+ highCount,
406
+ moderateCount,
407
+ ballotAnomalies,
408
+ documentAnomalies,
409
+ attendanceAnomalies,
410
+ avgZScore: avgZScore.toFixed(2),
411
+ };
412
+ }
413
+ checkForCriticalAnomalies() {
414
+ if (!this.data || this.data.length === 0)
415
+ return null;
416
+ const recentQuarters = this.data.slice(0, 2);
417
+ const criticalAnomalies = recentQuarters.filter((record) => record.anomaly_severity === 'CRITICAL' || record.anomaly_severity === 'HIGH');
418
+ return criticalAnomalies.length > 0 ? criticalAnomalies[0] : null;
419
+ }
420
+ }
421
+ // ============================================================================
422
+ // ALERT SYSTEM
423
+ // ============================================================================
424
+ class AnomalyAlertSystem {
425
+ constructor(_dataManager) {
426
+ }
427
+ checkAndDisplayAlert(anomaly) {
428
+ if (!anomaly)
429
+ return;
430
+ const dismissedTimestamp = localStorage.getItem(CONFIG.alertDismissKey);
431
+ if (dismissedTimestamp) {
432
+ const age = Date.now() - parseInt(dismissedTimestamp, 10);
433
+ if (age < CONFIG.alertDismissDuration) {
434
+ logger.debug('Alert was recently dismissed, not showing');
435
+ return;
436
+ }
437
+ }
438
+ const banner = document.getElementById('anomaly-alert-banner');
439
+ const message = document.getElementById('alert-message');
440
+ if (banner && message) {
441
+ const alertText = this.generateAlertMessage(anomaly);
442
+ message.textContent = alertText;
443
+ const severity = anomaly.anomaly_severity.toLowerCase();
444
+ banner.className = `alert-banner ${severity}`;
445
+ banner.classList.remove('hidden');
446
+ const dismissBtn = banner.querySelector('.dismiss-alert');
447
+ if (dismissBtn) {
448
+ dismissBtn.onclick = () => this.dismissAlert();
449
+ }
450
+ }
451
+ }
452
+ dismissAlert() {
453
+ const banner = document.getElementById('anomaly-alert-banner');
454
+ if (banner) {
455
+ banner.classList.add('hidden');
456
+ localStorage.setItem(CONFIG.alertDismissKey, Date.now().toString());
457
+ }
458
+ }
459
+ generateAlertMessage(anomaly) {
460
+ const year = anomaly.year;
461
+ const quarter = `Q${anomaly.quarter}`;
462
+ const type = anomaly.anomaly_type;
463
+ const zScore = parseFloat(anomaly.max_z_score).toFixed(2);
464
+ const direction = anomaly.anomaly_direction;
465
+ let actualValue = '';
466
+ let baseline = '';
467
+ if (type === 'BALLOT_ANOMALY') {
468
+ actualValue = `${anomaly.total_ballots} ballots`;
469
+ baseline = `${Math.round(parseFloat(anomaly.q_baseline_ballots))} baseline`;
470
+ }
471
+ else if (type === 'DOCUMENT_ANOMALY') {
472
+ actualValue = `${anomaly.documents_produced} documents`;
473
+ baseline = `${Math.round(parseFloat(anomaly.q_baseline_docs))} baseline`;
474
+ }
475
+ return `${year} ${quarter} ${type}: ${parseFloat(zScore) > 0 ? '+' : ''}${zScore} Z-score, ${direction} (${actualValue} vs ${baseline})`;
476
+ }
477
+ }
478
+ // ============================================================================
479
+ // CHART RENDERERS
480
+ // ============================================================================
481
+ class AnomalyDetectionCharts {
482
+ dataManager;
483
+ chartInstances = {};
484
+ constructor(dataManager) {
485
+ this.dataManager = dataManager;
486
+ }
487
+ async renderAll() {
488
+ await this.renderAnomalyTimeline();
489
+ await this.renderZScoreDistribution();
490
+ await this.renderAnomalyTypeChart();
491
+ await this.renderSeverityHeatmap();
492
+ await this.renderQuarterlyFrequency();
493
+ await this.renderRecentAnomaliesFeed();
494
+ }
495
+ async renderAnomalyTimeline() {
496
+ const canvas = document.getElementById('anomaly-timeline-chart');
497
+ if (!canvas)
498
+ return;
499
+ const data = this.dataManager.data;
500
+ const anomalies = data.filter((r) => r.anomaly_type !== 'NO_ANOMALY');
501
+ const dataPoints = anomalies.map((record) => {
502
+ const year = parseInt(record.year, 10);
503
+ const quarter = parseInt(record.quarter, 10);
504
+ return {
505
+ x: year + (quarter - 1) * 0.25,
506
+ y: parseFloat(record.max_z_score),
507
+ record,
508
+ };
509
+ });
510
+ if (this.chartInstances.timeline)
511
+ this.chartInstances.timeline.destroy();
512
+ const ctx = canvas.getContext('2d');
513
+ this.chartInstances.timeline = new Chart(ctx, {
514
+ type: 'scatter',
515
+ data: {
516
+ datasets: [
517
+ {
518
+ label: 'Anomalies',
519
+ data: dataPoints,
520
+ backgroundColor: dataPoints.map((p) => this.getSeverityColor(p.record.anomaly_severity)),
521
+ borderColor: dataPoints.map((p) => this.getSeverityColor(p.record.anomaly_severity)),
522
+ pointRadius: dataPoints.map((p) => this.getSeverityRadius(p.record.anomaly_severity)),
523
+ pointHoverRadius: 8,
524
+ },
525
+ ],
526
+ },
527
+ options: {
528
+ responsive: true,
529
+ maintainAspectRatio: false,
530
+ plugins: {
531
+ legend: { display: false },
532
+ tooltip: {
533
+ callbacks: {
534
+ label: (context) => {
535
+ const record = context.raw.record;
536
+ return [
537
+ `${record.year} Q${record.quarter}`,
538
+ `Type: ${record.anomaly_type}`,
539
+ `Severity: ${record.anomaly_severity}`,
540
+ `Z-Score: ${parseFloat(record.max_z_score).toFixed(2)}`,
541
+ `Direction: ${record.anomaly_direction}`,
542
+ ];
543
+ },
544
+ },
545
+ },
546
+ },
547
+ scales: {
548
+ x: {
549
+ title: { display: true, text: 'Year' },
550
+ ticks: { callback: (value) => Math.floor(value) },
551
+ },
552
+ y: {
553
+ title: { display: true, text: 'Z-Score' },
554
+ grid: {
555
+ color: (context) => {
556
+ if (context.tick.value === 2.0 || context.tick.value === -2.0) {
557
+ return '#f57c00';
558
+ }
559
+ return 'rgba(255, 255, 255, 0.1)';
560
+ },
561
+ },
562
+ },
563
+ },
564
+ },
565
+ });
566
+ }
567
+ async renderZScoreDistribution() {
568
+ const canvas = document.getElementById('zscore-distribution-chart');
569
+ if (!canvas)
570
+ return;
571
+ const data = this.dataManager.data;
572
+ const zScores = [];
573
+ data.forEach((record) => {
574
+ const ballotZ = parseFloat(record.ballot_z_score);
575
+ const docZ = parseFloat(record.doc_z_score);
576
+ const attendanceZ = parseFloat(record.attendance_z_score);
577
+ if (!isNaN(ballotZ))
578
+ zScores.push(ballotZ);
579
+ if (!isNaN(docZ))
580
+ zScores.push(docZ);
581
+ if (!isNaN(attendanceZ))
582
+ zScores.push(attendanceZ);
583
+ });
584
+ const bins = [];
585
+ const binSize = 0.5;
586
+ const minZ = -3;
587
+ const maxZ = 11;
588
+ for (let i = minZ; i < maxZ; i += binSize) {
589
+ bins.push({
590
+ min: i,
591
+ max: i + binSize,
592
+ count: 0,
593
+ isOutlier: Math.abs(i) >= 2.0 || Math.abs(i + binSize) >= 2.0,
594
+ });
595
+ }
596
+ zScores.forEach((z) => {
597
+ const bin = bins.find((b) => z >= b.min && z < b.max);
598
+ if (bin)
599
+ bin.count++;
600
+ });
601
+ if (this.chartInstances.distribution)
602
+ this.chartInstances.distribution.destroy();
603
+ const ctx = canvas.getContext('2d');
604
+ this.chartInstances.distribution = new Chart(ctx, {
605
+ type: 'bar',
606
+ data: {
607
+ labels: bins.map((b) => `${b.min.toFixed(1)}`),
608
+ datasets: [
609
+ {
610
+ label: 'Frequency',
611
+ data: bins.map((b) => b.count),
612
+ backgroundColor: bins.map((b) => b.isOutlier ? 'rgba(211, 47, 47, 0.7)' : 'rgba(0, 217, 255, 0.7)'),
613
+ borderColor: bins.map((b) => (b.isOutlier ? '#d32f2f' : '#00d9ff')),
614
+ borderWidth: 1,
615
+ },
616
+ ],
617
+ },
618
+ options: {
619
+ responsive: true,
620
+ maintainAspectRatio: false,
621
+ plugins: {
622
+ legend: { display: false },
623
+ tooltip: {
624
+ callbacks: { label: (context) => `Count: ${context.parsed.y}` },
625
+ },
626
+ },
627
+ scales: {
628
+ x: { title: { display: true, text: 'Z-Score' } },
629
+ y: { title: { display: true, text: 'Frequency' }, beginAtZero: true },
630
+ },
631
+ },
632
+ });
633
+ }
634
+ async renderAnomalyTypeChart() {
635
+ const canvas = document.getElementById('anomaly-type-chart');
636
+ if (!canvas)
637
+ return;
638
+ const anomalies = this.dataManager.identifyActiveAnomalies();
639
+ const ballotCount = anomalies.filter((a) => a.anomaly_type === 'BALLOT_ANOMALY').length;
640
+ const documentCount = anomalies.filter((a) => a.anomaly_type === 'DOCUMENT_ANOMALY').length;
641
+ const attendanceCount = anomalies.filter((a) => a.anomaly_type === 'ATTENDANCE_ANOMALY').length;
642
+ if (this.chartInstances.typeChart)
643
+ this.chartInstances.typeChart.destroy();
644
+ const ctx = canvas.getContext('2d');
645
+ this.chartInstances.typeChart = new Chart(ctx, {
646
+ type: 'doughnut',
647
+ data: {
648
+ labels: ['Ballot Anomaly', 'Document Anomaly', 'Attendance Anomaly'],
649
+ datasets: [
650
+ {
651
+ data: [ballotCount, documentCount, attendanceCount],
652
+ backgroundColor: [
653
+ 'rgba(25, 118, 210, 0.8)',
654
+ 'rgba(56, 142, 60, 0.8)',
655
+ 'rgba(245, 124, 0, 0.8)',
656
+ ],
657
+ borderColor: ['#1976d2', '#388e3c', '#f57c00'],
658
+ borderWidth: 2,
659
+ },
660
+ ],
661
+ },
662
+ options: {
663
+ responsive: true,
664
+ maintainAspectRatio: false,
665
+ plugins: {
666
+ legend: { position: 'bottom' },
667
+ tooltip: {
668
+ callbacks: {
669
+ label: (context) => {
670
+ const total = ballotCount + documentCount + attendanceCount;
671
+ const pct = total > 0 ? ((context.parsed / total) * 100).toFixed(1) : 0;
672
+ return `${context.label}: ${context.parsed} (${pct}%)`;
673
+ },
674
+ },
675
+ },
676
+ },
677
+ },
678
+ });
679
+ }
680
+ async renderSeverityHeatmap() {
681
+ const container = document.getElementById('severity-heatmap');
682
+ if (!container)
683
+ return;
684
+ const data = this.dataManager.data;
685
+ container.innerHTML = '';
686
+ const years = Array.from(new Set(data.map((r) => parseInt(r.year, 10)))).sort();
687
+ const quarters = [1, 2, 3, 4];
688
+ const width = container.clientWidth || 800;
689
+ const height = Math.min(600, years.length * 25);
690
+ const margin = { top: 40, right: 40, bottom: 40, left: 60 };
691
+ const cellWidth = (width - margin.left - margin.right) / quarters.length;
692
+ const cellHeight = (height - margin.top - margin.bottom) / years.length;
693
+ const svg = d3
694
+ .select(container)
695
+ .append('svg')
696
+ .attr('width', width)
697
+ .attr('height', height);
698
+ const cells = svg.selectAll('g').data(data).enter().append('g');
699
+ cells
700
+ .append('rect')
701
+ .attr('x', (d) => margin.left + (parseInt(d.quarter) - 1) * cellWidth)
702
+ .attr('y', (d) => {
703
+ const yearIndex = years.indexOf(parseInt(d.year));
704
+ return margin.top + yearIndex * cellHeight;
705
+ })
706
+ .attr('width', cellWidth - 2)
707
+ .attr('height', cellHeight - 2)
708
+ .attr('fill', (d) => this.getHeatmapColor(d.anomaly_severity))
709
+ .attr('stroke', '#0a0e27')
710
+ .attr('stroke-width', 1)
711
+ .style('cursor', 'pointer')
712
+ .on('mouseover', function (event, d) {
713
+ d3.select(this).attr('stroke', '#00d9ff').attr('stroke-width', 2);
714
+ d3.select('body')
715
+ .append('div')
716
+ .attr('class', 'heatmap-tooltip')
717
+ .style('position', 'absolute')
718
+ .style('background', 'rgba(10, 14, 39, 0.95)')
719
+ .style('color', '#fff')
720
+ .style('padding', '10px')
721
+ .style('border-radius', '4px')
722
+ .style('border', '1px solid #00d9ff')
723
+ .style('pointer-events', 'none')
724
+ .style('z-index', '10000')
725
+ .html(`<strong>${d.year} Q${d.quarter}</strong><br>
726
+ Severity: ${d.anomaly_severity}<br>
727
+ Type: ${d.anomaly_type}<br>
728
+ Max Z-Score: ${parseFloat(d.max_z_score).toFixed(2)}`)
729
+ .style('left', `${event.pageX + 10}px`)
730
+ .style('top', `${event.pageY - 10}px`);
731
+ })
732
+ .on('mouseout', function () {
733
+ d3.select(this).attr('stroke', '#0a0e27').attr('stroke-width', 1);
734
+ d3.selectAll('.heatmap-tooltip').remove();
735
+ });
736
+ svg
737
+ .selectAll('.year-label')
738
+ .data(years)
739
+ .enter()
740
+ .append('text')
741
+ .attr('class', 'year-label')
742
+ .attr('x', margin.left - 10)
743
+ .attr('y', (_d, i) => margin.top + i * cellHeight + cellHeight / 2)
744
+ .attr('text-anchor', 'end')
745
+ .attr('dominant-baseline', 'middle')
746
+ .attr('fill', '#e0e0e0')
747
+ .attr('font-size', '12px')
748
+ .text((d) => d);
749
+ svg
750
+ .selectAll('.quarter-label')
751
+ .data(quarters)
752
+ .enter()
753
+ .append('text')
754
+ .attr('class', 'quarter-label')
755
+ .attr('x', (_d, i) => margin.left + i * cellWidth + cellWidth / 2)
756
+ .attr('y', margin.top - 10)
757
+ .attr('text-anchor', 'middle')
758
+ .attr('fill', '#e0e0e0')
759
+ .attr('font-size', '12px')
760
+ .text((d) => `Q${d}`);
761
+ }
762
+ async renderQuarterlyFrequency() {
763
+ const canvas = document.getElementById('quarterly-frequency-chart');
764
+ if (!canvas)
765
+ return;
766
+ const anomalies = this.dataManager.identifyActiveAnomalies();
767
+ const quarterData = {
768
+ 1: { critical: 0, high: 0, moderate: 0, total: 0 },
769
+ 2: { critical: 0, high: 0, moderate: 0, total: 0 },
770
+ 3: { critical: 0, high: 0, moderate: 0, total: 0 },
771
+ 4: { critical: 0, high: 0, moderate: 0, total: 0 },
772
+ };
773
+ anomalies.forEach((record) => {
774
+ const quarter = parseInt(record.quarter, 10);
775
+ const severity = record.anomaly_severity;
776
+ quarterData[quarter].total++;
777
+ if (severity === 'CRITICAL')
778
+ quarterData[quarter].critical++;
779
+ else if (severity === 'HIGH')
780
+ quarterData[quarter].high++;
781
+ else if (severity === 'MODERATE')
782
+ quarterData[quarter].moderate++;
783
+ });
784
+ if (this.chartInstances.quarterly)
785
+ this.chartInstances.quarterly.destroy();
786
+ const ctx = canvas.getContext('2d');
787
+ this.chartInstances.quarterly = new Chart(ctx, {
788
+ type: 'bar',
789
+ data: {
790
+ labels: ['Q1', 'Q2', 'Q3', 'Q4'],
791
+ datasets: [
792
+ {
793
+ label: 'Critical',
794
+ data: [1, 2, 3, 4].map((q) => quarterData[q].critical),
795
+ backgroundColor: 'rgba(211, 47, 47, 0.8)',
796
+ borderColor: '#d32f2f',
797
+ borderWidth: 1,
798
+ },
799
+ {
800
+ label: 'High',
801
+ data: [1, 2, 3, 4].map((q) => quarterData[q].high),
802
+ backgroundColor: 'rgba(245, 124, 0, 0.8)',
803
+ borderColor: '#f57c00',
804
+ borderWidth: 1,
805
+ },
806
+ {
807
+ label: 'Moderate',
808
+ data: [1, 2, 3, 4].map((q) => quarterData[q].moderate),
809
+ backgroundColor: 'rgba(251, 192, 45, 0.8)',
810
+ borderColor: '#fbc02d',
811
+ borderWidth: 1,
812
+ },
813
+ ],
814
+ },
815
+ options: {
816
+ responsive: true,
817
+ maintainAspectRatio: false,
818
+ plugins: { legend: { position: 'bottom' } },
819
+ scales: {
820
+ x: { stacked: true, title: { display: true, text: 'Quarter' } },
821
+ y: {
822
+ stacked: true,
823
+ title: { display: true, text: 'Anomaly Count' },
824
+ beginAtZero: true,
825
+ ticks: { stepSize: 1 },
826
+ },
827
+ },
828
+ },
829
+ });
830
+ }
831
+ async renderRecentAnomaliesFeed() {
832
+ const container = document.getElementById('recent-anomalies-feed');
833
+ if (!container)
834
+ return;
835
+ const anomalies = this.dataManager.identifyActiveAnomalies();
836
+ const recent = anomalies.slice(0, 5);
837
+ container.innerHTML = '';
838
+ if (recent.length === 0) {
839
+ container.innerHTML = '<p>No recent anomalies detected</p>';
840
+ return;
841
+ }
842
+ recent.forEach((record) => {
843
+ const item = document.createElement('div');
844
+ item.className = `anomaly-feed-item ${record.anomaly_severity.toLowerCase()}`;
845
+ const severity = record.anomaly_severity;
846
+ const icon = ALERT_CONFIG[severity]?.icon || '⚪';
847
+ const zScore = parseFloat(record.max_z_score).toFixed(2);
848
+ let detailsText = '';
849
+ if (record.anomaly_type === 'BALLOT_ANOMALY') {
850
+ detailsText = `${record.total_ballots} ballots vs ${Math.round(parseFloat(record.q_baseline_ballots))} baseline`;
851
+ }
852
+ else if (record.anomaly_type === 'DOCUMENT_ANOMALY') {
853
+ detailsText = `${record.documents_produced} documents vs ${Math.round(parseFloat(record.q_baseline_docs))} baseline`;
854
+ }
855
+ const header = document.createElement('div');
856
+ header.style.cssText = 'display: flex; align-items: center; gap: 10px; margin-bottom: 5px;';
857
+ const iconSpan = document.createElement('span');
858
+ iconSpan.style.fontSize = '1.5rem';
859
+ iconSpan.textContent = icon;
860
+ header.appendChild(iconSpan);
861
+ const badge = document.createElement('span');
862
+ badge.className = `severity-badge ${severity.toLowerCase()}`;
863
+ badge.textContent = severity;
864
+ header.appendChild(badge);
865
+ const period = document.createElement('span');
866
+ const periodStrong = document.createElement('strong');
867
+ periodStrong.textContent = `${record.year} Q${record.quarter}`;
868
+ period.appendChild(periodStrong);
869
+ header.appendChild(period);
870
+ item.appendChild(header);
871
+ const details = document.createElement('div');
872
+ details.style.marginLeft = '2.5rem';
873
+ const lines = [
874
+ ['Type:', record.anomaly_type],
875
+ ['Z-Score:', `${parseFloat(zScore) > 0 ? '+' : ''}${zScore}`],
876
+ ['Direction:', record.anomaly_direction],
877
+ ['Details:', detailsText],
878
+ ];
879
+ lines.forEach(([label, value]) => {
880
+ const p = document.createElement('p');
881
+ p.style.margin = '2px 0';
882
+ const strong = document.createElement('strong');
883
+ strong.textContent = label;
884
+ p.appendChild(strong);
885
+ p.appendChild(document.createTextNode(` ${value}`));
886
+ details.appendChild(p);
887
+ });
888
+ item.appendChild(details);
889
+ container.appendChild(item);
890
+ });
891
+ }
892
+ // --- colour helpers ---
893
+ getSeverityColor(severity) {
894
+ const colors = {
895
+ CRITICAL: '#d32f2f',
896
+ HIGH: '#f57c00',
897
+ MODERATE: '#fbc02d',
898
+ LOW: '#388e3c',
899
+ };
900
+ return colors[severity] || '#666';
901
+ }
902
+ getSeverityRadius(severity) {
903
+ const sizes = {
904
+ CRITICAL: 8,
905
+ HIGH: 7,
906
+ MODERATE: 6,
907
+ LOW: 5,
908
+ };
909
+ return sizes[severity] || 5;
910
+ }
911
+ getHeatmapColor(severity) {
912
+ const colors = {
913
+ CRITICAL: '#d32f2f',
914
+ HIGH: '#f57c00',
915
+ MODERATE: '#fbc02d',
916
+ LOW: '#388e3c',
917
+ NO_ANOMALY: '#2e3b4e',
918
+ };
919
+ return colors[severity] || colors.NO_ANOMALY;
920
+ }
921
+ }
922
+ // ============================================================================
923
+ // LOADING / ERROR UI
924
+ // ============================================================================
925
+ function showLoading(translations) {
926
+ const sections = document.querySelectorAll('#anomaly-detection-dashboard .chart-card');
927
+ sections.forEach((section) => {
928
+ const canvas = section.querySelector('canvas');
929
+ const container = section.querySelector('div[id$="-heatmap"], div[id$="-feed"]');
930
+ if (canvas || container) {
931
+ const loading = document.createElement('div');
932
+ loading.className = 'loading-indicator';
933
+ loading.textContent = translations.loading;
934
+ loading.style.padding = '20px';
935
+ loading.style.textAlign = 'center';
936
+ loading.style.color = '#00d9ff';
937
+ if (canvas) {
938
+ canvas.classList.add('hidden');
939
+ section.appendChild(loading);
940
+ }
941
+ else if (container) {
942
+ container.innerHTML = '';
943
+ container.appendChild(loading);
944
+ }
945
+ }
946
+ });
947
+ }
948
+ function hideLoading() {
949
+ const loadingIndicators = document.querySelectorAll('.loading-indicator');
950
+ loadingIndicators.forEach((indicator) => indicator.remove());
951
+ const canvases = document.querySelectorAll('#anomaly-detection-dashboard canvas');
952
+ canvases.forEach((canvas) => canvas.classList.remove('hidden'));
953
+ }
954
+ function showDashboardError(message) {
955
+ const dashboard = document.getElementById('anomaly-detection-dashboard');
956
+ if (!dashboard)
957
+ return;
958
+ const errorDiv = document.createElement('div');
959
+ errorDiv.className = 'error-message';
960
+ errorDiv.style.padding = '20px';
961
+ errorDiv.style.backgroundColor = 'rgba(211, 47, 47, 0.2)';
962
+ errorDiv.style.border = '2px solid #d32f2f';
963
+ errorDiv.style.borderRadius = '8px';
964
+ errorDiv.style.margin = '20px 0';
965
+ errorDiv.style.color = '#fff';
966
+ const heading = document.createElement('h3');
967
+ heading.textContent = '⚠️ Error Loading Dashboard';
968
+ errorDiv.appendChild(heading);
969
+ const msgP = document.createElement('p');
970
+ msgP.textContent = message;
971
+ errorDiv.appendChild(msgP);
972
+ const helpP = document.createElement('p');
973
+ helpP.textContent =
974
+ 'Please try refreshing the page or contact support if the issue persists.';
975
+ errorDiv.appendChild(helpP);
976
+ dashboard.insertBefore(errorDiv, dashboard.firstChild);
977
+ }
978
+ // ============================================================================
979
+ // PUBLIC API
980
+ // ============================================================================
981
+ /**
982
+ * Initialise the Anomaly Detection & Early Warning dashboard.
983
+ *
984
+ * Loads CSV data (local-first with remote fallback), processes anomaly
985
+ * statistics, renders all six Chart.js/D3 visualizations, and activates the
986
+ * alert banner for CRITICAL/HIGH anomalies in recent quarters.
987
+ */
988
+ export async function init() {
989
+ logger.debug('Initializing Anomaly Detection Dashboard...');
990
+ const dataManager = new AnomalyDetectionDataManager();
991
+ const alertSystem = new AnomalyAlertSystem(dataManager);
992
+ const charts = new AnomalyDetectionCharts(dataManager);
993
+ const t = dataManager.getTranslations();
994
+ showLoading(t);
995
+ try {
996
+ await dataManager.fetchData();
997
+ const dashboard = document.getElementById('anomaly-detection-dashboard');
998
+ if (dashboard) {
999
+ showDataSourceDisclaimer(dashboard, dataManager.dataSourceType);
1000
+ }
1001
+ const criticalAnomaly = dataManager.checkForCriticalAnomalies();
1002
+ if (criticalAnomaly) {
1003
+ alertSystem.checkAndDisplayAlert(criticalAnomaly);
1004
+ }
1005
+ await charts.renderAll();
1006
+ const stats = dataManager.calculateAnomalyStats();
1007
+ logger.debug('Anomaly Statistics:', stats);
1008
+ hideLoading();
1009
+ logger.debug('✅ Anomaly Detection Dashboard initialized successfully');
1010
+ }
1011
+ catch (error) {
1012
+ logger.error('Failed to initialize dashboard:', error);
1013
+ hideLoading();
1014
+ showDashboardError(error.message);
1015
+ }
1016
+ }
1017
+ //# sourceMappingURL=anomaly-detection.js.map