Module:NodeInfo

Revision as of 06:52, 17 April 2015 by Nanamin (talk | contribs)

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

local BaseTable = require("Module:BaseTable")
local Formatting = require('Module:Formatting')
local EnemyShip = require("Module:EnemyShip")

local format = require('Module:StringInterpolation').format

local NodeInfo = BaseTable({
    _item_class = EnemyShip,
    _header_template = [[!#
    !Form
    !Fleet
    !AP/AS/AS+]],
    _column_cell_templates = {
        node = [[| colspan="${colspan}" rowspan="${rowspan}" style="text-align: center; color: ${color}; background-color: ${bg_color};" |${values.node}]],
        formation = [[| style="text-align: center; background-color: ${bg_color}; color: ${color};" |${values.formation}]],
        fleet = [[| style="width: 500px; background-color: ${bg_color};" |${values.fleet}]],
        as = [[| style="text-align: center; background-color: ${bg_color}; color: ${color};" |${values.as}]],
    },
    _empty_node_template = [[| style="text-align: center;" |${values.node}
    | colspan="3" style="text-align: center;" |Must be my imagination (battle avoided)]],
    _resource_node_template = [[| style="text-align: center; background-color: ${values.bg_color};" |${values.node}
    | style="text-align: center; background-color: ${values.bg_color};" |${values.node_type}
    | colspan="2" style="text-align: center; background-color: ${values.bg_color};" |${values.text}]],
    _columns = {
        "node",
        "formation",
        "fleet",
        "as",
    },
    _day_battle_color = "gold",
    _night_battle_color = "blue",
    _night_battle_bg_color = "lightblue",
    _boss_battle_color = "red",
    --_resource_node_bg_color = "lightgreen",
    _resource_node_bg_color = "initial",
    --_maelstrom_node_bg_color = "pink",
    _maelstrom_node_bg_color = "initial",
})

function NodeInfo:node(row)
    local color, time_color, bg_color = "initial", self._day_battle_color, "initial"
    if row.boss then
        color = self._boss_battle_color
    end
    if row.time == "Night" then
        time_color = self._night_battle_color
        bg_color = self._night_battle_bg_color
    end
    return { values = { node = row.node, time = row.time }, color = color, time_color = time_color, bg_color = bg_color }
end

function NodeInfo:formation(row)
    if row.final then
        row.formation = row.formation .. " (Final)"
    end
    local color = "initial"
    if row.boss then
        color = self._boss_battle_color
    end
    return { values = { formation = row.formation }, color = color }
end

function NodeInfo:fleet(row)
    return { values = { fleet = row.fleet } }
end

function NodeInfo:as(row)
    color = "initial"
    if row.boss then
        color = self._boss_battle_color
    end
    return { values = { as = row.as }, color = color }
end

function NodeInfo:process_node(item)
    local split = mw.ustring.find(item, '/')
	local node, time
	if split then
	    node = mw.ustring.sub(item, 1, split - 1)
	    time = mw.ustring.sub(item, split + 1):gsub("^%l", string.upper)
	else
	    node = item:upper()
	    time = ""
	end
	return node, time
end

function NodeInfo:insert_item(node, time, boss, final, formation, fleet, as, item_key)
    local air_parity = string.format("%.1d", as * (2 / 3))
    local air_supremacy = tostring(as * 2)
    local air_string = air_parity .. "/" .. as .. "/" .. air_supremacy
    table.insert(self._items, {
        node = node,
        time = time,
		boss = boss,
		final = final,
		formation = formation,
		fleet = fleet,
		as = air_string,
	})
end

function NodeInfo:create_items()
    local mode = 1
    local node, time, boss, final, formation, fleet, as_rating = nil, nil, false, false, nil, "", 0
	for index, item_key in ipairs(self._args) do
		if item_key == "-" or mw.ustring.find(item_key, "#") then
		    if mode == 3 then
		        self:insert_item(node, time, boss, final, formation, fleet, as_rating, item_key)
		    end
			table.insert(self._items, "break")
			
			node, time, boss, final, formation, fleet, as_rating = nil, nil, false, false, nil, "", 0
			mode = 1
			
			if mw.ustring.find(item_key, "#") then
			    item_key = mw.ustring.sub(item_key, 2)
			    
			    --If it has no /, then it's an empty node; otherwise, it has a resource and number
			    if not mw.ustring.find(item_key, '/') then
			        table.insert(self._items, item_key .. "/empty")
			    else
			        table.insert(self._items, item_key)
			    end
			    table.insert(self._items, "break")
			end
		else
			--Each item will be just a string, so we need to check for one of the _columns, which will be done by mode
			if mode == 1 then
			    --First item should always be the node
			    --Node format: !node/day|night where the second part is day -or- night; ! indicates a boss node
			    if mw.ustring.sub(item_key, 1, 1) == "!" then
			        boss = true
			        item_key = mw.ustring.sub(item_key, 2)
			    end
			    
			    --If there's a *, then it's a final form.
			    if mw.ustring.sub(item_key, 1, 1) == "*" then
			        final = true
			        item_key = mw.ustring.sub(item_key, 2)
			    end
			    
			    node, time = self:process_node(item_key)
			    mode = 2
		    elseif mode == 2 then
		        formation = item_key
		        mode = 3
		    else
		        --Fleets are of variable size, so we append onto a string until we hit the next node declaration
		        local split = mw.ustring.find(item_key, '/')
		        local ship_name, ship_suffix
		        if split then
		            ship_name = mw.ustring.sub(item_key, 1, split - 1)
		            ship_suffix = mw.ustring.sub(item_key, split + 1)
		        else
		            ship_name = item_key
		            ship_suffix = ""
		        end
		        local ship = EnemyShip(ship_name, ship_suffix)
		        
		        if fleet ~= "" then
		            fleet = fleet .. " " -- Actually matters
		        end
		        fleet = fleet .. Formatting:format_image{ship:battle_card(), caption = ship:name(), link = ship:base_name()}
		        
		        if ship:as_rating() then
		            as_rating = as_rating + ship:as_rating()
		        end
            end
		end
    end
    if mode == 3 then
        self:insert_item(node, time, boss, final, formation, fleet, as_rating, item_key)
    end
end

function NodeInfo:create_data_rows()
    for index, item in ipairs(self._items) do
		local row_values
		if type(item) == "string" then
			row_values = item
		else
			row_values = {}
			for _, column in ipairs(self._columns) do
				row_values[column] = self[column](self, item)
			end
			if index > 1 then
			    for _, column in ipairs(self._columns) do
			    	for i = index - 1, 1, -1 do
			    	    if column == "node" then
						    local previous_cell = self._data_rows[i][column]
    						if previous_cell then
	    					    if row_values[column].values.node == previous_cell.values.node and row_values[column].values.time == previous_cell.values.time then
		    				    	previous_cell.rowspan = previous_cell.rowspan + 1
			    			    	row_values[column] = nil
				    		    else
					    	    	row_values[column].rowspan = 1
    					    		row_values[column].colspan = 1
    	    					end
	    	    				break
	    	    			end
		    			end
		            end
		        end
		    else
				for _, column in ipairs(self._columns) do
			    	row_values[column].rowspan = 1
			    	row_values[column].colspan = 1
				end
			end
		end
		table.insert(self._data_rows, row_values)
	end
end

function NodeInfo:process_resource_node(resource, amount)
    --Amount may or may not be just numbers
    local action, units, node_type, bg_color = "Gained", "", "Resource", self._resource_node_bg_color
    
    if mw.ustring.sub(amount, 1, 1) == "-" then
        action = "Lost"
        amount = mw.ustring.sub(amount, 2)
        node_type = "Storm"
        bg_color = self._maelstrom_node_bg_color
    end
    
    if mw.ustring.find(amount, " ") then
        local split = mw.ustring.find(amount, " ")
        units = mw.ustring.sub(amount, split + 1)
        amount = mw.ustring.sub(amount, 1, split - 1)
    end
    
    local text = action .. " " .. amount .. " " .. resource .. " " .. units
    return text, node_type, bg_color
end

function NodeInfo:build_rows()
    local bg_color
	for index, row_values in ipairs(self._data_rows) do
		if row_values ~= "break" then
			table.insert(self._rows, self._row_starter)
			if row_values == "header" then
				table.insert(self._rows, self._header)
			elseif type(row_values) == "table" then
			    if row_values["node"] then
			        bg_color = row_values["node"].bg_color
			    elseif bg_color == nil then
			        bg_color = "initial"
			    end
				for _, column in ipairs(self._columns) do
			        if row_values[column] then
				        row_values[column].bg_color = bg_color
				    end
					if row_values[column] then
						table.insert(self._rows, format(self._column_cell_templates[column] or self._cell, row_values[column]))
					end
			    end
	    	elseif mw.ustring.find(row_values, '/') then
		        local split = mw.ustring.find(row_values, '/')
    	        local node = mw.ustring.sub(row_values, 1, split - 1)
	            local resource = mw.ustring.sub(row_values, split + 1)
	            if resource == "empty" then
	                table.insert(self._rows, format{self._empty_node_template, values = { node = node } })
    	        else
	                split = mw.ustring.find(resource, '/')
	                local amount = mw.ustring.sub(resource, split + 1)
	                resource = Formatting:format_image{mw.ustring.sub(resource, 1, split - 1) .. ".png", caption = mw.ustring.sub(resource, 1, split - 1), size = "22x22px"}
	                local text, node_type, bg_color = self:process_resource_node(resource, amount)
    	            table.insert(self._rows, format{self._resource_node_template, values = {
    	                node = node,
    	                text = text,
    	                node_type = node_type,
    	                bg_color = bg_color,
    	            }})
	            end
		    end
		end
	end
end

return NodeInfo