ダッシュボードも作れるStipple.jlの紹介

# Stippleの紹介

JuliaのWebフレームワークにGenieがあります。Juliaの機能を活かしており、とても使い心地の良いパッケージなのですが、英語/日本語問わずまだまだサンプルが少ない状態です。そんな中で[Genie.jl](https://github.com/GenieFramework/Genie.jl)の関連情報をあさっていたらJuliaCon 2020でGenieの作者の[Adrian Salceanu](https://live.juliacon.org/speaker/3MGMJN)さんが[Stipple](https://github.com/GenieFramework/Stipple.jl)というDashboardsの作成にも使えそうなWeb UI用パッケージを紹介されていました。Webサーバー越しにデータバインディングを実現している面白いパッケージなので、簡単に紹介したいと思います。

## インストール

GenieはWebサーバー用のフレームワークで、その上にStippleというパッケージがあります。この二つをインストールします。

```julia
pkg> add Genie
pkg> add Stipple
```

## 実行

Julia REPLで次のコードを実行します。

```julia
using Genie, Genie.Router, Genie.Renderer.Html, Stipple

# define (reactive) model
Base.@kwdef mutable struct Name <: ReactiveModel
  name::R{String} = "World!"
end

# initialize the model
model = Stipple.init(Name)

# define UI
function ui()
  page(
    root(model), class="container", [
      h1([
        "Hello "
        span("", @text(:name); style="color:red")
      ])

      p([
        "What is your name? "
        input("", placeholder="Type your name", @bind(:name))
      ])
    ], title="Basic Stipple"
  ) |> html
end

# bind root "/" to ui
route("/", ui)

# start web server
up()
```

`up()`を実行するとWebサーバーが起動します。環境にもよりますが、例えば下記のように表示されるので、ブラウザからアクセスしてみます。
```
Web Sockets server running at 127.0.0.1:8001

Web Server starting at http://127.0.0.1:8000

Web Server running at http://127.0.0.1:8000
Genie.AppServer.ServersCollection(Task (runnable) @0x0000000015eae850, Task (runnable) @0x00000000356d2e10)
```
![Stipple_example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171142/3658a5c0-7db6-4eb8-b352-524c3ab94958.png)

この時、Julia REPLに下記のようなエラーが出ることがありますが、たぶんfavicon.icoがないために出ているだけなので無視してokです。

```julia
[ Info: / 200
[ Info: / 200
┌ Error: error handling request
│   exception =
│    IOError: stream is closed or unusable
│    Stacktrace:
│     [1] check_open at .\stream.jl:328 [inlined]
      ...
│     [12] (::HTTP.Servers.var"#13#14"{HTTP.Handlers.var"#4#5"{HTTP.Handlers.RequestHandlerFunction{Genie.AppServer.var"#6#12"}},HTTP.ConnectionPool.Transaction{Sockets.TCPSocket},HTTP.Streams.Stream{HTTP.Messages.Request,HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}})() at .\task.jl:356
└ @ HTTP.Servers C:\Users\dskkato\.julia\packages\HTTP\atT5q\src\Servers.jl:373
[ Info: /css/stipple/stipplecore.min.css 200
[ Info: /js/stipple/vue_filters.js 200
[ Info: /js/stipple/stipplecore.js 200
[ Info: /js/stipple/vue.js 200
[ Info: /js/stipple/underscore-min.js 200
[ Info: /__/channels.js?v=1.1.0 200
```

## 動かしてみる

StippleのUI部分にはVueが使われているようで、コンポーネント間のデータを同期してくれます。また、Julia-REPLと双方向のデータバインディングを提供実現しています。一つずつ試して行きましょう。

### UIのコンポーネント間の同期

まずは先ほどの画面のテキストボックスにある`World!`を適当に`Julia!`に書き換えて見ます。すると、赤い文字の部分も入力に追従して自動で変化していきます。VueやReact等を触ったことある方ならなじみのある操作かと思います。

![Stipple_example2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171142/8bfc601f-3e72-85e6-a45e-c050a0d3ccec.png)

### Juliaとの双方向データバインディング

#### UI -> Julia

Stippleの目玉はこれかと思います。先ほど`Julia!`に書き換えた状態でmodelの状態を確認してみます。ちゃんと`Julia!`に更新されていますね。

```julia
julia> model
Name(Observable{String} with 1 listeners. Value:
"Julia!")
```

#### Julia -> UI

次にJulia側から操作してみます。この時、オリジナルのStringオブジェクトを書き換えたことが分かるように`[]`で参照を取ってきて更新する必要がある見たいです。

```julia
julia> model.name[] = "Julia-REPL"
```

下記のように書くと、Stippleがオブジェクトの更新をトラッキングできなくなるようで、うまく動かなくなるので注意が必要です。

```julia
julia> model.name = "Julia-REPL"
```

すぐにUIにも反映されます。

![Stipple_example3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171142/b843237f-18ae-4ebe-f82e-1217a9cd248a.png)

### カウントダウン

最後に、簡単なカウントダウンを動かしてみます。

```julia
for i in reverse(0:10)
  model.name[] = "$i"
  sleep(1)
end 
```

(画面はそのうちupします...)

## Stippleのポテンシャル

JuliaCon 2020での発表資料やDiscorseを見ているとダッシュボードを作れる程度には開発が進んでいるようです。多少HTMLのことを知らないと使いにくいかもしれませんが、簡単なGUIにも使えそうな印象を受けました。

Julia REPL->UIのフローはブロードキャストされているようで、マルチクライアントの状態でもすべての状態が更新されます。惜しむらくは、UI上での操作が他のクライアントに反映されませんでした。REPLからは出来ているので、大した問題ではないかもしれませんが。

## Demos (リポジトリから転載)

* [German Credits visualisation dashboard](https://github.com/GenieFramework/Stipple-Demo-GermanCredits)
* [Iris Flowers dataset k-Means clustering dashboard](https://github.com/GenieFramework/Stipple-Demo-IrisClustering)

## 関連情報

* [Stipple: Reactive data dashboards with Julia \[WIP\]](https://discourse.julialang.org/t/stipple-reactive-data-dashboards-with-julia-wip/37291) in Discourse.
* [repo](https://github.com/GenieFramework/Stipple.jl) on the GitHub
* [Interactive data dashboards with Julia and Stipple in JuliaCon 2020](https://live.juliacon.org/talk/8SZSBE)