Module: Lexdrill::Beat

Defined in:
lib/lexdrill/beat.rb

Overview

Global rhythm config: repeats loops of loop_size consecutive words repetitions times before advancing to the next loop. Disabled (plain word-by-word advance) unless explicitly configured. drill beat rand selects a third mode (marked by the literal contents "rand") where WordList.next ignores the counter/rhythm entirely and picks a uniformly random word each time instead.

Defined Under Namespace

Classes: LoopInfo

Constant Summary collapse

PATH =
Lexdrill::Config.path("beat")
MIN_LOOP_SIZE =
2
MAX_LOOP_SIZE =
8
DEFAULT_REPETITIONS =
8
RAND_MARKER =
"rand"
ALIASES =
{
  "polka" => 2,
  "waltz" => 3,
  "rock" => 4,
  "jazz" => 5,
  "jiga" => 6,
  "balkan" => 7,
  "samba" => 8
}.freeze

Class Method Summary collapse

Class Method Details

.clearObject



49
50
51
# File 'lib/lexdrill/beat.rb', line 49

def self.clear
  FileUtils.rm_f(PATH)
end

.configured?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/lexdrill/beat.rb', line 33

def self.configured?
  File.exist?(PATH) && !rand?
end

.cycle_length(word_count) ⇒ Object

Total steps in one full cycle through the word list at the current rhythm, or plain word_count when no beat is configured.



71
72
73
74
75
# File 'lib/lexdrill/beat.rb', line 71

def self.cycle_length(word_count)
  return word_count unless configured?

  chunk_sizes(word_count).sum { |size| size * repetitions }
end

.index_for(word_count, step) ⇒ Object

Maps a step (already bounded within cycle_length) to a word index.



78
79
80
# File 'lib/lexdrill/beat.rb', line 78

def self.index_for(word_count, step)
  loop_info(word_count, step).index
end

.loop_info(word_count, step) ⇒ Object

Full detail on where step falls: word index, the current loop's word range, which repeat pass it is, and how many total. A single "loop" spanning the whole list (shown once) when no beat is configured.



91
92
93
94
95
96
97
# File 'lib/lexdrill/beat.rb', line 91

def self.loop_info(word_count, step)
  unless configured?
    return LoopInfo.new(index: step, chunk_start: 1, chunk_end: word_count, loop_number: 1, total_loops: 1)
  end

  locate(word_count, step)
end

.loop_sizeObject



61
62
63
# File 'lib/lexdrill/beat.rb', line 61

def self.loop_size
  settings[0]
end

.rand?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/lexdrill/beat.rb', line 37

def self.rand?
  File.exist?(PATH) && File.read(PATH).strip == RAND_MARKER
end

.repetitionsObject



65
66
67
# File 'lib/lexdrill/beat.rb', line 65

def self.repetitions
  settings[1]
end

.repetitions_or_default(value) ⇒ Object



57
58
59
# File 'lib/lexdrill/beat.rb', line 57

def self.repetitions_or_default(value)
  value ? value.to_i : DEFAULT_REPETITIONS
end

.set(loop_size, repetitions) ⇒ Object



41
42
43
# File 'lib/lexdrill/beat.rb', line 41

def self.set(loop_size, repetitions)
  File.write(PATH, "#{loop_size} #{repetitions}")
end

.set_randObject



45
46
47
# File 'lib/lexdrill/beat.rb', line 45

def self.set_rand
  File.write(PATH, RAND_MARKER)
end

.step_for_index(word_count, target_index) ⇒ Object

The inverse of index_for: the earliest step that lands on target_index, for drill go to jump the counter straight to a specific word.



84
85
86
# File 'lib/lexdrill/beat.rb', line 84

def self.step_for_index(word_count, target_index)
  (0...cycle_length(word_count)).find { |step| index_for(word_count, step) == target_index }
end

.valid_loop_size?(value) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/lexdrill/beat.rb', line 53

def self.valid_loop_size?(value)
  (MIN_LOOP_SIZE..MAX_LOOP_SIZE).cover?(value)
end