bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
162 lines (143 loc) • 4.64 kB
JavaScript
/**
* @module utils/helpers
* @description Common utility functions for the bowling analysis system
*/
const fs = require('fs');
const path = require('path');
/**
* Ensures a directory exists, creates it if it doesn't
* @param {string} dirPath - Directory path to ensure
* @returns {boolean} Whether the directory exists or was created
*/
function ensureDirectoryExists(dirPath) {
if (!fs.existsSync(dirPath)) {
try {
fs.mkdirSync(dirPath, { recursive: true });
return true;
} catch (error) {
console.error(`Error creating directory ${dirPath}: ${error.message}`);
return false;
}
}
return true;
}
/**
* Loads JSON data from a file
* @param {string} filePath - Path to the JSON file
* @param {boolean} [silent=false] - Whether to suppress error messages
* @returns {Object|null} Parsed JSON data or null if error
*/
function loadJsonFromFile(filePath, silent = false) {
try {
const resolvedPath = path.resolve(filePath);
if (!fs.existsSync(resolvedPath)) {
if (!silent) {
console.warn(`File not found: ${resolvedPath}`);
}
return null;
}
const data = fs.readFileSync(resolvedPath, 'utf8');
return JSON.parse(data);
} catch (error) {
if (!silent) {
console.error(`Error loading JSON from ${filePath}: ${error.message}`);
}
return null;
}
}
/**
* Saves data as JSON to a file
* @param {string} filePath - Path to save the file
* @param {Object} data - Data to save
* @param {boolean} [createDir=true] - Whether to create directory if it doesn't exist
* @returns {boolean} Whether the save was successful
*/
function saveJsonToFile(filePath, data, createDir = true) {
try {
const resolvedPath = path.resolve(filePath);
const dirPath = path.dirname(resolvedPath);
if (createDir) {
ensureDirectoryExists(dirPath);
}
fs.writeFileSync(resolvedPath, JSON.stringify(data, null, 2));
return true;
} catch (error) {
console.error(`Error saving JSON to ${filePath}: ${error.message}`);
return false;
}
}
/**
* Calculates the mean of an array of numbers
* @param {Array<number>} values - Array of numerical values
* @returns {number} Mean value
*/
function calculateMean(values) {
if (!values || values.length === 0) return 0;
return values.reduce((sum, val) => sum + val, 0) / values.length;
}
/**
* Calculates standard deviation of an array of numbers
* @param {Array<number>} values - Array of numerical values
* @returns {number} Standard deviation
*/
function calculateStandardDeviation(values) {
if (!values || values.length <= 1) return 0;
const mean = calculateMean(values);
const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;
return Math.sqrt(variance);
}
/**
* Smooths an array using a moving average
* @param {Array<number>} values - Array of values to smooth
* @param {number} windowSize - Size of the smoothing window
* @returns {Array<number>} Smoothed values
*/
function smoothArray(values, windowSize = 3) {
if (!values || values.length === 0) return [];
if (windowSize <= 1) return [...values];
const halfWindow = Math.floor(windowSize / 2);
const result = [];
for (let i = 0; i < values.length; i++) {
let sum = 0;
let count = 0;
for (let j = Math.max(0, i - halfWindow); j <= Math.min(values.length - 1, i + halfWindow); j++) {
if (values[j] !== null && values[j] !== undefined) {
sum += values[j];
count++;
}
}
result[i] = count > 0 ? sum / count : values[i];
}
return result;
}
/**
* Gets filename without extension
* @param {string} filePath - File path
* @returns {string} Filename without extension
*/
function getFilenameWithoutExtension(filePath) {
const basename = path.basename(filePath);
const lastDotIndex = basename.lastIndexOf('.');
return lastDotIndex === -1 ? basename : basename.slice(0, lastDotIndex);
}
/**
* Generate a UUID v4
* @returns {string} A UUID v4 string
*/
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
module.exports = {
ensureDirectoryExists,
loadJsonFromFile,
saveJsonToFile,
calculateMean,
calculateStandardDeviation,
smoothArray,
getFilenameWithoutExtension,
generateUUID
};