commit cbda7b1e5c1bbd68ae7263ffc59be4baedca6fa6
parent 212f72f5969e08b058d74f4ed51506b048fbec73
Author: NunoSempere <nuno.semperelh@protonmail.com>
Date: Sun, 14 Apr 2024 21:42:38 -0400
move glue code function to the end
Diffstat:
| M | main.go | | | 356 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
1 file changed, 172 insertions(+), 184 deletions(-)
diff --git a/main.go b/main.go
@@ -34,180 +34,6 @@ type Poll struct {
/* Globals */
var r = rand.New(rand.NewPCG(uint64(100), uint64(2224)))
-var dev = false
-
-/* Load data from csvs */
-func readStates() ([]State, error) {
- var states map[string]State = make(map[string]State)
-
- /* Electoral college votes for the 2024 election*/
- votes_file, err := os.Open("data/num-electors/electoral-college-votes.csv")
- // votes_file, err := os.Open("data/electoral-college-votes-2010-census.csv")
- if err != nil {
- return nil, fmt.Errorf("error opening the votes file: %v", err)
- }
- defer votes_file.Close()
-
- votes_reader := csv.NewReader(votes_file)
- if _, err := votes_reader.Read(); err != nil { // Skip header
- return nil, fmt.Errorf("error reading votes header: %v", err)
- }
- for {
- csv_record, err := votes_reader.Read()
- if err != nil {
- break // EOF or an error
- }
- votes, err := strconv.Atoi(csv_record[1])
- if err != nil {
- continue // Error in converting votes, skip this record
- }
- state := csv_record[0]
- if _, exists := states[state]; !exists {
- states[state] = State{Name: state, Votes: votes, PresidentialElectoralHistory: make(map[string]string)}
- }
- }
-
- /* Election results */
- var years = []string{"2000", "2004", "2008", "2012", "2016", "2020"}
- for _, year := range years {
- electoral_history_filename := fmt.Sprintf("data/electoral-history/%s.csv", year)
- electoral_history_file, err := os.Open(electoral_history_filename)
- if err != nil {
- return nil, fmt.Errorf("error opening the electoral_history file for %s: %v", year, err)
- }
- electoral_history_reader := csv.NewReader(electoral_history_file)
- if _, err := electoral_history_reader.Read(); err != nil { // Skip header
- return nil, fmt.Errorf("error reading electoral_history header for %s: %v", year, err)
- }
- for {
- record, err := electoral_history_reader.Read()
- if err != nil {
- break // EOF or an error
- }
- state, party := record[0], record[1]
- data, exists := states[state]
- if !exists {
- continue // State not found in votes map, skip
- }
- // Update the party winning in the specific year
- data.PresidentialElectoralHistory[year] = party
- states[state] = data
- }
-
- electoral_history_file.Close()
- }
-
- /* Read polls */
- polls_file, err := os.Open("data/polls/president_polls_state.csv") // Make sure to update this path
- if err != nil {
- return nil, fmt.Errorf("error opening the polls file: %v", err)
- }
- defer polls_file.Close()
-
- // Using a temporary map to group poll results by state and poll ID
- state_polls_map := make(map[string]map[string]Poll)
-
- polls_reader := csv.NewReader(polls_file)
- _, err = polls_reader.Read() // Skip the header
- if err != nil {
- return nil, fmt.Errorf("error reading polls header: %v", err)
- }
-
- for {
- record, err := polls_reader.Read()
- if err != nil {
- break // EOF or an error
- }
-
- poll_id := record[0]
- state_name := record[12]
- end_date := record[14]
- partisan := record[32]
- candidate_name := record[44]
-
- date_layout := "1/2/06"
- parsed_date, err := time.Parse(date_layout, end_date)
- if err != nil {
- fmt.Println("Error parsing date: ", err)
- }
-
- sample_size, err := strconv.Atoi(record[22])
- if err != nil {
- continue // If error, skip this record
- }
-
- percentage, err := strconv.ParseFloat(record[47], 64) // percentage is in the 42nd column
- if err != nil {
- fmt.Printf("Error parsing percentage")
- continue // If error, skip this record
- }
-
- if _, exists := state_polls_map[state_name]; !exists {
- state_polls_map[state_name] = make(map[string]Poll)
- }
-
- poll, exists := state_polls_map[state_name][poll_id]
- if !exists {
- poll = Poll{
- PollId: poll_id,
- SampleSize: sample_size,
- PollResults: make(map[string]float64),
- Date: parsed_date,
- Partisan: partisan,
- }
- }
- poll.PollResults[candidate_name] = percentage
- state_polls_map[state_name][poll_id] = poll
- }
-
- // Add the aggregated poll data to the respective states
- for state_name, polls := range state_polls_map {
-
- // Filter polls by recency and by having both Biden and Trump
- var recent_polls []Poll
- for _, poll := range polls {
- if poll.Date.After(time.Now().AddDate(0, 0, -30)) {
- recent_polls = append(recent_polls, poll)
- }
- }
- var recent_biden_trump_polls []Poll
- for _, recent_poll := range recent_polls {
- has_biden := false
- has_trump := false
- for candidate_name, _ := range recent_poll.PollResults {
- if candidate_name == "Biden" {
- has_biden = true
- } else if candidate_name == "Trump" {
- has_trump = true
- }
- }
- if has_biden && has_trump {
- recent_biden_trump_polls = append(recent_biden_trump_polls, recent_poll)
- }
- }
-
- if state, exists := states[state_name]; exists {
- state.Polls = recent_biden_trump_polls
- states[state_name] = state // Not redundant
- } else {
- // fmt.Printf("Encountered new state: %s\n", state_name)
- /*
- states[state_name] = State{
- Name: state_name,
- Polls: polls_slice,
- }
- */
- }
- }
-
- // Convert statesData map to a slice for returning
- var states_slice []State
- for _, state := range states {
- states_slice = append(states_slice, state)
- }
-
- return states_slice, nil
-}
/* Sampling helper functions */
func getNormalCDF(x float64, mean float64, std float64) float64 {
@@ -225,7 +51,6 @@ func getChanceCandidateWinsFromPollShare(candidate_p float64, poll_sample_size f
}
func getChanceRepublicanWinFromPoll(poll Poll, pretty_print bool) float64 {
-
biden_percentage, biden_exists := poll.PollResults["Biden"]
trump_percentage, trump_exists := poll.PollResults["Trump"]
if !biden_exists || !trump_exists {
@@ -249,11 +74,9 @@ func getChanceRepublicanWinFromPoll(poll Poll, pretty_print bool) float64 {
fmt.Printf("\n\t\tPoll says chance of R win: %f", p_republican_win)
}
return p_republican_win
-
}
func getChanceRepublicanWinFromPollPlusUncertainty(poll Poll, state State, pretty_print bool) float64 {
-
// Uncertainty from the state
n_republican_win := 0
for _, party := range state.PresidentialElectoralHistory {
@@ -297,7 +120,6 @@ func getChanceRepublicanWinFromPollPlusUncertainty(poll Poll, state State, prett
fmt.Printf("\n\t\tN republican wins: %d", n_republican_win)
fmt.Printf("\n\t\t=> Reducing additional uncertainty")
}
-
}
std_error := std_error_poll_mean + std_additional_uncertainty
@@ -310,7 +132,6 @@ func getChanceRepublicanWinFromPollPlusUncertainty(poll Poll, state State, prett
fmt.Printf("\n\t\tPoll plus uncertainty says chance of R win: %f", p_republican_win)
}
return p_republican_win
-
}
/* Print state by state data */
@@ -357,9 +178,7 @@ func printStates(states []State) {
_ = getChanceRepublicanWinFromPoll(aggregate_poll, true)
_ = getChanceRepublicanWinFromPollPlusUncertainty(aggregate_poll, state, true)
}
-
}
-
}
/* Sample state by state */
@@ -445,7 +264,6 @@ func sampleFromState(state State) VotesForEachParty {
/* Simulate election */
func simulateElection(states []State) int {
-
republican_seats := 0
for _, state := range states {
election_sample := sampleFromState(state)
@@ -464,7 +282,6 @@ func barString(n int) string {
}
func printElectoralCollegeHistogram(samples []int) {
-
histogram := [538]int{}
for _, sample := range samples {
histogram[sample]++
@@ -490,7 +307,179 @@ func printElectoralCollegeHistogram(samples []int) {
}
}
+}
+
+/* Load data from csvs */
+// Glue code
+func readStates() ([]State, error) {
+ var states map[string]State = make(map[string]State)
+
+ /* Electoral college votes for the 2024 election*/
+ votes_file, err := os.Open("data/num-electors/electoral-college-votes.csv")
+ // votes_file, err := os.Open("data/electoral-college-votes-2010-census.csv")
+ if err != nil {
+ return nil, fmt.Errorf("error opening the votes file: %v", err)
+ }
+ defer votes_file.Close()
+
+ votes_reader := csv.NewReader(votes_file)
+ if _, err := votes_reader.Read(); err != nil { // Skip header
+ return nil, fmt.Errorf("error reading votes header: %v", err)
+ }
+ for {
+ csv_record, err := votes_reader.Read()
+ if err != nil {
+ break // EOF or an error
+ }
+ votes, err := strconv.Atoi(csv_record[1])
+ if err != nil {
+ continue // Error in converting votes, skip this record
+ }
+ state := csv_record[0]
+ if _, exists := states[state]; !exists {
+ states[state] = State{Name: state, Votes: votes, PresidentialElectoralHistory: make(map[string]string)}
+ }
+ }
+
+ /* Election results */
+ var years = []string{"2000", "2004", "2008", "2012", "2016", "2020"}
+ for _, year := range years {
+ electoral_history_filename := fmt.Sprintf("data/electoral-history/%s.csv", year)
+ electoral_history_file, err := os.Open(electoral_history_filename)
+ if err != nil {
+ return nil, fmt.Errorf("error opening the electoral_history file for %s: %v", year, err)
+ }
+ electoral_history_reader := csv.NewReader(electoral_history_file)
+ if _, err := electoral_history_reader.Read(); err != nil { // Skip header
+ return nil, fmt.Errorf("error reading electoral_history header for %s: %v", year, err)
+ }
+ for {
+ record, err := electoral_history_reader.Read()
+ if err != nil {
+ break // EOF or an error
+ }
+ state, party := record[0], record[1]
+ data, exists := states[state]
+ if !exists {
+ continue // State not found in votes map, skip
+ }
+ // Update the party winning in the specific year
+ data.PresidentialElectoralHistory[year] = party
+ states[state] = data
+ }
+
+ electoral_history_file.Close()
+ }
+
+ /* Read polls */
+ polls_file, err := os.Open("data/polls/president_polls_state.csv") // Make sure to update this path
+ if err != nil {
+ return nil, fmt.Errorf("error opening the polls file: %v", err)
+ }
+ defer polls_file.Close()
+
+ // Using a temporary map to group poll results by state and poll ID
+ state_polls_map := make(map[string]map[string]Poll)
+
+ polls_reader := csv.NewReader(polls_file)
+ _, err = polls_reader.Read() // Skip the header
+ if err != nil {
+ return nil, fmt.Errorf("error reading polls header: %v", err)
+ }
+
+ for {
+ record, err := polls_reader.Read()
+ if err != nil {
+ break // EOF or an error
+ }
+ poll_id := record[0]
+ state_name := record[12]
+ end_date := record[14]
+ partisan := record[32]
+ candidate_name := record[44]
+
+ date_layout := "1/2/06"
+ parsed_date, err := time.Parse(date_layout, end_date)
+ if err != nil {
+ fmt.Println("Error parsing date: ", err)
+ }
+
+ sample_size, err := strconv.Atoi(record[22])
+ if err != nil {
+ continue // If error, skip this record
+ }
+
+ percentage, err := strconv.ParseFloat(record[47], 64) // percentage is in the 42nd column
+ if err != nil {
+ fmt.Printf("Error parsing percentage")
+ continue // If error, skip this record
+ }
+
+ if _, exists := state_polls_map[state_name]; !exists {
+ state_polls_map[state_name] = make(map[string]Poll)
+ }
+
+ poll, exists := state_polls_map[state_name][poll_id]
+ if !exists {
+ poll = Poll{
+ PollId: poll_id,
+ SampleSize: sample_size,
+ PollResults: make(map[string]float64),
+ Date: parsed_date,
+ Partisan: partisan,
+ }
+ }
+ poll.PollResults[candidate_name] = percentage
+ state_polls_map[state_name][poll_id] = poll
+ }
+
+ // Add the aggregated poll data to the respective states
+ for state_name, polls := range state_polls_map {
+
+ // Filter polls by recency and by having both Biden and Trump
+ var recent_polls []Poll
+ for _, poll := range polls {
+ if poll.Date.After(time.Now().AddDate(0, 0, -30)) {
+ recent_polls = append(recent_polls, poll)
+ }
+ }
+ var recent_biden_trump_polls []Poll
+ for _, recent_poll := range recent_polls {
+ has_biden := false
+ has_trump := false
+ for candidate_name, _ := range recent_poll.PollResults {
+ if candidate_name == "Biden" {
+ has_biden = true
+ } else if candidate_name == "Trump" {
+ has_trump = true
+ }
+ }
+ if has_biden && has_trump {
+ recent_biden_trump_polls = append(recent_biden_trump_polls, recent_poll)
+ }
+ }
+
+ if state, exists := states[state_name]; exists {
+ state.Polls = recent_biden_trump_polls
+ states[state_name] = state // Not redundant
+ } else {
+ // fmt.Printf("Encountered new state: %s\n", state_name)
+ /*
+ states[state_name] = State{
+ Name: state_name,
+ Polls: polls_slice,
+ }
+ */
+ }
+ }
+
+ // Convert statesData map to a slice for returning
+ var states_slice []State
+ for _, state := range states {
+ states_slice = append(states_slice, state)
+ }
+ return states_slice, nil
}
func main() {
@@ -518,5 +507,4 @@ func main() {
p_republicans = p_republicans / float64(n_sims)
fmt.Printf("\n%% republicans: %f\n", p_republicans)
-
}