Partially implement #11 Cumulative Share Effort on calculator, added mean shares per day
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
DataHoarder 2024-02-28 05:11:11 +01:00
parent 50e1acbb3a
commit 4bebd10182
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
4 changed files with 130 additions and 18 deletions

View file

@ -1,3 +1,4 @@
{% import "git.gammaspectra.live/P2Pool/p2pool-observer/utils" %}
{% code
type CalculateShareTimePage struct {
// inherit from base page, so its' title is used in error page.
@ -7,6 +8,8 @@ type CalculateShareTimePage struct {
Magnitude float64
Efforts []CalculateShareTimePageEffortEntry
EstimatedRewardPerDay uint64
EstimatedSharesPerDay float64
EstimatedBlocksPerDay float64
}
%}
@ -16,6 +19,7 @@ type CalculateShareTimePageEffortEntry struct {
Probability float64
Between float64
BetweenSolo float64
ShareProbabilities []float64
}
%}
@ -25,6 +29,17 @@ type CalculateShareTimePageEffortEntry struct {
{% func (p *CalculateShareTimePage) Content() %}
<style type="text/css">
.bulk {
color: #00dddd;
}
.mode {
font-weight: bolder;
/* color: rgb(100,206,145); */
color: #00ffff;
}
</style>
<div style="text-align: center">
<form action="/calculate-share-time" method="get">
<h2>Average Share Time Calculator</h2>
@ -34,6 +49,8 @@ type CalculateShareTimePageEffortEntry struct {
<small>Do note this time will vary (can get shares sooner, or later, even way later), depending on your luck, and changing difficulty of the pool due to increase / reductions in hashrate.</small>
<br/>
For lower hashrate, this average is what statistically will be achieved long term.
<br/>
The long term average per-share effort would be <span style="font-weight:bolder; color: {%s effort_color(100) %};">100%</span>
</p>
<div>
<label for="hashrate">Your Hashrate</label><br/>
@ -57,7 +74,7 @@ type CalculateShareTimePageEffortEntry struct {
<hr/>
<div style="text-align: center">
<table class="center" style="max-width: calc(15em + 15em + 15em + 15em);">
<table class="center" style="max-width: calc(15em + 15em + 15em + 15em + 15em);">
{% code between := (float64(p.Context().Pool.SideChain.LastBlock.Difficulty) / (p.Hashrate * p.Magnitude)) %}
{% code between_solo := (float64(p.Context().Pool.MainChain.Difficulty.Lo) / (p.Hashrate * p.Magnitude)) %}
<tr style="line-height: 1.5;">
@ -65,20 +82,26 @@ type CalculateShareTimePageEffortEntry struct {
<td style="width: 15em"><strong>P2Pool Hashrate</strong><br/>{%s si_units(diff_hashrate(p.Context().Pool.SideChain.LastBlock.Difficulty, p.Context().Consensus.TargetBlockTime), 2) %}H/s</td>
<td style="width: 15em"><strong>Your Hashrate</strong><br/>{%s si_units(p.Hashrate * p.Magnitude, 2) %}H/s</td>
<td title="Mean frequency between P2Pool shares" style="width: 15em; border: #ff6600 dashed 1px;"><strong>Your Share Mean<br/>{%s time_duration_long(between) %}</strong></td>
<td title="Mean P2Pool shares per day" style="width: 15em; border: #ff6600 dashed 1px;"><strong>Your Daily Mean Shares<br/>{%f.3 p.EstimatedSharesPerDay %} share(s)</strong></td>
</tr>
<tr><th colspan="4">&nbsp;</th></tr>
<tr><th colspan="5">&nbsp;</th></tr>
<tr style="line-height: 1.5;">
<td><strong>Monero Difficulty</strong><br/>{%s si_units(p.Context().Pool.MainChain.Difficulty.Lo, 2) %}</td>
<td><strong>Monero Hashrate</strong><br/>{%s si_units(diff_hashrate(p.Context().Pool.MainChain.Difficulty, uint64(p.Context().Pool.MainChain.Consensus.BlockTime)), 2) %}H/s</td>
<td title="Mean frequency between P2Pool finds Monero Blocks"><strong>P2Pool Block Mean</strong><br/><em>{%s time_duration_long(float64(p.Context().Pool.MainChain.Difficulty.Lo) / float64(diff_hashrate(p.Context().Pool.SideChain.LastBlock.Difficulty, p.Context().Consensus.TargetBlockTime))) %}</em></td>
<td title="Mean frequency between Solo Monero Blocks (without P2Pool)"><strong>Your Solo Block Mean</strong><br/><em>{%s time_duration_long(between_solo) %}</em></td>
<td title="Mean Solo Monero Blocks (without P2Pool) per day"><strong>Your Solo Daily Mean Blocks</strong><br/><em>{%f.3 p.EstimatedBlocksPerDay %} block(s)</em></td>
</tr>
<tr><th colspan="4">&nbsp;</th></tr>
<tr style="line-height: 1.5; font-size: 21px;"><td></td><td colspan="2" style="border: #ff6600 dashed 1px;"><strong>Your Estimated Daily Reward</strong><br/>{%s monero_to_xmr(p.EstimatedRewardPerDay) %} XMR</td><td></td></tr>
<tr><th colspan="4">&nbsp;</th></tr>
<tr><th colspan="5">&nbsp;</th></tr>
<tr style="line-height: 1.5; font-size: 21px;"><td></td><td colspan="3" style="border: #ff6600 dashed 1px;"><strong>Your Estimated Daily Reward</strong><br/>{%s monero_to_xmr(p.EstimatedRewardPerDay) %} XMR</td><td></td></tr>
</table>
<br/>
<h3>Single Share Effort</h3>
<table class="center" style="max-width: calc(10em + 15em + 15em + 15em);">
<tr style="line-height: 1.5;">
<th>Found Effort</th>
<th>Found Chance</th>
<th>Share Effort</th>
<th>Found Probability</th>
<th>P2Pool Estimate</th>
<th>Solo Estimate</th>
</tr>
@ -86,7 +109,7 @@ type CalculateShareTimePageEffortEntry struct {
{% for _, e := range p.Efforts %}
<tr>
<td style="font-size: 17px; font-weight:bolder; color: {%s effort_color(e.Effort) %};">
{%f.2 e.Effort %}%
{%f.0 e.Effort %}%
</td>
<td title="Chance share is not found before: {%f.5 100 - e.Probability %}%">
{%f.5 e.Probability %}%
@ -99,7 +122,48 @@ type CalculateShareTimePageEffortEntry struct {
</td>
</tr>
{% endfor %}
<tr><td></td><td></td></tr>
</table>
<br/>
<h3>Cumulative Share Effort</h3>
<table class="center" style="max-width: calc(15em + 15em + {%d len(p.Efforts[0].ShareProbabilities)*2 %}em);">
<tr>
<th colspan="2"></th>
<th colspan="{%d len(p.Efforts[0].ShareProbabilities) %}">Number of shares</th>
</tr>
<tr style="line-height: 1.5;">
<th>Cumulative Effort</th>
<th>Cumulative Time</th>
{% for i := range p.Efforts[0].ShareProbabilities %}
<th>{%d i %}</th>
{% endfor %}
</tr>
{% for _, e := range p.Efforts %}
<tr>
<td style="font-size: 17px; font-weight:bolder; color: {%s effort_color(e.Effort) %};">
{%f.0 e.Effort %}%
</td>
<td>
{%s time_duration_long(e.Between) %}
</td>
{% code var mode = utils.ProbabilityMode(e.ShareProbabilities...) %}
{% for _, p := range e.ShareProbabilities %}
{% if p*100 > 1 %}
<td class="{% if mode == p %}mode{% else %}{% endif %}" title="{%f.5 p*100 %}%">{%f.0 p*100 %}%</td>
{% else %}
<td title="{%f.5 p*100 %}%"></td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
<tr>
<th colspan="2"></th>
{% for i := range p.Efforts[0].ShareProbabilities %}
<th>{%d i %}</th>
{% endfor %}
</tr>
</table>
</div>
{% endif %}

View file

@ -8,7 +8,6 @@ import (
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"github.com/mazznoer/colorgrad"
"math"
"strconv"
"strings"
"time"
@ -148,7 +147,7 @@ const effortRangeStart = 0.15
const effortRangeEnd = 0.8
func effort_color(effort float64) string {
probability := 1 - math.Exp(-effort/100)
probability := utils.ProbabilityEffort(effort)
// rescale
probability *= effortRangeEnd - effortRangeStart

View file

@ -335,27 +335,41 @@ func main() {
currentHashRate := magnitude * hashRate
var effortSteps = []float64{25, 50, 75, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000}
const shareSteps = 15
calculatePage := &views.CalculateShareTimePage{
Hashrate: hashRate,
Magnitude: magnitude,
Efforts: nil,
EstimatedRewardPerDay: 0,
EstimatedSharesPerDay: 0,
EstimatedBlocksPerDay: 0,
}
if currentHashRate > 0 {
var efforts []views.CalculateShareTimePageEffortEntry
for _, v := range []float64{25, 50, 75, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000} {
efforts = append(efforts, views.CalculateShareTimePageEffortEntry{
Effort: v,
Probability: (1 - math.Exp(-(v / 100))) * 100,
Between: (float64(poolInfo.SideChain.LastBlock.Difficulty) * (v / 100)) / currentHashRate,
BetweenSolo: (float64(poolInfo.MainChain.Difficulty.Lo) * (v / 100)) / currentHashRate,
})
for _, effort := range effortSteps {
e := views.CalculateShareTimePageEffortEntry{
Effort: effort,
Probability: utils.ProbabilityEffort(effort) * 100,
Between: (float64(poolInfo.SideChain.LastBlock.Difficulty) * (effort / 100)) / currentHashRate,
BetweenSolo: (float64(poolInfo.MainChain.Difficulty.Lo) * (effort / 100)) / currentHashRate,
ShareProbabilities: make([]float64, shareSteps+1),
}
for i := uint64(0); i <= shareSteps; i++ {
e.ShareProbabilities[i] = utils.ProbabilityNShares(i, effort)
}
efforts = append(efforts, e)
}
calculatePage.Efforts = efforts
longWeight := types.DifficultyFrom64(uint64(currentHashRate)).Mul64(3600 * 24)
calculatePage.EstimatedSharesPerDay = float64(longWeight.Mul64(1000).Div64(poolInfo.SideChain.LastBlock.Difficulty).Lo) / 1000
calculatePage.EstimatedBlocksPerDay = float64(longWeight.Mul64(1000).Div(poolInfo.MainChain.NextDifficulty).Lo) / 1000
calculatePage.EstimatedRewardPerDay = longWeight.Mul64(poolInfo.MainChain.BaseReward).Div(poolInfo.MainChain.NextDifficulty).Lo
}

35
utils/statistics.go Normal file
View file

@ -0,0 +1,35 @@
package utils
import (
"math"
)
func ProbabilityEffort(effort float64) float64 {
return 1 - math.Exp(-effort/100)
}
func ProbabilityMode(i ...float64) (n float64) {
//cannot use max as it's not variadic
for _, item := range i {
if item > n {
n = item
}
}
return n
}
func ProbabilityNShares(shares uint64, effort float64) float64 {
num := math.Pow(effort/100, float64(shares))
den := float64(Factorial(shares))
return (num / den) * math.Exp(-effort/100)
}
// Factorial Valid for small n
func Factorial(n uint64) (result uint64) {
if n > 0 {
result = n * Factorial(n-1)
return result
}
return 1
}