Module:BATTD costs: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
mNo edit summary |
||
| (4 intermediate revisions by the same user not shown) | |||
| Line 3: | Line 3: | ||
-- helper functions | -- helper functions | ||
local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, | 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 31: | Line 31: | ||
end | end | ||
local function | local function RecursiveGetTotalCosts(currentCost, purchasedUpgrades, myUpgradeId) | ||
-- skip this upgrade if we don't have all the prereqs | |||
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do | for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do | ||
if not | if not purchasedUpgrades[prereqId] then return false end | ||
end | end | ||
-- skip this upgrade if it's locked by an already purchased upgrade | -- skip this upgrade if it's locked by an already purchased upgrade | ||
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do | for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do | ||
if upgradeLocksById[purchasedUpgradeId][ | if upgradeLocksById[purchasedUpgradeId][myUpgradeId] then return false end | ||
end | end | ||
--upgradeLocksById[startingUpgrade][myUpgradeId] = true | |||
-- shallow copy purchasedUpgrades but with this upgrade included in it now | -- shallow copy purchasedUpgrades but with this upgrade included in it now | ||
local purchasedUpgradesNext = { [ | local purchasedUpgradesNext = { [myUpgradeId] = true } | ||
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do | for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do | ||
purchasedUpgradesNext[purchasedUpgradeId] = true | purchasedUpgradesNext[purchasedUpgradeId] = true | ||
end | end | ||
-- | -- add row to output | ||
row = {sFormat("|-\n|$%s||$%s", FormatNum(currentCost), FormatNum(currentCost*0.7))} | |||
for accessibleUpgradeId, _ in pairs(accessibleUpgrades) do | for accessibleUpgradeId, _ in pairs(accessibleUpgrades) do | ||
row[#row+1] = sFormat("||%s", purchasedUpgradesNext[accessibleUpgradeId] and Y or N) | |||
end | end | ||
outputTable[#outputTable+1] = tConcat(row, "") | |||
for | -- depth first | ||
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do | |||
RecursiveGetTotalCosts(currentCost + upgradesById[prereqOfId].cost, purchasedUpgradesNext, prereqOfId) | |||
end | end | ||
-- breadth next | |||
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do | |||
for | 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, | RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, startingUpgrade) | ||
outputTable[#outputTable+1] = " | outputTable[#outputTable+1] = "|}" | ||
return tConcat(outputTable, "") | return tConcat(outputTable, "\n") | ||
end | end | ||
| Line 111: | Line 86: | ||
local query = mw.ext.cargo.query | local query = mw.ext.cargo.query | ||
local upgradesById = {} | local upgradesById = { root = {} } -- key:value table - upgrade:upgrade data | ||
local upgradeLocksById = {} | local upgradeLocksById = { root = {} } -- key:values table - upgrades:upgrades that this upgrade locks | ||
local upgradePrereqsById = {} -- key:values table - upgrade:prerequisites to purchase this upgrade | local upgradePrereqsById = { root = {} } -- key:values table - upgrade:prerequisites to purchase this upgrade | ||
local upgradePrereqsOfById = { -- key:values table - upgrades:upgrades this is a prerequisite of | local upgradePrereqsOfById = { root = {} } -- key:values table - upgrades:upgrades this is a prerequisite of | ||
} | -- tower cost + total cost of this upgrade and all its prereqs | ||
local baseCost = tonumber(query("battd_characters", "cost", { | |||
where=sFormat("name='%s'", towerName) | |||
})[1].cost) | |||
-- cargo queries for data | -- cargo queries for data | ||
| Line 168: | Line 146: | ||
end | end | ||
end | end | ||
return upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, baseCost | return upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, baseCost | ||
| Line 181: | Line 154: | ||
local purchasedUpgrades = {} -- this upgrade and any other upgrades that had to already be purchased to get it | 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 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) | ||
baseCost = baseCost + upgradesById[myUpgradeId].cost | if not purchasedUpgrades[myUpgradeId] then baseCost = baseCost + upgradesById[myUpgradeId].cost end | ||
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do | for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do | ||
if prereqId ~= "root" then GetPurchasedUpgrades( | if prereqId ~= "root" then GetPurchasedUpgrades(prereqId) end | ||
purchasedUpgrades[prereqId] = true | |||
end | end | ||
end | end | ||
GetPurchasedUpgrades(upgradeId) | |||
-- 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 205: | Line 179: | ||
-- find upgrades that are reachable from the current upgrades owned | -- find upgrades that are reachable from the current upgrades owned | ||
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 | ||
end | end | ||
if not purchasedUpgrades[myUpgradeId] then accessibleUpgrades[myUpgradeId] = true end | if not purchasedUpgrades[myUpgradeId] then accessibleUpgrades[myUpgradeId] = true end | ||
| Line 230: | Line 200: | ||
end | end | ||
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, | return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, upgradeId, | ||
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N) | upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N) | ||
end | end | ||
Latest revision as of 21:59, 6 July 2026
Documentation for this module may be created at Module:BATTD costs/doc
local p = {}
-- helper functions
local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, startingUpgrade,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
local sFormat = string.format
local tConcat = table.concat
local sGsub = string.gsub
-- create the table headers
local headerRow = {"{|class=\"wikitable sortable\" style=\"text-align:center\"\n!Total cost!!Sell value"}
for upgradeId, _ in pairs(accessibleUpgrades) do
headerRow[#headerRow+1] = sFormat("!![[%s|%s]]", upgradesById[upgradeId]._pageName, upgradesById[upgradeId].name)
end
local outputTable = {tConcat(headerRow, "")}
-- english-only alternative to FormatNum that takes up less time
local function FormatNum(num)
local formatted = tostring(num)
-- skip if less than 1000
local k = (num > 999 and 1 or 0)
while k ~= 0 do
formatted, k = sGsub(formatted, "^(-?%d+)(%d%d%d)", "%1,%2")
end
return formatted
end
local function RecursiveGetTotalCosts(currentCost, purchasedUpgrades, myUpgradeId)
-- skip this upgrade if we don't have all the prereqs
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
if not purchasedUpgrades[prereqId] then return false 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
--upgradeLocksById[startingUpgrade][myUpgradeId] = true
-- shallow copy purchasedUpgrades but with this upgrade included in it now
local purchasedUpgradesNext = { [myUpgradeId] = true }
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
purchasedUpgradesNext[purchasedUpgradeId] = true
end
-- add row to output
row = {sFormat("|-\n|$%s||$%s", FormatNum(currentCost), FormatNum(currentCost*0.7))}
for accessibleUpgradeId, _ in pairs(accessibleUpgrades) do
row[#row+1] = sFormat("||%s", purchasedUpgradesNext[accessibleUpgradeId] and Y or N)
end
outputTable[#outputTable+1] = tConcat(row, "")
-- depth first
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do
RecursiveGetTotalCosts(currentCost + upgradesById[prereqOfId].cost, purchasedUpgradesNext, prereqOfId)
end
-- breadth next
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
for _, prereqOfId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do
--RecursiveGetTotalCosts(currentCost + upgradesById[prereqOfId].cost, purchasedUpgradesNext, prereqOfId)
end
end
return true
end
RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, startingUpgrade)
outputTable[#outputTable+1] = "|}"
return tConcat(outputTable, "\n")
end
local function SetUpTables(towerName)
local sFormat = string.format
local query = mw.ext.cargo.query
local upgradesById = { root = {} } -- key:value table - upgrade:upgrade data
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
-- tower cost + total cost of this upgrade and all its prereqs
local baseCost = tonumber(query("battd_characters", "cost", {
where=sFormat("name='%s'", towerName)
})[1].cost)
-- cargo queries for data
local upgrades, upgradePrereqs, upgradeLocks =
query("battd_upgrades", "_pageName, id, name, tower, cost", {
where=sFormat("tower='%s'", towerName),
orderBy="cost"
}),
query("battd_upgrades=main, battd_upgrades__previous=prev", "main.id=thisId, prev._value=prevId", {
where=sFormat("main.tower='%s' AND NOT unused", towerName),
join="main._ID=prev._RowID"
}),
query("battd_upgrades=main, battd_upgrades__locked_by_upgrades=lock", "main.id=thisId, lock._value=lockId", {
where=sFormat("main.tower='%s' AND NOT unused", towerName),
join="main._ID=lock._RowID"
})
-- build upgradesById
for i, upgrade in ipairs(upgrades) do
upgradesById[upgrade.id] = upgrade
upgradeLocksById[upgrade.id] = {}
end
-- build upgradePrereqsById, upgradePrereqsOfById
for i, upgrade in ipairs(upgradePrereqs) do
-- upgrade:next table
if upgrade.prevId then
if upgradePrereqsOfById[upgrade.prevId] then
upgradePrereqsOfById[upgrade.prevId][#upgradePrereqsOfById[upgrade.prevId]+1] = upgrade.thisId
else
upgradePrereqsOfById[upgrade.prevId] = {upgrade.thisId}
end
else
-- if this upgrade has no prereqs, give it a fake upgrade called "root" as a prereq
upgradePrereqsOfById["root"][#upgradePrereqsOfById["root"]+1] = upgrade.thisId
upgradePrereqsById[upgrade.thisId] = {"root"}
end
-- upgrade:prev table
if upgradePrereqsById[upgrade.thisId] then
upgradePrereqsById[upgrade.thisId][#upgradePrereqsById[upgrade.thisId]+1] = upgrade.prevId
else
upgradePrereqsById[upgrade.thisId] = {upgrade.prevId}
end
end
-- build upgradeLocksById
for _, upgrade in ipairs(upgradeLocks) do
if upgrade.lockId then
upgradeLocksById[upgrade.thisId][upgrade.lockId] = true
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
local function GetPurchasedUpgrades(myUpgradeId)
if not purchasedUpgrades[myUpgradeId] then baseCost = baseCost + upgradesById[myUpgradeId].cost end
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
if prereqId ~= "root" then GetPurchasedUpgrades(prereqId) end
purchasedUpgrades[prereqId] = true
end
end
GetPurchasedUpgrades(upgradeId)
-- 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
local function DetermineAccessibility(myUpgradeId)
if myUpgradeId == upgradeId then return end
-- if this upgrade is locked by an already purchased upgrade, then it is inaccessible
for _, upgradeLock in ipairs(upgradeLocksById[myUpgradeId]) do
if purchasedUpgrades[upgradeLock] then return end
end
-- find upgrades that are reachable from the current upgrades owned
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
-- 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 (accessibleUpgrades[prereqId] or purchasedUpgrades[prereqId] or prereqId == "root") or prereqId == upgradeId then return end
end
if not purchasedUpgrades[myUpgradeId] then accessibleUpgrades[myUpgradeId] = true end
-- determine accessibility of next upgrades
if upgradePrereqsOfById[myUpgradeId] then
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do
DetermineAccessibility(prereqOfId)
end
end
end
-- start with the root
for _, prereqOfId in ipairs(upgradePrereqsOfById.root) do
DetermineAccessibility(prereqOfId)
end
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, upgradeId,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
end
-- GLOBAL FUNCTIONS
p["tower"] = function(frame)
local upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, baseCost = SetUpTables(frame.args[1])
end
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], "Y", "N")
end
return p