Module:Rank-n scale
Jump to navigation
Jump to search
Documentation transcluded from /doc
Note: Do not invoke this module directly; use the corresponding template instead: Template:Rank-n scale.
Documentation transcluded from /doc
Note: Do not invoke this module directly; use the corresponding template instead: Template:Rank-n scale.
local infobox = require('Module:Infobox')
local p = {}
local function rotate_word(str, n) -- rotate word s by n steps
return string.sub(str, n+1, #str) .. string.sub(str, 1, n)
end
local function rotate_word_full(str)
local full = {}
for i = 1, #str do
full[i] = rotate_word(str, i-1)
end
return full
end
local function bright_dark_chiral(str)
local full = rotate_word_full(str)
local bright, dark = str, str
for i = 2, #str do
if bright > full[i] then
bright = full[i]
end
if dark < full[i] then
dark = full[i]
end
end
local bright2, dark2 = string.reverse(str), string.reverse(str)
for i = 2, #str do
local rev = string.reverse(full[i])
if bright2 > rev then
bright2 = rev
end
if dark2 < rev then
dark2 = rev
end
end
if bright2 == bright then
return {["blh"] = bright, ["brh"] = bright, ["dlh"] = dark, ["drh"] = dark, ["chiral"] = "no"}
elseif bright2 < bright then
return {["blh"] = bright, ["brh"] = bright2, ["dlh"] = dark, ["drh"] = dark2, ["chiral"] = "yes"}
else
return {["blh"] = bright2, ["brh"] = bright, ["dlh"] = dark2, ["drh"] = dark, ["chiral"] = "yes"}
end
end
local function table_length(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
local function abelianize(str) -- sorts string by letter. from rosetta code because I'm lazy.
local t = {} str:gsub("(%S)", function(c) t[#t+1]=c end) -- use "(.)" as pattern to preserve whitespace
table.sort(t, function(a,b) return a<b end) -- implicitly
return table.concat(t)
end
local function list_step_varieties(str)
local strstr = str .. str
local step_vars = {}
for i = 1, math.floor(#str/2) do
local r = {}
for j = 1, #str do
local u = abelianize(string.sub(strstr, j, j+i-1))
r[u] = true
end
step_vars[i] = r
end
return step_vars
end
local function max_variety(str)
local lsv = list_step_varieties(str)
local max_var = 0
local is_strict = "yes"
for i = 1, math.floor(#str/2) do
i_step_var = table_length(lsv[i])
if i_step_var > max_var then
if max_var ~= 0 then
is_strict = "no"
end
max_var = i_step_var
end
end
return {["max variety"] = max_var, ["is strict?"] = is_strict}
end
function p.create_infobox(frame)
local scale = frame.args["scale"]
local mv = max_variety(scale)
local bdc = bright_dark_chiral(scale)
local brightest_mode
local darkest_mode
if bdc["chiral"] == "yes" then
brightest_mode = {"Brightest mode", "LH " .. bdc["blh"] .. "\nRH ".. bdc["brh"]}
darkest_mode = {"Darkest mode", "LH " .. bdc["dlh"] .. "\nRH ".. bdc["drh"]}
else
brightest_mode = {"Brightest mode", bdc["brh"]}
darkest_mode = {"Darkest mode", bdc["drh"]}
end
local entries = {
{"Scale structure"},
{"Step pattern"},
brightest_mode,
darkest_mode,
{"Is chiral?", bdc["chiral"]},
{"Maximum variety", mv["max variety"]},
{"Has strict variety?", mv["is strict?"]},
}
return infobox.build_multilink(scale, entries)
end
-- {"Mean variety", " "}
-- {"Is generator-offset?", " "},
-- {"Tuning ranges"},
-- {"Parent scales"},
-- {"Descendant scales"},
return p