feat: statistics: finish dev
This commit is contained in:
184
service/statistics/cache.go
Normal file
184
service/statistics/cache.go
Normal 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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user