37,444 Pages

Documentation for this module may be created at Module:CurveTable/doc

```local p = {}

-- Parses a string of the format `x,y` with numerical `x` and `y` into an array with named numbers `x` and `y`.
function parsePoint(string)
local stringArray = mw.text.split(string, ",")

local point = {}
point["x"] = tonumber(stringArray)
point["y"] = tonumber(stringArray)

return point
end

-- Rounds `value` according to the type of rounding indicated by `mode`.
function round(mode, value)
if mode == "ceil"    then return math.ceil(value)
elseif mode == "floor"   then return math.floor(value)
elseif mode == "trunc"   then return value >= 0 and math.floor(value - 0.5) or math.ceil(value + 0.5)
elseif mode == "nearest" then return math.floor(value + 0.5)
else return value
end
end

-- Interpolates (or extrapolates) the x-coordinate `c` based on points `a` and `b`.
function interpolatePoint(a, b, c)
return a["y"] + (c - a["x"]) * (b["y"] - a["y"]) / (b["x"] - a["x"])
end

-- Interpolates (or extrapolates) the x-coordinate `target` in the curve table `curveTable`.
function interpolate(curveTable, target)
if #curveTable == 1 then
-- One point in curve table; interpret as horizontal line
return parsePoint(curveTable)["y"]
end

-- Find the first point that is greater than `target`
for i = 1, #curveTable, 1 do
local point = parsePoint(curveTable[i])

if target == point["x"] then
-- `target` is on a point in the curve table; no interpolation/extrapolation required
return point["y"]
elseif target < point["x"] then
if i == 1 then
-- `target` comes before the first point; extrapolate from first two points in table
return interpolatePoint(parsePoint(curveTable), parsePoint(curveTable), target)
else
-- `target` is in between two points; interpolate between current and previous point
return interpolatePoint(parsePoint(curveTable[i - 1]), parsePoint(curveTable[i]), target)
end
end
end

-- `target` is after last point. Extrapolate from last two points in table
return interpolatePoint(parsePoint(curveTable[#curveTable - 1]), parsePoint(curveTable[#curveTable]), target)
end

-- See documentation at [[Template:CurveTable]].
function p.evaluate(frame)
local curveTable = mw.text.split(frame.args, " ")
if #curveTable == 0 then
-- Empty curve table
return "Not enough points in curve table."
end

local target1 = tonumber(frame.args)
return round(frame.args["round"], interpolate(curveTable, target1))
end

return p
```
Community content is available under CC-BY-SA unless otherwise noted.