ElectronでSplatoon2のルール・エリア通知desktopアプリを作成する

# Splatoon2開幕

いよいよ待ちに待ったSplatoon2が開幕しました！皆さん楽しんでますか？
今回からルール・エリアの変更が2時間ごとになり，苦手なルール・エリアに当たってしまっても少し待てば好みのものが回ってくる可能性が高くなりました（もちろん逆も言えますが）．
事前にルール・エリアの変更予定がわかっていれば，遊び始めるタイミングをそこに合わせる等々できて嬉しいなと思い，今回はルール・エリア通知desktopアプリをElectronで作ってみることにしました~~twitterにもbotがありますが気にしない~~．

こんな感じの通知アプリを作りました．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/59864/5290b215-f2dc-e393-18a7-f1f83466aa4c.png)

なお，本記事，公開しているコードは非公式であり，任天堂株式会社とは一切関係ありません．



## Electron

[Electron](https://electron.atom.io/)とは，Atomエディタを開発するために生まれたCross Platform Desktop Application Engineです.
Node.js + HTML + CSSでアプリケーションを作成でき，同じコードでWindows，Linux，OS X用のアプリケーションを生成することができます．Electronを使ったアプリケーションの作り方は，すでに様々なサイトで紹介されていますのでそちらを参考にしてください．
今回は，デスクトップのメニューバーに表示するElectron製アプリをReactを使って作ってみます．


## Babel + Electron + Menubar + React + Browserify + SASS

今回はメニューバーに表示するアプリを作りたいので，Electronの[menubarプラグイン](https://github.com/maxogden/menubar)を使用します．
そして，コンテンツの設計はReactで行い，jsxやsassが変更された時は自動でリコンパイルが走って変更結果がリアルタイムに反映されるようにしてほしい．．．　というわがままにドンピシャで対応してくれるコードが．．．なんとこちらにあります．

https://github.com/itsnauman/electron-menubar-boilerplate

今回はこちらのコードをありがたく使わせていただくことにします．
本コードでは，

```
npm install -g gulp-cli electron-prebuilt
git clone --depth=1 --branch=master https://github.com/itsnauman/electron-menubar-boilerplate.git (project-name)
cd (project-name)
rm -rf .git
npm install
```

して

```
gulp serve
```

を起動しておくだけで，jsx，sassのリコンパイルからelectronアプリへの反映までを自動で行ってくれます．
client(コンテンツ)側(jsx, sass)のコードはapp以下，main(システム)側のコードはsrc以下に置き，更新がかかるとコンパイル後のコードがbuild以下に置かれるような設定になっています．

プロジェクト構成は以下のような感じ

```
project-name
  |- package.json
  |- gulpfile.js
  |- app
      |- index.html
      |- index.js
      |- index.scss
  |- src
      |- index.js
  |- node-modules
  |- build
```

なお，今回はapp以下の構成をjsxとscssで階層分けしたかったので，gulpfileを若干書き換えてあります．

(余談ですが，「boilerplate(ボイラープレート)」とは，もともとは活版印刷に使われた鋼板でできた鋳型のことを指し，そこから転じてIT分野では雛形プロジェクトのことを指します．なので今回のケース以外でも，boilerplate + 使いたい機能で検索すると，github等にあげられている非常にありがたいテンプレートプロジェクトが見つかることがあります．)

## イカルール・エリア通知desktopアプリ

今回作ったアプリのコードは[こちら](https://github.com/yukiB/Splarm)になります（アイコンやフォントは含んでいません）．masterはsplatoon用，feature/spla2ブランチはsplatoon2用になります．

### ルール・エリアの変更予定情報の取得

Splatoon2用エリア，ルール情報は，<https://splatoon2.ink/>(非公式)のものを使用しています．　apiとしては<https://splatoon2.ink/data/schedules.json>として使用可能です．詳しい情報はコードを参照してください．

## メニューバーへのアプリ設置

```index.js
// main側
const menubar = require('menubar')
const {app} = require('electron')

var mb = menubar({index: path.join('file://', __dirname, '/index.html'), width:300, height:200, preloadWindow:true})

mb.on('ready', function ready() {
  console.log('app is ready')
})
```

menubarプラグインを導入しておけば，electronでmain側で設定する必要があるのはこれだけで済みます．

```index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Splarm</title>
    <meta charset="UTF-8"> 
    <link rel="stylesheet" href="css/index.css" />
  </head>
  <body  bgcolor="#e5e5e5">
    <div id="container"></div>
    <script src="js/index.js"></script>
    <!-- build:remove -->
    <!-- Connect to server process -->
    <script>require('electron-connect').client.create()</script>
    <!-- end:build -->
  </body>
</html>
```

`require('electron-connect').client.create()`はgulp側で立てたserverへ接続するために記述しています．あとは`container` idのdivにreactでガンガンコンテンツを生成していくだけです．

index.htmlが呼び出している，client側のindex.jsは例えばこんな感じ

```index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Container from './components/Container'


ReactDOM.render(
  <Container />,
  document.getElementById('container')
)
```

### main側とclient側の連携

clientでpostした情報をmainに持って来たり，mainからclientに返すためには`ipcMain, ipcRenderer`を使います．　

```main.js
// main側
const {ipcMain} = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg)  // prints "ping"
  event.sender.send('asynchronous-reply', 'pong')
})

ipcMain.on('synchronous-message', (event, arg) => {
  console.log(arg)  // prints "ping"
  event.returnValue = 'pong'
})
```

```client.js
// client（web page）側
const {ipcRenderer} = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"

ipcRenderer.on('asynchronous-reply', (event, arg) => {
  console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')
```

`ipcRenderer.on`で非同期通信のreturn待ち，`ipcRenderer.send`で非同期送信です．簡単ですね．

### デスクトップ通知

デスクトップ通知もElectronなら簡単にできます．

```js
let n = new Notification("title", {body: "content", timeout: 2000});
```

で，以下のような通知を出すことができます．


![image.png](https://qiita-image-store.s3.amazonaws.com/0/59864/27919408-159e-c99f-d9a0-c8ec1831d8ed.png)


### アイコン変更

メニューバーのアイコンを変更するためにはルートディレクトリに`IconTemplate.png`をおいてください．menubarプラグインのデフォルトアイコンは猫マークですが，pngを設置することで変更できます．今回は24x24の画像を作成し，使用しました．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/59864/a1efe5a5-fe17-cba9-c3cd-b7ef2efbda01.png)


また，アプリアイコンや，デスクトップ通知時に表示されるアイコンを変更したい場合は，アプリとしてパッケージングする際に，

```shell-session

electron-packager . Splarm --platform=darwin --arch=x64 --icon=./path/to/icon
```

のようにパスを指定してあげればOKです（上はOSXの例）

### おまけ（フォントの修正）

最後にアプリの雰囲気を出すためにフォントを変えてみましょう．

Splatoonのフォントに近いものとして，

- イカモドキ（公開停止）・・・数字，ひらがな，カタカナ
- [paintball](http://fizzystack.web.fc2.com/paintball-ja.html)・・・アルファベット
- [チェックポイント](http://marusexijaxs.web.fc2.com/quizfont.html#quizfont2) ・・・漢字

があげられていたのでそちらを使うこととします(イカモドキは公開当時ダウンロードしていたものを使用しました)．

それぞれのttfファイルをリソースパスに配置し，

```css

@font-face {
	font-family: 'フォント名';
	src: url('フォントファイルのurl');
}
```

のように読み込んであげれば，以降font-familyに指定してあげることでフォントを読み込めるようになります．

最終的に以下のような様相になりました．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/59864/5aee289d-f7ea-fa31-22a9-7c138121d36c.png)



# おわりに

アプリを起動しておけば，自分の狙ったタイミングで遊べるようになります．
興味のある方はgitから落として使ってみてください．
ただ，手元の環境上OSX版しか挙動は確認できていませんのであしからず．

それではみなさん良いイカライフを！！