Module:ItemList/SMW

From Fallen London Wiki

Documentation for this module may be created at Module:ItemList/SMW/doc

local itemlist = require("Module:ItemList/Test SMW")

local p = {}


function quality_from_effect(effect)
    local quality, sign, value = string.match(effect, "%[%[File:.*link=([^%|]*)%|alt=%]%] %[%[%1%]%]%s+([%+-])(%d+)")
    
    value = tonumber(value)
    if sign == '-' then
        value = value * -1
    end

    if quality and value then mw.smw.set({["Has effect"] = quality .. ";" .. value}) end

    return quality, value
end

--[[
Create Best-in-Slot text for the item

Input parameters:
    @class: item class (e.g. "Hats", etc.)
    @quality: quality to check (e.g. "Shadowy". Can also be "BDR")
    @value: value of quality effect for this item (e.g. "2" or "-4")
    @fate: non-nil if this is a Fate item
    @retired: true it retired

The function returns the values:
    @bis: Best-in-Slot text for the item. nil if not actually Best-in-Slot 
    @errors: Error categories if something went wrong in the parsing
]]
function bis_msg(class, quality, value, fate, retired)
    local attributes = {
        ["Watchful"] = true,
        ["Shadowy"] = true,
        ["Persuasive"] = true,
        ["Dangerous"] = true,
        ["Bizarre"] = true,
        ["Dreaded"] = true,
        ["Respectable"] = true,
        ["A Player of Chess"] = true,
        ["Artisan of the Red Science"] = true,
        ["Glasswork"] = true,
        ["Kataleptic Toxicology"] = true,
        ["Mithridacy"] = true,
        ["Monstrous Anatomy"] = true,
        ["Shapeling Arts"] = true,
        ["Neathproofed"] = true,
        ["Zeefaring"] = true,
        ["BDR"] = true
    }
    
    local item_class = {
        ["Burden"] = true,   	
        ["Hat"] = true,
        ["Clothing"] = true,
        ["Gloves"] = true,
        ["Weapon"] = true,
        ["Boots"] = true,
        ["Companion"] = true,
        ["Treasure"] = true,        
        ["Destiny"] = true,
        ["Affiliation"] = true,
        ["Transport"] = true,
        ["Home Comfort"] = true,
        ["Ship"] = true,
        ["Spouse"] = true,
        ["Club"] = true
    }
    
    if (not quality) or (quality == nil) or (not item_class[class]) then
        -- Either we can't parse the effects field or the item class is a non-equipable class
        return nil, "[[Category:Items with Malformed Effects Field]]"
    end

	-- any effect less than 0 is not interesting here
--	if (value <= 0) then
--		return nil, nil
--	end
    
    local qualifier = nil
    local bis = nil
    local is_bdr = false
    if (attributes[quality]) then
    	if (quality == "BDR") then
    		is_bdr = true
    		quality = "Respectable,Dreaded,Bizarre"
    	end
   	
        local success, max_values = pcall(itemlist.find_minmax, class, quality, "max")
        if not success or not max_values then
            -- In case the call throws an exception. Hopefully will never happen.
	        return nil, "[[Category:Items with Module Error Parsing Effects]]"
        end
        
        local has_mood = false
        if (max_values.value > max_values.no_mood) then
        	has_mood = true
        end

		local count = 0
        if (value >= max_values.value) then
           	bis = ""
           	if (value == max_values.value) then
           		count = max_values.count
       		end
        elseif (value >= max_values.no_mood) then
        	bis = "non-[[Mood]] "
           	if (value == max_values.no_mood) then
           		count = max_values.no_mood_count
       		end
        elseif ((fate == nil) and (value >= max_values.no_fate)) then
            bis = "non-Fate "
           	if (value == max_values.no_fate) then
           		count = max_values.no_fate_count
       		end
            
            if (has_mood) then
            	bis = bis .. "non-[[Mood]] "
            end
        end
        
        if (bis) then
            if (retired) then
                -- find_minmax() returns count of non-retired items.
                -- So if this item *is* retired and still BiS, we should increment
                -- the count before deciding if it's strict/shared
                count = count + 1
            end

            bis = (count > 1 and "Shared" or "Strict") .. " Best-in-Slot " .. bis
            bis = bis .. (is_bdr and "[[BDR]] item" or "item")
            qualifier = bis
        else -- try to determine worst-in-slot status
        	local wis = nil
	        local success, min_values = pcall(itemlist.find_minmax, class, quality, "min")
	        if not success or not min_values then
	            -- In case the call throws an exception. Hopefully will never happen.
		        return nil, "[[Category:Items with Module Error Parsing Effects]]"
	        end
	        
	        local has_mood = false
	        if (min_values.value < min_values.no_mood) then
	        	has_mood = true
	        end
	        
	        local count = 0
	        if (value <= min_values.value) then
	           	wis = ""
	           	if (value == min_values.value) then
	           		count = min_values.count
	       		end
	        elseif (value <= min_values.no_mood) then
	        	wis = "non-[[Mood]] "
	           	if (value == min_values.no_mood) then
	           		count = min_values.no_mood_count
	       		end
	        elseif ((fate == nil) and (value <= min_values.no_fate)) then
	            wis = "non-Fate "
	           	if (value == min_values.no_fate) then
	           		count = min_values.no_fate_count
	       		end
	            
	            if (has_mood) then
	            	wis = wis .. "non-[[Mood]] "
	            end
	        end
	        
	        if (wis) then
	            if (retired) then
	                -- find_minmax() returns count of non-retired items.
	                -- So if this item *is* retired and still WiS, we should increment
	                -- the count before deciding if it's strict/shared
	                count = count + 1
	            end
	
	            wis = (count > 1 and "Shared" or "Strict") .. " Worst-in-Slot " .. wis
	            wis = wis .. (is_bdr and "[[BDR]] item" or "item")
	            qualifier = wis
	        end	
        end
	end

    return qualifier, nil
end

--[[
Show all effects which were passed to the calling Item template,
no matter if there is only the "Effect1" parameter, or if it goes to Effect100.
]]
function p.effects(frame)
    targs = frame:getParent().args
    res = ""
    list = {}
    name = frame.args.name
 
    for k, v in pairs(targs) do
        num = string.match(k, "^Effects(%d+)$")
        if (num) then
            table.insert(list, tonumber(num))
        end
    end
    table.sort(list)

    local total_bdr = 0
    local has_bis = false
    
    local retired = targs["Access"] and targs["Access"] == "Retired"

    for _, num in ipairs(list) do
    	local effect = targs["Effects" .. num]
  	    local quality, value = quality_from_effect(effect)

	    local bdr = {
    	    ["Bizarre"] = true,
	        ["Dreaded"] = true,
        	["Respectable"] = true
    	}

		res = res .. "*" .. effect
		
        -- special case: ignore. Companion can never be used while in London
        if (name ~= "The Imperturbable Patroness") then
            bis, errors = bis_msg(targs["Item Type"], quality, value, targs["Fate"], retired)

            if (bis ~= nil) then
                has_bis = true
                res = res .. " (" .. bis .. ")"
            end

            if (errors ~= nil) then
                res = res .. errors
            end

            if (bdr[quality]) then
                total_bdr = total_bdr + value
            end
        end

		res = res .. "\n"
    end

	-- If this is a BDR item, check separately for BDR Best-in-Slot
	if (total_bdr > 0) then
    	bis, errors = bis_msg(targs["Item Type"], "BDR", total_bdr, targs["Fate"], retired)
    	
        if (bis ~= nil) then
            res = res .. ":* " .. (has_bis and "Also: " or "") .. bis
			res = res .. "\n"
        end

		if (errors ~= nil) then
			res = res .. errors
		end
	end

    return res
end

return p