Files
GaCy-GO/internal/common/currency_wars_score.go
T

121 lines
3.3 KiB
Go
Raw Normal View History

package common
import (
"encoding/json"
"fmt"
"strconv"
)
type CurrencyWarsWeeklyRank struct {
Rank uint32 `json:"rank"`
Score uint32 `json:"score"`
Reward uint32 `json:"reward"`
}
type CurrencyWarsScoreDivision struct {
Rule uint32 `json:"rule"`
OCRule uint32 `json:"oc_rule"`
WeeklyModify uint32 `json:"weekly_modify"`
ExpModify uint32 `json:"exp_modify"`
}
type CurrencyWarsScoreNode struct {
Chapter uint32 `json:"chapter"`
Section uint32 `json:"section"`
Weekly uint32 `json:"weekly"`
Exp uint32 `json:"exp"`
}
type CurrencyWarsOfferingLevel struct {
Level uint32 `json:"level"`
ItemCost uint32 `json:"item_cost"`
RewardID uint32 `json:"reward_id"`
}
type CurrencyWarsScore struct {
FormatVersion uint32 `json:"format_version"`
TargetClientVersion string `json:"target_client_version"`
TargetAssemblySHA256 string `json:"target_assembly_sha256"`
WeeklyCap uint32 `json:"weekly_cap"`
WeeklyRanks []CurrencyWarsWeeklyRank `json:"weekly_ranks"`
Divisions map[string]CurrencyWarsScoreDivision `json:"divisions"`
Rules map[string][]CurrencyWarsScoreNode `json:"rules"`
OfferingLevels []CurrencyWarsOfferingLevel `json:"offering_levels"`
}
func LoadCurrencyWarsScore(catalog *CurrencyWarsCatalog) (*CurrencyWarsScore, error) {
raw, err := ReadResourceFile("resources/CurrencyWarsScore.json")
if err != nil {
return nil, err
}
var out CurrencyWarsScore
if err = json.Unmarshal(raw, &out); err != nil {
return nil, err
}
if catalog != nil {
if out.FormatVersion != 1 || out.TargetClientVersion != catalog.ClientVersion || out.TargetAssemblySHA256 != catalog.Provenance.GameAssemblySHA256 {
return nil, fmt.Errorf("CW score revision differs from catalog")
}
}
return &out, nil
}
func (s *CurrencyWarsScore) CalculateRunScore(divisionID uint32, isOverclock bool, chapter, section uint32, isWon bool) (weeklyScore, expBase, expExtra uint32) {
if s == nil {
return 0, 0, 0
}
divKey := strconv.FormatUint(uint64(divisionID), 10)
div, exists := s.Divisions[divKey]
if !exists {
return 0, 0, 0
}
rule := div.Rule
if isOverclock && div.OCRule != 0 {
rule = div.OCRule
}
ruleKey := strconv.FormatUint(uint64(rule), 10)
nodes, exists := s.Rules[ruleKey]
if !exists || len(nodes) == 0 {
return 0, 0, 0
}
here := chapter*100 + section
var best *CurrencyWarsScoreNode
for i := range nodes {
n := &nodes[i]
at := n.Chapter*100 + n.Section
if at < here || (isWon && at == here) {
best = n
}
}
if best == nil {
return 0, 0, 0
}
weeklyMod := div.WeeklyModify
if weeklyMod == 0 {
weeklyMod = 100
}
weeklyScore = (best.Weekly * weeklyMod) / 100
expBase = best.Exp
if div.ExpModify > 100 {
expExtra = (best.Exp * (div.ExpModify - 100)) / 100
}
return weeklyScore, expBase, expExtra
}
func (s *CurrencyWarsScore) OfferingLevel(exp uint32) (level uint32, levelExp uint32) {
if s == nil || len(s.OfferingLevels) == 0 {
return 0, exp
}
left := exp
for _, row := range s.OfferingLevels {
if row.ItemCost == 0 {
continue
}
if left < row.ItemCost {
break
}
left -= row.ItemCost
level = row.Level
}
return level, left
}