diff --git a/array.lua b/array.lua index afdc0b1..ab29ea6 100644 --- a/array.lua +++ b/array.lua @@ -153,4 +153,12 @@ function Array:equals(array) return getmetatable(array) == Array and #self == #array and equal_values +end + +function Array:sum() + local total = 0 + for _, value in ipairs(self) do + total = total + value + end + return total end \ No newline at end of file diff --git a/scale.lua b/scale.lua index 640d23d..057e98e 100644 --- a/scale.lua +++ b/scale.lua @@ -82,6 +82,10 @@ function Scale.c_major() }) end +function Scale:count_alterations() + return self.notes:map(function(n) return n.alteration end):sum() +end + --[[ Warning: only works for ionian scales ]] @@ -110,12 +114,14 @@ end Warning: only works for ionian scales ]] function Scale:circle_of_5ths_rotate(iterations) - if(iterations == 0) then + local total_alterations = self:count_alterations()+iterations + local rotation = ( (total_alterations + 5) % 12 ) - 5 + if(rotation == 0) then return self - elseif(iterations < 0) then - return self:to_the_left_on_circle_of_5ths(-iterations) - elseif(iterations > 0) then - return self:to_the_right_on_circle_of_5ths(iterations) + elseif(rotation < 0) then + return self:to_the_left_on_circle_of_5ths(-rotation) + elseif(rotation > 0) then + return self:to_the_right_on_circle_of_5ths(rotation) else return "Error" end diff --git a/test/test_scale.lua b/test/test_scale.lua index 3a2e9c6..132c015 100644 --- a/test/test_scale.lua +++ b/test/test_scale.lua @@ -359,4 +359,13 @@ function TestScale:testGetDistance() luaunit.assertEquals(f_sharp_maj:get_distance(g_flat_min), 2) luaunit.assertEquals(f_sharp_maj:get_distance(d_sharp_min), 0) luaunit.assertEquals(f_sharp_maj:get_distance(d_sharp_min_harm), 1) -end \ No newline at end of file +end + +function TestScale:test_c5ths_rotate() + local c_major = Scale.c_major() + luaunit.assertEquals(c_major:circle_of_5ths_rotate(12), c_major:circle_of_5ths_rotate(0)) + luaunit.assertEquals(c_major:circle_of_5ths_rotate(8), c_major:circle_of_5ths_rotate(-4)) + luaunit.assertEquals(c_major:circle_of_5ths_rotate(-8), c_major:circle_of_5ths_rotate(4)) + luaunit.assertEquals(c_major:circle_of_5ths_rotate(123), c_major:circle_of_5ths_rotate(3)) + luaunit.assertEquals(c_major:circle_of_5ths_rotate(-123), c_major:circle_of_5ths_rotate(-3)) +end