Spaces:
Running
Running
| use serde::{Deserialize, Serialize}; | |
| pub struct LogisticsConfig { | |
| pub weight_coefficient: f64, | |
| pub distance_coefficient: f64, | |
| pub complexity_bias: f64, | |
| } | |
| pub enum LogisticsZone { | |
| Local, // Within city (< 50km) | |
| Regional, // Within state (50 - 300km) | |
| National, // Outside state (> 300km) | |
| } | |
| impl Default for LogisticsConfig { | |
| fn default() -> Self { | |
| Self { | |
| weight_coefficient: 0.15, // Adjusted for Indian gram-based pricing | |
| distance_coefficient: 1.0, | |
| complexity_bias: 1.0, | |
| } | |
| } | |
| } | |
| pub struct PricingFeatures { | |
| pub distance_km: f64, | |
| pub user_rate_per_km: f64, | |
| pub product_weight: f64, | |
| pub base_charge: f64, | |
| pub config: LogisticsConfig, | |
| } | |
| // ======================================================== | |
| // ADVANCED OOPS CONCEPTS: POLYMORPHIC ZONAL PRICING | |
| // ======================================================== | |
| /// Strategy trait for calculating regional zone pricing coefficients. | |
| pub trait ZonalPricingStrategy: Send + Sync { | |
| fn multiplier(&self) -> f64; | |
| } | |
| pub struct LocalZoneStrategy; | |
| impl ZonalPricingStrategy for LocalZoneStrategy { | |
| fn multiplier(&self) -> f64 { | |
| 1.0 | |
| } | |
| } | |
| pub struct RegionalZoneStrategy; | |
| impl ZonalPricingStrategy for RegionalZoneStrategy { | |
| fn multiplier(&self) -> f64 { | |
| 1.5 | |
| } | |
| } | |
| pub struct NationalZoneStrategy; | |
| impl ZonalPricingStrategy for NationalZoneStrategy { | |
| fn multiplier(&self) -> f64 { | |
| 2.5 | |
| } | |
| } | |
| /// Factory pattern to retrieve the correct zonal pricing strategy object dynamically. | |
| pub struct ZonalPricingStrategyFactory; | |
| impl ZonalPricingStrategyFactory { | |
| pub fn get_strategy(distance_km: f64) -> Box<dyn ZonalPricingStrategy> { | |
| if distance_km < 50.0 { | |
| Box::new(LocalZoneStrategy) | |
| } else if distance_km < 300.0 { | |
| Box::new(RegionalZoneStrategy) | |
| } else { | |
| Box::new(NationalZoneStrategy) | |
| } | |
| } | |
| } | |
| // ======================================================== | |
| // PRICING ENGINE CLASS IMPLEMENTATION | |
| // ======================================================== | |
| /// The `PricingEngine` handles the platform's economic logic, including dynamic delivery fees | |
| /// and trust-adjusted platform service charges. Refactored using dynamic strategy patterns. | |
| pub struct PricingEngine; | |
| impl PricingEngine { | |
| /// Estimates the delivery fee using a multi-factor linear estimation model. | |
| /// | |
| /// The model accounts for: | |
| /// 1. **Zonal Logic**: Higher multipliers for cross-state shipments (polymorphically resolved). | |
| /// 2. **Volumetric Weight**: Uses a gram-to-kg conversion with configurable coefficients. | |
| /// 3. **Distance Variable**: Direct linear scaling with the merchant's custom rate-per-km. | |
| pub fn estimate_delivery_fee(features: PricingFeatures) -> f64 { | |
| let strategy = ZonalPricingStrategyFactory::get_strategy(features.distance_km); | |
| let zone_multiplier = strategy.multiplier(); | |
| // Convert weight from grams to kg for institutional pricing parity | |
| let weight_kg = features.product_weight / 1000.0; | |
| let weight_component = weight_kg * features.config.weight_coefficient * 50.0; // ₹50 per kg baseline | |
| let base_with_zone = features.base_charge * zone_multiplier; | |
| let distance_component = features.distance_km | |
| * (features.user_rate_per_km * features.config.distance_coefficient); | |
| let raw_total = (base_with_zone + distance_component + weight_component) | |
| * features.config.complexity_bias; | |
| // Perform final rounding to match currency precision | |
| (raw_total * 100.0).round() / 100.0 | |
| } | |
| /// Calculates the platform's service fee for a transaction. | |
| /// | |
| /// This is a **Secure Incentive** model: | |
| /// - Base fees are tiered by transaction value. | |
| /// - **Trust Discount**: High trust scores (0-100) provide a linear discount of up to 50%. | |
| pub fn calculate_platform_fee(_price: f64, _trust_score: f64) -> f64 { | |
| 0.0 | |
| } | |
| /// Aggregates all price components into a final total consumer charge. | |
| pub fn calculate_total_consumer_price( | |
| product_price: f64, | |
| delivery_fee: f64, | |
| tax_amount: f64, | |
| _trust_score: f64, | |
| ) -> f64 { | |
| ((product_price + delivery_fee + tax_amount) * 100.0).round() / 100.0 | |
| } | |
| } | |
| mod tests { | |
| use super::*; | |
| fn test_zero_distance_pricing() { | |
| let features = PricingFeatures { | |
| distance_km: 0.0, | |
| user_rate_per_km: 15.0, | |
| product_weight: 500.0, | |
| base_charge: 20.0, | |
| config: LogisticsConfig::default(), | |
| }; | |
| let fee = PricingEngine::estimate_delivery_fee(features); | |
| // (0 * 15 + 0.5 * 0.15 * 50 + 20 * 1.0) * 1.0 = 23.75 | |
| assert_eq!(fee, 23.75); | |
| } | |
| fn test_extreme_weight_pricing() { | |
| let features = PricingFeatures { | |
| distance_km: 10.0, | |
| user_rate_per_km: 15.0, | |
| product_weight: 100000.0, // 100kg | |
| base_charge: 20.0, | |
| config: LogisticsConfig::default(), | |
| }; | |
| let fee = PricingEngine::estimate_delivery_fee(features); | |
| // (150 + 100 * 0.15 * 50 + 20) = 150 + 750 + 20 = 920.0 | |
| assert_eq!(fee, 920.0); | |
| } | |
| } | |