Spaces:
Sleeping
Sleeping
| export interface NormEntry { | |
| id: number; | |
| division_factor: string; | |
| sub_type: string; | |
| composition: string; | |
| count_range: string; | |
| route: string; | |
| rules: { | |
| upto_3000m: string; | |
| above_3000m: string; | |
| }; | |
| tolerance_adjustments: { | |
| tolerance_3_percent: string; | |
| tolerance_5_7_percent: string; | |
| tolerance_10_percent: string; | |
| tolerance_plus0_minus3_5: string; | |
| tolerance_1_2_percent: string; | |
| }; | |
| } | |
| export interface ToleranceOption { | |
| key: keyof NormEntry["tolerance_adjustments"]; | |
| label: string; | |
| } | |
| export const TOLERANCE_OPTIONS: ToleranceOption[] = [ | |
| { key: "tolerance_1_2_percent", label: "+/- 1% or +/- 2%" }, | |
| { key: "tolerance_3_percent", label: "+/- 3%" }, | |
| { key: "tolerance_5_7_percent", label: "+/- 5%, 6% or 7%" }, | |
| { key: "tolerance_10_percent", label: "+/- 10%" }, | |
| { key: "tolerance_plus0_minus3_5", label: "+0/-3% or +0/-5%" }, | |
| ]; | |
| export interface CalculationResult { | |
| applicableRule: string; | |
| ruleDescription: string; | |
| baseReservation: number; | |
| toleranceAdjustment: string; | |
| adjustedPercentage: number; | |
| finalReservation: number; | |
| orderQty: number; | |
| } | |
| interface ParsedRule { | |
| percentage: number; | |
| fixedMeters: number; | |
| } | |
| interface ToleranceAdjustment { | |
| adjustmentPercent: number; | |
| isLess: boolean; | |
| label: string; | |
| } | |
| export function parseRuleString(ruleString: string): ParsedRule { | |
| let percentage = 0; | |
| let fixedMeters = 0; | |
| const pattern = /(\d+(?:\.\d+)?)\s*%\s*or\s*(\d+(?:\.\d+)?)\s*m/i; | |
| const match = ruleString.match(pattern); | |
| if (match) { | |
| percentage = parseFloat(match[1]); | |
| fixedMeters = parseFloat(match[2]); | |
| } | |
| return { percentage, fixedMeters }; | |
| } | |
| export function parseToleranceAdjustment(toleranceString: string): ToleranceAdjustment { | |
| if (toleranceString.toLowerCase().includes("std norms") || toleranceString.toLowerCase().includes("standard")) { | |
| return { adjustmentPercent: 0, isLess: false, label: "As per Std Norms" }; | |
| } | |
| const extraPattern = /(\d+(?:\.\d+)?)\s*%\s*extra/i; | |
| const lessPattern = /-?\s*(\d+(?:\.\d+)?)\s*%\s*less/i; | |
| const extraMatch = toleranceString.match(extraPattern); | |
| if (extraMatch) return { adjustmentPercent: parseFloat(extraMatch[1]), isLess: false, label: `+${extraMatch[1]}% Extra` }; | |
| const lessMatch = toleranceString.match(lessPattern); | |
| if (lessMatch) return { adjustmentPercent: parseFloat(lessMatch[1]), isLess: true, label: `-${lessMatch[1]}% Less` }; | |
| return { adjustmentPercent: 0, isLess: false, label: toleranceString }; | |
| } | |
| export function calculateBaseReservation(orderQty: number, percentage: number, fixedMeters: number): number { | |
| const percentageReservation = orderQty * (percentage / 100); | |
| return Math.max(percentageReservation, fixedMeters); | |
| } | |
| export function calculateFinalReservation(orderQty: number, ruleString: string, toleranceString: string): CalculationResult { | |
| const { percentage, fixedMeters } = parseRuleString(ruleString); | |
| const tolerance = parseToleranceAdjustment(toleranceString); | |
| const baseReservation = calculateBaseReservation(orderQty, percentage, fixedMeters); | |
| let adjustedPercentage = percentage; | |
| if (tolerance.isLess) { | |
| adjustedPercentage = Math.max(0, percentage - tolerance.adjustmentPercent); | |
| } else { | |
| adjustedPercentage = percentage + tolerance.adjustmentPercent; | |
| } | |
| const finalReservation = calculateBaseReservation(orderQty, adjustedPercentage, fixedMeters); | |
| const ruleDescription = orderQty <= 3000 ? `Upto 3000m: ${ruleString}` : `Above 3000m: ${ruleString}`; | |
| return { | |
| applicableRule: ruleString, | |
| ruleDescription, | |
| baseReservation: Math.round(baseReservation * 100) / 100, | |
| toleranceAdjustment: tolerance.label, | |
| adjustedPercentage, | |
| finalReservation: Math.round(finalReservation * 100) / 100, | |
| orderQty | |
| }; | |
| } | |
| // Grouping functions | |
| export function getUniqueDivisionFactors(data: NormEntry[]): string[] { | |
| return [...new Set(data.map(item => item.division_factor))].sort(); | |
| } | |
| export function getSubTypesByDivision(data: NormEntry[], division: string): string[] { | |
| return [...new Set(data.filter(item => item.division_factor === division).map(item => item.sub_type))].sort(); | |
| } | |
| export function getCompositionsByDivisionAndSubType(data: NormEntry[], division: string, subType: string): string[] { | |
| return [...new Set(data.filter(item => item.division_factor === division && item.sub_type === subType).map(item => item.composition))].sort(); | |
| } | |
| export function getCountRangesByComposition(data: NormEntry[], division: string, subType: string, composition: string): string[] { | |
| return [...new Set(data.filter(item => item.division_factor === division && item.sub_type === subType && item.composition === composition).map(item => item.count_range))].sort(); | |
| } | |
| export function findNormEntry(data: NormEntry[], division: string, subType: string, composition: string, countRange: string): NormEntry | undefined { | |
| return data.find(item => item.division_factor === division && item.sub_type === subType && item.composition === composition && item.count_range === countRange); | |
| } |