Module:Sandbox/User:Artoire/1: Difference between revisions
mNo edit summary |
mNo edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 3: | Line 3: | ||
current_xp = 24, |
current_xp = 24, |
||
target_xp = 37, |
target_xp = 37, |
||
ingot = ' |
ingot = 'Coarse Deathstone (Etched)', |
||
profession = 'Stonemason', -- 'Bonewright'/'Stonemason'/'Blacksmith' |
|||
ore_buy = 'true', |
|||
pole_buy = 'none', -- 'none'/'logs'/'pole' |
|||
}) |
}) |
||
]] |
]] |
||
Line 10: | Line 13: | ||
require('Module:Mw.html extension') |
require('Module:Mw.html extension') |
||
local xp = require('Module:Experience') |
local xp = require('Module:Experience') |
||
local cache = require('Module:Break Isolation').get_module_store('Module:Sandbox/User:Artoire/1') |
|||
local currency = require('Module:Currency') |
local currency = require('Module:Currency') |
||
local lang = mw.language.getContentLanguage() |
local lang = mw.language.getContentLanguage() |
||
local |
local _ingots = {} |
||
local function lookup_ingots(profession) |
|||
if cache.ingots then return cache.ingots end |
|||
if _ingots[profession] then |
|||
local ingots = { |
|||
return _ingots[profession] |
|||
end |
|||
_ingots[profession] = { |
|||
recipes = {}, |
recipes = {}, |
||
order = {} |
order = {} |
||
} |
} |
||
cache.ingots = ingots |
|||
for _, result in ipairs(mw.smw.ask{ |
for _, result in ipairs(mw.smw.ask{ |
||
({ |
|||
'[[Uses facility::Goblin Smelter||Gnome Smelter]]', |
|||
Blacksmith = '[[Uses facility::Goblin Smelter||Gnome Smelter]]', |
|||
Stonemason = '[[Uses facility::T.E.A. Machine]]', |
|||
Bonewright = '[[Uses facility::B.R.E.W.S. Vat]]' |
|||
})[profession], |
|||
['?Recipe JSON'] = '', |
['?Recipe JSON'] = '', |
||
mainlabel = '-', |
mainlabel = '-', |
||
Line 30: | Line 38: | ||
result = mw.text.jsonDecode(result[1]) |
result = mw.text.jsonDecode(result[1]) |
||
local ingot = result.output[1].name |
local ingot = result.output[1].name |
||
_ingots[profession].recipes[ingot] = { |
|||
xp = result.xp, |
xp = result.xp, |
||
facility = result.facility, |
facility = result.facility, |
||
Line 37: | Line 45: | ||
level = result.level |
level = result.level |
||
} |
} |
||
table.insert( |
table.insert(_ingots[profession].order, ingot) |
||
end |
end |
||
return |
return _ingots[profession] |
||
end |
end |
||
local function lookup_weapons() |
local function lookup_weapons(profession) |
||
local ingots = lookup_ingots(profession) |
|||
if cache.weapons then return cache.weapons end |
|||
local ingots = lookup_ingots() |
|||
local weapons = {} |
local weapons = {} |
||
cache.weapons = weapons |
|||
for _, result in ipairs(mw.smw.ask{ |
for _, result in ipairs(mw.smw.ask{ |
||
({ |
|||
'[[Uses facility::Goblin Forge||Gnome Forge]]', |
|||
Blacksmith = '[[Uses facility::Goblin Forge||Gnome Forge]]', |
|||
Stonemason = '[[Category:Stonemason]][[Category:Pages with recipes]][[Uses facility::!T.E.A. Machine]]', |
|||
Bonewright = '[[Category:Bonewright]][[Category:Pages with recipes]][[Uses facility::!B.R.E.W.S. Vat]]' |
|||
})[profession], |
|||
['?Recipe JSON'] = '', |
['?Recipe JSON'] = '', |
||
mainlabel = '-', |
mainlabel = '-', |
||
Line 56: | Line 66: | ||
local lvl = result['Profession Level A'] |
local lvl = result['Profession Level A'] |
||
result = mw.text.jsonDecode(result[1]) |
result = mw.text.jsonDecode(result[1]) |
||
if not result.passive and result.profession == profession then |
|||
local ingot |
|||
local |
local ingot |
||
local pole |
|||
for _, material in ipairs(result.materials) do |
|||
for _, material in ipairs(result.materials) do |
|||
if ingots.recipes[material.name] then |
|||
assert(not ingot) |
|||
ingot |
assert(not ingot) |
||
ingot = material |
|||
else |
|||
else |
|||
assert(not pole) |
|||
pole |
assert(not pole) |
||
pole = material |
|||
end |
|||
end |
end |
||
weapons[ingot.name] = weapons[ingot.name] or {} |
|||
table.insert(weapons[ingot.name], { |
|||
facility = result.facility, |
|||
level = result.level, |
|||
ingot = ingot, |
|||
pole = pole, |
|||
name = result.output[1].name, |
|||
xp = result.xp |
|||
}) |
|||
end |
end |
||
weapons[ingot.name] = weapons[ingot.name] or {} |
|||
table.insert(weapons[ingot.name], { |
|||
facility = result.facility, |
|||
level = result.level, |
|||
ingot = ingot, |
|||
pole = pole, |
|||
name = result.output[1].name, |
|||
xp = result.xp |
|||
}) |
|||
end |
end |
||
return weapons |
return weapons |
||
Line 93: | Line 105: | ||
end |
end |
||
local _lookup_price_cache = {} |
|||
cache.lookup_price = cache.lookup_price or {} |
|||
local function lookup_price(item) |
local function lookup_price(item) |
||
_lookup_price_cache[item] = _lookup_price_cache[item] or _lookup_price_uncached(item) |
|||
return |
return _lookup_price_cache[item] |
||
end |
end |
||
Line 119: | Line 131: | ||
end |
end |
||
local _lookup_pole_cache = {} |
|||
cache.lookup_pole = cache.lookup_pole or {} |
|||
local function lookup_pole(pole) |
local function lookup_pole(pole) |
||
_lookup_pole_cache[pole] = _lookup_pole_cache[pole] or _lookup_pole_uncached(pole) |
|||
return |
return _lookup_pole_cache[pole] |
||
end |
end |
||
Line 136: | Line 148: | ||
end |
end |
||
local _lookup_ore_cache = {} |
|||
cache.lookup_ore = cache.lookup_ore or {} |
|||
local function lookup_ore(ore) |
local function lookup_ore(ore) |
||
_lookup_ore_cache[ore] = _lookup_ore_cache[ore] or _lookup_ore_uncached(ore) |
|||
return |
return _lookup_ore_cache[ore] |
||
end |
end |
||
Line 153: | Line 165: | ||
end |
end |
||
local _lookup_log_cache = {} |
|||
cache.lookup_log = cache.lookup_log or {} |
|||
local function lookup_log(log) |
local function lookup_log(log) |
||
_lookup_log_cache[log] = _lookup_log_cache[log] or _lookup_log_uncached(log) |
|||
return |
return _lookup_log_cache[log] |
||
end |
end |
||
Line 163: | Line 175: | ||
local p = {} |
local p = {} |
||
function p.ingots() |
function p.ingots(frame) |
||
return table.concat(lookup_ingots().order, ',') |
return table.concat(lookup_ingots(frame.args.profession).order, ',') |
||
end |
end |
||
Line 170: | Line 182: | ||
return p._main(frame:getParent().args) |
return p._main(frame:getParent().args) |
||
end |
end |
||
p.w = lookup_weapons |
|||
function p._main(args) |
function p._main(args) |
||
local profession = args.profession |
|||
local current_xp = tonumber(args.current_xp) or 0 |
local current_xp = tonumber(args.current_xp) or 0 |
||
local current_lvl |
local current_lvl |
||
Line 201: | Line 213: | ||
buying_poles = not (buying_logs or chopping_logs) |
buying_poles = not (buying_logs or chopping_logs) |
||
local ingot = lookup_ingots().recipes[args.ingot] |
local ingot = lookup_ingots(profession).recipes[args.ingot] |
||
local result = mw.html.create() |
local result = mw.html.create() |
||
Line 224: | Line 236: | ||
tbl |
tbl |
||
:tag('tr') |
:tag('tr') |
||
:th(skillclickpic( |
:th(skillclickpic(({ |
||
Blacksmith = 'Miner', |
|||
:th{ 'Ore', attr = { colspan = '3' } }:done() |
|||
Stonemason = 'Miner', |
|||
:th{ 'Ingot', attr = { colspan = '2' } }:done() |
|||
Bonewright = 'Gatherer' |
|||
})[profession])):done() |
|||
:th{ ({ |
|||
Blacksmith = 'Ore', |
|||
Stonemason = 'Rock', |
|||
Bonewright = 'Bone' |
|||
})[profession], attr = { colspan = '3' } }:done() |
|||
:th{ ({ |
|||
Blacksmith = 'Ingot', |
|||
Stonemason = 'Etched', |
|||
Bonewright = 'Brewed' |
|||
})[profession], attr = { colspan = '2' } }:done() |
|||
:IF(chopping_logs) |
:IF(chopping_logs) |
||
:th(skillclickpic('Woodcutter')):done() |
:th(skillclickpic('Woodcutter')):done() |
||
Line 235: | Line 259: | ||
:END() |
:END() |
||
:th{ 'Pole', attr = { colspan = '3' } }:done() |
:th{ 'Pole', attr = { colspan = '3' } }:done() |
||
:th(skillclickpic( |
:th(skillclickpic(profession)):done() |
||
:th{ 'Product', attr = { colspan = '3' } }:done() |
:th{ 'Product', attr = { colspan = '3' } }:done() |
||
:th{ 'Cost', attr = { colspan = '10' } }:done() |
:th{ 'Cost', attr = { colspan = '10' } }:done() |
||
:done() |
:done() |
||
for _, weapon in ipairs(lookup_weapons()[ingot.ingot]) do |
for _, weapon in ipairs(lookup_weapons(profession)[ingot.ingot]) do |
||
if not ingot.xp then |
if not ingot.xp then |
||
tbl |
tbl |
||
:tr() |
:tr() |
||
:td{ |
:td{ |
||
'Missing XP for |
'Missing XP for preparing [[' .. ingot.ingot .. ']]; Please [' .. tostring(mw.uri.fullUrl(ingot.ingot, 'action=edit§ion=1')) .. ' edit the page] to add the experience earned (after |exp =)', |
||
attr = { colspan = colspan } |
attr = { colspan = colspan } |
||
} |
} |
||
Line 319: | Line 343: | ||
local cost = needed_ores * lookup_price(ingot.ore)[buying_ores and 'buy' or 'sell'] |
local cost = needed_ores * lookup_price(ingot.ore)[buying_ores and 'buy' or 'sell'] |
||
local dbg = { args = args, needed_ores = needed_ores, lookup_ore = lookup_price(ingot.ore) } |
|||
if chopping_logs then |
if chopping_logs then |
||
if needed_logs then |
if needed_logs then |
||
dbg.needed_logs = needed_logs |
|||
dbg.lookup_chop_log = lookup_price(pole_info.log) |
|||
cost = cost + needed_logs * lookup_price(pole_info.log).sell |
cost = cost + needed_logs * lookup_price(pole_info.log).sell |
||
end |
end |
||
elseif buying_logs then |
elseif buying_logs then |
||
if needed_logs then |
if needed_logs then |
||
dbg.needed_logs = needed_logs |
|||
dbg.lookup_buy_log = lookup_price(pole_info.log) |
|||
cost = cost + needed_logs * lookup_price(pole_info.log).buy |
cost = cost + needed_logs * lookup_price(pole_info.log).buy |
||
end |
end |
||
else |
else |
||
if weapon.pole then |
if weapon.pole then |
||
dbg.needed_poles = needed_poles |
|||
dbg.lookup_buy_poles = lookup_price(weapon.pole.name) |
|||
cost = cost + needed_poles * lookup_price(weapon.pole.name).buy |
cost = cost + needed_poles * lookup_price(weapon.pole.name).buy |
||
end |
end |
||
end |
end |
||
row:node(currency._cell(cost, { html = 'yes' })) |
|||
if args.debug then |
|||
dbg.cost = cost |
|||
row |
|||
:td{ mw.text.jsonEncode(dbg), attr = { colspan = "10" } } |
|||
else |
|||
row:node(currency._cell(cost, { html = 'yes' })) |
|||
end |
|||
end |
end |
||
end |
end |
Latest revision as of 20:30, 21 December 2024
Documentation for this module may be created at Module:Sandbox/User:Artoire/1/doc
--[[
mw.log(p._main{
current_xp = 24,
target_xp = 37,
ingot = 'Coarse Deathstone (Etched)',
profession = 'Stonemason', -- 'Bonewright'/'Stonemason'/'Blacksmith'
ore_buy = 'true',
pole_buy = 'none', -- 'none'/'logs'/'pole'
})
]]
require('strict')
require('Module:Mw.html extension')
local xp = require('Module:Experience')
local currency = require('Module:Currency')
local lang = mw.language.getContentLanguage()
local _ingots = {}
local function lookup_ingots(profession)
if _ingots[profession] then
return _ingots[profession]
end
_ingots[profession] = {
recipes = {},
order = {}
}
for _, result in ipairs(mw.smw.ask{
({
Blacksmith = '[[Uses facility::Goblin Smelter||Gnome Smelter]]',
Stonemason = '[[Uses facility::T.E.A. Machine]]',
Bonewright = '[[Uses facility::B.R.E.W.S. Vat]]'
})[profession],
['?Recipe JSON'] = '',
mainlabel = '-',
sort = 'Profession Level A',
limit = '500'
}) do
result = mw.text.jsonDecode(result[1])
local ingot = result.output[1].name
_ingots[profession].recipes[ingot] = {
xp = result.xp,
facility = result.facility,
ingot = result.output[1].name,
ore = result.materials[1].name,
level = result.level
}
table.insert(_ingots[profession].order, ingot)
end
return _ingots[profession]
end
local function lookup_weapons(profession)
local ingots = lookup_ingots(profession)
local weapons = {}
for _, result in ipairs(mw.smw.ask{
({
Blacksmith = '[[Uses facility::Goblin Forge||Gnome Forge]]',
Stonemason = '[[Category:Stonemason]][[Category:Pages with recipes]][[Uses facility::!T.E.A. Machine]]',
Bonewright = '[[Category:Bonewright]][[Category:Pages with recipes]][[Uses facility::!B.R.E.W.S. Vat]]'
})[profession],
['?Recipe JSON'] = '',
mainlabel = '-',
sort = 'Profession Level A',
limit = '500'
}) do
local lvl = result['Profession Level A']
result = mw.text.jsonDecode(result[1])
if not result.passive and result.profession == profession then
local ingot
local pole
for _, material in ipairs(result.materials) do
if ingots.recipes[material.name] then
assert(not ingot)
ingot = material
else
assert(not pole)
pole = material
end
end
weapons[ingot.name] = weapons[ingot.name] or {}
table.insert(weapons[ingot.name], {
facility = result.facility,
level = result.level,
ingot = ingot,
pole = pole,
name = result.output[1].name,
xp = result.xp
})
end
end
return weapons
end
local function _lookup_price_uncached(item)
local result = mw.smw.ask{
('[[Sold item::%s]]'):format(item),
['?Shop buy price'] = 'buy',
['?Shop sell price'] = 'sell',
mainlabel = '-'
}[1]
return {
buy = tonumber(result.buy),
sell = tonumber(result.sell)
}
end
local _lookup_price_cache = {}
local function lookup_price(item)
_lookup_price_cache[item] = _lookup_price_cache[item] or _lookup_price_uncached(item)
return _lookup_price_cache[item]
end
local function _lookup_pole_uncached(pole)
local pole_data = mw.text.jsonDecode(mw.smw.ask{
('[[%s]]'):format(pole),
['?Recipe JSON'] = '',
mainlabel = '-'
}[1][1])
local post = pole_data.materials[1].name
local post_data = mw.text.jsonDecode(mw.smw.ask{
('[[%s]]'):format(post),
['?Recipe JSON'] = '',
mainlabel = '-'
}[1][1])
return {
level = pole_data.level,
pole = pole,
post = post,
log = post_data.materials[1].name
}
end
local _lookup_pole_cache = {}
local function lookup_pole(pole)
_lookup_pole_cache[pole] = _lookup_pole_cache[pole] or _lookup_pole_uncached(pole)
return _lookup_pole_cache[pole]
end
local function _lookup_ore_uncached(ore)
local data = mw.smw.ask{
('[[%s]]'):format(ore),
['?Profession Level A'] = '',
mainlabel = '-'
}[1]
return {
level = tonumber(data[1])
}
end
local _lookup_ore_cache = {}
local function lookup_ore(ore)
_lookup_ore_cache[ore] = _lookup_ore_cache[ore] or _lookup_ore_uncached(ore)
return _lookup_ore_cache[ore]
end
local function _lookup_log_uncached(log)
local data = mw.smw.ask{
('[[%s]]'):format(log),
['?Profession Level A'] = '',
mainlabel = '-'
}[1]
return {
level = tonumber(data[1])
}
end
local _lookup_log_cache = {}
local function lookup_log(log)
_lookup_log_cache[log] = _lookup_log_cache[log] or _lookup_log_uncached(log)
return _lookup_log_cache[log]
end
local p = {}
local p = {}
function p.ingots(frame)
return table.concat(lookup_ingots(frame.args.profession).order, ',')
end
function p.main(frame)
return p._main(frame:getParent().args)
end
function p._main(args)
local profession = args.profession
local current_xp = tonumber(args.current_xp) or 0
local current_lvl
if current_xp <= 500 then
current_lvl = current_xp
current_xp = xp._total_xp(current_lvl)
else
current_lvl = xp._level_at(current_xp)
end
local target_xp = tonumber(args.target_xp) or 0
local target_lvl
if target_xp <= 500 then
target_lvl = target_xp
target_xp = xp._total_xp(target_lvl)
else
target_lvl = xp._level_at(target_xp)
end
local remaining_xp = target_xp - current_xp
local buying_ores = args.ore_buy ~= 'false'
local buying_poles = args.pole_buy
local chopping_logs = buying_poles == 'none'
local buying_logs = buying_poles == 'logs'
buying_poles = not (buying_logs or chopping_logs)
local ingot = lookup_ingots(profession).recipes[args.ingot]
local result = mw.html.create()
result:wikitext(('To get from %s xp (level %s) to %s xp (level %s) requires %s experience'):format(lang:formatNum(current_xp), current_lvl, lang:formatNum(target_xp), target_lvl, lang:formatNum(remaining_xp)))
local tbl = result:tag('table')
:addClass('wikitable sortable')
local function skillclickpic(profession)
return ('[[File:%s small icon.png|15px|link=%s|%s level]]'):format(profession, profession, profession)
end
local colspan = 23
if chopping_logs then
colspan = colspan + 1
end
if chopping_logs or buying_logs then
colspan = colspan + 3
end
tbl
:tag('tr')
:th(skillclickpic(({
Blacksmith = 'Miner',
Stonemason = 'Miner',
Bonewright = 'Gatherer'
})[profession])):done()
:th{ ({
Blacksmith = 'Ore',
Stonemason = 'Rock',
Bonewright = 'Bone'
})[profession], attr = { colspan = '3' } }:done()
:th{ ({
Blacksmith = 'Ingot',
Stonemason = 'Etched',
Bonewright = 'Brewed'
})[profession], attr = { colspan = '2' } }:done()
:IF(chopping_logs)
:th(skillclickpic('Woodcutter')):done()
:END()
:IF(chopping_logs or buying_logs)
:th{ 'Log', attr = { colspan = '3' } }:done()
:th(skillclickpic('Carpenter')):done()
:END()
:th{ 'Pole', attr = { colspan = '3' } }:done()
:th(skillclickpic(profession)):done()
:th{ 'Product', attr = { colspan = '3' } }:done()
:th{ 'Cost', attr = { colspan = '10' } }:done()
:done()
for _, weapon in ipairs(lookup_weapons(profession)[ingot.ingot]) do
if not ingot.xp then
tbl
:tr()
:td{
'Missing XP for preparing [[' .. ingot.ingot .. ']]; Please [' .. tostring(mw.uri.fullUrl(ingot.ingot, 'action=edit§ion=1')) .. ' edit the page] to add the experience earned (after |exp =)',
attr = { colspan = colspan }
}
:done()
break
end
if not weapon.xp then
tbl
:tr()
:td{
'Missing XP for creating [[' .. weapon.name .. ']]; Please ['.. tostring(mw.uri.fullUrl(weapon.name, 'action=edit§ion=1')) .. ' edit the page] to add the experience earned (after |exp =)',
attr = { colspan = colspan }
}
:done()
else
local xp_per = weapon.xp + ingot.xp * weapon.ingot.quantity
local needed = math.ceil(remaining_xp / xp_per)
local needed_ores = needed * weapon.ingot.quantity
local row = tbl
:tag('tr')
:td(lookup_ore(ingot.ore).level):done()
:td{ needed_ores .. '×', css = { ['border-right'] = '0', ['padding-right'] = '0', ['text-align'] = 'right', ['data-sort-value'] = needed_ores } }:done()
:td{ ('[[File:%s.png|link=%s|30px]]'):format(ingot.ore, ingot.ore), css = { ['border-left'] = '0', ['padding-left'] = '0' }, addClass = 'plinkt-image no-border' }:done()
:td{ '[[' .. ingot.ore .. ']]', addClass = 'plinkt-link no-border' }:done()
:td{ ('[[File:%s.png|link=%s|30px]]'):format(ingot.ingot, ingot.ingot), css = { ['border-left'] = '0', ['padding-left'] = '0' }, addClass = 'plinkt-image no-border', ['data-sort-value'] = needed_ores }:done()
:td{ '[[' .. ingot.ingot .. ']]', addClass = 'plinkt-link no-border' }:done()
local pole_info
local needed_logs, needed_poles
if weapon.pole then
needed_poles = needed * weapon.pole.quantity
if chopping_logs or buying_logs then
pole_info = lookup_pole(weapon.pole.name)
needed_logs = math.ceil(needed_poles / 2)
end
if chopping_logs then
row
:td(lookup_log(pole_info.log).level):done()
end
if chopping_logs or buying_logs then
row
:td{ needed_logs .. '×', css = { ['border-right'] = '0', ['padding-right'] = '0', ['text-align'] = 'right' }, attr = { ['data-sort-value'] = needed_logs } }:done()
:td{ ('[[File:%s.png|link=%s|30px]]'):format(pole_info.log, pole_info.log), css = { ['border-left'] = '0', ['padding-left'] = '0' }, addClass = 'plinkt-image no-border' }:done()
:td{ '[[' .. pole_info.log .. ']]', addClass = 'plinkt-link no-border' }:done()
:td(pole_info.level):done()
end
row
:td{ needed_poles .. '×', css = { ['border-right'] = '0', ['padding-right'] = '0', ['text-align'] = 'right' }, attr = { ['data-sort-value'] = needed_poles } }:done()
:td{ ('[[File:%s.png|link=%s|30px]]'):format(weapon.pole.name, weapon.pole.name), css = { ['border-left'] = '0', ['padding-left'] = '0' }, addClass = 'plinkt-image no-border' }:done()
:td{ '[[' .. weapon.pole.name .. ']]', addClass = 'plinkt-link no-border' }:done()
else
if chopping_logs then
row
:na()
end
if chopping_logs or buying_logs then
row
:td{ '<small>N/A</small>', addClass = 'table-na', attr = { ['data-sort-value'] = '0', colspan = '3' } }:done()
:na()
end
row
:td{ '<small>N/A</small>', addClass = 'table-na', attr = { ['data-sort-value'] = '0', colspan = '3' } }:done()
end
row
:td(weapon.level)
:td{ needed .. '×', css = { ['border-right'] = '0', ['padding-right'] = '0', ['text-align'] = 'right' }, attr = { ['data-sort-value'] = needed } }:done()
:td{ ('[[File:%s.png|link=%s|30px]]'):format(weapon.name, weapon.name), css = { ['border-left'] = '0', ['padding-left'] = '0' }, addClass = 'plinkt-image no-border' }:done()
:td{ '[[' .. weapon.name .. ']]', addClass = 'plinkt-link no-border' }
local cost = needed_ores * lookup_price(ingot.ore)[buying_ores and 'buy' or 'sell']
if chopping_logs then
if needed_logs then
cost = cost + needed_logs * lookup_price(pole_info.log).sell
end
elseif buying_logs then
if needed_logs then
cost = cost + needed_logs * lookup_price(pole_info.log).buy
end
else
if weapon.pole then
cost = cost + needed_poles * lookup_price(weapon.pole.name).buy
end
end
row:node(currency._cell(cost, { html = 'yes' }))
end
end
return result
end
return p