Skip to content

Commit

Permalink
Add reporter.Callback, sensible zero UpdateInterval (#61)
Browse files Browse the repository at this point in the history
* Adds `reporter.Callback` for direct retrieval of observer output in Go code
* Fix reporters did not work with unspecified `UpdateInterval`
  • Loading branch information
mlange-42 authored May 13, 2024
1 parent bb84971 commit 10b9588
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 17 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

## [[unpublished]](https://github.com/mlange-42/arche-model/compare/v0.7.0...main)

### Features

* Adds `reporter.Callback` for direct retrieval of observer output in Go code (#61)

### Bugfixes

* Fix typo in error message when adding UI system as normal system (#60)
* Fix reporters did not work with unspecified `UpdateInterval` (#61)

## [[v0.7.0]](https://github.com/mlange-42/arche-model/compare/v0.6.0...v0.7.0)

Expand Down
40 changes: 40 additions & 0 deletions reporter/callback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package reporter

import (
"github.com/mlange-42/arche-model/observer"
"github.com/mlange-42/arche/ecs"
)

// Callback reporter calling a function on each update.
type Callback struct {
Observer observer.Row // Observer to get data from.
UpdateInterval int // Update/print interval in model ticks.
HeaderCallback func(header []string)
Callback func(step int, row []float64)
step int64
}

// Initialize the system
func (s *Callback) Initialize(w *ecs.World) {
s.Observer.Initialize(w)
if s.UpdateInterval == 0 {
s.UpdateInterval = 1
}
if s.HeaderCallback != nil {
s.HeaderCallback(s.Observer.Header())
}
s.step = 0
}

// Update the system
func (s *Callback) Update(w *ecs.World) {
s.Observer.Update(w)
if s.step%int64(s.UpdateInterval) == 0 {
values := s.Observer.Values(w)
s.Callback(int(s.step), values)
}
s.step++
}

// Finalize the system
func (s *Callback) Finalize(w *ecs.World) {}
35 changes: 35 additions & 0 deletions reporter/callback_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package reporter_test

import (
"fmt"

"github.com/mlange-42/arche-model/model"
"github.com/mlange-42/arche-model/reporter"
"github.com/mlange-42/arche-model/system"
)

func ExampleCallback() {
// Create a new model.
m := model.New()

data := [][]float64{}

// Add a Print reporter with an Observer.
m.AddSystem(&reporter.Callback{
Observer: &ExampleObserver{},
Callback: func(step int, row []float64) {
data = append(data, row)
},
HeaderCallback: func(header []string) {},
})

// Add a termination system that ends the simulation.
m.AddSystem(&system.FixedTermination{Steps: 3})

// Run the simulation.
m.Run()

fmt.Println(data)
// Output:
// [[1 2 3] [1 2 3] [1 2 3]]
}
3 changes: 3 additions & 0 deletions reporter/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type CSV struct {
func (s *CSV) Initialize(w *ecs.World) {
s.Observer.Initialize(w)
s.header = s.Observer.Header()
if s.UpdateInterval == 0 {
s.UpdateInterval = 1
}
if s.Sep == "" {
s.Sep = ","
}
Expand Down
7 changes: 3 additions & 4 deletions reporter/csv_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ func ExampleCSV() {

// Add a CSV reporter with an Observer.
m.AddSystem(&reporter.CSV{
Observer: &ExampleObserver{},
File: "../out/test.csv",
Sep: ";",
UpdateInterval: 10,
Observer: &ExampleObserver{},
File: "../out/test.csv",
Sep: ";",
})

// Add a termination system that ends the simulation.
Expand Down
3 changes: 3 additions & 0 deletions reporter/csv_snaphot.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type SnapshotCSV struct {
func (s *SnapshotCSV) Initialize(w *ecs.World) {
s.Observer.Initialize(w)
s.header = s.Observer.Header()
if s.UpdateInterval == 0 {
s.UpdateInterval = 1
}

if s.Sep == "" {
s.Sep = ","
Expand Down
7 changes: 3 additions & 4 deletions reporter/csv_snapshot_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ func ExampleSnapshotCSV() {

// Add a SnapshotCSV reporter with an Observer.
m.AddSystem(&reporter.SnapshotCSV{
Observer: &ExampleSnapshotObserver{},
FilePattern: "../out/test-%06d.csv",
Sep: ";",
UpdateInterval: 10,
Observer: &ExampleSnapshotObserver{},
FilePattern: "../out/test-%06d.csv",
Sep: ";",
})

// Add a termination system that ends the simulation.
Expand Down
5 changes: 2 additions & 3 deletions reporter/csv_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ func TestSnapshotCSV(t *testing.T) {
m := model.New()

m.AddSystem(&reporter.SnapshotCSV{
Observer: &ExampleSnapshotObserver{},
FilePattern: "../out/test-%06d.csv",
UpdateInterval: 10,
Observer: &ExampleSnapshotObserver{},
FilePattern: "../out/test-%06d.csv",
})
m.AddSystem(&system.FixedTermination{Steps: 100})

Expand Down
5 changes: 2 additions & 3 deletions reporter/csv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ func TestCSV(t *testing.T) {
m := model.New()

m.AddSystem(&reporter.CSV{
Observer: &ExampleObserver{},
File: "../out/test.csv",
UpdateInterval: 10,
Observer: &ExampleObserver{},
File: "../out/test.csv",
})
m.AddSystem(&system.FixedTermination{Steps: 100})

Expand Down
3 changes: 3 additions & 0 deletions reporter/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ type Print struct {
func (s *Print) Initialize(w *ecs.World) {
s.Observer.Initialize(w)
s.header = s.Observer.Header()
if s.UpdateInterval == 0 {
s.UpdateInterval = 1
}
s.step = 0
}

Expand Down
7 changes: 4 additions & 3 deletions reporter/print_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ func ExamplePrint() {

// Add a Print reporter with an Observer.
m.AddSystem(&reporter.Print{
Observer: &ExampleObserver{},
UpdateInterval: 10,
Observer: &ExampleObserver{},
})

// Add a termination system that ends the simulation.
m.AddSystem(&system.FixedTermination{Steps: 20})
m.AddSystem(&system.FixedTermination{Steps: 3})

// Run the simulation.
m.Run()
Expand All @@ -26,4 +25,6 @@ func ExamplePrint() {
// [1 2 3]
// [A B C]
// [1 2 3]
// [A B C]
// [1 2 3]
}

0 comments on commit 10b9588

Please sign in to comment.