|
|
| Line 1: |
Line 1: |
| local mos = require("Module:MOS") | | local mos = require("Module:MOS") |
| local rat = require("Module:Rational")
| |
| local utils = require("Module:Utils")
| |
| local mosnot = require("Module:MOS notation")
| |
| local et = require("Module:ET")
| |
| local tip = require("Module:Template input parse") | | local tip = require("Module:Template input parse") |
| local tamnams = require("Module:TAMNAMS") | | local tamnams = require("Module:TAMNAMS") |
| local p = {} | | local p = {} |
|
| |
| -- TODO:
| |
| -- - Adopt new mos/tamnams functions for modmosses, then cleanup unneded functions
| |
|
| |
|
| -- Global variables for cell colors | | -- Global variables for cell colors |
| Line 21: |
Line 14: |
| p.cell_color_sm_altered_size = "#F8CBAD" | | p.cell_color_sm_altered_size = "#F8CBAD" |
|
| |
|
| -- Helper function
| |
| -- Determines whether an item is in an array
| |
| function p.find_item_in_table(table, item)
| |
| local item_found = false
| |
| for i = 1, #table do
| |
| if table[i] == item then
| |
| item_found = true
| |
| break
| |
| end
| |
| end
| |
| return item_found
| |
| end
| |
|
| |
| -- Calculate the mosstep vector from the mosstep pattern
| |
| -- Given a mos's step pattern and a quantity of mossteps, this takes an interval
| |
| -- (as a substring of the mosstep pattern starting from the root) and counts the number
| |
| -- of L's and s's in that substring. Allowed steps are:
| |
| -- - L - a single large step
| |
| -- - s - a single small step (can be capital S or lowercase s)
| |
| -- - c - a single chroma, defined as L-s; counting this adds one L and subtracts one s
| |
| -- Note that L-c=s and s+c=L.
| |
| -- - A - an augmented step, defined as L+c; counting this adds two L's and subtracts one s
| |
| -- - d - a diminished step, defined as s-c; counting this subtracts one L and adds two s's
| |
| -- Note that adding a chroma to an s makes it an L, and removing a chroma from an L
| |
| -- makes it an s.
| |
| -- Above-equave mossteps are supported.
| |
| function p.convert_mosstep_pattern_to_mosstep_vector(mosstep_pattern, mossteps)
| |
| local mossteps = mossteps or 7
| |
| local mosstep_pattern = mosstep_pattern or "LLLsLLs"
| |
|
| |
| local large_step_count = 0
| |
| local small_step_count = 0
| |
| local step_count = #mosstep_pattern
| |
|
| |
| -- If the number of mossteps exceeds the mosstep pattern, divide that quantity
| |
| -- by the number of steps and round up, then duplicate the pattern by that much.
| |
| local number_of_repetitions = math.ceil(mossteps / step_count)
| |
| local mosstep_pattern_duplicated = string.rep(mosstep_pattern, number_of_repetitions)
| |
|
| |
| -- Count the number of L's and s's in the string
| |
| -- C's, A's, and d's are worth some number of L's and s's
| |
| for i = 1, mossteps do
| |
| local step = string.sub(mosstep_pattern_duplicated, 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
| |
|
| |
| local mosstep_vector = { ["L"] = large_step_count, ["s"] = small_step_count }
| |
| return mosstep_vector
| |
| end
| |
|
| |
| -- Produce an encoded mosdegree from a mosstep vector
| |
| -- For an interval with two specific sizes, its large size is iL js and small size
| |
| -- is (i-1)L (j+1)s, for a difference of a single large step swapped with a single
| |
| -- small step. Alterations are denoted by adding or subtracting chromas, c, where a
| |
| -- chroma is L-s. An augmented step is L+c, denoted with a single A, so A=L+L-s.
| |
| -- Summing the number of L's and s's cancels out any negative step quantites for the
| |
| -- single A, so for any mosstep represented as a string of L's, s's, and A's, the sum of
| |
| -- the number of L's and s's produces the original interval (in mossteps). Similar
| |
| -- inductive reasoning applies with c's and d's, should a scale contain such steps.
| |
| -- To find how many alterations a mosstep vector had been applied to it:
| |
| -- - First, add or subtract chromas as needed until neither the L-count nor s-count
| |
| -- is negative, and record that number of chromas as k1.
| |
| -- - Then compare the step vector of that mosstep with the expected large or small size.
| |
| -- However many chromas are needed to add to reach the small size, or how many
| |
| -- chromas are need to remove to reach the small size, is the additional number
| |
| -- of chromas, k2, needed to reach the mos's large or small size. (Note that if
| |
| -- adding chromas, k2 is positive, but if removing chromas, k2 is negative.)
| |
| -- - Add k1 and k2. This is the number of alrerations the mosstep was from its large
| |
| -- or small size.
| |
| -- - Note that for mossteps with two specific sizes, there are effectively two "zero
| |
| -- points", one each for the large and small size, and which one to use depends
| |
| -- on whichever is closer. For mossteps with only one size, there is only one
| |
| -- zero point.
| |
| function p.calculate_mosstep_quality(input_mos, mosstep_vector)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local mosstep_vector = mosstep_vector or { ["L"] = 5, ["s"] = 2 }
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the number of mossteps in the bright gen and dark gen
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen["L"] + bright_gen["s"]
| |
| local mossteps_per_dark_gen = mossteps_per_period - mossteps_per_bright_gen
| |
|
| |
| -- Get the number of mossteps as the sum of the number of L's and s's
| |
| local mossteps = mosstep_vector["L"] + mosstep_vector["s"]
| |
|
| |
| -- Get the brightest and darkest modes for the input mos
| |
| local brightest_mode = mos.brightest_mode(input_mos)
| |
| local darkest_mode = string.reverse(brightest_mode)
| |
|
| |
| -- Get the expected vector of the large mosstep
| |
| local expected_large_mosstep_vector = p.convert_mosstep_pattern_to_mosstep_vector(brightest_mode, mossteps)
| |
|
| |
| -- Since the size difference between the large and small intervals is a single chroma,
| |
| -- which is L-s, simply count the large step difference between the given mosstep vector
| |
| -- and the expected large and small ones.
| |
| local large_step_count = mosstep_vector["L"]
| |
| local number_of_chromas = large_step_count - expected_large_mosstep_vector["L"]
| |
|
| |
| -- Determine what mosstep was passed in; is it a generator or period?
| |
| local mos_is_nL_ns = input_mos.nL == input_mos.ns
| |
| local mosstep_is_period = mossteps % mossteps_per_period == 0
| |
| local mosstep_is_bright_gen = mossteps % mossteps_per_period == mossteps_per_bright_gen and not mos_is_nL_ns
| |
| local mosstep_is_dark_gen = mossteps % mossteps_per_period == mossteps_per_dark_gen and not mos_is_nL_ns
| |
|
| |
| -- Rules for encoding are shown in the comments below.
| |
| -- Encoding follows the rules as found in the module mos notation, where:
| |
| -- - 3 = 2x augmented
| |
| -- - 2 = 1x augmented
| |
| -- - 1 = major
| |
| -- - 0 = perfect (used for generators, roots, and periods)
| |
| -- - -1 = minor
| |
| -- - -2 = 1x diminished
| |
| -- - -3 = 2x diminished
| |
| -- The number_of_chromas found previously must be translated to this encoding.
| |
| local encoded_quality = 0
| |
| if mosstep_is_period then
| |
| -- For periods:
| |
| -- - If the number of chromas is 1 or more, that quality is augmented
| |
| -- - If the nubmer of chromas is 0, that quality is perfect
| |
| -- - If the number of chromas is -1 or less, that quality is diminished
| |
| -- The encoded quality should always skip 1 and -1
| |
| if number_of_chromas >= 1 then
| |
| encoded_quality = number_of_chromas + 1
| |
| elseif number_of_chromas == 0 then
| |
| encoded_quality = number_of_chromas
| |
| elseif number_of_chromas <= -1 then
| |
| encoded_quality = number_of_chromas - 1
| |
| end
| |
| elseif mosstep_is_bright_gen then
| |
| -- For bright gens:
| |
| -- If the number of chromas is 1 or more, that quality is augmented
| |
| -- If the number of chromas is 0, that quality is perfect
| |
| -- If the number of chromas is -1 or less, that is diminished
| |
| -- The encoded quality should always skip 1 and -1
| |
| if number_of_chromas >= 1 then
| |
| encoded_quality = number_of_chromas + 1
| |
| elseif number_of_chromas == 0 then
| |
| encoded_quality = 0
| |
| elseif number_of_chromas <= -1 then
| |
| encoded_quality = number_of_chromas - 1
| |
| end
| |
| elseif mosstep_is_dark_gen then
| |
| -- For bright gens:
| |
| -- If the number of chromas is 0 or more, that quality is augmented
| |
| -- If the number of chromas is -1, that quality is perfect
| |
| -- If the number of chromas is -2 or less, that is diminished
| |
| -- The encoded quality should always skip 1 and -1
| |
| if number_of_chromas >= 0 then
| |
| encoded_quality = number_of_chromas + 2
| |
| elseif number_of_chromas == -1 then
| |
| encoded_quality = 0
| |
| elseif number_of_chromas <= -2 then
| |
| encoded_quality = number_of_chromas
| |
| end
| |
| else
| |
| -- For all other intervals:
| |
| -- If the number of chromas is 1 or more, that quality is augmented
| |
| -- If the number of chromas is 0, that quality is major
| |
| -- If the number of chromas is -1, that quality is minor
| |
| -- If the number of chromas is -2 or less, that is diminished
| |
| -- The encoded quality should always skip 0
| |
| if number_of_chromas >= 1 then
| |
| encoded_quality = number_of_chromas + 1
| |
| elseif number_of_chromas == 0 then
| |
| encoded_quality = 1
| |
| elseif number_of_chromas == -1 then
| |
| encoded_quality = -1
| |
| elseif number_of_chromas <= -2 then
| |
| encoded_quality = number_of_chromas
| |
| end
| |
| end
| |
|
| |
| return encoded_quality
| |
| end
| |
|
| |
| -- Helper function
| |
| -- Given a quality (and only a quality), decode it from a numeric value to text.
| |
| -- Encoding follows the rules as found in the module mos notation, where:
| |
| -- - 3 = 2x augmented
| |
| -- - 2 = 1x augmented
| |
| -- - 1 = major
| |
| -- - 0 = perfect (used for generators, roots, and periods)
| |
| -- - -1 = minor
| |
| -- - -2 = 1x diminished
| |
| -- - -3 = 2x diminished
| |
| -- That encoded value should be converted back to text
| |
| function p.decode_quality(encoded_quality)
| |
|
| |
| local quality_as_text = ""
| |
| if encoded_quality == 0 then
| |
| quality_as_text = "Perf."
| |
| elseif encoded_quality == 1 then
| |
| quality_as_text = "Maj."
| |
| elseif encoded_quality == 2 then
| |
| quality_as_text = "Aug."
| |
| elseif encoded_quality > 2 then
| |
| quality_as_text = (encoded_quality - 1) .. "× Aug."
| |
| elseif encoded_quality == -1 then
| |
| quality_as_text = "Min."
| |
| elseif encoded_quality == -2 then
| |
| quality_as_text = "Dim."
| |
| elseif encoded_quality < -2 then
| |
| quality_as_text = (math.abs(encoded_quality) - 1) .. "× Dim."
| |
| end
| |
|
| |
| return quality_as_text
| |
| end
| |
|
| |
| -- Helper function
| |
| -- Calcualtes the qualities of each scale degree given a mosstep pattern and input mos
| |
| -- Input mos is necessary for comparing step patterns with the true mos pattern, esp. with modmosses.
| |
| function p.calculate_mode_degrees(input_mos, mosstep_pattern)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local mosstep_pattern = mosstep_pattern or "LLsLLLs"
| |
|
| |
| -- Get the number of mossteps per period
| |
| local mossteps_per_equave = input_mos.nL + input_mos.ns
| |
|
| |
| local mode_degrees = {}
| |
| for i = 1, mossteps_per_equave + 1 do
| |
| local mossteps = i - 1
| |
|
| |
| local mosdegree_vector = p.convert_mosstep_pattern_to_mosstep_vector(mosstep_pattern, mossteps)
| |
| local encoded_mosdegree = p.calculate_mosstep_quality(input_mos, mosdegree_vector)
| |
| table.insert(mode_degrees, encoded_mosdegree)
| |
| end
| |
|
| |
| return mode_degrees
| |
| end
| |
|
| |
| -- Helper function
| |
| -- Calculate the UDP for each mode, given the modes are for the true
| |
| -- mos pattern and start at the brightest mode
| |
| function p.calculate_mos_mode_udps(input_mos)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local modes = mos.modes_by_brightness(input_mos)
| |
|
| |
| local brightness_order = {}
| |
| for i = 1, #modes do
| |
| table.insert(brightness_order, tamnams.mode_udp(modes[i], input_mos))
| |
| end
| |
|
| |
| return brightness_order
| |
| end
| |
|
| |
| -- Helper function
| |
| -- Calculate the rotational order for each mode, given the modes are
| |
| -- for the true mos pattern and start at the brightest mode
| |
| function p.calculate_mos_mode_rotational_order(input_mos)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the number of mossteps in the bright gen and dark gen
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen["L"] + bright_gen["s"]
| |
|
| |
| -- For each scale degree within a single period of a step pattern,
| |
| -- there is a unique mode.
| |
| -- If the mos is single-period, then there are x+y unique modes.
| |
| -- If the mos is multi-period nxL nys, then there are x+y modes instead
| |
| -- of nx+ny modes due to repetition.
| |
| local number_of_modes = mossteps_per_period
| |
|
| |
| local bright_gens_up = 0
| |
| local rotational_order = {}
| |
| for i = 1, mossteps_per_period do
| |
| local current_mode_order = bright_gens_up % mossteps_per_period + 1
| |
| bright_gens_up = bright_gens_up + mossteps_per_bright_gen
| |
| table.insert(rotational_order, current_mode_order)
| |
| end
| |
|
| |
| return rotational_order
| |
| end
| |
|
| |
| -- Calculate the rotations of a step pattern
| |
| -- Modes can either be sorted by decreasing brightness or by leftward shifts (rotation)
| |
| -- This is meant to be used as a helper function for the following functions:
| |
| -- - calculate_mos_mode_degrees
| |
| -- - calculate_modmos_mode_degrees
| |
| function p.calculate_step_pattern_rotations(input_mos, mosstep_pattern, rotate_by_generator)
| |
| local input_mos = input_mos or mos.new(6, 4)
| |
| local mosstep_pattern = mosstep_pattern or "LLsLsLLsLs"
| |
| local rotate_by_generator = rotate_by_generator == true
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the amount to shift by
| |
| -- Shifting by the number of mossteps in the generator produces modes by
| |
| -- descending brightness; shifting by 1 produces them in rotational order
| |
| local shift_amount = 1
| |
| if rotate_by_generator then
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen["L"] + bright_gen["s"]
| |
| shift_amount = mossteps_per_bright_gen
| |
| end
| |
|
| |
| local current_mode = mosstep_pattern
| |
| local rotations = {}
| |
| for i = 1, mossteps_per_equave do
| |
| if not p.find_item_in_table(rotations, current_mode) then
| |
| table.insert(rotations, current_mode)
| |
| end
| |
|
| |
| -- Rotate current mode
| |
| local first_substr = string.sub(current_mode, 1, shift_amount)
| |
| local second_substr = string.sub(current_mode, shift_amount + 1, mossteps_per_equave)
| |
| current_mode = second_substr .. first_substr
| |
| end
| |
|
| |
| return rotations
| |
| end
| |
|
| |
| -- Helper function
| |
| -- Calculate the scale degrees given an input mos and its modes
| |
| -- Modes can also be modmos modes
| |
| function p.calculate_mos_mode_degrees(input_mos, modes)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local modes = modes or p.calculate_step_pattern_rotations(input_mos, "LLLsLLs", true)
| |
|
| |
| -- Get the number of mossteps per period and equave
| |
| local mossteps_per_equave = input_mos.nL + input_mos.ns
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the number of mossteps per bright gen
| |
| local bright_gen = mos.bright_gen(input_mos)
| |
| local mossteps_per_bright_gen = bright_gen["L"] + bright_gen["s"]
| |
|
| |
| local mode_degrees = {}
| |
| for i = 1, #modes do
| |
| local current_mode_degrees = p.calculate_mode_degrees(input_mos, modes[i])
| |
| table.insert(mode_degrees, current_mode_degrees)
| |
| end
| |
|
| |
| return mode_degrees
| |
| end
| |
|
| |
| -- Helper function
| |
| -- For a given modmos step pattern, find the closest true-mos mode and alterations
| |
| -- The mos and its modes in rotational order should also be passed in
| |
| -- This finds the closest mode for only the modmos's step pattern, not all rotations
| |
| -- Alterations are denoted as a UDP followed by which scale degrees are altered from the original mode
| |
| -- If multiple true-mos modes are tied with being closest, use the darkest mode instead
| |
| function p.compare_modmos_with_true_mos_modes(input_mos, true_mos_modes, modmos_step_pattern)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local true_mos_modes = true_mos_modes or p.calculate_step_pattern_rotations(mos.new(5, 2), "LLLsLLs", true)
| |
| local modmos_step_pattern = modmos_step_pattern or "sLsLLsA"
| |
|
| |
| -- Get the number of mossteps per period and equave, and periods per equave
| |
| local mossteps_per_equave = (input_mos.nL + input_mos.ns)
| |
| local periods_per_equave = utils._gcd(input_mos.nL, input_mos.ns)
| |
| local mossteps_per_period = mossteps_per_equave / periods_per_equave
| |
|
| |
| -- Get the modmos's mosstep vectors to compare
| |
| local modmos_vector = p.calculate_mode_degrees(input_mos, modmos_step_pattern)
| |
|
| |
| -- Compare each mode in the array of mos modes.
| |
| -- For each mode compared, count how many alterations there are. The mode
| |
| -- with the fewest alterations is the closest true mos mode.
| |
| local index_of_closest_mode = 1
| |
| local lowest_number_of_alterations = mossteps_per_equave
| |
| for i = 1, #true_mos_modes do
| |
| local number_of_alterations = 0
| |
|
| |
| -- Get the current mode's degree vector
| |
| local mode_vector = p.calculate_mode_degrees(input_mos, true_mos_modes[i])
| |
|
| |
| -- Compare the vectors
| |
| for j = 1, #true_mos_modes[i] do
| |
| if mode_vector[j] ~= modmos_vector[j] then
| |
| number_of_alterations = number_of_alterations + 1
| |
| end
| |
| end
| |
|
| |
| -- If the current mode had fewer alterations, update
| |
| if number_of_alterations < lowest_number_of_alterations then
| |
| index_of_closest_mode = i
| |
| lowest_number_of_alterations = number_of_alterations
| |
| end
| |
|
| |
| -- If the current mode had the same number of alterations but is of a darker mode, update
| |
| --if number_of_alterations == lowest_number_of_alterations then
| |
| -- index_of_closest_mode = i
| |
| --end
| |
| end
| |
|
| |
| -- Calculate the UDP of the closest mode
| |
| local gens_down = (index_of_closest_mode - 1) * periods_per_equave
| |
| local gens_up = (mossteps_per_period - index_of_closest_mode) * periods_per_equave
| |
| local udp_of_closest_mode = gens_up .. "|" .. gens_down
| |
| if periods_per_equave ~= 1 then
| |
| udp_of_closest_mode = udp_of_closest_mode .. string.format("(%d)", periods_per_equave)
| |
| end
| |
|
| |
| -- Calculate alterations by comparing the modmos and the closest mode's degrees
| |
| local mode_vector = p.calculate_mode_degrees(input_mos, true_mos_modes[index_of_closest_mode])
| |
| local alterations = ""
| |
| for i = 1, #mode_vector do
| |
| if mode_vector[i] ~= modmos_vector[i] then
| |
| local encoded_degree = { ["Mossteps"] = i - 1, ["Quality"] = modmos_vector[i] }
| |
| local decoded_degree = mosnot.decode_mosstep_quality(encoded_degree, "m", "mosdegree", "abbreviated")
| |
| alterations = string.format("%s %s", alterations, decoded_degree)
| |
| end
| |
| end
| |
|
| |
| return udp_of_closest_mode .. alterations
| |
| end
| |
|
| |
| -- Helper function
| |
| -- For a given modmos step pattern, find the closest true-mos mode and alterations for each modmos mode
| |
| function p.calculate_modmos_mode_alterations(input_mos, modmos_step_pattern)
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local modmos_step_pattern = modmos_step_pattern or "LLLsLLs"
| |
|
| |
| -- Calculate the modes for the truemos and modmos
| |
| local true_mos_modes = p.calculate_step_pattern_rotations(input_mos, mos.brightest_mode(input_mos), true)
| |
| local modmos_modes = p.calculate_step_pattern_rotations(input_mos, modmos_step_pattern, false)
| |
|
| |
| -- Get each mode's alterations
| |
| local alterations = {}
| |
| for i = 1, #modmos_modes do
| |
| local alteration = p.compare_modmos_with_true_mos_modes(input_mos, true_mos_modes, modmos_modes[i])
| |
| table.insert(alterations, alteration)
| |
| end
| |
|
| |
| return alterations
| |
| end
| |
|
| |
| -- Helper function
| |
| -- Calculates row colors given precalculated degree vectors for each mode
| |
| function p.calculate_row_colors(input_mos, input_mode_vectors)
| |
| -- Default input mos and brightest/darkest true mos modes
| |
| local input_mos = input_mos or mos.new(5, 2)
| |
| local brightest_true_mode = mos.brightest_mode(input_mos)
| |
| local darkest_true_mode = string.reverse(brightest_true_mode)
| |
|
| |
| -- Default input mode vectors
| |
| local input_mode_vectors = input_mode_vectors or p.calculate_mos_mode_degrees(input_mos, p.calculate_step_pattern_rotations(input_mos, brightest_true_mode, true))
| |
|
| |
| -- Brightest and darkest vectors
| |
| local brightest_vector = p.calculate_mode_degrees(input_mos, brightest_true_mode)
| |
| local darkest_vector = p.calculate_mode_degrees(input_mos, darkest_true_mode)
| |
|
| |
| local row_colors = {}
| |
| for i = 1, #input_mode_vectors do
| |
| local cell_colors = {}
| |
| for j = 1, #input_mode_vectors[i] do
| |
| if input_mode_vectors[i][j] == brightest_vector[j] and input_mode_vectors[i][j] == darkest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_perfect_size)
| |
| elseif input_mode_vectors[i][j] == brightest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_large_size)
| |
| elseif input_mode_vectors[i][j] == darkest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_small_size)
| |
| elseif input_mode_vectors[i][j] > brightest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_lg_altered_size)
| |
| elseif input_mode_vectors[i][j] < darkest_vector[j] then
| |
| table.insert(cell_colors, p.cell_color_sm_altered_size)
| |
| end
| |
| end
| |
| table.insert(row_colors, cell_colors)
| |
| end
| |
|
| |
| return row_colors
| |
| end
| |
|
| |
|
| -- A simplified version of calculate_row_colors | | -- A simplified version of calculate_row_colors |