// Local recording inventory and closed camera playback. export const LOCAL = /^(?:[a-f0-9]{8}--[a-f0-9]{10}|[0-9]{4}-[0-9]{2}-[0-9]{2}--[0-9]{2}-[0-9]{2}-[0-9]{2}|[a-f0-9]{16}\|(?:[a-f0-9]{8}--[a-f0-9]{10}|[0-9]{4}-[0-9]{2}-[0-9]{2}--[0-9]{2}-[0-9]{2}-[0-9]{2}))$/ export const SEGMENT = /^(?:[a-f0-9]{8}--[a-f0-9]{10}|[0-9]{4}-[0-9]{2}-[0-9]{2}--[0-9]{2}-[0-9]{2}-[0-9]{2}|[a-f0-9]{16}[|_](?:[a-f0-9]{8}--[a-f0-9]{10}|[0-9]{4}-[0-9]{2}-[0-9]{2}--[0-9]{2}-[0-9]{2}-[0-9]{2}))--[0-9]{1,6}$/ const FILES = ["rlog", "qlog", "fcamera", "dcamera", "ecamera", "qcamera"] export const LABELS = { rlog: "Full log", qlog: "Quick log", fcamera: "Road video", dcamera: "Driver video", ecamera: "Wide video", qcamera: "Quick video" } export function validLocalHistory(value, complete = false) { if (value?.schemaVersion !== 1 || value.source !== "local" || (!complete && value.partialHistory !== true) || typeof value.scanIncomplete !== "boolean" || !Array.isArray(value.routes) || value.routes.length > (complete ? 1 : 100)) return false let count = 0 const routes = new Set() return value.routes.every((route) => { if (typeof route?.routeId !== "string" || !LOCAL.test(route.routeId) || routes.has(route.routeId) || !Array.isArray(route.segments) || route.segments.length > 512 || !Number.isSafeInteger(route.segmentCount) || route.segmentCount !== route.segments.length) return false routes.add(route.routeId) const numbers = new Set() count += route.segmentCount return count <= 512 && route.segments.every((segment) => { if (!Number.isSafeInteger(segment?.number) || segment.number < 0 || segment.number > 999999 || typeof segment.segmentName !== "string" || !SEGMENT.test(segment.segmentName) || (!segment.segmentName.startsWith(route.routeId.replace('|', '_') + '--') && !segment.segmentName.startsWith(route.routeId + '--')) || Number(segment.segmentName.slice(segment.segmentName.lastIndexOf('--') + 2)) !== segment.number || numbers.has(segment.number) || segment.files === null || typeof segment.files !== "object" || Object.keys(segment.files).length !== FILES.length || !FILES.every((key) => typeof segment.files[key] === "boolean") || (!complete && !FILES.some((key) => segment.files[key]))) return false numbers.add(segment.number) return true }) }) } export const VIDEOS = ["fcamera", "dcamera", "ecamera", "qcamera"] export const hasVideo = (files) => VIDEOS.some((key) => files?.[key]) export const availableFiles = (files) => FILES.filter((key) => files?.[key]).map((key) => LABELS[key]) export const routeFiles = (route) => availableFiles(Object.fromEntries(FILES.map((key) => [key, route.segments.some((segment) => segment.files[key])]))) export const firstQuickVideo = (route) => route.segments.find((segment) => segment.files.qcamera) || null export function routeDate(route, locale = undefined, timeZone = undefined) { const validTime = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 && Number.isFinite(new Date(value * 1000).getTime()) const captured = validTime(route.startTime) const value = captured ? route.startTime : validTime(route.fileTime) ? route.fileTime : null if (value === null) return { label: "Date unavailable", source: "", datetime: null } const date = new Date(value * 1000) return { label: new Intl.DateTimeFormat(locale, { year: "numeric", month: "short", day: "numeric", hour: "numeric", minute: "2-digit", ...(timeZone ? { timeZone } : {}) }).format(date), source: captured ? "" : "File date", datetime: date.toISOString() } } export function connectRouteUrl(route) { if (typeof route?.routeId !== "string" || !LOCAL.test(route.routeId) || typeof route.connectUrl !== "string") return null const host = route.provider === "konik" ? "stable.konik.ai" : route.provider === undefined || route.provider === "comma" ? "connect.comma.ai" : null if (host === null) return null const match = /^https:\/\/(connect\.comma\.ai|stable\.konik\.ai)\/([a-f0-9]{16})\/([^/?#]+)$/.exec(route.connectUrl) const [device, identifier] = route.routeId.includes('|') ? route.routeId.split('|') : [null, route.routeId] return match && match[1] === host && match[3] === identifier && (device === null || match[2] === device) ? route.connectUrl : null } export const recordingUrl = (segmentName, camera = "qcamera") => SEGMENT.test(segmentName) && ["qcamera", "fcamera", "dcamera", "ecamera"].includes(camera) ? `./api/recordings/media/${encodeURIComponent(segmentName)}${camera === "qcamera" ? "" : "/" + camera}` : null export const quickRoadUrl = (segmentName) => recordingUrl(segmentName) export const segmentSummaryUrl = (segmentName) => SEGMENT.test(segmentName) ? `./api/recordings/segment-summary?segmentName=${encodeURIComponent(segmentName)}` : null export function validSegmentSummary(value, segmentName) { const metric = (v) => v === null || (typeof v === "number" && Number.isFinite(v) && v >= 0) return value?.schemaVersion === 1 && value.source === "closed_local_rlog" && value.segmentName === segmentName && typeof value.sourceSha256 === "string" && /^[a-f0-9]{64}$/.test(value.sourceSha256) && [value.observedCarSpanSeconds, value.estimatedDistanceMeters, value.observedLatActiveSeconds, value.observedLongActiveSeconds].every(metric) && value.gaps && Number.isSafeInteger(value.gaps.carState) && value.gaps.carState >= 0 && Number.isSafeInteger(value.gaps.carControl) && value.gaps.carControl >= 0 && typeof value.sampleCoverageComplete === "boolean" } export const detailMetric = (seconds, unit = "s") => seconds === null ? "Unavailable" : `${seconds.toFixed(unit === "m" ? 1 : 2)} ${unit}` const searchText = value => String(value || "").normalize("NFKD").replace(/\p{M}/gu, "") .toLocaleLowerCase().replace(/(\d+)(?:st|nd|rd|th)\b/g, "$1").replace(/[^\p{L}\p{N}]+/gu, " ").trim() export function routeMatchesSearch(route, query) { const date = routeDate(route) const index = searchText(`${route.displayName || ""} ${route.routeId} ${date.label} ${date.datetime || ""}`) return searchText(query).split(" ").every(word => index.includes(word)) } export const driveVideoUrl = (routeId, camera) => LOCAL.test(routeId) && VIDEOS.includes(camera) ? `./api/recordings/route/${encodeURIComponent(routeId)}/${camera}` : null export const logUrl = (segmentName, filename) => SEGMENT.test(segmentName) && /^(rlog|qlog)\.(zst|bz2)$/.test(filename) ? `./api/recordings/files/${encodeURIComponent(segmentName)}/${filename}` : null export const logArchiveUrl = routeId => LOCAL.test(routeId) ? `./api/recordings/logs/${encodeURIComponent(routeId)}` : null export const cameraLabel = camera => LABELS[camera]?.replace(" video", "") export const formatDuration = minutes => minutes >= 60 ? `${Math.floor(minutes / 60)}h ${minutes % 60}m` : `${minutes} min` export const formatBytes = bytes => bytes >= 1e9 ? `${(bytes / 1e9).toFixed(2)} GB` : `${((bytes || 0) / 1e6).toFixed(1)} MB` export function validRouteDetail(value, routeId) { return value?.schemaVersion === 1 && value.source === "local" && value.route?.routeId === routeId && typeof value.route.inventoryComplete === "boolean" && validLocalHistory({ schemaVersion: 1, source: "local", scanIncomplete: !value.route.inventoryComplete, routes: [value.route] }, true) }