improve repl

add addr & help commands, don't restart if paused
This commit is contained in:
Norwin Roosen 2020-12-29 22:03:21 +01:00
parent c3ee33f8ce
commit 6f2e2fd666
No known key found for this signature in database
GPG Key ID: 24BC059DE24C43A3
5 changed files with 76 additions and 38 deletions

View File

@ -83,7 +83,7 @@ func main() {
// local 🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊
wg.Add(1)
go pixelflut.Flut(img, offset, *shuffle, false, false, false, *address, *connections, stopChan, &wg)
go pixelflut.Flut(img, offset, *shuffle, false, false, *address, *connections, stopChan, &wg)
}
} else if *hevringAddr != "" {

View File

@ -16,7 +16,7 @@ import (
// using `conns` connections. Pixels are sent column wise, unless `shuffle`
// is set. Stops when stop is closed.
// @cleanup: use FlutTask{} as arg
func Flut(img *image.NRGBA, position image.Point, shuffle, rgbsplit, randoffset, recreateConns bool, address string, conns int, stop chan bool, wg *sync.WaitGroup) {
func Flut(img *image.NRGBA, position image.Point, shuffle, rgbsplit, randoffset bool, address string, conns int, stop chan bool, wg *sync.WaitGroup) {
var cmds commands
if rgbsplit {
// do a RGB split of white

View File

@ -34,10 +34,17 @@ type FlutTask struct {
MaxConns int
Img *image.NRGBA
Offset image.Point
Paused bool
Shuffle bool // TODO: refactor these as RenderOpts bitfield
RGBSplit bool
RandOffset bool
NewConn bool
}
func (t FlutTask) String() string {
return fmt.Sprintf(
" %d conns @ %s\n img %v offset %v\n shuffle %v rgbsplit %v randoffset %v paused %v",
t.MaxConns, t.Address, t.Img.Bounds().Size(), t.Offset, t.Shuffle, t.RGBSplit, t.RandOffset, t.Paused,
)
}
type FlutAck struct{ Ok bool }
@ -54,11 +61,11 @@ func (h *Hevring) Flut(task FlutTask, reply *FlutAck) error {
close(h.taskQuit)
}
fmt.Printf("[hevring] Rán gave us /w o r k/! %v\n", task)
fmt.Printf("[hevring] Rán gave us /w o r k/!\n%v\n", task)
h.task = task
h.taskQuit = make(chan bool)
go pixelflut.Flut(task.Img, task.Offset, task.Shuffle, task.RGBSplit, task.RandOffset, task.NewConn, task.Address, task.MaxConns, h.taskQuit, nil)
go pixelflut.Flut(task.Img, task.Offset, task.Shuffle, task.RGBSplit, task.RandOffset, task.Address, task.MaxConns, h.taskQuit, nil)
reply.Ok = true
return nil
}

View File

@ -109,12 +109,14 @@ func (r *Rán) applyTask(t FlutTask) {
return
}
r.task = t
for _, c := range r.clients {
if t.Paused {
return
}
for i, c := range r.clients {
ack := FlutAck{}
// @speed: should send tasks async
err := c.Call("Hevring.Flut", r.task, &ack)
if err != nil || !ack.Ok {
log.Printf("[rán] client didn't accept task")
log.Printf("[rán] client %d didn't accept task", i)
}
}
}
@ -142,5 +144,11 @@ func (r *Rán) SetTask(img *image.NRGBA, offset image.Point, address string, max
// fetch server state & sample foreign activity in image regions. assign
// subregions to clients (per connection), considering their bandwidth.
r.applyTask(FlutTask{address, maxConns, img, offset, true})
r.applyTask(FlutTask{
Address: address,
MaxConns: maxConns,
Img: img,
Offset: offset,
Shuffle: true,
})
}

View File

@ -21,8 +21,8 @@ type Fluter interface {
toggleMetrics()
}
const commandMode = "CMD"
const textMode = "TXT"
const commandMode = "cmd"
const textMode = "txt"
// RunREPL starts reading os.Stdin for commands to apply to the given Fluter
func RunREPL(f Fluter) {
@ -31,13 +31,16 @@ func RunREPL(f Fluter) {
var textCol image.Image = image.White
var bgCol image.Image = image.Transparent
fmt.Print("[rán] REPL is active. ")
printHelp()
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
inputStr := scanner.Text()
switch mode {
switch strings.ToLower(mode) {
case textMode:
if inputStr == commandMode {
if strings.ToLower(inputStr) == commandMode {
fmt.Println("[rán] command mode")
mode = commandMode
continue
@ -50,52 +53,48 @@ func RunREPL(f Fluter) {
input := strings.Split(inputStr, " ")
cmd := strings.ToLower(input[0])
args := input[1:]
t := f.getTask()
printTask := true
switch cmd {
case "stop":
t.Paused = true
f.stopTask()
printTask = false
case "start":
f.applyTask(f.getTask())
t.Paused = false
case "offset":
if len(args) == 2 {
if len(args) == 1 && args[0] == "rand" {
t.RandOffset = true
t.Offset = image.Point{}
} else if len(args) == 2 {
t.RandOffset = false
x, err := strconv.Atoi(args[0])
y, err2 := strconv.Atoi(args[1])
if err == nil && err2 == nil {
t := f.getTask()
t.Offset = image.Pt(x, y)
f.applyTask(t)
}
}
case "conns":
if len(args) == 1 {
if conns, err := strconv.Atoi(args[0]); err == nil {
t := f.getTask()
t.MaxConns = conns
f.applyTask(t)
}
}
case "addr":
if len(args) == 1 {
t.Address = args[0]
}
case "shuffle":
t := f.getTask()
t.Shuffle = !t.Shuffle
f.applyTask(t)
case "rgbsplit":
t := f.getTask()
t.RGBSplit = !t.RGBSplit
f.applyTask(t)
case "randoffset":
t := f.getTask()
t.RandOffset = !t.RandOffset
f.applyTask(t)
case "newconn":
t := f.getTask()
t.NewConn = !t.NewConn
f.applyTask(t)
case "txt":
if len(args) > 0 {
@ -110,35 +109,59 @@ func RunREPL(f Fluter) {
bgCol = parseColorOrPalette(args[2])
}
if len(args) < 4 {
fmt.Printf("[rán] text mode, return via %v\n", commandMode)
fmt.Printf("[rán] text mode, return via '%v'\n", strings.ToUpper(commandMode))
mode = textMode
printTask = false
} else {
input := strings.Join(args[3:], " ")
t := f.getTask()
t.Img = render.RenderText(input, textSize, textCol, bgCol)
f.applyTask(t)
}
case "img":
if len(args) > 0 {
path := strings.Join(args, " ")
t := f.getTask()
if img, err := render.ReadImage(path); err != nil {
fmt.Println(err)
} else {
t.Img = render.ImgToNRGBA(img)
f.applyTask(t)
}
}
case "metrics":
f.toggleMetrics()
printTask = false
default:
printTask = false
fmt.Print("[rán] unknown command. ")
printHelp()
}
if printTask {
fmt.Println(t)
}
f.applyTask(t)
}
}
}
func printHelp() {
fmt.Println(`available commands:
start start fluting
stop pause fluting
conns <n> set number of connections per client
addr <host>:<port> set target server
offset <x> <y> set top-left offset
offset rand random offset for each draw
metrics toggle bandwidth reporting (may cost some performance)
img <filepath> set image
txt <scale> <color <bgcolor> <txt> send text
txt [<scale> [<color> [<bgcolor>]] enter interactive text mode
rgbsplit toggle RGB split effect
shuffle toggle between column-wise & randomized draw order`)
}
// try to parse as hex-encoded RGB color,
// alternatively treat it as palette name. If both fail,
// give image.Transparent