Solución
solution.tsTypeScript
type ZONE = 'local' | 'regional' | 'nacional'
interface PriceAndRechargeByZoneResult {
recharge: number
basePrice: number
totalPrice: number
}
type PriceAndRechargeByZone = Omit<PriceAndRechargeByZoneResult, 'totalPrice'>
const ERROR_RESULT: number = -1
const MIN_VALID_WEIGHT: number = 1
const MIN_VALID_DISTANCE: number = 1
const LOCAL_RECHARGE_RATE = 0.10
const REGIONAL_RECHARGE_RATE = 0.05
const NATIONAL_RECHARGE_RATE = 0.02
const LOCAL_BASE_PRICE_RATE = 2
const REGIONAL_BASE_PRICE_RATE = 5
const NATIONAL_BASE_PRICE_RATE = 10
const MIN_WEIGHT_FOR_DISCOUNT = 20
const DISCOUNT_BY_WEIGHT_RATE = 0.90
const PRICE_AND_RECHARGE_BY_ZONE: Record<ZONE, (weight: number, distance: number) => PriceAndRechargeByZone> = {
local: (weight: number, distance: number) => ({ recharge: distance * LOCAL_RECHARGE_RATE, basePrice: weight * LOCAL_BASE_PRICE_RATE }),
regional: (weight: number, distance: number) => ({ recharge: distance * REGIONAL_RECHARGE_RATE, basePrice: weight * REGIONAL_BASE_PRICE_RATE }),
nacional: (weight: number, distance: number) => ({ recharge: distance * NATIONAL_RECHARGE_RATE, basePrice: weight * NATIONAL_BASE_PRICE_RATE}),
}
export function calculateShippingCost(weigth: number, distance: number, zone: ZONE): number {
if (!isValidWeigth(weigth)) return ERROR_RESULT
if (!isValidDistance(distance)) return ERROR_RESULT
const { totalPrice } = calculateBasePriceAndRechargeByZone(zone, weigth, distance)
const total = applyDiscountByWeight(totalPrice, weigth)
return rountToDecimals(total)
}
function calculateBasePriceAndRechargeByZone(zone: ZONE, weigth: number, distance: number): PriceAndRechargeByZoneResult {
const { basePrice, recharge } = PRICE_AND_RECHARGE_BY_ZONE[zone](weigth, distance)
return {
basePrice,
recharge,
totalPrice: basePrice + recharge
}
}
function applyDiscountByWeight(total: number, weight: number): number {
return weight > MIN_WEIGHT_FOR_DISCOUNT
? total * DISCOUNT_BY_WEIGHT_RATE
: total
}
function rountToDecimals(value: number): number {
return Math.round(value * 100) / 100;
}
function isValidWeigth(weight: number): boolean {
return weight >= MIN_VALID_WEIGHT
}
function isValidDistance(distance: number): boolean {
return distance >= MIN_VALID_DISTANCE
}0respuestas