Module:Shindo

local p = {} local getArgs = require("Module:Arguments").getArgs local data = mw.loadData("Module:Shindo/data") local messages = mw.loadData("Module:Shindo/messages") local makeInvokeFunc = require("Module:MakeInvokeFunc")(p) local message = require("Module:Message")(messages) local yn = require("Module:Yesno")

local function getValueOfColor(tbl) return (tbl[1] + tbl[2] + tbl[3]) / 3 / 255 end

local function rgbColor(tbl) return tbl[1] .. (tbl[2] and ", " .. tbl[2] .. (tbl[3] and ", " .. tbl[3] or "") or "") end

local function averageColor(tbl) local colors = {} for k,v in pairs(tbl) do		colors[k] = v	end local avg = {0, 0, 0} for _,color in pairs(colors) do		avg[1] = avg[1] + color[1] avg[2] = avg[2] + color[2] avg[3] = avg[3] + color[3] end avg[1] = math.ceil(avg[1] / #colors) - avg[1] / #colors > 0.5 and math.floor(avg[1] / #colors) or math.ceil(avg[1] / #colors) avg[2] = math.ceil(avg[2] / #colors) - avg[2] / #colors > 0.5 and math.floor(avg[2] / #colors) or math.ceil(avg[2] / #colors) avg[3] = math.ceil(avg[3] / #colors) - avg[3] / #colors > 0.5 and math.floor(avg[3] / #colors) or math.ceil(avg[3] / #colors) return avg end

local function listIntensitiesFromScale(scale, intensities, labelScale, scale2) local out = '' if yn(labelScale) then out = out .. data[scale].short .. ' '	end local categoriesAreSame = true local category = "" for k,v in pairs(intensities) do		if data[scale].ranks[v] == nil then error(message("invalidIntensity", {v, scale})) end out = out .. data[scale].ranks[v].label if k ~= #intensities then if #intensities == 2 then out = out .. '–'			else out = out .. '/'			end end if category == "" and categoriesAreSame then category = data[scale].ranks[v].category or "" end categoriesAreSame = categoriesAreSame and category ~= "" and (data[scale].ranks[v].category and data[scale].ranks[v].category == category or false) end if categoriesAreSame and category ~= "" and not scale2 then out = out .. " (" .. category .. ")" end return out end

p._color = function(args) local scale = string.lower(args.scale or args[1] or error(message("noScaleShortCode"))) local intensity = string.upper(args.intensity or args[2] or error(message("noIntensity"))) if data[scale] == nil then error(message("invalidScale", {scale})) end if data[scale].ranks[intensity] == nil then error(message("invalidIntensity", {intensity, scale})) end local order = data[scale].ranks[intensity].order local color = data[scale].colors[order] local colorIntensity = getValueOfColor(color) return 'background-color:rgb(' .. rgbColor(color) .. '); color:' .. (colorIntensity < 0.5 and "white" or "black") .. ";" end

p._formatInWikitable = function(args) local scale = string.lower(args.scale or args[1] or error(message("noScaleShortCode"))) local link = args.link ~= nil and args.link or true local labelScale = args.labelScale ~= nil and args.labelScale or true local doColor = args.color ~= nil and args.color or true local intensity = string.upper(args.intensity or args[2] or error(message("noIntensity"))) local intensities = mw.text.split(intensity, "/") or { intensity } if data[scale] == nil then error(message("invalidScale", {scale})) end local colors = {} for k,v in pairs(intensities) do		local order = data[scale].ranks[v].order colors[k] = data[scale].colors[order] end local color = averageColor(colors) local colorIntensity = getValueOfColor(color) local out = "" if yn(args.header or false) then out = out .. "! " 	else out = out .. "| "	end out = out .. (args.tagProps ~= nil and args.tagProps or "") if (yn(doColor)) then out = out .. 'style="background-color:rgba(' .. rgbColor(color) .. '); color:' .. (colorIntensity < 0.5 and "white" or "black") .. ';' .. (args.style or "") .. '" | ' elseif (args.style) then out = out .. 'style="' .. (args.style or "") .. '" | ' end if yn(link) then out = out .. '"	end	if yn(doColor) then		out = out .. ''	end	out = out .. listIntensitiesFromScale(scale, intensities, labelScale, false)	if yn(doColor) then		out = out .. ' '	end	if yn(link) then		out = out .. "" end return out end

p._formatTag = function(args) local scale = string.lower(args.scale or args[1] or error(message("noScaleShortCode"))) local scale2 = args.scale2 or args[3] or nil if scale2 ~= nil then scale2 = string.lower(scale2) end local link = args.link ~= nil and args.link or true local labelScale = args.labelScale ~= nil and args.labelScale or true local doColor = args.color ~= nil and args.color or true local intensity = string.upper(args.intensity or args[2] or error(message("noIntensity"))) local intensities = mw.text.split(intensity, "/") or { intensity } local intensity2 = args.intensity2 or args[4] or (scale2 and error(message("noIntensity"))) or nil local intensities2 = {} if intensity2 ~= nil then intensity2 = string.upper(intensity2) intensities2 = mw.text.split(intensity2, "/") or { intensity2 } end if data[scale] == nil then error(message("invalidScale", {scale})) end if scale2 and data[scale2] == nil then error(message("invalidScale", {scale2})) end local colors = {} for k,v in pairs(intensities) do		local order = data[scale].ranks[v].order colors[k] = data[scale].colors[order] end local color = averageColor(colors) local colorIntensity = getValueOfColor(color) local out = '' if yn(doColor) then out = out .. '<' .. (args.tag or "span") .. ' style="background-color:rgba(' .. rgbColor(color) .. '); padding:4px; color:' .. (colorIntensity < 0.5 and "white" or "black") .. '; '	elseif args.style then		out = out .. '<' .. (args.tag or "span") .. ' style="' else out = out .. '<' .. (args.tag or "span") end if args.style then out = out .. args.style out = out .. '" '	elseif yn(doColor) then		out = out .. '" ' end out = out .. (args.tagProps ~= nil and args.tagProps or "") out = out .. ">"	if yn(link) then out = out .. '' .. data[scale].name .. ".id .. "|"	end if yn(doColor) then out = out .. '' end out = out .. listIntensitiesFromScale(scale, intensities, labelScale, scale2) if yn(doColor) then out = out .. ' '	end if yn(link) then out = out .. "]]"	end if (scale2) then out = out .. " ("		if yn(link) then			out = out .. '' .. data[scale2].name .. ".id .. "|"		end		if yn(doColor) then			out = out .. ''		end		out = out .. listIntensitiesFromScale(scale2, intensities2, true, true)		if yn(doColor) then			out = out .. ' '		end		if yn(link) then			out = out .. "]]"		end		out = out .. ")" end out = out .. ''	return mw.getCurrentFrame:preprocess(out) end

p._format = function(args) if args["format"] == "wikitable" then return p.formatInWikitable(args) else return p.formatTag(args) end end

p._getScaleName = function(args) local scale = string.lower(args.scale or args[1] or error(message("noScaleShortCode"))) if data[scale] == nil then error(message("invalidScale", {scale})) end local out = '' if yn(args.link or true) then out = out .. 	end	out = out .. data[scale].name	if yn(args.link or true) then		out = out ..  end return out end

-- uses binary search to convert a peak ground acceleration to a seismic intensity function convert(pga, ranks, ranksSorted, left, right) left = left ~= nil and left or 0 right = right ~= nil and right or #ranksSorted index = math.floor((left + right) / 2) local lower = ranks[ranksSorted[index + 1]].pga local upper = ranksSorted[index + 2] and ranks[ranksSorted[index + 2]].pga or math.huge if (pga >= upper) then return convert(pga, ranks, ranksSorted, index, right) elseif (pga < lower) then return convert(pga, ranks, ranksSorted, left, index) else return ranksSorted[index + 1] end end

p._convert = function(args) local scale = string.lower(args.scale or args[1] or error(message("noScaleShortCode"))) if data[scale] == nil then error(message("invalidScale", {scale})) end local ranksSorted = {} for k,v in ipairs(data["mmi"].ranksSorted) do ranksSorted[k] = v end return convert(tonumber(args.pga or args[2]), data[scale].ranks, ranksSorted) end

p.convert1 = convert --debugging

p._list = function(args) local out = mw.html.create('ul') for k,v in pairs(data) do		local list = out:tag('li') list:wikitext(' : ' .. v.name .. '') local tb = list:tag('table'):addClass("wikitable") tb :tag("tr") :tag("th"):wikitext("Seismic intensity"):done :tag("th"):wikitext("Display"):done :done for l,w in pairs(v.order) do tb:tag('tr'):wikitext(' ' .. p.format({k, w, tag = "td"})):done end list:done end out:allDone return tostring(out) end

-- make each scale invokable for k,v in pairs(data) do if p["_" .. k] ~= nil then error(message("scaleNameInvalid", k)) end p["_" .. k] = function(args) args["scale"] = k		args["intensity"] = args["intensity"] or args[1] or nil args["scale2"] = args["scale2"] or args[2] or nil args["intensity2"] = args["intensity2"] or args[3] or nil if args["format"] == "wikitable" then return p.formatInWikitable(args) else return p.formatTag(args) end end end

-- make all functions that begin with _ invokable local q = mw.clone(p) for k,v in pairs(q) do	if mw.ustring.sub(k, 1, 1) == "_" then p[mw.ustring.sub(k, 2, #k)] = makeInvokeFunc(k) end end

return p