Module:Sandbox/Spacing form/Point
This module generates glyphs for Hvtari, an upcoming constructed language project. A list of "pivots" define the shape and pronunciation of each Hvtari morpheme. Because Hvtari script is generative (containing complex information such as conjugation), uploading an image for each morpheme is not feasible. Therefore, we decided to generate Hvtari script dynamically. We also want to organize the project on a wiki, so testing is under way here.
Currently we've settled on SVG. Relevant code will arrive soon.
--[[
Preview with "publictestwiki.com/wiki/User:Spacing form/sandbox"
]]
local pt = {}
pt._lenny = function(arr)
local len = 0
while arr[len+1] ~= nil do
len = len + 1
end
return len
end
-- Using data from ./pivot
pt._preparePivots = function(dict_raw_values)
local dict_pivots = {}
for k in pairs(dict_raw_values) do
local flat_seq = dict_raw_values[k]
local pivots = {}
local i = 1 -- i_pivot
--mw.log(pt._lenny(flat_seq))
while i < pt._lenny(flat_seq)/2 do
local pivot = {x = flat_seq[i*2-1], y = flat_seq[i*2]}
pivots[i] = pivot
i = i + 1
end
dict_pivots[k] = pivots
end
return dict_pivots
end
pt.load = function()
local pivots = pt._preparePivots(mw.loadData("Module:Sandbox/Spacing form/Point/pivots"))
return pivots
end
-- Display a glyph for a syllable in SVG format
pt.displayGlyph = function(frame)
local pivots = pt._preparePivots(mw.loadData("Module:Sandbox/Spacing form/Point/pivots"))
-- data in the form of {ba = {{x,y},{x,y},...}, be = {...} }
local sta = frame.args[1]
if pivots[sta] == nil then
return("[ERROR: syllable not found]")
end
local glyph = mw.html.create("svg")
glyph:attr("xmlns", "https://www.w3.org/2000/svg")
glyph:attr("width", "100")
glyph:attr("height", "100")
glyph:css("border", "1px solid black")
local coords = pivots[sta]
local line = glyph:tag("path", args.selfClosing)
local str_path = mw.ustring.format("M %d %d ", coords[1]["x"], coords[1]["y"])
for i = 1, #coords-1 do
str_path = str_path .. mw.ustring.format("M %d %d ", coords[i]["x"], coords[i]["y"])
end
line:attr("d", str_path)
return tostring(glyph)
end
-- A fluent HTML interface
pt.printDiv = function(frame)
local div = mw.html.create("div")
div:wikitext("''Don't'' reinvent the wheel.")
div:newline()
div:newline()
div:wikitext("<small>Exceptions can be made.</small>")
div:css("border", "1px solid black")
return tostring(div)
end
-- Take two strings and display them in two boxes
pt.printParagraphs = function(frame) -- use ... for variable number of paragraphs
local args = frame.args
local div = mw.html.create("div")
local p1 = div:tag("p")
p1:addClass("kename")
p1:wikitext(args[1])
local p2 = div:tag("p")
p2:addClass("larame")
p2:wikitext(args[2])
-- call p2:allDone() to return to root node
return tostring(div)
end
-- Repeat a string n times and display them with decreasing font size
pt.printRepeat = function(frame)
local args = frame.args
local s = args[1]
local n = tonumber(args[2])
local span_root = mw.html.create("span")
for i = 1, n do
local span = span_root:tag("span")
local font_size = tostring(16+2*n-2*i) .. "px"
span:css("font-size", font_size)
span:wikitext(s)
end
return tostring(span_root)
end
-- Example of loading and using data from ./data
pt.findNearest = function(frame)
local args = frame.args
local coords = mw.loadData("Module:Sandbox/Spacing form/Point/data") -- loaded only once
local pt = { tonumber(args[1]), tonumber(args[2]) }
local nearest_distance
local nearest_name
for name in pairs(coords) do
local pt_goal = coords[name]
local distance = ((pt[1]-pt_goal[1])^2 + (pt[2]-pt_goal[2])^2) ^ (1/2)
if nearest_distance == nil or distance < nearest_distance then
nearest_distance = distance
nearest_name = name
end
end
local ret = mw.ustring.format("Closest Ndoto is N. %s, %.1fm away.", nearest_name, nearest_distance)
return ret
end
-- Use mw.ustring, not string
-- Takes three arguments `name`, `x`, and `y` and returns a string
pt.printRepr = function(frame)
local params = {"x", "y", "name"}
local args = pt._getArgs(frame.args, params)
local ret = mw.ustring.format("(%d,%d) is %s's latest position\n", args.x, args.y, args.name)
return ret
end
-- Helper function that populates the argument list (edited)
pt._getArgs = function(frame_args, params)
local new_args = {}
for k, v in ipairs(frame_args) do
new_args[params[k]] = frame_args[k]
end
for k in pairs(frame_args) do
new_args[k] = frame_args[k]
end
return new_args
end
return pt