Source: compute/voteCasters/score/castScore.js

/** @module */

import seedrandom from 'seedrandom'
import castScoreGrid from './castScoreGrid.js'

// The main difference between this and plurality is we need to return a grid from here.
// We also will return a set of votes from that grid.

/**
 * Voters cast votes for candidates.
 * @param {object} geometry - geometry for casting votes
 * @param {object[]} geometry.canPoints - For 2D, an array of arrays: [x,y].
 * For 1D, an array of numbers: x.
 * @param {object[]} geometry.voterGeoms - For 2D, an array of objects: {x,y,w}.
 * For 1D, an array of objects: {x,w,densityProfile}.
 * @param {object} geometry.parties
 * @param {object} geometry.strategySeed
 * @param {object} geometry.voterStrategyList
 * @param {object} castOptions - options for how to cast votes.
 * @returns {object} votes
 */
export default function castScore(geometry, castOptions) {
    const { canPoints, voterGeoms, parties, strategySeed, voterStrategyList } = geometry
    const { verbosity } = castOptions

    // get fraction of votes for each candidate so we can summarize results
    const n = canPoints.length
    const votesByGeom = []
    const scoreSumByCan = (new Array(n)).fill(0)
    let totalVotes = 0
    const strategyRngs = [seedrandom(`green${strategySeed}`), seedrandom(`orange${strategySeed}`)]
    for (let i = 0; i < voterGeoms.length; i++) {
        const voterGeom = voterGeoms[i]
        const voterStrategy = voterStrategyList[i]

        const votesForGeom = castScoreGrid(voterGeom, geometry, castOptions, strategyRngs, voterStrategy)
        votesByGeom[i] = votesForGeom
        const { totalVotes: totalVotesForGeom,
            scoreSumByCan: scoreSumByCanForGeom } = votesForGeom

        for (let k = 0; k < n; k++) {
            scoreSumByCan[k] += scoreSumByCanForGeom[k]
        }
        totalVotes += totalVotesForGeom
    }
    const maxScore = 1
    const scoreFractionAverageByCan = scoreSumByCan.map((x) => x / (totalVotes * maxScore))

    const candidateTallies = { scoreFractionAverageByCan }
    const numCans = canPoints.length
    const votes = { candidateTallies, parties, numCans }
    if (verbosity < 2) return votes

    votes.votesByGeom = votesByGeom
    return votes
}