Skip to content

Commit

Permalink
refactor(wau & mau): change calculate method according to comment
Browse files Browse the repository at this point in the history
change the GetPeriodInfoFromPOs method. add basic tests.
  • Loading branch information
Ayanami1314 committed Nov 20, 2024
1 parent 32d3bc4 commit 92dbb36
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 28 deletions.
60 changes: 32 additions & 28 deletions model/converter/statistic.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,45 +24,49 @@ func ConvertDailyInfoFromPO(po po.StatisticPO) model.DailyInfo {
}
}

// GetPeriodInfoFromPOs 从统计数据中获取指定的周期信息, 调用者保证pos中的数据是按时间增序排列的
// GetPeriodInfoFromPOs 从统计数据中获取指定的周期信息, 调用者保证pos中的数据是按时间增序排列的, 保证返回的数据是按时间增序排列的
func GetPeriodInfoFromPOs(pos []po.StatisticPO, keys []model.PeriodInfoKey) (map[model.PeriodInfoKey][]model.PeriodInfo, error) {
const week = 7
const month = 30
periodInfoMap := make(map[model.PeriodInfoKey][]model.PeriodInfo)
total := len(pos)
for _, key := range keys {
periodInfoMap[key] = make([]model.PeriodInfo, 0)
switch key {
case model.PeriodInfoKeyMAU:
for i := range pos {
if i >= month-1 {
monthWindow := make([]int64, month)
for j := i - month + 1; j <= i; j++ {
monthWindow[j] = pos[j].UVCount
}
newInfo := model.PeriodInfo{
StartTime: pos[i-month+1].Date.Unix(),
EndTime: pos[i].Date.Unix(),
Value: mathutil.Average(monthWindow...),
Key: key,
}
periodInfoMap[key] = append(periodInfoMap[key], newInfo)
months := total / month
// 这里反向遍历, 保证返回的数据是按时间增序排列的
for i := months - 1; i >= 0; i-- {
end := total - 1 - i*month
start := end - month + 1
monthWindow := make([]int64, month)
for j := start; j <= end; j++ {
monthWindow[j-start] = pos[j].UVCount
}
newInfo := model.PeriodInfo{
StartTime: pos[start].Date.Unix(),
EndTime: pos[end].Date.Unix(),
Value: mathutil.Average(monthWindow...),
Key: key,
}
periodInfoMap[key] = append(periodInfoMap[key], newInfo)
}
case model.PeriodInfoKeyWAU:
periodInfoMap[key] = make([]model.PeriodInfo, 0)
for i := range pos {
if i >= week-1 {
weekWindow := make([]int64, week)
for j := i - week + 1; j <= i; j++ {
weekWindow[j] = pos[j].UVCount
}
newInfo := model.PeriodInfo{
StartTime: pos[i-week+1].Date.Unix(),
EndTime: pos[i].Date.Unix(),
Value: mathutil.Average(weekWindow...),
Key: key,
}
periodInfoMap[key] = append(periodInfoMap[key], newInfo)
weeks := total / week
for i := weeks - 1; i >= 0; i-- {
end := total - 1 - i*week
start := end - week + 1
weekWindow := make([]int64, week)
for j := start; j <= end; j++ {
weekWindow[j-start] = pos[j].UVCount
}
newInfo := model.PeriodInfo{
StartTime: pos[start].Date.Unix(),
EndTime: pos[end].Date.Unix(),
Value: mathutil.Average(weekWindow...),
Key: key,
}
periodInfoMap[key] = append(periodInfoMap[key], newInfo)
}
default:
return nil, fmt.Errorf(model.ErrInvalidPeriodInfoKey, key)
Expand Down
57 changes: 57 additions & 0 deletions model/converter/statistic_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package converter

import (
"jcourse_go/model/model"
"jcourse_go/model/po"
"jcourse_go/util"
"math/rand"
"testing"
"time"

Expand Down Expand Up @@ -37,3 +39,58 @@ func TestConvertStatisticDataFromPO(t *testing.T) {
assert.True(t, statisticData.UVData.Contains(10086))
})
}

func TestGetPeriodInfoFromPOs(t *testing.T) {
// Helper function to create a StatisticPO with a given date and UVCount
createStatisticPO := func(daysAgo int) po.StatisticPO {
return po.StatisticPO{
Date: util.GetMidTime(time.Now()).AddDate(0, 0, -daysAgo),
UVCount: int64(rand.Uint64() % 1000),
PVCount: int64(rand.Uint64() % 1000),
TotalReviews: 10000 - int64(daysAgo)*100,
TotalUsers: 1000 - int64(daysAgo)*10,
NewReviews: 100,
NewUsers: 10,
}
}

// Test data
pos := make([]po.StatisticPO, 40)
for i := 0; i < 40; i++ {
pos[i] = createStatisticPO(i)
}

keys := []model.PeriodInfoKey{model.PeriodInfoKeyMAU, model.PeriodInfoKeyWAU}

// Call the function
periodInfoMap, err := GetPeriodInfoFromPOs(pos, keys)
assert.Nil(t, err)

// Verify the results for MAU
mauInfo := periodInfoMap[model.PeriodInfoKeyMAU]
assert.Equal(t, 1, len(mauInfo))
assert.Equal(t, pos[10].Date.Unix(), mauInfo[0].StartTime)
assert.Equal(t, pos[39].Date.Unix(), mauInfo[0].EndTime)
mau := int64(0)
for i := 10; i < 40; i++ {
mau += pos[i].UVCount
}
mau /= 30
assert.Equal(t, mau, mauInfo[0].Value) // Average of UVCounts from 0 to 29

// Verify the results for WAU
wauInfo := periodInfoMap[model.PeriodInfoKeyWAU]
assert.Equal(t, 5, len(wauInfo))
for i, info := range wauInfo {
start := 7*i + 5 // 6, 13, 20, 27, 34
end := start + 6
expectedValue := int64(0)
for j := start; j <= end; j++ {
expectedValue += pos[j].UVCount
}
expectedValue /= 7
assert.Equal(t, pos[start].Date.Unix(), info.StartTime)
assert.Equal(t, pos[end].Date.Unix(), info.EndTime)
assert.Equal(t, expectedValue, info.Value)
}
}

0 comments on commit 92dbb36

Please sign in to comment.