SMITE Esports Wiki
Advertisement
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

To edit the documentation or categories for this module, click here.


local util_args = require('Module:ArgsUtil')
local util_table = require('Module:TableUtil')
local util_text = require('Module:TextUtil')
local util_vars = require('Module:VarsUtil')
local bool_false = { ['false'] = true, ['0'] = true, ['no'] = true, [''] = true }
local argPrefix = 'q?'
local lang = mw.getLanguage('en')
local bool_to_str = { [true] = 'Yes', [false] = 'No' }

local p = {}

function p.queryAndCast(query, dontcast)
	local tables = util_table.concatIfTable(query.tables)
	local fields = util_table.concatIfTable(query.fields)
	query.join = util_table.concatIfTable(query.join)

	local result = mw.ext.cargo.query(tables, fields, query)
	
	if dontcast then
		return result
	else
		p.cast(result, query.types or {}, query.coalesce or {})
		return result
	end
end

function p.cast(result, types, coalesce)
	for i, row in ipairs(result) do
		for k, v in pairs(row) do
			row[k] = p.castField(v, types[k])
			for coalesceKey, coalesceValueList in pairs(coalesce) do
				row[coalesceKey] = p.coalesce(row, coalesceValueList)
			end
		end
	end
end

function p.coalesce(row, tbl)
	for _, v in ipairs(tbl) do
		if row[v] then
			return row[v]
		end
	end
	return nil
end

function p.castField(v, v_type)
	if v == '' then
		return nil
	elseif v_type == 'boolean' then
		return p.strToBool(v)
	elseif v_type == 'number' then
		return tonumber(v)
	else
		return v
	end
end

function p.getOneResult(query)
	local result = p.queryAndCast(query)
	if result[1] then
		return result[1][query.fields]
	end
	return nil
end

function p.getOneRow(query)
	local result = p.queryAndCast(query)
	return result[1] or {}
end

function p.getOneField(query, field)
	local result = p.queryAndCast(query)
	local tbl = {}
	for i, row in ipairs(result) do
		tbl[#tbl+1] = row[field]
	end
	return tbl
end

function p.strToBool(v)
	if not v then
		return false
	elseif bool_false[lang:lc(v)] then
		return false
	end
	return true
end

function p.makeDict(result, key)
	local tbl = {}
	for _, row in ipairs(result) do
		tbl[row[key]] = row
	end
	return tbl
end

function p.makeConstDict(result, key, value)
	local tbl = {}
	for _, row in ipairs(result) do
		tbl[row[key]] = row[value]
	end
	return tbl
end

function p.makeOrderedDict(result, key, sortkey, increasing)
	--[[
	Format the table like this:
	{
		a1, a2, a3, a4,
		a1 = { key = value, ... },
		a2 = { key = value, ... },
		a3 = { key = value, ... },
		a4 = { key = value, ... }
	}
	]]
	local tbl = {}
	for k, row in ipairs(result) do
		tbl[k] = row[key]
		tbl[row[key]] = mw.clone(row)
	end
	if sortkey then
		util_table.dictByKeys(tbl, sortkey, increasing)
	end
	return tbl
end

function p.getOrderedDict(query, key, sortkey, increasing)
	local result = p.queryAndCast(query)
	return p.makeOrderedDict(result, key, sortkey, increasing)
end

function p.getOrderedList(query, key)
	local result = p.queryAndCast(query)
	return p.makeOrderedList(result, key)
end

function p.makeOrderedList(result, key)
	local tbl = {}
	for k, row in ipairs(result) do
		tbl[#tbl+1] = row[key]
	end
	return tbl
end

function p.groupResultOrdered(result, key, f)
	local data = {}
	local this
	local thisvalue
	local thistab
	local i = 1
	for _, row in ipairs(result) do
		if not row[key] then row[key] = 'Uncategorized' end
		if row[key] ~= thisvalue then
			data[#data+1] = { name = row[key], index = i }
			i = i + 1
			thistab = data[#data] or {}
			thisvalue = row[key]
		end
		thistab[#thistab+1] = f and f(row) or row
	end
	return data
end	

function p.groupResultByValue(result, key, f)
	local data = {}
	local this
	local thisvalue
	local i = 1
	for _, row in ipairs(result) do
		if row[key] ~= thisvalue then
			thisvalue = row[key]
			data[thisvalue] = { name = row[key] }
			i = i + 1
			thistab = data[thisvalue]
		end
		thistab[#thistab+1] = f and f(row) or row
	end
	return data
end

function p.queryFromArgs(args, defaults)
	-- sometimes we want to specify query args in the template
	-- this function parses them into args that cargo will understand
	-- change argPrefix above to change the prefix for query params
	local query = mw.clone(defaults or {})
	for k, v in pairs(args) do
		if string.sub(k, 0, 2) == argPrefix then
			query[string.sub(k,3)] = v
		end
	end
	return query
end

function p.store(tbl)
	tbl[1] = ''
	for k, v in pairs(tbl) do
		if type(v) == 'boolean' then
			tbl[k] = bool_to_str[v]
		end
	end
	mw.getCurrentFrame():callParserFunction{
		name = '#cargo_store',
		args = tbl
	}
	return
end

function p.doWeStoreCargo(nocargo, desiredNamespace,title)
	local argOkay = not util_args.castAsBool(nocargo)
	if not desiredNamespace then
		return argOkay
	end
	if not title then
		title = mw.title.getCurrentTitle()
	end
	return argOkay and title.nsText == desiredNamespace
end

function p.whereFromArg(str, ...)
	-- if an arg is defined, formats a string with the arg to be included in a where table
	-- if it's not defined, returns false and NOT nil so the table can be used
	-- with util_table.concat
	if not next({...}) then
		return false
	else
		return str:format(...)
	end
end

function p.whereFromArgList(str, argTbl, sep, f)
	if not sep then sep = '%s*,%s*' end
	if not argTbl then return nil end
	argTbl = util_table.guaranteeTable(argTbl)
	if not next(argTbl) then return end
	local splitArgs = {}
	for _, arg in ipairs(argTbl) do
		splitArgs[#splitArgs+1] = util_args.splitAndMap(arg, sep, f)
	end
	local argsForFormat = {}
	for lineIndex, v in ipairs(splitArgs[1]) do
		argsForFormat[lineIndex] = {}
		for i, arg in ipairs(splitArgs) do
			argsForFormat[lineIndex][i] = arg[lineIndex]
		end
	end
	local where = {}
	for _, condition in ipairs(argsForFormat) do
		where[#where+1] = p.whereFromArg(str, unpack(condition))
	end
	return ('(%s)'):format(p.concatWhereOr(where))
end

function p.concatWhere(tbl)
	local arr = {}
	-- pairs because maybe some entries are nil, and since it's an AND, order doesn't matter
	for _, v in pairs(tbl) do
		if v then
			arr[#arr+1] = v
		end
	end
	if not next(arr) then return nil end
	return '(' .. util_table.concat(arr, ' AND ') .. ')'
end

function p.concatWhereOr(tbl)
	local arr = {}
	-- pairs because maybe some entries are nil, and since it's an AND, order doesn't matter
	for _, v in pairs(tbl) do
		if v then
			arr[#arr+1] = v
		end
	end
	return '(' .. util_table.concat(arr, ' OR ') .. ')'
end

function p.fakeHolds(field, str, sep)
	sep = sep or ','
	return ('%s__full RLIKE ".*(^|%s)%s($|%s).*"'):format(field, sep, str, sep)
end

function p.makeMinMaxQuery(query, field, orderby, order)
	-- modifies a pre-existing query to add an extra set of conditions to get the max/min value of some field
	-- order will be either MIN or MAX, and orderby is usually going to be a date/datetime
	-- example: c.makeMinMaxQuery(query, 'SP.Champion','SP.Time','MAX')
	--to get the most-recent played champions
	local query2 = mw.clone(query)
	query2.fields = ("%s(%s)=value, %s=field"):format(order or 'MAX', orderby, field)
	local result = p.queryAndCast(query2)
	util_table.mapInPlace(result, function(row)
		return row.value and ('(%s="%s" AND %s="%s")'):format(field, row.field, orderby, row.value)
	end)
	local newwhere = {
		next(result) and ("(%s)"):format(p.concatWhereOr(result)),
		query.where and ("(%s)"):format(query.where)
	}
	return p.concatWhere(newwhere)
end

function p.getUniqueLine(...)
	local args = {...}
	for k, v in ipairs(args) do
		if type(v) == 'string' then
			args[k] = util_vars.getGlobalIndex(v) or v
		end
	end
	return mw.title.getCurrentTitle().text .. util_table.concat(args, '_')
end

return p
Advertisement