add popular vote to EC elections. TODO: add turnout counts to all other elections

This commit is contained in:
Elijah R 2024-06-18 22:57:55 -04:00
parent e8183499c6
commit e7d63c3279
4 changed files with 123 additions and 75 deletions

View file

@ -3,13 +3,4 @@ enum VoteType {
Popular,
}
export function VoteTypeString(voteType: VoteType) {
switch (voteType) {
case VoteType.Electoral:
return "Electoral Votes";
case VoteType.Popular:
return "Votes";
}
}
export default VoteType;

View file

@ -26,378 +26,432 @@ const Presidential_2024 = {
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 2323282
},
"AK": {
electoralVotes: 3,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 359530
},
"AZ": {
electoralVotes: 11,
odds: {
"Republican": 0.5,
"Democratic": 0.5,
}
},
population: 3387326
},
"AR": {
electoralVotes: 6,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 1219069
},
"CA": {
electoralVotes: 54,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 17501380
},
"CO": {
electoralVotes: 10,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 3256980
},
"CT": {
electoralVotes: 7,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 3256980
},
"DE": {
electoralVotes: 3,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 504346
},
"DC": {
electoralVotes: 3,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 344356
},
"FL": {
electoralVotes: 30,
odds: {
"Republican": 0.6,
"Democratic": 0.4,
}
},
population: 11067456
},
"GA": {
electoralVotes: 16,
odds: {
"Republican": 0.5,
"Democratic": 0.5,
}
},
population: 4999960,
},
"HI": {
electoralVotes: 4,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 574469
},
"ID": {
electoralVotes: 4,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 867934
},
"IL": {
electoralVotes: 19,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 6033744
},
"IN": {
electoralVotes: 11,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 3033210
},
"IA": {
electoralVotes: 6,
odds: {
"Republican": 0.8,
"Democratic": 0.2,
}
},
population: 1690871
},
"KS": {
electoralVotes: 6,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 1373986
},
"KY": {
electoralVotes: 8,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 1373986
},
"LA": {
electoralVotes: 8,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 2148062
},
"ME": {
electoralVotes: 2,
odds: {
"Republican": 0.2,
"Democratic": 0.8,
}
},
population: 819461
},
"ME-01": {
electoralVotes: 1,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 443286
},
"ME-02": {
electoralVotes: 1,
odds: {
"Republican": 0.8,
"Democratic": 0.2,
}
},
population: 376349
},
"MD": {
electoralVotes: 10,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 3037030
},
"MA": {
electoralVotes: 11,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 3631402
},
"MI": {
electoralVotes: 15,
odds: {
"Republican": 0.5,
"Democratic": 0.5,
}
},
population: 5539302
},
"MN": {
electoralVotes: 10,
odds: {
"Republican": 0.4,
"Democratic": 0.6,
}
},
population: 3277171
},
"MS": {
electoralVotes: 6,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
popultion: 1313759
},
"MO": {
electoralVotes: 10,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 3025962
},
"MT": {
electoralVotes: 4,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 603674
},
"NE": {
electoralVotes: 4,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 956383
},
"NE-02": {
electoralVotes: 1,
odds: {
"Republican": 0.55,
"Democratic": 0.45,
}
},
population: 339666
},
"NV": {
electoralVotes: 6,
odds: {
"Republican": 0.5,
"Democratic": 0.5,
}
},
population: 1405376
},
"NH": {
electoralVotes: 4,
odds: {
"Republican": 0.4,
"Democratic": 0.6,
}
},
population: 806205
},
"NJ": {
electoralVotes: 14,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 4549457
},
"NM": {
electoralVotes: 5,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 923965
},
"NY": {
electoralVotes: 28,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 8616861
},
"NC": {
electoralVotes: 16,
odds: {
"Republican": 0.55,
"Democratic": 0.45,
}
},
population: 5524804
},
"ND": {
electoralVotes: 3,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 362024
},
"OH": {
electoralVotes: 17,
odds: {
"Republican": 0.8,
"Democratic": 0.2,
}
},
population: 5922202
},
"OK": {
electoralVotes: 7,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 1560699
},
"OR": {
electoralVotes: 8,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 2374321
},
"PA": {
electoralVotes: 19,
odds: {
"Republican": 0.5,
"Democratic": 0.5,
}
},
population: 6936976
},
"RI": {
electoralVotes: 4,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 517757
},
"SC": {
electoralVotes: 9,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 2513329
},
"SD": {
electoralVotes: 3,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 422609
},
"TN": {
electoralVotes: 11,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 3053851
},
"TX": {
electoralVotes: 40,
odds: {
"Republican": 0.8,
"Democratic": 0.2,
}
},
population: 11315056
},
"UT": {
electoralVotes: 6,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 1488289
},
"VT": {
electoralVotes: 3,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 367428
},
"VA": {
electoralVotes: 13,
odds: {
"Republican": 0.2,
"Democratic": 0.8,
}
},
population: 4460524
},
"WA": {
electoralVotes: 12,
odds: {
"Republican": 0,
"Democratic": 1,
}
},
population: 4087631
},
"WV": {
electoralVotes: 4,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 794731
},
"WI": {
electoralVotes: 10,
odds: {
"Republican": 0.5,
"Democratic": 0.5,
}
},
population: 3298041
},
"WY": {
electoralVotes: 3,
odds: {
"Republican": 1,
"Democratic": 0,
}
},
population: 276765
}
}
}

View file

@ -5,7 +5,7 @@ import {MakePrediction} from "./predictor.js";
import Election from "./election.js";
import Presidential_2024 from "./elections/2024.js";
import Elections from "./elections/elections.js";
import VoteType, { VoteTypeString } from "./VoteType.js";
import VoteType from "./VoteType.js";
const configraw = fs.readFileSync("config.json", "utf-8");
const config = JSON.parse(configraw);
@ -101,7 +101,7 @@ if (!config.token) {
.addFields(result.candidates.map(c => {
return {
name: `${(result.winner === c.name ? ":white_check_mark:" : "")} ${c.name} (${c.party})`,
value: `${c.votes} ${VoteTypeString(election.voteType)}${election.voteType === VoteType.Popular ? ` (${((c.votes / result.totalVotes) * 100).toFixed(2)}%)` : ""}`,
value: `${election.voteType === VoteType.Electoral ? `${c.electoralVotes} Electoral Votes, ` : ""}${c.votes} votes (${((c.votes / result.totalVotes) * 100).toFixed(2)}%)`,
inline: true
}
}))

View file

@ -18,23 +18,22 @@ export function MakePrediction(election : Election) : Promise<Prediction> {
name: candidate.name,
party: candidate.party,
votes: 0,
electoralVotes: 0,
});
}
for (const state of Object.keys(election.states)) {
if (election.states[state].population === undefined) election.states[state].population = 1000;
if (Object.keys(election.states[state].odds).every(p => election.states[state].odds[p] <= 0))
for (const candidate of election.candidates)
election.states[state].odds[candidate.party] = 1;
var winner = "";
var votes = await getVotes(election.states[state].population!, election.states[state].odds);
var winner = Object.keys(votes).sort((a, b) => votes[b] - votes[a])[0];
if (election.voteType === VoteType.Electoral) {
winner = await weightedRand(election.states[state].odds);
pred.candidates.find((c : any) => c.party === winner).votes += election.states[state].electoralVotes;
} else if (election.voteType === VoteType.Popular) {
var votes = await getVotes(election.states[state].population!, election.states[state].odds);
winner = Object.keys(votes).sort((a, b) => votes[b] - votes[a])[0];
for (const candidate of election.candidates) {
pred.candidates.find((c : any) => c.party === candidate.party).votes += votes[candidate.party];
}
pred.candidates.find((c : any) => c.party === winner).electoralVotes += election.states[state].electoralVotes;
}
for (const candidate of election.candidates) {
pred.candidates.find((c : any) => c.party === candidate.party).votes += votes[candidate.party];
}
// @ts-ignore
draw.find(`#${state}`).fill(election.candidates.find((c : any) => c.party === winner).color);
@ -42,7 +41,10 @@ export function MakePrediction(election : Election) : Promise<Prediction> {
var s = sharp(Buffer.from(draw.svg()));
var png = await s.png().toBuffer();
pred.winner = pred.candidates.sort((a : any, b : any) => b.votes - a.votes)[0].name;
if (election.voteType === VoteType.Electoral)
pred.winner = pred.candidates.sort((a : any, b : any) => b.electoralVotes - a.electoralVotes)[0].name;
else if (election.voteType === VoteType.Popular)
pred.winner = pred.candidates.sort((a : any, b : any) => b.votes - a.votes)[0].name;
pred.totalVotes = pred.candidates.reduce((a : any, b : any) => a + b.votes, 0);
pred.svg = draw.svg();
pred.png = png;
@ -55,6 +57,7 @@ export interface Prediction {
candidates : {
name : string,
party : string,
electoralVotes : number,
votes : number,
}[],
winner: string,