port to sceneManager, IRC feedback

trunk
vilmibm 2023-02-21 05:57:27 +00:00
parent cb83223ab8
commit 86dc9cef2d
1 changed files with 112 additions and 116 deletions

View File

@ -3,6 +3,7 @@ package main
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"path" "path"
@ -15,9 +16,6 @@ import (
"github.com/rivo/tview" "github.com/rivo/tview"
) )
// TODO remove sidebar
// TODO add /help
const ( const (
maxInputLength = 10000 maxInputLength = 10000
logDir = "/town/var/signups/log" logDir = "/town/var/signups/log"
@ -27,7 +25,59 @@ type scene struct {
Name string Name string
Description string Description string
Host *character Host *character
Write func([]byte) SorryMsg string
Input *bytes.Buffer
OnAdvance func(*scene)
}
func newScene(name, desc, sorryMsg string, host *character, onAdvance func(*scene)) *scene {
return &scene{
Name: name,
Description: desc,
SorryMsg: sorryMsg,
Host: host,
Input: bytes.NewBuffer([]byte{}),
OnAdvance: onAdvance,
}
}
type sceneManager struct {
scenes []*scene
Current *scene
index int
output io.Writer
Save func()
}
func (m *sceneManager) Advance() bool {
if m.Current.Name == "done" {
return false
}
if m.Current.Input.Len() == 0 {
fmt.Fprintln(m.output, m.Current.Host.Say(m.Current.SorryMsg))
return false
}
m.Current.OnAdvance(m.Current)
m.index++
m.Current = m.scenes[m.index]
if m.Current.Name == "done" {
m.Save()
}
fmt.Fprintln(m.output, heredoc.Doc(`
[purple]----------[-:-:-]
`))
fmt.Fprintln(m.output, m.Current.Description)
return true
}
func newSceneManager(output io.Writer, scenes []*scene) *sceneManager {
return &sceneManager{
output: output,
scenes: scenes,
Current: scenes[0],
}
} }
type character struct { type character struct {
@ -47,7 +97,9 @@ func (c *character) Say(msg string) string {
if c.Name == "you" { if c.Name == "you" {
verb = "say" verb = "say"
} }
return fmt.Sprintf("[-:-:b]%s[-:-:-] %s: '%s'", return fmt.Sprintf(`[-:-:b]%s %s:[-:-:-]
%s
`,
c.Name, c.Name,
verb, verb,
strings.TrimSpace(msg)) strings.TrimSpace(msg))
@ -80,10 +132,9 @@ func _main(l *log.Logger, db *signup.DB) error {
l.Println("starting a session") l.Println("starting a session")
pages := tview.NewPages() pages := tview.NewPages()
mainFlex := tview.NewFlex() mainFlex := tview.NewFlex()
innerFlex := tview.NewFlex()
input := tview.NewTextArea() input := tview.NewTextArea()
input.SetBorder(true).SetBorderColor(tcell.ColorPaleTurquoise) input.SetBorder(true).SetBorderColor(tcell.ColorPaleTurquoise)
input.SetTitle("press ctrl+d to send") input.SetTitle("press enter to send")
input.SetMaxLength(2000) input.SetMaxLength(2000)
title := tview.NewTextView() title := tview.NewTextView()
@ -91,37 +142,19 @@ func _main(l *log.Logger, db *signup.DB) error {
title.SetTextAlign(tview.AlignCenter) title.SetTextAlign(tview.AlignCenter)
title.SetText("[purple]the tilde town sign up portal[-]") title.SetText("[purple]the tilde town sign up portal[-]")
footer := tview.NewTextView()
footer.SetText("type /help and press enter to get help")
msgScroll := tview.NewTextView() msgScroll := tview.NewTextView()
msgScroll.SetDynamicColors(true) msgScroll.SetDynamicColors(true)
msgScroll.SetBackgroundColor(tcell.ColorBlack) msgScroll.SetBackgroundColor(tcell.ColorBlack)
msgScroll.SetTextColor(tcell.ColorWhite) msgScroll.SetTextColor(tcell.ColorWhite)
sidebar := tview.NewTextView()
sidebar.SetBorder(true)
sidebar.SetDynamicColors(true)
sidebar.SetBackgroundColor(tcell.ColorBlack)
sidebar.SetTextColor(tcell.ColorGray)
sidebar.SetText(heredoc.Doc(`
[-:-:b]hey here are some hints[-:-:-]
quit by pressing [-:-:b]ctrl-c[-:-:-]
(your responses won't be saved)
type stuff. send it with [-:-:b]ctrl+d[-:-:-]
try a [-:-:b]verb[-:-:-] using [-:-:b]/[-:-:-] like:
[-:-:b]/nod[-:-:-]
`))
innerFlex.SetDirection(tview.FlexColumn)
innerFlex.AddItem(msgScroll, 0, 3, false)
innerFlex.AddItem(sidebar, 0, 1, false)
mainFlex.SetDirection(tview.FlexRow) mainFlex.SetDirection(tview.FlexRow)
mainFlex.AddItem(title, 1, -1, false) mainFlex.AddItem(title, 1, -1, false)
mainFlex.AddItem(innerFlex, 0, 1, false) mainFlex.AddItem(msgScroll, 0, 1, false)
mainFlex.AddItem(input, 5, -1, true) mainFlex.AddItem(input, 4, -1, true)
mainFlex.AddItem(footer, 1, -1, false)
pages.AddPage("main", mainFlex, true, true) pages.AddPage("main", mainFlex, true, true)
@ -144,9 +177,7 @@ func _main(l *log.Logger, db *signup.DB) error {
} }
scenes := []*scene{ scenes := []*scene{
{ newScene("start", heredoc.Doc(`
Name: "start",
Description: heredoc.Doc(`
You open your eyes. You open your eyes.
You're in some kind of workshop. You're in some kind of workshop.
@ -159,18 +190,15 @@ func _main(l *log.Logger, db *signup.DB) error {
[-:-:b]wire guy says:[-:-:-] [-:-:b]wire guy says:[-:-:-]
hello, welcome to the application for membership in tilde town. hello, welcome to the application for membership in tilde town.
first, please let me know what a good [-:-:b]email address[-:-:-] is for you? first, please let me know what a good [-:-:b]email address[-:-:-] is for you?
just say it out loud. as many times as you need. to get it right. just say it out loud. as many times as you need. to get it right.
when you're ready to move on, [-:-:b]/nod[-:-:-] once you've told me your email you can [-:-:b]/nod[-:-:-] to move on.
`), `),
Host: newCharacter("wire guy", "a lil homonculus made of discarded computer cables"), "i'm sorry, before going further could you share an email with me?",
Write: func(b []byte) { newCharacter("wire guy", "a lil homonculus made of discarded computer cables"),
su.Email = string(b) func(s *scene) { su.Email = string(s.Input.Bytes()) }),
}, newScene("how", heredoc.Doc(`
},
{
Name: "nodded",
Description: heredoc.Doc(`
The workshop fades away. You hear the sound of a dial up modem The workshop fades away. You hear the sound of a dial up modem
in the distance. in the distance.
@ -185,17 +213,13 @@ func _main(l *log.Logger, db *signup.DB) error {
[-:-:b]the shrike says:[-:-:-] [-:-:b]the shrike says:[-:-:-]
phweeturpff. how did you find out about the town? did anyone refer you? phweeturpff. how did you find out about the town? did anyone refer you?
just say your answer out loud. when you've said what you want, [-:-:b]/lean[-:-:-] just say your answer out loud. when you've said what you want, [-:-:b]/nod[-:-:-]
against a tree. to continue.
`), `),
Write: func(b []byte) { "phweeturpff",
su.How = string(b) newCharacter("the shrike", "a little grey bird. it has a pretty song."),
}, func(s *scene) { su.How = string(s.Input.Bytes()) }),
Host: newCharacter("the shrike", "a little grey bird. it has a pretty song."), newScene("what", heredoc.Doc(`
},
{
Name: "leaned",
Description: heredoc.Doc(`
You sink backwards into the forest. You find yourself floating in darkness. You sink backwards into the forest. You find yourself floating in darkness.
At the far reaches of your vision you can make out a faint neon grid. Around you At the far reaches of your vision you can make out a faint neon grid. Around you
@ -209,14 +233,10 @@ func _main(l *log.Logger, db *signup.DB) error {
as usual, just say your answer. when you're satisfied, please [-:-:b]/spin[-:-:-] as usual, just say your answer. when you're satisfied, please [-:-:b]/spin[-:-:-]
around in this void. around in this void.
`), `),
Write: func(b []byte) { "hmm did you say something?",
su.Why = string(b) newCharacter("the vcr", "a black and grey VCR from 1991"),
}, func(s *scene) { su.Why = string(s.Input.Bytes()) }),
Host: newCharacter("the vcr", "a black and grey VCR from 1991"), newScene("link", heredoc.Doc(`
},
{
Name: "spun",
Description: heredoc.Doc(`
You realize your eyes have been shut. You open them and, in an instant, You realize your eyes have been shut. You open them and, in an instant,
the neon grid and polygons are gone. You're in a convenience store. Outside the neon grid and polygons are gone. You're in a convenience store. Outside
it's dark besides a single pool of light coming from a street lamp. it's illuminating it's dark besides a single pool of light coming from a street lamp. it's illuminating
@ -235,14 +255,10 @@ func _main(l *log.Logger, db *signup.DB) error {
when you're happy you can submit this whole experience by leaving the when you're happy you can submit this whole experience by leaving the
store. just [-:-:b]/open[-:-:-] the door. store. just [-:-:b]/open[-:-:-] the door.
`), `),
Write: func(b []byte) { "just the one last thing please",
su.Links = string(b) newCharacter("the mop", "a greying mop with a wooden handle."),
}, func(s *scene) { su.Links = string(s.Input.Bytes()) }),
Host: newCharacter("the mop", "a greying mop with a wooden handle."), newScene("done", heredoc.Doc(`
},
{
Name: "done",
Description: heredoc.Doc(`
thank you for applying to tilde.town! thank you for applying to tilde.town!
please be on the look out for an email from [-:-:b]root@tilde.town[-:-:-] please be on the look out for an email from [-:-:b]root@tilde.town[-:-:-]
@ -251,38 +267,13 @@ func _main(l *log.Logger, db *signup.DB) error {
ok bye have a good one~ ok bye have a good one~
`), `),
Write: func(b []byte) { "",
su.Extra = string(b) nil,
}, func(s *scene) { su.Extra = string(s.Input.Bytes()) }),
},
} }
sceneIx := 0 sm := newSceneManager(msgScroll, scenes)
currentScene := scenes[sceneIx] sm.Save = save
inputWriter := bytes.NewBuffer([]byte{})
advanceScene := func(fromScene, sorryMsg string) {
if currentScene.Name != fromScene {
return
}
if inputWriter.Len() == 0 {
fmt.Fprintln(msgScroll, currentScene.Host.Say(sorryMsg))
return
}
l.Println("advancing scene")
currentScene.Write(inputWriter.Bytes())
inputWriter = bytes.NewBuffer([]byte{})
sceneIx++
currentScene = scenes[sceneIx]
fmt.Fprintln(msgScroll, heredoc.Doc(`
[purple]----------[-:-:-]
`))
fmt.Fprintln(msgScroll, currentScene.Description)
}
handleInput := func(msg string) { handleInput := func(msg string) {
msg = strings.TrimSpace(msg) msg = strings.TrimSpace(msg)
@ -295,37 +286,42 @@ func _main(l *log.Logger, db *signup.DB) error {
msg = split[0] msg = split[0]
} }
switch strings.TrimPrefix(msg, "/") { switch strings.TrimPrefix(msg, "/") {
case "help":
fmt.Fprintln(msgScroll, sm.Current.Host.Say(`some artificial beings will guide you through applying to tilde.town.
type things, then press enter. to take an action, put a "/" before a word.
for example typing:
/nod
and pressing enter will cause you to nod. some other verbs: /quit /look`))
case "quit": case "quit":
l.Println("got /quit") l.Println("got /quit")
app.Stop() app.Stop()
case "look": case "look":
fmt.Fprintln(msgScroll, "") fmt.Fprintln(msgScroll, "")
fmt.Fprintln(msgScroll, currentScene.Description) fmt.Fprintln(msgScroll, sm.Current.Description)
case "nod": case "nod":
advanceScene("start", if !sm.Advance() {
"i'm sorry, before going further could you share an email with me?") fmt.Fprintln(msgScroll, "you nod, but nothing happens.")
case "lean": fmt.Fprintln(msgScroll)
advanceScene("nodded", "phweeturpff") } else {
case "spin": l.Println("advancing scene")
advanceScene("leaned", "hmm did you say something?") }
case "open":
advanceScene("spun", "just the one last thing please")
save()
} }
return return
} }
if inputWriter.Len() > maxInputLength { if sm.Current.Input.Len() > maxInputLength {
fmt.Fprintln(msgScroll, fmt.Fprintln(msgScroll,
currentScene.Host.Say("sorry I've heard more than I can remember :( maybe it's time to move on")) sm.Current.Host.Say(
"sorry I've heard more than I can remember :( maybe it's time to move on"))
return return
} }
fmt.Fprintln(msgScroll, player.Say(msg)) fmt.Fprintln(msgScroll, player.Say(msg))
fmt.Fprintln(inputWriter, msg) fmt.Fprintln(sm.Current.Input, msg)
} }
defer func() { defer func() {
if currentScene.Name == "done" { l.Println("exiting")
currentScene.Write(inputWriter.Bytes()) if sm.Current.Name == "done" {
sm.Current.OnAdvance(sm.Current)
db.UpdateSignup(su) db.UpdateSignup(su)
} }
db.Close() db.Close()
@ -333,7 +329,7 @@ func _main(l *log.Logger, db *signup.DB) error {
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() { switch event.Key() {
case tcell.KeyCtrlD: case tcell.KeyEnter:
handleInput(input.GetText()) handleInput(input.GetText())
input.SetText("", false) input.SetText("", false)
return nil return nil
@ -343,7 +339,7 @@ func _main(l *log.Logger, db *signup.DB) error {
}) })
app.SetAfterDrawFunc(func(_ tcell.Screen) { app.SetAfterDrawFunc(func(_ tcell.Screen) {
fmt.Fprintln(msgScroll, currentScene.Description) fmt.Fprintln(msgScroll, sm.Current.Description)
app.SetAfterDrawFunc(nil) app.SetAfterDrawFunc(nil)
}) })