riksdagsmonitor 0.8.12 → 0.8.15
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.
- package/dist/lib/cia/dashboard-init.d.ts +26 -0
- package/dist/lib/cia/dashboard-init.d.ts.map +1 -0
- package/dist/lib/cia/dashboard-init.js +108 -0
- package/dist/lib/cia/dashboard-init.js.map +1 -0
- package/dist/lib/cia/data-loader.d.ts +408 -0
- package/dist/lib/cia/data-loader.d.ts.map +1 -0
- package/dist/lib/cia/data-loader.js +867 -0
- package/dist/lib/cia/data-loader.js.map +1 -0
- package/dist/lib/cia/election-predictions.d.ts +78 -0
- package/dist/lib/cia/election-predictions.d.ts.map +1 -0
- package/dist/lib/cia/election-predictions.js +259 -0
- package/dist/lib/cia/election-predictions.js.map +1 -0
- package/dist/lib/cia/i18n-translations.d.ts +111 -0
- package/dist/lib/cia/i18n-translations.d.ts.map +1 -0
- package/dist/lib/cia/i18n-translations.js +619 -0
- package/dist/lib/cia/i18n-translations.js.map +1 -0
- package/dist/lib/cia/visualizations.d.ts +64 -0
- package/dist/lib/cia/visualizations.d.ts.map +1 -0
- package/dist/lib/cia/visualizations.js +662 -0
- package/dist/lib/cia/visualizations.js.map +1 -0
- package/dist/lib/dashboards/anomaly-detection.d.ts +44 -0
- package/dist/lib/dashboards/anomaly-detection.d.ts.map +1 -0
- package/dist/lib/dashboards/anomaly-detection.js +1017 -0
- package/dist/lib/dashboards/anomaly-detection.js.map +1 -0
- package/dist/lib/dashboards/coalition-dashboard.d.ts +36 -0
- package/dist/lib/dashboards/coalition-dashboard.d.ts.map +1 -0
- package/dist/lib/dashboards/coalition-dashboard.js +629 -0
- package/dist/lib/dashboards/coalition-dashboard.js.map +1 -0
- package/dist/lib/dashboards/coalition-loader.d.ts +43 -0
- package/dist/lib/dashboards/coalition-loader.d.ts.map +1 -0
- package/dist/lib/dashboards/coalition-loader.js +665 -0
- package/dist/lib/dashboards/coalition-loader.js.map +1 -0
- package/dist/lib/dashboards/committees-dashboard.d.ts +23 -0
- package/dist/lib/dashboards/committees-dashboard.d.ts.map +1 -0
- package/dist/lib/dashboards/committees-dashboard.js +886 -0
- package/dist/lib/dashboards/committees-dashboard.js.map +1 -0
- package/dist/lib/dashboards/election-cycle.d.ts +62 -0
- package/dist/lib/dashboards/election-cycle.d.ts.map +1 -0
- package/dist/lib/dashboards/election-cycle.js +484 -0
- package/dist/lib/dashboards/election-cycle.js.map +1 -0
- package/dist/lib/dashboards/ministry-dashboard.d.ts +46 -0
- package/dist/lib/dashboards/ministry-dashboard.d.ts.map +1 -0
- package/dist/lib/dashboards/ministry-dashboard.js +1114 -0
- package/dist/lib/dashboards/ministry-dashboard.js.map +1 -0
- package/dist/lib/dashboards/party-dashboard.d.ts +56 -0
- package/dist/lib/dashboards/party-dashboard.d.ts.map +1 -0
- package/dist/lib/dashboards/party-dashboard.js +981 -0
- package/dist/lib/dashboards/party-dashboard.js.map +1 -0
- package/dist/lib/dashboards/politician-dashboard.d.ts +41 -0
- package/dist/lib/dashboards/politician-dashboard.d.ts.map +1 -0
- package/dist/lib/dashboards/politician-dashboard.js +611 -0
- package/dist/lib/dashboards/politician-dashboard.js.map +1 -0
- package/dist/lib/dashboards/pre-election.d.ts +64 -0
- package/dist/lib/dashboards/pre-election.d.ts.map +1 -0
- package/dist/lib/dashboards/pre-election.js +604 -0
- package/dist/lib/dashboards/pre-election.js.map +1 -0
- package/dist/lib/dashboards/risk-dashboard.d.ts +37 -0
- package/dist/lib/dashboards/risk-dashboard.d.ts.map +1 -0
- package/dist/lib/dashboards/risk-dashboard.js +863 -0
- package/dist/lib/dashboards/risk-dashboard.js.map +1 -0
- package/dist/lib/dashboards/seasonal-patterns.d.ts +24 -0
- package/dist/lib/dashboards/seasonal-patterns.d.ts.map +1 -0
- package/dist/lib/dashboards/seasonal-patterns.js +535 -0
- package/dist/lib/dashboards/seasonal-patterns.js.map +1 -0
- package/dist/lib/dashboards/stats-loader.d.ts +35 -0
- package/dist/lib/dashboards/stats-loader.d.ts.map +1 -0
- package/dist/lib/dashboards/stats-loader.js +145 -0
- package/dist/lib/dashboards/stats-loader.js.map +1 -0
- package/dist/lib/shared/chart-factory.d.ts.map +1 -0
- package/dist/lib/shared/chart-factory.js.map +1 -0
- package/dist/lib/shared/data-loader.d.ts.map +1 -0
- package/dist/lib/shared/data-loader.js.map +1 -0
- package/dist/lib/shared/dom-utils.d.ts.map +1 -0
- package/dist/lib/shared/dom-utils.js.map +1 -0
- package/dist/lib/shared/error-boundary.d.ts.map +1 -0
- package/dist/lib/shared/error-boundary.js.map +1 -0
- package/dist/lib/shared/fallback-ui.d.ts.map +1 -0
- package/dist/lib/shared/fallback-ui.js.map +1 -0
- package/dist/lib/shared/index.d.ts.map +1 -0
- package/dist/lib/shared/index.js.map +1 -0
- package/dist/lib/shared/logger.d.ts.map +1 -0
- package/dist/lib/shared/logger.js.map +1 -0
- package/dist/lib/shared/register-globals.d.ts +14 -0
- package/dist/lib/shared/register-globals.d.ts.map +1 -0
- package/dist/lib/shared/register-globals.js +21 -0
- package/dist/lib/shared/register-globals.js.map +1 -0
- package/dist/lib/shared/theme.d.ts.map +1 -0
- package/dist/lib/shared/theme.js.map +1 -0
- package/dist/lib/shared/types.d.ts.map +1 -0
- package/dist/lib/shared/types.js.map +1 -0
- package/dist/lib/ui/back-to-top.d.ts +13 -0
- package/dist/lib/ui/back-to-top.d.ts.map +1 -0
- package/dist/lib/ui/back-to-top.js +48 -0
- package/dist/lib/ui/back-to-top.js.map +1 -0
- package/dist/scripts/ai-analysis/coalition-detector.d.ts +28 -0
- package/dist/scripts/ai-analysis/coalition-detector.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/coalition-detector.js +242 -0
- package/dist/scripts/ai-analysis/coalition-detector.js.map +1 -0
- package/dist/scripts/ai-analysis/dashboard-analyzer.d.ts +73 -0
- package/dist/scripts/ai-analysis/dashboard-analyzer.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/dashboard-analyzer.js +511 -0
- package/dist/scripts/ai-analysis/dashboard-analyzer.js.map +1 -0
- package/dist/scripts/ai-analysis/document-analyzer.d.ts +196 -0
- package/dist/scripts/ai-analysis/document-analyzer.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/document-analyzer.js +1001 -0
- package/dist/scripts/ai-analysis/document-analyzer.js.map +1 -0
- package/dist/scripts/ai-analysis/domains/index.d.ts +15 -0
- package/dist/scripts/ai-analysis/domains/index.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/domains/index.js +494 -0
- package/dist/scripts/ai-analysis/domains/index.js.map +1 -0
- package/dist/scripts/ai-analysis/helpers.d.ts +43 -0
- package/dist/scripts/ai-analysis/helpers.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/helpers.js +79 -0
- package/dist/scripts/ai-analysis/helpers.js.map +1 -0
- package/dist/scripts/ai-analysis/index.d.ts +15 -0
- package/dist/scripts/ai-analysis/index.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/index.js +14 -0
- package/dist/scripts/ai-analysis/index.js.map +1 -0
- package/dist/scripts/ai-analysis/pipeline.d.ts +41 -0
- package/dist/scripts/ai-analysis/pipeline.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/pipeline.js +208 -0
- package/dist/scripts/ai-analysis/pipeline.js.map +1 -0
- package/dist/scripts/ai-analysis/political-significance.d.ts +63 -0
- package/dist/scripts/ai-analysis/political-significance.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/political-significance.js +227 -0
- package/dist/scripts/ai-analysis/political-significance.js.map +1 -0
- package/dist/scripts/ai-analysis/quality-assessor.d.ts +104 -0
- package/dist/scripts/ai-analysis/quality-assessor.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/quality-assessor.js +554 -0
- package/dist/scripts/ai-analysis/quality-assessor.js.map +1 -0
- package/dist/scripts/ai-analysis/swot/index.d.ts +56 -0
- package/dist/scripts/ai-analysis/swot/index.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/swot/index.js +360 -0
- package/dist/scripts/ai-analysis/swot/index.js.map +1 -0
- package/dist/scripts/ai-analysis/swot/placeholders.d.ts +30 -0
- package/dist/scripts/ai-analysis/swot/placeholders.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/swot/placeholders.js +381 -0
- package/dist/scripts/ai-analysis/swot/placeholders.js.map +1 -0
- package/dist/scripts/ai-analysis/types.d.ts +333 -0
- package/dist/scripts/ai-analysis/types.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/types.js +19 -0
- package/dist/scripts/ai-analysis/types.js.map +1 -0
- package/dist/scripts/ai-analysis/visualisation/index.d.ts +15 -0
- package/dist/scripts/ai-analysis/visualisation/index.d.ts.map +1 -0
- package/dist/scripts/ai-analysis/visualisation/index.js +179 -0
- package/dist/scripts/ai-analysis/visualisation/index.js.map +1 -0
- package/dist/scripts/analysis-framework/cross-reference.d.ts +35 -0
- package/dist/scripts/analysis-framework/cross-reference.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/cross-reference.js +290 -0
- package/dist/scripts/analysis-framework/cross-reference.js.map +1 -0
- package/dist/scripts/analysis-framework/index.d.ts +79 -0
- package/dist/scripts/analysis-framework/index.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/index.js +133 -0
- package/dist/scripts/analysis-framework/index.js.map +1 -0
- package/dist/scripts/analysis-framework/lenses/citizen.d.ts +29 -0
- package/dist/scripts/analysis-framework/lenses/citizen.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/lenses/citizen.js +220 -0
- package/dist/scripts/analysis-framework/lenses/citizen.js.map +1 -0
- package/dist/scripts/analysis-framework/lenses/economic.d.ts +29 -0
- package/dist/scripts/analysis-framework/lenses/economic.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/lenses/economic.js +227 -0
- package/dist/scripts/analysis-framework/lenses/economic.js.map +1 -0
- package/dist/scripts/analysis-framework/lenses/government.d.ts +32 -0
- package/dist/scripts/analysis-framework/lenses/government.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/lenses/government.js +265 -0
- package/dist/scripts/analysis-framework/lenses/government.js.map +1 -0
- package/dist/scripts/analysis-framework/lenses/international.d.ts +29 -0
- package/dist/scripts/analysis-framework/lenses/international.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/lenses/international.js +248 -0
- package/dist/scripts/analysis-framework/lenses/international.js.map +1 -0
- package/dist/scripts/analysis-framework/lenses/media.d.ts +29 -0
- package/dist/scripts/analysis-framework/lenses/media.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/lenses/media.js +211 -0
- package/dist/scripts/analysis-framework/lenses/media.js.map +1 -0
- package/dist/scripts/analysis-framework/lenses/opposition.d.ts +29 -0
- package/dist/scripts/analysis-framework/lenses/opposition.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/lenses/opposition.js +234 -0
- package/dist/scripts/analysis-framework/lenses/opposition.js.map +1 -0
- package/dist/scripts/analysis-framework/methodology-types.d.ts +309 -0
- package/dist/scripts/analysis-framework/methodology-types.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/methodology-types.js +38 -0
- package/dist/scripts/analysis-framework/methodology-types.js.map +1 -0
- package/dist/scripts/analysis-framework/political-classification.d.ts +58 -0
- package/dist/scripts/analysis-framework/political-classification.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/political-classification.js +414 -0
- package/dist/scripts/analysis-framework/political-classification.js.map +1 -0
- package/dist/scripts/analysis-framework/political-risk-assessment.d.ts +74 -0
- package/dist/scripts/analysis-framework/political-risk-assessment.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/political-risk-assessment.js +656 -0
- package/dist/scripts/analysis-framework/political-risk-assessment.js.map +1 -0
- package/dist/scripts/analysis-framework/political-threat-analysis.d.ts +65 -0
- package/dist/scripts/analysis-framework/political-threat-analysis.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/political-threat-analysis.js +553 -0
- package/dist/scripts/analysis-framework/political-threat-analysis.js.map +1 -0
- package/dist/scripts/analysis-framework/significance-scorer.d.ts +62 -0
- package/dist/scripts/analysis-framework/significance-scorer.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/significance-scorer.js +196 -0
- package/dist/scripts/analysis-framework/significance-scorer.js.map +1 -0
- package/dist/scripts/analysis-framework/types.d.ts +138 -0
- package/dist/scripts/analysis-framework/types.d.ts.map +1 -0
- package/dist/scripts/analysis-framework/types.js +12 -0
- package/dist/scripts/analysis-framework/types.js.map +1 -0
- package/dist/scripts/analysis-reader.d.ts +240 -0
- package/dist/scripts/analysis-reader.d.ts.map +1 -0
- package/dist/scripts/analysis-reader.js +495 -0
- package/dist/scripts/analysis-reader.js.map +1 -0
- package/dist/scripts/article-quality-enhancer.d.ts +148 -0
- package/dist/scripts/article-quality-enhancer.d.ts.map +1 -0
- package/dist/scripts/article-quality-enhancer.js +430 -0
- package/dist/scripts/article-quality-enhancer.js.map +1 -0
- package/dist/scripts/article-template/constants.d.ts +104 -0
- package/dist/scripts/article-template/constants.d.ts.map +1 -0
- package/dist/scripts/article-template/constants.js +225 -0
- package/dist/scripts/article-template/constants.js.map +1 -0
- package/dist/scripts/article-template/helpers.d.ts +83 -0
- package/dist/scripts/article-template/helpers.d.ts.map +1 -0
- package/dist/scripts/article-template/helpers.js +236 -0
- package/dist/scripts/article-template/helpers.js.map +1 -0
- package/dist/scripts/article-template/index.d.ts +39 -0
- package/dist/scripts/article-template/index.d.ts.map +1 -0
- package/dist/scripts/article-template/index.js +37 -0
- package/dist/scripts/article-template/index.js.map +1 -0
- package/dist/scripts/article-template/registry.d.ts +64 -0
- package/dist/scripts/article-template/registry.d.ts.map +1 -0
- package/dist/scripts/article-template/registry.js +405 -0
- package/dist/scripts/article-template/registry.js.map +1 -0
- package/dist/scripts/article-template/template.d.ts +18 -0
- package/dist/scripts/article-template/template.d.ts.map +1 -0
- package/dist/scripts/article-template/template.js +359 -0
- package/dist/scripts/article-template/template.js.map +1 -0
- package/dist/scripts/article-template/types.d.ts +90 -0
- package/dist/scripts/article-template/types.d.ts.map +1 -0
- package/dist/scripts/article-template/types.js +96 -0
- package/dist/scripts/article-template/types.js.map +1 -0
- package/dist/scripts/article-template.d.ts +18 -0
- package/dist/scripts/article-template.d.ts.map +1 -0
- package/dist/scripts/article-template.js +18 -0
- package/dist/scripts/article-template.js.map +1 -0
- package/dist/scripts/catalog-downloaded-data.d.ts +66 -0
- package/dist/scripts/catalog-downloaded-data.d.ts.map +1 -0
- package/dist/scripts/catalog-downloaded-data.js +239 -0
- package/dist/scripts/catalog-downloaded-data.js.map +1 -0
- package/dist/scripts/check-cia-schema-updates.d.ts +186 -0
- package/dist/scripts/check-cia-schema-updates.d.ts.map +1 -0
- package/dist/scripts/check-cia-schema-updates.js +363 -0
- package/dist/scripts/check-cia-schema-updates.js.map +1 -0
- package/dist/scripts/data-transformers/calendar.d.ts +16 -0
- package/dist/scripts/data-transformers/calendar.d.ts.map +1 -0
- package/dist/scripts/data-transformers/calendar.js +137 -0
- package/dist/scripts/data-transformers/calendar.js.map +1 -0
- package/dist/scripts/data-transformers/constants/committee-names.d.ts +15 -0
- package/dist/scripts/data-transformers/constants/committee-names.d.ts.map +1 -0
- package/dist/scripts/data-transformers/constants/committee-names.js +30 -0
- package/dist/scripts/data-transformers/constants/committee-names.js.map +1 -0
- package/dist/scripts/data-transformers/constants/content-labels-part1.d.ts +11 -0
- package/dist/scripts/data-transformers/constants/content-labels-part1.d.ts.map +1 -0
- package/dist/scripts/data-transformers/constants/content-labels-part1.js +900 -0
- package/dist/scripts/data-transformers/constants/content-labels-part1.js.map +1 -0
- package/dist/scripts/data-transformers/constants/content-labels-part2.d.ts +11 -0
- package/dist/scripts/data-transformers/constants/content-labels-part2.d.ts.map +1 -0
- package/dist/scripts/data-transformers/constants/content-labels-part2.js +900 -0
- package/dist/scripts/data-transformers/constants/content-labels-part2.js.map +1 -0
- package/dist/scripts/data-transformers/constants/content-labels.d.ts +13 -0
- package/dist/scripts/data-transformers/constants/content-labels.d.ts.map +1 -0
- package/dist/scripts/data-transformers/constants/content-labels.js +18 -0
- package/dist/scripts/data-transformers/constants/content-labels.js.map +1 -0
- package/dist/scripts/data-transformers/constants/index.d.ts +15 -0
- package/dist/scripts/data-transformers/constants/index.d.ts.map +1 -0
- package/dist/scripts/data-transformers/constants/index.js +15 -0
- package/dist/scripts/data-transformers/constants/index.js.map +1 -0
- package/dist/scripts/data-transformers/constants/locale-map.d.ts +13 -0
- package/dist/scripts/data-transformers/constants/locale-map.d.ts.map +1 -0
- package/dist/scripts/data-transformers/constants/locale-map.js +17 -0
- package/dist/scripts/data-transformers/constants/locale-map.js.map +1 -0
- package/dist/scripts/data-transformers/constants.d.ts +14 -0
- package/dist/scripts/data-transformers/constants.d.ts.map +1 -0
- package/dist/scripts/data-transformers/constants.js +14 -0
- package/dist/scripts/data-transformers/constants.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.d.ts +64 -0
- package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.js +805 -0
- package/dist/scripts/data-transformers/content-generators/ai-mindmap-analyzer.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/ai-swot-analyzer.d.ts +89 -0
- package/dist/scripts/data-transformers/content-generators/ai-swot-analyzer.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/ai-swot-analyzer.js +667 -0
- package/dist/scripts/data-transformers/content-generators/ai-swot-analyzer.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/cia-overview-section.d.ts +50 -0
- package/dist/scripts/data-transformers/content-generators/cia-overview-section.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/cia-overview-section.js +310 -0
- package/dist/scripts/data-transformers/content-generators/cia-overview-section.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/committee.d.ts +12 -0
- package/dist/scripts/data-transformers/content-generators/committee.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/committee.js +247 -0
- package/dist/scripts/data-transformers/content-generators/committee.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/dashboard-section.d.ts +124 -0
- package/dist/scripts/data-transformers/content-generators/dashboard-section.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/dashboard-section.js +564 -0
- package/dist/scripts/data-transformers/content-generators/dashboard-section.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.d.ts +82 -0
- package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.js +321 -0
- package/dist/scripts/data-transformers/content-generators/economic-dashboard-section.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/generic.d.ts +12 -0
- package/dist/scripts/data-transformers/content-generators/generic.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/generic.js +295 -0
- package/dist/scripts/data-transformers/content-generators/generic.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/index.d.ts +56 -0
- package/dist/scripts/data-transformers/content-generators/index.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/index.js +45 -0
- package/dist/scripts/data-transformers/content-generators/index.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/interpellations.d.ts +12 -0
- package/dist/scripts/data-transformers/content-generators/interpellations.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/interpellations.js +124 -0
- package/dist/scripts/data-transformers/content-generators/interpellations.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/mindmap-section.d.ts +137 -0
- package/dist/scripts/data-transformers/content-generators/mindmap-section.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/mindmap-section.js +286 -0
- package/dist/scripts/data-transformers/content-generators/mindmap-section.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/month-ahead.d.ts +17 -0
- package/dist/scripts/data-transformers/content-generators/month-ahead.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/month-ahead.js +212 -0
- package/dist/scripts/data-transformers/content-generators/month-ahead.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/monthly-review.d.ts +17 -0
- package/dist/scripts/data-transformers/content-generators/monthly-review.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/monthly-review.js +173 -0
- package/dist/scripts/data-transformers/content-generators/monthly-review.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/motions.d.ts +12 -0
- package/dist/scripts/data-transformers/content-generators/motions.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/motions.js +158 -0
- package/dist/scripts/data-transformers/content-generators/motions.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/newsworthiness.d.ts +52 -0
- package/dist/scripts/data-transformers/content-generators/newsworthiness.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/newsworthiness.js +244 -0
- package/dist/scripts/data-transformers/content-generators/newsworthiness.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/propositions.d.ts +12 -0
- package/dist/scripts/data-transformers/content-generators/propositions.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/propositions.js +263 -0
- package/dist/scripts/data-transformers/content-generators/propositions.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/sankey-section.d.ts +92 -0
- package/dist/scripts/data-transformers/content-generators/sankey-section.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/sankey-section.js +257 -0
- package/dist/scripts/data-transformers/content-generators/sankey-section.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/shared.d.ts +81 -0
- package/dist/scripts/data-transformers/content-generators/shared.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/shared.js +913 -0
- package/dist/scripts/data-transformers/content-generators/shared.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/stakeholder-swot-section.d.ts +83 -0
- package/dist/scripts/data-transformers/content-generators/stakeholder-swot-section.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/stakeholder-swot-section.js +219 -0
- package/dist/scripts/data-transformers/content-generators/stakeholder-swot-section.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/swot-section.d.ts +50 -0
- package/dist/scripts/data-transformers/content-generators/swot-section.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/swot-section.js +177 -0
- package/dist/scripts/data-transformers/content-generators/swot-section.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators/week-ahead.d.ts +12 -0
- package/dist/scripts/data-transformers/content-generators/week-ahead.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators/week-ahead.js +332 -0
- package/dist/scripts/data-transformers/content-generators/week-ahead.js.map +1 -0
- package/dist/scripts/data-transformers/content-generators.d.ts +15 -0
- package/dist/scripts/data-transformers/content-generators.d.ts.map +1 -0
- package/dist/scripts/data-transformers/content-generators.js +14 -0
- package/dist/scripts/data-transformers/content-generators.js.map +1 -0
- package/dist/scripts/data-transformers/document-analysis.d.ts +58 -0
- package/dist/scripts/data-transformers/document-analysis.d.ts.map +1 -0
- package/dist/scripts/data-transformers/document-analysis.js +396 -0
- package/dist/scripts/data-transformers/document-analysis.js.map +1 -0
- package/dist/scripts/data-transformers/helpers.d.ts +144 -0
- package/dist/scripts/data-transformers/helpers.d.ts.map +1 -0
- package/dist/scripts/data-transformers/helpers.js +408 -0
- package/dist/scripts/data-transformers/helpers.js.map +1 -0
- package/dist/scripts/data-transformers/index.d.ts +45 -0
- package/dist/scripts/data-transformers/index.d.ts.map +1 -0
- package/dist/scripts/data-transformers/index.js +66 -0
- package/dist/scripts/data-transformers/index.js.map +1 -0
- package/dist/scripts/data-transformers/metadata.d.ts +42 -0
- package/dist/scripts/data-transformers/metadata.d.ts.map +1 -0
- package/dist/scripts/data-transformers/metadata.js +385 -0
- package/dist/scripts/data-transformers/metadata.js.map +1 -0
- package/dist/scripts/data-transformers/policy-analysis.d.ts +105 -0
- package/dist/scripts/data-transformers/policy-analysis.d.ts.map +1 -0
- package/dist/scripts/data-transformers/policy-analysis.js +686 -0
- package/dist/scripts/data-transformers/policy-analysis.js.map +1 -0
- package/dist/scripts/data-transformers/risk-analysis.d.ts +104 -0
- package/dist/scripts/data-transformers/risk-analysis.d.ts.map +1 -0
- package/dist/scripts/data-transformers/risk-analysis.js +279 -0
- package/dist/scripts/data-transformers/risk-analysis.js.map +1 -0
- package/dist/scripts/data-transformers/types.d.ts +260 -0
- package/dist/scripts/data-transformers/types.d.ts.map +1 -0
- package/dist/scripts/data-transformers/types.js +11 -0
- package/dist/scripts/data-transformers/types.js.map +1 -0
- package/dist/scripts/data-transformers.d.ts +23 -0
- package/dist/scripts/data-transformers.d.ts.map +1 -0
- package/dist/scripts/data-transformers.js +35 -0
- package/dist/scripts/data-transformers.js.map +1 -0
- package/dist/scripts/deep-inspection/index.d.ts +55 -0
- package/dist/scripts/deep-inspection/index.d.ts.map +1 -0
- package/dist/scripts/deep-inspection/index.js +66 -0
- package/dist/scripts/deep-inspection/index.js.map +1 -0
- package/dist/scripts/detect-swedish-leakage.d.ts +69 -0
- package/dist/scripts/detect-swedish-leakage.d.ts.map +1 -0
- package/dist/scripts/detect-swedish-leakage.js +417 -0
- package/dist/scripts/detect-swedish-leakage.js.map +1 -0
- package/dist/scripts/editorial-framework.d.ts +121 -0
- package/dist/scripts/editorial-framework.d.ts.map +1 -0
- package/dist/scripts/editorial-framework.js +364 -0
- package/dist/scripts/editorial-framework.js.map +1 -0
- package/dist/scripts/editorial-pillars.d.ts +43 -0
- package/dist/scripts/editorial-pillars.d.ts.map +1 -0
- package/dist/scripts/editorial-pillars.js +215 -0
- package/dist/scripts/editorial-pillars.js.map +1 -0
- package/dist/scripts/extract-news-metadata.d.ts +12 -0
- package/dist/scripts/extract-news-metadata.d.ts.map +1 -0
- package/dist/scripts/extract-news-metadata.js +107 -0
- package/dist/scripts/extract-news-metadata.js.map +1 -0
- package/dist/scripts/extract-vocabulary.d.ts +15 -0
- package/dist/scripts/extract-vocabulary.d.ts.map +1 -0
- package/dist/scripts/extract-vocabulary.js +255 -0
- package/dist/scripts/extract-vocabulary.js.map +1 -0
- package/dist/scripts/fix-article-navigation.d.ts +37 -0
- package/dist/scripts/fix-article-navigation.d.ts.map +1 -0
- package/dist/scripts/fix-article-navigation.js +198 -0
- package/dist/scripts/fix-article-navigation.js.map +1 -0
- package/dist/scripts/fix-keywords-localization.d.ts +18 -0
- package/dist/scripts/fix-keywords-localization.d.ts.map +1 -0
- package/dist/scripts/fix-keywords-localization.js +270 -0
- package/dist/scripts/fix-keywords-localization.js.map +1 -0
- package/dist/scripts/fix-old-articles-branding.d.ts +17 -0
- package/dist/scripts/fix-old-articles-branding.d.ts.map +1 -0
- package/dist/scripts/fix-old-articles-branding.js +229 -0
- package/dist/scripts/fix-old-articles-branding.js.map +1 -0
- package/dist/scripts/generate-news-backport.d.ts +16 -0
- package/dist/scripts/generate-news-backport.d.ts.map +1 -0
- package/dist/scripts/generate-news-backport.js +379 -0
- package/dist/scripts/generate-news-backport.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.d.ts +124 -0
- package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.js +529 -0
- package/dist/scripts/generate-news-enhanced/ai-analysis-pipeline.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/analysis-cache.d.ts +59 -0
- package/dist/scripts/generate-news-enhanced/analysis-cache.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/analysis-cache.js +116 -0
- package/dist/scripts/generate-news-enhanced/analysis-cache.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/analysis-labels.d.ts +58 -0
- package/dist/scripts/generate-news-enhanced/analysis-labels.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/analysis-labels.js +144 -0
- package/dist/scripts/generate-news-enhanced/analysis-labels.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/config.d.ts +57 -0
- package/dist/scripts/generate-news-enhanced/config.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/config.js +286 -0
- package/dist/scripts/generate-news-enhanced/config.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/generators.d.ts +119 -0
- package/dist/scripts/generate-news-enhanced/generators.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/generators.js +2108 -0
- package/dist/scripts/generate-news-enhanced/generators.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/helpers.d.ts +123 -0
- package/dist/scripts/generate-news-enhanced/helpers.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/helpers.js +438 -0
- package/dist/scripts/generate-news-enhanced/helpers.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/index.d.ts +19 -0
- package/dist/scripts/generate-news-enhanced/index.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/index.js +221 -0
- package/dist/scripts/generate-news-enhanced/index.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/swot-analyzer.d.ts +35 -0
- package/dist/scripts/generate-news-enhanced/swot-analyzer.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/swot-analyzer.js +1179 -0
- package/dist/scripts/generate-news-enhanced/swot-analyzer.js.map +1 -0
- package/dist/scripts/generate-news-enhanced/types.d.ts +34 -0
- package/dist/scripts/generate-news-enhanced/types.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced/types.js +9 -0
- package/dist/scripts/generate-news-enhanced/types.js.map +1 -0
- package/dist/scripts/generate-news-enhanced.d.ts +25 -0
- package/dist/scripts/generate-news-enhanced.d.ts.map +1 -0
- package/dist/scripts/generate-news-enhanced.js +37 -0
- package/dist/scripts/generate-news-enhanced.js.map +1 -0
- package/dist/scripts/generate-news-indexes/constants.d.ts +20 -0
- package/dist/scripts/generate-news-indexes/constants.d.ts.map +1 -0
- package/dist/scripts/generate-news-indexes/constants.js +308 -0
- package/dist/scripts/generate-news-indexes/constants.js.map +1 -0
- package/dist/scripts/generate-news-indexes/helpers.d.ts +73 -0
- package/dist/scripts/generate-news-indexes/helpers.d.ts.map +1 -0
- package/dist/scripts/generate-news-indexes/helpers.js +352 -0
- package/dist/scripts/generate-news-indexes/helpers.js.map +1 -0
- package/dist/scripts/generate-news-indexes/index.d.ts +20 -0
- package/dist/scripts/generate-news-indexes/index.d.ts.map +1 -0
- package/dist/scripts/generate-news-indexes/index.js +75 -0
- package/dist/scripts/generate-news-indexes/index.js.map +1 -0
- package/dist/scripts/generate-news-indexes/template.d.ts +25 -0
- package/dist/scripts/generate-news-indexes/template.d.ts.map +1 -0
- package/dist/scripts/generate-news-indexes/template.js +644 -0
- package/dist/scripts/generate-news-indexes/template.js.map +1 -0
- package/dist/scripts/generate-news-indexes/types.d.ts +96 -0
- package/dist/scripts/generate-news-indexes/types.d.ts.map +1 -0
- package/dist/scripts/generate-news-indexes/types.js +9 -0
- package/dist/scripts/generate-news-indexes/types.js.map +1 -0
- package/dist/scripts/generate-news-indexes.d.ts +20 -0
- package/dist/scripts/generate-news-indexes.d.ts.map +1 -0
- package/dist/scripts/generate-news-indexes.js +19 -0
- package/dist/scripts/generate-news-indexes.js.map +1 -0
- package/dist/scripts/generate-rss.d.ts +48 -0
- package/dist/scripts/generate-rss.d.ts.map +1 -0
- package/dist/scripts/generate-rss.js +299 -0
- package/dist/scripts/generate-rss.js.map +1 -0
- package/dist/scripts/generate-sitemap-html.d.ts +79 -0
- package/dist/scripts/generate-sitemap-html.d.ts.map +1 -0
- package/dist/scripts/generate-sitemap-html.js +878 -0
- package/dist/scripts/generate-sitemap-html.js.map +1 -0
- package/dist/scripts/generate-sitemap.d.ts +23 -0
- package/dist/scripts/generate-sitemap.d.ts.map +1 -0
- package/dist/scripts/generate-sitemap.js +476 -0
- package/dist/scripts/generate-sitemap.js.map +1 -0
- package/dist/scripts/generate-types-from-cia-schemas.d.ts +176 -0
- package/dist/scripts/generate-types-from-cia-schemas.d.ts.map +1 -0
- package/dist/scripts/generate-types-from-cia-schemas.js +318 -0
- package/dist/scripts/generate-types-from-cia-schemas.js.map +1 -0
- package/dist/scripts/government-role-validator.d.ts +65 -0
- package/dist/scripts/government-role-validator.d.ts.map +1 -0
- package/dist/scripts/government-role-validator.js +217 -0
- package/dist/scripts/government-role-validator.js.map +1 -0
- package/dist/scripts/html-utils.d.ts +17 -0
- package/dist/scripts/html-utils.d.ts.map +1 -0
- package/dist/scripts/html-utils.js +29 -0
- package/dist/scripts/html-utils.js.map +1 -0
- package/dist/scripts/load-cia-stats.d.ts +89 -0
- package/dist/scripts/load-cia-stats.d.ts.map +1 -0
- package/dist/scripts/load-cia-stats.js +400 -0
- package/dist/scripts/load-cia-stats.js.map +1 -0
- package/dist/scripts/mcp-client/client.d.ts +73 -0
- package/dist/scripts/mcp-client/client.d.ts.map +1 -0
- package/dist/scripts/mcp-client/client.js +526 -0
- package/dist/scripts/mcp-client/client.js.map +1 -0
- package/dist/scripts/mcp-client/document-types.d.ts +23 -0
- package/dist/scripts/mcp-client/document-types.d.ts.map +1 -0
- package/dist/scripts/mcp-client/document-types.js +62 -0
- package/dist/scripts/mcp-client/document-types.js.map +1 -0
- package/dist/scripts/mcp-client/index.d.ts +34 -0
- package/dist/scripts/mcp-client/index.d.ts.map +1 -0
- package/dist/scripts/mcp-client/index.js +67 -0
- package/dist/scripts/mcp-client/index.js.map +1 -0
- package/dist/scripts/mcp-client/transport.d.ts +32 -0
- package/dist/scripts/mcp-client/transport.d.ts.map +1 -0
- package/dist/scripts/mcp-client/transport.js +102 -0
- package/dist/scripts/mcp-client/transport.js.map +1 -0
- package/dist/scripts/mcp-client.d.ts +18 -0
- package/dist/scripts/mcp-client.d.ts.map +1 -0
- package/dist/scripts/mcp-client.js +18 -0
- package/dist/scripts/mcp-client.js.map +1 -0
- package/dist/scripts/mcp-query-cli.d.ts +25 -0
- package/dist/scripts/mcp-query-cli.d.ts.map +1 -0
- package/dist/scripts/mcp-query-cli.js +66 -0
- package/dist/scripts/mcp-query-cli.js.map +1 -0
- package/dist/scripts/news-types/breaking-news.d.ts +178 -0
- package/dist/scripts/news-types/breaking-news.d.ts.map +1 -0
- package/dist/scripts/news-types/breaking-news.js +428 -0
- package/dist/scripts/news-types/breaking-news.js.map +1 -0
- package/dist/scripts/news-types/committee-reports.d.ts +212 -0
- package/dist/scripts/news-types/committee-reports.d.ts.map +1 -0
- package/dist/scripts/news-types/committee-reports.js +404 -0
- package/dist/scripts/news-types/committee-reports.js.map +1 -0
- package/dist/scripts/news-types/month-ahead.d.ts +71 -0
- package/dist/scripts/news-types/month-ahead.d.ts.map +1 -0
- package/dist/scripts/news-types/month-ahead.js +392 -0
- package/dist/scripts/news-types/month-ahead.js.map +1 -0
- package/dist/scripts/news-types/monthly-review.d.ts +61 -0
- package/dist/scripts/news-types/monthly-review.d.ts.map +1 -0
- package/dist/scripts/news-types/monthly-review.js +417 -0
- package/dist/scripts/news-types/monthly-review.js.map +1 -0
- package/dist/scripts/news-types/motions.d.ts +214 -0
- package/dist/scripts/news-types/motions.d.ts.map +1 -0
- package/dist/scripts/news-types/motions.js +447 -0
- package/dist/scripts/news-types/motions.js.map +1 -0
- package/dist/scripts/news-types/propositions.d.ts +204 -0
- package/dist/scripts/news-types/propositions.d.ts.map +1 -0
- package/dist/scripts/news-types/propositions.js +401 -0
- package/dist/scripts/news-types/propositions.js.map +1 -0
- package/dist/scripts/news-types/week-ahead.d.ts +231 -0
- package/dist/scripts/news-types/week-ahead.d.ts.map +1 -0
- package/dist/scripts/news-types/week-ahead.js +441 -0
- package/dist/scripts/news-types/week-ahead.js.map +1 -0
- package/dist/scripts/news-types/weekly-review/analysis.d.ts +47 -0
- package/dist/scripts/news-types/weekly-review/analysis.d.ts.map +1 -0
- package/dist/scripts/news-types/weekly-review/analysis.js +276 -0
- package/dist/scripts/news-types/weekly-review/analysis.js.map +1 -0
- package/dist/scripts/news-types/weekly-review/data-loader.d.ts +51 -0
- package/dist/scripts/news-types/weekly-review/data-loader.d.ts.map +1 -0
- package/dist/scripts/news-types/weekly-review/data-loader.js +298 -0
- package/dist/scripts/news-types/weekly-review/data-loader.js.map +1 -0
- package/dist/scripts/news-types/weekly-review/generator.d.ts +18 -0
- package/dist/scripts/news-types/weekly-review/generator.d.ts.map +1 -0
- package/dist/scripts/news-types/weekly-review/generator.js +284 -0
- package/dist/scripts/news-types/weekly-review/generator.js.map +1 -0
- package/dist/scripts/news-types/weekly-review/index.d.ts +20 -0
- package/dist/scripts/news-types/weekly-review/index.d.ts.map +1 -0
- package/dist/scripts/news-types/weekly-review/index.js +23 -0
- package/dist/scripts/news-types/weekly-review/index.js.map +1 -0
- package/dist/scripts/news-types/weekly-review/types.d.ts +72 -0
- package/dist/scripts/news-types/weekly-review/types.d.ts.map +1 -0
- package/dist/scripts/news-types/weekly-review/types.js +20 -0
- package/dist/scripts/news-types/weekly-review/types.js.map +1 -0
- package/dist/scripts/news-types/weekly-review/validation.d.ts +10 -0
- package/dist/scripts/news-types/weekly-review/validation.d.ts.map +1 -0
- package/dist/scripts/news-types/weekly-review/validation.js +95 -0
- package/dist/scripts/news-types/weekly-review/validation.js.map +1 -0
- package/dist/scripts/news-types/weekly-review.d.ts +15 -0
- package/dist/scripts/news-types/weekly-review.d.ts.map +1 -0
- package/dist/scripts/news-types/weekly-review.js +14 -0
- package/dist/scripts/news-types/weekly-review.js.map +1 -0
- package/dist/scripts/party-variants.d.ts +23 -0
- package/dist/scripts/party-variants.d.ts.map +1 -0
- package/dist/scripts/party-variants.js +50 -0
- package/dist/scripts/party-variants.js.map +1 -0
- package/dist/scripts/pipeline/index.d.ts +19 -0
- package/dist/scripts/pipeline/index.d.ts.map +1 -0
- package/dist/scripts/pipeline/index.js +17 -0
- package/dist/scripts/pipeline/index.js.map +1 -0
- package/dist/scripts/pipeline/orchestrator.d.ts +56 -0
- package/dist/scripts/pipeline/orchestrator.d.ts.map +1 -0
- package/dist/scripts/pipeline/orchestrator.js +147 -0
- package/dist/scripts/pipeline/orchestrator.js.map +1 -0
- package/dist/scripts/pipeline/types.d.ts +117 -0
- package/dist/scripts/pipeline/types.d.ts.map +1 -0
- package/dist/scripts/pipeline/types.js +13 -0
- package/dist/scripts/pipeline/types.js.map +1 -0
- package/dist/scripts/pipeline/validation.d.ts +66 -0
- package/dist/scripts/pipeline/validation.d.ts.map +1 -0
- package/dist/scripts/pipeline/validation.js +129 -0
- package/dist/scripts/pipeline/validation.js.map +1 -0
- package/dist/scripts/populate-analysis-data.d.ts +41 -0
- package/dist/scripts/populate-analysis-data.d.ts.map +1 -0
- package/dist/scripts/populate-analysis-data.js +255 -0
- package/dist/scripts/populate-analysis-data.js.map +1 -0
- package/dist/scripts/pre-article-analysis/data-downloader.d.ts +80 -0
- package/dist/scripts/pre-article-analysis/data-downloader.d.ts.map +1 -0
- package/dist/scripts/pre-article-analysis/data-downloader.js +230 -0
- package/dist/scripts/pre-article-analysis/data-downloader.js.map +1 -0
- package/dist/scripts/pre-article-analysis/data-persistence.d.ts +141 -0
- package/dist/scripts/pre-article-analysis/data-persistence.d.ts.map +1 -0
- package/dist/scripts/pre-article-analysis/data-persistence.js +345 -0
- package/dist/scripts/pre-article-analysis/data-persistence.js.map +1 -0
- package/dist/scripts/pre-article-analysis/markdown-serializer.d.ts +95 -0
- package/dist/scripts/pre-article-analysis/markdown-serializer.d.ts.map +1 -0
- package/dist/scripts/pre-article-analysis/markdown-serializer.js +648 -0
- package/dist/scripts/pre-article-analysis/markdown-serializer.js.map +1 -0
- package/dist/scripts/pre-article-analysis/pdf-converter.d.ts +58 -0
- package/dist/scripts/pre-article-analysis/pdf-converter.d.ts.map +1 -0
- package/dist/scripts/pre-article-analysis/pdf-converter.js +142 -0
- package/dist/scripts/pre-article-analysis/pdf-converter.js.map +1 -0
- package/dist/scripts/pre-article-analysis.d.ts +41 -0
- package/dist/scripts/pre-article-analysis.d.ts.map +1 -0
- package/dist/scripts/pre-article-analysis.js +578 -0
- package/dist/scripts/pre-article-analysis.js.map +1 -0
- package/dist/scripts/scb-client.d.ts +104 -0
- package/dist/scripts/scb-client.d.ts.map +1 -0
- package/dist/scripts/scb-client.js +286 -0
- package/dist/scripts/scb-client.js.map +1 -0
- package/dist/scripts/scb-context.d.ts +88 -0
- package/dist/scripts/scb-context.d.ts.map +1 -0
- package/dist/scripts/scb-context.js +307 -0
- package/dist/scripts/scb-context.js.map +1 -0
- package/dist/scripts/shared/version.d.ts +9 -0
- package/dist/scripts/shared/version.d.ts.map +1 -0
- package/dist/scripts/shared/version.js +28 -0
- package/dist/scripts/shared/version.js.map +1 -0
- package/dist/scripts/statistical-claims-detector.d.ts +119 -0
- package/dist/scripts/statistical-claims-detector.d.ts.map +1 -0
- package/dist/scripts/statistical-claims-detector.js +391 -0
- package/dist/scripts/statistical-claims-detector.js.map +1 -0
- package/dist/scripts/sync-cia-schemas.d.ts +52 -0
- package/dist/scripts/sync-cia-schemas.d.ts.map +1 -0
- package/dist/scripts/sync-cia-schemas.js +195 -0
- package/dist/scripts/sync-cia-schemas.js.map +1 -0
- package/dist/scripts/translation-dictionary.d.ts +45 -0
- package/dist/scripts/translation-dictionary.d.ts.map +1 -0
- package/dist/scripts/translation-dictionary.js +3642 -0
- package/dist/scripts/translation-dictionary.js.map +1 -0
- package/dist/scripts/types/article.d.ts +362 -0
- package/dist/scripts/types/article.d.ts.map +1 -0
- package/dist/scripts/types/article.js +6 -0
- package/dist/scripts/types/article.js.map +1 -0
- package/dist/scripts/types/content.d.ts +167 -0
- package/dist/scripts/types/content.d.ts.map +1 -0
- package/dist/scripts/types/content.js +6 -0
- package/dist/scripts/types/content.js.map +1 -0
- package/dist/scripts/types/editorial.d.ts +17 -0
- package/dist/scripts/types/editorial.d.ts.map +1 -0
- package/dist/scripts/types/editorial.js +6 -0
- package/dist/scripts/types/editorial.js.map +1 -0
- package/dist/scripts/types/language.d.ts +7 -0
- package/dist/scripts/types/language.d.ts.map +1 -0
- package/dist/scripts/types/language.js +6 -0
- package/dist/scripts/types/language.js.map +1 -0
- package/dist/scripts/types/mcp.d.ts +117 -0
- package/dist/scripts/types/mcp.d.ts.map +1 -0
- package/dist/scripts/types/mcp.js +6 -0
- package/dist/scripts/types/mcp.js.map +1 -0
- package/dist/scripts/types/party.d.ts +9 -0
- package/dist/scripts/types/party.d.ts.map +1 -0
- package/dist/scripts/types/party.js +6 -0
- package/dist/scripts/types/party.js.map +1 -0
- package/dist/scripts/types/validation.d.ts +136 -0
- package/dist/scripts/types/validation.d.ts.map +1 -0
- package/dist/scripts/types/validation.js +6 -0
- package/dist/scripts/types/validation.js.map +1 -0
- package/dist/scripts/types/workflow.d.ts +78 -0
- package/dist/scripts/types/workflow.d.ts.map +1 -0
- package/dist/scripts/types/workflow.js +6 -0
- package/dist/scripts/types/workflow.js.map +1 -0
- package/dist/scripts/update-stats-from-cia.d.ts +44 -0
- package/dist/scripts/update-stats-from-cia.d.ts.map +1 -0
- package/dist/scripts/update-stats-from-cia.js +310 -0
- package/dist/scripts/update-stats-from-cia.js.map +1 -0
- package/dist/scripts/validate-against-cia-schemas.d.ts +126 -0
- package/dist/scripts/validate-against-cia-schemas.d.ts.map +1 -0
- package/dist/scripts/validate-against-cia-schemas.js +299 -0
- package/dist/scripts/validate-against-cia-schemas.js.map +1 -0
- package/dist/scripts/validate-cross-references.d.ts +49 -0
- package/dist/scripts/validate-cross-references.d.ts.map +1 -0
- package/dist/scripts/validate-cross-references.js +183 -0
- package/dist/scripts/validate-cross-references.js.map +1 -0
- package/dist/scripts/validate-file-ownership.d.ts +68 -0
- package/dist/scripts/validate-file-ownership.d.ts.map +1 -0
- package/dist/scripts/validate-file-ownership.js +135 -0
- package/dist/scripts/validate-file-ownership.js.map +1 -0
- package/dist/scripts/validate-news-translations.d.ts +27 -0
- package/dist/scripts/validate-news-translations.d.ts.map +1 -0
- package/dist/scripts/validate-news-translations.js +258 -0
- package/dist/scripts/validate-news-translations.js.map +1 -0
- package/dist/scripts/validate-translations.d.ts +162 -0
- package/dist/scripts/validate-translations.d.ts.map +1 -0
- package/dist/scripts/validate-translations.js +378 -0
- package/dist/scripts/validate-translations.js.map +1 -0
- package/dist/scripts/workflow-state-coordinator.d.ts +354 -0
- package/dist/scripts/workflow-state-coordinator.d.ts.map +1 -0
- package/dist/scripts/workflow-state-coordinator.js +876 -0
- package/dist/scripts/workflow-state-coordinator.js.map +1 -0
- package/dist/scripts/world-bank-client.d.ts +122 -0
- package/dist/scripts/world-bank-client.d.ts.map +1 -0
- package/dist/scripts/world-bank-client.js +192 -0
- package/dist/scripts/world-bank-client.js.map +1 -0
- package/dist/scripts/world-bank-context.d.ts +88 -0
- package/dist/scripts/world-bank-context.d.ts.map +1 -0
- package/dist/scripts/world-bank-context.js +331 -0
- package/dist/scripts/world-bank-context.js.map +1 -0
- package/package.json +32 -7
- package/dist/lib/chart-factory.d.ts.map +0 -1
- package/dist/lib/chart-factory.js.map +0 -1
- package/dist/lib/data-loader.d.ts.map +0 -1
- package/dist/lib/data-loader.js.map +0 -1
- package/dist/lib/dom-utils.d.ts.map +0 -1
- package/dist/lib/dom-utils.js.map +0 -1
- package/dist/lib/error-boundary.d.ts.map +0 -1
- package/dist/lib/error-boundary.js.map +0 -1
- package/dist/lib/fallback-ui.d.ts.map +0 -1
- package/dist/lib/fallback-ui.js.map +0 -1
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/logger.d.ts.map +0 -1
- package/dist/lib/logger.js.map +0 -1
- package/dist/lib/theme.d.ts.map +0 -1
- package/dist/lib/theme.js.map +0 -1
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/types.js.map +0 -1
- /package/dist/lib/{chart-factory.d.ts → shared/chart-factory.d.ts} +0 -0
- /package/dist/lib/{chart-factory.js → shared/chart-factory.js} +0 -0
- /package/dist/lib/{data-loader.d.ts → shared/data-loader.d.ts} +0 -0
- /package/dist/lib/{data-loader.js → shared/data-loader.js} +0 -0
- /package/dist/lib/{dom-utils.d.ts → shared/dom-utils.d.ts} +0 -0
- /package/dist/lib/{dom-utils.js → shared/dom-utils.js} +0 -0
- /package/dist/lib/{error-boundary.d.ts → shared/error-boundary.d.ts} +0 -0
- /package/dist/lib/{error-boundary.js → shared/error-boundary.js} +0 -0
- /package/dist/lib/{fallback-ui.d.ts → shared/fallback-ui.d.ts} +0 -0
- /package/dist/lib/{fallback-ui.js → shared/fallback-ui.js} +0 -0
- /package/dist/lib/{index.d.ts → shared/index.d.ts} +0 -0
- /package/dist/lib/{index.js → shared/index.js} +0 -0
- /package/dist/lib/{logger.d.ts → shared/logger.d.ts} +0 -0
- /package/dist/lib/{logger.js → shared/logger.js} +0 -0
- /package/dist/lib/{theme.d.ts → shared/theme.d.ts} +0 -0
- /package/dist/lib/{theme.js → shared/theme.js} +0 -0
- /package/dist/lib/{types.d.ts → shared/types.d.ts} +0 -0
- /package/dist/lib/{types.js → shared/types.js} +0 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Dashboards/SeasonalPatterns
|
|
3
|
+
* @category Intelligence Analysis - Seasonal Parliamentary Patterns & Anomaly Detection
|
|
4
|
+
*
|
|
5
|
+
* Swedish Parliamentary Seasonal Activity Analysis & Quarterly Pattern Intelligence Dashboard.
|
|
6
|
+
*
|
|
7
|
+
* Advanced intelligence analysis implementing 23-year temporal pattern analysis
|
|
8
|
+
* (2002-2025) of Swedish parliamentary quarterly activity with sophisticated Z-score
|
|
9
|
+
* anomaly detection and seasonal pattern classification.
|
|
10
|
+
*
|
|
11
|
+
* @author Hack23 AB - Temporal Intelligence Team
|
|
12
|
+
* @license Apache-2.0
|
|
13
|
+
* @version 2.0.0
|
|
14
|
+
* @since 2024
|
|
15
|
+
|
|
16
|
+
*
|
|
17
|
+
* @intelligence Seasonal Parliamentary Pattern Intelligence — 23-year temporal analysis (2002-2025) implementing Z-score anomaly detection for quarterly parliamentary activity patterns. Classifies legislative seasons and detects statistically significant deviations from historical norms.
|
|
18
|
+
*
|
|
19
|
+
* @business Unique analytical methodology — seasonal pattern analysis is a sophisticated differentiator that most parliamentary monitoring tools lack. Demonstrates advanced data science capabilities to enterprise and research clients. Foundation for seasonal activity alerting subscription.
|
|
20
|
+
*
|
|
21
|
+
* @marketing Research partnership content — seasonal analysis methodology and findings are publishable in academic journals, driving research partnerships and academic user acquisition. Positions Riksdagsmonitor as a research-grade platform.
|
|
22
|
+
* */
|
|
23
|
+
import { logger, detectLanguage, showDataSourceDisclaimer, } from '../shared/index.js';
|
|
24
|
+
const d3 = globalThis.d3;
|
|
25
|
+
const Chart = globalThis.Chart;
|
|
26
|
+
const Papa = globalThis.Papa;
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// CONFIGURATION
|
|
29
|
+
// ============================================================================
|
|
30
|
+
const CONFIG = {
|
|
31
|
+
dataUrls: [
|
|
32
|
+
'cia-data/seasonal/view_riksdagen_seasonal_activity_patterns_sample.csv',
|
|
33
|
+
'https://raw.githubusercontent.com/Hack23/cia/master/service.data.impl/sample-data/view_riksdagen_seasonal_activity_patterns_sample.csv'
|
|
34
|
+
],
|
|
35
|
+
cacheKey: 'riksdag_seasonal_patterns',
|
|
36
|
+
cacheDuration: 24 * 60 * 60 * 1000,
|
|
37
|
+
zScoreThreshold: 2.0,
|
|
38
|
+
colors: {
|
|
39
|
+
primary: '#00d9ff',
|
|
40
|
+
secondary: '#ff006e',
|
|
41
|
+
tertiary: '#ffbe0b',
|
|
42
|
+
success: '#008838',
|
|
43
|
+
warning: '#fbc02d',
|
|
44
|
+
danger: '#d32f2f',
|
|
45
|
+
info: '#117a8b',
|
|
46
|
+
normal: '#388e3c',
|
|
47
|
+
elevated: '#f57c00',
|
|
48
|
+
reduced: '#1976d2',
|
|
49
|
+
anomaly: '#d32f2f'
|
|
50
|
+
},
|
|
51
|
+
quarterColors: {
|
|
52
|
+
Q1: '#1976d2',
|
|
53
|
+
Q2: '#388e3c',
|
|
54
|
+
Q3: '#fbc02d',
|
|
55
|
+
Q4: '#f57c00'
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// TRANSLATIONS (14 Languages)
|
|
60
|
+
// ============================================================================
|
|
61
|
+
const TRANSLATIONS = {
|
|
62
|
+
en: {
|
|
63
|
+
title: 'Seasonal Activity Patterns (2002-2025)',
|
|
64
|
+
subtitle: 'Quarterly Analysis with Z-Score Anomaly Detection',
|
|
65
|
+
filters: { year: 'Year', quarter: 'Quarter', election: 'Election Status', classification: 'Activity Classification', allYears: 'All Years', allQuarters: 'All Quarters', allElections: 'All', electionYears: 'Election Years', nonElectionYears: 'Non-Election Years', allClassifications: 'All Classifications' },
|
|
66
|
+
quarters: { Q1: 'Q1 - Winter Session', Q2: 'Q2 - Spring Session', Q3: 'Q3 - Summer Recess', Q4: 'Q4 - Autumn Session' },
|
|
67
|
+
charts: {
|
|
68
|
+
heatmap: { title: 'Quarterly Activity Heat Map (2002-2025)', description: 'Ballot volume by year and quarter with Z-score overlay' },
|
|
69
|
+
zscore: { title: 'Z-Score Anomaly Detection', description: 'Statistical outliers (|Z| ≥ 2.0) flagged in red' },
|
|
70
|
+
comparison: { title: 'Average Activity by Quarter (All Years)', description: 'Q1-Q4 baselines with standard deviation bands' },
|
|
71
|
+
classification: { title: 'Seasonal Pattern Classification', description: 'Distribution of NORMAL, ELEVATED, REDUCED, ANOMALY patterns' },
|
|
72
|
+
qoq: { title: 'Quarter-over-Quarter Changes', description: 'Sequential ballot changes (% and absolute)' }
|
|
73
|
+
},
|
|
74
|
+
classifications: { NORMAL_ACTIVITY: 'Normal Activity', ELEVATED_ACTIVITY: 'Elevated Activity', REDUCED_ACTIVITY: 'Reduced Activity', ANOMALY_DETECTED: 'Anomaly Detected', NORMAL_SEASONAL_PATTERN: 'Normal Seasonal Pattern', Q3_SUMMER_LULL: 'Q3 Summer Lull', Q4_ELEVATED_ACTIVITY: 'Q4 Elevated Activity', UNUSUALLY_HIGH_ACTIVITY: 'Unusually High Activity', UNUSUALLY_LOW_ACTIVITY: 'Unusually Low Activity' },
|
|
75
|
+
tooltips: { ballots: 'Ballots', zScore: 'Z-Score', classification: 'Classification', anomaly: 'ANOMALY', na: 'N/A', quarter: 'Quarter', year: 'Year' },
|
|
76
|
+
chartLabels: { ballotZScore: 'Ballot Z-Score', documentZScore: 'Document Z-Score', attendanceZScore: 'Attendance Z-Score', yearQuarter: 'Year-Quarter', zScore: 'Z-Score', quarter: 'Quarter', averageBallots: 'Average Ballots', year: 'Year', count: 'Count', changePercent: 'Change (%)', qoqChange: 'QoQ Change (%)', anomaly: 'ANOMALY' },
|
|
77
|
+
loading: 'Loading data...', error: 'Error loading data. Please try again.', dataAttribution: 'Data by CIA Platform'
|
|
78
|
+
},
|
|
79
|
+
sv: {
|
|
80
|
+
title: 'Säsongsmönster (2002-2025)',
|
|
81
|
+
subtitle: 'Kvartalsanalys med Z-poäng anomalidetektering',
|
|
82
|
+
filters: { year: 'År', quarter: 'Kvartal', election: 'Valstatus', classification: 'Aktivitetsklassificering', allYears: 'Alla år', allQuarters: 'Alla kvartal', allElections: 'Alla', electionYears: 'Valår', nonElectionYears: 'Icke-valår', allClassifications: 'Alla klassificeringar' },
|
|
83
|
+
quarters: { Q1: 'Q1 - Vintersession', Q2: 'Q2 - Vårsession', Q3: 'Q3 - Sommaruppehåll', Q4: 'Q4 - Höstsession' },
|
|
84
|
+
charts: { heatmap: { title: 'Kvartalsaktivitet värmekarta (2002-2025)', description: 'Omröstningsvolym per år och kvartal med Z-poäng' }, zscore: { title: 'Z-poäng anomalidetektering', description: 'Statistiska avvikelser (|Z| ≥ 2.0) markerade i rött' }, comparison: { title: 'Genomsnittlig aktivitet per kvartal (alla år)', description: 'Q1-Q4 baslinjer med standardavvikelseband' }, classification: { title: 'Säsongsmönster klassificering', description: 'Fördelning av NORMAL, FÖRHÖJD, REDUCERAD, ANOMALI mönster' }, qoq: { title: 'Kvartal-till-kvartal förändringar', description: 'Sekventiella omröstningsförändringar (% och absolut)' } },
|
|
85
|
+
classifications: { NORMAL_ACTIVITY: 'Normal aktivitet', ELEVATED_ACTIVITY: 'Förhöjd aktivitet', REDUCED_ACTIVITY: 'Reducerad aktivitet', ANOMALY_DETECTED: 'Anomali upptäckt', NORMAL_SEASONAL_PATTERN: 'Normalt säsongsmönster', Q3_SUMMER_LULL: 'Q3 sommaruppehåll', Q4_ELEVATED_ACTIVITY: 'Q4 förhöjd aktivitet', UNUSUALLY_HIGH_ACTIVITY: 'Ovanligt hög aktivitet', UNUSUALLY_LOW_ACTIVITY: 'Ovanligt låg aktivitet' },
|
|
86
|
+
tooltips: { ballots: 'Omröstningar', zScore: 'Z-poäng', classification: 'Klassificering', anomaly: 'ANOMALI', na: 'Saknas', quarter: 'Kvartal', year: 'År' },
|
|
87
|
+
chartLabels: { ballotZScore: 'Omröstningar Z-poäng', documentZScore: 'Dokument Z-poäng', attendanceZScore: 'Närvaro Z-poäng', yearQuarter: 'År-Kvartal', zScore: 'Z-poäng', quarter: 'Kvartal', averageBallots: 'Genomsnittliga omröstningar', year: 'År', count: 'Antal', changePercent: 'Förändring (%)', qoqChange: 'KtK-förändring (%)', anomaly: 'ANOMALI' },
|
|
88
|
+
loading: 'Laddar data...', error: 'Fel vid inläsning av data. Försök igen.', dataAttribution: 'Data från CIA-plattformen'
|
|
89
|
+
},
|
|
90
|
+
da: { title: 'Sæsonmønstre (2002-2025)', subtitle: 'Kvartalsanalyse med Z-score anomalidetektion', filters: { year: 'År', quarter: 'Kvartal', election: 'Valgstatus', classification: 'Aktivitetsklassificering', allYears: 'Alle år', allQuarters: 'Alle kvartaler', allElections: 'Alle', electionYears: 'Valgår', nonElectionYears: 'Ikke-valgår', allClassifications: 'Alle klassificeringer' }, quarters: { Q1: 'K1 - Vintersession', Q2: 'K2 - Forårssession', Q3: 'K3 - Sommerpause', Q4: 'K4 - Efterårssession' }, charts: { heatmap: { title: 'Kvartalsaktivitet varmekort (2002-2025)', description: 'Afstemningsvolumen efter år og kvartal med Z-score' }, zscore: { title: 'Z-score anomalidetektion', description: 'Statistiske afvigelser (|Z| ≥ 2.0) markeret med rødt' }, comparison: { title: 'Gennemsnitlig aktivitet efter kvartal (alle år)', description: 'K1-K4 basislinjer med standardafvigelsesbånd' }, classification: { title: 'Sæsonmønster klassificering', description: 'Fordeling af NORMAL, FORHØJET, REDUCERET, ANOMALI mønstre' }, qoq: { title: 'Kvartal-til-kvartal ændringer', description: 'Sekventielle afstemningsændringer (% og absolut)' } }, classifications: { NORMAL_ACTIVITY: 'Normal aktivitet', ELEVATED_ACTIVITY: 'Forhøjet aktivitet', REDUCED_ACTIVITY: 'Reduceret aktivitet', ANOMALY_DETECTED: 'Anomali opdaget', NORMAL_SEASONAL_PATTERN: 'Normalt sæsonmønster', Q3_SUMMER_LULL: 'K3 sommerpause', Q4_ELEVATED_ACTIVITY: 'K4 forhøjet aktivitet', UNUSUALLY_HIGH_ACTIVITY: 'Usædvanligt høj aktivitet', UNUSUALLY_LOW_ACTIVITY: 'Usædvanligt lav aktivitet' }, tooltips: { ballots: 'Afstemninger', zScore: 'Z-score', classification: 'Klassificering', anomaly: 'ANOMALI', na: 'Mangler', quarter: 'Kvartal', year: 'År' }, chartLabels: { ballotZScore: 'Afstemninger Z-score', documentZScore: 'Dokument Z-score', attendanceZScore: 'Fremmøde Z-score', yearQuarter: 'År-Kvartal', zScore: 'Z-score', quarter: 'Kvartal', averageBallots: 'Gennemsnitlige afstemninger', year: 'År', count: 'Antal', changePercent: 'Ændring (%)', qoqChange: 'KtK-ændring (%)', anomaly: 'ANOMALI' }, loading: 'Indlæser data...', error: 'Fejl ved indlæsning af data. Prøv igen.', dataAttribution: 'Data fra CIA-platformen' },
|
|
91
|
+
no: { title: 'Sesongmønstre (2002-2025)', subtitle: 'Kvartalsanalyse med Z-score anomalideteksjon', filters: { year: 'År', quarter: 'Kvartal', election: 'Valgstatus', classification: 'Aktivitetsklassifisering', allYears: 'Alle år', allQuarters: 'Alle kvartaler', allElections: 'Alle', electionYears: 'Valgår', nonElectionYears: 'Ikke-valgår', allClassifications: 'Alle klassifiseringer' }, quarters: { Q1: 'K1 - Vintersesjon', Q2: 'K2 - Vårsesjon', Q3: 'K3 - Sommerferie', Q4: 'K4 - Høstsesjon' }, charts: { heatmap: { title: 'Kvartalsaktivitet varmekart (2002-2025)', description: 'Avstemningsvolum etter år og kvartal med Z-score' }, zscore: { title: 'Z-score anomalideteksjon', description: 'Statistiske avvik (|Z| ≥ 2.0) markert i rødt' }, comparison: { title: 'Gjennomsnittlig aktivitet etter kvartal (alle år)', description: 'K1-K4 basislinjer med standardavviksbånd' }, classification: { title: 'Sesongmønster klassifisering', description: 'Fordeling av NORMAL, FORHØYET, REDUSERT, ANOMALI mønstre' }, qoq: { title: 'Kvartal-til-kvartal endringer', description: 'Sekvensielle avstemningsendringer (% og absolutt)' } }, classifications: { NORMAL_ACTIVITY: 'Normal aktivitet', ELEVATED_ACTIVITY: 'Forhøyet aktivitet', REDUCED_ACTIVITY: 'Redusert aktivitet', ANOMALY_DETECTED: 'Anomali oppdaget', NORMAL_SEASONAL_PATTERN: 'Normalt sesongmønster', Q3_SUMMER_LULL: 'K3 sommerferie', Q4_ELEVATED_ACTIVITY: 'K4 forhøyet aktivitet', UNUSUALLY_HIGH_ACTIVITY: 'Uvanlig høy aktivitet', UNUSUALLY_LOW_ACTIVITY: 'Uvanlig lav aktivitet' }, tooltips: { ballots: 'Avstemninger', zScore: 'Z-score', classification: 'Klassifisering', anomaly: 'ANOMALI', na: 'Mangler', quarter: 'Kvartal', year: 'År' }, chartLabels: { ballotZScore: 'Avstemninger Z-score', documentZScore: 'Dokument Z-score', attendanceZScore: 'Fremmøte Z-score', yearQuarter: 'År-Kvartal', zScore: 'Z-score', quarter: 'Kvartal', averageBallots: 'Gjennomsnittlige avstemninger', year: 'År', count: 'Antall', changePercent: 'Endring (%)', qoqChange: 'KtK-endring (%)', anomaly: 'ANOMALI' }, loading: 'Laster data...', error: 'Feil ved lasting av data. Prøv igjen.', dataAttribution: 'Data fra CIA-plattformen' },
|
|
92
|
+
fi: { title: 'Kausivaihtelut (2002-2025)', subtitle: 'Neljännesvuosi-analyysi Z-pisteiden poikkeamatunnistuksella', filters: { year: 'Vuosi', quarter: 'Kvartaali', election: 'Vaalitilanne', classification: 'Aktiviteettiluokitus', allYears: 'Kaikki vuodet', allQuarters: 'Kaikki kvartaalit', allElections: 'Kaikki', electionYears: 'Vaalivuodet', nonElectionYears: 'Ei-vaalivuodet', allClassifications: 'Kaikki luokitukset' }, quarters: { Q1: 'Q1 - Talviistunto', Q2: 'Q2 - Kevätistunto', Q3: 'Q3 - Kesätauko', Q4: 'Q4 - Syysistunto' }, charts: { heatmap: { title: 'Neljännesvuosi-aktiviteetti lämpökartta (2002-2025)', description: 'Äänestysvolyymi vuoden ja kvartaalin mukaan Z-pisteillä' }, zscore: { title: 'Z-piste poikkeamatunnistus', description: 'Tilastolliset poikkeamat (|Z| ≥ 2.0) merkitty punaisella' }, comparison: { title: 'Keskimääräinen aktiviteetti kvartaaleittain (kaikki vuodet)', description: 'Q1-Q4 perusviivat keskihajontakaistaleilla' }, classification: { title: 'Kausivaihtelujen luokittelu', description: 'NORMAALI, KOHONNUT, ALENTUNUT, POIKKEAMA -mallien jakauma' }, qoq: { title: 'Kvartaalista toiseen muutokset', description: 'Peräkkäiset äänestysmuutokset (% ja absoluuttinen)' } }, classifications: { NORMAL_ACTIVITY: 'Normaali aktiviteetti', ELEVATED_ACTIVITY: 'Kohonnut aktiviteetti', REDUCED_ACTIVITY: 'Alentunut aktiviteetti', ANOMALY_DETECTED: 'Poikkeama havaittu', NORMAL_SEASONAL_PATTERN: 'Normaali kausimalli', Q3_SUMMER_LULL: 'Q3 kesätauko', Q4_ELEVATED_ACTIVITY: 'Q4 kohonnut aktiviteetti', UNUSUALLY_HIGH_ACTIVITY: 'Epätavallisen korkea aktiviteetti', UNUSUALLY_LOW_ACTIVITY: 'Epätavallisen matala aktiviteetti' }, tooltips: { ballots: 'Äänet', zScore: 'Z-piste', classification: 'Luokitus', anomaly: 'POIKKEAMA', na: 'Puuttuu', quarter: 'Kvartaali', year: 'Vuosi' }, chartLabels: { ballotZScore: 'Äänet Z-piste', documentZScore: 'Dokumentti Z-piste', attendanceZScore: 'Läsnäolo Z-piste', yearQuarter: 'Vuosi-Kvartaali', zScore: 'Z-piste', quarter: 'Kvartaali', averageBallots: 'Keskimääräiset äänet', year: 'Vuosi', count: 'Lukumäärä', changePercent: 'Muutos (%)', qoqChange: 'KtK-muutos (%)', anomaly: 'POIKKEAMA' }, loading: 'Ladataan tietoja...', error: 'Virhe tietojen lataamisessa.', dataAttribution: 'Data CIA-alustalta' },
|
|
93
|
+
de: { title: 'Saisonale Muster (2002-2025)', subtitle: 'Quartalsanalyse mit Z-Score-Anomalieerkennung', filters: { year: 'Jahr', quarter: 'Quartal', election: 'Wahlstatus', classification: 'Aktivitätsklassifizierung', allYears: 'Alle Jahre', allQuarters: 'Alle Quartale', allElections: 'Alle', electionYears: 'Wahljahre', nonElectionYears: 'Nicht-Wahljahre', allClassifications: 'Alle Klassifizierungen' }, quarters: { Q1: 'Q1 - Wintersitzung', Q2: 'Q2 - Frühjahrssitzung', Q3: 'Q3 - Sommerpause', Q4: 'Q4 - Herbstsitzung' }, charts: { heatmap: { title: 'Quartalsaktivität Heatmap (2002-2025)', description: 'Abstimmungsvolumen nach Jahr und Quartal mit Z-Score' }, zscore: { title: 'Z-Score-Anomalieerkennung', description: 'Statistische Ausreißer (|Z| ≥ 2.0) rot markiert' }, comparison: { title: 'Durchschnittliche Aktivität nach Quartal (alle Jahre)', description: 'Q1-Q4 Basislinien mit Standardabweichungsbändern' }, classification: { title: 'Saisonale Musterklassifizierung', description: 'Verteilung von NORMAL, ERHÖHT, REDUZIERT, ANOMALIE Mustern' }, qoq: { title: 'Quartal-zu-Quartal Änderungen', description: 'Aufeinanderfolgende Abstimmungsänderungen (% und absolut)' } }, classifications: { NORMAL_ACTIVITY: 'Normale Aktivität', ELEVATED_ACTIVITY: 'Erhöhte Aktivität', REDUCED_ACTIVITY: 'Reduzierte Aktivität', ANOMALY_DETECTED: 'Anomalie erkannt', NORMAL_SEASONAL_PATTERN: 'Normales saisonales Muster', Q3_SUMMER_LULL: 'Q3 Sommerpause', Q4_ELEVATED_ACTIVITY: 'Q4 erhöhte Aktivität', UNUSUALLY_HIGH_ACTIVITY: 'Ungewöhnlich hohe Aktivität', UNUSUALLY_LOW_ACTIVITY: 'Ungewöhnlich niedrige Aktivität' }, tooltips: { ballots: 'Abstimmungen', zScore: 'Z-Score', classification: 'Klassifizierung', anomaly: 'ANOMALIE', na: 'Fehlt', quarter: 'Quartal', year: 'Jahr' }, chartLabels: { ballotZScore: 'Abstimmungen Z-Score', documentZScore: 'Dokument Z-Score', attendanceZScore: 'Anwesenheit Z-Score', yearQuarter: 'Jahr-Quartal', zScore: 'Z-Score', quarter: 'Quartal', averageBallots: 'Durchschnittliche Abstimmungen', year: 'Jahr', count: 'Anzahl', changePercent: 'Änderung (%)', qoqChange: 'QzQ-Änderung (%)', anomaly: 'ANOMALIE' }, loading: 'Daten werden geladen...', error: 'Fehler beim Laden der Daten.', dataAttribution: 'Daten von CIA-Plattform' },
|
|
94
|
+
fr: { title: 'Schémas saisonniers (2002-2025)', subtitle: 'Analyse trimestrielle avec détection d\'anomalies par score Z', filters: { year: 'Année', quarter: 'Trimestre', election: 'Statut électoral', classification: 'Classification d\'activité', allYears: 'Toutes les années', allQuarters: 'Tous les trimestres', allElections: 'Tous', electionYears: 'Années électorales', nonElectionYears: 'Années non-électorales', allClassifications: 'Toutes les classifications' }, quarters: { Q1: 'T1 - Session d\'hiver', Q2: 'T2 - Session de printemps', Q3: 'T3 - Pause estivale', Q4: 'T4 - Session d\'automne' }, charts: { heatmap: { title: 'Carte de chaleur d\'activité trimestrielle (2002-2025)', description: 'Volume de scrutins par année et trimestre avec score Z' }, zscore: { title: 'Détection d\'anomalies par score Z', description: 'Valeurs aberrantes statistiques (|Z| ≥ 2.0) marquées en rouge' }, comparison: { title: 'Activité moyenne par trimestre (toutes les années)', description: 'Lignes de base T1-T4 avec bandes d\'écart-type' }, classification: { title: 'Classification des schémas saisonniers', description: 'Distribution des schémas NORMAL, ÉLEVÉ, RÉDUIT, ANOMALIE' }, qoq: { title: 'Changements d\'un trimestre à l\'autre', description: 'Changements séquentiels de scrutins (% et absolu)' } }, classifications: { NORMAL_ACTIVITY: 'Activité normale', ELEVATED_ACTIVITY: 'Activité élevée', REDUCED_ACTIVITY: 'Activité réduite', ANOMALY_DETECTED: 'Anomalie détectée', NORMAL_SEASONAL_PATTERN: 'Schéma saisonnier normal', Q3_SUMMER_LULL: 'T3 pause estivale', Q4_ELEVATED_ACTIVITY: 'T4 activité élevée', UNUSUALLY_HIGH_ACTIVITY: 'Activité exceptionnellement élevée', UNUSUALLY_LOW_ACTIVITY: 'Activité exceptionnellement basse' }, tooltips: { ballots: 'Scrutins', zScore: 'Score Z', classification: 'Classification', anomaly: 'ANOMALIE', na: 'Manquant', quarter: 'Trimestre', year: 'Année' }, chartLabels: { ballotZScore: 'Scrutins Score Z', documentZScore: 'Document Score Z', attendanceZScore: 'Présence Score Z', yearQuarter: 'Année-Trimestre', zScore: 'Score Z', quarter: 'Trimestre', averageBallots: 'Scrutins moyens', year: 'Année', count: 'Nombre', changePercent: 'Changement (%)', qoqChange: 'TàT-changement (%)', anomaly: 'ANOMALIE' }, loading: 'Chargement des données...', error: 'Erreur lors du chargement des données.', dataAttribution: 'Données de la plateforme CIA' },
|
|
95
|
+
es: { title: 'Patrones estacionales (2002-2025)', subtitle: 'Análisis trimestral con detección de anomalías por puntuación Z', filters: { year: 'Año', quarter: 'Trimestre', election: 'Estado electoral', classification: 'Clasificación de actividad', allYears: 'Todos los años', allQuarters: 'Todos los trimestres', allElections: 'Todos', electionYears: 'Años electorales', nonElectionYears: 'Años no electorales', allClassifications: 'Todas las clasificaciones' }, quarters: { Q1: 'T1 - Sesión de invierno', Q2: 'T2 - Sesión de primavera', Q3: 'T3 - Receso de verano', Q4: 'T4 - Sesión de otoño' }, charts: { heatmap: { title: 'Mapa de calor de actividad trimestral (2002-2025)', description: 'Volumen de votaciones por año y trimestre' }, zscore: { title: 'Detección de anomalías por puntuación Z', description: 'Valores atípicos (|Z| ≥ 2.0) marcados en rojo' }, comparison: { title: 'Actividad promedio por trimestre (todos los años)', description: 'Líneas base T1-T4 con bandas de desviación estándar' }, classification: { title: 'Clasificación de patrones estacionales', description: 'Distribución de patrones NORMAL, ELEVADO, REDUCIDO, ANOMALÍA' }, qoq: { title: 'Cambios de trimestre a trimestre', description: 'Cambios secuenciales de votaciones' } }, classifications: { NORMAL_ACTIVITY: 'Actividad normal', ELEVATED_ACTIVITY: 'Actividad elevada', REDUCED_ACTIVITY: 'Actividad reducida', ANOMALY_DETECTED: 'Anomalía detectada', NORMAL_SEASONAL_PATTERN: 'Patrón estacional normal', Q3_SUMMER_LULL: 'T3 receso de verano', Q4_ELEVATED_ACTIVITY: 'T4 actividad elevada', UNUSUALLY_HIGH_ACTIVITY: 'Actividad inusualmente alta', UNUSUALLY_LOW_ACTIVITY: 'Actividad inusualmente baja' }, tooltips: { ballots: 'Votaciones', zScore: 'Puntuación Z', classification: 'Clasificación', anomaly: 'ANOMALÍA', na: 'N/A', quarter: 'Trimestre', year: 'Año' }, chartLabels: { ballotZScore: 'Votaciones Z', documentZScore: 'Documento Z', attendanceZScore: 'Asistencia Z', yearQuarter: 'Año-Trimestre', zScore: 'Puntuación Z', quarter: 'Trimestre', averageBallots: 'Votaciones promedio', year: 'Año', count: 'Recuento', changePercent: 'Cambio (%)', qoqChange: 'TaT-cambio (%)', anomaly: 'ANOMALÍA' }, loading: 'Cargando datos...', error: 'Error al cargar los datos.', dataAttribution: 'Datos de la plataforma CIA' },
|
|
96
|
+
nl: { title: 'Seizoenspatronen (2002-2025)', subtitle: 'Kwartaalanalyse met Z-score anomaliedetectie', filters: { year: 'Jaar', quarter: 'Kwartaal', election: 'Verkiezingsstatus', classification: 'Activiteitsclassificatie', allYears: 'Alle jaren', allQuarters: 'Alle kwartalen', allElections: 'Alle', electionYears: 'Verkiezingsjaren', nonElectionYears: 'Niet-verkiezingsjaren', allClassifications: 'Alle classificaties' }, quarters: { Q1: 'K1 - Wintersessie', Q2: 'K2 - Voorjaarssessie', Q3: 'K3 - Zomerpauze', Q4: 'K4 - Herfstsessie' }, charts: { heatmap: { title: 'Kwartaalactiviteit heatmap (2002-2025)', description: 'Stemvolume per jaar en kwartaal met Z-score' }, zscore: { title: 'Z-score anomaliedetectie', description: 'Statistische uitschieters (|Z| ≥ 2.0) gemarkeerd in rood' }, comparison: { title: 'Gemiddelde activiteit per kwartaal (alle jaren)', description: 'K1-K4 basislijnen met standaardafwijkingsbanden' }, classification: { title: 'Seizoenspatroon classificatie', description: 'Verdeling van patronen' }, qoq: { title: 'Kwartaal-op-kwartaal veranderingen', description: 'Opeenvolgende stemveranderingen' } }, classifications: { NORMAL_ACTIVITY: 'Normale activiteit', ELEVATED_ACTIVITY: 'Verhoogde activiteit', REDUCED_ACTIVITY: 'Verminderde activiteit', ANOMALY_DETECTED: 'Anomalie gedetecteerd', NORMAL_SEASONAL_PATTERN: 'Normaal seizoenspatroon', Q3_SUMMER_LULL: 'K3 zomerpauze', Q4_ELEVATED_ACTIVITY: 'K4 verhoogde activiteit', UNUSUALLY_HIGH_ACTIVITY: 'Ongewoon hoge activiteit', UNUSUALLY_LOW_ACTIVITY: 'Ongewoon lage activiteit' }, tooltips: { ballots: 'Stemmen', zScore: 'Z-score', classification: 'Classificatie', anomaly: 'ANOMALIE', na: 'Ontbreekt', quarter: 'Kwartaal', year: 'Jaar' }, chartLabels: { ballotZScore: 'Stemmen Z-score', documentZScore: 'Document Z-score', attendanceZScore: 'Aanwezigheid Z-score', yearQuarter: 'Jaar-Kwartaal', zScore: 'Z-score', quarter: 'Kwartaal', averageBallots: 'Gemiddelde stemmen', year: 'Jaar', count: 'Aantal', changePercent: 'Verandering (%)', qoqChange: 'KoK-verandering (%)', anomaly: 'ANOMALIE' }, loading: 'Gegevens laden...', error: 'Fout bij het laden van gegevens.', dataAttribution: 'Data van CIA-platform' },
|
|
97
|
+
ar: { title: 'الأنماط الموسمية (2002-2025)', subtitle: 'تحليل ربع سنوي مع كشف الشذوذ بالنقاط Z', filters: { year: 'السنة', quarter: 'الربع', election: 'حالة الانتخابات', classification: 'تصنيف النشاط', allYears: 'كل السنوات', allQuarters: 'كل الأرباع', allElections: 'الكل', electionYears: 'سنوات الانتخابات', nonElectionYears: 'سنوات بدون انتخابات', allClassifications: 'كل التصنيفات' }, quarters: { Q1: 'الربع 1', Q2: 'الربع 2', Q3: 'الربع 3', Q4: 'الربع 4' }, charts: { heatmap: { title: 'خريطة حرارية للنشاط الفصلي', description: 'حجم التصويت حسب السنة والربع' }, zscore: { title: 'كشف الشذوذ بالنقاط Z', description: 'القيم الشاذة مميزة بالأحمر' }, comparison: { title: 'متوسط النشاط حسب الربع', description: 'خطوط أساسية مع نطاقات الانحراف المعياري' }, classification: { title: 'تصنيف الأنماط الموسمية', description: 'توزيع الأنماط' }, qoq: { title: 'التغيرات من ربع لآخر', description: 'التغيرات المتسلسلة' } }, classifications: { NORMAL_ACTIVITY: 'نشاط عادي', ELEVATED_ACTIVITY: 'نشاط مرتفع', REDUCED_ACTIVITY: 'نشاط منخفض', ANOMALY_DETECTED: 'شذوذ مكتشف', NORMAL_SEASONAL_PATTERN: 'نمط موسمي عادي', Q3_SUMMER_LULL: 'عطلة صيفية', Q4_ELEVATED_ACTIVITY: 'نشاط مرتفع', UNUSUALLY_HIGH_ACTIVITY: 'نشاط مرتفع بشكل غير عادي', UNUSUALLY_LOW_ACTIVITY: 'نشاط منخفض بشكل غير عادي' }, tooltips: { ballots: 'تصويت', zScore: 'نقاط Z', classification: 'تصنيف', anomaly: 'شذوذ', na: 'غير متوفر', quarter: 'ربع', year: 'سنة' }, chartLabels: { ballotZScore: 'تصويت Z', documentZScore: 'مستند Z', attendanceZScore: 'حضور Z', yearQuarter: 'سنة-ربع', zScore: 'نقاط Z', quarter: 'ربع', averageBallots: 'متوسط التصويت', year: 'سنة', count: 'عدد', changePercent: 'تغيير (%)', qoqChange: 'ربع-ربع (%)', anomaly: 'شذوذ' }, loading: 'جاري تحميل البيانات...', error: 'خطأ في تحميل البيانات.', dataAttribution: 'البيانات من منصة CIA' },
|
|
98
|
+
he: { title: 'דפוסים עונתיים (2002-2025)', subtitle: 'ניתוח רבעוני עם זיהוי חריגות Z-Score', filters: { year: 'שנה', quarter: 'רבעון', election: 'סטטוס בחירות', classification: 'סיווג פעילות', allYears: 'כל השנים', allQuarters: 'כל הרבעונים', allElections: 'הכל', electionYears: 'שנות בחירות', nonElectionYears: 'שנים ללא בחירות', allClassifications: 'כל הסיווגים' }, quarters: { Q1: 'רבעון 1', Q2: 'רבעון 2', Q3: 'רבעון 3', Q4: 'רבעון 4' }, charts: { heatmap: { title: 'מפת חום של פעילות רבעונית', description: 'נפח הצבעות לפי שנה ורבעון' }, zscore: { title: 'זיהוי חריגות Z-Score', description: 'ערכים חריגים מסומנים באדום' }, comparison: { title: 'פעילות ממוצעת לפי רבעון', description: 'קווי בסיס עם רצועות סטיית תקן' }, classification: { title: 'סיווג דפוסים עונתיים', description: 'התפלגות דפוסים' }, qoq: { title: 'שינויים מרבעון לרבעון', description: 'שינויים רציפים בהצבעה' } }, classifications: { NORMAL_ACTIVITY: 'פעילות רגילה', ELEVATED_ACTIVITY: 'פעילות מוגברת', REDUCED_ACTIVITY: 'פעילות מופחתת', ANOMALY_DETECTED: 'חריגה זוהתה', NORMAL_SEASONAL_PATTERN: 'דפוס עונתי רגיל', Q3_SUMMER_LULL: 'הפסקת קיץ', Q4_ELEVATED_ACTIVITY: 'פעילות מוגברת', UNUSUALLY_HIGH_ACTIVITY: 'פעילות גבוהה במיוחד', UNUSUALLY_LOW_ACTIVITY: 'פעילות נמוכה במיוחד' }, tooltips: { ballots: 'הצבעות', zScore: 'Z-Score', classification: 'סיווג', anomaly: 'חריגה', na: 'חסר', quarter: 'רבעון', year: 'שנה' }, chartLabels: { ballotZScore: 'הצבעות Z', documentZScore: 'מסמך Z', attendanceZScore: 'נוכחות Z', yearQuarter: 'שנה-רבעון', zScore: 'Z-Score', quarter: 'רבעון', averageBallots: 'הצבעות ממוצעות', year: 'שנה', count: 'ספירה', changePercent: 'שינוי (%)', qoqChange: 'רבעון-רבעון (%)', anomaly: 'חריגה' }, loading: 'טוען נתונים...', error: 'שגיאה בטעינת נתונים.', dataAttribution: 'נתונים מפלטפורמת CIA' },
|
|
99
|
+
ja: { title: '季節パターン (2002-2025)', subtitle: 'Zスコア異常検出を伴う四半期分析', filters: { year: '年', quarter: '四半期', election: '選挙状況', classification: '活動分類', allYears: 'すべての年', allQuarters: 'すべての四半期', allElections: 'すべて', electionYears: '選挙年', nonElectionYears: '非選挙年', allClassifications: 'すべての分類' }, quarters: { Q1: 'Q1 - 冬季会期', Q2: 'Q2 - 春季会期', Q3: 'Q3 - 夏季休会', Q4: 'Q4 - 秋季会期' }, charts: { heatmap: { title: '四半期活動ヒートマップ', description: '年と四半期別の投票量' }, zscore: { title: 'Zスコア異常検出', description: '統計的外れ値を赤でマーク' }, comparison: { title: '四半期別平均活動', description: 'ベースラインと標準偏差バンド' }, classification: { title: '季節パターン分類', description: 'パターンの分布' }, qoq: { title: '四半期間の変化', description: '連続的な投票変化' } }, classifications: { NORMAL_ACTIVITY: '通常の活動', ELEVATED_ACTIVITY: '活動上昇', REDUCED_ACTIVITY: '活動減少', ANOMALY_DETECTED: '異常検出', NORMAL_SEASONAL_PATTERN: '通常の季節パターン', Q3_SUMMER_LULL: 'Q3夏季休会', Q4_ELEVATED_ACTIVITY: 'Q4活動上昇', UNUSUALLY_HIGH_ACTIVITY: '異常に高い活動', UNUSUALLY_LOW_ACTIVITY: '異常に低い活動' }, tooltips: { ballots: '投票', zScore: 'Zスコア', classification: '分類', anomaly: '異常', na: 'N/A', quarter: '四半期', year: '年' }, chartLabels: { ballotZScore: '投票Z', documentZScore: '文書Z', attendanceZScore: '出席Z', yearQuarter: '年-四半期', zScore: 'Zスコア', quarter: '四半期', averageBallots: '平均投票', year: '年', count: '数', changePercent: '変化 (%)', qoqChange: 'QoQ変化 (%)', anomaly: '異常' }, loading: 'データ読み込み中...', error: 'データの読み込みエラー。', dataAttribution: 'CIAプラットフォームのデータ' },
|
|
100
|
+
ko: { title: '계절별 패턴 (2002-2025)', subtitle: 'Z점수 이상 탐지를 통한 분기별 분석', filters: { year: '년도', quarter: '분기', election: '선거 상태', classification: '활동 분류', allYears: '모든 연도', allQuarters: '모든 분기', allElections: '모두', electionYears: '선거 연도', nonElectionYears: '비선거 연도', allClassifications: '모든 분류' }, quarters: { Q1: '1분기', Q2: '2분기', Q3: '3분기', Q4: '4분기' }, charts: { heatmap: { title: '분기별 활동 히트맵', description: '연도 및 분기별 투표량' }, zscore: { title: 'Z점수 이상 탐지', description: '통계적 이상값은 빨간색' }, comparison: { title: '분기별 평균 활동', description: '기준선과 표준편차 밴드' }, classification: { title: '계절별 패턴 분류', description: '패턴의 분포' }, qoq: { title: '분기별 변화', description: '순차적 투표 변화' } }, classifications: { NORMAL_ACTIVITY: '정상 활동', ELEVATED_ACTIVITY: '상승 활동', REDUCED_ACTIVITY: '감소 활동', ANOMALY_DETECTED: '이상 탐지', NORMAL_SEASONAL_PATTERN: '정상 계절 패턴', Q3_SUMMER_LULL: '여름 휴회', Q4_ELEVATED_ACTIVITY: '상승 활동', UNUSUALLY_HIGH_ACTIVITY: '비정상적으로 높은 활동', UNUSUALLY_LOW_ACTIVITY: '비정상적으로 낮은 활동' }, tooltips: { ballots: '투표', zScore: 'Z점수', classification: '분류', anomaly: '이상', na: 'N/A', quarter: '분기', year: '년도' }, chartLabels: { ballotZScore: '투표 Z', documentZScore: '문서 Z', attendanceZScore: '출석 Z', yearQuarter: '년-분기', zScore: 'Z점수', quarter: '분기', averageBallots: '평균 투표', year: '년도', count: '수', changePercent: '변화 (%)', qoqChange: 'QoQ 변화 (%)', anomaly: '이상' }, loading: '데이터 로딩 중...', error: '데이터 로딩 오류.', dataAttribution: 'CIA 플랫폼의 데이터' },
|
|
101
|
+
zh: { title: '季节性模式 (2002-2025)', subtitle: '带Z分数异常检测的季度分析', filters: { year: '年份', quarter: '季度', election: '选举状态', classification: '活动分类', allYears: '所有年份', allQuarters: '所有季度', allElections: '全部', electionYears: '选举年', nonElectionYears: '非选举年', allClassifications: '所有分类' }, quarters: { Q1: '第1季度', Q2: '第2季度', Q3: '第3季度', Q4: '第4季度' }, charts: { heatmap: { title: '季度活动热图', description: '按年份和季度' }, zscore: { title: 'Z分数异常检测', description: '统计异常值标记为红色' }, comparison: { title: '按季度的平均活动', description: '基线与标准差带' }, classification: { title: '季节性模式分类', description: '模式的分布' }, qoq: { title: '季度环比变化', description: '连续投票变化' } }, classifications: { NORMAL_ACTIVITY: '正常活动', ELEVATED_ACTIVITY: '活动升高', REDUCED_ACTIVITY: '活动降低', ANOMALY_DETECTED: '检测到异常', NORMAL_SEASONAL_PATTERN: '正常季节性模式', Q3_SUMMER_LULL: '夏季休会', Q4_ELEVATED_ACTIVITY: '活动升高', UNUSUALLY_HIGH_ACTIVITY: '异常高的活动', UNUSUALLY_LOW_ACTIVITY: '异常低的活动' }, tooltips: { ballots: '投票', zScore: 'Z分数', classification: '分类', anomaly: '异常', na: '无', quarter: '季度', year: '年份' }, chartLabels: { ballotZScore: '投票Z', documentZScore: '文档Z', attendanceZScore: '出勤Z', yearQuarter: '年-季度', zScore: 'Z分数', quarter: '季度', averageBallots: '平均投票', year: '年份', count: '计数', changePercent: '变化 (%)', qoqChange: 'QoQ变化 (%)', anomaly: '异常' }, loading: '加载数据中...', error: '加载数据出错。', dataAttribution: '数据来自CIA平台' }
|
|
102
|
+
};
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// DATA MANAGER
|
|
105
|
+
// ============================================================================
|
|
106
|
+
class SeasonalPatternsDataManager {
|
|
107
|
+
data = null;
|
|
108
|
+
async fetchData() {
|
|
109
|
+
const cached = this.getCachedData();
|
|
110
|
+
if (cached) {
|
|
111
|
+
logger.info('Using cached seasonal patterns data');
|
|
112
|
+
this.data = cached;
|
|
113
|
+
return cached;
|
|
114
|
+
}
|
|
115
|
+
let lastError = null;
|
|
116
|
+
for (let i = 0; i < CONFIG.dataUrls.length; i++) {
|
|
117
|
+
const url = CONFIG.dataUrls[i];
|
|
118
|
+
const isLocal = !url.startsWith('http');
|
|
119
|
+
try {
|
|
120
|
+
logger.info(`Fetching seasonal patterns data from ${isLocal ? 'local' : 'remote'} source (${i + 1}/${CONFIG.dataUrls.length})...`);
|
|
121
|
+
const response = await fetch(url);
|
|
122
|
+
if (!response.ok)
|
|
123
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
124
|
+
const csvText = await response.text();
|
|
125
|
+
const parsedData = this.parseCSV(csvText);
|
|
126
|
+
this.setCachedData(parsedData);
|
|
127
|
+
this.data = parsedData;
|
|
128
|
+
logger.info(`Loaded ${parsedData.length} seasonal activity records from ${isLocal ? 'local' : 'remote'} source`);
|
|
129
|
+
return parsedData;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
133
|
+
logger.error(`Failed to load from ${isLocal ? 'local' : 'remote'} source: ${lastError.message}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Try expired cache as fallback
|
|
137
|
+
const cached2 = localStorage.getItem(CONFIG.cacheKey);
|
|
138
|
+
if (cached2) {
|
|
139
|
+
try {
|
|
140
|
+
const parsed = JSON.parse(cached2);
|
|
141
|
+
if (parsed && typeof parsed === 'object' && 'data' in parsed) {
|
|
142
|
+
logger.info('Using expired cache as fallback');
|
|
143
|
+
this.data = parsed.data;
|
|
144
|
+
return parsed.data;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch { /* ignore */ }
|
|
148
|
+
}
|
|
149
|
+
throw lastError || new Error('All data sources failed');
|
|
150
|
+
}
|
|
151
|
+
parseCSV(csvText) {
|
|
152
|
+
if (typeof Papa !== 'undefined') {
|
|
153
|
+
const parsed = Papa.parse(csvText, { header: true, dynamicTyping: true, skipEmptyLines: true });
|
|
154
|
+
return parsed.data;
|
|
155
|
+
}
|
|
156
|
+
// CSP-safe fallback: simple CSV parser (no d3.csvParse — it requires unsafe-eval)
|
|
157
|
+
const lines = csvText.trim().split('\n');
|
|
158
|
+
if (lines.length < 2)
|
|
159
|
+
return [];
|
|
160
|
+
const headers = lines[0].split(',').map(h => h.trim().replace(/^"|"$/g, ''));
|
|
161
|
+
const data = [];
|
|
162
|
+
for (let i = 1; i < lines.length; i++) {
|
|
163
|
+
if (!lines[i].trim())
|
|
164
|
+
continue;
|
|
165
|
+
const values = lines[i].split(',').map(v => v.trim().replace(/^"|"$/g, ''));
|
|
166
|
+
const row = {};
|
|
167
|
+
headers.forEach((header, index) => {
|
|
168
|
+
const value = values[index];
|
|
169
|
+
if (typeof value === 'string' && /^-?\d+(\.\d+)?$/.test(value.trim())) {
|
|
170
|
+
row[header] = parseFloat(value);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
row[header] = value;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
data.push(row);
|
|
177
|
+
}
|
|
178
|
+
return data;
|
|
179
|
+
}
|
|
180
|
+
getCachedData() {
|
|
181
|
+
try {
|
|
182
|
+
const cached = localStorage.getItem(CONFIG.cacheKey);
|
|
183
|
+
if (!cached)
|
|
184
|
+
return null;
|
|
185
|
+
const parsed = JSON.parse(cached);
|
|
186
|
+
if (Date.now() - parsed.timestamp > CONFIG.cacheDuration)
|
|
187
|
+
return null;
|
|
188
|
+
return parsed.data;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
setCachedData(data) {
|
|
195
|
+
try {
|
|
196
|
+
localStorage.setItem(CONFIG.cacheKey, JSON.stringify({ data, timestamp: Date.now() }));
|
|
197
|
+
}
|
|
198
|
+
catch (e) {
|
|
199
|
+
logger.error('Error caching data:', e);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
aggregateByQuarter() {
|
|
203
|
+
if (!this.data)
|
|
204
|
+
return null;
|
|
205
|
+
const quarters = { Q1: [], Q2: [], Q3: [], Q4: [] };
|
|
206
|
+
this.data.forEach(row => { const q = `Q${row['quarter']}`; if (quarters[q])
|
|
207
|
+
quarters[q].push(row); });
|
|
208
|
+
const aggregated = {};
|
|
209
|
+
Object.keys(quarters).forEach(q => {
|
|
210
|
+
const records = quarters[q];
|
|
211
|
+
if (records.length === 0)
|
|
212
|
+
return;
|
|
213
|
+
const ballots = records.map(r => Number(r['total_ballots']) || 0);
|
|
214
|
+
const attendance = records.map(r => Number(r['attendance_rate']) || 0);
|
|
215
|
+
const docs = records.map(r => Number(r['documents_produced']) || 0);
|
|
216
|
+
aggregated[q] = { quarter: q, avgBallots: mean(ballots), stddevBallots: stddev(ballots), avgAttendance: mean(attendance), stddevAttendance: stddev(attendance), avgDocs: mean(docs), stddevDocs: stddev(docs), count: records.length };
|
|
217
|
+
});
|
|
218
|
+
return aggregated;
|
|
219
|
+
}
|
|
220
|
+
identifyAnomalies(threshold = CONFIG.zScoreThreshold) {
|
|
221
|
+
if (!this.data)
|
|
222
|
+
return [];
|
|
223
|
+
const anomalies = this.data.filter(row => {
|
|
224
|
+
const ballotZ = Math.abs(Number(row['ballot_z_score']) || 0);
|
|
225
|
+
const docZ = Math.abs(Number(row['doc_z_score']) || 0);
|
|
226
|
+
const attendanceZ = Math.abs(Number(row['attendance_z_score']) || 0);
|
|
227
|
+
return ballotZ >= threshold || docZ >= threshold || attendanceZ >= threshold;
|
|
228
|
+
});
|
|
229
|
+
anomalies.sort((a, b) => {
|
|
230
|
+
const maxZa = Math.max(Math.abs(Number(a['ballot_z_score']) || 0), Math.abs(Number(a['doc_z_score']) || 0), Math.abs(Number(a['attendance_z_score']) || 0));
|
|
231
|
+
const maxZb = Math.max(Math.abs(Number(b['ballot_z_score']) || 0), Math.abs(Number(b['doc_z_score']) || 0), Math.abs(Number(b['attendance_z_score']) || 0));
|
|
232
|
+
return maxZb - maxZa;
|
|
233
|
+
});
|
|
234
|
+
return anomalies;
|
|
235
|
+
}
|
|
236
|
+
filterData(filters) {
|
|
237
|
+
if (!this.data)
|
|
238
|
+
return [];
|
|
239
|
+
return this.data.filter(row => {
|
|
240
|
+
if (filters.year && filters.year !== 'all' && String(row['year']) !== filters.year)
|
|
241
|
+
return false;
|
|
242
|
+
if (filters.quarter && filters.quarter !== 'all' && String(row['quarter']) !== filters.quarter)
|
|
243
|
+
return false;
|
|
244
|
+
if (filters.election && filters.election !== 'all') {
|
|
245
|
+
const isElection = row['is_election_year'] === 't' || row['is_election_year'] === 'true';
|
|
246
|
+
if (filters.election === 'election' && !isElection)
|
|
247
|
+
return false;
|
|
248
|
+
if (filters.election === 'non-election' && isElection)
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
if (filters.classification && filters.classification !== 'all') {
|
|
252
|
+
if (row['base_activity_classification'] !== filters.classification && row['seasonal_pattern_classification'] !== filters.classification)
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function mean(arr) { if (arr.length === 0)
|
|
260
|
+
return 0; return arr.reduce((s, v) => s + v, 0) / arr.length; }
|
|
261
|
+
function stddev(arr) { if (arr.length === 0)
|
|
262
|
+
return 0; const avg = mean(arr); return Math.sqrt(mean(arr.map(v => Math.pow(v - avg, 2)))); }
|
|
263
|
+
// ============================================================================
|
|
264
|
+
// CHART RENDERER
|
|
265
|
+
// ============================================================================
|
|
266
|
+
class SeasonalPatternsCharts {
|
|
267
|
+
chartInstances = {};
|
|
268
|
+
translations;
|
|
269
|
+
dataManager;
|
|
270
|
+
constructor(dataManager, language = 'en') {
|
|
271
|
+
this.dataManager = dataManager;
|
|
272
|
+
this.translations = TRANSLATIONS[language] || TRANSLATIONS['en'];
|
|
273
|
+
}
|
|
274
|
+
destroyCharts() {
|
|
275
|
+
Object.keys(this.chartInstances).forEach(key => { if (this.chartInstances[key]) {
|
|
276
|
+
this.chartInstances[key].destroy();
|
|
277
|
+
delete this.chartInstances[key];
|
|
278
|
+
} });
|
|
279
|
+
}
|
|
280
|
+
async renderAll(filteredData = null) {
|
|
281
|
+
const data = filteredData || this.dataManager.data;
|
|
282
|
+
if (!data || data.length === 0)
|
|
283
|
+
return;
|
|
284
|
+
this.destroyCharts();
|
|
285
|
+
this.renderSeasonalHeatmap(data);
|
|
286
|
+
this.renderZScoreTimeline(data);
|
|
287
|
+
this.renderQuarterComparison(data);
|
|
288
|
+
this.renderClassificationChart(data);
|
|
289
|
+
this.renderQoQChangeChart(data);
|
|
290
|
+
}
|
|
291
|
+
renderSeasonalHeatmap(data) {
|
|
292
|
+
const container = document.getElementById('seasonal-heatmap');
|
|
293
|
+
if (!container || typeof d3 === 'undefined')
|
|
294
|
+
return;
|
|
295
|
+
container.innerHTML = '';
|
|
296
|
+
const margin = { top: 40, right: 100, bottom: 60, left: 60 };
|
|
297
|
+
const width = Math.min(container.clientWidth, 1200) - margin.left - margin.right;
|
|
298
|
+
const height = 600 - margin.top - margin.bottom;
|
|
299
|
+
const svg = d3.select(container).append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom).attr('role', 'img').attr('aria-label', this.translations.charts.heatmap.title).append('g').attr('transform', `translate(${margin.left},${margin.top})`);
|
|
300
|
+
const years = Array.from(new Set(data.map((d) => d['year']))).sort();
|
|
301
|
+
const quarters = [1, 2, 3, 4];
|
|
302
|
+
const xScale = d3.scaleBand().domain(quarters).range([0, width]).padding(0.05);
|
|
303
|
+
const yScale = d3.scaleBand().domain(years).range([0, height]).padding(0.05);
|
|
304
|
+
const maxBallots = d3.max(data, (d) => Number(d['total_ballots']) || 0);
|
|
305
|
+
const colorScale = d3.scaleSequential().domain([0, maxBallots]).interpolator(d3.interpolateYlOrRd);
|
|
306
|
+
const t = this.translations;
|
|
307
|
+
svg.selectAll('.cell').data(data).enter().append('rect').attr('class', 'cell')
|
|
308
|
+
.attr('x', (d) => xScale(d['quarter'])).attr('y', (d) => yScale(d['year']))
|
|
309
|
+
.attr('width', xScale.bandwidth()).attr('height', yScale.bandwidth())
|
|
310
|
+
.attr('fill', (d) => colorScale(Number(d['total_ballots']) || 0)).attr('stroke', '#fff').attr('stroke-width', 1)
|
|
311
|
+
.append('title').text((d) => {
|
|
312
|
+
const classText = t.classifications[d['seasonal_pattern_classification']] || t.classifications[d['base_activity_classification']] || d['seasonal_pattern_classification'] || t.tooltips.na;
|
|
313
|
+
return `${d['year']} Q${d['quarter']}\n${t.tooltips.ballots}: ${d['total_ballots']}\n${t.tooltips.zScore}: ${(Number(d['ballot_z_score']) || 0).toFixed(2)}\n${t.tooltips.classification}: ${classText}`;
|
|
314
|
+
});
|
|
315
|
+
const anomalies = data.filter((d) => Math.abs(Number(d['ballot_z_score']) || 0) >= CONFIG.zScoreThreshold);
|
|
316
|
+
svg.selectAll('.anomaly-marker').data(anomalies).enter().append('circle').attr('class', 'anomaly-marker')
|
|
317
|
+
.attr('cx', (d) => xScale(d['quarter']) + xScale.bandwidth() / 2).attr('cy', (d) => yScale(d['year']) + yScale.bandwidth() / 2)
|
|
318
|
+
.attr('r', 8).attr('fill', CONFIG.colors.danger).attr('stroke', '#fff').attr('stroke-width', 2)
|
|
319
|
+
.append('title').text((d) => `${t.tooltips.anomaly}: ${d['year']} Q${d['quarter']}\n${t.tooltips.zScore}: ${(Number(d['ballot_z_score']) || 0).toFixed(2)}`);
|
|
320
|
+
svg.append('g').attr('transform', `translate(0,${height})`).call(d3.axisBottom(xScale).tickFormat((q) => `Q${q}`));
|
|
321
|
+
svg.append('g').call(d3.axisLeft(yScale));
|
|
322
|
+
svg.append('text').attr('x', width / 2).attr('y', height + 40).attr('text-anchor', 'middle').text(t.filters?.quarter || 'Quarter').style('font-size', '14px');
|
|
323
|
+
svg.append('text').attr('transform', 'rotate(-90)').attr('x', -height / 2).attr('y', -40).attr('text-anchor', 'middle').text(t.filters?.year || 'Year').style('font-size', '14px');
|
|
324
|
+
}
|
|
325
|
+
renderZScoreTimeline(data) {
|
|
326
|
+
const canvas = document.getElementById('zscore-timeline-chart');
|
|
327
|
+
if (!canvas)
|
|
328
|
+
return;
|
|
329
|
+
const ctx = canvas.getContext('2d');
|
|
330
|
+
const t = this.translations.chartLabels;
|
|
331
|
+
const sortedData = [...data].sort((a, b) => { if (a['year'] !== b['year'])
|
|
332
|
+
return Number(a['year']) - Number(b['year']); return Number(a['quarter']) - Number(b['quarter']); });
|
|
333
|
+
const labels = sortedData.map(d => `${d['year']}-Q${d['quarter']}`);
|
|
334
|
+
this.chartInstances['zscore'] = new Chart(ctx, {
|
|
335
|
+
type: 'line', data: { labels, datasets: [
|
|
336
|
+
{ label: t.ballotZScore, data: sortedData.map(d => Number(d['ballot_z_score']) || 0), borderColor: CONFIG.colors.primary, backgroundColor: CONFIG.colors.primary + '40', borderWidth: 2, pointRadius: 3, tension: 0.1 },
|
|
337
|
+
{ label: t.documentZScore, data: sortedData.map(d => Number(d['doc_z_score']) || 0), borderColor: CONFIG.colors.secondary, backgroundColor: CONFIG.colors.secondary + '40', borderWidth: 2, pointRadius: 3, tension: 0.1 },
|
|
338
|
+
{ label: t.attendanceZScore, data: sortedData.map(d => Number(d['attendance_z_score']) || 0), borderColor: CONFIG.colors.tertiary, backgroundColor: CONFIG.colors.tertiary + '40', borderWidth: 2, pointRadius: 3, tension: 0.1 }
|
|
339
|
+
] },
|
|
340
|
+
options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top' }, tooltip: { callbacks: { label: (context) => { let label = context.dataset.label || ''; if (label)
|
|
341
|
+
label += ': '; label += context.parsed.y.toFixed(2); if (Math.abs(context.parsed.y) >= CONFIG.zScoreThreshold)
|
|
342
|
+
label += ' 🔴 ' + t.anomaly; return label; } } } }, scales: { x: { title: { display: true, text: t.yearQuarter }, ticks: { maxRotation: 90, minRotation: 45, autoSkip: true, maxTicksLimit: 20 } }, y: { title: { display: true, text: t.zScore }, min: -4, max: 4 } } }
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
renderQuarterComparison(data) {
|
|
346
|
+
const canvas = document.getElementById('quarter-comparison-chart');
|
|
347
|
+
if (!canvas)
|
|
348
|
+
return;
|
|
349
|
+
const ctx = canvas.getContext('2d');
|
|
350
|
+
const aggregated = this.aggregateDataByQuarter(data);
|
|
351
|
+
if (!aggregated)
|
|
352
|
+
return;
|
|
353
|
+
const labels = ['Q1', 'Q2', 'Q3', 'Q4'];
|
|
354
|
+
const avgBallots = labels.map(q => aggregated[q]?.avgBallots || 0);
|
|
355
|
+
const stddevBallots = labels.map(q => aggregated[q]?.stddevBallots || 0);
|
|
356
|
+
this.chartInstances['comparison'] = new Chart(ctx, {
|
|
357
|
+
type: 'bar', data: { labels: labels.map(q => this.translations.quarters[q] || q), datasets: [{ label: this.translations.charts?.comparison?.title || 'Average Ballots', data: avgBallots, backgroundColor: labels.map(q => CONFIG.quarterColors[q]), borderColor: labels.map(q => CONFIG.quarterColors[q]), borderWidth: 2 }] },
|
|
358
|
+
options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { callbacks: { label: (context) => [`Average: ${context.parsed.y.toFixed(1)} ballots`, `Std Dev: ±${stddevBallots[context.dataIndex].toFixed(1)}`] } } }, scales: { x: { title: { display: true, text: this.translations.chartLabels.quarter } }, y: { title: { display: true, text: this.translations.chartLabels.averageBallots }, beginAtZero: true } } }
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
aggregateDataByQuarter(data) {
|
|
362
|
+
if (!data)
|
|
363
|
+
return null;
|
|
364
|
+
const quarters = { Q1: [], Q2: [], Q3: [], Q4: [] };
|
|
365
|
+
data.forEach(row => { const q = `Q${row['quarter']}`; if (quarters[q])
|
|
366
|
+
quarters[q].push(row); });
|
|
367
|
+
const aggregated = {};
|
|
368
|
+
Object.keys(quarters).forEach(q => {
|
|
369
|
+
const records = quarters[q];
|
|
370
|
+
if (records.length === 0)
|
|
371
|
+
return;
|
|
372
|
+
const ballots = records.map(r => Number(r['total_ballots']) || 0);
|
|
373
|
+
aggregated[q] = { quarter: q, avgBallots: mean(ballots), stddevBallots: stddev(ballots), avgAttendance: 0, stddevAttendance: 0, avgDocs: 0, stddevDocs: 0, count: records.length };
|
|
374
|
+
});
|
|
375
|
+
return aggregated;
|
|
376
|
+
}
|
|
377
|
+
renderClassificationChart(data) {
|
|
378
|
+
const canvas = document.getElementById('classification-chart');
|
|
379
|
+
if (!canvas)
|
|
380
|
+
return;
|
|
381
|
+
const ctx = canvas.getContext('2d');
|
|
382
|
+
const years = Array.from(new Set(data.map(d => d['year']))).sort();
|
|
383
|
+
const classifications = {};
|
|
384
|
+
data.forEach(row => {
|
|
385
|
+
const classification = row['seasonal_pattern_classification'] || 'UNKNOWN';
|
|
386
|
+
if (!classifications[classification])
|
|
387
|
+
classifications[classification] = {};
|
|
388
|
+
if (!classifications[classification][row['year']])
|
|
389
|
+
classifications[classification][row['year']] = 0;
|
|
390
|
+
classifications[classification][row['year']]++;
|
|
391
|
+
});
|
|
392
|
+
const datasets = Object.keys(classifications).map(classification => {
|
|
393
|
+
const counts = years.map(year => classifications[classification][year] || 0);
|
|
394
|
+
let color = CONFIG.colors.info;
|
|
395
|
+
if (classification.includes('NORMAL'))
|
|
396
|
+
color = CONFIG.colors.normal;
|
|
397
|
+
else if (classification.includes('ELEVATED') || classification.includes('HIGH'))
|
|
398
|
+
color = CONFIG.colors.elevated;
|
|
399
|
+
else if (classification.includes('REDUCED') || classification.includes('LOW'))
|
|
400
|
+
color = CONFIG.colors.reduced;
|
|
401
|
+
else if (classification.includes('ANOMALY'))
|
|
402
|
+
color = CONFIG.colors.anomaly;
|
|
403
|
+
return { label: this.translations.classifications[classification] || classification, data: counts, backgroundColor: color, borderColor: color, borderWidth: 1 };
|
|
404
|
+
});
|
|
405
|
+
this.chartInstances['classification'] = new Chart(ctx, {
|
|
406
|
+
type: 'bar', data: { labels: years, datasets },
|
|
407
|
+
options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top' }, tooltip: { mode: 'index', intersect: false } }, scales: { x: { stacked: true, title: { display: true, text: this.translations.chartLabels.year } }, y: { stacked: true, title: { display: true, text: this.translations.chartLabels.count }, beginAtZero: true } } }
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
renderQoQChangeChart(data) {
|
|
411
|
+
const canvas = document.getElementById('qoq-change-chart');
|
|
412
|
+
if (!canvas)
|
|
413
|
+
return;
|
|
414
|
+
const ctx = canvas.getContext('2d');
|
|
415
|
+
const sortedData = [...data].filter(d => d['qoq_ballot_change_pct'] !== null && d['qoq_ballot_change_pct'] !== undefined).sort((a, b) => { if (a['year'] !== b['year'])
|
|
416
|
+
return Number(a['year']) - Number(b['year']); return Number(a['quarter']) - Number(b['quarter']); });
|
|
417
|
+
const labels = sortedData.map(d => `${d['year']}-Q${d['quarter']}`);
|
|
418
|
+
const changes = sortedData.map(d => Number(d['qoq_ballot_change_pct']) || 0);
|
|
419
|
+
const colors = changes.map(change => change > 0 ? CONFIG.colors.success : change < 0 ? CONFIG.colors.danger : CONFIG.colors.info);
|
|
420
|
+
this.chartInstances['qoq'] = new Chart(ctx, {
|
|
421
|
+
type: 'bar', data: { labels, datasets: [{ label: this.translations.chartLabels.qoqChange, data: changes, backgroundColor: colors, borderColor: colors, borderWidth: 1 }] },
|
|
422
|
+
options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { callbacks: { label: (context) => `Change: ${context.parsed.y.toFixed(2)}%` } } }, scales: { x: { title: { display: true, text: this.translations.chartLabels.yearQuarter }, ticks: { maxRotation: 90, minRotation: 45, autoSkip: true, maxTicksLimit: 20 } }, y: { title: { display: true, text: this.translations.chartLabels.changePercent } } } }
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
// ============================================================================
|
|
427
|
+
// DASHBOARD CONTROLLER
|
|
428
|
+
// ============================================================================
|
|
429
|
+
class SeasonalPatternsDashboard {
|
|
430
|
+
dataManager = new SeasonalPatternsDataManager();
|
|
431
|
+
chartRenderer = null;
|
|
432
|
+
currentLanguage;
|
|
433
|
+
translations;
|
|
434
|
+
currentFilters = { year: 'all', quarter: 'all', election: 'all', classification: 'all' };
|
|
435
|
+
constructor() {
|
|
436
|
+
this.currentLanguage = detectLanguage();
|
|
437
|
+
this.translations = TRANSLATIONS[this.currentLanguage] || TRANSLATIONS['en'];
|
|
438
|
+
if (!this.translations.tooltips)
|
|
439
|
+
this.translations.tooltips = TRANSLATIONS['en'].tooltips;
|
|
440
|
+
if (!this.translations.chartLabels)
|
|
441
|
+
this.translations.chartLabels = TRANSLATIONS['en'].chartLabels;
|
|
442
|
+
}
|
|
443
|
+
async initialize() {
|
|
444
|
+
try {
|
|
445
|
+
this.showLoading();
|
|
446
|
+
await this.dataManager.fetchData();
|
|
447
|
+
const dash = document.getElementById('seasonal-patterns-dashboard');
|
|
448
|
+
if (dash) {
|
|
449
|
+
showDataSourceDisclaimer(dash, 'live');
|
|
450
|
+
}
|
|
451
|
+
this.chartRenderer = new SeasonalPatternsCharts(this.dataManager, this.currentLanguage);
|
|
452
|
+
this.setupFilters();
|
|
453
|
+
await this.chartRenderer.renderAll();
|
|
454
|
+
this.hideLoading();
|
|
455
|
+
logger.info('Seasonal Patterns Dashboard initialized successfully');
|
|
456
|
+
}
|
|
457
|
+
catch (error) {
|
|
458
|
+
logger.error('Error initializing dashboard:', error);
|
|
459
|
+
this.showError();
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
setupFilters() {
|
|
463
|
+
const yearFilter = document.getElementById('year-filter');
|
|
464
|
+
const quarterFilter = document.getElementById('quarter-filter');
|
|
465
|
+
const electionFilter = document.getElementById('election-filter');
|
|
466
|
+
const classificationFilter = document.getElementById('classification-filter');
|
|
467
|
+
if (yearFilter) {
|
|
468
|
+
yearFilter.addEventListener('change', (e) => { this.currentFilters.year = e.target.value; this.applyFilters(); });
|
|
469
|
+
const years = Array.from(new Set(this.dataManager.data.map(d => d['year']))).sort((a, b) => Number(b) - Number(a));
|
|
470
|
+
years.forEach(year => { const o = document.createElement('option'); o.value = String(year); o.textContent = String(year); yearFilter.appendChild(o); });
|
|
471
|
+
}
|
|
472
|
+
if (quarterFilter) {
|
|
473
|
+
quarterFilter.addEventListener('change', (e) => { this.currentFilters.quarter = e.target.value; this.applyFilters(); });
|
|
474
|
+
}
|
|
475
|
+
if (electionFilter) {
|
|
476
|
+
electionFilter.addEventListener('change', (e) => { this.currentFilters.election = e.target.value; this.applyFilters(); });
|
|
477
|
+
}
|
|
478
|
+
if (classificationFilter) {
|
|
479
|
+
classificationFilter.addEventListener('change', (e) => { this.currentFilters.classification = e.target.value; this.applyFilters(); });
|
|
480
|
+
const classificationSet = new Set();
|
|
481
|
+
this.dataManager.data.forEach(d => { if (d['seasonal_pattern_classification'])
|
|
482
|
+
classificationSet.add(d['seasonal_pattern_classification']); if (d['base_activity_classification'])
|
|
483
|
+
classificationSet.add(d['base_activity_classification']); });
|
|
484
|
+
Array.from(classificationSet).sort().forEach(classification => {
|
|
485
|
+
const o = document.createElement('option');
|
|
486
|
+
o.value = classification;
|
|
487
|
+
o.textContent = this.translations.classifications?.[classification] || TRANSLATIONS['en']?.classifications?.[classification] || classification;
|
|
488
|
+
classificationFilter.appendChild(o);
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
async applyFilters() {
|
|
493
|
+
const filteredData = this.dataManager.filterData(this.currentFilters);
|
|
494
|
+
await this.chartRenderer.renderAll(filteredData);
|
|
495
|
+
}
|
|
496
|
+
showLoading() {
|
|
497
|
+
const container = document.getElementById('seasonal-patterns-dashboard');
|
|
498
|
+
if (container) {
|
|
499
|
+
container.classList.add('loading');
|
|
500
|
+
container.setAttribute('aria-busy', 'true');
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
hideLoading() {
|
|
504
|
+
const container = document.getElementById('seasonal-patterns-dashboard');
|
|
505
|
+
if (container) {
|
|
506
|
+
container.classList.remove('loading');
|
|
507
|
+
container.removeAttribute('aria-busy');
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
showError() {
|
|
511
|
+
const container = document.getElementById('seasonal-patterns-dashboard');
|
|
512
|
+
if (container) {
|
|
513
|
+
while (container.firstChild)
|
|
514
|
+
container.removeChild(container.firstChild);
|
|
515
|
+
const errorWrapper = document.createElement('div');
|
|
516
|
+
errorWrapper.className = 'error-message';
|
|
517
|
+
errorWrapper.setAttribute('role', 'alert');
|
|
518
|
+
const errorText = document.createElement('p');
|
|
519
|
+
errorText.textContent = `⚠️ ${this.translations.error || TRANSLATIONS['en'].error}`;
|
|
520
|
+
errorWrapper.appendChild(errorText);
|
|
521
|
+
container.appendChild(errorWrapper);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
// ============================================================================
|
|
526
|
+
// EXPORTED INIT
|
|
527
|
+
// ============================================================================
|
|
528
|
+
export async function init() {
|
|
529
|
+
const dashboardContainer = document.getElementById('seasonal-patterns-dashboard');
|
|
530
|
+
if (dashboardContainer) {
|
|
531
|
+
const dashboard = new SeasonalPatternsDashboard();
|
|
532
|
+
await dashboard.initialize();
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
//# sourceMappingURL=seasonal-patterns.js.map
|