Source: compute/voteCasters/score/castScore.js

  1. /** @module */
  2. import seedrandom from 'seedrandom'
  3. import castScoreGrid from './castScoreGrid.js'
  4. // The main difference between this and plurality is we need to return a grid from here.
  5. // We also will return a set of votes from that grid.
  6. /**
  7. * Voters cast votes for candidates.
  8. * @param {object} geometry - geometry for casting votes
  9. * @param {object[]} geometry.canPoints - For 2D, an array of arrays: [x,y].
  10. * For 1D, an array of numbers: x.
  11. * @param {object[]} geometry.voterGeoms - For 2D, an array of objects: {x,y,w}.
  12. * For 1D, an array of objects: {x,w,densityProfile}.
  13. * @param {object} geometry.parties
  14. * @param {object} geometry.strategySeed
  15. * @param {object} geometry.voterStrategyList
  16. * @param {object} castOptions - options for how to cast votes.
  17. * @returns {object} votes
  18. */
  19. export default function castScore(geometry, castOptions) {
  20. const { canPoints, voterGeoms, parties, strategySeed, voterStrategyList } = geometry
  21. const { verbosity } = castOptions
  22. // get fraction of votes for each candidate so we can summarize results
  23. const n = canPoints.length
  24. const votesByGeom = []
  25. const scoreSumByCan = (new Array(n)).fill(0)
  26. let totalVotes = 0
  27. const strategyRngs = [seedrandom(`green${strategySeed}`), seedrandom(`orange${strategySeed}`)]
  28. for (let i = 0; i < voterGeoms.length; i++) {
  29. const voterGeom = voterGeoms[i]
  30. const voterStrategy = voterStrategyList[i]
  31. const votesForGeom = castScoreGrid(voterGeom, geometry, castOptions, strategyRngs, voterStrategy)
  32. votesByGeom[i] = votesForGeom
  33. const { totalVotes: totalVotesForGeom,
  34. scoreSumByCan: scoreSumByCanForGeom } = votesForGeom
  35. for (let k = 0; k < n; k++) {
  36. scoreSumByCan[k] += scoreSumByCanForGeom[k]
  37. }
  38. totalVotes += totalVotesForGeom
  39. }
  40. const maxScore = 1
  41. const scoreFractionAverageByCan = scoreSumByCan.map((x) => x / (totalVotes * maxScore))
  42. const candidateTallies = { scoreFractionAverageByCan }
  43. const numCans = canPoints.length
  44. const votes = { candidateTallies, parties, numCans }
  45. if (verbosity < 2) return votes
  46. votes.votesByGeom = votesByGeom
  47. return votes
  48. }