From 4bebd101821075dc15b033e868b5b6f2828a67dc Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com> Date: Wed, 28 Feb 2024 05:11:11 +0100 Subject: [PATCH] Partially implement #11 Cumulative Share Effort on calculator, added mean shares per day --- cmd/web/views/calculate-share-time.qtpl | 82 ++++++++++++++++++++++--- cmd/web/views/funcs.go | 3 +- cmd/web/web.go | 28 ++++++--- utils/statistics.go | 35 +++++++++++ 4 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 utils/statistics.go diff --git a/cmd/web/views/calculate-share-time.qtpl b/cmd/web/views/calculate-share-time.qtpl index ffcf523..1275f23 100644 --- a/cmd/web/views/calculate-share-time.qtpl +++ b/cmd/web/views/calculate-share-time.qtpl @@ -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() %} + +

Average Share Time Calculator

@@ -34,6 +49,8 @@ type CalculateShareTimePageEffortEntry struct { 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.
For lower hashrate, this average is what statistically will be achieved long term. +
+ The long term average per-share effort would be 100%


@@ -57,7 +74,7 @@ type CalculateShareTimePageEffortEntry struct {
- +
{% 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)) %} @@ -65,20 +82,26 @@ type CalculateShareTimePageEffortEntry struct { + - + + - - - + + +
P2Pool Hashrate
{%s si_units(diff_hashrate(p.Context().Pool.SideChain.LastBlock.Difficulty, p.Context().Consensus.TargetBlockTime), 2) %}H/s
Your Hashrate
{%s si_units(p.Hashrate * p.Magnitude, 2) %}H/s
Your Share Mean
{%s time_duration_long(between) %}
Your Daily Mean Shares
{%f.3 p.EstimatedSharesPerDay %} share(s)
 
 
Monero Difficulty
{%s si_units(p.Context().Pool.MainChain.Difficulty.Lo, 2) %}
Monero Hashrate
{%s si_units(diff_hashrate(p.Context().Pool.MainChain.Difficulty, uint64(p.Context().Pool.MainChain.Consensus.BlockTime)), 2) %}H/s
P2Pool Block Mean
{%s time_duration_long(float64(p.Context().Pool.MainChain.Difficulty.Lo) / float64(diff_hashrate(p.Context().Pool.SideChain.LastBlock.Difficulty, p.Context().Consensus.TargetBlockTime))) %}
Your Solo Block Mean
{%s time_duration_long(between_solo) %}
Your Solo Daily Mean Blocks
{%f.3 p.EstimatedBlocksPerDay %} block(s)
 
Your Estimated Daily Reward
{%s monero_to_xmr(p.EstimatedRewardPerDay) %} XMR
 
 
Your Estimated Daily Reward
{%s monero_to_xmr(p.EstimatedRewardPerDay) %} XMR
+ +
+

Single Share Effort

+ - - + + @@ -86,7 +109,7 @@ type CalculateShareTimePageEffortEntry struct { {% for _, e := range p.Efforts %} {% endfor %} - +
Found EffortFound ChanceShare EffortFound Probability P2Pool Estimate Solo Estimate
- {%f.2 e.Effort %}% + {%f.0 e.Effort %}% {%f.5 e.Probability %}% @@ -99,7 +122,48 @@ type CalculateShareTimePageEffortEntry struct {
+ +
+

Cumulative Share Effort

+ + + + + + + + + {% for i := range p.Efforts[0].ShareProbabilities %} + + {% endfor %} + + + {% for _, e := range p.Efforts %} + + + + {% code var mode = utils.ProbabilityMode(e.ShareProbabilities...) %} + {% for _, p := range e.ShareProbabilities %} + {% if p*100 > 1 %} + + {% else %} + + {% endif %} + {% endfor %} + + {% endfor %} + + + + {% for i := range p.Efforts[0].ShareProbabilities %} + + {% endfor %} +
Number of shares
Cumulative EffortCumulative Time{%d i %}
+ {%f.0 e.Effort %}% + + {%s time_duration_long(e.Between) %} + {%f.0 p*100 %}%
{%d i %}
{% endif %} diff --git a/cmd/web/views/funcs.go b/cmd/web/views/funcs.go index 5cec346..bd312c7 100644 --- a/cmd/web/views/funcs.go +++ b/cmd/web/views/funcs.go @@ -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 diff --git a/cmd/web/web.go b/cmd/web/web.go index 44cbfd4..d76951d 100644 --- a/cmd/web/web.go +++ b/cmd/web/web.go @@ -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 } diff --git a/utils/statistics.go b/utils/statistics.go new file mode 100644 index 0000000..c25ff7e --- /dev/null +++ b/utils/statistics.go @@ -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 +}