Implement constraints in web UI
This commit is contained in:
parent
38eef74e77
commit
1d4036c19e
|
@ -139,12 +139,12 @@
|
|||
<input type="text" id="txtSeed" value="">
|
||||
</label>
|
||||
</div>
|
||||
<!--<div class="subheading">
|
||||
<div class="subheading">
|
||||
Constraints:
|
||||
</div>
|
||||
<div>
|
||||
<input type="file" id="conFile">
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 cols-12" style="align-self: start;">
|
||||
<div class="col-12 subheading">
|
||||
|
|
|
@ -90,11 +90,22 @@ async function clickCount() {
|
|||
}
|
||||
|
||||
// Read BLT file
|
||||
let filePath = document.getElementById('bltFile').value;
|
||||
filePath = filePath.substring(Math.max(filePath.lastIndexOf('\\'), filePath.lastIndexOf('/')) + 1);
|
||||
let bltPath = document.getElementById('bltFile').value;
|
||||
bltPath = bltPath.substring(Math.max(bltPath.lastIndexOf('\\'), bltPath.lastIndexOf('/')) + 1);
|
||||
|
||||
let bltFile = document.getElementById('bltFile').files[0];
|
||||
let electionData = await bltFile.text();
|
||||
let bltData = await bltFile.text();
|
||||
|
||||
// Read CON file (if applicable)
|
||||
let conPath = null;
|
||||
let conData = null;
|
||||
if (document.getElementById('conFile').files.length > 0) {
|
||||
conPath = document.getElementById('conFile').value;
|
||||
conPath = conPath.substring(Math.max(conPath.lastIndexOf('\\'), conPath.lastIndexOf('/')) + 1);
|
||||
|
||||
let conFile = document.getElementById('conFile').files[0];
|
||||
conData = await conFile.text();
|
||||
}
|
||||
|
||||
// Init STV options
|
||||
let optsStr = [
|
||||
|
@ -127,9 +138,11 @@ async function clickCount() {
|
|||
// Dispatch to worker
|
||||
worker.postMessage({
|
||||
'type': 'countElection',
|
||||
'electionData': electionData,
|
||||
'bltData': bltData,
|
||||
'conData': conData,
|
||||
'optsStr': optsStr,
|
||||
'filePath': filePath,
|
||||
'bltPath': bltPath,
|
||||
'conPath': conPath,
|
||||
'numbers': document.getElementById('selNumbers').value,
|
||||
'decimals': document.getElementById('txtDP').value,
|
||||
'normaliseBallots': document.getElementById('chkNormaliseBallots').checked,
|
||||
|
|
|
@ -27,12 +27,17 @@ onmessage = function(evt) {
|
|||
}
|
||||
|
||||
// Init election
|
||||
election = wasm['election_from_blt_' + numbers](evt.data.electionData);
|
||||
election = wasm['election_from_blt_' + numbers](evt.data.bltData);
|
||||
|
||||
if (evt.data.normaliseBallots) {
|
||||
wasm['election_normalise_ballots_' + numbers](election);
|
||||
}
|
||||
|
||||
// Init constraints if applicable
|
||||
if (evt.data.conData) {
|
||||
wasm['election_load_constraints_' + numbers](election, evt.data.conData);
|
||||
}
|
||||
|
||||
// Init STV options
|
||||
opts = wasm.STVOptions.new.apply(null, evt.data.optsStr);
|
||||
|
||||
|
@ -40,7 +45,7 @@ onmessage = function(evt) {
|
|||
opts.validate();
|
||||
|
||||
// Describe count
|
||||
postMessage({'type': 'describeCount', 'content': wasm['describe_count_' + numbers](evt.data.filePath, election, opts)});
|
||||
postMessage({'type': 'describeCount', 'content': wasm['describe_count_' + numbers](evt.data.bltPath, election, opts)});
|
||||
|
||||
// Init results table
|
||||
postMessage({'type': 'initResultsTable', 'content': wasm['init_results_table_' + numbers](election, opts)});
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#![allow(rustdoc::private_intra_doc_links)]
|
||||
|
||||
use crate::constraints::Constraints;
|
||||
use crate::election::{CandidateState, CountState, Election};
|
||||
use crate::numbers::{Fixed, GuardedFixed, NativeFloat64, Number, Rational};
|
||||
use crate::stv;
|
||||
|
@ -66,6 +67,13 @@ macro_rules! impl_type {
|
|||
election.0.normalise_ballots();
|
||||
}
|
||||
|
||||
/// Call [Constraints::from_con] and set [Election::constraints]
|
||||
#[wasm_bindgen]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn [<election_load_constraints_$type>](election: &mut [<Election$type>], text: String) {
|
||||
election.0.constraints = Some(Constraints::from_con(text.lines().map(|s| s.to_string()).into_iter()));
|
||||
}
|
||||
|
||||
/// Wrapper for [stv::count_init]
|
||||
#[wasm_bindgen]
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -303,22 +311,31 @@ fn update_results_table<N: Number>(stage_num: usize, state: &CountState<N>, opts
|
|||
result.push(&format!(r#"<td{}>{}</td>"#, tdclasses1, state.title).into());
|
||||
for candidate in state.election.candidates.iter() {
|
||||
let count_card = state.candidates.get(candidate).unwrap();
|
||||
if count_card.state == stv::CandidateState::Elected {
|
||||
result.push(&format!(r#"<td class="{}count elected">{}</td>"#, tdclasses2, pp(&count_card.transfers, opts.pp_decimals)).into());
|
||||
result.push(&format!(r#"<td class="{}count elected">{}</td>"#, tdclasses2, pp(&count_card.votes, opts.pp_decimals)).into());
|
||||
} else if count_card.state == stv::CandidateState::Excluded {
|
||||
result.push(&format!(r#"<td class="{}count excluded">{}</td>"#, tdclasses2, pp(&count_card.transfers, opts.pp_decimals)).into());
|
||||
if count_card.votes.is_zero() {
|
||||
result.push(&format!(r#"<td class="{}count excluded">Ex</td>"#, tdclasses2).into());
|
||||
} else {
|
||||
match count_card.state {
|
||||
CandidateState::Hopeful | CandidateState::Guarded => {
|
||||
result.push(&format!(r#"<td class="{}count">{}</td>"#, tdclasses2, pp(&count_card.transfers, opts.pp_decimals)).into());
|
||||
result.push(&format!(r#"<td class="{}count">{}</td>"#, tdclasses2, pp(&count_card.votes, opts.pp_decimals)).into());
|
||||
}
|
||||
CandidateState::Elected => {
|
||||
result.push(&format!(r#"<td class="{}count elected">{}</td>"#, tdclasses2, pp(&count_card.transfers, opts.pp_decimals)).into());
|
||||
result.push(&format!(r#"<td class="{}count elected">{}</td>"#, tdclasses2, pp(&count_card.votes, opts.pp_decimals)).into());
|
||||
}
|
||||
CandidateState::Doomed => {
|
||||
result.push(&format!(r#"<td class="{}count excluded">{}</td>"#, tdclasses2, pp(&count_card.transfers, opts.pp_decimals)).into());
|
||||
result.push(&format!(r#"<td class="{}count excluded">{}</td>"#, tdclasses2, pp(&count_card.votes, opts.pp_decimals)).into());
|
||||
}
|
||||
} else if count_card.state == stv::CandidateState::Withdrawn {
|
||||
result.push(&format!(r#"<td class="{}count excluded"></td>"#, tdclasses2).into());
|
||||
result.push(&format!(r#"<td class="{}count excluded">WD</td>"#, tdclasses2).into());
|
||||
} else {
|
||||
result.push(&format!(r#"<td class="{}count">{}</td>"#, tdclasses2, pp(&count_card.transfers, opts.pp_decimals)).into());
|
||||
result.push(&format!(r#"<td class="{}count">{}</td>"#, tdclasses2, pp(&count_card.votes, opts.pp_decimals)).into());
|
||||
CandidateState::Withdrawn => {
|
||||
result.push(&format!(r#"<td class="{}count excluded"></td>"#, tdclasses2).into());
|
||||
result.push(&format!(r#"<td class="{}count excluded">WD</td>"#, tdclasses2).into());
|
||||
}
|
||||
CandidateState::Excluded => {
|
||||
result.push(&format!(r#"<td class="{}count excluded">{}</td>"#, tdclasses2, pp(&count_card.transfers, opts.pp_decimals)).into());
|
||||
if count_card.votes.is_zero() {
|
||||
result.push(&format!(r#"<td class="{}count excluded">Ex</td>"#, tdclasses2).into());
|
||||
} else {
|
||||
result.push(&format!(r#"<td class="{}count excluded">{}</td>"#, tdclasses2, pp(&count_card.votes, opts.pp_decimals)).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.push(&format!(r#"<td class="{}count">{}</td>"#, tdclasses2, pp(&state.exhausted.transfers, opts.pp_decimals)).into());
|
||||
|
|
Loading…
Reference in New Issue