Spaces:
Sleeping
Sleeping
File size: 5,471 Bytes
7856e60 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogisticsConfig {
pub weight_coefficient: f64,
pub distance_coefficient: f64,
pub complexity_bias: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
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,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
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
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
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);
}
#[test]
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);
}
}
|