Skip to content

Commit 762be1c

Browse files
committed
Integrate modification
1 parent 896b766 commit 762be1c

79 files changed

Lines changed: 8570 additions & 603 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/.idea/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/.idea/docs.iml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/.idea/inspectionProfiles/Project_Default.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/.idea/inspectionProfiles/profiles_settings.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/.idea/misc.xml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/.idea/vcs.xml

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/css/style.css

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,12 @@ html, body { height: 100%; font-family: 'Inter', -apple-system, BlinkMacSystemFo
5454
}
5555
.port-btn:hover { background: var(--bg-hover); }
5656
.port-btn.active { background: rgba(88,166,255,0.12); border-color: var(--accent); }
57-
.port-btn.compare { background: rgba(255,123,114,0.10); border-color: rgba(255,123,114,0.65); }
5857
.port-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
5958
.port-info { flex: 1; min-width: 0; }
6059
.port-name { font-weight: 500; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
6160
.port-meta { font-size: 11px; color: var(--text-sec); }
6261
.port-chevron { color: var(--text-sec); font-size: 10px; }
6362
.port-btn.active .port-chevron { color: var(--accent); }
64-
.port-btn.compare .port-chevron { color: #ff7b72; }
6563

6664
.filter-row { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
6765
.filter-label { font-size: 11px; color: var(--text-sec); display: flex; justify-content: space-between; }
@@ -132,14 +130,20 @@ input[type="range"] {
132130
.rp-section:last-child { border-bottom: none; }
133131

134132
.chart-wrap { width: 100%; position: relative; }
135-
#chart-hourly,
136-
#chart-hourly-compare { height: 110px; width: 100%; display: block; }
137-
#chart-sog,
138-
#chart-sog-compare { height: 90px; width: 100%; display: block; }
139-
#chart-types,
140-
#chart-types-compare { height: 160px; width: 100%; display: block; }
141-
#chart-status,
142-
#chart-status-compare { height: 130px; width: 100%; display: block; }
133+
#chart-monthly{ height: 100px; width: 100%; display: block; }
134+
#chart-hourly { height: 110px; width: 100%; display: block; }
135+
#chart-sog { height: 90px; width: 100%; display: block; }
136+
#chart-types { height: 160px; width: 100%; display: block; }
137+
#chart-status { height: 110px; width: 100%; display: block; }
138+
139+
.month-ticks {
140+
display: flex; justify-content: space-between;
141+
padding: 0 1px; margin-top: 2px;
142+
}
143+
.month-ticks span {
144+
font-size: 9px; color: var(--text-sec); line-height: 1;
145+
width: calc(100% / 12); text-align: center;
146+
}
143147

144148

145149
.vessel-popup { min-width: 160px; }
@@ -190,30 +194,6 @@ input[type="range"] {
190194
.pdc-header { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
191195
.pdc-dot { width: 12px; height: 12px; border-radius: 50%; }
192196
.pdc-name { font-weight: 700; font-size: 13px; }
193-
.pdc-stat-rows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
194-
.pdc-stat-row {
195-
background: var(--bg-dark); border: 1px solid var(--border);
196-
border-radius: 6px; padding: 8px;
197-
}
198-
.pdc-stat-row.compare { border-color: rgba(255,123,114,0.45); background: rgba(255,123,114,0.05); }
199-
.pdc-stat-row-head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
200-
.pdc-row-title { min-width: 0; }
201-
.pdc-role {
202-
font-size: 9px; font-weight: 600; letter-spacing: .06em;
203-
text-transform: uppercase; color: var(--text-sec);
204-
}
205-
.pdc-row-name { font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
206-
.pdc-row-metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
207-
.pdc-row-metric { background: var(--bg-panel); border-radius: 5px; padding: 6px 7px; min-width: 0; }
208-
.pdc-compare-control { margin: 10px 0 12px; }
209-
.pdc-compare-control label {
210-
display: block; font-size: 10px; font-weight: 600; letter-spacing: .06em;
211-
text-transform: uppercase; color: var(--text-sec); margin-bottom: 5px;
212-
}
213-
.pdc-compare-control select {
214-
width: 100%; background: var(--bg-dark); border: 1px solid var(--border);
215-
border-radius: 5px; color: var(--text-prim); padding: 6px 8px; font-size: 11px;
216-
}
217197
.pdc-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 10px; }
218198
.pdc-stat { background: var(--bg-dark); border-radius: 5px; padding: 7px 9px; }
219199
.pdc-stat-val { font-size: 15px; font-weight: 700; line-height: 1; }
@@ -231,21 +211,33 @@ input[type="range"] {
231211
border-bottom: 1px solid var(--border);
232212
display: flex; align-items: center; gap: 6px;
233213
}
234-
.activity-context-bar.compare { border-top: 1px solid rgba(255,123,114,0.35); }
235-
.compare-chart-group { display: none; }
236-
.compare-chart-group.visible { display: block; }
237214
#activity-context-label,
238-
#fleet-context-label,
239-
#activity-compare-context-label,
240-
#fleet-compare-context-label {
215+
#fleet-context-label {
241216
font-size: 10px; font-weight: 600; letter-spacing: .05em;
242217
text-transform: uppercase; color: var(--text-sec);
243218
}
244219
#activity-context-label.port-mode,
245220
#fleet-context-label.port-mode { color: var(--accent); }
246-
#activity-compare-context-label,
247-
#fleet-compare-context-label { color: #ff7b72; }
248221
.chart-scope-note {
249222
font-size: 9px; font-weight: 400; text-transform: none;
250223
letter-spacing: 0; color: var(--text-sec); opacity: .75;
251224
}
225+
226+
/* ── Play animation buttons ─────────────────────────────────────────── */
227+
.play-controls { display: flex; gap: 6px; margin-top: 2px; }
228+
.play-btn {
229+
flex: 1; padding: 5px 0; border-radius: 5px; font-size: 11px; font-weight: 500;
230+
cursor: pointer; background: var(--bg-card); border: 1px solid var(--border);
231+
color: var(--text-sec); transition: background 0.15s, color 0.15s, border-color 0.15s;
232+
}
233+
.play-btn:hover { background: var(--bg-hover); color: var(--text-prim); }
234+
.play-btn.playing {
235+
background: rgba(63,185,80,0.15); border-color: rgba(63,185,80,0.5);
236+
color: #3fb950;
237+
}
238+
239+
/* ── Heatmap / extra map tools ──────────────────────────────────────── */
240+
#map-tools { top: 50px; right: 12px; padding: 5px 8px; }
241+
242+
/* ── Radar chart ────────────────────────────────────────────────────── */
243+
#chart-radar { height: 230px; width: 100%; display: block; }

docs/data/_audit_stats.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import json
2+
3+
with open("stats.json") as f:
4+
s = json.load(f)
5+
6+
total = s["global"]["total_records"]
7+
print(f"Expected total records : {total:,}")
8+
print()
9+
10+
h_sum = sum(r["n_records"] for r in s["hourly_activity"])
11+
print(f"hourly_activity sum : {h_sum:,} ({100*h_sum/total:.1f}% of total)")
12+
13+
m_sum = sum(r["n_records"] for r in s["monthly_activity"])
14+
print(f"monthly_activity sum : {m_sum:,} ({100*m_sum/total:.1f}% of total)")
15+
16+
ns_sum = sum(r["n_records"] for r in s["nav_status"])
17+
print(f"nav_status sum : {ns_sum:,} ({100*ns_sum/total:.1f}% of total)")
18+
19+
sog_sum = sum(r["count"] for r in s["sog_distribution"])
20+
print(f"sog_distribution sum : {sog_sum:,} ({100*sog_sum/total:.1f}% of total)")
21+
22+
vt_sum = sum(r["n_unique"] for r in s["vessel_types"])
23+
print(f"vessel_types sum : {vt_sum:,} (unique vessels, expect {s['global']['unique_vessels']:,})")
24+
25+
print()
26+
print("--- hourly_activity sample ---")
27+
for r in s["hourly_activity"][:4]:
28+
print(f" hour {r['hour']:02d}: {r['n_records']:,}")

docs/data/_check_vtypes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import json
2+
with open('stats.json') as f:
3+
s = json.load(f)
4+
total = sum(v['n_unique'] for v in s['vessel_types'])
5+
print(f"Total from vessel_types breakdown: {total:,}")
6+
print(f"Global unique_vessels field: {s['global']['unique_vessels']:,}")
7+
print()
8+
print("Top 10 types:")
9+
for v in s['vessel_types'][:10]:
10+
print(f" {v['type']}: {v['n_unique']}")

0 commit comments

Comments
 (0)