|
|
| (One intermediate revision by the same user not shown) |
| Line 1: |
Line 1: |
| --- This is the Shindo module. Named after the Japanese term used for classifying earthquakes {{lang|ja|{{ruby|[[wikt:震度|震度]]|しんど}}}}, this module provides utility for seismic intensity scales.
| |
| --
| |
| -- Seismic intensity data generated on [[Module:Shindo/data]]. Messages on [[Module:Shindo/messages]].
| |
| -- @module shindo
| |
| -- @alias p
| |
| -- @require Module:Arguments
| |
| -- @require Module:MakeInvokeFunc
| |
| -- @require Module:Message
| |
| -- @require Module:Yesno
| |
| -- @release beta
| |
| --
| |
|
| |
|
| |
| local p = {} | | 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")
| |
|
| |
| --- Gets the grayscale value of a specific color
| |
| -- @function getValueOfColor
| |
| -- @param {table} tbl table for colors
| |
| -- @param {number} tbl[1] red value
| |
| -- @param {number} tbl[2] green value
| |
| -- @param {number} tbl[3] blue value
| |
| -- @return {number} Decimal value of the color.
| |
| local function getValueOfColor(tbl)
| |
| return (tbl[1] + tbl[2] + tbl[3]) / 3 / 255
| |
| end
| |
|
| |
| --- Gets the color as a comma-separated value for CSS
| |
| -- @function rgbColor
| |
| -- @todo compute alpha transparency for dark mode, etc.
| |
| -- @param {table} tbl table for colors
| |
| -- @param {number} tbl[1] red value
| |
| -- @param {number} tbl[2] green value
| |
| -- @param {number} tbl[3] blue value
| |
| -- @return {string} The color in the format red, green, blue
| |
| local function rgbColor(tbl)
| |
| return tbl[1] .. (tbl[2] and ", " .. tbl[2] .. (tbl[3] and ", " .. tbl[3] or "") or "")
| |
| end
| |
|
| |
| --- Gets the average of multiple colors
| |
| -- @function averageColor
| |
| -- @param {table} tbl table of multiple colors
| |
| -- @return {number} Decimal value of the color.
| |
| 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
| |
|
| |
| --- Gets all the intensity values from a scale
| |
| -- @function listIntensitiesFromScale
| |
| -- @param {string} scale First scale name
| |
| -- @param {string} intensities Table of intensity values
| |
| -- @param {boolean} labelScale Whether to label a scale
| |
| -- @param {string} scale Second scale name
| |
| -- @return {string} List of intensities
| |
| 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
| |
|
| |
| --- Gets the inline CSS for a particular scale's intensity color
| |
| -- @function p._color
| |
| -- @param {table} args frame arguments
| |
| -- @param {string} args.scale The name of the scale
| |
| -- @param {string} args.intensity The intensity of the scale
| |
| -- @return {string} Preprocessed text output
| |
| 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
| |
|
| |
| --- Gets the format of the scale as a wikitable
| |
| -- @function p._formatInWikitable
| |
| -- @param {table} args frame arguments
| |
| -- @param {string} args.scale The name of the scale
| |
| -- @param {string} args.intensity The intensity of the scale
| |
| -- @param {string} args.tagProps additional properties for the wikitable row
| |
| -- @param {boolean} args.header if the formatting is done as a header
| |
| -- @param {boolean} args.link whether to link to the scale page
| |
| -- @param {boolean} args.labelScale whether to include the name of the scale
| |
| -- @return {string} Preprocessed text output
| |
| 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 .. '[[' .. data[scale].name .. "#" .. data[scale].id_prefix .. data[scale].ranks[intensity].id .. "|"
| |
| end
| |
| if yn(doColor) then
| |
| out = out .. '<span style=\"color:' .. (colorIntensity < 0.5 and "white" or "black") .. ';">'
| |
| end
| |
| out = out .. listIntensitiesFromScale(scale, intensities, labelScale, false)
| |
| if yn(doColor) then
| |
| out = out .. '</span>'
| |
| end
| |
| if yn(link) then
| |
| out = out .. "]]"
| |
| end
| |
| return out
| |
| end
| |
|
| |
| --- Gets the format of the scale as a tag
| |
| -- @function p._formatTag
| |
| -- @param {table} args frame arguments
| |
| -- @param {string} args.scale The name of the scale
| |
| -- @param {string} args.scale2 The name of a second scale
| |
| -- @param {string} args.intensity The intensity of the scale
| |
| -- @param {string} args.intensity2 The intensity for the second scale
| |
| -- @param {string} args.tag Tag name
| |
| -- @param {string} args.style styling for the tag
| |
| -- @param {string} args.tagProps additional properties for the tag
| |
| -- @param {boolean} args.color Whether to color the entry
| |
| -- @param {boolean} args.link whether to link to the scale page
| |
| -- @return {string} Preprocessed text output
| |
| 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 .. "#" .. data[scale].id_prefix .. data[scale].ranks[intensities[1]].id .. "|"
| |
| end
| |
| if yn(doColor) then
| |
| out = out .. '<span style=\"color:' .. (colorIntensity < 0.5 and "white" or "black") .. ';">'
| |
| end
| |
| out = out .. listIntensitiesFromScale(scale, intensities, labelScale, scale2)
| |
| if yn(doColor) then
| |
| out = out .. '</span>'
| |
| end
| |
| if yn(link) then
| |
| out = out .. "]]"
| |
| end
| |
| if (scale2) then
| |
| out = out .. " ("
| |
| if yn(link) then
| |
| out = out .. '[[' .. data[scale2].name .. "#" .. data[scale2].id_prefix .. data[scale2].ranks[intensities2[1]].id .. "|"
| |
| end
| |
| if yn(doColor) then
| |
| out = out .. '<span style=\"color:' .. (colorIntensity < 0.5 and "white" or "black") .. ';">'
| |
| end
| |
| out = out .. listIntensitiesFromScale(scale2, intensities2, true, true)
| |
| if yn(doColor) then
| |
| out = out .. '</span>'
| |
| end
| |
| if yn(link) then
| |
| out = out .. "]]"
| |
| end
| |
| out = out .. ")"
| |
| end
| |
| out = out .. '</' .. (args.tag or "span") .. '>'
| |
| return mw.getCurrentFrame():preprocess(out)
| |
| end
| |
|
| |
|
| p._format = function(args)
| | local function render(frame) |
| if args["format"] == "wikitable" then | | local args = frame and frame.args or {} |
| return p.formatInWikitable(args)
| | if args[1] and tostring(args[1]) ~= '' then |
| else
| | return tostring(args[1]) |
| return p.formatTag(args) | |
| end | | end |
| end
| | if args.value and tostring(args.value) ~= '' then |
| | | return tostring(args.value) |
| 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 .. '[[' .. data[scale].name .. '|' | |
| end
| |
| out = out .. data[scale].name
| |
| if yn(args.link or true) then
| |
| out = out .. ']]'
| |
| end | | end |
| return out
| | if args.intensity and tostring(args.intensity) ~= '' then |
| end
| | return tostring(args.intensity) |
| | |
| -- 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('<code>' .. k .. '</code>: [[' .. v.name .. '|' .. 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('<td><code>' .. w .. '</code></td> ' .. p.format({k, w, tag = "td"})):done()
| |
| end
| |
| list:done()
| |
| end | | end |
| out:allDone()
| | return '' |
| return tostring(out) | |
| end | | end |
|
| |
|
| -- make each scale invokable
| | setmetatable(p, { |
| for k,v in pairs(data) do
| | __index = function(t, k) |
| if p["_" .. k] ~= nil then error(message("scaleNameInvalid", k)) end
| | local f = function(frame) |
| p["_" .. k] = function(args) | | return render(frame) |
| 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 |
| | rawset(t, k, f) |
| | return f |
| end | | end |
| end
| | }) |
|
| |
|
| -- make all functions that begin with _ invokable
| | p.main = render |
| 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 | | return p |