package main import ( "bufio" "bytes" "encoding/json" "html/template" "log" "net/http" "os" "sync" "time" ) const sleepInterval = time.Second * 5 var geoJSONTmpl = template.Must(template.New("geojson").Parse( `{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [{{.X}}, {{.Z}}] }, "properties": { "name": "{{.Name | html }}" } }`)) type player struct { X float64 `json:"x"` Y float64 `json:"y"` Z float64 `json:"z"` Name string `json:"name"` } type players struct { fifo string wsf *websocketForwarder pls []*player mu sync.RWMutex } func newPlayers(fifo string, wsf *websocketForwarder) *players { return &players{fifo: fifo, wsf: wsf, pls: []*player{}} } func (p *player) MarshalJSON() ([]byte, error) { var buf bytes.Buffer if err := geoJSONTmpl.Execute(&buf, p); err != nil { return nil, err } return buf.Bytes(), nil } func (ps *players) readFromFIFO() ([]*player, error) { file, err := os.Open(ps.fifo) if err != nil { return nil, err } defer file.Close() reader := bufio.NewReader(file) decoder := json.NewDecoder(reader) var pls []*player if err = decoder.Decode(&pls); err != nil { return nil, err } return pls, nil } func (ps *players) run() { for { pls, err := ps.readFromFIFO() if err != nil { time.Sleep(sleepInterval) continue } ps.mu.Lock() ps.pls = pls ps.mu.Unlock() // TODO: Implement websocket broadcast. } } func (ps *players) ServeHTTP(rw http.ResponseWriter, r *http.Request) { rw.Header().Set("Content-Type", "application/json") ps.mu.RLock() defer ps.mu.RUnlock() encoder := json.NewEncoder(rw) if err := encoder.Encode(ps.pls); err != nil { log.Printf("error: sending JSON failed: %s\n", err) } }