Динамический расчет цены по диапазонам расстояний - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть случай, чтобы рассчитать стоимость такси, поэтому я объясню предложение

  • От 0 км до 10 км цена составляет 2$ за км.
  • От 10 км до 50 км цена составляет 1.5$ за км.
  • От 50 км до 100 км цена составляет 1.25$ за км.
  • Более 100 км 1$ на км.

Так что мне нужно рассчитать Общая стоимость .

У меня есть этот код, но мне нужна более гибкая реализация.

decimal price = 0;
//convert Distance from meters to Km
decimal DistanceKM = 35;

//==========================
//  ID   RangeKM   Pricing  
//   1      0         2$   
//   2     10         1.5$  
//   3     50         1.25$
//   4    100         1$
//==========================

List<Price> Prices = Prices
  .Where(x => x.RangeKM < DistanceKM)
  .OrderBy(x => x.RangeKM)
  .ToList();

for (int i = 0; i < Prices.Count; i++)
{
    decimal ss = Prices[i].Pricing * ((i + 1 < Prices.Count)
      ? Math.Min(DistanceKM, Prices[i + 1].RangeKM - Prices[i].RangeKM) 
      : DistanceKM);

    price += ss;

    DistanceKM -= (i + 1 < Prices.Count)
      ? Math.Min(DistanceKM, Prices[i + 1].RangeKM - Prices[i].RangeKM) 
      : DistanceKM;
} 

Примеры:

if DistanceKM   8km then the price =  (8*2$) = 16$  
if DistanceKM  35km then the price = ((10*2$) + (25*1.5$)) = 57.5$  
if DistanceKM  55km then the price = ((10*2$) + (40*1.5$) + (5*1.25$)) = 86.25$ 
if DistanceKM 120km then the price = ((10*2$) + (40*1.5$) + (50*1.25) + (20*1$)) = 162.5$  

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Если вы добавите другой конец диапазона к цене:

    //================================
    //= ID   StartKM  EndKM  Pricing  
    //=  1      0      10        2$   
    //=  2     10      50      1.5$  
    //=  3     50     100     1.25$
    //=  4    100     MAX        1$
    //===============================

, тогда вы можете рассчитать общую цену следующим образом:

        price = prices.Where(x => d > x.StartKM)
                .Sum(x => (Math.Min(d, x.EndKM) - x.StartKM) * x.Pricing);


  8 km costs   16,0 $
 35 km costs   57,5 $
 60 km costs  92,50 $
120 km costs 162,50 $

Total: 328,50 $
0 голосов
/ 17 сентября 2018

Давайте извлекать Price метод:

// Prices: Key - distance (in km); Value - price
private static Dictionary<decimal, decimal> defaultPrices = 
  new Dictionary<decimal, decimal>() {
    { 100m, 1.00m},
    {  50m, 1.25m},
    {  10m, 1.50m},
    {   0m, 2.00m},
};

private static decimal Price(decimal distance, 
  IDictionary<decimal, decimal> policy = null) {

  // if no price policy provided, use default one
  if (null == policy)
    policy = defaultPrices;

  decimal result = 0.00m;

  while (distance > policy.Keys.Min()) {
    var pair = policy
      .Where(item => distance > item.Key)
      .OrderByDescending(item => item.Key)
      .First();

    result += (distance - pair.Key) * pair.Value;
    distance = pair.Key;
  }

  return result;
}

Тогда мы можем легко использовать его, например, давайте вычислим tolal сумму:

  List<decimal> distances = ...

  // Alas, we can't Sum() decimals, let's Aggregate them
  decimal total = distances.Aggregate(0.00m, (s, d) => s + Price(d));  

Демо:

  decimal[] tests = new decimal[] {
    8, 35, 60, 120
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(d => $"{d,3} km costs {Price(d),6} $"));

  Console.WriteLine(report);

  string reportTotal = $"Total: {tests.Aggregate(0.00m, (s, d) => s + Price(d))} $";

  Console.WriteLine();
  Console.WriteLine(reportTotal);

Результат:

  8 km costs  16.00 $
 35 km costs  57.50 $
 60 km costs  92.50 $
120 km costs 162.50 $

Total: 328.50 $

Обратите внимание, что 60 км стоит 10 * 1.25$ + 40 * 1.50$ + 10 * 2.00$ == 92.50$, а не 86.25$как в вопросе.

...