Module:MOS intro: Difference between revisions

Ganaram inukshuk (talk | contribs)
m Minor rewording to meet current (personal) coding standards
Ganaram inukshuk (talk | contribs)
Broke up the function that generates the intro into several helper functions to make it easier to add additional info
Line 14: Line 14:
end
end


-- Function that creates a mos intro sentence, given a mos and any other names
-- Helper function
function p.mos_intro(input_mos, other_names)
-- Lists out names, with each name being bold
local input_mos = input_mos or mos.new(5, 2)
function p.mos_intro_list_names(mos_names, conjunction)
local other_names = other_names or "name1; name2; name3"
local mos_names = mos_names or { "name1", "name2", "name3" }
local conjunction = conjunction or "and"
-- Get the step counts and number of periods
-- List the names
local nL = input_mos.nL -- Number of large steps per equave
local names_list = ""
local ns = input_mos.ns -- Number of small steps per equave
if #mos_names == 1 then
local n = utils._gcd(nL, ns) -- Number of periods
-- Only one mos name
local x = round(nL / n) -- Number of large steps per period
names_list = string.format("'''%s'''", mos_names[1])
local y = round(ns / n) -- Number of small steps per period
elseif #mos_names == 2 then
-- Two mos names (name and alternate-name)
names_list = string.format("'''%s''' %s '''%s'''", mos_names[1], conjunction, mos_names[2])
elseif #mos_names > 2 then
-- Three or more mos names
for i = 1, #mos_names - 1 do
names_list = names_list .. string.format("'''%s''', ", mos_names[i])
end
names_list = names_list .. string.format("%s '''%s'''", conjunction, mos_names[#mos_names])
else
-- No names
names_list = ""
end
-- Get the equave as a ratio and in cents
return names_list
local equave = input_mos.equave
end
local equave_in_cents = rat.cents(equave)


-- Get the period in cents
-- Helper function
local period_in_cents = equave_in_cents / n
-- Introduces the mos by its scale sig and names
function p.mos_intro_scalesig_and_tamnams_names(input_mos, tamnams_name, other_names)
local input_mos = input_mos or mos.new(5, 2)
local tamnams_name = tamnams_name or "diatonic"
local other_names = other_names or "other-name"
-- Get the scalesig
-- Get the scalesig
Line 37: Line 53:
-- Get all the mos's names, starting with tamnams names if applicable
-- Get all the mos's names, starting with tamnams names if applicable
-- Some mosses have two tamnams names, so it's necessary to tokenize it
local tamnams_names_list = p.mos_intro_list_names(p.parse_entries(tamnams_name), "and")
local tamnams_name = mos.tamnams_name[scale_sig] or ""
local other_names_list = p.mos_intro_list_names(p.parse_entries(other_names), "or")
local mos_names = p.parse_entries(tamnams_name)
-- Construct the sentence
local sentence = string.format("'''%s''' ", scale_sig)
-- Tokenize the other names passed in, then add them to the mos names
-- Add names
local other_names_tokenized = p.parse_entries(other_names)
if tamnams_names_list ~= "" and if_others_names_list ~= "" then
for i = 1, #other_names_tokenized do
-- There are both tamnams names and alternate names
mos_names[#mos_names + 1] = other_names_tokenized[i]
sentence = sentence .. string.format("([[TAMNAMS]] name %s; also called %s)", tamnams_names_list, other_names_list)
elseif tamnams_names_list ~= "" and if_others_names_list == "" then
-- There are only tamnams names
sentence = sentence .. string.format("([[TAMNAMS]] name %s)", tamnams_names_list)
elseif tamnams_names_list == "" and if_others_names_list ~= "" then
-- There are no tamnams names but there are alternate names
sentence = sentence .. string.format("(also called %s)", other_names_list)
end
end
-- Get the eds (ets) corresponding to the collapsed and equalized mosses
return sentence
local collapsed_et = et.new(nL, input_mos.equave)
end
local equalized_et = et.new(nL + ns, input_mos.equave)
 
-- Helper function
-- Introduces the mos by its step counts and number of periods
-- This is meant to immediately follow the sentence provided by:
-- - mos_intro_tamnams_names()
function p.mos_intro_steps_and_periods(input_mos)
local input_mos = input_mos or mos.new(3, 6, 3)
-- Get the sizes of the generator for the collapsed and equalized et in steps
-- Get the equave and the equave in cents
-- These are used to calculate cent values for the generators
local equave = input_mos.equave
local generator = mos.bright_gen(input_mos)
local equave_in_cents = rat.cents(equave)
local gen_collapsed_in_steps = generator["L"]
local equave_as_ratio = rat.as_ratio(equave)
local gen_equalized_in_steps = generator["L"] + generator["s"]
-- Is the mos octave-equivalent or non-octave?
-- Get the step counts and number of periods
local is_octave_equivalent = equave_in_cents == 1200
local nL = input_mos.nL -- Number of large steps per equave
local ns = input_mos.ns -- Number of small steps per equave
local n = utils._gcd(nL, ns) -- Number of periods
local x = round(nL / n) -- Number of large steps per period
local y = round(ns / n) -- Number of small steps per period
-- How many places should cent values be rounded to?
-- Construct the sentence
local round = 3
sentence = " is "
-- Create the intro string starting with the scale
-- Is the scale nonoctave?
local intro = "'''" .. scale_sig .. "'''"
if equave_in_cents == 1200 then
sentence = sentence .. string.format("an [[octave-equivalent]] [[moment of symmetry]] scale")
-- Add the mos names, if any
if #mos_names == 1 then
-- Only one mos name
intro = intro .. ", also called '''" .. mos_names[1] .. "''', is a"
elseif #mos_names == 2 then
-- Two mos names (name and alternate-name)
intro = intro .. ", also called '''" .. mos_names[1] .. "''' or '''" .. mos_names[2] .. "''', is a"
elseif #mos_names > 2 then
-- Three or more mos names (name, alternate-name, and other-alternate-name)
intro = intro .. ", also called "
for i = 1, #mos_names - 1 do
intro = intro .. "'''" .. mos_names[i] .. "''', "
end
intro = intro .. "or '''" .. mos_names[#mos_names] .. "''', is a"
else
else
-- No names
sentence = sentence .. string.format("a [[non-octave]], [[%s]]-equivalent [[moment_of_symmetry]] scale", equave_as_ratio)
intro = intro .. " is a"
end
end
-- Add whether it's non-octave
-- What are the step counts? Should the word "step" contain an s?
if is_octave_equivalent then
local s_nl = ""
intro = intro .. " [[moment of symmetry]] scale consisting of "
local s_ns = ""
else
if nL ~= 1 then
intro = intro .. " [[non-octave]] [[moment of symmetry]] scale consisting of "
s_nl = "s"
end
if ns ~= 1 then
s_ns = "s"
end
end
sentence = sentence .. string.format(" containing %d large step%s and %d small step%s", nL, s_nl, ns, s_ns)
-- Add the step counts per period
-- How does it repeat?
-- Determine where "steps" should be plural or singular, as well
local s_x = ""
if nL == 1 then
local s_y = ""
intro = intro .. "1 large step and "
local repetition = ""
else
if x ~= 1 then
intro = intro .. nL .. " large steps and "
s_x = "s"
end
if y ~= 1 then
s_y = "s"
end
if n == 2 then
repetition = "twice"
elseif n > 2 then
repetition = string.format("%d times", n)
end
end
if ns == 1 then
if n == 1 and equave_in_cents == 1200 then
intro = intro .. "1 small step,"
sentence = sentence .. string.format(" and repeating every [[octave]].")
else
elseif n == 1 and equave_in_cents ~= 1200 then
intro = intro .. ns .. " small steps,"
sentence = sentence .. string.format(" and repeating every interval of %s (%.3f¢).", equave_as_ratio, equave_in_cents)
elseif n ~= 1 and equave_in_cents == 1200 then
sentence = sentence .. string.format(", with a [[period]] of %d large step%s and %d small step%s", x, s_x, y, s_y)
sentence = sentence .. string.format(" that repeats every %.3f¢, or %s every [[octave]].", equave_in_cents / n, repetition)
elseif n ~= 1 and equave_in_cents ~= 1200 then
sentence = sentence .. string.format(", with a [[period]] of %d large step%s and %d small step%s", x, s_x, y, s_y)
sentence = sentence .. string.format(" that repeats every %.3f¢, or %s every interval of %s (%.3f¢).", equave_in_cents / n, repetition, equave_as_ratio, equave_in_cents)
end
end
-- Add the number of repetitions
return sentence
-- If multi-period, determine whether "steps" should be plural or singular, as well
end
if n == 1 then
 
intro = intro .. " repeating every "
-- Helper function
else
-- Calculates the generator ranges of the mos
intro = intro .. " with a [[period]] of "
function p.mos_intro_generator_ranges(input_mos)
if x == 1 then
local input_mos = input_mos or mos.new(5, 2)
intro = intro .. "1 large step and "
else
-- Get the step counts and number of periods
intro = intro .. x .. " large steps and "
local nL = input_mos.nL -- Number of large steps per equave
end
local ns = input_mos.ns -- Number of small steps per equave
if y == 1 then
local n = utils._gcd(nL, ns) -- Number of periods
intro = intro .. "1 small step "
else
-- Get the equave as a ratio and in cents
intro = intro .. y .. " small steps "
local equave = input_mos.equave
end
local equave_in_cents = rat.cents(equave)
if n == 2 then
intro = intro .. "that repeats twice every "
-- Get the eds (ets) corresponding to the collapsed and equalized mosses
else
local collapsed_et = et.new(nL, input_mos.equave)
intro = intro .. "that repeats " .. n .. " times every "
local equalized_et = et.new(nL + ns, input_mos.equave)
end
end
-- Get the sizes of the bright generator for the collapsed and equalized et in steps
-- These are used to calculate cent values for the generators
-- The values for the dark generator are the period complements
local generator = mos.bright_gen(input_mos)
local gen_collapsed_in_steps = generator["L"]
local gen_equalized_in_steps = generator["L"] + generator["s"]
local bright_gen_max = et.cents(collapsed_et, gen_collapsed_in_steps)
local bright_gen_min = et.cents(equalized_et, gen_equalized_in_steps)
local dark_gen_min = equave_in_cents / n - bright_gen_max
local dark_gen_max = equave_in_cents / n - bright_gen_min
-- Add the equivalence interval
local sentence = string.format("[[Generating intervals|generator]] that produce this scale range from %.3f¢ to %.3f¢, or from %.3f¢ to %.3f¢.", bright_gen_min, bright_gen_max, dark_gen_min, dark_gen_max)
if is_octave_equivalent then
intro = intro .. "[[octave]]"
else
intro = intro .. "interval of [[" .. rat.as_ratio(equave) .. "]] (" .. utils._round_dec(equave_in_cents, round) .. "¢)"
end
-- Add the period (this is a pun)
return sentence
if n == 1 then
end
intro = intro .. ". "
 
else
-- Function that creates a mos intro, given a mos and any other names
intro = intro .. ", or every " .. utils._round_dec(period_in_cents, round) .. "¢. "
-- Intro (or lead section) consists of multiple sentences, and each is called individually
end
function p.mos_intro(input_mos, other_names)
local input_mos = input_mos or mos.new(5, 2)
local other_names = other_names or "name1; name2; name3"
-- Add the generator range (for bright generator)
-- Get tamnams names
local collapsed_gen_in_cents = et.cents(collapsed_et, gen_collapsed_in_steps)
local tamnams_name = mos.tamnams_name[scale_sig] or ""
local equalized_gen_in_cents = et.cents(equalized_et, gen_equalized_in_steps)
intro = intro .. "This scale is made using a [[generator]] ranging from " .. utils._round_dec(equalized_gen_in_cents, round)
intro = intro .. "¢ to " .. utils._round_dec(collapsed_gen_in_cents, round) .. "¢, "
-- Add the generator range (for dark generator)
-- Construct the sentence
-- The dark generator range is the period complement of the bright generator's extremes,
local scalesig_and_names = p.mos_intro_scalesig_and_tamnams_names(input_mos, tamnams_name, other_names)
-- or the period in cents (equave / periods) minus the size of the bright generator
local steps_and_periods = p.mos_intro_steps_and_periods(input_mos)
intro = intro .. "or from " .. utils._round_dec(equave_in_cents / n - collapsed_gen_in_cents, round)
local gens = p.mos_intro_generator_ranges(input_mos)
intro = intro .. "¢ to " .. utils._round_dec(equave_in_cents / n - equalized_gen_in_cents, round) .. "¢."
return intro
return string.format("%s %s %s", scalesig_and_names, steps_and_periods, gens)
end
end