new functions, yadda yadda

This commit is contained in:
Nils Stinnesbeck 2020-11-15 20:46:32 +01:00
parent 620db27468
commit 95587ba68d
Signed by: nils
GPG Key ID: 86D4882C6C6CA48B
6 changed files with 179 additions and 59 deletions

View File

@ -121,3 +121,25 @@ nav li a:hover {
.item { .item {
margin: auto; 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
}

2
go.mod
View File

@ -3,8 +3,10 @@ module git.nils.zone/nils/goCake
go 1.15 go 1.15
require ( require (
git.nils.zone/nils/prettify v0.0.4
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.1.0 // 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 github.com/stretchr/testify v1.6.1
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
) )

View File

@ -15,9 +15,9 @@ func main() {
http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("css")))) http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("css"))))
// when navigating to /home it should serve the home page // when navigating to /home it should serve the home page
// http.HandleFunc("/", Home) http.HandleFunc("/", Home)
http.HandleFunc("/", Rewards)
http.HandleFunc("/rewards", Rewards) http.HandleFunc("/rewards", Rewards)
http.HandleFunc("/table", Rewards)
http.ListenAndServe(getPort(), nil) http.ListenAndServe(getPort(), nil)
} }

View File

@ -2,11 +2,15 @@ package main
import ( import (
"errors" "errors"
"fmt"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/lucasb-eyer/go-colorful"
) )
type line struct { type line struct {
@ -19,16 +23,28 @@ type line struct {
Reference string 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 // Rewards needs a comment
func Rewards(w http.ResponseWriter, r *http.Request) { func Rewards(w http.ResponseWriter, r *http.Request) {
type data struct { type data struct {
Title string Title string
Uploaded bool Uploaded bool
Success bool Success bool
Rewards map[time.Month]string Rewards rewards
CumulativeRewards map[time.Month]string CumulativeRewards map[time.Month]string
Color string Color string
ColorAlt string
ColorAltAlt string
Currency string Currency string
ErrorText string
Lending bool
} }
// set common attributes // set common attributes
@ -48,32 +64,54 @@ func Rewards(w http.ResponseWriter, r *http.Request) {
case http.MethodPost: case http.MethodPost:
// upload the file that was posted here // upload the file that was posted here
var success bool = false var success bool = false
var e string
lines, err := uploadFile(w, r) lines, err := uploadFile(w, r)
if err == nil { if err == nil {
success = true success = true
} else {
e = err.Error()
} }
// prepare data for usage // prepare data for usage
var color string var color string
var currency string var currency string
var rewards map[time.Month]string var rewards rewards
if success == true { if success == true {
currency = lines[1].Cryptocurrency currency = lines[1].Cryptocurrency
color, _ = getCurrencyOpts(currency) color, _, d.Lending = getCurrencyOpts(currency)
rewards = monthlyRewardOverview(lines) rewards = monthlyRewardOverview(lines)
} }
// prettify.Print(rewards) // prettify.Print(rewards)
d.Uploaded = true d.Uploaded = true
d.Success = success 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.Color = color
d.ColorAlt = getOtherColors(color, 2)
d.ColorAltAlt = getOtherColors(color, 4)
d.Currency = currency d.Currency = currency
d.ErrorText = e
render(w, "rewards.html", d) render(w, "rewards.html", d)
} }
// create a new line instance // 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) { func uploadFile(w http.ResponseWriter, r *http.Request) ([]line, error) {
// Maximum upload of 10 MB files // Maximum upload of 10 MB files
r.ParseMultipartForm(10 << 20) 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 // Get handler for filename, size and headers
file, handler, err := r.FormFile("csvFile") file, handler, err := r.FormFile("csvFile")
if err != nil { if err != nil {
return nil, err return nil, errors.New("please upload a .csv file")
} }
defer file.Close() 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 // accept this gift and read content of file
fileContents, err := ioutil.ReadAll(file) fileContents, err := ioutil.ReadAll(file)
if err != nil { if err != nil {
fmt.Println("file was uploaded but can't be read! 1", err)
return nil, err return nil, err
} }
// read uploaded file // 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 lines, err
} }
return nil, errors.New("please only upload .csv files") 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 // set default precision
precision = 8 precision = 8
lending = false
// set other options according to the coin // set other options according to the coin
switch currency { switch currency {
case "BTC": // Bitcoin case "BTC": // Bitcoin
color = "#F7931A" color = "#F7931A"
lending = true
case "DASH": case "DASH":
color = "#008de4" color = "#008de4"
case "DFI": // DeFiChain case "DFI": // DeFiChain
color = "#fd0bb0" color = "#fd0bb0"
case "ETH": // Ethereum case "ETH": // Ethereum
color = "#627eea" color = "#627eea"
lending = true
precision = 18 precision = 18
case "PIVX": case "PIVX":
color = "#5e4778" color = "#5e4778"
@ -123,30 +168,49 @@ func getCurrencyOpts(currency string) (color string, precision int) {
color = "#24b852" color = "#24b852"
case "USDT": // Tether case "USDT": // Tether
color = "#26a17b" color = "#26a17b"
lending = true
precision = 6 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 // 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 // loop through all lines
for i := range lines { for i := range lines {
// filter out operations // filter out operations
switch lines[i].Operation { switch lines[i].Operation {
case "Staking reward ", "Confectionery Lapis DFI Bonus ", "Lapis DFI Bonus ", "Lapis reward ", "Referral reward ": case "Staking reward":
sums[lines[i].Date.Month()] += lines[i].Amount 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 // get precision for specific coin
_, precision := getCurrencyOpts(lines[0].Cryptocurrency) _, precision, _ := getCurrencyOpts(lines[0].Cryptocurrency)
// fill empty data with zeroes // 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 { func fillSums(s map[time.Month]float64, precision int) map[time.Month]string {
@ -166,12 +230,13 @@ func fillSums(s map[time.Month]float64, precision int) map[time.Month]string {
return sumsString return sumsString
} }
func readUploadedFile(fileContents []byte) []line { func readUploadedFile(fileContents []byte) ([]line, error) {
var lines []line var lines []line
csvLines := strings.Split(string(fileContents), "\n") csvLines := strings.Split(string(fileContents), "\n")
// loop through all lines (except headers) // loop through all lines (except headers)
for _, csvLine := range csvLines[1:] { for _, csvLine := range csvLines[1:] {
if csvLine != "" {
// split arguments by comma // split arguments by comma
csvArgs := strings.Split(csvLine, ",") csvArgs := strings.Split(csvLine, ",")
@ -187,7 +252,7 @@ func readUploadedFile(fileContents []byte) []line {
var err error var err error
l.Date, err = time.Parse(time.RFC3339, csvArgs[0]) l.Date, err = time.Parse(time.RFC3339, csvArgs[0])
if err != nil { if err != nil {
panic(err) return nil, err
} }
l.Operation = csvArgs[1] l.Operation = csvArgs[1]
l.Cryptocurrency = csvArgs[2] l.Cryptocurrency = csvArgs[2]
@ -197,14 +262,6 @@ func readUploadedFile(fileContents []byte) []line {
l.Reference = csvArgs[6] l.Reference = csvArgs[6]
lines = append(lines, l) 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
} }

View File

@ -19,7 +19,7 @@
<ul> <ul>
{{ if .Title}} {{ if .Title}}
<!-- set current tab active, according to title --> <!-- set current tab active, according to title -->
<!-- <li><a {{ if (eq .Title "Home") }}class="active"{{end}} href="/">Home</a></li> --> <li><a {{ if (eq .Title "Home") }}class="active"{{end}} href="/">Home</a></li>
<!-- <li><a {{ if (eq .Title "Rewards") }}class="active"{{end}} href="rewards">Monthly Rewards</a></li> --> <!-- <li><a {{ if (eq .Title "Rewards") }}class="active"{{end}} href="rewards">Monthly Rewards</a></li> -->
<!-- <li><a {{ if (eq .Title "Graphs") }}class="active"{{end}} href="graphs">Graphs</a></li> --> <!-- <li><a {{ if (eq .Title "Graphs") }}class="active"{{end}} href="graphs">Graphs</a></li> -->
<li><a {{ if (eq .Title "Monthly Rewards") }}class="active"{{end}} href="rewards">Monthly Rewards</a></li> <li><a {{ if (eq .Title "Monthly Rewards") }}class="active"{{end}} href="rewards">Monthly Rewards</a></li>
@ -29,8 +29,8 @@
{{end}} {{end}}
{{define "footer"}} {{define "footer"}}
<div class="footer">&hearts; 2020 Nils Jakobi <div class="footer">
- <a href="https://git.nils.zone/nils/goCake">Source Code</a> &hearts; <a href="https://github.com/thunderstorm99/goCoinAnalyzer">Source Code</a> &hearts;
</div> </div>
</body> </body>
</html> </html>
@ -46,23 +46,59 @@
var rewardOptions = { var rewardOptions = {
title: {"text":"Monthly Rewards","subtext":"{{.Currency}}"}, title: {"text":"Monthly Rewards","subtext":"{{.Currency}}"},
tooltip: {"show":true}, tooltip: {"show":true},
legend: {"show":false}, legend: {"show":true},
dataZoom:[{"type":"inside"}], dataZoom:[{"type":"inside"}],
xAxis: {{ template "xAxis" . }} xAxis: {{ template "xAxis" . }}
yAxis: [{}], yAxis: [{}],
series: [{{template "series" . }}], series: [{{template "series" . }}],
color: ["{{.Color}}"], color: ["{{.Color}}","{{.ColorAlt}}","{{.ColorAltAlt}}"],
}; };
rewardChart.setOption(rewardOptions); rewardChart.setOption(rewardOptions);
</script> </script>
{{ end }} {{ end }}
{{define "xAxis"}} {{define "xAxis"}}
[{"data":[ {{ range $month, $amount := .Rewards}}"{{ $month }}",{{ end }}]}], [{"data":[ {{ range $month, $amount := .Rewards.Staking}}"{{ $month }}",{{ end }}]}],
{{end}} {{end}}
{{define "series"}} {{define "series"}}
{"name":"{{.Currency}}","type":"bar","waveAnimation":false,"data":[ {{if .Lending}}
{{ range $month, $amount := .Rewards}}{"value": "{{ $amount }}" },{{ end }} // Lending coins
{"name":"Lapis reward","type":"bar","stack":"stackA","waveAnimation":false,"data":[
{{ range $month, $amount := .Rewards.Lapis}}{"value": "{{ $amount }}" },{{ end }}
]},
{"name":"Referral reward","type":"bar","stack":"stackA","waveAnimation":false,"data":[
{{ range $month, $amount := .Rewards.Referral}}{"value": "{{ $amount }}" },{{ end }}
]},
{{else}}
// Stakeable coins
{"name":"Staking Rewards","type":"bar","stack":"stackA","waveAnimation":false,"data":[
{{ range $month, $amount := .Rewards.Staking}}{"value": "{{ $amount }}" },{{ end }}
]},
{"name":"Lapis DFI Bonus","type":"bar","stack":"stackA","waveAnimation":false,"data":[
{{ range $month, $amount := .Rewards.LapisDFI}}{"value": "{{ $amount }}" },{{ end }}
]},
{"name":"Confectionery Lapis DFI Bonus","type":"bar","stack":"stackA","waveAnimation":false,"data":[
{{ range $month, $amount := .Rewards.Confectionery}}{"value": "{{ $amount }}" },{{ end }}
]}, ]},
{{end}} {{end}}
{{end}}
{{define "table"}}
<table class="table">
<thead>
<tr>
<th>Month</th>
<th>{{.Currency}}</th>
</tr>
</thead>
<tbody>
{{ range $month, $amount := .Rewards.Staking}}
<tr>
<td class="left">{{ $month }}</td>
<td class="right">{{ $amount }}</td>
</tr>
{{ end }}
</tbody>
</table>
{{end}}

View File

@ -14,12 +14,15 @@
{{if .Uploaded}} {{if .Uploaded}}
<!-- Uploaded but not successful --> <!-- Uploaded but not successful -->
<div class="err"> <div class="err">
<p>Please only upload .csv Files!</p> {{if ne .ErrorText ""}}
<p>{{.ErrorText}}</p>
{{end}}
</div> </div>
{{end}} {{end}}
{{else}} {{else}}
<!-- successful --> <!-- successful -->
{{template "barGraph" .}} {{template "barGraph" .}}
<!-- {{template "table" .}} -->
{{end}} {{end}}
</div> </div>
{{template "footer" .}} {{template "footer" .}}