ski-din-calculator
Version:
Calculate a skier's DIN binding release value based on height, weight, age, skill level, and boot sole length
152 lines (151 loc) • 6.64 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateDIN = calculateDIN;
exports.lookupDIN = lookupDIN;
const din_lookup_1 = require("./din-lookup");
const errors_1 = require("./errors");
/**
* Calculates the DIN binding release value for a skier based on their physical characteristics and skiing style.
*
* @param skierHeightCm - Skier's height in centimeters (1-250)
* @param skierWeightKg - Skier's weight in kilograms (1-150)
* @param skierAge - Skier's age in years (3-100)
* @param skierType - Skiing style: 1 (Cautious), 2 (Moderate), 3 (Aggressive)
* @param bootSoleLengthMm - Boot sole length in millimeters (200-360)
* @returns DIN calculation result or null if no matching entry found
* @throws {InvalidHeightError} When height is outside valid range
* @throws {InvalidWeightError} When weight is outside valid range
* @throws {InvalidAgeError} When age is outside valid range
* @throws {InvalidSkierTypeError} When skier type is not 1, 2, or 3
* @throws {InvalidBootSoleLengthError} When boot sole length is outside valid range
*/
function calculateDIN(skierHeightCm, skierWeightKg, skierAge, skierType, bootSoleLengthMm) {
// Input validation
if (skierHeightCm <= 0 || skierHeightCm > 250) {
throw new errors_1.InvalidHeightError(skierHeightCm);
}
if (skierWeightKg <= 0 || skierWeightKg > 150) {
throw new errors_1.InvalidWeightError(skierWeightKg);
}
if (skierAge < 3 || skierAge > 100) {
throw new errors_1.InvalidAgeError(skierAge);
}
if (skierType < 1 || skierType > 3) {
throw new errors_1.InvalidSkierTypeError(skierType);
}
if (bootSoleLengthMm < 200 || bootSoleLengthMm > 360) {
throw new errors_1.InvalidBootSoleLengthError(bootSoleLengthMm);
}
// 1. Determine skier code based on height and weight
const weightCode = getWeightCode(skierWeightKg);
const heightCode = getHeightCode(skierHeightCm, skierWeightKg);
// Weight code determined: weightCode = ${weightCode} for ${skierWeightKg}kg
// Take the lower of the weightCode and heightCode for DIN chart lookup (closest to the top of the chart)
let skierCode = Math.min(weightCode, heightCode);
// Ensure the skier code is at least 1
skierCode = adjustSkierCodeForAgeAndSkill(skierAge, skierType, skierCode);
// Ensure the adjusted skier code does not go below 1
skierCode = Math.max(1, skierCode);
// 4. Get DIN value using the lookup table
return lookupDIN(skierCode, bootSoleLengthMm);
}
// Adjusts skier code based on age and skill level
function adjustSkierCodeForAgeAndSkill(skierAge, skierType, skierCode) {
let adjustedSkierCode = skierCode;
// Adjust for skill level (beginner reduces the code, aggressive increases it)
if (skierType === 2) {
adjustedSkierCode += 1; // Beginner
}
else if (skierType === 3) {
adjustedSkierCode += 2; // Advanced/Expert (more aggressive)
}
// Adjust for age
if (skierAge < 10 || skierAge > 50) {
adjustedSkierCode -= 1;
}
// Return the adjusted skier code, ensuring it does not drop below 1
return Math.max(1, adjustedSkierCode);
}
// Helper function to get weight code based on skier weight
function getWeightCode(weightKg) {
if (weightKg < 13)
return 1; // Skier Code A
if (weightKg <= 17)
return 2; // Skier Code B
if (weightKg <= 21)
return 3; // Skier Code C
if (weightKg <= 25)
return 4; // Skier Code D
if (weightKg <= 30)
return 5; // Skier Code E
if (weightKg <= 35)
return 6; // Skier Code F
if (weightKg <= 41)
return 7; // Skier Code G
if (weightKg <= 48)
return 8; // Skier Code H
if (weightKg <= 57)
return 9; // Skier Code I
if (weightKg <= 66)
return 10; // Skier Code J
if (weightKg <= 78)
return 11; // Skier Code K
if (weightKg <= 94)
return 12; // Skier Code L and above
return 13;
}
// Helper function to get height code based on skier height (only applicable for skier codes H to M)
// Helper function to get height code based on skier height (only applicable for skier codes H to M)
function getHeightCode(heightCm, weightKg) {
// Only apply height logic if weight exceeds 41 kg
if (weightKg > 41) {
if (heightCm <= 148)
return 8; // Skier Code H (for ≤ 4'10")
if (heightCm <= 157)
return 9; // Skier Code I
if (heightCm <= 166)
return 10; // Skier Code J
if (heightCm <= 178)
return 11; // Skier Code K
if (heightCm <= 194)
return 12; // Skier Code L
if (heightCm >= 195)
return 13; // Skier Code M
}
return 50; // If weight is less than 41 kg, height is not considered, so return an invalid height code
}
/**
* Looks up DIN value based on skier code and boot sole length.
*
* @param skierCode - Numeric skier code (1-16)
* @param bootSoleLengthMm - Boot sole length in millimeters
* @returns DIN result or null if no matching entry found
*/
function lookupDIN(skierCode, bootSoleLengthMm) {
// Convert skierCode from number to its corresponding letter
const skierCodeLetter = convertToLetterSkierCode(skierCode);
// Find matching entry in the lookup table
const matchingEntry = din_lookup_1.dinLookupTable.find(entry => entry.skierCode === skierCodeLetter &&
bootSoleLengthMm >= entry.bootSoleRange[0] &&
bootSoleLengthMm <= entry.bootSoleRange[1]);
// If no matching entry is found, return null or throw an error as needed
if (!matchingEntry) {
return null;
}
// Return the DIN value and additional information directly from the lookup table
return {
skierCode: matchingEntry.skierCode,
dinValue: matchingEntry.dinValue,
twistRange: matchingEntry.twistRange,
forwardLeanRange: matchingEntry.forwardLeanRange,
torqueRange: matchingEntry.twistRange, // Using twistRange as torqueRange for now
originalSkierCode: skierCode,
safetyWarning: matchingEntry.dinValue > 10 ? "Consult an expert for aggressive skiing conditions" : "",
suggestedRecheckInterval: "Recheck annually or after weight change of 10%"
};
}
// Convert numeric skier code to a letter-based skier code
function convertToLetterSkierCode(skierCode) {
const skierCodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'];
return skierCodes[Math.max(0, skierCode - 1)]; // Ensures we stay within bounds of the skierCodes array
}