-- Module for TAMNAMS-related things as it pertains to mosses
-- This module is meant to be used with other modules, not as part of a template
-- Work in progress
local mos = require('Module:MOS')
local rat = require('Module:Rational')
local utils = require('Module:Utils')
local p = {}
--------------------------------------------------------------------------------
------------------------------- LOOKUP TABLES ----------------------------------
--------------------------------------------------------------------------------
-- Lookup table for tamnams step ratios
p.tamnams_ratios = {
['1:1'] = 'equalized',
['4:3'] = 'supersoft',
['3:2'] = 'soft',
['5:3'] = 'semisoft',
['2:1'] = 'basic',
['5:2'] = 'semihard',
['3:1'] = 'hard',
['4:1'] = 'superhard',
['1:0'] = 'collapsed'
}
-- And step ratio ranges
p.tamnams_ranges = {
['1:1 to 2:1'] = 'soft-of-basic',
['1:1 to 4:3'] = 'ultrasoft',
['4:3 to 3:2'] = 'parasoft',
['3:2 to 2:1'] = 'hyposoft',
['3:2 to 5:3'] = 'quasisoft',
['5:3 to 2:1'] = 'minisoft',
['2:1 to 5:2'] = 'minihard',
['5:2 to 3:1'] = 'quasihard',
['2:1 to 3:1'] = 'hypohard',
['3:1 to 4:1'] = 'parahard',
['4:1 to 1:0'] = 'ultrahard',
['2:1 to 1:0'] = 'hard-of-basic'
}
-- Lookup table for tamnams extended step ratios
p.tamnams_ratios_ext = {
['1:1'] = 'equalized',
['6:5'] = 'semiequalized',
['4:3'] = 'supersoft',
['3:2'] = 'soft',
['5:3'] = 'semisoft',
['2:1'] = 'basic',
['5:2'] = 'semihard',
['3:1'] = 'hard',
['4:1'] = 'superhard',
['6:1'] = 'extrahard',
['10:1'] = 'semicollapsed',
['1:0'] = 'collapsed'
}
-- And extended step ratio ranges
p.tamnams_ranges_ext = {
['1:1 to 2:1'] = 'soft-of-basic',
['1:1 to 6:5'] = 'semiequalized',
['6:5 to 4:3'] = 'ultrasoft',
['4:3 to 3:2'] = 'parasoft',
['3:2 to 2:1'] = 'hyposoft',
['3:2 to 5:3'] = 'quasisoft',
['5:3 to 2:1'] = 'minisoft',
['2:1 to 5:2'] = 'minihard',
['5:2 to 3:1'] = 'quasihard',
['2:1 to 3:1'] = 'hypohard',
['3:1 to 4:1'] = 'parahard',
['4:1 to 6:1'] = 'hyperhard',
['6:1 to 10:1'] = 'clustered',
['4:1 to 10:1'] = 'ultrahard',
['10:1 to 1:0'] = 'pseudocollapsed',
['2:1 to 1:0'] = 'hard-of-basic'
}
-- Lookup table for official tamnams names
p.tamnams_name = {
['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'] = 'archaeotonic',
['1L 7s'] = 'antipine',
['2L 6s'] = 'subaric',
['3L 5s'] = 'checkertonic',
['4L 4s'] = 'tetrawood',
['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',
['8L 1s'] = 'subneutralic',
['1L 9s'] = 'antisinatonic',
['2L 8s'] = 'jaric',
['3L 7s'] = 'sephiroid',
['4L 6s'] = 'lime',
['5L 5s'] = 'pentawood',
['6L 4s'] = 'lemon',
['7L 3s'] = 'dicoid',
['8L 2s'] = 'taric',
['9L 1s'] = 'sinatonic'
}
-- And prefixes
p.tamnams_prefix = {
['1L 1s'] = 'monwd-',
['2L 2s'] = 'biwd-',
['1L 5s'] = 'amech-',
['2L 4s'] = 'mal-',
['3L 3s'] = 'triwd-',
['4L 2s'] = 'citro-',
['5L 1s'] = 'mech-',
['1L 6s'] = 'on-',
['2L 5s'] = 'pel-',
['3L 4s'] = 'mosh-',
['4L 3s'] = 'smi-',
['5L 2s'] = 'dia-',
['6L 1s'] = 'arch-',
['1L 7s'] = 'apine-',
['2L 6s'] = 'subar-',
['3L 5s'] = 'check-',
['4L 4s'] = 'tetrawd-',
['5L 3s'] = 'oneiro-',
['6L 2s'] = 'ek-',
['7L 1s'] = 'pine-',
['1L 8s'] = 'ablu-',
['2L 7s'] = 'bal-',
['3L 6s'] = 'cher-',
['4L 5s'] = 'gram-',
['5L 4s'] = 'cthon-',
['6L 3s'] = 'hyru-',
['7L 2s'] = 'arm-',
['8L 1s'] = 'blu-',
['1L 9s'] = 'asina-',
['2L 8s'] = 'jara-',
['3L 7s'] = 'seph-',
['4L 6s'] = 'lime-',
['5L 5s'] = 'pentawd-',
['6L 4s'] = 'lem-',
['7L 3s'] = 'dico-',
['8L 2s'] = 'tara-',
['9L 1s'] = 'sina-'
}
-- And abbrevs
p.tamnams_abbrev = {
['1L 1s'] = 'wood',
['2L 2s'] = 'bw',
['1L 5s'] = 'amech',
['2L 4s'] = 'mal',
['3L 3s'] = 'trw',
['4L 2s'] = 'cit',
['5L 1s'] = 'mech',
['1L 6s'] = 'on',
['2L 5s'] = 'pel',
['3L 4s'] = 'mosh',
['4L 3s'] = 'smi',
['5L 2s'] = 'dia',
['6L 1s'] = 'arch',
['1L 7s'] = 'apine',
['2L 6s'] = 'subar',
['3L 5s'] = 'chk',
['4L 4s'] = 'ttw',
['5L 3s'] = 'onei',
['6L 2s'] = 'ek',
['7L 1s'] = 'pine',
['1L 8s'] = 'ablu',
['2L 7s'] = 'bal',
['3L 6s'] = 'ch',
['4L 5s'] = 'gram',
['5L 4s'] = 'cth',
['6L 3s'] = 'hyru',
['7L 2s'] = 'arm',
['8L 1s'] = 'blu',
['1L 9s'] = 'asi',
['2L 8s'] = 'jar',
['3L 7s'] = 'seph',
['4L 6s'] = 'lime',
['5L 5s'] = 'pw',
['6L 4s'] = 'lem',
['7L 3s'] = 'dico',
['8L 2s'] = 'tar',
['9L 1s'] = 'si'
}
--------------------------------------------------------------------------------
----------------------------- LOOKUP FUNCTIONS ---------------------------------
--------------------------------------------------------------------------------
-- Function for looking up a mos's name (octave-equivalent mosses only)
-- Also works for prefixes and abbrevs
function p.lookup_name(input_mos, lookup_type)
local input_mos = mos.parse(input_mos) or "5L 2s"
local lookup_type = lookup_type or "name"
if lookup_type == "name" or lookup_type == "NAME" then
return p.tamnams_name[scalesig]
elseif lookup_type == "prefix" or lookup_type == "PREFIX" then
return p.tamnams_prefix[scalesig]
elseif lookup_type == "abbrev" or lookup_type == "ABBREV" then
return p.tamnams_abbrev[scalesig]
else
return nil
end
end
-- Function for looking up a step ratio range
-- Module:Rational is used to help simplify ratios
function p.lookup_step_ratio(step_ratio, use_extended)
local step_ratio = step_ratio or rat.new(2, 1)
local use_extended = use_extended == true
-- Produce the key needed to lookup the step ratio name
-- use_extended is used to toggle between central range and extended range
local key = rat.as_ratio(step_ratio, ':')
if use_extended then
return p.tamnams_ratios_ext[key]
else
return p.tamnams_ratios[key]
end
end
-- Function for looking up a step ratio range
-- Module:Rational is used to help simplify ratios
function p.lookup_step_ratio_range(step_ratio_1, step_ratio_2, use_extended)
local step_ratio_1 = step_ratio_1 or rat.new(1, 0)
local step_ratio_2 = step_ratio_2 or rat.new(2, 1)
local use_extended = use_extended == true
-- Produce the key needed for the lookup table as a/b to c/d
-- Swap ratios if ratio 1 has a higher hardness than ratio 2
local key = ""
local float_1 = rat.as_float(step_ratio_1)
local float_2 = rat.as_float(step_ratio_2)
if (float_1 > float_2) then
key = string.format('%s to %s', rat.as_ratio(step_ratio_2, ':'), rat.as_ratio(step_ratio_1, ':'))
else
key = string.format('%s to %s', rat.as_ratio(step_ratio_1, ':'), rat.as_ratio(step_ratio_2, ':'))
end
-- use_extended is used to toggle between central range and extended range
if use_extended then
return p.tamnams_ranges_ext[key]
else
return p.tamnams_ranges[key]
end
end
function p.lookup_named_ancestor(input_mos)
end
--------------------------------------------------------------------------------
------------------------------ HELPER FUNCTIONS --------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-------------------------- ENCODE/DECODE FUNCTIONS -----------------------------
--------------------------------------------------------------------------------
-- Function that encodes a sequence of mossteps into a vector.
-- Step sequences of L's and s's are encoded into a vector containing how many
-- L's and s's there are. Steps that denote alterations by a chroma are allowed
-- since they can be expressed as the sum (or difference) between multiple large
-- and small steps:
-- - c: a single chroma; the difference between a large and small step, or L - s
-- - A: an augmented step; a large step plus a chroma, or 2L + s
-- - d: a diminished step, a small step minus a chroma, or -L + 2s
-- Proposed encoding (work-in-progress):
-- 2 = Large size plus 2 chromas, or 2x-aug size for period intervals
-- 1 = Large size plus 1 chroma, or augmented size for period intervals
-- 0 = Large size, or perfect size for period intervals
-- -1 = Small size, or diminished size for period intervals
-- -2 = Small size minus 1 chroma, or 2x-dim for period intervals
-- Encoding can continue for any number of chromas; only [-2, 2] is shown for
-- demonstration.
-- Large/small size is translated to major/minor, or aug/perf/dim based on what
-- interval it is (nonperfectable vs dark gen vs bright gen).
-- Encoding can be adapted for use with mos notation (EG, diamond-mos), where
-- the values denote how many chromas are added/subtracted.
function p.encode_mosstep_sequence_to_vector(input_mos, mosstep_sequence)
local input_mos = input_mos or mos.new(5, 2)
local mosstep_sequence = mosstep_sequence or "LLAALLAA"
local encoding = {
--['Is period'] = #mosstep_sequence % utils._gcd(5, 2) == 0,
['L'] = 0,
['s'] = 0
}
local large_step_count = 0
local small_step_count = 0
for i = 1, #mosstep_sequence do
local step = string.sub(mosstep_sequence, i, i)
if step == "L" then
large_step_count = large_step_count + 1
elseif step == "s" or step == "S" then
small_step_count = small_step_count + 1
elseif step == "c" then
large_step_count = large_step_count + 1
small_step_count = small_step_count - 1
elseif step == "A" then
large_step_count = large_step_count + 2
small_step_count = small_step_count - 1
elseif step == "d" then
large_step_count = large_step_count - 1
small_step_count = small_step_count + 2
end
end
encoding['L'] = large_step_count
encoding['s'] = small_step_count
return encoding
end
--------------------------------------------------------------------------------
----------------------------- TESTER FUNCTION ----------------------------------
--------------------------------------------------------------------------------
function p.tester()
return p.lookup_step_ratio_range(rat.new(10, 1), rat.new(1, 0), true)
end
return p