last changed 10/19/2025
enum class SocialChoiceFunction { PLURALITY, APPROVAL, SUPERMAJORITY, IRV }
class ContestInfo(
    val name: String,
    val id: Int,
    val candidateNames: Map<String, Int>,       // candidate name -> candidate id
    val choiceFunction: SocialChoiceFunction,   // electionguard has "VoteVariationType"
    val nwinners: Int = 1,                      // aka "numberElected"
    val voteForN: Int = nwinners,               // aka "contestSelectionLimit" or "optionSelectionLimit"
    val minFraction: Double? = null,            // supermajority only.
)
class Contest(
        val info: ContestInfo,
        val votes: Map<Int, Int>,   // candidateId -> nvotes
        val Nc: Int,                // trusted maximum ballots/cards that contain this contest
        val Ncast: Int,             // number of cast ballots containing this Contest, including undervotes
        val winners: List<Int>,
    )
    
class RaireContest(
    val info: ContestInfo,
    val winners: List<Int>,
    val Nc: Int,
    val Ncast: Int,
    val undervotes: Int,
)
data class AuditableCard (
    val location: String, // info to find the card for a manual audit. Aka ballot identifier.
    val index: Int,  // index into the original, canonical list of cards
    val prn: Long,   // psuedo random number
    val phantom: Boolean,
    val contests: IntArray, // list of contests on this ballot. optional when !hasStyle
    val votes: List<IntArray>?, // for each contest, an array of the candidate ids voted for; for IRV, ranked first to last; missing for pooled data
    val poolId: Int?, // for OneAudit
)
data class Cvr(
    val id: String, // ballot identifier
    val votes: Map<Int, IntArray>, // contest -> list of candidates voted for; for IRV, ranked first to last
    val phantom: Boolean = false,
    val poolId: Int? = null,
)
For non-IRV contests:
For IRV contests:
For each audit round, for each contest, verify that the cards selected for auditing have the smallest PRN.