forked from yvv/decision
Fusion de chantier/acte-certification (lots H et S) dans le lot V : le tampon et ses états, avec le quorum et les Propositions seed
- conflits résolus des deux côtés : kept_params garde le quorum (S) et la part simulée, la version déplacée, le cran d'avant (V) ; proposals.rs garde seedMinimal / seedProposal (S) et tallyPending / tallySimulated / myVoteState (V) ; - simulation::reexamine juge sur le quorum gardé par l'adoption (params.quorum, à défaut celui de l'article) ; - l'acte répété n'examine plus une adoption qui tient (params.reexamined) ; - tests V repris sans texte en vigueur au départ (I1, E1 : la Proposition seed) et sur un quorum 2 (small_web) ; le test overview d'une personne invitée dans Monnaie libre suit la simulation (elle vote, chaîne fermée). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,12 @@
|
||||
//! its threshold, it **returns among the proposals** and the version it had
|
||||
//! displaced comes back into force (a removed text comes back, a level of
|
||||
//! inertia goes back, the order and the title of before apply again); its
|
||||
//! adoption is void. At or above, it stays.
|
||||
//! adoption is void. At or above, it stays, and its adoption says so
|
||||
//! (`params.reexamined`): the act run again examines it no more.
|
||||
//!
|
||||
//! Told only (no `--apply`), the re-examination sets the simulated votes apart
|
||||
//! without removing them: an entry that would return only once a more recent one
|
||||
//! returned before it is told as no longer in effect.
|
||||
|
||||
use crate::AppState;
|
||||
use crate::adoption;
|
||||
@@ -141,7 +146,8 @@ pub async fn discard(state: &AppState, apply: bool) -> AppResult<Discarded> {
|
||||
for a in adoptions {
|
||||
let params: Value = serde_json::from_str(&a.params).unwrap_or(Value::Null);
|
||||
let simulated = tally_of(¶ms["simulated"]);
|
||||
if simulated.cast() == 0 {
|
||||
// Without simulated votes, or examined by an act already: nothing to examine.
|
||||
if simulated.cast() == 0 || !params["reexamined"].is_null() {
|
||||
continue;
|
||||
}
|
||||
if let Some(r) = reexamine(state, &a, ¶ms, simulated, apply).await? {
|
||||
@@ -164,14 +170,19 @@ async fn reexamine(
|
||||
let in_effect = match a.kind.as_str() {
|
||||
"remove" => p.status == "applied" && unit.in_force_id.is_none(),
|
||||
"inertia" => {
|
||||
p.status == "applied" && p.inertia_target.as_deref().and_then(InertiaLevel::parse) == Some(docs::inertia_of(unit))
|
||||
p.status == "applied"
|
||||
&& p.inertia_target.as_deref().and_then(InertiaLevel::parse) == Some(docs::inertia_of(unit))
|
||||
}
|
||||
_ => unit.in_force_id.as_deref() == Some(p.id.as_str()),
|
||||
};
|
||||
// Applied: the simulated votes are gone. Told only: they still count, set them apart.
|
||||
let proven = if apply { st.tally(&p.id) } else { minus(st.tally(&p.id), st.simulated_counted(&p.id)) };
|
||||
let level = serde_json::from_value::<InertiaLevel>(params["level"].clone()).unwrap_or_else(|_| st.voting_level(unit, &p));
|
||||
let eval = st.scale().evaluate(proven, level).ok();
|
||||
// At the level and on the quorum it was voted at (ADR 0013; an adoption of before
|
||||
// holds the C of before, `constant`, which is no quorum: the article's quorum now).
|
||||
let level =
|
||||
serde_json::from_value::<InertiaLevel>(params["level"].clone()).unwrap_or_else(|_| st.voting_level(unit, &p));
|
||||
let quorum = params["quorum"].as_u64().and_then(|q| u32::try_from(q).ok()).unwrap_or_else(|| st.quorum_of(unit));
|
||||
let eval = st.scale().evaluate(proven, level, quorum).ok();
|
||||
let holds = eval.is_some_and(|e| e.reached);
|
||||
let displaced = params["displaced"].as_str().map(str::to_owned);
|
||||
let mut r = Reexamined {
|
||||
@@ -196,6 +207,15 @@ async fn reexamine(
|
||||
if apply && in_effect && !holds {
|
||||
give_back(state, &st, unit, &p, a, params, displaced.as_deref()).await?;
|
||||
r.returned = true;
|
||||
} else if apply {
|
||||
// It stays (or something else took its place since): examined once, never again.
|
||||
let mut kept = params.clone();
|
||||
kept["reexamined"] = serde_json::json!({ "at": util::now(), "proven": r.proven, "required": r.required });
|
||||
sqlx::query("UPDATE adoptions SET params = ? WHERE id = ?")
|
||||
.bind(kept.to_string())
|
||||
.bind(a.id)
|
||||
.execute(&state.db)
|
||||
.await?;
|
||||
}
|
||||
Ok(Some(r))
|
||||
}
|
||||
@@ -225,7 +245,11 @@ async fn give_back(
|
||||
.await?;
|
||||
if a.kind == "inertia" {
|
||||
let from = serde_json::from_value::<InertiaLevel>(params["from_inertia"].clone()).unwrap_or_default();
|
||||
sqlx::query("UPDATE units SET inertia = ? WHERE id = ?").bind(from.as_db()).bind(&unit.id).execute(&mut *tx).await?;
|
||||
sqlx::query("UPDATE units SET inertia = ? WHERE id = ?")
|
||||
.bind(from.as_db())
|
||||
.bind(&unit.id)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
sqlx::query("DELETE FROM inertia_changes WHERE proposal_id = ? AND cause = 'vote'")
|
||||
.bind(&p.id)
|
||||
.execute(&mut *tx)
|
||||
|
||||
Reference in New Issue
Block a user