Outward Wiki
Advertisement

Module used by Used In template and Crafting recipes template to list recipes.


-- TODO: This module is a bit overly obtuse and difficult to follow. Could do with a refactoring.

local p = {}
function p.recipes(frame)
	if frame == mw.getCurrentFrame() then
		args = require('Module:ProcessArgs').merge(true)
	else
		frame = mw.getCurrentFrame()
	end	
	
	local noHeader = args.noheader or 'false'
	local searchBy = args.searchby or "ingredient"
	local searchFor = args.searchfor or mw.title.getCurrentTitle().text
	local fulfills = args.fulfills or ''
	local limit = args.limit or 10000
	local isListing = args.listing or 'false'
	
	local category = args.category or ''
	local class = args.class or ''
	local itype = args.type or ''
	local fullImage = args.fullimage or 'false'

	local isBlacksmith = args.isBlacksmith or nil

	mw.log(string.format('searchBy: %s', searchBy))
	mw.log(string.format('searchFor: %s', searchFor))
	mw.log(string.format('fulfills: %s', fulfills))
	
	local result = p.doQuery(searchBy,searchFor,fulfills,limit,category,class,itype,isListing,isBlacksmith)
	if not result then
		return '<span style="color:#e77">\'\'No items found.\'\'</span>'
	end
	
	formattedResult = p.formatResult(result, frame, isBlacksmith)
	mw.logObject(formattedResult)
	return p.makeTable(formattedResult,noHeader)
end

function p.doQuery(searchBy, searchFor, fulfills,limit,category,class,itype,isListing,isBlacksmith)
	
	local joinQuery = ''
	if isBlacksmith == nil then
		joinQuery = 'ItemData._pageName=ItemRecipes._pageName'
	else
		joinQuery = 'ItemData._pageName=ItemRecipes.itemname'
	end
	
	local result = mw.ext.cargo.query('ItemRecipes,ItemData',
		p.cargoFields(),
		{
			join = joinQuery,
			where = p.cargoWhere(searchBy,searchFor,fulfills,category,class,itype,isListing,isBlacksmith),
			orderBy = 'ItemRecipes.itemname',
			groupBy = 'itemname,station,count',
			limit = limit
		}
	)
	if not next(result) then
		return nil
	else
		return result
	end
end

function p.cargoFields()
	return 'ItemRecipes._pageName=_pageName,ItemRecipes.itemname=itemname,ItemData.name=name,ItemData.image=image,ItemRecipes.count=count,ItemRecipes.ingredient1=ingredient1,ItemRecipes.ingredient2=ingredient2,ItemRecipes.ingredient3=ingredient3,ItemRecipes.ingredient4=ingredient4,ItemRecipes.station=station,ItemRecipes.blacksmith=blacksmith,ItemRecipes.blacksmithSilver=blacksmithSilver,ItemRecipes.bIngredient1=bIngredient1,ItemRecipes.bIngredient1qty=bIngredient1qty,ItemRecipes.bIngredient2=bIngredient2,ItemRecipes.bIngredient2qty=bIngredient2qty,ItemRecipes.bIngredient3=bIngredient3,ItemRecipes.bIngredient3qty=bIngredient3qty,ItemData.DLC=DLC'
end

function p.cargoWhere(searchBy,searchFor,fulfills,category,class,itype,isListing,isBlacksmith)
	local whereOr = {}
	local whereAnd = {}
	local fields = {}
	local fulfills = p.explode(',', fulfills)
	local categories = p.explode(',', category)
	
	if isBlacksmith == nil then
		whereAnd[#whereAnd+1] = 'ItemRecipes.ingredient1 IS NOT NULL'
	else
		whereAnd[#whereAnd+1] = 'ItemRecipes.bIngredient1 IS NOT NULL'
	end
	
	if searchBy == 'ingredient' then
		fields = {'ItemRecipes.ingredient1','ItemRecipes.ingredient2','ItemRecipes.ingredient3','ItemRecipes.ingredient4','ItemRecipes.alternateIngredients','ItemRecipes.bIngredient1','ItemRecipes.bIngredient2','ItemRecipes.bIngredient3'}
		whereAnd[#whereAnd+1] = string.format('ItemRecipes._pageName != "%s"', searchFor)
	elseif searchBy == 'station' then
		fields = {'ItemRecipes.station'}
	elseif searchBy == 'result' then
		if isBlacksmith == nil then
			fields = {'ItemRecipes._pageName'}
		else
			fields = {'ItemRecipes.itemname'}
		end
	end	
	
	for k,v in ipairs(fields) do
		if v == 'ItemRecipes.alternateIngredients' then
			operator = 'HOLDS'
		else 
			operator = '='
		end
		if searchFor == 'none' then 
			whereOr[#whereOr+1] = string.format('%s IS NULL', v)
		else
			whereOr[#whereOr+1] = string.format('%s %s "%s"', v, operator, searchFor)
		end
		for k2,v2 in ipairs(fulfills) do
			whereOr[#whereOr+1] = string.format('%s %s "%s"', v, operator, v2)
		end
	end
		
	whereOrString = table.concat(whereOr, ' OR ')
	
	if isListing == 'true' then
		if categories ~= nil then
			local whereCategory = {}
			for kc,vc in ipairs(categories) do
				if not p.isempty(vc) then
					whereCategory[#whereCategory+1] = string.format('ItemData.category = "%s"', vc)
				end
			end
			whereCategoryString = table.concat(whereCategory, ' OR ')
			if not p.isempty(whereCategoryString) then
				whereAnd[#whereAnd+1] = string.format('(%s)', whereCategoryString)
			end
		end
		if not p.isempty(class) then
			whereAnd[#whereAnd+1] = string.format('ItemData.class = "%s"', class)
		end
		if not p.isempty(itype) then
			whereAnd[#whereAnd+1] = string.format('ItemData.type = "%s"', itype)
		end
	end
	
	whereAndString = table.concat(whereAnd, ' AND ')
	
	if not p.isempty(whereOrString) and not p.isempty(whereAndString) then
		whereString = string.format('%s AND (%s)', whereAndString, whereOrString)
	elseif not p.isempty(whereAndString) then
		whereString = whereAndString
	else
		whereString = whereOrString
	end
	
	return whereString
end

function p.formatResult(result,frame,isBlacksmith)
	local formatted = {}
	for k,v in ipairs(result) do
		formatted[k] = p.formatRow(v,frame,isBlacksmith)
	end
	
	return formatted
end

function p.formatRow(row,frame,isBlacksmith)
	local formattedRow = {}
	local columns = {'Result','Ingredients','Station'}
	local count = ''
	local link = ''
	if isBlacksmith == nil then
		link = row._pageName
	else
		link = row.itemname	
	end
	local image = ''
	local ingredient1 = "''unknown''"
	local ingredient2 = ''
	local ingredient3 = ''
	local ingredient4 = ''
	
	if p.isempty(row.image) then
		image = 'Placeholder.png'
	else 
		image = row.image
	end
	
	if not p.isempty(row.count) then
		count = string.format('%dx ', row.count)
	end
	
	if p.isempty(row.station) then
		station = "''None''"
    else
        station = row.station
        if (station == 'Blacksmiths') then
            station = string.format("[[%s]]", row.blacksmith)
        else
            station = string.format("[[%s]]", row.station)
        end
	end
	
    if (row.station == 'Blacksmiths') then
        if not p.isempty(row.blacksmithSilver) then
            ingredient1 = string.format("<ul><li>%s {{s}} [[silver]]</li>", row.blacksmithSilver)
        else
            ingredient1 = '<ul>'
        end
        if not p.isempty(row.bIngredient1) then
            ingredient2 = string.format("<li>%sx [[%s]]</li>", row.bIngredient1qty, row.bIngredient1)
        end
        if not p.isempty(row.bIngredient2) then
            ingredient3 = string.format("<li>%sx [[%s]]</li>", row.bIngredient2qty, row.bIngredient2)
        end
        if not p.isempty(row.bIngredient3) then
            ingredient4 = string.format("<li>%sx [[%s]]</li></ul>", row.bIngredient3qty, row.bIngredient3)
        else
            ingredient4 = "</ul>"
        end
    else
        if not p.isempty(row.ingredient1) then
            ingredient1 = string.format("<ul><li>[[%s]]</li>", row.ingredient1)
        end
        if not p.isempty(row.ingredient2) then
            ingredient2 = string.format("<li>[[%s]]</li>", row.ingredient2)
        end
        if not p.isempty(row.ingredient3) then
            ingredient3 = string.format("<li>[[%s]]</li>", row.ingredient3)
        end
        if not p.isempty(row.ingredient4) then
            ingredient4 = string.format("<li>[[%s]]</li>", row.ingredient4)
        else
            ingredient4 = "</ul>"
        end
    end
	
	local imgAndName = string.format('[[File:%s|35px|frameless|center|link=%s]]%s[[%s]]', image, link, count, link)
	if not p.isempty(row.DLC) then
		imgAndName = imgAndName .. ' {{' .. row.DLC .. '}}'
	end

	formattedRow = {
		frame:preprocess(imgAndName),
		frame:preprocess(string.format('<div>%s%s%s%s</div>', ingredient1, ingredient2, ingredient3, ingredient4)),
		frame:preprocess(station)
	}
	
	return formattedRow
end

function p.makeTable(formatted, noHeader)
	local tbl = mw.html.create('table'):addClass('wikitable')
	if noHeader == 'false' then 
		tbl:tag('tr')
			:tag('th'):wikitext('Result'):done()
			:tag('th'):wikitext('Ingredients'):done()
			:tag('th'):wikitext('Station'):done()
	end
	for _, row in ipairs(formatted) do 
		tr = tbl:tag('tr')
		for i, v in ipairs(row) do
			if (i == 2) then
				tr:tag('td'):cssText('text-align: left'):wikitext(v)
			else
				tr:tag('td'):cssText('text-align: center'):wikitext(v)
			end
		end
	end
	return tbl
end

-- Source: http://lua-users.org/wiki/MakingLuaLikePhp
-- Credit: http://richard.warburton.it/
function p.explode(div,str)
    if (div=='') then return false end
    local pos,arr = 0,{}
    for st,sp in function() return string.find(str,div,pos,true) end do
        table.insert(arr,string.sub(str,pos,st-1))
        pos = sp + 1
    end
    table.insert(arr,string.sub(str,pos))
    return arr
end


function p.isempty(s)
	return s == nil or s == '' or s == 0 or s == false
end

return p
Advertisement