# pyRCV2: Preferential vote counting # Copyright © 2020–2021 Lee Yingtong Li (RunasSudo) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from pyRCV2.model import Constraint def CONException(Exception): pass def readCON(data, election): lines = data.split('\n') constraints = {} for line in lines: if not line: continue bits = line.split(' ') # Read constraint category if bits[0].startswith('"'): idx = next(i for i in range(len(bits)) if bits[i].endswith('"')) category = ' '.join(bits[0:idx+1]).strip('"') else: idx = 0 category = bits[0] # Read constraint name idx += 1 if bits[idx].startswith('"'): idx2 = next(i for i in range(idx, len(bits)) if bits[i].endswith('"')) name = ' '.join(bits[idx:idx2+1]).strip('"') idx = idx2 else: name = bits[idx] # Read min, max n_min = int(bits[idx + 1]) n_max = int(bits[idx + 2]) # Read candidates candidates = [] for v in bits[idx+3:]: candidates.append(election.candidates[int(v)-1]) if category not in constraints: constraints[category] = {} if name in constraints[category]: raise CONException('Duplicate constraint "' + name + '" in category "' + category + '"') constraints[category][name] = Constraint(category, name, n_min, n_max, candidates) return constraints