how does it work section in introduction and code formatting

This commit is contained in:
Radu Ioan Fericean
2012-03-13 00:03:38 +02:00
parent 3120bf8890
commit 219013c8d1
6 changed files with 129 additions and 105 deletions

View File

@@ -57,4 +57,4 @@ resetvolumediscountseconds
addrecievedcallseconds
:Example: curl "http://127.0.0.1:8000/addrecievedcallseconds?cstmid=vdf&subj=rif&dest=0257@amount=100"
resetuserbudget
:Example: curl "http://127.0.0.1:8000/resetuserbudget?cstmid=vdf&subj=rif&dest=0257"
:Example: curl "http://127.0.0.1:8000/resetuserbudget?cstmid=vdf&subj=rif&dest=0257"

View File

@@ -2,7 +2,7 @@ Introduction
============
CGRates is a very fast and easy scalable rating engine targeted especially for telecom providers.
It is written in go (http://golang.net) and accesible from any language via JSON RPC. The code is well documented (go doc compliant api docs) and heavily tested.
It is written in go (http://golang.net) and accessible from any language via JSON RPC. The code is well documented (go doc compliant API docs) and heavily tested.
Supported databases: kyoto_ cabinet, redis_, mongodb_.
@@ -20,4 +20,28 @@ Features
+ Fully/Easy configurable
+ Very fast (5000+ req/sec)
+ Good documentation
+ Commercial support available
+ Commercial support available
How does CGRates work?
----------------------
Let's start with the most important function: finding the cost of a certain call. The call information comes to CGRates as the following values: subject, destination, start time and end time. The engine will lookup in the database for the activation periods applicable to the received subject and destination. What are the activation periods?
The activation period is a structure describing different prices for a call on different intervals of time. This structure has an activation time, from this time on the activation period is in effect and one ore more (usually more than one) intervals with prices. An interval is looking like this:
::
type Interval struct {
Month time.Month
MonthDay int
WeekDays []time.Weekday
StartTime, EndTime string // ##:##:## format
Ponder, ConnectFee, Price, BillingUnit float64
}
It specifies the Month, the MonthDay, the WeekDays and the StartTime and the EndTime when the Interval's Price is in effect.
For example the interval {"Month": 1, "WeekDays":[1,2,3,4,5]. "StartTime":"18:00:00", "Price":0.1, "BillingUnit": 1} specifies that the Price for the first month of each year from Monday to Friday starting 18:00 is 0.1 cents per second. Most structure elements are optional and they can be combined in any way it makes sense. If an element is omitted it means it is zero ore any.
The ConnectFee specifies the connection price for the call if this interval is the first one from the call and the Ponder will establishes which interval will set the price for a call segment if more then one applies to it.
The other functions relay on a user budget structure to manage the postpaid and prepaid different quotas.

View File

@@ -33,15 +33,15 @@ type Destination struct {
Serializes the destination for the storage. Used for key-value storages.
*/
func (d *Destination) store() (result string) {
for _, p := range d.Prefixes {
result += p + ","
}
result = strings.TrimRight(result, ",")
return
for _, p := range d.Prefixes {
result += p + ","
}
result = strings.TrimRight(result, ",")
return
}
func (d *Destination) restore(input string) {
d.Prefixes = strings.Split(input, ",")
d.Prefixes = strings.Split(input, ",")
}
/*

View File

@@ -18,9 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package timespans
import (
// "log"
"strings"
// "log"
"strconv"
"strings"
)
/*
@@ -41,56 +41,56 @@ type TariffPlan struct {
Serializes the tariff plan for the storage. Used for key-value storages.
*/
func (tp *TariffPlan) store() (result string) {
result += strconv.FormatFloat(tp.SmsCredit, 'f', -1, 64) + ";"
result += strconv.FormatFloat(tp.Traffic, 'f', -1, 64) + ";"
result += strconv.FormatFloat(tp.ReceivedCallSecondsLimit, 'f', -1, 64) + ";"
if tp.RecivedCallBonus == nil {
tp.RecivedCallBonus = &RecivedCallBonus{}
}
result += tp.RecivedCallBonus.store() + ";"
for i, mb := range tp.MinuteBuckets {
if i > 0 {
result += ","
}
result += mb.store()
}
if tp.VolumeDiscountThresholds != nil {
result += ";"
}
for i, vd := range tp.VolumeDiscountThresholds {
if i > 0 {
result += ","
}
result += strconv.FormatFloat(vd.Volume, 'f', -1, 64) + "|" + strconv.FormatFloat(vd.Discount, 'f', -1, 64)
}
result = strings.TrimRight(result, ";")
return
result += strconv.FormatFloat(tp.SmsCredit, 'f', -1, 64) + ";"
result += strconv.FormatFloat(tp.Traffic, 'f', -1, 64) + ";"
result += strconv.FormatFloat(tp.ReceivedCallSecondsLimit, 'f', -1, 64) + ";"
if tp.RecivedCallBonus == nil {
tp.RecivedCallBonus = &RecivedCallBonus{}
}
result += tp.RecivedCallBonus.store() + ";"
for i, mb := range tp.MinuteBuckets {
if i > 0 {
result += ","
}
result += mb.store()
}
if tp.VolumeDiscountThresholds != nil {
result += ";"
}
for i, vd := range tp.VolumeDiscountThresholds {
if i > 0 {
result += ","
}
result += strconv.FormatFloat(vd.Volume, 'f', -1, 64) + "|" + strconv.FormatFloat(vd.Discount, 'f', -1, 64)
}
result = strings.TrimRight(result, ";")
return
}
/*
De-serializes the tariff plan for the storage. Used for key-value storages.
*/
func (tp *TariffPlan) restore(input string) {
elements := strings.Split(input, ";")
tp.SmsCredit, _ = strconv.ParseFloat(elements[0], 64)
tp.Traffic, _ = strconv.ParseFloat(elements[1], 64)
tp.ReceivedCallSecondsLimit, _ = strconv.ParseFloat(elements[2], 64)
tp.RecivedCallBonus = &RecivedCallBonus{}
tp.RecivedCallBonus.restore(elements[3])
for _, mbs := range strings.Split(elements[4], ",") {
mb := &MinuteBucket{}
mb.restore(mbs)
tp.MinuteBuckets = append(tp.MinuteBuckets, mb)
}
if len(elements) > 5 {
for _, vdss := range strings.Split(elements[5], ",") {
vd := &VolumeDiscount{}
vds := strings.Split(vdss, "|")
vd.Volume, _ = strconv.ParseFloat(vds[0], 64)
vd.Discount, _ = strconv.ParseFloat(vds[1], 64)
tp.VolumeDiscountThresholds = append(tp.VolumeDiscountThresholds, vd)
}
}
elements := strings.Split(input, ";")
tp.SmsCredit, _ = strconv.ParseFloat(elements[0], 64)
tp.Traffic, _ = strconv.ParseFloat(elements[1], 64)
tp.ReceivedCallSecondsLimit, _ = strconv.ParseFloat(elements[2], 64)
tp.RecivedCallBonus = &RecivedCallBonus{}
tp.RecivedCallBonus.restore(elements[3])
for _, mbs := range strings.Split(elements[4], ",") {
mb := &MinuteBucket{}
mb.restore(mbs)
tp.MinuteBuckets = append(tp.MinuteBuckets, mb)
}
if len(elements) > 5 {
for _, vdss := range strings.Split(elements[5], ",") {
vd := &VolumeDiscount{}
vds := strings.Split(vdss, "|")
vd.Volume, _ = strconv.ParseFloat(vds[0], 64)
vd.Discount, _ = strconv.ParseFloat(vds[1], 64)
tp.VolumeDiscountThresholds = append(tp.VolumeDiscountThresholds, vd)
}
}
}
/*
@@ -115,26 +115,26 @@ type RecivedCallBonus struct {
Serializes the tariff plan for the storage. Used for key-value storages.
*/
func (rcb *RecivedCallBonus) store() (result string) {
result += strconv.FormatFloat(rcb.Credit, 'f', -1, 64) + ","
result += strconv.FormatFloat(rcb.SmsCredit, 'f', -1, 64) + ","
result += strconv.FormatFloat(rcb.Traffic, 'f', -1, 64)
if rcb.MinuteBucket != nil {
result += ","
result += rcb.MinuteBucket.store()
}
return
result += strconv.FormatFloat(rcb.Credit, 'f', -1, 64) + ","
result += strconv.FormatFloat(rcb.SmsCredit, 'f', -1, 64) + ","
result += strconv.FormatFloat(rcb.Traffic, 'f', -1, 64)
if rcb.MinuteBucket != nil {
result += ","
result += rcb.MinuteBucket.store()
}
return
}
/*
De-serializes the tariff plan for the storage. Used for key-value storages.
*/
func (rcb *RecivedCallBonus) restore(input string) {
elements := strings.Split(input, ",")
rcb.Credit, _ = strconv.ParseFloat(elements[0], 64)
rcb.SmsCredit, _ = strconv.ParseFloat(elements[1], 64)
rcb.Traffic, _ = strconv.ParseFloat(elements[2], 64)
if len(elements) > 3 {
rcb.MinuteBucket = &MinuteBucket{}
rcb.MinuteBucket.restore(elements[3])
}
elements := strings.Split(input, ",")
rcb.Credit, _ = strconv.ParseFloat(elements[0], 64)
rcb.SmsCredit, _ = strconv.ParseFloat(elements[1], 64)
rcb.Traffic, _ = strconv.ParseFloat(elements[2], 64)
if len(elements) > 3 {
rcb.MinuteBucket = &MinuteBucket{}
rcb.MinuteBucket.restore(elements[3])
}
}

View File

@@ -79,7 +79,7 @@ func (ts *TimeSpan) Contains(t time.Time) bool {
}
/*
will set ne interval as spans's interval if new ponder is greater then span's interval ponder
will set the interval as spans's interval if new ponder is greater then span's interval ponder
or if the ponders are equal and new price is lower then spans's interval price
*/
func (ts *TimeSpan) SetInterval(i *Interval) {

View File

@@ -20,9 +20,9 @@ package timespans
import (
// "log"
"sort"
"sync"
"strconv"
"strings"
"sync"
)
/*
@@ -74,44 +74,44 @@ func (bs bucketsorter) Less(j, i int) bool {
Serializes the user budget for the storage. Used for key-value storages.
*/
func (ub *UserBudget) store() (result string) {
result += strconv.FormatFloat(ub.Credit, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.SmsCredit, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.Traffic, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.VolumeDiscountSeconds, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.ReceivedCallSeconds, 'f', -1, 64) + ";"
result += strconv.Itoa(ub.ResetDayOfTheMonth) + ";"
result += ub.TariffPlanId
if ub.MinuteBuckets != nil {
result += ";"
}
for i, mb := range ub.MinuteBuckets {
if i > 0 {
result += ","
}
result += mb.store()
}
return
result += strconv.FormatFloat(ub.Credit, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.SmsCredit, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.Traffic, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.VolumeDiscountSeconds, 'f', -1, 64) + ";"
result += strconv.FormatFloat(ub.ReceivedCallSeconds, 'f', -1, 64) + ";"
result += strconv.Itoa(ub.ResetDayOfTheMonth) + ";"
result += ub.TariffPlanId
if ub.MinuteBuckets != nil {
result += ";"
}
for i, mb := range ub.MinuteBuckets {
if i > 0 {
result += ","
}
result += mb.store()
}
return
}
/*
De-serializes the user budget for the storage. Used for key-value storages.
*/
func (ub *UserBudget) restore(input string) {
elements := strings.Split(input, ";")
ub.Credit, _ = strconv.ParseFloat(elements[0], 64)
ub.SmsCredit, _ = strconv.ParseFloat(elements[1], 64)
ub.Traffic, _ = strconv.ParseFloat(elements[2], 64)
ub.VolumeDiscountSeconds, _ = strconv.ParseFloat(elements[3], 64)
ub.ReceivedCallSeconds, _ = strconv.ParseFloat(elements[4], 64)
ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[5])
ub.TariffPlanId = elements[6]
if len(elements) > 7 {
for _, mbs := range strings.Split(elements[7], ",") {
mb := &MinuteBucket{}
mb.restore(mbs)
ub.MinuteBuckets = append(ub.MinuteBuckets, mb)
}
}
elements := strings.Split(input, ";")
ub.Credit, _ = strconv.ParseFloat(elements[0], 64)
ub.SmsCredit, _ = strconv.ParseFloat(elements[1], 64)
ub.Traffic, _ = strconv.ParseFloat(elements[2], 64)
ub.VolumeDiscountSeconds, _ = strconv.ParseFloat(elements[3], 64)
ub.ReceivedCallSeconds, _ = strconv.ParseFloat(elements[4], 64)
ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[5])
ub.TariffPlanId = elements[6]
if len(elements) > 7 {
for _, mbs := range strings.Split(elements[7], ",") {
mb := &MinuteBucket{}
mb.restore(mbs)
ub.MinuteBuckets = append(ub.MinuteBuckets, mb)
}
}
}
/*