| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- package model
- import (
- "errors"
- "math/rand"
- "rocommon/service"
- "rocommon/util"
- "roserver/serverproto"
- "strconv"
- "strings"
- "time"
- )
- var lastTimeStamp uint64 = 0
- var sequence = 0
- const (
- STAMP_SHIFT_BITS = 22 //时间戳左移位数
- ZONE_MASK = 32768 //2^15 15位->32767
- ZONE_MASK_MULTI = 0x7fff //15位
- SEQUENCE_MASK = 0xfff //12位
- SEQUENCE_BITS = 12 //序列号位数
- SEQUENCE_MASK_MULTI = 0xffff
- //SEQUENCE_BITS_MULTI = 16 //序列号12位
- SEQUENCE_BITS_MULTI = 20 //序列号12位
- TIMESTAMP_BITS_MULTI = 32 //时间戳占用位数
- LOGIC_BITS = 5 //logic ID 5占位
- LOGIC_MASK = 0x1f
- LOGIC_MASK64 = 0x0000000000007fff
- ZONE_MASK64_MULTI = 0x000000000000FFC0
- )
- //role uuid
- func GenerateUid() uint64 {
- serviceConfig := service.GetServiceConfig()
- zone := serviceConfig.Node.Zone
- id := serviceConfig.Node.Id
- return GUIDCreate(zone, id)
- }
- func GenerateUidByZone(zone int) uint64 {
- serviceConfig := service.GetServiceConfig()
- if zone <= 0 {
- zone = serviceConfig.Node.Zone
- }
- id := serviceConfig.Node.Id
- return GUIDCreate(zone, id)
- }
- func ParseUid(uid uint64) (zone, id int32) {
- id = int32(uid & LOGIC_MASK)
- zone = int32((uid >> LOGIC_BITS) & LOGIC_MASK64)
- return
- }
- func GUIDCreate(zone, id int) uint64 {
- currentTimeStamp := uint64(time.Now().Unix())
- if lastTimeStamp == 0 {
- lastTimeStamp = currentTimeStamp
- }
- //zone[2^12] id[2^8]
- if zone >= ZONE_MASK || id >= 256 {
- util.ErrorF("GUIDCreate zone=%v[%v] id=%v[%v] invalid", zone, ZONE_MASK, id, 256)
- return 0
- }
- if lastTimeStamp == currentTimeStamp {
- sequence++
- if sequence > SEQUENCE_MASK {
- //一秒内尝试的数量超过上限
- return 0
- }
- } else {
- lastTimeStamp = currentTimeStamp
- sequence = 1
- }
- //zone -> 2^15
- //logicid -> 2^5
- var uid uint64 = 0
- //前32位时间戳(秒)
- uid |= lastTimeStamp << TIMESTAMP_BITS_MULTI
- //12位序列号
- uid |= uint64(sequence&SEQUENCE_MASK_MULTI) << SEQUENCE_BITS_MULTI
- //15位区域id
- uid |= uint64(zone&ZONE_MASK_MULTI) << LOGIC_BITS
- //左后是逻辑ID(服务器id)
- uid |= uint64(id & LOGIC_MASK)
- return uid
- }
- func GUIDCreateTest(zone, id int) uint64 {
- currentTimeStamp := uint64(time.Now().Unix())
- if lastTimeStamp == 0 {
- lastTimeStamp = currentTimeStamp
- }
- if zone > ZONE_MASK {
- return 0
- }
- if lastTimeStamp == currentTimeStamp {
- sequence++
- if sequence > 256 {
- //一秒内尝试的数量超过上限
- return 0
- }
- } else {
- lastTimeStamp = currentTimeStamp
- sequence = 1
- }
- var uid uint64 = 0
- //前32位时间戳(秒)
- uid |= (lastTimeStamp >> 1) << 23
- //16位序列号
- uid |= uint64(sequence&SEQUENCE_MASK_MULTI) << 15
- //8位区域id
- uid |= uint64(zone&ZONE_MASK_MULTI) << 5
- //左后是逻辑ID(服务器id)
- uid |= uint64(id & LOGIC_MASK)
- return uid
- }
- //item id
- var uuidLow uint32 = 0
- var uuidHigh uint32 = 1
- func UUIDCreate() uint64 {
- if uuidLow == 0 {
- uuidLow = uint32(time.Now().Unix())
- }
- uuidHigh++
- uuid := uint64(uuidHigh)
- uuid <<= 32
- uuid += uint64(uuidLow)
- return uuid
- }
- //是否同一天(24点)
- func IsSameDay(source int64) bool {
- loc := util.GetLoc()
- nowTime := time.Unix(util.GetTimeSeconds(), 0).In(loc)
- sourceTime := time.Unix(source, 0).In(loc)
- if nowTime.YearDay() != sourceTime.YearDay() {
- return true
- }
- return false
- }
- //是否是同一天(24点)
- func IsSameDayMs(sourceMs uint64) int {
- loc := util.GetLoc()
- timeS := int64(sourceMs / 1000)
- timeMS := int64(sourceMs % 1000)
- tempTime := time.Unix(timeS, timeMS).In(loc)
- nowTime := time.Unix(util.GetTimeSeconds(), 0).In(loc)
- nt1 := nowTime.YearDay()
- nt2 := tempTime.YearDay()
- if nt1 != nt2 {
- return nt1 - nt2
- }
- return 0
- }
- //判断是否是同一天true不天, false同一天(凌晨晨5点)
- func IsDailyResetHour5(sourceMs uint64) bool {
- if sourceMs <= 0 {
- return false
- }
- tempTime := util.GetTimeByUint64(sourceMs)
- nowTime := util.GetCurrentTimeNow()
- nt1 := nowTime.YearDay()
- nt2 := tempTime.YearDay()
- deltaDay := nt1 - nt2
- if nowTime.Year() != tempTime.Year() {
- if isLeapYear(tempTime.Year()) {
- deltaDay = 366 - nt2
- } else {
- deltaDay = 365 - nt2
- }
- deltaDay += nt1
- }
- if deltaDay < 0 {
- return false
- } else if deltaDay == 0 {
- if tempTime.Hour() < 5 && nowTime.Hour() >= 5 {
- return true
- }
- } else if deltaDay == 1 {
- if tempTime.Hour() < 5 || tempTime.Hour() >= 5 && nowTime.Hour() >= 5 {
- return true
- }
- } else {
- return true
- }
- return false
- }
- func isLeapYear(year int) bool {
- if year%4 == 0 && year%100 != 0 || year%400 == 0 {
- return true
- }
- return false
- }
- func Str2Num(str string) (int, error) {
- if str == "" {
- return 0, nil
- }
- str = strings.Replace(str, "\u00A0", "", -1)
- str = strings.Replace(str, "\u0020", "", -1)
- str = strings.Replace(str, "\u0009", "", -1)
- num, e := strconv.ParseInt(str, 10, 32)
- if e != nil {
- return 0, errors.New("service invalid num convert error:" + str)
- } else {
- return int(num), nil
- }
- }
- func Str2NumU64(str string) (uint64, error) {
- str = strings.Replace(str, "\u00A0", "", -1)
- str = strings.Replace(str, "\u0020", "", -1)
- num, e := strconv.ParseUint(str, 10, 64)
- if e != nil {
- return 0, errors.New("service invalid num convert error:" + str)
- } else {
- return num, nil
- }
- }
- func Str2Float32(str string) (float32, error) {
- str = strings.Replace(str, "\u00A0", "", -1)
- str = strings.Replace(str, "\u0020", "", -1)
- num, e := strconv.ParseFloat(str, 32)
- if e != nil {
- return 0, errors.New("service invalid num convert error:" + str)
- } else {
- return float32(num), nil
- }
- }
- func Str2Float32_2(str string) (float32, float32) {
- resList := strings.Split(str, ":")
- if len(resList) > 1 {
- resType, _ := Str2Float32(resList[0])
- resValue, _ := Str2Float32(resList[1])
- return resType, resValue
- }
- return 0, 0
- }
- func Str2Res(str string) (int32, int32) {
- resList := strings.Split(str, ":")
- if len(resList) > 1 {
- resType, _ := Str2Num(resList[0])
- resValue, _ := Str2Num(resList[1])
- return int32(resType), int32(resValue)
- }
- return 0, 0
- }
- func Str2ResBySep(str string, sep string) (int32, int32) {
- resList := strings.Split(str, sep)
- if len(resList) > 1 {
- resType, _ := Str2Num(resList[0])
- resValue, _ := Str2Num(resList[1])
- return int32(resType), int32(resValue)
- }
- return 0, 0
- }
- func Str2Res_3(str string) (int32, int32, int32) {
- resList := strings.Split(str, ":")
- if len(resList) >= 3 {
- value1, _ := Str2Num(resList[0])
- value2, _ := Str2Num(resList[1])
- value3, _ := Str2Num(resList[2])
- return int32(value1), int32(value2), int32(value3)
- }
- return 0, 0, 0
- }
- func Str2Res_4(str string) (int32, int32, int32, int32) {
- resList := strings.Split(str, ":")
- if len(resList) >= 4 {
- value1, _ := Str2Num(resList[0])
- value2, _ := Str2Num(resList[1])
- value3, _ := Str2Num(resList[2])
- value4, _ := Str2Num(resList[3])
- return int32(value1), int32(value2), int32(value3), int32(value4)
- }
- return 0, 0, 0, 0
- }
- func Str2Res_5(str string) (int32, int32, int32, int32, int32) {
- resList := strings.Split(str, ":")
- if len(resList) >= 5 {
- value1, _ := Str2Num(resList[0])
- value2, _ := Str2Num(resList[1])
- value3, _ := Str2Num(resList[2])
- value4, _ := Str2Num(resList[3])
- value5, _ := Str2Num(resList[4])
- return int32(value1), int32(value2), int32(value3), int32(value4), int32(value5)
- }
- return 0, 0, 0, 0, 0
- }
- //最小堆
- type MinHeap struct {
- ItemList []int32
- }
- func (h *MinHeap) Len() int {
- return len(h.ItemList)
- }
- func (h *MinHeap) Less(i, j int) bool {
- return h.ItemList[i] < h.ItemList[j]
- }
- func (h *MinHeap) Swap(i, j int) {
- h.ItemList[i], h.ItemList[j] = h.ItemList[j], h.ItemList[i]
- }
- func (h *MinHeap) Push(item interface{}) {
- h.ItemList = append(h.ItemList, item.(int32))
- }
- func (h *MinHeap) Pop() (ret interface{}) {
- l := len(h.ItemList)
- h.ItemList, ret = h.ItemList[:l-1], h.ItemList[l-1]
- return
- }
- //随机打乱数组Fisher-Yates随机置乱算法
- func GenRandomArray(selfArray []int32) []int32 {
- if len(selfArray) <= 0 {
- return nil
- }
- rand.Seed(time.Now().UnixNano())
- for i := len(selfArray) - 1; i > 0; i-- {
- randNum := rand.Intn(i + 1)
- selfArray[i], selfArray[randNum] = selfArray[randNum], selfArray[i]
- }
- return selfArray
- }
- func GenRandomArrayByLen(numLen int) []int32 {
- if numLen <= 0 {
- return nil
- }
- rand.Seed(time.Now().UnixNano())
- var selfArray []int32
- for idx := 0; idx < numLen; idx++ {
- selfArray = append(selfArray, int32(idx+1))
- }
- for i := len(selfArray) - 1; i > 0; i-- {
- randNum := rand.Intn(i + 1)
- selfArray[i], selfArray[randNum] = selfArray[randNum], selfArray[i]
- }
- return selfArray
- }
- //字符串相似度算法
- func MessageLD(s, t string, ignoreCase bool) int {
- if ignoreCase {
- s = strings.ToLower(s)
- t = strings.ToLower(t)
- }
- d := make([][]int, len(s)+1)
- for i := range d {
- d[i] = make([]int, len(t)+1)
- }
- for i := range d {
- d[i][0] = i
- }
- for j := range d[0] {
- d[0][j] = j
- }
- for j := 1; j <= len(t); j++ {
- for i := 1; i <= len(s); i++ {
- if s[i-1] == t[j-1] {
- d[i][j] = d[i-1][j-1]
- } else {
- min := d[i-1][j]
- if d[i][j-1] < min {
- min = d[i][j-1]
- }
- if d[i-1][j-1] < min {
- min = d[i-1][j-1]
- }
- d[i][j] = min + 1
- }
- }
- }
- return d[len(s)][len(t)]
- }
- //二倍均值算法,count剩余个数,amount剩余金额
- func DoubleAverage(count, amount int64) int64 {
- //最小钱
- min := int64(1)
- if count <= 0 {
- count = 1
- }
- if count == 1 {
- //返回剩余金额
- return amount
- }
- //计算最大可用金额,min最小是1分钱,减去的min,下面会加上,避免出现0分钱
- max := amount - min*count
- if max < 0 {
- return 0
- }
- //计算最大可用平均值
- avg := max / count
- //二倍均值基础加上最小金额,防止0出现,作为上限
- avg2 := 2*avg + min
- //随机红包金额序列元素,把二倍均值作为随机的最大数
- //rand.Seed(time.Now().UnixNano())
- //加min是为了避免出现0值,上面也减去了min
- x := rand.Int63n(avg2) + min
- return x
- }
- /*
- 使用说明
- rand.Seed(time.Now().UnixNano())
- var sumAmount int64 = 0
- var remainAmount int64 = 2
- rewardNum := 10
- for idx := 0; idx < rewardNum; idx++ {
- delAmount := DoubleAverage(int64(rewardNum-idx), int64(remainAmount))
- remainAmount -= delAmount
- sumAmount += delAmount
- log.Printf("delAmount=%v", delAmount)
- }
- log.Printf("sumAmount=%v", sumAmount)
- */
- func Str2ResMapList(strList []string, resList map[int32]int32) {
- for _, str := range strList {
- k, v := Str2Res(str)
- if k <= 0 || v <= 0 {
- continue
- }
- resList[k] += v
- }
- }
- func Str2ResSliceList(strList []string) []*serverproto.KeyValueType {
- var outList []*serverproto.KeyValueType
- for _, str := range strList {
- k, v := Str2Res(str)
- if k <= 0 || v <= 0 {
- continue
- }
- outList = append(outList, &serverproto.KeyValueType{
- Key: k,
- Value: v,
- })
- }
- return outList
- }
|