Skip to content
Snippets Groups Projects
Commit 4e6c2ff3 authored by Hans Moog's avatar Hans Moog
Browse files

Feat: simplified formulas for mana calculations

parent 2909a601
Branches
No related tags found
No related merge requests found
...@@ -5,18 +5,18 @@ import ( ...@@ -5,18 +5,18 @@ import (
) )
type Balance struct { type Balance struct {
calculator *Calculator calculator *Calculator
currentBalance uint64 currentBalance uint64
lastErosion uint64 lastErosion uint64
roundingErrorInLastErosion float64 accumulatedRoundingError float64
} }
func NewBalance(calculator *Calculator) *Balance { func NewBalance(calculator *Calculator) *Balance {
return &Balance{ return &Balance{
calculator: calculator, calculator: calculator,
currentBalance: 0, currentBalance: 0,
lastErosion: 0, lastErosion: 0,
roundingErrorInLastErosion: 0, accumulatedRoundingError: 0,
} }
} }
...@@ -25,23 +25,33 @@ func (balance *Balance) GetValue() uint64 { ...@@ -25,23 +25,33 @@ func (balance *Balance) GetValue() uint64 {
} }
func (balance *Balance) AddTransfer(movedCoins uint64, receivedTime uint64, spentTime uint64) { func (balance *Balance) AddTransfer(movedCoins uint64, receivedTime uint64, spentTime uint64) {
gainedMana, _ := balance.calculator.GenerateMana(movedCoins, spentTime-receivedTime) gainedMana, roundingError := balance.calculator.GenerateMana(movedCoins, spentTime-receivedTime)
if spentTime >= balance.lastErosion { if balance.currentBalance != 0 {
balance.Erode(spentTime) if spentTime >= balance.lastErosion {
} else { balance.Erode(spentTime)
fmt.Println("empty") } else {
// revert old actions fmt.Println("empty")
// apply new // revert old actions
// replay old // apply new
// replay old
}
} }
balance.currentBalance += gainedMana balance.currentBalance += gainedMana
balance.accumulatedRoundingError += roundingError
balance.lastErosion = spentTime
fmt.Println("GENERATE: ", spentTime-receivedTime, movedCoins, gainedMana)
} }
func (balance *Balance) Erode(erosionTime uint64) { func (balance *Balance) Erode(erosionTime uint64) {
if balance.lastErosion <= erosionTime { if balance.lastErosion <= erosionTime {
balance.currentBalance, _ = balance.calculator.ErodeMana(balance.currentBalance, erosionTime-balance.lastErosion) erodedMana, _ := balance.calculator.ErodeMana(balance.currentBalance, erosionTime-balance.lastErosion)
fmt.Println("ERODE: ", erosionTime-balance.lastErosion, balance.currentBalance, erodedMana)
balance.currentBalance = erodedMana
} else { } else {
fmt.Println("empty") fmt.Println("empty")
// revert old erosions // revert old erosions
......
package mana
import (
"fmt"
"testing"
)
func TestBalance_AddTransfer(t *testing.T) {
calculator := NewCalculator(500, 0.1)
balance1 := NewBalance(calculator)
balance1.AddTransfer(1000, 0, 500)
balance1.AddTransfer(1000, 500, 1000)
balance1.AddTransfer(1000, 1000, 1700)
fmt.Println(balance1.GetValue())
balance2 := NewBalance(calculator)
balance2.AddTransfer(1000, 0, 1700)
fmt.Println(balance2.GetValue())
}
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
// A calculator that can be used to calculate the changes of mana due to erosion or mana generation. // A calculator that can be used to calculate the changes of mana due to erosion or mana generation.
type Calculator struct { type Calculator struct {
decayInterval float64 decayInterval float64
decayRate float64 decayFactor float64
options *CalculatorOptions options *CalculatorOptions
tokenSupplyScalefactor float64 tokenSupplyScalefactor float64
} }
...@@ -17,13 +17,13 @@ func NewCalculator(decayInterval float64, decayRate float64, optionalOptions ... ...@@ -17,13 +17,13 @@ func NewCalculator(decayInterval float64, decayRate float64, optionalOptions ...
return &Calculator{ return &Calculator{
// store key settings // store key settings
decayInterval: decayInterval, decayInterval: decayInterval,
decayRate: decayRate,
// configure optional parameters // configure optional parameters
options: DEFAULT_OPTIONS.Override(optionalOptions...), options: DEFAULT_OPTIONS.Override(optionalOptions...),
// derive important factors ... // derive important factors ...
// ... make mana reach exactly the token supply as it's max value (n coins => n mana) // ... make mana reach exactly the token supply as it's max value (n coins => n mana)
decayFactor: 1 - decayRate,
tokenSupplyScalefactor: decayRate / (1 - decayRate), tokenSupplyScalefactor: decayRate / (1 - decayRate),
} }
} }
...@@ -31,9 +31,7 @@ func NewCalculator(decayInterval float64, decayRate float64, optionalOptions ... ...@@ -31,9 +31,7 @@ func NewCalculator(decayInterval float64, decayRate float64, optionalOptions ...
// Returns the amount of mana that was generated by holding the given amount of coins for the given time. // Returns the amount of mana that was generated by holding the given amount of coins for the given time.
func (calculator *Calculator) GenerateMana(coins uint64, heldTime uint64) (result uint64, roundingError float64) { func (calculator *Calculator) GenerateMana(coins uint64, heldTime uint64) (result uint64, roundingError float64) {
// calculate results // calculate results
relativeDecayTime := float64(heldTime) / float64(calculator.decayInterval) gainedMana := float64(coins) * calculator.options.ManaScaleFactor * (1 - math.Pow(calculator.decayFactor, float64(heldTime)/calculator.decayInterval))
erosionFactor := (1 - math.Pow(1-calculator.decayRate, float64(relativeDecayTime+1)) - calculator.decayRate) / calculator.decayRate
gainedMana := float64(coins) * calculator.options.ManaScaleFactor * calculator.tokenSupplyScalefactor * erosionFactor
// assign rounded results & determine roundingErrors // assign rounded results & determine roundingErrors
result = uint64(math.Round(gainedMana)) result = uint64(math.Round(gainedMana))
...@@ -52,8 +50,7 @@ func (calculator *Calculator) ErodeMana(mana uint64, decayTime uint64) (result u ...@@ -52,8 +50,7 @@ func (calculator *Calculator) ErodeMana(mana uint64, decayTime uint64) (result u
} }
// calculate results // calculate results
growthFactor := math.Log(1-calculator.decayRate) / float64(calculator.decayInterval) erodedMana := float64(mana) * math.Pow(calculator.decayFactor, float64(decayTime)/calculator.decayInterval)
erodedMana := float64(mana) * math.Pow(math.E, growthFactor*float64(decayTime))
// assign rounded results & determine roundingErrors // assign rounded results & determine roundingErrors
result = uint64(math.Round(erodedMana)) result = uint64(math.Round(erodedMana))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment