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 }