mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 15:43:49 +01:00
The tower repo had business logic beyond simple CRUD: AddGem used a fetch-transform-save pattern, progress capping was inline in the handler, and RP donation orchestrated multiple repo calls with conditional page advancement. Move these into a new TowerService following the established service layer pattern.
103 lines
2.9 KiB
Go
103 lines
2.9 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"erupe-ce/common/stringsupport"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// DonateRPResult holds the outcome of a guild tower RP donation.
|
|
type DonateRPResult struct {
|
|
ActualDonated uint16
|
|
Advanced bool
|
|
}
|
|
|
|
// TowerService encapsulates tower business logic, sitting between handlers and repos.
|
|
type TowerService struct {
|
|
towerRepo TowerRepo
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewTowerService creates a new TowerService.
|
|
func NewTowerService(tr TowerRepo, log *zap.Logger) *TowerService {
|
|
return &TowerService{
|
|
towerRepo: tr,
|
|
logger: log,
|
|
}
|
|
}
|
|
|
|
// AddGem adds quantity to a specific gem index for a character.
|
|
// This is a fetch-transform-save operation that reads the current gems CSV,
|
|
// updates the value at the given index, and writes back.
|
|
func (svc *TowerService) AddGem(charID uint32, gemIndex int, quantity int) error {
|
|
gems, err := svc.towerRepo.GetGems(charID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
newGems := stringsupport.CSVSetIndex(gems, gemIndex, stringsupport.CSVGetIndex(gems, gemIndex)+quantity)
|
|
return svc.towerRepo.UpdateGems(charID, newGems)
|
|
}
|
|
|
|
// GetTenrouiraiProgressCapped returns the guild's tenrouirai progress with
|
|
// mission scores capped to their respective goals.
|
|
func (svc *TowerService) GetTenrouiraiProgressCapped(guildID uint32) (TenrouiraiProgressData, error) {
|
|
progress, err := svc.towerRepo.GetTenrouiraiProgress(guildID)
|
|
if err != nil {
|
|
return progress, err
|
|
}
|
|
|
|
if progress.Page < 1 {
|
|
progress.Page = 1
|
|
}
|
|
|
|
idx := int(progress.Page*3) - 3
|
|
if idx >= 0 && idx+2 < len(tenrouiraiData) {
|
|
if progress.Mission1 > tenrouiraiData[idx].Goal {
|
|
progress.Mission1 = tenrouiraiData[idx].Goal
|
|
}
|
|
if progress.Mission2 > tenrouiraiData[idx+1].Goal {
|
|
progress.Mission2 = tenrouiraiData[idx+1].Goal
|
|
}
|
|
if progress.Mission3 > tenrouiraiData[idx+2].Goal {
|
|
progress.Mission3 = tenrouiraiData[idx+2].Goal
|
|
}
|
|
}
|
|
|
|
return progress, nil
|
|
}
|
|
|
|
// DonateGuildTowerRP processes a tower RP donation, advancing the mission page
|
|
// if the cumulative donation meets the requirement. Returns the actual RP consumed
|
|
// and whether the page was advanced.
|
|
func (svc *TowerService) DonateGuildTowerRP(guildID uint32, donatedRP uint16) (*DonateRPResult, error) {
|
|
page, donated, err := svc.towerRepo.GetGuildTowerPageAndRP(guildID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var requirement int
|
|
for i := 0; i < (page*3)+1 && i < len(tenrouiraiData); i++ {
|
|
requirement += int(tenrouiraiData[i].Cost)
|
|
}
|
|
|
|
result := &DonateRPResult{
|
|
ActualDonated: donatedRP,
|
|
}
|
|
|
|
if donated+int(donatedRP) >= requirement {
|
|
if err := svc.towerRepo.AdvanceTenrouiraiPage(guildID); err != nil {
|
|
svc.logger.Error("Failed to advance tower mission page", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
result.ActualDonated = uint16(requirement - donated)
|
|
result.Advanced = true
|
|
}
|
|
|
|
if err := svc.towerRepo.DonateGuildTowerRP(guildID, result.ActualDonated); err != nil {
|
|
svc.logger.Error("Failed to update guild tower RP", zap.Error(err))
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|