From e7d63c3279595cfcd53f9beaf143a130379c004a Mon Sep 17 00:00:00 2001 From: Elijah R Date: Tue, 18 Jun 2024 22:57:55 -0400 Subject: [PATCH] add popular vote to EC elections. TODO: add turnout counts to all other elections --- src/VoteType.ts | 9 --- src/elections/2024.ts | 162 ++++++++++++++++++++++++++++-------------- src/index.ts | 4 +- src/predictor.ts | 23 +++--- 4 files changed, 123 insertions(+), 75 deletions(-) diff --git a/src/VoteType.ts b/src/VoteType.ts index febf2dd..1919775 100644 --- a/src/VoteType.ts +++ b/src/VoteType.ts @@ -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; \ No newline at end of file diff --git a/src/elections/2024.ts b/src/elections/2024.ts index dab8a21..657fb44 100644 --- a/src/elections/2024.ts +++ b/src/elections/2024.ts @@ -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 } } } diff --git a/src/index.ts b/src/index.ts index 81ec061..653ed0b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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 } })) diff --git a/src/predictor.ts b/src/predictor.ts index cebcce5..28aa0f8 100644 --- a/src/predictor.ts +++ b/src/predictor.ts @@ -18,23 +18,22 @@ export function MakePrediction(election : Election) : Promise { 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 { 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,