summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go188
1 files changed, 188 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..41dab39
--- /dev/null
+++ b/main.go
@@ -0,0 +1,188 @@
+package main
+
+import (
+ "fmt"
+ "strconv"
+ "os"
+ "time"
+ // "path/filepath"
+ xl "anyxcelize"
+ // "git.gabbott.dev/george/excelize/v2"
+ st "saggytrousers"
+ bt "badtudexo"
+)
+
+func usage() {
+ fmt.Println(`bt-eqpct: check fields calculated from percentages
+Usage:
+ bt-eqpct FILE -b BASE -p PERCENT -r RESULT -t TOLERANCE
+ -s SHEET -o OUTPUT
+As an example, -b can be a price, -p can be discount %, and -r discount value.
+Then it is calculated: BASE * (PERCENT ± TOLERANCE), and checked if RESULT is
+in this range. This checks the discount amount is always within the tolerance
+of what the percentage should be; if out, either the percentage or the value
+(either -p or -r) are probably wrong and need correcting in the data.
+
+The fields -b, -p and -r are required. If they are not passed, they will be
+prompted for. The function Locate() is used to find these and is passed the
+strings you passed in as params.
+`)
+ os.Exit(0)
+}
+
+func parseArgs(args []string) {
+ if len(args) < 2 {
+ usage()
+ }
+
+ for i := 0; i < len(args); i++ {
+ arg := args[i]
+ switch arg {
+ case "--help", "-h", "help", "helpme":
+ usage()
+
+ case "-b", "--base":
+ i++
+ base = args[i]
+ case "-p", "--pct", "--percent", "--percentage":
+ i++
+ percent = args[i]
+ case "-r", "--result":
+ i++
+ result = args[i]
+ case "-t", "--tol", "--tolerance":
+ i++
+ t, err := strconv.ParseFloat(args[i], 64)
+ if err != nil {
+ fmt.Printf("Tolerance passed with -t could not be parsed into a float64\n")
+ os.Exit(-1)
+ }
+ tol = t
+
+ case "-s", "--sheet":
+ i++
+ sheet = args[i]
+
+ case "--time", "--timings":
+ timeme = true
+ case "-o", "--out", "--output":
+ i++
+ out = args[i]
+ case "-v", "--verbose":
+ verbose = true
+
+ default:
+ filename = arg
+ }
+ }
+}
+
+// Constants
+const ToleranceNotSetValue float64 = 420.69
+
+// Globals
+var base string
+var percent string
+var result string
+var tol float64 = ToleranceNotSetValue
+var timeme bool = false
+var verbose bool = false
+var out string
+var sheet string
+var filename string
+
+
+func main() {
+ args := os.Args
+ parseArgs(args)
+
+ file, err := xl.OpenFile(filename)
+ if err != nil {
+ fmt.Printf("Cannot open file [%s], err [%v].\n", filename, err)
+ return
+ }
+
+ /* Ask user to select the sheet */
+ sheet = st.SelectSheet(file, sheet)
+
+ /* Try find base, percent, result rows, else prompt for them */
+ header := st.GetHeader(file, sheet)
+ baseIdx := bt.LocateOrAsk(header, base, "Please choose the base: ")
+ percentIdx := bt.LocateOrAsk(header, percent, "Please choose the percent: ")
+ resultIdx := bt.LocateOrAsk(header, result, "Please choose the resultant value: ")
+ if tol == ToleranceNotSetValue {
+ tol = st.GetFloat64("Please set the tolerance: ")
+ }
+
+ if verbose {
+ fmt.Printf("base index: %v\n", baseIdx)
+ fmt.Printf("percent index: %v\n", percentIdx)
+ fmt.Printf("result index: %v\n", resultIdx)
+ }
+
+ /* Now load all rows in. */
+ st.Log(verbose, "Loading rows...")
+ loadStart := time.Now()
+ rows := st.GetRows(file, sheet) // panics if fails, which is ok
+ loadTime := time.Since(loadStart)
+ st.Log(verbose, " done!\n")
+
+ /* Get columns from rows as []float64 for call to EqPct. */
+ var wasError bool = false
+ start := time.Now()
+ db, err := st.DowncastF64(st.TransmogrifyRows(rows, baseIdx))
+ if err != nil {
+ wasError = true
+ fmt.Printf("%v\n", err)
+ }
+ dp, err := st.DowncastF64(st.TransmogrifyRows(rows, percentIdx))
+ if err != nil {
+ wasError = true
+ fmt.Printf("%v\n", err)
+ }
+ dr, err := st.DowncastF64(st.TransmogrifyRows(rows, resultIdx))
+ if err != nil {
+ wasError = true
+ fmt.Printf("%v\n", err)
+ }
+ st.Log(verbose, "About to call bt.EqPct.\n")
+
+ if len(db) != len(dp) || len(dp) != len(dr) {
+ st.ErrLog(verbose,
+ fmt.Sprintf("Length mismatch: db = %v, dp = %v, dr = %v",
+ len(db), len(dp), len(dr)))
+ } else {
+ st.Log(verbose, fmt.Sprintf("Lengths are %v\n", len(db)))
+ }
+
+ indexes, err := bt.EqPct(db, dp, dr, tol)
+ if err != nil {
+ wasError = true
+ fmt.Printf("There was an error [%v]\n", err)
+ os.Exit(-1)
+ }
+ st.Log(verbose, "bt.EqPct completed successfully.\n")
+ end := time.Since(start)
+ // lenMax := len(string(len(db)))
+ for _, v := range indexes {
+ st.Log(true, fmt.Sprintf("%7v: %v * %v pct should be %v but found %v.\n",
+ v,
+ db[v],
+ dp[v],
+ (db[v] * dp[v])/100.00,
+ dr[v]))
+ }
+ if verbose {
+ fmt.Printf("base index: %v\n", baseIdx)
+ fmt.Printf("percent index: %v\n", percentIdx)
+ fmt.Printf("result index: %v\n", resultIdx)
+ }
+
+ if timeme {
+ fmt.Printf("Time to load: %v\n", loadTime)
+ fmt.Printf("Time to process: %v\n", end)
+ }
+ if verbose {
+ fmt.Printf("Was error: %v\n", wasError)
+ }
+}