Core/src/helpers/curve.cr

46 lines
1.7 KiB
Crystal

class TETU::Helpers::Curve
include YAML::Serializable
property function : String
property coefs : Hash(String, Float64 | Int32)
def coef(name : String, default : Float64 = 0.0) : Float64
@coefs.fetch(name, default).to_f64
end
# Proc(Float64, Tick, Float64).new { |x| x }
# (x) : the tier of the upgrade
FUNCTIONS = {
# = x (any constant name is accepted, only one)
"constant" => ->(f : Curve, x : Float64, t : TETU::Tick) {
f.coefs.values.first.to_f64
},
# a(x + b) + c (constants are a, b)
"linear" => ->(f : Curve, x : Float64, t : TETU::Tick) {
x * f.coef("a", 1.0) + f.coef("b", 0.0)
},
# ax⁰ + bx¹ + cx² + dx³ + ... (constants to define are alpha order)
"polynome" => ->(f : Curve, x : Float64, t : TETU::Tick) {
coef_ordered = f.coefs.keys.sort
return 0.0 if coef_ordered.empty?
index = 0
coef_ordered[1..-1].reduce(f.coef(coef_ordered.first)) do |base, coef|
index += 1
base + coef.to_f64 * (x ** index)
end
},
# log[base](x + b)*c + d (constants are a, base, b, c)
"log" => ->(f : Curve, x : Float64, t : TETU::Tick) {
Math.log(x + f.coef("b", 2.0), f.coef("base", 2.0)) * f.coef("a", 1.0) + f.coef("c", 0.0)
},
# (a^x)b + c (constants are a, base, b, c)
"squared" => ->(f : Curve, x : Float64, t : TETU::Tick) {
(x + f.coef("b", 2.0)) ** f.coef("base", 2.0) * f.coef("a", 1.0) + f.coef("c", 0.0)
},
}
def execute(x : Float64, t : TETU::Tick = 0) : Float64
f = FUNCTIONS.fetch(@function) { raise "Invalid \"#{@function}\" name for function type. Valids are #{FUNCTIONS.keys.join(", ")}" }
f.call(self, x, t)
end
end