Module:Recipes

local item_link = require('Module:Item').go local trim = mw.text.trim local cargo = mw.ext.cargo

local currentFrame -- global cache for current frame object.

local function itemLink(name, args) local args = args or {} args[1] = name args['small'] = 'y'	return item_link(currentFrame, args) end

-- credit: http://richard.warburton.it -- this version is with trim. local function explode(div,str) if (div=='') then return false end local pos,arr = 0,{} -- for each divider found for st,sp in function return string.find(str,div,pos,true) end do		table.insert(arr, trim(string.sub(str,pos,st-1))) -- Attach chars left of current divider pos = sp + 1 -- Jump past current divider end table.insert(arr, trim(string.sub(str,pos))) -- Attach chars right of last divider return arr end

local metals = { ['Copper/Tin'] = 1, ['Silver/Tungsten'] = 1, ['Gold/Platinum'] = 1, ['Iron/Lead'] = 1, ['Cobalt/Palladium'] = 1, ['Mythril/Orichalcum'] = 1, ['Adamantite/Titanium'] = 1, ['Tin/Copper'] = 2, ['Tungsten/Silver'] = 2, ['Platinum/Gold'] = 2, ['Lead/Iron'] = 2, ['Palladium/Cobalt'] = 2, ['Orichalcum/Mythril'] = 2, ['Titanium/Adamantite'] = 2, }

-- retuan a array of itemname, split xxx/yyy to item1=xxx, item2=yyy. If it's something like "Lead/Iron Bar", it will normalize as item1 = Iron Bar, item2 = Lead Bar. local function split(name) local count = select(2, name:gsub("/", "/", 2)) if count == 0 then -- only 1 item return { trim(name) } elseif count == 1 then -- 2 items local item1a, item1b, item2a, item2b = name:match("^%s*(%S+)%s*(.-)/%s*(%S+)%s*(.-)$") local x = metals[item1a..'/'..item2a] if tostring(item1b) == '' and x then item1b = item2b end if x == 2 then return {trim(item2a..' '..item2b), trim(item1a..' '..item1b)} else return {trim(item1a..' '..item1b), trim(item2a..' '..item2b)} end else -- 3 or more items return explode('/', name) end end

-- return 1 or 2 value(s), when input is name[note], return item, note. local function itemname(str) local item, note = str:match("^(.-)(%b[])$") if item then return item, note else return str end end

-- normalize ingredient name input, Lead Bar=>¦Lead Bar¦, Iron/Lead Bar => ¦Iron Bar¦Lead Bar¦, Lead/Iron Bar => ¦Iron Bar¦Lead Bar¦ .... local function normalize(name) local result = '¦' for k, v in ipairs(split(name)) do result = result .. itemname(v) .. '¦'	end return result end

local function escape(str) return str:gsub("'", "\'"):gsub("&#39;", "\'") end local function enclose(str) return "'" .. escape(str) .. "'" end

local function getItemGroupName(item) if item == 'Wood' or item == 'Ebonwood' or item == 'Rich Mahogany' or item == 'Pearlwood' or item == 'Shadewood' or item == 'Spooky Wood' or item == 'Boreal Wood' or item == 'Palm Wood' then return 'Any Wood' elseif item == 'Iron Bar' or item == 'Lead Bar' then return 'Any Iron Bar' elseif item == 'Sand Block' or item == 'Pearlsand Block' or item == 'Crimsand Block' or item == 'Ebonsand Block' or item == 'Hardened Sand Block' then return 'Any Sand' elseif item == 'Red Pressure Plate' or item == 'Green Pressure Plate' or item == 'Gray Pressure Plate' or item == 'Brown Pressure Plate' or item == 'Blue Pressure Plate' or item == 'Yellow Pressure Plate' or item == 'Lihzahrd Pressure Plate' then return 'Any Pressure Plate' elseif item == 'Bird' or item == 'Blue Jay' or item == 'Cardinal' then return 'Any Bird' elseif item == 'Black Scorpion' or item == 'Scorpion' then return 'Any Scorpion' elseif item == 'Squirrel' or item == 'Red Squirrel' then return 'Any Squirrel' elseif item == 'Grubby' or item == 'Sluggy' or item == 'Buggy' then return 'Any Bug' elseif item == 'Mallard Duck' or item == 'Duck' then return 'Any Duck' elseif item == 'Sulphur Butterfly' or item == 'Julia Butterfly' or item == 'Monarch Butterfly' or item == 'Purple Emperor Butterfly' or item == 'Red Admiral Butterfly' or item == 'Tree Nymph Butterfly' or item == 'Ulysses Butterfly' or item == 'Zebra Swallowtail Butterfly' then return 'Any Butterfly' elseif item == 'Firefly' or item == 'Lightning Bug' then return 'Any Firefly' elseif item == 'Snail' or item == 'Glowing Snail' then return 'Any Snail' end end

local function criStr(args) local constraints = {} -- station = ? local _station = trim(args['station'] or '') if _station ~= '' then constraints['station'] = 'station = ' .. enclose(_station) end -- result = ? local _result = trim(args['result'] or '') if _result ~= '' then local str = '' for _, v in ipairs(explode('/', _result)) do			if str ~= '' then str = str .. ' OR ' end str = str .. 'result = ' .. enclose(v) end constraints['result'] = str end -- ingredient = ? local _ingredient = trim(args['ingredient'] or '') if _ingredient ~= '' then local str = '' for _, v in ipairs(explode('/', _ingredient)) do			if str ~= '' then str = str .. ' OR ' end str = str .. "ingredients HOLDS LIKE '%¦" .. escape(v) .. "¦%'"			-- any xxx local group = getItemGroupName(v) if group then str = str .. " OR ingredients HOLDS LIKE '%¦" .. escape(group) .. "¦%'"			end end constraints['ingredient'] = str end local where = '' if constraints['station'] then where = constraints['station'] end if constraints['result'] then if where ~= '' then where = where .. ' AND ' end where = where .. '(' .. constraints['result'] .. ')' end if constraints['ingredient'] then if where ~= '' then where = where .. ' AND ' end where = where .. '(' .. constraints['ingredient'] .. ')' end return where end

local function resultCell(result, amount, version) local str = '' if version then end str = str .. itemLink(result) if amount ~= '1' then str = str .. ' ('..amount..') ' end return str end

local function ingredientsCell(args) local str = '' for _, v in ipairs(explode('^', args)) do		local item, amount = v:match('^(.-)¦(.-)$') str = str .. '' .. itemLink(item) if amount ~= '1' then str = str .. ' ('..amount..') ' end str = str .. '' end str = str .. '' return str end

local function stationCell(station) if station == 'Work Bench and Chair' then return itemLink('Work Bench') .. " and " .. itemLink('Chair') else return itemLink(station) end end

-

local p = {}

-- for p.register = function(frame) local args = frame:getParent.args local _result = trim(args['result'] or '') local _amount = trim(args['amount'] or '') local _version = trim(args['version'] or ''):lower

-- ingredients local ingredients = {} -- list of {index, itemname, amount} for k, v in pairs(args) do		if(type(k) == 'number') then if k % 2 == 1 then -- 2n-1, nth item local index, item, amount = (k+1)/2, trim(v), trim(args[k+1]) ingredients[index] = {item, amount} end end end

local serialized = '' -- serialized ingredients list for _, v in ipairs(ingredients) do serialized = serialized .. '^' .. v[1] .. '¦' .. v[2] end serialized = mw.ustring.sub(serialized, 2)

table.sort(ingredients, function(a, b) return a[1] < b[1] end) -- sort by ingredient item name local ingredients_string = '' local ingredients_string_full = '' for _, v in ipairs(ingredients) do		local name, amount = unpack(v) local ingstr = normalize(name) ingredients_string = ingredients_string .. '^' .. ingstr ingredients_string_full = ingredients_string_full .. '^' .. ingstr .. amount end --store frame:callParserFunction('#cargo_store:_table=newRecipes',{		result = _result,		amount = _amount,		version = _version,		station = trim(args['station'] or ''), 		ingredients = mw.ustring.sub(ingredients_string, 2),		ings = mw.ustring.sub(ingredients_string_full, 2),		args = serialized,	}) end

-- for p.query = function(frame) currentFrame = frame local args = frame:getParent.args local where = trim(args['where'] or '')

if where == '' then where = criStr(args) end

-- no constraint no result. if where == '' then return 'No constraint' end

-- query local result = mw.ext.cargo.query('newRecipes', 'result, amount, version, station, args', {		where = where,		groupBy = "result, amount, ings, version",		orderBy = "station, result, amount DESC, version",		limit = 2000,	})

-- format: local _title = trim(args['title'] or '') if trim(args['nostation'] or ) ~=  then -- no station str = '  ' return str else -- with station str = '  ' return str

end

end

return p