hashgen.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package hashgen
  2. import (
  3. "encoding/hex"
  4. "errors"
  5. "fmt"
  6. "sync"
  7. "time"
  8. "github.com/patrickmn/go-cache"
  9. "github.com/sirupsen/logrus"
  10. "gogs.daxia.dev/huanan/pkg.daxia.dev/encrypt"
  11. "gogs.daxia.dev/huanan/pkg.daxia.dev/time_utils"
  12. )
  13. var openNumberCache *cache.Cache
  14. var openNumberCacheLocker = sync.Mutex{}
  15. type HashItem []byte
  16. const HashCount = 100000
  17. func Init() {
  18. for {
  19. //同步今天,和明天
  20. timeNow := time.Now()
  21. today := time_utils.GetFormatTime(timeNow)
  22. yesterday := time_utils.GetFormatTime(timeNow.Add(time.Hour * -24))
  23. cacheHash(today)
  24. cacheHash(yesterday)
  25. <-time.After(15 * time.Minute)
  26. }
  27. }
  28. func cacheHash(dayStr string) {
  29. cache := getCacheInstance()
  30. key := "on_" + dayStr
  31. _, exists := cache.Get(key)
  32. if exists {
  33. return
  34. }
  35. openNumberModelInterface := genOpenNumberHashItem(dayStr)
  36. logrus.Infof("cache hash:%s-%v", dayStr, len(openNumberModelInterface))
  37. cache.Set(key, openNumberModelInterface, 48*time.Hour)
  38. }
  39. func GetOpenNumber(dayStr string, roomID int32, clientHash []byte, index int32) ([]string, string, error) {
  40. cache := getCacheInstance()
  41. key := "on_" + dayStr
  42. openNumberModelInterface, exists := cache.Get(key)
  43. if !exists {
  44. return nil, "", errors.New("not exists:" + key)
  45. }
  46. hashItemList := openNumberModelInterface.([]HashItem)
  47. serverHash := hashItemList[HashCount-index-1] //index从0开始,用最后一期,表示第一期
  48. openNumList, _ := GetRoomOpenNumber(int(roomID), serverHash, clientHash)
  49. return openNumList, hex.EncodeToString(serverHash), nil
  50. }
  51. func getCacheInstance() *cache.Cache {
  52. openNumberCacheLocker.Lock()
  53. defer openNumberCacheLocker.Unlock()
  54. if openNumberCache != nil {
  55. return openNumberCache
  56. }
  57. openNumberCache = cache.New(48*time.Hour, 2*48*time.Hour)
  58. openNumberCache.OnEvicted(func(name string, val interface{}) {
  59. //
  60. })
  61. return openNumberCache
  62. }
  63. func genOpenNumberHashItem(day string) []HashItem {
  64. seed := encrypt.KeyDataSHA256([]byte("D40163E6E6E35A2204059B0F1121D2DF" + day))
  65. hashList := make([]HashItem, HashCount)
  66. hashA := seed
  67. for i := 0; i < HashCount; i++ {
  68. hashItem := encrypt.KeyDataSHA256(hashA)
  69. hashA = hashItem
  70. hashList[i] = hashItem
  71. }
  72. return hashList
  73. }
  74. func GetRoomOpenNumber(roomID int, hashItem, clientHash []byte) ([]string, string) {
  75. resultStrList := make([]string, 5)
  76. roomHashItem := getRoomHash(hashItem, roomID)
  77. hashItem = encrypt.KeyDataSHA256(append(roomHashItem, clientHash...))
  78. cardList := calNum(hashItem)
  79. resultStrList[0] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[0], cardList[5], cardList[10], cardList[15], cardList[20])
  80. resultStrList[1] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[1], cardList[6], cardList[11], cardList[16], cardList[21])
  81. resultStrList[2] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[2], cardList[7], cardList[12], cardList[17], cardList[22])
  82. resultStrList[3] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[3], cardList[8], cardList[13], cardList[18], cardList[23])
  83. resultStrList[4] = fmt.Sprintf("%s,%s,%s,%s,%s", cardList[4], cardList[9], cardList[14], cardList[19], cardList[24])
  84. return resultStrList, hex.EncodeToString(hashItem)
  85. }
  86. func getRoomHash(hashItem []byte, roomID int) []byte {
  87. roomHash := encrypt.GetMD5HashString(fmt.Sprintf("room_hash_%d", roomID))
  88. roomHashHex, _ := hex.DecodeString(roomHash)
  89. hashItem = encrypt.KeyDataSHA256(append(hashItem, roomHashHex...))
  90. return hashItem
  91. }
  92. func calNum(hashData []byte) []string {
  93. resultStrList := make([]string, 25)
  94. filterMap := map[string]bool{}
  95. offset := 0
  96. for i := 0; i < 25; i++ {
  97. item := fmt.Sprintf("%d", (int(hashData[i])+offset)%52) //生成[0-51]
  98. _, exists := filterMap[item]
  99. if exists {
  100. offset++
  101. i--
  102. continue
  103. }
  104. resultStrList[i] = item
  105. filterMap[item] = true
  106. offset = 0
  107. }
  108. return resultStrList
  109. }