Files
dcalc/backend/go/internal/service/adventure.go
T
2026-04-02 15:34:18 +08:00

138 lines
3.5 KiB
Go

package service
import (
"encoding/base64"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"time"
)
type AdventureService struct {
projectRoot string
cache *Cache
jobs []Job
tokenToJob map[string]string
}
type Job struct {
Name string `json:"name"`
JobID string `json:"jobId"`
Title string `json:"title"`
Children []JobChild `json:"children"`
}
type JobChild struct {
Name string `json:"name"`
JobGrowID string `json:"jobGrowId"`
Title string `json:"title"`
}
type AdventureParent struct {
ID int `json:"id"`
Name string `json:"name"`
Title string `json:"title"`
Children []AdventureChild `json:"children"`
}
type AdventureChild struct {
ID int `json:"id"`
Name string `json:"name"`
Title string `json:"title"`
Open bool `json:"open"`
Value string `json:"value"`
}
func NewAdventureService(projectRoot string, cache *Cache) (*AdventureService, error) {
jobsPath := filepath.Join(projectRoot, "openapi", "jobs.json")
content, err := os.ReadFile(jobsPath)
if err != nil {
return nil, err
}
var jobs []Job
if err := json.Unmarshal(content, &jobs); err != nil {
return nil, err
}
svc := &AdventureService{
projectRoot: projectRoot,
cache: cache,
jobs: jobs,
tokenToJob: make(map[string]string),
}
for parentIndex, parent := range jobs {
for childIndex, child := range parent.Children {
token := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%02d%02d00", parentIndex, childIndex)))
svc.tokenToJob[token] = "GF." + parent.Name + "." + child.Name
}
}
return svc, nil
}
func (s *AdventureService) Jobs() []Job {
jobs := make([]Job, len(s.jobs))
copy(jobs, s.jobs)
return jobs
}
func (s *AdventureService) AdventureList() ([]AdventureParent, error) {
return GetOrLoad(s.cache, "adventure:list", 10*time.Minute, func() ([]AdventureParent, error) {
result := make([]AdventureParent, 0, len(s.jobs))
for parentIndex, parent := range s.jobs {
children := make([]AdventureChild, 0, len(parent.Children))
for childIndex, child := range parent.Children {
children = append(children, AdventureChild{
ID: childIndex,
Name: child.Name,
Title: child.Title,
Open: true,
Value: base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%02d%02d00", parentIndex, childIndex))),
})
}
result = append(result, AdventureParent{
ID: parentIndex,
Name: parent.Name,
Title: parent.Title,
Children: children,
})
}
return result, nil
})
}
func (s *AdventureService) AlterByToken(token string) (string, error) {
alter, ok := s.tokenToJob[token]
if !ok {
return "", fmt.Errorf("invalid adventure token")
}
return alter, nil
}
func (s *AdventureService) ResolveDirectories(jobIdentifier string, jobGrowIdentifier string) (string, string, error) {
for _, job := range s.jobs {
jobMatched := jobIdentifier == job.Name || jobIdentifier == job.JobID
if !jobMatched {
continue
}
for _, child := range job.Children {
if jobGrowIdentifier == child.Name || jobGrowIdentifier == child.JobGrowID {
return job.Name, child.Name, nil
}
}
}
return "", "", fmt.Errorf("unknown job path: %s/%s", jobIdentifier, jobGrowIdentifier)
}
func (s *AdventureService) DirectoriesFromAlter(alter string) (string, string, error) {
parts := strings.Split(alter, ".")
if len(parts) != 3 || parts[0] != "GF" {
return "", "", fmt.Errorf("invalid alter value: %s", alter)
}
return parts[1], parts[2], nil
}