From dba7e562c4f2b26660acc421e752b609388697bb Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Tue, 7 Apr 2026 20:33:00 -0500 Subject: [PATCH] =?UTF-8?q?fix:=20address=20PR=20review=20=E2=80=94=20vari?= =?UTF-8?q?ant=20hash=20snippet=20and=20scaling=20denominator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - compute_variant_hash: use refractor_tier key, json.dumps with sort_keys instead of str(), add variant=0 remapping guard - Section 5.3.1 step 3: scaling denominator is total_requested_addition, not total_requested_reduction Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/prd-evolution/05-rating-boosts.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/prd-evolution/05-rating-boosts.md b/docs/prd-evolution/05-rating-boosts.md index 2af0e1d..d655302 100644 --- a/docs/prd-evolution/05-rating-boosts.md +++ b/docs/prd-evolution/05-rating-boosts.md @@ -122,7 +122,7 @@ proportionally so the 108-sum invariant is always preserved. Specifically: 1. Negative deltas are applied first, each capped at the column's current value (0 floor). 2. The total amount actually reduced is computed. -3. Positive deltas are scaled by `actually_reduced / total_requested_reduction` so that +3. Positive deltas are scaled by `actually_reduced / total_requested_addition` so that additions always equal reductions. 4. A warning is logged when truncation occurs. @@ -230,18 +230,19 @@ are currently always 0. The evolution system uses variant to store evolved versi variant number derived from a **deterministic hash** of all inputs that affect the card: ```python -import hashlib +import hashlib, json -def compute_variant_hash(player_id: int, evolution_tier: int, +def compute_variant_hash(player_id: int, refractor_tier: int, cosmetics: list[str] | None) -> int: - """Compute a stable variant number from evolution + cosmetic state.""" + """Compute a stable variant number from refractor + cosmetic state.""" inputs = { "player_id": player_id, - "evolution_tier": evolution_tier, + "refractor_tier": refractor_tier, "cosmetics": sorted(cosmetics or []), } - raw = hashlib.sha256(str(inputs).encode()).hexdigest() - return int(raw[:8], 16) # 32-bit unsigned integer from first 8 hex chars + raw = hashlib.sha256(json.dumps(inputs, sort_keys=True).encode()).hexdigest() + result = int(raw[:8], 16) # 32-bit unsigned integer from first 8 hex chars + return result if result != 0 else 1 # variant=0 is reserved for base cards ``` - `variant = 0`: Base card (standard, shared across all teams)