123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- package otherutils
- import (
- "bytes"
- "fmt"
- "math/rand"
- "strings"
- "sync/atomic"
- "time"
- )
- const (
- charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
- maxBase = 62
- defaultBase = 61
- maxOrderNum = 65536
- )
- var orderIncrId uint32 // 订单自增ID,每次重启从头开始即可
- // ConvertToBaseN converts a decimal number to a string representation in the specified base (2-62)
- func ConvertToBaseN(decimalNum int64, base int64) (string, error) {
- if base <= 0 || base > maxBase {
- return "", fmt.Errorf("base must be between 1 and %d", maxBase)
- }
- if decimalNum == 0 {
- return "0", nil
- }
- if decimalNum < 0 {
- return "", fmt.Errorf("negative numbers are not supported")
- }
- var buf bytes.Buffer
- for decimalNum > 0 {
- remainder := decimalNum % base
- decimalNum /= base
- buf.WriteByte(charset[remainder])
- }
- // Reverse the result
- result := buf.Bytes()
- for i, j := 0, len(result)-1; i < j; i, j = i+1, j-1 {
- result[i], result[j] = result[j], result[i]
- }
- return string(result), nil
- }
- // ConvertToDecimal converts a string in the specified base (2-62) to decimal
- func ConvertToDecimal(str string, base int64) (int64, error) {
- if base <= 0 || base > maxBase {
- return 0, fmt.Errorf("base must be between 1 and %d", maxBase)
- }
- if str == "" {
- return 0, fmt.Errorf("empty string is not valid")
- }
- var result int64
- for i, char := range str {
- index := strings.IndexRune(charset, char)
- if index == -1 || index >= int(base) {
- return 0, fmt.Errorf("invalid character '%c' for base %d", char, base)
- }
- // Use multiplication instead of math.Pow to avoid floating point precision issues
- power := len(str) - i - 1
- multiplier := int64(1)
- for j := 0; j < power; j++ {
- multiplier *= base
- }
- result += int64(index) * multiplier
- }
- return result, nil
- }
- // formatDateTime returns a compact string representation of the current time
- func formatDateTime(t time.Time) int64 {
- y, m, d := t.Date()
- h, mi, s := t.Hour(), t.Minute(), t.Second()
- return int64(y)*1e10 + int64(m)*1e8 + int64(d)*1e6 + int64(h)*1e4 + int64(mi)*1e2 + int64(s)
- }
- // CreateOutTradeNo generates a unique trade number
- func CreateOutTradeNo(playerId int64, serverId int64, zoneId int) string {
- n := atomic.AddUint32(&orderIncrId, 1) % maxOrderNum
- num := formatDateTime(time.Now())
- baseN, _ := ConvertToBaseN(num, defaultBase)
- serverIdStr, _ := ConvertToBaseN(serverId, defaultBase)
- playerIdStr, _ := ConvertToBaseN(playerId, defaultBase)
- orderStr, _ := ConvertToBaseN(int64(n), defaultBase)
- return fmt.Sprintf("%sZ%sZ%sZ%sZ%d",
- baseN, serverIdStr, playerIdStr, orderStr, zoneId)
- }
- func TestCreateOutTradeNo() {
- var (
- playerId = 1
- serverId = 102
- zoneId = 1
- )
- for i := 0; i < 10000; i += 1 {
- playerId += 10000000
- orderCode := CreateOutTradeNo(int64(playerId), int64(serverId), zoneId)
- fmt.Println(orderCode)
- }
- }
- // 随机不含重复字符的字符串
- // l长度 超过20需修改逻辑 命中会降低
- func RandString(l int) string {
- cl := len(charset)
- if l > cl || l <= 0 {
- return ""
- }
- bytes := make([]byte, l)
- selected := make(map[byte]bool)
- for i := 0; i < l; {
- b := rand.Intn(cl)
- char := charset[b]
- if !selected[char] {
- bytes[i] = char
- selected[char] = true
- i++
- }
- }
- return string(bytes)
- }
|