Disney Magic Kingdoms Wiki
Advertisement
Disney Magic Kingdoms Wiki

Description

This module provides utility functions for use in other modules.


--[=[<nowiki>

Lua Module for Utility Functions

wordinal:
    Word-Ordinal form of number
    Parameters:
    	1 = Number (0-99)
    Return:
    	Ordinal in Word form of number
    	"??" for 0 or non-numeric input
    	Input number for number >= 100

ordinal:
	Ordinal Numbers
	Parameters:
		1 = Number
		2 = Cardinal (return cardinal number if true)
	Return:
		Ordinal Number
		(Or simply number if cardinal is true)
		it does not seem logical to have an ordinal function
		return cardinal numbers, but it saves 'Ifs' in the
		calling module
--]=]

local p = {}

local date = require('Dev:Date')

local tOnesOrd = {
	[0] = '??',
	[1] = 'first',
	[2] = 'second',
	[3] = 'third',
	[4] = 'fourth',
	[5] = 'fifth',
	[6] = 'sixth',
	[7] = 'seventh',
	[8] = 'eighth',
	[9] = 'ninth',
	[10] = 'tenth',
	[11] = 'eleventh',
	[12] = 'twelfth',
	[13] = 'thirteenth',
	[14] = 'fourteenth',
	[15] = 'fifteenth',
	[16] = 'sixteenth',
	[17] = 'seventeenth',
	[18] = 'eighteenth',
	[19] = 'nineteenth'
}

local tTensOrd = {
	[2] = 'twentieth',
	[3] = 'thirtieth',
	[4] = 'fortieth',
	[5] = 'fiftieth',
	[6] = 'sixtieth',
	[7] = 'seventieth',
	[8] = 'eightieth',
	[9] = 'ninetieth'
}

local tTens = {
	[2] = 'twenty',
	[3] = 'thirty',
	[4] = 'forty',
	[5] = 'fifty',
	[6] = 'sixty',
	[7] = 'seventy',
	[8] = 'eighty',
	[9] = 'ninety'
}

-- return word form ordinal number
function p.wordinal(num)
	local n = tonumber(num) or 0
	if n >= 100 then return num end

	if n < 20 then
		return tOnesOrd[n]
	elseif n % 10 == 0 then
		return tTensOrd[n / 10]
	else
		return tTens[math.floor(n / 10)] .. '-' .. tOnesOrd[n % 10]
	end
end

local function _ordinal(num, cardinal)
    local n = tonumber(num) or 0
    local i = math.fmod(n,10)
    local o = ""

	if not cardinal then
		o = (i==1 and n~=11 and "st")
		    or (i==2 and n~=12 and "nd")
		    or (i==3 and n~=13 and "rd")
		    or (n~=0 and "th")
		    or ""
	end

    return tostring(n) .. o
end

-- return ordinal number
function p.ordinal(num, cardinal)
	return _ordinal(num, cardinal)
end

-- return string with "," as thousands seperator
function p.th_comma(n) -- credit http://richard.warburton.it
	local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$')
	return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right
end

-- getArgs
-- if no frame then local call
-- if parameter 2: preferParent = true, the parent arguments take
-- precedence over the frame arguments
-- otherwise frame arguments take precedence over parent arguments
function p.getArgs(frame, preferParent)
    local tArgs = {}

    if
        type(frame.args) == 'table' and
        type(frame.getParent) == 'function'
    then
    	local fArgs = frame.args
    	local parent = frame:getParent()
    	local pArgs = parent and parent.args or {}

		if preferParent then
			fArgs, pArgs = pArgs, fArgs
		end
		
		for k, v in pairs(fArgs) do
			if type(v) == 'string' then
				v = v:match('^%s*(.-)%s*$')
				if v == "" then v = nil end
			end
			tArgs[k] = v
		end
		for k, v in pairs(pArgs) do
			if not tArgs[k] then
				if type(v) == 'string' then
					v = v:match('^%s*(.-)%s*$')
					if v == "" then v = nil end
				end
				tArgs[k] = v
			end
		end
    elseif type(frame) == 'table' then
		for k, v in pairs(frame) do
			if type(v) == 'string' then
				v = v:match('^%s*(.-)%s*$')
				if v == "" then v = nil end
			end
			tArgs[k] = v
		end
	else
        tArgs = frame
    end

    return tArgs
end

-- Date Functions
local eventstarttime = " 15:00:00 UTC"
function p.dayStart()
	-- This specifies the UTC time the events start
	-- Used to be 15:00:00 UTC, but currently has been changed to 16:00:00 UTC
	return eventstarttime
end

-- Output Date in text format
function p.strDate(sDate, days, noYear, cardinal, whenTo)
	if not sDate or sDate == "" then return "" end

    local theDate = date(sDate .. eventstarttime)

    local nDays = tonumber(days) or 0

    local day = ""
    local retText = {}

	if whenTo then
		if theDate < date() then
			table.insert(retText, " started on ")
		else
			table.insert(retText, " will start on ")
		end
	end

    if nDays > 0 then
        local start = theDate:copy()
        theDate:adddays(nDays)
        
        table.insert(retText, _ordinal(start:getday(), cardinal))

        if whenTo or start:getmonth() ~= theDate:getmonth() then
            table.insert(retText, start:fmt(" %B"))
        end

        if whenTo or (not noYear and start:getyear() ~= theDate:getyear()) then
            table.insert(retText, start:fmt(" %Y"))
        end

		if whenTo then
			if theDate < date() then
				table.insert(retText, " and ended on ")
			else
				table.insert(retText, " and will end on ")
			end
		else
	        table.insert(retText, " - ")
	    end
    end

    table.insert(retText, _ordinal(theDate:getday(), cardinal))

    table.insert(retText, theDate:fmt(" %B"))

    if not noYear then
        table.insert(retText, theDate:fmt(" %Y"))
    end

	if whenTo and nDays > 0 then
		table.insert(retText, ", lasting ")
		table.insert(retText, tostring(nDays))
		if nDays > 1 then
			table.insert(retText, " days")
		else
			table.insert(retText, " day")
		end
	end
    return table.concat(retText)
end

-- output multiple dates in text format
function p.strMultiDate(tDates, cardinal)
	if type(tDates) ~= 'table' then return "" end

    table.sort(tDates)

    local multiDates = {}

    local prevDate = nil

    local monAnd = nil
    local yearAnd = nil

    for i = #tDates, 1, -1 do
        local curDate = date(tDates[i])
        local parts = {_ordinal(curDate:getday(), cardinal),
                        "", "", ""}

        if prevDate then
            if prevDate:getyear() ~= curDate:getyear() then
                parts[2] = curDate:fmt(" %B")
                parts[3] = curDate:fmt(" %Y")
                
                if yearAnd then
                    parts[4] = ", "
                else
                    if monAnd then
                        parts[4] = "; and "
                    else
                        parts[4] = " and "
                        yearAnd = true
                    end
                end
                monAnd = nil
            else
                if prevDate:getmonth() ~= curDate:getmonth() then
                    parts[2] = curDate:fmt(" %B")

                    if monAnd then
                        parts[4] = "; and "
                    else
                        parts[4] = " and "
                    end
                    monAnd = nil
                else
                    if monAnd then
                        parts[4] = ", "
                    else
                        parts[4] = " and "
                        monAnd = true
                    end
                end
            end
        else
            parts[2] = curDate:fmt(" %B")
            parts[3] = curDate:fmt(" %Y")
        end

        multiDates[i] = parts
        prevDate = curDate
    end

    prevDate = nil

    monAnd = nil
    yearAnd = nil

    for i = 1, #tDates do
        local curDate = date(tDates[i])

        if prevDate then
            if prevDate:getyear() == curDate:getyear() then
                if prevDate:getmonth() == curDate:getmonth() then
                    if multiDates[i][4] == " and " and monAnd then
                        multiDates[i][4] = "; and "
                    end
                end
            end
        end

        if multiDates[i][4] == " and " then
            monAnd = true
        end
        prevDate = curDate
    end

    local retText = {}

    for _, sDate in ipairs(multiDates) do
        table.insert(retText, table.concat(sDate))
    end

    return table.concat(retText)
end

return p
Advertisement