77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
|
package usecase
|
||
|
|
||
|
import (
|
||
|
"app-cloudep-member-server/internal/domain"
|
||
|
"app-cloudep-member-server/internal/domain/usecase"
|
||
|
mgo "app-cloudep-member-server/internal/model/mongo"
|
||
|
"context"
|
||
|
"math"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type GenerateUseCaseParam struct {
|
||
|
GenerateUIDRepo mgo.AutoIdModel
|
||
|
}
|
||
|
|
||
|
type GenerateUseCase struct {
|
||
|
generateUIDRepo mgo.AutoIdModel
|
||
|
}
|
||
|
|
||
|
func MustGenerateUseCase(param GenerateUseCaseParam) usecase.UIDGenerateUseCase {
|
||
|
return &GenerateUseCase{
|
||
|
generateUIDRepo: param.GenerateUIDRepo,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Generate 利用 mongo 創立全局唯一的 ark id
|
||
|
// TODO 如果之後有效能問題,扛在同一個 mongo 資料庫,在改成雪花算法
|
||
|
func (g GenerateUseCase) Generate(ctx context.Context) (string, error) {
|
||
|
var data mgo.AutoId
|
||
|
err := g.generateUIDRepo.Inc(ctx, &data)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
uid := strconv.Itoa(int(domain.InitAutoId + data.Counter))
|
||
|
code, err := generateReferralCode(uid)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
return code, nil
|
||
|
}
|
||
|
|
||
|
// generateReferralCode 從 UID 生成 referralCode
|
||
|
func generateReferralCode(uid string) (string, error) {
|
||
|
uidInt, err := strconv.ParseInt(uid, 10, 64)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
maxReferralUIDBoundary := int64(math.Pow(float64(len(domain.ConvertTable)), float64(domain.DefaultReferralCodeLen)))
|
||
|
if uidInt > maxReferralUIDBoundary {
|
||
|
return "", usecase.UIDOutOfRangeErrorCodeError("uid encode out of range")
|
||
|
}
|
||
|
|
||
|
encoded := encodeToBase(uidInt, 10, domain.DefaultReferralCodeLen)
|
||
|
|
||
|
return encoded, nil
|
||
|
}
|
||
|
|
||
|
func encodeToBase(num int64, base int, length int) string {
|
||
|
result := ""
|
||
|
for num > 0 {
|
||
|
index := num % int64(base)
|
||
|
result = domain.ConvertTable[index] + result
|
||
|
num /= int64(base)
|
||
|
}
|
||
|
|
||
|
// makes sure the length fo result feats the input length
|
||
|
if len(result) < length {
|
||
|
result = strings.Repeat(domain.ConvertTable[0], length-len(result)) + result
|
||
|
}
|
||
|
|
||
|
return result
|
||
|
}
|