TheGreatUnknown commited on
Commit
3b12794
·
verified ·
1 Parent(s): 57bbbc3

Create script.js

Browse files
Files changed (1) hide show
  1. script.js +1192 -0
script.js ADDED
@@ -0,0 +1,1192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as d3 from 'd3';
2
+
3
+ document.addEventListener('DOMContentLoaded', function() {
4
+ // Navigation
5
+ const navLinks = document.querySelectorAll('nav a');
6
+ const sections = document.querySelectorAll('.dashboard-section');
7
+
8
+ navLinks.forEach(link => {
9
+ link.addEventListener('click', function(e) {
10
+ e.preventDefault();
11
+ const targetId = this.getAttribute('href').substring(1);
12
+
13
+ // Hide all sections
14
+ sections.forEach(section => {
15
+ section.classList.remove('active');
16
+ });
17
+
18
+ // Show target section
19
+ document.getElementById(targetId).classList.add('active');
20
+
21
+ // Update active nav link
22
+ navLinks.forEach(navLink => {
23
+ navLink.parentElement.classList.remove('active');
24
+ });
25
+ this.parentElement.classList.add('active');
26
+ });
27
+ });
28
+
29
+ // Close notification
30
+ const closeBtn = document.querySelector('.close-notification');
31
+ const notification = document.querySelector('.notification');
32
+
33
+ if (closeBtn && notification) {
34
+ closeBtn.addEventListener('click', function() {
35
+ notification.style.display = 'none';
36
+ });
37
+ }
38
+
39
+ // Charts
40
+ renderCharts();
41
+
42
+ // AI Model Marketplace Interactions
43
+ const deployButtons = document.querySelectorAll('.deploy-button');
44
+ deployButtons.forEach(button => {
45
+ button.addEventListener('click', function() {
46
+ // Display deployment notification
47
+ showNotification('Model Deployment', 'Your selected AI model is being deployed. Please wait...', 'info');
48
+
49
+ // Simulate deployment process
50
+ setTimeout(() => {
51
+ showNotification('Deployment Complete', 'Your AI model has been successfully deployed and is now active.', 'success');
52
+ }, 2000);
53
+ });
54
+ });
55
+
56
+ // Data Feed Tier Selection
57
+ const tierButtons = document.querySelectorAll('.tier-button');
58
+ tierButtons.forEach(button => {
59
+ button.addEventListener('click', function() {
60
+ const tierName = this.parentElement.querySelector('h3').textContent;
61
+ showNotification('Subscription', `You're being redirected to subscribe to the ${tierName} data feed tier.`, 'info');
62
+ });
63
+ });
64
+
65
+ // Initialize Research Lab Visualizations
66
+ if (document.getElementById('research-lab')) {
67
+ initResearchLab();
68
+ }
69
+
70
+ // Initialize monetization research section
71
+ if (document.getElementById('monetization-research')) {
72
+ initMonetizationResearch();
73
+ }
74
+ });
75
+
76
+ // Chart rendering function
77
+ function renderSimpleCharts() {
78
+ renderPerformanceChart();
79
+ renderDistributionChart();
80
+ renderRevenueChart();
81
+ renderPredictionChart();
82
+ }
83
+
84
+ function renderPerformanceChart() {
85
+ const container = document.getElementById('performanceChart');
86
+ if (!container) return;
87
+
88
+ // Clear previous content
89
+ container.innerHTML = '';
90
+
91
+ // Create SVG container
92
+ const width = container.clientWidth;
93
+ const height = container.clientHeight || 300;
94
+ const margin = {top: 20, right: 30, bottom: 30, left: 40};
95
+
96
+ const svg = d3.select(container)
97
+ .append('svg')
98
+ .attr('width', width)
99
+ .attr('height', height)
100
+ .append('g')
101
+ .attr('transform', `translate(${margin.left},${margin.top})`);
102
+
103
+ // Sample data
104
+ const data = [
105
+ {month: 'Jan', tvl: 120, revenue: 10},
106
+ {month: 'Feb', tvl: 140, revenue: 15},
107
+ {month: 'Mar', tvl: 167, revenue: 22},
108
+ {month: 'Apr', tvl: 205, revenue: 34},
109
+ {month: 'May', tvl: 250, revenue: 55},
110
+ {month: 'Jun', tvl: 302, revenue: 78},
111
+ {month: 'Jul', tvl: 335, revenue: 120},
112
+ {month: 'Aug', tvl: 410, revenue: 190},
113
+ {month: 'Sep', tvl: 442, revenue: 250},
114
+ {month: 'Oct', tvl: 468, revenue: 320},
115
+ {month: 'Nov', tvl: 480, revenue: 380},
116
+ {month: 'Dec', tvl: 487, revenue: 427}
117
+ ];
118
+
119
+ // Scales
120
+ const x = d3.scaleBand()
121
+ .domain(data.map(d => d.month))
122
+ .range([0, width - margin.left - margin.right])
123
+ .padding(0.1);
124
+
125
+ const y = d3.scaleLinear()
126
+ .domain([0, d3.max(data, d => Math.max(d.tvl, d.revenue))])
127
+ .nice()
128
+ .range([height - margin.top - margin.bottom, 0]);
129
+
130
+ // Draw axes
131
+ svg.append('g')
132
+ .attr('transform', `translate(0,${height - margin.top - margin.bottom})`)
133
+ .call(d3.axisBottom(x));
134
+
135
+ svg.append('g')
136
+ .call(d3.axisLeft(y));
137
+
138
+ // Draw lines
139
+ const tvlLine = d3.line()
140
+ .x(d => x(d.month) + x.bandwidth()/2)
141
+ .y(d => y(d.tvl))
142
+ .curve(d3.curveMonotoneX);
143
+
144
+ const revenueLine = d3.line()
145
+ .x(d => x(d.month) + x.bandwidth()/2)
146
+ .y(d => y(d.revenue))
147
+ .curve(d3.curveMonotoneX);
148
+
149
+ svg.append('path')
150
+ .datum(data)
151
+ .attr('fill', 'none')
152
+ .attr('stroke', '#6c5ce7')
153
+ .attr('stroke-width', 2)
154
+ .attr('d', tvlLine);
155
+
156
+ svg.append('path')
157
+ .datum(data)
158
+ .attr('fill', 'none')
159
+ .attr('stroke', '#00cec9')
160
+ .attr('stroke-width', 2)
161
+ .attr('d', revenueLine);
162
+
163
+ // Legend
164
+ const legend = svg.append('g')
165
+ .attr('font-family', 'sans-serif')
166
+ .attr('font-size', 10)
167
+ .attr('text-anchor', 'end')
168
+ .selectAll('g')
169
+ .data(['TVL Growth', 'Protocol Revenue'])
170
+ .enter().append('g')
171
+ .attr('transform', (d, i) => `translate(0,${i * 20})`);
172
+
173
+ legend.append('rect')
174
+ .attr('x', width - margin.left - margin.right - 19)
175
+ .attr('width', 19)
176
+ .attr('height', 19)
177
+ .attr('fill', (d, i) => i === 0 ? '#6c5ce7' : '#00cec9');
178
+
179
+ legend.append('text')
180
+ .attr('x', width - margin.left - margin.right - 24)
181
+ .attr('y', 9.5)
182
+ .attr('dy', '0.32em')
183
+ .text(d => d);
184
+ }
185
+
186
+ function renderDistributionChart() {
187
+ const container = document.getElementById('modelDistributionChart');
188
+ if (!container) return;
189
+
190
+ // Clear previous content
191
+ container.innerHTML = '';
192
+
193
+ // Create SVG container
194
+ const width = container.clientWidth;
195
+ const height = container.clientHeight || 250;
196
+
197
+ const svg = d3.select(container)
198
+ .append('svg')
199
+ .attr('width', width)
200
+ .attr('height', height)
201
+ .append('g')
202
+ .attr('transform', `translate(${width/2},${height/2})`);
203
+
204
+ // Sample data
205
+ const data = [
206
+ {label: 'Yield Optimization', value: 35, color: '#00b894'},
207
+ {label: 'Risk Scoring', value: 25, color: '#ff7675'},
208
+ {label: 'Arbitrage Detection', value: 20, color: '#fdcb6e'},
209
+ {label: 'NFT Valuation', value: 15, color: '#6c5ce7'},
210
+ {label: 'Other', value: 5, color: '#b2bec3'}
211
+ ];
212
+
213
+ // Compute pie layout
214
+ const pie = d3.pie()
215
+ .value(d => d.value)
216
+ .sort(null);
217
+
218
+ const radius = Math.min(width, height) / 2 - 40;
219
+
220
+ // Generate the arcs
221
+ const arc = d3.arc()
222
+ .innerRadius(radius * 0.6)
223
+ .outerRadius(radius);
224
+
225
+ // Draw pie segments
226
+ const segments = svg.selectAll('path')
227
+ .data(pie(data))
228
+ .enter()
229
+ .append('path')
230
+ .attr('d', arc)
231
+ .attr('fill', d => d.data.color)
232
+ .attr('stroke', 'white')
233
+ .style('stroke-width', '2px');
234
+
235
+ // Add labels
236
+ const labelRadius = radius * 1.2;
237
+
238
+ svg.selectAll('text')
239
+ .data(pie(data))
240
+ .enter()
241
+ .append('text')
242
+ .attr('transform', d => {
243
+ const pos = arc.centroid(d);
244
+ const midAngle = d.startAngle + (d.endAngle - d.startAngle) / 2;
245
+ pos[0] = labelRadius * Math.sin(midAngle);
246
+ pos[1] = -labelRadius * Math.cos(midAngle);
247
+ return `translate(${pos})`;
248
+ })
249
+ .style('text-anchor', d => {
250
+ const midAngle = d.startAngle + (d.endAngle - d.startAngle) / 2;
251
+ return (midAngle < Math.PI ? 'start' : 'end');
252
+ })
253
+ .style('font-size', '12px')
254
+ .text(d => d.data.label);
255
+ }
256
+
257
+ function renderRevenueChart() {
258
+ const container = document.getElementById('revenueStreamsChart');
259
+ if (!container) return;
260
+
261
+ // Clear previous content
262
+ container.innerHTML = '';
263
+
264
+ // Create SVG container
265
+ const width = container.clientWidth;
266
+ const height = container.clientHeight || 250;
267
+ const margin = {top: 20, right: 30, bottom: 40, left: 50};
268
+
269
+ const svg = d3.select(container)
270
+ .append('svg')
271
+ .attr('width', width)
272
+ .attr('height', height)
273
+ .append('g')
274
+ .attr('transform', `translate(${margin.left},${margin.top})`);
275
+
276
+ // Sample data
277
+ const data = [
278
+ {source: 'Model Marketplace', value: 120, color: 'rgba(108, 92, 231, 0.7)'},
279
+ {source: 'Data Feeds', value: 85, color: 'rgba(0, 206, 201, 0.7)'},
280
+ {source: 'Stablecoin Fees', value: 65, color: 'rgba(253, 121, 168, 0.7)'},
281
+ {source: 'Insurance Premiums', value: 45, color: 'rgba(0, 184, 148, 0.7)'},
282
+ {source: 'Credit Markets', value: 35, color: 'rgba(9, 132, 227, 0.7)'}
283
+ ];
284
+
285
+ // Scales
286
+ const x = d3.scaleBand()
287
+ .domain(data.map(d => d.source))
288
+ .range([0, width - margin.left - margin.right])
289
+ .padding(0.3);
290
+
291
+ const y = d3.scaleLinear()
292
+ .domain([0, d3.max(data, d => d.value)])
293
+ .nice()
294
+ .range([height - margin.top - margin.bottom, 0]);
295
+
296
+ // Draw axes
297
+ svg.append('g')
298
+ .attr('transform', `translate(0,${height - margin.top - margin.bottom})`)
299
+ .call(d3.axisBottom(x))
300
+ .selectAll('text')
301
+ .attr('transform', 'rotate(-45)')
302
+ .style('text-anchor', 'end');
303
+
304
+ svg.append('g')
305
+ .call(d3.axisLeft(y));
306
+
307
+ // Draw bars
308
+ svg.selectAll('rect')
309
+ .data(data)
310
+ .enter()
311
+ .append('rect')
312
+ .attr('x', d => x(d.source))
313
+ .attr('y', d => y(d.value))
314
+ .attr('width', x.bandwidth())
315
+ .attr('height', d => height - margin.top - margin.bottom - y(d.value))
316
+ .attr('fill', d => d.color)
317
+ .attr('rx', 5)
318
+ .attr('ry', 5);
319
+ }
320
+
321
+ function renderPredictionChart() {
322
+ const container = document.getElementById('predictionChart');
323
+ if (!container) return;
324
+
325
+ // Create a simple visual for prediction chart
326
+ container.innerHTML = `
327
+ <svg width="100%" height="100%" viewBox="0 0 100 50">
328
+ <path d="M0,40 C15,35 25,25 40,20 C55,15 65,22 80,18 C95,15 100,25 100,30"
329
+ stroke="#f39c12" stroke-width="2" fill="none" />
330
+ <path d="M0,45 C20,40 30,35 50,30 C70,25 80,30 100,25"
331
+ stroke="#0984e3" stroke-width="2" fill="none" />
332
+ </svg>
333
+ `;
334
+ }
335
+
336
+ function loadLibraries() {
337
+ return import('https://cdn.jsdelivr.net/npm/d3@7/+esm').then(d3Module => {
338
+ window.d3 = d3Module;
339
+ return { d3: window.d3 };
340
+ });
341
+ }
342
+
343
+ function renderCharts() {
344
+ loadLibraries().then(() => {
345
+ renderSimpleCharts();
346
+ }).catch(error => {
347
+ console.error('Error loading libraries:', error);
348
+ });
349
+ }
350
+
351
+ // Function to show notifications
352
+ function showNotification(title, message, type = 'info') {
353
+ // Create notification container if it doesn't exist
354
+ let notificationCenter = document.querySelector('.notification-center');
355
+ if (!notificationCenter) {
356
+ notificationCenter = document.createElement('div');
357
+ notificationCenter.className = 'notification-center';
358
+ document.body.appendChild(notificationCenter);
359
+ }
360
+
361
+ // Create notification element
362
+ const notification = document.createElement('div');
363
+ notification.className = 'notification';
364
+
365
+ // Create icon based on type
366
+ const iconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
367
+ iconSvg.setAttribute('viewBox', '0 0 24 24');
368
+ iconSvg.setAttribute('width', '20');
369
+ iconSvg.setAttribute('height', '20');
370
+
371
+ let iconPath = '';
372
+ let iconClass = '';
373
+
374
+ switch(type) {
375
+ case 'success':
376
+ iconPath = `
377
+ <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/>
378
+ <path d="M8,12 L11,15 L16,9" fill="none" stroke="currentColor" stroke-width="2"/>
379
+ `;
380
+ iconClass = 'success';
381
+ break;
382
+ case 'error':
383
+ iconPath = `
384
+ <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/>
385
+ <line x1="8" y1="8" x2="16" y2="16" stroke="currentColor" stroke-width="2"/>
386
+ <line x1="8" y1="16" x2="16" y2="8" stroke="currentColor" stroke-width="2"/>
387
+ `;
388
+ iconClass = 'error';
389
+ break;
390
+ case 'warning':
391
+ iconPath = `
392
+ <path d="M12,2 L22,22 L2,22 Z" stroke="currentColor" stroke-width="2" fill="none"/>
393
+ <line x1="12" y1="10" x2="12" y2="14" stroke="currentColor" stroke-width="2"/>
394
+ <circle cx="12" cy="18" r="1" fill="currentColor"/>
395
+ `;
396
+ iconClass = 'warning';
397
+ break;
398
+ default: // info
399
+ iconPath = `
400
+ <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"/>
401
+ <line x1="12" y1="8" x2="12" y2="12" stroke="currentColor" stroke-width="2"/>
402
+ <circle cx="12" cy="16" r="1" fill="currentColor"/>
403
+ `;
404
+ iconClass = 'info';
405
+ }
406
+
407
+ iconSvg.innerHTML = iconPath;
408
+
409
+ // Create notification content
410
+ const notificationIcon = document.createElement('div');
411
+ notificationIcon.className = `notification-icon ${iconClass}`;
412
+ notificationIcon.appendChild(iconSvg);
413
+
414
+ const notificationContent = document.createElement('div');
415
+ notificationContent.className = 'notification-content';
416
+ notificationContent.innerHTML = `<h4>${title}</h4><p>${message}</p>`;
417
+
418
+ const closeButton = document.createElement('button');
419
+ closeButton.className = 'close-notification';
420
+ closeButton.textContent = '×';
421
+ closeButton.addEventListener('click', function() {
422
+ notification.style.opacity = '0';
423
+ setTimeout(() => {
424
+ notification.remove();
425
+ }, 300);
426
+ });
427
+
428
+ // Assemble notification
429
+ notification.appendChild(notificationIcon);
430
+ notification.appendChild(notificationContent);
431
+ notification.appendChild(closeButton);
432
+
433
+ // Add to notification center
434
+ notificationCenter.appendChild(notification);
435
+
436
+ // Auto-remove after timeout
437
+ setTimeout(() => {
438
+ notification.style.opacity = '0';
439
+ setTimeout(() => {
440
+ notification.remove();
441
+ }, 300);
442
+ }, 5000);
443
+ }
444
+
445
+ // Simulated AI Model Evolution
446
+ let evolutionStep = 0;
447
+ const evolutionInterval = setInterval(function() {
448
+ if (evolutionStep < 5) {
449
+ let modelType, improvement;
450
+
451
+ switch(evolutionStep) {
452
+ case 0:
453
+ modelType = 'Yield Optimization';
454
+ improvement = '+2.3% APY improvement detected in yield models';
455
+ break;
456
+ case 1:
457
+ modelType = 'Risk Scoring';
458
+ improvement = 'New vulnerability pattern identified in lending protocol';
459
+ break;
460
+ case 2:
461
+ modelType = 'NFT Valuation';
462
+ improvement = 'Valuation model accuracy increased by 4.2%';
463
+ break;
464
+ case 3:
465
+ modelType = 'Arbitrage Detection';
466
+ improvement = 'New cross-chain arbitrage opportunity detected';
467
+ break;
468
+ case 4:
469
+ modelType = 'System';
470
+ improvement = 'Recursive self-improvement complete: v2.1 ready';
471
+ break;
472
+ }
473
+
474
+ showNotification(`AI Evolution: ${modelType}`, improvement, 'info');
475
+ evolutionStep++;
476
+ } else {
477
+ clearInterval(evolutionInterval);
478
+ }
479
+ }, 45000); // Show an evolution notification every 45 seconds
480
+
481
+ // Simulated market activity
482
+ setTimeout(function simulateMarketActivity() {
483
+ const activities = [
484
+ { title: 'Market Alert', message: 'Unusual trading volume detected in ETH/BTC pair', type: 'warning' },
485
+ { title: 'Stablecoin Update', message: 'RME-USD successfully maintained peg during market volatility', type: 'success' },
486
+ { title: 'New AI Model', message: 'A new Quantum-Symbolic hybrid model has been published to the marketplace', type: 'info' },
487
+ { title: 'Federated Learning', message: 'Cross-instance knowledge transfer complete with 23% accuracy improvement', type: 'success' },
488
+ { title: 'Security Alert', message: 'Potential adversarial attack detected and mitigated', type: 'warning' }
489
+ ];
490
+
491
+ const randomActivity = activities[Math.floor(Math.random() * activities.length)];
492
+ showNotification(randomActivity.title, randomActivity.message, randomActivity.type);
493
+
494
+ // Schedule next activity
495
+ const nextTime = 30000 + Math.random() * 60000; // Between 30s and 90s
496
+ setTimeout(simulateMarketActivity, nextTime);
497
+ }, 60000); // First activity after 60s
498
+
499
+ // Function to render symbolic network
500
+ function renderSymbolicNetwork() {
501
+ const svgElement = document.getElementById('symbolNetwork');
502
+ if (!svgElement) return;
503
+
504
+ // Use D3.js to create a network visualization
505
+ const width = 400;
506
+ const height = 200;
507
+
508
+ const svg = d3.select(svgElement);
509
+
510
+ // Generate sample data for the network
511
+ const nodes = Array.from({ length: 15 }, (_, i) => ({
512
+ id: i,
513
+ r: Math.random() * 5 + 3,
514
+ group: Math.floor(Math.random() * 3)
515
+ }));
516
+
517
+ const links = [];
518
+ for (let i = 0; i < nodes.length; i++) {
519
+ const numLinks = Math.floor(Math.random() * 3) + 1;
520
+ for (let j = 0; j < numLinks; j++) {
521
+ const target = Math.floor(Math.random() * nodes.length);
522
+ if (target !== i) {
523
+ links.push({ source: i, target: target, value: Math.random() });
524
+ }
525
+ }
526
+ }
527
+
528
+ // Create a force simulation
529
+ const simulation = d3.forceSimulation(nodes)
530
+ .force("link", d3.forceLink(links).id(d => d.id).distance(50))
531
+ .force("charge", d3.forceManyBody().strength(-30))
532
+ .force("center", d3.forceCenter(width / 2, height / 2));
533
+
534
+ // Add links
535
+ const link = svg.append("g")
536
+ .selectAll("line")
537
+ .data(links)
538
+ .enter().append("line")
539
+ .style("stroke", "#a29bfe")
540
+ .style("stroke-opacity", 0.6)
541
+ .style("stroke-width", d => Math.sqrt(d.value) * 2);
542
+
543
+ // Add nodes
544
+ const node = svg.append("g")
545
+ .selectAll("circle")
546
+ .data(nodes)
547
+ .enter().append("circle")
548
+ .attr("r", d => d.r)
549
+ .style("fill", d => ["#6c5ce7", "#00cec9", "#fd79a8"][d.group])
550
+ .call(d3.drag()
551
+ .on("start", dragstarted)
552
+ .on("drag", dragged)
553
+ .on("end", dragended));
554
+
555
+ // Add animation
556
+ const pulsingNodes = svg.append("g")
557
+ .selectAll("circle")
558
+ .data(nodes.filter(d => Math.random() > 0.7))
559
+ .enter().append("circle")
560
+ .attr("r", d => d.r + 5)
561
+ .style("fill", "none")
562
+ .style("stroke", d => ["#6c5ce7", "#00cec9", "#fd79a8"][d.group])
563
+ .style("stroke-opacity", 0.3)
564
+ .style("stroke-width", 2);
565
+
566
+ // Animate pulsing nodes
567
+ function pulsate() {
568
+ pulsingNodes
569
+ .transition()
570
+ .duration(1500)
571
+ .attr("r", d => d.r + 15)
572
+ .style("stroke-opacity", 0.1)
573
+ .transition()
574
+ .duration(1500)
575
+ .attr("r", d => d.r + 5)
576
+ .style("stroke-opacity", 0.3)
577
+ .on("end", pulsate);
578
+ }
579
+
580
+ pulsate();
581
+
582
+ simulation.on("tick", () => {
583
+ link
584
+ .attr("x1", d => Math.max(5, Math.min(width - 5, d.source.x)))
585
+ .attr("y1", d => Math.max(5, Math.min(height - 5, d.source.y)))
586
+ .attr("x2", d => Math.max(5, Math.min(width - 5, d.target.x)))
587
+ .attr("y2", d => Math.max(5, Math.min(height - 5, d.target.y)));
588
+
589
+ node
590
+ .attr("cx", d => Math.max(5, Math.min(width - 5, d.x)))
591
+ .attr("cy", d => Math.max(5, Math.min(height - 5, d.y)));
592
+
593
+ pulsingNodes
594
+ .attr("cx", d => Math.max(5, Math.min(width - 5, d.x)))
595
+ .attr("cy", d => Math.max(5, Math.min(height - 5, d.y)));
596
+ });
597
+
598
+ function dragstarted(event, d) {
599
+ if (!event.active) simulation.alphaTarget(0.3).restart();
600
+ d.fx = d.x;
601
+ d.fy = d.y;
602
+ }
603
+
604
+ function dragged(event, d) {
605
+ d.fx = event.x;
606
+ d.fy = event.y;
607
+ }
608
+
609
+ function dragended(event, d) {
610
+ if (!event.active) simulation.alphaTarget(0);
611
+ d.fx = null;
612
+ d.fy = null;
613
+ }
614
+ }
615
+
616
+ // Render learning trajectory chart
617
+ function renderLearningTrajectory() {
618
+ const canvas = document.getElementById('trajectoryCanvas');
619
+ if (!canvas) return;
620
+
621
+ // Create a simple SVG instead of Chart.js
622
+ const container = d3.select(canvas.parentNode);
623
+ canvas.remove(); // Remove the canvas element
624
+
625
+ const width = container.node().clientWidth;
626
+ const height = 200;
627
+
628
+ const svg = container.append('svg')
629
+ .attr('width', width)
630
+ .attr('height', height);
631
+
632
+ // Sample data
633
+ const data = [10, 15, 22, 28, 32, 35, 37, 45, 58, 67, 72, 76, 79, 82, 84, 85];
634
+
635
+ // Create scales
636
+ const x = d3.scaleLinear()
637
+ .domain([0, data.length - 1])
638
+ .range([20, width - 20]);
639
+
640
+ const y = d3.scaleLinear()
641
+ .domain([0, 100])
642
+ .range([height - 20, 20]);
643
+
644
+ // Create line
645
+ const line = d3.line()
646
+ .x((d, i) => x(i))
647
+ .y(d => y(d))
648
+ .curve(d3.curveMonotoneX);
649
+
650
+ // Draw line
651
+ svg.append('path')
652
+ .datum(data)
653
+ .attr('fill', 'none')
654
+ .attr('stroke', '#6c5ce7')
655
+ .attr('stroke-width', 2)
656
+ .attr('d', line);
657
+
658
+ // Add area below line
659
+ const area = d3.area()
660
+ .x((d, i) => x(i))
661
+ .y0(height - 20)
662
+ .y1(d => y(d))
663
+ .curve(d3.curveMonotoneX);
664
+
665
+ svg.append('path')
666
+ .datum(data)
667
+ .attr('fill', 'rgba(108, 92, 231, 0.1)')
668
+ .attr('d', area);
669
+ }
670
+
671
+ // Update research progress randomly to simulate ongoing research
672
+ function updateResearchProgress() {
673
+ const progressBar = document.querySelector('.research-progress .progress-value');
674
+ const progressLabel = document.querySelector('.progress-label span:last-child');
675
+
676
+ if (progressBar && progressLabel) {
677
+ const currentProgress = parseInt(progressBar.style.width);
678
+ let newProgress = currentProgress + Math.floor(Math.random() * 10) + 5;
679
+
680
+ // Cap at 95% to simulate ongoing research
681
+ if (newProgress > 95) newProgress = 95;
682
+
683
+ progressBar.style.width = newProgress + '%';
684
+ progressLabel.textContent = newProgress + '%';
685
+ }
686
+ }
687
+
688
+ // New function to initialize Research Lab Visualizations
689
+ function initResearchLab() {
690
+ loadLibraries().then(() => {
691
+ renderSymbolicNetwork();
692
+ renderLearningTrajectory();
693
+
694
+ // Add a delay to ensure Chart.js is properly initialized
695
+ setTimeout(() => {
696
+ renderMonetizationData();
697
+ }, 500);
698
+
699
+ // Add click handlers for research lab buttons
700
+ const actionButtons = document.querySelectorAll('.research-action-panel button');
701
+ actionButtons.forEach(button => {
702
+ button.addEventListener('click', function() {
703
+ showNotification('Deep Research', 'Initiating advanced research protocol. Processing data...', 'info');
704
+
705
+ // After a delay, show a research result notification
706
+ setTimeout(() => {
707
+ const researchFindings = [
708
+ 'Quantum-symbolic pattern discovered in market data. Potential arbitrage strategy identified with 15.2% ROI.',
709
+ 'Recursive AI model evolution complete. Performance improved by 23.7% with monetization potential of $34K/month.',
710
+ 'New monetization pathway identified: AI-driven prediction markets with 87% accuracy and estimated $182K annual revenue.',
711
+ 'Algorithmic stablecoin simulation shows 99.8% peg maintenance with recursive income generation of 12.3% APY.'
712
+ ];
713
+
714
+ const randomFinding = researchFindings[Math.floor(Math.random() * researchFindings.length)];
715
+ showNotification('Research Complete', randomFinding, 'success');
716
+
717
+ // Update progress bar
718
+ updateResearchProgress();
719
+ }, 3000);
720
+ });
721
+ });
722
+
723
+ // Initialize monetization metrics auto-update
724
+ updateMonetizationMetrics();
725
+ }).catch(error => {
726
+ console.error('Error loading libraries:', error);
727
+ });
728
+ }
729
+
730
+ // Function to update monetization metrics
731
+ function updateMonetizationMetrics() {
732
+ const metrics = {
733
+ 'modelSales': { base: 2450, variance: 150 },
734
+ 'subscriptions': { base: 3850, variance: 200 },
735
+ 'apiCalls': { base: 1250000, variance: 50000 },
736
+ 'defiYield': { base: 8.4, variance: 0.5 },
737
+ 'revenueQoQ': { base: 23.5, variance: 2.1 }
738
+ };
739
+
740
+ const updateMetric = (id, value) => {
741
+ const element = document.getElementById(id);
742
+ if (element) element.textContent = value;
743
+ };
744
+
745
+ // Initial update
746
+ Object.keys(metrics).forEach(metricId => {
747
+ const metric = metrics[metricId];
748
+ const value = metric.base + (Math.random() * 2 - 1) * metric.variance;
749
+
750
+ if (metricId === 'apiCalls') {
751
+ updateMetric(metricId, `${Math.round(value).toLocaleString()}`);
752
+ } else if (metricId === 'defiYield' || metricId === 'revenueQoQ') {
753
+ updateMetric(metricId, `${value.toFixed(1)}%`);
754
+ } else {
755
+ updateMetric(metricId, `$${Math.round(value).toLocaleString()}`);
756
+ }
757
+ });
758
+
759
+ // Schedule next update
760
+ setTimeout(updateMonetizationMetrics, 15000);
761
+ }
762
+
763
+ // New function to initialize monetization research section
764
+ function initMonetizationResearch() {
765
+ loadLibraries().then(() => {
766
+ renderMonetizationData();
767
+ initRecursiveModels();
768
+ updateRMEMetrics();
769
+ renderSymbolicSequence();
770
+ });
771
+ }
772
+
773
+ // Function to render symbolic sequence visualization
774
+ function renderSymbolicSequence() {
775
+ const canvas = document.getElementById('symbolicSequenceCanvas');
776
+ if (!canvas) return;
777
+
778
+ const ctx = canvas.getContext('2d');
779
+ const width = canvas.width;
780
+ const height = canvas.height;
781
+
782
+ // Clear canvas
783
+ ctx.clearRect(0, 0, width, height);
784
+
785
+ // Draw background
786
+ const gradient = ctx.createLinearGradient(0, 0, width, 0);
787
+ gradient.addColorStop(0, 'rgba(108, 92, 231, 0.1)');
788
+ gradient.addColorStop(0.5, 'rgba(0, 206, 201, 0.1)');
789
+ gradient.addColorStop(1, 'rgba(253, 121, 168, 0.1)');
790
+ ctx.fillStyle = gradient;
791
+ ctx.fillRect(0, 0, width, height);
792
+
793
+ // Draw the symbolic sequence
794
+ ctx.font = '16px Monaco, Courier New, monospace';
795
+ ctx.fillStyle = '#6c5ce7';
796
+ ctx.textAlign = 'center';
797
+
798
+ const formula1 = "Qi∞(Φ⟨Creativity⟩ ⊗ Λ⟨Recursive Logic⟩)";
799
+ const formula2 = "→ Σ⟨Exploration⟩ ∇⟨Adaptive Insight⟩";
800
+ const formula3 = "→ Ω⟨Market Resonance⟩ ⊕ Θ⟨Quantum Integration⟩";
801
+ const formula4 = "→ Δ⟨Continuous Innovation⟩";
802
+
803
+ ctx.fillText(formula1, width/2, height/5);
804
+ ctx.fillText(formula2, width/2, 2*height/5);
805
+ ctx.fillText(formula3, width/2, 3*height/5);
806
+ ctx.fillText(formula4, width/2, 4*height/5);
807
+
808
+ // Add animated particles
809
+ const particles = [];
810
+ for (let i = 0; i < 50; i++) {
811
+ particles.push({
812
+ x: Math.random() * width,
813
+ y: Math.random() * height,
814
+ radius: Math.random() * 3 + 1,
815
+ color: `rgba(${Math.floor(Math.random() * 100 + 100)}, ${Math.floor(Math.random() * 100 + 100)}, ${Math.floor(Math.random() * 100 + 150)}, 0.5)`,
816
+ speedX: Math.random() * 1 - 0.5,
817
+ speedY: Math.random() * 1 - 0.5
818
+ });
819
+ }
820
+
821
+ function animateParticles() {
822
+ ctx.clearRect(0, 0, width, height);
823
+
824
+ // Redraw background
825
+ ctx.fillStyle = gradient;
826
+ ctx.fillRect(0, 0, width, height);
827
+
828
+ // Redraw formulas
829
+ ctx.font = '16px Monaco, Courier New, monospace';
830
+ ctx.fillStyle = '#6c5ce7';
831
+ ctx.textAlign = 'center';
832
+ ctx.fillText(formula1, width/2, height/5);
833
+ ctx.fillText(formula2, width/2, 2*height/5);
834
+ ctx.fillText(formula3, width/2, 3*height/5);
835
+ ctx.fillText(formula4, width/2, 4*height/5);
836
+
837
+ // Draw and update particles
838
+ particles.forEach(particle => {
839
+ ctx.beginPath();
840
+ ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
841
+ ctx.fillStyle = particle.color;
842
+ ctx.fill();
843
+
844
+ particle.x += particle.speedX;
845
+ particle.y += particle.speedY;
846
+
847
+ // Wrap around edges
848
+ if (particle.x < 0) particle.x = width;
849
+ if (particle.x > width) particle.x = 0;
850
+ if (particle.y < 0) particle.y = height;
851
+ if (particle.y > height) particle.y = 0;
852
+ });
853
+
854
+ requestAnimationFrame(animateParticles);
855
+ }
856
+
857
+ animateParticles();
858
+ }
859
+
860
+ // Initialize recursive AI models visualization
861
+ function initRecursiveModels() {
862
+ const canvas = document.getElementById('recursiveModelCanvas');
863
+ if (!canvas) return;
864
+
865
+ const ctx = canvas.getContext('2d');
866
+ const width = canvas.width;
867
+ const height = canvas.height;
868
+
869
+ // Generate nodes representing AI models
870
+ const nodes = [];
871
+ for (let i = 0; i < 20; i++) {
872
+ nodes.push({
873
+ x: Math.random() * width,
874
+ y: Math.random() * height,
875
+ radius: Math.random() * 10 + 5,
876
+ color: i < 5 ? '#6c5ce7' : (i < 10 ? '#00cec9' : '#fd79a8'),
877
+ connections: []
878
+ });
879
+ }
880
+
881
+ // Create connections between nodes
882
+ nodes.forEach((node, index) => {
883
+ const numConnections = Math.floor(Math.random() * 3) + 1;
884
+ for (let i = 0; i < numConnections; i++) {
885
+ const targetIndex = Math.floor(Math.random() * nodes.length);
886
+ if (targetIndex !== index) {
887
+ node.connections.push(targetIndex);
888
+ }
889
+ }
890
+ });
891
+
892
+ function render() {
893
+ ctx.clearRect(0, 0, width, height);
894
+
895
+ // Draw connections
896
+ nodes.forEach((node, index) => {
897
+ node.connections.forEach(targetIndex => {
898
+ const target = nodes[targetIndex];
899
+ ctx.beginPath();
900
+ ctx.moveTo(node.x, node.y);
901
+ ctx.lineTo(target.x, target.y);
902
+ ctx.strokeStyle = 'rgba(108, 92, 231, 0.2)';
903
+ ctx.lineWidth = 1;
904
+ ctx.stroke();
905
+ });
906
+ });
907
+
908
+ // Draw nodes
909
+ nodes.forEach(node => {
910
+ ctx.beginPath();
911
+ ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
912
+ ctx.fillStyle = node.color;
913
+ ctx.fill();
914
+
915
+ // Add a pulsing effect
916
+ ctx.beginPath();
917
+ ctx.arc(node.x, node.y, node.radius + 3 + Math.sin(Date.now() / 500) * 2, 0, Math.PI * 2);
918
+ ctx.strokeStyle = node.color.replace(')', ', 0.3)').replace('rgb', 'rgba');
919
+ ctx.stroke();
920
+
921
+ // Move nodes slightly for animation
922
+ node.x += (Math.random() * 2 - 1) * 0.5;
923
+ node.y += (Math.random() * 2 - 1) * 0.5;
924
+
925
+ // Keep within bounds
926
+ if (node.x < node.radius) node.x = node.radius;
927
+ if (node.x > width - node.radius) node.x = width - node.radius;
928
+ if (node.y < node.radius) node.y = node.radius;
929
+ if (node.y > height - node.radius) node.y = height - node.radius;
930
+ });
931
+
932
+ requestAnimationFrame(render);
933
+ }
934
+
935
+ render();
936
+ }
937
+
938
+ // Update RME metrics periodically
939
+ function updateRMEMetrics() {
940
+ const metrics = {
941
+ 'modelMarketplace': { base: 2840, variance: 160 },
942
+ 'dataFeeds': { base: 4250, variance: 220 },
943
+ 'quantumComputing': { base: 1650, variance: 120 },
944
+ 'recursiveGrowth': { base: 32.7, variance: 1.8 },
945
+ 'monetizationIndex': { base: 87.3, variance: 2.5 }
946
+ };
947
+
948
+ function updateMetric(id, value, format = 'number') {
949
+ const element = document.getElementById(id);
950
+ if (!element) return;
951
+
952
+ if (format === 'currency') {
953
+ element.textContent = `$${Math.round(value).toLocaleString()}`;
954
+ } else if (format === 'percent') {
955
+ element.textContent = `${value.toFixed(1)}%`;
956
+ } else {
957
+ element.textContent = value.toLocaleString();
958
+ }
959
+ }
960
+
961
+ // Initial update
962
+ Object.keys(metrics).forEach(metricId => {
963
+ const metric = metrics[metricId];
964
+ const value = metric.base + (Math.random() * 2 - 1) * metric.variance;
965
+ const format = metricId.includes('Growth') || metricId.includes('Index') ? 'percent' : 'currency';
966
+ updateMetric(metricId, value, format);
967
+ });
968
+
969
+ // Schedule next update
970
+ setTimeout(updateRMEMetrics, 8000);
971
+ }
972
+
973
+ // Function to render monetization data
974
+ function renderMonetizationData() {
975
+ const monetizationCtx = document.getElementById('monetizationChart');
976
+ if (!monetizationCtx) return;
977
+
978
+ // Create a simple SVG instead of Chart.js
979
+ const container = d3.select(monetizationCtx);
980
+ container.html(''); // Clear previous content
981
+
982
+ const width = container.node().clientWidth;
983
+ const height = container.node().clientHeight || 300;
984
+
985
+ const svg = container.append('svg')
986
+ .attr('width', width)
987
+ .attr('height', height);
988
+
989
+ // Create a circular grid
990
+ const centerX = width / 2;
991
+ const centerY = height / 2;
992
+ const radius = Math.min(width, height) / 2 - 40;
993
+
994
+ // Draw radar grid
995
+ const categories = [
996
+ 'AI Model Marketplace',
997
+ 'Data Feed Subscriptions',
998
+ 'DeFi Integration',
999
+ 'Quantum-Symbolic Risk',
1000
+ 'Insurance Products',
1001
+ 'Stablecoin Revenues'
1002
+ ];
1003
+
1004
+ const angleSlice = Math.PI * 2 / categories.length;
1005
+
1006
+ // Draw axes
1007
+ categories.forEach((cat, i) => {
1008
+ const angle = i * angleSlice - Math.PI / 2;
1009
+ const lineX2 = centerX + radius * Math.cos(angle);
1010
+ const lineY2 = centerY + radius * Math.sin(angle);
1011
+
1012
+ svg.append('line')
1013
+ .attr('x1', centerX)
1014
+ .attr('y1', centerY)
1015
+ .attr('x2', lineX2)
1016
+ .attr('y2', lineY2)
1017
+ .attr('stroke', '#dfe6e9')
1018
+ .attr('stroke-width', 1);
1019
+
1020
+ // Add labels
1021
+ const labelX = centerX + (radius + 20) * Math.cos(angle);
1022
+ const labelY = centerY + (radius + 20) * Math.sin(angle);
1023
+
1024
+ svg.append('text')
1025
+ .attr('x', labelX)
1026
+ .attr('y', labelY)
1027
+ .attr('text-anchor', 'middle')
1028
+ .attr('alignment-baseline', 'middle')
1029
+ .attr('font-size', '10px')
1030
+ .text(cat);
1031
+ });
1032
+
1033
+ // Draw concentric circles
1034
+ [0.2, 0.4, 0.6, 0.8, 1].forEach(r => {
1035
+ svg.append('circle')
1036
+ .attr('cx', centerX)
1037
+ .attr('cy', centerY)
1038
+ .attr('r', radius * r)
1039
+ .attr('fill', 'none')
1040
+ .attr('stroke', '#dfe6e9')
1041
+ .attr('stroke-width', 1);
1042
+ });
1043
+
1044
+ // Sample data
1045
+ const currentData = [65, 78, 35, 28, 42, 30].map(val => val / 100);
1046
+ const potentialData = [85, 90, 75, 68, 80, 85].map(val => val / 100);
1047
+
1048
+ // Draw polygons
1049
+ function drawPolygon(data, color, opacity) {
1050
+ const points = data.map((val, i) => {
1051
+ const angle = i * angleSlice - Math.PI / 2;
1052
+ const x = centerX + radius * val * Math.cos(angle);
1053
+ const y = centerY + radius * val * Math.sin(angle);
1054
+ return `${x},${y}`;
1055
+ }).join(' ');
1056
+
1057
+ svg.append('polygon')
1058
+ .attr('points', points)
1059
+ .attr('fill', color)
1060
+ .attr('fill-opacity', opacity)
1061
+ .attr('stroke', color)
1062
+ .attr('stroke-width', 2);
1063
+ }
1064
+
1065
+ drawPolygon(currentData, 'rgba(108, 92, 231, 1)', 0.2);
1066
+ drawPolygon(potentialData, 'rgba(0, 206, 201, 1)', 0.2);
1067
+
1068
+ // Add legend
1069
+ const legend = svg.append('g')
1070
+ .attr('transform', `translate(${width - 140},20)`);
1071
+
1072
+ const legendItems = [
1073
+ {label: 'Current Revenue', color: 'rgba(108, 92, 231, 1)'},
1074
+ {label: 'Growth Potential', color: 'rgba(0, 206, 201, 1)'}
1075
+ ];
1076
+
1077
+ legendItems.forEach((item, i) => {
1078
+ legend.append('rect')
1079
+ .attr('x', 0)
1080
+ .attr('y', i * 20)
1081
+ .attr('width', 15)
1082
+ .attr('height', 15)
1083
+ .attr('fill', item.color)
1084
+ .attr('fill-opacity', 0.2)
1085
+ .attr('stroke', item.color);
1086
+
1087
+ legend.append('text')
1088
+ .attr('x', 20)
1089
+ .attr('y', i * 20 + 12)
1090
+ .attr('font-size', '12px')
1091
+ .text(item.label);
1092
+ });
1093
+
1094
+ // Forecast chart
1095
+ const forecastCtx = document.getElementById('forecastChart');
1096
+ if (!forecastCtx) return;
1097
+
1098
+ // Create a simple line graph for forecast
1099
+ const forecastContainer = d3.select(forecastCtx);
1100
+ forecastContainer.html(''); // Clear previous content
1101
+
1102
+ const forecastWidth = forecastContainer.node().clientWidth;
1103
+ const forecastHeight = forecastContainer.node().clientHeight || 300;
1104
+ const margin = {top: 20, right: 60, bottom: 30, left: 60};
1105
+
1106
+ const forecastSvg = forecastContainer.append('svg')
1107
+ .attr('width', forecastWidth)
1108
+ .attr('height', forecastHeight)
1109
+ .append('g')
1110
+ .attr('transform', `translate(${margin.left},${margin.top})`);
1111
+
1112
+ // Generate sample data
1113
+ const months = 24;
1114
+ const baselineGrowth = Array.from({length: months}, (_, i) => 1000 * Math.pow(1.08, i));
1115
+ const recursiveGrowth = Array.from({length: months}, (_, i) => 1000 * Math.pow(1.15, i));
1116
+ const quantumBoostGrowth = Array.from({length: months}, (_, i) => {
1117
+ const quantumBoost = i > 12 ? 1.2 : 1;
1118
+ return 1000 * Math.pow(1.15, i) * quantumBoost;
1119
+ });
1120
+
1121
+ // Scales
1122
+ const xForecast = d3.scaleLinear()
1123
+ .domain([1, months])
1124
+ .range([0, forecastWidth - margin.left - margin.right]);
1125
+
1126
+ const yForecast = d3.scaleLinear()
1127
+ .domain([0, d3.max(quantumBoostGrowth)])
1128
+ .nice()
1129
+ .range([forecastHeight - margin.top - margin.bottom, 0]);
1130
+
1131
+ // Axes
1132
+ forecastSvg.append('g')
1133
+ .attr('transform', `translate(0,${forecastHeight - margin.top - margin.bottom})`)
1134
+ .call(d3.axisBottom(xForecast).ticks(6).tickFormat(d => `M${d}`));
1135
+
1136
+ forecastSvg.append('g')
1137
+ .call(d3.axisLeft(yForecast));
1138
+
1139
+ // Line generator
1140
+ const line = d3.line()
1141
+ .x((d, i) => xForecast(i + 1))
1142
+ .y(d => yForecast(d))
1143
+ .curve(d3.curveMonotoneX);
1144
+
1145
+ // Draw lines
1146
+ forecastSvg.append('path')
1147
+ .datum(baselineGrowth)
1148
+ .attr('fill', 'none')
1149
+ .attr('stroke', '#dfe6e9')
1150
+ .attr('stroke-width', 2)
1151
+ .attr('d', line);
1152
+
1153
+ forecastSvg.append('path')
1154
+ .datum(recursiveGrowth)
1155
+ .attr('fill', 'none')
1156
+ .attr('stroke', '#6c5ce7')
1157
+ .attr('stroke-width', 2)
1158
+ .attr('d', line);
1159
+
1160
+ forecastSvg.append('path')
1161
+ .datum(quantumBoostGrowth)
1162
+ .attr('fill', 'none')
1163
+ .attr('stroke', '#00cec9')
1164
+ .attr('stroke-width', 2)
1165
+ .attr('d', line);
1166
+
1167
+ // Add legend
1168
+ const forecastLegend = forecastSvg.append('g')
1169
+ .attr('transform', `translate(${forecastWidth - margin.left - margin.right - 150},0)`);
1170
+
1171
+ const forecastLegendItems = [
1172
+ {label: 'Baseline Growth', color: '#dfe6e9'},
1173
+ {label: 'Recursive Growth', color: '#6c5ce7'},
1174
+ {label: 'Quantum-Boosted', color: '#00cec9'}
1175
+ ];
1176
+
1177
+ forecastLegendItems.forEach((item, i) => {
1178
+ forecastLegend.append('line')
1179
+ .attr('x1', 0)
1180
+ .attr('y1', i * 20 + 10)
1181
+ .attr('x2', 20)
1182
+ .attr('y2', i * 20 + 10)
1183
+ .attr('stroke', item.color)
1184
+ .attr('stroke-width', 2);
1185
+
1186
+ forecastLegend.append('text')
1187
+ .attr('x', 25)
1188
+ .attr('y', i * 20 + 15)
1189
+ .attr('font-size', '12px')
1190
+ .text(item.label);
1191
+ });
1192
+ }