This repository has been archived on 2021-05-25. You can view files and clone it, but cannot push or open issues or pull requests.
pyRCV2/html/worker.js

110 lines
3.6 KiB
JavaScript

/*
pyRCV2: Preferential vote counting
Copyright © 2020 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 <https://www.gnu.org/licenses/>.
*/
importScripts('http://peterolson.github.com/BigRational.js/BigInt_BigRat.min.js', 'https://cdn.jsdelivr.net/npm/big.js@6.0.0/big.min.js', 'bundle.js');
onmessage = function(evt) {
// Set settings
if (evt.data.numbers === 'native') {
py.pyRCV2.numbers.set_numclass(py.pyRCV2.numbers.Native);
}
if (evt.data.numbers === 'int') {
py.pyRCV2.numbers.set_numclass(py.pyRCV2.numbers.NativeInt);
}
if (evt.data.numbers === 'rational') {
py.pyRCV2.numbers.set_numclass(py.pyRCV2.numbers.Rational);
}
if (evt.data.numbers === 'fixed') {
py.pyRCV2.numbers.set_numclass(py.pyRCV2.numbers.Fixed);
py.pyRCV2.numbers.set_dps(evt.data.fixedDPs);
}
let election = py.pyRCV2.blt.readBLT(evt.data.data);
postMessage({'type': 'init', 'election': {
'candidates': election.candidates.map(c => c.py_name)
}});
// Create counter
let counter;
if (evt.data.transfers === 'uig') {
counter = py.pyRCV2.method.base_stv.BaseUIGSTVCounter(election, evt.data.options);
} else if (evt.data.transfers === 'wright') {
counter = py.pyRCV2.method.wright.WrightSTVCounter(election, evt.data.options);
} else {
counter = py.pyRCV2.method.base_stv.BaseWIGSTVCounter(election, evt.data.options);
}
if (evt.data.options['ties'] === 'backwards_random') {
counter.options['ties'] = [py.pyRCV2.ties.TiesBackwards(), py.pyRCV2.ties.TiesRandom()];
} else if (evt.data.options['ties'] === 'random') {
counter.options['ties'] = [py.pyRCV2.ties.TiesRandom()];
} //else if (evt.data.options['ties'] === 'prompt') {
// counter.options['ties'] = [py.pyRCV2.ties.TiesPrompt()];
//}
// Reset
let result = counter.reset();
postMessage({'type': 'result', 'result': {
'comment': result.comment,
'candidates': result.candidates.py_items().map(([c, cc]) => [c.py_name, {
'transfers': cc.transfers.pp(2),
'votes': cc.votes.pp(2),
'state': cc.state
}]),
'exhausted': {
'transfers': result.exhausted.transfers.pp(2),
'votes': result.exhausted.votes.pp(2)
},
'loss_fraction': {
'transfers': result.loss_fraction.transfers.pp(2),
'votes': result.loss_fraction.votes.pp(2)
},
'total': result.total.pp(2),
'quota': result.quota.pp(2)
}});
// Step election
while (true) {
result = counter.step();
if (py.isinstance(result, py.pyRCV2.model.CountCompleted)) {
postMessage({'type': 'done'});
break;
} else {
postMessage({'type': 'result', 'result': {
'comment': result.comment,
'candidates': result.candidates.py_items().map(([c, cc]) => [c.py_name, {
'transfers': cc.transfers.pp(2),
'votes': cc.votes.pp(2),
'state': cc.state
}]),
'exhausted': {
'transfers': result.exhausted.transfers.pp(2),
'votes': result.exhausted.votes.pp(2)
},
'loss_fraction': {
'transfers': result.loss_fraction.transfers.pp(2),
'votes': result.loss_fraction.votes.pp(2)
},
'total': result.total.pp(2),
'quota': result.quota.pp(2)
}});
}
}
}