@jjlmoya/utils-civic 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +2 -0
  4. package/src/tests/locale_completeness.test.ts +1 -1
  5. package/src/tests/tool_validation.test.ts +1 -1
  6. package/src/tool/coalition-majority-calculator/bibliography.astro +6 -0
  7. package/src/tool/coalition-majority-calculator/bibliography.ts +12 -0
  8. package/src/tool/coalition-majority-calculator/coalition-majority-calculator.css +467 -0
  9. package/src/tool/coalition-majority-calculator/component.astro +62 -0
  10. package/src/tool/coalition-majority-calculator/contract.test.ts +14 -0
  11. package/src/tool/coalition-majority-calculator/controller.ts +89 -0
  12. package/src/tool/coalition-majority-calculator/dom-views.ts +145 -0
  13. package/src/tool/coalition-majority-calculator/entry.ts +28 -0
  14. package/src/tool/coalition-majority-calculator/evaluator.ts +13 -0
  15. package/src/tool/coalition-majority-calculator/i18n/de.ts +51 -0
  16. package/src/tool/coalition-majority-calculator/i18n/en.ts +74 -0
  17. package/src/tool/coalition-majority-calculator/i18n/es.ts +51 -0
  18. package/src/tool/coalition-majority-calculator/i18n/fr.ts +12 -0
  19. package/src/tool/coalition-majority-calculator/i18n/id.ts +45 -0
  20. package/src/tool/coalition-majority-calculator/i18n/it.ts +12 -0
  21. package/src/tool/coalition-majority-calculator/i18n/ja.ts +21 -0
  22. package/src/tool/coalition-majority-calculator/i18n/ko.ts +21 -0
  23. package/src/tool/coalition-majority-calculator/i18n/nl.ts +12 -0
  24. package/src/tool/coalition-majority-calculator/i18n/pl.ts +12 -0
  25. package/src/tool/coalition-majority-calculator/i18n/pt.ts +12 -0
  26. package/src/tool/coalition-majority-calculator/i18n/ru.ts +12 -0
  27. package/src/tool/coalition-majority-calculator/i18n/sv.ts +12 -0
  28. package/src/tool/coalition-majority-calculator/i18n/tr.ts +12 -0
  29. package/src/tool/coalition-majority-calculator/i18n/zh.ts +12 -0
  30. package/src/tool/coalition-majority-calculator/index.ts +11 -0
  31. package/src/tool/coalition-majority-calculator/logic.test.ts +60 -0
  32. package/src/tool/coalition-majority-calculator/logic.ts +146 -0
  33. package/src/tool/coalition-majority-calculator/seo.astro +12 -0
  34. package/src/tool/coalition-majority-calculator/storage.ts +32 -0
  35. package/src/tool/coalition-majority-calculator/ui.ts +80 -0
  36. package/src/tools.ts +2 -0
@@ -0,0 +1,32 @@
1
+ import type { PartyInput } from './logic';
2
+
3
+ export interface CoalitionSavedState {
4
+ parties: PartyInput[];
5
+ threshold: number;
6
+ }
7
+
8
+ const STORAGE_KEY = 'jjlmoya-civic-coalition-majority';
9
+
10
+ export function saveCoalitionState(state: CoalitionSavedState): void {
11
+ try {
12
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
13
+ } catch {}
14
+ }
15
+
16
+ export function loadCoalitionState(): CoalitionSavedState | null {
17
+ try {
18
+ const raw = localStorage.getItem(STORAGE_KEY);
19
+ if (!raw) return null;
20
+ const parsed = JSON.parse(raw) as CoalitionSavedState;
21
+ if (!Array.isArray(parsed.parties) || typeof parsed.threshold !== 'number') return null;
22
+ return parsed;
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ export function clearCoalitionState(): void {
29
+ try {
30
+ localStorage.removeItem(STORAGE_KEY);
31
+ } catch {}
32
+ }
@@ -0,0 +1,80 @@
1
+ export interface CoalitionMajorityUI {
2
+ [key: string]: string;
3
+ addParty: string;
4
+ allCoalitions: string;
5
+ calculate: string;
6
+ chamberSeats: string;
7
+ coalitionSceneLabel: string;
8
+ criticalDefections: string;
9
+ emptyState: string;
10
+ explanation: string;
11
+ edgeCasesText: string;
12
+ edgeCasesTitle: string;
13
+ filterCoalitions: string;
14
+ maximumParties: string;
15
+ majorityThreshold: string;
16
+ methodTitle: string;
17
+ methodText: string;
18
+ minimalCoalition: string;
19
+ noPivots: string;
20
+ noMatchingCoalitions: string;
21
+ none: string;
22
+ notDoText: string;
23
+ notDoTitle: string;
24
+ partyName: string;
25
+ partySeats: string;
26
+ partyTable: string;
27
+ pivotal: string;
28
+ pivotalParty: string;
29
+ redundantMembers: string;
30
+ removeParty: string;
31
+ reset: string;
32
+ resultTitle: string;
33
+ seats: string;
34
+ surplus: string;
35
+ surplusCoalition: string;
36
+ threshold: string;
37
+ thresholdHint: string;
38
+ totalCoalitions: string;
39
+ winningCoalitions: string;
40
+ }
41
+
42
+ export const ui: CoalitionMajorityUI = {
43
+ addParty: 'Add party',
44
+ allCoalitions: 'All winning coalitions',
45
+ calculate: 'Calculate coalitions',
46
+ chamberSeats: 'Total seats',
47
+ coalitionSceneLabel: 'Coalition constellation',
48
+ criticalDefections: 'Critical defections',
49
+ emptyState: 'Add at least two parties and enter their seats to see the coalition constellation.',
50
+ explanation: 'This model treats every listed party as willing to join any combination. It measures seat arithmetic, not political compatibility.',
51
+ edgeCasesText: 'Blank or duplicate names are made unique. Zero seat parties can never be critical. Above 20 parties the exact search is stopped.',
52
+ edgeCasesTitle: 'Edge cases and warnings',
53
+ filterCoalitions: 'Show',
54
+ maximumParties: 'Maximum 20 parties because exhaustive enumeration grows as 2 to the power of N.',
55
+ majorityThreshold: 'Majority threshold',
56
+ methodTitle: 'Model applied',
57
+ methodText: 'Every non empty subset is checked. A coalition wins at or above the declared threshold. A party is pivotal when removing it makes a winning coalition lose.',
58
+ minimalCoalition: 'Minimal winning coalition',
59
+ noMatchingCoalitions: 'No coalitions match this filter.',
60
+ noPivots: 'No party is pivotal under this threshold.',
61
+ none: 'None',
62
+ notDoText: 'It does not assess ideology, policy compatibility, bargaining, legitimacy, stability, or whether a government will form.',
63
+ notDoTitle: 'What this tool does not do',
64
+ partyName: 'Party name',
65
+ partySeats: 'Seats',
66
+ partyTable: 'Coalition details',
67
+ pivotal: 'pivotal',
68
+ pivotalParty: 'Pivotal party',
69
+ redundantMembers: 'Redundant members',
70
+ removeParty: 'Remove party',
71
+ reset: 'Reset example',
72
+ resultTitle: 'Coalition map',
73
+ seats: 'seats',
74
+ surplus: 'surplus',
75
+ surplusCoalition: 'Surplus coalition',
76
+ threshold: 'Threshold',
77
+ thresholdHint: 'A coalition wins when its seats meet or exceed this threshold.',
78
+ totalCoalitions: 'Possible non-empty coalitions',
79
+ winningCoalitions: 'Winning coalitions',
80
+ };
package/src/tools.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export { ALL_ENTRIES } from './entries';
2
2
  import type { ToolDefinition } from './types';
3
+ import { COALITION_MAJORITY_CALCULATOR_TOOL } from './tool/coalition-majority-calculator';
3
4
  import { ELECTION_SEAT_APPORTIONMENT_CALCULATOR_TOOL } from './tool/election-seat-apportionment-calculator';
4
5
  import { VOTE_SEAT_DISPROPORTIONALITY_ANALYZER_TOOL } from './tool/vote-seat-disproportionality-analyzer';
5
6
 
6
7
  export const ALL_TOOLS: ToolDefinition[] = [
8
+ COALITION_MAJORITY_CALCULATOR_TOOL,
7
9
  ELECTION_SEAT_APPORTIONMENT_CALCULATOR_TOOL,
8
10
  VOTE_SEAT_DISPROPORTIONALITY_ANALYZER_TOOL,
9
11
  ];