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. Lives at ~/.drill.beat, independent of whichever project's .drill.txt is active. 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 =
File.join(Dir.home, ".drill.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



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

def self.clear
  FileUtils.rm_f(PATH)
end

.configured?Boolean

Returns:

  • (Boolean)


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

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.



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

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.



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

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.



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

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



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

def self.loop_size
  settings[0]
end

.rand?Boolean

Returns:

  • (Boolean)


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

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

.repetitionsObject



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

def self.repetitions
  settings[1]
end

.repetitions_or_default(value) ⇒ Object



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

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

.set(loop_size, repetitions) ⇒ Object



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

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

.set_randObject



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

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.



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

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)


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

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