Module:BATTD costs: Difference between revisions

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


-- LOCAL FUNCTIONS
-- helper functions


local function GetTotalCosts(baseCost, upgradesById, upgradeLocksById, upgradePrereqsOfById, Y, N)
local function GetTotalCosts(baseCost, initialPurchasedUpgrades, accessibleUpgrades, startingUpgrade,
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
local sFormat = string.format
local sFormat = string.format
local tConcat = table.concat
local tConcat = table.concat
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"}
for id, upgrade in ipairs(upgradesById) do
for upgradeId, _ in pairs(accessibleUpgrades) do
headerRow[#headerRow+1] = sFormat("!![[%s|%s]]", upgrade._pageName, upgrade.name)
headerRow[#headerRow+1] = sFormat("!![[%s|%s]]", upgradesById[upgradeId]._pageName, upgradesById[upgradeId].name)
end
end
Line 29: Line 31:
end
end
local function RecursiveGetTotalCosts(currentCost, purchasedUpgrades, availableUpgrades)
local function RecursiveGetTotalCosts(currentCost, purchasedUpgrades, myUpgradeId)
row = {sFormat("\n|-\n|$%s||$%s", FormatNum(currentCost), FormatNum(currentCost*0.7))}
-- 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
for id, upgrade in pairs(upgradesById) do
-- add row to output
row[#row+1] = sFormat("||%s", purchasedUpgrades[id] and Y or N)
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
end
outputTable[#outputTable+1] = tConcat(row, "")
outputTable[#outputTable+1] = tConcat(row, "")
for availableUpgradeId, availableUpgrade in pairs(availableUpgrades) do
-- depth first
-- shallow copy purchasedUpgrades
for _, prereqOfId in ipairs(upgradePrereqsOfById[myUpgradeId]) do
local purchasedUpgradesNext = { availableUpgrade }
RecursiveGetTotalCosts(currentCost + upgradesById[prereqOfId].cost, purchasedUpgradesNext, prereqOfId)
local availableUpgradesNext = {}
end
local doNext = true
-- breadth next
for purchasedUpgradeId, purchasedUpgrade in pairs(purchasedUpgrades) do
for purchasedUpgradeId, _ in pairs(purchasedUpgrades) do
if upgradeLocksById[purchasedUpgradeId] and upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
for _, prereqOfId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do
doNext = false
--RecursiveGetTotalCosts(currentCost + upgradesById[prereqOfId].cost, purchasedUpgradesNext, prereqOfId)
break
end
purchasedUpgradesNext[i+2] = purchasedUpgrade
for _, nextUpgrade in pairs(upgradePrereqsOfById[purchasedUpgrade.id]) do
if not upgradeLocksById[purchasedUpgradeId] and upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
availableUpgradesNext[#availableUpgradesNext+1] = nextUpgrade
end
end
end
if doNext then
RecursiveGetTotalCosts(currentCost + availableUpgrade.cost, purchasedUpgradesNext, availableUpgradesNext)
end
end
end
end
return true
end
end
outputTable[#outputTable+1] = "\n|}"
RecursiveGetTotalCosts(baseCost, initialPurchasedUpgrades, startingUpgrade)
return tConcat(outputTable, "")
outputTable[#outputTable+1] = "|}"
end
local a = [[-- add this combination's row to outputTable
return tConcat(outputTable, "\n")
row = {sFormat("\n|-\n|$%s||$%s", lang:formatNum(currentCost), lang:formatNum(currentCost*0.7))}
for i, upgrade in ipairs(upgrades) do
if not alreadyPurchasedUpgrades[upgrade.id] and not upgradeLocksById[upgradeId][upgrade.id] then
row[#row+1] = sFormat("||%s", purchasedUpgrades[upgrade.id] and Y or N)
end
end
end
outputTable[#outputTable+1] = tConcat(row, "\n")
for thisUpgradeId, _ in pairs(purchasedUpgrades) do
-- skip if this upgrade is a leaf
if upgradePrereqsOfById[thisUpgradeId] then
for _, nextUpgradeId in pairs(upgradePrereqsOfById[thisUpgradeId]) do
if not purchasedUpgrades[nextUpgradeId] then
-- shallow copy purchasedUpgrades and check if nextUpgradeId is locked by another upgrade
local purchasedUpgradesNext = {}
local doNext = true
for purchasedUpgrade, _ in pairs(purchasedUpgrades) do
-- if nextUpgradeId is locked by a purchasedUpgrade then don't proceed
if upgradeLocksById[purchasedUpgrade] and upgradeLocksById[purchasedUpgrade][nextUpgradeId] then
doNext = false
break
end
purchasedUpgradesNext[purchasedUpgrade] = true
end
if doNext then
purchasedUpgradesNext[nextUpgradeId] = true
recursiveGetTotalCosts(currentCost + upgradesById[nextUpgradeId].cost, purchasedUpgradesNext)
-- lock this combination so it isn't repeated on the graph again
if not upgradeLocksById[thisUpgradeId] then upgradeLocksById[thisUpgradeId] = {} end
upgradeLocksById[thisUpgradeId][nextUpgradeId] = true
if not upgradeLocksById[nextUpgradeId] then upgradeLocksById[nextUpgradeId] = {} end
upgradeLocksById[nextUpgradeId][thisUpgradeId] = true
end
end
end
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 lang = mw.language.new("en")
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)
local notPurchasedUpgrades = {} -- this upgrade and all upgrades the player has to have already purchased to get it
-- cargo queries for data
-- cargo queries for data
Line 133: Line 103:
}),
}),
query("battd_upgrades=main, battd_upgrades__previous=prev", "main.id=thisId, prev._value=prevId", {
query("battd_upgrades=main, battd_upgrades__previous=prev", "main.id=thisId, prev._value=prevId", {
where=sFormat("main.tower='%s'", towerName),
where=sFormat("main.tower='%s' AND NOT unused", towerName),
join="main._ID=prev._RowID"
join="main._ID=prev._RowID"
}),
}),
query("battd_upgrades=main, battd_upgrades__locked_by_upgrades=lock", "main.id=thisId, lock._value=lockId", {
query("battd_upgrades=main, battd_upgrades__locked_by_upgrades=lock", "main.id=thisId, lock._value=lockId", {
where=sFormat("main.tower='%s'", towerName),
where=sFormat("main.tower='%s' AND NOT unused", towerName),
join="main._ID=lock._RowID"
join="main._ID=lock._RowID"
})
})
Line 144: Line 114:
for i, upgrade in ipairs(upgrades) do
for i, upgrade in ipairs(upgrades) do
upgradesById[upgrade.id] = upgrade
upgradesById[upgrade.id] = upgrade
notPurchasedUpgrades[upgrade.id] = upgrade
upgradeLocksById[upgrade.id] = {}
if upgrade.name == upgradeName then upgradeId = upgrade.id end
end
end


Line 158: Line 127:
end
end
else
else
-- if this upgrade is a root upgrade and is not already purchased
-- 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"}
end
end
Line 169: Line 139:
end
end
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 alreadyPurchasedUpgrades
-- build purchasedUpgrades recursively
local function getAlreadyPurchasedUpgrades(myUpgradeId)
local function GetPurchasedUpgrades(myUpgradeId)
local cost = upgradesById[myUpgradeId].cost
if not purchasedUpgrades[myUpgradeId] then baseCost = baseCost + upgradesById[myUpgradeId].cost end
notPurchasedUpgrades[myUpgradeId] = nil
for i, id in ipairs(upgradePrereqsById[myUpgradeId]) do
for _, prereqId in ipairs(upgradePrereqsById[myUpgradeId]) do
cost = cost + getAlreadyPurchasedUpgrades(id)
if prereqId ~= "root" then GetPurchasedUpgrades(prereqId) end
purchasedUpgrades[prereqId] = true
end
end
return cost
end
end
 
-- build upgradeLocksById
GetPurchasedUpgrades(upgradeId)
for i, upgrade in ipairs(upgradeLocks) do
if upgrade.lockId then
-- generate a list of upgrades that are reachable from this upgrade, but do not have this upgrade as a prerequisite
if upgradeLocksById[upgrade.thisId] then
-- also generate a list of upgrades that are immediately reachable from this upgrade
upgradeLocksById[upgrade.thisId][upgrade.lockId] = true
local function DetermineAccessibility(myUpgradeId)
else
if myUpgradeId == upgradeId then return end
upgradeLocksById[upgrade.thisId] = {[upgrade.lockId] = true}
-- 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
end
end
-- start with the root
for _, prereqOfId in ipairs(upgradePrereqsOfById.root) do
DetermineAccessibility(prereqOfId)
end
end
-- tower cost + total cost of this upgrade and all its prereqs
return GetTotalCosts(baseCost, purchasedUpgrades, accessibleUpgrades, upgradeId,
local baseCost = getAlreadyPurchasedUpgrades(upgradeId) + query("battd_characters", "cost", {
upgradesById, upgradeLocksById, upgradePrereqsById, upgradePrereqsOfById, Y, N)
where=sFormat("name='%s'", towerName)
})[1].cost
return GetTotalCosts(baseCost, notPurchasedUpgrades, upgradeLocksById, upgradePrereqsOfById, Y, N)
end
end


-- GLOBAL FUNCTIONS
-- GLOBAL FUNCTIONS


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


function p.upgrade(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