From e29a3b9d557528f80a2eee21caa8dd95d5553137 Mon Sep 17 00:00:00 2001 From: yuriy0803 <68668177+yuriy0803@users.noreply.github.com> Date: Wed, 14 Apr 2021 12:23:26 +0200 Subject: [PATCH] Charts Share and Diff =) --- api.json | 12 +- api/server.go | 69 ++++++- storage/redis.go | 144 ++++++++++++++ www/app/controllers/account/index.js | 283 ++++++++++++++++++++++++++- www/app/controllers/index.js | 191 +++++++++++++++++- www/app/templates/account/index.hbs | 1 + www/app/templates/index.hbs | 7 +- 7 files changed, 687 insertions(+), 20 deletions(-) diff --git a/api.json b/api.json index 13fbb3e..95ea16e 100644 --- a/api.json +++ b/api.json @@ -64,14 +64,18 @@ "poolCharts":"*/20 * * * *", "poolChartsNum":74, "minerCharts":"*/20 * * * *", - "minerChartsNum":74 + "minerChartsNum":74, + "netCharts":"*/20 * * * *", + "netChartsNum":74, + "shareCharts":"*/20 * * * *", + "shareChartsNum":74 }, "upstreamCheckInterval": "5s", "upstream": [ { "name": "main", - "url": "http://192.168.178.26:8545", + "url": "http://192.168.178.30:8545", "timeout": "10s" }, { @@ -103,7 +107,7 @@ "immatureDepth": 20, "keepTxFees": false, "interval": "10m", - "daemon": "http://192.168.178.26:8545", + "daemon": "http://192.168.178.30:8545", "timeout": "10s" }, @@ -113,7 +117,7 @@ "interval": "20m", "daemon": "http://192.168.178.26:8545", "timeout": "10s", - "address": "0xf8d10632dedf8cb9033b1438187a618d08734cc8", + "address": "0x9dd0226060b6d9644066029f4993CB2A40cF775D", "gas": "21000", "gasPrice": "50000000000", "autoGas": true, diff --git a/api/server.go b/api/server.go index 8b88e86..69cf037 100644 --- a/api/server.go +++ b/api/server.go @@ -23,8 +23,12 @@ type ApiConfig struct { Listen string `json:"listen"` PoolCharts string `json:"poolCharts"` PoolChartsNum int64 `json:"poolChartsNum"` + NetCharts string `json:"netCharts"` + NetChartsNum int64 `json:"netChartsNum"` MinerChartsNum int64 `json:"minerChartsNum"` MinerCharts string `json:"minerCharts"` + ShareCharts string `json:"shareCharts"` + ShareChartsNum int64 `json:"shareChartsNum"` StatsCollectInterval string `json:"statsCollectInterval"` HashrateWindow string `json:"hashrateWindow"` HashrateLargeWindow string `json:"hashrateLargeWindow"` @@ -106,13 +110,19 @@ func (s *ApiServer) Start() { c := cron.New() poolCharts := s.config.PoolCharts - log.Printf("pool charts config is :%v", poolCharts) + log.Printf("Pool charts config is :%v", poolCharts) c.AddFunc(poolCharts, func() { s.collectPoolCharts() }) + netCharts := s.config.NetCharts + log.Printf("Net charts config is :%v", netCharts) + c.AddFunc(netCharts, func() { + s.collectnetCharts() + }) + minerCharts := s.config.MinerCharts - log.Printf("miner charts config is :%v", minerCharts) + log.Printf("Miner charts config is :%v", minerCharts) c.AddFunc(minerCharts, func() { miners, err := s.backend.GetAllMinerAccount() @@ -124,6 +134,20 @@ func (s *ApiServer) Start() { s.collectMinerCharts(login, miner["currentHashrate"].(int64), miner["hashrate"].(int64), miner["workersOnline"].(int64)) } }) + ///test share chart + shareCharts := s.config.ShareCharts + log.Printf("Share charts config is :%v", shareCharts) + c.AddFunc(shareCharts, func() { + miners, err := s.backend.GetAllMinerAccount() + if err != nil { + log.Println("Get all miners account error: ", err) + } + for _, login := range miners { + miner, _ := s.backend.CollectWorkersStats(s.hashrateWindow, s.hashrateLargeWindow, login) + s.collectshareCharts(login, miner["workersOnline"].(int64)) + } + + }) c.Start() }() @@ -149,6 +173,28 @@ func (s *ApiServer) collectPoolCharts() { } } +func (s *ApiServer) collectnetCharts() { + ts := util.MakeTimestamp() / 1000 + now := time.Now() + year, month, day := now.Date() + hour, min, _ := now.Clock() + t2 := fmt.Sprintf("%d-%02d-%02d %02d_%02d", year, month, day, hour, min) + //stats := s.getStats() + //diff := fmt.Sprint(stats["difficulty"]) + nodes, erro := s.backend.GetNodeStates() + if erro != nil { + log.Printf("Failed to fetch Diff charts from backend: %v", erro) + return + } + diff := fmt.Sprint(nodes[0]["difficulty"]) + log.Println("Difficulty Hash is ", ts, t2, diff) + err := s.backend.WriteDiffCharts(ts, t2, diff) + if err != nil { + log.Printf("Failed to fetch Diff charts from backend: %v", err) + return + } +} + func (s *ApiServer) collectMinerCharts(login string, hash int64, largeHash int64, workerOnline int64) { ts := util.MakeTimestamp() / 1000 now := time.Now() @@ -163,6 +209,21 @@ func (s *ApiServer) collectMinerCharts(login string, hash int64, largeHash int64 } } +func (s *ApiServer) collectshareCharts(login string, workerOnline int64) { + ts := util.MakeTimestamp() / 1000 + now := time.Now() + year, month, day := now.Date() + hour, min, _ := now.Clock() + t2 := fmt.Sprintf("%d-%02d-%02d %02d_%02d", year, month, day, hour, min) + + log.Println("Share chart is created", ts, t2) + + err := s.backend.WriteShareCharts(ts, t2, login, 0, 0, workerOnline) + if err != nil { + log.Printf("Failed to fetch miner %v charts from backend: %v", login, err) + } +} + func (s *ApiServer) listen() { r := mux.NewRouter() r.HandleFunc("/api/finders", s.FindersIndex) @@ -210,6 +271,7 @@ func (s *ApiServer) collectStats() { return } } + stats["netCharts"], err = s.backend.GetNetCharts(s.config.NetChartsNum) stats["poolCharts"], err = s.backend.GetPoolCharts(s.config.PoolChartsNum) s.stats.Store(stats) log.Printf("Stats collection finished %s", time.Since(start)) @@ -258,6 +320,8 @@ func (s *ApiServer) StatsIndex(w http.ResponseWriter, r *http.Request) { reply["immatureTotal"] = stats["immatureTotal"] reply["candidatesTotal"] = stats["candidatesTotal"] reply["exchangedata"] = stats["exchangedata"] + reply["netCharts"] = stats["netCharts"] + reply["workersTotal"] = stats["workersTotal"] } err = json.NewEncoder(w).Encode(reply) @@ -377,6 +441,7 @@ func (s *ApiServer) AccountIndex(w http.ResponseWriter, r *http.Request) { stats["pageSize"] = s.config.Payments stats["exchangedata"] = generalstats["exchangedata"] stats["minerCharts"], err = s.backend.GetMinerCharts(s.config.MinerChartsNum, login) + stats["shareCharts"], err = s.backend.GetShareCharts(s.config.ShareChartsNum, login) stats["paymentCharts"], err = s.backend.GetPaymentCharts(login) reply = &Entry{stats: stats, updatedAt: now} s.miners[login] = reply diff --git a/storage/redis.go b/storage/redis.go index 03fdb4e..52d3dd2 100644 --- a/storage/redis.go +++ b/storage/redis.go @@ -97,6 +97,20 @@ type BlockData struct { immatureKey string } +type NetCharts struct { + Timestamp int64 `json:"x"` + TimeFormat string `json:"timeFormat"` + NetHash int64 `json:"y"` +} + +type ShareCharts struct { + Timestamp int64 `json:"x"` + TimeFormat string `json:"timeFormat"` + Valid int64 `json:"valid"` + Stale int64 `json:"stale"` + WorkerOnline string `json:"workerOnline"` +} + func (b *BlockData) RewardInShannon() int64 { reward := new(big.Int).Div(b.Reward, util.Shannon) return reward.Int64() @@ -185,12 +199,65 @@ func (r *RedisClient) WritePoolCharts(time1 int64, time2 string, poolHash string return cmd.Err() } +func (r *RedisClient) WriteDiffCharts(time1 int64, time2 string, netHash string) error { + s := join(time1, time2, netHash) + cmd := r.client.ZAdd(r.formatKey("charts", "difficulty"), redis.Z{Score: float64(time1), Member: s}) + return cmd.Err() +} + func (r *RedisClient) WriteMinerCharts(time1 int64, time2, k string, hash, largeHash, workerOnline int64) error { s := join(time1, time2, hash, largeHash, workerOnline) cmd := r.client.ZAdd(r.formatKey("charts", "miner", k), redis.Z{Score: float64(time1), Member: s}) return cmd.Err() } +func (r *RedisClient) WriteShareCharts(time1 int64, time2, login string, valid, stale, workerOnline int64) error { + valid_s := r.client.HGet(r.formatKey("chartsNum", "share", login), "valid") + stale_s := r.client.HGet(r.formatKey("chartsNum", "share", login), "stale") + + if valid_s.Err() == redis.Nil || stale_s.Err() == redis.Nil { + r.client.HSet(r.formatKey("chartsNum", "share", login), "valid", strconv.FormatInt(0, 10)) + r.client.HSet(r.formatKey("chartsNum", "share", login), "stale", strconv.FormatInt(0, 10)) + //return nil, nil + } else if valid_s.Err() != nil || stale_s.Err() != nil { + r.client.HSet(r.formatKey("chartsNum", "share", login), "valid", strconv.FormatInt(0, 10)) + r.client.HSet(r.formatKey("chartsNum", "share", login), "stale", strconv.FormatInt(0, 10)) + //return nil, valid_s.Err() + } + + v_s, _ := valid_s.Int64() + s_s, _ := stale_s.Int64() + + l_valid := r.client.HGet(r.formatKey("chartsNum", "share", login), "lastvalid") + l_stale := r.client.HGet(r.formatKey("chartsNum", "share", login), "laststale") + + if l_valid.Err() == redis.Nil || l_stale.Err() == redis.Nil { + r.client.HSet(r.formatKey("chartsNum", "share", login), "lastvalid", strconv.FormatInt(0, 10)) + r.client.HSet(r.formatKey("chartsNum", "share", login), "laststale", strconv.FormatInt(0, 10)) + //return nil, nil + } else if l_valid.Err() != nil || l_stale.Err() != nil { + r.client.HSet(r.formatKey("chartsNum", "share", login), "lastvalid", strconv.FormatInt(0, 10)) + r.client.HSet(r.formatKey("chartsNum", "share", login), "laststale", strconv.FormatInt(0, 10)) + //return nil, l_valid.Err() + } + l_v, _ := l_valid.Int64() + l_s, _ := l_stale.Int64() + + valid_c := v_s - l_v + stale_c := s_s - l_s + s := join(time1, time2, valid_c, stale_c, workerOnline) + cmd := r.client.ZAdd(r.formatKey("charts", "share", login), redis.Z{Score: float64(time1), Member: s}) + + tx := r.client.Multi() + defer tx.Close() + tx.Exec(func() error { + tx.HSet(r.formatKey("chartsNum", "share", login), "lastvalid", strconv.FormatInt(v_s, 10)) + tx.HSet(r.formatKey("chartsNum", "share", login), "laststale", strconv.FormatInt(s_s, 10)) + return nil + }) + return cmd.Err() +} + func (r *RedisClient) GetPoolCharts(poolHashLen int64) (stats []*PoolCharts, err error) { tx := r.client.Multi() @@ -230,6 +297,46 @@ func convertPoolChartsResults(raw *redis.ZSliceCmd) []*PoolCharts { return reverse } +func (r *RedisClient) GetNetCharts(netHashLen int64) (stats []*NetCharts, err error) { + + tx := r.client.Multi() + defer tx.Close() + + now := util.MakeTimestamp() / 1000 + + cmds, err := tx.Exec(func() error { + tx.ZRemRangeByScore(r.formatKey("charts", "difficulty"), "-inf", fmt.Sprint("(", now-172800)) + tx.ZRevRangeWithScores(r.formatKey("charts", "difficulty"), 0, netHashLen) + return nil + }) + + if err != nil { + return nil, err + } + + stats = convertNetChartsResults(cmds[1].(*redis.ZSliceCmd)) + return stats, nil +} + +func convertNetChartsResults(raw *redis.ZSliceCmd) []*NetCharts { + var result []*NetCharts + for _, v := range raw.Val() { + // "Timestamp:TimeFormat:Hash" + pc := NetCharts{} + pc.Timestamp = int64(v.Score) + str := v.Member.(string) + pc.TimeFormat = str[strings.Index(str, ":")+1 : strings.LastIndex(str, ":")] + pc.NetHash, _ = strconv.ParseInt(str[strings.LastIndex(str, ":")+1:], 10, 64) + result = append(result, &pc) + } + + var reverse []*NetCharts + for i := len(result) - 1; i >= 0; i-- { + reverse = append(reverse, result[i]) + } + return reverse +} + func convertMinerChartsResults(raw *redis.ZSliceCmd) []*MinerCharts { var result []*MinerCharts for _, v := range raw.Val() { @@ -290,6 +397,43 @@ func (r *RedisClient) GetMinerCharts(hashNum int64, login string) (stats []*Mine return stats, nil } +func (r *RedisClient) GetShareCharts(shareNum int64, login string) (stats []*ShareCharts, err error) { + + tx := r.client.Multi() + defer tx.Close() + now := util.MakeTimestamp() / 1000 + cmds, err := tx.Exec(func() error { + tx.ZRemRangeByScore(r.formatKey("charts", "share", login), "-inf", fmt.Sprint("(", now-172800)) + tx.ZRevRangeWithScores(r.formatKey("charts", "share", login), 0, shareNum) + return nil + }) + if err != nil { + return nil, err + } + stats = convertShareChartsResults(cmds[1].(*redis.ZSliceCmd)) + return stats, nil +} + +func convertShareChartsResults(raw *redis.ZSliceCmd) []*ShareCharts { + var result []*ShareCharts + for _, v := range raw.Val() { + + mc := ShareCharts{} + mc.Timestamp = int64(v.Score) + str := v.Member.(string) + mc.TimeFormat = strings.Split(str, ":")[1] + mc.Valid, _ = strconv.ParseInt(strings.Split(str, ":")[2], 10, 64) + mc.Stale, _ = strconv.ParseInt(strings.Split(str, ":")[3], 10, 64) + mc.WorkerOnline = strings.Split(str, ":")[4] + result = append(result, &mc) + } + var reverse []*ShareCharts + for i := len(result) - 1; i >= 0; i-- { + reverse = append(reverse, result[i]) + } + return reverse +} + func (r *RedisClient) GetPaymentCharts(login string) (stats []*PaymentCharts, err error) { tx := r.client.Multi() diff --git a/www/app/controllers/account/index.js b/www/app/controllers/account/index.js index 6511969..5d3d694 100644 --- a/www/app/controllers/account/index.js +++ b/www/app/controllers/account/index.js @@ -5,6 +5,7 @@ export default Ember.Controller.extend({ netstats: Ember.computed.reads('applicationController'), stats: Ember.computed.reads('applicationController.model.stats'), config: Ember.computed.reads('applicationController.config'), + hashrate: Ember.computed.reads('applicationController.hashrate'), chartOptions: Ember.computed("model.hashrate", { get() { @@ -15,7 +16,7 @@ export default Ember.Controller.extend({ backgroundColor: "rgba(255, 255, 255, 0.1)", type: "spline", marginRight: 10, - height: 200, + height: 290, events: { load: function() { var series = this.series[0]; @@ -30,8 +31,67 @@ export default Ember.Controller.extend({ title: { text: "" }, + ////// + rangeSelector : { + enabled: true, + selected: 4, + allButtonsEnabled: true, + inputDateFormat: '%Y/%m/%d %H:%M', + inputEditDateFormat: '%Y/%m/%d %H:%M', + inputEnabled: false, + buttons: [{ + type: 'hour', + count: 1, + text: '1h' + }, + { + type: 'hour', + count: 2, + text: '2h' + }, + { + type: 'hour', + count: 4, + text: '4h' + }, + { + type: 'hour', + count: 6, + text: '6h' + }, + { + type: 'hour', + count: 12, + text: '12h' + }, + { + type: 'all', + text: 'All' + } + ], + }, + navigator: { + enabled: true + }, + credits: { + enabled: false, + position: { + align: 'right', + x: -10, + verticalAlign: 'bottom', + y: -5 + }, + href: "https://highcharts.com", + text: "Highcharts" + }, + /////// xAxis: { ordinal: false, + labels: { + style: { + color: "#000" + } + }, type: "datetime", dateTimeLabelFormats: { millisecond: "%H:%M:%S", @@ -46,7 +106,15 @@ export default Ember.Controller.extend({ }, yAxis: { title: { - text: "Hashrate by Account" + text: "Hashrate", + style: { + color: "#000" + }, + }, + labels: { + style: { + color: "#000" + } }, //softMin: e.getWithDefault("model.currentHashrate") / 1000000, //softMax: e.getWithDefault("model.currentHashrate") / 1000000, @@ -57,7 +125,11 @@ export default Ember.Controller.extend({ color: "#808080" }], legend: { - enabled: true + enabled: true, + itemStyle: + { + color: "#000" + }, }, tooltip: { formatter: function() { @@ -68,10 +140,10 @@ export default Ember.Controller.extend({ useHTML: true }, exporting: { - enabled: false + enabled: true }, series: [{ - color: "#E99002", + color: "#15BD27", name: "3 hours average hashrate", data: function() { var e, a = []; @@ -100,6 +172,7 @@ export default Ember.Controller.extend({ }() }, { name: "30 minutes average hashrate", + color: "#E99002", data: function() { var e, a = []; if (null != t) { @@ -125,6 +198,206 @@ export default Ember.Controller.extend({ } return a; }() + + }] + }; + return a; + } + }), + + shareChart: Ember.computed("model.hashrate", { + get() { + var e = this, + t = e.getWithDefault("model.shareCharts"), + a = { + chart: { + backgroundColor: "rgba(255, 255, 255, 0.1)", + type: "column", + marginRight: 10, + height: 180 + // events: { + /* load: function() { + var series = this.series[0]; + setInterval(function() { + var x = (new Date()).getTime(), + y = e.getWithDefault("model.workersOnline") / 1000000; + series.addPoint([x, y], true, true); + }, 1090000000); + } */ + // } + }, + title: { + text: "" + }, + xAxis: { + ordinal: false, + labels: { + style: { + color: "#000" + } + }, + type: "datetime", + dateTimeLabelFormats: { + millisecond: "%H:%M:%S", + second: "%H:%M:%S", + minute: "%H:%M", + hour: "%H:%M", + day: "%e. %b", + week: "%e. %b", + month: "%b '%y", + year: "%Y" + } + }, + //rangeSelector: { + // selected: 1, + // }, + yAxis: { + title: { + text: "Shares", + style: { + color: "#000" + }, + }, + labels: { + style: { + color: "#000" + } + } + //softMin: e.getWithDefault("model.currentHashrate") / 1000000, + //softMax: e.getWithDefault("model.currentHashrate") / 1000000, + }, + plotOptions: { + series: { + marginleft: 0, + pointWidth: 10 + // marker: { + // enabled: false + // } + }, + column: { + stacking: 'normal', + grouping: false + //shadow: false + //borderWidth: 0 + } + }, + plotLines: [{ + value: 0, + width: 1, + color: "#aaaaaa" + }], + legend: { + enabled: true, + itemStyle: + { + color: "#000" + }, + }, + tooltip: { + formatter: function() { + return this.y > 1000000000000 ? "" + this.point.d + "
Shares " + (this.y / 1000000000000) + "
" : this.y > 1000000000 ? "" + this.point.d + "
Shares " + (this.y / 1000000000) + "
" : this.y > 1000000 ? "" + this.point.d + "
Shares " + (this.y / 1000000) + "
" : "" + this.point.d + "
Shares " + this.y + ""; + + }, + + useHTML: true + }, + exporting: { + enabled: false + }, + series: [{ + color: "#15BD27", + name: "Valid share", + data: function() { + var e, a = []; + if (null != t) { + for (e = 0; e <= t.length - 1; e += 1) { + var n = 0, + r = 0, + l = 0; + r = new Date(1e3 * t[e].x); + l = r.toLocaleString(); + n = t[e].valid; + a.push({ + x: r, + d: l, + y: n + }); + } + } else { + a.push({ + x: 0, + d: 0, + y: 0 + }); + } + return a; + }() + + }, { + + name: "Stale share", + color: "#E99002", + data: function() { + var e, a = []; + if (null != t) { + for (e = 0; e <= t.length - 1; e += 1) { + var n = 0, + r = 0, + l = 0; + r = new Date(1e3 * t[e].x); + l = r.toLocaleString(); + n = t[e].stale; + a.push({ + x: r, + d: l, + y: n + }); + } + } else { + a.push({ + x: 0, + d: 0, + y: 0 + }); + } + return a; + }() + + /* }, { + + name: "Workers", + color: "#FF0000", + type: 'spline', + plotLines: [{ + // value: 0, + width: 1, + color: "#aaaaaa" + }], + data: function() { + var e, a = []; + if (null != t) { + for (e = 0; e <= t.length - 1; e += 1) { + var n = 0, + r = 0, + l = 0; + r = new Date(1e3 * t[e].x); + l = r.toLocaleString(); + n = t[e].workerOnline; + a.push({ + x: r, + d: l, + y: n + }); + } + } else { + a.push({ + x: 0, + d: 0, + y: 0 + }); + } + return a; + }() */ }] }; return a; diff --git a/www/app/controllers/index.js b/www/app/controllers/index.js index 2960479..34656a2 100644 --- a/www/app/controllers/index.js +++ b/www/app/controllers/index.js @@ -15,6 +15,7 @@ export default Ember.Controller.extend({ return value; } }), + chartOptions: Ember.computed("model.hashrate", { get() { var e = this, @@ -23,7 +24,7 @@ export default Ember.Controller.extend({ chart: { backgroundColor: "rgba(255, 255, 255, 0.1)", type: "spline", - height: 300, + height: 220, marginRight: 10, events: { load: function() { @@ -36,7 +37,10 @@ export default Ember.Controller.extend({ } }, title: { - text: "Our pool's hashrate" + text: "Pool Hashrate", + style: { + color: "#000" + } }, xAxis: { labels: { @@ -64,10 +68,10 @@ export default Ember.Controller.extend({ plotLines: [{ value: 0, width: 1, - color: "#000" + color: "#ccc" }], legend: { - enabled: false + enabled: true }, tooltip: { formatter: function() { @@ -75,9 +79,9 @@ export default Ember.Controller.extend({ }, useHTML: true }, - exporting: { - enabled: false - }, + exporting: { + enabled: false + }, series: [{ color: "#15BD27", name: "Hashrate", @@ -109,5 +113,178 @@ export default Ember.Controller.extend({ }; return a; } + }), + + chartDiff: Ember.computed("model.hashrate", { + get() { + var e = this, + t = e.getWithDefault("stats.model.netCharts"), + a = { + chart: { + backgroundColor: "rgba(255, 255, 255, 0.1)", + type: "spline", + height: 250, + marginRight: 10, + //zoomType: 'xy', + /* events: { + load: function() { + var series = this.series[0]; + setInterval(function() { + var x = (new Date()).getTime(), y = e.getWithDefault("difficulty") / 1000000; + series.addPoint([x, y], true, true); + }, 1090000000); + } + } */ + }, + title: { + text: "Network Difficulty", + style: { + color: "#000" + } + }, + rangeSelector : { + enabled: true, + selected: 4, + allButtonsEnabled: true, + inputDateFormat: '%Y/%m/%d %H:%M', + inputEditDateFormat: '%Y/%m/%d %H:%M', + inputEnabled: false, + buttons: [{ + type: 'hour', + count: 1, + text: '1h' + }, + { + type: 'hour', + count: 2, + text: '2h' + }, + { + type: 'hour', + count: 4, + text: '4h' + }, + { + type: 'hour', + count: 6, + text: '6h' + }, + { + type: 'hour', + count: 12, + text: '12h' + }, + { + type: 'all', + text: 'All' + } + ], + }, + navigator: { + enabled: true + }, + /* scrollbar: { + enabled:true, + barBackgroundColor: 'gray', + barBorderRadius: 7, + barBorderWidth: 0, + buttonBackgroundColor: 'gray', + buttonBorderWidth: 0, + buttonArrowColor: 'yellow', + buttonBorderRadius: 7, + rifleColor: 'yellow', + trackBackgroundColor: 'white', + trackBorderWidth: 1, + trackBorderColor: 'silver', + trackBorderRadius: 7 + + + }, */ + credits: { + enabled: false, + position: { + align: 'right', + x: -10, + verticalAlign: 'bottom', + y: -5 + }, + href: "https://highcharts.com", + text: "Highcharts" + }, + xAxis: { + + labels: { + style: { + color: "#000" + } + //minRange: 1 + }, + ordinal: false, + type: "datetime" + }, + yAxis: { + + title: { + text: "DIFFICULTY", + style: { + color: "#000" + } + }, + + labels: { + style: { + color: "#000" + } + } + }, + plotLines: [{ + value: 0, + width: 1, + color: "#000" + }], + legend: { + enabled: false + }, + tooltip: { + formatter: function() { + return this.y > 1000000000000 ? "" + this.point.d + "
Difficulty " + (this.y / 1000000000000).toFixed(2) + " TH/s
" : this.y > 1000000000 ? "" + this.point.d + "
Difficulty " + (this.y / 1000000000).toFixed(2) + " GH/s
" : this.y > 1000000 ? "" + this.point.d + "
Difficulty " + (this.y / 1000000).toFixed(2) + " MH/s
" : "" + this.point.d + "
Difficulty " + this.y.toFixed(2) + " H/s"; + }, + useHTML: true + }, + exporting: { + enabled: true + }, + series: [{ + color: "#F87217", + name: "Difficulty", + data: function() { + var e, a = []; + if (null != t) { + for (e = 0; e <= t.length - 1; e += 1) { + var n = 0, + r = 0, + l = 0; + r = new Date(1e3 * t[e].x); + l = r.toLocaleString(); + n = t[e].y; a.push({ + x: r, + d: l, + y: n + }); + } + } else { + a.push({ + x: 0, + d: 0, + y: 0 + }); + } + return a; + }() + + }] + }; + return a; + } }) }); \ No newline at end of file diff --git a/www/app/templates/account/index.hbs b/www/app/templates/account/index.hbs index a5f29df..bf3137e 100644 --- a/www/app/templates/account/index.hbs +++ b/www/app/templates/account/index.hbs @@ -1,5 +1,6 @@
{{high-charts mode=chartMode chartOptions=chartOptions content=chartData}} +{{high-charts mode=chartMode chartOptions=shareChart content=chartData}} {{#if model.workers}}

Your Workers

diff --git a/www/app/templates/index.hbs b/www/app/templates/index.hbs index 9d71c73..8cfc405 100644 --- a/www/app/templates/index.hbs +++ b/www/app/templates/index.hbs @@ -47,9 +47,12 @@
+
+ {{high-charts mode=mode chartOptions=chartOptions content=chartData}} +
- {{high-charts mode=chartMode chartOptions=chartOptions content=chartData}} -
+ {{high-charts mode=mode chartOptions=chartDiff content=chartData}} +
{{#if (equals config.Network 'mordor')}}