USRSE / USRSE/usrse.github.io

feat(elections): STV tabulation engine with test fixtures

Open
#1,944 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
HTML
Stars
33
Forks
104
Avg merge
12h 3m
Merged PRs (30d)
10

Description

Summary

Implement a Single Transferable Vote tabulation engine that elects multiple winners using the Droop quota and surplus transfer.

Part of #1933.

Requirements

  • Pure function: `tabulateSTV(ballots, candidates, seats) → { rounds[], winners[], exhaustedBallots }`
  • Compute Droop quota: `floor(validBallots / (seats + 1)) + 1`
  • Elect any candidate reaching quota; transfer surplus using a documented method (Meek, Gregory, or Weighted Inclusive Gregory — pick and document one)
  • When no candidate reaches quota, eliminate lowest and redistribute
  • Handle tie-breaks deterministically (same rule as IRV)
  • Handle exhausted ballots explicitly
  • Stop when all seats filled, or when remaining candidates ≤ remaining seats (auto-elect)
  • Document the chosen surplus-transfer method in code comments AND in `docs/elections/tabulation.md`
  • Golden fixture tests with hand-calculated multi-seat elections
  • Tabulation runs server-side only

Context

  • Epic: #1933
  • Depends on schema issue
  • STV handles multi-seat races (board elections)
  • IRV issue: see sibling issue

Implementation notes

  • Start with Weighted Inclusive Gregory (WIG) — simpler to explain publicly than Meek, widely used (e.g., Scottish local elections)
  • Same `packages/tabulation/` package as IRV
  • Compare against a reference (e.g., OpenSTV) for at least 3 test cases

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the packages/tabulation/ package and read the IRV sibling issue and the schema issue first. Define the server-side STV API, then add hand-calculated golden fixtures and compare at least three cases with OpenSTV. Done means deterministic quota, transfers, eliminations, exhaustion, auto-election, and documented WIG behavior in code and docs/elections/tabulation.md.

Written by the indexing model from the issue text.

Assessment

Domain
backend, documentation, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.