Module:BATTD costs: Difference between revisions

From Blooncyclopedia, the independent Bloons knowledge base
Jump to navigation Jump to search
yes i know this is broken i will fix it l8r
mNo edit summary
Line 10: Line 10:
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 i, upgrade in ipairs(upgrades) do
for i, upgrade in ipairs(accessibleUpgrades) do
headerRow[i+1] = sFormat("!![[%s|%s]]", upgrade._pageName, upgrade.name)
headerRow[i+1] = sFormat("!![[%s|%s]]", upgradesById[upgrade]._pageName, upgradesById[upgrade].name)
end
end
Line 35: Line 35:
mw.logObject(availableUpgrades)
mw.logObject(availableUpgrades)
for i, upgrade in ipairs(upgrades) do
for i, upgrade in ipairs(accessibleUpgrades) do
row[i+1] = sFormat("||%s", purchasedUpgrades[upgrade.id] and Y or N)
row[i+1] = sFormat("||%s", purchasedUpgrades[upgrade.id] and Y or N)
end
end
Line 41: Line 41:
outputTable[#outputTable+1] = tConcat(row, "")
outputTable[#outputTable+1] = tConcat(row, "")
for availableUpgradeId, availableUpgrade in pairs(availableUpgrades) do
for _, availableUpgradeId in ipairs(availableUpgrades) do
-- shallow copy purchasedUpgrades and availableUpgrades
-- shallow copy purchasedUpgrades and availableUpgrades
local purchasedUpgradesNext = {}
local purchasedUpgradesNext = {}
Line 47: Line 47:
local doNext = true
local doNext = true
for purchasedUpgradeId, purchasedUpgrade in pairs(purchasedUpgrades) do
for _, purchasedUpgradeId in ipairs(purchasedUpgrades) do
if upgradeLocksById[availableUpgradeId] and upgradeLocksById[purchasedUpgradeId][purchasedUpgradeId] then
if upgradeLocksById[purchasedUpgradeId] and upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
doNext = false
doNext = false
break
break
end
end
purchasedUpgradesNext[purchasedUpgradeId] = purchasedUpgrade
purchasedUpgradesNext[#purchasedUpgradesNext+1] = upgradesById[purchasedUpgradeId]
for _, nextUpgrade in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do
for _, nextUpgradeId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do
if not upgradeLocksById[purchasedUpgradeId] and upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
if not upgradeLocksById[purchasedUpgradeId] and not upgradeLocksById[purchasedUpgradeId][nextUpgradeId] then
availableUpgradesNext[nextUpgrade.id] = nextUpgrade
availableUpgradesNext[#availableUpgradesNext+1] = nextUpgradeId
end
end
end
end
Line 63: Line 63:
if doNext then
if doNext then
purchasedUpgradesNext[availableUpgradeId] = availableUpgrade
purchasedUpgradesNext[#purchasedUpgradesNext+1] = availableUpgradeId
RecursiveGetTotalCosts(currentCost + availableUpgrade.cost, purchasedUpgradesNext, availableUpgradesNext)
RecursiveGetTotalCosts(currentCost + upgradesById[availableUpgradeId].cost, purchasedUpgradesNext, availableUpgradesNext)
end
end
end
end
Line 120: Line 120:
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 outputTable = {}
Line 174: Line 173:
else
else
upgradePrereqsById[upgrade.thisId] = {upgrade.prevId}
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
end
end
Line 187: Line 197:
return cost
return cost
end
end
-- tower cost + total cost of this upgrade and all its prereqs
local baseCost = getAlreadyPurchasedUpgrades(upgradeId) + query("battd_characters", "cost", {
where=sFormat("name='%s'", towerName)
})[1].cost
local function getAccessibleUpgrades(myUpgradeId)
local function getAccessibleUpgrades(myUpgradeId)
for _, upgrade in ipairs(upgradePrereqsOfById[myUpgradeId]) do
for _, upgrade in ipairs(upgradePrereqsOfById[myUpgradeId]) do
accessibleUpgrades[#accessibleUpgrades+1] = upgrade
if not purchasedUpgrades[upgrade] then
if upgradePrereqsOfById[upgrade] then  
if upgradeLocksById[upgrade] then
if upgradeLocksById[upgrade] then
for _, upgradeLock in ipairs(upgradeLocksById[upgrade]) do
for _, upgradeLock in ipairs(upgradeLocksById[upgrade]) do
Line 199: Line 212:
end
end
end
end
getAccessibleUpgrades(upgrade)
accessibleUpgrades[#accessibleUpgrades+1] = upgrade
if upgradePrereqsOfById[upgrade] then
getAccessibleUpgrades(upgrade)
end
end
end
end
end
end
end
getAccessibleUpgrades("root")
getAccessibleUpgrades("root")
 
--return ""
-- build upgradeLocksById
return GetTotalCosts(baseCost, accessibleUpgrades, upgradesById, upgradeLocksById, upgradePrereqsOfById, Y, N)
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
-- tower cost + total cost of this upgrade and all its prereqs
local baseCost = getAlreadyPurchasedUpgrades(upgradeId) + query("battd_characters", "cost", {
where=sFormat("name='%s'", towerName)
})[1].cost
return GetTotalCosts(baseCost, availableUpgrades, upgradesById, upgradeLocksById, upgradePrereqsOfById, Y, N)
end
end



Revision as of 00:17, 17 June 2026

Documentation for this module may be created at Module:BATTD costs/doc

local p = {}

-- LOCAL FUNCTIONS

local function GetTotalCosts(baseCost, accessibleUpgrades, upgradesById, upgradeLocksById, 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 i, upgrade in ipairs(accessibleUpgrades) do
		headerRow[i+1] = sFormat("!![[%s|%s]]", upgradesById[upgrade]._pageName, upgradesById[upgrade].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, availableUpgrades)
		row = {sFormat("\n|-\n|$%s||$%s", FormatNum(currentCost), FormatNum(currentCost*0.7))}
		
		mw.logObject(purchasedUpgrades)
		mw.logObject(availableUpgrades)
		
		for i, upgrade in ipairs(accessibleUpgrades) do
			row[i+1] = sFormat("||%s", purchasedUpgrades[upgrade.id] and Y or N)
		end
		
		outputTable[#outputTable+1] = tConcat(row, "")
		
		for _, availableUpgradeId in ipairs(availableUpgrades) do
			-- shallow copy purchasedUpgrades and availableUpgrades
			local purchasedUpgradesNext = {}
			local availableUpgradesNext = {}
			local doNext = true
			
			for _, purchasedUpgradeId in ipairs(purchasedUpgrades) do
				if upgradeLocksById[purchasedUpgradeId] and upgradeLocksById[purchasedUpgradeId][availableUpgradeId] then
					doNext = false
					break
				end
				
				purchasedUpgradesNext[#purchasedUpgradesNext+1] = upgradesById[purchasedUpgradeId]
				
				for _, nextUpgradeId in ipairs(upgradePrereqsOfById[purchasedUpgradeId]) do
					if not upgradeLocksById[purchasedUpgradeId] and not upgradeLocksById[purchasedUpgradeId][nextUpgradeId] then
						availableUpgradesNext[#availableUpgradesNext+1] = nextUpgradeId
					end
				end
			end
			
			if doNext then
				purchasedUpgradesNext[#purchasedUpgradesNext+1] = availableUpgradeId
				RecursiveGetTotalCosts(currentCost + upgradesById[availableUpgradeId].cost, purchasedUpgradesNext, availableUpgradesNext)
			end
		end
	end
	RecursiveGetTotalCosts(baseCost, {}, upgradePrereqsOfById.root)
	
	outputTable[#outputTable+1] = "\n|}"
	
	return tConcat(outputTable, "")
end
	
local a = [[-- add this combination's row to outputTable
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
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 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
	
	-- 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'", 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'", 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 and is not already purchased
			upgradePrereqsOfById["root"][#upgradePrereqsOfById["root"]+1] = upgrade.thisId
		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 alreadyPurchasedUpgrades
	local function getAlreadyPurchasedUpgrades(myUpgradeId)
		local cost = upgradesById[myUpgradeId].cost
		purchasedUpgrades[myUpgradeId] = true
		
		for i, id in ipairs(upgradePrereqsById[myUpgradeId]) do
			cost = cost + getAlreadyPurchasedUpgrades(id)
		end
		return cost
	end
	
	-- tower cost + total cost of this upgrade and all its prereqs
	local baseCost = getAlreadyPurchasedUpgrades(upgradeId) + query("battd_characters", "cost", {
		where=sFormat("name='%s'", towerName)
	})[1].cost
	
	local function getAccessibleUpgrades(myUpgradeId)
		
		for _, upgrade in ipairs(upgradePrereqsOfById[myUpgradeId]) do
			if not purchasedUpgrades[upgrade] then
				if upgradeLocksById[upgrade] then
					for _, upgradeLock in ipairs(upgradeLocksById[upgrade]) do
						if purchasedUpgrades[upgradeLock] then return end
					end
				end
				
				accessibleUpgrades[#accessibleUpgrades+1] = upgrade
				
				if upgradePrereqsOfById[upgrade] then
					getAccessibleUpgrades(upgrade)
				end
			end
		end
	end
	getAccessibleUpgrades("root")
	--return ""
	return GetTotalCosts(baseCost, accessibleUpgrades, upgradesById, upgradeLocksById, upgradePrereqsOfById, Y, N)
end

-- GLOBAL FUNCTIONS

function p.tower(frame)
	return ""
end

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