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() }