add popular vote to EC elections. TODO: add turnout counts to all other elections
This commit is contained in:
parent
e8183499c6
commit
e7d63c3279
4 changed files with 123 additions and 75 deletions
|
@ -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;
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}))
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue