- crates/ld-engine : formule inertielle (parité avec la maquette, garde C), coquille / changement de fond, assistant d'édition à règles, composition d'un document sous vote permanent (adoptions, aperçus, rivales). - crates/trustin-access : qui voit, qui ouvre, qui gère les accès. - crates/ld-server : API axum + SQLite, connexion Ğ1 (client OAuth2 de connect.monnaie-libre.fr), invitations, entrée en vigueur automatique, signalements de contradiction, traductions éditoriales, publication git, taille de la toile lue sur la chaîne. - seeds/acte-engagement-certification.json : 33 articles, fr + en + es ; en vigueur : préambule, E1, E2 (seed a minima). - maquette/ : frontend, backend et docker v2 déplacés tels quels. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
86 lines
2.4 KiB
Python
86 lines
2.4 KiB
Python
"""WoT members threshold formula for binary votes.
|
|
|
|
Core formula:
|
|
Result = C + B^W + (M + (1-M) * (1 - (T/W)^G)) * max(0, T - C)
|
|
|
|
Where:
|
|
C = constant_base
|
|
B = base_exponent
|
|
W = wot_size (corpus of eligible voters)
|
|
T = total_votes (for + against)
|
|
M = majority_ratio (majority_pct / 100)
|
|
G = gradient_exponent
|
|
|
|
Inertia behaviour:
|
|
- Low participation (T << W) -> near-unanimity required
|
|
- High participation (T -> W) -> simple majority M suffices
|
|
|
|
Reference test case:
|
|
wot_size=7224, votes_for=97, votes_against=23 (total=120)
|
|
params M50 B.1 G.2 => threshold=94, adopted (97 >= 94)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
|
|
def wot_threshold(
|
|
wot_size: int,
|
|
total_votes: int,
|
|
majority_pct: int = 50,
|
|
base_exponent: float = 0.1,
|
|
gradient_exponent: float = 0.2,
|
|
constant_base: float = 0.0,
|
|
) -> int:
|
|
"""Compute the minimum number of *for* votes required for adoption.
|
|
|
|
Parameters
|
|
----------
|
|
wot_size:
|
|
Size of the eligible voter corpus (WoT members).
|
|
total_votes:
|
|
Number of votes cast (for + against).
|
|
majority_pct:
|
|
Majority percentage (0-100). 50 = simple majority at full participation.
|
|
base_exponent:
|
|
B in the formula. ``B^W`` contributes a vanishingly small offset
|
|
when W is large (0 < B < 1).
|
|
gradient_exponent:
|
|
G controls how fast the required super-majority decays toward M as
|
|
participation increases.
|
|
constant_base:
|
|
C, a fixed additive floor on the threshold.
|
|
|
|
Returns
|
|
-------
|
|
int
|
|
The ceiling of the computed threshold. A vote passes when
|
|
``votes_for >= wot_threshold(...)``.
|
|
"""
|
|
if wot_size <= 0:
|
|
raise ValueError("wot_size doit etre strictement positif")
|
|
if total_votes < 0:
|
|
raise ValueError("total_votes ne peut pas etre negatif")
|
|
if not (0 <= majority_pct <= 100):
|
|
raise ValueError("majority_pct doit etre entre 0 et 100")
|
|
|
|
C = constant_base
|
|
B = base_exponent
|
|
W = wot_size
|
|
T = total_votes
|
|
M = majority_pct / 100.0
|
|
G = gradient_exponent
|
|
|
|
# Guard: if no votes, threshold is at least ceil(C + B^W)
|
|
if T == 0:
|
|
return math.ceil(C + B ** W)
|
|
|
|
# Core formula
|
|
participation_ratio = T / W
|
|
inertia_factor = 1.0 - participation_ratio ** G
|
|
required_ratio = M + (1.0 - M) * inertia_factor
|
|
result = C + B ** W + required_ratio * max(0.0, T - C)
|
|
|
|
return math.ceil(result)
|