# Visualise your FSM

It can be extremely useful to visualise you FSM and with that in mind FSM2 is able to export your FSM to the smcat format and then convert that to an svg file (image).

<https://github.com/sverweij/state-machine-cat>

Start by exporting your fsm2 file to an smcat file.

```dart
final machine = StateMachine.create((g) => g
    ..initialState(Solid())
    ..state<Solid>((b) => b
      ..on<OnMelted>((s, e) => b.transitionTo(
            Liquid(),
            sideEffect: (e) => print('Melted'),
          )))
   ));
await machine.export('/path/to/file.smcat');
```

#### Install

Next we need to install the visualisation tools.

```bash
pub global activate fsm2
fsm2 --install
```

#### Generate

Now you can generate svg files to show your fsm.

```bash
fsm2 /path/to/file.smcat
```

fms2 will now generate an svg file which you can view using any suitable svg viewer.

### Display

You now have two options to view the generated svg files.

#### Firefox

If you have firefox installed the fsm2 can automatically display the svg using firefox:

```bash
fsm2 --show /path/to/file.smcat
```

#### FSM2 Viewer

We have now created a flutter desktop application call fsm2\_viewer.

{% embed url="<https://github.com/bsutton/fsm2_viewer>" %}

![Desktop application for viewing all the svg pages of your FSM.](/files/-MOiog8zuauj0G8urq90)

#### Page Breaks

When you FSM gets large it can be had to analyse the entire statemachine one page.

FSM2 allows you to put page breaks into rendered image.

You can add a page break at any state of coregion.

```dart
final machine = StateMachine.create((g) => g
    ..initialState<S>()
    ..state<Alive>((b) => b
      ..initialState<Young>()
      ..onEnter((s, e) async => watcher.onEnter(s, e))
      ..onExit((s, e) async => watcher.onExit(s, e))
      ..on<OnBirthday, Young>(
          condition: (e) => human.age < 18, sideEffect: (e) async => human.age++)
      ..on<OnBirthday, MiddleAged>(
          condition: (e) => human.age < 50, sideEffect: (e) async => human.age++)
      ..on<OnBirthday, Old>(
          condition: (e) => human.age < 80, sideEffect: (e) async => human.age++)
      ..on<OnDeath, Purgatory>()
      ..state<Young>((b) => b..onExit((s, e) async => watcher.onExit(s, e)))
      ..state<MiddleAged>(
          (b) => b..onEnter((s, e) async => watcher.onEnter(s, e)))
      ..state<Old>((b) => b))
    ..state<Dead>((b) => b
      ..pageBreak
      ..onEnter((s, e) async => watcher.onEnter(s, e))

      /// ..initialState<InHeaven>()
      ..state<Purgatory>((b) => b
        ..onEnter((s, e) async => watcher.onEnter(s, e))
        ..on<OnJudged, Buddhist>(
            condition: (e) => e.judgement == Judgement.good,
            conditionLabel: 'good')
        ..on<OnJudged, Catholic>(
            condition: (e) => e.judgement == Judgement.bad,
            conditionLabel: 'bad')
        ..on<OnJudged, SalvationArmy>(
            condition: (e) => e.judgement == Judgement.ugly,
            conditionLabel: 'ugly'))
      ..state<InHeaven>((b) => b..state<Buddhist>((b) => b))
      ..state<InHell>((b) => b
        ..state<Christian>(
            (b) => b..state<SalvationArmy>((b) {})..state<Catholic>((b) => b))))
    ..onTransition((from, event, to) => watcher.log('${event.runtimeType}')));
```

In the above example the 'Dead' will appear on two pages. It will appear on page 1 as a simple state and it will appear on  page 1 as the parent state of any nested children. The blue border indicates a parent state whose contents is displayed on the next page.

![Page 1](/files/-MODgmGTY7RZzXn5A9-l)

![Page 2](/files/-MODgpOjOmrK_I8zlqNE)

#### Watch and refresh

Whilst working on you fsm it can be handy to see the latest version of the FSM.

You can use the fsm2 watch option to regenerate and display the latest svg file:

```bash
fsm2 -s -w /path/to/file.smcat
```

Now each time you regenerate the smcat file fsm2 will launch firefox with the latest version.

#### Script it

You can use [dcli](https://pub.dev/packages/dcli) to re-generate and display your smcat file on demand.

{% hint style="info" %}
Dcli is a library and tooling for creating cli apps using dart.
{% endhint %}

```bash
pub global activate dcli
cd /your/projectroot/tool
dcli create gen_smcat.dart
```

Dcli will create a sample script and a pubspec.yaml in the tool directory. Edit the pubspec.yaml in the tool directory to include your own project:

```bash
name: gen_smcat
version: 0.0.1
description: A script generated by dcli.
environment: 
  sdk: '>=2.9.0 <3.0.0'
dependencies: 
  args: ^1.0.0
  dcli: ^0.32.0
  path: ^1.0.0
  fsm2: ^0.10.0
  <your project name>:
    path: ..

dev_dependencies: 
  pedantic: ^1.0.0
```

Replace the contents of gen\_smcat.dart with:

```bash
#! /usr/bin/env dcli

import 'dart:io';
import 'package:dcli/dcli.dart';
/// path to script that generates fsm 
import '../cleaning_air_fsm.dart';
 
void main(List<String> args) {

  // replace 'createMachine' with a call to your method
  // that creates your fsm.
  
  var machine = createMachine();
  machine.export('cleaning_air.smcat');

}

```

To generate and visualise your FSM.

Open two terminal windows

Use the first terminal window to regenerate the smcat file each time you change your fsm.

```bash
tool/gen_smcat.dart
```

Use the second terminal to have fsm2 watch for changes and automatically display them.

```bash
fsm2 --show tool/cleaning_air.smcat
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://fsm2.onepub.dev/visualise-your-fsm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
