Files
pyMC_Repeater/repeater/web/html/assets/RfHealthCorrelation-CtxvC3aj.js
T
2026-06-23 16:35:02 +01:00

1 line
30 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{C as e,D as t,K as n,N as r,P as i,T as a,U as o,X as s,_t as c,c as l,h as u,ht as d,i as f,j as p,l as m,m as ee,o as h,p as g,r as _,s as v,u as y,x as te,y as ne,z as b}from"./runtime-core.esm-bundler-CINEgm0a.js";import{a as re,l as x,t as S}from"./runtime-dom.esm-bundler-B3VeUO8l.js";import{t as C}from"./api-DSaJA91r.js";import{d as w,t as T}from"./index-Cijj_ZXo.js";import{_ as E,a as D,d as O,f as ie,g as ae,i as k,l as A,m as j,n as M,o as oe,s as N,t as P,u as F,v as se,y as I}from"./ChartCard-Cb2qelXJ.js";import{t as L}from"./PacketDetailsModal-BlVcpmGq.js";import"./chartjs-adapter-date-fns.esm-Bq5A--VJ.js";var R={class:`sticky top-0 z-20 border-b border-stroke px-6 py-4 flex items-center justify-between shadow-sm backdrop-blur-md bg-surface-primary/95 dark:bg-surface-elevated/92 supports-backdrop-filter:bg-surface-primary/80 supports-backdrop-filter:dark:bg-surface-elevated/78`},z={class:`text-sm text-content-secondary mt-1`},B={class:`px-6 py-4 space-y-6`},V={class:`flex items-center gap-3`},H={class:`grid grid-cols-2 gap-4`},U={class:`bg-surface-primary rounded-lg p-4`},ce={class:`text-content-primary font-medium`},W={class:`bg-surface-primary rounded-lg p-4`},G={class:`text-content-primary font-medium`},K={class:`bg-surface-primary rounded-lg p-4`},q={class:`text-2xl text-content-primary font-semibold`},J={class:`grid grid-cols-2 gap-4`},Y={class:`bg-surface-primary rounded-lg p-4 border-l-4 border-sky-500`},le={class:`text-3xl text-content-primary font-bold`},ue={class:`bg-surface-primary rounded-lg p-4 border-l-4 border-amber-500`},de={class:`text-3xl text-content-primary font-bold`},fe={class:`bg-surface-primary rounded-lg p-4`},pe={class:`space-y-2 text-sm text-content-secondary`},me={class:`flex gap-2`},he={class:`flex gap-2`},ge={class:`bg-surface-primary rounded-lg p-4`},X={class:`flex items-center justify-between gap-3`},_e={class:`text-xs text-content-secondary mt-1`},ve={class:`flex items-center gap-2`},Z=[`value`],ye={key:0,class:`text-sm text-content-secondary mt-3`},be={key:1,class:`text-sm text-danger mt-3`},xe={key:2,class:`mt-3 space-y-3`},Se={class:`grid grid-cols-2 md:grid-cols-4 gap-2 text-xs`},Ce={class:`rounded-md border border-stroke-subtle px-2 py-2`},we={class:`text-content-primary font-semibold`},Q={class:`rounded-md border border-stroke-subtle px-2 py-2`},Te={class:`text-content-primary font-semibold`},Ee={class:`rounded-md border border-stroke-subtle px-2 py-2`},De={class:`text-content-primary font-semibold`},Oe={class:`rounded-md border border-stroke-subtle px-2 py-2`},ke={class:`text-content-primary font-semibold`},Ae={class:`text-xs text-content-secondary`},je={class:`grid grid-cols-1 md:grid-cols-2 gap-3`},Me={class:`rounded-md border border-stroke-subtle p-3`},Ne={key:0,class:`text-xs text-content-secondary`},Pe={key:1,class:`space-y-1.5`},Fe={class:`font-medium text-content-primary`},Ie={class:`rounded-md border border-stroke-subtle p-3`},Le={key:0,class:`text-xs text-content-secondary`},Re={key:1,class:`space-y-1.5`},ze=[`title`],Be={class:`font-medium text-content-primary`},Ve={class:`glass-card border border-stroke-subtle dark:border-stroke rounded-xl overflow-hidden`},He={key:0,class:`px-3 py-3 text-sm text-content-secondary`},Ue={key:1,class:`max-h-56 overflow-y-auto`},We={class:`md:col-span-2 text-content-secondary text-xs`},Ge={class:`md:col-span-2 text-content-primary text-xs font-medium`},Ke=[`title`],qe={class:`md:col-span-2 md:text-right`},Je=[`onClick`],Ye={class:`sticky bottom-0 z-10 bg-white dark:bg-surface-elevated border-t border-stroke-subtle px-6 py-4 flex justify-end gap-3`},Xe=w(u({__name:`IncidentDetailsModal`,props:{incident:{default:null}},emits:[`close`],setup(e,{emit:n}){let u=e,te=n,ne=Array.from({length:15},(e,t)=>t+1),b=o(10),w=o([]),T=o(!1),E=o(null),D=o(null),O=o(!1),ie=e=>new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`}),ae=(e,t)=>{let n=Math.max(0,t-e),r=Math.floor(n/1e3),i=Math.floor(r/60),a=Math.floor(i/60);return a>0?`${a}h ${i%60}m`:i>0?`${i}m ${r%60}s`:`${r}s`},k=h(()=>{if(!u.incident)return null;let e=u.incident;return{startTime:ie(e.startMs),endTime:ie(e.endMs),duration:ae(e.startMs,e.endMs),peakNoise:e.peakNoiseDelta.toFixed(2),totalCrc:e.totalCrc.toLocaleString(),severityColor:e.severity===`high`?`bg-danger/10 text-danger`:e.severity===`medium`?`bg-warning/10 text-warning`:`bg-success/10 text-success`}}),A=h(()=>u.incident?{startTs:Math.floor(u.incident.startMs/1e3)-b.value,endTs:Math.ceil(u.incident.endMs/1e3)+b.value,contextSeconds:b.value}:null),j=e=>e<1e10?e*1e3:e,M=e=>new Date(j(e)).toLocaleTimeString(`en-US`,{hour:`2-digit`,minute:`2-digit`,second:`2-digit`}),oe=e=>({0:`REQ`,1:`RESP`,2:`MSG`,3:`ACK`,4:`ADVERT`,5:`GRP_TXT`,6:`GRP_DATA`,7:`ANON_REQ`,8:`PATH`,9:`TRACE`,10:`MP`,15:`CUSTOM`})[e]??`T${e}`,N=e=>({0:`Transport Flood`,1:`Flood`,2:`Direct`,3:`Transport Direct`})[e]??`Route ${e}`,P=e=>e.is_duplicate?`Duplicate`:!e.transmitted||e.drop_reason?`Dropped`:`Forwarded`,F=e=>{if(Array.isArray(e))return e.filter(e=>typeof e==`string`);if(typeof e==`string`)try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(e=>typeof e==`string`)}catch{return[]}return[]},se=e=>{let t=F(e.original_path).length,n=F(e.forwarded_path).length;return!t&&!n?`No path`:t&&n?`${t}->${n} hops`:`${Math.max(t,n)} hops`},I=h(()=>{let e=w.value,t=e.filter(e=>!e.transmitted||!!e.drop_reason).length,n=e.filter(e=>!!e.is_duplicate).length,r=e.filter(e=>F(e.original_path).length>0||F(e.forwarded_path).length>0).length,i=new Map;for(let t of e)t.drop_reason&&i.set(t.drop_reason,(i.get(t.drop_reason)??0)+1);let a=Array.from(i.entries()).sort((e,t)=>t[1]-e[1]).slice(0,3).map(([e,t])=>`${e} (${t})`);return{total:e.length,dropped:t,duplicates:n,withPath:r,topDropReasons:a}}),Xe=h(()=>[...w.value].sort((e,t)=>j(e.timestamp)-j(t.timestamp)).slice(0,20)),Ze=e=>`${F(e.original_path).join(`>`)}|${F(e.forwarded_path).join(`>`)}`,$=h(()=>{let e=new Map,t=new Map;for(let n of w.value){let r=n.packet_hash||`unknown`,i=e.get(r)??{count:0,samples:[]};i.count+=1,i.samples.length<3&&i.samples.push(n),e.set(r,i);let a=Ze(n);if(!a||a===`|`)continue;let o=t.get(a)??{count:0,samples:[]};o.count+=1,o.samples.length<3&&o.samples.push(n),t.set(a,o)}return{repeatedHashes:Array.from(e.entries()).filter(([,e])=>e.count>1).sort((e,t)=>t[1].count-e[1].count).slice(0,6).map(([e,t])=>({hash:e,count:t.count,samples:t.samples})),repeatedPaths:Array.from(t.entries()).filter(([,e])=>e.count>1).sort((e,t)=>t[1].count-e[1].count).slice(0,6).map(([e,t])=>({path:e,count:t.count,samples:t.samples}))}}),Qe=async e=>{if(D.value=e,O.value=!0,e.packet_hash&&(!e.header||!e.raw_packet))try{let t=await C.get(`/packet_by_hash`,{packet_hash:e.packet_hash});t.data&&D.value?.packet_hash===e.packet_hash&&(D.value={...D.value,...t.data})}catch{}},$e=()=>{O.value=!1,D.value=null},et=async()=>{if(!A.value){w.value=[];return}T.value=!0,E.value=null;try{let e=await C.get(`/filtered_packets`,{start_timestamp:A.value.startTs,end_timestamp:A.value.endTs,limit:250});w.value=Array.isArray(e.data)?e.data:[]}catch(e){w.value=[],E.value=e instanceof Error?e.message:`Failed to load packet context`}finally{T.value=!1}};p(()=>u.incident?.id,async e=>{if(!e){w.value=[],E.value=null;return}await et()},{immediate:!0}),p(b,async()=>{u.incident&&await et()});let tt=e=>{e.target===e.currentTarget&&te(`close`)};return(n,o)=>(a(),l(f,{to:`body`},[ee(S,{name:`fade`},{default:r(()=>[e.incident?(a(),y(`div`,{key:0,class:`modal-backdrop z-40!`,onClick:tt},[v(`div`,{class:`modal-card max-w-2xl max-h-[90vh] overflow-y-auto shadow-xl`,onClick:o[3]||=x(()=>{},[`stop`])},[v(`div`,R,[v(`div`,null,[o[4]||=v(`h3`,{class:`text-lg font-semibold text-content-primary`},`RF Degradation Event`,-1),v(`p`,z,c(k.value?.startTime),1)]),v(`button`,{onClick:o[0]||=e=>te(`close`),class:`text-content-tertiary hover:text-content-secondary transition-colors text-2xl leading-none`},` × `)]),v(`div`,B,[v(`div`,V,[v(`div`,{class:d([`px-4 py-2 rounded-lg font-medium text-sm`,k.value?.severityColor])},` Severity: `+c(e.incident.severity.toUpperCase()),3)]),v(`div`,H,[v(`div`,U,[o[5]||=v(`div`,{class:`text-xs text-content-tertiary uppercase tracking-wide mb-1`},`Start Time`,-1),v(`div`,ce,c(k.value?.startTime),1)]),v(`div`,W,[o[6]||=v(`div`,{class:`text-xs text-content-tertiary uppercase tracking-wide mb-1`},`End Time`,-1),v(`div`,G,c(k.value?.endTime),1)])]),v(`div`,K,[o[7]||=v(`div`,{class:`text-xs text-content-tertiary uppercase tracking-wide mb-1`},`Duration`,-1),v(`div`,q,c(k.value?.duration),1)]),v(`div`,J,[v(`div`,Y,[o[8]||=v(`div`,{class:`text-xs text-content-tertiary uppercase tracking-wide mb-1`},`Peak Noise Delta`,-1),v(`div`,le,`+`+c(k.value?.peakNoise),1),o[9]||=v(`div`,{class:`text-xs text-content-secondary mt-1`},`dB above baseline`,-1)]),v(`div`,ue,[o[10]||=v(`div`,{class:`text-xs text-content-tertiary uppercase tracking-wide mb-1`},`Total CRC Errors`,-1),v(`div`,de,c(k.value?.totalCrc),1),o[11]||=v(`div`,{class:`text-xs text-content-secondary mt-1`},`detected during event`,-1)])]),v(`div`,fe,[o[15]||=v(`div`,{class:`text-sm font-medium text-content-primary mb-3`},`What This Means`,-1),v(`ul`,pe,[v(`li`,me,[o[12]||=v(`span`,{class:`text-sky-500 font-bold`},``,-1),v(`span`,null,`Noise floor increased `+c(k.value?.peakNoise)+` dB above baseline, indicating RF interference or environmental factors.`,1)]),v(`li`,he,[o[13]||=v(`span`,{class:`text-amber-500 font-bold`},``,-1),v(`span`,null,c(k.value?.totalCrc)+` CRC errors occurred during this period, suggesting packet corruption.`,1)]),o[14]||=v(`li`,{class:`flex gap-2`},[v(`span`,{class:`text-content-tertiary font-bold`},``),v(`span`,null,`The strong correlation between noise and CRC errors indicates the noise floor was the primary cause of packet degradation.`)],-1)])]),v(`div`,ge,[v(`div`,X,[v(`div`,null,[o[16]||=v(`div`,{class:`text-sm font-medium text-content-primary`},`Packet Context Around Incident`,-1),v(`div`,_e,` ±`+c(A.value?.contextSeconds??0)+`s around window `,1)]),v(`div`,ve,[i(v(`select`,{"onUpdate:modelValue":o[1]||=e=>b.value=e,class:`px-2 py-1 text-xs rounded-md border border-stroke-subtle bg-background-mute text-content-primary`},[(a(!0),y(_,null,t(s(ne),e=>(a(),y(`option`,{key:e,value:e},` ±`+c(e)+`s `,9,Z))),128))],512),[[re,b.value,void 0,{number:!0}]]),v(`button`,{class:`px-2 py-1 text-xs rounded-md border border-stroke-subtle text-content-secondary hover:text-content-primary hover:bg-surface-hover`,onClick:et},` Refresh `)])]),T.value?(a(),y(`div`,ye,`Loading nearby packets...`)):E.value?(a(),y(`div`,be,c(E.value),1)):(a(),y(`div`,xe,[v(`div`,Se,[v(`div`,Ce,[o[17]||=v(`div`,{class:`text-content-tertiary`},`Total`,-1),v(`div`,we,c(I.value.total),1)]),v(`div`,Q,[o[18]||=v(`div`,{class:`text-content-tertiary`},`Dropped`,-1),v(`div`,Te,c(I.value.dropped),1)]),v(`div`,Ee,[o[19]||=v(`div`,{class:`text-content-tertiary`},`Duplicates`,-1),v(`div`,De,c(I.value.duplicates),1)]),v(`div`,Oe,[o[20]||=v(`div`,{class:`text-content-tertiary`},`With path data`,-1),v(`div`,ke,c(I.value.withPath),1)])]),v(`div`,Ae,[o[21]||=v(`span`,{class:`font-medium text-content-primary`},`Top drop reasons:`,-1),g(` `+c(I.value.topDropReasons.length?I.value.topDropReasons.join(`, `):`None`),1)]),v(`div`,je,[v(`div`,Me,[o[22]||=v(`div`,{class:`text-xs font-semibold text-content-tertiary uppercase tracking-wide mb-2`},` Repeated Packet Hashes `,-1),$.value.repeatedHashes.length===0?(a(),y(`div`,Ne,` No repeated hashes in this window. `)):(a(),y(`div`,Pe,[(a(!0),y(_,null,t($.value.repeatedHashes,e=>(a(),y(`div`,{key:e.hash,class:`text-xs text-content-secondary`},[v(`span`,Fe,c(e.hash),1),g(` x`+c(e.count),1)]))),128))]))]),v(`div`,Ie,[o[23]||=v(`div`,{class:`text-xs font-semibold text-content-tertiary uppercase tracking-wide mb-2`},` Repeated Paths `,-1),$.value.repeatedPaths.length===0?(a(),y(`div`,Le,` No repeated paths in this window. `)):(a(),y(`div`,Re,[(a(!0),y(_,null,t($.value.repeatedPaths,e=>(a(),y(`div`,{key:e.path,class:`text-xs text-content-secondary truncate`,title:e.path},[v(`span`,Be,c(e.path),1),g(` x`+c(e.count),1)],8,ze))),128))]))])]),v(`div`,Ve,[o[28]||=v(`div`,{class:`hidden md:grid grid-cols-12 gap-2 px-3 py-2 border-b border-stroke-subtle dark:border-stroke text-content-secondary dark:text-content-muted text-[11px] font-semibold uppercase tracking-wide`},[v(`div`,{class:`col-span-2`},`Time`),v(`div`,{class:`col-span-2`},`Type`),v(`div`,{class:`col-span-2`},`Status`),v(`div`,{class:`col-span-4`},`Route / Path / Reason`),v(`div`,{class:`col-span-2 text-right`},`Inspect`)],-1),Xe.value.length===0?(a(),y(`div`,He,` No packets found in this context window. `)):(a(),y(`div`,Ue,[(a(!0),y(_,null,t(Xe.value,e=>(a(),y(`div`,{key:`${e.packet_hash}-${e.timestamp}`,class:`packet-context-row grid grid-cols-1 md:grid-cols-12 gap-2 px-3 py-2 border-b border-stroke-subtle dark:border-dark-border/50 hover:bg-background-mute dark:hover:bg-stroke/5 transition-colors duration-150`},[v(`div`,We,[o[24]||=v(`span`,{class:`md:hidden text-content-tertiary font-semibold uppercase tracking-wide mr-1`},`Time:`,-1),g(` `+c(M(e.timestamp)),1)]),v(`div`,Ge,[o[25]||=v(`span`,{class:`md:hidden text-content-tertiary font-semibold uppercase tracking-wide mr-1`},`Type:`,-1),g(` `+c(oe(e.type)),1)]),v(`div`,{class:d([`md:col-span-2 text-xs font-medium`,{"text-warning":P(e)===`Duplicate`,"text-danger":P(e)===`Dropped`,"text-success":P(e)===`Forwarded`}])},[o[26]||=v(`span`,{class:`md:hidden text-content-tertiary font-semibold uppercase tracking-wide mr-1`},`Status:`,-1),g(` `+c(P(e)),1)],2),v(`div`,{class:`md:col-span-4 text-content-secondary text-xs truncate`,title:`${N(e.route)} | ${se(e)} | ${e.drop_reason??`no drop reason`}`},[o[27]||=v(`span`,{class:`md:hidden text-content-tertiary font-semibold uppercase tracking-wide mr-1`},`Details:`,-1),g(` `+c(N(e.route))+` | `+c(se(e))+` | `+c(e.drop_reason??`ok`),1)],8,Ke),v(`div`,qe,[v(`button`,{class:`glass-card border border-stroke-subtle dark:border-stroke hover:border-primary rounded-lg px-2 py-1 text-[11px] text-content-primary hover:text-primary hover:bg-primary/5 transition-all duration-200 focus:outline-none focus:ring-1 focus:ring-primary/20`,onClick:t=>Qe(e)},` Open `,8,Je)])]))),128))]))])]))])]),v(`div`,Ye,[v(`button`,{onClick:o[2]||=e=>te(`close`),class:`px-4 py-2 rounded-lg bg-surface-primary text-content-primary hover:bg-surface-hover transition-colors font-medium`},` Close `)])])])):m(``,!0)]),_:1}),ee(L,{packet:D.value,"is-open":O.value,onClose:$e},null,8,[`packet`,`is-open`])]))}}),[[`__scopeId`,`data-v-2abc6745`]]),Ze={class:`p-3 sm:p-6 space-y-4 sm:space-y-6`},$={class:`flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between`},Qe={class:`flex items-center gap-2 sm:gap-3`},$e=[`value`],et={class:`grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4`},tt={class:`glass-card rounded-[15px] p-4`},nt={class:`mt-2 text-2xl font-semibold text-content-primary`},rt={class:`glass-card rounded-[15px] p-4`},it={class:`mt-2 text-2xl font-semibold text-content-primary`},at={class:`glass-card rounded-[15px] p-4`},ot={class:`mt-2 text-2xl font-semibold text-content-primary`},st={class:`glass-card rounded-[15px] p-4`},ct={class:`mt-2 text-2xl font-semibold text-content-primary`},lt={class:`mt-1 text-xs text-content-muted`},ut={class:`glass-card rounded-[15px] p-3 sm:p-5`},dt={class:`grid grid-cols-1 xl:grid-cols-2 gap-4 sm:gap-6`},ft={class:`glass-card rounded-[15px] p-4 sm:p-6`},pt={class:`space-y-3`},mt={class:`text-content-primary font-medium`},ht={class:`text-content-secondary text-sm mt-1`},gt={class:`text-content-secondary text-sm mt-1`},_t={class:`glass-card rounded-[15px] p-4 sm:p-6`},vt={key:0,class:`text-content-secondary text-sm`},yt={key:1,class:`space-y-3 max-h-[26rem] overflow-y-auto pr-1`},bt=[`onClick`],xt={class:`flex items-center justify-between gap-2`},St={class:`text-content-primary font-medium`},Ct={class:`grid grid-cols-2 gap-2 mt-3 text-xs sm:text-sm text-content-secondary group-hover:text-content-primary transition-colors`},wt={class:`glass-card rounded-[15px] p-4 sm:p-6`},Tt={class:`grid grid-cols-2 md:grid-cols-5 gap-3 text-sm`},Et={class:`border border-stroke-subtle rounded-lg p-3`},Dt={class:`text-content-primary font-medium`},Ot={class:`border border-stroke-subtle rounded-lg p-3`},kt={class:`text-content-primary font-medium`},At={class:`border border-stroke-subtle rounded-lg p-3`},jt={class:`text-content-primary font-medium`},Mt={class:`border border-stroke-subtle rounded-lg p-3`},Nt={class:`text-content-primary font-medium`},Pt=u({name:`RfHealthCorrelationView`,__name:`RfHealthCorrelation`,setup(l){N.register(oe,O,ie,F,A,k,se,I,E,D,ae,j);let u=[{value:1,label:`1 Hour`},{value:6,label:`6 Hours`},{value:24,label:`24 Hours`},{value:48,label:`2 Days`},{value:168,label:`1 Week`}],f=o(24),p=o(null),m=o(null),g=o(!1),x=o(!1),S=o(!0),C=o(null),w=o(`Connecting...`),L=o({}),R=o([]),z=o([]),B=o([]),V=o([]),H=o([]),U=o(null),ce=(e,t)=>typeof window>`u`?t:window.getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t,W=e=>{if(!e.startsWith(`var(`))return e;let t=e.match(/var\((--[^,)]+)/);return t?ce(t[1],e):e},G={noise:`var(--color-primary)`,crc:`var(--color-accent-red)`,packetCount:`var(--color-accent-green)`,grid:`var(--color-border-subtle)`,ticks:`var(--color-text-secondary)`,tooltipBg:`var(--color-surface-elevated)`,tooltipText:`var(--color-text-primary)`,tooltipBorder:`var(--color-border-subtle)`},K=e=>{if(typeof e==`number`&&Number.isFinite(e))return e;if(typeof e==`string`){let t=Number(e);if(Number.isFinite(t))return t}return null},q=e=>{let t=K(e);return t===null?null:t>0x38d7ea4c68000?Math.round(t/1e3):t>0xe8d4a51000?Math.round(t):t>1e9?Math.round(t*1e3):null},J=e=>!e||typeof e!=`object`||Array.isArray(e)?null:e,Y=(e,t)=>{if(e.length===0)return 0;let n=[...e].sort((e,t)=>e-t);return n[Math.max(0,Math.min(n.length-1,Math.round((n.length-1)*t)))]},le=e=>Y(e,.5),ue=(e,t,n)=>Math.min(n,Math.max(t,e)),de=e=>{let t=[],n=J(e)?.data??e,r=e=>{e.forEach(e=>{let n=J(e);if(!n)return;let r=q(n.timestamp),i=K(n.noise_floor_dbm??n.noise_floor??n.value);r!==null&&i!==null&&t.push({t:r,v:i})})};if(Array.isArray(n))r(n);else{let e=J(n);e&&(Array.isArray(e.history)&&r(e.history),Array.isArray(e.chart_data)&&r(e.chart_data),Array.isArray(e.values)&&r(e.values))}return t.sort((e,t)=>e.t-t.t)},fe=e=>{let t=[],n=J(e)?.data??e,r=e=>{e.forEach(e=>{let n=J(e);if(!n)return;let r=q(n.timestamp),i=K(n.count??n.crc_errors??n.value);r!==null&&i!==null&&t.push({t:r,v:i})})};if(Array.isArray(n))r(n);else{let e=J(n);e&&Array.isArray(e.history)&&r(e.history)}return t.sort((e,t)=>e.t-t.t)},pe=(e,t)=>{let n=[],r=J(J(e)?.data??e);if(!r||!Array.isArray(r.series))return n;let i=Array.isArray(r.timestamps)?r.timestamps.map(e=>q(e)).filter(e=>e!==null):[];return r.series.forEach(e=>{let r=J(e);if(!r)return;let a=String(r.type??``),o=String(r.name??``);if(!(a===t||o===t))return;let s=r.data;if(Array.isArray(s)){if(s.length>0&&Array.isArray(s[0])){s.forEach(e=>{if(!Array.isArray(e)||e.length<2)return;let t=q(e[0]),r=K(e[1]);t!==null&&r!==null&&n.push({t,v:r})});return}s.forEach((e,t)=>{let r=i[t]??null,a=K(e);r!==null&&a!==null&&n.push({t:r,v:a})})}}),n.sort((e,t)=>e.t-t.t)},me=e=>{let t=pe(e,`rx_count`),n=pe(e,`tx_count`),r=new Map;return t.forEach(e=>{r.set(e.t,(r.get(e.t)??0)+e.v)}),n.forEach(e=>{r.set(e.t,(r.get(e.t)??0)+e.v)}),Array.from(r.entries()).map(([e,t])=>({t:e,v:t})).sort((e,t)=>e.t-t.t)},he=(e,t,n)=>{let r=new Map;e.forEach(e=>{let n=Math.floor(e.t/t)*t;r.has(n)||r.set(n,[]),r.get(n)?.push(e.v)});let i=new Map;return r.forEach((e,t)=>{if(e.length!==0){if(n===`sum`){i.set(t,e.reduce((e,t)=>e+t,0));return}i.set(t,e.reduce((e,t)=>e+t,0)/e.length)}}),i},ge=()=>{let e=Math.max(3e4,Math.round(f.value*60*60*1e3/120)),t=he(R.value,e,`avg`),n=he(z.value,e,`sum`),r=he(B.value,e,`sum`),i=new Set([...t.keys(),...n.keys(),...r.keys()]);return Array.from(i).sort((e,t)=>e-t).map(e=>({bucketMs:e,noise:t.has(e)?t.get(e)??null:null,crc:n.get(e)??0,packets:r.has(e)?r.get(e)??0:0}))},X=(e,t)=>{if(e.length!==t.length||e.length<3)return null;let n=e.reduce((e,t)=>e+t,0)/e.length,r=t.reduce((e,t)=>e+t,0)/t.length,i=0,a=0,o=0;for(let s=0;s<e.length;s+=1){let c=e[s]-n,l=t[s]-r;i+=c*l,a+=c*c,o+=l*l}let s=Math.sqrt(a*o);return s===0?null:i/s},_e=(e,t,n)=>n<0?null:n===0?X(e,t):e.length<=n||t.length<=n?null:X(e.slice(0,e.length-n),t.slice(n)),ve=e=>{if(e.length===0)return[];let t=e.map(e=>e.noise).filter(e=>e!==null);if(t.length<5)return[];let n=le(t),r=n+Math.max(2,Y(t,.9)-n),i=Math.max(1,Y(e.map(e=>e.crc),.9)),a=e.filter(e=>{if(e.noise===null)return!1;let t=e.noise>=r,n=e.crc>=i;return t&&n});if(a.length===0)return[];let o=e.length>1?e[1].bucketMs-e[0].bucketMs:6e4,s=[],c=a[0].bucketMs,l=a[0].bucketMs,u=[a[0]],d=()=>{let e=u.map(e=>e.noise===null?0:e.noise-n),t=Math.max(...e),r=u.reduce((e,t)=>e+t.crc,0),i=t*2.5+r*.8,a=i>=20?`high`:i>=8?`medium`:`low`;s.push({id:`${c}-${l}`,startMs:c,endMs:l,peakNoiseDelta:t,totalCrc:r,totalDrops:0,severity:a})};for(let e=1;e<a.length;e+=1){let t=a[e];if(t.bucketMs-l<=o*1.5){l=t.bucketMs,u.push(t);continue}d(),c=t.bucketMs,l=t.bucketMs,u=[t]}return d(),s.sort((e,t)=>t.startMs-e.startMs).slice(0,12)},Z=h(()=>{let e=K(L.value.total_packets);if(e!==null)return e;let t=K(L.value.received)??0,n=K(L.value.transmitted)??0;return Math.max(t,n)}),ye=h(()=>{let e=K(L.value.dropped);if(e!==null)return e;let t=K(L.value.received)??0,n=K(L.value.transmitted)??0;return Math.max(0,t-n)}),be=h(()=>Z.value<=0?0:ye.value/Z.value),xe=h(()=>R.value.length===0?null:R.value[R.value.length-1].v),Se=h(()=>R.value.length<3?null:le(R.value.map(e=>e.v))),Ce=h(()=>z.value.reduce((e,t)=>e+t.v,0)),we=h(()=>{let e=xe.value,t=Se.value,n=0;e!==null&&t!==null&&(n=Math.max(0,e-t)*2.2);let r=(Z.value>0?Ce.value/Z.value:0)*120,i=be.value*100;return ue(Math.round(100-(n+r+i)),0,100)}),Q=h(()=>{let e=R.value.length>0?R.value[R.value.length-1].t:0,t=z.value.length>0?z.value[z.value.length-1].t:0,n=B.value.length>0?B.value[B.value.length-1].t:0,r=Math.max(e,t,n),i=r>0?Math.max(0,Math.round((Date.now()-r)/1e3)):null;return{noiseSamples:R.value.length,crcSamples:z.value.length,packetSamples:B.value.length,freshnessSeconds:i}}),Te=e=>new Date(e).toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`}),Ee=(e,t)=>{let n=Math.max(0,t-e),r=Math.floor(n/1e3),i=Math.floor(r/60),a=Math.floor(i/60);return a>0?`${a}h ${i%60}m`:i>0?`${i}m ${r%60}s`:`${r}s`};h(()=>{if(!U.value)return null;let e=U.value;return{startTime:Te(e.startMs),endTime:Te(e.endMs),duration:Ee(e.startMs,e.endMs),peakNoise:e.peakNoiseDelta.toFixed(2),totalCrc:e.totalCrc.toLocaleString(),severityColor:e.severity===`high`?`bg-danger/10 text-danger`:e.severity===`medium`?`bg-warning/10 text-warning`:`bg-success/10 text-success`}});let De=h(()=>{let e=V.value.filter(e=>e.noise!==null),t=e.map(e=>e.noise),n=e.map(e=>e.crc),r=e.map(e=>e.packets),i=X(t,n),a=X(t,r),o=0,s=i,c=0,l=a;for(let e=1;e<=3;e+=1){let i=_e(t,n,e),a=_e(t,r,e);(i??0)>(s??-1/0)&&(o=e,s=i),(a??0)>(l??-1/0)&&(c=e,l=a)}return[{label:`Noise vs CRC errors`,correlation:i,strongestLagBuckets:o,strongestLagCorrelation:s},{label:`Noise vs packet activity`,correlation:a,strongestLagBuckets:c,strongestLagCorrelation:l}]}),Oe=e=>e===null||Number.isNaN(e)?`Insufficient samples`:e.toFixed(3),ke=e=>new Date(e).toLocaleString([],{hour:`2-digit`,minute:`2-digit`,month:`short`,day:`numeric`}),Ae=e=>e===null?`Unknown`:e<60?`${e}s ago`:e<3600?`${Math.round(e/60)}m ago`:`${Math.round(e/3600)}h ago`,je=async()=>{g.value?x.value=!0:S.value=!0,C.value=null;try{let[e,t,n,r]=await Promise.all([M(`/packet_stats`,{hours:f.value}),M(`/noise_floor_history`,{hours:f.value},{idleTimeoutMs:3e4,onPhaseChange:e=>{w.value=e===`receiving`?`Receiving data...`:`Connecting...`}}),M(`/crc_error_history`,{hours:f.value}),M(`/metrics_graph_data`,{hours:f.value,resolution:`average`,metrics:`rx_count,tx_count`})]),i=J(e.data)??{},a=J(i.data)??i;L.value={total_packets:K(a.total_packets)??void 0,received:K(a.received)??void 0,transmitted:K(a.transmitted)??void 0,dropped:K(a.dropped)??void 0},R.value=de(t.data),z.value=fe(n.data),B.value=me(r.data),V.value=ge(),H.value=ve(V.value),V.value.length===0&&(C.value=`No correlation data available for the selected time range.`),await ne(),Ne(),g.value=!0}catch(e){C.value=e instanceof Error?e.message:`Failed to load RF health correlation data.`}finally{S.value=!1,x.value=!1}},Me=()=>{m.value&&=(n(m.value).destroy(),null)},Ne=()=>{if(!p.value||V.value.length===0){Me();return}let e=p.value.getContext(`2d`);if(!e)return;let t=V.value.filter(e=>e.noise!==null).map(e=>({x:e.bucketMs,y:e.noise})),r=V.value.map(e=>({x:e.bucketMs,y:e.crc})),i=Math.max(1,...r.map(e=>e.y)),a=V.value.map(e=>({x:e.bucketMs,y:e.packets})),o=a.map(e=>e.y),s=o.length>0?Y(o,.95):1,c=Math.max(1,Math.ceil(s*1.25)),l=f.value>48?`day`:`hour`,u={type:`bar`,data:{datasets:[{type:`line`,label:`Noise floor (dBm)`,yAxisID:`yNoise`,data:t,borderColor:W(G.noise),backgroundColor:W(G.noise),borderWidth:2,tension:.25,pointRadius:0,pointHoverRadius:3},{type:`line`,label:`Packet count (bucket)`,yAxisID:`yPacketCount`,data:a,borderColor:W(G.packetCount),backgroundColor:W(G.packetCount),borderWidth:2,tension:.25,pointRadius:0,pointHoverRadius:3},{type:`bar`,label:`CRC errors`,yAxisID:`yCount`,data:r,borderWidth:0,backgroundColor:W(G.crc),barPercentage:.9,categoryPercentage:1}]},options:{responsive:!0,maintainAspectRatio:!1,interaction:{mode:`index`,intersect:!1},plugins:{legend:{position:`top`,labels:{color:W(G.ticks)}},tooltip:{backgroundColor:W(G.tooltipBg),titleColor:W(G.tooltipText),bodyColor:W(G.tooltipText),borderColor:W(G.tooltipBorder),borderWidth:1}},scales:{x:{type:`time`,time:{unit:l},min:Date.now()-f.value*60*60*1e3,max:Date.now(),grid:{color:W(G.grid)},ticks:{color:W(G.ticks),maxTicksLimit:8}},yNoise:{type:`linear`,position:`left`,title:{display:!0,text:`Noise floor (dBm)`,color:W(G.ticks)},grid:{color:W(G.grid)},ticks:{color:W(G.ticks)}},yCount:{type:`linear`,position:`right`,beginAtZero:!0,max:Math.ceil(i*1.2),title:{display:!0,text:`CRC errors`,color:W(G.ticks)},grid:{drawOnChartArea:!1},ticks:{color:W(G.ticks)}},yPacketCount:{type:`linear`,position:`right`,offset:!0,beginAtZero:!0,max:Math.ceil(c*1.2),title:{display:!0,text:`Packet count`,color:W(G.ticks)},grid:{drawOnChartArea:!1},ticks:{color:W(G.ticks)}}}}};if(m.value){let e=n(m.value);e.data=u.data,e.options=u.options,e.update();return}m.value=b(new N(e,u))},Pe=()=>{S.value=!0,Ie.runNow()},Fe=()=>{m.value&&window.setTimeout(()=>{n(m.value)?.resize()},80)},Ie=T(je,{intervalMs:3e4,immediate:!0});return e(()=>{window.addEventListener(`resize`,Fe)}),te(()=>{window.removeEventListener(`resize`,Fe),Me()}),(e,n)=>(a(),y(`div`,Ze,[v(`div`,$,[n[4]||=v(`div`,null,[v(`h2`,{class:`text-xl sm:text-2xl font-bold text-content-primary`},`RF Health Correlation`),v(`p`,{class:`text-xs sm:text-sm text-content-secondary mt-1`},` Live correlation of noise floor, CRC errors, and packet activity so you can spot traffic-related peaks. `)],-1),ee(Xe,{incident:U.value,onClose:n[0]||=e=>U.value=null},null,8,[`incident`]),v(`div`,Qe,[n[3]||=v(`label`,{class:`text-content-secondary text-xs sm:text-sm`},`Window:`,-1),i(v(`select`,{"onUpdate:modelValue":n[1]||=e=>f.value=e,class:`modal-select w-auto`,onChange:Pe},[(a(),y(_,null,t(u,e=>v(`option`,{key:e.value,value:e.value,class:`bg-surface text-content-primary`},c(e.label),9,$e)),64))],544),[[re,f.value]])])]),v(`div`,et,[v(`div`,tt,[n[5]||=v(`div`,{class:`text-content-secondary text-xs uppercase tracking-wide`},`RF health score`,-1),v(`div`,nt,c(we.value),1)]),v(`div`,rt,[n[6]||=v(`div`,{class:`text-content-secondary text-xs uppercase tracking-wide`},`Current noise floor`,-1),v(`div`,it,c(xe.value===null?`N/A`:`${xe.value.toFixed(1)} dBm`),1)]),v(`div`,at,[n[7]||=v(`div`,{class:`text-content-secondary text-xs uppercase tracking-wide`},`CRC errors`,-1),v(`div`,ot,c(Math.round(Ce.value).toLocaleString()),1)]),v(`div`,st,[n[8]||=v(`div`,{class:`text-content-secondary text-xs uppercase tracking-wide`},`Dropped packets (reported)`,-1),v(`div`,ct,c(Math.round(ye.value).toLocaleString()),1),v(`div`,lt,`Drop rate: `+c((be.value*100).toFixed(2))+`%`,1)])]),v(`div`,ut,[n[9]||=v(`h3`,{class:`text-content-primary text-lg sm:text-xl font-semibold mb-3`},`Correlation timeline`,-1),ee(P,{class:`h-[17rem] sm:h-[22rem]`,"is-loading":S.value,"is-updating":x.value,error:C.value,status:w.value,onRetry:n[2]||=()=>s(Ie).runNow()},{default:r(()=>[v(`canvas`,{ref_key:`chartCanvasRef`,ref:p,class:`w-full h-full`},null,512)]),_:1},8,[`is-loading`,`is-updating`,`error`,`status`])]),v(`div`,dt,[v(`div`,ft,[n[10]||=v(`h3`,{class:`text-content-primary text-lg font-semibold mb-4`},`Correlation details`,-1),v(`div`,pt,[(a(!0),y(_,null,t(De.value,e=>(a(),y(`div`,{key:e.label,class:`border border-stroke-subtle rounded-lg p-3`},[v(`div`,mt,c(e.label),1),v(`div`,ht,` Base correlation: `+c(Oe(e.correlation)),1),v(`div`,gt,` Strongest lag: +`+c(e.strongestLagBuckets)+` bucket(s), `+c(Oe(e.strongestLagCorrelation)),1)]))),128))])]),v(`div`,_t,[n[12]||=v(`h3`,{class:`text-content-primary text-lg font-semibold mb-4`},`Detected incidents`,-1),H.value.length===0?(a(),y(`div`,vt,` No degradation windows detected for the selected time range. `)):(a(),y(`div`,yt,[(a(!0),y(_,null,t(H.value,e=>(a(),y(`div`,{key:e.id,class:`border border-stroke-subtle rounded-lg p-3 hover:bg-surface-hover/5 cursor-pointer transition-colors group`,onClick:t=>U.value=e},[v(`div`,xt,[v(`div`,St,c(ke(e.startMs))+` to `+c(ke(e.endMs)),1),v(`span`,{class:d([`text-xs font-semibold px-2 py-1 rounded-full`,{"bg-accent-red-bg text-accent-red":e.severity===`high`,"bg-warning-bg text-warning":e.severity===`medium`,"bg-accent-green-bg text-accent-green":e.severity===`low`}])},c(e.severity),3)]),v(`div`,Ct,[v(`div`,null,`Noise delta: +`+c(e.peakNoiseDelta.toFixed(1))+` dB`,1),v(`div`,null,`CRC burst: `+c(Math.round(e.totalCrc).toLocaleString())+` errors`,1)]),n[11]||=v(`div`,{class:`text-xs text-content-tertiary mt-2 opacity-0 group-hover:opacity-100 transition-opacity`},`Click to view details`,-1)],8,bt))),128))]))])]),v(`div`,wt,[n[17]||=v(`h3`,{class:`text-content-primary text-lg font-semibold mb-4`},`Data quality`,-1),v(`div`,Tt,[v(`div`,Et,[n[13]||=v(`div`,{class:`text-content-secondary`},`Noise samples`,-1),v(`div`,Dt,c(Q.value.noiseSamples),1)]),v(`div`,Ot,[n[14]||=v(`div`,{class:`text-content-secondary`},`CRC samples`,-1),v(`div`,kt,c(Q.value.crcSamples),1)]),v(`div`,At,[n[15]||=v(`div`,{class:`text-content-secondary`},`Packet events`,-1),v(`div`,jt,c(Q.value.packetSamples),1)]),v(`div`,Mt,[n[16]||=v(`div`,{class:`text-content-secondary`},`Freshness`,-1),v(`div`,Nt,c(Ae(Q.value.freshnessSeconds)),1)])])])]))}});export{Pt as default};