mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-06-26 21:11:34 +02:00
1 line
30 KiB
JavaScript
1 line
30 KiB
JavaScript
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}; |