Module:BreedingCalculator
Jump to navigation
Jump to search
Documentation for this module may be created at Module:BreedingCalculator/doc
local p = {}
local cargo = mw.ext.cargo
-- TODO: Pull this data from Cargo somehow
local ExclusiveChildren = {
["Relaxaurus Lux"]="Relaxaurus+Sparkit",
["Incineram Noct"]="Incineram+Maraith",
["Mau Cryst"]="Mau+Pengullet",
["Vanwyrm Cryst"]="Vanwyrm+Foxcicle",
["Eikthyrdeer Terra"]="Eikthyrdeer+Hangyu",
["Elphidran Aqua"]="Elphidran+Surfent",
["Pyrin Noct"]="Pyrin+Katress",
["Mammorest Cryst"]="Mammorest+Wumpo",
["Mossanda Lux"]="Mossanda+Grizzbolt",
["Dinossom Lux"]="Dinossom+Rayhound",
["Jolthog Cryst"]="Jolthog+Pengullet",
["Frostallion Noct"]="Frostallion+Helzephyr",
["Ice Kingpaca"]="Kingpaca+Reindrix",
["Lyleen Noct"]="Lyleen+Menasting",
["Leezpunk Ignis"]="Leezpunk+Flambelle",
["Blazehowl Noct"]="Blazehowl+Felbat",
["Robinquill Terra"]="Robinquill+Fuddler",
["Broncherry Aqua"]="Broncherry+Fuack",
["Surfent Terra"]="Surfent+Dumud",
["Gobfin Ignis"]="Gobfin+Rooby",
["Suzaku Aqua"]="Suzaku+Jormuntide",
["Ice Reptyro"]="Reptyro+Foxcicle",
["Hangyu Cryst"]="Hangyu+Swee",
["Lyleen"]="Mossanda+Petallia",
["Faleris"]="Vanwyrm+Anubis",
["Grizzbolt"]="Mossanda+Rayhound",
["Orserk"]="Grizzbolt+Relaxaurus",
["Shadowbeak"]="Kitsun+Astegon",
}
-- TODO: Pull this data from Cargo somehow
local ExclusiveParents = {
["Relaxaurus+Sparkit"]="Relaxaurus Lux",
["Sparkit+Relaxaurus"]="Relaxaurus Lux",
["Incineram+Maraith"]="Incineram Noct",
["Maraith+Incineram"]="Incineram Noct",
["Mau+Pengullet"]="Mau Cryst",
["Pengullet+Mau"]="Mau Cryst",
["Vanwyrm+Foxcicle"]="Vanwyrm Cryst",
["Foxcicle+Vanwyrm"]="Vanwyrm Cryst",
["Eikthyrdeer+Hangyu"]="Eikthyrdeer Terra",
["Hangyu+Eikthyrdeer"]="Eikthyrdeer Terra",
["Elphidran+Surfent"]="Elphidran Aqua",
["Surfent+Elphidran"]="Elphidran Aqua",
["Pyrin+Katress"]="Pyrin Noct",
["Katress+Pyrin"]="Pyrin Noct",
["Mammorest+Wumpo"]="Mammorest Cryst",
["Wumpo+Mammorest"]="Mammorest Cryst",
["Mossanda+Grizzbolt"]="Mossanda Lux",
["Grizzbolt+Mossanda"]="Mossanda Lux",
["Dinossom+Rayhound"]="Dinossom Lux",
["Rayhound+Dinossom"]="Dinossom Lux",
["Jolthog+Pengullet"]="Jolthog Cryst",
["Pengullet+Jolthog"]="Jolthog Cryst",
["Frostallion+Helzephyr"]="Frostallion Noct",
["Helzephyr+Frostallion"]="Frostallion Noct",
["Kingpaca+Reindrix"]="Ice Kingpaca",
["Reindrix+Kingpaca"]="Ice Kingpaca",
["Lyleen+Menasting"]="Lyleen Noct",
["Menasting+Lyleen"]="Lyleen Noct",
["Leezpunk+Flambelle"]="Leezpunk Ignis",
["Flambelle+Leezpunk"]="Leezpunk Ignis",
["Blazehowl+Felbat"]="Blazehowl Noct",
["Felbat+Blazehowl"]="Blazehowl Noct",
["Robinquill+Fuddler"]="Robinquill Terra",
["Fuddler+Robinquill"]="Robinquill Terra",
["Broncherry+Fuack"]="Broncherry Aqua",
["Fuack+Broncherry"]="Broncherry Aqua",
["Surfent+Dumud"]="Surfent Terra",
["Dumud+Surfent"]="Surfent Terra",
["Gobfin+Rooby"]="Gobfin Ignis",
["Rooby+Gobfin"]="Gobfin Ignis",
["Suzaku+Jormuntide"]="Suzaku Aqua",
["Jormuntide+Suzaku"]="Suzaku Aqua",
["Reptyro+Foxcicle"]="Ice Reptyro",
["Foxcicle+Reptyro"]="Ice Reptyro",
["Hangyu+Swee"]="Hangyu Cryst",
["Swee+Hangyu"]="Hangyu Cryst",
["Mossanda+Petallia"]="Lyleen",
["Petallia+Mossanda"]="Lyleen",
["Vanwyrm+Anubis"]="Faleris",
["Anubis+Vanwyrm"]="Faleris",
["Mossanda+Rayhound"]="Grizzbolt",
["Rayhound+Mossanda"]="Grizzbolt",
["Grizzbolt+Relaxaurus"]="Orserk",
["Relaxaurus+Grizzbolt"]="Orserk",
["Kitsun+Astegon"]="Shadowbeak",
["Astegon+Kitsun"]="Shadowbeak",
}
function Round(value)
return math.floor(value + 0.5)
end
function Split(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
function CalculateBreedingRank (palBreedingRanks, parent1, parent2)
local parent1Rank = palBreedingRanks[parent1]
local parent2Rank = palBreedingRanks[parent2]
if (parent1Rank == nil) or (parent2Rank == nil) then
return 0
end
if parent1Rank == parent2Rank then
return parent1Rank
end
-- Get the average of the two parents, rounded up.
local childRankRaw = math.floor((parent1Rank + parent2Rank) / 2)
return childRankRaw
end
function ScanBreedingRank (breedingRankPals, childRank)
local childName = breedingRankPals[childRank]
if childName == nil then
childRank = Round((childRank * 5 / 5))
childName = breedingRankPals[childRank]
if childName == nil then
childName = 'Unknown'
end
end
return childRank, childName
end
function BruteForceParents (palBreedingRanks, breedingRankPals, target)
local parents = {}
for parent1, rank in pairs(palBreedingRanks) do
for parent2, rank2 in pairs(palBreedingRanks) do
local child = GetChild(palBreedingRanks, breedingRankPals, parent1, parent2)
mw.log('BruteForceParents(' .. target .. ', ' .. parent1 .. ', ' .. parent2 .. ') = ' .. child)
if child == target then
table.insert(parents, {parent1, parent2})
end
end
end
return parents
end
function GetParents ( palBreedingRanks, breedingRankPals, child )
if ExclusiveChildren[child] ~= nil then
local parents = Split(ExclusiveChildren[child], '+')
mw.log('GetParents(' .. child .. ') = EXCLUSIVE(' .. parents[0] .. ', ' .. parents[1] .. ')')
return {
{parents[0], parents[1]},
{child, child}
}
end
mw.log('GetParents(' .. child .. ')')
local output = ''
local parents = BruteForceParents(palBreedingRanks, breedingRankPals, child)
for key, ppair in pairs(parents) do
output = output .. '\n\n' .. ppair[0] .. ' + ' .. ppair[1]
end
return output
end
function GetChild ( palBreedingRanks, breedingRankPals, parent1, parent2 )
if parent1 == parent2 then
return parent1
end
if ExclusiveParents[parent1..'+'..parent2] ~= nil then
return ExclusiveParents[parent1..'+'..parent2]
end
local childRankRaw = CalculateBreedingRank(palBreedingRanks, parent1, parent2)
local childRank, childName = ScanBreedingRank(breedingRankPals, childRankRaw)
--mw.log('GetChild(' .. parent1 .. ', ' .. parent2 .. ') = ' .. childName .. ' (' .. childRank .. ')')
local output = '' .. ('GetChild(' .. parent1 .. ', ' .. parent2 .. ') = ' .. childName .. ' (' .. childRank .. ')')
return output .. '\n\n' .. childName
end
function p.BuildTables ()
local output = ''
local tables = 'Pals'
local fields = 'Pal, Number, BreedingRank'
-- optional parameters are grouped in one table
-- you can omit any or all of them, except join if you use more than one table
local args = {
where = 'Pals.Number > 0 AND Pals.Pal IS NOT NULL AND Pals.BreedingRank > 0 AND Pals.BreedingRank <= 1500',
-- Sorting by Paldeck number is IMPORTANT for later!
orderBy = 'Pals.Number',
offset = 0,
}
local results = cargo.query( tables, fields, args )
-- Check if there were zero results.
if #results == 0 then
mw.log(output)
return 'No results found'
end
-- Loop through the results, building a BreedingRank -> Pal table and a Pal -> BreedingRank table
local breedingRankPals = {}
local palBreedingRanks = {}
local paldeck = {}
local maxBreedingRank = 0
for r = 1, #results do
local result = results[r]
local name = result.Pal or 'Unknown'
if ExclusiveChildren[name] == nil then
-- Only add a Breeding Rank if it is not an exclusive child.
local breedingRank = result.BreedingRank or '0'
local currentBreedingRank = math.floor(tonumber(breedingRank) or 0)
if currentBreedingRank > maxBreedingRank then
maxBreedingRank = currentBreedingRank
end
palBreedingRanks[name] = breedingRank
local paldeckNumber = result.Number:gsub('B', '')
paldeck[name] = tonumber(paldeckNumber)
if breedingRankPals[currentBreedingRank] == nil then
-- If two Pals have the same rank, use the first result (the one with the lowest Paldeck number).
breedingRankPals[currentBreedingRank] = name
end
end
end
local prevBreedingRank = 1
for r = 1, maxBreedingRank do
local needsValue = not breedingRankPals[r]
if needsValue then
-- Calculate which Pal would be used.
local prevPal = breedingRankPals[prevBreedingRank]
if prevPal == nil or prevPal == 'Unknown' then
mw.log('Unknown BreedingRank (' .. r .. ')')
breedingRankPals[r] = 'Unknown'
else
local nextBreedingRank = r + 1
local nextPal = breedingRankPals[nextBreedingRank]
while nextPal == nil do
nextBreedingRank = nextBreedingRank + 1
nextPal = breedingRankPals[nextBreedingRank]
end
local prevDiff = r - prevBreedingRank
local nextDiff = nextBreedingRank - r
-- Use whichever Pal is closer
if prevDiff < nextDiff then
breedingRankPals[r] = prevPal
elseif prevDiff > nextDiff then
breedingRankPals[r] = nextPal
else
local prevDeck = paldeck[prevPal]
local nextDeck = paldeck[nextPal]
if prevDeck > nextDeck then
breedingRankPals[r] = prevPal
else
breedingRankPals[r] = nextPal
end
end
--
end
mw.log('Calculated BreedingRank (' .. r .. ') = ' .. breedingRankPals[r])
else
mw.log('Got BreedingRank (' .. r .. ') = ' .. breedingRankPals[r])
prevBreedingRank = r
end
end
return output, breedingRankPals, palBreedingRanks
end
function p.Main( frame )
local function_args = frame.args
local operation = function_args.operation
if not operation then
return 'No operation specified'
end
local output, breedingRankPals, palBreedingRanks = p.BuildTables()
-- Call a different function based on the operation
if operation == 'GetParents' then
local child = function_args.child
output = output .. GetParents(palBreedingRanks, breedingRankPals, child)
elseif operation == 'GetChild' then
local parent1 = function_args.parent1
local parent2 = function_args.parent2
output = output .. GetChild(palBreedingRanks, breedingRankPals, parent1, parent2)
else
output = output .. 'Invalid operation'
end
return output
end
return p