Skip to content

Instantly share code, notes, and snippets.

@bojanrajkovic
Last active March 11, 2026 19:07
Show Gist options
  • Select an option

  • Save bojanrajkovic/9641e4f4e3cb43da3276734f0f1e8f5c to your computer and use it in GitHub Desktop.

Select an option

Save bojanrajkovic/9641e4f4e3cb43da3276734f0f1e8f5c to your computer and use it in GitHub Desktop.
Olivia CPAP Sleep Analysis Dashboard
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Olivia — CPAP Sleep Analysis Dashboard</title>
<style>
:root {
--bg: #1a1a2e;
--bg2: #16213e;
--bg3: #0f3460;
--text: #e0e0e0;
--text2: #a0a0b0;
--accent: #e94560;
--accent2: #533483;
--good: #4ecca3;
--warn: #f0a500;
--bad: #e94560;
--border: #2a2a4a;
--card: #1e1e3a;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.5;
min-height: 100vh;
}
.header {
background: linear-gradient(135deg, var(--bg2), var(--accent2));
padding: 24px 32px;
border-bottom: 1px solid var(--border);
}
.header h1 { font-size: 1.5rem; font-weight: 600; }
.header .subtitle { color: var(--text2); font-size: 0.9rem; margin-top: 4px; }
.header .meta { display: flex; gap: 24px; margin-top: 12px; flex-wrap: wrap; }
.header .meta-item {
background: rgba(0,0,0,0.3);
padding: 6px 14px;
border-radius: 6px;
font-size: 0.8rem;
font-family: 'SF Mono', 'Cascadia Code', monospace;
}
.header .meta-item span { color: var(--text2); }
.nav {
display: flex;
gap: 0;
background: var(--bg2);
border-bottom: 1px solid var(--border);
overflow-x: auto;
}
.nav button {
background: none;
border: none;
color: var(--text2);
padding: 12px 20px;
font-size: 0.85rem;
cursor: pointer;
border-bottom: 2px solid transparent;
white-space: nowrap;
font-family: inherit;
}
.nav button:hover { color: var(--text); background: rgba(255,255,255,0.03); }
.nav button.active { color: var(--accent); border-bottom-color: var(--accent); }
.content { padding: 24px 32px; max-width: 1400px; margin: 0 auto; }
.section { display: none; }
.section.active { display: block; }
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
}
.card h2 { font-size: 1.1rem; margin-bottom: 4px; }
.card h3 { font-size: 0.95rem; margin-bottom: 8px; color: var(--text2); font-weight: 400; }
.card .desc { font-size: 0.85rem; color: var(--text2); margin-bottom: 16px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.grid3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; }
@media (max-width: 900px) { .grid2, .grid3 { grid-template-columns: 1fr; } }
.stat-row { display: flex; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
.stat {
background: rgba(0,0,0,0.2);
border: 1px solid var(--border);
border-radius: 8px;
padding: 14px 18px;
flex: 1;
min-width: 140px;
}
.stat .label { font-size: 0.75rem; color: var(--text2); text-transform: uppercase; letter-spacing: 0.5px; }
.stat .value { font-size: 1.6rem; font-weight: 700; margin-top: 2px; font-family: 'SF Mono', monospace; }
.stat .sub { font-size: 0.75rem; color: var(--text2); margin-top: 2px; }
.stat.good .value { color: var(--good); }
.stat.warn .value { color: var(--warn); }
.stat.bad .value { color: var(--bad); }
canvas { width: 100%; height: auto; display: block; border-radius: 6px; }
.heatmap-container { overflow-x: auto; }
.heatmap { border-collapse: collapse; width: 100%; min-width: 700px; font-size: 0.8rem; font-family: 'SF Mono', monospace; }
.heatmap th { padding: 6px 8px; text-align: center; color: var(--text2); font-weight: 400; font-size: 0.75rem; }
.heatmap td { padding: 6px 8px; text-align: center; border-radius: 3px; }
.heatmap .date-cell { text-align: left; color: var(--text2); white-space: nowrap; font-size: 0.75rem; }
.rec-list { list-style: none; }
.rec-list li {
padding: 16px;
margin-bottom: 12px;
border-radius: 8px;
border-left: 4px solid;
background: rgba(0,0,0,0.2);
}
.rec-list li.tonight { border-color: var(--good); }
.rec-list li.specialist { border-color: var(--warn); }
.rec-list li.monitor { border-color: var(--accent2); }
.rec-list .rec-tag {
display: inline-block;
font-size: 0.7rem;
padding: 2px 8px;
border-radius: 4px;
margin-bottom: 6px;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 600;
}
.rec-list .tonight .rec-tag { background: rgba(78,204,163,0.2); color: var(--good); }
.rec-list .specialist .rec-tag { background: rgba(240,165,0,0.2); color: var(--warn); }
.rec-list .monitor .rec-tag { background: rgba(83,52,131,0.3); color: #b080e0; }
.rec-list .rec-title { font-weight: 600; margin-bottom: 4px; }
.rec-list .rec-body { font-size: 0.85rem; color: var(--text2); }
.timeline-row {
display: flex;
align-items: center;
margin-bottom: 3px;
font-size: 0.75rem;
font-family: 'SF Mono', monospace;
}
.timeline-label { width: 80px; color: var(--text2); flex-shrink: 0; }
.timeline-bar-container { flex: 1; height: 18px; position: relative; background: rgba(0,0,0,0.2); border-radius: 3px; }
.timeline-bar {
position: absolute;
height: 100%;
border-radius: 2px;
min-width: 1px;
}
.legend { display: flex; gap: 16px; margin: 12px 0; flex-wrap: wrap; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 0.75rem; color: var(--text2); }
.legend-swatch { width: 12px; height: 12px; border-radius: 2px; flex-shrink: 0; }
.finding-box {
background: rgba(233,69,96,0.08);
border: 1px solid rgba(233,69,96,0.2);
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
}
.finding-box.info {
background: rgba(78,204,163,0.08);
border-color: rgba(78,204,163,0.2);
}
.finding-box h4 { font-size: 0.9rem; margin-bottom: 6px; }
.finding-box p { font-size: 0.85rem; color: var(--text2); }
</style>
</head>
<body>
<div class="header">
<h1>Olivia — CPAP Sleep Analysis</h1>
<div class="subtitle">ResMed AirSense 10 AutoSet &middot; Feb 21 – Mar 11, 2026 &middot; 8 weeks post-op</div>
<div class="meta">
<div class="meta-item"><span>Mode:</span> AutoSet 6–11 cmH2O</div>
<div class="meta-item"><span>EPR:</span> Level 3</div>
<div class="meta-item"><span>Ramp:</span> 4 cmH2O start</div>
<div class="meta-item"><span>Mask:</span> Nasal Pillow</div>
</div>
</div>
<div class="nav">
<button class="active" data-tab="overview">Overview</button>
<button data-tab="heatmaps">Event Heatmaps</button>
<button data-tab="trend">Trend Analysis</button>
<button data-tab="worst">Night Explorer</button>
<button data-tab="findings">Key Findings</button>
<button data-tab="recs">Recommendations</button>
</div>
<div class="content">
<!-- OVERVIEW -->
<div class="section active" id="sec-overview">
<div class="stat-row">
<div class="stat warn">
<div class="label">Avg AHI (last 7d)</div>
<div class="value">2.6</div>
<div class="sub">Up from 1.5 two weeks ago</div>
</div>
<div class="stat bad">
<div class="label">Worst Night OAs</div>
<div class="value">53</div>
<div class="sub">Mar 10 — 49 in 2-hr window</div>
</div>
<div class="stat good">
<div class="label">Best Night AHI</div>
<div class="value">0.6</div>
<div class="sub">Feb 21 — proves settings can work</div>
</div>
<div class="stat warn">
<div class="label">Pressure Ceiling Hits</div>
<div class="value">6</div>
<div class="sub">Nights where machine maxed at 11</div>
</div>
</div>
<div class="grid2">
<div class="card">
<h2>Nightly AHI</h2>
<h3>Apnea-Hypopnea Index over time</h3>
<canvas id="ahi-chart" height="220"></canvas>
</div>
<div class="card">
<h2>Obstructive Apnea Events</h2>
<h3>Total OA count per night</h3>
<canvas id="oa-chart" height="220"></canvas>
</div>
</div>
<div class="card">
<h2>Session Fragmentation</h2>
<h3>Mask-on/off cycles per night — more = worse sleep</h3>
<canvas id="sessions-chart" height="180"></canvas>
</div>
</div>
<!-- HEATMAPS -->
<div class="section" id="sec-heatmaps">
<div class="card">
<h2>Obstructive Apneas by Hour</h2>
<p class="desc">Each cell = OA count in that hour of the sleep period (7 PM to 7 AM). Darker red = more events. Look for where clusters land each night.</p>
<div class="heatmap-container">
<table class="heatmap" id="oa-heatmap"></table>
</div>
</div>
<div class="card">
<h2>All Respiratory Events by Hour</h2>
<p class="desc">Includes obstructive apneas, central apneas, unclassified apneas, and arousals.</p>
<div class="heatmap-container">
<table class="heatmap" id="all-events-heatmap"></table>
</div>
</div>
<div class="card">
<h2>Mask-On Sessions by Hour</h2>
<p class="desc">Each count = mask was removed and replaced. More sessions in an hour = more disrupted sleep. Evening (19-22) fragmentation is normal settling-in.</p>
<div class="heatmap-container">
<table class="heatmap" id="sessions-heatmap"></table>
</div>
</div>
<div class="card">
<h2>Average Apnea Duration by Hour (seconds)</h2>
<p class="desc">Longer apneas = more severe airway collapse. Darker = longer events.</p>
<div class="heatmap-container">
<table class="heatmap" id="duration-heatmap"></table>
</div>
</div>
</div>
<!-- TREND -->
<div class="section" id="sec-trend">
<div class="card">
<h2>Worsening Trend</h2>
<p class="desc">Sleep improved after the Jan 14 surgery, but has been progressively worsening since late February.</p>
<div class="stat-row">
<div class="stat good">
<div class="label">Week 1 (Feb 21-27)</div>
<div class="value">1.5</div>
<div class="sub">Avg AHI &middot; 5-6 wks post-op</div>
</div>
<div class="stat warn">
<div class="label">Week 2 (Feb 28-Mar 6)</div>
<div class="value">2.8</div>
<div class="sub">Avg AHI &middot; 6-7 wks post-op</div>
</div>
<div class="stat warn">
<div class="label">Week 3 (Mar 7-11)</div>
<div class="value">2.3</div>
<div class="sub">Avg AHI &middot; 7-8 wks post-op</div>
</div>
</div>
<canvas id="trend-chart" height="260"></canvas>
<div class="legend">
<div class="legend-item"><div class="legend-swatch" style="background:#e94560"></div> OA events (left axis)</div>
<div class="legend-item"><div class="legend-swatch" style="background:#4ecca3"></div> AHI (right axis)</div>
<div class="legend-item"><div class="legend-swatch" style="background:rgba(240,165,0,0.3)"></div> Weekly avg AHI</div>
</div>
</div>
<div class="finding-box">
<h4>The "spike" nights are getting worse</h4>
<p>Feb 25: 43 OAs &rarr; Mar 2: 36 &rarr; Mar 6: 49 &rarr; Mar 10: 53. The bad nights are almost entirely obstructive (OAI &asymp; AHI), indicating airway collapse — not a central breathing drive problem.</p>
</div>
<div class="card">
<h2>Possible Causes of Worsening</h2>
<div class="grid2">
<div class="finding-box" style="margin:0">
<h4>Growth Spurt</h4>
<p>Eating more lately. Growth-related changes in soft tissue or airway dimensions may be narrowing the airway. Adenoids peak growth at ages 2-8.</p>
</div>
<div class="finding-box" style="margin:0">
<h4>Room / Bed Change</h4>
<p>Recently moved rooms. Hose threaded through headboard creates fixed anchor point — may increase mask-off events and discourage lateral sleep.</p>
</div>
<div class="finding-box info" style="margin:0">
<h4>Post-Surgical Changes</h4>
<p>Residual adenoid tissue (couldn't be fully removed due to palate risk) may be undergoing changes at 6-8 weeks post-op.</p>
</div>
<div class="finding-box info" style="margin:0">
<h4>Seasonal / Cold</h4>
<p>Recent mild cold + late Feb to March seasonal transition. Nasal congestion increases upper airway resistance.</p>
</div>
</div>
</div>
</div>
<!-- NIGHT EXPLORER -->
<div class="section" id="sec-worst">
<div class="card">
<h2>How Did the Night Go?</h2>
<p class="desc">Select a night to see the session timeline, pressure levels, and event summary.</p>
<div style="margin-top:12px;">
<select id="night-select" style="background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:6px;padding:8px 14px;font-size:0.9rem;font-family:'SF Mono',monospace;cursor:pointer;min-width:240px;">
</select>
</div>
</div>
<div id="night-stats" class="stat-row" style="margin-top:0;"></div>
<div class="card">
<h2>Session Timeline</h2>
<p class="desc">Each bar = one CPAP session. Color indicates average pressure level. Gaps = mask off.</p>
<div class="legend">
<div class="legend-item"><div class="legend-swatch" style="background:#e94560"></div> High pressure (avg &ge;9 cmH2O)</div>
<div class="legend-item"><div class="legend-swatch" style="background:#f0a500"></div> Mid-range (avg 6-9 cmH2O)</div>
<div class="legend-item"><div class="legend-swatch" style="background:#533483"></div> Ramp / low (avg &lt;6 cmH2O)</div>
<div class="legend-item"><div class="legend-swatch" style="background:rgba(255,255,255,0.1)"></div> Gap (mask off)</div>
</div>
<div id="night-timeline" style="margin-top:12px;"></div>
</div>
<div id="night-callout"></div>
</div>
<!-- FINDINGS -->
<div class="section" id="sec-findings">
<div class="card">
<h2>Key Findings from CPAP Data Analysis</h2>
<h3>Feb 21 – Mar 11, 2026 &middot; Post-op from partial adenoidectomy + turbinate reduction (Jan 14)</h3>
</div>
<div class="finding-box">
<h4>1. OA Clusters Shift From Night to Night — Tied to REM, Not the Clock</h4>
<p>Obstructive apnea clusters aren't fixed at 2-4 AM. They appear at different hours each night (sometimes 01:00, sometimes 03:00, sometimes 05:00), consistent with REM-linked events. Whenever the cluster hits, it's dense and concentrated — suggesting a state change (entering REM or rolling supine) rather than gradual worsening.</p>
</div>
<div class="finding-box">
<h4>2. Strong Positional Component</h4>
<p>AHI swings from 0.6 to 5.6 between nights — too variable for fixed anatomy alone. Good nights prove current pressures work. Two position-dependent collapse mechanisms: pharyngeal (residual adenoids) + tracheal (tracheomalacia). Both worsen supine. The repeat sleep study should include positional monitoring.</p>
</div>
<div class="finding-box">
<h4>3. Machine Hitting 11 cmH2O Pressure Ceiling</h4>
<p>During OA clusters, pressure is frequently pegged at exactly 11.00 cmH2O (the maximum). The AutoSet algorithm would go higher if allowed but can't. For a 6-year-old, 11 is already on the higher end — but the data shows it's not enough during supine + REM conditions.</p>
</div>
<div class="finding-box">
<h4>4. Ramp Restart Creates Vicious Cycle</h4>
<p>Power-cycling the machine after each wakeup drops pressure to 4 cmH2O ramp start. The airway immediately collapses at this pressure, causing more apneas before the machine ramps back up. Even SmartStart restarts at ramp pressure if ramp is enabled.</p>
</div>
<div class="finding-box info">
<h4>5. Progressive Worsening Trend</h4>
<p>Avg AHI rose from 1.5 (week of Feb 21) to 2.8 (week of Feb 28). "Spike" nights getting progressively worse: 43 &rarr; 36 &rarr; 49 &rarr; 53 OA events. Something is actively changing — growth spurt, room change, post-surgical changes, or seasonal factors.</p>
</div>
<div class="finding-box info">
<h4>6. Mask Leaks Are NOT the Problem</h4>
<p>Leak rates consistently near zero across all time periods. Median leak 0.00 L/s. Mask fit/seal is not a contributing factor.</p>
</div>
<div class="finding-box info">
<h4>7. Clonidine-REM Interaction</h4>
<p>Current under-dosing of clonidine ER (0.12-0.13mg vs prescribed 0.15mg) means less REM suppression &rarr; more REM sleep &rarr; more opportunity for REM-related OA clusters. Full dose suppresses REM by ~40%. However, higher dose also raises arousal threshold. Needs coordinated specialist discussion.</p>
</div>
</div>
<!-- RECOMMENDATIONS -->
<div class="section" id="sec-recs">
<div class="card">
<h2>Recommendations</h2>
<h3>Organized by urgency: tonight, specialist visit, ongoing monitoring</h3>
</div>
<ul class="rec-list">
<li class="tonight">
<div class="rec-tag">Do Tonight</div>
<div class="rec-title">Stop power-cycling the machine</div>
<div class="rec-body">Leave the machine on when she disconnects the hose. Power-cycling forces a full restart from 4 cmH2O ramp pressure. Leaving it on won't fully solve the ramp issue (SmartStart still applies ramp), but it's less disruptive.</div>
</li>
<li class="tonight">
<div class="rec-tag">Do Tonight</div>
<div class="rec-title">Fix the hose routing</div>
<div class="rec-body">Unthread the hose from the headboard. Mount the 3D-printed hook on the wall above her pillow and route the hose from overhead. The current through-headboard routing creates a fixed anchor that pulls on the mask during position changes, potentially causing mask-off events and discouraging lateral sleep.</div>
</li>
<li class="tonight">
<div class="rec-tag">Do Tonight</div>
<div class="rec-title">Encourage lateral sleeping</div>
<div class="rec-body">Place a firm pillow or rolled blanket behind her back after she falls asleep on her side. A body pillow she can hug in front naturally encourages side positioning. Pool noodle under the fitted sheet creates a ridge that discourages supine without waking her.</div>
</li>
<li class="specialist">
<div class="rec-tag">Specialist Visit</div>
<div class="rec-title">Share this data — especially the worsening trend</div>
<div class="rec-body">The progressive worsening (avg AHI 1.5 &rarr; 2.8 over two weeks, spike nights getting worse) suggests something is actively changing. Bring the nightly AHI table and hourly heatmaps to show the pattern.</div>
</li>
<li class="specialist">
<div class="rec-tag">Specialist Visit</div>
<div class="rec-title">Ramp start pressure — raise or disable</div>
<div class="rec-body">The 4 cmH2O ramp restart is clearly counterproductive during mid-night wakeups. Ask about raising ramp start to 6 cmH2O (the minimum therapeutic pressure) or disabling ramp entirely. This addresses the vicious restart cycle.</div>
</li>
<li class="specialist">
<div class="rec-tag">Specialist Visit</div>
<div class="rec-title">Repeat sleep study with positional monitoring</div>
<div class="rec-body">Already planned. The AHI variability (0.6 to 5.6) strongly suggests a positional component. Body position tracking during the study would confirm whether supine position triggers the OA clusters and determine the true pressure needed for supine + REM conditions.</div>
</li>
<li class="specialist">
<div class="rec-tag">Specialist Visit</div>
<div class="rec-title">Pressure ceiling discussion</div>
<div class="rec-body">The machine is at 11 cmH2O max and still failing during OA clusters. For a 6-year-old this is already high — the right answer might be raising pressure OR addressing the underlying cause (growth, positional factors). Let the sleep study guide this.</div>
</li>
<li class="specialist">
<div class="rec-tag">Specialist Visit</div>
<div class="rec-title">Coordinate clonidine dosing with sleep specialist</div>
<div class="rec-body">Current underdose (0.12-0.13mg vs prescribed 0.15mg) provides less REM suppression. Full dose may reduce REM-related OA clusters, but also raises arousal threshold. The prescribing physician and sleep specialist should discuss together.</div>
</li>
<li class="specialist">
<div class="rec-tag">Specialist Visit</div>
<div class="rec-title">Airway re-evaluation</div>
<div class="rec-body">Is residual adenoid tissue enlarging with the growth spurt? The progressive worsening at 6-8 weeks post-op warrants a look at the airway anatomy, especially given her age (peak adenoid growth: 2-8 years) and increased appetite.</div>
</li>
<li class="monitor">
<div class="rec-tag">Ongoing</div>
<div class="rec-title">Track whether positional changes help</div>
<div class="rec-body">After implementing pillow/noodle/hose changes, compare AHI and session counts for the next week against the current baseline. If the positional hypothesis is correct, you should see fewer spike nights.</div>
</li>
<li class="monitor">
<div class="rec-tag">Ongoing</div>
<div class="rec-title">Watch for the trend to continue or stabilize</div>
<div class="rec-body">If the worsening trend continues despite the mechanical fixes, that points more strongly toward anatomical changes (growth) that need clinical intervention.</div>
</li>
</ul>
</div>
</div>
<script>
// ============================================================
// DATA
// ============================================================
const DATES = [
'02-21','02-22','02-23','02-24','02-25','02-26','02-27',
'02-28','03-01','03-02','03-03','03-04','03-05','03-06',
'03-07','03-08','03-09','03-10'
];
const LABELS = DATES.map(d => d.replace('-','/'));
const AHI = [0.6,1.1,1.2,1.2,4.3,1.0,1.1, 2.8,1.4,4.0,1.1,1.8,3.2,5.6, 1.7,1.2,1.2,5.2];
const OAI = [0.1,0.8,1.0,1.1,4.3,0.4,1.0, 1.5,1.3,3.6,0.8,1.5,2.6,5.6, 1.2,1.1,1.0,5.0];
const OA_CT = [2,10,9,12,43,5,10, 12,13,36,9,13,22,49, 15,12,11,53];
const SESSIONS = [1,18,18,28,25,11,17, 6,16,14,11,15,6,22, 8,18,11,20];
const HOURS = ['19','20','21','22','23','00','01','02','03','04','05','06'];
const HOUR_LABELS = HOURS.map(h => h + ':00');
const HM_DATES = ['02-28','03-01','03-02','03-03','03-04','03-05','03-06','03-07','03-08','03-09','03-10'];
const OA_BY_HOUR = [
[0,9,1,0,1,0,1,0,0,0,0,0],
[0,0,0,1,0,0,1,0,9,1,1,0],
[0,8,5,1,0,1,3,0,7,0,11,0],
[0,4,0,0,0,0,0,3,2,0,0,0],
[0,0,0,0,0,0,0,0,1,11,0,1],
[2,0,0,1,0,0,0,0,0,6,8,5],
[2,0,4,0,0,9,1,4,3,0,15,11],
[0,0,0,0,7,0,0,1,1,0,6,0],
[0,0,0,0,1,1,5,0,3,0,0,0],
[0,0,0,0,0,1,3,0,0,0,7,0],
[0,0,0,0,0,0,1,34,15,3,0,0],
];
const ALL_EV_BY_HOUR = [
[0,9,2,0,2,0,2,1,0,4,1,0],
[0,0,0,2,1,2,1,0,10,2,2,0],
[1,9,5,1,0,1,4,0,7,0,13,0],
[0,6,0,1,0,0,0,3,2,0,0,1],
[0,0,1,0,0,0,0,0,2,11,0,1],
[2,0,0,2,0,0,2,1,0,6,9,6],
[2,0,4,0,0,9,1,5,3,0,15,11],
[0,1,0,0,10,0,0,2,3,0,6,2],
[0,0,1,1,1,1,6,0,3,0,0,0],
[1,0,0,0,0,1,3,0,1,0,9,0],
[1,0,0,0,1,0,1,34,17,3,0,0],
];
const SESS_BY_HOUR = [
[0,3,1,0,0,0,0,0,0,1,0,0],
[2,3,3,4,0,0,1,0,3,0,0,0],
[3,3,4,1,0,0,1,0,1,1,0,0],
[2,3,0,0,0,1,1,1,2,0,0,1],
[1,0,1,0,2,2,0,0,5,4,0,0],
[1,0,0,0,0,1,0,0,0,2,2,0],
[4,1,3,1,1,2,0,3,1,0,5,1],
[0,0,5,0,0,0,0,0,0,0,2,0],
[1,0,0,1,2,1,7,1,0,0,2,0],
[1,3,0,0,0,1,5,0,0,0,0,0],
[2,1,0,0,1,0,0,6,9,0,0,0],
];
const DUR_BY_HOUR = [
[0,44,92,0,12,0,14,11,0,38,120,0],
[0,0,0,10,0,0,13,0,42,45,10,0],
[0,38,38,11,0,12,30,0,44,0,34,0],
[0,65,0,14,0,0,0,13,10,0,0,0],
[0,0,120,0,0,0,0,0,80,17,0,11],
[53,0,0,68,0,0,12,10,0,30,73,23],
[76,0,18,0,0,35,10,11,15,0,25,24],
[0,0,0,0,33,0,0,11,10,0,13,0],
[0,0,0,0,10,24,33,0,10,0,0,0],
[10,0,0,0,0,12,17,0,10,0,13,0],
[0,0,0,0,0,0,24,29,42,42,0,0],
];
var NIGHTS_DATA = null;
const NIGHTS_DATA_URL = 'https://gist.githubusercontent.com/bojanrajkovic/9641e4f4e3cb43da3276734f0f1e8f5c/raw/nights-data.json';
// ============================================================
// NAVIGATION
// ============================================================
document.querySelectorAll('.nav button').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.nav button').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
btn.classList.add('active');
document.getElementById('sec-' + btn.dataset.tab).classList.add('active');
});
});
// ============================================================
// CHART HELPERS
// ============================================================
function setupCanvas(id) {
const canvas = document.getElementById(id);
const dpr = window.devicePixelRatio || 1;
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr);
return { ctx, w: rect.width, h: rect.height };
}
function drawBarChart(id, data, { color, thresholds, yMax }) {
const { ctx, w, h } = setupCanvas(id);
const pad = { top: 20, right: 16, bottom: 40, left: 40 };
const cw = w - pad.left - pad.right;
const ch = h - pad.top - pad.bottom;
const max = yMax || Math.max(...data) * 1.2;
const barW = Math.min(cw / data.length * 0.7, 24);
const gap = cw / data.length;
ctx.strokeStyle = 'rgba(255,255,255,0.06)';
ctx.lineWidth = 1;
for (let i = 0; i <= 4; i++) {
const y = pad.top + ch - (ch * i / 4);
ctx.beginPath(); ctx.moveTo(pad.left, y); ctx.lineTo(w - pad.right, y); ctx.stroke();
ctx.fillStyle = '#606080';
ctx.font = '10px monospace';
ctx.textAlign = 'right';
ctx.fillText((max * i / 4).toFixed(max > 10 ? 0 : 1), pad.left - 6, y + 3);
}
if (thresholds) {
thresholds.forEach(t => {
const y = pad.top + ch - (ch * t.value / max);
ctx.strokeStyle = t.color || 'rgba(233,69,96,0.4)';
ctx.setLineDash([4, 4]);
ctx.beginPath(); ctx.moveTo(pad.left, y); ctx.lineTo(w - pad.right, y); ctx.stroke();
ctx.setLineDash([]);
ctx.fillStyle = t.color || 'rgba(233,69,96,0.6)';
ctx.font = '10px sans-serif';
ctx.textAlign = 'left';
ctx.fillText(t.label, w - pad.right - 60, y - 4);
});
}
data.forEach((val, i) => {
const x = pad.left + i * gap + (gap - barW) / 2;
const barH = (val / max) * ch;
const y = pad.top + ch - barH;
let c = typeof color === 'function' ? color(val) : color;
ctx.fillStyle = c;
ctx.beginPath();
ctx.roundRect(x, y, barW, barH, [3, 3, 0, 0]);
ctx.fill();
ctx.fillStyle = '#606080';
ctx.font = '9px monospace';
ctx.textAlign = 'center';
ctx.save();
ctx.translate(x + barW / 2, pad.top + ch + 14);
ctx.rotate(-0.5);
ctx.fillText(LABELS[i], 0, 0);
ctx.restore();
});
}
// ============================================================
// RENDER CHARTS
// ============================================================
function renderOverview() {
drawBarChart('ahi-chart', AHI, {
color: v => v >= 5 ? '#e94560' : v >= 3 ? '#f0a500' : '#4ecca3',
yMax: 7,
thresholds: [{ value: 5, label: 'AHI >= 5', color: 'rgba(233,69,96,0.4)' }]
});
drawBarChart('oa-chart', OA_CT, {
color: v => v >= 40 ? '#e94560' : v >= 20 ? '#f0a500' : '#4ecca3',
yMax: 60
});
drawBarChart('sessions-chart', SESSIONS, {
color: v => v >= 20 ? '#e94560' : v >= 15 ? '#f0a500' : 'rgba(78,204,163,0.6)',
yMax: 35
});
}
// ============================================================
// HEATMAPS
// ============================================================
function renderHeatmap(tableId, data, dates, { maxVal, colorFn, emptyChar }) {
const table = document.getElementById(tableId);
emptyChar = emptyChar || '\u00B7';
let html = '<tr><th></th>';
HOUR_LABELS.forEach(h => html += '<th>' + h + '</th>');
html += '<th>Total</th></tr>';
data.forEach((row, ri) => {
const total = row.reduce((a, b) => a + b, 0);
html += '<tr><td class="date-cell">' + dates[ri] + '</td>';
row.forEach(val => {
if (val === 0) {
html += '<td style="color:rgba(255,255,255,0.15)">' + emptyChar + '</td>';
} else {
const intensity = Math.min(val / maxVal, 1);
const bg = colorFn(intensity);
html += '<td style="background:' + bg + ';color:#fff;font-weight:' + (intensity > 0.5 ? 600 : 400) + '">' + val + '</td>';
}
});
html += '<td style="color:' + (total > maxVal * 2 ? '#e94560' : '#a0a0b0') + ';font-weight:600">' + total + '</td>';
html += '</tr>';
});
table.innerHTML = html;
}
function renderHeatmaps() {
renderHeatmap('oa-heatmap', OA_BY_HOUR, HM_DATES, {
maxVal: 15,
colorFn: function(i) { return 'rgba(233,69,96,' + (0.15 + i * 0.75) + ')'; }
});
renderHeatmap('all-events-heatmap', ALL_EV_BY_HOUR, HM_DATES, {
maxVal: 15,
colorFn: function(i) { return 'rgba(240,165,0,' + (0.15 + i * 0.7) + ')'; }
});
renderHeatmap('sessions-heatmap', SESS_BY_HOUR, HM_DATES, {
maxVal: 7,
colorFn: function(i) { return 'rgba(83,52,131,' + (0.2 + i * 0.7) + ')'; }
});
renderHeatmap('duration-heatmap', DUR_BY_HOUR, HM_DATES, {
maxVal: 80,
colorFn: function(i) { return 'rgba(240,165,0,' + (0.15 + i * 0.7) + ')'; }
});
}
// ============================================================
// TREND CHART
// ============================================================
function renderTrend() {
const { ctx, w, h } = setupCanvas('trend-chart');
const pad = { top: 20, right: 50, bottom: 40, left: 50 };
const cw = w - pad.left - pad.right;
const ch = h - pad.top - pad.bottom;
const oaMax = 60;
const ahiMax = 7;
ctx.strokeStyle = 'rgba(255,255,255,0.06)';
for (let i = 0; i <= 4; i++) {
const y = pad.top + ch - (ch * i / 4);
ctx.beginPath(); ctx.moveTo(pad.left, y); ctx.lineTo(w - pad.right, y); ctx.stroke();
ctx.fillStyle = '#e94560';
ctx.font = '10px monospace';
ctx.textAlign = 'right';
ctx.fillText(Math.round(oaMax * i / 4), pad.left - 6, y + 3);
ctx.fillStyle = '#4ecca3';
ctx.textAlign = 'left';
ctx.fillText((ahiMax * i / 4).toFixed(1), w - pad.right + 6, y + 3);
}
var weekRanges = [[0, 7], [7, 14], [14, 18]];
var weekAvgs = [1.5, 2.8, 2.3];
weekRanges.forEach(function(range, wi) {
var s = range[0], e = range[1];
var x1 = pad.left + (s / (DATES.length - 1)) * cw;
var x2 = pad.left + ((e - 1) / (DATES.length - 1)) * cw;
var y = pad.top + ch - (weekAvgs[wi] / ahiMax) * ch;
ctx.fillStyle = 'rgba(240,165,0,0.08)';
ctx.fillRect(x1, y, x2 - x1, pad.top + ch - y);
ctx.strokeStyle = 'rgba(240,165,0,0.4)';
ctx.setLineDash([3, 3]);
ctx.beginPath(); ctx.moveTo(x1, y); ctx.lineTo(x2, y); ctx.stroke();
ctx.setLineDash([]);
ctx.fillStyle = 'rgba(240,165,0,0.6)';
ctx.font = '9px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('avg ' + weekAvgs[wi], (x1 + x2) / 2, y - 4);
});
var gap = cw / DATES.length;
var barW = Math.min(gap * 0.5, 18);
OA_CT.forEach(function(val, i) {
var x = pad.left + i * gap + (gap - barW) / 2;
var barH = (val / oaMax) * ch;
var y = pad.top + ch - barH;
ctx.fillStyle = val >= 40 ? 'rgba(233,69,96,0.8)' : 'rgba(233,69,96,0.4)';
ctx.beginPath();
ctx.roundRect(x, y, barW, barH, [3, 3, 0, 0]);
ctx.fill();
});
ctx.strokeStyle = '#4ecca3';
ctx.lineWidth = 2;
ctx.beginPath();
AHI.forEach(function(val, i) {
var x = pad.left + i * gap + gap / 2;
var y = pad.top + ch - (val / ahiMax) * ch;
if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
});
ctx.stroke();
AHI.forEach(function(val, i) {
var x = pad.left + i * gap + gap / 2;
var y = pad.top + ch - (val / ahiMax) * ch;
ctx.fillStyle = val >= 5 ? '#e94560' : '#4ecca3';
ctx.beginPath();
ctx.arc(x, y, 4, 0, Math.PI * 2);
ctx.fill();
});
LABELS.forEach(function(lbl, i) {
var x = pad.left + i * gap + gap / 2;
ctx.fillStyle = '#606080';
ctx.font = '9px monospace';
ctx.textAlign = 'center';
ctx.save();
ctx.translate(x, pad.top + ch + 14);
ctx.rotate(-0.5);
ctx.fillText(lbl, 0, 0);
ctx.restore();
});
ctx.fillStyle = '#e94560';
ctx.font = '10px sans-serif';
ctx.save();
ctx.translate(12, pad.top + ch / 2);
ctx.rotate(-Math.PI / 2);
ctx.textAlign = 'center';
ctx.fillText('OA Events', 0, 0);
ctx.restore();
ctx.fillStyle = '#4ecca3';
ctx.save();
ctx.translate(w - 8, pad.top + ch / 2);
ctx.rotate(-Math.PI / 2);
ctx.textAlign = 'center';
ctx.fillText('AHI', 0, 0);
ctx.restore();
}
// ============================================================
// NIGHT EXPLORER
// ============================================================
function timeToMin(t) {
var parts = t.split(':');
var h = parseInt(parts[0]), m = parseInt(parts[1]);
if (h < 12) h += 24;
return (h - 18) * 60 + m;
}
function sessionDurationMin(s) {
var startM = timeToMin(s.start);
var endM = timeToMin(s.end);
if (endM <= startM) endM += 24 * 60;
return endM - startM;
}
function pressColor(avgPress) {
if (avgPress < 6) return '#533483';
if (avgPress < 9) return '#f0a500';
return '#e94560';
}
function populateNightSelect() {
var select = document.getElementById('night-select');
if (!NIGHTS_DATA) return;
select.innerHTML = '';
DATES.forEach(function(d) {
if (!NIGHTS_DATA[d]) return;
var opt = document.createElement('option');
opt.value = d;
var dateIdx = DATES.indexOf(d);
var ahi = dateIdx >= 0 ? AHI[dateIdx] : '?';
var oa = dateIdx >= 0 ? OA_CT[dateIdx] : '?';
opt.textContent = NIGHTS_DATA[d].label + ' — AHI ' + ahi + ', ' + oa + ' OAs, ' + NIGHTS_DATA[d].sessions.length + ' sessions';
select.appendChild(opt);
});
// Default to worst night
var worst = DATES.reduce(function(best, d, i) { return AHI[i] > AHI[best] ? i : best; }, 0);
select.value = DATES[worst];
select.addEventListener('change', function() { renderNight(select.value); });
renderNight(DATES[worst]);
}
function renderNight(nightKey) {
if (!NIGHTS_DATA || !NIGHTS_DATA[nightKey]) return;
var night = NIGHTS_DATA[nightKey];
var dateIdx = DATES.indexOf(nightKey);
var ahi = dateIdx >= 0 ? AHI[dateIdx] : null;
var oaCount = dateIdx >= 0 ? OA_CT[dateIdx] : night.totalOA;
var sessions = night.sessions;
// Compute stats
var longestMin = 0;
var totalSleepMin = 0;
sessions.forEach(function(s) {
var dur = sessionDurationMin(s);
totalSleepMin += dur;
if (dur > longestMin) longestMin = dur;
});
var maxPressure = 0;
sessions.forEach(function(s) { if (s.maxPress > maxPressure) maxPressure = s.maxPress; });
// Render stats
var statsHtml = '';
function statClass(val, warnThresh, badThresh, invert) {
if (invert) return val >= badThresh ? 'good' : val >= warnThresh ? 'warn' : 'bad';
return val >= badThresh ? 'bad' : val >= warnThresh ? 'warn' : 'good';
}
statsHtml += '<div class="stat ' + statClass(ahi, 3, 5, false) + '"><div class="label">AHI</div><div class="value">' + (ahi !== null ? ahi : '—') + '</div></div>';
statsHtml += '<div class="stat ' + statClass(oaCount, 15, 30, false) + '"><div class="label">Obstructive Apneas</div><div class="value">' + oaCount + '</div></div>';
statsHtml += '<div class="stat ' + statClass(sessions.length, 10, 18, false) + '"><div class="label">Sessions</div><div class="value">' + sessions.length + '</div></div>';
var longestStr = longestMin >= 60 ? Math.floor(longestMin / 60) + 'h ' + (longestMin % 60) + 'm' : longestMin + 'm';
statsHtml += '<div class="stat ' + statClass(longestMin, 120, 240, true) + '"><div class="label">Longest Session</div><div class="value">' + longestStr + '</div></div>';
var totalStr = totalSleepMin >= 60 ? Math.floor(totalSleepMin / 60) + 'h ' + (totalSleepMin % 60) + 'm' : totalSleepMin + 'm';
statsHtml += '<div class="stat ' + statClass(totalSleepMin, 360, 480, true) + '"><div class="label">Total Mask-On</div><div class="value">' + totalStr + '</div></div>';
document.getElementById('night-stats').innerHTML = statsHtml;
// Render timeline
var container = document.getElementById('night-timeline');
var totalMin = 14 * 60; // 18:00 to 08:00
var html = '<div style="position:relative;height:20px;margin-left:80px;margin-bottom:4px;">';
for (var hh = 18; hh <= 32; hh++) {
var displayH = hh >= 24 ? hh - 24 : hh;
var pct = ((hh - 18) / 14) * 100;
if (hh % 2 === 0 && pct <= 100) {
html += '<span style="position:absolute;left:' + pct + '%;transform:translateX(-50%);font-size:10px;color:#606080;font-family:monospace">' + String(displayH).padStart(2, '0') + ':00</span>';
}
}
html += '</div>';
// Single continuous timeline row
html += '<div class="timeline-row" style="height:28px;">';
html += '<div class="timeline-label">Sessions</div>';
html += '<div class="timeline-bar-container" style="height:28px;">';
sessions.forEach(function(s) {
var startM = timeToMin(s.start);
var endM = timeToMin(s.end);
if (endM <= startM) endM += 24 * 60;
var left = Math.max(0, (startM / totalMin) * 100);
var width = Math.max(((endM - startM) / totalMin) * 100, 0.3);
if (left + width > 100) width = 100 - left;
var color = pressColor(s.avgPress);
var dur = endM - startM;
var durStr = dur >= 60 ? Math.floor(dur / 60) + 'h ' + (dur % 60) + 'm' : dur + 'm';
html += '<div class="timeline-bar" style="left:' + left + '%;width:' + width + '%;background:' + color + ';border-radius:2px;" title="' + s.start + ' – ' + s.end + ' (' + durStr + ') avg ' + s.avgPress + ' max ' + s.maxPress + ' cmH₂O"></div>';
});
html += '</div></div>';
// Per-session detail rows for fragmented nights
if (sessions.length > 1 && sessions.length <= 30) {
html += '<div style="margin-top:16px;font-size:0.75rem;font-family:\'SF Mono\',monospace;color:var(--text2);">';
html += '<div style="display:grid;grid-template-columns:70px 70px 60px 65px 65px 1fr;gap:4px 12px;padding:4px 0;border-bottom:1px solid var(--border);font-weight:600;color:var(--text);">';
html += '<span>Start</span><span>End</span><span>Dur</span><span>Avg P</span><span>Max P</span><span></span></div>';
sessions.forEach(function(s) {
var dur = sessionDurationMin(s);
var durStr = dur >= 60 ? Math.floor(dur / 60) + 'h' + (dur % 60 ? ' ' + (dur % 60) + 'm' : '') : dur + 'm';
var color = pressColor(s.avgPress);
var barWidth = Math.min((s.maxPress / 11) * 100, 100);
html += '<div style="display:grid;grid-template-columns:70px 70px 60px 65px 65px 1fr;gap:4px 12px;padding:3px 0;border-bottom:1px solid rgba(255,255,255,0.04);align-items:center;">';
html += '<span>' + s.start + '</span>';
html += '<span>' + s.end + '</span>';
html += '<span>' + durStr + '</span>';
html += '<span style="color:' + color + '">' + s.avgPress + '</span>';
html += '<span style="color:' + (s.maxPress >= 10.5 ? '#e94560' : '#a0a0b0') + '">' + s.maxPress + '</span>';
html += '<div style="height:6px;background:rgba(255,255,255,0.05);border-radius:3px;overflow:hidden;"><div style="width:' + barWidth + '%;height:100%;background:' + color + ';border-radius:3px;"></div></div>';
html += '</div>';
});
html += '</div>';
}
container.innerHTML = html;
// Callout
var callout = document.getElementById('night-callout');
var rampSessions = sessions.filter(function(s) { return s.avgPress <= 5; });
var ceilingHits = sessions.filter(function(s) { return s.maxPress >= 10.8; });
var calloutHtml = '';
if (rampSessions.length >= 3 && oaCount > 10) {
calloutHtml += '<div class="finding-box"><h4>Ramp restart cycle detected</h4>';
calloutHtml += '<p>' + rampSessions.length + ' sessions started at ramp pressure (&le;5 cmH&#8322;O). ';
calloutHtml += 'Combined with ' + oaCount + ' obstructive apneas, this suggests the vicious cycle: apnea cluster &rarr; wake &rarr; mask off &rarr; mask on &rarr; ramp at 4 cmH&#8322;O &rarr; immediate collapse &rarr; more apneas.</p></div>';
}
if (ceilingHits.length >= 3) {
calloutHtml += '<div class="finding-box"><h4>Pressure ceiling reached repeatedly</h4>';
calloutHtml += '<p>' + ceilingHits.length + ' sessions hit max pressure (&ge;10.8 cmH&#8322;O). The machine wanted to go higher but is capped at 11. This night needed more pressure than available.</p></div>';
}
if (sessions.length <= 3 && oaCount <= 5) {
calloutHtml += '<div class="finding-box info"><h4>Good night</h4>';
calloutHtml += '<p>Only ' + sessions.length + ' session' + (sessions.length > 1 ? 's' : '') + ' with ' + oaCount + ' OA' + (oaCount !== 1 ? 's' : '') + '. Low fragmentation and few events suggest the position and pressure were working well.</p></div>';
}
callout.innerHTML = calloutHtml;
}
async function loadNightsData() {
try {
var resp = await fetch(NIGHTS_DATA_URL);
NIGHTS_DATA = await resp.json();
populateNightSelect();
} catch(e) {
document.getElementById('night-timeline').innerHTML = '<p style="color:var(--bad)">Failed to load session data: ' + e.message + '</p>';
}
}
// ============================================================
// INIT
// ============================================================
function init() {
renderOverview();
renderHeatmaps();
renderTrend();
loadNightsData();
}
var resizeTimeout;
window.addEventListener('resize', function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(init, 200);
});
init();
</script>
</body>
</html>
{
"02-21": {
"label": "Feb 21 \u2192 Feb 22",
"sessions": [
{
"start": "19:40",
"end": "07:06",
"avgPress": 7.4,
"maxPress": 10.8
}
],
"totalOA": 2,
"totalEvents": 9,
"totalSessions": 1
},
"02-22": {
"label": "Feb 22 \u2192 Feb 23",
"sessions": [
{
"start": "19:18",
"end": "20:50",
"avgPress": 5.6,
"maxPress": 8.6
},
{
"start": "20:51",
"end": "20:58",
"avgPress": 9.4,
"maxPress": 9.5
},
{
"start": "21:00",
"end": "21:02",
"avgPress": 9.5,
"maxPress": 9.5
},
{
"start": "21:06",
"end": "21:10",
"avgPress": 9.4,
"maxPress": 9.5
},
{
"start": "21:13",
"end": "21:15",
"avgPress": 9.3,
"maxPress": 9.3
},
{
"start": "21:21",
"end": "21:34",
"avgPress": 9.8,
"maxPress": 10.6
},
{
"start": "21:36",
"end": "21:44",
"avgPress": 9.8,
"maxPress": 9.9
},
{
"start": "21:46",
"end": "21:48",
"avgPress": 10.4,
"maxPress": 10.5
},
{
"start": "21:49",
"end": "21:53",
"avgPress": 10.3,
"maxPress": 10.5
},
{
"start": "22:02",
"end": "22:06",
"avgPress": 9.9,
"maxPress": 10.2
},
{
"start": "22:08",
"end": "22:12",
"avgPress": 9.5,
"maxPress": 9.8
},
{
"start": "22:32",
"end": "22:43",
"avgPress": 10.6,
"maxPress": 11.0
},
{
"start": "22:46",
"end": "22:48",
"avgPress": 10.7,
"maxPress": 10.7
},
{
"start": "22:53",
"end": "02:43",
"avgPress": 7.8,
"maxPress": 10.7
},
{
"start": "02:44",
"end": "05:31",
"avgPress": 7.1,
"maxPress": 10.6
},
{
"start": "05:32",
"end": "07:33",
"avgPress": 7.7,
"maxPress": 9.7
},
{
"start": "07:34",
"end": "08:24",
"avgPress": 9.3,
"maxPress": 10.7
}
],
"totalOA": 10,
"totalEvents": 16,
"totalSessions": 17
},
"02-23": {
"label": "Feb 23 \u2192 Feb 24",
"sessions": [
{
"start": "20:37",
"end": "21:10",
"avgPress": 7.0,
"maxPress": 7.4
},
{
"start": "21:12",
"end": "21:36",
"avgPress": 6.5,
"maxPress": 6.8
},
{
"start": "21:39",
"end": "21:44",
"avgPress": 6.4,
"maxPress": 6.4
},
{
"start": "21:50",
"end": "22:39",
"avgPress": 9.0,
"maxPress": 11.0
},
{
"start": "22:40",
"end": "22:41",
"avgPress": 7.6,
"maxPress": 7.6
},
{
"start": "22:54",
"end": "22:56",
"avgPress": 7.6,
"maxPress": 7.6
},
{
"start": "22:58",
"end": "23:04",
"avgPress": 7.6,
"maxPress": 7.6
},
{
"start": "23:07",
"end": "00:40",
"avgPress": 7.7,
"maxPress": 10.5
},
{
"start": "00:42",
"end": "00:47",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "00:48",
"end": "00:49",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "00:55",
"end": "03:37",
"avgPress": 6.9,
"maxPress": 8.9
},
{
"start": "03:39",
"end": "03:49",
"avgPress": 6.1,
"maxPress": 10.8
},
{
"start": "03:50",
"end": "04:00",
"avgPress": 10.7,
"maxPress": 11.0
},
{
"start": "04:27",
"end": "04:28",
"avgPress": 10.5,
"maxPress": 10.5
},
{
"start": "04:35",
"end": "05:23",
"avgPress": 8.2,
"maxPress": 10.5
},
{
"start": "05:24",
"end": "05:25",
"avgPress": 8.6,
"maxPress": 8.6
},
{
"start": "05:33",
"end": "05:34",
"avgPress": 8.6,
"maxPress": 8.6
},
{
"start": "06:02",
"end": "06:48",
"avgPress": 9.2,
"maxPress": 11.0
}
],
"totalOA": 9,
"totalEvents": 15,
"totalSessions": 18
},
"02-24": {
"label": "Feb 24 \u2192 Feb 25",
"sessions": [
{
"start": "19:31",
"end": "19:34",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:36",
"end": "19:41",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:43",
"end": "19:45",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:47",
"end": "19:48",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:00",
"end": "20:02",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:04",
"end": "20:08",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:09",
"end": "20:39",
"avgPress": 5.5,
"maxPress": 6.6
},
{
"start": "20:40",
"end": "20:44",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:44",
"end": "20:59",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "21:05",
"end": "21:06",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "21:08",
"end": "21:09",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "21:12",
"end": "22:54",
"avgPress": 6.4,
"maxPress": 7.2
},
{
"start": "22:55",
"end": "22:56",
"avgPress": 6.4,
"maxPress": 6.4
},
{
"start": "23:10",
"end": "23:12",
"avgPress": 6.4,
"maxPress": 6.4
},
{
"start": "23:18",
"end": "01:20",
"avgPress": 7.4,
"maxPress": 9.2
},
{
"start": "01:21",
"end": "01:27",
"avgPress": 6.6,
"maxPress": 6.6
},
{
"start": "01:31",
"end": "01:32",
"avgPress": 6.6,
"maxPress": 6.6
},
{
"start": "01:34",
"end": "02:31",
"avgPress": 7.1,
"maxPress": 9.4
},
{
"start": "02:34",
"end": "03:46",
"avgPress": 9.8,
"maxPress": 11.0
},
{
"start": "03:49",
"end": "03:53",
"avgPress": 10.7,
"maxPress": 11.0
},
{
"start": "03:57",
"end": "04:03",
"avgPress": 10.1,
"maxPress": 10.7
},
{
"start": "04:12",
"end": "04:13",
"avgPress": 9.9,
"maxPress": 9.9
},
{
"start": "04:15",
"end": "04:16",
"avgPress": 9.9,
"maxPress": 9.9
},
{
"start": "04:18",
"end": "05:37",
"avgPress": 8.0,
"maxPress": 9.9
},
{
"start": "05:38",
"end": "05:46",
"avgPress": 8.3,
"maxPress": 9.0
},
{
"start": "05:48",
"end": "05:49",
"avgPress": 9.0,
"maxPress": 9.0
},
{
"start": "05:51",
"end": "06:21",
"avgPress": 7.8,
"maxPress": 9.0
},
{
"start": "06:22",
"end": "06:38",
"avgPress": 9.7,
"maxPress": 11.0
}
],
"totalOA": 12,
"totalEvents": 14,
"totalSessions": 28
},
"02-25": {
"label": "Feb 25 \u2192 Feb 26",
"sessions": [
{
"start": "19:14",
"end": "20:15",
"avgPress": 8.5,
"maxPress": 11.0
},
{
"start": "20:21",
"end": "20:29",
"avgPress": 7.2,
"maxPress": 7.6
},
{
"start": "20:35",
"end": "21:52",
"avgPress": 6.9,
"maxPress": 7.9
},
{
"start": "21:53",
"end": "21:54",
"avgPress": 6.9,
"maxPress": 6.9
},
{
"start": "21:55",
"end": "23:35",
"avgPress": 7.5,
"maxPress": 11.0
},
{
"start": "23:36",
"end": "00:25",
"avgPress": 9.8,
"maxPress": 11.0
},
{
"start": "00:39",
"end": "02:00",
"avgPress": 8.2,
"maxPress": 10.2
},
{
"start": "02:04",
"end": "02:05",
"avgPress": 10.0,
"maxPress": 10.0
},
{
"start": "02:06",
"end": "02:10",
"avgPress": 10.1,
"maxPress": 10.2
},
{
"start": "02:11",
"end": "02:13",
"avgPress": 10.1,
"maxPress": 10.1
},
{
"start": "02:17",
"end": "02:19",
"avgPress": 10.1,
"maxPress": 10.1
},
{
"start": "02:25",
"end": "02:59",
"avgPress": 9.1,
"maxPress": 10.1
},
{
"start": "03:06",
"end": "03:10",
"avgPress": 8.6,
"maxPress": 9.1
},
{
"start": "03:16",
"end": "03:17",
"avgPress": 10.9,
"maxPress": 11.0
},
{
"start": "03:29",
"end": "03:31",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "03:34",
"end": "03:35",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "03:44",
"end": "03:46",
"avgPress": 10.8,
"maxPress": 11.0
},
{
"start": "03:49",
"end": "04:37",
"avgPress": 8.7,
"maxPress": 11.0
},
{
"start": "04:40",
"end": "04:46",
"avgPress": 10.5,
"maxPress": 11.0
},
{
"start": "04:46",
"end": "04:47",
"avgPress": 10.3,
"maxPress": 10.3
},
{
"start": "04:53",
"end": "04:57",
"avgPress": 9.4,
"maxPress": 10.3
},
{
"start": "04:59",
"end": "05:00",
"avgPress": 9.2,
"maxPress": 9.2
},
{
"start": "05:04",
"end": "05:40",
"avgPress": 9.5,
"maxPress": 11.0
},
{
"start": "05:45",
"end": "06:31",
"avgPress": 10.0,
"maxPress": 11.0
},
{
"start": "06:34",
"end": "06:39",
"avgPress": 10.0,
"maxPress": 10.8
}
],
"totalOA": 43,
"totalEvents": 43,
"totalSessions": 25
},
"02-26": {
"label": "Feb 26 \u2192 Feb 27",
"sessions": [
{
"start": "19:18",
"end": "19:20",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:22",
"end": "19:27",
"avgPress": 6.8,
"maxPress": 7.5
},
{
"start": "19:30",
"end": "19:33",
"avgPress": 7.2,
"maxPress": 7.5
},
{
"start": "19:53",
"end": "19:54",
"avgPress": 7.2,
"maxPress": 7.2
},
{
"start": "20:02",
"end": "20:03",
"avgPress": 6.3,
"maxPress": 7.2
},
{
"start": "20:08",
"end": "20:12",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:19",
"end": "00:04",
"avgPress": 6.7,
"maxPress": 9.1
},
{
"start": "00:05",
"end": "00:09",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "00:11",
"end": "00:41",
"avgPress": 4.5,
"maxPress": 6.1
},
{
"start": "00:42",
"end": "00:43",
"avgPress": 6.1,
"maxPress": 6.1
},
{
"start": "00:45",
"end": "06:41",
"avgPress": 7.8,
"maxPress": 11.0
}
],
"totalOA": 5,
"totalEvents": 11,
"totalSessions": 11
},
"02-27": {
"label": "Feb 27 \u2192 Feb 28",
"sessions": [
{
"start": "19:58",
"end": "20:02",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:03",
"end": "20:05",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:10",
"end": "22:58",
"avgPress": 6.9,
"maxPress": 11.0
},
{
"start": "23:08",
"end": "23:49",
"avgPress": 7.5,
"maxPress": 8.9
},
{
"start": "23:49",
"end": "01:04",
"avgPress": 6.4,
"maxPress": 9.0
},
{
"start": "01:06",
"end": "01:09",
"avgPress": 8.9,
"maxPress": 8.9
},
{
"start": "01:11",
"end": "01:12",
"avgPress": 8.9,
"maxPress": 8.9
},
{
"start": "01:16",
"end": "01:22",
"avgPress": 9.5,
"maxPress": 10.3
},
{
"start": "01:24",
"end": "01:37",
"avgPress": 10.3,
"maxPress": 11.0
},
{
"start": "01:38",
"end": "01:44",
"avgPress": 10.6,
"maxPress": 11.0
},
{
"start": "02:19",
"end": "02:20",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "02:37",
"end": "02:38",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "02:44",
"end": "02:45",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "02:55",
"end": "02:56",
"avgPress": 7.8,
"maxPress": 7.8
},
{
"start": "02:59",
"end": "03:00",
"avgPress": 7.8,
"maxPress": 7.8
},
{
"start": "03:18",
"end": "04:26",
"avgPress": 8.2,
"maxPress": 10.5
},
{
"start": "04:27",
"end": "07:27",
"avgPress": 8.9,
"maxPress": 11.0
}
],
"totalOA": 10,
"totalEvents": 13,
"totalSessions": 17
},
"02-28": {
"label": "Feb 28 \u2192 Mar 1",
"sessions": [
{
"start": "20:10",
"end": "20:15",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:16",
"end": "20:37",
"avgPress": 9.7,
"maxPress": 11.0
},
{
"start": "20:39",
"end": "20:40",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "21:42",
"end": "04:56",
"avgPress": 8.2,
"maxPress": 11.0
},
{
"start": "04:57",
"end": "04:58",
"avgPress": 8.3,
"maxPress": 8.3
},
{
"start": "07:21",
"end": "07:23",
"avgPress": 8.2,
"maxPress": 8.3
}
],
"totalOA": 12,
"totalEvents": 22,
"totalSessions": 6
},
"03-01": {
"label": "Mar 1 \u2192 Mar 2",
"sessions": [
{
"start": "19:35",
"end": "19:42",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:45",
"end": "19:50",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:24",
"end": "20:25",
"avgPress": 6.0,
"maxPress": 6.0
},
{
"start": "20:32",
"end": "20:37",
"avgPress": 6.0,
"maxPress": 6.0
},
{
"start": "20:41",
"end": "20:45",
"avgPress": 6.0,
"maxPress": 6.0
},
{
"start": "21:17",
"end": "21:25",
"avgPress": 6.0,
"maxPress": 6.0
},
{
"start": "21:31",
"end": "21:33",
"avgPress": 6.1,
"maxPress": 6.1
},
{
"start": "21:36",
"end": "22:02",
"avgPress": 6.7,
"maxPress": 7.0
},
{
"start": "22:03",
"end": "22:29",
"avgPress": 5.6,
"maxPress": 6.0
},
{
"start": "22:31",
"end": "22:32",
"avgPress": 6.0,
"maxPress": 6.0
},
{
"start": "22:33",
"end": "22:35",
"avgPress": 6.0,
"maxPress": 6.0
},
{
"start": "22:39",
"end": "01:22",
"avgPress": 8.8,
"maxPress": 11.0
},
{
"start": "01:22",
"end": "03:19",
"avgPress": 8.3,
"maxPress": 11.0
},
{
"start": "03:21",
"end": "03:40",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "03:44",
"end": "03:46",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "03:47",
"end": "06:44",
"avgPress": 8.5,
"maxPress": 11.0
}
],
"totalOA": 13,
"totalEvents": 20,
"totalSessions": 16
},
"03-02": {
"label": "Mar 2 \u2192 Mar 3",
"sessions": [
{
"start": "19:02",
"end": "19:05",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:09",
"end": "19:52",
"avgPress": 8.3,
"maxPress": 11.0
},
{
"start": "19:53",
"end": "20:33",
"avgPress": 9.9,
"maxPress": 11.0
},
{
"start": "20:36",
"end": "20:38",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "20:41",
"end": "20:49",
"avgPress": 10.8,
"maxPress": 11.0
},
{
"start": "20:57",
"end": "20:59",
"avgPress": 10.6,
"maxPress": 10.6
},
{
"start": "21:09",
"end": "21:11",
"avgPress": 9.5,
"maxPress": 10.6
},
{
"start": "21:25",
"end": "21:26",
"avgPress": 10.0,
"maxPress": 11.0
},
{
"start": "21:28",
"end": "21:54",
"avgPress": 9.9,
"maxPress": 11.0
},
{
"start": "21:56",
"end": "22:12",
"avgPress": 5.6,
"maxPress": 7.1
},
{
"start": "22:21",
"end": "01:16",
"avgPress": 7.9,
"maxPress": 11.0
},
{
"start": "01:17",
"end": "03:50",
"avgPress": 7.6,
"maxPress": 11.0
},
{
"start": "03:58",
"end": "04:36",
"avgPress": 9.6,
"maxPress": 11.0
},
{
"start": "04:37",
"end": "05:47",
"avgPress": 8.4,
"maxPress": 11.0
}
],
"totalOA": 36,
"totalEvents": 41,
"totalSessions": 14
},
"03-03": {
"label": "Mar 3 \u2192 Mar 4",
"sessions": [
{
"start": "19:17",
"end": "19:22",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:23",
"end": "19:31",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "20:16",
"end": "20:23",
"avgPress": 6.0,
"maxPress": 6.0
},
{
"start": "20:29",
"end": "20:31",
"avgPress": 8.7,
"maxPress": 8.7
},
{
"start": "20:36",
"end": "00:47",
"avgPress": 8.2,
"maxPress": 11.0
},
{
"start": "00:49",
"end": "01:43",
"avgPress": 8.3,
"maxPress": 10.9
},
{
"start": "01:53",
"end": "02:04",
"avgPress": 8.2,
"maxPress": 10.6
},
{
"start": "02:08",
"end": "03:05",
"avgPress": 8.5,
"maxPress": 10.6
},
{
"start": "03:08",
"end": "03:10",
"avgPress": 10.4,
"maxPress": 10.5
},
{
"start": "03:14",
"end": "06:05",
"avgPress": 8.2,
"maxPress": 11.0
},
{
"start": "06:07",
"end": "06:40",
"avgPress": 8.5,
"maxPress": 9.1
}
],
"totalOA": 9,
"totalEvents": 13,
"totalSessions": 11
},
"03-04": {
"label": "Mar 4 \u2192 Mar 5",
"sessions": [
{
"start": "19:32",
"end": "21:02",
"avgPress": 7.3,
"maxPress": 11.0
},
{
"start": "21:02",
"end": "21:17",
"avgPress": 4.8,
"maxPress": 6.0
},
{
"start": "23:31",
"end": "23:34",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "23:37",
"end": "00:22",
"avgPress": 6.6,
"maxPress": 8.1
},
{
"start": "00:27",
"end": "00:32",
"avgPress": 8.1,
"maxPress": 8.1
},
{
"start": "00:33",
"end": "03:15",
"avgPress": 7.6,
"maxPress": 11.0
},
{
"start": "03:18",
"end": "03:44",
"avgPress": 10.3,
"maxPress": 11.0
},
{
"start": "03:47",
"end": "03:48",
"avgPress": 10.6,
"maxPress": 10.6
},
{
"start": "03:50",
"end": "03:51",
"avgPress": 10.6,
"maxPress": 10.6
},
{
"start": "03:54",
"end": "03:57",
"avgPress": 10.6,
"maxPress": 10.6
},
{
"start": "03:59",
"end": "04:00",
"avgPress": 10.6,
"maxPress": 10.6
},
{
"start": "04:12",
"end": "04:25",
"avgPress": 9.9,
"maxPress": 10.6
},
{
"start": "04:27",
"end": "04:30",
"avgPress": 10.8,
"maxPress": 10.8
},
{
"start": "04:32",
"end": "04:46",
"avgPress": 10.5,
"maxPress": 11.0
},
{
"start": "04:57",
"end": "06:40",
"avgPress": 8.7,
"maxPress": 11.0
}
],
"totalOA": 13,
"totalEvents": 15,
"totalSessions": 15
},
"03-05": {
"label": "Mar 5 \u2192 Mar 6",
"sessions": [
{
"start": "19:34",
"end": "22:30",
"avgPress": 8.0,
"maxPress": 11.0
},
{
"start": "00:32",
"end": "04:07",
"avgPress": 7.2,
"maxPress": 10.4
},
{
"start": "04:09",
"end": "04:10",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "04:14",
"end": "05:12",
"avgPress": 8.7,
"maxPress": 11.0
},
{
"start": "05:20",
"end": "05:41",
"avgPress": 10.3,
"maxPress": 11.0
},
{
"start": "05:50",
"end": "06:10",
"avgPress": 10.5,
"maxPress": 11.0
}
],
"totalOA": 22,
"totalEvents": 28,
"totalSessions": 6
},
"03-06": {
"label": "Mar 6 \u2192 Mar 7",
"sessions": [
{
"start": "19:37",
"end": "19:39",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:42",
"end": "19:44",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:48",
"end": "19:50",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "19:52",
"end": "19:57",
"avgPress": 4.3,
"maxPress": 5.9
},
{
"start": "20:00",
"end": "20:57",
"avgPress": 9.0,
"maxPress": 10.9
},
{
"start": "21:35",
"end": "21:41",
"avgPress": 8.9,
"maxPress": 10.7
},
{
"start": "21:44",
"end": "21:51",
"avgPress": 10.5,
"maxPress": 10.6
},
{
"start": "21:52",
"end": "21:55",
"avgPress": 10.9,
"maxPress": 11.0
},
{
"start": "22:02",
"end": "22:40",
"avgPress": 9.8,
"maxPress": 11.0
},
{
"start": "23:43",
"end": "00:40",
"avgPress": 7.1,
"maxPress": 11.0
},
{
"start": "00:40",
"end": "00:47",
"avgPress": 10.6,
"maxPress": 11.0
},
{
"start": "00:51",
"end": "02:22",
"avgPress": 8.7,
"maxPress": 11.0
},
{
"start": "02:23",
"end": "02:47",
"avgPress": 8.6,
"maxPress": 10.2
},
{
"start": "02:50",
"end": "02:54",
"avgPress": 10.4,
"maxPress": 10.7
},
{
"start": "02:56",
"end": "02:58",
"avgPress": 10.5,
"maxPress": 10.7
},
{
"start": "03:02",
"end": "05:21",
"avgPress": 9.9,
"maxPress": 11.0
},
{
"start": "05:22",
"end": "05:32",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "05:33",
"end": "05:35",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "05:36",
"end": "05:45",
"avgPress": 10.8,
"maxPress": 11.0
},
{
"start": "05:47",
"end": "05:51",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "05:58",
"end": "05:59",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "06:06",
"end": "06:37",
"avgPress": 10.6,
"maxPress": 11.0
}
],
"totalOA": 49,
"totalEvents": 50,
"totalSessions": 22
},
"03-07": {
"label": "Mar 7 \u2192 Mar 8",
"sessions": [
{
"start": "18:56",
"end": "21:05",
"avgPress": 8.2,
"maxPress": 11.0
},
{
"start": "21:08",
"end": "21:10",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "21:10",
"end": "21:19",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "21:21",
"end": "21:22",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "21:24",
"end": "21:29",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "21:29",
"end": "05:34",
"avgPress": 8.1,
"maxPress": 11.0
},
{
"start": "05:35",
"end": "05:56",
"avgPress": 10.1,
"maxPress": 11.0
},
{
"start": "05:59",
"end": "06:45",
"avgPress": 8.8,
"maxPress": 11.0
}
],
"totalOA": 15,
"totalEvents": 24,
"totalSessions": 8
},
"03-08": {
"label": "Mar 8 \u2192 Mar 9",
"sessions": [
{
"start": "18:43",
"end": "18:47",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "18:53",
"end": "18:54",
"avgPress": 8.5,
"maxPress": 10.0
},
{
"start": "18:55",
"end": "19:49",
"avgPress": 9.3,
"maxPress": 11.0
},
{
"start": "19:50",
"end": "22:03",
"avgPress": 8.3,
"maxPress": 11.0
},
{
"start": "22:06",
"end": "23:58",
"avgPress": 8.3,
"maxPress": 11.0
},
{
"start": "23:59",
"end": "00:52",
"avgPress": 6.6,
"maxPress": 7.7
},
{
"start": "00:55",
"end": "01:08",
"avgPress": 9.6,
"maxPress": 11.0
},
{
"start": "01:11",
"end": "01:14",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "01:15",
"end": "01:16",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "01:17",
"end": "01:25",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "01:26",
"end": "01:28",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "01:30",
"end": "01:39",
"avgPress": 4.1,
"maxPress": 5.2
},
{
"start": "01:40",
"end": "01:47",
"avgPress": 7.0,
"maxPress": 8.6
},
{
"start": "01:49",
"end": "01:52",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "02:02",
"end": "05:32",
"avgPress": 7.6,
"maxPress": 10.2
},
{
"start": "05:34",
"end": "05:35",
"avgPress": 9.5,
"maxPress": 9.5
},
{
"start": "05:40",
"end": "05:41",
"avgPress": 9.5,
"maxPress": 9.5
}
],
"totalOA": 12,
"totalEvents": 15,
"totalSessions": 17
},
"03-09": {
"label": "Mar 9 \u2192 Mar 10",
"sessions": [
{
"start": "18:31",
"end": "19:17",
"avgPress": 5.2,
"maxPress": 6.8
},
{
"start": "19:18",
"end": "20:22",
"avgPress": 8.2,
"maxPress": 10.8
},
{
"start": "20:22",
"end": "20:26",
"avgPress": 7.2,
"maxPress": 7.2
},
{
"start": "20:28",
"end": "20:29",
"avgPress": 7.2,
"maxPress": 7.2
},
{
"start": "20:51",
"end": "00:58",
"avgPress": 7.3,
"maxPress": 9.2
},
{
"start": "00:59",
"end": "01:22",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "01:24",
"end": "01:30",
"avgPress": 7.2,
"maxPress": 9.8
},
{
"start": "01:32",
"end": "01:43",
"avgPress": 9.5,
"maxPress": 9.8
},
{
"start": "01:44",
"end": "01:49",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "01:53",
"end": "01:55",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "01:56",
"end": "05:44",
"avgPress": 7.4,
"maxPress": 11.0
}
],
"totalOA": 11,
"totalEvents": 15,
"totalSessions": 11
},
"03-10": {
"label": "Mar 10 \u2192 Mar 11",
"sessions": [
{
"start": "18:38",
"end": "19:34",
"avgPress": 6.5,
"maxPress": 11.0
},
{
"start": "19:35",
"end": "19:38",
"avgPress": 10.6,
"maxPress": 11.0
},
{
"start": "19:39",
"end": "20:49",
"avgPress": 7.2,
"maxPress": 10.4
},
{
"start": "20:51",
"end": "23:16",
"avgPress": 7.3,
"maxPress": 11.0
},
{
"start": "23:17",
"end": "02:16",
"avgPress": 8.3,
"maxPress": 11.0
},
{
"start": "02:17",
"end": "02:29",
"avgPress": 7.4,
"maxPress": 11.0
},
{
"start": "02:31",
"end": "02:37",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "02:38",
"end": "02:39",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "02:41",
"end": "02:47",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "02:49",
"end": "02:52",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "02:58",
"end": "03:02",
"avgPress": 11.0,
"maxPress": 11.0
},
{
"start": "03:04",
"end": "03:07",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "03:10",
"end": "03:14",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "03:14",
"end": "03:21",
"avgPress": 6.8,
"maxPress": 11.0
},
{
"start": "03:39",
"end": "03:41",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "03:41",
"end": "03:42",
"avgPress": 4.0,
"maxPress": 4.0
},
{
"start": "03:44",
"end": "03:45",
"avgPress": 4.5,
"maxPress": 4.9
},
{
"start": "03:48",
"end": "03:58",
"avgPress": 10.4,
"maxPress": 11.0
},
{
"start": "03:59",
"end": "05:39",
"avgPress": 8.7,
"maxPress": 11.0
}
],
"totalOA": 53,
"totalEvents": 57,
"totalSessions": 19
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment