2024-election-modelling/main.go

140 lines
3.5 KiB
Go
Raw Normal View History

2024-04-13 14:22:28 +00:00
package main
import (
"encoding/csv"
2024-04-13 14:22:28 +00:00
"fmt"
2024-04-13 19:26:18 +00:00
rand "math/rand/v2"
"os"
2024-04-13 15:19:35 +00:00
"strconv"
2024-04-13 19:26:18 +00:00
// "strings"
2024-04-13 14:22:28 +00:00
)
2024-04-13 19:26:18 +00:00
/* Structs */
2024-04-13 18:44:00 +00:00
type State struct {
Name string
Votes int
VictoriousPartyPerElection map[string]string
}
2024-04-13 19:26:18 +00:00
type VotesForEachParty struct {
Democrats int
Republicans int
}
type src = *rand.Rand
/* Globals */
var r = rand.New(rand.NewPCG(uint64(1), uint64(2)))
/* Load data from csvs */
2024-04-13 18:44:00 +00:00
func readStates() ([]State, error) {
var states map[string]State = make(map[string]State)
2024-04-13 15:19:35 +00:00
2024-04-13 18:44:00 +00:00
/* Electoral college votes for the 2024 election*/
2024-04-13 18:55:57 +00:00
votes_file, err := os.Open("data/electoral-college-votes.csv")
if err != nil {
2024-04-13 16:42:13 +00:00
return nil, fmt.Errorf("error opening the votes file: %v", err)
}
2024-04-13 18:55:57 +00:00
defer votes_file.Close()
votes_reader := csv.NewReader(votes_file)
if _, err := votes_reader.Read(); err != nil { // Skip header
2024-04-13 16:42:13 +00:00
return nil, fmt.Errorf("error reading votes header: %v", err)
2024-04-13 15:19:35 +00:00
}
for {
2024-04-13 18:55:57 +00:00
csv_record, err := votes_reader.Read()
if err != nil {
2024-04-13 16:42:13 +00:00
break // EOF or an error
}
2024-04-13 18:55:57 +00:00
votes, err := strconv.Atoi(csv_record[1])
2024-04-13 15:19:35 +00:00
if err != nil {
2024-04-13 16:42:13 +00:00
continue // Error in converting votes, skip this record
2024-04-13 15:19:35 +00:00
}
2024-04-13 18:55:57 +00:00
state := csv_record[0]
2024-04-13 18:44:00 +00:00
if _, exists := states[state]; !exists {
states[state] = State{Name: state, Votes: votes, VictoriousPartyPerElection: make(map[string]string)}
}
}
2024-04-13 16:42:13 +00:00
/* Election results */
var years = []string{"2000", "2004", "2008", "2012", "2016", "2020"}
2024-04-13 16:42:13 +00:00
for _, year := range years {
2024-04-13 18:55:57 +00:00
results_filename := fmt.Sprintf("data/results/%s.csv", year)
results_file, err := os.Open(results_filename)
2024-04-13 16:35:52 +00:00
if err != nil {
2024-04-13 16:42:13 +00:00
return nil, fmt.Errorf("error opening the results file for %s: %v", year, err)
}
2024-04-13 18:55:57 +00:00
defer results_file.Close()
resultsReader := csv.NewReader(results_file)
2024-04-13 16:42:13 +00:00
if _, err := resultsReader.Read(); err != nil { // Skip header
return nil, fmt.Errorf("error reading results header for %s: %v", year, err)
}
for {
record, err := resultsReader.Read()
if err != nil {
break // EOF or an error
}
state, party := record[0], record[1]
2024-04-13 18:44:00 +00:00
data, exists := states[state]
2024-04-13 16:42:13 +00:00
if !exists {
continue // State not found in votes map, skip
}
// Update the party winning in the specific year
data.VictoriousPartyPerElection[year] = party
2024-04-13 18:44:00 +00:00
states[state] = data
2024-04-13 16:35:52 +00:00
}
}
2024-04-13 16:42:13 +00:00
// Convert statesData map to a slice for returning
var states_slice []State
for _, state := range states {
states_slice = append(states_slice, state)
2024-04-13 16:35:52 +00:00
}
return states_slice, nil
2024-04-13 16:35:52 +00:00
}
2024-04-13 18:44:00 +00:00
func sampleFromState(state State) VotesForEachParty {
switch state.Name {
case "Nebraska":
return VotesForEachParty{Democrats: 1, Republicans: 0}
case "Maine":
return VotesForEachParty{Democrats: 1, Republicans: 0}
default:
2024-04-13 19:26:18 +00:00
{
p_republican := 0.0
for _, party := range state.VictoriousPartyPerElection {
if party == "R" {
p_republican++
}
}
p_republican = p_republican / float64(len(state.VictoriousPartyPerElection))
if r.Float64() < p_republican {
return VotesForEachParty{Democrats: 0, Republicans: state.Votes}
} else {
return VotesForEachParty{Democrats: state.Votes, Republicans: 0}
}
}
2024-04-13 18:44:00 +00:00
}
}
2024-04-13 14:22:28 +00:00
func main() {
2024-04-13 18:44:00 +00:00
states, err := readStates()
if err != nil {
fmt.Println("Error:", err)
return
}
for _, state := range states {
2024-04-13 19:26:18 +00:00
fmt.Printf("%s: Votes: %d,\n\tWinners: ", state.Name, state.Votes)
for year, party := range state.VictoriousPartyPerElection {
fmt.Printf("[%s: %s] ", year, party)
2024-04-13 16:35:52 +00:00
}
2024-04-13 19:26:18 +00:00
election_sample := sampleFromState(state)
fmt.Printf("\n\tSample: Democrat seats: %d, Republican seats: %d", election_sample.Democrats, election_sample.Republicans)
fmt.Println()
2024-04-13 16:35:52 +00:00
}
2024-04-13 14:22:28 +00:00
}