Module:Infobox MOS

Revision as of 21:08, 2 April 2023 by Inthar (talk | contribs) (maintenance)
Module documentation[view] [edit] [history] [purge]
This module should not be invoked directly; use its corresponding template instead: Template:Infobox MOS.

This module generates an infobox providing information about a given moment of symmetry (MOS) scale.

Introspection summary for Module:Infobox MOS 
Functions provided (2)
Line Function Params
86 infobox_MOS (invokable) (frame)
285 build (title, structure_entries, et_entries, adjacent_links)
Lua modules required (6)
Variable Module Functions used
ET Module:ET backslash_display
new
backslash_modifier
cents
as_string
infobox Module:Infobox dependency not used
i Module:Interval dependency not used
MOS Module:MOS parse
brightest_mode
bright_gen
as_string
rat Module:Rational new
as_ratio
eq
u Module:Utils dependency not used

No function descriptions were provided. The Lua code may have further information.


local p = {}
local i = require('Module:Interval')
local u = require('Module:Utils')
local rat = require('Module:Rational')
local MOS = require('Module:MOS')
local ET = require('Module:ET')
local infobox = require('Module:Infobox')

local tamnams_name = { -- Only mosses with 2/1-equave names in TAMNAMS
	['1L 1s'] = 'monowood',
	['2L 2s'] = 'biwood',
	['1L 5s'] = 'antimachinoid',
	['2L 4s'] = 'malic',
	['3L 3s'] = 'triwood',
	['4L 2s'] = 'citric',
	['5L 1s'] = 'machinoid',
	['1L 6s'] = 'onyx',
	['2L 5s'] = 'antidiatonic',
	['3L 4s'] = 'mosh',
	['4L 3s'] = 'smitonic',
	['5L 2s'] = 'diatonic',
	['6L 1s'] = 'arch(a)eotonic',
	['1L 7s'] = 'antipine',
	['2L 6s'] = 'subaric',
	['3L 5s'] = 'checkertonic',
	['4L 4s'] = 'tetrawood; diminished',
	['5L 3s'] = 'oneirotonic',
	['6L 2s'] = 'ekic',
	['7L 1s'] = 'pine',
	['1L 8s'] = 'antisubneutralic',
	['2L 7s'] = 'balzano',
	['3L 6s'] = 'tcherepnin',
	['4L 5s'] = 'gramitonic',
	['5L 4s'] = 'semiquartal',
	['6L 3s'] = 'hyrulic',
	['7L 2s'] = 'armotonic; superdiatonic',
	['8L 1s'] = 'subneutralic',
	['1L 9s'] = 'antisinaic',
	['2L 8s'] = 'jaric',
	['3L 7s'] = 'sephiroid',
	['4L 6s'] = 'lime',
	['5L 5s'] = 'pentawood',
	['6L 4s'] = 'lemon',
	['7L 3s'] = 'dicoid',
	['8L 2s'] = 'taric',
	['9L 1s'] = 'sinatonic'
}

local common_suffix = {
	['3/2'] = 'f',
	['2'] = 'o',
	['2/1'] = 'o',
	['3'] = 't',
	['3/1'] = 't',
}

local common_ratio = {
	['f'] = rat.new(3, 2),
	['o'] = 2,
	['t'] = 3,
}

function gcd(x, y)
	if x < y then
		x, y = y, x
	end
	while y > 0 do
		x, y = y, x % y
	end
	return x
end

function display_range (arg1, arg2, arg3, arg4) --If arg1 < arg2, then display "arg3 to arg4"; otherwise display "arg4 to arg3".
	if arg1 < arg2 then
		return arg3 .. ' to ' .. arg4
	else 
		return arg4 .. ' to ' .. arg3
	end
end
	
function round(num, numDecimalPlaces)
  local mult = 10^(numDecimalPlaces or 0)
  return math.floor(num * mult + 0.5) / mult
end

function p.infobox_MOS(frame)
	-- debug mode
	local debug_mode = frame.args['debug'] ~= nil
	local categories = ''
	
	local tuning = frame.args['Tuning']
	local mos = MOS.parse(tuning) or MOS.parse('5L 2s')
	-- category of the main article
	categories = categories .. '[[Category:' .. tuning .. '| ]]'
	
	local equave = mos.equave
	local equave_link = ' (' .. rat.as_ratio(equave)  .. '-equivalent)'
	local equave_disp = '<' .. rat.as_ratio(equave) .. '>'
	if rat.eq(equave, 2) then
		equave_link = ''
		equave_disp = ''
	end
	local nL = mos.nL
	local ns = mos.ns
	
	local has_prev_y = (ns > 1)
	local has_prev_x = (nL > 1)
	local prev_L, next_L, prev_s,next_s, prev_L_prev_s, prev_L_next_s, next_L_prev_s, next_L_next_s = '', '', '', '', '', '', '', ''
	next_s = '[[' .. nL .. 'L ' .. (ns + 1) .. 's' .. equave_link .. '|↓' .. nL .. 'L ' .. (ns + 1) .. 's' .. equave_disp .. ']]'
	next_L = '[[' .. (nL + 1) .. 'L ' .. ns .. 's' .. equave_link .. '|' .. (nL + 1) .. 'L ' .. ns .. 's' .. equave_disp .. '→]]'
	next_L_next_s = '[[' .. (nL + 1) .. 'L ' .. (ns + 1) .. 's' .. equave_link .. '|' .. (nL + 1) .. 'L ' .. (ns + 1) .. 's' .. equave_disp .. '↘]]'
	if has_prev_y then
		prev_s = '[[' .. nL .. 'L ' .. (ns - 1) .. 's' .. equave_link .. '|↑' .. nL .. 'L ' .. (ns - 1) .. 's' .. equave_disp .. ']]'
		next_L_prev_s = '[[' .. (nL + 1) .. 'L ' .. (ns - 1) .. 's' .. equave_link .. '|' .. (nL + 1) .. 'L ' .. (ns - 1) .. 's' .. equave_disp .. '↗]]'
	end
	if has_prev_x then
		prev_L = '[[' .. (nL - 1) .. 'L ' .. ns .. 's' .. equave_link .. '|←' .. (nL - 1) .. 'L ' .. ns .. 's' .. equave_disp .. ']]'
		prev_L_next_s = '[[' .. (nL - 1) .. 'L ' .. (ns + 1) .. 's' .. equave_link .. '|↙' .. (nL - 1) .. 'L ' .. (ns + 1) .. 's' .. equave_disp .. ']]'
	end
	if has_prev_y and has_prev_x then
		prev_L_prev_s = '[[' .. (nL - 1) .. 'L ' .. (ns - 1) .. 's' .. equave_link .. '|↖' .. (nL - 1) .. 'L ' .. (ns - 1) .. 's' .. equave_disp .. ']]'
	end
	
	local adjacent_links = {
		[1]=prev_L_prev_s, 
		[2]=prev_s, 
		[3]=next_L_prev_s, 
		[4]=prev_L, 
		[5]=next_L, 
		[6]=prev_L_next_s, 
		[7]=next_s, 
		[8]=next_L_next_s
	}
	
	local period = rat.as_ratio(equave)
	d = gcd(nL, ns)
	if d > 1 then
		period = ET.backslash_display(ET.new(d, equave), 1)
	end
	local pattern = MOS.brightest_mode(mos)
	local collapsed_et = ET.new(nL, equave)
	local abstract_bright_gen = MOS.bright_gen(mos)
	local collapsed_bright_steps = abstract_bright_gen['L']
	local collapsed_dark_steps = nL/d - collapsed_bright_steps
	local equalized_et = ET.new(nL + ns, equave)
	local equalized_bright_steps = abstract_bright_gen['L'] + abstract_bright_gen['s']
	local equalized_dark_steps = (nL + ns)/d - equalized_bright_steps
	
	local structure_data = {}
	
	table.insert(structure_data, {
		'Brightest mode',
		pattern
	})
	table.insert(structure_data, {
		'Period',
		period
	})
	table.insert(structure_data, {
		'Range for [[bright]] [[generator]]',
		display_range(collapsed_bright_steps/collapsed_et.size, equalized_bright_steps/equalized_et.size, 
			collapsed_bright_steps .. ET.backslash_modifier(collapsed_et) .. ' (' .. round(ET.cents(collapsed_et, collapsed_bright_steps), 1) .. '¢)', 
			equalized_bright_steps .. ET.backslash_modifier(equalized_et) .. ' (' .. round(ET.cents(equalized_et, equalized_bright_steps), 1) .. '¢)'
		)
	})
	table.insert(structure_data, {
		'Range for [[dark]] [[generator]]',
		display_range(collapsed_dark_steps/collapsed_et.size, equalized_dark_steps/equalized_et.size, 
			collapsed_dark_steps .. ET.backslash_modifier(collapsed_et) .. ' (' .. round(ET.cents(collapsed_et, collapsed_dark_steps), 1) .. '¢)', 
			equalized_dark_steps .. ET.backslash_modifier(equalized_et) .. ' (' .. round(ET.cents(equalized_et, equalized_dark_steps), 1) .. '¢)'
		)
	})
	if nL == ns then
		parent_mos_link = 'none'
	else 
		parent_mos_link = '[[' .. math.min(nL, ns) .. 'L ' .. math.max(nL, ns)-math.min(nL, ns) .. 's' .. equave_link .. '|'  
		.. math.min(nL, ns) .. 'L ' .. math.max(nL, ns)-math.min(nL, ns) .. 's' .. equave_disp .. ']]'
	end
	table.insert(structure_data, {
		'Parent MOS',
		parent_mos_link
	})
	table.insert(structure_data, {
		'[[Operations on MOSes#Sistering|Sister MOS]]',
		'[[' .. ns .. 'L ' .. nL .. 's' .. equave_link .. '|' .. ns .. 'L ' .. nL .. 's' .. equave_disp .. ']]'
	})
	table.insert(structure_data, {
		'Daughter MOSes',
		'[[' .. nL + ns .. 'L ' .. nL .. 's' .. equave_link .. '|'  
		.. nL + ns .. 'L ' .. nL .. 's' .. equave_disp .. ']], [[' 
		.. nL .. 'L ' .. nL + ns .. 's' .. equave_link.. '|' .. nL .. 'L ' .. nL + ns .. 's' .. equave_disp .. ']]'
	})
	local tamnams = tamnams_name[MOS.as_string(mos)]
	if tamnams ~= nil then
		table.insert(structure_data, {
			'[[TAMNAMS#Mos pattern names|TAMNAMS name]]',
			tamnams
		})
	end
	local other_names = frame.args['Other names']
	if other_names ~= nil then
		table.insert(structure_data, {
			'Other names', other_names
		})
	end
	-- Compute et generators by taking mediants from collapsed and equalized generators
	
	local supersoft_et = ET.new(1*collapsed_et.size + 3*equalized_et.size, equave, nil)
	local supersoft_bright_steps = 1*collapsed_bright_steps + 3*equalized_bright_steps
	local supersoft_gen = ET.backslash_display(supersoft_et, supersoft_bright_steps)
	local supersoft_gen_cents = round(ET.cents(supersoft_et, supersoft_bright_steps), 1)
	
	local soft_et = ET.new(1*collapsed_et.size + 2*equalized_et.size, equave, nil)
	local soft_bright_steps =  1*collapsed_bright_steps + 2*equalized_bright_steps
	local soft_gen = ET.backslash_display(soft_et, soft_bright_steps)
	local soft_gen_cents = round(ET.cents(soft_et, soft_bright_steps), 1)
	
	local semisoft_et = ET.new(2*collapsed_et.size + 3*equalized_et.size, equave, nil)
	local semisoft_bright_steps = 2*collapsed_bright_steps + 3*equalized_bright_steps
	local semisoft_gen = ET.backslash_display(semisoft_et, semisoft_bright_steps)
	local semisoft_gen_cents = round(ET.cents(semisoft_et, semisoft_bright_steps), 1)
	
	local basic_et = ET.new(1*collapsed_et.size + 1*equalized_et.size, equave, nil)
	local basic_bright_steps = 1*collapsed_bright_steps + 1*equalized_bright_steps
	local basic_gen = ET.backslash_display(basic_et, basic_bright_steps)
	local basic_gen_cents = round(ET.cents(basic_et, basic_bright_steps), 1)
	
	local semihard_et = ET.new(3*collapsed_et.size + 2*equalized_et.size, equave, nil)
	local semihard_bright_steps = 3*collapsed_bright_steps + 2*equalized_bright_steps
	local semihard_gen = ET.backslash_display(semihard_et, semihard_bright_steps)
	local semihard_gen_cents = round(ET.cents(semihard_et, semihard_bright_steps), 1)
	
	local hard_et = ET.new(2*collapsed_et.size + 1*equalized_et.size, equave, nil)
	local hard_bright_steps = 2*collapsed_bright_steps + 1*equalized_bright_steps
	local hard_gen = ET.backslash_display(hard_et, hard_bright_steps)
	local hard_gen_cents = round(ET.cents(hard_et, hard_bright_steps), 1)
	
	local superhard_et = ET.new(3*collapsed_et.size + 1*equalized_et.size, equave, nil)
	local superhard_bright_steps = 3*collapsed_bright_steps + 1*equalized_bright_steps
	local superhard_gen = ET.backslash_display(superhard_et, superhard_bright_steps)
	local superhard_gen_cents = round(ET.cents(superhard_et, superhard_bright_steps), 1)
	
	local et_data = {}
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Supersoft]] (L:s = 4:3)',
		'[[' .. ET.as_string(supersoft_et) .. '|' .. supersoft_gen .. ']] (' .. supersoft_gen_cents .. '¢)'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Soft]] (L:s = 3:2)',
		'[[' .. ET.as_string(soft_et) .. '|' .. soft_gen .. ']] (' .. soft_gen_cents .. '¢)'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Semisoft]] (L:s = 5:3)',
		'[[' .. ET.as_string(semisoft_et) .. '|' .. semisoft_gen .. ']] (' .. semisoft_gen_cents .. '¢)'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Basic]] (L:s = 2:1)',
		'[[' .. ET.as_string(basic_et) .. '|' .. basic_gen .. ']] (' .. basic_gen_cents .. '¢)'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Semihard]] (L:s = 5:2)',
		'[[' .. ET.as_string(semihard_et) .. '|' .. semihard_gen .. ']] (' .. semihard_gen_cents .. '¢)'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Hard]] (L:s = 3:1)',
		'[[' .. ET.as_string(hard_et) .. '|' .. hard_gen .. ']] (' .. hard_gen_cents .. '¢)'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Superhard]] (L:s = 4:1)',
		'[[' .. ET.as_string(superhard_et) .. '|' .. superhard_gen .. ']] (' .. superhard_gen_cents .. '¢)'
	})
	local title = nL .. 'L ' .. ns .. 's' .. equave_disp
	result = p.build(
		title,
		structure_data,
		et_data,
		adjacent_links
	)
	if not debug_mode then
		result = result .. categories
	end
	return result
end

function p.build(title, structure_entries, et_entries, adjacent_links)
	local s = '<div style="\n' ..
		'border: 1px solid #999;\n' ..
		'margin: 0;\n' ..
		'margin-left: 1em;\n' ..
		'margin-bottom: 0.5em;\n' ..
		'padding: 0.5em;\n' ..
		'background-color: #f0f0f0;\n' ..
		'min-width: 15em;\n' ..
		'float: right;\n' ..
		'max-width: 100%;\n' ..
		'overflow: auto;\n' ..
		'">\n' ..
		'{| width="100%" style="border-collapse: collapse;"\n' ..
		'|+ style="font-weight: bold; text-align: center;" | '
	s = s .. '<table style="width: 100%; margin: 0"><tr>'
		.. '<td style="width: 15%; text-align: left; white-space: nowrap; font-size: smaller">'
		.. adjacent_links[1]
		.. '</td>'
		.. '<td style="\n' 
		.. 'width: 50%; padding-left: 1em; padding-right: 1em; text-align: center; font-size: smaller">'
		.. adjacent_links[2]
		.. '\n</td><td style="width: 15%; text-align: right; white-space: nowrap; font-size: smaller">'
		.. adjacent_links[3]
		.. '</td>' 
		.. '\n<tr>'
		.. '<td style="width: 15%; text-align: left; white-space: nowrap; font-size: smaller">'
		.. adjacent_links[4]
		.. '</td>'
		.. '<td style="width: 50%; padding-left: 1em; padding-right: 1em; text-align: center">'
		.. title
		.. '</td>'
		.. '<td style="width: 15%; text-align: right; white-space: nowrap; font-size: smaller">'
		.. adjacent_links[5]
		.. '</td>'
		.. '</tr>'
		.. '<tr>'
		.. '<td style="width: 15%; text-align: left; white-space: nowrap; font-size: smaller">'
		.. adjacent_links[6]
		.. '</td><td style="\n' 
		.. 'width: 50%; padding-left: 1em; padding-right: 1em; text-align: center; font-size: smaller">'
		.. adjacent_links[7]
		.. '\n</td>'
		.. '<td style="width: 15%; text-align: right; white-space: nowrap; font-size: smaller">'
		.. adjacent_links[8]
		.. '</td>'
		.. '</tr>'
		..  '</table>'
	s = s .. '\n'
	for i, entry in ipairs(structure_entries) do
		if #entry > 1 then
			local caption = entry[1]
			local text = entry[2]
			s = s .. '|-\n' ..
				'| style="text-align:right; padding-right: 0.25em" | ' .. caption .. '\n' ..
				'| style="background-color: white; padding-left: 0.25em; font-weight: bold" | ' .. text .. '\n'
		elseif #entry == 1 then
			local text = entry[1]
			s = s .. '|-\n'
				.. '| colspan="2" style="text-align: center;" | ' .. text .. '\n'
		end
	end
	s = s .. '|-\n'
	    .. '|colspan="2" style="text-align:center;"| <b>Equal tunings</b>\n'
	for i, entry in ipairs(et_entries) do
		if #entry > 1 then
			local caption = entry[1]
			local text = entry[2]
			s = s .. '|-\n' ..
				'| style="text-align:right; padding-right: 0.25em" | ' .. caption .. '\n' ..
				'| style="background-color: white; padding-left: 0.25em; font-weight: bold" | ' .. text .. '\n'
		elseif #entry == 1 then
			local text = entry[1]
			s = s .. '|-\n'
				.. '| colspan="2" style="text-align: center;" | ' .. text .. '\n'
		end
	end
	s = s .. '|}</div>'
	return s
end

return p