@@ -1594,10 +1594,14 @@ <h3>P95 Latency</h3>
15941594 < div class ="metric-card ">
15951595 < div class ="icon "> < i class ="fas fa-database "> </ i > </ div >
15961596 < h3 > Storage Efficiency</ h3 >
1597- < div class ="metric-value success " id ="storageEfficiency "> 24%</ div >
1598- < div class ="metric-target "> Post-consolidation ratio</ div >
1599- < div class ="progress-bar ">
1600- < div class ="progress-fill " style ="width: 24% "> </ div >
1597+ < div class ="metric-value success " id ="storageEfficiency "> 7.2 TB</ div >
1598+ < div class ="metric-target "> Space saved by compression</ div >
1599+ < div class ="sparkline-container ">
1600+ < canvas id ="storageSparkline " class ="sparkline-chart "> </ canvas >
1601+ < div class ="sparkline-info ">
1602+ < span class ="sparkline-trend " id ="storageTrend "> ↑ 0.3 TB</ span >
1603+ < span class ="sparkline-period "> Last 7d</ span >
1604+ </ div >
16011605 </ div >
16021606 < div class ="status-indicator success ">
16031607 < i class ="fas fa-compress-arrows-alt "> </ i > Optimized
@@ -1659,10 +1663,14 @@ <h3>API Performance</h3>
16591663 < div class ="metric-card ">
16601664 < div class ="icon "> < i class ="fas fa-rocket "> </ i > </ div >
16611665 < h3 > Memory Velocity</ h3 >
1662- < div class ="metric-value success " id ="memoryVelocity "> 2.8GB/s</ div >
1663- < div class ="metric-target "> Target: > 2.0GB/s</ div >
1664- < div class ="progress-bar ">
1665- < div class ="progress-fill " style ="width: 140% "> </ div >
1666+ < div class ="metric-value success " id ="memoryVelocity "> 1,847</ div >
1667+ < div class ="metric-target "> Memories processed/hour</ div >
1668+ < div class ="sparkline-container ">
1669+ < canvas id ="velocitySparkline " class ="sparkline-chart "> </ canvas >
1670+ < div class ="sparkline-info ">
1671+ < span class ="sparkline-trend " id ="velocityTrend "> ↑ 127</ span >
1672+ < span class ="sparkline-period "> Last 24h</ span >
1673+ </ div >
16661674 </ div >
16671675 < div class ="status-indicator success ">
16681676 < i class ="fas fa-check-circle "> </ i > High Throughput
@@ -1672,10 +1680,14 @@ <h3>Memory Velocity</h3>
16721680 < div class ="metric-card ">
16731681 < div class ="icon "> < i class ="fas fa-search-plus "> </ i > </ div >
16741682 < h3 > Pattern Discovery Rate</ h3 >
1675- < div class ="metric-value success " id ="patternDiscoveryRateCard "> 4.2/hr</ div >
1676- < div class ="metric-target "> Target: > 3.0/hr</ div >
1677- < div class ="progress-bar ">
1678- < div class ="progress-fill " style ="width: 140% "> </ div >
1683+ < div class ="metric-value success " id ="patternDiscoveryRateCard "> 73.2%</ div >
1684+ < div class ="metric-target "> Pattern recognition accuracy</ div >
1685+ < div class ="sparkline-container ">
1686+ < canvas id ="patternSparkline " class ="sparkline-chart "> </ canvas >
1687+ < div class ="sparkline-info ">
1688+ < span class ="sparkline-trend " id ="patternTrend "> ↑ 2.1%</ span >
1689+ < span class ="sparkline-period "> Last 24h</ span >
1690+ </ div >
16791691 </ div >
16801692 < div class ="status-indicator success ">
16811693 < i class ="fas fa-check-circle "> </ i > Above Target
@@ -2462,15 +2474,46 @@ <h4>🚀 Production Features:</h4>
24622474 let p95LatencyData = [ ] ;
24632475 const MAX_SPARKLINE_POINTS = 48 ; // 24 hours worth of data (30min intervals)
24642476
2477+ // Storage Efficiency Sparkline Data
2478+ let storageData = [ ] ;
2479+
2480+ // Memory Velocity Sparkline Data
2481+ let velocityData = [ ] ;
2482+
2483+ // Pattern Discovery Sparkline Data
2484+ let patternData = [ ] ;
2485+
24652486 // Initialize with sample data
24662487 function initializeSparklineData ( ) {
24672488 p95LatencyData = [ ] ;
2489+ storageData = [ ] ;
2490+ velocityData = [ ] ;
2491+ patternData = [ ] ;
2492+
24682493 for ( let i = 0 ; i < MAX_SPARKLINE_POINTS ; i ++ ) {
2469- // Generate realistic latency data with some variation
2494+ // P95 Latency data
24702495 const baseLatency = 38 ;
2471- const variation = ( Math . random ( ) - 0.5 ) * 10 ; // ±5ms variation
2472- const value = Math . max ( 25 , Math . min ( 50 , baseLatency + variation ) ) ;
2473- p95LatencyData . push ( value ) ;
2496+ const latencyVariation = ( Math . random ( ) - 0.5 ) * 10 ; // ±5ms variation
2497+ const latencyValue = Math . max ( 25 , Math . min ( 50 , baseLatency + latencyVariation ) ) ;
2498+ p95LatencyData . push ( latencyValue ) ;
2499+
2500+ // Storage Efficiency data (in TB)
2501+ const baseStorage = 7.2 ;
2502+ const storageVariation = ( Math . random ( ) - 0.5 ) * 0.8 ; // ±0.4TB variation
2503+ const storageValue = Math . max ( 6.0 , Math . min ( 8.5 , baseStorage + storageVariation ) ) ;
2504+ storageData . push ( storageValue ) ;
2505+
2506+ // Memory Velocity data (memories/hour)
2507+ const baseVelocity = 1847 ;
2508+ const velocityVariation = ( Math . random ( ) - 0.5 ) * 300 ; // ±150 variation
2509+ const velocityValue = Math . max ( 1400 , Math . min ( 2200 , baseVelocity + velocityVariation ) ) ;
2510+ velocityData . push ( velocityValue ) ;
2511+
2512+ // Pattern Discovery data (accuracy %)
2513+ const basePattern = 73.2 ;
2514+ const patternVariation = ( Math . random ( ) - 0.5 ) * 8 ; // ±4% variation
2515+ const patternValue = Math . max ( 65 , Math . min ( 85 , basePattern + patternVariation ) ) ;
2516+ patternData . push ( patternValue ) ;
24742517 }
24752518 }
24762519
@@ -2482,6 +2525,30 @@ <h4>🚀 Production Features:</h4>
24822525 drawSparkline ( ) ;
24832526 }
24842527
2528+ function updateStorageSparkline ( newValue ) {
2529+ if ( storageData . length >= MAX_SPARKLINE_POINTS ) {
2530+ storageData . shift ( ) ;
2531+ }
2532+ storageData . push ( newValue ) ;
2533+ drawStorageSparkline ( ) ;
2534+ }
2535+
2536+ function updateVelocitySparkline ( newValue ) {
2537+ if ( velocityData . length >= MAX_SPARKLINE_POINTS ) {
2538+ velocityData . shift ( ) ;
2539+ }
2540+ velocityData . push ( newValue ) ;
2541+ drawVelocitySparkline ( ) ;
2542+ }
2543+
2544+ function updatePatternSparkline ( newValue ) {
2545+ if ( patternData . length >= MAX_SPARKLINE_POINTS ) {
2546+ patternData . shift ( ) ;
2547+ }
2548+ patternData . push ( newValue ) ;
2549+ drawPatternSparkline ( ) ;
2550+ }
2551+
24852552 function drawSparkline ( ) {
24862553 const canvas = document . getElementById ( 'p95Sparkline' ) ;
24872554 if ( ! canvas ) return ;
@@ -2562,6 +2629,195 @@ <h4>🚀 Production Features:</h4>
25622629 }
25632630 }
25642631
2632+ // Storage Efficiency Sparkline
2633+ function drawStorageSparkline ( ) {
2634+ const canvas = document . getElementById ( 'storageSparkline' ) ;
2635+ if ( ! canvas ) return ;
2636+
2637+ const ctx = canvas . getContext ( '2d' ) ;
2638+ const rect = canvas . getBoundingClientRect ( ) ;
2639+ canvas . width = rect . width * window . devicePixelRatio ;
2640+ canvas . height = rect . height * window . devicePixelRatio ;
2641+ ctx . scale ( window . devicePixelRatio , window . devicePixelRatio ) ;
2642+
2643+ const width = rect . width ;
2644+ const height = rect . height ;
2645+
2646+ ctx . clearRect ( 0 , 0 , width , height ) ;
2647+
2648+ if ( storageData . length < 2 ) return ;
2649+
2650+ const min = Math . min ( ...storageData ) ;
2651+ const max = Math . max ( ...storageData ) ;
2652+ const range = max - min || 1 ;
2653+
2654+ ctx . beginPath ( ) ;
2655+ ctx . strokeStyle = '#b8bb26' ; // Gruvbox green
2656+ ctx . lineWidth = 2 ;
2657+
2658+ const stepX = width / ( storageData . length - 1 ) ;
2659+
2660+ storageData . forEach ( ( value , index ) => {
2661+ const x = index * stepX ;
2662+ const y = height - ( ( value - min ) / range ) * height ;
2663+
2664+ if ( index === 0 ) {
2665+ ctx . moveTo ( x , y ) ;
2666+ } else {
2667+ ctx . lineTo ( x , y ) ;
2668+ }
2669+ } ) ;
2670+
2671+ ctx . stroke ( ) ;
2672+ updateStorageTrend ( ) ;
2673+ }
2674+
2675+ function updateStorageTrend ( ) {
2676+ const trendElement = document . getElementById ( 'storageTrend' ) ;
2677+ if ( ! trendElement || storageData . length < 2 ) return ;
2678+
2679+ const current = storageData [ storageData . length - 1 ] ;
2680+ const previous = storageData [ storageData . length - 2 ] ;
2681+ const change = current - previous ;
2682+
2683+ if ( Math . abs ( change ) < 0.05 ) {
2684+ trendElement . textContent = '→ Stable' ;
2685+ trendElement . className = 'sparkline-trend' ;
2686+ } else if ( change > 0 ) {
2687+ trendElement . textContent = `↗ +${ change . toFixed ( 1 ) } TB` ;
2688+ trendElement . className = 'sparkline-trend up' ;
2689+ } else {
2690+ trendElement . textContent = `↘ ${ change . toFixed ( 1 ) } TB` ;
2691+ trendElement . className = 'sparkline-trend down' ;
2692+ }
2693+ }
2694+
2695+ // Memory Velocity Sparkline
2696+ function drawVelocitySparkline ( ) {
2697+ const canvas = document . getElementById ( 'velocitySparkline' ) ;
2698+ if ( ! canvas ) return ;
2699+
2700+ const ctx = canvas . getContext ( '2d' ) ;
2701+ const rect = canvas . getBoundingClientRect ( ) ;
2702+ canvas . width = rect . width * window . devicePixelRatio ;
2703+ canvas . height = rect . height * window . devicePixelRatio ;
2704+ ctx . scale ( window . devicePixelRatio , window . devicePixelRatio ) ;
2705+
2706+ const width = rect . width ;
2707+ const height = rect . height ;
2708+
2709+ ctx . clearRect ( 0 , 0 , width , height ) ;
2710+
2711+ if ( velocityData . length < 2 ) return ;
2712+
2713+ const min = Math . min ( ...velocityData ) ;
2714+ const max = Math . max ( ...velocityData ) ;
2715+ const range = max - min || 1 ;
2716+
2717+ ctx . beginPath ( ) ;
2718+ ctx . strokeStyle = '#b8bb26' ; // Gruvbox green
2719+ ctx . lineWidth = 2 ;
2720+
2721+ const stepX = width / ( velocityData . length - 1 ) ;
2722+
2723+ velocityData . forEach ( ( value , index ) => {
2724+ const x = index * stepX ;
2725+ const y = height - ( ( value - min ) / range ) * height ;
2726+
2727+ if ( index === 0 ) {
2728+ ctx . moveTo ( x , y ) ;
2729+ } else {
2730+ ctx . lineTo ( x , y ) ;
2731+ }
2732+ } ) ;
2733+
2734+ ctx . stroke ( ) ;
2735+ updateVelocityTrend ( ) ;
2736+ }
2737+
2738+ function updateVelocityTrend ( ) {
2739+ const trendElement = document . getElementById ( 'velocityTrend' ) ;
2740+ if ( ! trendElement || velocityData . length < 2 ) return ;
2741+
2742+ const current = velocityData [ velocityData . length - 1 ] ;
2743+ const previous = velocityData [ velocityData . length - 2 ] ;
2744+ const change = current - previous ;
2745+
2746+ if ( Math . abs ( change ) < 5 ) {
2747+ trendElement . textContent = '→ Stable' ;
2748+ trendElement . className = 'sparkline-trend' ;
2749+ } else if ( change > 0 ) {
2750+ trendElement . textContent = `↗ +${ Math . round ( change ) } ` ;
2751+ trendElement . className = 'sparkline-trend up' ;
2752+ } else {
2753+ trendElement . textContent = `↘ ${ Math . round ( change ) } ` ;
2754+ trendElement . className = 'sparkline-trend down' ;
2755+ }
2756+ }
2757+
2758+ // Pattern Discovery Sparkline
2759+ function drawPatternSparkline ( ) {
2760+ const canvas = document . getElementById ( 'patternSparkline' ) ;
2761+ if ( ! canvas ) return ;
2762+
2763+ const ctx = canvas . getContext ( '2d' ) ;
2764+ const rect = canvas . getBoundingClientRect ( ) ;
2765+ canvas . width = rect . width * window . devicePixelRatio ;
2766+ canvas . height = rect . height * window . devicePixelRatio ;
2767+ ctx . scale ( window . devicePixelRatio , window . devicePixelRatio ) ;
2768+
2769+ const width = rect . width ;
2770+ const height = rect . height ;
2771+
2772+ ctx . clearRect ( 0 , 0 , width , height ) ;
2773+
2774+ if ( patternData . length < 2 ) return ;
2775+
2776+ const min = Math . min ( ...patternData ) ;
2777+ const max = Math . max ( ...patternData ) ;
2778+ const range = max - min || 1 ;
2779+
2780+ ctx . beginPath ( ) ;
2781+ ctx . strokeStyle = '#b8bb26' ; // Gruvbox green
2782+ ctx . lineWidth = 2 ;
2783+
2784+ const stepX = width / ( patternData . length - 1 ) ;
2785+
2786+ patternData . forEach ( ( value , index ) => {
2787+ const x = index * stepX ;
2788+ const y = height - ( ( value - min ) / range ) * height ;
2789+
2790+ if ( index === 0 ) {
2791+ ctx . moveTo ( x , y ) ;
2792+ } else {
2793+ ctx . lineTo ( x , y ) ;
2794+ }
2795+ } ) ;
2796+
2797+ ctx . stroke ( ) ;
2798+ updatePatternTrend ( ) ;
2799+ }
2800+
2801+ function updatePatternTrend ( ) {
2802+ const trendElement = document . getElementById ( 'patternTrend' ) ;
2803+ if ( ! trendElement || patternData . length < 2 ) return ;
2804+
2805+ const current = patternData [ patternData . length - 1 ] ;
2806+ const previous = patternData [ patternData . length - 2 ] ;
2807+ const change = current - previous ;
2808+
2809+ if ( Math . abs ( change ) < 0.1 ) {
2810+ trendElement . textContent = '→ Stable' ;
2811+ trendElement . className = 'sparkline-trend' ;
2812+ } else if ( change > 0 ) {
2813+ trendElement . textContent = `↗ +${ change . toFixed ( 1 ) } %` ;
2814+ trendElement . className = 'sparkline-trend up' ;
2815+ } else {
2816+ trendElement . textContent = `↘ ${ change . toFixed ( 1 ) } %` ;
2817+ trendElement . className = 'sparkline-trend down' ;
2818+ }
2819+ }
2820+
25652821 // Close modal when clicking outside
25662822 window . onclick = function ( event ) {
25672823 const modals = document . querySelectorAll ( '.branch-modal' ) ;
@@ -2599,6 +2855,9 @@ <h4>🚀 Production Features:</h4>
25992855 // Initial sparkline draw
26002856 setTimeout ( ( ) => {
26012857 drawSparkline ( ) ;
2858+ drawStorageSparkline ( ) ;
2859+ drawVelocitySparkline ( ) ;
2860+ drawPatternSparkline ( ) ;
26022861 } , 100 ) ;
26032862 } ) ;
26042863
@@ -3452,14 +3711,14 @@ <h4>🚀 Production Features:</h4>
34523711 function updateMetrics ( ) {
34533712 // Simulate real system performance data updates
34543713 const elements = [
3455- { id : 'p95Latency' , current : 38 , min : 35 , max : 48 , suffix : 'ms' } ,
3456- { id : 'storageEfficiency' , current : 24 , min : 22 , max : 26 , suffix : '% ' } ,
3714+ { id : 'p95Latency' , current : 38 , min : 35 , max : 48 , suffix : 'ms' , sparkline : 'p95' } ,
3715+ { id : 'storageEfficiency' , current : 7.2 , min : 6.5 , max : 8.0 , suffix : ' TB' , decimal : 1 , sparkline : 'storage ' } ,
34573716 { id : 'predictionAccuracy' , current : 89.2 , min : 87.5 , max : 91.0 , suffix : '%' , decimal : 1 } ,
34583717 { id : 'relevancePrecision' , current : 91.7 , min : 90.0 , max : 93.5 , suffix : '%' , decimal : 1 } ,
34593718 { id : 'cacheHitRate' , current : 94.3 , min : 92.0 , max : 96.0 , suffix : '%' , decimal : 1 } ,
34603719 { id : 'apiPerformance' , current : 99.1 , min : 98.5 , max : 99.8 , suffix : '%' , decimal : 1 } ,
3461- { id : 'memoryVelocity' , current : 2.8 , min : 2.5 , max : 3.2 , suffix : 'GB/s ' , decimal : 1 } ,
3462- { id : 'patternDiscoveryRateCard' , current : 4 .2, min : 3.8 , max : 4.6 , suffix : '/hr ' , decimal : 1 }
3720+ { id : 'memoryVelocity' , current : 1847 , min : 1600 , max : 2100 , suffix : '' , sparkline : 'velocity' } ,
3721+ { id : 'patternDiscoveryRateCard' , current : 73 .2, min : 68.0 , max : 78.0 , suffix : '% ' , decimal : 1 , sparkline : 'pattern' }
34633722 ] ;
34643723
34653724 elements . forEach ( el => {
@@ -3475,9 +3734,15 @@ <h4>🚀 Production Features:</h4>
34753734 element . textContent = Math . round ( newValue ) + el . suffix ;
34763735 }
34773736
3478- // Update sparkline for P95 latency
3479- if ( el . id === 'p95Latency ' ) {
3737+ // Update sparklines for relevant metrics
3738+ if ( el . sparkline === 'p95 ' ) {
34803739 updateSparklineData ( newValue ) ;
3740+ } else if ( el . sparkline === 'storage' ) {
3741+ updateStorageSparkline ( newValue ) ;
3742+ } else if ( el . sparkline === 'velocity' ) {
3743+ updateVelocitySparkline ( newValue ) ;
3744+ } else if ( el . sparkline === 'pattern' ) {
3745+ updatePatternSparkline ( newValue ) ;
34813746 }
34823747 }
34833748 } ) ;
0 commit comments