<commit_before>$: << '/home/emily/Software/SonicPi/sonic-pi/app/server/vendor/mini_kanren/lib'

require 'mini_kanren'

###################################################
################# USER PARAMETERS #################
chord_sequence = [:c, :f, :g] # TODO: implement from this
beats_for_each_chord = [1, 1, 1] # TODO: implement from this
beats_per_bar = 3 # TODO: implement from this
$scale = [:c, :d, :e, :f, :g, :a, :b] # TODO: implement this with a ring?
number_of_voices = 3 # TODO: implement from this
length_of_canon = 3 # TODO: implement from this
###################################################
################ SYSTEM PARAMETERS ################
P_SINGLE = 0.25
P_DOUBLE = 0.25
P_TRIPLE = 0.2
P_QUADRUPLE = 0.1
P_QUINTUPLE = 1
###################################################

chords = MiniKanren.exec do
  extend SonicPi::Lang::Core
  extend SonicPi::RuntimeMethods

   # Generate the chord sequence.
  ## Get time signature
  time_sig = [[4,4], [3,4]].choose

  ## Get number of voices
  case time_sig
  when [4,4]
    num_voices = rrand_i(2,4)
  when [3,4]
    num_voices = rrand_i(2,3)
  else
    puts "Error: where did that time signature come from?!"
  end

  ## Get the chords
  chord_choice = [:I, :IV, :V, :VI]
  chords = Array.new(time_sig[0])
  for i in 0..chords.length
    chords[i] = fresh
  end

  chord_constraints = []
  ### End on I
  chord_constraints << eq(chords[chords.length - 1], :I)

  ### For the rest, choose a chord at random
  for i in 0..chords.length - 2
    chord_constraints << eq(chords[i], chord_choice.choose())
  end

  q = fresh
  run(1, q, eq(q, chords), *chord_constraints)
end


# Hard code it for now...
root_notes = [[:g, :c, :g], [:e, :f, :e], [:c, :f, :c]]

# Generate the canon structure
canon = Array.new(length_of_canon)
for i in 0..canon.length - 1
  canon[i] = Array.new(beats_per_bar)
  for j in 0..beats_per_bar - 1
    canon[i][j] = {root_note: root_notes[i][j], rhythm: nil, notes: nil}
  end
end

canon_results = MiniKanren.exec do

  ################### DEFINE FUNCTIONS ###################

  # Given two notes in the scale, find the median between them (rounded down if the median is between two values)<commit_msg>Add root notes generation. Untested.<commit_after>$: << '/home/emily/Software/SonicPi/sonic-pi/app/server/vendor/mini_kanren/lib'

require 'mini_kanren'

###################################################
################# USER PARAMETERS #################
chord_sequence = [:c, :f, :g] # TODO: implement from this
beats_for_each_chord = [1, 1, 1] # TODO: implement from this
beats_per_bar = 3 # TODO: implement from this
$scale = [:c, :d, :e, :f, :g, :a, :b] # TODO: implement this with a ring?
number_of_voices = 3 # TODO: implement from this
length_of_canon = 3 # TODO: implement from this
###################################################
################ SYSTEM PARAMETERS ################
P_SINGLE = 0.25
P_DOUBLE = 0.25
P_TRIPLE = 0.2
P_QUADRUPLE = 0.1
P_QUINTUPLE = 1
###################################################

chords = MiniKanren.exec do
  extend SonicPi::Lang::Core
  extend SonicPi::RuntimeMethods
  # Generate the chord sequence.
  ## Get time signature
  time_sig = [[4,4], [3,4]].choose

  ## Get the chords
  chord_choice = [:I, :IV, :V, :VI]
  chords = Array.new(time_sig[0])
  for i in 0..chords.length - 1
    chords[i] = fresh
  end

  chord_constraints = []
  # End on I
  chord_constraints << eq(chords[chords.length - 1], :I)

  # For the rest, choose a chord at random
  for i in 0..chords.length - 2
    chord_constraints << eq(chords[i], chord_choice.choose())
  end

  q = fresh
  run(1, q, eq(q, chords), *chord_constraints)
end

# Get the root notes by choosing ones from the chords
names_to_notes = {
  :I => lambda { $scale[1], $scale[3], $scale[5]].choose },
  :IV => lambda { [$scale[4], $scale[6], $scale[8]].choose },
  :V => lambda { [$scale[5], $scale[7], $scale[9]].choose },
  :VI => lambda { [$scale[6], $scale[8], $scale[10]].choose }
}

# Get number of voices
num_voices = rrand_i(2,4)

root_notes = Array.new(num_voices)

for i in 0..root_notes.length - 1
  root_notes = Array.new(chords.length)
  for j in 0..chords.length - 1
    root_notes[i][j] = names_to_notes[chords[j].call]
  end
end

puts root_notes

# Generate the canon structure
canon = Array.new(length_of_canon)
for i in 0..canon.length - 1
  canon[i] = Array.new(beats_per_bar)
  for j in 0..beats_per_bar - 1
    canon[i][j] = {root_note: root_notes[i][j], rhythm: nil, notes: nil}
  end
end

canon_results = MiniKanren.exec do

  ################### DEFINE FUNCTIONS ###################

  # Given two notes in the scale, find the median between them (rounded down if the median is between two values)
{'fraction_non_alphanumeric': 0.23197625106022052, 'fraction_numerical': 0.019083969465648856, 'mean_word_length': 4.276286353467562, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '757109', 'n_tokens_mistral': 1777, 'n_tokens_neox': 1683, 'n_words': 471}