mirror of
https://github.com/miguelmota/cointop
synced 2024-11-14 18:12:57 +00:00
189 lines
4.6 KiB
Go
189 lines
4.6 KiB
Go
package cointop
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/cointop-sh/cointop/pkg/api/types"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var coinslock sync.Mutex
|
|
var updatecoinsmux sync.Mutex
|
|
|
|
// UpdateCoins updates coins view
|
|
func (ct *Cointop) UpdateCoins() error {
|
|
log.Debug("UpdateCoins()")
|
|
coinslock.Lock()
|
|
defer coinslock.Unlock()
|
|
cachekey := ct.CacheKey("allCoinsSlugMap")
|
|
|
|
var err error
|
|
var allCoinsSlugMap map[string]types.Coin
|
|
cached, found := ct.cache.Get(cachekey)
|
|
if found {
|
|
// cache hit
|
|
allCoinsSlugMap, _ = cached.(map[string]types.Coin)
|
|
log.Debug("UpdateCoins() soft cache hit")
|
|
}
|
|
|
|
// cache miss
|
|
if allCoinsSlugMap == nil {
|
|
log.Debug("UpdateCoins() cache miss")
|
|
ch := make(chan []types.Coin)
|
|
err = ct.api.GetAllCoinData(ct.State.currencyConversion, ch)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for coins := range ch {
|
|
go ct.processCoins(coins)
|
|
}
|
|
} else {
|
|
ct.processCoinsMap(allCoinsSlugMap)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateCurrentPageCoins updates all the coins in the current page
|
|
func (ct *Cointop) UpdateCurrentPageCoins() error {
|
|
log.Debugf("UpdateCurrentPageCoins(%d)", len(ct.State.coins))
|
|
currentPageCoins := make([]string, len(ct.State.coins))
|
|
for i, entry := range ct.State.coins {
|
|
currentPageCoins[i] = entry.Name
|
|
}
|
|
|
|
coins, err := ct.api.GetCoinDataBatch(currentPageCoins, ct.State.currencyConversion)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
go ct.processCoins(coins)
|
|
return nil
|
|
}
|
|
|
|
// ProcessCoinsMap processes coins map
|
|
func (ct *Cointop) processCoinsMap(coinsMap map[string]types.Coin) {
|
|
log.Debug("ProcessCoinsMap()")
|
|
|
|
var coins []types.Coin
|
|
for _, v := range coinsMap {
|
|
coins = append(coins, v)
|
|
}
|
|
|
|
ct.processCoins(coins)
|
|
}
|
|
|
|
// ProcessCoins processes coins list
|
|
func (ct *Cointop) processCoins(coins []types.Coin) {
|
|
log.Debug("ProcessCoins()")
|
|
updatecoinsmux.Lock()
|
|
defer updatecoinsmux.Unlock()
|
|
|
|
ct.CacheAllCoinsSlugMap()
|
|
|
|
for _, v := range coins {
|
|
k := v.Name
|
|
|
|
// Fix for https://github.com/cointop-sh/cointop/issues/59
|
|
// some APIs returns rank 0 for new coins
|
|
// or coins with low market cap data so we need to put them
|
|
// at the end of the list
|
|
if v.Rank == 0 {
|
|
v.Rank = 10000
|
|
}
|
|
|
|
ilast, _ := ct.State.allCoinsSlugMap.Load(k)
|
|
ct.State.allCoinsSlugMap.Store(k, &Coin{
|
|
ID: v.ID,
|
|
Name: v.Name,
|
|
Symbol: v.Symbol,
|
|
Rank: v.Rank,
|
|
Price: v.Price,
|
|
Volume24H: v.Volume24H,
|
|
MarketCap: v.MarketCap,
|
|
AvailableSupply: v.AvailableSupply,
|
|
TotalSupply: v.TotalSupply,
|
|
PercentChange1H: v.PercentChange1H,
|
|
PercentChange24H: v.PercentChange24H,
|
|
PercentChange7D: v.PercentChange7D,
|
|
PercentChange30D: v.PercentChange30D,
|
|
PercentChange1Y: v.PercentChange1Y,
|
|
LastUpdated: v.LastUpdated,
|
|
})
|
|
if ilast != nil {
|
|
last, _ := ilast.(*Coin)
|
|
if last != nil {
|
|
ivalue, _ := ct.State.allCoinsSlugMap.Load(k)
|
|
l, _ := ivalue.(*Coin)
|
|
l.Favorite = last.Favorite
|
|
ct.State.allCoinsSlugMap.Store(k, l)
|
|
}
|
|
}
|
|
}
|
|
|
|
size := 0
|
|
// NOTE: there's no Len method on sync.Map so need to manually count
|
|
ct.State.allCoinsSlugMap.Range(func(key, value interface{}) bool {
|
|
size++
|
|
return true
|
|
})
|
|
|
|
if len(ct.State.allCoins) < size {
|
|
var list []*Coin
|
|
for _, v := range coins {
|
|
k := v.Name
|
|
icoin, _ := ct.State.allCoinsSlugMap.Load(k)
|
|
coin, _ := icoin.(*Coin)
|
|
list = append(list, coin)
|
|
}
|
|
ct.State.allCoins = append(ct.State.allCoins, list...)
|
|
} else {
|
|
// update list in place without changing order
|
|
ct.State.allCoinsSlugMap.Range(func(key, value interface{}) bool {
|
|
cm, _ := value.(*Coin)
|
|
for k := range ct.State.allCoins {
|
|
c := ct.State.allCoins[k]
|
|
if c.ID == cm.ID {
|
|
// TODO: improve this
|
|
c.ID = cm.ID
|
|
c.Name = cm.Name
|
|
c.Symbol = cm.Symbol
|
|
c.Rank = cm.Rank
|
|
c.Price = cm.Price
|
|
c.Volume24H = cm.Volume24H
|
|
c.MarketCap = cm.MarketCap
|
|
c.AvailableSupply = cm.AvailableSupply
|
|
c.TotalSupply = cm.TotalSupply
|
|
c.PercentChange1H = cm.PercentChange1H
|
|
c.PercentChange24H = cm.PercentChange24H
|
|
c.PercentChange7D = cm.PercentChange7D
|
|
c.PercentChange30D = cm.PercentChange30D
|
|
c.PercentChange1Y = cm.PercentChange1Y
|
|
c.LastUpdated = cm.LastUpdated
|
|
c.Favorite = cm.Favorite
|
|
}
|
|
}
|
|
|
|
return true
|
|
})
|
|
}
|
|
|
|
time.AfterFunc(10*time.Millisecond, func() {
|
|
ct.Sort(ct.State.sortBy, ct.State.sortDesc, ct.State.coins, true)
|
|
ct.UpdateTable()
|
|
})
|
|
}
|
|
|
|
// GetListCount returns count of coins list
|
|
func (ct *Cointop) GetListCount() int {
|
|
log.Debug("GetListCount()")
|
|
if ct.IsFavoritesVisible() {
|
|
return len(ct.State.favorites)
|
|
} else if ct.IsPortfolioVisible() {
|
|
return len(ct.State.portfolio.Entries)
|
|
} else {
|
|
return len(ct.State.allCoins)
|
|
}
|
|
}
|