Module:Rates: Difference between revisions
From Ephinea PSO Wiki
No edit summary |
No edit summary |
||
| (53 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
-- <nowiki> | |||
-- | |||
-- Formats drop rates and calculates two rates multiplied together (usually DAR and RDR) | |||
-- | |||
local p = {} | local p = {} | ||
-- Every DAR/RDR fraction between 1/2 and 1/1 | |||
local wholeFractions = | local wholeFractions = | ||
{ | { | ||
| Line 7: | Line 13: | ||
[0.875] = "7/8", | [0.875] = "7/8", | ||
[0.85] = "17/20", | [0.85] = "17/20", | ||
[0.7] = "7/10", | |||
[0.8] = "4/5", | [0.8] = "4/5", | ||
[0.6] = "3/5", | [0.6] = "3/5", | ||
[0.5625] = "9/16", | [0.5625] = "9/16", | ||
[0.55] = "9/20", | [0.55] = "9/20", | ||
[0.50625] = "81/160", | |||
[0.5] = "1/2" | [0.5] = "1/2" | ||
} | } | ||
function | -- | ||
return | -- Multiply a DAR and RDR together. Any number works but it's basically just for those | ||
-- | |||
-- @param dar {number} | |||
-- @param rdr {number} | |||
-- @return {number} | |||
-- | |||
local function calcRate(dar, rdr) | |||
local mult = {} | |||
mult[1] = dar | |||
mult[2] = rdr | |||
-- Initialize numbers for string conversion | |||
local frac = {} | |||
frac[1] = {} | |||
frac[2] = {} | |||
-- If either number is a fraction, split it up into numerator and denominator | |||
-- Thanks, Ender! | |||
for i=1,2,1 do | |||
for number in string.gmatch(mult[i], '([^/]+)') do | |||
table.insert(frac[i], number) | |||
end | |||
-- If either number wasn't a fraction, fill 1 in for its denominator | |||
if frac[i][2] == nil then | |||
frac[i][2] = 1 | |||
end | |||
end | |||
return (frac[1][1]/frac[1][2])*(frac[2][1]/frac[2][2]) | |||
end | end | ||
-- | |||
-- Number formatting. Pass in a number in either fraction, decimal, or whole format and convert it. | |||
-- | |||
-- @param rate {string} | |||
-- @param fmt {string} -- "f" for fraction, "p" for percent, "n" for both fraction and percent used in the Note template | |||
-- @param digits {number} -- optional | |||
-- @return {string} | |||
-- | |||
local function fmtRate(rate, fmt, digits) | local function fmtRate(rate, fmt, digits) | ||
local out = "" | local out = "" | ||
if | local frac = {} | ||
-- If either number is a fraction, split it up into numerator and denominator | |||
-- Thanks, Ender! | |||
for number in string.gmatch(rate, '([^/]+)') do | |||
table.insert(frac, number) | |||
end | |||
-- If either number wasn't a fraction, fill 1 in for its denominator | |||
if frac[2] == nil then | |||
frac[2] = 1 | |||
end | end | ||
local num = frac[1] | |||
local den = frac[2] | |||
-- Turn rate into a number! | |||
rate = num / den | |||
if fmt == "f" then | if fmt == "f" then | ||
if wholeFractions[rate] == nil then | if wholeFractions[rate] == nil then | ||
if rate < 10 then | if not digits then | ||
digits = 0 | |||
end | |||
-- Set maximum number of decimal places | |||
if 1/rate < 10 then | |||
-- Displays with two places between 1.01 ~ 9.99 | |||
digits = math.max(digits, 2) | digits = math.max(digits, 2) | ||
elseif rate < 100 then | elseif 1/rate < 100 then | ||
-- Displays with one place between 10.1 ~ 99.9 | |||
digits = math.max(digits, 1) | digits = math.max(digits, 1) | ||
end | end | ||
out = | -- Even if we're displaying one or more decimal places, cut zeroes off | ||
out = string.format("1/%." .. digits .. "f", 1/rate) | |||
return out:gsub("%.0+$", "") | |||
else | else | ||
out = | out = wholeFractions[rate] | ||
end | end | ||
return out | return out | ||
elseif fmt == "p" then | elseif fmt == "p" then | ||
-- Display up to five decimal places. Cut zeroes off | |||
out = string.format("%.5f", rate * 100) | |||
return out | if string.find(out, "%.") then | ||
out = string.gsub(out, "%.0+$", "") | |||
end | |||
return string.format("%s%%", out) | |||
end | end | ||
end | end | ||
-- | |||
-- Rate display accessed through #invoke. Display up to TWO rates plus their combination! | |||
-- | |||
-- @param frame {table} | |||
-- @return {string} | |||
-- | |||
function p.displayRate(frame) | function p.displayRate(frame) | ||
local | -- Separate the format (strings) from the rates (numbers passed in as strings). | ||
local | local fmt = frame.args[1] | ||
local rate = {} | |||
rate[1] = frame.args[2] | |||
if frame.args[3] == nil then | |||
rate[2] = 1 | |||
else | |||
rate[2] = frame.args[3] | |||
end | |||
if rate[1] == "0" or rate[2] == "0" then | |||
return nil | |||
end | |||
local out = "" | local out = "" | ||
if fmt == "f" then | if fmt == "f" then | ||
-- Fraction | |||
out = out .. fmtRate(rate[1], "f") | |||
elseif fmt == "p" then | elseif fmt == "p" then | ||
out = out .. fmtRate(rate | -- Percentage | ||
out = out .. fmtRate(rate[1], "p") | |||
elseif fmt == "n" then | elseif fmt == "n" then | ||
out = out .. fmtRate(rate, "f", 2) .. " (" .. fmtRate(rate, "p") .. ")" | -- Fraction with hover text showing first two input rates as Fraction (Percentage) | ||
local span = mw.html.create("span") | |||
span | |||
:addClass("more_info") | |||
:attr("title", string.format("Drop Rate: %s (%s), Rare Rate: %s (%s)", fmtRate(rate[1], "f"), fmtRate(rate[1], "p"), fmtRate(rate[2], "f", 2), fmtRate(rate[2], "p"))) | |||
:css("border-bottom", "1px dotted") | |||
:wikitext(string.format("%s", fmtRate(calcRate(rate[1], rate[2]), "f"))) | |||
--out = out .. fmtRate(rate, "f", 2) .. " (" .. fmtRate(rate, "p") .. ")" | |||
return span:allDone() | |||
end | end | ||
return out | return out | ||
| Line 60: | Line 146: | ||
return p | return p | ||
-- </nowiki> | |||
Latest revision as of 14:17, 12 June 2023
Documentation for this module may be created at Module:Rates/doc
-- <nowiki>
--
-- Formats drop rates and calculates two rates multiplied together (usually DAR and RDR)
--
local p = {}
-- Every DAR/RDR fraction between 1/2 and 1/1
local wholeFractions =
{
[0.9] = "9/10",
[0.88] = "22/25",
[0.875] = "7/8",
[0.85] = "17/20",
[0.7] = "7/10",
[0.8] = "4/5",
[0.6] = "3/5",
[0.5625] = "9/16",
[0.55] = "9/20",
[0.50625] = "81/160",
[0.5] = "1/2"
}
--
-- Multiply a DAR and RDR together. Any number works but it's basically just for those
--
-- @param dar {number}
-- @param rdr {number}
-- @return {number}
--
local function calcRate(dar, rdr)
local mult = {}
mult[1] = dar
mult[2] = rdr
-- Initialize numbers for string conversion
local frac = {}
frac[1] = {}
frac[2] = {}
-- If either number is a fraction, split it up into numerator and denominator
-- Thanks, Ender!
for i=1,2,1 do
for number in string.gmatch(mult[i], '([^/]+)') do
table.insert(frac[i], number)
end
-- If either number wasn't a fraction, fill 1 in for its denominator
if frac[i][2] == nil then
frac[i][2] = 1
end
end
return (frac[1][1]/frac[1][2])*(frac[2][1]/frac[2][2])
end
--
-- Number formatting. Pass in a number in either fraction, decimal, or whole format and convert it.
--
-- @param rate {string}
-- @param fmt {string} -- "f" for fraction, "p" for percent, "n" for both fraction and percent used in the Note template
-- @param digits {number} -- optional
-- @return {string}
--
local function fmtRate(rate, fmt, digits)
local out = ""
local frac = {}
-- If either number is a fraction, split it up into numerator and denominator
-- Thanks, Ender!
for number in string.gmatch(rate, '([^/]+)') do
table.insert(frac, number)
end
-- If either number wasn't a fraction, fill 1 in for its denominator
if frac[2] == nil then
frac[2] = 1
end
local num = frac[1]
local den = frac[2]
-- Turn rate into a number!
rate = num / den
if fmt == "f" then
if wholeFractions[rate] == nil then
if not digits then
digits = 0
end
-- Set maximum number of decimal places
if 1/rate < 10 then
-- Displays with two places between 1.01 ~ 9.99
digits = math.max(digits, 2)
elseif 1/rate < 100 then
-- Displays with one place between 10.1 ~ 99.9
digits = math.max(digits, 1)
end
-- Even if we're displaying one or more decimal places, cut zeroes off
out = string.format("1/%." .. digits .. "f", 1/rate)
return out:gsub("%.0+$", "")
else
out = wholeFractions[rate]
end
return out
elseif fmt == "p" then
-- Display up to five decimal places. Cut zeroes off
out = string.format("%.5f", rate * 100)
if string.find(out, "%.") then
out = string.gsub(out, "%.0+$", "")
end
return string.format("%s%%", out)
end
end
--
-- Rate display accessed through #invoke. Display up to TWO rates plus their combination!
--
-- @param frame {table}
-- @return {string}
--
function p.displayRate(frame)
-- Separate the format (strings) from the rates (numbers passed in as strings).
local fmt = frame.args[1]
local rate = {}
rate[1] = frame.args[2]
if frame.args[3] == nil then
rate[2] = 1
else
rate[2] = frame.args[3]
end
if rate[1] == "0" or rate[2] == "0" then
return nil
end
local out = ""
if fmt == "f" then
-- Fraction
out = out .. fmtRate(rate[1], "f")
elseif fmt == "p" then
-- Percentage
out = out .. fmtRate(rate[1], "p")
elseif fmt == "n" then
-- Fraction with hover text showing first two input rates as Fraction (Percentage)
local span = mw.html.create("span")
span
:addClass("more_info")
:attr("title", string.format("Drop Rate: %s (%s), Rare Rate: %s (%s)", fmtRate(rate[1], "f"), fmtRate(rate[1], "p"), fmtRate(rate[2], "f", 2), fmtRate(rate[2], "p")))
:css("border-bottom", "1px dotted")
:wikitext(string.format("%s", fmtRate(calcRate(rate[1], rate[2]), "f")))
--out = out .. fmtRate(rate, "f", 2) .. " (" .. fmtRate(rate, "p") .. ")"
return span:allDone()
end
return out
end
return p
-- </nowiki>