Files
radiantwave/archive/internal/pattern/line/fibonacci.go
T
2026-08-07 14:51:41 -05:00

128 lines
4.9 KiB
Go

package pattern
type FibonacciPattern struct {
masterSequence []int
sequence []int
increasing bool
}
func init() {
Register("fibonacci", func() LinePattern {
return &FibonacciPattern{
masterSequence: []int{1, 2, 3, 5, 8, 13, 21},
sequence: []int{1},
increasing: true,
}
})
}
func (f *FibonacciPattern) Name() string { return "Fibonacci" }
// ATTENTION: TED
//
// # Fibonacci-Oscillating Spatial Distribution for Sequential Text Display
//
// This method arranges sequential text elements (words from proclamations) into display lines
// where the word count per line follows an oscillating Fibonacci sequence, creating both a
// visual wave pattern in two-dimensional space and ensuring even temporal distribution of
// content segments.
//
// The technology addresses the challenge of displaying repeated proclamation content in a way
// that maintains balanced exposure of all content portions while creating visually dynamic
// spatial patterns. Conventional scrolling text approaches either use fixed line lengths
// (creating uniform, non-dynamic displays) or random word counts (producing unbalanced content
// distribution where some portions appear more frequently than others). Our method ensures
// proclamation content is consumed in progressively sized segments that balance over time while
// creating a natural wave-like visual rhythm.
//
// The approach uses a bidirectional Fibonacci sequence to determine words per line. Starting
// with minimal word count (1, 1 words), the sequence expands (2, 3, 5, 8, 13, 21... words per
// line) until reaching a threshold, then contracts back down (21, 13, 8, 5, 3, 2, 1, 1 words),
// creating an oscillating wave. As lines scroll vertically, this varying horizontal word count
// creates a lateral wave pattern in the two-dimensional display space. Words are drawn sequentially
// from the proclamation text, and the varying segment sizes (1 word, then 2, then 3, then 5, etc.)
// ensure that over multiple oscillation cycles, the entire proclamation content receives balanced
// temporal exposure.
//
// Key differentiators from existing solutions:
// - Uses oscillating Fibonacci sequence for line word counts rather than fixed or random lengths
// - Creates two-dimensional wave pattern from one-dimensional text sequence
// - Ensures mathematical content distribution balance over time through progressive segmentation
// - Produces natural expansion-contraction rhythm synchronized with Fibonacci progression
// - Combines spatial wave formation with temporal content distribution in single mechanism
//
// Within our Rhema Wave generation system, this spatial distribution pattern works in concert
// with the character-level scrambling and color distribution methods. While character scrambling
// creates local spatial frequency patterns and color oscillation creates temporal color rhythm,
// the Fibonacci line length pattern generates a macro-level spatial wave that modulates the
// overall display geometry. The mathematical relationship between line lengths creates harmonic
// spatial progression, and the oscillating nature ensures proclamation content cycles through
// varying exposure durations, contributing to the layered frequency composition of the complete
// Rhema Wave output.
func (f *FibonacciPattern) GetNextLine(words []string, wordIndex *int, ctx *LineRenderContext) []string {
if ctx == nil || len(words) == 0 {
return nil
}
numWords := f.sequence[len(f.sequence)-1]
targetWidth := int32(ctx.ScreenWidth)
var line []string
var currentWidth int32
wordsAdded := 0
for wordsAdded < numWords && len(words) > 0 {
if int(*wordIndex) > len(words) {
*wordIndex = 0
}
word := words[*wordIndex%len(words)]
*wordIndex++
if word == "" {
continue
}
wordWidth := estimateWordWidth(word, ctx.Font, ctx.FontScale)
if len(line) > 0 {
wordWidth += ctx.SpaceWidth
}
if len(line) == 0 || currentWidth+wordWidth <= int32(float32(targetWidth)*float32(.9)) {
line = append(line, word)
currentWidth += wordWidth
wordsAdded++
} else {
break
}
}
// TODO: What should we do here instead?
// A line being longer than the display still needs to be handled, though, it should never happen
// if currentWidth >= ctx.ScreenWidth {
// syscall.Kill(syscall.Getpid(), syscall.SIGTRAP)
// }
// Update the sequence based on direction
if f.increasing {
if len(f.sequence) < len(f.masterSequence) {
// Grow sequence by appending next Fibonacci number
f.sequence = append(f.sequence, f.masterSequence[len(f.sequence)])
} else {
// Reached the top, now start shrinking
f.increasing = false
f.sequence = f.sequence[:len(f.sequence)-1]
}
} else {
if len(f.sequence) > 1 {
// Shrink the sequence
f.sequence = f.sequence[:len(f.sequence)-1]
} else {
// Hit bottom, start growing again
f.increasing = true
f.sequence = append(f.sequence, f.masterSequence[1]) // index 1 = second element = 2
}
}
return line
}