1class Currency:
2 def __init__(self, name, rate):
3 self.name = name
4 self.rate = rate
5
6 def __eq__(self, other):
7 if not isinstance(other, Currency):
8 return False
9
10 return self.name == other.name and self.rate == other.rate
11
12
13class PoliticalParty:
14 def __init__(self, name, motto, members=None, preferred_currency=None):
15 self.name = name
16 self._motto = motto
17 self.members = members if members is not None else []
18 self.preferred_currency = preferred_currency
19
20 @property
21 def motto(self):
22 return self._motto
23
24 def convert_currency_to_voters(self, amount, currency):
25 voters = amount // currency.rate
26
27 if self.preferred_currency == currency:
28 voters *= 2
29
30 return int(voters)
31
32 def __str__(self):
33 return self.name
34
35 def __add__(self, other):
36 if isinstance(other, PoliticalParty):
37 return Coalition(self, other)
38
39 return NotImplemented
40
41
42class Coalition:
43 def __init__(self, *parties):
44 self.parties = []
45
46 for party in parties:
47 self._add_party_if_missing(party)
48
49 def _add_party_if_missing(self, party):
50 for current_party in self.parties:
51 if current_party.name == party.name:
52 return
53
54 self.parties.append(party)
55
56 @property
57 def members(self):
58 result = {}
59
60 for party in self.parties:
61 result[party.name] = party.members.copy()
62
63 return result
64
65 def __str__(self):
66 names = []
67
68 for party in self.parties:
69 names.append(str(party))
70
71 return "-".join(names)
72
73 def __add__(self, other):
74 if isinstance(other, PoliticalParty):
75 return Coalition(*self.parties, other)
76
77 if isinstance(other, Coalition):
78 return Coalition(*self.parties, *other.parties)
79
80 return NotImplemented
81
82
83class Elections:
84 all_elections = {}
85
86 def __init__(self, year):
87 self.year = year
88 self.participants = {}
89 Elections.all_elections[year] = self
90
91 def register_party_or_coalition(self, participant):
92 if participant not in self.participants:
93 self.participants[participant] = 0
94
95 def vote(self, participant):
96 if participant in self.participants:
97 self.participants[participant] += 1
98
99 def rig_elections(self, participant, amount, currency):
100 if participant not in self.participants:
101 return
102
103 bought_votes = 0
104
105 if isinstance(participant, PoliticalParty):
106 bought_votes = participant.convert_currency_to_voters(amount, currency)
107
108 elif isinstance(participant, Coalition):
109 for party in participant.parties:
110 current_votes = party.convert_currency_to_voters(amount, currency)
111 if current_votes > bought_votes:
112 bought_votes = current_votes
113
114 self.participants[participant] += bought_votes
115
116 def get_results(self):
117 results = {}
118
119 for participant, votes in self.participants.items():
120 results[str(participant)] = votes
121
122 return results
123
124 @classmethod
125 def get_results_by_year(cls, year):
126 if year not in cls.all_elections:
127 return {}
128
129 return cls.all_elections[year].get_results()
..............F......
======================================================================
FAIL: test_convert_currency_to_voters_floating_point_edge_case (test.TestPoliticalParty.test_convert_currency_to_voters_floating_point_edge_case)
convert_currency_to_voters should properly account for floating point edge cases (e.g. 0.200001 errors).
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 55, in test_convert_currency_to_voters_floating_point_edge_case
self.assertEqual(5, party.convert_currency_to_voters(2, currency))
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 5 != 4
----------------------------------------------------------------------
Ran 21 tests in 0.001s
FAILED (failures=1)
25.03.2026 11:35
25.03.2026 11:36
25.03.2026 11:37