package hashgen import ( "encoding/hex" "errors" "fmt" "sync" "time" "github.com/patrickmn/go-cache" "github.com/sirupsen/logrus" "gogs.daxia.dev/huanan/pkg.daxia.dev/encrypt" "gogs.daxia.dev/huanan/pkg.daxia.dev/time_utils" ) var openNumberCache *cache.Cache var openNumberCacheLocker = sync.Mutex{} type HashItem []byte const HashCount = 100000 func Init() { for { //同步今天,和明天 timeNow := time.Now() today := time_utils.GetFormatTime(timeNow) yesterday := time_utils.GetFormatTime(timeNow.Add(time.Hour * -24)) cacheHash(today) cacheHash(yesterday) <-time.After(15 * time.Minute) } } func cacheHash(dayStr string) { cache := getCacheInstance() key := "on_" + dayStr _, exists := cache.Get(key) if exists { return } openNumberModelInterface := genOpenNumberHashItem(dayStr) logrus.Infof("cache hash:%s-%v", dayStr, len(openNumberModelInterface)) cache.Set(key, openNumberModelInterface, 48*time.Hour) } func GetOpenNumber(dayStr string, roomID int32, clientHash []byte, index int32) ([]string, string, error) { cache := getCacheInstance() key := "on_" + dayStr openNumberModelInterface, exists := cache.Get(key) if !exists { return nil, "", errors.New("not exists:" + key) } hashItemList := openNumberModelInterface.([]HashItem) serverHash := hashItemList[HashCount-index-1] //index从0开始,用最后一期,表示第一期 openNumList, _ := GetRoomOpenNumber(int(roomID), serverHash, clientHash) return openNumList, hex.EncodeToString(serverHash), nil } func getCacheInstance() *cache.Cache { openNumberCacheLocker.Lock() defer openNumberCacheLocker.Unlock() if openNumberCache != nil { return openNumberCache } openNumberCache = cache.New(48*time.Hour, 2*48*time.Hour) openNumberCache.OnEvicted(func(name string, val interface{}) { // }) return openNumberCache } func genOpenNumberHashItem(day string) []HashItem { seed := encrypt.KeyDataSHA256([]byte("D40163E6E6E35A2204059B0F1121D2DF" + day)) hashList := make([]HashItem, HashCount) hashA := seed for i := 0; i < HashCount; i++ { hashItem := encrypt.KeyDataSHA256(hashA) hashA = hashItem hashList[i] = hashItem } return hashList } func GetRoomOpenNumber(roomID int, hashItem, clientHash []byte) ([]string, string) { resultStrList := make([]string, 5) roomHashItem := getRoomHash(hashItem, roomID) hashItem = encrypt.KeyDataSHA256(append(roomHashItem, clientHash...)) cardList := calNum(hashItem) resultStrList[0] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[0], cardList[5], cardList[10], cardList[15], cardList[20]) resultStrList[1] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[1], cardList[6], cardList[11], cardList[16], cardList[21]) resultStrList[2] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[2], cardList[7], cardList[12], cardList[17], cardList[22]) resultStrList[3] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[3], cardList[8], cardList[13], cardList[18], cardList[23]) resultStrList[4] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[4], cardList[9], cardList[14], cardList[19], cardList[24]) return resultStrList, hex.EncodeToString(hashItem) } func getRoomHash(hashItem []byte, roomID int) []byte { roomHash := encrypt.GetMD5HashString(fmt.Sprintf("room_hash_%d", roomID)) hashItem = encrypt.KeyDataSHA256(append(hashItem, roomHash...)) return hashItem } func calNum(hashData []byte) []string { resultStrList := make([]string, 25) filterMap := map[string]bool{} offset := 0 for i := 0; i < 25; i++ { item := fmt.Sprintf("%d", (int(hashData[i])+offset)%52) //生成[0-51] _, exists := filterMap[item] if exists { offset++ i-- continue } resultStrList[i] = item filterMap[item] = true offset = 0 } return resultStrList }