diff --git a/README.md b/README.md index f93c103..f80e4f9 100644 --- a/README.md +++ b/README.md @@ -36,31 +36,35 @@ The sample app also keeps a running total of the last 25 `Moments` to allow for ### Type CycleMonitor records state as `Moments` over time with a schema of: - struct Moment { - var drivers: [Driver] - var cause: Driver - var effect: String - var context: String - var isApproved = false - - struct Driver { // Drivers are event producers - var label: String - var action: String - var id: String - } - } +```swift +struct Moment { + var drivers: [Driver] + var cause: Driver + var effect: String + var context: String + var isApproved = false + + struct Driver { // Drivers are event producers + var label: String + var action: String + var id: String + } +} +``` Each `Moment` provides its cause/effect as well as a list of the drivers/event-producers that were being recorded at the time. The moment's active driver/event-producer indicates itself as the cause by providing a non-nil `action`. A `Moment's` context/effect can conveniently be created using the reflective abilities of `Wrap` (`func wrap(_ object: T) -> [String: Any]?`). ### Broadcast As events are experienced on the client, they can be encoded as `Moments`, converted to JSON and broadcasted to the monitor. `MultipeerJSON` is provided as a convenience to make those broadcasts and is designed to consume a incoming stream of JSON encoded `Moments`. `MultipeerJSON` also buffers outgoing transmissions until a connection is established. - let moment = CycleMonitor.Moment(...) - let JSON = moment.coerced() as [AnyHashable: Any] - let transmitter = MultipeerJSON() - let responses: RxSwift.Observable<[AnyHashable: Any]> = transmitter.rendered( - RxSwift.Observable.just(JSON) - ) +```swift +let moment = CycleMonitor.Moment(...) +let JSON = moment.coerced() as [AnyHashable: Any] +let transmitter = MultipeerJSON() +let responses: RxSwift.Observable<[AnyHashable: Any]> = transmitter.rendered( + RxSwift.Observable.just(JSON) +) +``` ### Consumption If your application is designed to consume a single source-of-truth/state, it has the potential to disregard its version of that state and instead consume a new state injected remotely. `CycleMonitor` can send states to a client in order to review their rendering. However, converting incoming JSON to your application's `State` is not as easy as the inverse and requires traditional JSON serialization. Selecting the _Effects On Device_ tab begins the broadcast of a stream of JSON serialized `Moments` back to the client. @@ -68,8 +72,10 @@ If your application is designed to consume a single source-of-truth/state, it ha ### Validation Once the `effect` of a `cause` on a `context` is considered to be correct, that `Moment` can be serialized and further tested as development continues. To save `Moments`, select their checkbox in the timeline and then select `File > Export Tests`. Those files can then be imported into the client's Xcode project and tested. The sample app uses this single (pseudo code) process for all `Moments`: - // 1. deserialize all `.moment` files into the application's `Moment` types - // 2. assert that each `Moment's` `cause` applied to its `context` produces its `effect` +``` +// 1. deserialize all `.moment` files into the application's `Moment` types +// 2. assert that each `Moment's` `cause` applied to its `context` produces its `effect` +``` This approach only tests the business-logic/state-manipulation portion of the application, not the rendering of the resulting state via drivers.