107 lines
3.0 KiB
Go
107 lines
3.0 KiB
Go
package progress
|
|
|
|
import (
|
|
"bd2server/internal/server/stateio"
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func fieldRewardKey(pack, id int) string {
|
|
return fmt.Sprintf("%d:%d", pack, id)
|
|
}
|
|
|
|
// FieldRewardOpened reads persisted entries on every call; request rollback
|
|
// therefore does not leave an opened-object cache behind.
|
|
func (s *Store) FieldRewardOpened(pack, id int, period string) (bool, error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
store, err := s.fieldRewardEntries()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
raw, found, err := store.LoadEntry("progress", "field_rewards", fieldRewardKey(pack, id))
|
|
return found && string(raw) == period, err
|
|
}
|
|
func (s *Store) fieldRewardEntries() (stateio.EntryStore, error) {
|
|
if s.storage == nil {
|
|
s.storage = stateio.NewMemory()
|
|
}
|
|
store, ok := s.storage.(stateio.EntryStore)
|
|
if !ok {
|
|
return nil, fmt.Errorf("progress: field rewards require entry storage")
|
|
}
|
|
return store, nil
|
|
}
|
|
func (s *Store) MarkFieldRewardOpened(pack, id int, period string) error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
if pack <= 0 || id <= 0 {
|
|
return fmt.Errorf("progress: invalid field reward identity")
|
|
}
|
|
store, err := s.fieldRewardEntries()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return store.PutEntry("progress", "field_rewards", fieldRewardKey(pack, id), []byte(period))
|
|
}
|
|
func (s *Store) OpenedFieldRewards(pack int) ([]int, error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
store, err := s.fieldRewardEntries()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
entries, err := store.ListEntries("progress", "field_rewards")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
prefix := fmt.Sprintf("%d:", pack)
|
|
var ids []int
|
|
for key, raw := range entries {
|
|
if len(raw) == 0 {
|
|
return nil, fmt.Errorf("progress: invalid field reward entry")
|
|
}
|
|
if suffix, found := strings.CutPrefix(key, prefix); found {
|
|
id, e := strconv.Atoi(suffix)
|
|
if e != nil || id <= 0 {
|
|
return nil, fmt.Errorf("progress: invalid field reward key")
|
|
}
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
sort.Ints(ids)
|
|
return ids, nil
|
|
}
|
|
|
|
// OpenedFieldRewardPeriods reads the complete opened-object snapshot once from
|
|
// the current request transaction. The returned maps are owned by the caller;
|
|
// nothing is cached across requests or transaction rollback.
|
|
func (s *Store) OpenedFieldRewardPeriods() (map[int]map[int]string, error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
store, err := s.fieldRewardEntries()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
entries, err := store.ListEntries("progress", "field_rewards")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
periods := map[int]map[int]string{}
|
|
for key, raw := range entries {
|
|
packKey, objectKey, found := strings.Cut(key, ":")
|
|
pack, packErr := strconv.Atoi(packKey)
|
|
id, idErr := strconv.Atoi(objectKey)
|
|
if !found || packErr != nil || idErr != nil || pack <= 0 || id <= 0 || key != fieldRewardKey(pack, id) || len(raw) == 0 {
|
|
return nil, fmt.Errorf("progress: invalid field reward entry %q", key)
|
|
}
|
|
if periods[pack] == nil {
|
|
periods[pack] = map[int]string{}
|
|
}
|
|
periods[pack][id] = string(raw)
|
|
}
|
|
return periods, nil
|
|
}
|