81 lines
1.6 KiB
Go
81 lines
1.6 KiB
Go
package invited_code
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
)
|
|
|
|
type Converter struct {
|
|
Base int
|
|
Length int
|
|
ConvertTable []string
|
|
}
|
|
|
|
func (c *Converter) EncodeFromNum(id int64) (string, error) {
|
|
code, err := generateCode(id, c.Base, c.Length, c.ConvertTable)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return code, nil
|
|
}
|
|
|
|
func (c *Converter) DecodeFromCode(code string) (int64, error) {
|
|
var result int64 = 0
|
|
length := len(code)
|
|
|
|
for i := 0; i < length; i++ {
|
|
char := string(code[i])
|
|
index := -1
|
|
for j, v := range c.ConvertTable {
|
|
if v == char {
|
|
index = j
|
|
break
|
|
}
|
|
}
|
|
|
|
if index >= 0 {
|
|
result = result*int64(c.Base) + int64(index)
|
|
} else {
|
|
return 0, fmt.Errorf("character not found in convert table")
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// generateCode 從 UID 生成 referralCode
|
|
func generateCode(id int64, base int, length int, convertTable []string) (string, error) {
|
|
maxReferralUIDBoundary := int64(math.Pow(float64(len(ConvertTable)), float64(DefaultCodeLen)))
|
|
if id > maxReferralUIDBoundary {
|
|
return "", fmt.Errorf("encode out of range")
|
|
}
|
|
|
|
encoded := encodeToBase(id, base, length, convertTable)
|
|
|
|
return encoded, nil
|
|
}
|
|
|
|
func encodeToBase(num int64, base int, length int, convertTable []string) string {
|
|
result := ""
|
|
for num > 0 {
|
|
index := num % int64(base)
|
|
result = convertTable[index] + result
|
|
num /= int64(base)
|
|
}
|
|
|
|
if len(result) < length {
|
|
result = strings.Repeat(convertTable[0], length-len(result)) + result
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func MustConverter(base int, length int, convertTable []string) ConvertUseCase {
|
|
return &Converter{
|
|
Base: base,
|
|
Length: length,
|
|
ConvertTable: convertTable,
|
|
}
|
|
}
|