Refactor PPLNS window display in miner page
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
2fe65a7a62
commit
d40172d479
|
@ -8,19 +8,29 @@ import (
|
||||||
type PositionChart struct {
|
type PositionChart struct {
|
||||||
totalItems uint64
|
totalItems uint64
|
||||||
bucket []uint64
|
bucket []uint64
|
||||||
|
perBucket int
|
||||||
idle byte
|
idle byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PositionChart) Add(index int, value uint64) {
|
func (p *PositionChart) Add(index int, value uint64) {
|
||||||
if index < 0 || index > int(p.totalItems) {
|
if index < 0 || index >= int(p.totalItems) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(p.bucket) == 1 {
|
if len(p.bucket) == 1 {
|
||||||
p.bucket[0] += value
|
p.bucket[0] += value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
i := uint64(index) * uint64(len(p.bucket)-1) / (p.totalItems - 1)
|
|
||||||
p.bucket[i] += value
|
p.bucket[p.indexOf(index)] += value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PositionChart) indexOf(index int) int {
|
||||||
|
if len(p.bucket) == 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
i := (index*len(p.bucket) - 1) / int(p.totalItems-1)
|
||||||
|
|
||||||
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PositionChart) Total() (result uint64) {
|
func (p *PositionChart) Total() (result uint64) {
|
||||||
|
@ -61,11 +71,28 @@ func (p *PositionChart) String() string {
|
||||||
return string(position)
|
return string(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PositionChart) StringWithoutDelimiters() string {
|
||||||
|
position := make([]byte, len(p.bucket))
|
||||||
|
for i, e := range utils.ReverseSlice(slices.Clone(p.bucket)) {
|
||||||
|
if e > 0 {
|
||||||
|
if e > 9 {
|
||||||
|
position[i] = '+'
|
||||||
|
} else {
|
||||||
|
position[i] = 0x30 + byte(e)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
position[i] = p.idle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(position)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PositionChart) StringWithSeparator(index int) string {
|
func (p *PositionChart) StringWithSeparator(index int) string {
|
||||||
if index < 0 || index > int(p.totalItems) {
|
if index < 0 || index >= int(p.totalItems) {
|
||||||
return p.String()
|
return p.String()
|
||||||
}
|
}
|
||||||
separatorIndex := index * (len(p.bucket) - 1) / int(p.totalItems-1)
|
separatorIndex := p.indexOf(index)
|
||||||
position := make([]byte, 1+2*2+len(p.bucket))
|
position := make([]byte, 1+2*2+len(p.bucket))
|
||||||
position[0], position[1] = '[', '<'
|
position[0], position[1] = '[', '<'
|
||||||
position[2+separatorIndex] = '|'
|
position[2+separatorIndex] = '|'
|
||||||
|
@ -92,9 +119,14 @@ func NewPositionChart(size uint64, totalItems uint64) *PositionChart {
|
||||||
if size < 1 {
|
if size < 1 {
|
||||||
size = 1
|
size = 1
|
||||||
}
|
}
|
||||||
|
perBucket := int(totalItems / size)
|
||||||
|
if totalItems%size > 0 {
|
||||||
|
perBucket += 1
|
||||||
|
}
|
||||||
return &PositionChart{
|
return &PositionChart{
|
||||||
totalItems: totalItems,
|
totalItems: totalItems,
|
||||||
bucket: make([]uint64, size),
|
bucket: make([]uint64, size),
|
||||||
|
perBucket: perBucket,
|
||||||
idle: '.',
|
idle: '.',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
cmd/utils/position_chart_test.go
Normal file
13
cmd/utils/position_chart_test.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestChart(t *testing.T) {
|
||||||
|
p := NewPositionChart(32, 4096)
|
||||||
|
for i := 0; i < 4096; i++ {
|
||||||
|
p.Add(i, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,13 +11,14 @@ type MinerPage struct {
|
||||||
Refresh int
|
Refresh int
|
||||||
Positions struct {
|
Positions struct {
|
||||||
Resolution int
|
Resolution int
|
||||||
|
ResolutionWindow int
|
||||||
SeparatorIndex int
|
SeparatorIndex int
|
||||||
Blocks *cmdutils.PositionChart
|
Blocks *cmdutils.PositionChart
|
||||||
Uncles *cmdutils.PositionChart
|
Uncles *cmdutils.PositionChart
|
||||||
|
BlocksInWindow *cmdutils.PositionChart
|
||||||
|
UnclesInWindow *cmdutils.PositionChart
|
||||||
Payouts *cmdutils.PositionChart
|
Payouts *cmdutils.PositionChart
|
||||||
}
|
}
|
||||||
SharesInWindow int
|
|
||||||
UnclesInWindow int
|
|
||||||
ExpectedRewardPerWindow uint64
|
ExpectedRewardPerWindow uint64
|
||||||
ExpectedRewardPerDay uint64
|
ExpectedRewardPerDay uint64
|
||||||
WindowWeight uint64
|
WindowWeight uint64
|
||||||
|
@ -136,7 +137,7 @@ type MinerPage struct {
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td title="{%s utc_date(p.Miner.LastShareTimestamp) %}">{%s time_elapsed_short(p.Miner.LastShareTimestamp) %}</td>
|
<td title="{%s utc_date(p.Miner.LastShareTimestamp) %}">{%s time_elapsed_short(p.Miner.LastShareTimestamp) %}</td>
|
||||||
<td>{%d p.SharesInWindow %} blocks (+{%d p.UnclesInWindow %} uncles)</td>
|
<td>{%dul p.Positions.BlocksInWindow.Total() %} blocks (+{%dul p.Positions.UnclesInWindow.Total() %} uncles)</td>
|
||||||
{% code windowWeightRatio := float64(p.WindowWeight) / float64(p.Context().Pool.SideChain.Window.Weight.Lo) %}
|
{% code windowWeightRatio := float64(p.WindowWeight) / float64(p.Context().Pool.SideChain.Window.Weight.Lo) %}
|
||||||
<td>{%s si_units(windowWeightRatio * float64(diff_hashrate(p.Context().Pool.SideChain.Difficulty, p.Context().Consensus.TargetBlockTime)), 3) %}H/s</td>
|
<td>{%s si_units(windowWeightRatio * float64(diff_hashrate(p.Context().Pool.SideChain.Difficulty, p.Context().Consensus.TargetBlockTime)), 3) %}H/s</td>
|
||||||
<td>{%f.3 windowWeightRatio*100 %}%</td>
|
<td>{%f.3 windowWeightRatio*100 %}%</td>
|
||||||
|
@ -167,16 +168,30 @@ type MinerPage struct {
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
<h2>Share positions</h2>
|
<h2>Share positions</h2>
|
||||||
<p class="small">
|
<p class="small">
|
||||||
Shares appear on the right, and get older towards the left. The pipe (<code>|</code>) character denotes the current PPLNS window end.
|
Shares appear on the right, and get older towards the left.
|
||||||
<br/>
|
<br/>
|
||||||
Number denotes the amount of shares per slice, with the plus (<code>+</code>) character being more than 9, and dot (<code>.</code>) being none.
|
Number denotes the amount of shares per slice, with the plus (<code>+</code>) character being more than 9, and dot (<code>.</code>) being none.
|
||||||
<br/>
|
<br/>
|
||||||
Each slice accounts for {%d p.Positions.Resolution %} P2Pool blocks, or around {%dul (uint64(p.Positions.Resolution) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes.
|
Each slice accounts for {%d p.Positions.Resolution %} P2Pool blocks, or around {%dul (uint64(p.Positions.Resolution) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes.
|
||||||
</p>
|
</p>
|
||||||
<h3>Shares during last day</h3>
|
<h3>Shares and uncles in PPLNS window</h3>
|
||||||
<code class="mono">{%s p.Positions.Blocks.StringWithSeparator(p.Positions.SeparatorIndex) %}</code>
|
<p class="small">
|
||||||
|
Each slice accounts for {%d p.Positions.ResolutionWindow %} P2Pool block heights, or around {%dul (uint64(p.Positions.ResolutionWindow) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes.
|
||||||
|
<br/>
|
||||||
|
Shares within the PPLNS window will be weighted towards receiving a payout when any Monero block is found by any P2Pool miner.
|
||||||
|
</p>
|
||||||
|
<code class="mono">{%s p.Positions.BlocksInWindow.String() %}</code>
|
||||||
|
<br/>
|
||||||
|
<code class="mono">{%s p.Positions.UnclesInWindow.String() %}</code>
|
||||||
|
|
||||||
<h3>Uncles during last day</h3>
|
<h3>Shares and uncles during last day</h3>
|
||||||
|
<p class="small">
|
||||||
|
Each slice accounts for {%d p.Positions.Resolution %} P2Pool block heights, or around {%dul (uint64(p.Positions.Resolution) * p.Context().Consensus.TargetBlockTime) / 60 %} minutes.
|
||||||
|
<br/>
|
||||||
|
The pipe (<code>|</code>) character denotes roughly the PPLNS window end.
|
||||||
|
</p>
|
||||||
|
<code class="mono">{%s p.Positions.Blocks.StringWithSeparator(p.Positions.SeparatorIndex) %}</code>
|
||||||
|
<br/>
|
||||||
<code class="mono">{%s p.Positions.Uncles.StringWithSeparator(p.Positions.SeparatorIndex) %}</code>
|
<code class="mono">{%s p.Positions.Uncles.StringWithSeparator(p.Positions.SeparatorIndex) %}</code>
|
||||||
|
|
||||||
{% if p.Positions.Payouts.Total() > 0 %}
|
{% if p.Positions.Payouts.Total() > 0 %}
|
||||||
|
|
|
@ -896,10 +896,12 @@ func main() {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sharesInWindow := cmdutils.NewPositionChart(30, uint64(poolInfo.SideChain.WindowSize))
|
||||||
|
unclesInWindow := cmdutils.NewPositionChart(30, uint64(poolInfo.SideChain.WindowSize))
|
||||||
|
|
||||||
sharesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows)
|
sharesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows)
|
||||||
unclesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows)
|
unclesFound := cmdutils.NewPositionChart(30*totalWindows, consensus.ChainWindowSize*totalWindows)
|
||||||
|
|
||||||
var sharesInWindow, unclesInWindow uint64
|
|
||||||
var longDiff, windowDiff types.Difficulty
|
var longDiff, windowDiff types.Difficulty
|
||||||
|
|
||||||
wend := tipHeight - currentWindowSize
|
wend := tipHeight - currentWindowSize
|
||||||
|
@ -927,14 +929,14 @@ func main() {
|
||||||
}
|
}
|
||||||
if share.SideHeight > wend {
|
if share.SideHeight > wend {
|
||||||
windowDiff = windowDiff.Add64(uncleWeight)
|
windowDiff = windowDiff.Add64(uncleWeight)
|
||||||
unclesInWindow++
|
unclesInWindow.Add(int(int64(tipHeight)-int64(share.SideHeight)), 1)
|
||||||
}
|
}
|
||||||
longDiff = longDiff.Add64(uncleWeight)
|
longDiff = longDiff.Add64(uncleWeight)
|
||||||
} else {
|
} else {
|
||||||
sharesFound.Add(int(int64(tipHeight)-toInt64(share.SideHeight)), 1)
|
sharesFound.Add(int(int64(tipHeight)-toInt64(share.SideHeight)), 1)
|
||||||
if share.SideHeight > wend {
|
if share.SideHeight > wend {
|
||||||
windowDiff = windowDiff.Add64(share.Difficulty)
|
windowDiff = windowDiff.Add64(share.Difficulty)
|
||||||
sharesInWindow++
|
sharesInWindow.Add(int(int64(tipHeight)-toInt64(share.SideHeight)), 1)
|
||||||
}
|
}
|
||||||
longDiff = longDiff.Add64(share.Difficulty)
|
longDiff = longDiff.Add64(share.Difficulty)
|
||||||
}
|
}
|
||||||
|
@ -947,20 +949,24 @@ func main() {
|
||||||
minerPage := &views.MinerPage{
|
minerPage := &views.MinerPage{
|
||||||
Refresh: refresh,
|
Refresh: refresh,
|
||||||
Positions: struct {
|
Positions: struct {
|
||||||
Resolution int
|
Resolution int
|
||||||
SeparatorIndex int
|
ResolutionWindow int
|
||||||
Blocks *cmdutils.PositionChart
|
SeparatorIndex int
|
||||||
Uncles *cmdutils.PositionChart
|
Blocks *cmdutils.PositionChart
|
||||||
Payouts *cmdutils.PositionChart
|
Uncles *cmdutils.PositionChart
|
||||||
|
BlocksInWindow *cmdutils.PositionChart
|
||||||
|
UnclesInWindow *cmdutils.PositionChart
|
||||||
|
Payouts *cmdutils.PositionChart
|
||||||
}{
|
}{
|
||||||
Resolution: int(foundPayout.Resolution()),
|
Resolution: int(foundPayout.Resolution()),
|
||||||
SeparatorIndex: int(consensus.ChainWindowSize*totalWindows - currentWindowSize),
|
ResolutionWindow: int(sharesInWindow.Resolution()),
|
||||||
Blocks: sharesFound,
|
SeparatorIndex: int(consensus.ChainWindowSize*totalWindows - currentWindowSize),
|
||||||
Uncles: unclesFound,
|
Blocks: sharesFound,
|
||||||
Payouts: foundPayout,
|
BlocksInWindow: sharesInWindow,
|
||||||
|
Uncles: unclesFound,
|
||||||
|
UnclesInWindow: unclesInWindow,
|
||||||
|
Payouts: foundPayout,
|
||||||
},
|
},
|
||||||
SharesInWindow: int(sharesInWindow),
|
|
||||||
UnclesInWindow: int(unclesInWindow),
|
|
||||||
Weight: longDiff.Lo,
|
Weight: longDiff.Lo,
|
||||||
WindowWeight: windowDiff.Lo,
|
WindowWeight: windowDiff.Lo,
|
||||||
Miner: miner,
|
Miner: miner,
|
||||||
|
|
Loading…
Reference in a new issue