Solución

@isakidev·12/5/2026TypeScript
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
Respuestas

Aún no hay respuestas

¡Sé el primero en responder!

Escribir un comentario

Recuerda ser amable. Estás comentando la solución de otra persona. Comparte tu perspectiva de forma constructiva y respetuosa.

Debes iniciar sesión para publicar un comentario.