Module:MOS modes: Difference between revisions

Ganaram inukshuk (talk | contribs)
m Added todo
Ganaram inukshuk (talk | contribs)
Adopt functions provided by other templates; also a bugfix to "round" being missing
Line 2: Line 2:
local rat = require('Module:Rational')
local rat = require('Module:Rational')
local utils = require('Module:Utils')
local utils = require('Module:Utils')
local tip = require('Module:Template input parse')
local p = {}
local p = {}


-- TODO: collapse table if the number of modes is, say, more than 12
-- TODO: collapse table if the number of modes is, say, more than 12
-- Function that takes a mos and produces all of the modes by brightness
-- The mos is entered as a data structure provided by Module:MOS
function p.modes_by_brightness(input_mos)
-- Default parameter, which corresponds to 5L 2s <2/1>
local input_mos = input_mos or mos.new(5, 2, 2)
-- Get the number of L's, s's, and periods
local nL = input_mos.nL
local ns = input_mos.ns
local periods = utils._gcd(nL, ns)
-- Find its brightest mode as a string of L's and s's
local brightest_mode = mos.brightest_mode(input_mos)
-- Find the size of the generator aned period in mossteps
local gen = mos.bright_gen(input_mos)
local gen_in_mossteps = gen['L'] + gen['s']
local period_size  = round((nL + ns) / periods)
-- For a mos xL ys, there are x+y unique modes that can be obtained by the following process:
-- For a generator g in mossteps (g < x+y) and starting with the brightest mode (as a string
-- of L's and s's), move the first g steps to the end to get the next-brightest mode.
-- Repeat this process with the rotated string to get all modes. The x+y-1th time this is done
-- will be the darkest mode.
-- In the case of a multiperiod mos nxL nys, consider it as the mos for xL ys and duplicate
-- each result n times. This way, the number of rotations needed to be performed is still x+y-1.
local brightest_mode_substr = string.sub(brightest_mode, 1, period_size)
local modes = { brightest_mode }
local current_mode = brightest_mode_substr
for i = 1, period_size - 1 do
-- Move the first g characters from the beginning to the end
local first_substr = string.sub(current_mode, 1, gen_in_mossteps)
local second_substr = string.sub(current_mode, gen_in_mossteps + 1, period_size)
current_mode = second_substr .. first_substr
-- Duplicate the string (just in case) then add it to the array of modes
local current_mode_duplicated = string.rep(current_mode, periods)
table.insert(modes, current_mode_duplicated)
end
return modes
end
-- Helper function that parses entries from a semicolon-delimited string and returns them in an array
function p.parse_entries(unparsed)
local parsed = {}
for entry in string.gmatch(unparsed, '([^;]+)') do
local trimmed = entry:gsub("^%s*(.-)%s*$", "%1")
table.insert(parsed, trimmed) -- Add to array
end
return parsed
end


-- "Main" function
-- "Main" function
Line 71: Line 18:
-- Get the mos's modes and the mode count
-- Get the mos's modes and the mode count
local mos_modes = p.modes_by_brightness(input_mos)
local mos_modes = mos.modes_by_brightness(input_mos)
local periods = utils._gcd(input_mos.nL, input_mos.ns) -- Needed for UDP
local periods = mos.period_count(input_mos)
local mossteps_per_period = (input_mos.nL + input_mos.ns) / periods
local mossteps_per_period = mos.period_step_count(input_mos)


-- This is for entering multiple columns of info, if a single column of mode names isn't enough
-- This is for entering multiple columns of info, if a single column of mode names isn't enough
Line 92: Line 39:
-- Used for calculating rotational order
-- Used for calculating rotational order
local bright_gen = mos.bright_gen(input_mos)
local bright_gen = mos.bright_gen(input_mos)
local mossteps_per_bright_gen = bright_gen['L'] + bright_gen['s']
local mossteps_per_bright_gen = mos.bright_gen_step_count(input_mos)
-- Make a table with a column for the mode (as a string of L's and s's) and UDP
-- Make a table with a column for the mode (as a string of L's and s's) and UDP
Line 118: Line 65:
-- As of coding, mos mode listings are fairly inconsistent or nonexistent, but consist of
-- As of coding, mos mode listings are fairly inconsistent or nonexistent, but consist of
-- the UDP, step pattern, and any mode names(s) in some order
-- the UDP, step pattern, and any mode names(s) in some order
-- This table orders them as UDP, step pattern, and (TODO) mode names, as that's more common
-- This table orders them as UDP, step pattern, and mode names, as that's more common
for i = 1, #mos_modes do
for i = 1, #mos_modes do
result = result .. "|-\n"
result = result .. "|-\n"
Line 178: Line 125:
else
else
mode_names_unparsed = frame.args['Mode Names']
mode_names_unparsed = frame.args['Mode Names']
mode_names = p.parse_entries(mode_names_unparsed)
mode_names = tip.parse_entries(mode_names_unparsed)
end
end