Module:Infobox MOS

From Xenharmonic Wiki
Revision as of 18:32, 31 March 2023 by Inthar (talk | contribs)
Jump to navigation Jump to search
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
10 infobox_MOS (invokable) (frame)
154 build (title, entries, prev_x, next_x, prev_y, next_y)
Lua modules required (7)
Variable Module Functions used
ET Module:ET new
backslash_ratio
infobox Module:Infobox dependency not used
i Module:Interval dependency not used
l Module:Limits dependency not used
MOS Module:MOS parse
rat Module:Rational 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 l = require('Module:Limits')
local MOS = require('Module:MOS')
local ET = require('Module:ET')
local infobox = require('Module:Infobox')

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')
	assert(mos, "failed to parse variable mos")
	-- category of the main article
	categories = categories .. '[[Category:' .. tuning .. '| ]]'
	
	local equave_link = ' (' .. mos.equave .. '-equivalent)'
	local equave_disp = ' <' .. mos.equave .. '>'
	if rat.eq(mos.equave, 2) then
		equave_link = ''
		equave_disp = ''
	end
	
	local prev_L, prev_s = '', ''
	if mos.nL > 1 then
		prev_L = '[[' .. (mos.nL - 1) .. 'L ' .. mos.ns .. 's' .. equave_link .. '|← ' .. (mos.nL - 1) .. 'L' .. mos.ns .. 's' .. equave_disp .. ']]'
	end
	local next_L = '[[' .. (mos.nL + 1) .. 'L ' .. mos.ns .. 's' .. equave_link .. '|' .. (mos.nL + 1) .. 'L' .. mos.ns .. 's' .. equave_disp .. '→]]'
	if mos.ns > 1 then
		prev_s = '[[' .. mos.nL .. 'L ' .. (mos.ns - 1) .. 's' .. equave_link .. '|↑' .. mos.nL .. 'L' .. (mos.ns - 1) .. 's' .. equave_disp .. ']]'
	end
	local next_s = '[[' .. mos.nL .. 'L ' .. (mos.ns + 1) .. 's' .. equave_link .. '|↓' .. mos.nL .. 'L' .. (mos.ns + 1) .. 's' .. equave_disp .. '\n]]'
	
	local infobox_data = {}
	
	table.insert(infobox_data, {
		'Brightest mode',
		'LLLsLLs'
	})
	table.insert(infobox_data, {
		'Period',
		'2/1'
	})
	table.insert(infobox_data, {
		'Range for [[bright]] [[generator]]',
		''
	})
	table.insert(infobox_data, {
		'Range for [[dark]] [[generator]]',
		''
	})
	table.insert(infobox_data, {
		'Parent MOS',
		'[[3L 2s]]'
	})
	table.insert(infobox_data, {
		'Daughter MOSes',
		'[[5L 7s]], [[7L 5s]]'
	})
	table.insert(infobox_data, {
		'[[Operations on MOSes#Sistering|Sister MOS]]',
		'[[2L 5s]]'
	})
	table.insert(infobox_data, {
		'[[Operations on MOSes#Neutralization|Neutralized MOS]]',
		'[[3L 4s]]'
	})
	table.insert(infobox_data, {
		'[[TAMNAMS#Mos pattern names|TAMNAMS name]]',
		'diatonic'
	})

	-- Compute et generators by taking mediants from paucitonic and equalized generators
	local paucitonic_et = 5
	local paucitonic_steps = 3
	local equalized_et = 7
	local equalized_steps = 4
	
	local supersoft_et = ET.new(1*paucitonic_et + 3*equalized_et)
	local supersoft_steps = 1*paucitonic_steps + 3*equalized_steps
	local supersoft_gen = ET.backslash_ratio(supersoft_et, supersoft_steps)
	
	local soft_et = ET.new(1*paucitonic_et + 2*equalized_et)
	local soft_steps =  1*paucitonic_steps + 2*equalized_steps
	local soft_gen = ET.backslash_ratio(soft_et, soft_steps)
	
	local semisoft_et = ET.new(2*paucitonic_et + 3*equalized_et)
	local semisoft_steps = 2*paucitonic_steps + 3*equalized_steps
	local semisoft_gen = ET.backslash_ratio(semisoft_et, semisoft_steps)
	
	local basic_et = ET.new(1*paucitonic_et + 1*equalized_et)
	local basic_steps = 1*paucitonic_steps + 1*equalized_steps
	local basic_gen = ET.backslash_ratio(basic_et, basic_steps)
	
	local semihard_et = ET.new(3*paucitonic_et + 2*equalized_et)
	local semihard_steps = 3*paucitonic_steps + 2*equalized_steps
	local semihard_gen = ET.backslash_ratio(semihard_et, semihard_steps)
	
	local hard_et = ET.new(2*paucitonic_et + 1*equalized_et)
	local hard_steps = 2*paucitonic_steps + 1*equalized_steps
	local hard_gen = ET.backslash_ratio(hard_et, hard_steps)
	
	local superhard_et = ET.new(3*paucitonic_et + 1*equalized_et)
	local superhard_steps = 3*paucitonic_steps + 1*equalized_steps
	local superhard_gen = ET.backslash_ratio(superhard_et, superhard_steps)
	
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Supersoft]] (L:s = 4:3)',
		'[[' .. supersoft_et .. '|' .. supersoft_gen .. ']] (' .. supersoft_gen_cents .. ')'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Soft]] (L:s = 3:2)',
		'[[' .. soft_et .. '|' .. soft_gen .. ']] (' .. soft_gen_cents .. ')'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Semisoft]] (L:s = 5:3)',
		'[[' .. semisoft_et .. '|' .. semisoft_gen .. ']] (' .. semisoft_gen_cents .. ')'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Basic]] (L:s = 2:1)',
		'[[' .. basic_et .. '|' .. basic_gen .. ']] (' .. basic_gen_cents .. ')'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Semihard]] (L:s = 5:2)',
		'[[' .. semihard_et .. '|' .. semihard_gen .. ']] (' .. semihard_gen_cents .. ')'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Hard]] (L:s = 3:1)',
		'[[' .. hard_et .. '|' .. hard_gen .. ']] (' .. hard_gen_cents .. ')'
	})
	table.insert(et_data, {
		'[[TAMNAMS#Step ratio spectrum|Superhard]] (L:s = 4:1)',
		'[[' .. superhard_et .. '|' .. superhard_gen .. ']] (' .. superhard_gen_cents .. ')'
	})
	result = p.build(
		tuning,
		infobox_data,
		edo_data,
		prev_L,
		next_L,
		prev_s,
		next_s
	)
	if not debug_mode then
		result = result .. categories
	end
	return result
end

function p.build(title, entries, prev_x, next_x, prev_y, next_y)
	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;" | '
	local has_adjacent_x = (prev_x and #prev_x > 0) or (next_x and #next_x > 0)
	local has_adjacent_y = (prev_y and #prev_y > 0) or (next_y and #next_y > 0)
	
	if prev_y then -- prev y
		s = s .. '<table style="width: 100%; margin: 0"><tr>'
			.. '<td></td><td style="\n' 
			.. 'width: 50%; padding-left: 1em; padding-right: 1em; text-align: center; font-size: smaller">'
			.. prev_y
			.. '\n</td><td></td>' 
			.. '\n<tr>'
			.. '<td style="width: 15%; text-align: left; white-space: nowrap; font-size: smaller">'
			.. (prev_x or '')
			.. '</td>'
			.. '<td style="width: 70%; padding-left: 1em; padding-right: 1em; text-align: center">'
			.. title
			.. '</td>'
			.. '<td style="width: 15%; text-align: right; white-space: nowrap; font-size: smaller">'
			.. (next_x or '')
			.. '</td>'
			.. '</tr>'
		if next_y then
			s = s .. '<tr>'
			.. '<td></td><td style="\n' 
			.. 'width: 50%; padding-left: 1em; padding-right: 1em; text-align: center; font-size: smaller">'
			.. next_y
			.. '\n</td><td></td>'
			.. '</tr>'
		end
		s = s ..  '</table>'
	elseif has_adjacent_x then -- no prev y, has adjacent x
		s = s .. '<table style="width: 100%; margin: 0"><tr>'
			.. '<td style="width: 15%; text-align: left; white-space: nowrap; font-size: smaller">'
			.. (prev_x or '')
			.. '</td>'
			.. '<td style="width: 70%; padding-left: 1em; padding-right: 1em; text-align: center">'
			.. title
			.. '</td>'
			.. '<td style="width: 15%; text-align: right; white-space: nowrap; font-size: smaller">'
			.. (next_x or '')
			.. '</td>'
			.. '</tr>'
		if next_y then
			s = s .. '<tr><td></td>'
			.. '<td style="\n' 
			.. 'width: 50%; padding-left: 1em; padding-right: 1em; text-align: center; font-size: smaller">'
			.. next_y
			.. '\n</td><td></td>'
			.. '</tr>'
		end
		s = s ..  '</table>'
	elseif next_y then -- no prev y, no adjacent x, so first row should be title in center
		s = s .. '<table style="width: 100%; margin: 0"><tr>'
			.. '<td>'
			.. '</td>'
			.. '<td>'
			.. title
			.. '</td>'
			.. '<td>'
			.. '</td>'
			.. '</tr>'
			.. '<tr><td></td>'
			.. '<td style="\n' 
			.. 'width: 50%; text-align: left; white-space: nowrap; font-size: smaller">'
			.. next_y
			.. '\n</td><td></td>'
			.. '</tr>'
			.. '</table>' 
	else
		s = s .. title
	end
	s = s .. '\n'
	for i, entry in ipairs(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(edo_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