diff --git a/.gitignore b/.gitignore index 2e7d4fa..d86905b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ # Go workspace file go.work build + +*.csv diff --git a/cmd/lady/comment.go b/cmd/lady/comment.go index b6a7044..c71d361 100644 --- a/cmd/lady/comment.go +++ b/cmd/lady/comment.go @@ -3,7 +3,8 @@ package main import ( "fmt" "io" - "os" + "strings" + "time" "github.com/urfave/cli/v2" "github.com/ysoldak/fpvc-lady/internal/game" @@ -23,9 +24,9 @@ func commentAction(cc *cli.Context) (err error) { go ttsEngine.Run() // Serial - serial := io.ReadWriter(os.Stdin) + var serial io.ReadWriter port := cc.String(flagPort) - if port != "none" { + if port != "demo" { serial, err = utils.NewSerial(port) if err != nil { return err @@ -34,52 +35,97 @@ func commentAction(cc *cli.Context) (err error) { // CSP messageChan := make(chan csp.Message, 10) - listener := net.NewListener(serial, messageChan) - go listener.Run() + if serial != nil { + listener := net.NewListener(serial, messageChan) + go listener.Run() + } else { + go demo(messageChan) + } // Game g := game.NewGame() + // Trace + go trace() + // Main loop fmt.Println() fmt.Println("The lady is ready.") fmt.Println() fmt.Println("Listening to combat events...") fmt.Println() + speakerChan <- "The lady is ready." - for { - message := <-messageChan + traceChan <- "START" + + for message := range messageChan { + switch message.Command { case csp.CommandBeacon: event := csp.NewBeaconFromMessage(&message) player, new := g.Beacon(event) if new { speakerChan <- fmt.Sprintf("%s registered", player.Name) + traceChan <- fmt.Sprintf("REG %02X %s", player.ID, strings.ReplaceAll(player.Name, " ", "_")) } case csp.CommandHit: if message.IsRequest() { event := csp.NewHitRequestFromMessage(&message) + traceChan <- fmt.Sprintf("HIT %02X %d", event.ID, event.Lives) g.HitRequest(event) + phrase := fmt.Sprintf("%s was hit.", g.Victim.Name) + if cc.Bool(flagSpeakLives) { + phrase += fmt.Sprintf(" %d lives left.", g.Victim.Lives) + } + speakerChan <- phrase } if message.IsResponse() { event := csp.NewHitResponseFromMessage(&message) - victim, ok := g.HitResponse(event) - if !ok { - continue + traceChan <- fmt.Sprintf("CLM %02X %d", event.ID, event.Power) + if g.HitResponse(event) { + attacker, _ := g.Player(event.ID) + speakerChan <- fmt.Sprintf("Score to %s.", attacker.Name) } - attacker, _ := g.Player(event.ID) - phrase := fmt.Sprintf("%s was hit by %s.", victim.Name, attacker.Name) - if cc.Bool(flagSpeakLives) { - phrase += fmt.Sprintf(" %d lives left.", victim.Lives) - } - speakerChan <- phrase } } - println() - println() - println() + + fmt.Println() + fmt.Println() + fmt.Println() for _, line := range g.Table() { - println(line) + fmt.Println(line) + } + } + + return nil +} + +func demo(messageChan chan csp.Message) { + a := csp.NewBeacon(0xA1, "ALICE ", "fake fake fake fake ") + b := csp.NewBeacon(0xB1, "BARTOLOMEO", "fake fake fake fake ") + time.Sleep(2 * time.Second) + + messageChan <- *a.Message() + time.Sleep(1 * time.Second) + messageChan <- *b.Message() + + time.Sleep(6 * time.Second) + + messageChan <- *a.Message() + time.Sleep(1 * time.Second) + messageChan <- *b.Message() + + time.Sleep(5 * time.Second) + + lives := byte(5) + for { + messageChan <- *csp.NewHitRequest(0xA1, lives).Message() + time.Sleep(100 * time.Millisecond) + messageChan <- *csp.NewHitResponse(0xB1, 3).Message() + time.Sleep(3 * time.Second) + lives-- + if lives == 0 { + break } } } diff --git a/cmd/lady/flags.go b/cmd/lady/flags.go index 7c9b659..7b532bb 100644 --- a/cmd/lady/flags.go +++ b/cmd/lady/flags.go @@ -22,8 +22,8 @@ func getFlags() []cli.Flag { }, &cli.StringFlag{ Name: flagSpeak, - Usage: "Speech command: [system], google, none or any other command to convert text to speech.", - EnvVars: []string{"SPEECH"}, + Usage: "Text-to-speech command: [system], google, none or any other command to convert text to speech.", + EnvVars: []string{"SPEAK"}, Required: false, Value: "system", }, diff --git a/cmd/lady/trace.go b/cmd/lady/trace.go new file mode 100644 index 0000000..79dcb42 --- /dev/null +++ b/cmd/lady/trace.go @@ -0,0 +1,26 @@ +package main + +import ( + "log" + "os" +) + +var traceChan = make(chan string, 10) + +func trace() { + + filename := "fpvcc-log.csv" + f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Println(err) + } + defer f.Close() + + tracer := log.New(f, "", log.Ldate|log.Ltime|log.Lmicroseconds) + + for { + event := <-traceChan + tracer.Println(event) + } + +} diff --git a/internal/game/game.go b/internal/game/game.go index 0ed9952..ef45e8d 100644 --- a/internal/game/game.go +++ b/internal/game/game.go @@ -29,11 +29,12 @@ func (g *Game) Beacon(event *csp.Beacon) (player *Player, new bool) { func (g *Game) HitRequest(event *csp.HitRequest) { victim, _ := g.Player(event.ID) - victim.Lives = event.Lives + victim.Lives = event.Lives - 1 + victim.Deaths++ g.Victim = victim } -func (g *Game) HitResponse(event *csp.HitResponse) (victim *Player, ok bool) { +func (g *Game) HitResponse(event *csp.HitResponse) (ok bool) { attacker, _ := g.Player(event.ID) if attacker == nil { attacker = &Player{ @@ -43,14 +44,12 @@ func (g *Game) HitResponse(event *csp.HitResponse) (victim *Player, ok bool) { } g.Players = append(g.Players, attacker) } - victim = g.Victim if g.Victim != nil { - g.Victim = nil attacker.Kills++ - victim.Deaths++ - victim.Lives-- + g.Victim = nil + return true } - return victim, victim != nil + return false } func (g *Game) Player(id byte) (player *Player, isNew bool) {