OmniAICreator/Qiita-1.07M huggingface dataset:
[GitHub] IssueとPull Requestのテンプレート機能を利用してフォーマットを統一する

IssueとPull Requestのテンプレートを作成しておけば、Issue・Pull Requestを作成するタミングでテンプレートの内容をデフォルトで表示してくれる機能があります。
Issue・Pull Requestを作成する人が複数人いる場合は、フォーマットが人に依存したり、フォーマットの指定があっても守ってくれない人がいるケースもあると思いますが、GitHubのテンプレ機能を利用することで、作業者が複数人でも統一したフォーマットをあらかじめ用意しておくことができます。

[Railsのリポジトリ](https://github.com/rails/rails/tree/master/.github)でもGitHubのテンプレート機能は使われています。

この記事は個人ブログでも掲載しています。
http://tackeyy.com/blog/how-to-make-github-issue-and-pull_request-template

# テンプレートの配置場所

以下のどちらかにテンプレートファイルを配置してください。

- リポジトリのルートディレクトリ
- ` .github/ ` ディレクトリ直下

Railsは ` .github/ ` 以下にファイルを置いているのでぼくもそれにあわせてみました。

# テンプレートファイル

マークダウンに対応しているので以下の名前で ` *.md ` ファイルを作成します。

- PULL_REQUEST_TEMPLATE.md
- ISSUE_TEMPLATE.md

以下のような感じでファイルを置いてください。
GitHubの説明上はファイル名は大文字なのですが、小文字にしても問題ありません。

https://github.com/tackeyy/blog/pull/20/files

```
.github/issue_template.md

+### Summary
+
+### TODO
```

```
.github/pull_request_template.md

+fixes #
+
+### Summary
+
+### Other Information
```

# どんな感じになるか？

[![https://gyazo.com/0e5c8987493093e890c54ef5c65cf3d9](https://i.gyazo.com/0e5c8987493093e890c54ef5c65cf3d9.png)](https://gyazo.com/0e5c8987493093e890c54ef5c65cf3d9)

[![https://gyazo.com/8c9856aea4582a9ca187f88b610538a2](https://i.gyazo.com/8c9856aea4582a9ca187f88b610538a2.png)](https://gyazo.com/8c9856aea4582a9ca187f88b610538a2)

（昔のbranchからmasterに向けたPull Requestなのでコンフリクトしてます）


# 参考

https://github.com/blog/2111-issue-and-pull-request-templates
[Rails][SEO] PubSubHubbubにPOSTリクエストを送信してWebページをいち早くGoogleにインデックスしてもらう

Googleにいち早くインデックスしてもらうのはSEOを考えると重要です。

Railsで作成している[私のブログ](http://tackeyy.com/)では毎日sitemapを作成した後に検索エンジンに対して通知を飛ばしていますが、
投稿したブログがインデックスされるまでに少し時間がかかってしまいます。

ブログを投稿後にPubSubHubbubにPOSTリクエストをすればより早くインデックスしてもらいやすくなるため、今回対応してみました。

この記事は個人ブログでも掲載しています。
http://tackeyy.com/blog/send-post-request-to-pubsubhubbub

# PubSubHubbubとは

> PubSubHubbub (パブサブハブバブ) とは、更新情報を Google にリアルタイムで通知することができるプロトコルです。略して、PuSH (プッシュ) とも呼ばれます。Pub は Publisher (配信)、Sub は Subscriber (購読) を意味しており、その間に Hub というサービス (中間サーバ) があるため、このような名前になっています。配信側がコンテンツを更新すると、Hub が購読側に通知を行います。購読側は更新情報をすぐに知ることができるため、リアルタイムの情報配信が実現できる仕組みになっています。

https://murashun.jp/blog/20150915-01.html

PubSubHubbubについて調べたのですが、引用させていただいた上記の記事が一番わかりやすかったので、目を通しておくと良いです。

# PubSubHubbubにPOSTリクエストを送る

今回実装するのはこのブログなので、記事が公開されたタイミングでPubSubHubbubに対して投稿した記事のURLをPOSTします。
URLをPOSTするだけなので自前で実装できそうですが、車輪の再発明になりそうなのでGemを探してみました。

## PubSubHubbub対応に使えるGems

- [igrigorik/PubSubHubbub](https://github.com/igrigorik/PubSubHubbub)
- [Gargron/pubsubhubbub](https://github.com/Gargron/pubsubhubbub)
- [shiro16/nagareboshi](https://github.com/shiro16/nagareboshi)

Star数も多くPubSubHubbubが鉄板なようです。
pubsubhubbubはマストドンの人が作ってるGemで、フィードなどがある場合は使い勝手が良さそうです。
今回はPubSubHubbubとnagareboshiを比較して以下の3点の理由からnagareboshiを採用しました。

1. シンプル
  - ` Nagareboshi::Sender.publish("http://example.com/") ` でOK
2. 名前が良い
  - PubSubHubbubは ` EventMachine.run ` ですが、 ` Nagareboshi::Sender.publish ` の方が個人的にわかりやすい（EventMachineってなんやねんと思う）
  - [shooting_star](https://github.com/shiro16/nagareboshi/blob/master/lib/nagareboshi/sender.rb#L14-L27)もいいですねw
3. 自分でメンテできそう
  - star数が少なくてメンテされてなさげですが、コード量も少なくやっていることもシンプルなので何かあっても自分でメンテできそうです

# nagareboshi(Gem)を使ってPubSubHubbubにPOSTする

nagareboshiでPubSubHubbubにPOSTする対応をした以下のコミットを簡単に説明します。

https://github.com/tackeyy/blog/commit/764a67f8b06424d17678fa4efab8901ea8b3eaf8

- Gemfileにnagareboshiを追加

```
Gemfile
+# PubSubHubbub
+gem 'nagareboshi'
```

- nagareboshiの設定を追加

```
config/initializers/nagareboshi.rb
+Nagareboshi.configure do |config|
+  config.send = Rails.env.production?
+end
```

- ブログ投稿後にPubSubHubbubにURLをPOST

```
app/models/post.rb

+ after_create :post_pubsubhubbub

+  private
+
+  def post_pubsubhubbub
+    return if wip?
+    # modelではRailsのヘルパーが使えないので *_path じゃなくてべた書き
+    Nagareboshi::Sender.publish("#{Settings.url}/blog/#{friendly_id}")
+  end
```

PubSubHubbubにPOSTが成功したら204が返るので2xx系じゃなければエラーとしたり、Slack通知したりすれば良いと思います。（個人のSlackチーム作ってないし、エラーだと投稿できずにだるいのでいったん未対応です）

```
[1] pry(#<Post>)> Nagareboshi::Sender.publish("http://example.com/")
=> #<Net::HTTPNoContent 204 No Content readbody=true>
```

以上です。

# 最後に

上記の対応を行った後に記事を投稿して30分経っても、インデックスが確認できず・・・
以下のように ` site:url ` でインデックスされているかの確認ができます。

` site:http://tackeyy.com/blog/how-to-make-github-issue-and-pull_request-template `

# 参考

[30分以内に新しいコンテンツをGoogleにインデックスさせる方法](https://www.suzukikenichi.com/blog/how-to-get-new-content-indexed-within-30-minutes/)
[nagareboshiっていうgemをつくったよ](http://shiro-16.hatenablog.com/entry/2014/08/29/110000)
Capistranoでdeploy:rollbackを--dry-run付きで実行するとエラーになる

#### 検証環境

```shell-session
$ ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]

$ cap -v
Capistrano Version: 3.6.1 (Rake Version: 12.0.0)
```

#### 事象

`deploy:rollback`を`--dry-run`オプション付きで実行すると以下のエラーが出る。

```
00:00 deploy:rollback_release_path
      There are no older releases to rollback to
```

#### 対処法

`--dry-run`オプション無しで実行するとエラーは出ずロールバックも正常に行える。
おそらく過去のリリースを取得するための`ls`コマンドが実行されていないためではないかと思われる。要検証。
dataframe中のNaN入っている行を全て表示

たとえば５万行のデータがあって、その中の`NaN`が入っている行を全て表示したいです。

下のデータの場合 index 101のbananaと index 102のcherryに`NaN`が入っているので、その2行を表示したいです。

```py3
df = pd.DataFrame(
    {
        'apple' : [1.1, 1.2, 1.3, 1.4]
        ,'banana' : [2.1, np.nan, 2.3, 2.4]
        ,'cherry': [3.1, 3.2, np.nan, 3.4]
        , 'damson': [4.1, 4.2, 4.3, 4.4]
    },
    index=[100, 101, 102, 103]
)
```

![スクリーンショット 2017-08-07 10.23.18.png](https://qiita-image-store.s3.amazonaws.com/0/54698/8a85ccc9-0ee5-c485-5ec8-cf9be6ee1aa9.png)

各カラムに何個の `NaN`が入っているかをチェックします。

```
df.isnull().sum()
```
結果：

```
apple     0
banana    1
cherry    1
damson    0
dtype: int64
```

`type(df.isnull().sum())`自体はpandasのSeriesデータタイプであることを確認

```
type(df.isnull().sum())
```

結果： `pandas.core.series.Series`

Seriesデータは `iteritem()`メソッド持っているため、NaNの個数０より大きいカラムを抽出します。

```
l = []
for index, value in df.isnull().sum().iteritems():
    if value > 0:
        l.append(index)
l
```
結果： `['banana', 'cherry']` 


![スクリーンショット 2017-08-07 10.38.29.png](https://qiita-image-store.s3.amazonaws.com/0/54698/5dd55248-74dc-e68a-d243-81c44bdfacc8.png)

上の図は別々で表示していますが、この複数行を連結して表示します(重複のindexを除いて表示する)。

```
result = []
for i in l:
    result.append(df.loc[df[i].isnull() == True, :])
df_nan = pd.concat(result)


df_final =  df_nan.reset_index().drop_duplicates(subset='index', keep='last').set_index('index')
df_final
```

![スクリーンショット 2017-08-07 11.06.32.png](https://qiita-image-store.s3.amazonaws.com/0/54698/837d39cc-df7b-8464-8444-2686c23ebd1c.png)
Node-REDをインストールする

IoTのダッシュボードを作ってみます
道具として、Node-REDを使います。Node-REDを動かすために、まずnode.jsをインストールします。

#1. Firefoxを用意します
- Node-REDでノードを編集するにはFirefoxが推奨なので使用できることを確認します
- Firefoxが未インストールの場合、[Firefoxのサイト](https://www.mozilla.org/ja/firefox/)からダウンロードしてインストールします
- このあと、Node-REDの作業をする際には、Firefoxで`localhost:1880`など開いて作業するようにします

#2. node.jsをインストールします
-[node.jsのサイト](https://nodejs.org/ja/)へアクセスし、環境(Macbook/Windows)に合ったnode.jsをインストールします
-このときnpmも同時にインストールされます
<img width="869" alt="スクリーンショット 2017-07-17 16.36.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/66be3b87-143e-d769-f476-12454a082e5b.png">


#3. Node-REDをインストールします
-[NodeーREDのインストールのページ](https://nodered.org/docs/getting-started/installation)へアクセスし、npmでNode-REDをインストールします
-Node-REDでは、[Library](https://flows.nodered.org/)からいろいろなノードを追加することが可能です
<img width="1169" alt="スクリーンショット 2017-07-17 16.36.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/7830ee9d-aaf1-5d95-0614-8e7d9de3b2ac.png">

- ターミナル画面から`node-red`と入力してNode-REDを起動します。デフォルトでport=1880で起動されます
- ブラウザから`http://localhost:1880`へアクセスし、Node-REDの画面を開きます

<img width="980" alt="スクリーンショット 2017-10-05 11.30.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/7f43b8b0-2d4a-2f4d-dc0e-1be935311226.png">

- 同じ画面で[Cntl]+CでNode-REDを停止します
さくらインターネットからGoogle Domainに移行

さくらインターネットからGoogle Domainに移行するときのメモです。

嵌って完了するまでに時間が掛かってしまいました。
分かっていれば、さくらインターネットからのレスを起点に1時間で完了できるレベルの作業です。
嵌ったポイントを分かりやすくするために、実際に作業した時系列で手順を記載します。
**正しい手順は、Step6の作業を一番最初にするとスムーズです。**

#Step 1
さくらインターネットの管理画面で、契約情報　→　契約ドメイン と入り、移管したいドメインのボタンから｢転出｣を押します。

![step3.png](https://qiita-image-store.s3.amazonaws.com/0/130074/63559f43-5847-cecd-a0fb-0cdf0dfb3127.png)

#Step 2
表示された画面で、
「注意事項を確認し、同意しました。」にチェックを入れ、管理者メールアドレスに受信できるメールアドレスを入力し、送信します。
そうすると、自分は1営業日後にさくらインターネットからメールが届きました。

![step4.png](https://qiita-image-store.s3.amazonaws.com/0/130074/27638e4a-525c-f0f1-2558-d8a1604d7682.png)


※遅くとも3営業日以内に返信を頂けるようです。
※ここが分かりにくいし、少し不安になります。しょうがない部分かもしれませんが...


#Step 3
メールに

【オースコード】

と記載されたコードをコピーして、Google Domainを開きます。

#Step 4
ここにドメイン名を入力し、続行を押します。

![step1.png](https://qiita-image-store.s3.amazonaws.com/0/130074/984a54fb-4ca0-3e36-2376-8b608b956cb0.png)


※申請ドメイン名は、移管させたいドメイン名が入っているので、そのまま触らず。
(画像はわざと入力内容を｢ここにドメイン名が入っています。｣にしました。通常example.comと選択したドメインが入っているはず)


#Step 5
![step5.png](https://qiita-image-store.s3.amazonaws.com/0/130074/c6d2df0d-7271-9896-5876-d8012c09919b.png)


オースコードを入力する項目があるので、入力して続行。あとは、支払いまで続行を押下。

#Step 6　※この手順を一番最初にやるべきです。
ここで嵌りました。
この手順のままだと承認確認メールがさくらインターネットに届いてしまいます。さくらインターネットの管理画面で**ドメイン登録者のメールアドレス**を変更する必要があります。さくらインターネットに質問したら、教えてくれました。

下記手順で自分のメールアドレスに変更して、再度Step 4から実施してください。

[さくらインターネットのヘルプ](https://help.sakura.ad.jp/hc/ja/articles/206052982)

![a41dcedf-bbe3-8d88-e868-718b9786642a.png](https://qiita-image-store.s3.amazonaws.com/0/130074/60419c50-7b5f-955d-d1ad-cf19084ad9ac.png)

上記黒塗りのところに届くメールアドレスが記載されています。さくらインターネットのメールアドレスになっている場合、変更が必要です。自分はさくらインターネットが何かしてくれるかと期限切れまで待ってしまいました…

#Step 7
メールが届くので、その中にあるリンク(｢確認｣というボタンを押す)を開きます。

![無題2.png](https://qiita-image-store.s3.amazonaws.com/0/130074/8c84bf4d-b110-ed70-72e8-9c916f97f536.png)

#Step 8
移管がほぼ完了している旨表示されるので、別途メールが届くのを待ちます。
届いたら、JPRSの移管承認ページが表示されるので、承認ボタンを押します。

![無題3.png](https://qiita-image-store.s3.amazonaws.com/0/130074/76f97969-de1f-d1b7-8426-e040532fc4c0.png)



#嵌ったところ以外で、困ったこと
- さくらインターネットで移管手続きの申請をマイページの契約情報から実施。転出ボタンを押すところまでは迷いなくやれます。
ただフォームから申請を送信するところがわかりづらいです。やってよいことなのか少し悩みます。転出手続きなので、分かりやすくしたくないところかもしれませんが...


- 連続して2つのドメインを移行させようと2つ目を作業進行させている時、支払いできないことが発生。原因はよくわかりません。しばらく待ったら、出来るようになりました。
[実験]Rubyでマルチスレッド・マルチプロセスの挙動の違いを調べてみた

# はじめに
Rubyの並列処理について、いくつか基本的なケースの挙動を確認してみます。具体的には、マルチプロセス・マルチスレッド・GIL(※1)・排他ロックあたりの挙動を見ていきます。

今回使用した環境は以下のとおりです。
Rubyのバージョン: `ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]`
parallelのバージョン: `parallel (1.9.0)`

# 並列処理のさまざまなケース

並列処理の条件を変えてcounter変数をインクリメントし、counter変数のふるまいの違いを調べます。

### マルチプロセスの場合

```ruby
counter = 0
Parallel.each(1..100, in_processes: 2) do # 2プロセスでインクリメントする
  counter += 1
  print "%d, " % counter
end

# 結果:
# 1, 1, 2, 3, 4, 5, ..., 60, 36, 61, 62, 37, 63,
```

プロセスごとに別のcounterが作られるため、最大値が100になりません。

ところで、最大値が100にならないのは、counterのインクリメントに対して排他制御がかかっていないためとも考えられます(※2)。それでは、次のケースを試してみます。


### マルチプロセスで排他ロックをかけた場合

```ruby
counter = 0
Parallel.each(1..100, in_processes: 2) do # 2プロセスでインクリメントする
  open(File.join(Dir.tmpdir, 'counter.lock')) do |f|
    begin
      f.flock(File::LOCK_EX) 
      counter += 1
      print "%d, " % counter
    ensure
      f.flock(File::LOCK_UN)
    end
  end
end

# 結果:
# 1, 2, 3, 4, 5, ..., 17, 18, 19, 20, 21, 79,
```
counterのインクリメントに対して排他制御をかけても、最大値が100になりません(※2)。このことから、プロセスごとに別のcounterが作られていることがわかります。


### マルチスレッドでブロッキングIOがある場合
```ruby
counter = 0
Parallel.each(1..100, in_threads: 10) do # 10スレッドでインクリメントする
  counter += 1
  print "%d, " % counter
end

# 結果:
# 1, 2, 3, 4, 5, ..., 100, 87, 94, 95, 89, 97, 91, 99, 92,
```

異なるスレッドでも同じcounterを引き継ぐので、最大値が100になります。数値が1から順番にならないことがあるのは、printのブロッキングIO処理でGILが外れるためです。

### マルチスレッドでブロッキングIOがある場合(排他ロックつき)

```ruby
counter = 0
Parallel.each(1..100, in_threads: 10) do # 10スレッドでインクリメントする
  open(File.join(Dir.tmpdir, 'counter.lock')) do |f|
    begin
      f.flock(File::LOCK_EX) 
      counter += 1
      print "%d, " % counter
    ensure
      f.flock(File::LOCK_UN)
    end
  end
end

# 結果:
# 1, 2, 3, 4, 5, ..., 95, 96, 97, 98, 99, 100
# （つねに1から順番どおりに並ぶ）
```

counterのインクリメントとその後のprintに対して排他制御をかけると、数値がつねに1から順番に並ぶようになりました。printでGILが外れても他のスレッドが割り込まなくなることが確認できます。


### マルチスレッドでブロッキングIOがない場合
```ruby
counter = 0
counters = []
Parallel.each(1..100, in_threads: 10) do # 10スレッドでインクリメントする
  counter += 1
  counters << counter
end
puts counters.join(', ')

# 結果:
# 1, 2, 3, 4, 5, ..., 95, 96, 97, 98, 99, 100
# （つねに1から順番どおりに並ぶ）
```

マルチスレッドのブロックからブロッキングIO処理を外してみると、何回試しても数値が1から順番になります。GILのはたらきにより、並列化がまったく行われていないことがわかります。

# 補足
※1. GIL(Global Interpreter Lock)とは、スレッドセーフティを保つため、スレッド全体に対してかかる大きなロックです。RubyがCによる実装のレベルでスレッドセーフでないこと、細かい粒度でロックを設定するとシングルスレッドの場合にパフォーマンスが落ちることが、GILが実装されている主な理由です。
ブロッキングIOによる待ちが発生すると、一時的にGILは外れるようになっています。

※2. Javaなどでは、値のインクリメントは
・値の読み込み
・読み込んだ値に1を足して書き込み
の2つのプロセスが非アトミックに行われます。もしインクリメントの処理がアトミックならば、もともと排他ロックは必要ありません。Rubyではどうなのでしょうか？
列中に含まれる複数の値を1行ずつ処理する


![tidyr_separe_rows.png](https://qiita-image-store.s3.amazonaws.com/0/19462/9e841cd1-c796-15bc-9675-14246cee004a.png)

タイトルのように、一つの列の中で複数の値に分割できそうな値を含んだデータフレームを扱う場合、区切り文字を元にデータを分割するという処理が必要になるかと思います。次のようなデータです。

``` r
d <- data.frame(
  id    = 1:3,
  tag   = c("apple,banana,melon", "grape,orange", "peer,mango,pine apple"),
  score = c("0.7,0.5,0.4", "0.6,0.2", "0.7,0.4,0.3")
)
```

tag、scoreという列に、カンマ区切りで複数の値が格納されています。このtagとscoreに含まれる個々の値は、apple = 0.7, banana = 0.5のように対となるデータであるとします。

こんなデータの持ち方をするなよ、と怒られそうですが、JSONのような階層構造をもったデータを無理にテーブル形式へ保存しようとするとこういうデータが生まれやすい気がします。

こうしたデータを処理・集計しやすく扱うためにはどうすれば良いでしょうか。**tidyr**パッケージには、まさにこのようなデータの処理をするための関数`separate_rows`が用意されています。まずは関数の実行例を示します。

``` r
library(tidyr)
d %>% 
  separate_rows(tag, score, sep = ",")
```

    ##   id        tag score
    ## 1  1      apple   0.7
    ## 2  1     banana   0.5
    ## 3  1      melon   0.4
    ## 4  2      grape   0.6
    ## 5  2     orange   0.2
    ## 6  3       peer   0.7
    ## 7  3      mango   0.4
    ## 8  3 pine apple   0.3

関数`separate_rows`は、**tidyr**のバージョン0.5.0(2016年6月リリース)で追加された関数です(**tidyr**の最新バージョンは0.6.3)。従来の`separe()`が横方向に列を分割するのに対して、縦方向にデータを分割していきます。まさに今回のようなデータを処理するのに適しています。

詳しい使い方を説明します。と言っても難しいことは特になく、分割対象の列名を引数に与え、区切り文字を*sep*引数で指定するだけです。*convert*という引数も用意されていますが、これは分割後のデータ型を適当な型に変換するかのオプションです。初期値では*FALSE*が指定されており、分割後のデータ型は元のデータ型を引き継ぎます。

*convert*の指定の違いを示します。今回のように、scoreの値を文字でなく数値にしたい場合には*TRUE*を指定すると良いでしょう。

``` r
d %>% 
  separate_rows(tag, score, sep = ",") %>% 
  purrr::map_chr(class)
```

    ##          id         tag       score 
    ##   "integer" "character" "character"

``` r
d %>% 
  separate_rows(tag, score, sep = ",", convert = TRUE) %>% 
  purrr::map_chr(class)
```

    ##          id         tag       score 
    ##   "integer" "character"   "numeric"

これまでのtidyrの記事で見かけない関数だったので紹介しました。

- http://qiita.com/kazutan/items/ab81958994426e67e017
- https://heavywatal.github.io/rstats/tidyr.html

Enjoy!
Herokuにデプロイ (JRuby編）

#始めに
JRubyで開発したモジュールをHerokuにデプロイする方法を書いてみます

#デプロイ
##まずは読むべきサイト
https://devcenter.heroku.com/articles/moving-an-existing-rails-app-to-run-on-jruby
に必要なことは全部記載されています

##重要なポイントを列挙してみる
###Gemファイルへの記載
- ruby 'version', :engine => 'jruby', :engine_version => 'version'を記載する(versionにはそれぞれ使用するモジュールのversionを記載する
- gem 'activerecord-jdbcpostgresql-adapter'を追加する
- gem 'activerecord-jdbcsqlite3-adapter'をコメントアウトする 
- gem 'tzinfo-data'のplatforms:をjrubyのみにする

###Gemファイルの修正後にやること
- bundle updateを実行しGemfile.lockを更新する

#デプロイ後、herokuのサイトにアクセスしたときエラーが出たら
##まずやること
`heroku run rails c`
を打ち、エラーが発生している個所を特定する
大体の場合、
`/usr/bin/env: ‘jruby.exe’: No such file or director`
というエラーが出るので、
「bin/bundle,bin/rails,bin/rake」の「jruby.exe」を「jruby」に変更する
(参考サイト)
https://stackoverflow.com/questions/18433609/getting-usr-bin-env-ruby-exe-no-such-file-or-directory-on-heroku
文字領域検出 by Python with OpenCV on macOS

# はじめに

機械学習のためのデータ収集に文字領域の取得が必要になったので、そのやり方を探していたらOpenCVで簡単にできそう...だったのに苦労したので経過を含めてまとめます。

# Python、OpenCVのインストール

以下のURLを参照。

- [Macで深層学習の環境をさくっと作る手順 with TensorFlow and OpenCV](http://qiita.com/mix_dvd/items/b49651cf1181a986506c)

- [Ubuntu 16.04で機械学習の環境をさくっと作る手順](http://qiita.com/mix_dvd/items/4bf7f6e7fa19068ea1d4)

# サンプルプログラム

[opencv_contrib/modules/text/samples/textdetection.py](https://github.com/opencv/opencv_contrib/blob/master/modules/text/samples/textdetection.py)

実行すると、以下のエラーが出ました。

```
error: erfilter.cpp:4111: error: (-215) !contours.empty() in function MSERsToERStats
```

# 修正と実行

44行目以降の数行を以下のように修正。

```py3:

  regions = cv2.text.detectRegions(channel,er1,er2)
  
  if len(regions) > 0:
    rects = cv2.text.erGrouping(img,channel,[r.tolist() for r in regions])
    #rects = cv2.text.erGrouping(img,channel,[x.tolist() for x in regions], cv2.text.ERGROUPING_ORIENTATION_ANY,'trained_classifier_erGrouping.xml',0.5)
    
    #Visualization
    for rect in rects:
      cv2.rectangle(vis, (rect[0],rect[1]), (rect[0]+rect[2],rect[1]+rect[3]), (0, 0, 0), 4)
      cv2.rectangle(vis, (rect[0],rect[1]), (rect[0]+rect[2],rect[1]+rect[3]), (255, 255, 255), 2)
``` 

で、実行すると以下のとおり。

![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/114240/67b1c2e3-8047-3671-2def-6cc4c104653f.png)

できた！

# おまけ

そして、ふと思うところがあって再び元のサンプルを実行してみたら、エラーなく実行されました(T^T)

...理由がわかりませんorz

どなたかご存知であればご教示下さい（汗）
ロゴをiTerm2でソッコー表示

以下のスクリプトをパスの通っているところに配置し

```shell-session
logo bash
```

とするとiTerm2のシェルエクステンションの機能でターミナル上にbashのロゴを表示する。

```rb:logo
#!/usr/bin/env ruby

require 'open-uri'
require 'nokogiri'
require 'net/http'
require 'uri'
require 'erb'
include ERB::Util

puts "Usage: #{$0} facebook twitter ..." unless ARGV.count > 0

ARGV.each_with_index do |arg, i|
  q=url_encode arg
  url="http://instantlogosearch.com/?q=#{q}"
  
  charset=nil
  html=open(url) do |f|
    charset=f.charset
    f.read
  end
  
  doc=Nokogiri::HTML.parse html, nil, charset
  next unless doc!=nil
  node=doc.xpath('//div[@class="brand-logo__download-ctas"]')[0]
  next unless node!=nil
  imgurl=node.css('a')[1].attribute('href').value
  next unless imgurl!=nil
  system "curl -s #{imgurl} | ~/.iterm2/imgcat"
end
```
ExpoでDropboxからインポート/エクスポートを実現する

# やりたいこと
reduxのstateをjsonとしてdropboxに吐き出してエクスポートし、それのインポートも可能にしたい

# 問題
Expoを用いたReact Naitveの開発をしているのでdropboxのsdk等をつかえない
-> OSのシェア機能で他アプリを呼び出して、ごにょごにょして解決するのがよさそう

# 解決

### エクスポート
こちらはさほど難しくなかった。
`react-native`の`Share`を呼び出してjsonを渡してあげることで実現できる。(dropboxが端末にインストールされている前提)

```js
Export = () => {
  Share.share({
    message: JSON.stringify(this.props.data)
  })
}
```

### インポート
こちらが大変だった。
DocumentPickerを使えばアプリを呼び出せるが、どうやって中身を読むのかで困った。

自分の技術力では実装できずにexpo.ioのforumに質問を投げたところ、実現できた。

```js
Import = async () => {
  try {
    const pickerResponse = await DocumentPicker.getDocumentAsync()
    if (pickerResponse.type === 'cancel') {
      return false
    } else if (pickerResponse.type === 'success') {
      try {
        const downloaded = await FileSystem.downloadAsync(pickerResponse.uri, FileSystem.documentDirectory + 'import.json')
        const fileResponse = await FileSystem.readAsStringAsync(downloaded.uri)
        console.log(JSON.parse(fileResponse))
      } catch (exception) {
        console.log(`[FileSystem]: ${exception}`)
      }
    } else {
      return false
    }
  } catch (exception) {
    console.log(`[DocumentPicker]: ${exception}`)
  }
}
```

forumの質問はこちら(https://forums.expo.io/t/read-a-contents-from-dropbox-with-documentpicker-filesystem/1976)

# はまったところ
割りと初歩的な(かつ当然と言われれば当然な気もする...)ところなのかもしれないが、インポートの際にDocumentPickerを用いてDropboxからファイルを選択した際に例外を投げるところでつまづいた。
原因はdocumentPickerが返してくれるuriはfile:///だがローカルにはないらしく参照できなかったからだと思われる。
これに気が付かずハマったが、forumでダウンロードされてないからじゃないかという指摘を頂き、`FileSystem.downloadAsync()`を使ってダウンロードすることを試すとうまくいった。


# 最後に
Expoはとても便利だが提供してくれるAPIをしっかり理解して使いこなす必要がある。
nativeでのファイルの扱いや連携のいい勉強になった。
forumはとても頼りになります、ありがとうございました。
機械学習論文読みメモ_90


[Computational and Statistical Tradeoffs in Learning to Rank](https://arxiv.org/abs/1608.06203), NIPS2016
最近の巨大で異質なデータに対して、制限されたリソース内で行われる推論の精度保証を得る事は重要である。
ランキングの学習において、本論ではcomplexityに応じたrank breaking algorithmを階層的に構築し、すなわちデータのスケッチを可能にする。
これによりデータ量を利用可能リソースに応じてトレードオフする事が可能にする一方で、その中で望まれた精度を維持する事を可能にした。

[Bayesian Optimization with a Finite Budget: An Approximate Dynamic Programming Approach](https://papers.nips.cc/paper/6188-bayesian-optimization-with-a-finite-budget-an-approximate-dynamic-programming-approach), NIPS2016
評価コストの高い目的関数が与えられていて、その評価回数の最大値が与えられているような状況における最適化を考える。
この設定では、最適なbayesian optimizationの戦略はdynamic programmingの枠組みで得られる。
しかし結果として、非常に複雑な問題を解く必要が出てきてしまう。
本論ではrolloutを用いる事で近似的にこれを解く手法を新たに提案する。
この手法はBayesian optimizationに最適化された手法となっている。

[The Robustness of Estimator Composition](https://arxiv.org/abs/1609.01226), NIPS2017
Breakdown pointの考え方を用いてcomposite estimatorのロバスト性を定式化した。
Composite estimatorは複数の推定器を適用する手法で、データを複数の独立な集合に分け、それぞれに最初の推定器を適用した後、その出力に対して別の推定器をさらに適用する、という事を繰り返していく。
Breakdown pointはデータの最小セットであって、それを有意に変化させると出力結果も有意に変化するような集合を示す。
そのため基本的には大きなbreakdown pointを持つ事が良い。
本論は、各個の推定器にmildな仮定を置く事で、composite estimatorのbreakdown pointが各個の推定器のbreakdown pointの大きさの積で表せる事を示した。
この事は様々なタスクに対して適用できる。
機械学習論文読みメモ_89


[Dynamic Filter Networks](https://arxiv.org/pdf/1605.09673v2.pdf)
畳み込み層のフィルタは通常一度推論時には固定される。
本論では、それを入力に応じて変化させる事が可能な、Dynamic Filter Networkを提案する。
このモデルはパラメータ量をあまり増やすことなく、表現力を向上させる事ができる。
広い範囲のfiltering operationはこのモデルにおいて汎用的に学習する事ができる。
またこの層を重ねる事でrecurrent構造も表現できる。

[Regularized Nonlinear Acceleration](http://papers.nips.cc/paper/6266-regularized-nonlinear-acceleration.pdf), NIPS2016
一般的な最適化問題に適用可能な収束高速化技術を提案する。
提案手法は、任意の最適化プロセスにおいて各ステップで得られる予測値の非線形な平均値を用いる。
この平均値計算に用いる重みは、簡単で小さな線形システムを用いる事で計算でき、その結果はオンラインで更新される。
この高速化手法は元となる最適化手法とは別に動かす事ができるため、並列に適用可能である。

[Single-Image Depth Perception in the Wild](http://papers.nips.cc/paper/6488-single-image-depth-perception-in-the-wild.pdf), NIPS2016
制約なく得られた単一カメラ画像に対する深さ情報の推定問題を扱う。
本論では新たにDepth in the wildと呼ばれるデータ作成し、それは制約なく集められた画像とそれに対してランダムに選ばれた２つのピクセル点間の相対的な深さの差を与える。
本論ではこうした相対的深さを用いて学習する事で、深さ推定を可能にするモデルを提案する。
従来手法と比較して、提案手法はより簡単かつ高速化を可能にした。
また従来のRGBDデータを用いて学習した手法を含めて比較しても、提案手法はより良い性能を得た。
[VBA] A,C列を、別シートのA,B列にコピー

特定の列（複数）をコピーしたいときのVBAメモ。
列ごとに別の処理を行うとき用のベース。

```vbnet
Sub colCopySample()

    Dim t As Single
    Dim cpY As Long
    Dim psY As Long
    Dim x   As Long
    Dim cpVal As String
    Dim cpWS As Worksheet
    Dim psWS As Worksheet
    Set cpWS = Worksheets("Sheet1") 'コピー元
    Set psWS = Worksheets("Sheet2") 'ペースト先
    
    Dim cpArr             As Variant
    Dim psArr(1048576, 2) As String
    Dim col(2) As Long
    
    'コピーする列の配列
    col(0) = Range("A:A").Column
    col(1) = Range("C:C").Column    'MAX_Col
    
    'コピー範囲 / Cells(min_Row, min_Col) ～ Cells(MAX_Row, MAX_Col)
    Set cpArr = cpWS.Range(cpWS.Cells(1, "A"), _
                           cpWS.Cells(1048576, col(1)))
    cpArr = cpArr.Value

    t = Timer

    For psY = 0 To 1048575
    
        cpY = psY + 1
        
        x = 0
        cpVal = cpArr(cpY, col(x))
        If Len(cpVal) <> 0 Then
            psArr(psY, x) = cpVal
        End If
        
        x = 1
        cpVal = cpArr(cpY, col(x))
        If Len(cpVal) <> 0 Then
            psArr(psY, x) = cpVal
        End If
        
    Next
    
    Set cpArr = Nothing
    
    'ペースト
    psWS.Range(psWS.Cells(1, "A"), psWS.Cells(1048576, "B")).Clear
    psWS.Range(psWS.Cells(1, "A"), psWS.Cells(1048576, "B")) = psArr
    
    MsgBox "finish! (" & Round(Timer - t, 2) & "秒)"
    
End Sub
```
ざっくばらんメモ_2：kaggle、ceres::LocalParameterizaion、アジャイル


###kaggle zillow challenge
[現在のコード](https://github.com/festa78/kaggle_zillow)
前回までは複数のモデルを学習して得たモデルの予測値の平均（アンサンブル？）を用いていた。
今回はそのアンサンブルするモデルを追加する事にする。
Gaussian Process Regression:メモリエラー、見送り
KNearest Regressor:OKだがとても重い
Kernel Ridge Regression:メモリエラー、見送り
Support Vector Regression:OKだがとても重い
Random Forest:OK
Linear Regression:OK
全てsklearnからのモデルを利用。
パラメータはとりあえず試しなので、基本はデフォルト設定を利用した。
ひとまずOKかつ重くもないRandom ForestとLinear Regressionを加えて
試したところ：0.0677271-> 0.0664433。
OKだが重いモデルも適用したところ0.0659825（やっとサンプルベンチマークを超えられた
Adaboost、GradientBoostも追加したところ0.0655690

次に、stackingを試してみる。
これはベースモデルの予測結果を特徴抽出結果と捉えて入力に加える事で、性能を向上させる手法である。
大雑把な手法は以下である：
１．trainデータをsplitして得たtrain_fold, test_foldの組み合わせに対して、train_foldで
　　訓練したモデルでtest_foldを予測した結果を元のtrainデータに足したものをtrain_meta
　　として保存。これを各ベースモデルに対して行う。
２．続いてtrainデータを全て利用して学習したモデルでtestデータを予測した結果を
　　元のtestデータに足してものをtest_metaとして保存。これを各ベースモデルに対し行う。
３．train_metaへ学習を行い、test_metaへ予測を行った結果を最終結果とする。

ー結果0.0656203でstackingしない時より性能が落ちてしまう。
現状のstackingは2foldで行っていたので、追加して５foldで試してみる。
結果：0.0656738で改善せず。
もしかすると、stackingは今回の問題ではあまり効果がないのかもしれない。

むしろ各月毎に予測しなくてはいけないのに、全て同じ値を用いている方が大きな問題かもしれない。

###ceresのLocalParameterization
ceresで良く使われるLocalParameterizationの意味について。
ある対象の状態を定めるパラメータは、最適化時にはoverparameterizedな場合が多い。
例えば３次元空間内で描かれるある球面上に存在する点のパラメータを考えた時、
ある点周りの微小移動に関していえば、その接面上の移動を考えれば十分であり、
法線方向の移動は無視しても問題ない。
その場合、実際に扱う次元は接面上の２次元空間のみであり、最適化がしやすくなる。
こうした考え方を適用可能にするのがLocalParameterizationである。
実際は、与えられているパラメータブロックに対して、
微小移動に対する計算を関数として与える事が必要になる。
しかし基本的な微小移動関数はすでに定義されているので、それをただ用いるのが
一番良いやり方ではある。

###アジャイル？な開発プロセスについて
twitterか何かに流れていたのだが、
四輪自動車を作成する事を考えた時、直接車の車輪や車体などの部品を作り上げて最後に合体させるのではなく、
まず相対的にシンプルな自転車から初めて、次に二輪自動車、最後に四輪自動車というふうに
発展させていく事が良いという図があった。
たしかに直接四輪自動車の部品を１つ１つ作り上げて合体させる場合、合体させるまで「走る」という機能を
機械に持たせる事ができない。
つまり、実現したい機能が「走る」事に関連している場合、それを最低限実現する機械（自転車）を開発して、
その後は「走る」機能を発展・改善していくプロセスを辿る方が良いという事になる。
これはシステム統合テスト（あるいは早期の市場でのテスト） のしやすさを言っているだと思っているが、
あるいは何か機能（「走る」）を作る時に、それを実現する機械を大きく１つ作れば良いと考えるのではなく、
その機能に関してどのようなユースケースがあるかを全て吟味して、発見したユースケース間をパスを
繋いでいくように細かく作っていく方がビジネス的にチャンスも多く良いという事かもしれない。
研究などにおいても大テーマを小テーマに分割して、各小テーマを論文として量産し食い繋ぎつつ、
最も重要な大テーマに迫っていくというのは良くある話ではある。
CLIP STUDIO プラグインを複数のレイヤー表現色に対応させるために

CLIP STDUIO PAINT EXのプラグイン開発に関する話です。

CLIP STUDIO PAINTでは「カラー」「グレー」「モノクロ」の3種類のレイヤー表現色を使うことができる。
サンプルではカラーのみに対応しているが、他のレイヤーモードにも対応するために必要な事柄を書く。

### フィルタを実行できるレイヤーモードを設定
サンプルの初期化の部分のtarget[]の要素をを増やす。
この種類はドキュメント16p「ターゲットレイヤーの種類」に書いてある。
表現色と「ターゲットレイヤーの種類」は以下のように対応する。

カラー <-> kTriglavPlugInFilterTargetKindRasterLayerRGBAlpha
グレー <-> kTriglavPlugInFilterTargetKindRasterLayerGrayAlpha
モノクロ <-> kTriglavPlugInFilterTargetKindRasterLayerBinarizationGrayAlpha

コードは例えば以下のようになる。

```
TriglavPlugInInt target[]={kTriglavPlugInFilterTargetKindRasterLayerRGBAlpha, 
                           kTriglavPlugInFilterTargetKindRasterLayerGrayAlpha, 
                           kTriglavPlugInFilterTargetKindRasterLayerBinarizationGrayAlpha
};
TriglavPlugInFilterInitializeSetTargetKinds(pRecordSuite,hostObject,target,3);
```

### レイヤーの表現色を判定

オフスクリーンサービスのgetChannelOrderProcを使って「チャンネルオーダー」を取得する。

```
TriglavPlugInInt order;
pOffscreenService->getChannelOrderProc(&order, sourceOffscreenObject);
```

得られる値はドキュメント16p「オフスクリーンのチャンネルオーダー」のいずれかである。
レイヤー表現色とチャンネルオーダーの対応は上記「表現色・チャンネルオーダー・色深度の関係まとめ」のようになる。

カラー <-> kTriglavPlugInOffscreenChannelOrderRGBAlpha (0x03)
グレー <-> kTriglavPlugInOffscreenChannelOrderGrayAlpha (0x02)
モノクロ <-> kTriglavPlugInOffscreenChannelOrderBinarizationGrayAlpha (0x06)

ドキュメントによるとチャンネルオーダーは全部で8種類があるようだが、他のモードが返ってくる場面があるのかは分からない。上記の3つに対応しておけばひとまず十分と思われる。

### 色深度の設定
ドキュメント13ページ「■フィルタの実装における注意点」にある1-5の流れを行う場合、ビットマップサービスのcreateProc()の第4引数に適切な色深度を設定する必要がある。
その場合は表現色に応じて以下のようにする。

カラー <-> 4
グレー <-> 2
モノクロ <-> 2

これより少なくすると動かなくなるが、多くした場合は動く（が、メモリを食うので推奨されないと思われる）。
Java の名前変更キーバインドが Pleiades All in one Eclipse で機能しない

# 環境
OS : macOS siera
Eclipse : Oxygen (Pleiades All in one Eclipse 使用)

# 事象
⌥⌘R でインラインの名前変更機能が起動しない

# キーバインドの設定を修正
- 環境設定を開く
- [一般]->[キー] を選択
- キー画面のフィルターに「名前」を入力
- 表示されたコマンドの一覧で「名前変更 - リファクタリング」のコマンドに着目
- カテゴリーが「リファクタリング - Java」となっている行を選択
- 「場合」を「ウィンドウ」から「Java ソースの編集」に変更
- [適用して閉じる]を押す
Vagrant-docker-nginx環境でhtmlをローカルで編集できるようにする


Vagrant上のdockerでnginxを立ち上げコンテンツをローカル(Mac)上で編集できる環境を作成します。

#環境
MacOS 10.12.6 (Sierra)
Vagrant 1.9.7
CentOS 7.3(VM)
Docker 17.06.0-ce

#下準備
下記ページのnginxの準備ができていること。
[Vagrant上のdockerでnginxを作成しホストからアクセスする](http://qiita.com/Manjiii/items/bcd2f390391038f890f6)

#コンテンツ用のディレクトリを用意
以下のようにローカル（Mac）上のVagrantディレクトリ内にnginxのコンテンツ用のディレクトリを用意します。

```
.
├── Vagrantfile
└── docker
    └── nginx
        └── html
```

#Vagrantfileの編集
```
cd /[vagrant用のディレクトリ]
vi Vagrantfile

Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
 ---略----


#dockerのprovision部分を以下のように編集する
  config.vm.provision "docker" do |d|
    d.run "nginx", image: "nginx", args: "-v /vagrant/docker/nginx/html:/usr/share/nginx/html -p 8080:80"
  end
#ホスト上の/vagrant/docker/nginx/htmlをdocker上の/usr/share/nginx/htmlにマウントする


 # config.vm.synced_folder "../data", "/vagrant_data"
↓上記の行をコメントアウトを外し以下のように編集
config.vm.synced_folder ".", "/vagrant"
#ホストの現在のディレクトリをゲストの/vagrantにマウント

 ---略----
  # SHELL
end

```

#ホストでファイルを編集しnginxに反映されることを確認する

１．以下のファイルを編集する
[vagrant用のディレクトリ]/docker/nginx/html/index.html
この時vagrant rsync-autoのログにrsyncするログが表示されます。

２．http://192.168.33.10:8080/
\#IPは設定したもの
をブラウザ等で開き、編集した内容が表示されることを確認する。
FuelPHP1.7.3でAssetのパスをドキュメントルートに

## 概要
デフォルトのままだとAssetクラスで扱う素材は、ドキュメントルートから1階層さがった下記のパスとなリます。

- public/assets/css/
- public/assets/img/
- public/assets/js/

csss, img, jsをドキュメントルート直下に配置した場合、Assetクラスがそのままでは使えないようなので、調整してみる。

## Asset設定ファイルを修正
pathsを追加する。
ただし、ドキュメントルートからのパスなので、空文字をセット。

```php:fule/app/config/asset.php
<?php

return array(
    'paths'         => array(''),
    'add_mtime'     => true,
    'fail_silently' => false
);
```

## コントローラを作って実行してみる

```php:fuel/app/classes/controller/asset.php
<?php

/**
 * Smartyサンプル
 *
 * @package  app
 * @extends  Controller
 */
class Controller_Asset extends Controller
{
    /**
     * Smartyテンプレートのテスト
     *
     * @access  public
     * @return  Response
     */
    public function action_index()
    {
        // CSSの読み込み(linkタグ生成)
        echo htmlspecialchars(Asset::css('bootstrap.css'));
        echo '<br>';

        // JSの読み込み(scriptタグ生成)
        echo htmlspecialchars(Asset::js('bootstrap.js'));
        echo '<br>';

        // 画像の読み込み(imgタグ生成)
        echo htmlspecialchars(Asset::img('icon.jpg'));
        echo '<br>';
    }
}
```

## テストしてみる
下記のように表示されたので成功のようです。

```html:www.example.com
<link type="text/css" rel="stylesheet" href="http://www.example.com/css/bootstrap.css?1502024558" /> 
<script type="text/javascript" src="http://www.example.com/js/bootstrap.js?1502024558"></script> 
<img src="http://www.example.com/img/icon.jpg?1342323155" alt="" />
```

以上。

## 参考サイト

- [Assetクラス](http://fuelphp.jp/docs/1.7/classes/asset/usage.html)
Ubuntu新規インストール時の環境構築メモ

デュアルブートとか仮想マシンとか、新しくUbuntuをインストールする機会が多いので、備忘録を兼ねたメモです。

# 環境
```bash
$ arch
x86_64
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
$ uname -a
Linux E440-l 4.4.0-89-generic #112-Ubuntu SMP Mon Jul 31 19:38:41 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
```

# 下準備
お決まりのアップデート、Windowsとのデュアルブート時のズレ防止、端末で操作しやすくするためにフォルダ名を英語表記に。

```bash
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo timedatectl set-local-rtc 1
$ LANG=C xdg-user-dirs-gtk-update
```

# LAMP環境

```bash
$ sudo apt-get install git
$ sudo apt-get install ruby
$ sudo apt-get install apache2
$ sudo apt-get install php
$ sudo apt-get install libapache2-mod-php
$ sudo apt-get install mysql-server
$ sudo apt-get install php-mysql
$ sudo apt-get install phpmyadmin
```

# エディタ
個々お好きなものがあると思うので、自分に合うものをどうぞ。
自分は[Atom](https://atom.io/)使ってます。
ホームページからdebパッケージダウンロードしてから、インストールします。

```bash
$ sudo dpkg -i (package name).deb
```

# 諸々
### FuelPHP
個人的に使う機会が多いので、メモ。
[FuelPHP » Downloads](https://fuelphp.com/downloads) より最新版をダウンロード。
展開して、publicフォルダ内のファイルをドキュメントルートに、その他をその一つ上の階層にコピー。
あとはインストール。

```bash
$ cd /var/www
$ php oil refine install
```
[http://localhost/](http://localhost/) で初期ページが表示されれば完了。

# Reference
[Ubuntuのバージョン確認とアーキテクチャ確認コマンド | mawatari.jp](Ubuntuのバージョン確認とアーキテクチャ確認コマンド | mawatari.jp)
[UbuntuとWindowsをデュアルブートしていると時刻が9時間ずれる - 出羽と発火後忘失](http://yukihane.hatenablog.com/entry/201605/ubuntu16.04-datetime)
[Ubuntu日本語フォーラム / カタカナ表記のフォルダ名を英語表記にするには](https://forums.ubuntulinux.jp/viewtopic.php?id=12701)
[Ubuntu 16.04 LTS 日本語 Remix でLAMPなど - Qiita](http://qiita.com/suppy193/items/84153ce3c70deb89c37a)
AWS S3だけでHLSの原理試作

# やりたいこと
Android/iPhoneに動画を配信したい場合、現状ではHTTPストリーミングのHLS(HTTP Live Streaming)が候補になるかと思います。ここでは、AWSを最低限利用して、HLSを実現する試作を行ってみました。

HLSに関しては以下の資料が参考になります。
https://developer.apple.com/jp/documentation/StreamingMediaGuide.pdf

# 動画ファイルの作成
素材はNHKさんを利用させて頂きます。
http://www.nhk.or.jp/archives/creative/material/

ダウンロードしたMP4ファイルをAmazon Elastic Transcoderを利用してHLS形式にします。HLS形式にするというのは、ダウンロードしたファイルはMP4コンテナにH.264ビデオ、AACオーディオデータ格納されているのですが、これをMPEG2TSというライブ放送用のコンテナに入れ替えます。また複数のTSファイルに変換されるので、そのプレイリストファイル(m3u8)を作成します。

Elastic Transcoderはデータの入出力にS3を利用しますので、以下のようにS3フォルダを作成しておきます。

<img width="384" alt="スクリーンショット 2017-08-06 22.53.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/d93e7043-9563-a851-8703-4b58246f4e9b.png">

uploaded以下にHLS形式に変換するMP4ファイルをアップロードしておきます。次にElastic Transcoderを選択して、"Create new pipeline"を選択します。Elastic Transcoderでは、複数の変換処理を連続して行うことが可能です。これをパイプラインと読んでいます。それぞれの変換処理はジョブと呼ばれています。パイプラインの設定では、先ほど作成したバケットを選択して下さい。IAM Roleはデフォルトの選択でS3の入出力ができますので問題ありません。

<img width="507" alt="スクリーンショット 2017-08-06 23.01.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/ed24f929-8f72-0109-6f1c-16f0d49327ef.png">

次に"Create New Job"を選択してパイプラインに実際の変換処理(ジョブ)を追加します。

<img width="536" alt="スクリーンショット 2017-08-06 23.07.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/2842aecc-18ab-c20b-0167-9608d39b3f46.png">

変換処理は、先ほどアップロードしたMP4ファイルを選択します。出力先バケットとして"transcoded"を選択します。変換形式はHLS 1Mを選択しました。Segment Durationが10秒を選択したので、概ね10秒ごとのtsファイルに分類されます。

<img width="427" alt="スクリーンショット 2017-08-06 23.17.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/c14616fc-2289-6c47-7c87-1a5185af9354.png">

ジョブを作成すると変換処理が実施されます。

# S3の設定
先ほど作成したS3のバケットを見ると、transcodedバケット以下にm3u8ファイルと複数のtsファイルが作成されています。

<img width="497" alt="スクリーンショット 2017-08-06 23.24.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/e9871dbf-2517-011e-7424-34d23b2daf91.png">

動作確認のためにtranscoded以下をまとめて公開してしまいます。

<img width="456" alt="スクリーンショット 2017-08-06 23.25.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/467205c6-b1cd-e9c7-d279-670f42565609.png">

# 動作確認
m3u8ファイルのURLをコピーしてSafariでURLを入力するとHLS再生に成功しました。以上、サーバーのコードを一切書かないでHLS再生が実現できました。

<img width="682" alt="スクリーンショット 2017-08-06 23.26.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/c4c769a1-ff68-e46e-4d65-010a8c3e3f0a.png">
resetボタンとvalue属性

HTMLにおいてずっと気になっていたことがある。すなわち、input要素のresetボタンは、<strong>どこへ</strong>リセットしているのか、ということである。

例えば、

~~~HTML
    1: <input type="text" name="message1">
    2: <input type="reset">
~~~

というふうに入力フォームとresetボタンを作成したとき、resetボタンを押すと、message1に入力されていたパラメータがリセット（クリア）される。これは分かりやすい。

だが、

~~~HTML
    1: <input type="text" value="文字を入れてね" name="message2">
    2: <input type="reset">
~~~

というふうに、入力フォームにvalue属性、つまり最初から入力されているパラメータがあった時にどうなるのかというと、resetボタンを押すと、それまでの入力内容を破棄して、元の形、つまりmessage2であれば「文字を入れてね」が入力された状態に戻るのである。

入力漏れがあっても空のまま送信されないだけ良いのかもしれないが、「リセット」と書かれたボタンを押せば空っぽに戻ると思う人も多いような気もするので、一文添えておくべきかもしれない。
SharePoint CAML Query メモ

個人的メモ

## よくやるミス

* タグの大文字小文字を意識する
* 日付と時刻型は `IncludeTimeValue="TRUE"` を付けないと時間を比較してくれない
* Where を使うフィールドにインデックスを作成する

## CAML Query の投げ方

```js:JavaScript
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query></Query></View>');

var ctx = new SP.ClientContext.get_current();
var items = ctx.get_web().get_lists().getByTitle('<Your List Name>').getItems(camlQuery);
ctx.load(items);

```

## 取得列の指定

列 A , B , C を取得する

```xml
<View>
    <ViewFields>
        <FieldRef Name="A"/>
        <FieldRef Name="B"/>
        <FieldRef Name="C"/>
    </ViewFields>
    <Query>
    </Query>
</View>
```


## 比較式

列 A は数値列とする

* A = 0

```xml
<View>
    <Query>
        <Where>
            <Eq>
                <FieldRef Name='A' />
                <Value Type="Integer">0</Value>
            </Eq>
        </Where>
    </Query>
</View>
```

* A <> 0

```xml
<View>
    <Query>
        <Where>
            <Neq>
                <FieldRef Name='A' />
                <Value Type="Integer">0</Value>
            </Neq>
        </Where>
    </Query>
</View>
```


* A < 0

```xml
<View>
    <Query>
        <Where>
            <Lt>
                <FieldRef Name='A' />
                <Value Type="Integer">0</Value>
            </Lt>
        </Where>
    </Query>
</View>
```

* A <= 0

```xml
<View>
    <Query>
        <Where>
            <Leq>
                <FieldRef Name='A' />
                <Value Type="Integer">0</Value>
            </Leq>
        </Where>
    </Query>
</View>
```

* A > 0

```xml
<View>
    <Query>
        <Where>
            <Gt>
                <FieldRef Name='A' />
                <Value Type="Integer">0</Value>
            </Gt>
        </Where>
    </Query>
</View>
```

* A>= 0

```xml
<View>
    <Query>
        <Where>
            <Geq>
                <FieldRef Name='A' />
                <Value Type="Integer">0</Value>
            </Geq>
        </Where>
    </Query>
</View>
```


## OrderBy の昇順と降順

A 列を降順にするには、Ascending (昇順) を FALSE にする

```xml
<View>
    <Query>
        <OrderBy>
            <FieldRef Name='A' Ascending='FALSE' />
        </OrderBy>
    </Query>
</View>
```

## MAX , MIN

列 A の MAX 値を取得するには、降順にして 1 件取ってくる  
MIN 値の時は Ascending の値を TRUE にする

```xml
<View>
    <ViewFields>
        <FieldRef Name='A' />
    </ViewFields>
    <Query>
        <OrderBy>
            <FieldRef Name='A' Ascending='FALSE' />
        </OrderBy>
    </Query>
    <RowLimit>1</RowLimit>
</View>
```

## Between

AND でつなぐしかない

A 列が日付と時間型と仮定した例

```xml
<View>
    <Query>
        <Where>
            <And>
                <Geq>
                    <FieldRef Name='A' />
                    <Value IncludeTimeValue='False' Type='DateTime'>2017-07-01</Value>
                </Geq>
                <Leq>
                    <FieldRef Name='A' />
                    <Value IncludeTimeValue='False' Type='DateTime'>2017-07-31</Value>
                </Leq>
            </And>
        </Where>
    </Query>
</View>
```
fullcalendar + typescript + asp.net mvc

FullcalendarをNUGETでインストール。
typescript用のDefineファイルもNUGET

カレンダーのイベントは、ASP.NET MVCのコントロールアクションから取得するようにする。

はまったのは、
public jsonresult GetEvents(double start,double end)
の例が多かったが、
実際は
public jsonresult GetEvents(string start,string end)
で取得する。

これはGoogleChromeの要素の検証からNetworkをキャプチャして判断。
他に資料はなかった。
Google Chrome拡張機能をコマンドラインでパッケージ化する方法(for macOS)

コマンドラインでGoogle Chrome拡張機能をパッケージングする方法です(for macOS)

```bash
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --disable-gpu \
  --pack-extension=<SRC_PATH> \
  --pack-extension-key=<PRIVATE_KEY_PATH>
```

`--disable-gpu` フラグがミソでした。
assertの引数をfalse固定にするというテクニック

例えば、以下の関数があったとします。

```cpp
const char* nameOfUser( UserData *user )
{
    return user->name();
}
```

もし user が NULL だった場合、この関数は落ちます。
user が NULL になる可能性が理論上あり得るあるなら NULL チェックをすれば良いですが
user が NULL になる可能性が理論上あり得ない場合、NULL チェックは不要と判断するでしょう。
しかし、「理論上あり得ない」と「実際にあり得ない」はイコールではありません。
複雑なプログラムになればなるほど、我々の小さな脳で導き出した理論は間違う可能性が高くなるのです。
そこで、assert を使うことにします。

```cpp
const char* nameOfUser( UserData *user )
{
    assert( user != NULL );
    return user->name();
}
```

このコードだったら、もし user が NULL の場合、アサーションが発生してくれます。

しかしこれは Debug ビルドの場合のみです。
一般的に(特にアプリ開発では)、Release ビルドの場合は NDEBUG が定義されているため、アサーションが無効化されます。
つまり、Release ビルドでは、上記のコードは最初のコードと同一になり、user->name() にアクセスした際に落ちます。

「絶妙のタイミングで関数が呼ばれた時」とか「１万回に１回の確率」などで user が NULL になるとしたらどうでしょう？
スレッドの排他処理が中途半端だと、そういうことも有り得ます。
もちろんバグなのですが、再現性が低ければ、それがデバッグ中やテスト中に発覚しない可能性もあります。
つまり、user が NULL になる可能性がある状態のままリリースされてしまうのです。
ユーザーは様々な使い方をするので、この再現性が低い状況を起こしてしまうでしょう。
そうなるとユーザーの環境でクラッシュが発生してしまいます。
これは避けなければなりません。

そこで以下のように実装します。

```cpp
const char* nameOfUser( UserData *user )
{
    if ( user == NULL ) {
        assert( false );
        return NULL;
    }
    return user->name();
}
```

assert の引数を false にして、「Debug ビルドだと必ず落ちる」というパスにしてしまいましょう。

こうすると、Release ビルドでアサーションが無効になっても、クラッシュすることなく関数が終了します。
(もちろん関数の戻りが NULL であることを考慮した設計にする必要はあります。)
こうして世界からまた１つクラッシュが減るのです。

これは本来の assert の使い方ではないかもしれません。

```cpp
if ( user == NULL ) {
    assert( false );
    return NULL;
}
```
よりも

```cpp
assert( user != NULL );
```
の方が意図が分かりやすいのも確かです。
しかし、この書き方にもメリットが多いと思います。

そもそも、今回の例で言うと関数の頭で NULL チェックすべきです。
たとえ、理論上 NULL になることが有り得ない場合でも。
例えば、関数を呼ぶ側でチェックしてる場合、不要と感じるのは最もですが、その意図を知らない第３者が別のところで関数を呼んだ場合、そこで NULL チェックをする保証はありません。
NULL チェックはするに越したことはないのです。
NULL チェックを省略する理由としては、「冗長だから」とか「チェックの分、処理が遅くなるなら」ということでしょうが、近年のアプリ環境からすれば誤差みたいなものでしょう。

NULLチェックに限らず、関数内での前提条件は全てチェックすべきだと思っています。
もちろん限度はありますが。

今までの話の流れだと、assert の引数を false 固定にする意図が
「Release ビルドで assert してもクラッシュしないようにしよう」
ということになってしまいますが、実はこれは結果であり、本来の意図とは異なります。
本来の意図は
「冗長でもチェックはしよう。もし理論上有り得ないなら assert しちゃえ」
です。
```assert(false)``` を、「一応チェックしているけど、俺は理論上有り得ないと思ってるからね！」という意思表明として使いましょう。
なんでもmake xxxで済ませたい


シンプルなC言語のプロジェクトを作ってみる
目的は、とりあえず、何をするにもmake xxxで済ませたい。

http://qiita.com/tksmiura/items/0a77e5c301532ae30c9a
の続き

http://qiita.com/szkny/items/07b4c93702b3f8090fa3
あたりを参考にして

ut_*.c　という名前のソースをテストプログラムとしてビルドして実行する。(make のwildcardを利用するのでファイルを増やしてもMakefileの変更は不要)

make testとかmake gcovとか実行するビルドして、テストやカバレッジを取ってくれる。

```
% make test
cc -o ut_main ut_main.c
cc -o ut_sub ut_sub.c
result ut_main.c 3/3 
result ut_sub.c 0/0
```

make debugと実行するとデバッグビルドしてgdbの起動まで行う。

http://www.ne.jp/asahi/hishidama/home/tech/unix/cmd/make2.html
あたりを参照


プロジェクト全体は、
https://gist.github.com/tksmiura/fc273ba726ed380dcd5bf6488c24c553

にあげておきます。

```Makefile
#TARGETS
PROGRAM = main
DEBUG_TARGET = main_debug
HEADERS = $(wildcard *.h)
SRCS = main.c
TEST_SRCS = $(wildcard ut_*.c)
TESTS = $(basename $(TEST_SRCS)) 
GCOV_TESTS = $(TEST_SRCS:.c=_gcov)

# ENVIRONMENT
CC ?= gcc
CFLAGS ?= -Wall -O2
DEBUG_OPTION ?= -O0 -g
DEBUGGER = gdb -tui
GCOV = gcov

# suffixes
.SUFFIXES: .c .o .debug_o

#default target
all: $(PROGRAM)

#
# target
#

# サフィックスルール
.c.o:
	$(CC) $(CFLAGS) -c $<

#依存関係
define MAKEOBJECTS
$(1:.c=.o): $(1) $(HEADERS)
endef
$(foreach VAR,$(SRCS),$(eval $(call MAKEOBJECTS,$(VAR))))

$(PROGRAM): $(SRCS:.c=.o)
	$(CC) -o $(PROGRAM) $^

#
# debug(gdb)
#
.c.debug_o:
	$(CC) $(CFLAGS) $(DEBUG_OPTION) -o $@ -c $<

#依存関係
define MAKEDEBUG
$(1:.c=.debug_o): $(1) $(HEADERS)
endef
$(foreach VAR,$(SRCS),$(eval $(call MAKEDEBUG,$(VAR))))


$(DEBUG_TARGET): $(SRCS:.c=.debug_o)
	$(CC) -o $@ $^

.PHONY: debug
debug: $(DEBUG_TARGET)
	$(DEBUGGER) $^

#
# unit test 
#

# targets for test
define MAKETARGETS
$(1): $(1).c $(HEADERS)
	$(CC) -o $(1) $(1).c
endef
$(foreach VAR,$(TESTS),$(eval $(call MAKETARGETS,$(VAR))))

.PHONY: test
test: $(TESTS)
	@for test in $(TESTS) ; do \
		./$$test ;\
	done

#
# gcov
#

# target gov (unit test only) 
define MAKETARGETS_GCOV
$(1)_gcov: $(1).c
	$(CC) -o $(1)_gcov --coverage $(1).c
endef
$(foreach VAR,$(TESTS),$(eval $(call MAKETARGETS_GCOV,$(VAR))))

.PHONY: gcov
gcov: $(GCOV_TESTS)
	@for test in $(GCOV_TESTS) ; do \
		./$$test ;\
	done
	$(GCOV) -b $(TEST_SRCS:.c=.gcda)

#
# clean
#
.PHONY: clean
clean:
	$(RM) $(PROGRAM) $(DEBUG_TARGET) $(TESTS) $(GCOV_TESTS)
	$(RM) $(SRCS:.c=.o) $(SRCS:.c=.debug_o) 
	$(RM) *.gcda *.gcno *.gcov 
```


全体的に手抜きなので、ヘッダはwildcardで*.hを検索し、

```
HEADERS = $(wildcard *.h)
```

どれかが変更されれば、リビルドされるように設定。
(defineでルールを定義してforeachで展開)

```
#依存関係
define MAKEOBJECTS
$(1:.c=.o): $(1) $(HEADERS)
endef
$(foreach VAR,$(SRCS),$(eval $(call MAKEOBJECTS,(VAR))))
```

実際、#includeしてない場合も考えられますが、いちいち依存関係を記述する手間を省くため。こうしています。

デバッグ用のオブジェクトを*.debug_oとしているは自分でもどうかと思っていますが、フォルダ分けとかも面倒な感じなのでこうしています。
OpenAI GymのFrozenLake-v0をQ学習で解く

OpenAI Gymにある迷路探索問題FrozenLake-v0を解いてみました．

https://gym.openai.com/envs/FrozenLake8x8-v0

## ルール

- 4x4の盤面を移動する．
- Sが開始地点で，Gがゴール．
- Hが落とし穴でゲーム失敗で，Fは床で移動できる．
- 隣接4方向に移動可能
- 現在の位置とゲームオーバーかどうかが分かる．
- 意図した方向に進める確率は1/3で，それ以外だと90度直角に進む．
- env.reset()してもマップは変わらない．

### クリア条件

- Gに到達したら+1,落とし穴に落ちたら-1として，直近100回のスコアの平均が0.78以上獲得
- 意図した方向に1/3の確率でしか進めないので，1.0になることはまずない．

### 表示

```
SFFF
FHFH
FFFH
HFFG
```

- S: ゲーム開始地点
- G: クリア地点(移動できれば成功)
- H: 落とし穴(落ちると失敗)
- F: 移動できる場所

## 解法

Q学習を使って解きました．

```math
Q(s_t, a_t) \leftarrow Q(s_t, a_t) + \alpha (r_{t+1} + \gamma \max_{a' \in A(s')} Q(s_{t+1}, a') - Q(s_t, a_t))
```

下記値をハイパーパラメータとしました．

- $\alpha = 0.03$
- $\gamma = 0.90$
- $\epsilon = 0.001$

## Code

https://github.com/namakemono/openai-gym-benchmark/blob/master/envs/frozen_lake_v0.py

```python
# -*- coding: utf-8 -*-
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
import numpy as np
import gym
from gym import wrappers

def run():
    env = gym.make("FrozenLake-v0")
    env = wrappers.Monitor(env, directory="/tmp/frozenlake-v0", force=True)
    logger.info("Observation Space: %d, Action Space: %d" % (env.observation_space.n, env.action_space.n))
    max_episode = 10000
    Q = np.zeros((env.observation_space.n, env.action_space.n)) # Action Values
    Gs = [] # Revenues
    best = -1
    for episode in range(max_episode):
        x = env.reset()
        X = [] # States
        done = False
        alpha, gamma = 0.03, 0.9
        while not done:
            if np.random.random() < 0.001:
                a = np.random.randint(env.action_space.n)
            else:
                a = np.argmax(Q[x,:])
            X.append(x)
            x, r, done, info = env.step(a)
            if done:
                r = (2*r - 1) * 100.0
            logger.debug("State: %d, Reward: %d, Done: %s, Info: %s" % (x, r, done, info))
            x_pre = X[-1]
            Q[x_pre,a] += alpha * (r + gamma * np.max(Q[x,:]) - Q[x_pre,a])
        Gs.append(int(r > 0))
        avg = np.mean(Gs[-100:])
        best = max(best, avg)
        logger.info("Episode: %d, End of turn: %d, Revenue: %.2f, Average: %.2f, Best: %.2f" % (episode, len(X), r, avg, best))

if __name__ == "__main__":
    run()
```

## Score

- Episodes to solve: 1909
- Best 100-episode average reward: 0.80 ± 0.04.

## References

1. [Q学習](https://ja.wikipedia.org/wiki/Q%E5%AD%A6%E7%BF%92)
2. [squirrelinhell's algorithm](https://gym.openai.com/evaluations/eval_4ER334HTWu0qjB00Hxljg)
3. [sakib-shahriyar's algorithm](https://gym.openai.com/evaluations/eval_4R0BTBDERyap3oWmxTSa2g)
FuelPHP1.7.3をインストールする

## 概要
FuelPHP1.7.3のインストール方法を忘れないようメモしておきます。

## コードのダウンロード(1.7.3)
公式サイトの下記ページに紹介されているoil createコマンドでインストールしようとしたが...
スクリプトエラーになるので、ZIPダウンロードしてcomposer installすることにしました。

- [FuelPHP &raquo; Downloads](https://www.fuelphp.com/downloads)

ダウンロードしたファイル（fuelphp-1.7.3.zip）を解凍し、任意のフォルダに展開します。

## 必要なファイル以外を整理する
下記ファイルのみ残す。

- fuel
- public
- composer.json
- composer.lock
- composer.phar
- oil

## composer.jsonからドキュメントのインストールを削除
ドキュメントをインストール対象から外したいのでjsonを加工する。

```:composer.json(8行目)
{ "type": "vcs", "url": "https://github.com/fuel/docs" },
```

```:composer.json(19行目)
"fuel/docs": "dev-1.7/master",
```

```:composer.json(44行目)
"{$name}": ["fuel/docs"]
```

## composerの実行

```
$ php composer.phar self-update
$ php composer.phar update
Loading composer repositories with package information
Updating dependencies (including require-dev)                          
Package operations: 0 installs, 2 updates, 0 removals
  - Removing composer/installers (v1.0.21)
  - Installing composer/installers (v1.3.0): Loading from cache
  - Updating psr/log (1.0.0 => 1.0.2): Loading from cache
Writing lock file
Generating autoload files
```

## 除外設定ファイル(.gitignore)を作成する
gitでバージョン管理を行うため、除外設定ファイルを作成します。
githubにて除外設定ファイルが配布されているのでそれを参考に適用します。

https://github.com/github/gitignore/blob/master/FuelPHP.gitignore

```:.gitignore
# temp files from editors
*~
*.bak
.DS_Store
.buildpath
.project
.settings
*.tmproj
build
.idea
nbproject/

# hidden files created by Windows
Thumbs.db
desktop.ini

# the composer package lock file and install directory
#/composer.lock
/fuel/vendor

# any of the fuel packages installed by default
/docs/
/fuel/core/
/fuel/packages/docs/
/fuel/packages/auth/
/fuel/packages/email/
/fuel/packages/oil/
/fuel/packages/orm/
/fuel/packages/parser/

# dynamically generated files
/fuel/app/logs/*/*/*
/fuel/app/cache/*/*
/fuel/app/config/crypt.php
```

## githubに登録する。

```
$ git init
$ git add -A
$ git commit -m "first commit."
$ git remote add origin git@github.com:hoge/******.git
$ git push -u origin master
```

## 参考サイト

- [Packagist - fuel/fuel](https://packagist.org/packages/fuel/fuel)

以上です。
VMware workstation player(VMware-player)のexeファイルは捨てないほうがいい

# 環境
windows10 Home
VMware Workstation 12 Player(VMware-player-12.5.7-5813279.exe)

# 概要

windows10でアンインストールするのに便利だから。

windows10で「設定」→「アプリと機能」からアンインストールしようとしても出来なかった。

![キャプチャ.JPG](https://qiita-image-store.s3.amazonaws.com/0/189581/8c48e7d1-e086-ad48-bfab-9cc160b29f7b.jpeg)

こんな感じでアンインストールは表示されるけどクリックできない。
インストールで追加されたvmware関連のサービスを全部無効にしてもダメだった。。
<br>


そこでインストールに使用した.exeファイルを実行してみると
![キャプチャ2.JPG](https://qiita-image-store.s3.amazonaws.com/0/189581/6857b51e-0693-2305-69bb-c1a0fdf715f7.jpeg)
分かりにくいですが、こちらの削除はクリックできます。
こちらから無事アンインストール完了。

# リンク
参考にさせていただいたサイト
https://ameblo.jp/maya-phillips/entry-12191514535.html
【Rails】modelから取得したデータをjson化してviewに出力したいぞ

## 今回のお題

Railsを触っていて、modelから取得したデータをjson化してviewに出力しjQueryに読ませる、
という処理を行ったのでviewに出力するところまでを備忘録として残しておきます。

## controller
```hoge_controller.rb
def index
    @array_hoges = []
    @hoges.each do |hoge|
      @array_hoges << hoge
    end

    respond_to do |format|
      format.html
      format.json { render json: @array_hoges }
    end
end
```

hogesテーブルから取得した情報をarray_hogesに格納しています。
jsonファイルとしての出力ではなく、画面内にjsonとして出力するのでrespond_toを使っています。

## view
```hoge/index.html.erb
<%= @array_hoges.to_json %>
```

たったこれだけです。怖いくらいあっさりできてしまいました。
実際はこのjsonをhtmlタグ内に出力し、jQueryで読み込みを行う処理がありましたが今回は割愛です。