You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cointop/cointop/portfolio.go

182 lines
4.2 KiB
Go

5 years ago
package cointop
import (
"fmt"
"regexp"
"strconv"
"strings"
"github.com/miguelmota/cointop/pkg/color"
"github.com/miguelmota/cointop/pkg/pad"
)
5 years ago
func (ct *Cointop) togglePortfolio() error {
ct.filterByFavorites = false
ct.portfoliovisible = !ct.portfoliovisible
ct.updateTable()
return nil
}
func (ct *Cointop) toggleShowPortfolio() error {
ct.filterByFavorites = false
ct.portfoliovisible = true
ct.updateTable()
return nil
}
func (ct *Cointop) togglePortfolioUpdateMenu() error {
ct.portfolioupdatemenuvisible = !ct.portfolioupdatemenuvisible
if ct.portfolioupdatemenuvisible {
return ct.showPortfolioUpdateMenu()
}
return ct.hidePortfolioUpdateMenu()
}
func (ct *Cointop) updatePortfolioUpdateMenu() {
coin := ct.highlightedRowCoin()
exists := ct.portfolioEntryExists(coin)
value := strconv.FormatFloat(coin.Holdings, 'f', -1, 64)
var mode string
var current string
var submitText string
if exists {
mode = "Edit"
current = fmt.Sprintf("(current %s %s)", value, coin.Symbol)
submitText = "Set"
} else {
mode = "Add"
submitText = "Add"
}
header := color.GreenBg(fmt.Sprintf(" %s Portfolio Entry %s\n\n", mode, pad.Left("[q] close ", ct.maxtablewidth-15, " ")))
label := fmt.Sprintf(" Enter holdings for %s %s", color.Yellow(coin.Name), current)
content := fmt.Sprintf("%s\n%s\n\n%s%s\n\n\n [Enter] %s [ESC] Cancel", header, label, strings.Repeat(" ", 29), coin.Symbol, submitText)
ct.update(func() {
ct.portfolioupdatemenuview.Clear()
ct.portfolioupdatemenuview.Frame = true
fmt.Fprintln(ct.portfolioupdatemenuview, content)
fmt.Fprintln(ct.inputview, value)
ct.inputview.SetCursor(len(value), 0)
})
}
func (ct *Cointop) showPortfolioUpdateMenu() error {
ct.portfolioupdatemenuvisible = true
ct.updatePortfolioUpdateMenu()
ct.setActiveView(ct.portfolioupdatemenuviewname)
return nil
}
func (ct *Cointop) hidePortfolioUpdateMenu() error {
ct.portfolioupdatemenuvisible = false
ct.setViewOnBottom(ct.portfolioupdatemenuviewname)
ct.setViewOnBottom(ct.inputviewname)
ct.setActiveView(ct.tableviewname)
ct.update(func() {
ct.portfolioupdatemenuview.Clear()
ct.portfolioupdatemenuview.Frame = false
fmt.Fprintln(ct.portfolioupdatemenuview, "")
ct.inputview.Clear()
fmt.Fprintln(ct.inputview, "")
})
return nil
}
// sets portfolio entry holdings from inputed value
func (ct *Cointop) setPortfolioHoldings() error {
defer ct.hidePortfolioUpdateMenu()
coin := ct.highlightedRowCoin()
b := make([]byte, 100)
n, err := ct.inputview.Read(b)
if n == 0 {
return nil
}
value := normalizeFloatstring(string(b))
shouldDelete := value == ""
var holdings float64
if !shouldDelete {
holdings, err = strconv.ParseFloat(value, 64)
if err != nil {
return err
}
}
ct.setPortfolioEntry(coin.Name, holdings)
if shouldDelete {
ct.removePortfolioEntry(coin.Name)
ct.updateTable()
ct.goToGlobalIndex(0)
} else {
ct.updateTable()
ct.goToGlobalIndex(coin.Rank - 1)
}
return nil
}
func (ct *Cointop) portfolioEntry(c *coin) (*portfolioEntry, bool) {
if c == nil {
return &portfolioEntry{}, true
}
var p *portfolioEntry
var isNew bool
var ok bool
key := strings.ToLower(c.Name)
if p, ok = ct.portfolio.Entries[key]; !ok {
// NOTE: if not found then try the symbol
key := strings.ToLower(c.Symbol)
if p, ok = ct.portfolio.Entries[key]; !ok {
p = &portfolioEntry{
Coin: c.Name,
Holdings: 0,
}
isNew = true
}
}
return p, isNew
}
func (ct *Cointop) setPortfolioEntry(coin string, holdings float64) {
c, _ := ct.allcoinsslugmap[strings.ToLower(coin)]
p, isNew := ct.portfolioEntry(c)
if isNew {
key := strings.ToLower(coin)
ct.portfolio.Entries[key] = &portfolioEntry{
Coin: coin,
Holdings: holdings,
}
} else {
p.Holdings = holdings
}
}
func (ct *Cointop) removePortfolioEntry(coin string) {
delete(ct.portfolio.Entries, strings.ToLower(coin))
}
func (ct *Cointop) portfolioEntryExists(c *coin) bool {
_, isNew := ct.portfolioEntry(c)
return !isNew
}
func (ct *Cointop) portfolioEntriesCount() int {
return len(ct.portfolio.Entries)
}
func normalizeFloatstring(input string) string {
re := regexp.MustCompile(`(\d+\.\d+|\.\d+|\d+)`)
result := re.FindStringSubmatch(input)
if len(result) > 0 {
return result[0]
}
return ""
}