Module:Graph:Utils

local p = {}

function p.titleToJson(title) -- Load mediawiki page and decodes it as json local t = mw.title.new(title) if not t.exists then return nil else return mw.text.jsonDecode(t:getContent(), mw.text.JSON_TRY_FIXING) end end

function p.recodeListToMap(frame) -- a function to re-code a json table in format [{},{},{}] to a map {}, -- with each source object containing the same set of values, and the response -- mapping the "from" value to "to" value -- parameters: tbl, from, to local args = frame.args local tbl = p.titleToJson(args[1]) local from = args[2] local to = args[3] local result = p.recodeListToMapFunc(tbl, from, to, args) return mw.text.jsonEncode(result) end

function p.recodeListToMapFunc(tbl, from, to, values) -- a function to re-code a json table in format [{},{},{}] to a map {}, -- with each source object containing the same set of values, and the response -- mapping the "from" values to "to" values -- parameters: tbl, from, to local dict = {} for k, v in pairs(tbl) do if v[from] ~= nil and v[to] ~= nil then dict[v[from]] = v[to] end end local result = {} for key, val in pairs(values) do if type(key) == "string" then local k = dict[key] if k ~= nil then result[k] = val end end end return result end

function p.parseCsv(frame) local args = frame.args local content = mw.title.new(args[1]):getContent() local columnName = args[2] local result = p.parseCsvFunc(content, columnName) return mw.text.jsonEncode(result) end

function p.parseCsvFunc(content, columnName) -- Simple, no escaping, csv parser. Assumes first row contains column names -- given csv text, extracts first column and names it 'id', and any other -- column that has the same name as the given columnName, and names it 'v' -- the result is in form: [{id=...,v=...}, {id=...,v=...}], ...] -- if coulmn is not found, v= will not be given local result = {} local numberIdx = false

for v in string.gmatch(content, '([^\n]*)') do local val = mw.text.trim(v) if val ~= then local parts = mw.text.split( val, ',', true ) if numberIdx == false then numberIdx = true for i, v in ipairs(parts) do local val = mw.text.trim(v) if val == columnName then numberIdx = i break end end else local val = nil if numberIdx ~= true then val = tonumber(mw.text.trim(parts[numberIdx])) end table.insert(result, { id=mw.text.trim(parts[1]), v=val }) end end end return result end

function p.parseHCsv(frame) local args = frame.args local content = mw.title.new(args[1]):getContent() local rowId = args[2] local result = p.parseHCsvFunc(content, rowId) return mw.text.jsonEncode(result) end

function p.parseHCsvFunc(content, id) -- Simple, no escaping, csv parser. Assumes first row contains column names -- given csv text, extracts just the row whos first column matches given id -- first column is not returned, all other column's headers become IDs -- the result is in form: [{id=...,v=...}, {id=...,v=...}], ...] -- DEBUG: =mw.text.jsonEncode(p.parseHCsvFunc('i,x,y,z\nb,1,2,3\na,2,3,4','a')) local result = {} local headers = false

for v in string.gmatch(content, '([^\n]*)') do local val = mw.text.trim(v) if val ~= then local parts = mw.text.split( val, ',', true ) if headers == false then headers = {} for i, v in ipairs(parts) do table.insert(headers, mw.text.trim(v)) end elseif mw.text.trim(parts[1]) == id then local isFirst = true for i, v in ipairs(parts) do if isFirst then isFirst = false else table.insert(result, { id=headers[i], v=tonumber(mw.text.trim(v)) }) end end break end end end return result end

function p.expandDict(frame) return mw.text.jsonEncode(p.expandDictFunc(mw.text.jsonDecode(frame.args[1]))) end

function p.expandDictFunc(inp) -- Converts compressed format json table to expanded format, for example: -- { "a": 10, "b": 20 } -- will be converted to -- [{ "id": "a", "v": 10 }, { "id": "b", "v": 20 }] -- DEBUG: =mw.text.jsonEncode(p.expandDictFunc(mw.text.jsonDecode('{ "a": 10, "b": 20 }'))) local result = {} for k, v in pairs(inp) do table.insert(result, { id=k, v=v }) end return result end

return p