Module:Common

-- Module:Common -- Common operations that can be used across multiple modules

local libraryUtil = require('libraryUtil')

local p = {}

-- Define often-used variables and functions. local floor = math.floor local infinity = math.huge local checkType = libraryUtil.checkType local checkTypeMulti = libraryUtil.checkTypeMulti

-- Table operations

-- Loops through each of the tables within the array/table, selecting the value of the key and adding it to a table to be returned -- If the child table does not contain a value with the key, or if the child table is null, a nil value is substituted (i.e. no checking is done) function p.tableSelectValues(rootTable, key) local result = { } if (rootTable ~= nil) then for _, childTable in ipairs(rootTable) do			if (childTable ~= nil) then table.insert(result, childTable[key]) else table.insert(result, nil) end end end return result end -- Returns true if the table/array contains a table that has a key with a specific value, otherwise returns false function p.tableHasTableWithKeyOfValue(table, key, value) local result = p.tableGetTableWithKeyOfValue(table, key, value) return (result ~= nil) end -- Returns a table from the table/array that contains a key with a specific value, otherwise returns nil -- For example calling TableGetTableWithKeyOfValue(test, "id", 1) for the following table: test = { first = { id = 1, data = "somedata" }, second = { id = 2, data = "somemoredata" }, } Will return: { id = 1, data="somedata" } -- function p.tableGetTableWithKeyOfValue(tbl, key, value, caseInsensitive) -- Ensure that the key or table isn't nil if (key == nil or tbl == nil) then return nil end -- Default caseInsensitive to false if (caseSensitive == nil) then caseSensitive = false end -- Loop over tables in table for i = 1, #tbl do		-- Check to see if the table has a value at the specified key if ((p.tableHasKeyWithValue(tbl[i], key, value) == true) or (caseInsensitive and p.tableHasKeyWithValueCaseInsensitive(tbl[i], key, value) == true)) then return tbl[i] end end --for _, childTable in ipairs(tbl) do	--	if (tableHasKeyWithValue(childTable, key, value) == true) then --		return childTable --	end --end return nil end -- Returns true if the table has a key with a specific value (case sensitive) function p.tableHasKeyWithValue(table, key, value) return (table[key] == value) end

-- Returns true if the table has a key with a specific value (case insensitive) function p.tableHasKeyWithValueCaseInsensitive(table, key, value) return (string.lower(table[key]) == string.lower(value)) end

-- Returns true if the table contains a specific value, assuming the table is indexed by integer (array-like) function p.tableContainsValue(tbl, value) for _, v in ipairs(tbl) do       if v == value then return true end end return false end

-- Asserts if the value of the key in the input table is nil or empty, returning true if so and erroring function p.tableValueIsNilOrEmpty(tbl, key) if (p.isNilOrEmpty(tbl[key]) == true) then error("Key \""..key.."\" in input table is nil or empty") return true else return false end end

-- Returns true if the input table is sequentially indexed function p.isArray(t) local i = 0 for _ in pairs(t) do		i = i + 1 if t[i] == nil then return false end end return true end

-- Takes a table and returns an array containing all the indexes (integer values) -- of any numerical keys that have non-nil values, sorted in numerical order -- Equivalent to Module:TableTools.numKeys on Wikipedia function p.tableGetIndexes(t) checkType('numKeys', 1, t, 'table') local isPositiveInteger = p.isPositiveInteger local nums = {} for k, v in pairs(t) do		if isPositiveInteger(k) then nums[#nums + 1] = k		end end table.sort(nums) return nums end

-- String operations

function p.upperCaseFirst(str) return (str:gsub("^%l", string.upper)) end

function p.startsWith(str, start) return str:sub(1, #start) == start end

function p.endsWith(str, ending) return ending == "" or str:sub(-#ending) == ending end

-- This template will add the appropriate ordinal indicator to a given number (typically integer), returning a string containing both the number and the ordinal indicator. -- For an integer ending in 1, 2 or 3 (except for integers ending in 11, 12 or 13), the ordinal suffix will be -st, -nd and -rd, respectively. -- If the input is not a number, no ordinal indicator will be added. function p.stringAddOrdinal(number) local str = tostring(number) -- If the input is not a number, just return it as a string if (tonumber(number) == nil) then return str end if (p.endsWith(str, "1") and not p.endsWith(str, "11")) then return str.."st" elseif (p.endsWith(str, "2") and not p.endsWith(str, "12")) then return str.."nd" elseif (p.endsWith(str, "3") and not p.endsWith(str, "13")) then return str.."rd" else return str.."th" end end

-- Number operations

-- This function returns true if the given value is a positive integer, and false if not. function p.isPositiveInteger(v) return type(v) == 'number' and v >= 1 and floor(v) == v and v < infinity end

-- This function returns true if the given number is a NaN value, and false function p.isNan(v) return type(v) == 'number' and tostring(v) == '-nan' end

-- Logical and misc operations

-- Returns true if input (string) is nil or empty function p.isNilOrEmpty(str) return (str == nil or str == "") end

function p.isNotNilOrEmpty(str) return not p.isNilOrEmpty(str) end

-- Outputs the default if input is empty or nil function p.default(input, default) if (input == "" or input == nil) then return default else return input end end

-- Operates like the ternary operator in C#/JS etc function p.ternary(condition, valueIfTrue, valueIfFalse) if (condition == nil or condition == false)	 then return valueIfFalse else return valueIfTrue end end

return p