This commit is contained in:
root
2026-09-19 20:21:47 +02:00
commit 0798933b05
62 changed files with 7658 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
// Command asm assembles ship-program source into the binary that the
// program endpoint accepts: asm prog.s > prog.bin
package main
import (
"fmt"
"os"
"wh/vm"
)
func main() {
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "usage: asm <source.s> > program.bin")
os.Exit(2)
}
src, err := os.ReadFile(os.Args[1])
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
prog, err := vm.Assemble(string(src))
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Stdout.Write(prog)
}
+41
View File
@@ -0,0 +1,41 @@
// Command daily runs one simulated day against the database. Schedule it
// once a day (cron/systemd timer).
package main
import (
"context"
"flag"
"fmt"
"log"
"wh/config"
"wh/runner"
"wh/store"
)
func main() {
dsn := flag.String("db", config.DatabaseURL(), "sqlite:<path> or postgres:// URL (default: $DATABASE_URL)")
cfg, err := config.Bind(flag.CommandLine)
if err != nil {
log.Fatal(err)
}
flag.Parse()
ctx := context.Background()
st, err := store.Open(*dsn)
if err != nil {
log.Fatal(err)
}
defer st.Close()
if err := st.Migrate(ctx); err != nil {
log.Fatal(err)
}
res, err := runner.RunNextDay(ctx, st, *cfg)
if err != nil {
log.Fatal(err)
}
fmt.Printf("day %d complete: %d events, %d downlinks, hash %x\n", res.Day, len(res.Events), len(res.Downlinks), res.Hash[:8])
for _, e := range res.Events {
fmt.Println(" ", e)
}
}
+40
View File
@@ -0,0 +1,40 @@
// Command server serves the player HTTP API and the web front end.
package main
import (
"context"
"flag"
"log"
"net/http"
"wh/api"
"wh/config"
"wh/store"
"wh/web"
)
func main() {
dsn := flag.String("db", config.DatabaseURL(), "sqlite:<path> or postgres:// URL (default: $DATABASE_URL)")
addr := flag.String("addr", ":8080", "listen address")
cfg, err := config.Bind(flag.CommandLine)
if err != nil {
log.Fatal(err)
}
flag.Parse()
if err := cfg.Validate(); err != nil {
log.Fatal(err)
}
st, err := store.Open(*dsn)
if err != nil {
log.Fatal(err)
}
defer st.Close()
if err := st.Migrate(context.Background()); err != nil {
log.Fatal(err)
}
mux := api.New(st, *cfg)
mux.Handle("/", web.Handler()) // the site; API routes are more specific and win
log.Printf("listening on %s", *addr)
log.Fatal(http.ListenAndServe(*addr, mux))
}