///|
pub fn run_json(request : String) -> String {
try {
guard request.length() <= 3000000 else {
raise Limit("request exceeds 3000000 UTF-16 units")
}
let o = obj(@json.parse(request))
let ballots = arr(required(o, "ballots")).map(v => {
let b = obj(v)
{
weight: num(required(b, "weight")),
ranking: arr(required(b, "ranking")).map(group => arr(group).map(txt)),
}
})
let e = election(arr(required(o, "candidates")).map(txt), ballots)
let algorithm = txt(o.get("method").unwrap_or(Json::string("audit")))
let result = match algorithm {
"schulze" => @json.to_json(e.schulze())
"ranked_pairs" => @json.to_json(e.ranked_pairs())
"irv" =>
@json.to_json(
e.irv(arr(o.get("tie_order").unwrap_or(Json::array([]))).map(txt)),
)
"irv_possible" =>
@json.to_json(
e.irv_possibilities(num(o.get("max_states").unwrap_or(jn(65535)))),
)
"audit" =>
jo([
("schulze", @json.to_json(e.schulze())),
("ranked_pairs", @json.to_json(e.ranked_pairs())),
])
_ => raise Invalid("unknown method")
}
jo([
("ok", Json::boolean(true)),
("candidates", @json.to_json(e.candidates())),
("total_weight", jn(e.total_weight())),
("pairwise", @json.to_json(e.pairwise())),
("condorcet", @json.to_json(e.condorcet())),
("result", result),
]).stringify()
} catch {
e => {
let (code, message) = match e {
TallyError::Invalid(s) => ("invalid", s)
TallyError::Limit(s) => ("limit", s)
_ => ("json", "invalid JSON request")
}
jo([
("ok", Json::boolean(false)),
("code", Json::string(code)),
("error", Json::string(message)),
]).stringify()
}
}
}