@@ -34,6 +34,7 @@ class EnhancedPatternApp {
3434 // Initialize core components
3535 this . database = new PatternDatabase ( ) ;
3636 this . explorer = new SystematicExplorer ( ) ;
37+ this . sequencer = null ;
3738
3839 // Application state
3940 this . currentPattern = null ;
@@ -44,6 +45,7 @@ class EnhancedPatternApp {
4445 // Initialize the application
4546 this . setupEventListeners ( ) ;
4647 this . initialize ( ) ;
48+ this . initializeSequencer ( ) ;
4749
4850 console . log ( '✅ Enhanced Pattern Application initialized successfully' ) ;
4951 }
@@ -56,7 +58,8 @@ class EnhancedPatternApp {
5658 'MathUtils' , 'RegularPolygonGenerator' , 'EuclideanGenerator' ,
5759 'PerfectBalanceAnalyzer' , 'PatternAnalyzer' , 'CenterOfGravityCalculator' ,
5860 'AdvancedPatternCombiner' , 'UnifiedPatternParser' , 'PatternConverter' ,
59- 'SystematicExplorer' , 'PatternDatabase' , 'UIComponents' , 'AppConfig'
61+ 'SystematicExplorer' , 'PatternDatabase' , 'UIComponents' , 'AppConfig' ,
62+ 'SequencerController' , 'SequencerIntegration'
6063 ] ;
6164
6265 const missingClasses = requiredClasses . filter ( className =>
@@ -87,6 +90,94 @@ class EnhancedPatternApp {
8790 console . log ( '🎯 Application initialization complete' ) ;
8891 }
8992
93+ /**
94+ * Initialize the sequencer controller
95+ */
96+ async initializeSequencer ( ) {
97+ try {
98+ console . log ( '🎵 Initializing sequencer...' ) ;
99+
100+ // Create sequencer controller
101+ this . sequencer = new SequencerController ( 'patternSequencerCanvas' , 'balanceSection' , {
102+ autoPlay : false ,
103+ defaultTempo : 120 ,
104+ defaultVolume : 0.5 ,
105+ enableAudio : true ,
106+ enableVisual : true
107+ } ) ;
108+
109+ // Setup sequencer event listeners
110+ this . setupSequencerEvents ( ) ;
111+
112+ console . log ( '✅ Sequencer initialized successfully' ) ;
113+
114+ } catch ( error ) {
115+ console . error ( '❌ Failed to initialize sequencer:' , error ) ;
116+ // Continue without sequencer if initialization fails
117+ this . sequencer = null ;
118+ }
119+ }
120+
121+ /**
122+ * Setup sequencer event listeners
123+ */
124+ setupSequencerEvents ( ) {
125+ if ( ! this . sequencer ) return ;
126+
127+ // Sequencer control buttons
128+ const playBtn = document . getElementById ( 'sequencerPlayBtn' ) ;
129+ const pauseBtn = document . getElementById ( 'sequencerPauseBtn' ) ;
130+ const stopBtn = document . getElementById ( 'sequencerStopBtn' ) ;
131+ const tempoSlider = document . getElementById ( 'sequencerTempoSlider' ) ;
132+ const volumeSlider = document . getElementById ( 'sequencerVolumeSlider' ) ;
133+ const tempoDisplay = document . getElementById ( 'sequencerTempoDisplay' ) ;
134+ const volumeDisplay = document . getElementById ( 'sequencerVolumeDisplay' ) ;
135+ const statusDisplay = document . getElementById ( 'sequencerStatus' ) ;
136+
137+ if ( playBtn ) {
138+ playBtn . addEventListener ( 'click' , ( ) => this . sequencer . play ( ) ) ;
139+ }
140+
141+ if ( pauseBtn ) {
142+ pauseBtn . addEventListener ( 'click' , ( ) => this . sequencer . pause ( ) ) ;
143+ }
144+
145+ if ( stopBtn ) {
146+ stopBtn . addEventListener ( 'click' , ( ) => this . sequencer . stop ( ) ) ;
147+ }
148+
149+ if ( tempoSlider && tempoDisplay ) {
150+ tempoSlider . addEventListener ( 'input' , ( e ) => {
151+ const tempo = parseInt ( e . target . value ) ;
152+ this . sequencer . setTempo ( tempo ) ;
153+ tempoDisplay . textContent = tempo ;
154+ } ) ;
155+ }
156+
157+ if ( volumeSlider && volumeDisplay ) {
158+ volumeSlider . addEventListener ( 'input' , ( e ) => {
159+ const volume = parseInt ( e . target . value ) / 100 ;
160+ this . sequencer . updateAudioSettings ( { volume } ) ;
161+ volumeDisplay . textContent = `${ e . target . value } %` ;
162+ } ) ;
163+ }
164+
165+ // Listen for sequencer events
166+ this . sequencer . on ( 'onPlaybackChange' , ( data ) => {
167+ if ( statusDisplay ) {
168+ statusDisplay . textContent = data . isPlaying ? 'Playing' :
169+ data . isPaused ? 'Paused' : 'Ready' ;
170+ }
171+ } ) ;
172+
173+ this . sequencer . on ( 'onError' , ( error ) => {
174+ console . error ( 'Sequencer error:' , error ) ;
175+ if ( statusDisplay ) {
176+ statusDisplay . textContent = 'Error' ;
177+ }
178+ } ) ;
179+ }
180+
90181 /**
91182 * Setup all event listeners for the application
92183 */
@@ -319,7 +410,7 @@ class EnhancedPatternApp {
319410 // Show and populate balance section
320411 const balanceSection = document . getElementById ( 'balanceSection' ) ;
321412 if ( balanceSection ) {
322- balanceSection . style . display = 'flex ' ;
413+ balanceSection . style . display = 'grid ' ;
323414
324415 const balanceInfo = balanceSection . querySelector ( '.balance-info-compact' ) ;
325416 const balanceViz = balanceSection . querySelector ( '.balance-visualization-large' ) ;
@@ -347,14 +438,30 @@ class EnhancedPatternApp {
347438 <strong>Milne's Formula:</strong> |∑(e^(i2πkⱼ/n))| / onsets = ${ analysis . balanceAnalysis . normalizedMagnitude . toFixed ( 6 ) }
348439 </div>
349440 </div>
441+ <div class="analysis-box cog-box" style="margin-top: 8px;">
442+ <div class="analysis-box-header">
443+ <span class="analysis-box-icon">🎯</span>
444+ <span class="analysis-box-title">Center of Gravity</span>
445+ </div>
446+ <div class="analysis-box-content">
447+ <div class="cog-distance-value">
448+ Distance: ${ analysis . cogAnalysis ?. distance ?. toFixed ( 4 ) || 'N/A' }
449+ </div>
450+ <div class="cog-angle-value">
451+ Angle: ${ analysis . cogAnalysis ?. angle ?. toFixed ( 1 ) || 'N/A' } °
452+ </div>
453+ <div class="cog-description">
454+ ${ analysis . cogAnalysis ?. distance < 0.1 ? '🎯 Geometrically Centered' : 'Pattern analysis' }
455+ </div>
456+ </div>
457+ </div>
350458 ` ;
351459 }
352-
353- if ( balanceViz ) {
354- balanceViz . innerHTML = UIComponents . renderCogVisualization ( analysis . cogAnalysis , analysis . stepCount ) ;
355- }
356460 }
357461
462+ // Load pattern into sequencer
463+ this . loadPatternIntoSequencer ( pattern , analysis ) ;
464+
358465 } catch ( error ) {
359466 console . error ( '❌ Analysis display error:' , error ) ;
360467
@@ -439,6 +546,12 @@ class EnhancedPatternApp {
439546 const balanceAnalysis = PerfectBalanceAnalyzer . calculateBalance ( pattern . steps , pattern . stepCount ) ;
440547 const cogAnalysis = CenterOfGravityCalculator . calculateCenterOfGravity ( pattern . steps ) ;
441548
549+ console . log ( '🔍 Analysis generated:' , {
550+ balanceAnalysis : balanceAnalysis ? 'OK' : 'MISSING' ,
551+ cogAnalysis : cogAnalysis ? 'OK' : 'MISSING' ,
552+ cogProperties : cogAnalysis ? Object . keys ( cogAnalysis ) : 'N/A'
553+ } ) ;
554+
442555 return {
443556 title : 'Mathematical Pattern Analysis' ,
444557 patternOutputItems : patternOutputItems ,
@@ -1287,6 +1400,34 @@ ${perfectBalancePatterns.map((pattern, index) => {
12871400 this . updateDatabaseStats ( ) ;
12881401 }
12891402 }
1403+
1404+ /**
1405+ * Load pattern into sequencer for playback and visualization
1406+ */
1407+ loadPatternIntoSequencer ( pattern , analysis ) {
1408+ if ( ! this . sequencer ) {
1409+ console . warn ( '⚠️ Sequencer not available' ) ;
1410+ return ;
1411+ }
1412+
1413+ try {
1414+ // Create sequencer-compatible pattern object
1415+ const sequencerPattern = SequencerIntegration . convertPatternResult ( pattern ) ;
1416+
1417+ // Add CoG data for visualization
1418+ if ( analysis && analysis . cogAnalysis ) {
1419+ sequencerPattern . cogData = analysis . cogAnalysis ;
1420+ }
1421+
1422+ // Load pattern into sequencer
1423+ this . sequencer . updatePattern ( sequencerPattern ) ;
1424+
1425+ console . log ( `🎵 Pattern loaded into sequencer: ${ sequencerPattern . name } ` ) ;
1426+
1427+ } catch ( error ) {
1428+ console . error ( '❌ Failed to load pattern into sequencer:' , error ) ;
1429+ }
1430+ }
12901431}
12911432
12921433// Export for global access
0 commit comments