Module:BATTD costs: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
mNo edit summary |
||
| Line 3: | Line 3: | ||
-- LOCAL FUNCTIONS | -- LOCAL FUNCTIONS | ||
local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N) | local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, nextUpgrades, | ||
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N) | |||
local sFormat = string.format | local sFormat = string.format | ||
local tConcat = table.concat | local tConcat = table.concat | ||
| Line 52: | Line 53: | ||
if upgradePrereqsOfById[purchasedUpgradeId] then | if upgradePrereqsOfById[purchasedUpgradeId] then | ||
for _, nextUpgradeId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do | for _, nextUpgradeId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do | ||
if not purchasedUpgrades[nextUpgradeId] then availableUpgradesNext[nextUpgradeId] = true end | if accessibleUpgrades[nextUpgradeId] and not purchasedUpgrades[nextUpgradeId] then availableUpgradesNext[nextUpgradeId] = true end | ||
end | end | ||
end | end | ||
| Line 88: | Line 89: | ||
end | end | ||
RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, nextUpgrades) | |||
RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, | |||
outputTable[#outputTable+1] = "\n|}" | outputTable[#outputTable+1] = "\n|}" | ||
| Line 115: | Line 111: | ||
local purchasedUpgrades = {} | local purchasedUpgrades = {} | ||
local accessibleUpgrades = {} -- list of upgrades that we can get from this upgrade | local accessibleUpgrades = {} -- list of upgrades that we can get from this upgrade | ||
local nextUpgrades = {} | |||
-- cargo queries for data | -- cargo queries for data | ||
| Line 187: | Line 184: | ||
})[1].cost | })[1].cost | ||
-- 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 GetAccessibleUpgrades(myUpgradeId) | local function GetAccessibleUpgrades(myUpgradeId) | ||
for _, | for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do | ||
if | if prereqOfId ~= upgradeId then | ||
-- | local doNext = true | ||
if upgradeLocksById[ | -- if this upgrade is locked by an already purchased upgrade, then it is inaccessible | ||
for _, upgradeLock in ipairs(upgradeLocksById[ | if upgradeLocksById[prereqOfId] then | ||
if purchasedUpgrades[upgradeLock] then | for _, upgradeLock in ipairs(upgradeLocksById[prereqOfId]) do | ||
if purchasedUpgrades[upgradeLock] then | |||
doNext = false | |||
break | |||
end | |||
end | end | ||
end | end | ||
-- upgrades with multiple prereqs are only accessible if we can reach all prereqs | -- upgrades with multiple prereqs are only accessible if we can reach all its prereqs | ||
for _, prereqId in ipairs(upgradePrereqsById[ | -- if it is accessible, it'll be reached again on another recursion | ||
if not accessibleUpgrades[prereqId] | for _, prereqId in ipairs(upgradePrereqsById[prereqOfId]) do | ||
if not (accessibleUpgrades[prereqId] or purchasedUpgrades[prereqId] or prereqId == "root") or prereqId == upgradeId then | |||
doNext = false | |||
break | |||
end | |||
if (prereqId == "root" or purchasedUpgrades[prereqId]) and not purchasedUpgrades[prereqOfId] then nextUpgrades[prereqOfId] = true end | |||
end | end | ||
accessibleUpgrades[ | 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 | ||
| Line 209: | Line 222: | ||
GetAccessibleUpgrades("root") | GetAccessibleUpgrades("root") | ||
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N) | return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, nextUpgrades, | ||
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N) | |||
end | end | ||
Revision as of 07:11, 17 June 2026
Documentation for this module may be created at Module:BATTD costs/doc
local p = {}
-- LOCAL FUNCTIONS
local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, nextUpgrades,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
local sFormat = string.format
local tConcat = table.concat
local sGsub = string.gsub
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 GetPurchasedAndAvailableUpgrades(purchasedUpgrades, availableUpgradeId)
-- skip this upgrade if we don't have all the prereqs
if upgradePrereqsById[availableUpgradeId] then
for _, prereqId in ipairs(upgradePrereqsById[availableUpgradeId]) do
if prereqId ~= "root" and not purchasedUpgrades[prereqId] then
return nil, nil
end
end
end
-- shallow copy purchasedUpgrades and availableUpgrades
local purchasedUpgradesNext = {}
local availableUpgradesNext = {}
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
if upgradeLocksById[purchasedUpgradeId] and upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
return nil, nil
end
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
purchasedUpgradesNext[availableUpgradeId] = true
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)
mw.logObject(availableUpgrades)
for upgradeId, _ in pairs(accessibleUpgrades) do
row[#row+1] = sFormat("||%s", purchasedUpgrades[upgradeId] and Y or N)
end
outputTable[#outputTable+1] = tConcat(row, "")
if purchasedUpgrades and availableUpgrades then
for availableUpgradeId, _ in pairs(availableUpgrades) do
local purchasedUpgradesNext, availableUpgradesNext = GetPurchasedAndAvailableUpgrades(purchasedUpgrades, availableUpgradeId)
if purchasedUpgradesNext and availableUpgradesNext then
purchasedUpgradesNext[availableUpgradeId] = true
if #outputTable == 20 then return end
RecursiveGetTotalCosts(currentCost + upgradesById[availableUpgradeId].cost, purchasedUpgradesNext, availableUpgradesNext)
end
end
end
end
RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, nextUpgrades)
outputTable[#outputTable+1] = "\n|}"
return tConcat(outputTable, "")
end
local function Upgrade(towerName, upgradeName, Y, N)
local sFormat = string.format
local query = mw.ext.cargo.query
local outputTable = {}
local upgradeId = ""
local upgradesById = {} -- key:value table - upgrade:upgrade data
local upgradeLocksById = {} -- key:values table - upgrades:upgrades that this upgrade locks
local upgradePrereqsById = {} -- key:values table - upgrade:prerequisites to purchase this upgrade
local upgradePrereqsOfById = { -- key:values table - upgrades:upgrades this is a prerequisite of
root = {}
}
local purchasedUpgrades = {}
local accessibleUpgrades = {} -- list of upgrades that we can get from this upgrade
local nextUpgrades = {}
-- 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
if upgrade.name == upgradeName then upgradeId = upgrade.id end
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 is a root upgrade
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 i, upgrade in ipairs(upgradeLocks) do
if upgrade.lockId then
if upgradeLocksById[upgrade.thisId] then
upgradeLocksById[upgrade.thisId][upgrade.lockId] = true
else
upgradeLocksById[upgrade.thisId] = {[upgrade.lockId] = true}
end
end
end
-- build purchasedUpgrades
local function GetPurchasedUpgrades(myUpgradeId)
local cost = upgradesById[myUpgradeId].cost
purchasedUpgrades[myUpgradeId] = true
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
if prereqId ~= "root" then cost = cost + GetPurchasedUpgrades(prereqId) end
end
return cost
end
-- tower cost + total cost of this upgrade and all its prereqs
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
-- also generate a list of upgrades that are immediately reachable from this upgrade
local function GetAccessibleUpgrades(myUpgradeId)
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do
if prereqOfId ~= upgradeId then
local doNext = true
-- if this upgrade is locked by an already purchased upgrade, then it is inaccessible
if upgradeLocksById[prereqOfId] then
for _, upgradeLock in ipairs(upgradeLocksById[prereqOfId]) do
if purchasedUpgrades[upgradeLock] then
doNext = false
break
end
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
for _, prereqId in ipairs(upgradePrereqsById[prereqOfId]) do
if not (accessibleUpgrades[prereqId] or purchasedUpgrades[prereqId] or prereqId == "root") or prereqId == upgradeId then
doNext = false
break
end
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
GetAccessibleUpgrades("root")
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, nextUpgrades,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
end
-- GLOBAL FUNCTIONS
p["tower"] = function(frame)
return ""
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