Module:BATTD costs: Difference between revisions

mNo edit summary
mNo edit summary
 
(13 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
end
return nil, nil
end
-- skip this upgrade if it's locked by an already purchased upgrade
end
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] and upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
return nil, nil
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
availableUpgradesNext[availableUpgradeId] = nil
--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 = {}
local accessibleUpgrades = {} -- list of upgrades that we can get from this upgrade
local nextUpgrades = {}
-- cargo queries for data
-- cargo queries for data
Line 133: 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 146: 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 160: Line 141:


-- build upgradeLocksById
-- build upgradeLocksById
for i, 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)
-- build purchasedUpgrades
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
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
-- also generate a list of upgrades that are immediately reachable from this upgrade
-- also generate a list of upgrades that are immediately reachable from this upgrade
local function GetAccessibleUpgrades(myUpgradeId)
local function DetermineAccessibility(myUpgradeId)
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do
if myUpgradeId == upgradeId then return end
if prereqOfId ~= upgradeId then
local doNext = true
-- 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
for _, upgradeLock in ipairs(upgradeLocksById[myUpgradeId]) do
if upgradeLocksById[prereqOfId] then
if purchasedUpgrades[upgradeLock] then return end
for _, upgradeLock in ipairs(upgradeLocksById[prereqOfId]) do
end
if purchasedUpgrades[upgradeLock] then
doNext = false
-- find upgrades that are reachable from the current upgrades owned
break
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
end
-- upgrades with multiple prereqs are only accessible if we can reach all its prereqs
end
-- if it is accessible, it'll be reached again on another recursion
end
if not (accessibleUpgrades[prereqId] or purchasedUpgrades[prereqId] or prereqId == "root") or prereqId == upgradeId then return end
end
-- 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 not purchasedUpgrades[myUpgradeId] then accessibleUpgrades[myUpgradeId] = true end
for _, prereqId in ipairs(upgradePrereqsById[prereqOfId]) do
if not (accessibleUpgrades[prereqId] or purchasedUpgrades[prereqId] or prereqId == "root") or prereqId == upgradeId then
-- determine accessibility of next upgrades
doNext = false
if upgradePrereqsOfById[myUpgradeId] then  
break
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do
end
DetermineAccessibility(prereqOfId)
if (prereqId == "root" or purchasedUpgrades[prereqId]) and not purchasedUpgrades[prereqOfId] then nextUpgrades[prereqOfId] = true end
end
if doNext then
if not purchasedUpgrades[prereqOfId] then accessibleUpgrades[prereqOfId] = true end
-- do not check leaves
if upgradePrereqsOfById[prereqOfId] then GetAccessibleUpgrades(prereqOfId) end
end
end
end
end
end
end
-- start with the root
for _, prereqOfId in ipairs(upgradePrereqsOfById.root) do
DetermineAccessibility(prereqOfId)
end
end
GetAccessibleUpgrades("root")
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, upgradeId,
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, nextUpgrades,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
end
end
Line 231: 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