Fix login bonus
Build and Push Docker images to Docker Hub / build-and-push (push) Has been cancelled

This commit is contained in:
Ilya Groshev
2026-05-06 10:16:03 +03:00
parent 5645740099
commit 60e0402525
4 changed files with 4627 additions and 38 deletions
+7 -13
View File
@@ -42,34 +42,30 @@ func main() {
userStore := sqlite.New(db, nil)
authdb, err := database.Open(*authdbPath)
authDb, err := database.Open(*authdbPath)
if err != nil {
log.Fatalf("open auth database: %v", err)
}
defer db.Close()
defer authDb.Close()
authStore, err := auth.NewAuthStore(authdb)
authStore, err := auth.NewAuthStore(authDb)
if err != nil {
log.Fatalf("init auth store: %v", err)
}
// Auth user check
userExists := authStore.UserExists(*name)
if userExists {
log.Fatal("Username is already taken")
}
// lunar-tear user
var userPlatform model.ClientPlatform
if *platform == "android" {
userPlatform.OsType = 2
userPlatform.PlatformType = 2
userPlatform.OsType = model.OsTypeAndroid
userPlatform.PlatformType = model.PlatformTypeGooglePlayStore
} else {
userPlatform.OsType = 1
userPlatform.PlatformType = 1
userPlatform.OsType = model.OsTypeIOS
userPlatform.PlatformType = model.PlatformTypeAppStore
}
userUuid := uuid.New().String()
@@ -81,8 +77,6 @@ func main() {
log.Fatalf("Register user in database: %v", err)
}
// Bind
authUser, err := authStore.CreateUser(*name, *password)
if err != nil {
log.Fatalf("Register auth account: %v", err)
File diff suppressed because it is too large Load Diff
+49 -4
View File
@@ -2,6 +2,8 @@ package masterdata
import (
"log"
"sort"
"lunar-tear/server/internal/utils"
)
@@ -18,29 +20,72 @@ type LoginBonusReward struct {
}
type LoginBonusCatalog struct {
stamps map[loginBonusStampKey]LoginBonusReward
stamps map[loginBonusStampKey]LoginBonusReward
bonusPages map[int32][]int32
totalPages map[int32]int32
}
func (c *LoginBonusCatalog) LookupStampReward(loginBonusId, pageNumber, stampNumber int32) (LoginBonusReward, bool) {
entry, ok := c.stamps[loginBonusStampKey{loginBonusId, pageNumber, stampNumber}]
pages := c.bonusPages[loginBonusId]
lower := int32(-1)
for _, p := range pages {
if p <= pageNumber {
lower = p
} else {
break
}
}
if lower < 0 {
return LoginBonusReward{}, false
}
entry, ok := c.stamps[loginBonusStampKey{loginBonusId, lower, stampNumber}]
return entry, ok
}
func (c *LoginBonusCatalog) TotalPageCount(loginBonusId int32) int32 {
return c.totalPages[loginBonusId]
}
func LoadLoginBonusCatalog() *LoginBonusCatalog {
stamps, err := utils.ReadTable[EntityMLoginBonusStamp]("m_login_bonus_stamp")
if err != nil {
log.Fatalf("load login bonus stamp table: %v", err)
}
cat := &LoginBonusCatalog{
stamps: make(map[loginBonusStampKey]LoginBonusReward, len(stamps)),
bonuses, err := utils.ReadTable[EntityMLoginBonus]("m_login_bonus")
if err != nil {
log.Fatalf("load login bonus table: %v", err)
}
cat := &LoginBonusCatalog{
stamps: make(map[loginBonusStampKey]LoginBonusReward, len(stamps)),
bonusPages: make(map[int32][]int32),
totalPages: make(map[int32]int32, len(bonuses)),
}
for _, b := range bonuses {
cat.totalPages[b.LoginBonusId] = b.TotalPageCount
}
seenPages := make(map[loginBonusStampKey]struct{})
for _, s := range stamps {
cat.stamps[loginBonusStampKey{s.LoginBonusId, s.LowerPageNumber, s.StampNumber}] = LoginBonusReward{
PossessionType: s.RewardPossessionType,
PossessionId: s.RewardPossessionId,
Count: s.RewardCount,
}
dedup := loginBonusStampKey{LoginBonusId: s.LoginBonusId, LowerPageNumber: s.LowerPageNumber}
if _, exists := seenPages[dedup]; !exists {
seenPages[dedup] = struct{}{}
cat.bonusPages[s.LoginBonusId] = append(cat.bonusPages[s.LoginBonusId], s.LowerPageNumber)
}
}
for id := range cat.bonusPages {
sort.Slice(cat.bonusPages[id], func(i, j int) bool {
return cat.bonusPages[id][i] < cat.bonusPages[id][j]
})
}
return cat
}
+57 -21
View File
@@ -2,13 +2,17 @@ package service
import (
"context"
"fmt"
"log"
"time"
"github.com/google/uuid"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "lunar-tear/server/gen/proto"
"lunar-tear/server/internal/gametime"
"lunar-tear/server/internal/masterdata"
"lunar-tear/server/internal/runtime"
"lunar-tear/server/internal/store"
@@ -31,24 +35,25 @@ func (s *LoginBonusServiceServer) ReceiveStamp(ctx context.Context, req *emptypb
userId := CurrentUserId(ctx, s.users, s.sessions)
catalog := s.holder.Get().LoginBonus
s.users.UpdateUser(userId, func(user *store.UserState) {
user, err := s.users.LoadUser(userId)
if err != nil {
return nil, fmt.Errorf("load user: %w", err)
}
nextPage, nextStamp, reward, err := resolveNextStamp(catalog, user.LoginBonus)
if err != nil {
return nil, err
}
log.Printf("[LoginBonusService] bonusId=%d page %d->%d stamp %d->%d possType=%d possId=%d count=%d (-> gift box)",
user.LoginBonus.LoginBonusId,
user.LoginBonus.CurrentPageNumber, nextPage,
user.LoginBonus.CurrentStampNumber, nextStamp,
reward.PossessionType, reward.PossessionId, reward.Count)
s.users.UpdateUser(userId, func(u *store.UserState) {
now := gametime.NowMillis()
nextStamp := user.LoginBonus.CurrentStampNumber + 1
reward, ok := catalog.LookupStampReward(
user.LoginBonus.LoginBonusId,
user.LoginBonus.CurrentPageNumber,
nextStamp,
)
if !ok {
log.Fatalf("[LoginBonusService] no reward found for bonusId=%d page=%d stamp=%d",
user.LoginBonus.LoginBonusId, user.LoginBonus.CurrentPageNumber, nextStamp)
}
log.Printf("[LoginBonusService] stamp %d -> possType=%d possId=%d count=%d (-> gift box)",
nextStamp, reward.PossessionType, reward.PossessionId, reward.Count)
user.Gifts.NotReceived = append(user.Gifts.NotReceived, store.NotReceivedGiftState{
u.Gifts.NotReceived = append(u.Gifts.NotReceived, store.NotReceivedGiftState{
GiftCommon: store.GiftCommonState{
PossessionType: reward.PossessionType,
PossessionId: reward.PossessionId,
@@ -58,11 +63,42 @@ func (s *LoginBonusServiceServer) ReceiveStamp(ctx context.Context, req *emptypb
ExpirationDatetime: now + int64(30*24*time.Hour/time.Millisecond),
UserGiftUuid: uuid.New().String(),
})
user.Notifications.GiftNotReceiveCount = int32(len(user.Gifts.NotReceived))
user.LoginBonus.CurrentStampNumber = nextStamp
user.LoginBonus.LatestRewardReceiveDatetime = now
user.LoginBonus.LatestVersion = now
u.Notifications.GiftNotReceiveCount = int32(len(u.Gifts.NotReceived))
u.LoginBonus.CurrentPageNumber = nextPage
u.LoginBonus.CurrentStampNumber = nextStamp
u.LoginBonus.LatestRewardReceiveDatetime = now
u.LoginBonus.LatestVersion = now
})
return &pb.ReceiveStampResponse{}, nil
}
func resolveNextStamp(catalog *masterdata.LoginBonusCatalog, lb store.UserLoginBonusState) (nextPage, nextStamp int32, reward masterdata.LoginBonusReward, err error) {
bonusId := lb.LoginBonusId
curPage := lb.CurrentPageNumber
curStamp := lb.CurrentStampNumber
nextPage = curPage
nextStamp = curStamp + 1
var ok bool
reward, ok = catalog.LookupStampReward(bonusId, nextPage, nextStamp)
if !ok {
nextPage = curPage + 1
nextStamp = 1
total := catalog.TotalPageCount(bonusId)
if total > 0 && nextPage > total {
err = status.Errorf(codes.FailedPrecondition,
"login bonus %d exhausted (page %d stamp %d is the last)",
bonusId, curPage, curStamp)
return
}
reward, ok = catalog.LookupStampReward(bonusId, nextPage, nextStamp)
if !ok {
err = status.Errorf(codes.FailedPrecondition,
"no reward found for login bonus %d page %d stamp %d",
bonusId, nextPage, nextStamp)
return
}
}
return
}