bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
148 lines (128 loc) • 4.24 kB
JavaScript
/**
* @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
};