Files
lunar-tear/server/internal/service/loginbonus.go
T
Ilya Groshev 60e0402525
Build and Push Docker images to Docker Hub / build-and-push (push) Has been cancelled
Fix login bonus
2026-05-06 10:16:03 +03:00

105 lines
3.2 KiB
Go

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"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
type LoginBonusServiceServer struct {
pb.UnimplementedLoginBonusServiceServer
users store.UserRepository
sessions store.SessionRepository
holder *runtime.Holder
}
func NewLoginBonusServiceServer(users store.UserRepository, sessions store.SessionRepository, holder *runtime.Holder) *LoginBonusServiceServer {
return &LoginBonusServiceServer{users: users, sessions: sessions, holder: holder}
}
func (s *LoginBonusServiceServer) ReceiveStamp(ctx context.Context, req *emptypb.Empty) (*pb.ReceiveStampResponse, error) {
log.Printf("[LoginBonusService] ReceiveStamp")
userId := CurrentUserId(ctx, s.users, s.sessions)
catalog := s.holder.Get().LoginBonus
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()
u.Gifts.NotReceived = append(u.Gifts.NotReceived, store.NotReceivedGiftState{
GiftCommon: store.GiftCommonState{
PossessionType: reward.PossessionType,
PossessionId: reward.PossessionId,
Count: reward.Count,
GrantDatetime: now,
},
ExpirationDatetime: now + int64(30*24*time.Hour/time.Millisecond),
UserGiftUuid: uuid.New().String(),
})
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
}