71 lines
1.9 KiB
Go
71 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// A piece is one module's code for one moment, as the controller placed it (novox/hq ADR 0204 §3,
|
|
// ADR 0211 §3): under a line naming the module, in module order.
|
|
type Piece struct {
|
|
Module string `json:"module"`
|
|
Lines int `json:"lines"`
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
// marker is the line the controller writes before each module's code: "# <module>", nothing else.
|
|
var marker = regexp.MustCompile(`^# ([a-z0-9][a-z0-9-]*)$`)
|
|
|
|
// Pieces splits a moment file into its modules' pieces, exactly as the runner does: a marker line
|
|
// opens a piece; what comes before the first marker is the holder's own header and runs nowhere.
|
|
func Pieces(content string) []Piece {
|
|
var out []Piece
|
|
var cur *Piece
|
|
var b strings.Builder
|
|
flush := func() {
|
|
if cur != nil {
|
|
cur.Code = b.String()
|
|
cur.Lines = strings.Count(cur.Code, "\n")
|
|
out = append(out, *cur)
|
|
}
|
|
b.Reset()
|
|
}
|
|
for _, line := range strings.SplitAfter(content, "\n") {
|
|
if m := marker.FindStringSubmatch(strings.TrimRight(line, "\n")); m != nil {
|
|
flush()
|
|
cur = &Piece{Module: m[1]}
|
|
continue
|
|
}
|
|
if cur != nil {
|
|
b.WriteString(line)
|
|
}
|
|
}
|
|
flush()
|
|
return out
|
|
}
|
|
|
|
// Hooks is every moment's pieces on this machine, read from the files the controller placed.
|
|
func (m *Machine) Hooks() map[string]any {
|
|
moments := map[string]any{}
|
|
total := 0
|
|
for _, moment := range Moments {
|
|
p := MomentsDir + "/" + moment
|
|
if !m.exists(p) {
|
|
moments[moment] = map[string]any{"placed": false}
|
|
continue
|
|
}
|
|
pieces := Pieces(m.read(p) + "\n")
|
|
total += len(pieces)
|
|
moments[moment] = map[string]any{"placed": true, "pieces": orEmpty(pieces)}
|
|
}
|
|
return map[string]any{"moments": moments, "pieces": total,
|
|
"note": "each piece runs on its own with sh as root, bounded (MESH_POWER_BOUND, default 30 s); outcomes are in the journal under mesh-power"}
|
|
}
|
|
|
|
func orEmpty[T any](s []T) []T {
|
|
if s == nil {
|
|
return []T{}
|
|
}
|
|
return s
|
|
}
|