session

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2025 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	SpeedRunAPIBase string `json:"speed_run_API_base"`
}

Config holds configuration options so that Service.GetConfig can work for both backend and frontend.

type FileProvider

type FileProvider interface {
	WriteFile(string, []byte, os.FileMode) error
	ReadFile(string) ([]byte, error)
	MkdirAll(string, os.FileMode) error
	UserHomeDir() (string, error)
}

FileProvider wraps os hooks and file operations to allow DI for testing.

type JsonFile

type JsonFile struct {
	// contains filtered or unexported fields
}

JsonFile represents a SplitFile as a JSON file

JsonFile provide utilities to work with the OS filesystem using the Wails runtime, and store information like the current filename and lastUsedDirectory for UX purposes.

func NewJsonFile

func NewJsonFile(runtime RuntimeProvider, fileProvider FileProvider) *JsonFile

NewJsonFile creates a JsonFile with the provided RuntimeProvider and FileProvider

In production code this will always be runtime.WailsRuntime and runtime.FileRuntime

func (*JsonFile) Load

func (j *JsonFile) Load() (SplitFilePayload, error)

Load reads a JSON (*.osf) file from the path returned from the open file dialog and unserializes it into a SplitFilePayload

func (*JsonFile) Save

func (j *JsonFile) Save(splitFilePayload SplitFilePayload, splitFile SplitFile) error

Save takes a SplitFile payload from the frontend, which modifies the passed in spitFile (or nil if a new file) from the Session Service backend.

We originally just sent in the payload, created a new SplitFile from that, and set Sessions Services's loaded SplitFile with that new one, but when we added the concept of run history that no longer scaled.

func (*JsonFile) Startup

func (j *JsonFile) Startup(ctx context.Context)

Startup is called either directly by Wails.Run OnStartup, or by something else in that chain.

The specific context.Context must be provided by Wails.Run OnStartup or opening save/load file dialogs will panic.

type Persister

type Persister interface {
	Startup(ctx context.Context)
	Load() (split SplitFilePayload, err error)
	Save(split SplitFilePayload, splitFile SplitFile) error
}

Persister is an interface that services that save and load splitfiles must implement to be used by session.Service

type Run

type Run struct {
	// contains filtered or unexported fields
}

Run maintains the history attempts in a SplitFile.

This is useful to calculate things like gold splits, sum of best segments, etc...

type RuntimeProvider

type RuntimeProvider interface {
	SaveFileDialog(context.Context, runtime.SaveDialogOptions) (string, error)
	OpenFileDialog(context.Context, runtime.OpenDialogOptions) (string, error)
}

RuntimeProvider wraps Wails.runtime calls to allow for DI for testing.

type Segment

type Segment struct {
	// contains filtered or unexported fields
}

Segment represents a portion of a game that you want to time (e.g. "Level 1")

func NewFromPayload

func NewFromPayload(payload SegmentPayload) (Segment, error)

NewFromPayload creates a new Segment from the given SegmentPayload.

This is a pattern used often in OpenSplit where you fetch a payload, modify it, then pass it into a modification or creation func to persist changes internally.

func (*Segment) GetPayload

func (s *Segment) GetPayload() SegmentPayload

GetPayload retrieves a SegmentPayload representing the state of the Segment

type SegmentPayload

type SegmentPayload struct {
	ID       string `json:"id"`
	Name     string `json:"name"`
	BestTime string `json:"best_time"`
	Average  string `json:"average_time"`
}

SegmentPayload is a snapshot of a given Segment useful for communicating state while protecting internal data.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service represents the interface from the backend Go system to the frontend React system.

It is the primary glue that brings together a Timer, SplitFile, Run history, Persister, and the status of the current Run / SplitFile. If there's one struct that's key to understand in OpenSplit, it's this one.

Service contains the authoritative state of the system, and communicates parts of that state to the front end both by imperative functions that are bound to the frontend with Wails.Run, and events sent to the frontend via Service.emitEvent

It communicates timer updates to the frontend, and passes along frontend calls to bound functions to the OpenSplit backend systems

func NewService

func NewService(timer Timer, timeUpdatedChannel chan time.Duration, splitFile *SplitFile, persister Persister) *Service

NewService creates a new Service from the passed in components.

Generally in real code splitFile should be nil and will be populated from Service.UpdateSplitFile or Service.LoadSplitFile Timer updates will be sent over the timeUpdatedChannel at approximately 60FPS.

func (*Service) CloseSplitFile

func (s *Service) CloseSplitFile()

CloseSplitFile unloads the loaded SplitFile, and resets the system.

func (*Service) GetConfig

func (s *Service) GetConfig() *Config

GetConfig is designed to expose configuration options from the environment or other sources (config files) to the frontend. Go services can just read the environment, but the frontend has no reliable way to do so, so this func is bound to the app in main which generates a typescript function for the frontend.

func (*Service) GetLoadedSplitFile

func (s *Service) GetLoadedSplitFile() *SplitFilePayload

GetLoadedSplitFile returns the SplitFilePayload representation of the currently loaded SplitFile

It returns a payload, modifications to it do not affect the internal state. To do that modify the payload then send the modified payload to UpdateSplitFile.

func (*Service) GetSessionStatus

func (s *Service) GetSessionStatus() ServicePayload

GetSessionStatus is a convenience method for the frontend to query the state of the system imperatively

func (*Service) LoadSplitFile

func (s *Service) LoadSplitFile() (SplitFilePayload, error)

LoadSplitFile retrieves a SplitFilePayload from Persister configured storage.

It creates a new SplitFile from the retrieved SplitFilePayload, sets that as the loaded split file, and resets the system.

func (*Service) Pause

func (s *Service) Pause()

Pause toggles the timer between the running and not running state.

func (*Service) Reset

func (s *Service) Reset()

Reset brings the system back to a default state.

If there was a current run loaded, information about that run is added to the SplitFile history.

func (*Service) Split

func (s *Service) Split()

Split advances the state of a run

Split has several logical branches depending on the state of the run. It can start a run if currentIndex is -1, advance to the next split and generate split information if in the middle of a run, end a run once the last segment is split, and Reset for a new run if called when the run is over.

func (*Service) Startup

func (s *Service) Startup(ctx context.Context)

Startup is designed to be called by Wails.Run OnStartup to supply the proper context.Context that allows the session.Service to call Wails runtime functions that do things like open file dialogs.

It also provides the context to the configured Persister so that it may also open file dialogs, calls Reset to ensure the state is fresh, and starts a loop to listen for updates from Timer. These updates are then passed along to the frontend to update the visual timer.

func (*Service) UpdateSplitFile

func (s *Service) UpdateSplitFile(payload SplitFilePayload) error

UpdateSplitFile uses the configured Persister to save the SplitFile to the configured storage.

It creates a SplitFile from the given SplitFilePayload and then sets that SplitFile as the currently loaded one.

type ServicePayload

type ServicePayload struct {
	SplitFile            *SplitFilePayload `json:"split_file"`
	CurrentSegmentIndex  int               `json:"current_segment_index"`
	CurrentSegment       *SegmentPayload   `json:"current_segment"`
	Finished             bool              `json:"finished"`
	Paused               bool              `json:"paused"`
	CurrentTime          time.Duration     `json:"current_time"`
	CurrentTimeFormatted string            `json:"current_time_formatted"`
}

ServicePayload is a snapshot of the session.Service, useful for communicating the state of the service to the frontend without exposing internal data.

type SplitFile

type SplitFile struct {
	// contains filtered or unexported fields
}

SplitFile represents the data and history of a game/category combo.

func NewSplitFile

func NewSplitFile(gameName string, gameCategory string, segments []Segment, attempts int, runs []Run) *SplitFile

NewSplitFile constructor for SplitFile

func (*SplitFile) GetPayload

func (s *SplitFile) GetPayload() SplitFilePayload

GetPayload gets a snapshot of the SplitFile. Useful for communicating the state of the file while protecting the internal data.

func (*SplitFile) NewAttempt

func (s *SplitFile) NewAttempt()

NewAttempt provides a public function to increment the attempts count

func (*SplitFile) SetAttempts

func (s *SplitFile) SetAttempts(attempts int)

SetAttempts provides a public function to set the attempts count

type SplitFilePayload

type SplitFilePayload struct {
	GameName     string           `json:"game_name"`
	GameCategory string           `json:"game_category"`
	Segments     []SegmentPayload `json:"segments"`
	Attempts     int              `json:"attempts"`
	Runs         []Run            `json:"runs"`
}

SplitFilePayload is a snapshot of a SplitFile

Used to communicate the state of a SplitFile to the frontend and Persister implementations without exposing internals.

type SplitPayload

type SplitPayload struct {
	SplitIndex   int            `json:"split_index"`
	NewIndex     int            `json:"new_index"`
	SplitSegment SegmentPayload `json:"split_segment"`
	NewSegment   SegmentPayload `json:"new_segment"`
	Finished     bool           `json:"finished"`
	CurrentTime  string         `json:"current_time"`
}

SplitPayload is a snapshot of split data to communicate information about a split to the frontend, and also the run history in SplitFile runs

type Timer

type Timer interface {
	IsRunning() bool
	Run()
	Start()
	Pause()
	Reset()
	GetCurrentTimeFormatted() string
	GetCurrentTime() time.Duration
}

Timer is an interface that a stopwatch service must implement to be used by session.Service

type UserCancelledSave

type UserCancelledSave struct {
	// contains filtered or unexported fields
}

UserCancelledSave is a error that informs the calling system that the user cancelled a file open/load dialog.

Wails generates exported bound methods to typescript functions that return a promise, if a not nil error is returned as the second return, Wails will reject the promise instead of fulfilling it. So this isn't necessarily an error that needs to be handled, but it is a convenient way to communicate to the frontend to catch() a promise instead of fulfilling it so that it doesn't try to do anything with an empty data structure.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL