The Alchemist Code Wiki
READ MORE
The Alchemist Code Wiki
Explore
Main Page
All Pages
Interactive Maps
Units
Team Building Tools
Global Tier List
ACDB Unit Builder
Raid Buffer/Debuffer List
Team Building
About Units
About Units
List of Units
Jobs
About Jobs
List of Jobs
Job Upgrades
Job+ List
Equipment
Unit Shards
Elemental Shards
Enlightenment
Truth Seals
Obtainables
Mementos
About Mementos
List of Mementos
Memento Quick Reference
Mementos Rated By Usefulness
Memento Leader Skills
Gear
About Gear
Free (Permanent)
Free (Event)
Summon
VCR (Memento)
PvP
Enlightened Gear Skills
Consumables
Gameplay & Guides
Gameplay
About the Game
Lore
Mechanics
New Player Help
Help Center
Beginner's Guide
Reroll Guide
Glossary of Terms
Recommended Free Units
Shard Farm Priority
Banners
Lore
Main Story
Ancient Story
Genesis Story
Sacred Stone Memories
Babel Chronicles
Character Stories
Event Stories
NPCs
News and Events
List of Events by Date
References
Update History
Shops
Milestones
Friends
Mercenaries
Alchemia Port
Experience Charts
Other Resources
Guides and Rankings
Discord
Alchemist Code Database
Quests
Story
Character Quests
Events
Multiplay
Raids
Battle
Babel Expedition
FANDOM
Fan Central
BETA
Games
Anime
Movies
TV
Video
Wikis
Explore Wikis
Community Central
Start a Wiki
Don't have an account?
Register
Sign In
FANDOM
Explore
Current Wiki
Start a Wiki
Don't have an account?
Register
Sign In
Sign In
Register
The Alchemist Code Wiki
21,533
pages
Explore
Main Page
All Pages
Interactive Maps
Units
Team Building Tools
Global Tier List
ACDB Unit Builder
Raid Buffer/Debuffer List
Team Building
About Units
About Units
List of Units
Jobs
About Jobs
List of Jobs
Job Upgrades
Job+ List
Equipment
Unit Shards
Elemental Shards
Enlightenment
Truth Seals
Obtainables
Mementos
About Mementos
List of Mementos
Memento Quick Reference
Mementos Rated By Usefulness
Memento Leader Skills
Gear
About Gear
Free (Permanent)
Free (Event)
Summon
VCR (Memento)
PvP
Enlightened Gear Skills
Consumables
Gameplay & Guides
Gameplay
About the Game
Lore
Mechanics
New Player Help
Help Center
Beginner's Guide
Reroll Guide
Glossary of Terms
Recommended Free Units
Shard Farm Priority
Banners
Lore
Main Story
Ancient Story
Genesis Story
Sacred Stone Memories
Babel Chronicles
Character Stories
Event Stories
NPCs
News and Events
List of Events by Date
References
Update History
Shops
Milestones
Friends
Mercenaries
Alchemia Port
Experience Charts
Other Resources
Guides and Rankings
Discord
Alchemist Code Database
Quests
Story
Character Quests
Events
Multiplay
Raids
Battle
Babel Expedition
Editing
Module:Data
Back to page
Edit source
View history
Talk (0)
Edit Page
Module:Data
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
-- <nowiki> local p = {} local h = {} local cargo = require('Module:CargoUtil') local yesno = require('Module:Yesno') local dataModel = require("Module:Data/Model") local util_text = require('Module:TextUtil') local util_time = require('Module:TimeUtil') local split = util_text.split local gsplit = util_text.gsplit local trim = util_text.trim local langs = {'english', 'japanese'} local locPrefixes = { ['Ability'] = true, ['Artifact'] = true, ['ConceptCard'] = true, ['Item'] = true, ['Job'] = true, ['Skill'] = true, ['Unit'] = true, } function h.getEntityType(args) local name = args.name or mw.title.getCurrentTitle().prefixedText return name:match('Data:Game/MasterParam/([^/]+)/.+') end local hasOtherdesc = false local hasCharadesc = false function p.displayLocs(data) local locs = data.loc if not locs then return end local entityType = h.getEntityType(data) if not entityType or not locPrefixes[entityType] then return end local definitions = mw.loadData('Module:CargoDeclare/'..entityType..'Loc') -- HOTFIX: "otherdesc" local temp = {} for param, obj in pairs(locs) do if param == 'otherdesc' then hasOtherdesc = true param = 'desc_ot' end if param == 'charadesc' then hasCharadesc = true end for lang, value in pairs(obj) do temp[param] = temp[param] or {} temp[param][lang] = value end end locs = temp -- Build localization wikitable local wikitable = mw.html.create('table'):addClass('wikitable') local tr = wikitable:tag('tr') tr:tag('th'):wikitext('param') for _, lang in ipairs(langs) do tr:tag('th'):wikitext(lang) end for _, definition in ipairs(definitions) do local field = definition.field if field and locs[field] then tr = wikitable:tag('tr') tr:tag('th'):wikitext(field) for _, lang in ipairs(langs) do tr:tag('td'):wikitext(locs[field][lang]) end end end return tostring(wikitable) end function p.storeLocs(nocargo, data) local locs = data.loc if not locs then return end local entityType = h.getEntityType(data) if not entityType or not locPrefixes[entityType] then return end local iname = (data.gl or data.jp or {}).iname local definitions = mw.loadData('Module:CargoDeclare/'..entityType..'Loc') -- HOTFIX: "otherdesc" local temp = {} for param, obj in pairs(locs) do if param == 'otherdesc' then param = 'desc_ot' end for lang, value in pairs(obj) do temp[param] = temp[param] or {} temp[param][lang] = value end end locs = temp local rows = {} for _, definition in ipairs(definitions) do local field = definition.field if field and locs[field] then for lang, value in pairs(locs[field]) do rows[lang] = rows[lang] or { _table = entityType .. 'Loc', iname = iname, lang = lang, } rows[lang][field] = value end end end local result = {} -- Store localization if not yesno(nocargo) then for _, row in pairs(rows) do mw.logObject(row) cargo.store(row) end end return table.concat(result) end function h.getTitlePath() local curTitle = mw.title.getCurrentTitle() --if curTitle.prefixedText == "Module:Data" then curTitle = mw.title.new("Game/MasterParam/Unit/UN_V2_LOGI", "Data") end local titleNodes = {curTitle.subpageText} while curTitle.baseText ~= curTitle.text do curTitle = curTitle.basePageTitle table.insert(titleNodes, 1, curTitle.subpageText) end return titleNodes end -- Generates table for data page function h.insertQueryResult(result, title, tbl) local fields = {} local found = {} local count = 0 local hideCols = true for i, row in pairs(tbl) do count = count + 1 for col in ipairs(row) do if found[col] == nil then table.insert(fields, col) found[col] = true end end for col in pairs(row) do if found[col] == nil then table.insert(fields, col) found[col] = true hideCols = false end end end table.sort(fields, function(a, b) return a == "server" or a == "lang" or (b ~= "server" and b ~= "lang" and (a or '') < (b or '')) end) if count == 0 then return nil end if title ~= nil then table.insert(result, "==="..title.."===\n") end table.insert(result, '{| class="wikitable"') for i, col in ipairs(fields) do table.insert(result, "\n|-") if not hideCols then table.insert(result, "\n! ") table.insert(result, col) end -- Merge matching rows local allSame = true local testVal = tbl[next(tbl)][col] for j, row in pairs(tbl) do if type(testVal) == 'table' and type(row[col]) == 'table' then for k, v in pairs(testVal) do if v ~= row[col][k] then allSame = false end end for k, v in pairs(row[col]) do if v ~= testVal[k] then allSame = false end end elseif row[col] ~= testVal then allSame = false end end local function writeVal(val) if type(val) == "table" then table.insert(result, "\n") h.insertQueryResult(result, nil, {val}) else table.insert(result, tostring(val or '')) end end if allSame then table.insert(result, '\n| colspan="'..count..'" | ') writeVal(testVal) else for j, row in pairs(tbl) do table.insert(result, "\n| ") writeVal(row[col]) end end end table.insert(result, "\n|}\n") end p.insertQueryResult = h.insertQueryResult -- Will only actually perform the declares on the CargoTable template pages. function p.init(frame) local args = require('Module:Arguments').getArgs(frame, {parentFirst=true}) return p._init(args) end function p._init(args) local declareStatements = {} local recFunc function recFunc(node) if node.nodes ~= nil then for k, child in pairs(node.nodes) do recFunc(child) end end if node.model ~= nil then for tbl, model in pairs(node.model) do local statement = {"", _table = tbl, server = "String"} for col, colModel in pairs(model) do if type(colModel) == "string" then colModel = {colModel} end local modelType = colModel[1] if colModel.list ~= nil then modelType = "List ("..colModel.list..") of "..modelType end statement[col] = modelType end declareStatements[tbl] = statement end end end recFunc(dataModel) local curTitle = mw.title.getCurrentTitle() if args[1] then curTitle = mw.title.new(args[1]) end if curTitle.basePageTitle.prefixedText == "Template:CargoTable" then local statement = declareStatements[curTitle.subpageText] if statement == nil then return "Invalid table "..curTitle.subpageText end local tbl = {'{{#cargo_declare:', '}}'} for k,v in pairs(statement) do if k ~= 1 then tbl[#tbl+1] = '| ' .. k..' = '..v end end table.sort(tbl) local declare = table.concat(tbl, '\n') if yesno(args.debug) then return tostring(mw.html.create('pre'):wikitext(declare)) else mw.log(declare) return mw.getCurrentFrame():callParserFunction('#cargo_declare', statement) end end if mw.getCurrentFrame():getParent() == nil then return nil end return "asdf" end -- Called from Data pages function p.insert(frame) local args = require('Module:Arguments').getArgs(frame, {parentFirst = true}) return p._insert(args) end function p._insert(args) local nocargo = args.nocargo local curNode = {nodes = {Game = dataModel}} local titlePath = h.getTitlePath() for i, pathItem in ipairs(titlePath) do if curNode == nil then return nil end if i == #titlePath then break end if curNode.nodes == nil then return nil end curNode = curNode.nodes[pathItem] end if curNode.model == nil then return nil end -- Now that we know this is a valid page local result = {} if next(curNode.model) ~= nil then table.insert(result, "==Tables==\nThe following tables have these rows defined by this data entry.\n") end -- Decode JSON local jsonSets = {} for k, v in pairs(args) do if type(v) == 'string' then v = mw.text.decode(mw.text.unstripNoWiki(v)) local success, result = pcall(mw.text.jsonDecode, v) if success then v = result end args[k] = v end end local content_sha256s = {} local suffix = '_sha256' for server, json in pairs(args) do if server == 'gl' or server == 'jp' or server == 'loc' then jsonSets[server] = json elseif string.sub(server, -string.len(suffix)) == suffix then -- TODO: Store this in a cargo table somewhere. content_sha256s[string.sub(server, 1, -string.len(suffix))] = json end end -- Convert Functions local convertFrom = { table = function(val, model) if model.list ~= nil then return table.concat(val, model.list) end error("JSON data for "..model[1].." is a table but is not modeled to handle it.") end, } -- Insert Rows local where = '_pageId='..mw.title.getCurrentTitle().id local errors = {} -- Do loc first result[#result+1] = p.storeLocs(nocargo, args) result[#result+1] = p.displayLocs(args) local locSets = jsonSets.loc or {} jsonSets.loc = nil local expected = 0 for param, json in pairs(locSets) do if type(json) == "table" then for lang, value in pairs(json) do cargo.store{ _table = 'Loc', lang = lang, param = param, value = value, } expected = expected + 1 end end end -- Query loc table local rows = cargo.query{ tables = 'Loc', fields = 'lang, param, value', where = where, orderBy = 'lang' } -- Check if expected row count matches actual row count. local actual = #rows if actual ~= expected then table.insert(result, string.format('Entry count mismatch in table %q (%s expected, got %s)\n', 'Loc', expected, actual)) errors.cargoStore = true end -- Generate loc tables from queried data local queryResult = {} for i, row in ipairs(rows) do if row.lang == 'english' and row.param == 'name' then local pagename = string.gsub(row.value, "[%[%]]", { ["["] = "【", ["]"] = "】", }) if pagename ~= row.value then row.value = '[[' .. pagename .. '|' .. row.value .. ']]' else row.value = '[[' .. row.value .. ']]' end end queryResult[i] = row end h.insertQueryResult(result, tbl, queryResult) local iname for server, json in pairs(jsonSets) do if not iname and json.iname then iname = json.iname end end local actualTitle = table.concat(titlePath, '/', 1, 3) mw.logObject(actualTitle, 'actualTitle') if actualTitle == 'Game/MasterParam/Buff' then local definitions = mw.loadData('Module:CargoDeclare/BuffDetail') for server, json in pairs(jsonSets) do for i=1,11 do local values = { _table = 'BuffDetail', } for _, definition in ipairs(definitions) do local field = definition.field if definition.type == 'Integer' then values[field] = tonumber(json[field..i]) else values[field] = json[field..i] end end values.server = server values.buff_iname = iname values.idx = i if (values.type or 0) <= 0 then mw.logObject(values, "Skipped insert into BuffDetail values") else mw.logObject(values, "#cargo_store") cargo.store(values) end end end end if actualTitle == 'Game/MasterParam/Job' then local definitions = mw.loadData('Module:CargoDeclare/JobRank') local jobRanks = {} for server, json in pairs(jsonSets) do for i, rank in ipairs(json.ranks) do local values = { _table = 'JobRank', } for _, definition in ipairs(definitions) do local field = definition.field if rank[field] ~= nil then if definition.type == 'Integer' then values[field] = tonumber(rank[field]) else values[field] = rank[field] end rank[field] = nil -- remove end end values.server = server values.job_iname = iname values.idx = i mw.logObject(values, "#cargo_store") cargo.store(values) values._table = nil jobRanks[i] = jobRanks[i] or {} jobRanks[i][#jobRanks[i]+1] = values end json.ranks = nil -- done end table.insert(result, '=== JobRank ===\n') for i, rank in ipairs(jobRanks) do h.insertQueryResult(result, nil, rank) end end -- Now get the data for tbl, model in pairs(curNode.model) do expected = 0 for server, json in pairs(jsonSets) do local statement = {_table = tbl, server = server} for col, colModel in pairs(model) do if type(colModel) == "string" then colModel = {colModel} end -- Extract value local jsonVal = json[colModel.from or colModel.alias or col] json[colModel.from or colModel.alias or col] = nil -- Convert datatypes here local converter = convertFrom[type(jsonVal)] if converter ~= nil then jsonVal = converter(jsonVal, colModel) end if colModel[1] == 'Datetime' then jsonVal = util_time.worldTimeToUTC(jsonVal, server) or jsonVal end -- Append to statement statement[col] = jsonVal end mw.logObject(statement, 'statement') cargo.store(statement) expected = expected + 1 end -- Query the data local query = { tables = tbl, fields = {"server"}, where = where, orderBy = 'server', } for col in pairs(model) do -- Required to query only existing columns. local ok, _ = pcall(cargo.query, {tables=tbl, fields=col, where=1, limit=1}) if ok then table.insert(query.fields, col) end end local rows = cargo.query(query) local actual = #rows if actual ~= expected then table.insert(result, string.format('Entry count mismatch in table %q (%s expected, got %s)\n', tbl, expected, actual)) errors.cargoStore = true end -- Generate tables from queried data queryResult = {} for i, row in ipairs(rows) do for col, val in pairs(row) do if type(model[col]) == "table" then if model[col].list ~= nil then val = #val == 0 and {} or split(val, model[col].list, true) end if model[col].dataRef ~= nil then if type(val) == "table" then for k, v in pairs(val) do if not v:find('__HIDE__$') then val[k] = "[[Data:Game/"..model[col].dataRef.."/"..v.."|"..v.."]]" else val[k] = v end end elseif #val > 0 and not val:find('__HIDE__$') then val = "[[Data:Game/"..model[col].dataRef.."/"..val.."|"..val.."]]" end end end row[col] = val end queryResult[i] = row end h.insertQueryResult(result, tbl, queryResult) end local hasEffects = false local jsonEffects = {} for server, json in pairs(jsonSets) do if json.effects then hasEffects = true jsonEffects[server] = {effects = {}} for i,effect in ipairs(json.effects) do local values = {} values._table = 'ConceptCardEffect' values.server = server values.cc_iname = iname jsonEffects[server].effects[i] = {} for k,v in pairs(effect) do values[k] = v jsonEffects[server].effects[i][k] = v effect[k] = nil end cargo.store(values) jsonEffects[server].server = server end -- A table of failed effect insertions. local errorEffects = {} for i, effect in ipairs(json.effects) do local empty = true for k, v in pairs(effect) do empty = false end if not empty then errorEffects[#errorEffects+1] = effect end end json.effects = #errorEffects > 0 and errorEffects or nil end end if next(jsonEffects) then table.insert(result, '===ConceptCardEffect===\n') local toInsert = {} for k in pairs(jsonEffects) do table.insert(toInsert, k) end table.sort(toInsert) for i, k in ipairs(toInsert) do toInsert[i] = jsonEffects[k] end h.insertQueryResult(result, nil, toInsert) end local buffDetailRows = cargo.query{ tables = 'BuffDetail', fields = 'buff_iname, server, idx, calc, type, tktag, vini, vmax, vone', where = where, orderBy = 'idx' } h.insertQueryResult(result, 'BuffDetail', buffDetailRows) -- Display unused keys here local unused = false for server, json in pairs(jsonSets) do if next(json) ~= nil then unused = true json.server = server end end if unused then table.insert(result, "===Unused Keys===\nThe following keys were not used by inserted into any table and are thus unused.\n") local toInsert = {} for k in pairs(jsonSets) do table.insert(toInsert, k) end table.sort(toInsert) for i, k in ipairs(toInsert) do toInsert[i] = jsonSets[k] end h.insertQueryResult(result, nil, toInsert) end table.insert(result, '[[Category:Data pages]]') -- Tracking category. -- Handle errors encountered if errors.cargoStore then table.insert(result, '[[Category:Data pages that failed a table insert]]' ) end if hasEffects then table.insert(result, '[[Category:Data pages with effects]]') end if hasOtherdesc then table.insert(result, '[[Category:Data pages with otherdesc]]') end if hasCharadesc then table.insert(result, '[[Category:Data pages with charadesc]]') end return table.concat(result) end -- Add functions to model p.model = (function() dataModel.tables = {} local recFunc function recFunc(node) if node.nodes ~= nil then for k, child in pairs(node.nodes) do recFunc(child) end end if node.model ~= nil then for tbl, model in pairs(node.model) do dataModel.tables[tbl] = model end end end recFunc(dataModel) ----------- -- Query -- ----------- dataModel.query = function(tables, fields, args) local query = args query.tables = tables query.fields = fields local result = cargo.query(query) local toCast = {} if type(query.tables) == 'string' then query.tables = split(query.tables, ',', true) end if type(query.fields) == 'string' then query.fields = split(query.fields, ',', true) end for _, field in ipairs(query.fields) do -- Extract alias local t = split(field, '=', true) local alias = trim(t[2] or t[1]) local fnMatch = string.match(t[1], "([^()]*)[(](.*)[)](.*)") if fnMatch ~= nil then mw.log(fnMatch) toCast[alias] = {"String"} else -- Extract table local t2 = split(t[1], '.', true) local tbl = #t2 > 1 and trim(t2[1]) or nil local key = trim(t2[#t2]) if tbl == nil then for _, tblName in ipairs(query.tables) do tblName = trim(tblName) if (dataModel.tables[tblName] or {})[key] ~= nil then tbl = tblName break end end end local model = (dataModel.tables[tbl] or {})[key] toCast[alias] = type(model) == "string" and {model} or model end end local castFuncs = { Integer = tonumber } for i, row in ipairs(result) do for k, castTo in pairs(toCast) do local castFunc = castFuncs[castTo[1]] or function(v) return v end if castTo.list ~= nil then local list = {} if row[k] and row[k] ~= '' then for s in gsplit(row[k], castTo.list, true) do list[#list+1] = castFunc(s) end end row[k] = list else row[k] = castFunc(row[k]) end end end return result end ------------ -- getLoc -- ------------ dataModel.getLoc = function(_pageName, param, lang) if _pageName == nil then return '???' end local where = "_pageName='".._pageName.."' and param='"..param.."' and value<>'' and lang='" local thisLang = cargo.query{tables='Loc',fields='value',where=where..(lang or "english'")} if #thisLang == 0 then thisLang = cargo.query{tables='Loc',fields='value',where=where.."english'"} end if #thisLang == 0 then thisLang = cargo.query{tables='Loc',fields='value',where=where.."japanese'"} end if #thisLang == 0 then thisLang = {{value = ''}} end return thisLang[1].value end ------------- -- Sources -- ------------- dataModel.sources = require("Module:Data/Sources")(dataModel) return dataModel end)() return p
Summary:
Please note that all contributions to the The Alchemist Code Wiki are considered to be released under the CC BY-NC-SA
Cancel
Editing help
(opens in new window)
Template used on this page:
Module:Data/doc
(
edit
)
Follow on IG
TikTok
Join Fan Lab