<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://pool.calebcooper.ie/index.php?action=history&amp;feed=atom&amp;title=Module%3AGraph%3AUtils</id>
	<title>Module:Graph:Utils - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pool.calebcooper.ie/index.php?action=history&amp;feed=atom&amp;title=Module%3AGraph%3AUtils"/>
	<link rel="alternate" type="text/html" href="https://pool.calebcooper.ie/index.php?title=Module:Graph:Utils&amp;action=history"/>
	<updated>2026-04-10T15:40:22Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://pool.calebcooper.ie/index.php?title=Module:Graph:Utils&amp;diff=9914&amp;oldid=prev</id>
		<title>Caleb Cooper: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://pool.calebcooper.ie/index.php?title=Module:Graph:Utils&amp;diff=9914&amp;oldid=prev"/>
		<updated>2020-01-28T15:03:40Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 15:03, 28 January 2020&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Caleb Cooper</name></author>
	</entry>
	<entry>
		<id>https://pool.calebcooper.ie/index.php?title=Module:Graph:Utils&amp;diff=9913&amp;oldid=prev</id>
		<title>powerstorewiki&gt;Caleb Cooper: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://pool.calebcooper.ie/index.php?title=Module:Graph:Utils&amp;diff=9913&amp;oldid=prev"/>
		<updated>2020-01-21T18:20:50Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.titleToJson(title)&lt;br /&gt;
	-- Load mediawiki page and decodes it as json&lt;br /&gt;
	local t = mw.title.new(title)&lt;br /&gt;
	if not t.exists then&lt;br /&gt;
		return nil&lt;br /&gt;
	else&lt;br /&gt;
		return mw.text.jsonDecode(t:getContent(), mw.text.JSON_TRY_FIXING)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.recodeListToMap(frame)&lt;br /&gt;
	-- a function to re-code a json table in format [{},{},{}] to a map {},&lt;br /&gt;
	-- with each source object containing the same set of values, and the response&lt;br /&gt;
	-- mapping the &amp;quot;from&amp;quot; value to &amp;quot;to&amp;quot; value&lt;br /&gt;
	-- parameters: tbl, from, to&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local tbl = p.titleToJson(args[1])&lt;br /&gt;
	local from = args[2]&lt;br /&gt;
	local to = args[3]&lt;br /&gt;
	local result = p.recodeListToMapFunc(tbl, from, to, args)&lt;br /&gt;
	return mw.text.jsonEncode(result)&lt;br /&gt;
end&lt;br /&gt;
 &lt;br /&gt;
function p.recodeListToMapFunc(tbl, from, to, values)&lt;br /&gt;
	-- a function to re-code a json table in format [{},{},{}] to a map {},&lt;br /&gt;
	-- with each source object containing the same set of values, and the response&lt;br /&gt;
	-- mapping the &amp;quot;from&amp;quot; values to &amp;quot;to&amp;quot; values&lt;br /&gt;
	-- parameters: tbl, from, to&lt;br /&gt;
	local dict = {}&lt;br /&gt;
	for k, v in pairs(tbl) do&lt;br /&gt;
		if v[from] ~= nil and v[to] ~= nil then&lt;br /&gt;
			dict[v[from]] = v[to]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local result = {}&lt;br /&gt;
	for key, val in pairs(values) do&lt;br /&gt;
		if type(key) == &amp;quot;string&amp;quot; then&lt;br /&gt;
			local k = dict[key]&lt;br /&gt;
			if k ~= nil then&lt;br /&gt;
				result[k] = val&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.parseCsv(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local content = mw.title.new(args[1]):getContent()&lt;br /&gt;
	local columnName = args[2]&lt;br /&gt;
	local result = p.parseCsvFunc(content, columnName)&lt;br /&gt;
	return mw.text.jsonEncode(result)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.parseCsvFunc(content, columnName)&lt;br /&gt;
	-- Simple, no escaping, csv parser. Assumes first row contains column names&lt;br /&gt;
	-- given csv text, extracts first column and names it &amp;#039;id&amp;#039;, and any other&lt;br /&gt;
	-- column that has the same name as the given columnName, and names it &amp;#039;v&amp;#039;&lt;br /&gt;
	-- the result is in form:  [{id=...,v=...}, {id=...,v=...}], ...]&lt;br /&gt;
	-- if coulmn is not found, v= will not be given&lt;br /&gt;
	local result = {}&lt;br /&gt;
	local numberIdx = false&lt;br /&gt;
&lt;br /&gt;
	for v in string.gmatch(content, &amp;#039;([^\n]*)&amp;#039;) do&lt;br /&gt;
		local val = mw.text.trim(v)&lt;br /&gt;
		if val ~= &amp;#039;&amp;#039; then&lt;br /&gt;
			local parts = mw.text.split( val, &amp;#039;,&amp;#039;, true )&lt;br /&gt;
			if numberIdx == false then&lt;br /&gt;
				numberIdx = true&lt;br /&gt;
				for i, v in ipairs(parts) do&lt;br /&gt;
					local val = mw.text.trim(v)&lt;br /&gt;
					if val == columnName then&lt;br /&gt;
						numberIdx = i&lt;br /&gt;
						break&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				local val = nil&lt;br /&gt;
				if numberIdx ~= true then&lt;br /&gt;
					val = tonumber(mw.text.trim(parts[numberIdx]))&lt;br /&gt;
				end&lt;br /&gt;
				table.insert(result, {&lt;br /&gt;
					id=mw.text.trim(parts[1]),&lt;br /&gt;
					v=val&lt;br /&gt;
				})&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.parseHCsv(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local content = mw.title.new(args[1]):getContent()&lt;br /&gt;
	local rowId = args[2]&lt;br /&gt;
	local result = p.parseHCsvFunc(content, rowId)&lt;br /&gt;
	return mw.text.jsonEncode(result)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.parseHCsvFunc(content, id)&lt;br /&gt;
	-- Simple, no escaping, csv parser. Assumes first row contains column names&lt;br /&gt;
	-- given csv text, extracts just the row whos first column matches given id&lt;br /&gt;
	-- first column is not returned, all other column&amp;#039;s headers become IDs&lt;br /&gt;
	-- the result is in form:  [{id=...,v=...}, {id=...,v=...}], ...]&lt;br /&gt;
	-- DEBUG:  =mw.text.jsonEncode(p.parseHCsvFunc(&amp;#039;i,x,y,z\nb,1,2,3\na,2,3,4&amp;#039;,&amp;#039;a&amp;#039;))&lt;br /&gt;
	local result = {}&lt;br /&gt;
	local headers = false&lt;br /&gt;
&lt;br /&gt;
	for v in string.gmatch(content, &amp;#039;([^\n]*)&amp;#039;) do&lt;br /&gt;
		local val = mw.text.trim(v)&lt;br /&gt;
		if val ~= &amp;#039;&amp;#039; then&lt;br /&gt;
			local parts = mw.text.split( val, &amp;#039;,&amp;#039;, true )&lt;br /&gt;
			if headers == false then&lt;br /&gt;
				headers = {}&lt;br /&gt;
				for i, v in ipairs(parts) do&lt;br /&gt;
					table.insert(headers, mw.text.trim(v))&lt;br /&gt;
				end&lt;br /&gt;
			elseif mw.text.trim(parts[1]) == id then&lt;br /&gt;
				local isFirst = true&lt;br /&gt;
				for i, v in ipairs(parts) do&lt;br /&gt;
					if isFirst then&lt;br /&gt;
						isFirst = false&lt;br /&gt;
					else&lt;br /&gt;
						table.insert(result, {&lt;br /&gt;
							id=headers[i],&lt;br /&gt;
							v=tonumber(mw.text.trim(v))&lt;br /&gt;
						})&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.expandDict(frame)&lt;br /&gt;
	return mw.text.jsonEncode(p.expandDictFunc(mw.text.jsonDecode(frame.args[1])))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.expandDictFunc(inp)&lt;br /&gt;
	-- Converts compressed format json table to expanded format, for example:&lt;br /&gt;
	--    { &amp;quot;a&amp;quot;: 10, &amp;quot;b&amp;quot;: 20 }&lt;br /&gt;
	-- will be converted to &lt;br /&gt;
	--    [{ &amp;quot;id&amp;quot;: &amp;quot;a&amp;quot;, &amp;quot;v&amp;quot;: 10 }, { &amp;quot;id&amp;quot;: &amp;quot;b&amp;quot;, &amp;quot;v&amp;quot;: 20 }]&lt;br /&gt;
	-- DEBUG:  =mw.text.jsonEncode(p.expandDictFunc(mw.text.jsonDecode(&amp;#039;{ &amp;quot;a&amp;quot;: 10, &amp;quot;b&amp;quot;: 20 }&amp;#039;)))&lt;br /&gt;
	local result = {}&lt;br /&gt;
	for k, v in pairs(inp) do&lt;br /&gt;
		table.insert(result, {&lt;br /&gt;
			id=k,&lt;br /&gt;
			v=v&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>powerstorewiki&gt;Caleb Cooper</name></author>
	</entry>
</feed>