128 lines
4.9 KiB
Go
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 Radiant 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
|
|
// Radiant 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
|
|
}
|