OmniAICreator/Qiita-1.07M huggingface dataset:
テスト担当者も上流工程の技術を学ぶべき3つの理由

[ソフトウェアテスト Advent Calendar](https://qiita.com/advent-calendar/2018/softwaretesting) 2018の14日目です。

今日は[JaSST'18 Shikoku](http://www.jasst.jp/symposium/jasst18shikoku.html)と[JaSST Review'18](http://www.jasst.jp/symposium/jasstreview18.html)が同時開催という、前代未聞の豪華な一日でしたね。

## はじめに
2018年は主に自動テストの要件定義ゃーをやらせていただいているのですが、スポットで入らせていただいた業務システムのテストリーダーのお仕事は近年稀にみる学びがありま、テスト技術者もプロセス設計や要件定義といった上流工程の技術を学ぶべきとしみじみ感じた1年でした。
今日はそんなしみじみ感じた内容をだらだらと書いてみようと思います。[^1]「上流工程は上流工程の人に任せておけばいいんじゃ？」って人も「上流工程のことわからないで何をテストしてるの？」って人も[^2]、駄文に少々お付き合いいただければと思います。


## テスト担当者も上流工程の技術を学ぶべき3つの理由
2018年の出来事から、上流工程技術が必要だと痛感したことを3つ挙げます。

1. 計画を立てるため
2. 現場で使えるシステムを納品して受入れテストですんなりOKをもらうため
3. 業務を改善するため

### 1. 計画を立てるため
計画というのは、テスト計画だったり目標達成への計画だったり、テスト担当者にとっても身近な存在です。

計画を立てるためには、成果物を定義する必要があります。成果物の内容によってタスクが決まります。裏を返せば、成果物が決まらないとタスクが明確になりません。タスクが決まったら、依存関係とリソースを調整してスケジュールを作成します。

成果物に何を含むのか、要件を定義しないと、タスクがあやふやになります。後からタスクが漏れていることが分かるとスケジュールが押しますし、タスクが曖昧だと見積もりと合わなくなってやっぱりスケジュールが押します。
計画通りに物事が進まない方は、要件定義を学びましょう。いい計画はいい要件定義から。テスト担当者も要件定義を学びましょう。

### 2. 現場で使えるシステムを納品して受入れテストですんなりOKをもらうため
テストに寄せたくて受入テストってキーワードを使いましたが、テスト担当者はシステム開発チームの一員ですので、いいシステム（現場に定着するシステム）を提供するためには全力投球したいところです。

業務系システムの受入テストでは、システムが実業務にマッチするかどうかを見ていきます。すなわち、「現場で使い物になる」システムかどうかを見極めるテストをしていきます。最後の最後でひっくり返されないよう、テスト担当者として業務シナリオをレビューしたり、シナリオテストを実施しなければなりません。

シナリオテストのインプットはユーザーシナリオで、本来であれば要件定義の成果物に含まれているべきものですが、機能先行で開発が進んだ場合、ユーザーシナリオが存在しないことがあります。プロジェクトの一員としてテストに参画している場合、「ユーザーシナリオがないのでテストしません」と突っぱねるのはテスト担当者として仕事を放棄しているようなものです。
ユーザーシナリオがあったとしても、それが十分かどうか検証する必要がありますし、結局、ユーザーシナリオが作れるだけのスキルはあるに越したことはありません。

登場人物は誰なのか、業務の目的はなんなのか。システムが業務で使い物になるかどうかはそこからです。ヒアリング力と妄想力を駆使して、お客さまの業務を理解し、お客さまがすんなりシステムを導入できるよう検証しましょう。
それから、ユーザーシナリオが定義されていないような開発現場がこの世からなくなるよう、促しましょう。要件定義、マジだいじ。

### 3. 業務を改善するため
業務というのは、材料（入力）と活動と成果物（出力）の連鎖でできています。これを、プロセスと呼びます。プロセスは目に見えないので、書き出してみることで無駄が見えたり暗黙知が共有できたりします。もちろん、テストにもプロセスがあります。

プロセスについては私は、[ボクらのプロセスにきづこう #wacate](http://www.slideshare.net/tosikawa/ss-42414861)で学びました。形式としては、PFD（プロセスフローダイアグラム）[^3]を使うと簡潔にまとめることができます。PFDは私がの周りのテスト技術者の中で広く広まっている手法です。
​もっと細かいプロセスを書くなら、[マジカ](https://www.magicaland.org/)が使えます。IT屋さんではない人に業務フローを定義してもらうときに活躍しているツールです。以前、自分が暗黙でやってたいろんなタスクを引き継ぐときにマジカを使ってみたら、スムーズに定義ができて感動ものでした。
「可愛いは正義」が口癖の羽生さん[^4]が作っているだけあって、可愛いくてとっつきやすい反面、現場に持ち込みにくいのが若干の難点。とりあえず社内で付箋とゴミ袋のスタイル[^5]に抵抗がなくなってきているので、次はマジカの普及を狙っていたりします。

業務を楽にするためにも、業務プロセスが見えないと始まりません。
テスト担当者も業務プロセスを書けるようになりましょう。

## まとめ
テスト担当者も、武器は多いほうがいい。

テストと要件定義の関係についてはもうちょっと掘り下げたいところですが[^6]、忘年会の時間が迫っているので今日はここまで。

今週末は[WACATE](https://wacate.jp/workshops/2018winter/)や[PHP Conference](http://phpcon.php.gr.jp/2018/)があるみたいですね。参加される方は、いろんな方々とたくさん交流をされるとよいかと思います。それでは、忘年会に行ってきます！​[^7]


[^1]: アドベントカレンダーってこんなんでいいんでしたっけ？ｗ
[^2]: もちろん「上流工程のことわからないで何をテストしてるの？」派です
[^3]: PFDの適切なリンク先がわからなかったです…清水さんが書いたやつってないんでしたっけ？
[^4]: [『はじめよう! 要件定義 ~ビギナーからベテランまで 』](http://amzn.asia/d/bjau18y)とか[『改訂第3版 すらすらと手が動くようになる SQL書き方ドリル (WEB+DB PRESS plus)』](http://amzn.asia/d/4Hkcef1)とか、「できるを増やす」をテーマに活動されていて、大好きなのです
[^5]: ゴミ袋って、ホワイトボードマーカーで書いたり消したりできるんですよ。付箋を貼ってはがして線を書いて、更に持ち運べる。安い。素晴らしい！出所は、みずのりさんのTOCのワークショップだったか…？
[^6]: 表記揺れとか考察とか不足しまくってますが今週は時間が…なぜ私はこの日にカレンダーを設定してしまったのか
[^7]: 乾杯の時間になってしまった！！！！！orz
カービィのコマンドを作りました

以前カービィのコマンドを作ったのでそれについてまとめます。

パスが通ったディレクトリにファイルを置かないとだめなようなので、以下のコマンドを叩いて確認しました。

```
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
パスについて、詳しいことは下のURLに記載されています。
・[自作のコマンドを作成した](https://qiita.com/yoshiken/items/2b8e6c24d6b95e65b625)
・[自作コマンドの作り方](https://qiita.com/b4b4r07/items/129f11c80aa34479b764)

パスが通ったディレクトリを用意してもいいみたいですが、私はすでにあるものを使用することにしました。
ファイル名は「kirby」で作成しました。

```
$ cd /usr/local/bin/
$ vim kirby 
```

kirbyコマンドを叩いたらランダムで台詞を吐くようにしました。

```bash:kirby
#!/bin/sh

NUM=$(expr $RANDOM % 10)
case $NUM in
0) echo "(つ   ′-′   )つ < ぽよー！" ;;
1) echo "(つ   ′-′   )つ < ぽよ？" ;;
2) echo "(つ   ′-′   )つ < ぽよぽよー！！" ;;
3) echo "(つ   ′-′   )つ < ぽよ！ぽよぽよ！ぽよ？" ;;
4) echo "(つ   ′-′   )つ < ぽよ・・・" ;;
5) echo "(つ   ′-′   )つ < ペポーイ!" ;;
6) echo "(つ   ′-′   )つ < ハァイ♪";;
7) echo "(つ   ′-′   )つ < ぽーよー！";;
8) echo "(つ   ′-′   )つ < ぽよ、ぽよぽよぽよ";;
9) echo "(つ   ′-′   )つ < ぽよ〜";;
esac
```

コマンドを実行できるように権限をあたえます。

```
$ chmod a+x kirby
```

こんな感じになりました。

```
$ kirby
(つ   ′-′   )つ < ぽよぽよー！！
$ kirby
(つ   ′-′   )つ < ハァイ♪
$ kirby
(つ   ′-′   )つ < ぽよぽよー！！
$ kirby
(つ   ′-′   )つ < ぽよ〜
$ kirby
(つ   ′-′   )つ < ペポーイ!
```

次はもっと立体的な感じで作れたらいいなと思います。
以上です。
2*2行列を数値として処理するRuby

```
x = readlines.map{|line| line.chomp.split(/\s/).map(&:to_i)}
puts x.map{|row| row.map{|i| i+1} }.map{|row| row.join(" ")}.join("\n")
=begin
1 1
1 1
が
2 2
2 2
=end
```

# 参考

参考にしたWebサイトや技術書などを列挙する

- [teratailに感謝](https://teratail.com/questions/161792)

# 次にやること

線形代数をやる
TIMESTAMPの指定でS3の過去の状態を復元できるs3-pit-restore

[Advent Calendar](https://qiita.com/advent-calendar/2018/lifull)の季節ですが、あまりにも小ネタなので単発記事で書きます。

S3に保存されている「もう必要ないだろう」と思っていたデータが急遽必要となり、過去のS3のデータを復元する必要が出てきました。念の為バージョン管理していたものの、一つ一つのファイルを指定していくのは大変だし、Pythonスクリプトでやるには不安だしどうしよう…。

そんなとき、[こちら](https://serverfault.com/questions/589713/restore-a-versioned-s3-bucket-to-a-particular-point-in-time)で紹介されていた[s3-pit-restore](https://github.com/madisoft/s3-pit-restore)のおかげで助かった、という記事です。

https://github.com/madisoft/s3-pit-restore

このようにタイムスタンプの指定でローカルのディレクトリに復元したり、

```bash
$ s3-pit-restore -b my-bucket -d restored-bucket-local -t "06-17-2016 23:59:50 +2"
```

別のバケット(restored-bucket-s3)に移したりできます。今回必要だったデータの容量が大きいため、私はこちらでやりました。

```bash
 $ s3-pit-restore -b my-bucket -B restored-bucket-s3 -t "06-17-2016 23:59:50 +2"
```

もちろん、バージョン管理されたS3バケットでしか使えないし、多少の時間はかかりますが、とりあえずこれで事無きを得ました。
pythonで3次元の散布図

* matplotlibで3次元の散布図を描きたいとき用のメモ書き
* コピペして使おう
* コード内のコメント見れば大体わかるはず。たぶん。


```py

import numpy as np #適当な配列作るためにNumpy使う
X = np.array([i for i in range(1,1000)]) #自然数の配列
Y = np.sin(X) #特に意味のない正弦
Z = np.log(Y) #特に意味のない自然対数
#備考：Numpyだとnp.log()は自然対数。常用対数はnp.log10()

import matplotlib.pyplot as plt

#seabornでグラフをきれいにしたいだけのコード
import seaborn as sns
sns.set_style("darkgrid")

#3次元プロットするためのモジュール
from mpl_toolkits.mplot3d import Axes3D

#グラフの枠を作っていく
fig = plt.figure()
ax = Axes3D(fig)

#軸にラベルを付けたいときは書く
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")

#.plotで描画
#linestyle='None'にしないと初期値では線が引かれるが、3次元の散布図だと大抵ジャマになる
#markerは無難に丸
ax.plot(X,Y,Z,marker="o",linestyle='None')

#最後に.show()を書いてグラフ表示
plt.show()
```

![3dscatter.png](https://qiita-image-store.s3.amazonaws.com/0/185939/27487dec-f0bb-5564-12f9-9bc1b00cf305.png)

参考
https://www.amazon.co.jp/dp/B07NQ5W8DW/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1
Zsh + Prezto の設定ファイルを整理する

# 概要
 Zsh + Prezto の設定ファイル（ `.zshrc` 、 `.zlogin` など）を1つのディレクトリにまとめて整理する方法です。 Prezto を使っているとこれらのファイルはシンボリックリンクになっているため、ただ移動するだけでは読み込めなくなってしまいます。そこで、シンボリックリンクの貼り直しなどの必要な手順をまとめました。


# 目標
すべてのファイルがホームディレクトリにあるデフォルトの状態から、このようなディレクトリ構造にしたい。

```
/Users/ttsutchi
├── .zshenv   # .zsh.d以下を読み込む
└── .zsh.d   # .zshenv以外の設定ファイルを格納するディレクトリ
    ├── .zprezto   # 以下のファイルの実体やプラグインなどが格納されているディレクトリ
    ├── .zshenv   # これらのファイルは.zprezto/runcoms/にある実体のシンボリックリンク
    ├── .zshrc
    ├── .zlogin
　　︙
    その他.zファイル
```


# 実行環境
MacOS High Sierra 10.13.6
Zsh 5.6.2
[Prezto](https://github.com/sorin-ionescu/prezto)


# 手順
ホームディレクトリで作業していきます。

###  `.zsh.d` ディレクトリの作成
設定ファイルを格納するディレクトリを作成します。ここでは `.zsh.d` とします。

```:terminal

$ touch .zsh.d
```

###  `.zprezto` を `.zsh.d` ディレクトリに移動
 Prezto の本体である `.zprezto` を `.zsh.d` に移動させます。

```:terminal

$ mv .zprezto .zsh.d
```

### それ以外のファイルを削除(もしくは移動)
`.zcompdump` を削除します。 `.zhistory` も削除したいのですが、すぐに再生成されてしまうため、すべての移行が完了してから最後に削除することにします。（どちらも再生成されるので削除しても問題ないですが、 `.zsh.d` に移動させることもできます）

```:terminal

$ rm .zcompdump .history
```

### シンボリックリンクも削除
`zshenv` 、 `.zshrc` などのファイルはシンボリックリンクなので、 `unlink` コマンドで削除します。

```:terminal

$ unlink .zlogin .zlogout .zpreztorc .zprofile .zshenv .zshrc
```



### `.zshenv` を新たに作成
 Zsh 起動時に最初に読み込まれる `.zshenv` を新たに作成します。

```:terminal

$ touch .zshenv
```

### 環境変数 `ZDOTDIR` の設定
以下の2行を先ほど作成した `.zshenv` に記述して、 `.zsh.d` を `ZDOTDIR` として指定します。

```:.zshenv
export ZDOTDIR=$HOME/.zsh.d
source $ZDOTDIR/.zshenv
```

以下のコマンドを実行すれば記述できます。

```:terminal

echo -e "export ZDOTDIR=$HOME/.zsh.d\nsource $ZDOTDIR/.zshenv" >> .zshenv
```

### シェルを再起動

`.zshenv` を読み込むために、以下のコマンドを実行するかターミナルを再起動することで Zsh を再起動します。

```:terminal

$ zsh
```

### シンボリックリンクを貼り直す

以下のコマンドを実行して、 `.zprezto` の中にある `.zshrc` などのファイルのシンボリックリンクを `.zsh.d` に貼ります。4行を一度に実行することに注意。

```:terminal

$ setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done
```

### シェルを再起動

今貼ったシンボリックリンクを読み込むために、最後にもう一度以下のコマンドを実行するかターミナルを再起動することで Zsh を再起動します。

```:terminal

$ zsh
```

### ホームディレクトリの `.zhistory` を削除
`.zhistory` は `.zsh.d` に生成されるようになったので、最後に残ったホームディレクトリの `.zhistory` を削除します。

```:terminal

$ rm .zhistory
```

### 確認
設定ファイルが読み込まれ、テーマやプラグインなどが反映されていればOKです。

# トラブルシューティング
・以下のようなメッセージが出たときは、 `q` で進みます。

```
This is the Z Shell configuration function for new users,
zsh-newuser-install.
You are seeing this message because you have no zsh startup files
(the files .zshenv, .zprofile, .zshrc, .zlogin in the directory
~/.zsh.d).  This function can help you with a few settings that should
make your use of the shell easier.

You can:

(q)  Quit and do nothing.  The function will be run again next time.

(0)  Exit, creating the file ~/.zsh.d/.zshrc containing just a comment.
     That will prevent this function being run again.

(1)  Continue to the main menu.

```

# 参考
・Prezto
https://github.com/sorin-ionescu/prezto
redis-sentinelで、ssh portforwarding越しにredisのレプリケーションを行う場合の注意点

自分用のメモ代わりに。

# 事象

テスト環境で下記のように、  

* srv1
    * redis master (port 6400)
    * redis sentinel
* srv2
    * redis slave (from srv1 master) (port 6400)

という構成を作った。

srv1 と srv2は別のNWにあり、レプリケーションのために  
ssh portforwardingを行った。

```
+---------------+     +-------------+  ssh port forwarding   +------------+
| srv1:sentinel | --> | srv1:master | ---------------------> | srv2:slave |
+---------------+     +-------------+                        +------------+
```

この場合に、srv2:slaveをsrv1:masterに繋ぐまでは、想定通りsrv1:masterのredisは  
masterのママとなる。

が、srv2:redisを

```
slaveof localhost [forwarding port]
```

と、srv2 -> srv1のsshトンネルを経由して接続させると、srv1:masterのredisが  
sentinelよりslaveに降格させられる事象が発生した。  


# 原因

srv1:sentinelが、srv1:masterに接続してきたsrv2:slaveのredisを、
srv1のローカルIPアドレス+srv2:slaveのlisten portとして認識した為。  

つまり、sentinelはsrv1:masterに接続したsrv2:slaveをslave化しようとして、  
srv1:masterのredisに対して slaveof していた。

# 対策

srv2:redisのportを変更した。

このときにsrv1:sentinelは

* srv1 IPアドレス + srv2:slave port

として認識することには変わらないので、srv1に  
srv2:slaveのredisと同じポートで動いているredisが無いように気をつけること。
プロパティの上手な使い方　インターンにて　 Swift 

インターンにて、より見やすくするためにアドバイスをいただいたことです。

タスク内容
tableViewのセルを長押しした時にコピーのアイコンが表示されるようにする。また、上の2行のみ表示されるようにする。

- 自分で作ったコード

``````Swift
func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
   if indexPath.row == 0 || indexPath.row == 1 {
    return true	            
      if NSStringFromSelector(action) == "copy:" {
       return true
      }
      return false
   }
}
``````
- 自分を担当してくれている方が教えてくれたコード

````Swift
func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
    let isAllowCopyCell = indexPath.row == 0 || indexPath.row == 1
    let isCopyAction = NSStringFromSelector(action) == "copy:"
    if isAllowCopyCell && isCopyAction {
     return true
    }
    return false
}
````

自分で作ったコードだと、もし仮に新たな条件を付け足す場合に新たなif文を作らなくてはならない。
自分を担当してくれている方が作ったコードだとそんなことはしなくていいし、まとまっていて見やすい。
些細なことかもしれないが、とても勉強になりました。
実行されるだけでなくて、見やすさや今後のことを考えられるコードをかけるようになりたいです。
Railsのactive_storageとmini_magick使ってみる

#初めに
ActiveStorageという機能があってすごく便利だったのでやり方をまとめる

#active_storage:install
active_storageを使うにはコンソールで

```
rails active_storage:install
```

を行う。
そうすると必要なファイルが作られるのでrails db:migrateする

#保存、表示

モデルファイルに

```
has_one_attached :image
```

と書くか、もしくは

```
has_many_attached :images
```

と書く

has_one_attachedはそのモデルに一つの画像を紐づける場合に使ってhas_many_attachedは複数の画像を紐づけるときに使う。

もちろんhas_many_attached :imagesとかいたらimagesは配列としてわたるので

表示する際に

```erb
<%= image_tag(@post.images) %>
```

と書くとうまくいかないので

```erb
<% images.count.times do |i| %>
  <%= image_tag(@post.images[i]) %>
<% end %>
```

みたいにする。

has_one_attached :image　の場合は一つしか画像を紐づけていないので

```erb
<%= image_tag(@post.image) %>
```

で画像を表示できる。


#画像投稿

画像を投稿する際には

has_one_attached :image　の場合は

投稿フォームに(postモデルに紐づけている場合)

```erb
<%= form_with(model: post, local: true) do |f| %>
  
  #省略

  <%= f.label :image %>
  <%= f.file_field :image %>

  <%= f.submit %>
<% end %>
```

でOK

コントローラーには

```ruby
def create
  @post = Post.create(post_params)
end

private

def post_params
  params.require(:post).permit(:image,:何か,:何か)
end 
```


て感じで書いておけば大丈夫


has_many_attached :images　の場合は

フォームの

```erb
<%= f.file_field :image %>
```

のところを

```erb
<%= f.file_field :images, multiple: true %>
```

書けばOK

コントローラーには

```ruby
def create
  @post = Post.create(post_params)
end

private

def post_params
  params.require(:post).permit(images: [],:何か,:何か)
end 

```

みたいに書く

 
#mini_magick

mini_magickを使えば画像にいろいろできる（語彙力....）


とりあえずGemfileに

```
gem 'mini_magick', '~> 4.8'
```

を追加する。　おそらくコメントアウトされてあるのでそれを使う


このmini_magickを使う場合image_magickを使う必要がある。

このimage_magickだがwindows環境でうまく使えなかった(自分だけかもしれないが....)

だがWSLでubuntuを使ってやってみたところうまくいった。

ubuntuでimage_magickをインストールするには

```
sudo apt-get install imagemagick
```

と書けばいける


mini_magickの使い方だが画像に対して

```
image.resize "100x100"
=>リサイズ
image.path 
=> 画像の名前表示
```

みたいな感じ

詳しくは
https://github.com/minimagick/minimagick


画像を表示する際にその画像をリサイズしたい場合は

```ruby:post.rb

def thumbnail
  return self.image.variant(resize: '300x300').processed
end

```

とかいてview側で

```erb
<%= image_tag(@post.thumbnail) %>
```

と書いてやるようです。


#active_storageのvalidation

アクティブストレージで保存する画像に対してバリデーションをするには

models/post.rbに

```ruby
validate :image_type

def image_type
  if image.attached? && image.content_type.in?(%("image/jpeg image/png"))
    errors.add(:image, 'error message')
  elsif !image.attached?
    errors.add(:image, 'error message')
  end
end 

```

みたいにやるそうです。


#参考にしたサイト

Dean Active Storage For Multiple Images | Validate & Resize | Ruby on Rails 5.2
https://www.youtube.com/watch?v=A23zCePXe74&t=617s
隠れマルコフ

```{r}

#隠れマルコフ

#勉強中

Viterbi_pois <- function(x, prms, trans){

N <- length(x)
K <- ncol(trans)
z <- matrix(0, N, K)
best_logp <- matrix(-Inf, N, K)
best_logp[1, 1] <- 0 + log(dpois(x[1], prms[1]))

for(t in 2:N){
for(k in 1:K){
for(j in 1:K){

tmp_logp <- best_logp[t-1, j] + log(trans[j, k]) + log(dpois(x[t], lambda = prms[k]))

if(tmp_logp > best_logp[t, k]){
z[t, k] <- j;best_logp[t, k] <- tmp_logp
}

}
}
}

best_z <- rep(1, N)
best_z[N] <- which.max(best_logp[N, ])

for(t in 1:(N-1)){
best_z[N-t] <- z[N-t+1, best_z[N-t+1]]
}

return(cbind(best_z,best_logp))

}


N <- 500
K <- 4
prms <- c(1, 4, 7, 10)
transit <- rbind(c(0.9, 0.05, 0.025, 0.025),
                c(0.025, 0.95, 0, 0.025),
                c(0.025, 0.025, 0.95, 0),
                c(0, 0.025, 0.025, 0.95))
z <- rep(1,N)
for(i in 2:N) z[i] <- which(rmultinom(1, 1, prob = transit[z[i-1], ]) == 1)
x <- rpois(N, prms[z])



viterbi_result=data.frame(viterbi=Viterbi_pois(x,prms,transit),z=z)

best_log_p=Viterbi_pois(x,prms,transit)[,2:5]

plot(best_log_p)





```

```{r}

library(dplyr)

A=t(matrix(c(0.1,0.7,0.2,0.2,0.1,0.7,0.7,0.2,0.1),ncol=3))

B=t(matrix(c(0.9,0.1,0.6,0.4,0.1,0.9),ncol=3))

p=c(1/3,1/3,1/3)

n=100

X=sample(c(1:ncol(B)),n,replace = T)

X[1]=1

#alpha_ite

alpha_box=array(0,dim=c(n,ncol(A)))

for(i in 1:n){

if(i==1){  

alpha=p*B[,X[1]]

}else{

alpha_vec=c()

mat=A*alpha

for(j in 1:ncol(A)){

alpha_vec=c(alpha_vec,sum(mat[,j])*B[j,X[i]])

}

alpha=alpha_vec

}

alpha_box[i,]=alpha  

print(alpha)

}


#beta_ite

beta_box=array(0,dim=c(n,3))

beta=rep(1,nrow(A))

beta_box[1,]=beta

for(i in 2:n){

beta_vec=c()

for(j in 1:ncol(A)){

beta_vec=c(beta_vec,sum(A[j,]*B[,X[i]])*beta[j])  

}

beta=beta_vec

beta_box[i,]=beta

print(beta)


}

N=n



a_ij=array(0,dim=dim(A))

b_jk=array(0,dim=dim(B))

for(n in 1:(N-1)){

for(i in 1:ncol(A)){
for(j in 1:nrow(A)){  

value1=sum(alpha_box[1:(n-1),i]*B[j,X[2:n]]*beta_box[2:n,j])*A[i,j]

value2=sum(alpha_box[1:(n-1),i]*beta_box[1:(n-1),i])

a_ij[i,j]=value1/value2

}
}

print(a_ij)

}


for(n in 1:N){

for(k in 1:ncol(B)){
for(j in 1:nrow(B)){  

value1=sum(ifelse(X[1:n]==k,1,0)*alpha_box[1:n,j]*beta_box[1:n,j])

value2=sum(alpha_box[1:n,j]*beta_box[1:n,j])

b_jk[j,k]=value1/value2

}
}

print(b_jk)

}

p_i=alpha_box[1,]*beta_box[1,]/sum(alpha_box[1,]*beta_box[1,])

alpha_beta_i=apply(tail(alpha_box*beta_box,nrow(alpha_box*beta_box)-1),2,sum)

```

```{r}

A=t(matrix(c(0.2,0.6,0.2,0.1,0.1,0.8,0.6,0.2,0.2),ncol=3))

B=t(matrix(c(0.7,0.3,0.5,0.5,0.4,0.6),ncol=3))

ite=100


for(l in 1:ite){

A_pre=A;B_pre=B
  
  
for(i in 1:length(p_i)){
for(j in 1:length(p_i)){
  
A[i,j]=sum(A[i,j]*c(alpha_box[1:(n-1),i])*c(B[j,X[2:length(X)]])*c(beta_box[2:n,j]) ) 
  
}
}

A=((A)/apply(A,1,sum))

for(j in 1:nrow(B)){
for(k in 1:ncol(B)){
  
B[j,k]=sum(ifelse(X==k,1,0)*(alpha_box*beta_box)[,j])  
  
  
}  
}

B=(B/apply(B,1,sum))

print(sum(abs(A-A_pre)))
print(sum(abs(B-B_pre)))

}



```
Macを触ったことのなかった新人エンジニアが再帰プログラムを説明してみた


はじめまして。リンクアンドモチベーションで[モチベーションクラウド] (https://www.motivation-cloud.com/)の開発をしている[@ohtatakato] (https://qiita.com/ohtatakato)です。

この記事は、「[モチベーションクラウド Advent Calendar 2018] (https://qiita.com/advent-calendar/2018/mcs)」の記事となります。

新卒2年目から未経験で急遽エンジニアとなり、現場に入ってまだ1ヶ月の私ですが、研修を通して学んだことをまとめていきます。


この記事では、再帰プログラムとは何なのかが分かっていない方の為に具体例を示しながらなるべく分かりやすく説明しようと思います。


## 再帰プログラムとは

再帰とはwikipediaに下記のように記載があります。
>再帰（さいき）は、あるものについて記述する際に、記述しているものそれ自身への参照が、その記述中にあらわれることをいう
 
つまり、再帰プログラムとはプログラム中で自身への参照をしているプログラムのことを言うわけですが、私はこれだけではいまいち何を言っているのか分かりませんでした。

### 具体例 ： クリスマスツリーに星を飾る
クリスマスツリーに星を一つずつ飾ってn個の星が飾られた状態をつくります。

仮に10個の星が箱の中に入っていたとして、ツリーに星を飾る回数を数えるときに、
下記のように考えることができます。

「10個の星を飾り付けるためには9個の星を飾り付けた状態のツリーにさらに1個星を飾れば良い」

これを数式で表すと下記のように書けます。

`kazatteru_hoshi(n)`でn個の星が飾られた状態を示すとすると

`kazatteru_hoshi(10) = kazatteru_hoshi(9) + 1`

このように10個の星を飾るためには9個の星が飾られている必要があり、
同様に9個の星を飾るためには8個の星が飾られている必要があります。
まさにこれが再帰的な試行なのです。

n個の星を飾る行為は下記のように記述することができます。

```ruby
def kazatteru_hoshi(n)
  if n < 1
    return 0
  else
    return kazatteru_hoshi(n - 1) + 1
  end
end
```
※nはintとする

## 再帰プログラムは漸化式だった！
ここまで学習してみて、再帰プログラムを作成する際には高校数学の漸化式の作成と同様のことをしていることに気がつきました。
今回のクリスマスツリーを飾る試行の漸化式は下記のようになります。

```
f(1) = 1
f(n) = f(n-1) + 1
この漸化式を解くとf(n) = n
```

wikipediaで「漸化式」を調べてみると
>漸化式（ぜんかしき、英: recurrence relation; 再帰関係式）は、各項がそれ以前の項の函数として定まるという意味で数列を再帰的に定める等式である。
  
つまり、高校生の頃に学んだ漸化式を作成することができれば、再帰プログラムを組むことは容易にできるということです。

↓フィボナッチ数列の漸化式も再帰で書けますね

```
f(0) = 0
f(1) = 1
f(n) = f(n-2) + f(n-1)
```

```ruby
def fibo(num)
  if num < 0
    return "numは0以上の整数"
  else
    case num
    when 0
      return 0
    when 1
      return 1
    else
      return fibo(num-2) + fibo(num-1)
    end
  end
end
```



## 注意点
再帰プログラムにおいて自身を呼び出す回数が多くなると計算量が膨大になってしまう可能性があるので注意が必要です。
これに関してはお正月休みに詳しくまとめようと思います。

## 最後に
モチベーションクラウドは社員と複数のパートナー企業様、フリーランスの方の混合チームで開発しています。
エンジニアになる以前はスクラムマスターとして携わっていたのですが、その時からプロダクトだけでなく、その根底にあるチーム創りを大切にしています。
興味がある方は[モチベーションクラウド Advent Calendar 2018] (https://qiita.com/advent-calendar/2018/mcs)の下記記事をご覧ください。

[スクラムマスターを経験して味わった成功体験と失敗体験] (https://qiita.com/kiiiiita/items/7f7ce7b8fdfb7a6a5b2b)
[組織で技術的負債に立ち向かうための取り組み] (https://qiita.com/cawpea/items/fd0c6633cd2b0c919d7a)
AWS ML University の機械学習についてのコンテンツを訳してみた

# はじめに
この記事は株式会社ナレッジコミュニケーションが運営する [Amazon AI by ナレコム Advent Calendar 2018](https://qiita.com/advent-calendar/2018/knowcom-amazonai) の14日目の記事になります。

Amazon.comのエンジニアが機械学習について学ぶ際に利用している映像コンテンツが「 AWS ML University 」として無料に公開されました。この記事ではその中の機械学習についての記事をざっくり訳をしてご紹介していこうと思います。

コンテンツへのアクセス方法は[こちら](https://qiita.com/Yoshiyuki03/items/bfbf416ab47ef5121927)に記載しています。

# AWS What is Machine Learning

## In This Video
今回紹介する動画の主な内容は、以下の構成となります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/55411163-3da6-614a-4cec-9a95bc703bd4.png)

- 概要 ~MLについて~
- ユースケース
- キーコンセプト
- マシン・ラーニングとスマートアプリ
- Amazon Machine Learning
- 事例

## 概要 ~MLについて~

マシン・ラーニング（ML）について

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/0b0aed4d-560e-5346-c844-4474c2c24d95.png)

Machine Learning は人工知能技術（AI）の一部です。既存のデータを利用することでデータに基づいた予測を導き出すことができます。機械学習は予測結果を分析モデルのデータとして加えることで、より正確な予測結果を導きだすことが可能となる技術です。

## Machine Learning の学習モデル

Machine Learning は大きく分けて以下の５つの学習モデルに分類されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/0db89234-1c91-93a0-24ed-ef30e1ab4f7d.png)

- 教師なし学習
- 教師あり学習
    - 分類
    - 回帰
- 強化学習

### 教師あり学習

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/aefb92c3-3399-7063-13a0-07f1e012a861.png)

教師あり学習は、MLモデルにインプットとアウトプットのデータセットを与え、正しいアウトプットを教えていく学習方法です。教師あり学習には「分類」と「回帰」というグループがあります。

### 教師なし学習

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/c5232354-75b9-2cd8-2d57-2bab2967a1ef.png)

教師なし学習モデルは、教師ありと違い、答えがついているデータを与えない手法となります。インプットされたデータからモデル自身がパターンやクラスタに必要な情報をくみ取り、構築していくという学習モデルです。教師なし学習には、「クラスタリング(分類)」と「リグレッション(回帰)」という2つの手法があります。

## Machine Learning and Smart Application

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/52550ade-7a15-d3e7-9ea1-c6d6576b9752.png)

機械学習技術をアプリケーションに導入することは、顧客の好みや購入品の傾向といった情報を知ることに繋がりビジネスを拡大する上でとても重要な要素となります。

## Amazon Machine Learning

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/3dee0785-cc22-f041-9e43-93b5cb3640b8.png)

Amazonでは、以下の2つのサービスを提供しております。

- Amazon Machine Learning
    - モデル構築に専念したい開発者やデータサイエンティスト向けのサービス
- Apache Spark on Amazon EMR
    - Amazon EMRより簡単にマネージドされたApache Sparkクラスタを構築

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/8c76baa0-c017-f700-28a4-f386da3374bd.png)

Amazon MLには3つの予測モデルが用意されています。

- 二項分類
    - Yes/Noなど二者択一の予測モデル
- 多項分類
    - 3つ以上のモデルの中から正しいカテゴリを予測するモデル 
- 回帰
    - 数値の予測モデル

## 事例

![image.png](https://qiita-image-store.s3.amazonaws.com/0/321349/b4286404-2b1b-1590-cc15-3d5783784850.png)

- 課題
    - 新築物件に対する価格を即座に表示させたい。
    - 1日毎に数時間規模の分析処理を実行していた。
    - 柔軟にコンピューティング及びストレージのリソースを変更させたい。
- 解決した結果
    - AWSのサービスを利用してマシン・ラーニング基盤を開発
    - 1億件以上もの新築の正確なデータを提供することがで

# まとめ
「What Is Machine Learning」の動画を簡単にまとめてみました。
次回はディープ・ラーニングの入門記事を紹介したいと思います。
マウスカーソルを操ってめちゃくちゃイライラさせるUXを作ってみた

この記事は、[CSS Advent Calendar 2018 - Qiita](https://qiita.com/advent-calendar/2018/css)の14日目の記事です。

# 成果物

![ezgif-4-10179e34aa8f.gif](https://qiita-image-store.s3.amazonaws.com/0/91558/306536e0-2b35-7523-467c-a9bdfba06c14.gif)

[CodePen - Mouse Cursor Jamming](https://codepen.io/redshoga/full/OrMaEN)

"CLICK ME!"ボタンに近づけば近くほどマウスカーソルがあらぶります。それだけ。
もちろんスマホはカーソルが表示されないため非対応(?)

# どうやって実装しているか

**マウスカーソルの位置を変更することはブラウザではできません。**
そもそもそれができたらセキュリティ的に怖いことになります。

今回実装したのは擬似的にマウスカーソルをいじっているように**見せかけている**だけです。

やっていることはこれ↓だけ

1. ブラウザ上でマウスカーソルの表示を消す
2. (消えている)マウスカーソルの位置を取得
3. カーソルの位置あたりにこちらで用意したカーソルの画像を表示する
4. カーソルの画像の位置をよしなに動かす

まず、ブラウザ上では以下のコードでマウスカーソルを消すことができます。ちなみに`cursor: url(...)`で独自のカーソルに変えられます。

```html
<div class="target">...<div>
<style>
.target {
  cursor: none
}
</style>
```

また、ブラウザ上ではマウスカーソルの位置を取得できます。

```javascript
viewElement.addEventListener('mousemove', (mouse) => {
  console.log(mouse.pageX, mouse.pageY)
  ...
})
```

これでやりたいようにできます。

# コード全体

<p data-height="420" data-theme-id="0" data-slug-hash="OrMaEN" data-default-tab="js,result" data-user="redshoga" data-pen-title="Mouse Cursor Jamming" class="codepen">See the Pen <a href="https://codepen.io/redshoga/pen/OrMaEN/">Mouse Cursor Jamming</a> by いーふとイチオカ🔰(@redshoga) (<a href="https://codepen.io/redshoga">@redshoga</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 余談

なんでこれを作ろうと思ったかというと、以前どっかの怪しいサイトでやられたからです。

その時は「マウスがジャックされた！！」って思ったんですが、なんやこれマウスカーソル非表示にしてる↑みたいにしてるだけやんけ!ってすぐ気がつきました。

ただあまりリテラシーのない人とかがウェブサイトに入って「ウィルスにかかりました！ほらマウスカーソルが乗っ取られてるでしょ!」みたいな言われたら、パニクってなにするかさせられるかわからない。だから、`cursor`プロパティでカーソルいじれるってある種の脆弱性だと思います。

そんなこともあって**`cursor`プロパティは廃止にした方がいいと思うんです。**(もしくはnoneやurlの設定をできないようにする)

~~おわり~~おしり
Jupyterでなんでもやってみよう

# はじめに

Jupyterについて約一年ぶりに投稿します。
去年の投稿は[こちらです](https://qiita.com/mk_tri/items/f29c3477a5099f12cb18)

Jupyterは主に、データサイエンスや統計処理等で主に使われているツールです。
Webブラウザ上で動き、設定次第によってローカル環境や、リモート環境からアクセス可能です。

セルと呼ばれるスペース単位で、pythonのコード[^1]を実行でき、トライ&エラーがやりやすいです。


自分は、プログラム以外のコマンド処理等の作業はJupyterを使って、コマンドを半自動生成したりして、効率化をはかっています。（ほんとに効率化できているかは微妙ですが）

このようなことは、当然プログラムを書いて、コマンドラインから実行すれば同じ結果を得られますが
Jupyterを使って書いたほうが楽だと思います[^2]。

今回は自分がよく 使うJupyterを1つ紹介したいと思います。[^3]

自分はこういう風に使ってるという方はコメント欄にでも書き込んでくれると嬉しいです。

※Jupyterといいながら普段はJupyter Labをメインに使ってます

# ケース1：SQL生成

insertでも updateでもとあるデータをもとにして、似たようなSQLを大量に生成するときによくやっています。

## 1.データを準備する

データフレームである必要はないですが、個人的には楽ちんなのでデータフレームで
csvデータを読み込んでます。


 読み込むCSVファイル

![s4.PNG](https://qiita-image-store.s3.amazonaws.com/0/83335/d134b40d-53e8-00b5-8ae2-9c01a352819f.png)

 Jupyter上でCSVファイルを読み込む
![s1.PNG](https://qiita-image-store.s3.amazonaws.com/0/83335/182d7dfc-4a38-6af3-ae34-accf6ed70f38.png)


## 2.SQLのフォーマットを準備する

Sqlのひな型を作ります。ここをいろいろ変更すれば、同一データから様々なSqlを生成できます。

![s2.PNG](https://qiita-image-store.s3.amazonaws.com/0/83335/773ebb14-872e-519b-03ab-b7fd1553e342.png)


## 3.SQLを生成

ループを回して、Sqlを生成します。
今回はprint関数で表示させて結果をコピーしてますが、特定のファイルに保存するのが再利用しやすくいいと思います。

![s3.PNG](https://qiita-image-store.s3.amazonaws.com/0/83335/ab806f29-25e9-1374-0133-1f4deec4d6c6.png)



#　最後に

やってることはただのデータを読み込んでSQL文を生成してるだけです。
ですが、やはり手軽に変更できて、結果をすぐに表示できるJupyterは便利です。
もし、退屈なルーティーン作業等があれば、Jupyterでやってみるのも手かもしれません。
[この本]
(https://www.amazon.co.jp/%E9%80%80%E5%B1%88%E3%81%AA%E3%81%93%E3%81%A8%E3%81%AFPython%E3%81%AB%E3%82%84%E3%82%89%E3%81%9B%E3%82%88%E3%81%86-%E2%80%95%E3%83%8E%E3%83%B3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC%E3%81%AB%E3%82%82%E3%81%A7%E3%81%8D%E3%82%8B%E8%87%AA%E5%8B%95%E5%8C%96%E5%87%A6%E7%90%86%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Al-Sweigart/dp/487311778X)と組み合わせてみると面白いかもしれません[^4]


今回の処理を動画にしました。こんな感じです
![JupyterLab-Google-Chrome-2018_12_14-19_43_13.gif](https://qiita-image-store.s3.amazonaws.com/0/83335/565a7384-494a-eb83-42f5-e9152ef6dce3.gif)


終わり


[^1]: 設定次第でnode.jsやhaskellなどの言語もJupyter上で実行できます。
[^2]: 個人の感想です。
[^3]: ほんとは３つの予定でしたが、力尽きました。
[^4]: 私は読んでません。
rmarkdownでpythonを実行(Rstudio1.2Preview版,reticulate)

取り急ぎのメモ

* pythonで書いているけれど、Rmarkdownでレポートにしたい
* Rstudio1.2Previewが出たと聞いたので、飛びついた。
* reticulateを使ってPythonが使えるらしい。
* 取り敢えず後でrmdファイルに貼り付けて使えるようにメモ
* 参考: https://speakerdeck.com/t_usausausa/reticulate-and-rstudio

### セットアップ

* reticulate入れる
* 使いたいpythonのパスを指定する（今回はanaconda環境）

```py

```{r setup, include=FALSE}
library(reticulate)
use_python("/Users/user/anaconda3/bin/python")
```#これで囲む
```

## pythonのコードで書く

* チャンクでpython指定してから書く



```py

```{python}
import numpy as np
x=np.array([i for i in range(100)])
y= x**2

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("darkgrid")
plt.plot(x,y)
plt.show()
```#
```

* 取り敢えずこのへんのモジュールは使えるらしい。
クラスより構造体が利用される理由 Swift

インターン先でclassよりstructを使っているまたはみる回数のほうが多いような気がした。
柑橘系でくらべてみました。
## クラスより構造体が利用される理由
クラスは参照型名ため、インスタンスが引数として渡されたとき、そのインスタンスの参照が渡されるから下のような場合、プロパティの値を変更すると両方のインスタンスに影響されてしまう。

```swift
class Food {
    var number: Int = 0
}

class Fruit {
    var citrusFruit: Food
    init(citrusFruit: Food) {
        self.citrusFruit = citrusFruit
    }
}

let citrusFruit = Food()
citrusFruit.number = 5
let orange = Fruit(citrusFruit: citrusFruit)
citrusFruit.number = 10
let lemon = Fruit(citrusFruit: citrusFruit)
orange.citrusFruit.number // 10
lemon.citrusFruit.number // 10
```

逆に、構造体は値型なので、インスタンスが引数として渡されるとき、その参照ではなくて**値そのものが渡される**から、それぞれのインスタンスは別々のインスタンスを保持できる。

```swift

struct Food {
    var number: Int = 0
}

struct Fruit {
    var citrusFruit: Food
}

var citrusFruit = Food()
citrusFruit.number = 5
let orange = Fruit(citrusFruit: citrusFruit)
citrusFruit.number = 10
let lemon = Fruit(citrusFruit: citrusFruit)
orange.citrusFruit.number // 5
lemon.citrusFruit.number // 10
```
クラスを利用するときは**参照を共有する必要がある**ときと、**インスタンスのライフサイクルと合わして処理を実行する**とき！
WIMPなGUIの始祖として、特に旧Mac系LnFの元となったSmalltalkと当初そのプラットフォームだったAltoについて簡単にまとめました

<iframe src="//www.slideshare.net/slideshow/embed_code/key/jVPSBJhBwCPjD5" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/sumim/it2550-125876561" title="IT25・50ライブビューイング＠札幌・前説 (参照資料リンク入り改訂版)" target="_blank">IT25・50ライブビューイング＠札幌・前説 (参照資料リンク入り改訂版)</a> </strong> from <strong><a href="https://www.slideshare.net/sumim" target="_blank">sumim</a></strong> </div>
GraphQL-Rubyのunauthorized_objectの処理をTypeに移す ほか

# unauthorized_objectについて
http://graphql-ruby.org/authorization/authorization.html

GraphQL-Rubyにはresolveしたオブジェクトへの参照権限があるのかのチェック、ない場合の処理を実装することができます


以下のようにType側に実装し、

```rb
class Types::SomeType < Types::BaseObject
  ...
  def self.authorized?(object, context)
    super && object.published?
  end
end
```

Schemaに定義したunauthorized_objectでエラーハンドリングが行なえます

```rb
class Schema < GraphQL::Schema
  ...
  def self.unauthorized_object(error)
    # raise or return some object
  end
end
```

## Type側でエラーハンドリングをしたい
できればunauthorizedの処理はType側にまとめたいところです
`unauthorized_object`に渡る`error`は`type`を持っているので
以下のように実装することでType側に処理を移すことができます。

```rb
# Schema
def self.unauthorized_object(error)
  if error.type.respond_to? :unauthorized_object
    error.type.unauthorized_object(error)
  end
end

# SomeType
def self.unauthorized_object(error)
  # エラーハンドリング
end
```

## データをマスクする
`error.object`でresolveしたオブジェクトを取得することができるので公開したくないフィールドを空文字やnilに返ることができます

```rb
def self.unauthorized_object(error)
  object = error.object
  object.some_hidden_content = nil
  object
end
```
リモートリポジトリを複数設定にする方法

今回は１つのローカルリポジトリに対して、２つのリモートリポジトリを登録する方法についてご紹介したいと思います。

設定方法がとても簡単だったので、自分用として記録します。

##現在のリポジトリを確認

```
git remote -v
origin  git@bitbucket.org:hogehoge/hoge.git (fetch)
origin  git@bitbucket.org:hogehoge/hoge.git (push)
```
上記を実行することで、現在設定されているリモートリポジトリを確認することが出来ます。

ここでリポジトリが２つ以上出てきたら、複数設定されているということになります。

現在は　bitbucketしか表示されていませんね。

##リモートリポジトリの追加

では、新たに登録したいリモートリポジトリを作成したら、

```
git remote add foofoo git@github.com:redamoon/foofoo.git
```

を実行。

fooに入るのはラベルと言って、自分が覚えやすい、管理しやすいもので構いません。

私は新たにGit hubのリモートリポジトリを追加したので

```
git remote add github git@github.com:redamoon/foofoo.git
```

としました。ここはお好みで！

これで２つのリモートリポジトリが作れちゃいました。

後は最初に打った、``git remote -v``で確認してみると

```
git remote -v
github  https://github.com/git@github.com:redamoon/foofoo.git (fetch)
github  https://github.com/git@github.com:redamoon/foofoo.git (push)
origin  git@bitbucket.org:hogehoge/hoge.git (fetch)
origin  git@bitbucket.org:hogehoge/hoge.git (push)
```

となり、設定されているはずです。

##それぞれのリポジトリに対してpushする方法

pushをするにはそれぞれのリモートリポジトリのラベルを指定してあげれば大丈夫です。

```
git push origin master
git push foofoo master
```

こんな感じですね！



　【参考記事】
https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%81%A7%E3%81%AE%E4%BD%9C%E6%A5%AD
Site24x7とZapierを連携して、Googleスプレッドシートにアラートを書き出してみた。

はじめまして。
某IT企業にてインターンをしております、@tefu-tefu と申します。

『クラウドで使える統合監視ソフトウェア』ということでお世話になっている、
Site24x7のAdventCalendarとのことなので、私も記事を投稿してみたいと思います(ง •̀_•́)ง

今回はSite24x7の連携機能の１つ、**Zapierとの連携**をしていこうと思いますので、お付き合いいただければ。

ちなみに・・Zapierは初めて使ってみます！

では、いきましょう。
#Zapierと連携して、やりたいこと。

Zapierと連携すると、Site24x7から他のオンラインアプリを操作する作業を自動化できるんです。
（Slack、HipChat、Gmail、Zohoレポート、Trello、、）
なので、下記のようなことができます。

・連絡先がSite24x7に新規追加されると、Gmailを送る
・監視がSite24x7に新規追加されると、Googleスプレッドシートに記録される
・Site24x7でアラートが上がった時、Trelloにタスクを追加する　etc...

様々な組み合わせがあるみたいなので、最善の方法を選んでいただければと思います。
今回私はこれをやってみようかと思います。

**・Site24x7でアラートが上がった時、Googleスプレッドシートにそのアラートを記録する**
アラートをずらっと並べて見られると、危機迫ると言いますか。。そのためです。
##連携方法

連携方法まで語ってしまうと大変長くなりますので、詳しくは[**ここ**](https://www.site24x7.jp/help/admin/third-party-integration/zapier.html)を参照してください。
順番通り進めていただければ誰でもできます。私もこのページに沿って設定しました。

私はZapierを初めて使うので、サインアップから行いましたが、すでにZapierをお使いの方はログインをするだけです。

TriggerにSite24x7を選び、Actionで組み合わせたいオンラインアプリを選択します。
ここで私はスプレッドシートを選択。
![2018-12-14_15h50_52.png](https://qiita-image-store.s3.amazonaws.com/0/326030/dd8de572-94a5-ab4e-c6e1-d2f0528f18a8.png)

Google側で連携させるスプレッドシートを作成しておくといいと思いますが、
連携させたタイミング（Googleのアカウント認証の後）でも全然大丈夫でした。

そして、びっくりしたのがここです。
![2018-12-14_15h10_37.png](https://qiita-image-store.s3.amazonaws.com/0/326030/b2db03fa-bcc7-5275-c3d8-290675131da3.png)

スプレッドシートの1行目に
　date
　monitor name
　status
　contents
って入れておいたら、紐付けができたんです。Zapierすごいですね。優秀。

引き続き設定を進めて、**Finish**して、**dashboard**に辿り着くかと思います。
そしたらここを**ON**
![2018-12-14_16h22_50.png](https://qiita-image-store.s3.amazonaws.com/0/326030/e10df9fa-70e6-1249-d374-fb621f5c60d6.png)

Site24x7に戻ります。
　管理 -> サードパーティ連携
![2018-12-14_16h28_12.png](https://qiita-image-store.s3.amazonaws.com/0/326030/357090a1-34c2-454a-bf43-58d8d0711ffc.png)
追加されましたー！

しばらくアラートが発生するのを待ってみると、スプレッドシートの方も充実してきます。
![2018-12-14_16h37_13.png](https://qiita-image-store.s3.amazonaws.com/0/326030/633f1638-6f94-3d70-9bff-f98cfa7d6b9e.png)

ただ、出力されるデータの日本語が文字化けを起こすという。。
（こちらの問題に関しては、対応してくださるとのことですので、来年には日本語も写るといいな・・！）

##終わりに##
Site24x7単体では、今回のようにシートに一覧出力！という機能はまだないようです。
しかし、こうやって連携を駆使して「やれるところに、得意なところに、やってもらおう★」という思考、いいですよね。※文字化けしなければ。

また、サービスによる仕様の違いがどーしても気に食わない！という企業様にも、
連携機能って融通が利くんじゃなかろうかと思います。

では今回はこの辺でヾ(*ﾟｰﾟ)ﾉ~~~☆
PHPで$_SERVERを使ってURL（パラメータ）を取得する。

# PHPでURLを取得したい

メモです。
[PHPリファレンス](http://php.net/manual/ja/reserved.variables.server.php) の写し書きです。

### ドメイン名の取得
現在のスクリプトが実行されているサーバーのホスト名です。 
スクリプトがバーチャルホスト上で実行されている場合は そのバーチャルホスト名となります。

```php
$_SERVER['SERVER_NAME'];
```

### スクリプト名の取得
現在のスクリプトのパス。 スクリプト自身のページを指定するのに有用です。
__FILE__ 定数には、カレント(すなわち読み込まれた)ファイルのパスとファイル名が 含まれます。

```php
$_SERVER['SCRIPT_NAME'];
```

### パラメータの取得
ページがアクセスされた際にもし検索引数があればそれが格納されます。

```php
$_SERVER['QUERY_STRING'];
```

### 絶対パスの取得
現在実行されているスクリプトの絶対パス

```php
$_SERVER['SCRIPT_FILENAME'];
```

#### ※注意（相対パス）
>file.php あるいは ../file.php のような相対パスを指定して CLI でスクリプトが実行されている場合、 $_SERVER['SCRIPT_FILENAME'] には ユーザーが指定した相対パスが含まれます。 

### ページアクセスしたURL(URI)
ページにアクセスするために指定された URI。例えば、 '/index.html' 

```php
$_SERVER['REQUEST_URI'];
```
XamarinでiOSのシステム音・バイブ機能を呼び出す

DependencyService使ってiOS側に書くしかないです

````csharp
[assembly: Dependency(typeof(DeviceFunction))]
namespace hoge.iOS
{
    public class DeviceFunction : IDeviceFunction
    {
        private SystemSound _sound = null;
        private SystemSound _vibe = null;

        public void PlayVibrate()
        {
            if (_vibe == null)
            {
                _vibe = new SystemSound(1519);
            }
            _vibe.PlaySystemSound(); // サウンドと言いつつ振動する
        }

        public void PlayGoSound()
        {
            if (_sound == null)
            {
                _sound = new SystemSound(1104);
            }
            _sound.PlaySystemSound();
        }
}
````

少し古い記事ですがID番号をまとめてくれてる記事ありました

https://dev.classmethod.jp/smartphone/ios-systemsound/
［ブログ］最尤推定と最小二乗法が同じ意味になるとき

# はじめに
　どうもお久しぶりです．AIとか自動運転，EVなどをよく見る世の中になりました．他にネタはないのかと思う時があります（笑）．時代のせいか僕が通う大学も最近情報系の授業が入ってきているのを感じます．大学も手探りで情報系の教育を模索しているような気がします．結局個人の意欲によるところがあると思うのですが．
　さて，そんな時流の中である講演を聞くと，ある日エレーーー先生がこんなことを言ってきました．『最小二乗法と最尤推定法は大体同値なんじゃよ．』っと．当時僕は最小二乗法は知っていましたが，統計なんてよくわからず，『最尤推定法ってなんじゃらほい？』って感じでした．なので，「へーそーなんだ．」以上の感覚を持てませんでした．
　しかし，妙にエレーーー先生の言葉頭に残り，ある日ググって[こんな記事](https://mathwords.net/saisyonijoho)を見つけました．これを見た僕は先生の意味が分かり，喉元の小骨が取れた気がしてすっきり納得しました．
　本記事は先の記事を自分なりにまとめた備忘録です．よければ暇つぶし程度に読んでみてください．
　本記事は最小二乗法と最尤推定法の定義をまず述べ，その後証明，そして二項分布でも成り立つよということ(具体例の記事もリンク張っときました．)を解説しました．

# 最小二乗法
　最小二乗法について説明します．(まぁ，大体の人が知っていそうですが．)説明変数を$x_i$，目的変数を$y_i$という２種類のデータが与えられています．その時に２つのデータの間に次のような$y = f(x)$という関係があるとします．その様な関数$f(x)$を求める方法の1つです．
　最小二乗法では下記のような量$G$を定義します．

```math
 G := \sum_{i=1}^n (y_i - f(x_i))^2
```

　その後$G$を最小にするような関数$f(x)$を求めます．これが最小二乗法です．
　簡単な具体例を示します．普通は$f(x)=ax+b$を推定するという問題を考えます．その場合は$G$を最小にするような$a$,$b$を推定することになります．($a$，$b$で$G$を偏微分して$\frac{\partial G}{\partial a}=0$，$\frac{\partial G}{\partial b}=0$を連立して解けば行けます．)

# 最尤推定法
　次に最尤推定法について説明します．最尤推定法には目的変数が従う確率分布をあらかじめ決めておく必要があります．この分布は$y_i$，$x_i$，関数$f(x)$が与えられて初めて決まるものとします．そのような確率分布の関数を$p(y,f(x))$としておきます．この確率をもとに最適な関数$f(x)$を求める方法の1つです．
　最尤推定法では次のような量$L$を定めます．

```math
 L := \sum_{i=1}^n \log{p(y_i,f(x_i))}
```

　その後$L$を最大にするような関数$f(x)$を求めます．これが最尤推定法です．
　繰り返しますが<font color="DeepPink">本手法は最小二乗法と違い，目的変数が従う確率分布$p$をあらかじめ決めないといけない</font>ところがあります．

# 同じの意味になるとき
## 証明
　一見まるで違う最小二乗法と最尤推定法です．しかし，最尤推定法がある条件を満たすとき，最尤推定法と最小二乗法が同じ意味になるときがあります．それは<font color="DeepPink">確率分布$p$が正規分布になる時</font>です．今回は実際にどうなるか計算してみます．$p$が正規分布となる時，確率は具体的に下記の様に書くことが出来ます．

```math
 p(y_i,f(x_i))= \frac{1}{\sqrt{2 \pi \sigma^2}} e^{-\frac{(y_i-f(x_i))}{2\sigma^2}}
```
　ここで尤度$L$を計算してみます．

```math
 L = \sum_{i=1}^n \log{p(y_i,f(x_i))}\\
=-\frac{\sum_{i=1}^n(y_i-f(x_i))}{2\sigma^2}-\frac{n}{2}\log{2 \pi \sigma^2}\\
=-\frac{G}{2\sigma^2}-\frac{n}{2}\log{2 \pi \sigma^2}
```

　ここで$\frac{n}{2}\log{2 \pi \sigma^2}$，$\frac{1}{2\sigma^2}$は定数です．よって変数は$G$のみです．$G$が最小になる時，$L$は最大になります．つまり，最小二乗法と最尤推定法が一致することが言えました．

## ちょっとひねった例
　ここでちょっとひねった例を示します．それを[ここ](https://qiita.com/katsu1110/items/5792250de638e377ee14)に示します．リンクを貼った記事では最尤度推定を行うにあたって<font color="OrangeRed">確率分布$p$に二項分布</font>を用いています．本記事と関係ないように思えます．しかし，[ド・モアブル=ラプラスの極限定理(中心極限定理の特別な時)](https://ja.wikipedia.org/wiki/%E4%BA%8C%E9%A0%85%E5%88%86%E5%B8%83)よりサンプル数$n$が十分大きいとき．(どれくらい大きければいいかというと$np(1-p)>5$くらいあればいいらしいです．wikipediaに書いてありました．（笑）)二項分布の確率は下記の様に正規分布に近似できます．

```math
p \sim \frac{1}{\sqrt{2 \pi \sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}}
```


[証明はここにあります．](https://en.wikipedia.org/wiki/De_Moivre%E2%80%93Laplace_theorem)
　よって二項分布で最尤推定した結果も<font color="DeepPink">サンプル数$n$が十分大きければ，$p$が正規分布の時と同じようになり，最小二乗法と最尤推定法の結果が一致します．</font>

# おわりに

　読んだ人が「へーそーなんだ」って思ったらいいなって思います．統計などの記事はネットに書き尽くされているの何番煎じになっているか怖いですが，一応記事を書いてみました．僕が書いたので間違っているかもしれませんが，そこはご愛敬で．ちゃんと学びたい人はちゃんと本をかって読んで勉強しましょう．

以上
Gemfileで指定されたRubyのバージョンを変更する

自分用メモ。

<h1>サーバーが起動しない</h1>

```
bundle exec rails s
```
を実行すると、

**Your Ruby version is 2.5.1, but your Gemfile specified 2.3.3**
というエラーが出た。

今回、Gemfileのバージョンを2.5.1にしたかったため、Gemfileを書き換えることにした。

<h1>Gemfileを書き換える</h1>
ディレクトリ内のGemfileを開く

バージョンは３行目に書かれていた

```
ruby '2.3.3'
```

これを2.5.5に直す。

保存して再度サーバー起動を試みるも、
**Could not find concurrent-ruby-1.1.1 in any of the sources**
**Run `bundle install` to install missing gems.**
というエラー発生。

<h1>bundle updateの実行</h1>
下記のサイトがそのまま役に立った。
>http://startonlineeikaiwa.com/programming/2017/01/18/rails-server%E5%AE%9F%E8%A1%8C%E2%86%92%E3%80%8Crun-bundle-install-to-install-missing-gems-%E3%80%8D%E2%86%92bundle-update%E3%81%A7%E8%A7%A3%E6%B1%BA/

```
bundle update
bundle exec rails s
```
で解決。
Rails Girlsのドキュメントについて

# 導入

あなたは[Rails Girlsのガイド](http://railsgirls.jp/)を見たことがあるでしょうか。これ、実によくできているんですが、ドキュメントの保守はどこでも大変です。では、Rails Girlsではどうやってドキュメントを保守しているのでしょうか。また、ドキュメントの中身はどうなっているのでしょうか。

# 本題

## 管理

ドキュメントは[GitHub上のレポジトリ](https://github.com/railsgirls-jp/railsgirls-jp.github.io)で管理されています。
コントリビューターの数を見ると、本稿執筆時点（2018/12/14）で67名がコントリビュートしており、チュートリアルのみのドキュメントとしてはかなり多くの人が関わっているプロジェクトだと思います。

## 内容

Rails Girls本編でカバーしている内容以外にも、かなり豊富な内容が盛り込まれています。例えば、[Deviseに関する章](http://railsgirls.jp/devise)があったり、[RSpecに関する章](http://railsgirls.jp/testing-rspec)もあったりします。
これらがどういうときに使われるかというと、イベント後の自習やフォローアップ（More）の題材に使われたりします。
なお、日本語版独自の内容というのはなく、すべて本家の翻訳版となっています。

## 実装

ドキュメントサイトは[Jekyll](https://jekyllrb.com/)という静的サイトジェネレーターを使って構築されています。
環境構築は通常のRubyプロジェクトと同様にcloneした後`bundle install`すれば終了です。

## 更新

更新は通常のOSSと同様にプルリクエストを通じて行われます。
修正したい箇所に該当するmarkdownファイルを見つけ、編集してコミットし、プルリクエストを送ってマージされれば変更が反映されます。バージョンなどはなく、マージされれば即座にデプロイされます。いいですね！
コミットの頻度は極端に多いときと少ないときがあります、これはRails Girlsの本編が開かれるタイミングで打ち合わせをし、その中で見つけた修正点をその場か翌日程度のタイミングで直すことが多いためです。

## 問題点

このように、基本的にはイベント本編と歩調をあわせて更新されるドキュメントですが、内容の節で紹介したRSpecの章が訳されていないことからもわかるとおり、決して完璧にメンテナンスされているわけではありません。
記述されているRubyやライブラリのバージョンを最新に保つことはできていますが、大掛かりな修正まではなかなか手が回らないのが現状です。
特に現在悩みのタネとなっているのがWindowsへの対応です。

### WindowsかCloud9か

そもそも、Ruby開発者の圧倒的多数はMacかLinuxを使っているため、Windowsマシンを持参する参加者に対しては、Windowsの使用経験がある少数のコーチがつく必要がありました。また、RubyInstallerが古いなどの問題で他の環境と条件を揃えることも困難な場合がありました。
そのため、最近はCloud9というクラウド上で動くIDEを使ってもらうケースが増えました。クラウドではLinuxが動くため、WindowsにRubyをインストールする必要もなく、最新のRubyを使うことも容易であるというのが利点でした。

### Cloud9のアカウント問題

そこで、最近のRails GirlsではCloud9を利用してもらうことを推奨していました。しかし、全国のRails Girlsでオーガニゼーションを統一した結果、アカウント数が上限に達してしまっていました。

### WSL

そこで、最新のWindows上で動作するWSL (Windows Subsystem for Linux)を利用してもらう方向に切り替えようとしているのが現時点の状況となります。
WSLについての説明は省きますが、要はWindows上でLinuxが直接動くし、エディタはWindowsネイティブなものを使えるし、もうこれでいいのではという感じです。

## WSLに対応したドキュメントの作成

WSLに関しては、常用しているコーチがあまりおらず、ドキュメントも手付かずのままとなっています。
次回のRails Girlsの開催が迫る中、限られた時間でドキュメントの作成を行わなくてはなりません。

### Want help!

この記事をここまで読んでくれたそこのあなた！私達と一緒にドキュメント作成に参加しませんか？
@okuramasafumi までご連絡ください！（Twitterでも同じIDです）
複数モデル、複数レコードの一括更新(Rails)

複数モデル、複数レコードの一括更新をしようとして少し悩んだので実装方法をメモ

##実行環境など
Rails 5.2.1
ruby 2.5.1

##テーブル構成

###teams
| id | name |
|:---------|:---------|:---------|
| 1 | チーム1 |

###members
| id | team_id | name |
|:---------|:---------|:---------|
| 1 | 1 | 一郎 |
| 2 | 1 | 次郎 |
| 3 | 1 | 三郎 |

##Model

```team.rb
class Team < ApplicationRecord
  has_many :members
end
```

```member.rb
class member < ApplicationRecord
  belongs_to :team

  def self.multi_update(members_params)
    members_params.to_h.map do |id, member_param|
      member = self.find(id)
      member.update_attributes!(member_param)
    end
  end
end
```
##Controller

```team_controller.rb
class TeamsController < ApplicationController

  def edit
    @team = Team.includes(:members).find(params[:id])
  end
  def update
    team = Team.find(params[:id])
    ActiveRecord::Base.transaction do
      team.update_attributes!(team_params)
      Member.multi_update(members_params)
    end
  end

  private
    def team_params
      params.require(:team).permit(:name)
    end
    def members_params
      params.require(:team).permit(members: :name)[:members]
    end
end
```

##View

```edit.html.slim
//ajaxを切る場合はオプションで「local: true」を指定する
= form_with model: team, url: team_path(team.id) do |f|
  label チーム名
  = f.text_field :name

  label メンバー
  - team.members.each do |member|
    = f.fields_for "members[]", member do |af|
      p 名前
      p.control
        = af.text_field :name

  = f.submit "更新"
```

#参考サイト
http://j-caw.co.jp/blog/?p=1590

#その他
間違いや修正点などありましたらコメントお願いします。
Travis CI でGitHubのReleasesにファイルをアップロードする。2018-12-14

# 概要
![スクリーンショット 2018-12-14 17.06.46.png](https://qiita-image-store.s3.amazonaws.com/0/3800/b4d0b838-0e18-5886-eaa2-791e084422ff.png)

GitHubのReleasesへのファイルのアップロードをTravis CIを使って行います
ググったらいくつか記事は見つかったもののちょっと情報が古いものが多かったので、2018年12月の状況として記事にします

# やること
1. `travis` コマンドのインストール
2. **`travis setup releases` にて `.travis.yml` の作成**
3. `.travis.yml` をpush

# 1. `travis` コマンドのインストール
```
% gem install travis
```

上記コマンドでインストールします
`ffi` というgemのインストールでエラーになるかもしれませんが、解決方法は割愛します

# 2. `travis setup releases` にて `.travis.yml` の作成
**ここが本題**

あとは以下のコマンドで `.travis.yml` を作成してほぼ完了です

```
% touch .travis.yml # .travis.ymlが存在しないとエラーになるのでtouchしましたが、すでにある場合は不要です
% travis setup releases --pro -r abetomo/csv-select
Username: abetomo
Password for abetomo: ***
File to Upload:
Deploy only from abetomo/csv-select? |yes|
Encrypt API key? |yes|
```

## コマンドのオプション
* `abetomo/csv-select` は例です。自分のリポジトリを指定します

## 入力
* `Username:`
    * GitHubのユーザ名
* `Password for xxx:`
    * GitHubのパスワード
* `File to Upload:`
    * アップロードしたいファイルを指定するのだけれど空でEnterでも良いです。（あとから `.travis.yml` を修正すればよいので）
* `Deploy only from xxx/yyy? |yes|`
    * そのままEnter
* `Encrypt API key? |yes|`
    * そのままEnter

## `.travis.yml`
実行すると `.travis.yml` が作成されています

```.travis.yml
deploy:
  provider: releases
  api_key:
    secure:（略）
  file: ''
  on:
    repo: abetomo/csv-select
```

あとは必要な情報を追加していきます。
例として自分の最終形を載せておきます

```.travis.yml
language: node_js
node_js:
- 10
before_deploy:
- npm run pkg
deploy:
  provider: releases
  api_key:
    secure: （略）
  file_glob: true
  file: build/Release/csv-select-*
  skip_cleanup: true
  on:
    tags: true
    repo: abetomo/csv-select
```

設定内容の詳細は昔から変わっていないので割愛します

# 3. `.travis.yml` をpush
ふつうにpushするだけなので割愛します

# 4. 補足
私の場合はtagがコミットされたらdeployする設定だったので、tagをコミットしたらGitHubのReleasesにファイルをアップロードされていました :congratulations: 

# まとめ
* GitHubでtokenを作成したり...のような手順がいらなくなった
* `travis setup releases` を実行するだけで良くなったので楽でした

## 「GitHubでtokenを作成したり...」について補足
GitHubの [Personal access tokens](https://github.com/settings/tokens) で `travis` コマンドが作ったtokenを確認できます
flatten() に再帰は必要ない（Python版）

スクリプト言語には `flatten([[1, 2, [3]], 4]) -> [1, 2, 3, 4]` みたいな、ネストしたリストを平坦化する関数が用意されています。

`flatten` は動作がわかりやすいので、再帰呼び出しのサンプルにもってこいです。

でも・・・

> でも良く考えると flatten() は、現在いる要素の子要素がリストの場合、そのリストの中身をすべて現在いる場所に移動し、自身を削除し、そして今と同じ箇所で再検査すればいいだけなのだ。スタックとして覚えておく必要もない。なので実装は以下の様になる。
>
> [Big Sky :: flatten() に再帰は必要ない](https://mattn.kaoriya.net/software/lang/c/20181214140011.htm)

という事なので、Pythonでも実装してみましょう。

はじめの「再帰を使った flatten()」 を私たちに馴染み深い Python で書くとこんな感じ：

```python
def rec_flatten(src_list):
    """再帰を使ったflatten()"""
    flat_list = []
    for x in src_list:
        if isinstance(x, list):
            flat_list.extend(rec_flatten(x))
        else:
            flat_list.append(x)
    return flat_list
```

これだとリストがネストした分だけ、関数の再帰呼び出しもネストすることになり、`[[[[[[[[[[...[[[1]]]...]]]]]]]]]]` みたいな深くネストしたリストではスタックが足りなくなることがある。

ちなみに再帰呼び出しの最大回数は `sys.getrecursionlimit` で調べられます。

```shell
$ python -c 'import sys; print(sys.getrecursionlimit())'
1000
```

さて、Pythonのリストは変更可能なので、元記事と同じように「子要素のリストの中身を現在いる場所に移動」する事で、再帰無しで flatten を実装できます！

具体的には「スライスへの代入」を使います。

```python
def flatten(alist):
    alist = list(alist)
    i = 0
    while i < len(alist):
        if isinstance(alist[i], list):
            alist[i:i+1] = alist[i]
        else:
            i += 1
    return alist
```

※コメントでも指摘されていますが、Pythonのリストはリンクリストではないので、この実装だと非効率かもしれません。

ちなみに、Pythonの標準ライブラリには `flatten` はありませんでした[^1]。ざんねん。

[^1]: `itertools.chain.from_iterable` で１レベルの展開はできる。
TOSHIBA FlashAirでリアルタイムに写真を転送する

これは [さくらインターネットAdvent Calendar 2018](https://qiita.com/advent-calendar/2018/sakura) 14日目の記事です。

こんにちは[こたまご](https://twitter.com/chibiegg)です。

FlashAirをカメラと一緒に使ってみたので、成果物と開発時に気づいたことをメモします。

毎年わたしだけさくらインターネットに関係ないようなことを書いてる気がしますが...
さくらインターネットには写真が好きな社員がかなりおおく写真に関連するサークルがいくつかあります。
わたしも写真部やインフラ研究部の一環で写真をよく撮りにいったり、サークル関係なく何人かの社員で撮影したりしてますので、まぁよしとしてください。

一部はTwitterやInstagram ([1](https://www.instagram.com/chibiegg/), [2](https://www.instagram.com/hinatan_net/)) に掲載してます。

ということで、本題です。

# FlashAirとは

[公式の説明](https://flashair-developers.com/ja/discover/overview/)によると

>FlashAirは、無線LAN機能を搭載したSDHC/SDXCメモリカードです。FlashAirは、カード単体で無線LANのアクセスポイントとして機能するため、FlashAir搭載機器同士でファイルの送受信を行ったり、PCやスマートフォンなど外部の無線LAN機器からFlashAir内のファイルにアクセスしたりすることが可能です。
>
>FlashAirは、世界の主要な国で発売、利用されており、多数の機器で動作確認が行われています。

とあります。

が、FlashAirにはここに書かれた以上の価値があります。

一般的なWiFi内蔵SDカードは画像転送することだけを機能として持っていますが、このFlashAirは自分でプログラムを仕込んで、好きな動作をさせることができます。

ということで、カメラが趣味の私は何か作って遊べないかと思い、いつ使うのかわからない便利な機能を作ってみました。

# 作ったもの

カメラで撮影したタイミングでMacに写真を転送。
受信した写真を表示。

どんな写真が撮影されているか、大きなモニタでモニタリングすることができます。

![イメージ図](https://qiita-image-store.s3.amazonaws.com/0/73788/43e9c0ce-9185-f146-d53a-440fb67fe2f3.png)

# 作り方

実行するのに必要なファイル全体はREADMEと共にgithubに置いておきます。
https://github.com/chibiegg/airview

FlashAirにはSDカード内部に記録されたLuaスクリプトを実行する機能があります。
実行のタイミングは以下の中から選んで利用することができます。

( 参照：[FlashAir Developers - Luaスクリプトの実行方法](https://flashair-developers.com/ja/documents/api/lua/guide/) )


* FlashAirの起動時
* FlashAirへファイルを書き込んだとき
* HTTPでアクセスがあったとき

今回は、ファイルを書き込んだときにLuaスクリプトを実行し、新しいファイルをGoで実装したサーバにHTTPで通知するような方法で実装しました。
画像送信をリトライできるように、Luaスクリプトから通知するのはファイル名のみで、JPEGファイルの実体はGo側からHTTPでダウンロードするようにしました。

FlashAirに仕込むLuaスクリプトはこちら ([notify.lua](https://github.com/chibiegg/airview/blob/master/lua/notify.lua)) 。

サーバ側はGoで簡単なHTTPサーバを実装し、JPEGファイルのダウンロードは同時に走らないようにキューイングして行うようにしました。

サーバ側のコードはこちら ([main.go](https://github.com/chibiegg/airview/blob/master/bin/main.go))

画像の表示はブラウザで行うようにし、Ajaxを用いたポーリングで新しい画像を取得する、というレガシーな設計となっています。

サーバを起動した状態で、写真を撮ると通知が来て、どんどんダウンロードされるのがログからわかります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/73788/0502f163-3a0e-16d2-56a8-80d13b305551.png)


# 工夫したポイント

`/SD_WLAN/CONFIG` の `LUA_SD_EVENT` は同時実行しないようになっています。
その制約のため、1ファイル1処理を必ずしたいという実装はなかなか難しいです。

今回は一度Luaスクリプトが起動したら、無限ループで終了しないようにし、ポーリング動作で動くようにしました。
そのため、本来はFlashAirの起動時に動作するようにしても問題なく動くと思います。


# 開発中に便利だったもの

FlashAirを機器の中で動かす場合のデバッグがちょっと大変でした。
最初はログをSDカード内に書き込もうと思ったのですが、カメラのようにファイルシステムを利用する機器の中で書き換え動作を行うと当然ですがファイルシステムが破壊されました。

[FlashAir開発者向け非公式wiki | エラーを調べる方法](https://seesaawiki.jp/flashair-dev/d/%A5%A8%A5%E9%A1%BC%A4%F2%C4%B4%A4%D9%A4%EB%CA%FD%CB%A1) にいくつかのデバッグ方法が記載されているので、大変役に立ちました。
この中でも、私は http://flashair/eva.cgi にアクセスする方法でだいたい事足りました。

# 12月25日はさくらの聖夜

今年も[さくらの聖夜](https://connpass.com/event/112016/)を開催します。
わたしのこの内容もLTして、実演しようと思っていますので、ぜひお越しくださいー。
DOMAで複数列のIN句（列:条件 = n:n）を実装する。

# 複数列のIN句？？？

こんなの

```sql
SELECT * FROM TEST_TBL
WHERE
    (FIRST_NAME, LAST_NAME) IN (
        ('山田', '太郎'),
        ('鈴木', '次郎')
    )
```

# DOMAで実装
普通にやるとダメなのでfor文で頑張る。

```sql
SELECT * FROM TEST_TBL
WHERE
    (FIRST_NAME, LAST_NAME) IN (
        /*%for condition : conditionList */
            (/* condition.firstName */'firstname', /* condition.lastName */'lastname')
            /*%if condition_has_next */
                ,
            /*%end */
        /*%end */
        /*%if conditionList == null || conditionList.isEmpty() */
            (NULL, NULL)
        /*%end */
    )
```