OmniAICreator/Qiita-1.07M huggingface dataset:
Git LFS をソースツリーで

まさにこの記事の通りすぎます！


http://ipponshimeji.cocolog-nifty.com/blog/2017/03/sourcetreegit-l.html

注意点というか、まぁ細かいことですが、
LFSで管理するファイルを作成するのは、guiでの入力が発狂するほど、
面倒くさいので、

http://q7z.hatenablog.com/entry/2016/12/10/000222

のページからコマンドをコピーしてくるのが良いです。
MySQL8.0でSequel Proを使えるようにする

# 問題
[Sequel Pro](https://www.sequelpro.com/)がMySQL8.0ではクラッシュして接続できない

# 解決策
[Issue](https://github.com/sequelpro/sequelpro/issues/2699)を見ると、一旦アンインストールしてnightlyバージョン入れてねってことでアンインストールしてHomebrewでインストール。

```console
$ brew cask install homebrew/cask-versions/sequel-pro-nightly
```

<img width="173" alt="スクリーンショット 2018-09-22 5.14.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/211748/d15398ff-90d3-23fe-71f8-a17f2baac014.png">

アイコンの色がパンケーキっぽくなくなったけどインストール完了。接続してみる。

```console
$ mysql --version
mysql  Ver 8.0.11 for osx10.13 on x86_64 (Homebrew)
```

<img width="1539" alt="スクリーンショット 2018-09-22 5.25.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/211748/7520f12a-8386-51d3-5a8c-2ae6c19f3a1e.png">

<img width="1539" alt="スクリーンショット 2018-09-22 5.25.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/211748/64fd085c-d55f-71ef-a45d-023ae1e99c65.png">

無事接続できました。

# ※追記
**後継のSequel Aceが出たのでそちらを使いましょう**
https://github.com/Sequel-Ace/Sequel-Ace
Scalaで型パラメータそのものに対してpattern matchを行う方法

# 問題

scalaで型パラメータをまるで引数のようにしてパターンマッチしたい。

```scala
def func[T](): String = {
  // 理想的にはこう書けると嬉しい
  T match {
    case Int => "いんと！"
    case Long => "ろんぐ！"
    case _ => "そのた！"
  }
}


println(func[Int]) // いんと！
println(func[Long]) // ろんぐ！
println(func[Float]) // そのた！
```

## 2018/10/28 追記

[コメント欄](https://qiita.com/bigwheel/items/60d1fc40e3b14a5236f6#comment-41e086fccbf58f853837)で指摘して頂いた通り、型パラメータに対してpattern matchを行いたいという要望自体に問題がある可能性が高いです。
リンク先で書かれている通り、型クラス・ポリモーフィズムやoverloadingで解決したほうが良いケースは多いでしょう。

# 解決策

リフレクションのClassTagを利用する。
ただ、僕が調べた限りだとScalaの言語上の制約によりpattern match構文を使っても簡潔には書けない。

## 1. if-elseチェーンを使う

```scala
import scala.reflect._

def func[T:ClassTag](): String = {
  if (implicitly[ClassTag[T]] == classTag[Int])
    "いんと！"
  else if (implicitly[ClassTag[T]] == classTag[Long])
    "ろんぐ！"
  else
    "そのた！"
}
```

## 2. pattern match with if guardを使う

```scala
import scala.reflect._

def func[T: ClassTag](): String = {
  implicitly[ClassTag[T]] match {
    case x if x == classTag[Int] => "いんと！"
    case x if x == classTag[Long] => "ろんぐ！"
    case _ => "そのた！"
  }
}
```

## 3. 先頭が大文字の変数へ一度代入を行ったのちpattern matchを行う

```scala
import scala.reflect._

def func[T: ClassTag](): String = {
  val IntClassTag = classTag[Int]
  val LongClassTag = classTag[Long]
  
  implicitly[ClassTag[T]] match {
    case IntClassTag => "いんと！"
    case LongClassTag => "ろんぐ！"
    case _ => "そのた！"
  }
}
```

# 蛇足

これら以外のパターンやもっと簡潔に書く方法があればぜひ教えてください。
Microsoft Cloud App Security で Office 365を監視 その１

# 初めに
MicrosoftのCASB製品であるCloud App Security（以下 MCAS）ですが、いままでOffice 365などの運用で悩みの種だった「ユーザーが変なことをしていないか」ということを監視、コントロールすることができます。
しかし、実際に何ができるかわからないという意見も多いです。
ここでは実際にMCASのAPI連携で何ができるのか一つ一つひも解いていこうかと思います。

#概要
今回はわかりやすいところでポリシーテンプレートをそのまま利用してユーザー動作を監視します。
ユーザーの不正な操作として、退職前に大量データのデータをSPSやOneDriveからダウンロードすること監視します。該当の操作があった場合、警告がアラート一覧に表示されます。

##必要ライセンス
　Microsoft Cloud App Security、Office 365 Cloud App Security
　（※ Office 365 Cloud App Securityでは機能が制限されます）

#設定と動作確認
それでは実際に設定して動作をみていきます
##設定
1. MCASの管理コンソールに移動します。
2. [制御]-[ポリシーを選択します]
![スクリーンショット (52).png](https://qiita-image-store.s3.amazonaws.com/0/262585/013d3b01-7dd9-3f27-8694-369bedda6427.png)
3. [ポリシーの作成]-[アクティビティポリシー]を選択します。
![スクリーンショット (53).png](https://qiita-image-store.s3.amazonaws.com/0/262585/a5555b21-51f4-62ff-3dc4-e000d588c545.png)
4. ポリシーテンプレートから[単独ユーザーによる大量ダウンロード]選択します。上書きするポップアップが出たら適用します。
![スクリーンショット (55).png](https://qiita-image-store.s3.amazonaws.com/0/262585/aed55339-bd2e-d556-b690-30f35b7323f2.png)
5. [ポリシーのフィルターを作成する]から[反復アクティビティ]の[反復アクティビティの最低回数]を変更します。ここでは後ほど確認しやすいように5回に減らしておきます。
![スクリーンショット (61)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/262585/e1f5db12-0514-511c-0e10-ae5727746f8a.jpeg)
6. そのままスクロールして作成を選択します。
![スクリーンショット (59).png](https://qiita-image-store.s3.amazonaws.com/0/262585/5c9c8233-242d-24f2-ff4e-08b8337e40bc.png)
7. ポリシーの一覧に作成したポリシーが表示されていることを確認してください。
![スクリーンショット (63)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/262585/3a1bc5d1-05e8-5a6f-b3ec-76712f84ced6.jpeg)


##動作確認
1. OneDriveに移動します。あらかじめ10個程度のファイルをアップロードしておきます。
ファイルを複数選択してダウンロードします。
2. MCASの管理コンソールに移動します。10分ほどするとアラートが表示されます。

#まとめ
今回はNCASのポリシーテンプレートで簡単な監視を行ってみました。
他にもいろいろやってみようと思います。

#リンク
##MCASシリーズ
　
##関連リンク
[DOCS:Microsoft Cloud app Security アクティビティ ポリシー](https://docs.microsoft.com/ja-jp/cloud-app-security/user-activity-policies)
CentOS7  WordPress インストール

<https://www.server-world.info/query?os=CentOS_7&p=initial_conf&f=1>

'''
[root@localhost ~]# useradd mmserver
[root@localhost ~]# passwd mmserver 
Changing password for user mmserver.
New UNIX password:              # 設定したいパスワードを入力
Retype new UNIX password:       # パスワード再入力
passwd: all authentication tokens updated successfully.

[root@localhost ~]# usermod -G wheel mmserver
'''

SSH設定
'''
[root@dlp ~]# vi /etc/ssh/sshd_config

'''
'''
[mmserver@ik1-340-30343 ~]$ mkdir -p ~/.ssh
[mmserver@ik1-340-30343 ~]$ vi ~/.ssh/authorized_keys
[mmserver@ik1-340-30343 ~]$ chmod 700 ~/.ssh
[mmserver@ik1-340-30343 ~]$ chmod 600 ~/.ssh/authorized_keys
'''

publickey再作成
<http://wright.mydns.jp/?p=795>


<https://qiita.com/fk_2000/items/019b62818e34be973227>


WordPressインストール
'''

'''

<https://qiita.com/ikenyal/items/b599d7a29d884e67b3a9>


日本語化
<https://eng-entrance.com/linux-localization-lang>


ドメイン設定
<http://www.machiiro.jp/2015/06/08/domain/>
Docker for Windowsのダイアログの内容が表示されない（真っ白になる）

# 事象
Docker for Windowsの各種ダイアログの内容が表示されない
（動作はしているようだが、ウィンドウの中身が真っ白）

Docker for Windowsインストーラ実行時のダイアログも同様。

# 解決策
1. Duet Displayを使っている場合はアンインストールして再起動
2. 1.で治らなければ電源オプションをデフォルトに戻してみる

私の環境では1.で治りました。
同じ事象に悩まされてる人が減りますように。

## 事象確認および解決した環境
- Duet Display 1.5.2.1
- OS(Version): Windows 10 Pro (1803)
- OS build: 171134.286

# 原因
https://github.com/docker/for-win/issues/1736#issuecomment-413812187
によれば、
Duet Displayに互換性のないハードウェアアクセラレーション機能を使うアプリケーションにおいて、一般的な事象らしい。
私はDuet Displayを使い始めて日が浅かったので、気づくのに時間かかった。

# 参考
https://github.com/docker/for-win/issues/1736
https://forums.docker.com/t/blank-dialog-boxes-after-new-docker-install/46729
本当にSSRする必要があるのか考えてみた話

## まえがき

今回タイトルにしたSSRというのは、Server Side Renderingのイニシャルで、広義にはテンプレートエンジンを用いてサーバーサイドでHTMLを生成する手法も含まれるとは思いますが、以下説明しているSSRはクライアントで組み立てていたVirtualDOMをサーバーサイドで組み立てるアプローチのことを指すという認識でお願いします。

まずSSRは一体何を解決するためにあるのか、そこから考えていこうと思います。

## SSRまでの経緯

だいぶ省略しますがページを表示するまでのパターンを考えます。

もっともシンプルなのは、HTMLファイルを直接返すアプローチです。

![HTML (1).png](https://qiita-image-store.s3.amazonaws.com/0/252348/5eae930c-513a-0b91-4aaf-1e79b9d08c0f.png)

サーバーはHTMLファイルを返すだけだし、クライアントはHTMLをパースしたら表示するだけです。
CSSを使えばインタラクティブに見せることもできます。テンプレートエンジンやタスクマネージャーなどを使えば、共通化したりもできます。

しかし次第に動的にサーバー通信を行って、その結果をユーザーに見せたり、入力を受け付けるようなページを作りたくなってきます。そしてJavascriptを用いて、ユーザーの入力やデータの更新などに反応してDOM構造を操作したりするようになってきました。

![HTML+JS (1).png](https://qiita-image-store.s3.amazonaws.com/0/252348/e1ecea60-53ee-7651-55a6-f9610b36ced0.png)

最初はJQueryなどでうまくまわっていましたが、例えばインタラクションが複雑になるにつれてDOMの操作に時間がかかるようになりVirtualDOMを描画するReactのようなライブラリが出てきたり、データが複雑になるにつれて、MVCの分離が提唱されFluxやReduxのようなフレームワークがでてきました。しかし、それにあわせてJavascriptファイルの重さがかなりのものになってきました。

このようなCSR(Client Side Rendering)の場合、Javascriptファイルを読み込み、実行するまでの時間ユーザーは待たされることになります。

一般に、ネットワークIOよりも、ディスクIO、CPU時間の方が圧倒的に速いので、サーバー側で、ユーザーに描画するDOMを組み立てて返した方が速い、これが、SSRが出てきた経緯だと考えます。

![SSR.png](https://qiita-image-store.s3.amazonaws.com/0/252348/8d8af596-674b-fefa-64ff-726d23a70f57.png)

## メリット・デメリット

たぶんこの記事は見る人によってかなり多様なケースがありえると思うので、おそらくどんなケースにも当てはまりそうなことだけ書こうと思います。

SSRは主には[FMP(First Meaningful Paint)](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint?hl=ja)のスコアを上げるためのアプローチだと考えられます。
なので、SEO対策をする必要があるサービス（ブログなど）や高速化にリソースを割けるときには有効なアプローチです。

ちなみにSEO対策、というのもいろんなものがあるのですが、上で言っているのは[モバイル検索順位に表示速度も影響する](https://webmasters.googleblog.com/2018/01/using-page-speed-in-mobile-search.html)ことに関してです。

GoogleのクローラーはJavascriptを解釈できるようになっているので、Javascriptを読み込まないと表示されないコンテンツを指してのSEO対策はSSRをしようがしまいが条件は変わらないためメリットとはいえません。

逆に言えば、そこに対してメリットがないサービスにSSRを使おうとしている場合、サービスが複雑になる以上にリターンが少ないケースが多いと思います。おそらくこれは大きなデメリットだと思います。

SSRにしたからといって、ユーザーの入力などに反応するにはクライアント側でJavascriptでハンドリングしないといけないですし、URLをまたいでも1つのアプリのように見せるSPAの場合、どのページにどのように移動してもクライアント側の状態とサーバー側の状態が必ず一致するようにAPIを設計しないといけないですし、常に気をつけなければいけません。これはかなり苦労すると思います。

## さいごに

実は今[next.js](https://nextjs.org/)を触っていて、それに関する記事を書こうと思っていたのですが、触っている中で~~自由度が低く複雑なわりに解決できることが少ないなと思い始めたので~~、SSRとは何か、何のためのものか、本当に必要なのかと考えをまとめるためにこちらの記事を先に書きました。誤りなどあればコメントお願いします。

追記(2020/02/26)
Next.jsに関しては現在かなり洗練されてきているように感じていて、Next.jsのために覚えなければならないことは少なからずあるもののそこまで多くなく、(単語にするとpagesディレクトリ、publicディレクトリ、getInitialPropsくらい)多様な利用方法にも対応できるような設計になっているので、react + webpack-dev-serverとかで開発を始めようと思っているくらいのノリなら迷わずNext.jsを使って見ることをおすすめします。

みなさんの思考の手助けになると幸いです。

追記(2020/05/24)
[Next.jsで開発中のブログサービス(Minimal Blog)](https://blog.minimalcorp.com/)も参考にしてみてください。
nodeのバージョンをアップデートする方法

備忘録。nodeのバージョンをアップデートするには、下記コマンドを実行する。

#nvmを利用している場足
```bash
$ nvm install 8.x --reinstall-packages-from=node
```

#Homebrewを利用している場合
```bash
$ brew update && brew upgrade node
```
端末の位置を測定する方法とそれぞれの方法の比較（GPS、Wifi、携帯電話ネットワーク）

ラズパイを使って子供の見守りツール(*1)を作ろうと思いつきました。

「位置情報取得はＧＰＳ受信モジュールをＯＫ！」なんて思っていたのですがそんな単純なものでもなさそうです。
市販されている製品は「Wi-Fiアクセスポイントからも位置情報を取っているので精度高い」とアピールしていたのでそのあたりを調べたら良記事がゴロゴロしてました。

元記事はテキストだけで読みづらかったので抜粋して表に整理してみました。

**本記事のまとめに利用した記事**
[GPSのよくある疑問や誤解｜I.D.A Online](https://www.ida-japan.co.jp/gpsknowledge/gpsknowledge2.html)

**その他の有用記事（より詳細な方法）**
[位置情報を取得する仕組み：位置情報を使ってみよう](http://www.atmarkit.co.jp/ait/articles/0902/12/news135.html)
[GPSを使わない位置情報取得を検証してみた](https://www.ydc.co.jp/column/0002/20171108.html)
[Wi-Fi マックアドレスから位置取得 – マルティスープ株式会社](https://maps.multisoup.co.jp/blog/1088/)
[Wi-Fiだけでも現在地を測定できる仕組みとは？](http://www.appbank.net/2013/02/24/iphone-news/552221.php)

# 測定に利用されている技術・特徴・長所・短所
位置情報の測定に利用されている方法はGPSだけではなく無線LANと携帯電話ネットワークも活用できます。
それぞれの方法の概要と長所・短所（主に精度、測定速度）をまとめました。

| 技術名|概要|長所| 短所 | 
|:-----------------|:------------------|:------------------|:------------------|
|GPS|3つ以上のGPS衛星+時刻合わせ衛星.<br>GPSから電波と発信時間を受け取って計算で位置を特定する。|最も精度が高い(数m) | 測定が遅い<br>室内では利用不可。ビルや木など障害物に弱い。(*2)  |
|無線LAN(Wi-Fi)|端末の周囲にある無線LANアクセスポイントを特定して、サーバーに記録されたアクセスポイントの位置情報から推測|・室内でも利用可能<br>・測定が速い。精度はまずまず(10-200m)|アクセスポイントが必要|
|携帯電話ネットワーク|基地局の位置と携帯電話との距離を計算して場所を推定|屋内利用可能。測定が速い|精度が低い|
|方位センサー＋車速センサー|カーナビ限定。トンネル内のようにGPSが利用できない場合に推測。|GPSがなくてもOK|自作困難(徒歩で移動している人の速度取得できない）|

※その他、地磁気を使った方法なども実用化されているようです。
[GPS電波が届かない空港施設内でもナビ、NTTデータが地磁気を利用：測位の誤差は平均3メートル](http://www.atmarkit.co.jp/ait/articles/1809/21/news078.html)

## (*1)子供の見守りツール
以下のような構成でいけるかな？と。

<端末側>
- ラズパイ Zero
- GPS受信機
- モバイルバッテリ－
- ソラコムSIM
- Pythonプログラム(サーバ側のAPIを使ってリアルタイムでデータ送信）
- 収納ケース

<サーバ側>
- API Gateway
- Lambda
- RDS
- Webアプリ（Linux + nginx + Nodejsとか？）

ちなみに自作は面倒だったり非エンジニアの方にはピッタリのグッズが市販されています。

＜Bsize　みまもりGPS＞　月額480円、端末4,800円　初期費や解約手数料・N年縛りなし
https://www.bsize.com/bot/gps/

使い勝手など評判も良さそうです。
[テレビでも話題！超安価な、みまもりGPS [Bsize GPS BOT]を試す](http://luchs.fxproject-blog.com/gps-bot/)

ちなみに、ソフトバンクからも[みまもりGPS](https://www.softbank.jp/mobile/service/mimamorigps/)なる同様の端末が販売されていますが、初期費用（端末代、事務手数料）が高額で契約に二年縛りがあったりするのでおすすめできません。

## (*2)GPSの精度が落ちるケース
以下のような状況だと精度が落ちるそうです。

- ビルなどの近くや谷間 
- トンネルや森の中 
- 高圧電線や1.5GHz 帯の携帯電話などの近く 
- 長い距離を移動したとき
- 周囲の環境が異なる場所へ移動したとき
- 天候(曇りや雨の日は空が雲で覆われているので、通常の晴れている日より精度が落ちる）
CuPyを使った二次元FFTの高速化

先日のGTC2018でnumpyのFFTがCupyで動くということを知りました

以前、numpyで二次元FFTをやっていて遅かったので、どのくらい改善するのかトライしてみました

**結論から言うと、データが大きいかCPUがしょぼい場合はGPUを使った方が早いです**

#機材
　1)8086K + GTX1070
　2)6500 + GTX960
　3)Jetson TX2

#環境
機材1),2) 
　OS:Windows10
　GPUのドライバー：399.07
　CUDA:9.0
　CuDNN:v7.1
　python:3.6.6
　CuPy:4.1.0
　numpy:1.15.1

機材3)
　Jetpack：3.3
　python:3.5.2
　CuPy:4.4.1
　numpy:1.15.0

 


#numpy

```python
import CV2
import numpy as np

#画像の読み込み
img = cv2.imread(image, 0)
#リサイズ
img = cv2.resize(img, (200,200))
#float32に変換
img = img_fft.astype(np.float32)

#2次元FFT処理
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
ms = 20*np.log(np.abs(fshift))

#uint8に戻す
ms = ms.astype(np.uint8)

```



#CuPy

GPUへの行きと帰りを書くだけでOKです

```python
import CV2
import numpy as np
import Cupy as cp

#画像の読み込み
img = cv2.imread(image, 0)
#リサイズ
img = cv2.resize(img, (200,200))
#float32に変換
img = img_fft.astype(np.float32)

#GPUに送る
f = cp.asarray(img)

#####ここからGPU#####
#2次元FFT処理
f = cp.fft.fft2(f)
fshift = cp.fft.fftshift(f)
ms_gpu = 20*cp.log(cp.abs(fshift))
#uint8に戻す
ms_gpu = ms.astype(cp.uint8)
#####ここまでGPU#####

#CPUに戻す
ms_cpu = cp.asnumpy(ms_gpu)

```

#性能比較（1回目）
200pix,200pixの画像960枚を変換

|CPU|GPU|numpy(sec)|CuPy(sec)|%|
|---|---|---|---|---|
|8086K|GTX1070  |0.78|1.72 |220%|
|6500|GTX960|0.91|1.93|212%|
|Jetson  |TX2|8.11|3.32|-60%|

キャッシュに乗るくらいだとCPUの方が早い模様
Jetsonはこの時点でかなりの高速化


#性能比較（2回目）
800pix,800pixの画像960枚を変換

|CPU|GPU|numpy(sec)|CuPy(sec)|%|
|---|---|---|---|---|
|8086K|GTX1070  |12.44|4.80 |-61%|
|6500|GTX960|14.19|8.09|-43%|
|Jetson  |TX2|126.05|20.63|-84%|

このくらいになってくるとPCでもGPU使用が圧勝
Firebaseコマンドが実行出来ない場合の対処法


先日、同期2人とWebアプリ作成しよう！と意気込み、手始めにFirebaseを利用してWebサイトのデプロイに挑戦してみました。
しかし、何度Firebaseのコマンドを実行しても`-bash: firebase: command not found`が表示されてしまい実行出来ない・・・。(自分だけでなく2人とも)

同じような事例が調べても見つからず困りましたが、無事に解決出来たのでメモしておきます。
##簡単にFirebaseについて説明
FirebaseとはMBaaS (Mobile Backend as a Service)と呼ばれるクラウドサービスの一種。
バックエンドの処理をFirebaseのサービスに担ってもらうことで、アプリ開発者はフロントエンドの開発に注力することができます。

##Firebaseを始めてみた
Firebaseの利用手順については、[Firebaseの始め方](https://qiita.com/kohashi/items/43ea22f61ade45972881)や[Firebase 入門 - 環境を整える](https://qiita.com/t_furu/items/562f0cd4eff72e76b954)などのサイトを参考にしました。

上記のサイトなどを参考にして、
1. [Node.js](https://nodejs.org/en/)をインストール
2. [Firebaseコンソール](https://firebase.google.com)でプロジェクトを作成
3. `npm install -g firebase-tools`でCLIのインストール
といった順序で、CLIのインストールをするところまでは順調に進みました。
##Firebaseのコマンドを実行しようと思ったら・・・・
ところが、Firebase CLIのインストールが完了後、
ターミナルでFirebaseのコマンドを実行してみると・・・

```
$ firebase login
-bash: firebase: command not found
```

あれ・・？実行出来ない・・・？
サイトの手順通りに試したのに・・・

正しくインストールをしたつもりでしたが、この時点で
`firebase login` `firebase init` `firebase version` 
などのコマンドも実行出来ませんでした。
##npmのPATHが問題
結論から言うとインストールしたnpmのPATHに問題がありました。

コマンドが実行できない場合はまず、ターミナルで`npm bin -g`実行し、
グローバルディレクトリの場所を確認しましょう。

```
$ npm bin -g
/Users/ユーザー名/.npm-global/bin
(not in PATH env variable)
```
`not in PATH env variable`はnpmのPATHが通っていないことを意味します。

もし、上記のような表示が出ていた場合、Firebaseコマンドを実行する前に

```
$ export PATH=$PATH:`npm bin -g`
```
このようにPATHを通せばFirebaseコマンドを実行できるようになります。

もし`npm bin -g`を実行して、上記のようなPATHが帰ってこなかった場合は、
npmのインストールに問題がありFirebaseのコマンドが実行出来なかったと考えられます。
##終わりに
「Firebase コマンド 実行できない」などで調べてもなかなか解決策が見つかりませんでしたが、
結局のところnpmの問題だからなんですね。

npmのPATHについて書かれてる記事は色々見つかりました。
下記の記事も参考にしてください。
###参考
[Windows で Node.js を始める時のあれこれ](http://iwa4.hatenablog.com/entry/2013/04/24/173352)
[グローバルにインストールしたnode moduleがnot foundになる時の対処](https://qiita.com/joe-re/items/12987cdeee506dea3889)
[Movable Type]特定のコンテンツタイプのデータを丸ごとブログ移動する、ほか

## 環境
- Movable Type 7 r4208

管理画面からはできないので、SQLで行う。
すべて自己責任で。

## コンテンツタイプを丸ごとブログ移行
コンテンツタイプID=5のタイプとデータを丸ごとブログID=6に移動する場合。
コンテンツタイプIDやブログIDはURL等から推測。

```sql
UPDATE mt_content_type SET content_type_blog_id = 5 WHERE content_type_id = 6;
UPDATE mt_cf SET cf_blog_id = 5 WHERE cf_content_type_id =6;
UPDATE mt_cd SET cd_blog_id = 5 WHERE cd_content_type_id =6;
```

## テンプレートをブログ移行
テンプレートID=209をブログID=5に移行する場合。
テンプレートIDやブログIDはURL等から推測。

```sql
UPDATE mt_template SET template_blog_id = 5 WHERE template_id =209;
```

## テンプレートをブログまたいで複製
テンプレートID=198をブログID=5に複製する場合。
テンプレートID以外を選択してINSERT。

```sql
INSERT INTO mt_template (`template_blog_id`, `template_build_dynamic`, `template_build_interval`, `template_build_type`, `template_created_by`, `template_created_on`, `template_identifier`, `template_linked_file`, `template_linked_file_mtime`, `template_linked_file_size`, `template_modified_by`, `template_modified_on`, `template_name`, `template_outfile`, `template_rebuild_me`, `template_text`, `template_type`, `template_current_revision`, `template_content_type_id`)
SELECT 5, `template_build_dynamic`, `template_build_interval`, `template_build_type`, `template_created_by`, `template_created_on`, `template_identifier`, `template_linked_file`, `template_linked_file_mtime`, `template_linked_file_size`, `template_modified_by`, `template_modified_on`, `template_name`, `template_outfile`, `template_rebuild_me`, `template_text`, `template_type`, `template_current_revision`, `template_content_type_id`
FROM `mt_template`
WHERE template_id=198
```

## その他
同じような方法でページやブログ記事等のデータ（主にmt_entryテーブル）を移行できるのではないかと思う。
ブログ記事についてはカスタムフィールド（mt_field/mt_entry_metaなど）に注意。
テーブルのカラムを削除して、新しいカラムを入れる

#生成されたマイグレーションファイルの名前を統一するために
順番を指定せずカラムを追加し、その後そのカラムの名前を変更したのですが、
***rename_column***の名前でカラム名変更のマイグレーションファイルを作りました。
しかし***add_column***の名前のマイグレーションファイルで統一してとのこと。

一旦カラム（とカラム作成時にできたマイグレーションファイル）を削除して、
もう一度カラムを追加（add_columnのマイグレーションファイル名で）したので、
その備忘録として書いてます。

#カラム名を元に戻す⇨カラムを削除する
①```$rake db:migrate:status```　
上記でこれで現在のマイグレーションファイルの状態を表示。

upと表示されてるマイグレーションファイルはDBに反映されているってことです。

なのでrollbackして、ファイルを削除していきます。

```$rake db:rollback```

上記コマンドによってDBに反映される前の状態に戻ってます。
この後に再度下記コマンド。

```rake db:migrate:status```

すると、マイグレーションファイルがdownとなり読み込む前の状態に戻っています（```rails db:migrate```する前の状態）。
downとなっているのを確認できたら、removeコマンドでそのマイグレーションファイルを削除しましょう。

*rake db:rollbackは、downメソッドが呼び出されて1つ前のバージョンの状態に戻すことができます。

今回は「カラム追加」、「カラム名変更」の２回分ロールバックして、それぞれのファイルを削除しました。

#カラム追加時に順番を指定
カラムとマイグレーションを削除したので、
新しいカラムを追加します。

```$rails generate migration AddColumnToUsers```
みたいに入力。

作成されたマイグレーションファイルにカラム順を指定する。

```migration_file.rb
class AddColumnToUsers < ActiveRecord::Migration
  def change
    add_column :users, :batch_feeling_on, :datetime, after: :score　　←batch_feeling_onカラム（datetime型）の順番をafter:でscoreカラムの後に指定。
  end
end
```

で、```rails db:migrate```

これでOK。

##やったことまとめ（メモ）

###rollbackする
１回目の　```rake db:rollback``` でカラム名が元に戻った
（rake db:migrate:statusで確認）

２回目の　```rake db:rollback``` でカラムを追加する前の状態に戻った
（rake db:migrate:statusで確認）

それぞれdown（DBに反映されてない）になったこと確認したので、
次にマイグレーションファイルをそれぞれ削除。

###マイグレーションファイル削除
①カラム追加したマイグレーションファイル
```$rm db/migrate/20180914044143_add_column_to_users.rb```

②カラム名変更したマイグレーションファイル
```$rm　db/migrate/20180920015211_rename_batch_feeling_column_to_users.rb```

###あとは普通にカラム追加
```$rails generate migration AddColumnToUsers```

このコマンドでマイグレーションファイル作成される。
作成されたマイグレーションファイルの中に、
```after: :追加するカラムの前に置くカラム``` のようにして順番を指定。


なお下記コマンドで最初からカラム名とデータ型を指定することが可能
```$rails generate migration AddColumnToUsers batch_feeling_on:datetime　　　``` 
          ****batch_feeling_on:datetime：***の後に半角いらない！！
こうすれば、最初からカラム名とデータ型が記入済みのマイグレーションファイルが作成される。


参考
https://joppot.info/2014/10/14/2073
https://qiita.com/akira-hamada/items/91c5589e52e247ba8b8b
https://www.rubylife.jp/rails/model/index8.html
php-master-changes 2018-09-21

わりとドキュメント修正の多い日
今回より下位バージョンからのマージの場合は適用バージョンもなるべく入れるようにしてみたけど、書き方はそのうち変わるかもしれず

# 2018-09-21
## sebastianbergmann: Fix
- https://github.com/php/php-src/commit/a3117998648c61f6094d0feaac02f108c8c58f6a
- UPGRADING の integral を integer に修正

## sebastianbergmann: Fix
- https://github.com/php/php-src/commit/72231ed74746f09fb3096761b77cb5130309ca1e
- UPGRADING の 関数名に () を追加
- 以前若者にプログラミング教えた時、関数名に () 付けるの (笑) みたいで気になると言われたのを思い出すなど（後々慣れました）

## petk: Remove HAVE_TIME_H
- https://github.com/php/php-src/commit/a1b5698d4e3aa8514752b1fdc9a001952f984398
- C89 前提で time.h はあるだろ、というので autoconf でチェックして定義するマクロ HAVE_TIME_H を削除

## petk: Fix permissions
- https://github.com/php/php-src/commit/bfa2c7158ffb8af0ad9d71028992485059c7027d
- [7.3~]
- 実行許可のいらないファイルから実行許可ビットを外した

## cmb69: Update NEWS and UPGRADING wrt. PR 2760
- https://github.com/php/php-src/commit/7b9b398daad24d8829df487131bdf5d266e34f74
- [PR 2760](https://github.com/php/php-src/pull/2760) に対応して NEWS と UPGRADING を更新

## weltling: Upgrade PCRE2 to 10.32
- https://github.com/php/php-src/commit/91b2b6c65d544f39c45498ebafbab84b81d465b5
- PCRE2 を 10.32 へ更新

## weltling: Fixed bug [#76909](https://bugs.php.net/bug.php?id=76909) preg_match difference between 7.3 and < 7.3
- https://github.com/php/php-src/commit/7a02ecb7fef994332d83dae56ac5584d536f3de0
- [7.3~]
- preg_match() が 7.3 とそれ以前で挙動が違うのを修正
- バンドル版の PCRE2 へ[上流からのパッチ](https://bugs.exim.org/show_bug.cgi?id=2321)を適用した形

## weltling: Add test for bug [#76909](https://bugs.php.net/bug.php?id=76909)
- https://github.com/php/php-src/commit/9c58ab37c78d596fcbda1c1c6d53698aa3119024
- [7.3~]
- ↑のバグ修正にテストを追加
google-home-notifier + VoiceTextで警告音と音声がかぶらないようにする

Google Homeに任意のテキストをText-To-Speechでしゃべらせるgoogle-home-notifier、これの音声品質がイマイチってことで、HOYAの[VoiceText Web API](https://cloud.voicetext.jp/webapi)を利用する方法が提案されています。我が家でもこちらのスクリプトを流用させていただいています（ありがとうございます）。

がじぇねこ [Google Homeで好きな言葉を話してもらう その2(VoiceText)](http://gadgetneko.blog.jp/archives/5326857.html)

VoiceTextのAPIにテキストを渡すと、WAVなりMP3なりの音声ファイルが帰ってくるので、それをHTTP参照可能な場所（OUT_PATHに定義）に保存し、URLとして返すということをするのがVoiceTextWriter.jsです。

さて、いつからかわかりませんが、音声再生前に鳴る「ディン！」という「これからメッセージを鳴らすよ！」的な警告音と音声がかぶってしまってメッセージ冒頭が聞き取りづらいという点に気付きました。どちらかというと鳴らされるより鳴らす立場の使い方が多く気付いてなかっただけかもですが、セットアップした頃はそんなことなかったと思うんですよね。

まぁ気になり出したら気になるので、

- APIに投げるテキストの最初にスペースやカンマ、ハイフンなどを入れて無音区間が作れないか？
- 音声再生のタイミングを指定するようなパラメーターを探す
- 「ディン」を消せないか？

など試行錯誤したものの不発。そもそもディンは誰が鳴らしてるのかもわからないし、なんと呼ぶのかもわからないのでググるのも難しい。少なくともVoiceTextWriter.jsやVoiceText Web APIではなく、google-home-notifierか、音声を流し込まれたGoogleHomeの規定動作なんでしょうけど、、

# SoXで音声冒頭に無音区間を挿入する
ということでもっと簡単に指定できるパラメーターがあるかもとは思いましたが、思いつく方法として、生成された音声ファイルを音声ツールのSoXで加工して冒頭に無音区間を挿入する、という荒技で乗り切ってみました。

我が家はCentOSで運用していて、SoXは

```
yum install sox
```

でサクっと入りました。Raspbianでもapt-getなどですぐ入れられるんじゃないかと思います。
そしてVoiceTextWeiter.jsを以下のように改変します。
冒頭のパス定義にDELAYER_PATHを追加（2行目）。パスは環境にあわせていただき、ファイル名をOUT_PATHのものと違えておきます。ここでは「_temp2.wav」とします。OUTPUT_URLのファイル名はDELAYED_PATHのものに合わせます。そして一番最後のelseブロックのfs.writeFrileSync()（音声ファイル保存）とresolve()（URLを返す）の間にSoX実行コードを挿入します。

```javascript:VoiceTextWriter.js
// ... 冒頭部分
var OUT_PATH = '/home/xxx/google-home/api-server/public/voice/_temp.wav'
var DELAYED_PATH = '/home/xxx/google-home/api-server/public/voice/_temp2.wav' //追加
var OUTPUT_URL = 'http://xxx.xxx.xxx.xxx:12345/googlehome/_temp2.wav'; //ファイル名を上記にあわせる

// ... 略
// ... 最後の方のelseブロックの中

	    }else{
   	    	 fs.writeFileSync(OUT_PATH, buf, 'binary');

   	    	 // SoXを実行するコード（ここから）
   	    	 const exec = require('child_process').exec;
   	    	 exec('/usr/bin/sox ' + OUT_PATH + ' ' + DELAYED_PATH + " delay 0.7", (err,stdout,stderr)=> {
                      if (err) { console.log(err); }
                                    console.log(stdout);
                      });
   	    	 // SoXを実行するコード（ここまで）

   	    	 resolve(OUTPUT_URL);
	    }


```

ちなみに、ここで実行しているSoXのコマンドは、

```
sox (入力ファイル名) (出力ファイル名) delay 0.7
```
の形です。0.7が遅延時間なのでお好みで調整してください。

もっと簡単にどこかのパラメーター1ついじるだけで済むよ、など情報ありましたらお知らせいただければと思います。
DjangoのModelで設定したバリデーションにカスタムのエラーメッセージをつける

昨日に更新した[記事](https://qiita.com/fumihiko-hidaka/items/018d751e280f65dd2a28)に引き続いてDjangoのModelについての備忘録もかねて。

# 正規表現のバリデーションにメッセージをつける！

DjangoのModelのpropertyに正規表現のバリデーションを設定したんですが、エラーメッセージがイケてないんですね……
ユーザにはわかりにくいといいますか……という訳で設定してみました。

```model.py
from django.core.validators import RegexValidator, slug_re

class HogeModel(models.Model):
    name = models.CharField(max_length=128, verbose_name='名前', validators=[RegexValidator(
        slug_re,
        '名前には半角英数字、アンダーバー、ハイフンのみ指定できます。',
        'invalid'
    )])
```

これで、Django adminのformから更新した際に入力エラーになっていると、カスタムなエラーメッセージが表示されます:heart_eyes:
google-home-notifierが「Error: get key failed from google」を吐いたので対策してみた

# はじめに
- gmailなどが届いたら、Google homeさんが教えてくれるようにしていた->[参考](https://qiita.com/ezmscrap/items/7a7f555faf7371a56e9d)
- ところが、日本時間 2018/09/21(金) 午前07:30程度から、メールが着信してもGoogle homeさんが反応しなくなっていた
- 調べてみたところ、google homeさんをしゃべらせる仕掛けであるgoogle-home-notifierが「Error: get key failed from google」なるエラーを出力していた
- これは、googleからの戻り値が変わっていたためと分かった
- googleの変更に合わせて、node_modules/google-tts-api/lib/key.jsを修正してやることで解決した

# 環境
- Windows 10 pro バージョン1803
- Windows Subsystem for Linux(WSL) ubuntu VERSION="18.04.1 LTS (Bionic Beaver)"
- node.js v10.6.0
- 'google-home-notifier': '1.2.0',

# 現象
- 日本時間 2018/09/21(金) 午前07:30程度から、google-home-notifierが「Error: get key failed from google」なるエラーを出力していた

# 原因
- google翻訳(https://translate.google.com)の返すキーが、「TKK = '405291.1334555331'」から「TKK='12345678.90123'」になり、それをチェックする「node_modules/google-tts-api/lib/key.js」でエラーが返っていた。

# 対策
- 「node_modules/google-tts-api/lib/key.js」の24行目の「`eval(html.match(/TKK=eval\(\'\(.*\)\'\);/g)[0]);`」を「`eval(html.match(/TKK='[0-9]+.[0-9]+'/g)[0]);`」に書き換えた。

# おわりに
- 以上は暫定対策
- Githubを覗くと、この問題への対策の[pull request](https://github.com/zlargon/google-tts/pull/14/commits/b5d1b8561fc1a34fac1e66bb280cd153d1a31044)があった
- そちらを取り込んだ方が確実ではあると思う
- 今回は、自分で調べて対策した情報を折角なので残す形にした
機械学習／ディープラーニングにおけるバッチサイズ、イテレーション数、エポック数の決め方

Keras、TensorFlow、Pytorchなどの機械学習／ディープラーニングのフレームワークを利用する際、

- バッチサイズ
- イテレーション数
- エポック数

などのハイパーパラメータを決める必要があります。
しかし、どうやって決めれば良いのかよく分からず、サンプルプログラムで設定している数値をそのまま使う場合が多いと思います。

そこで、これらのハイパーパラメータの決め方について説明します。
結論を先に言ってしまうと、この場合はこうですという定番の方法があるわけではなく、問題毎にそれぞれのハイパーパラメータをうまく調整していくしかありません。

じゃあ、どうやってうまく調整してくのかということを述べる前に、これらのハイパーパラメータの意味について説明します。
ハイパーパラメータの意味が分かれば、どのように調整していけば良いのかなんとなく分かってくるかと思います。

### バッチサイズとは？
ディープラーニングでは、損失関数を最小化して最適なパラメータ（重み、バイアス）を見つけるために勾配降下法と呼ばれる手法が使われます。
多くの場合、ミニバッチ勾配降下法というバッチ勾配降下法と確率的勾配降下法の間を取った手法が使われ、データセットを幾つかのサブセットに分ける必要があります（学習データとテストデータに分けるのとは別の話しです）。

そして、この幾つかに分けたぞれぞれのサブセットに含まれるデータの数をバッチサイズと呼びます。
例えば、1,000件のデータセットを200件ずつのサブセットに分ける場合、バッチサイズは200となります。
また、バッチサイズのことをミニバッチサイズと呼ぶこともあります。

![Untitled Diagram (1).png](https://qiita-image-store.s3.amazonaws.com/0/127582/4d92bedb-c849-d0cd-c6ad-28e0fc8c20c7.png)

バッチサイズは機械学習の分野の慣習[^1]として2のn乗の値が使われることが多く、32, 64, 128, 256, 512, 1024, 2048辺りがよく使われる数値だと思います。
データセットの件数が数百件程度であれば32, 64をまずは試してみて、数万件程度であれば1024, 2048をまずは試して見るのが良いのではないでしょうか。
そして、学習がうまくいっておらず、他に調整するパラメータがなくなった時にバッチサイズを大きくしたり小さくしたりするのが良いと思います。

### イテレーション数とは？
イテレーション数はデータセットに含まれるデータが少なくとも1回は学習に用いられるのに必要な学習回数であり、バッチサイズが決まれば自動的に決まる数値です。
先程の1,000件のデータセットを200件ずつのサブセットに分ける場合では、イテレーション数は5 (=1,000/200)となります。
つまり、学習を5回繰り返す（イテレートする）ということです。

### エポック数とは？
1. データセットをバッチサイズに従ってN個のサブセットに分ける。
2. 各サブセットを学習に回す。つまり、N回学習を繰り返す。

1と2の手順により、データセットに含まれるデータは少なくとも1回は学習に用いられることになります。
そして、この1と2の手順を1回実行することを1エポックと呼びます。
つまり、エポック数とは1と2の手順を何回実行するのかということです。

普通、1エポックで十分に学習されることはなく、数エポックから数十エポック回すことが多いです。
では、何回エポックを回せば十分なのでしょうか？

答えとしては、損失関数（コスト関数）の値がほぼ収束するまでです。
そして、データの性質や件数によって収束するまでに掛かる回数は異なるので、実際に幾つかの数値で試してみて損失関数の推移を見るしかありません。
また、ほぼ収束と書いたのは、完全に収束まで実行すると過学習になる恐れがあるためです。

### バッチサイズ、イテレーション数、エポック数の決め方
ここまで読んで頂ければ、これらのハイパーパラメータの決め方がなんとなく分かってきたと思います。

バッチサイズについては、データセットのサイズが小さければ32, 64などの小さめの値、大きければ1024, 2048などの大きめの値をまずは使ってみるのがよいでしょう。
そして、バッチサイズが決まればイテレーション数は自動的に決まります。
最後に、エポック数は幾つかの数値で試してみて、損失関数の値の推移を見ながら最適そうな値を探すということになります。

#### 参考資料
[Epoch vs Batch Size vs Iterations (Medium)](https://medium.com/@sujathamudadla1213/epoch-vs-batch-vs-iteration-in-neural-networks-8d02ea155304)

[^1]: SVMの代表的なライブラリであるLIBSVMのグリッドサーチでは2のn乗刻みで最適なパラメータを探索する。
VRChatのトラスト値をブラウザから確認する方法

### 前置き
表題の通り自分のVRChatのトラスト値をブラウザから確認します。
つい先ほど(9/21時点)ゲーム画面から色で確認できるようになったので旬を過ぎた話題かもしれませんが、要望が有ったので記事にします。
誰でも理解できるように書くのでちょっと冗長に感じられる方もいらっしゃるかもしれませんがご容赦願います。

### 1.Google Chromeをインストールする
Google Chrome に開発者向けのツールが有りますのでそれを使って確認します。
Fire Fox とかでも同じことができますが、Chrome 前提で書いてゆきますのでご容赦ください。
https://www.google.co.jp/chrome/?brand=CHBD&gclid=Cj0KCQjwrZLdBRCmARIsAFBZllGJYdSPdFHG_xBH1ckh3c0TpBImOCJ-iOV7snL9Ho5ddM2boVVy-kEaAsbzEALw_wcB

### 2.VRChatのサイトにログインして自分のページにアクセスする
こちらからVRChatのサイトに自分のIDでログインできます。
https://vrchat.net/
Google Chromeでログインして右上の自分のアイコン(オレンジ色に囲った部分)をクリックすると自分のアバターが表示されたページが表示されます。(プライバシーのために一部画像を加工しています)
![1.png](https://qiita-image-store.s3.amazonaws.com/0/159653/038cb20a-b868-bd88-5044-6b4b3d6f30f2.png)


### 3.開発者向けツール(Developer Tool)を起動してNetworkタブを開く
ブラウザの上の適当なところで右クリックすると`検証(I)`と表示されますのでそれを左クリックしてください。
するとブラウザの右側(下側かも)に開発者向けツールが開きます。その中の上部に`Network`と書かれたタブ(オレンジ色に囲った部分)が有るのでそれをクリックしてください。ここにはブラウザでWebサイトにアクセスした際の通信内容が表示されます。ブラウザ上には特に表示されていませんが、このページにアクセスした際にトラスト値も一緒に取得しているので、Networkタブでトラスト値も取得できます。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/159653/1179a043-7942-1503-568b-1ecb25774bda.png)

### 4.開発者向けツール(Developer Tool)を起動してネットワークタブを開く
先ほどの図では開発者向けツールを開いてから、現在のページにアクセスしなおしていないのでNetworkタブ上には何も表示されていません。
キーボードのF5を押すかURLを選択してEnter を押すと再度ページが読み込まれて、Networkタブ上に通信内容が表示されます。
一気に大量に流れて読みにくいですが、下図のオレンジ色の部分のように`usr_`から始まる通信が有るのでそれを左クリックしてください。
すると、右側にその通信内容の中身が表示されますので、下図の赤い部分を左クリックしてください。
そうすると表示される水色の部分が自分のトラスト値です。
私の場合`system_trust_known`やら`system_trust_trusted`と書いてあることが確認できます。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/159653/064413ee-109d-1b7e-f4bd-2fd1566dbd85.png)

### 補足
同様にしてフレンドのページにアクセスすれば、そのフレンドのトラスト値も確認できます。トラスト値が高いと`system_trust_veteran`や`system_legend`(最高値?)と表示されるようです。フレンドのトラスト値を確認するのも面白いかもしれません。
[追記]`system_trust_legend`というタグも存在し、ゲーム内でveteranと表示されるのはそのタグが付いている人のようです。（ふんわりした曖昧な情報ですみません。。。）
また、Networkタブを長時間開いて情報が多すぎて訳が分からなくなったら、開発者向けツール右上の×を押して開きなおせば過去のものは消えるのでご活用ください。
Redigoを使う(6)　パブリッシュ／サブスクライブ

# はじめに

[Redis](https://redis.io/)のGo言語向けクライアントライブラリ[Redigo](https://github.com/gomodule/redigo)の使い方を見ます。

あまり知られていないかもしれませんが、RedisにはPub/Sub（パブリッシュ／サブスクライブ）機能があります。この機能を使うと、例えばサーバ間のメッセージ通知のような1対多の通信を行うことができます。この記事ではパブリッシュ／サブスクライブの行い方を見ます。

# 環境

* OS: Windows 10
* Redis: [win-3.2.100](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.2.100)
* Go言語: [1.11](https://blog.golang.org/go1.11)

# サブスクライブ

Redisでは、いわゆる「トピックベース」の通信ができます。受信側（サブスクライバー）は始めにトピック（チャネルと呼びます）を指定して購読を開始し、チャネルからの通信を待機します。

```go:subscriber.go
package main

import (
	"fmt"

	"github.com/gomodule/redigo/redis"
)

func main() {
	// 接続
	conn, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	psc := redis.PubSubConn{Conn: conn}
	psc.Subscribe("channel_1", "channel_2", "channel_3")
	for {
		switch v := psc.Receive().(type) {
		case redis.Message:
			fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
		case redis.Subscription:
			fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
		case error:
			return
		}
	}
}
```

上記は[サンプル](https://godoc.org/github.com/gomodule/redigo/redis#PubSubConn)をほぼそのまま持ってきたコードです。イディオム的にそのまま使えばよいと思います（実用的には切断された時に再接続を試す処理が必要と思います）。`Subscribe`で購読を開始するチャネルを並べて記し、`Receive`でブロッキングでメッセージを待機します。

サブスクライブに成功するとチャネルは`redis.Subscription`を受け取ります（case節の２つ目）。このとき成功したチャネル名と通知の種類（"subscribe"）、購読チャネル数が得られます。

# パブリッシュ

次は送信側（パブリッシャー）のコードです。

```go:publisher.go
package main

import (
	"fmt"

	"github.com/gomodule/redigo/redis"
)

func main() {
	// 接続
	conn, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	// パブリッシュ
	r, err := redis.Int(conn.Do("PUBLISH", "channel_1", "hello"))
	if err != nil {
		panic(err)
	}
	fmt.Println(r)
}
```

サブスクライバー側のコードを実行した状態で上のコードを実行すると、サブスクライバー側のターミナルにメッセージが表示されます。複数を起動していれば全てに同じ内容が表示されます。

パブリッシャー側のコードは比較的単純です。PUBLISHコマンドでチャネルとメッセージを指定して送信します。戻り値はメッセージが配信されたサブスクライバーの数になります。

# おわりに

Redidoでのパブリッシュ／サブスクライブの行い方を見ていきました。

# 参考

* [Redigoを使う(1)　基本的な使い方](https://qiita.com/riverplus/items/c1df770838d3868c3a13)
* [Redigoを使う(2)　様々なデータ型を扱う](https://qiita.com/riverplus/items/04aa969d699c78f58598)
* [Redigoを使う(3)　トランザクションを行う](https://qiita.com/riverplus/items/5379111adda57f9ac18a)
* [Redigoを使う(4)　コネクションプールを使う](https://qiita.com/riverplus/items/12f9b37cf1795d9bdbb1)
* [Redigoを使う(5)　ユーティリティ関数](https://qiita.com/riverplus/items/a359ba7e74642a870440)
初心者がRailsガイドを1から100まで読んでみる　Railsをはじめよう編その４　モデル

####5.4.Articleモデルを作成する
とうとうモデルくんが姿を表しました。
今まではコントローラとビューの挙動について色々と学んできました。
ビューからリクエストを送信して、その中身（パラメータ）を受け取ったコントローラ（のアクション）がごにょごにょして別のビューに渡したりする。
そのやりとりはルーティングをもとに行われる。
そんな感じでした。

でも肝心のデータの保存先についてはまだ言及されていませんでした。
ITとはInformartion Technology（情報技術）の略で情報を扱うのが本業です。その情報はデータベースに格納されます。データの流れを把握すれば、そのシステムを把握できたと言っても過言ではないでしょう。
とっても大事なデータ、それを扱うのがモデルくんです。

「Railsのモデルは、単数形の名前を持ち、対応するデータベーステーブル名は複数形で表されるというルールがあります。」
例えばモデルの名前はArticle（単数形）だとしたらデータベースのテーブル名はarticles（複数形）だということですね。
Railsの哲学である「設定より規約」ってここら辺の命名規則も含まれてるのかな。
モデルを作ればテーブルも同時に作られるのか。

モデル作成用のジェネレータがあります。
`$ rails generate model Article title:string text:text`
このコマンドの見方だけど、
「Articleって名前のモデルを作るよ。そのテーブルにはstring型のtitleという項目と、text型のtextという項目を設定するよ」という意味だ。
![IMG_20180921_224701.jpg](https://qiita-image-store.s3.amazonaws.com/0/283826/fa298015-bd71-0ba1-db67-8fd50ee35bfe.jpeg)


実際にコマンドを打ってみるとこうなる。
<img width="439" alt="スクリーンショット 2018-09-21 16.55.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/283826/028a419f-47d0-2102-f8e5-25474a9bf389.png">


いくつかファイルが作られた。
でも今必要なのはこの二つらしい。

```article.rb
class Article < ApplicationRecord
end
```

``` タイムスタンプ_create_articles.rb
class CreateArticles < ActiveRecord::Migration[5.1]
  def change
    create_table :articles do |t|
      t.string :title
      t.text :text

      t.timestamps
    end
  end
end
```

モデルくん本体と、マイグレーションファイルというもので、マイグレーションファイルはテーブル作成の元になるファイルらしい。ジェネレータコマンド打っただけではテーブルはまだ作られないんだね。
（このファイルはこの後つかうよ）

モデルくんの中身はまだ空っぽで、マイグレーションファイルにはさっきテーブルに追加しようとコマンドに書いたtitle,textフィールド的なものが書いてあるね。

いよいよ、モデルくんの晴れ舞台というわけだ。

その５
https://qiita.com/Natsuki_on_Rails/items/72e9b304169db3e7448b
Raspberry Pi 3で非公開SSIDのWiFiに接続する

## 概要

RaspberryPi3がWiFiに接続できない．


しかしながら，通常にSSIDには接続できる．非公開SSID(hidden SSID)にのみ接続できない模様．

設定ファイルにオプションを追加すれば接続ができました．

## 変更内容

下記ファイルを変更します．

```
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
```

非公開SSIDに対しては``scan_ssid=1``を指定しなければいけないようです．

```
network={
    ssid="xxxxx"
    psk="yyyy"
    scan_ssid=1
}
```

## まとめ

Raspberry Pi3で非公開SSIDのWiFiに接続するには設定ファイルに``scan_ssid=1``を設定する必要がある．

``sudo raspi-config``でNetwork, WiFiと進んでSSIDやパスフレーズを設定したあとに，``/etc/wpa_supplicant/wpa_supplicant.conf``を変更する必要がある．
Truffle使ってERC20トークン実装、INFURA及びgethoを使ってデプロイ

#はじめに
普段、[イーサリアム研究所](https://medium.com/the-dapps-community)というサイトでイーサリアムの技術的記事を発信しています。
しかしリサーチを進める中で理解できないことも多く、少しでもわかることを増やして行きたいとの思いから自分でコントラクトを書いていくことにしました。

またイーサリアム研究所の運営元Popshootは[getho](https://getho.io)というノードホスティングサービスを出していることもあり、そこの理解も深めたいとの思いがありました。

というわけでTruffleを使ってERC20トークンを発行し、gethoを使ってプライベートネットにコントラクトをデプロイしたところまでを**超簡単**に振り返ります。

#参考書籍/記事
**書籍**
[ブロックチェーンアプリケーション開発の教科書](http://amzn.asia/d/8le88e7)


**記事**
[Truffle公式ドキュメント](https://truffleframework.com/docs/truffle/overview)
[サーバーレスフレームワークTruffleでÐappを爆速開発する ①Tutorial](https://qiita.com/syrohei/items/5eb573b781caedde16a1)
[Macのローカル環境でEthereumの送金を行う](https://tomokazu-kozuma.com/make-ethereum-remit-in-macs-local-environment/)
[Gethコンソールでよく使うコマンドをまとめました](https://gootablog.com/geth-console-comand-matome#i)
[Ethereumのテストネット上にトークンをデプロイする](https://qiita.com/shiki_tak/items/855bd5d2213213610365#3-%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)
[TruffleでINFURAにコントラクトをデプロイする[web3.js]](https://noumenon-th.net/programming/2018/06/06/truffle_infura/)

など。

##流れ
・gethインストール
・Truffleインストール
・OpenZeppelinインストール
・トークンのコントラクトとテストコードを書く
・developmentネットワークにデプロイ
・MetaMask用意
・Infura or Getho登録
・Ropstenネットワークにデプロイ

この手順で完了です。

つまづいたことは幾つかありますが、特に一つあげるならMetaMaskを設定してRopstenにデプロイする前に、MetaMask Ether Faucetに接続することを忘れていて少し時間を食ってしまうミスを犯しました。。

##Infuraとgetho
Gethなどのクライアントを使わずにメインネット、テストネットにコントラクトをデプロイするためのノードを立ち上げられるサービスです。

######Truffle.jsファイルを編集、HDWalletProviderを利用し、Ropstenへ繋いでみると
以下はgethoを使った場合。hoge,hogehogeは各自で変更。

```js:truffle.js
var HDWalletProvider = require("truffle-hdwallet-provider");
 var mnemonic = "hoge";
 var accessToken = "hogehoge";


module.exports = {
    networks: {
      development: {
        host: "localhost",
          port: 8545,
            network_id: "10"
          },
          getho: {
            host: "curious-spider-84967.getho.io/jsonrpc",
            port: 80,
            network_id: 1010,
            gas: 4712388
      }
    }
  };

```

######デプロイ
```
$ truffle migrate --network getho

Using network 'getho'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0x18697b907a0ac23f0c8a7240b02463cb5d2e42d18e4f5a9af707cdbb5ecfccd8
  Migrations: 0xe660167a2c25b5fd758c33947999d9dfd05518e0
Saving successful migration to network...
  ... 0xd2f229e520600b208a2a9659468a002b1081f9ea8e89b26458f7d64d985e519d
Saving artifacts...
Running migration: 2_deploy_my_token.js
  Deploying DappsToken...
  ... 0x510e0aed23a75da9283441b618e993f167e02a743ddec2198d8d229a5eb56fc7
  DappsToken: 0x6176e9ec8ab713e3ab4ca415d25f57eea52e3cd6
Saving successful migration to network...
  ... 0xdca6660536cf9ac0b1e76f5f98d630a95b1c4c1c4020b9b2ea035173489b0ddc
Saving artifacts...

```
デプロイ完了。

##感想
トークン発行からデプロイまで、フレームワークが用意されてるので思ったより簡単でした。RailsでWebアプリを作る感じのアレです。
EC-CUBE3（Symfony2）でラジオボタンとチェックボックスにattr属性が使えない 


#概要
EC-CUBE3をカスタマイズしていると必ずぶち当たるフォームのカスタマイズ
その中でも中々情報が落ちてないform_themeについて自分メモ。

##環境
`EC-CUBE 3.0.16`
`PHP 7.19`

##そもそもなぜラジオボタンとチェックボックスにattrが使えないのか
参考：http://d.hatena.ne.jp/shimooka/20120726/1343280157
>デフォルトのフォームテーマ(form_div_layout.html.twig)では、choice_widgetブロック内でexpandedの場合に改めてform_widget関数を呼び出しているが属性情報を引き継いでいないため、ラジオボタンとチェックボックスに属性を直接付けることができない。

らしいです。（非力）

##そこで`form_theme`の出番なのです。
EC-CUBE3ではformのレイアウトはデフォルトで以下のファイルを読み込んでいます。

```
src/Eccube/Resource/template/Form/form_layout.twig
```

あの忌まわしい`Class="form-group"`をここで外すこともできます。
（その場合は該当するType全ての`Class="form-group"`が外れてしまいます。）


さて話しが逸れましたが、`form_theme`使っていきます。

`form_widget(form.test)`の中がラジオボタンorチェックボックスだったとします。
そしてそのformにクラスtest-classを付けたいとします。
先ずはソースから↓

```twig:test.twig
<div class="form-group">
 {% form_theme form _self %}
 {% block choice_test_widget %}
  {% spaceless %}
   {% for child in form.test %}
    {{ form_widget(child,{attr : {'class': 'test-class'}}) }}
   {% endfor %}
  {% endspaceless %}
 {% endblock choice_test_widget %}
</div>
```


...はい、よく分かりませんね。
一行ずつ解説。

```twig:test.twig
{% form_theme form _self %}
```
参照：https://symfony.com/doc/current/form/form_customization.html
>特別な{% form_theme form _self %}タグを使用することで、Twigはオーバーライドされたフォームブロックに対して同じテンプレート内を調べます。form.age フィールドがintegerタイプフィールドであると仮定すると、そのウィジェットがレンダリングされると、カスタマイズされた  integer_widgetブロックが使用されます。

###twigを何かしらオーバーライド（上書き）するみたいです。

```twig:test.twig
{% block choice_test_widget %}
//何かしらの処理
{% endblock choice_test_widget %}
```
`choice`はフォームタイプのことです。`test_widget`がブロック名ですね。

```twig:test.twig
{% spaceless %}
//何かしらの処理
{% endspaceless %}
```
HTMLの空白行を取り除いてくれるそうです。（適当）

```twig:test.twig
{% for child in form.test %}
//何かしらの処理
{% endfor %}
```

`form.test`がウィジェットの形だと`form_widget(form.test)`となる部分ですね。
いわゆる、該当するフォームを指定。
分かりやすいように`child`という変数に代入しています。
（もちろん何でもOK）

```twig:test.twig
{{ form_widget(child,{attr : {'class': 'test-class'}}) }}
```
ここで今回の記事のメインです。普段なら`form_widget(form.test)`とやるところを
`form_widget(child ~`としています。
これは先ほどのforで回した`form.test`が変数`child`に入っているということなんですね。

こうやってバラすことで`{attr : {'class': 'test-class'}}`が適用されるようになります。

ちなみに上記のやり方でレイアウトを好きに作れるので、個別にclass="form-control"を
外したい時などにも使えます。

##まとめ
###Symfony2はク〇めんどい。

以上。
herokuでlibSM.so.6のインポートエラー発生したときの解決メモ

#環境
heroku/7.16.0 linux-x64 node-v10.10.0


# エラー

herokuでopenCVとか使うpythonのやつデプロイすると，herokuのログに


```
Import Error: libSM.so.6: cannot open ~~
```
こんなのが出る

#対処
こちらの通りにやればできる
https://stackoverflow.com/questions/49469764/how-to-use-opencv-with-heroku/51004957#51004957

#簡単な手順
1. heroku-buildpack-aptを追加する

```bash
$ heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-apt
```

2.Aptfileをつくる

```text:Aptfile
libsm6
libxrender1
libfontconfig1
libice6
```

3.デプロイ

```bash
$ git add .
$ git commit -m "add Aptfile"
$ git push heroku master
```

以上
Makefileの書き方メモ


#Makefileの基本的な構造
```
  (1.変数の設定)
-------------------
  (2.ターゲットと実行)
```

#<b>1.変数の設定</b>
###CC=
使用するコンパイラ



```Makefile:C言語の場合
CC = gcc
```

```Makefile:C++の場合
CXX = g++
```

```Makefile:IntelCコンパイラを使用する場合
CC = icc
```

###INCLUDE= or INCDIR=
インクルードするディレクトリの指定をする。


```Makefile:初期値
INCLUDE = -I./include
```
```Makefile:e.g.
INCDIR = -I /usr/local/include -I /usr/include
```

###CFLAGS =
Cコンパイルのオプション

CFLAGSにて設定する各オプションについて

| オプション | 内容 |
|:-:|:-:|
| -Wall  |  全ての警告を出力する |
| -O2  | コードの最適化レベル <br> gccのデフォルトは-O0 |
| -D  |  マクロ定義 |
| -g  |　デバッグ用の情報を保存する |
| | ... |
<!--TODO: pkg-config について-->
<!--http://x68000.q-e-d.net/~68user/unix/pickup?gcc-->

```e.g.
CFLAGS = -Wall -O2 $(INCDIR)
```

###LDFLAGS =
リンク用のディレクトリを指定する。

```e.g.
LDFLAGS = -L /usr/lib -L /usr/local/lib
```

###LIBS =
ライブラリ用のファイルを指定をする。

```e.g.
LDFLAGS = -l 〇〇〇 -l 〇〇〇.a
```

###OBJS =
生成されるオブジェクト名を指定する。

```e.g.
OBJS = 〇〇〇.o
```
#<b>2.ターゲットと実行</b>

##<b>ターゲット(実行ファイル)と依存ファイル</b>
ターゲット(実行ファイル)と依存ファイルを:区切りで記述します。

```e.g
〇〇〇.out:〇〇〇1.o 〇〇〇2.o 〇〇〇3.o
```

その他にターゲットは型ルールやコマンドに使われます(後述)。



###よく使われる自動変数(マクロ)
| マクロ | 内容 |
|:-:|:-:|
| $<  |  最初の依存するファイルの名前 |
| $@ | ターゲットファイル名 |
|   | ... |

#<b>ターゲット(型ルール)と処理
※古い手法としてサフィックスルールが使われていましたが、現在では型ルールが一般的です。

| サフィックスルール | 型ルール | 内容 |
|:-:|:-:|:-:|
| .c.o: | %.o : %.c | 〇〇.cというファイルに対して〇〇.oを生成する |
| .o.out: | %.out : %.o | 〇〇.oというファイルに対して〇〇.outを生成する  |
|   |   | ...  |


```e.g.
.c.o:
	$(CC) $(CFLAGS) -c $< -o $@
```

test1.c test2.cというファイルがあればtest1.oとtest2.oが生成される。

#<b>ターゲット(コマンド)と処理
make cleanなどのコマンドを実行した時の処理を記述する。

| コマンド名 | 処理内容 |
|:-:|:-:|
|  all | 全てを実行する処理を記述する |
|  clean |  生成されたファイルを削除する処理を記述する |
| install |　installコマンドを用いてどこに何をインストールするかの処理を記述する |
|  | ... |

```e.g.
clean:
	rm -f *.out
	rm -f *.o
```
2018年9月第3週　今週気になった記事まとめ

# 今週気になった記事まとめ
##■テトリスっぽくAIと言葉遊びをしながらブロックを消していくゲーム「Semantris」レビュー
https://gigazine.net/news/20180918-semantris-google-game/
やってみたけどAIの関連語の選び方も違和感ないし、そもそもゲームとしてしっかり面白かった。

##■子どもの「プログラミング教育」はゲームから始めるべき？ 
http://www.itmedia.co.jp/pcuser/articles/1809/16/news018.html
うちのプログラミングの勉強にもこういうものは使った方が良いのだろうか？
皆書けるようにはなっている気がするけど、アルゴリズムっていう部分がどこまでできるようになっているのかは未知数な気もする。
書いてるうちに身につく気もするけれど・・・。

##■なぜ技術ブログを書きまくるのか？　『Developers.IO』のクラスメソッドが伝える、エンジニアの成長サイクル
https://dev.classmethod.jp/jobs/saiyo-2018-09-18/
インフラの知識を持ってなくても使えることを強みにしているイメージがAWSにはあるけど、AWSユーザとAWSエンジニアっていうものはイコールじゃないってことかな。
コアスキルを持たせてからAWSというルートで教育は進めるしかないってことだろうか。

##■電子タトゥーのさらに上をゆく技術!ミネソタ大学が細胞修復機能を皮膚に直接プリントする印刷ツールを発表
https://techable.jp/archives/83678
傷を修復するのはどうやるんだろうか…？

##■セサミストリートのバートとアーニーはゲイで「仲のいいカップル」と脚本家、ただし公式は否定
https://gigazine.net/news/20180919-sesame-street-gay-couple/
脚本家は公式じゃないのかという素朴な疑問。
windowsでNode.jsをバージョン管理する

## 前提
windows7 64bit  
Node.js v8.11.1を使っていた。
v8.12.0がリリースされてたのでバージョンアップしたい。

## Node.jsについて
そもそもNode.jsのバージョンがよくわかってなかったので調べた。
まとめると、

+ 現在の体制でのLTSリリースが始まったのはv4から
+ 偶数番号が安定版。奇数番号は最新機能版
+ 12ヶ月ごとにLTSをリリース
+ Node.js v4はサポート切れ
+ 2018年10月からNode.js 10が LTSになる

せっかくなのでv10への切替を視野にバージョン管理ツールを入れる

## バージョン管理ツール(nodist)のインストール
windowsの場合はnvm-windowsかnodist、という感じだったのでnodistにすることに
### 0.下準備
変に影響があっても困るので、
現在インストールされているNode.jsをアンインストールする。

+ コントロールパネルのプログラムと機能からアンインストール
+ C:\Users\ユーザー名\AppData\Roaming 以下、npmフォルダとnpm-cacheフォルダの削除

を実施。プロキシの認証情報が書かれている .npmrcは残した。

### 1.インストール
https://github.com/marcelklehr/nodist/releases
から最新版のインストーラー(NodistSetup-v0.8.8.exe)を取得。

デフォルトのインストール先(```C:\Program Files (x86)\Nodist```)にインストール。
その後OS再起動。

### 2.実行
```
$ nodist -v
0.8.8
```
インストールはできた。

## Node.jsのバージョン切替
```
$ nodist dist
Could not read response for https://nodejs.org/dist/index.json
Could not read response for https://iojs.org/dist/index.json
Could not read response for https://nodejs.org/dist/index.json.
Sorry.
```
知 っ て た 。

### プロキシの設定
調べたがconfig的なものに設定する方法はないらしく、環境変数に設定する。

```
$ set http_proxy=http://username:password@proxy.host:port
```
nodist distで選択可能なNode.jsのバージョンを表示(再び)

```
$ nodist dist
　...
  10.9.0
  10.10.0
  10.11.0
```
成功。
プロキシの認証情報はターミナルが閉じると消えてしまうので、都度設定する必要がある。

### Node.jsバージョン切替方法
```
$ nodist 8.12.0
8.12.0
Installing 8.12.0
 8.12.0 [===============] 22475/22475 KiB 100% 0.0s
Installation successful.

$ nodist
  (x64)
  7.2.1
> 8.12.0  (global: 8.12.0)
```
v8.12.0への切替が出来た。
（インストールされていないものは探してきてくれるっぽい？）

### npmの切替
nodist npm [ver] でnpmのバージョン管理も出来る。
verにmatchと指定するとNode.jsのバージョンにあわせて変更してくれる。

```
$ nodist npm match
npm match
stream.js:74
      throw er; // Unhandled stream error in pipe.
      ^

Error: Failed to read response from https://codeload.github.com/npm/npm/tar.gz/v6.4.1
```
嘘でしょ。
なぜかnpm v6.4.1は見つからないらしい。(9/21現在)

そのため、

```
$ nodist 8.11.4
8.11.4
Installing 8.11.4
 8.11.4 [===============] 22244/22244 KiB 100% 0.0s
Installation successful.

$ nodist npm match
npm match
...

$ npm -v
5.6.0
```
一旦はNode.js v8.11.4 と npm v5.6.0で動くように。


## yarn
普段はnpmでなくyarnを使っているので、
npm v6.4.1が取得できないという~~瑣末な~~問題は置いておく。
yarnはNode.js v4以上であれば動作するとのことなので、動作確認。

Node.js v8系に関しては問題なかったが、Node.js v10では下記のような状態に。

```
$ nodist 10.11.0
10.11.0
Installing 10.11.0
 10.11.0 [===============] 24174/24174 KiB 100% 0.0s
Installation successful.

$ node -v
v10.11.0

$ yarn init
yarn init v1.6.0
(node:7736) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security
 and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or B
uffer.from() methods instead.
...
```
yarnのバージョンが古かったことが原因。
v1.9.4に更新後、問題なく動作することが確認できた。



## nodistコマンド集(備忘録)

|コマンド|説明|
|:-:|:-:|
|nodist<br>nodist ls|インストールされているバージョンの一覧表示|
|nodist [ver]|指定したバージョンに切替(addも兼ねる)|
|nodist dist|切替可能なバージョンの一覧表示|
|nodist add [ver]|指定したバージョンのインストール|
|nodist rm [ver]|指定したバージョンのアンインストール|
|nodist npm match|npmのバージョンを現在のNode.jsに対応したものに変える|

npmの削除は ```C:\Program Files (x86)\Nodist\npmv``` 内の対応フォルダを消すことで可能。


以上、やったことのメモ
ETロボコン　Macでやる簡単リモートスタート

#本記事について

###ETロボコンとは
組込みソフトウェアプログラミング教育を目的としたロボコンのことである。
実際の競技と、ソフトウェアの内容を説明するモデルの完成度によって競われる。

###本記事を書こうと思った理由
筆者の偏見が混じっているかもしれないが、ETロボコンはWindowsで開発している人が多い。
そのためか、Macでリモートスタートをするための直接的な記事が少なく、大変苦労したので、書くことにした。

リモートスタートと調べると、minicomとかTera Termといったツールをインストールしましょうと出てくるが、リモートスタート自体はscreenコマンドを使えば想像以上に簡単にできるよということを伝えたい。

あんまりしっかり書き過ぎると勉強にならないかもしれないので、説明はあまり詳しくしないで行う。

#開発環境
ハード：MacOS High Sierra
言語：C++

走行体は2018年度版のものを用いた。

#screenコマンド
このscreenコマンドが今回のミソ。ちょっと説明。
自分の理解としては、screenコマンドは多くの端末との画面を共有することができるコマンドである。

ほかのMacユーザーがどうやってリモートスタートを実現しているのかは知らないが、筆者はこれを利用しようと考えた。

今回のリモートスタートは、screenコマンドで走行体とパソコンのウィンドウを共有することで実現する。

#リモートスタートしてみよう
##走行体とパソコンをBluetooth接続
いわゆる初期設定。
EV3wayの公式ページを参考に行った。

URL->https://afrel.co.jp/archives/15586

公式は正義ということを実感した。

##プログラムの準備
これは公式に技術教育などで配布されたサンプルプログラムを利用しよう。
動くことがわかってしまえば、サンプルを真似るなり理解して再構成するなり、できるはず。

##端末名を調べる
```ls /dev/tty.*```
端末を接続する前と接続した後の上記コマンドの実行結果を比較して端末名を取得する。

うちの場合の端末名は以下のようになっている。
```/dev/tty.MindstormEV3-SerialPort```

端末名がわかったところで接続に移ろう。

##端末と接続する
接続手順は間違えてはいけない。繋がらなくなってしまう。
一般性があるのかはわからないが、自走行体の接続手順を以下に記す。

１走行体を起動する。
２パソコンと走行体をBluetooth環境設定から接続。
３appを起動する。
４```screen "端末名"``` をターミナルに入力。
５キャリブレーションなどを行って、走行体をスタート位置に設置する。
６パソコンでキーを入力する。ー＞スタート

screen "端末名" を実行すると画面がまっさらになるが問題はない。
screenはウィンドウを共有するので、returnキーを押さなくてもキーを押すだけで走行体へデータが送られるということに注意。つまり、キーを押したらすぐにスタートする。

どうだろう。簡単ではないだろうか。

#データも取得できる、、、~~はず~~できます！
Bluetoothポインタにファイル出力をすることによって、データをターミナルに出力することも可能だ。

筆者は以下のようにscreenの設定ファイルである「*.screenrc*」に以下の記述を加えることにより、ログを取得している。

```
deflog on
logfile "/保存先のパス/ログファイル名.log"
```

*deflog on*はデフォルトでログを毎回とるようになる設定を、
*logfile*はログファイルの保存場所と保存名の指定をしている。

たぶん、screen本来の使い方と違うけど笑

~~が、しかし、現状、筆者はデータを取得できていない。~~

~~ターミナルの出力履歴が残らないのだ。
一応その辺りもscreenの設定ファイルから履歴を増やしてみたり、ターミナルのlogファイル出力に挑戦して見たりしたが、挫折した。~~

~~ダメだった理由は
走行体の電源をブチ切りしてるのがダメなのかなとか、
```fclose("ファイルポインタ");```していないからかなとか、
そんなことを思っている。~~

~~もし、解決方法知ってるよ！　という方は参考になるホームページとかあったら教えて欲しいです（切実）。~~







#参考文献
走行体との接続手順について
https://afrel.co.jp/archives/15586

screenについて
GNUという会社が作ったらしいので、一緒にscreenと調べれば、いろいろ参考になると思う。
端末名と接続方法ー＞https://qiita.com/kobaboy/items/2e15805cf485de3ddf79
screenとはー＞https://ja.wikipedia.org/wiki/GNU_Screen
など