diff --git a/host.d/config.d/mayhem-party.d/env.env b/host.d/config.d/mayhem-party.d/env.env index 3a49e12..1d986ce 100644 --- a/host.d/config.d/mayhem-party.d/env.env +++ b/host.d/config.d/mayhem-party.d/env.env @@ -4,3 +4,4 @@ export BUTTON_V01=true export WRAP_REFRESH_ON_SIGUSR1=true export MAIN_INTERVAL_DURATION=5ms export OUTPUT_KEYBOARD=false +export BUTTON_V01_CONFIG=./config.d/mayhem-party.d/v01.yaml diff --git a/host.d/config.d/mayhem-party.d/remap.d/live.yaml b/host.d/config.d/mayhem-party.d/remap.d/live.yaml index f6e64cd..c555863 120000 --- a/host.d/config.d/mayhem-party.d/remap.d/live.yaml +++ b/host.d/config.d/mayhem-party.d/remap.d/live.yaml @@ -1 +1 @@ -players_offset_1.yaml \ No newline at end of file +players_offset_4.yaml \ No newline at end of file diff --git a/host.d/config.d/mayhem-party.d/v01.yaml b/host.d/config.d/mayhem-party.d/v01.yaml new file mode 100644 index 0000000..94253a0 --- /dev/null +++ b/host.d/config.d/mayhem-party.d/v01.yaml @@ -0,0 +1,21 @@ +feedback: + addr: :17071 +users: + bel: + player: 2 + message: its bel + broadcast: + message: 8 +players: +- {} +- transformation: + w: t + a: f + s: g + d: h + q: r + e: y + 1: 5 + 2: 6 + 3: 7 + 4: 8 diff --git a/src/device/input/button/v01.go b/src/device/input/button/v01.go index 3af599b..4732ae0 100644 --- a/src/device/input/button/v01.go +++ b/src/device/input/button/v01.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "log" "mayhem-party/src/device/input/raw" + "net/http" "os" "time" @@ -31,6 +32,9 @@ type ( N string } v01Cfg struct { + Feedback struct { + Addr string + } Users map[string]struct { Player int Message string @@ -47,12 +51,41 @@ func NewV01(ctx context.Context, src raw.Raw) V01 { b, _ := ioutil.ReadFile(FlagButtonV01Config) yaml.Unmarshal(b, &cfg) ctx, can := context.WithCancel(ctx) - return V01{ + result := V01{ ctx: ctx, can: can, src: src, cfg: cfg, } + go result.listen() + return result +} + +func (v01 V01) listen() { + if v01.cfg.Feedback.Addr == "" { + return + } + s := &http.Server{ + Addr: v01.cfg.Feedback.Addr, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r = r.WithContext(v01.ctx) + user, ok := v01.cfg.Users[r.URL.Query().Get("user")] + if !ok { + user = v01.cfg.Users["broadcast"] + } + w.Write([]byte(user.Message)) + }), + } + go func() { + <-v01.ctx.Done() + log.Println("closing v01 server") + s.Close() + }() + log.Println("starting v01 server") + if err := s.ListenAndServe(); err != nil && v01.ctx.Err() == nil { + log.Println("err with v01 server", err) + panic(err) + } } func (v01 V01) CloseWrap() raw.Raw { diff --git a/src/device/input/button/v01_exported_test.go b/src/device/input/button/v01_exported_test.go index 2372d18..73e5a99 100644 --- a/src/device/input/button/v01_exported_test.go +++ b/src/device/input/button/v01_exported_test.go @@ -3,7 +3,9 @@ package button_test import ( "context" "fmt" + "io" "mayhem-party/src/device/input/button" + "net/http" "os" "path" "testing" @@ -14,6 +16,7 @@ func TestV01(t *testing.T) { src := constSrc(fmt.Sprintf(`{"T":%v,"U":"bel","Y":"abc","N":"cde"}`, time.Now().UnixNano()/int64(time.Millisecond)-50)) t.Logf("(%v) %s", len(src), src.Read()) v01 := button.NewV01(context.Background(), src) + defer v01.Close() got := v01.Read() want := []button.Button{ {Down: true, Char: 'a'}, @@ -50,6 +53,7 @@ func TestV01WithCfg(t *testing.T) { t.Run("unknown user ignored", func(t *testing.T) { v01 := button.NewV01(context.Background(), constSrc(`{"U":"qt","Y":"w"}`)) + defer v01.Close() got := v01.Read() if len(got) != 0 { t.Error(got) @@ -58,6 +62,7 @@ func TestV01WithCfg(t *testing.T) { t.Run("player2", func(t *testing.T) { v01 := button.NewV01(context.Background(), constSrc(`{"U":"bel","Y":"w","N":"w"}`)) + defer v01.Close() got := v01.Read() if len(got) != 2 { t.Error(got) @@ -70,3 +75,63 @@ func TestV01WithCfg(t *testing.T) { } }) } + +func TestV01Feedback(t *testing.T) { + d := t.TempDir() + p := path.Join(d, "cfg.yaml") + os.WriteFile(p, []byte(` + feedback: + addr: :27071 + users: + bel: + player: 2 + message: to bel + broadcast: + message: to everyone + players: + - transformation: + w: t + - transformation: + w: i + `), os.ModePerm) + button.FlagButtonV01Config = p + ctx, can := context.WithCancel(context.Background()) + defer can() + + v01 := button.NewV01(ctx, constSrc(`{"U":"qt","Y":"w"}`)) + defer v01.Close() + + for { + time.Sleep(time.Millisecond * 100) + resp, err := http.Get("http://localhost:27071?user=bel") + if err != nil { + continue + } + resp.Body.Close() + break + } + + t.Run("specific user", func(t *testing.T) { + resp, err := http.Get("http://localhost:27071?user=bel") + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + b, _ := io.ReadAll(resp.Body) + if string(b) != "to bel" { + t.Error(b) + } + }) + + t.Run("broadcast", func(t *testing.T) { + resp, err := http.Get("http://localhost:27071") + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + b, _ := io.ReadAll(resp.Body) + if string(b) != "to everyone" { + t.Error(b) + } + }) +}