费率的计费计算
Billing calculation of rates
Azure 费率卡 API returns 一个 MeterRates 字段(请参阅 documentation)。
Azure UsageAggregate 给出了一个数量(参见documentation)。
根据天蓝色的支持page。这是提问的论坛。
那么,如何应用电表费率?
电表费率示例:
{"0":20, "100":15, "200":10}
如果我有175的数量是100*20 + 75*15
还是175*15
?
为什么要指定包含数量?
示例:rates:{"0":23}
包含数量 10 可以表示为费率:
{"0":0, "10":23}
example meter rates: {"0":20, "100":15, "200":10}
if I have a quantity of 175 is the amount 100*20 + 75*15 or 175*15 ?
定价为分级定价。因此,当您获得费率时,它实际上会告诉您:
- 来自
0 - 99
个单元,单元率是20
- 来自
100 - 199
个单元,单元率是15
- 从
200
个单元及以上,单元率是10
根据这个逻辑,你的计算应该是:
99 * 20 + 75 * 15 = 3105
让我困惑的一件事是上限。以上计算基于我从 Azure 计费团队收到的信息。让我感到困惑的是,如果消耗量是 99.5
个单位,会发生什么情况?对于第一个 99
个单位,它很好,但我不确定如何计算额外的 0.5
个单位。
Guarav 触及了问题的核心,这也是我将其标记为答案的原因。基于此,我设计了以下代码来实现逻辑。它分为两部分:
- 根据计量费率创建遗愿清单
- 使用存储桶列表处理数量以确定金额
以下函数创建一个桶列表(每个桶对象都是一个简单的 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;
}
第二个函数使用具有两个有用属性的 meter 对象:存储桶列表和包含的数量。根据价目表文件(正如我所读的),在超过包含的数量之前,您不会开始计算可计费数量。我敢肯定这里可以进行一些重构,但是桶的有序处理是关键。
我认为我已经通过识别它是双精度而不是整数来解决数量问题。因此,与任何单个桶关联的数量是桶最大值和桶最小值之间的差值(除非我们只填充了部分桶)。
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 允许我每天或每小时提取数据。我想每小时提取一次数据,这样我就可以按一天中的时间关联我的成本。但是什么时候才真正算帐合适呢?好像hourly是错误的,daily可能行,但可能只适用于整个月。
最近我刚做了这个类似的任务。以下是我的示例(我认为您可以使用正则表达式来删除这些字符,而不是像我一样使用替换)。第一个函数解析费率信息字符串生成键值对集合,第二个函数用于计算总价。
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;
}
Azure 费率卡 API returns 一个 MeterRates 字段(请参阅 documentation)。 Azure UsageAggregate 给出了一个数量(参见documentation)。
根据天蓝色的支持page。这是提问的论坛。
那么,如何应用电表费率?
电表费率示例:
{"0":20, "100":15, "200":10}
如果我有175的数量是100*20 + 75*15
还是175*15
?
为什么要指定包含数量?
示例:rates:{"0":23}
包含数量 10 可以表示为费率:
{"0":0, "10":23}
example meter rates: {"0":20, "100":15, "200":10}
if I have a quantity of 175 is the amount 100*20 + 75*15 or 175*15 ?
定价为分级定价。因此,当您获得费率时,它实际上会告诉您:
- 来自
0 - 99
个单元,单元率是20
- 来自
100 - 199
个单元,单元率是15
- 从
200
个单元及以上,单元率是10
根据这个逻辑,你的计算应该是:
99 * 20 + 75 * 15 = 3105
让我困惑的一件事是上限。以上计算基于我从 Azure 计费团队收到的信息。让我感到困惑的是,如果消耗量是 99.5
个单位,会发生什么情况?对于第一个 99
个单位,它很好,但我不确定如何计算额外的 0.5
个单位。
Guarav 触及了问题的核心,这也是我将其标记为答案的原因。基于此,我设计了以下代码来实现逻辑。它分为两部分:
- 根据计量费率创建遗愿清单
- 使用存储桶列表处理数量以确定金额
以下函数创建一个桶列表(每个桶对象都是一个简单的 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;
}
第二个函数使用具有两个有用属性的 meter 对象:存储桶列表和包含的数量。根据价目表文件(正如我所读的),在超过包含的数量之前,您不会开始计算可计费数量。我敢肯定这里可以进行一些重构,但是桶的有序处理是关键。
我认为我已经通过识别它是双精度而不是整数来解决数量问题。因此,与任何单个桶关联的数量是桶最大值和桶最小值之间的差值(除非我们只填充了部分桶)。
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 允许我每天或每小时提取数据。我想每小时提取一次数据,这样我就可以按一天中的时间关联我的成本。但是什么时候才真正算帐合适呢?好像hourly是错误的,daily可能行,但可能只适用于整个月。
最近我刚做了这个类似的任务。以下是我的示例(我认为您可以使用正则表达式来删除这些字符,而不是像我一样使用替换)。第一个函数解析费率信息字符串生成键值对集合,第二个函数用于计算总价。
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;
}