UNPKG

bowling-analysis-system

Version:

A comprehensive system for analyzing bowling techniques using video processing and metrics calculation

148 lines (128 loc) 4.24 kB
/** * @module utils/confidence * @description Shared utilities for confidence calculations and thresholds */ const systemConfig = require('../config/system-config'); /** * Calculate confidence score based on value range and threshold * * @param {number} value - The value to assess * @param {number} minThreshold - Minimum acceptable threshold * @param {number} optimalThreshold - Optimal/ideal threshold * @param {boolean} [higherIsBetter=true] - Whether higher values are better * @returns {number} Confidence score between 0-1 */ function calculateConfidence(value, minThreshold, optimalThreshold, higherIsBetter = true) { // Handle invalid inputs if (value === null || value === undefined || isNaN(value)) { return 0; } if (higherIsBetter) { // Handle case where higher values are better if (value <= minThreshold) { return 0; } else if (value >= optimalThreshold) { return 1; } else { // Linear interpolation between thresholds return (value - minThreshold) / (optimalThreshold - minThreshold); } } else { // Handle case where lower values are better if (value >= minThreshold) { return 0; } else if (value <= optimalThreshold) { return 1; } else { // Linear interpolation between thresholds return (minThreshold - value) / (minThreshold - optimalThreshold); } } } /** * Calculate weighted confidence from multiple scores * * @param {Array<{score: number, weight: number}>} scores - Array of scores with weights * @returns {number} Weighted confidence score */ function calculateWeightedConfidence(scores) { if (!Array.isArray(scores) || scores.length === 0) { return 0; } let totalWeight = 0; let weightedSum = 0; for (const { score, weight } of scores) { if (score === null || score === undefined || isNaN(score) || weight === null || weight === undefined || isNaN(weight)) { continue; } // Keep raw scores, only ensure weight is positive const rawScore = score; const positiveWeight = Math.max(0, weight); weightedSum += rawScore * positiveWeight; totalWeight += positiveWeight; } if (totalWeight === 0) { return 0; } return weightedSum / totalWeight; } /** * Apply sigmoid function to transform confidence scores * with adjustable sensitivity * * @param {number} confidence - Raw confidence score * @param {number} [sensitivity=1] - Sensitivity factor (steepness of curve) * @returns {number} Transformed confidence score (0-1) */ function applySigmoidTransform(confidence, sensitivity = 1) { if (confidence === null || confidence === undefined || isNaN(confidence)) { return 0; } // Use input directly without normalization // Apply sigmoid transform centered at 0 const x = confidence * sensitivity; const sigmoid = 1 / (1 + Math.exp(-x)); return sigmoid; } /** * Check if confidence meets minimum threshold * * @param {number} confidence - Confidence score to check * @param {string} [thresholdType='EVENT_CONFIDENCE'] - Threshold type from system config * @returns {boolean} Whether confidence meets threshold */ function meetsConfidenceThreshold(confidence, thresholdType = 'EVENT_CONFIDENCE') { if (confidence === null || confidence === undefined || isNaN(confidence)) { return false; } const threshold = systemConfig.THRESHOLDS[thresholdType] || systemConfig.THRESHOLDS.EVENT_CONFIDENCE; return confidence >= threshold; } /** * Score confidence level into categories * * @param {number} confidence - Confidence score * @returns {string} Confidence category (low, medium, high) */ function categorizeConfidence(confidence) { if (confidence === null || confidence === undefined || isNaN(confidence)) { return 'low'; } // Use raw confidence value for thresholds if (confidence < systemConfig.THRESHOLDS.CONFIDENCE_LOW) { return 'low'; } else if (confidence < systemConfig.THRESHOLDS.CONFIDENCE_MEDIUM) { return 'medium'; } else { return 'high'; } } module.exports = { calculateConfidence, calculateWeightedConfidence, applySigmoidTransform, meetsConfidenceThreshold, categorizeConfidence };