Add session and Complete Split
This commit is contained in:
parent
66d98098c5
commit
2dc039dff1
45
api.go
Normal file
45
api.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CompleteSplit marks a split as finished and unlocks its dependent splits if they have no other dependencies
|
||||||
|
func CompleteSplit(session *Session, split *Split) error {
|
||||||
|
fmt.Printf("Splitting split %s (%s)\n", split.Name, split.State)
|
||||||
|
if split.State == Locked {
|
||||||
|
fmt.Println("Death!!")
|
||||||
|
return errors.New("cannot complete a split that is locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set provided split to finished
|
||||||
|
split.State = Finished
|
||||||
|
|
||||||
|
// Iterate over dependencies
|
||||||
|
for _, dep := range split.Dependencies {
|
||||||
|
// Check if dependency has no other dependencies
|
||||||
|
hasOtherDependencies := false
|
||||||
|
for _, otherDep := range session.Graph.Splits {
|
||||||
|
if otherDep == dep || otherDep.State == Finished {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, otherDep2 := range otherDep.Dependencies {
|
||||||
|
if otherDep2 == dep {
|
||||||
|
hasOtherDependencies = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hasOtherDependencies {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no other dependencies, set dependency to unlocked
|
||||||
|
if !hasOtherDependencies {
|
||||||
|
dep.State = Unlocked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
124
graph.go
Normal file
124
graph.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SplitState represents the state of a split
|
||||||
|
type SplitState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Locked SplitState = "locked"
|
||||||
|
Unlocked SplitState = "unlocked"
|
||||||
|
Started SplitState = "started"
|
||||||
|
Finished SplitState = "finished"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Split represents a split in the speedrun graph
|
||||||
|
type Split struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Icon string
|
||||||
|
Dependencies []*Split
|
||||||
|
Timestamp time.Time
|
||||||
|
State SplitState
|
||||||
|
}
|
||||||
|
|
||||||
|
// Graph represents the speedrun graph
|
||||||
|
type Graph struct {
|
||||||
|
Splits []*Split
|
||||||
|
Start *Split
|
||||||
|
Final *Split
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSplit creates a new split
|
||||||
|
func NewSplit(name, icon string) *Split {
|
||||||
|
return &Split{
|
||||||
|
ID: rand.Intn(1000000), // Randomly generating ID
|
||||||
|
Name: name,
|
||||||
|
Icon: icon,
|
||||||
|
Timestamp: time.Time{},
|
||||||
|
State: Locked,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDependency adds a dependency to a split
|
||||||
|
func (s *Split) AddDependency(dep *Split) {
|
||||||
|
s.Dependencies = append(s.Dependencies, dep)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadGraphFromFile reads graph from file representation
|
||||||
|
func ReadGraphFromFile(filename string) (*Graph, error) {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
splits := make(map[string]*Split)
|
||||||
|
|
||||||
|
// Read lines from file
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
parts := strings.Split(line, ",")
|
||||||
|
name := parts[0]
|
||||||
|
icon := parts[1]
|
||||||
|
dependencies := strings.Split(parts[2], "|")
|
||||||
|
|
||||||
|
// Create split
|
||||||
|
split := NewSplit(name, icon)
|
||||||
|
splits[name] = split
|
||||||
|
|
||||||
|
// Create dependencies
|
||||||
|
for _, depName := range dependencies {
|
||||||
|
dep := splits[depName]
|
||||||
|
if dep != nil {
|
||||||
|
split.AddDependency(dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set start and final splits
|
||||||
|
var start, final *Split
|
||||||
|
for _, split := range splits {
|
||||||
|
if split.Name == "Start" {
|
||||||
|
start = split
|
||||||
|
} else if len(split.Dependencies) == 0 {
|
||||||
|
if final != nil {
|
||||||
|
fmt.Println(final.Name)
|
||||||
|
return nil, errors.New("more than one final split found, only one split with no dependencies can exist")
|
||||||
|
}
|
||||||
|
final = split
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if start == nil {
|
||||||
|
return nil, errors.New("no start split found, there should be a split with name 'Start'")
|
||||||
|
}
|
||||||
|
if final == nil {
|
||||||
|
return nil, errors.New("no final split found, there should be the only split with no dependencies")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create graph
|
||||||
|
graph := &Graph{
|
||||||
|
Splits: make([]*Split, 0, len(splits)),
|
||||||
|
Start: start,
|
||||||
|
Final: final,
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.Start.State = Unlocked
|
||||||
|
|
||||||
|
// Append splits to graph
|
||||||
|
for _, split := range splits {
|
||||||
|
graph.Splits = append(graph.Splits, split)
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph, nil
|
||||||
|
}
|
138
main.go
138
main.go
@ -1,127 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SplitState represents the state of a split
|
|
||||||
type SplitState string
|
|
||||||
|
|
||||||
const (
|
|
||||||
Locked SplitState = "locked"
|
|
||||||
Unlocked SplitState = "unlocked"
|
|
||||||
Started SplitState = "started"
|
|
||||||
Finished SplitState = "finished"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Split represents a split in the speedrun graph
|
|
||||||
type Split struct {
|
|
||||||
ID int
|
|
||||||
Name string
|
|
||||||
Icon string
|
|
||||||
Dependencies []*Split
|
|
||||||
Timestamp time.Time
|
|
||||||
State SplitState
|
|
||||||
}
|
|
||||||
|
|
||||||
// Graph represents the speedrun graph
|
|
||||||
type Graph struct {
|
|
||||||
Splits []*Split
|
|
||||||
Start *Split
|
|
||||||
Final *Split
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSplit creates a new split
|
|
||||||
func NewSplit(name, icon string) *Split {
|
|
||||||
return &Split{
|
|
||||||
ID: rand.Intn(1000), // Randomly generating ID
|
|
||||||
Name: name,
|
|
||||||
Icon: icon,
|
|
||||||
Timestamp: time.Time{},
|
|
||||||
State: Locked,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddDependency adds a dependency to a split
|
|
||||||
func (s *Split) AddDependency(dep *Split) {
|
|
||||||
s.Dependencies = append(s.Dependencies, dep)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadGraphFromFile reads graph from file representation
|
|
||||||
func ReadGraphFromFile(filename string) (*Graph, error) {
|
|
||||||
file, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
splits := make(map[string]*Split)
|
|
||||||
|
|
||||||
// Read lines from file
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := scanner.Text()
|
|
||||||
parts := strings.Split(line, ",")
|
|
||||||
name := parts[0]
|
|
||||||
icon := parts[1]
|
|
||||||
dependencies := strings.Split(parts[2], "|")
|
|
||||||
|
|
||||||
// Create split
|
|
||||||
split := NewSplit(name, icon)
|
|
||||||
splits[name] = split
|
|
||||||
|
|
||||||
// Create dependencies
|
|
||||||
for _, depName := range dependencies {
|
|
||||||
dep := splits[depName]
|
|
||||||
if dep != nil {
|
|
||||||
split.AddDependency(dep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set start and final splits
|
|
||||||
var start, final *Split
|
|
||||||
for _, split := range splits {
|
|
||||||
if split.Name == "Start" {
|
|
||||||
start = split
|
|
||||||
} else if len(split.Dependencies) == 0 {
|
|
||||||
if final != nil {
|
|
||||||
fmt.Println(final.Name)
|
|
||||||
return nil, errors.New("more than one final split found, only one split with no dependencies can exist")
|
|
||||||
}
|
|
||||||
final = split
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if start == nil {
|
|
||||||
return nil, errors.New("no start split found, there should be a split with name 'Start'")
|
|
||||||
}
|
|
||||||
if final == nil {
|
|
||||||
return nil, errors.New("no final split found, there should be the only split with no dependencies")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create graph
|
|
||||||
graph := &Graph{
|
|
||||||
Splits: make([]*Split, 0, len(splits)),
|
|
||||||
Start: start,
|
|
||||||
Final: final,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append splits to graph
|
|
||||||
for _, split := range splits {
|
|
||||||
graph.Splits = append(graph.Splits, split)
|
|
||||||
}
|
|
||||||
|
|
||||||
return graph, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Create a session with a random ID and read the graph from file
|
||||||
|
session := &Session{
|
||||||
|
ID: generateRandomID(),
|
||||||
|
Graph: nil,
|
||||||
|
}
|
||||||
|
|
||||||
// Read graph from file
|
// Read graph from file
|
||||||
graph, err := ReadGraphFromFile("graph.txt")
|
graph, err := ReadGraphFromFile("graph.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -129,8 +18,17 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example usage
|
// Set the graph for the session
|
||||||
|
session.Graph = graph
|
||||||
|
|
||||||
|
fmt.Println("Session ID:", session.ID)
|
||||||
fmt.Println("Graph:")
|
fmt.Println("Graph:")
|
||||||
fmt.Println("Start:", graph.Start.Name)
|
PrettyPrintGraph(graph)
|
||||||
fmt.Println("Final:", graph.Final.Name)
|
|
||||||
|
CompleteSplit(session, graph.Start)
|
||||||
|
CompleteSplit(session, graph.Splits[1])
|
||||||
|
CompleteSplit(session, graph.Splits[2])
|
||||||
|
|
||||||
|
PrettyPrintGraph(graph)
|
||||||
|
fmt.Println("Done.")
|
||||||
}
|
}
|
||||||
|
23
print.go
Normal file
23
print.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PrettyPrintGraph prints the entire graph in a readable format
|
||||||
|
func PrettyPrintGraph(graph *Graph) {
|
||||||
|
// Print start split
|
||||||
|
printSplit(graph.Start, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// printSplit prints a split and its dependencies recursively with proper indentation
|
||||||
|
func printSplit(split *Split, indent int) {
|
||||||
|
// Print split information
|
||||||
|
fmt.Printf("%s- %s (%s)\n", strings.Repeat(" ", indent), split.Name, split.State)
|
||||||
|
|
||||||
|
// Recursively print dependencies
|
||||||
|
for _, dep := range split.Dependencies {
|
||||||
|
printSplit(dep, indent+1)
|
||||||
|
}
|
||||||
|
}
|
7
session.go
Normal file
7
session.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// Session represents a user session
|
||||||
|
type Session struct {
|
||||||
|
ID string
|
||||||
|
Graph *Graph
|
||||||
|
}
|
13
util.go
Normal file
13
util.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "math/rand"
|
||||||
|
|
||||||
|
// generateRandomID generates a random session ID
|
||||||
|
func generateRandomID() string {
|
||||||
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
b := make([]byte, 10)
|
||||||
|
for i := range b {
|
||||||
|
b[i] = charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user