core/coaster.go

177 lines
4.7 KiB
Go
Raw Normal View History

2024-12-15 17:40:14 +08:00
package core
import (
"encoding/json"
"errors"
"fmt"
logrus "github.com/sirupsen/logrus"
"os"
"strconv"
"time"
)
// TODO 目前没有实现tickerInfo用一分钟维度的candle代替, 后续如果订阅ws的话ticker就不用了也还是直接用candle1m就够了
type Coaster struct {
InstID string `json:"instID"`
Period string `json:"period"`
Count int `json:"count"`
Scale float64 `json:"scale"`
LastUpdateTime int64 `json:"lastUpdateTime"`
UpdateNickName string `json:"updateNickName"`
CandleList CandleList `json:"candleList"`
Ma7List MaXList `json:"ma7List"`
Ma30List MaXList `json:"ma30List"`
}
type CoasterInfo struct {
InstID string
Period string
InsertedNew bool
}
func (co Coaster) RPushSample(cr *Core, sp Sample, ctype string) (*Sample, error) {
cd := Candle{}
spjs, _ := json.Marshal(sp)
logrus.Debug("RPushSample spjs: ", string(spjs))
if ctype == "candle" {
json.Unmarshal(spjs, &cd)
cd.Data[0] = cd.Data[0]
cd.Data[1], _ = strconv.ParseFloat(cd.Data[1].(string), 64)
cd.Data[2], _ = strconv.ParseFloat(cd.Data[2].(string), 64)
cd.Data[3], _ = strconv.ParseFloat(cd.Data[3].(string), 64)
cd.Data[4], _ = strconv.ParseFloat(cd.Data[4].(string), 64)
cd.Data[5], _ = strconv.ParseFloat(cd.Data[5].(string), 64)
cd.Data[6], _ = strconv.ParseFloat(cd.Data[6].(string), 64)
sm, err := co.CandleList.RPush(&cd)
if err == nil {
now := time.Now().UnixMilli()
co.LastUpdateTime = now
co.CandleList.LastUpdateTime = now
co.UpdateNickName = GetRandomString(12)
co.CandleList.UpdateNickName = GetRandomString(12)
2024-12-15 17:40:14 +08:00
}
return &sm, err
}
mx := MaX{}
if ctype == "ma7" {
json.Unmarshal(spjs, &mx)
sm, err := co.Ma7List.RPush(&mx)
if err == nil {
now := time.Now().UnixMilli()
co.LastUpdateTime = now
co.Ma7List.UpdateNickName = GetRandomString(12)
2024-12-15 17:40:14 +08:00
co.Ma7List.LastUpdateTime = now
}
return &sm, err
}
if ctype == "ma30" {
json.Unmarshal(spjs, &mx)
sm, err := co.Ma30List.RPush(&mx)
// bj, _ := json.Marshal(co)
if err == nil {
now := time.Now().UnixMilli()
co.LastUpdateTime = now
co.Ma30List.UpdateNickName = GetRandomString(12)
2024-12-15 17:40:14 +08:00
co.Ma30List.LastUpdateTime = now
}
return &sm, err
}
return nil, nil
}
func (co *Coaster) SetToKey(cr *Core) (string, error) {
co.CandleList.RecursiveBubbleS(len(co.CandleList.List), "asc")
co.Ma7List.RecursiveBubbleS(len(co.Ma7List.List), "asc")
co.Ma30List.RecursiveBubbleS(len(co.Ma30List.List), "asc")
js, _ := json.Marshal(*co)
coasterName := co.InstID + "|" + co.Period + "|coaster"
res, err := cr.RedisLocalCli.Set(coasterName, string(js), 0).Result()
return res, err
}
func (coi *CoasterInfo) Process(cr *Core) {
curCo, _ := cr.GetCoasterFromPlate(coi.InstID, coi.Period)
go func(co Coaster) {
//这里执行创建一个tray对象,用现有的co的数据计算和填充其listMap
// TODO 发到一个channel里来执行下面的任务
allow := os.Getenv("SARDINE_MAKESERIES") == "true"
if !allow {
return
}
srs, err := co.UpdateTray(cr)
if err != nil || srs == nil {
logrus.Warn("tray err: ", err)
return
}
_, err = srs.SetToKey(cr)
if err != nil {
logrus.Warn("srs SetToKey err: ", err)
return
}
//实例化完一个tray之后拿着这个tray去执行Analytics方法
//
// srsinfo := SeriesInfo{
// InstID: curCo.InstID,
// Period: curCo.Period,
// }
//
// cr.SeriesChan <- &srsinfo
2024-12-15 17:40:14 +08:00
}(curCo)
go func(co Coaster) {
// 每3次会有一次触发缓存落盘
// run := utils.Shaizi(3)
// if run {
_, err := co.SetToKey(cr)
if err != nil {
logrus.Warn("coaster process err: ", err)
fmt.Println("coaster SetToKey err: ", err)
}
// }
}(curCo)
}
// TODO 类似于InsertIntoPlate函数照猫画虎就行了
func (co *Coaster) UpdateTray(cr *Core) (*Series, error) {
cr.Mu1.Lock()
defer cr.Mu1.Unlock()
//尝试从内存读取tray对象
tr, trayFounded := cr.TrayMap[co.InstID]
if !trayFounded {
tr1, err := co.LoadTray(cr)
if err != nil {
return nil, err
}
cr.TrayMap[co.InstID] = tr1
tr = tr1
}
srs, seriesFounded := tr.SeriesMap["period"+co.Period]
err := errors.New("")
if !seriesFounded {
srs1, err := tr.NewSeries(cr, co.Period)
if err != nil {
return nil, err
}
tr.SeriesMap["period"+co.Period] = srs1
} else {
err = srs.Refresh(cr)
}
// if err == nil {
// bj, _ := json.Marshal(srs)
// logrus.Debug("series:,string"(bj))
// }
return srs, err
}
// TODO
func (co *Coaster) LoadTray(cr *Core) (*Tray, error) {
tray := Tray{}
tray.Init(co.InstID)
prs := cr.Cfg.Config.Get("candleDimentions").MustArray()
for _, v := range prs {
tray.NewSeries(cr, v.(string))
}
return &tray, nil
}