diff --git a/css/main.css b/css/main.css index 2270693..bc1b02f 100644 --- a/css/main.css +++ b/css/main.css @@ -120,4 +120,26 @@ nav li a:hover { .item { margin: auto; +} + +.table { + border-collapse:collapse; + border-spacing:0; + margin: 0 auto; + width: min-content + 20px; + margin-bottom: 10%; +} + +.left { + text-align: left; +} + +.right { + text-align: right +} + +.table td, .table th { + border-color:black; + border-style:solid; + border-width:2px } \ No newline at end of file diff --git a/go.mod b/go.mod index 8c5085c..2fbbc3b 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,10 @@ module git.nils.zone/nils/goCake go 1.15 require ( + git.nils.zone/nils/prettify v0.0.4 github.com/davecgh/go-spew v1.1.1 // indirect github.com/kr/pretty v0.1.0 // indirect + github.com/lucasb-eyer/go-colorful v1.0.3 github.com/stretchr/testify v1.6.1 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect ) diff --git a/main.go b/main.go index 3231fa3..3b81a8b 100644 --- a/main.go +++ b/main.go @@ -15,9 +15,9 @@ func main() { http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("css")))) // when navigating to /home it should serve the home page - // http.HandleFunc("/", Home) - http.HandleFunc("/", Rewards) + http.HandleFunc("/", Home) http.HandleFunc("/rewards", Rewards) + http.HandleFunc("/table", Rewards) http.ListenAndServe(getPort(), nil) } diff --git a/rewards.go b/rewards.go index a832997..93e4a6c 100644 --- a/rewards.go +++ b/rewards.go @@ -2,11 +2,15 @@ package main import ( "errors" + "fmt" "io/ioutil" + "log" "net/http" "strconv" "strings" "time" + + "github.com/lucasb-eyer/go-colorful" ) type line struct { @@ -19,16 +23,28 @@ type line struct { Reference string } +type rewards struct { + Staking map[time.Month]string + Confectionery map[time.Month]string + LapisDFI map[time.Month]string + Lapis map[time.Month]string + Referral map[time.Month]string +} + // Rewards needs a comment func Rewards(w http.ResponseWriter, r *http.Request) { type data struct { Title string Uploaded bool Success bool - Rewards map[time.Month]string + Rewards rewards CumulativeRewards map[time.Month]string Color string + ColorAlt string + ColorAltAlt string Currency string + ErrorText string + Lending bool } // set common attributes @@ -48,32 +64,54 @@ func Rewards(w http.ResponseWriter, r *http.Request) { case http.MethodPost: // upload the file that was posted here var success bool = false + var e string + lines, err := uploadFile(w, r) if err == nil { success = true + } else { + e = err.Error() } // prepare data for usage var color string var currency string - var rewards map[time.Month]string + var rewards rewards if success == true { currency = lines[1].Cryptocurrency - color, _ = getCurrencyOpts(currency) + color, _, d.Lending = getCurrencyOpts(currency) rewards = monthlyRewardOverview(lines) } // prettify.Print(rewards) d.Uploaded = true d.Success = success - d.Rewards = rewards + d.Rewards.Staking = rewards.Staking + d.Rewards.Confectionery = rewards.Confectionery + d.Rewards.Lapis = rewards.Lapis + d.Rewards.LapisDFI = rewards.LapisDFI + d.Rewards.Referral = rewards.Referral d.Color = color + d.ColorAlt = getOtherColors(color, 2) + d.ColorAltAlt = getOtherColors(color, 4) d.Currency = currency + d.ErrorText = e render(w, "rewards.html", d) } // create a new line instance } +func getOtherColors(color string, factor float64) string { + col, err := colorful.Hex(color) + if err != nil { + log.Fatal(err) + } + // get r,g,b from color + r, g, b := col.LinearRgb() + // return color reduced in "brightness" by factor of f + return colorful.LinearRgb(r/factor, g/factor, b/factor).Hex() +} + func uploadFile(w http.ResponseWriter, r *http.Request) ([]line, error) { // Maximum upload of 10 MB files r.ParseMultipartForm(10 << 20) @@ -81,7 +119,7 @@ func uploadFile(w http.ResponseWriter, r *http.Request) ([]line, error) { // Get handler for filename, size and headers file, handler, err := r.FormFile("csvFile") if err != nil { - return nil, err + return nil, errors.New("please upload a .csv file") } defer file.Close() @@ -91,30 +129,37 @@ func uploadFile(w http.ResponseWriter, r *http.Request) ([]line, error) { // accept this gift and read content of file fileContents, err := ioutil.ReadAll(file) if err != nil { + fmt.Println("file was uploaded but can't be read! 1", err) return nil, err } // read uploaded file - lines := readUploadedFile(fileContents) + lines, err := readUploadedFile(fileContents) + if err != nil { + return nil, fmt.Errorf("the .csv file could not be read, error was: %s", err) + } return lines, err } return nil, errors.New("please only upload .csv files") } -func getCurrencyOpts(currency string) (color string, precision int) { +func getCurrencyOpts(currency string) (color string, precision int, lending bool) { // set default precision precision = 8 + lending = false // set other options according to the coin switch currency { case "BTC": // Bitcoin color = "#F7931A" + lending = true case "DASH": color = "#008de4" case "DFI": // DeFiChain color = "#fd0bb0" case "ETH": // Ethereum color = "#627eea" + lending = true precision = 18 case "PIVX": color = "#5e4778" @@ -123,30 +168,49 @@ func getCurrencyOpts(currency string) (color string, precision int) { color = "#24b852" case "USDT": // Tether color = "#26a17b" + lending = true precision = 6 } - return color, precision + return color, precision, lending } -func monthlyRewardOverview(lines []line) map[time.Month]string { +func monthlyRewardOverview(lines []line) rewards { // create a map to hold all months' sums - sums := make(map[time.Month]float64) + staking := make(map[time.Month]float64) + confectionery := make(map[time.Month]float64) + lapisDFI := make(map[time.Month]float64) + lapis := make(map[time.Month]float64) + referral := make(map[time.Month]float64) // loop through all lines for i := range lines { // filter out operations switch lines[i].Operation { - case "Staking reward ", "Confectionery Lapis DFI Bonus ", "Lapis DFI Bonus ", "Lapis reward ", "Referral reward ": - sums[lines[i].Date.Month()] += lines[i].Amount + case "Staking reward": + staking[lines[i].Date.Month()] += lines[i].Amount + case "Confectionery Lapis DFI Bonus": + confectionery[lines[i].Date.Month()] += lines[i].Amount + case "Lapis DFI Bonus": + lapisDFI[lines[i].Date.Month()] += lines[i].Amount + case "Lapis reward": + lapis[lines[i].Date.Month()] += lines[i].Amount + case "Referral reward": + referral[lines[i].Date.Month()] += lines[i].Amount } } // get precision for specific coin - _, precision := getCurrencyOpts(lines[0].Cryptocurrency) + _, precision, _ := getCurrencyOpts(lines[0].Cryptocurrency) // fill empty data with zeroes - sumsString := fillSums(sums, precision) + r := rewards{ + Staking: fillSums(staking, precision), + Confectionery: fillSums(confectionery, precision), + LapisDFI: fillSums(lapisDFI, precision), + Lapis: fillSums(lapis, precision), + Referral: fillSums(referral, precision), + } - return sumsString + return r } func fillSums(s map[time.Month]float64, precision int) map[time.Month]string { @@ -166,45 +230,38 @@ func fillSums(s map[time.Month]float64, precision int) map[time.Month]string { return sumsString } -func readUploadedFile(fileContents []byte) []line { +func readUploadedFile(fileContents []byte) ([]line, error) { var lines []line csvLines := strings.Split(string(fileContents), "\n") // loop through all lines (except headers) for _, csvLine := range csvLines[1:] { - // split arguments by comma - csvArgs := strings.Split(csvLine, ",") + if csvLine != "" { + // split arguments by comma + csvArgs := strings.Split(csvLine, ",") - // fix stupid " in lines - for i := range csvArgs { - csvArgs[i] = strings.ReplaceAll(csvArgs[i], `"`, "") + // fix stupid " in lines + for i := range csvArgs { + csvArgs[i] = strings.ReplaceAll(csvArgs[i], `"`, "") + } + + // create output variable + var l line + + // assign values from CSV file to output variable + var err error + l.Date, err = time.Parse(time.RFC3339, csvArgs[0]) + if err != nil { + return nil, err + } + l.Operation = csvArgs[1] + l.Cryptocurrency = csvArgs[2] + l.Amount, _ = strconv.ParseFloat(csvArgs[3], 64) + l.TransactionID = csvArgs[4] + l.WithdrawalAddress = csvArgs[5] + l.Reference = csvArgs[6] + lines = append(lines, l) } - - // create output variable - var l line - - // assign values from CSV file to output variable - var err error - l.Date, err = time.Parse(time.RFC3339, csvArgs[0]) - if err != nil { - panic(err) - } - l.Operation = csvArgs[1] - l.Cryptocurrency = csvArgs[2] - l.Amount, _ = strconv.ParseFloat(csvArgs[3], 64) - l.TransactionID = csvArgs[4] - l.WithdrawalAddress = csvArgs[5] - l.Reference = csvArgs[6] - lines = append(lines, l) - } - return lines -} - -func uploadHandler(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case "GET": - render(w, "upload", nil) - case "POST": - uploadFile(w, r) } + return lines, nil } diff --git a/templates/includes.html b/templates/includes.html index cfc8472..23514f2 100644 --- a/templates/includes.html +++ b/templates/includes.html @@ -19,7 +19,7 @@