You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.7 KiB
165 lines
5.7 KiB
export function findRadarFrameIndexForTime(targetTimeMs, vizData) {
|
|
if (!vizData || vizData.radarFrames.length === 0) return -1;
|
|
// Initialize low, high, and answer variables for binary search
|
|
// 'ans' will store the index of the closest frame found so far
|
|
// 'low' and 'high' define the search range
|
|
let low = 0,
|
|
high = vizData.radarFrames.length - 1,
|
|
ans = 0;
|
|
// Perform binary search to find the radar frame whose timestamp is closest to, but not exceeding, the target time
|
|
while (low <= high) {
|
|
let mid = Math.floor((low + high) / 2);
|
|
// If the current frame's timestamp is less than or equal to the target time,
|
|
// it's a potential answer, and we try to find a more recent one in the right half.
|
|
if (vizData.radarFrames[mid].timestampMs <= targetTimeMs) {
|
|
ans = mid;
|
|
low = mid + 1;
|
|
} else {
|
|
// If the current frame's timestamp is greater than the target time,
|
|
// we need to look in the left half.
|
|
high = mid - 1;
|
|
}
|
|
}
|
|
// Return the index of the found radar frame.
|
|
return ans;
|
|
}
|
|
|
|
|
|
|
|
export function extractTimestampInfo(filename) {
|
|
// Return null if filename is not provided
|
|
if (!filename) return null;
|
|
|
|
// Try to match the old JSON filename pattern: "Tracks_YYYYMMDD_HHMMSS.ms"
|
|
let match = filename.match(/Tracks_(\d{8}_\d{6}\.\d{3})/);
|
|
if (match) return { timestampStr: match[1], format: "json" };
|
|
|
|
// NEW: Add this block to match the new filename pattern
|
|
match = filename.match(/fHist_(\d{8}_\d{6}\.\d{3})/);
|
|
if (match) return { timestampStr: match[1], format: "json" };
|
|
|
|
// Try to match video filename pattern (e.g., from GoPro): "WIN_YYYYMMDD_HH_MM_SS"
|
|
match = filename.match(/WIN_(\d{8})_(\d{2})_(\d{2})_(\d{2})/);
|
|
if (match) {
|
|
const timestamp = `${match[1]}_${match[2]}${match[3]}${match[4]}`;
|
|
return { timestampStr: timestamp, format: "video" };
|
|
}
|
|
// Try to match another common video filename pattern: "video_YYYYMMDD_HHMMSS"
|
|
match = filename.match(/video_(\d{8}_\d{6})/);
|
|
if (match)
|
|
return {
|
|
timestampStr: match[1],
|
|
format: "video",
|
|
};
|
|
// If no pattern matches, return null
|
|
return null;
|
|
}
|
|
|
|
export function parseTimestamp(timestampStr, format) {
|
|
// Return null if timestamp string or format is not provided.
|
|
if (!timestampStr || !format) return null;
|
|
let day,
|
|
month,
|
|
year,
|
|
hour,
|
|
minute,
|
|
second,
|
|
millisecond = 0;
|
|
// Parse video timestamp format: YYYYMMDD_HH_MM_SS
|
|
// Example: 20231027_10_30_00
|
|
if (format === "video") {
|
|
[year, month, day] = [
|
|
timestampStr.substring(0, 4),
|
|
timestampStr.substring(4, 6),
|
|
timestampStr.substring(6, 8),
|
|
];
|
|
[hour, minute, second] = [
|
|
timestampStr.substring(9, 11),
|
|
timestampStr.substring(11, 13),
|
|
timestampStr.substring(13, 15),
|
|
];
|
|
}
|
|
else if (format === "json") {
|
|
// Parse JSON timestamp format: DDMMYYYY_HHMMSS.ms
|
|
[day, month, year] = [
|
|
timestampStr.substring(0, 2),
|
|
timestampStr.substring(2, 4),
|
|
timestampStr.substring(4, 8),
|
|
];
|
|
[hour, minute, second, millisecond] = [
|
|
timestampStr.substring(9, 11),
|
|
timestampStr.substring(11, 13),
|
|
timestampStr.substring(13, 15),
|
|
parseInt(timestampStr.substring(16, 19)),
|
|
];
|
|
} else {
|
|
// Return null for unsupported formats
|
|
return null;
|
|
} // Create a Date object using UTC to avoid timezone issues
|
|
const date = new Date(
|
|
Date.UTC(year, month - 1, day, hour, minute, second, millisecond)
|
|
);
|
|
|
|
// Check if the created Date object is valid.
|
|
// If getTime() returns NaN, the date is invalid.
|
|
return isNaN(date.getTime()) ? null : date;
|
|
}
|
|
|
|
/**
|
|
* Creates a throttled function that only invokes the provided function
|
|
* at most once per every `delay` milliseconds.
|
|
* @param {Function} func The function to throttle.
|
|
* @param {number} delay The number of milliseconds to throttle invocations to.
|
|
* @returns {Function} Returns the new throttled function.
|
|
*/
|
|
export function throttle(func, delay) {
|
|
// `lastCall` keeps track of the timestamp of the last successful invocation.
|
|
let lastCall = 0;
|
|
// Return a new function that, when called, will throttle the execution of the original function
|
|
return function (...args) {
|
|
// Get the current timestamp.
|
|
const now = new Date().getTime();
|
|
|
|
// If the time since the last call is less than the delay, do not execute the function
|
|
if (now - lastCall < delay) {
|
|
return;
|
|
}
|
|
// Otherwise, update the last call time and execute the original function
|
|
lastCall = now;
|
|
return func(...args); // Apply the original function with its arguments.
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Formats milliseconds into a MM:SS.ms string.
|
|
* @param {number} milliseconds The time in milliseconds.
|
|
* @returns {string} The formatted time string.
|
|
*/
|
|
export function formatTime(milliseconds) {
|
|
if (isNaN(milliseconds) || milliseconds < 0) {
|
|
return "00:00.000";
|
|
}
|
|
const totalSeconds = milliseconds / 1000;
|
|
const minutes = Math.floor(totalSeconds / 60);
|
|
const seconds = Math.floor(totalSeconds % 60);
|
|
const ms = Math.round(milliseconds % 1000);
|
|
|
|
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}.${String(ms).padStart(3, '0')}`;
|
|
}
|
|
|
|
/**
|
|
* Formats a Date object into a HH:MM:SS.ms UTC string.
|
|
* @param {Date} date The date object to format.
|
|
* @returns {string} The formatted time string.
|
|
*/
|
|
export function formatUTCTime(date) {
|
|
if (!date || isNaN(date.getTime())) {
|
|
return "00:00:00.000";
|
|
}
|
|
const hours = String(date.getUTCHours()).padStart(2, '0');
|
|
const minutes = String(date.getUTCMinutes()).padStart(2, '0');
|
|
const seconds = String(date.getUTCSeconds()).padStart(2, '0');
|
|
const milliseconds = String(date.getUTCMilliseconds()).padStart(3, '0');
|
|
return `${hours}:${minutes}:${seconds}.${milliseconds}`;
|
|
}
|
|
|