Module:BATTD costs: Difference between revisions

mNo edit summary
mNo edit summary
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
local p = {}
local p = {}


-- LOCAL FUNCTIONS
-- helper functions


local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, nextUpgrades,
local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, startingUpgrade,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
local sFormat = string.format
local sFormat = string.format
Line 9: Line 9:
local sGsub = string.gsub
local sGsub = string.gsub
-- create the table headers
local headerRow = {"{|class=\"wikitable sortable\" style=\"text-align:center\"\n!Total cost!!Sell value"}
local headerRow = {"{|class=\"wikitable sortable\" style=\"text-align:center\"\n!Total cost!!Sell value"}
Line 30: Line 31:
end
end
local function GetPurchasedAndAvailableUpgrades(purchasedUpgrades, availableUpgradeId)
local function RecursiveGetTotalCosts(currentCost, purchasedUpgrades, myUpgradeId)
-- skip this upgrade if we don't have all the prereqs
-- skip this upgrade if we don't have all the prereqs
if upgradePrereqsById[availableUpgradeId] then
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
for _, prereqId in ipairs(upgradePrereqsById[availableUpgradeId]) do
if not purchasedUpgrades[prereqId] then return false end
if prereqId ~= "root" and not purchasedUpgrades[prereqId] then return nil, nil end
end
end
-- skip this upgrade if it's locked by an already purchased upgrade
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
if upgradeLocksById[purchasedUpgradeId][myUpgradeId] then return false end
end
end
-- shallow copy purchasedUpgrades and availableUpgrades
--upgradeLocksById[startingUpgrade][myUpgradeId] = true
local purchasedUpgradesNext = {}
local availableUpgradesNext = {}
-- shallow copy purchasedUpgrades but with this upgrade included in it now
local purchasedUpgradesNext = { [myUpgradeId] = true }
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
if upgradeLocksById[purchasedUpgradeId] then
if upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
return nil, nil
else
upgradeLocksById[purchasedUpgradeId][availableUpgradeId] = true
end
else
upgradeLocksById[purchasedUpgradeId] = {[availableUpgradeId] = true}
end
-- add this upgrade to the list of purchased upgrades
purchasedUpgradesNext[purchasedUpgradeId] = true
purchasedUpgradesNext[purchasedUpgradeId] = true
if upgradePrereqsOfById[purchasedUpgradeId] then
for _, nextUpgradeId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do
if accessibleUpgrades[nextUpgradeId] and not purchasedUpgrades[nextUpgradeId] then availableUpgradesNext[nextUpgradeId] = true end
end
end
end
end
purchasedUpgradesNext[availableUpgradeId] = true
-- add row to output
row = {sFormat("|-\n|$%s||$%s", FormatNum(currentCost), FormatNum(currentCost*0.7))}
return purchasedUpgradesNext, availableUpgradesNext
end
local function RecursiveGetTotalCosts(currentCost, purchasedUpgrades, availableUpgrades)
row = {sFormat("\n|-\n|$%s||$%s", FormatNum(currentCost), FormatNum(currentCost*0.7))}
mw.logObject(purchasedUpgrades)
for accessibleUpgradeId, _ in pairs(accessibleUpgrades) do
mw.logObject(availableUpgrades)
row[#row+1] = sFormat("||%s", purchasedUpgradesNext[accessibleUpgradeId] and Y or N)
for upgradeId, _ in pairs(accessibleUpgrades) do
row[#row+1] = sFormat("||%s", purchasedUpgrades[upgradeId] and Y or N)
end
end
outputTable[#outputTable+1] = tConcat(row, "")
outputTable[#outputTable+1] = tConcat(row, "")
if purchasedUpgrades and availableUpgrades then
-- depth first
for availableUpgradeId, _ in pairs(availableUpgrades) do
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do
local purchasedUpgradesNext, availableUpgradesNext = GetPurchasedAndAvailableUpgrades(purchasedUpgrades, availableUpgradeId)
RecursiveGetTotalCosts(currentCost + upgradesById[prereqOfId].cost, purchasedUpgradesNext, prereqOfId)
end
if purchasedUpgradesNext and availableUpgradesNext then
purchasedUpgradesNext[availableUpgradeId] = true
--if #outputTable == 20 then return end
-- breadth next
RecursiveGetTotalCosts(currentCost + upgradesById[availableUpgradeId].cost, purchasedUpgradesNext, availableUpgradesNext)
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
end
for _, prereqOfId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do
--RecursiveGetTotalCosts(currentCost + upgradesById[prereqOfId].cost, purchasedUpgradesNext, prereqOfId)
end
end
end
end
return true
end
end
RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, nextUpgrades)
RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, startingUpgrade)
outputTable[#outputTable+1] = "\n|}"
outputTable[#outputTable+1] = "|}"
return tConcat(outputTable, "")
return tConcat(outputTable, "\n")
end
end


local function Upgrade(towerName, upgradeName, Y, N)
local function SetUpTables(towerName)
local sFormat = string.format
local sFormat = string.format
local query = mw.ext.cargo.query
local query = mw.ext.cargo.query
local outputTable = {}
local upgradesById = { root = {} } -- key:value table  - upgrade:upgrade data
local upgradeId = ""
local upgradeLocksById = { root = {} } -- key:values table - upgrades:upgrades that this upgrade locks
local upgradePrereqsById = { root = {} } -- key:values table - upgrade:prerequisites to purchase this upgrade
local upgradePrereqsOfById = { root = {} } -- key:values table - upgrades:upgrades this is a prerequisite of
local upgradesById = {} -- key:value table  - upgrade:upgrade data
-- tower cost + total cost of this upgrade and all its prereqs
local upgradeLocksById = {} -- key:values table - upgrades:upgrades that this upgrade locks
local baseCost = tonumber(query("battd_characters", "cost", {
local upgradePrereqsById = {} -- key:values table - upgrade:prerequisites to purchase this upgrade
where=sFormat("name='%s'", towerName)
local upgradePrereqsOfById = { -- key:values table - upgrades:upgrades this is a prerequisite of
})[1].cost)
root = {}
}
local purchasedUpgrades = {} -- this upgrade and any other upgrades that had to already be purchased to get it
local accessibleUpgrades = {} -- list of upgrades that are possible to reach from this upgrade
local nextUpgrades = {} -- list of upgrades that are currently purchasable from this upgrade
-- cargo queries for data
-- cargo queries for data
Line 136: Line 114:
for i, upgrade in ipairs(upgrades) do
for i, upgrade in ipairs(upgrades) do
upgradesById[upgrade.id] = upgrade
upgradesById[upgrade.id] = upgrade
if upgrade.name == upgradeName then upgradeId = upgrade.id end
upgradeLocksById[upgrade.id] = {}
end
end


Line 149: Line 127:
end
end
else
else
-- if this upgrade is a root upgrade
-- if this upgrade has no prereqs, give it a fake upgrade called "root" as a prereq
upgradePrereqsOfById["root"][#upgradePrereqsOfById["root"]+1] = upgrade.thisId
upgradePrereqsOfById["root"][#upgradePrereqsOfById["root"]+1] = upgrade.thisId
upgradePrereqsById[upgrade.thisId] = {"root"}
upgradePrereqsById[upgrade.thisId] = {"root"}
Line 165: Line 143:
for _, upgrade in ipairs(upgradeLocks) do
for _, upgrade in ipairs(upgradeLocks) do
if upgrade.lockId then
if upgrade.lockId then
if upgradeLocksById[upgrade.thisId] then
upgradeLocksById[upgrade.thisId][upgrade.lockId] = true
upgradeLocksById[upgrade.thisId][upgrade.lockId] = true
else
upgradeLocksById[upgrade.thisId] = {[upgrade.lockId] = true}
end
end
end
end
end
return upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, baseCost
end
local function Upgrade(towerName, upgradeId, Y, N)
local upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, baseCost = SetUpTables(towerName)
local purchasedUpgrades = {} -- this upgrade and any other upgrades that had to already be purchased to get it
local accessibleUpgrades = {} -- list of upgrades that are possible to reach from this upgrade by some route
-- build purchasedUpgrades recursively
-- build purchasedUpgrades recursively
local function GetPurchasedUpgrades(myUpgradeId)
local function GetPurchasedUpgrades(myUpgradeId)
local cost = upgradesById[myUpgradeId].cost
if not purchasedUpgrades[myUpgradeId] then baseCost = baseCost + upgradesById[myUpgradeId].cost end
purchasedUpgrades[myUpgradeId] = true
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
if prereqId ~= "root" then cost = cost + GetPurchasedUpgrades(prereqId) end
if prereqId ~= "root" then GetPurchasedUpgrades(prereqId) end
purchasedUpgrades[prereqId] = true
end
end
return cost
end
end
-- tower cost + total cost of this upgrade and all its prereqs
GetPurchasedUpgrades(upgradeId)
local baseCost = GetPurchasedUpgrades(upgradeId) + query("battd_characters", "cost", {
where=sFormat("name='%s'", towerName)
})[1].cost
-- generate a list of upgrades that are reachable from this upgrade, but do not have this upgrade as a prerequisite
-- generate a list of upgrades that are reachable from this upgrade, but do not have this upgrade as a prerequisite
Line 195: Line 174:
-- if this upgrade is locked by an already purchased upgrade, then it is inaccessible
-- if this upgrade is locked by an already purchased upgrade, then it is inaccessible
if upgradeLocksById[myUpgradeId] then
for _, upgradeLock in ipairs(upgradeLocksById[myUpgradeId]) do
for _, upgradeLock in ipairs(upgradeLocksById[myUpgradeId]) do
if purchasedUpgrades[upgradeLock] then return end
if purchasedUpgrades[upgradeLock] then return end
end
end
end
-- find upgrades that are reachable from the current upgrades owned
-- find upgrades that are reachable from the current upgrades owned
local isNextUpgrade = true
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
-- upgrades with multiple prereqs are only accessible if we can reach all its prereqs
-- upgrades with multiple prereqs are only accessible if we can reach all its prereqs
-- if it is accessible, it'll be reached again on another recursion
-- if it is accessible, it'll be reached again on another recursion
if not (accessibleUpgrades[prereqId] or purchasedUpgrades[prereqId] or prereqId == "root") or prereqId == upgradeId then return end
if not (accessibleUpgrades[prereqId] or purchasedUpgrades[prereqId] or prereqId == "root") or prereqId == upgradeId then return end
if not (purchasedUpgrades[prereqId] or prereqId == "root") or purchasedUpgrades[myUpgradeId] then isNextUpgrade = nil end
end
end
nextUpgrades[myUpgradeId] = isNextUpgrade
if not purchasedUpgrades[myUpgradeId] then accessibleUpgrades[myUpgradeId] = true end
if not purchasedUpgrades[myUpgradeId] then accessibleUpgrades[myUpgradeId] = true end
Line 227: Line 200:
end
end
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, nextUpgrades,
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, upgradeId,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
end
end
Line 234: Line 207:


p["tower"] = function(frame)
p["tower"] = function(frame)
return ""
local upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, baseCost = SetUpTables(frame.args[1])
end
end


p["upgrade"] = function(frame)
p["upgrade"] = function(frame)
--return Upgrade(frame.args[1], frame.args[2], frame:expandTemplate{title = "Y", args = {}}, frame:expandTemplate{title = "N", args = {}})
return Upgrade(frame.args[1], frame.args[2], frame:expandTemplate{title = "Y", args = {}}, frame:expandTemplate{title = "N", args = {}})
return Upgrade(frame.args[1], frame.args[2], "Y", "N")
--return Upgrade(frame.args[1], frame.args[2], "Y", "N")
end
end


return p
return p