diff --git a/config.yaml b/config.yaml index 9774ddf..f3de1af 100644 --- a/config.yaml +++ b/config.yaml @@ -1,8 +1,9 @@ -ECVAlgorithm: 3 +ECVAlgorithm: 2 PlotHeight: 10.0 PlotWidth: 10.0 PollHistoryLimit: 3 TossupThreshold: 3.01 +Battleground: AZ,GA,MI,NH,NV,PA,VA,WI # ECVAlgorithm: Electoral College Vote Allocation Algorithm (integer) diff --git a/global/global.go b/global/global.go index 7e531de..3590abf 100644 --- a/global/global.go +++ b/global/global.go @@ -13,25 +13,27 @@ const INTERNET_FILE = "https://www.electoral-vote.com/evp2024/Pres/pres_polls.tx // Definition of the singleton global. type GlobalsStruct struct { - Version string // Software version string - InternetCsvFile string // INTERNET_PREFIX + CSV_FILE_NAME + ".txt" - LocalCsvFile string // CSV file name + extension - DirCsv string // CSV input directory (before database load) - DirDatabase string // Database directory path - DirPlots string // Plots directory path - DirTemp string // Temporary holding area directory path - DbDriver string // Database driver name - DbFile string // Database file name + extension - CfgFile string // Configuration file - PollHistoryLimit int // Cfg: Limit of how many polls are entertained - TossupThreshold float64 // Cfg: Threshold of difference below which a tossup can be inferred - ECVAlgorithm int // Cfg: ECV distribution algorithm - PlotWidth float64 // Width of plot canvase in dots - PlotHeight float64 // Height of plot canvase in dots - FlagFetch bool // Fetch new data from the internet? true/false - FlagLoad bool // Load new data into the database? true/false - FlagReport bool // Report requested? true/false - FlagPlot bool // Plots requested? true/false + Version string // Software version string + InternetCsvFile string // INTERNET_PREFIX + CSV_FILE_NAME + ".txt" + LocalCsvFile string // CSV file name + extension + DirCsv string // CSV input directory (before database load) + DirDatabase string // Database directory path + DirPlots string // Plots directory path + DirTemp string // Temporary holding area directory path + DbDriver string // Database driver name + DbFile string // Database file name + extension + CfgFile string // Configuration file + PollHistoryLimit int // Cfg: Limit of how many polls are entertained + TossupThreshold float64 // Cfg: Threshold of difference below which a tossup can be inferred + ECVAlgorithm int // Cfg: ECV distribution algorithm + Battleground []string // List of battleground states + PlotWidth float64 // Width of plot canvase in dots + PlotHeight float64 // Height of plot canvase in dots + FlagFetch bool // Fetch new data from the internet? true/false + FlagLoad bool // Load new data into the database? true/false + FlagReport bool // Report requested? true/false + FlagPlot bool // Plots requested? true/false + FlagBattleground bool // Only report on battleground states (-r ec)? true/false } // Here's the singleton. @@ -49,20 +51,21 @@ func InitGlobals() *GlobalsStruct { versionString = strings.TrimSpace(versionString) global = GlobalsStruct{ - Version: versionString, - InternetCsvFile: INTERNET_FILE, - LocalCsvFile: CSV_FILE_NAME, - DirCsv: "./csv/", - DirDatabase: "./database/", - DirPlots: "./plots/", - DirTemp: "./temp/", - DbFile: "ppolls2024.db", - DbDriver: "sqlite", - CfgFile: "config.yaml", - FlagFetch: false, - FlagLoad: false, - FlagReport: false, - FlagPlot: false, + Version: versionString, + InternetCsvFile: INTERNET_FILE, + LocalCsvFile: CSV_FILE_NAME, + DirCsv: "./csv/", + DirDatabase: "./database/", + DirPlots: "./plots/", + DirTemp: "./temp/", + DbFile: "ppolls2024.db", + DbDriver: "sqlite", + CfgFile: "config.yaml", + FlagFetch: false, + FlagLoad: false, + FlagReport: false, + FlagPlot: false, + FlagBattleground: false, } return &global diff --git a/helpers/config.go b/helpers/config.go index 2dba92c..08568fd 100644 --- a/helpers/config.go +++ b/helpers/config.go @@ -6,6 +6,7 @@ import ( "os" "ppolls2024/global" "strconv" + "strings" ) type paramsStruct struct { @@ -14,12 +15,13 @@ type paramsStruct struct { PollHistoryLimit string `yaml:"PollHistoryLimit"` TossupThreshold string `yaml:"TossupThreshold"` ECVAlgorithm string `yaml:"ECVAlgorithm"` + Battleground string `yaml:"Battleground"` PlotWidth string `yaml:"PlotWidth"` PlotHeight string `yaml:"PlotHeight"` } func GetConfig() { - + var params paramsStruct glob := global.GetGlobalRef() bytes, err := os.ReadFile(glob.CfgFile) @@ -38,6 +40,8 @@ func GetConfig() { } log.Printf("GetConfig: ECVAlgorithm: %d", glob.ECVAlgorithm) + glob.Battleground = strings.Split(params.Battleground, ",") + glob.PlotWidth, err = strconv.ParseFloat(params.PlotWidth, 64) if err != nil { log.Fatalf("GetConfig: strconv.ParseFloat(PlotWidth) from %s failed, reason: %s\n", glob.CfgFile, err.Error()) diff --git a/helpers/reports.go b/helpers/reports.go index ec47da6..467bfdc 100644 --- a/helpers/reports.go +++ b/helpers/reports.go @@ -54,6 +54,11 @@ func ReportEC() { fmt.Println("\nSt EV Last Poll Biden Trump Other Leading") fmt.Println(prtDivider) for _, stateECV = range stateECVTable { + if glob.FlagBattleground { + if !searchSlice(glob.Battleground, stateECV.state) { + continue + } + } // For the given state, query from the most recent to the least recent polling. sqlText := fmt.Sprintf("SELECT end_date, pct_biden, pct_trump FROM history WHERE state = '%s' ORDER BY end_date DESC", stateECV.state) diff --git a/helpers/utils.go b/helpers/utils.go index 5ff2641..f776f41 100644 --- a/helpers/utils.go +++ b/helpers/utils.go @@ -289,3 +289,15 @@ func ECVAward3(stateVotes int, pctBiden, pctTrump float64) (string, int, int, in } return "Trump", 0, stateVotes, 0, " " } + +// searchSlice looks for a target string in an array of strings. +// It returns true if the target string is found, +// Otherwise, it returns false. +func searchSlice(slice []string, target string) bool { + for _, str := range slice { + if str == target { + return true + } + } + return false +} diff --git a/main.go b/main.go index 31d925e..96736bc 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "log" "os" "path/filepath" "ppolls2024/global" @@ -19,6 +20,7 @@ func showHelp() { fmt.Printf("\t-r ID:\tReport by identifier (ID):\n") fmt.Printf("\t\tSC\tSC = state code (E.g. AL).\n") fmt.Printf("\t\tEC\tElectoral College tallies for all states.\n") + fmt.Printf("\t-b:\tProcess only battleground states in -r ec\n") fmt.Printf("\nExit codes:\n") fmt.Printf("\t0\tNormal completion or help shown due to command line error.\n") fmt.Printf("\t1\tSomething went wrong during execution.\n\n") @@ -56,6 +58,8 @@ func main() { ii++ rpt = strings.ToUpper(params[ii]) glob.FlagReport = true + case "-b": + glob.FlagBattleground = true default: fmt.Printf("*** The specified parameter (%s) is not supported!\n", params[ii]) showHelp() @@ -68,6 +72,11 @@ func main() { helpers.MakeDir(glob.DirPlots) helpers.MakeDir(glob.DirTemp) + // Validate the use of -b. + if glob.FlagBattleground && !glob.FlagReport { + log.Println("Warning: No reports requested. The battleground flag (-b) is ignored") + } + // Fetch new data? if glob.FlagFetch { helpers.Fetch(glob.DirCsv, glob.LocalCsvFile, glob.InternetCsvFile, glob.DirTemp)