From 9229fac02ae1d120675cc6db72b5e8053a12d041 Mon Sep 17 00:00:00 2001
From: yuriy0803 <68668177+yuriy0803@users.noreply.github.com>
Date: Tue, 2 Mar 2021 23:48:27 +0100
Subject: [PATCH] block charts
---
api/server.go | 2 +
storage/redis.go | 48 +++++++++
www/app/controllers/blocks.js | 177 ++++++++++++++++++++++++++++++++++
www/app/templates/blocks.hbs | 1 +
4 files changed, 228 insertions(+)
create mode 100644 www/app/controllers/blocks.js
diff --git a/api/server.go b/api/server.go
index 06ec0f8..280725b 100644
--- a/api/server.go
+++ b/api/server.go
@@ -204,6 +204,7 @@ func (s *ApiServer) collectStats() {
}
if len(s.config.LuckWindow) > 0 {
stats["luck"], err = s.backend.CollectLuckStats(s.config.LuckWindow)
+ stats["luckCharts"], err = s.backend.CollectLuckCharts(s.config.LuckWindow[0])
if err != nil {
log.Printf("Failed to fetch luck stats from backend: %v", err)
return
@@ -301,6 +302,7 @@ func (s *ApiServer) BlocksIndex(w http.ResponseWriter, r *http.Request) {
reply["candidates"] = stats["candidates"]
reply["candidatesTotal"] = stats["candidatesTotal"]
reply["luck"] = stats["luck"]
+ reply["luckCharts"] = stats["luckCharts"]
}
err := json.NewEncoder(w).Encode(reply)
diff --git a/storage/redis.go b/storage/redis.go
index 7186bb3..a218d84 100644
--- a/storage/redis.go
+++ b/storage/redis.go
@@ -4,6 +4,7 @@ import (
"fmt"
"math"
"math/big"
+ "sort"
"strconv"
"strings"
"time"
@@ -46,6 +47,15 @@ type PaymentCharts struct {
Amount int64 `json:"amount"`
}
+type LuckCharts struct {
+ Timestamp int64 `json:"x"`
+ Height int64 `json:"height"`
+ Difficulty int64 `json:"difficulty"`
+ Shares int64 `json:"shares"`
+ SharesDiff float64 `json:"sharesDiff"`
+ Reward string `json:"reward"`
+}
+
type SumRewardData struct {
Interval int64 `json:"inverval"`
Reward int64 `json:"reward"`
@@ -1102,6 +1112,44 @@ func (r *RedisClient) CollectLuckStats(windows []int) (map[string]interface{}, e
return stats, nil
}
+func (r *RedisClient) CollectLuckCharts(max int) (stats []*LuckCharts, err error) {
+ var result []*LuckCharts
+ tx := r.client.Multi()
+ defer tx.Close()
+
+ cmds, err := tx.Exec(func() error {
+ tx.ZRevRangeWithScores(r.formatKey("blocks", "matured"), 0, int64(max-1))
+ return nil
+ })
+ if err != nil {
+ return result, err
+ }
+ blocks := convertBlockResults(cmds[0].(*redis.ZSliceCmd))
+
+ for i, block := range blocks {
+ if i > (max - 1) {
+ break
+ }
+ lc := LuckCharts{}
+ var sharesDiff = float64(block.TotalShares) / float64(block.Difficulty)
+ lc.Timestamp = block.Timestamp
+ lc.Height = block.RoundHeight
+ lc.Difficulty = block.Difficulty
+ lc.Shares = block.TotalShares
+ lc.SharesDiff = sharesDiff
+ lc.Reward = block.RewardString
+ result = append(result, &lc)
+ }
+ sort.Sort(TimestampSorter(result))
+ return result, nil
+}
+
+type TimestampSorter []*LuckCharts
+
+func (a TimestampSorter) Len() int { return len(a) }
+func (a TimestampSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a TimestampSorter) Less(i, j int) bool { return a[i].Timestamp < a[j].Timestamp }
+
func convertCandidateResults(raw *redis.ZSliceCmd) []*BlockData {
var result []*BlockData
for _, v := range raw.Val() {
diff --git a/www/app/controllers/blocks.js b/www/app/controllers/blocks.js
new file mode 100644
index 0000000..4fc69a8
--- /dev/null
+++ b/www/app/controllers/blocks.js
@@ -0,0 +1,177 @@
+import Ember from 'ember';
+
+export default Ember.Controller.extend({
+ applicationController: Ember.inject.controller('application'),
+ config: Ember.computed.reads('applicationController.config'),
+ settings: Ember.computed.reads('applicationController.model.settings'),
+
+ BlockUnlockDepth: Ember.computed('settings', {
+ get() {
+ var depth = this.get('settings.BlockUnlockDepth');
+ if (depth) {
+ return depth;
+ }
+ return this.get('config').BlockUnlockDepth;
+ }
+ }),
+
+ chartOptions: Ember.computed("model.luckCharts", {
+ get() {
+ var e = this,
+ t = e.getWithDefault("model.luckCharts"),
+ a = {
+ colors: ['#f45b5b', '#8085e9', '#8d4654', '#7798BF', '#aaeeee',
+ '#ff0066', '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'],
+ chart: {
+ backgroundColor: "rgba(255, 255, 255, 0.1)",
+ marginRight: 10,
+ height: 200,
+ events: {
+ load: function() {
+ var series = this.series[0];
+ setInterval(function() {
+ var x = (new Date()).getTime(),
+ y = e.getWithDefault("model.luckCharts.difficulty");
+ series.addPoint([x, y], true, true);
+ }, 1090000000);
+ }
+ }
+ },
+ title: {
+ text: ""
+ },
+ xAxis: {
+ labels: {
+ style: {
+ color: '#6e6e70'
+ }
+ },
+ ordinal: false,
+ 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"
+ }
+ },
+ yAxis: {
+ labels: {
+ style: {
+ color: '#6e6e70'
+ }
+ },
+ title: {
+ text: "shares and difficulty",
+ style: {
+ color: 'black',
+ fontSize: '16px',
+ fontWeight: 'bold'
+ }
+ },
+ softMax: 100,
+ },
+ plotLines: [{
+ value: 0,
+ width: 1,
+ color: "#808080"
+ }],
+ plotOptions: {
+ series: {
+ shadow: true
+ },
+ candlestick: {
+ lineColor: '#404048'
+ },
+ map: {
+ shadow: false
+ }
+ },
+ legend: {
+ enabled: true
+ },
+ tooltip: {
+ formatter: function() {
+ var ss = this.y > 1000000000000 ? "" + (this.y / 1000000000000).toFixed(2) + " TH" : this.y > 1000000000 ? "" + (this.y / 1000000000).toFixed(2) + " GH" : this.y > 1000000 ? "" + (this.y / 1000000).toFixed(2) + " MH" : this.y > 1000 ? "" + (this.y / 1000).toFixed(2) + " KH" : "" + this.y.toFixed(2) + " H";
+ return ss + "
Number: " + this.point.h + "
" + this.point.d + "
Reward: " + (this.point.w/1000000000000000000).toFixed(8) + e.get('config.Unit') + "
Variance: " + (this.point.s*100).toFixed(2)+ "%";
+ },
+
+ useHTML: true
+ },
+ exporting: {
+ enabled: false
+ },
+ series: [{
+ step: 'center',
+ color: "#E99002",
+ 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].difficulty;
+ a.push({
+ x: r,
+ d: l,
+ h: t[e].height,
+ w: t[e].reward,
+ s: t[e].sharesDiff,
+ y: n
+ });
+ }
+ } else {
+ a.push({
+ x: 0,
+ d: 0,
+ y: 0
+ });
+ }
+ return a;
+ }()
+ }, {
+ step: 'center',
+ name: "shares",
+ 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].shares;
+ a.push({
+ x: r,
+ d: l,
+ h: t[e].height,
+ w: t[e].reward,
+ s: t[e].sharesDiff,
+ 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/blocks.hbs b/www/app/templates/blocks.hbs
index b951828..2d36a2d 100644
--- a/www/app/templates/blocks.hbs
+++ b/www/app/templates/blocks.hbs
@@ -9,6 +9,7 @@