mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-07 01:05:51 +08:00
seggs
This commit is contained in:
@@ -19,7 +19,7 @@ import { ModelManager } from "/assets/components/tools/model_manager.js?v=202603
|
||||
import { LivePlots } from "/assets/components/tools/plots.js"
|
||||
import { ThemeMaker } from "/assets/components/tools/theme_maker.js"
|
||||
import { TestingGround } from "/assets/components/tools/testing_ground.js"
|
||||
import { Tuning } from "/assets/components/tools/tuning.js?v=flm-saved-tunes-1"
|
||||
import { Tuning } from "/assets/components/tools/tuning.js?v=flm-route-length-1"
|
||||
import { Troubleshoot } from "/assets/components/tools/troubleshoot.js"
|
||||
import { TmuxLog } from "/assets/components/tools/tmux.js"
|
||||
import { ToggleControl } from "/assets/components/tools/toggles.js"
|
||||
|
||||
@@ -57,6 +57,16 @@ function safeCount(value) {
|
||||
return Number.isFinite(n) ? n : 0
|
||||
}
|
||||
|
||||
function formatRouteLength(route) {
|
||||
const segmentCount = Math.max(0, Math.round(safeCount(route?.segmentCount)))
|
||||
if (!segmentCount) return "Length unavailable"
|
||||
const approximateMinutes = Math.max(1, Math.round(safeCount(route?.approxDurationSeconds) / 60) || segmentCount)
|
||||
const duration = approximateMinutes >= 60
|
||||
? `~${Math.floor(approximateMinutes / 60)}h ${approximateMinutes % 60}m`
|
||||
: `~${approximateMinutes} min`
|
||||
return `${segmentCount} segment${segmentCount === 1 ? "" : "s"} (${duration})`
|
||||
}
|
||||
|
||||
function connectRouteUrl(routeName) {
|
||||
const dongleId = String(state.connectDongleId || "").trim()
|
||||
const routeId = String(routeName || "").trim()
|
||||
@@ -1196,6 +1206,7 @@ export function Tuning() {
|
||||
<span>
|
||||
<strong>${route.timestampLabel}</strong>
|
||||
<small>${route.name}</small>
|
||||
<small>${formatRouteLength(route)}</small>
|
||||
</span>
|
||||
</label>
|
||||
${() => connectRouteUrl(route.name) ? html`
|
||||
|
||||
@@ -259,6 +259,21 @@ class FakeDashboardAnalyzerProcess:
|
||||
self.terminated = True
|
||||
|
||||
|
||||
def test_route_inventory_counts_segments_without_video_probing(monkeypatch):
|
||||
segments = [
|
||||
SimpleNamespace(route_name=SimpleNamespace(time_str="route-new")),
|
||||
SimpleNamespace(route_name=SimpleNamespace(time_str="route-new")),
|
||||
SimpleNamespace(route_name=SimpleNamespace(time_str="route-new")),
|
||||
SimpleNamespace(route_name=SimpleNamespace(time_str="route-old")),
|
||||
]
|
||||
monkeypatch.setattr(utilities, "get_all_segment_names", lambda _path: segments)
|
||||
|
||||
assert utilities.get_routes_with_segment_counts("/tmp/routes") == [
|
||||
("route-old", 1),
|
||||
("route-new", 3),
|
||||
]
|
||||
|
||||
|
||||
def test_dashboard_background_analysis_does_not_start_onroad(monkeypatch):
|
||||
def fail_if_started(*args, **kwargs):
|
||||
raise AssertionError("worker started onroad")
|
||||
|
||||
@@ -5350,13 +5350,20 @@ def setup(app):
|
||||
@app.route("/api/routes", methods=["GET"])
|
||||
def list_routes():
|
||||
def generate():
|
||||
routes = [(path, name) for path in FOOTAGE_PATHS for name in utilities.get_routes_names(path)]
|
||||
routes = [
|
||||
(path, name, segment_count)
|
||||
for path in FOOTAGE_PATHS
|
||||
for name, segment_count in utilities.get_routes_with_segment_counts(path)
|
||||
]
|
||||
total = len(routes)
|
||||
connect_dongle_id = params.get("StockDongleId", encoding="utf-8") or params.get("DongleId", encoding="utf-8") or ""
|
||||
yield f"data: {json.dumps({'progress': 0, 'total': total, 'connectDongleId': connect_dongle_id})}\n\n"
|
||||
|
||||
with ThreadPoolExecutor(max_workers=10) as executor:
|
||||
futures = {executor.submit(utilities.process_route, path, name): (path, name) for path, name in routes}
|
||||
futures = {
|
||||
executor.submit(utilities.process_route, path, name, segment_count): (path, name)
|
||||
for path, name, segment_count in routes
|
||||
}
|
||||
for processed, future in enumerate(as_completed(futures), start=1):
|
||||
try:
|
||||
result = future.result()
|
||||
|
||||
@@ -2895,6 +2895,13 @@ def get_routes_names(footage_path):
|
||||
route_times = {segment.route_name.time_str for segment in segments}
|
||||
return sorted(route_times, reverse=True)
|
||||
|
||||
def get_routes_with_segment_counts(footage_path):
|
||||
route_counts = {}
|
||||
for segment in get_all_segment_names(footage_path):
|
||||
route_name = segment.route_name.time_str
|
||||
route_counts[route_name] = route_counts.get(route_name, 0) + 1
|
||||
return sorted(route_counts.items(), reverse=True)
|
||||
|
||||
def get_segments_in_route(route_time_str, footage_path):
|
||||
return [
|
||||
f"{segment.time_str}--{segment.segment_num}"
|
||||
@@ -2930,7 +2937,7 @@ def normalize_theme_name(name, for_path=False):
|
||||
return f"{normalized_parts[0]} ({' '.join(normalized_parts[1:])})".replace(" Week", "")
|
||||
return ' '.join(normalized_parts).replace(" Week", "")
|
||||
|
||||
def process_route(footage_path, route_name):
|
||||
def process_route(footage_path, route_name, segment_count=0):
|
||||
segment_path = f"{footage_path}{route_name}--0"
|
||||
qcamera_path = f"{segment_path}/qcamera.ts"
|
||||
|
||||
@@ -2954,7 +2961,9 @@ def process_route(footage_path, route_name):
|
||||
"name": route_name,
|
||||
"png": f"/thumbnails/{route_name}--0/preview.png",
|
||||
"timestamp": route_timestamp_str,
|
||||
"is_preserved": has_preserve_attr(segment_path)
|
||||
"is_preserved": has_preserve_attr(segment_path),
|
||||
"segmentCount": max(0, int(segment_count)),
|
||||
"approxDurationSeconds": max(0, int(segment_count)) * 60,
|
||||
}
|
||||
|
||||
def process_screen_recording(mp4):
|
||||
|
||||
Reference in New Issue
Block a user