feat: statistics: finish dev

This commit is contained in:
fallen-angle
2022-01-23 18:28:01 +08:00
parent 582807ae10
commit d844711191
29 changed files with 1670 additions and 51 deletions

184
service/statistics/cache.go Normal file
View File

@@ -0,0 +1,184 @@
package statistics
import (
"encoding/json"
"fmt"
"nCovTrack-Backend/global"
"nCovTrack-Backend/models"
"nCovTrack-Backend/utils"
"sort"
"strings"
"time"
)
const (
rds_NCOV_STATISTIC_KEY = "nCovStatistic"
rds_CHINA_TOTAL_KEY = "chinaTotal"
rds_CHINA_ADD_KEY = "chinaAdd"
rds_COUNTRY_LEVEL_KEY = "countryLevel"
rds_COUNTRY_LEVEL_CHILD_KEY = "countryLevelChild"
rds_PROVIENCE_LEVEL_CHILD_KEY = "provienceLevelChild"
rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY = "provienceLevelNowConfirm"
rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY = "provienceLevelTodayConfirm"
rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY = "provienceLevelTotalConfirm"
rds_CITY_LEVEL_CHILD_KEY = "cityLevelChild"
rds_CITY_LEVEL_NOW_CONFIRM_KEY = "cityLevelNowConfirm"
rds_CITY_LEVEL_TODAY_CONFIRM_KEY = "cityLevelTodayConfirm"
rds_CITY_LEVEL_TOTAL_CONFIRM_KEY = "cityLevelTotalConfirm"
rds_LAST_UPDATE_TIME = "statisticsLastUpdateTime"
rds_LAST_CACHE_TIME = "statisticsLastCacheTime"
SORT_TODAY_CONFIRM = "today"
SORT_TOTAL_CONFIRM = "total"
SORT_NOW_CONFIRM = "now"
json_FOREIGN_COUNTRY = "境外"
json_FOREIGN_CITY = "外地"
json_TO_BE_CONFIRM = "待确认"
)
var (
sortBy string
)
type AreaSlice []models.AreaInfo
func cacheNCovStatistics() {
resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_URL)
var nCovRes map[string]string
json.Unmarshal([]byte(resp), &nCovRes)
var nCovResData map[string]interface{}
json.Unmarshal([]byte(nCovRes["data"]), &nCovResData)
if !needToRecache(nCovResData) {
return
}
cacheChinaInfo(nCovResData)
cacheLevelInfo(nCovResData)
cacheLastUpdateTime(nCovResData)
}
func cacheChinaInfo(data map[string]interface{}) {
chinaTotal, _ := json.Marshal(data["chinaTotal"])
chinaAdd, _ := json.Marshal(data["chinaAdd"])
global.Redis.Set(rds_CHINA_TOTAL_KEY, chinaTotal, time.Duration(12*time.Hour))
global.Redis.Set(rds_CHINA_ADD_KEY, chinaAdd, time.Duration(12*time.Hour))
}
func cacheLastUpdateTime(data map[string]interface{}) {
global.Redis.Set(rds_LAST_UPDATE_TIME, data["lastUpdateTime"], time.Duration(12*time.Hour))
global.Redis.Set(rds_LAST_CACHE_TIME, time.Now().String(), time.Duration(12*time.Hour))
}
func needToRecache(data map[string]interface{}) bool {
rdsLastUpdateTime := global.Redis.Get(rds_LAST_UPDATE_TIME).Val()
newestUpdateTime := fmt.Sprintf("%v", data["lastUpdateTime"])
return rdsLastUpdateTime != newestUpdateTime
}
func cacheLevelInfo(data map[string]interface{}) {
areaTree, _ := json.Marshal(data["areaTree"])
// Get Every Level's Info
var countryLevels []models.AreaInfo
json.Unmarshal(areaTree, &countryLevels)
provienceLevels := children(countryLevels)
cityLevels := children(provienceLevels)
// Country Level Area Info With Child
cacheList(rds_COUNTRY_LEVEL_CHILD_KEY, areaInfoToJson(countryLevels)...)
// Country Level Area Info
areaInfoChildNil(&countryLevels)
cacheList(rds_COUNTRY_LEVEL_KEY, areaInfoToJson(countryLevels)...)
// Provience Level Area Info With Child
cacheList(rds_PROVIENCE_LEVEL_CHILD_KEY, areaInfoToJson(provienceLevels)...)
areaInfoChildNil(&provienceLevels)
// City Level Area Info With Child
cacheList(rds_CITY_LEVEL_CHILD_KEY, areaInfoToJson(cityLevels)...)
areaInfoChildNil(&provienceLevels)
// Provience Level Area Info Sorted by Now Confirm
provienceLevelsSlice := AreaSlice(provienceLevels)
sort.Sort(provienceLevelsSlice)
cacheList(rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...)
// City Level Area Info Sorted By Now Confirm
cityLevelsSlice := AreaSlice(cityLevels)
sort.Sort(cityLevelsSlice)
cacheList(rds_CITY_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...)
sortBy = SORT_TODAY_CONFIRM
// Provience Level Area Info Sorted by Today Confirm
sort.Sort(provienceLevelsSlice)
cacheList(rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...)
// City Level Area Info Sorted by Today Confirm
sort.Sort(cityLevelsSlice)
cacheList(rds_CITY_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...)
sortBy = SORT_TOTAL_CONFIRM
// Provience Level Area Info Sorted by Total Confirm
sort.Sort(provienceLevelsSlice)
cacheList(rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(provienceLevelsSlice)...)
// City Level Area Info Sorted by Total Confirm
sort.Sort(cityLevelsSlice)
cacheList(rds_CITY_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...)
}
func cacheList(key string, values ...interface{}) {
global.Redis.Del(key)
global.Redis.RPush(key, values...)
}
func children(parents []models.AreaInfo) []models.AreaInfo {
var areaInfos []models.AreaInfo
for _, parent := range parents {
if parent.Children == nil {
continue
}
for _, item := range parent.Children {
name := item.Name
if !strings.Contains(name, json_FOREIGN_CITY) && !strings.Contains(name, json_FOREIGN_COUNTRY) && !strings.Contains(name, json_TO_BE_CONFIRM) {
areaInfos = append(areaInfos, item)
}
}
}
return areaInfos
}
func areaInfoToJson(areaInfos []models.AreaInfo) []interface{} {
return utils.Map(areaInfos, func(item models.AreaInfo) interface{} {
jsonByte, _ := json.Marshal(item)
return jsonByte
})
}
func areaInfoChildNil(areaInfos *[]models.AreaInfo) {
utils.ForEach(areaInfos, func(item *models.AreaInfo) {
item.Children = nil
})
}
func checkCache() {
if global.Redis.Get(rds_LAST_UPDATE_TIME).Val() == "" {
cacheNCovStatistics()
}
}
func (s AreaSlice) Len() int { return len(s) }
func (s AreaSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s AreaSlice) Less(i, j int) bool {
if sortBy == SORT_TODAY_CONFIRM {
return s[i].Today.Comfirm > s[j].Today.Comfirm
}
if sortBy == SORT_TOTAL_CONFIRM {
return s[i].Total.Confirm > s[j].Total.Confirm
}
// Default sorted by now confirm
return s[i].Total.NowConfirm > s[j].Total.NowConfirm
}
func CacheNCov() {
cacheNCovStatistics()
}

View File

@@ -2,41 +2,57 @@ package statistics
import (
"encoding/json"
"fmt"
"nCovTrack-Backend/global"
"nCovTrack-Backend/utils"
"net/http"
"github.com/gin-gonic/gin"
"nCovTrack-Backend/models"
"strings"
)
func GetChinaNCovStatistics() func(c *gin.Context) {
return func(c *gin.Context) {
resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_URL)
var nCovRes map[string]string
json.Unmarshal([]byte(resp), &nCovRes)
fmt.Println(nCovRes)
var nCovResData interface{}
json.Unmarshal([]byte(nCovRes["data"]), &nCovResData)
c.JSON(http.StatusOK, nCovResData)
func GetAllProvienceData(sort string) []interface{} {
checkCache()
if sort == SORT_TODAY_CONFIRM {
return getEntireRedisList(rds_PROVIENCE_LEVEL_TODAY_CONFIRM_KEY)
}
if sort == SORT_TOTAL_CONFIRM {
return getEntireRedisList(rds_PROVIENCE_LEVEL_TOTAL_CONFIRM_KEY)
}
if sort == SORT_NOW_CONFIRM {
return getEntireRedisList(rds_PROVIENCE_LEVEL_NOW_CONFIRM_KEY)
}
return getEntireRedisList(rds_PROVIENCE_LEVEL_CHILD_KEY)
}
func GetChinaNCovStatistic() func(c *gin.Context) {
return func(c *gin.Context) {
//resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_URL)
var nCovRes map[string]string
//err := json.Unmarshal([]byte(resp), &nCovRes)
//fmt.Println(nCovRes)
//if err != nil {
// panic(err)
//}
//var nCovResData interface{}
//err := json.Unmarshal([]byte(nCovRes["data"]), &nCovResData)
//if err != nil {
// panic(err)
//}
nCovRes["1"] = "1"
c.JSON(http.StatusOK, nCovRes)
func GetAllCityData(sort string) []interface{} {
checkCache()
if sort == SORT_TODAY_CONFIRM {
return getEntireRedisList(rds_CITY_LEVEL_TODAY_CONFIRM_KEY)
}
if sort == SORT_TOTAL_CONFIRM {
return getEntireRedisList(rds_CITY_LEVEL_TOTAL_CONFIRM_KEY)
}
if sort == SORT_NOW_CONFIRM {
return getEntireRedisList(rds_CITY_LEVEL_NOW_CONFIRM_KEY)
}
return getEntireRedisList(rds_CITY_LEVEL_CHILD_KEY)
}
func GetCountryData(child bool) []interface{} {
if child {
return getEntireRedisList(rds_COUNTRY_LEVEL_CHILD_KEY)
}
return getEntireRedisList(rds_COUNTRY_LEVEL_KEY)
}
func GetChinaNCovStatistic() models.ChinaData {
data := models.ChinaData{}
json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_ADD_KEY).Val()), &data.ChinaAdd)
json.Unmarshal([]byte(global.Redis.Get(rds_CHINA_TOTAL_KEY).Val()), &data.ChinaTotal)
return data
}
func getEntireRedisList(key string) []interface{} {
var data []interface{}
dataStrArr := global.Redis.LRange(key, 0, -1).Val()
dataStr := "[" + strings.Join(dataStrArr[:], ",") + "]"
json.Unmarshal([]byte(dataStr), &data)
return data
}