3

Azure Rate Card API 返回 MeterRates 字段(请参阅文档)。Azure UsageAggregate 提供一个数量(请参阅文档)。

根据天蓝色支持页面。这是提问的论坛。

那么,如何应用计费率?

米率示例:

{"0":20, "100":15, "200":10}

如果我有一个数量 175 是数量100*20 + 75*15还是175*15

为什么要指定包含的数量?

示例:rates:{"0":23}包含数量 10 可以表示为费率:

{"0":0, "10":23}
4

3 回答 3

5

示例计费率:{"0":20, "100":15, "200":10}

如果我有 175 的数量是 100*20 + 75*15 还是 175*15 ?

定价是分层定价。因此,当您获得费率时,它基本上会告诉您:

  • 0 - 99单位,单位率是20
  • 100 - 199单位,单位率是15
  • 200单位及以上,单位率是10

根据这个逻辑,你的计算应该是:

99 * 20 + 75 * 15 = 3105

让我感到困惑的一件事是上限。以上计算基于我从 Azure 计费团队收到的信息。让我感到困惑的是,如果消费是说99.5单位会发生什么?对于第一个99单位来说很好,但我不确定如何0.5计算额外的单位。

于 2016-01-21T02:49:29.730 回答
2

Guarav 是问题的核心,这也是我将其标记为答案的原因。基于此,我设计了以下代码来实现逻辑。它分为两部分:

  1. 从计量费率创建一个桶列表
  2. 使用存储桶列表处理数量以确定数量

以下函数创建一个桶列表(每个桶对象是一个简单的 POCO,具有 Min、Max 和 Rate 属性)。该列表附加到具有来自费率卡 api 的其他属性的仪表对象。

        private Dictionary<int, RateBucket> ParseRateBuckets(string rates)
    {
        dynamic dRates = JsonConvert.DeserializeObject(rates);
        var rateContainer = (JContainer)dRates;

        var buckets = new Dictionary<int, RateBucket>();
        var bucketNumber = 0;
        foreach (var jToken in rateContainer.Children())
        {
            var jProperty = jToken as JProperty;
            if (jProperty != null)
            {
                var bucket = new RateBucket
                {
                    Min = Convert.ToDouble(jProperty.Name),
                    Rate = Convert.ToDouble(jProperty.Value.ToString())
                };

                if (bucketNumber > 0)
                    buckets[bucketNumber - 1].Max = bucket.Min;

                buckets.Add(bucketNumber, bucket);
            }

            bucketNumber++;
        }

        return buckets;
    }

第二个函数使用具有两个有用属性的仪表对象:桶列表和包含的数量。根据价目表文档(正如我所读),您在超过包含的数量之前不会开始计算可计费数量。我确信这里可以进行一些重构,但是桶的有序处理是关键。

我想我已经通过认识到它是双精度而不是整数来解决数量问题。因此,与任何单个桶相关联的数量是桶最大值和桶最小值之间的差异(除非我们只填充了部分桶)。

        private double CalculateUsageCost(RateCardMeter meter, double quantity)
    {
        var amount = 0.0;

        quantity -= meter.IncludedQuantity;

        if (quantity > 0)
        {
            for (var i = 0; i < meter.RateBuckets.Count; i++)
            {
                var bucket = meter.RateBuckets[i];
                if (quantity > bucket.Min)
                {
                    if (bucket.Max.HasValue && quantity > bucket.Max)
                        amount += (bucket.Max.Value - bucket.Min)*bucket.Rate;
                    else
                        amount += (quantity - bucket.Min)*bucket.Rate;
                }
            }
        }
        return amount;
    }

最后,文档并不清楚这些层的时间范围。如果我根据数量获得折扣价,我在什么时间范围内汇总数量?使用 api 允许我每天或每小时提取数据。我想每小时提取一次数据,这样我就可以按一天中的时间关联我的成本。但是什么时候适合实际计算账单呢?似乎每小时是错误的,每天可能有效,但它可能只适合整个月。

于 2016-01-21T12:42:22.340 回答
0

最近我刚刚做了这个类似的任务。以下是我的示例(我认为您可以使用正则表达式来删除这些字符,而不是像我一样使用替换)。第一个函数解析价格信息字符串以生成键值对集合,第二个函数用于计算总价。

private Dictionary<float, double> GetRatesDetail(string r)
{
    Dictionary<float, double> pairs = null;
    if(string.IsNullOrEmpty(r) || r.Length <=2)
    {
        pairs = new Dictionary<float, double>();
        pairs.Add(0, 0);
    }
    else
    {
        pairs = r.Replace("{", "").Replace("}", "").Split(',')
        .Select(value => value.Split(':'))
        .ToDictionary(pair => float.Parse(pair[0].Replace("\"", "")), pair => double.Parse(pair[1]));
    }

    return pairs;
}

public decimal Process(Dictionary<float, double> rates, decimal quantity)
{
    double ret = 0;

    foreach (int key in rates.Keys.OrderByDescending(k => k))
    {
        if (quantity >= key)
        {
            ret += ((double)quantity - key) * rates[key];
            quantity = key;
        }
    }

    return (decimal)ret;
}
于 2016-03-11T04:57:16.763 回答