Module:Shared: Difference between revisions

Issue finally found...
m (Add functions for parsing numbers)
Tag: Reverted
(Issue finally found...)
(12 intermediate revisions by 2 users not shown)
Line 1: Line 1:
-- Module that contains all functions regarding numeric formatting and calculations.
-- TODO: Make modules that now call Shared call Number (for relevant functions)
local numModule = require('Module:Number')
--So there are a handful of functions that I'm using in a lot of places
--So there are a handful of functions that I'm using in a lot of places
--So rather than continue to copy across the same handful of functions to every single new module
--So rather than continue to copy across the same handful of functions to every single new module
Line 46: Line 50:
end
end


-- Function to sort a dictionary-like structure where items are added like tbl['key'] = value
-- We need to turn this structure into a table first, in order to sort it.
function p.sortDictionary(dict, comparer)
local sortedTable = {}
    for k, v in pairs(dict) do
        table.insert(sortedTable, {key = k, value = v})
    end
   
    table.sort(sortedTable, comparer)
   
    return sortedTable
end


--General purpose function for going through a table after sorting based on a custom sort order
--General purpose function for going through a table after sorting based on a custom sort order
Line 72: Line 89:
end
end


-- conveniently shifts BLAH to Blah
-- Takes an input string and returns the same string with title case-like
-- Handy when formatting data in ALL CAPS or all lower case
-- formatting (that is, the first letter of every word becomes uppercase,
-- while the remainder becomes lowercase)
-- Examples:
-- titleCase('ALL CAPS') = 'All Caps'
-- titleCase('all lowercase') = 'All Lowercase'
-- titleCase('A MiXTUre') = 'A Mixture'
-- Note that non-alphanumeric characters are treated as a word boundary, so:
-- titleCase('a!b(c)d') = 'A!B(C)D' (not 'A!b(c)d')
--Originally snagged this from Module:VoidByReward written by User:NoBrainz
--Originally snagged this from Module:VoidByReward written by User:NoBrainz
function p.titleCase(head, tail)
function p.titleCase(head, tail)
Line 144: Line 168:
end
end


--Splits a string based on a sent in separating character
--- Splits a string based on a sent in separating character
--For example calling splitString ("Lith V1 Relic", " ") would return {"Lith", "V1", "Relic"}
--- For example calling splitString ("Lith V1 Relic", " ") would return {"Lith", "V1", "Relic"}
function p.splitString(inputstr, sep)
-- @param inputstr (string) The input to separate.
-- @param sep (string/char) The separation character.
-- @param trim (boolean) TRUE to trim the leading/trailing whitespaces
function p.splitString(inputstr, sep, trim)
if sep == nil then
if sep == nil then
sep = "%s"
sep = "%s"
Line 152: Line 179:
local t = {}
local t = {}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
if trim == true then
str = str:gsub("^%s*(.-)%s*$", "%1")
end
table.insert(t, str)
table.insert(t, str)
end
end
Line 165: Line 195:
--Adds commas
--Adds commas
function p.formatnum(number)
function p.formatnum(number)
if tonumber(number) == nil then
return numModule.formatnum(number)
return number
else
local result = number
while true do
-- Format in blocks of 3 digits at a time until formatting is complete
            local k
result, k = string.gsub(result, "^(-?%d+)(%d%d%d)", '%1,%2')
if k == 0 then
break
end
end
return result
end
end
end


Line 187: Line 204:


function p.round(val, maxDigits, minDigits)
function p.round(val, maxDigits, minDigits)
if val == nil then
return numModule.round(val, maxDigits, minDigits)
return nil
else
if type(maxDigits) == "table" then
minDigits = maxDigits[2]
maxDigits = maxDigits[1]
end
 
local result = val..""
local decimals = string.find(result, "%.")
if decimals ~= nil then
decimals = string.len(result) - decimals
else
decimals = 0
end
 
if maxDigits ~= nil and decimals > maxDigits then
result = string.format("%."..maxDigits.."f", result)
elseif minDigits ~= nil and decimals < minDigits then
result = string.format("%."..minDigits.."f", result)
end
 
return result
end
end
end


--From http://lua-users.org/wiki/SimpleRound
--From http://lua-users.org/wiki/SimpleRound
function p.round2(num, numDecimalPlaces)
function p.round2(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return numModule.round2(num, numDecimalPlaces)
return math.floor(num * mult + 0.5) / mult
end
end


Line 310: Line 303:
-- Euclidean Greatest Common Divisor algorithm
-- Euclidean Greatest Common Divisor algorithm
function p.gcd(a, b)
function p.gcd(a, b)
if b ~= 0 then
return numModule.gcd(a, b)
return p.gcd(b, a % b)
else
return math.abs(a)
end
end
end


--Formats a pair of numbers as a reduced fraction
--Formats a pair of numbers as a reduced fraction
function p.fraction(n, d)
function p.fraction(n, d)
local gcd = p.gcd(n, d)
return numModule.fraction(n, d)
return p.formatnum(n/gcd)..'/'..p.formatnum(d/gcd)
end
end


--Similar to p.fraction but returns the simplified numerator and denomerator separately without formatting
--Similar to p.fraction but returns the simplified numerator and denomerator separately without formatting
function p.fractionpair(n, d)
function p.fractionpair(n, d)
local gcd = p.gcd(n, d)
return numModule.fractionpair(n, d)
return n / gcd, d / gcd
end
end


Line 406: Line 393:
--Returns a number including the sign, even if positive
--Returns a number including the sign, even if positive
function p.numStrWithSign(number)
function p.numStrWithSign(number)
if number >= 0 then
return numModule.numStrWithSign(number)
return '+'..p.formatnum(number)
else
return p.formatnum(number)
end
end
end


Line 458: Line 441:
end
end


-- Converts a string to a numeric value, or the default value if the
-- Compares two strings, optionally ignoring case
-- string isn't a number.
function p.compareString(left, right, ignoreCase)
function p.toNumberOrDefault(str, def)
-- Both are nil (equal)
local num = tonumber(str)
if left == nil and right == nil then return true end
if num then
return num
-- Only one is nil (not equal)
if left == nil or right == nil then return false end
-- Convert inputs to strings, just in case
left =  tostring(left)
right = tostring(right)
if ignoreCase == true then
return left:upper() == right:upper()
else
else
return def
return left == right
end
end
end
end


-- Attempts to convert a string to a numeric value.
function p._replace(str, searchTerm, replacementTerm)
-- Throws an error if the value isn't a number.
if str == nil then  
function p.toNumberOrError(str, errorMsg)
return str
local num = tonumber(str)
local msg = errorMsg
if msg == nil then
msg = "NaN"
end
if num then
return num
else
error(msg)
end
end
    local escapedSearch = searchTerm:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%1")
    local result = str:gsub(escapedSearch, replacementTerm)
   
    return result
end
function p.replace(frame)
local args = frame:getParent().args
return p._replace(
frame.args[1],
frame.args[2] or '',
frame.args[3] or '')
end
end


return p
return p
915

edits