Files
nCovTrack-Backend/service/statistics/cache.go
2022-05-04 20:06:21 +08:00

203 lines
6.6 KiB
Go

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_PROVINCE_LEVEL_CHILD_KEY = "provinceLevelChild"
rds_PROVINCE_LEVEL_NOW_CONFIRM_KEY = "provinceLevelNowConfirm"
rds_PROVINCE_LEVEL_TODAY_CONFIRM_KEY = "provinceLevelTodayConfirm"
rds_PROVINCE_LEVEL_TOTAL_CONFIRM_KEY = "provinceLevelTotalConfirm"
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"
rds_CHINA_DAY_ADD_LIST_KEY = "chinaDayAdd"
rds_CHINA_DAY_LIST_KEY = "chinaDay"
SORT_TODAY_CONFIRM = "today"
SORT_TOTAL_CONFIRM = "total"
SORT_NOW_CONFIRM = "now"
D
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]interface{}
json.Unmarshal([]byte(resp), &nCovRes)
nCovResData := (nCovRes["data"].(map[string]interface{}))["diseaseh5Shelf"].(map[string]interface{})
if !needToRecache(nCovResData) {
return
}
cacheChinaInfo(nCovResData)
cacheLevelInfo(nCovResData)
cacheLastUpdateTime(nCovResData)
resp = utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_TREND_URL)
}
func CacheNCovTrend() {
resp := utils.GetWhioutHeader(global.CHINA_NCOV_STATISTIC_TREND_URL)
var nCovRes map[string]interface{}
json.Unmarshal([]byte(resp), &nCovRes)
nCovResData := nCovRes["data"].(map[string]interface{})
cacheChinaTrend(nCovResData)
}
func cacheChinaTrend(data map[string]interface{}) {
chinaDayAdd, _ := json.Marshal(data["chinaDayAddList"])
chinaDay, _ := json.Marshal(data["chinaDayList"])
global.Redis.Set(rds_CHINA_DAY_ADD_LIST_KEY, chinaDayAdd, 0)
global.Redis.Set(rds_CHINA_DAY_LIST_KEY, chinaDay, 0)
}
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)
provinceLevels := children(countryLevels)
cityLevels := children(provinceLevels)
// 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)...)
// Province Level Area Info With Child
cacheList(rds_PROVINCE_LEVEL_CHILD_KEY, areaInfoToJson(provinceLevels)...)
areaInfoChildNil(&provinceLevels)
// City Level Area Info With Child
cacheList(rds_CITY_LEVEL_CHILD_KEY, areaInfoToJson(cityLevels)...)
areaInfoChildNil(&provinceLevels)
// Province Level Area Info Sorted by Now Confirm
provinceLevelsSlice := AreaSlice(provinceLevels)
sort.Sort(provinceLevelsSlice)
cacheList(rds_PROVINCE_LEVEL_NOW_CONFIRM_KEY, areaInfoToJson(provinceLevelsSlice)...)
// 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
// Province Level Area Info Sorted by Today Confirm
sort.Sort(provinceLevelsSlice)
cacheList(rds_PROVINCE_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(provinceLevelsSlice)...)
// City Level Area Info Sorted by Today Confirm
sort.Sort(cityLevelsSlice)
cacheList(rds_CITY_LEVEL_TODAY_CONFIRM_KEY, areaInfoToJson(cityLevelsSlice)...)
sortBy = SORT_TOTAL_CONFIRM
// Province Level Area Info Sorted by Total Confirm
sort.Sort(provinceLevelsSlice)
cacheList(rds_PROVINCE_LEVEL_TOTAL_CONFIRM_KEY, areaInfoToJson(provinceLevelsSlice)...)
// 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
item.Parent = parent.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()
}