diff --git a/timespans/activationperiod.go b/timespans/activationperiod.go new file mode 100644 index 000000000..bf9ed47ce --- /dev/null +++ b/timespans/activationperiod.go @@ -0,0 +1,77 @@ +package timespans + +import ( + "time" + "strings" + "strconv" +) + +const LAYOUT = "2006-01-02T15:04:05Z07:00" + +/* +The struture that is saved to storage. +*/ +type ActivationPeriod struct { + ActivationTime time.Time + Intervals []*Interval +} + +/* +Adds one ore more intervals to the internal interval list. +*/ +func (ap *ActivationPeriod) AddInterval(is ...*Interval) { + for _, i := range is { + ap.Intervals = append(ap.Intervals, i) + } +} + +/* +Serializes the objects for the storage. +*/ +func (ap *ActivationPeriod) store() (result string){ + result += ap.ActivationTime.Format(LAYOUT) + ";" + var is string + for _,i := range ap.Intervals { + is = strconv.Itoa(int(i.Month)) + "|" + is += strconv.Itoa(i.MonthDay) + "|" + for _, wd := range i.WeekDays { + is += strconv.Itoa(int(wd)) + "," + } + is = strings.TrimRight(is, ",") + "|" + is += i.StartTime + "|" + is += i.EndTime + "|" + is += strconv.FormatFloat(i.Ponder, 'f', -1, 64) + "|" + is += strconv.FormatFloat(i.ConnectFee, 'f', -1, 64) + "|" + is += strconv.FormatFloat(i.Price, 'f', -1, 64) + "|" + is += strconv.FormatFloat(i.BillingUnit, 'f', -1, 64) + result += is + ";" + } + return +} + +/* +De-serializes the objects for the storage. +*/ +func (ap *ActivationPeriod) restore(input string) { + elements := strings.Split(input, ";") + ap.ActivationTime, _ = time.Parse(LAYOUT, elements[0]) + for _, is := range elements[1:len(elements) - 1]{ + i := &Interval{} + ise := strings.Split(is, "|") + month, _ := strconv.Atoi(ise[0]) + i.Month = time.Month(month) + i.MonthDay, _ = strconv.Atoi(ise[1]) + for _,d := range strings.Split(ise[2], ","){ + wd,_ := strconv.Atoi(d) + i.WeekDays = append(i.WeekDays, time.Weekday(wd)) + } + i.StartTime = ise[3] + i.EndTime = ise[4] + i.Ponder, _ = strconv.ParseFloat(ise[5], 64) + i.ConnectFee, _ = strconv.ParseFloat(ise[6], 64) + i.Price, _ = strconv.ParseFloat(ise[7], 64) + i.BillingUnit, _ = strconv.ParseFloat(ise[8], 64) + + ap.Intervals = append(ap.Intervals, i) + } +} diff --git a/timespans/activationperiod_test.go b/timespans/activationperiod_test.go new file mode 100644 index 000000000..acfd96699 --- /dev/null +++ b/timespans/activationperiod_test.go @@ -0,0 +1,65 @@ +package timespans + +import ( + "testing" + "time" + //"log" +) + +func TestApStoreRestore(t *testing.T) { + d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) + i := &Interval{Month: time.February, + MonthDay: 1, + WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, + StartTime: "14:30:00", + EndTime: "15:00:00"} + ap := ActivationPeriod{ActivationTime: d} + ap.AddInterval(i) + result := ap.store() + expected := "2012-02-01T14:30:01Z;2|1|3,4|14:30:00|15:00:00|0|0|0|0;" + if result != expected { + t.Errorf("Expected %q was %q", expected, result) + } + ap1 := ActivationPeriod{} + ap1.restore(result) + if ap1.ActivationTime != ap.ActivationTime { + t.Errorf("Expected %v was %v", ap.ActivationTime, ap1.ActivationTime) + } + i1 := ap1.Intervals[0] + if i1.Month != i.Month { + t.Errorf("Expected %q was %q", i.Month, i1.Month) + } + if i1.MonthDay != i.MonthDay { + t.Errorf("Expected %q was %q", i.MonthDay, i1.MonthDay) + } + for j,wd := range i1.WeekDays { + if wd != i1.WeekDays[j] { + t.Errorf("Expected %q was %q", i.StartTime, i1.StartTime) + } + } + if i1.StartTime != i.StartTime { + t.Errorf("Expected %q was %q", i.StartTime, i1.StartTime) + } + if i1.EndTime != i.EndTime { + t.Errorf("Expected %q was %q", i.EndTime, i1.EndTime) + } + if i1.Ponder != i.Ponder { + t.Errorf("Expected %q was %q", i.Ponder, i1.Ponder) + } + if i1.ConnectFee != i.ConnectFee { + t.Errorf("Expected %q was %q", i.ConnectFee, i1.ConnectFee) + } + if i1.Price != i.Price { + t.Errorf("Expected %q was %q", i.Price, i1.Price) + } + if i1.BillingUnit != i.BillingUnit { + t.Errorf("Expected %q was %q", i.BillingUnit, i1.BillingUnit) + } +} + +func BenchmarkRestore(b *testing.B) { + ap1 := ActivationPeriod{} + for i := 0; i < b.N; i++ { + ap1.restore("1328106601;2|1|3,4|14:30:00|15:00:00|0|0|0|0;") + } +} diff --git a/timespans/calldesc.go b/timespans/calldesc.go index d19c2fae5..d180650e7 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -4,70 +4,8 @@ import ( "fmt" "time" "strings" - "strconv" ) -const LAYOUT = "2006-01-02T15:04:05Z07:00" - -/* -The struture that is saved to storage. -*/ -type ActivationPeriod struct { - ActivationTime time.Time - Intervals []*Interval -} - -func (ap *ActivationPeriod) AddInterval(is ...*Interval) { - for _, i := range is { - ap.Intervals = append(ap.Intervals, i) - } -} - -func (ap *ActivationPeriod) store() (result string){ - result += ap.ActivationTime.Format(LAYOUT) + ";" - var is string - for _,i := range ap.Intervals { - is = strconv.Itoa(int(i.Month)) + "|" - is += strconv.Itoa(i.MonthDay) + "|" - for _, wd := range i.WeekDays { - is += strconv.Itoa(int(wd)) + "," - } - is = strings.TrimRight(is, ",") + "|" - is += i.StartTime + "|" - is += i.EndTime + "|" - is += strconv.FormatFloat(i.Ponder, 'f', -1, 64) + "|" - is += strconv.FormatFloat(i.ConnectFee, 'f', -1, 64) + "|" - is += strconv.FormatFloat(i.Price, 'f', -1, 64) + "|" - is += strconv.FormatFloat(i.BillingUnit, 'f', -1, 64) - result += is + ";" - } - return -} - -func (ap *ActivationPeriod) restore(input string) { - elements := strings.Split(input, ";") - ap.ActivationTime, _ = time.Parse(LAYOUT, elements[0]) - for _, is := range elements[1:len(elements) - 1]{ - i := &Interval{} - ise := strings.Split(is, "|") - month, _ := strconv.Atoi(ise[0]) - i.Month = time.Month(month) - i.MonthDay, _ = strconv.Atoi(ise[1]) - for _,d := range strings.Split(ise[2], ","){ - wd,_ := strconv.Atoi(d) - i.WeekDays = append(i.WeekDays, time.Weekday(wd)) - } - i.StartTime = ise[3] - i.EndTime = ise[4] - i.Ponder, _ = strconv.ParseFloat(ise[5], 64) - i.ConnectFee, _ = strconv.ParseFloat(ise[6], 64) - i.Price, _ = strconv.ParseFloat(ise[7], 64) - i.BillingUnit, _ = strconv.ParseFloat(ise[8], 64) - - ap.Intervals = append(ap.Intervals, i) - } -} - /* The input stucture that contains call information. */ @@ -78,12 +16,19 @@ type CallDescriptor struct { ActivationPeriods []*ActivationPeriod } +/* +Adds an activation period that applyes to current call descriptor. +*/ func (cd *CallDescriptor) AddActivationPeriod(aps ...*ActivationPeriod) { for _, ap := range aps { cd.ActivationPeriods = append(cd.ActivationPeriods, ap) } } +/* +Creates a string ready for storage containing the serialization of all +activation periods held in the internal list. +*/ func (cd *CallDescriptor) EncodeValues() (result string) { for _, ap := range cd.ActivationPeriods { result += ap.store() + "\n" @@ -91,6 +36,9 @@ func (cd *CallDescriptor) EncodeValues() (result string) { return } +/* +Restores the activation periods list from a storage string. +*/ func (cd *CallDescriptor) decodeValues(v string) { for _, aps := range strings.Split(v, "\n") { if(len(aps)>0){ @@ -101,10 +49,16 @@ func (cd *CallDescriptor) decodeValues(v string) { } } +/* +Constructs the key for the storage lookup. +*/ func (cd *CallDescriptor) GetKey() string { return fmt.Sprintf("%s:%s:%s", cd.CstmId, cd.Subject, cd.DestinationPrefix) } +/* +Finds the intervals applicable to the call descriptior. +*/ func (cd *CallDescriptor) getActiveIntervals() (is []*Interval) { now := time.Now() // add a second in the future to be able to pick the active timestamp @@ -122,6 +76,9 @@ func (cd *CallDescriptor) getActiveIntervals() (is []*Interval) { return } +/* +Splits the call timespan into sub time spans accordin to the received intervals. +*/ func (cd *CallDescriptor) splitInTimeSpans(intervals []*Interval) (timespans []*TimeSpan) { ts1 := &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cd.TimeEnd} timespans = append(timespans, ts1) @@ -138,6 +95,7 @@ func (cd *CallDescriptor) splitInTimeSpans(intervals []*Interval) (timespans []* } /* +Creates a CallCost structure with the cost nformation calculated for the received CallDescriptor. */ func (cd *CallDescriptor) GetCost(sg StorageGetter) (result *CallCost, err error) { @@ -170,4 +128,4 @@ type CallCost struct { CstmId, Subject, DestinationPrefix string Cost, ConnectFee float64 // ratesInfo *RatingProfile -} \ No newline at end of file +} diff --git a/timespans/calldesc_test.go b/timespans/calldesc_test.go index 6ff6769be..9e3054aa1 100644 --- a/timespans/calldesc_test.go +++ b/timespans/calldesc_test.go @@ -79,57 +79,6 @@ func TestRedisGetCost(t *testing.T) { } } -func TestApStoreRestore(t *testing.T) { - d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) - i := &Interval{Month: time.February, - MonthDay: 1, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"} - ap := ActivationPeriod{ActivationTime: d} - ap.AddInterval(i) - result := ap.store() - expected := "2012-02-01T14:30:01Z;2|1|3,4|14:30:00|15:00:00|0|0|0|0;" - if result != expected { - t.Errorf("Expected %q was %q", expected, result) - } - ap1 := ActivationPeriod{} - ap1.restore(result) - if ap1.ActivationTime != ap.ActivationTime { - t.Errorf("Expected %v was %v", ap.ActivationTime, ap1.ActivationTime) - } - i1 := ap1.Intervals[0] - if i1.Month != i.Month { - t.Errorf("Expected %q was %q", i.Month, i1.Month) - } - if i1.MonthDay != i.MonthDay { - t.Errorf("Expected %q was %q", i.MonthDay, i1.MonthDay) - } - for j,wd := range i1.WeekDays { - if wd != i1.WeekDays[j] { - t.Errorf("Expected %q was %q", i.StartTime, i1.StartTime) - } - } - if i1.StartTime != i.StartTime { - t.Errorf("Expected %q was %q", i.StartTime, i1.StartTime) - } - if i1.EndTime != i.EndTime { - t.Errorf("Expected %q was %q", i.EndTime, i1.EndTime) - } - if i1.Ponder != i.Ponder { - t.Errorf("Expected %q was %q", i.Ponder, i1.Ponder) - } - if i1.ConnectFee != i.ConnectFee { - t.Errorf("Expected %q was %q", i.ConnectFee, i1.ConnectFee) - } - if i1.Price != i.Price { - t.Errorf("Expected %q was %q", i.Price, i1.Price) - } - if i1.BillingUnit != i.BillingUnit { - t.Errorf("Expected %q was %q", i.BillingUnit, i1.BillingUnit) - } -} - func BenchmarkKyotoGetCost(b *testing.B) { b.StopTimer() getter, _ := NewKyotoStorage("test.kch") @@ -216,9 +165,3 @@ func BenchmarkDecoding(b *testing.B) { } } -func BenchmarkRestore(b *testing.B) { - ap1 := ActivationPeriod{} - for i := 0; i < b.N; i++ { - ap1.restore("1328106601;2|1|3,4|14:30:00|15:00:00|0|0|0|0;") - } -}