OmniAICreator/Qiita-1.07M huggingface dataset:
Nightwatch.jsでaxiosを使って外部APIを叩いた結果を利用する

# この記事のターゲット
- Nightwatch.js使い始め
- 正直Node.jsよくわからない
- Nightwatchから外部にhttpリクエストを出したい
- なんとなくrequestよりaxiosの方が名前がかっこいい

# Nightwatch.jsとは
http://nightwatchjs.org/

いわゆるE2E（end-to-end）テストフレームワーク。
ブラウザの操作とアサーションのメソッドをNode.jsで提供してくれる。
Nightwatch.jsの導入についてはこちら
[WebアプリのUI自動化テストでNightwatch.jsを試す](https://qiita.com/h5y1m141@github/items/9728db03cc24216f7219)

# axiosとは
JavaScriptのPromiseベースHTTP通信ライブラリ。
もちろんNode.jsでも動く。
Ajaxなどが簡単に実装できる。


# 本題
今回の想定ケースは以下の通り。

1. ブラウザで特定サイトにアクセスする
2. 画面から特定の文字列を取り出し、APIへのリクエストパラメータとする
3. APIからの返り値を画面のフォームに入力する

## axios


```javascript
module.exports = {
    'ログインテスト': (client) => {
        client
            //1. ブラウザで特定サイトにアクセスする
            .url('__loginUrl__')
            //2. 画面から特定の文字列を取り出し、APIへのリクエストパラメータとする
            .getValue('__取得したパラメータ__', function(result) {
                paramId = result.value;
                //apiリクエスト関数
                api(paramId, client);
            })
            //入力フォームにパラメータをセット
            .setValue('input[name=user_id]', 'hogehoge')
            .setValue('input[name=password]', 'fugafuga')
            //画面遷移を待つ
            .pause(3000)
            .verify.containsText('body', 'ログイン成功')
            .click('#logout > a')
            //画面遷移を待つ
            .pause(3000)
            .verify.containsText('body', 'ログアウト成功')
            .end()
    }
}
```

```javascript
function api(param, client) {
    //axiosを読み込む
    const axiosBase = require('axios');
    //apiのベースURLを設定
    const axios = axiosBase.create({
        baseURL: '__apiBaseUrl__',
        timeout: 100000,
        headers: ''
    });
    //getでAPIを叩く
    axios.get('__apiEndPoint__', {
        params: {
            user_id: userId,
            password: Password,
            param_id: paramId,
        }
    })
    .then(function(response) {
        console.log('SUCCESS!!');
        //3. APIからの返り値を画面のフォームに入力する
        client.setValue('input[name=param]', [response.data,client.Keys.ENTER])
    })
    .catch(function(error) {
        console.log('ERROR!!');
    });
}

```

# 所感
axios、名前かっこいいですよね。
麻雀の点数判定アプリを作る#4

#前回まで
OpenCVで牌をトリミングすることを考えていましたが，一般化が難しそうだったので一旦引き上げて別の方法を検討することにしました．そこで上がったのがYOLOです．カスタムデータで学習を行うことができれば，パラメータ調整地獄には陥らないはず．全く触れたことのない分野ですので，調べつつ導入していきます．

#YOLO
![20180614144003.png](https://qiita-image-store.s3.amazonaws.com/0/335220/e5e408d2-1582-0d69-599e-1307f6621292.png)
YOLOは2016年に発表された機械学習アルゴリズム．You Live Only Once(人生1度きり)をもじったYou Look Only Onceが由来とのこと．ユーモラスですね．

![rcnn.jpg](https://qiita-image-store.s3.amazonaws.com/0/335220/0c8c6293-dc9d-5124-49f9-1f61af7ac449.jpeg)


YOLOが発表される以前は物体検出を「分類問題」として扱っていたようです．R-CNN(Regions with Convolutional Neural Networks)という手法では上記の画像に見られるような方法で物体を「分類」しています．物体の領域候補を見つけてから，CNN(Convolutional Neural Networks)で特徴抽出し，分類器で分類するという流れです．また，各処理に用いられる手法がそれぞれ別のものであるため，処理時間がかかってしまうのだとか(腑に落ちないので，調べる中で補完します)．

一方YOLOでは回帰問題として扱い，入力画像に対し直接予測を行うため，R-CNN等のアルゴリズムよりも動作が高速です．

###学習アルゴリズム
大変分かりやすい解説がありました．ありがとうございます．実際に作業する上で特に重要なのはハイパーパラメータでしょう．学習を行う際に設定する必要がある筈ですので，頭に留めておきます．

参考:畳み込みニューラルネットワークの仕組み
https://postd.cc/how-do-convolutional-neural-networks-work/

#【次回】導入編
次回より環境を構築し，学習準備を行ってみます．
MySQLがbundle installできない

## エラー内容
```
$ bundle install

Errno::EACCES: Permission denied @ rb_sysopen -
/Users/username/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-17/2.5.0-static/mysql2-0.5.2/gem_make.out
An error occurred while installing mysql2 (0.5.2), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.2'` succeeds before bundling.
```

```
$ gem install mysql2 -v '0.5.2'

Building native extensions. This could take a while...
ERROR:  While executing gem ... (Errno::EACCES)
    Permission denied @ rb_sysopen - /Users/username/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-17/2.5.0-static/mysql2-0.5.2/gem_make.out
```

## やったこと

```
$ ls -ltr /Users/username/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/doc/
```

root 権限で install されていたので一旦消す

```
$ sudo rm -rf　/Users/username/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/extensions/x86_64-darwin-17/2.5.0-static/mysql2-0.5.2/
```
再インストール

```
$ gem install mysql2 -v '0.5.2' 
```

## 参考
https://qiita.com/akito19/items/e1dc54f907987e688cc0
https://qiita.com/mitsuaki1229/items/2b89640ca9fe25555328
VC++開発の覚え書き②

#概要
　コントロールのグループ化とフォーム内画面遷移、ComboBoxの要素を変数から入力する。

#内容
- [コントロールのグループ化](#コントロールのグループ化)
- [フォーム内画面遷移](#フォーム内画面遷移)
- [ComboBoxの要素を変数から](#comboboxの要素を変数から)

#コントロールのグループ化
1. パネルを配置
2. パネル上にコントロールを配置
3. this->Controls->Add()の確認

```C++
// 
// MainForm
// 
this->AutoScaleDimensions = System::Drawing::SizeF(8, 15);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(360, 640);

this->Controls->Add(this->SettingPanel);
this->Controls->Add(this->MenuPanel);

this->Name = L"MainForm";
this->Text = L"NK_HealthCare";
this->MenuPanel->ResumeLayout(false);
this->SettingPanel->ResumeLayout(false);
this->SettingPanel->PerformLayout();
this->ResumeLayout(false);
```
　`this->Contorols->Add(コントロール)`でコントロールを別のコントロール等に所属させることができます。これがコントロールのグループ化です。いわゆる親コントロールの`Enable`や`Visible`プロパティを変更することでまとめて操作することができます。

#フォーム内画面遷移
```C++
this->SettingPanel->Visible = false;
this->SettingPanel->Enable = false;
```
　コンストラクタの中で隠しておきたい(画面遷移先)のコントロールをまとめたパネルを見えなくし(`Visible = false`)、無効化する(`Enable = false`)ことでユーザーの目線からはその画面は存在しないものとして扱える。`Enable = false`をしていないとTabキーや十字キーでコントロール間を移動する際に画面から選択枠が消え、クリックした際にないはずのボタンの機能が呼び出されるなどの不具合の原因になります。
　画面を切り替えるにはこれの逆を行います。

```C++
// 隠していた画面の可視化、有効化
this->SettingPanel->Visible = true;
this->SettingPanel->Enable = true;

// 見せていた画面の不可視化、無効化
this->MenuPanel->Visible = false;
this->MenuPanel->Enable = false;
```
　これにより、あたかも別の画面に移動したかのように見せることができる。これを行うにはパネルを使用せずに行うこともできるが、コードが長くなるなど無駄が増えてしまうので、先のグループ化を行って一括で管理している。

#ComboBoxの要素を変数から
　ここまでと関連性は特にないですが覚え書きなのでご容赦を。

```C++
char* cstr[2] = {
	"あいうえお",
	"い"
};
int a = 2;

array<String^>^ str = gcnew array<String^>(a);

for (int i = 0; i < 2; i++) {
	str[i] = gcnew String(cstr[i]);
}

this->comboBox1->Items->AddRange(str);
```
　System::String^配列 str にchar*型の文字列 cstr を変換して格納し、それを`this->comboBox1->Items->AddRange(str);`のように与えることで変数の内容からコンボボックスを生成できる。`int a = 2;`は要素数を変数でも指定できることの確認である。


#最後に
　前回に続きただの覚え書きなのでスマートなやり方、正しい使い方ではありませんのでその点はご容赦ください。
send2trashによるファイルの一括削除

こんにちは、rickyといいます。
今回はファイルの管理の方法として、send2trashでファイルをゴミ箱に移す作業を行います。
フォルダの中にいらないtxtファイルが大量にある場合、そのカレントディレクトリ下から一括で消去する方法になります。

概要
ファイルの削除にはshutilモジュールもありますが、ファイルやフォルダを完全に削除してしまう場合があるので、扱いが難しいです。
そこでsend2trashモジュールを使います。
このモジュールを使うとファイルやフォルダをゴミ箱に移動させるので安全な消去が出来ます。

開発環境　Ubuntu18.10、python3.7.0、jupyter

今回はデスクトップに不要なtxtファイルを作成します。
その後そのファイルをまとめて削除するという流れになります。

以下ソースコード
#  ディレクトリの移動
import os
os.chdir('/home/ricky/Desktop/')

#  不要なファイルの生成
for i in range(10):
    junk_file = open('trash{}.txt'.format(i), 'a')
    junk_file.write('hogehoge{}'.format(i))
    junk_file.close()

#  一括削除
import os, send2trash
for filename in os.listdir():
    if filename.endswith('.txt'):
        send2trash.send2trash(filename)

あとがき
今回のメソッドは簡単にもかかわらず、ファイルに直接操作ができるので、かなり実用性が高いです。
カレントディレクトリ下にある不要なファイルを一つずつ削除するのではなく、コードを書くことで、消し忘れなども防ぐことが出来ます。
注意点としてはコードを書いている際にもカレントディレクトリについて意識しないと、別のファイルにあるtxtファイルを削除してしまう恐れがあります。ご注意を。

分かりづらいと感じられた所や、この書き方の方がいいよというアイデアがありましたら、ご一報いただけると幸いです。
ここまで読んでいただきありがとうございました。
今後のTask

# 今後のTaskの整理
さて、明日は日本に帰国し、また日本での日常生活に戻ります。と言うことで、明日からここの更新が心配になりますが、とりあえず、明日以降のTaskを自分の中で整理。１つずつこなしながら、夏までに何かしらの形を作り上げたい‼

## 今までの振り返り(できたこと)
- Windows/Macを使って、Anacondaを使ったDeepLearningの開発環境の構築(Anaconda 
 + Tensorflow + Keras)
- モデルを生成して、Webから参照できる方法の確立(Flask)
- Flaskで作った環境のProduction(Online)にて公開する方法の確立(GAE)

一応、これらのブックマーク的なものは過去ログで追えるようになったので大丈夫と思う。

## そして今後やりたいこと(やること)
- モデルを自分の手で作り上げる(Make the model by myself)
- 作ったモデルのProductionへの公開(Publish the model on Production)
- Monetize(Monetize)
pythonista3で写真をディレクトリに保存

# pythonista3 凄いじゃん _(´ཀ`」 ∠)
まじで色々できるし、初めからExampleにステキなサンプルはいってるし…
1200円はやすいぐらいでは(べた褒め)

でも、カメラロールの写真の使い方がいまいち分からなかったので、保存する用のスクリプト書きました

# ソースコード
```python
#coding:utf-8
import photos

# AssetCollectionリストからカメラロールを取得する
for album in photos.get_smart_albums():
  if album.title == 'All Photos':
    camera_roll = album
    break

#画像を一つだけ取得する
asset = photos.pick_asset(camera_roll)
img = asset.get_image()

#img.show()
img.save("photo.png") #任意の名前とディレクトリ
```
* img.save()の中身を ../ とか突っ込むとディレクトリを自由自在に移動できるのデス

* iosのアプリ開発これでよくね？

# 参考にさせていただいたサイト
[Pythonista 3でフォトライブラリの読み書き](https://halspg.wordpress.com/2017/11/20/pythonista_photos/)
[django]テストでユーザログインしたい



Client.login メソッドを使ってログインする

``` python

from django.test import Client, TestCase

class HogeTestCase(TestCase):
    """                                                                                                                                                                                                                                                                         
    """
    def setUp(self):
        """                                                                                                                                                                                                                                                                     
        """
        self.user = User.objects.create_user('HogeTaro', 'taro@hoge.com', 'password')
        
        self.client = Client()

        self.client.login(username='HogeTaro', password='password')
```
[django]ディレクトリ直下にプロジェクトを作りたい


hogeというディレクトリがすでににあって、以下のようにプロジェクトを作りたい場合

```
hoge
├── manage.py
└── prj
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
```

hogeディレクトリで以下のようにコマンドを叩く。

``` sh
django-admin startproject app .
```
生産性向上のための最低限ドリブン

# 最低限ドリブンとは #

最低限のタスクを消化することを基準に生産性を確保する方法について書きたいと思います。

これまではなんとなく過去の経験や知識をベースに、その時その時の自分のトレンドで仕事のやり方を改善してきましたが、この偶然性に任せきったやりかたではどうも振り回されすぎだなと思ってました。
生産性のブレを小さく抑えようと思い立ち、少し前からノートに記録を取るなどした結果から反省/分析してみて気づいたことを文章にまとめてみたのがこちらの「最低限ドリブン」という方法です。

以下に詳しいことを書きます。

## やり方 ##

手帳でもなんでも良いので、その日にやる最低限のタスクに絞って書き出します。
自分は次の条件で最初の書き出しを行います。

* 朝仕事を始めるタイミングで手帳に書き始めます。
* 時間帯の区切りは午前中です。具体的には8:30から11:00までの時間帯を対象範囲にしてます。
* 時間内に最低限やり切ろう(やり切れるはず)と思う分量のタスクを書きますが、最低1つ、最大でも2つまでと決めています。

## タスクの分割 ##

タスクを1つと数えるその内容ですが、「仕様書を作成する」などのような大きすぎる表現は避けます。
また同時に「仕様書の作成をできるだけ進める」のように分量が任意に解釈できてしまう表現も避けます。

タスクの例だと、

* xxxプロジェクト > 仕様書 > データベース仕様のセクションを書き上げる
* 昨日作っておいた提案書をチャットに添付してレビュアーに見てもらう
* Viewコンポーネントに機能追加し、依存関係に問題ないかをテストする

などのように具体的な範囲に区切ってタスクを書き出します。
こうすることで大雑把に捉えていた仕事をより理解/分解する作業も進むことになります。

また「どうも気が進まない仕事」というのはやはりあり、そういうものにも当然進捗は必要なので、

* 企画書の目次だけでも作る

というようなタスクを書くこともあります。
これは「○○をできるだけ進める」と似て非なるものです。
「できるだけ頑張る」という前提が臭ってしまうと「最低限」というルールに違反することになります。

## 最低限が達成できない場合 ##

最低限のタスクに絞って書いたつもりなのに、その日の終わりに振り返ってみたら達成できていなかった、ということはあると思います。
それを「自分の頑張りが足りなかった」と批判するのは無駄なので辞めましょう。
それはタスクが「最低限」ではなかったのです。
なのでさらにタスクを分解しましょう。そして潔く明日以降に繰り越しましょう。

## 予定より早くタスクを消化できてしまった場合 ##

タスクの分割に慣れてくるとこのケースに遭遇することのほうが寧ろ多いです。
実はこの状態になることがこの方法の目的であると言えます。
時間にも心にも余裕があるこの状態で、その日にもう少しタスクを追加して消化してみましょう。
タスクの追加ルールは朝書き出したときとほぼ同じです。
自分の場合、うまく午前中にタスクが消化できると午後イチでこの状態になれます。
午後何時まで仕事できるかは日によって違いますが、例えば13:00から16:00の範囲を対象にして最低限できそうなタスクを書き出します。

この方法で仕事を進めるようになってから自分の記録を見返すと、平均して1日に4つか5つのタスクを消化しているようです。
こうなったとしても欲張らずに朝チャージするタスクは2つを上限にするのを守っています。
そうでないと最低限ルールが崩れてしまい、モチベーションに一番影響する「午後イチの余裕」を見失ってしまう可能性があるように思います。

## 生産性は向上するか ##

方法論の理屈だけ読むと、最低限のリソース内で可能な範囲に留まってしまい「全体的な生産性の向上につながっていない」と解釈できないこともないです。
しかしここが不思議なところで、実際は細かく小さく進捗を重ねることで目に見えて生産性が向上した実感があります。
自分の場合はアウトプットが早くなりました。何日もチームメンバーからの連絡に返信しないなんてこともなくなりましたし、成果物を依頼者にリターンするスピードも上がったと思います。この場に書き込んでいるように文章作成を行う時間も確保できるようになりました。それだけではありません。アウトプットの効率を上げつつ同時に読書をする時間もきっちり確保できるようになりました。読書好きの自分にとってはとても嬉しいことです。
読書をすることで得た知識を仕事にフィードバックできるので正のスパイラルを作りやすいと思います。

あくまで個人の主観ではありますが、生産性向上につながっていると思います。
以前の自分がそうでしたが「進捗感が得られない」「ダラダラ仕事をしてしまっている」と日々感じている方には是非おすすめしたい方法と言えます。

## まとめ ##

なにか大きな目標に向かって頑張り続けるというのとは真逆の方法論です。結果的に大きな何かを達成することはあるかもしれませんが、基本的には「日々の進捗感を充実させる」ことが主眼です。
最低限ドリブンという方法は「自分にとって最低限とはいかほどか」という切り口で仕事への理解を深め、ついでにタスクを十分現実的な作業のレベルに落とし込み、そして消化する、この繰り返しです。

みなさんの日々の生産性向上に役立てば幸いです。
【FileMaker】簡易的な全文検索を実装する

FileMakerのソリューション開発の依頼を受ける際、よく請ける内容の一つに、「全文検索」があります。
以前、[【FileMaker】テキスト内を検索して、マーキングする](https://qiita.com/tyuma/items/46e41c07022c5352fe78) というPatternCountとTextStyleAddを使った検索方法をご紹介しましたが、一つのフィールド内での検索でした。
だがしかし、世の中的に「膨大なデータの中からキーワードにマッチしたデータを抽出したい」という気持ちがあるのは至極当然です。

全文検索、、、と難しく考えるとあれこれスクリプトを組まなければならないのか？と思いがちですが、FileMakerでは

[クイック検索の実行](https://fmhelp.filemaker.com/help/17/fmp/ja/#page/FMP_Help%2Fperform-quick-find.html)

があります。
これが優秀でして。

素晴らしいことに、全ての製品(Pro Advanced,Go,WebDirect,Server,Cloud,Data API,Web公開,Runtimeソリューション)で互換性があります。[^1]

[^1]: FileMaker Pro 11からの対応になりますので、それ以前のバージョンの場合はこの限りではありません。

もちろん、FileMaker画面上のステータスツールバーにはクイック検索が実施できるようにあらかじめ表示されています。
<img width="800" alt="quick1.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/ffd68b17-536e-dc47-c0a6-5e0700430afd.png">
が、ソリューション提供時にはステータスツールバーは表示しないことが多いですよね。

こういう時は１行スクリプトの出番です。

# 実装

レイアウト上にクイック検索を実装します。
<img width="886" alt="quick3.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/196d4e1e-ef11-f3b4-c685-0b11aab38ccc.png">

検索窓は、単純にグローバルフィールドを実装しています。
<img width="441" alt="quick2.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/1bf2ee43-1bdc-a024-13bd-02ac580d5a0f.png">

検索ボタンは、クイック検索の実行を指定してます。
<img width="1068" alt="quick4.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/a4223502-737b-cc44-22a4-c156afaee878.png">

# 実証
では、テストデータを入力し、検索してみます。
シンプルに「本」です。
<img width="888" alt="quick5.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/896d53b3-1498-7849-8c5f-62fb31f8eed8.png">
複数フィールドから「本」を検索しています。

ただし、このクイック検索の欠点は、 **<font color="Red">レイアウトに表示されていないフィールドは検索対象にならない</font>** 、ということです。
試しにnoteフィールドを表示せず、唯一入力されていた「超大作」という文字列を検索してみます。
<img width="929" alt="quick6.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/ba683bb2-9a37-0c4c-2ef6-1160ca9cd847.png">
はい、検索されません。

では、ポップオーバーに隠した状態での検索はどうでしょうか？
<img width="903" alt="quick7.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/daa62ac2-d095-3d4b-ab74-0110dd58bf74.png">

はい、検索されました！
<img width="905" alt="quick8.png" src="https://qiita-image-store.s3.amazonaws.com/0/60538/3353b8ab-6bf2-75d8-233b-1f1f06ddb642.png">

# 実装してみよう
簡易的ではありますが、このように検索機能を実装することでかなり使い勝手のいいソリューションに仕上がります。
「全文検索」できるようにしてね、と言われて頭を抱えるのではなく、「こういうことでいかがでしょうか？」とできることを組み合わせて提案していくのも顧客満足度を挙げる一つの手ですね。
組み合わせテストの用語「2因子間網羅」「直交表」「All-Pairs法」

本稿では、組み合わせテストの用語について簡潔に解説する。2因子間網羅、直交表、All-Pairs法について触れる。

## 組み合わせテスト

- 組み合わせテスト(combinatorial testing):複数の条件を組み合わせてテストする手法

## 全網羅組み合わせテスト

- 全網羅組み合わせテスト: 考えられるすべての条件の組み合わせをテストする手法
- 当然、全網羅組み合わせテストのほうが欠陥を検出できる可能性は高い。
- しかし、組み合わせ数が膨大になると、全網羅組み合わせテストは現実的に不可能になる。

たった3つの条件がそれぞれ3パターンあるだけで27通りのテストが必要。

| 組み合わせ    | 全網羅組み合わせテストの数 |
| ------------- | -------------------------- |
| 2 * 2         | 4                          |
| 3 * 3 * 3     | 27                         |
| 4 * 4 * 4 * 4 | 256                        |

## 2因子間網羅

- 因子(parameters): 変数名
  - 例: "OS"
  - 例: "PHPのバージョン"
  - 例: "データベース"
- 水準(values): 因子がとりうる値
  - 例: Windows, Linux, macOS
  - 例: PHP7.1, PHP7.2, PHP7.3
  - 例: MySQL, PostgreSQL, SQLite
- 2因子間網羅: 2因子間の組み合わせを網羅した状態
- 2因子間網羅を満たす組み合わせを作成する手法
  - 直交表(orthogonal array)
  - All-Pairs法(Pairwise法)

<center>全網羅とAll-Paris法による2因子間網羅の例</center>

![全網羅とAll-Paris法による2因子間網羅の例](https://qiita-image-store.s3.amazonaws.com/0/889/d9adf782-dc6b-6f7c-fc7c-b1a89679c5aa.png)

- 2因子間網羅では、「OSとPHP」「PHPとデータベース」「OSとデータベース」の組み合わせが全通り存在する。
- 2因子間の網羅率が100%であれば、妥当なテストと言える
  - 経験的根拠「多くの欠陥は2因子間でみつかる」[^IEEEの論文]
  - 1因子で見つかる欠陥: 29%〜68%
  - 2因子で見つかる欠陥: 70%〜97%
  - 3因子で見つかる欠陥: 89%〜99%
  - 1因子のテストは簡単だが、効果が薄い。
  - 3因子は2因子とそんなに変わらない割に、テストが大変。
  - だから、2因子間網羅で大抵は妥当。

<center>Fig. Failure triggering fault interactions, cumulative distribution.</center>

![2-Figure1-1](https://qiita-image-store.s3.amazonaws.com/0/889/34f35b13-0b35-1294-209f-d63eb15c14e7.png)

[^IEEEの論文]: [Software fault interactions and implications for software testing - IEEE Journals & Magazine](https://ieeexplore.ieee.org/abstract/document/1321063)

- 2因子間網羅を採用するか、3因子間網羅以上を採用するかは、**テスト工数と欠陥見逃しリスクのトレードオフ**になる。
  - テスト対象の重要度やバグりやすさによって、3因子間網羅、4因子間網羅、N因子間網羅、全網羅…とリスク回避に重きを置く選択もあり。
  - 例: 新機能はバグりやすいから、3因子間網羅にする。
  - 例: 返品返金処理は大クレームに繋がりやすいから、全網羅にする。
  - ちなみに、3因子間網羅のテストは3-wise testingと言われる。

## All-Pairs法と直交表の違い

- All-Pairs法と直交表: どちらも2因子間網羅なのは同じ。
- All-Pairs法: 2因子間が重複しないことを重視
  - したがって、組み合わせ数が少なくなる。
  - 水準の出現回数が均一にならないことがある。
      - 例: MySQLは4回しかテストされないが、PostgreSQLは5回ずつテストされる
- 直交表: 水準の出現回数が均等になること重視
  - したがって、重複したペアがあることがある。
  - 組み合わせ数が多くなる。
  - 直交表は科学実験の手法。実験ではデータが偏らないよう水準を均等に割り付けるのは大事な特性。
      - 例: 投薬Aの実験はデータが10回あるのに、投薬Bは7回しかないと実験データとしては良くない。

## 参考文献

* [石原一宏, 田中英和 (2012) 『【この1冊でよくわかる】ソフトウェアテストの教科書―品質を決定づけるテスト工程の基本と実践』 田中真史監修, ソフトバンククリエイティブ株式会社](https://amzn.to/2FnKjiE)
[Go]ループ内でpanicが起こった時、ループを終了させずにrecoverする

## 概要
Goでは、panicの乱用は推奨されないことが多いと思いますが、ループ処理中などに、不意にpanicを吐く外部パッケージが紛れ込んでしまった時など、panicを他のエラーと同様にハンドリングして処理を最後まで続けたいケースがありました。
今回は一つの解決の方針として、panicの発生する部分を無名関数でくるんで捕まえる、という方法を紹介します。

## 内容

### 例1：処理をそのままrecoverした場合

```go

package main

import "fmt"

func main() {

	var j int
	var k int

	for i := 1; i < 10; i++ {
		// 回数
		fmt.Printf("i = %d\n", i)

		// panic時にはrecover
		defer func() {
			if err := recover(); err != nil {
				fmt.Println("recover:", err)
			}
		}()

		// panicを吐く可能性がある処理
		hoge(i, j)
		huga(i, k)
	}

}

func hoge(i int, j int) {
	return
}

func huga(i int, k int) {
	if i == 5 {
		panic("panic")
	}
	return

}
```

#### 実行結果

```
i = 1
i = 2
i = 3
i = 4
i = 5
recover: panic
```

関数内でpanicが発生した時、deferを実行し、元の関数を終了する。
したがって、例1を実行すると i = 5 の時panicが発生し、deferでrecoverされるので正常終了するが、main関数が終了してしまうので、ループ処理も途中で終了してしまう。

### 例2：処理を無名関数でくるんでrecoverした場合

```go
package main

import "fmt"

func main() {

	var j int
	var k int

	for i := 1; i < 10; i++ {
		// 無名関数でラップする
		func() {
			// 回数
			fmt.Printf("i = %d\n", i)

			// panic時にはrecover
			defer func() {
				if err := recover(); err != nil {
					fmt.Println("recover:", err)
				}
			}()

			// panicを吐く可能性がある処理
			hoge(i, j)
			huga(i, k)
		}()
	}

}

func hoge(i int, j int) {
	return
}

func huga(i int, k int) {
	if i == 5 {
		panic("panic")
	}
	return

}
```

#### 実行結果
```
i = 1
i = 2
i = 3
i = 4
i = 5
recover: panic
i = 6
i = 7
i = 8
i = 9
```

例2は、ループの中身を無名関数で囲んだだけであるが、defer実施後に終了される関数が、無名関数となり、ループは無名関数の外側にあるので終了しない。（無名関数からローカル変数を参照できるので、処理に必要な引数の引き渡しも考慮する必要がない）

## まとめ
Goでは、panicの多用は推奨されないことが多いのですが、そのため、逆に不意にpanicが混じった時にハンドリングできず困ることもあるかもしれません。今回は一つの解決法として、panicの発生する部分を無名関数でくるんで捕まえる、という方法を紹介しました。
[Rails5]annotateってなんぞ？

# はじめに

Railsの勉強としてgem周りを触ってみる企画です。
今回は・・・

[annotate](https://github.com/ctran/annotate_models)

を試してみようかと思います。

## どういうgemなの？

簡単にいうと各スキーマの情報をファイルの先頭（あるいは末尾）に
コメント記載してくれるgemです。

例えばこのテーブル（モデル）のカラムって何があったっけ？とか
そういう情報を毎回都度DBにアクスセスして`show columns`したりとか
Rails consoleでモデル生成して確認したりとか・・・
そういう面倒な作業をなくしてくれる便利もの。
では早速いきましょう。

## 検証環境

以下の環境で実施しました。

```
[client]
・MacOS Mojave(10.14.2)
・Vagrant 2.2.2
・VBoxManage 6.0.0

[virtual]
・CentOS 7.6
・Rails 5.2.2
・ruby 2.3.1
```

ご参考までに。

# annotate導入

**1.gemのインストール**

事前にRails勉強用に作成したプロジェクトで進めます。
各MVCは適当に掲示板アプリを想定してPostsコントローラーなどを生成済みです。
(index,show,editの空ページが見れる程度)

```余談
$ rails g model post
$ rails g controller posts index show edit
```

その前提のもと、Gemfileに以下を追記。

```ruby:Gemfile
# annotate
gem 'annotate'
```

追記したらインストール。

```
$ bundle install

-----------
Fetching annotate 2.7.4
Installing annotate 2.7.4
-----------
→無事に完了。
```

**2.annotateの設定をする**

マイグレーションを実行した時に、
自動的にannotateを動かしたいので、以下のコマンドを実行。

```
$ rails g annotate:install
    create  lib/tasks/auto_annotate_models.rake
```

マイグレーション時に自動的にannotateしたくない場合は、
上記インストールコマンドは不要。
都度必要に応じてannotateする場合は、

```
$ bundle exec annotate
```

のコマンドを実行する。

**3.annotateを使ってみる**

すでに、PostモデルやUserモデルを生成しているので、
既存のファイルに対してannotateを実行してみましょう。
コマンドは上記と同じ。

```
$ bundle exec annotate
Annotated (6): app/models/post.rb, test/models/post_test.rb, test/fixtures/posts.yml,
app/models/user.rb, test/models/user_test.rb, test/fixtures/users.yml
```

６ファイルに適用されました。

**4.動作確認**

試しにPostモデルを見てみましょう。

```ruby:post.rb
# == Schema Information
#
# Table name: posts
#
#  id         :bigint(8)        not null, primary key
#  name       :string(255)
#  content    :string(255)
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Post < ApplicationRecord
end
```

おお、ちゃんとスキーマ情報が追加されてますね。
素晴らしい。

# 所感

大きい規模のプロジェクトになると、
必然的にテーブル数も多くなるので、「あのテーブルのカラムどうなってたっけ」
とかって結構あるあるですね。

テーブル定義書をわざわざ開くのも面倒なので、
annotateを入れてスキーマ情報を載せるようにしておけば、
すっかり構成を忘れちゃっても簡単に確認が出来て良い！

# おわりに

何かお気づきの点がありましたら、
ご指摘やアドバイス等頂けると大変助かります！
OneToOne データ更新(Update)

# はじめに
OneToOneの関係のテーブルにデータを更新(Update)する。
「[OneToOne データ取得(Select)](https://qiita.com/ma33588/items/b24953e454a22ed07c48)」の続き。

# データ更新(Update)
## Controllerよりアクセス
ControllerからRepository経由でアクセス

```php:app/Customize/Controller/SamplePageController.php
/**
 * @Route("/sample/{id}", name="sample_index")
 * @Template("Sample/index.twig")
 */
public function index($id)
{
    $product = $this->productRepository->find($id);
    dump($product);

    $size_a = $product->getProductSize()->getSizeA();
    $product->getProductSize()->setSizeA($size_a + 1);
    $this->entityManager->persist($product);
    $this->entityManager->flush();

    return [
        'shop_name' => $this->baseInfo->getShopName(),
        'product_name' => $product->getName(),
        'maker_name' => $product->getMakerName(),
        'size_a' => $product->getProductSize()->getSizeA(),
    ];
}
```


## ブラウザよりアクセス
/sample/1 でdtb_product_sizeのデータを更新できた。


#まとめ
find()して値を設定してpersist()してflush()

#参照
[OneToOne データ取得(Select)](https://qiita.com/ma33588/items/b24953e454a22ed07c48)
where.not  + distinctについてのメモ


RailsでECサイトを作成する際、メイン商品のカテゴリーに紐づいた関連商品をコントローラーで取得し、メイン商品のビューで表示させたいという時に、

・関連商品にメイン商品が取得されてしまう
・異なるカテゴリーごとにそれぞれ同じ商品を取得してしまう
　（例えばRuby Bagという商品がRuby、BAGSという複数のカテゴリにそれぞれ属していると、
　　BAGSの関連商品でRuby Bagが２回表示されてしまう。）

という問題が発生した。その時に解決法として使用した方法をメモしておく。

使用したコード
<span>@</span>related_productsで<span>@</span>productの関連商品を、一意かつ<span>@</span>productを含まずに取得

```ruby
@product = Spree::Product.find(params[:id])
@related_products = Spree::Product.in_taxons(@product.taxons).includes(master: [:images, :default_price]).where.not(id: @product.id).distinct
```

# where.not（条件）
条件に一致しないものを取得する。

例　hogeという名前のユーザー以外のユーザーを取得する

```ruby
User.where.not(name: "hoge")
```

# distinct
重複のない一意のレコードを取得する。
なお、同様のメソッドにuniqがあるが、Rails5から非推奨となり、distinctが推奨されている。

# 参考
http://railsdoc.com/references/not
https://railsguides.jp/active_record_querying.html
[Rails] リファクタリング render collection

user一覧など、インスタンス変数をloopさせて表示させるようなviewをリファクタリングする。
まずpartialを切る。

```app/views/users/index.erb
<% @users.each do |user| %>
　<%= render (partial: )user %> 
<% end %>
```

```app/views/users/_user.html.erb
<div class="users-index-item">
 <div class="user-right">
   <%= link_to user.name, user_path(user) %>
 </div>
</div>
```

ここからさらに`each`も省略できる。

```app/views/users/index.erb

　<%= render @users %> 
```
```app/views/users/_user.html.erb
<div class="users-index-item">
 <div class="user-right">
   <%= link_to user.name, user_path(user) %>
 </div>
</div>
```
railsが勝手に`@users`のコレクションをpartialに渡してくれる。
上のはindex.html.erbは下の省略バージョン。↓

```app/views/users/_user.html.erb
<%= render :partial => "user", :collection => @users %>
```
[golang] 今更golangに再入門してみた時の個人的な参考資料まとめ

## Pickup
- golang学習の際に参考にした資料の個人的なまとめになります
- 設定した学習のゴール： APIを昨今のデファクトスタンダードのディレクトリ構成で作成できるようになる

## Document
### ■ golangについてまず知っておくべき系のもの
公式のwikiを参考にした。
https://github.com/golang/go/wiki#getting-started-with-go

#### 基本的な構文
https://tour.golang.org/welcome/1

#### コーディング時に注意するべきこと
https://qiita.com/knsh14/items/8b73b31822c109d4c497

#### golangのライブラリ一覧
https://golang.org/pkg/

### ■ より発展的な学習
#### フレームワーク
- echo
https://github.com/labstack/echo

- iris
https://github.com/kataras/iris/tree/master/_examples

#### ディレクトリ構成
- デファクトスタンダード的な構成
https://github.com/golang-standards/project-layout

- API
https://github.com/golang-standards/project-layout/blob/master/api/README.md

- Mysql Driver
https://github.com/go-sql-driver/mysql
PHPで特殊なエスケープシーケンスを出力する

# エスケープシーケンス

コンソールに `echo` や `print` で `"\r"` などを出力すれば普通のエスケープシーケンスは出力できるんだけど、例えば「行消去」(`\e[2K`)のような特殊なエスケープシーケンスの出力方法がすぐに分からなかったのでメモ。

```php
  // エスケープシーケンスで行全体を消去
  echo chr(27) . "[2K";
```

進捗表示をやりたいときに `"\r"` だけだと消去できなかったので。


# 参考

- [ANSIエスケープシーケンス チートシート \- Qiita](https://qiita.com/PruneMazui/items/8a023347772620025ad6)
- [Clear PHP CLI output \- Stack Overflow](https://stackoverflow.com/questions/4320081/clear-php-cli-output)
Go で protocolbuf を使うと ProtoPackageIsVersion3 のエラーがでる件

2019/1/10 時点での内容です。
# 概要
Go 1.11にて、Module（vgo）を利用している前提にて、以下のエラーが発生した場合の対処について記載しています。

```
xxx: undefined: proto.ProtoPackageIsVersion3
```
※ Module（vgo）モードではない場合は、以下の記事を参考にしてください。
https://qiita.com/go_sagawa/items/5ba0ebb0cf42a629e2e9

## 背景
何処かのタイミングで各種ライブラリをアップデートした際に、上記エラーが発生し、ビルドが通らなくなりました。
また、私のケースでは、Go 1.11のModule（vgo）を利用しているため、このケースでの解決方法について記載します。
以下にて、今回の問題が取り上げられています。
https://github.com/golang/protobuf/issues/763

## 対応方法
該当のディレクトリへ移動します。go.modを見てみると、以下のように v1.2.0 が入っています。

```
require (
	...
	github.com/gogo/protobuf v1.2.0
)
```
以下のコマンドにて、特定バージョンのmoduleを追加します。

```
go get github.com/golang/protobuf@8d0c54c1246661d9a51ca0ba455d22116d485eaa
```
もう一度、go.mod を見てみると、追加したmoduleを確認することができます。

```
require (
	...
	github.com/gogo/protobuf v1.2.0
	...
	github.com/golang/protobuf v1.2.1-0.20181127190454-8d0c54c12466
)
```

これでビルドエラーは解消されました。
gulp-file-includeでエラー

#gulp-file-includeでエラー

gulpにgulp-file-includeをインストールしたら
下記エラーが出た

```gulp.shell
$ gulp

events.js:141
      throw er; // Unhandled 'error' event
      ^
Error: this is not a typed array.
```

#解決策
nodeのバージョンを上げたら実行できた。

最初v6.12.3に上げた見た所前述とは違うエラーが発生。
おそらく他のプラグインも関連している気がして
少し下げたバージョンをインストール。

```installnode.shell
$nvm install v4.9.1
```

#環境
今回の環境としては以下のような感じ

macos+virtualbox+vagrant+centos6.3

```version.shell
[vagrant@localhost example]$gulp -v
[08:36:27] CLI version 3.9.1
[08:36:27] Local version 3.9.1
[vagrant@localhost example]$node -v
v4.9.1
[vagrant@localhost example]$npm -v
2.15.11
[vagrant@localhost example]$nvm --version
0.29.0
```

#メモ
gulpはプラグインごとでもnodeのバージョンが違うとエラーが出るということが体験できた。
gulp自身のバージョンは書き方も変わるので注意が必要。
[gulp3.9.1から最新のgulp4.0に上げた時の記録](https://qiita.com/SwuBHj8aKGqBKHet/items/37a89c949a87de8d2058)
これはタスク管理ツール全般に言えることかもしれないが一度セッティングすればかなり便利だが
node周りのバージョンアップも激しいので運用コストも少しかかる印象です。
NIC model 簡単メモ

Show and Tell で述べられていたNIC model について調べる機会があったときのメモ
画像から説明文を生成するタスクをpythonでお手軽に実行してみたい人は以前書いた
[こちら](https://qiita.com/48saaan/items/1661a912c740308d3fd5)参考にしてみてください

#参考
元論文：[Show and Tell: A Neural Image Caption Generator](https://www.cv-foundation.org/openaccess/content_cvpr_2015/papers/Vinyals_Show_and_Tell_2015_CVPR_paper.pdf)
※図は元論文からの引用

[Show and Tell: A Neural Image Caption Generatorを読んだ](http://sesenosannko.hatenablog.com/entry/2016/12/03/172948)
[Show and Tell: A Neural Image Caption Generatorの紹介](https://www.slideshare.net/KCSKeioComputerSocie/show-and-tell-a-neural-image-caption-generator)





#ざっくりな流れ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/208438/e2308181-6313-e1d7-f86b-a215230340e3.png)
　　　　　　　図1　NIC model


（　① 事前学習によりモデルを作成する　）
② CNNによって入力画像の特徴ベクトルを中間層から出力
③ 最初のLSTMに特徴ベクトルを入力し、LSTMの出力$m_0$を2番目のLSTMに入力する
④ 2番目のLSTMにおいて、$m_0$と単語$S_0$をベクトル化した$W_eS_0$から、$S_0$に続く単語$S_1$を予測($log_{p_1}(S_1)$)
⑤ 2番目の出力$m_1$($p_1$は$m_1$をSoftmaxしたもの)を3番目のLSTMに入力
⑥ 3番目のLSTMにおいて、$m_1$と単語$S_1$をベクトル化した$W_eS_1$から、$S_1$に続く単語$S_2$を予測($log_{p_2}(S_2)$)
⑦ ストップワード$S_N$が予測されるまで、⑤と⑥のように単語予測をしていく
⑧ $S_0$から$S_N$が入力画像の説明文(キャプション)になる


 
 
以下、画像から説明文を出力するまでのちょっと詳しい流れです
※さらっと読んだだけなので間違いがあるかもしれません

#事前学習
　事前学習では単語の意味や文法と画像の特徴をまとめたベクトル空間を作ります
　そのベクトル空間から次に述べるLSTMが、入力された画像の説明文を予測します
　まず、事前学習ではMSCOCOやFlicker-8kなどのトレーニングデータセットによって単語予測のための条件付き確率式を作ります

```math
log_p(S|I) = \sum_{t=0}^{N} log_pp(S_t|I, S_0, ... , S_{t-1}) \\\
```

　t番目の単語$S_t\ $の確率は画像$I\ $とt個の単語列$S_0\ $, ..., $S_{t−1}\ $の条件付き確率、らしい
　単語$S_0$の次に来る単語は$S_1$の確立が高い、みたいな式ですたぶん
　
　次に、画像の特徴をCNNを使用して取得します
　Batch normalizationを使用したとか書いてありますが、
　学習時間の短縮や過学習の抑制のためなので割愛！
  （[CNN](https://deepage.net/deep_learning/2016/11/07/convolutional_neural_network.html)）（[Batch normalizationについて](https://qiita.com/t-tkd3a/items/14950dbf55f7a3095600)）


　CNNによって取得した画像の特徴と単語予測の条件付き確率式$log_p(S|I)$を [word embedding](https://qiita.com/ynqa/items/eb28d326a12fc87e3ee7)します
　（word embeddingは単語の意味や文法を保持したままベクトル空間に写像する手法・・・らしい）
　画像の特徴と単語予測の確率式を同ベクトル空間にすることにより、画像の特徴から単語を推測することができます

　元論文的な言い方をすると「画像を単語に翻訳する！」

　

#文の生成
　文作成には、図2のLSTMが使われます
　LSTM内のパラメータは事前学習によって決められたものを使用し、すべてのLSTMは同じパラメータを共有しているそうな～
![image.png](https://qiita-image-store.s3.amazonaws.com/0/208438/5b69b5c3-9914-16ec-09fb-91d86b56c5f1.png)
　　　　図2　LSTM-based Sentence Generater
![image.png](https://qiita-image-store.s3.amazonaws.com/0/208438/e2308181-6313-e1d7-f86b-a215230340e3.png)
　　　　　　　図1　NIC model(再掲)

　最初にCNNを使って入力画像(image)から画像の特徴をベクトルとして抽出します(中間層の出力を使う)
　抽出された特徴ベクトルを最初のLSTMに入力します
　この入力からは単語予測を行わず、出力$m_0$を次のLSTMに渡します
　※図2の青線と図1の青線は対応しているので、図を見た方がイメージしやすいかも

　次に、スタートワード$S_0$をword embeddingによってベクトル化した$W_eS_0\ $をLSTMに入力します
　前の出力である$m_0$と入力$W_eS_0\ $から単語を予測します
　予測には事前学習で作った、単語と画像特徴のベクトル空間を使用します
　出力$m_1$を[Softmax](http://hiro2o2.hatenablog.jp/entry/2016/07/21/013805)にかけて確率に変換した$p_1$と事前学習で作ったベクトル空間から、$S_0$に続く単語$S_1$を予測($log_{p_1}(S_1)$)

　このように前のLSTMの出力$m_{N-1}$を使いながら、ストップワード$S_N$が予測されるまで処理を続けます
　※文の始まりと終わりを認識するために$S_0$はスタートワードで$S_N$はストップワードという特別に設定したものです




　
　
　
元論文には、事前学習データセット別の結果とかも載っていますが、今回は割愛！
以上！
OpenapiGeneratorでtypescript-axiosで生成したコードをcreate-react-appで利用したら"Namespaces are not supported"とでた。

# 利用環境
- create-react-app
- typescript
- openapi-generatorでtypescript-axiosでクライアントの生成

## 状況
コンポーネント内にenumを書くとnamespaceを使ったコードが生成される

#### 元ファイル
```
# chemicalcheck.yaml
hoge: 
  type: string
  enum: ["ok", "caution"]
  example: "ok"
```

#### 生成
```
export namespace ChemicalCheck {
    /**
     * @export
     * @enum {string}
     */
    export enum Hoge {
        Ok = 'ok',
        Caution = 'caution'
    }
}
```


namespaceが使われてしまう。  
これをcreate-react-app内で使うと、namespaceはもう使うな的な感じで怒られる。  

参考
https://jser.info/2018/08/28/babel-7babeltypescript/
> Babel 7ではTypeScriptのコードをパースできるようになり、@babel/preset-typescriptを利用してFlowと同じように型情報を取り除いてJavaScriptに変換できます。
> 
> 制限として、Babel自体は型チェックを行なわないことやenum/namespaceのようなTypeScript独自の構文はサポートしてない点についても紹介されています。

https://github.com/facebook/create-react-app/issues/5633



#### 解決法
yamlの書き方を治す方法がいいと思う。
refで参照させてしまえば、namespaceが生成されない

```
# chemicalcheck.yaml
hoge: 
  $ref: ./result.yaml
```

```
# result.yaml
type: string
enum: ["ok", "caution"]
example: "ok"
```

#### おすすめしない解決法
全置換

```
export namespace Hoge
```
↓

```
export declare namespace Hoge
```

エラーは出なくなるけど、クライアント生成時に毎回書き換えるとかめんどくさい
最短（？）のフィボナッチ数列計算プログラム

# swap over +
　ただこれだけ。これで次々にフィボナッチ数列が計算できる。
これ以上に短いプログラムでフィボナッチ数列が計算できる言語・方法があるのかは正直良くわからないが、そこそこに短い方ではないかと思う。ちなみに対象の言語は Forth と [Paraphrase](https://github.com/iigura/Paraphrase) である。

　このプログラムはあくまでも計算するだけである。
しかし、計算すればその結果を見たくなるのが人情というものである。
なので、計算結果を表示させると以下のコードとなる（少し長くなった）。

``` Forth
swap over + dup .
```

　実際に計算させてみると以下のようになる。このコードで使用しているワードは Forth とコンパチ（なハズ）なので、今回は拙作の[Paraphrase](https://github.com/iigura/Paraphrase) を用いた（行頭の > は Paraphrase インタプリタのプロンプトである）。

``` Paraphrase
> 1 1 // F1 F2 をスタックに積む
 ok.
> swap over + dup .
 2 ok.
> swap over + dup .
 3 ok.
> swap over + dup .
 5 ok.
> swap over + dup .
 8 ok.
> swap over + dup .
 13 ok.
> swap over + dup .
 21 ok.
> swap over + dup .
 34 ok.
> swap over + dup .
 55 ok.
> swap over + dup .
 89 ok.
```

# なぜ計算できるのか？　その仕組の解説
スタックの上から 2 番目（セカンド）に F_{n-1} が、1 番上（TOS=Top Of Stack）に F_n が格納されているとする。

    +---------+
    | F_n     |
    +---------+
    | F_{n-1} |
    +---------+

swap で、

    +---------+
    | F_{n-1} |
    +---------+
    | F_n     |
    +---------+

となり、over で、

    +---------+
    | F_n     |
    +---------+
    | F_{n-1} |
    +---------+
    | F_n     |
    +---------+

となり、+ にて、

    +----------------------------+
    | F_n+F_{n-1}　つまり F_{n+1} |
    +----------------------------+
    | F_n                        |
    +----------------------------+

を得る。

Forth では、スタックの変化前と変化後を --- というキーワードを用いて表現する。
この記法を用いると、swap over + というプログラムは、

``` Forth
F_{n-1} F_n --- F_n F_{n+1}
```

という変化をスタックにもたらす。

# おわりに
　Forth は長い歴史を持つ言語である。そのため、おそらくここに書かれているようなことは既に誰かがとうの昔に書いている可能性も高い。もしご存知の方がいたら、コメント欄にでも書いていただければ幸いである。
glfw のインストールと導入(windows VisualStudio 2017) 

##目的
Visual studio でglfwを開発する環境をまとめる。

##ダウンロード
公式サイトから　glfw のwindows pre-compiled binariesをダウンロード

https://www.glfw.org/download.html

<img width="733" alt="コメント 2019-01-10 101858.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/251306/51cd7b8a-959e-5451-a513-b3a121f2466d.jpeg">

ダウンロードしたら、今回はとりあえずC:\openglにzipを展開します。

以下GLFWと表記します。

同様にGLEWもダウンロードします。
僕の読者の対象は、windowsということなのでwindowsバージョンのGLEWをダウンロードします。

http://glew.sourceforge.net/
![スケッチ.png](https://qiita-image-store.s3.amazonaws.com/0/251306/bc8155a7-b725-ad55-1178-6b92a8e0faa5.png)


##visual stdioで開発
visual Studioを起動

上のプロジェクトメニューからプロパティを設定する。

構成プロパティ → vc++ → インクルードライブラリーにGLFW/include,
GLEW/includeのアドレスを入れる。

![スケッチ (1).png](https://qiita-image-store.s3.amazonaws.com/0/251306/5ffeffc4-597d-4f1c-530d-312d38407cb5.png)


同様に
リンカー → 一般 → 追加のライブラリーディレクトリーに「GLFW/lib-VS2015/」「GLEW\lib\Release\x64」を追加

![スケッチ (2).png](https://qiita-image-store.s3.amazonaws.com/0/251306/6162b376-2daa-99ab-528d-a748a156e352.png)

リンカー → 入力 → 追加の既存ファイルに「GLFW/lib-VS2015/glfw3.dll」「GLEW\lib\Release\x64\glew32s.lib」「opengl32.lib」を追加

![スケッチ (3).png](https://qiita-image-store.s3.amazonaws.com/0/251306/847cec7d-ed41-90c4-10e6-b82b44d01666.png)

以上が終われば、楽しくglfwの開発がwindowsでできるようになります。

##終わりに
2019/1/10 現在　visual Studio 2017なのに、viual Studio2015のライブラリーを使っている状態なので 次バージョン glfw3.3がはやく完成してほしいと思った。

## 連絡先

tweeter: [tositada_nakada](https://twitter.com/nakadasanda17)
mail: nakadasanda@outlook.com

## 寄付

paypal: [tositada_nakada](https://www.paypal.me/nakadasanda)
Amazon:[欲しいものリスト](http://amzn.asia/fGpGuJo)
賢いパラメータ探索: Optuna入門 with Chainer

Preferred Networksのパラメータ探索ライブラリOptunaを使ってみたら便利だったので。

## はじめに
機械学習を上手く使うには、ハイパーパラメータの設定が重要になります。
しかし、手動でいちいちパラメータを探すのは膨大な労力を必要とします。
また、グリッドサーチにより探索できるパラメータ数にも限界があります。

賢く; すなわち短時間で良質なパラメータを発見するための自動化を導入します。
Optunaを使うことで、簡単に自動化されたパラメータ探索ができます。


## Optunaとは
> ハイパーパラメータの最適化フレームワーク
> 
> 主要機能:
> 1. Define-by-Run
> 既存のフレームワークは検索空間と目的関数を別々に定義します。 Optunaは、サーチスペースは目的関数内で定義され、すべてのハイパーパラメータは実行時に定義されます。この機能により、Optunaで書かれたコードはよりモジュール化され修正しやすくなります。
> 2. Parallel distributed optimization
> Optunaは、線形のスケーラビリティで並列化することができます。並列化を設定するには、ユーザーは複数の最適化プロセスを実行するだけで、Optunaは自動的に検証結果をバックグラウンドで共有します。
> 3. Pruning of unpromising trials
> 枝狩り機能は、トレーニングの初期段階で自動的に見込みのない試験を停止します。 Optunaは枝狩りを簡単に実装するためのインターフェースを提供します。
> (出典: https://optuna.org)

要約すると、1.賢いパラメータ探索が簡単に導入できて、2.複数サーバーでの分散探索が簡単にスケールして、3.Chainerの学習中に見込みの薄い探索を自動で中断してくれるフレームワークです。読みやすくシンプルなAPIなので、Chainer以外のあらゆるパラメータ探索にも使うことができます。


## サンプルプログラム
全文は[こちらのGist](https://gist.github.com/jin0g/21b51db70252b7415d46069e464b2d65)に公開しています。

```python:tune-mnist.py(一部抜粋)
import optuna
from optuna.integration import ChainerPruningExtension


# ここで探索空間を定義しつつ、探索自体も記述します
def objective(trial):
    # 学習率だけでなく、バッチサイズやモデル自体の定義も探索できます
    n_mid_units = trial.suggest_int('n_mid_units', 10, 1000)
    batchsize = trial.suggest_int('batchsize', 16, 512)
    lr = trial.suggest_loguniform('lr', 1e-5, 1e-1)
    momentum = trial.suggest_uniform('momentum', 0, 1)

    # Chainerの学習記述を分離して、trainerのみを管理すると便利です
    trainer = get_trainer(gpu, n_mid_units, batchsize, lr, momentum)

    # ここで枝狩りの処理を挿入しています
    # この例ではvalidation/main/lossを1epochごとに監視します
    trainer.extend(ChainerPruningExtension(
        trial, 'validation/main/loss', (1, 'epoch')))

    trainer.run()
    accuracy = trainer.observation['validation/main/accuracy']

    # 最終的な評価指数は1-accuracyすなわち誤差です
    return 1.0 - float(accuracy)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Chainer example: MNIST')
    parser.add_argument('--gpu', '-g', type=int, default=0)
    args = parser.parse_args()

    gpu = args.gpu  # note: global variable

    # 枝狩りの開始条件を2epoch後に設定します
    pruner = optuna.pruners.MedianPruner(n_warmup_steps=2)  # after 2epoch

    # sqliteが作成されます
    # dbをファイルを共有した、複数のサーバーで協調して探索を行えます
    study = optuna.study.create_study(storage='sqlite:///example.db',
        pruner=pruner, study_name='mnist', load_if_exists=True)
    study.optimize(objective, n_trials=100)

```


## 試してみる

```bash
$ pip install chainer numpy cupy optuna
$ git clone https://gist.github.com/21b51db70252b7415d46069e464b2d65.git optuna
$ cd optuna
$ python tune-mnist.py
```
学習を進めるとたまに発生するTracebackがエラーのように見えるかもしれません。これは、枝狩りが成功した時の正しい挙動です。


## まとめ
Chainer使ってるならOptuna便利そうです。
他に便利な機能などあればコメントで教えてください！
vue-router.js を cdn で使う

コピペで動きます。
テンプレートも外部ファイル化しておきます。


```main.js

var page1 = '<div>ページ１を表示</div>';

```



```welcome.blade.php

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="utf-8">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Laravel-Vue-todo</title>
    <style type="text/css">
        /*初期表示時にテンプレートが一瞬表示されてしまうのを防ぐ*/
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<body>


<h3>タイトル！（※書き換わらない）</h3>
<div id="app" v-cloak>
    <router-link to="/page1">トップページ</router-link>
    <router-link to="/page2">ユーザー一覧ページ</router-link>
    <router-view>(ここにコンテンツが表示される)</router-view>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="{{ asset('/js/main.js?hogde') }}"></script>


<script>


    // var page1 = '<div>ページ１を表示</div>';
    var page2 = '<div>ページ２を表示</div>';


    var router = new VueRouter({
        mode:'history',
        // base:'/app/public/',
        routes: [
            {
                path: '/page1',
                component: {
                    <!-- ここにページ１のコンテンツを設定(変数page1を設定しています) -->
                    template: page1
                }
            },
            {
                path: '/page2',
                component: {
                    <!-- ここにページ２のコンテンツを設定(変数page1を設定しています) -->
                    template: page2
                }
            }
        ]
    });
    // routerをマウント
    var app = new Vue({
        el: '#app',
        router: router
    }).$mount('#app');



</script>

</body>
</html>


```
Promise エラー

# 概要
Promise.allってした時に、どれかでエラーが発生した際どういう挙動になるのか試してみました。たぶんググれば見つかることなんだと思いますが。。。

# 疑問と結果
1. エラーが起きた場合は他の処理はどうなるのか
    * 他の処理はそのまま実行されました。
2. エラーが複数起きた場合、catchへは何が渡されるのか。
    * 一つ目のエラーだけがcatchへ渡されました。
    * また、catchは他の処理の終了を待たずに呼び出されました。

# 試した内容
## 1

```javascript
let promises =  [];

promises.push(new Promise((resolve, reject) => {
  console.log('reject1');
  throw new Error('reject1');
}));

for(let i = 0; i < 3; i++) {
  promises.push(new Promise((resolve) => {
    setTimeout(()=>{
      console.log(i);
      resolve(i);
    }, 100);
  }))
}

Promise.all(promises).then((data) => {
  console.log('success');
  console.log(data);
}).catch((error)=>{
  console.log('fail');
  console.log(error);
});
```

```
reject1
fail
Error: reject1
    at promises.push.Promise (/test/test.js:5:9)
    ...
0
1
2
```

エラーが起きても他は実行された。

## 2
```javascript
let promises =  [];

promises.push(new Promise((resolve, reject) => {
  console.log('reject1');
  throw new Error('reject1');
}));
promises.push(new Promise((resolve, reject) => {
  console.log('reject2');
  throw new Error('reject2');
}));

for(let i = 0; i < 3; i++) {
  promises.push(new Promise((resolve) => {
    setTimeout(()=>{
      console.log(i);
      resolve(i);
    }, 100);
  }))
}

Promise.all(promises).then((data) => {
  console.log('success');
  console.log(data);
}).catch((error)=>{
  console.log('fail');
  console.log(error);
});
```

```
reject1
fail
Error: reject1
    at promises.push.Promise (/test/test.js:5:9)
    ...
0
1
2
```
一つ目のエラーだけがcatchへ渡された。
centos7 で RubyOnRails 環境を構築する。ruby2.6.0

RubyOnRails5の環境を構築したので覚書です。

事前準備として
・環境 windows10のVMにCENTOS7を構築済み
・参考サイト：https://qiita.com/tomsyoya/items/addf78f28a63ecda82b3



GITをインストール

```
sudo yum update
$ yum install -y https://centos7.iuscommunity.org/ius-release.rpm
S yum -y install git2u yum-utils
$ yum-config-manager --disable ius

```

旧バージョンのGitをインストールしている場合は削除する
CENTOS7には標準でv1が入っているので消す

```
$ yum erase -y perl-Git
バージョン確認
$ git --version

```


```

rbenvをインストールする
ビルドに必要なpackageをインストール
$ sudo yum install -y openssl-devel readline-devel zlib-devel

packageが足りないのでbzip2とgccを入れる
$ yum -y install bzip2
$ yum -y install gcc

rbenvインストール
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv

```


~/.bash_profileにexport PATH="$HOME/.rbenv/bin:$PATH"とeval "$(rbenv init -)"を追加


```

$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ ~/.rbenv/bin/rbenv init
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

```


追加内容を反映

```

$ source ~/.bash_profile

```

・ruby-buildをインストール

```

$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build


```


bundlerをインストールします。


```
# "rbenv exec"をつけると、「rbenvの設定で現在有効なrubyのbundler」をインストールできる
$ rbenv exec gem install bundler


```


インストールできるRubyのバージョンを確認
(現時点で一番新しいｖｅｒｓｉｏｎを入れた）
2019/1/09時点

```
$ rbenv install -l
Rubyインストール
$ rbenv install 2.6.0
使用するrubyのバージョンを指定

$ rbenv global 2.6,0
インストールできたことを確認

$ ruby -v

```

gemとbundlerを入れる

```
gemを入れる
yum install rubygems -y

bundlerをインストールします。

# "rbenv exec"をつけると、「rbenvの設定で現在有効なrubyのbundler」をインストールできる
$ rbenv exec gem install bundler


```
・Rails インストール(最新を入れる）
2019/1/09時点

```

$ gem install rails
$ rails -v
Rails 5.2.2
```

mysqlをインストール
https://www.techbox.jp/entry/centos-mariadb-mysql
<<後日作成予定>>
情報処理安全確保支援士のオンライン講習を受講しました

昨年登録した情報処理安全確保支援士に義務付けられている講習を受講しました。

今回は、１年目ということでオンライン講習Aを受講しました。学習内容は、以下になります。

1. 知識
 - 情報セキュリティの最新動向

2. 技能
 - 情報セキュリティ早期警戒パートナーシップガイドライン
 - 「Japan Vulnerability Notes（JVN）」概説

3. 倫理
 - 情報セキュリティ従事者としての倫理的責任と義務

- - - 

個々の内容を簡易にまとめると、以下になります。

## 情報セキュリティの最新動向

情報セキュリティ10大脅威を活用し、情報セキュリティへの脅威のトレンド、脅威への対策なを学習する。
最新の「情報セキュリティ10大脅威 2018」は、IPAの以下で公開されている。

https://www.ipa.go.jp/security/vuln/10threats2018.html

## 情報セキュリティ早期警戒パートナーシップガイドライン 

脆弱性関連情報の連携体制を学習する。

詳細は、以下。
https://www.ipa.go.jp/security/ciadr/partnership_guide.html

## 「Japan Vulnerability Notes（JVN）」概説

JVN, CVSS, CWE等の読み方、脆弱性診断について学習する。

## 情報セキュリティ従事者としての倫理的責任と義務

倫理、社会的責任について学習する。
社会的責任は、ISO26000.

https://www.iso.org/iso-26000-social-responsibility.html

日本では、JIS化されており、 JIS Z 26000 で制定されている。

- - -

直接セキュリティに関する業務に関わっていないと忘れてしまっていることも多く、復習する良い機会でした。
講習で学習する内容の詳細のほとんどは、ネットで公開されており、そちらを参照することでより深く知ることができます。
JVN, CVSS, CWE等の読み方などは、ソフトウェア開発に関わるなら、把握しておいて損はないです。

オンライン講習の詳細は、IPAに掲載されています。
https://www.ipa.go.jp/siensi/lecture/index.html
Viで「E325:ATTENTIONエラー」の対処

# はじめに

viでファイルを編集中にうっかりCtrl+Cコマンドで中断してしまったため、多重オープンしてしまった。対処方法をまとめた。

# 事象

vi で対象ファイルを開いたら次のようなメッセージが毎回出てしまう

```:
--------------------------------------------- 
E325: ATTENTION 
Found a swap file by the name ".attention.sh.swp" 
 owned by: orenoscript dated: Tue Jan 01 00:01:00 2019 
 file name: /tmp/attention.sh 
 modified: YES 
 user name: root    host name: localhost.localdomain 
 process ID: 9999 
While opening file "attention.sh" 
 dated: Tue Jan 01 00:01:00 2019 
 NEWER than swap file! 

(1) Another program may be editing the same file. 
 If this is the case, be careful not to end up with two 
 different instances of the same file when making changes. 
 Quit, or continue with caution. 

(2) An edit session for this file crashed. 
 If this is the case, use ":recover" or "vim -r atention.sh" 
 to recover the changes (see ":help recovery"). 
 If you did this already, delete the swap file ".atention.sh.swp" 
 to avoid this message. 
"attention.sh" 540L, 627C 
Press ENTER or type command to continue 
--------------------------------------------- 
```

# 対処

1.オープンしようとしているファイルのパスに移動
2.ls -laコマンドで該当スワップファイルを確認

```
drwxr-xr-x. 6 root   root   4096 Jan 01 00:01 .
drwxr-xr-x. 6 root   root   4096 Jan 01 00:01 ..
-rw-r--r--. 1 root   root  12288 Jan 01 00:01 .attention.sh.swo *
-rw-r--r--. 1 root   root  12288 Jan 01 00:01 .attention.sh.swp *
-rwxr-xr-x. 1 root   root   1383 Jan 01 00:01 .attention.sh
```
<font color="red">※マークのファイルがスワップファイル</font>

3.rmコマンドでスワップファイルを削除
【Python機械学習Tips】sckit-learnのconfusion matrixでラベルを含めて表示する

# はじめに
scikit-learnのライブラリを使って簡単にconfusion matirxを表示できるが、数値マトリックスのみでラベルがないので実用上は不便です。
この対応を簡単に行うためのメモです。(ラベルつきDataFrameに変換して表示する)

なお、ここで紹介している小ネタを含めて、Pythonでモデルを構築する際の便利な技は、私の著書「Pythonで儲かるAIをつくる」の中にいろいろと記載されています。
下記のサポートサイトでコードはすべて公開していますので、関心のある方は是非そちらも参照して下さい。

[書籍「Pythonで儲かるAIをつくる」サポートサイト](https://github.com/makaishi2/profitable_ai_book_info/blob/master/README.md)

![スクリーンショット 2020-09-19 14.27.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/1b2b8fcd-d267-7e9d-d1e7-5f20051ce8a6.png)


# 前提 
sckit-learnがライブラリとして使えること

# サンプルコード
以下にサンプルコードを記載します。

```
# 余分なワーニングを非表示にする
import warnings
warnings.filterwarnings('ignore')

# 必要ライブラリのimport
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# データフレーム表示用関数
from IPython.display import display

# y_test に正解値、 y_predに予測値がすでに入っていることを前提にします。
# 以下の2行はこの前提を満たすためのダミーコードです。

y_test = np.array(
 ['疾患なし', '疾患なし', '疾患なし', '疾患なし', '疾患なし',
  '疾患あり', '疾患あり', '疾患あり', '疾患なし','疾患なし',
  '疾患あり', '疾患なし', '疾患なし', '疾患なし', '疾患あり',
  '疾患なし', '疾患なし', '疾患なし','疾患なし', '疾患なし',
  '疾患あり', '疾患あり', '疾患なし', '疾患なし', '疾患なし',
  '疾患あり', '疾患なし','疾患なし'])
    
y_pred = np.array(
['疾患なし', '疾患なし', '疾患なし', '疾患なし', '疾患なし',
 '疾患あり', '疾患あり', '疾患あり', '疾患なし', '疾患なし',
 '疾患あり', '疾患なし', '疾患なし', '疾患なし', '疾患あり',
 '疾患なし', '疾患あり', '疾患なし', '疾患なし', '疾患なし',
 '疾患なし', '疾患あり', '疾患なし', '疾患なし', '疾患なし',
 '疾患あり', '疾患なし', '疾患なし'])

# 混同行列(confusion matrix)の取得
labels = ['疾患なし', '疾患あり']
from sklearn.metrics import confusion_matrix
matrix = confusion_matrix(y_test, y_pred, labels=labels)

print(matrix)
```

出力結果
```
[[19  1]
 [ 1  7]]
```

ここで得られたnumpyの2次元配列``matrix``がscikit-learnのライブラリで得られた結果なのですが、単に数値の配列なので、読み取るのが難しいです。
そこで、次のような関数を定義します。

```
# 混同行列表示用関数

def make_cm(matrix, columns):
    # matrix numpy配列
    
    # columns 項目名リスト
    n = len(columns)
    
    # '正解データ'をn回繰り返すリスト生成
    act = ['正解データ'] * n
    pred = ['予測結果'] * n
    
    #データフレーム生成
    cm = pd.DataFrame(matrix, 
        columns=[pred, columns], index=[act, columns])
    return cm
```

次のような形で呼び出します。


```
# make_cmを使った混同行列標示
cm = make_cm(matrix, ['疾患なし', '疾患あり'])

# 結果の表示
display(cm)
```

結果は次のとおり。

![スクリーンショット 2020-09-19 14.23.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/d06145a0-ab26-1c4a-70f3-aefe9744aea3.png)

きれいにラベルが振られて、意味のわかりやすい混同行列表示になりました。
実装のテクニックという観点で解説すると、DataFrameのdisplay関数は、2階層のインデックスの表示もできるので、その方法を使っています。


この例は二値分類ですが、同じコードで多値分類も対応可能です。
php-master-changes 2019-01-09

今日はマイナーバージョンアップへ向けての準備、opcache 最適化の条件修正、pdo_mysql で persistent 接続を使う際にクラッシュする問題の修正、符号違いの比較の修正、鬼車のパッチへのセキュリティ修正取り込み、mysqlnd に入った以前の修正の 7.2 系以降へのバックポートがあった！

# 2019-01-09
## cmb69: Sync NEWS with 7.3.1
- https://github.com/php/php-src/commit/d7873ad8ff87603f7e38b5be4cc06db855f4b557
- [7.3~]
- NEWS で、7.3.1 のリリースを後ろにずらした分より多くの更新を入れるようにしたのを反映

## sgolemon: Bump for 7.1.27
- https://github.com/php/php-src/commit/fabade157323a0998ef2b97208b8f58779c40f2b
- [7.1~]
- 7.1 系の開発バージョンを 7.1.27 へ更新

## nikic: Make operator swapping depend on IGNORE_OVERLOADING flag
- https://github.com/php/php-src/commit/bf4dab016341070d36606f4d1cf3ac068082c9e2
- [7.3~]
- ext/opcache で、[昨日の修正](https://qiita.com/sj-i/items/789a0057f4b9316f01e3#nikic-dont-swap-operands-of-zend_mul)を戻して IGNORE_OVERLOADING を見て最適化の可否を判定するよう修正
- 演算子オーバーロードの可能性考えるなら `*` 以外だって可換でなくなる可能性あるので、若干引っかかってはいた

## Metabolix: Fixed bug [#77289](https://bugs.php.net/bug.php?id=77289)
- https://github.com/php/php-src/commit/63c38c9e4907b2d12885db7943b7053efe0d6c60
- [7.3~]
- ext/pdo_mysql で、persistent 接続を使う際にクラッシュする場合がある問題の修正
- リクエスト開始終了時の初期化みたいな処理（end_psession / restart_psession）が抜けてたのが、[last_message やらが ZendMM 管理になった](https://github.com/php/php-src/commit/a7305eb539596e175bd6c3ae9a20953358c5d677)ことでクラッシュにつながるようになった、みたいな話かな？

## jvoisin: Fix some sign-related issues in comparisons
- https://github.com/php/php-src/commit/fbdaabba62e8a7068dd0212b79be3607746ff26b
- 符号違いの比較が各所にあったのを修正

## cmb69: Update oniguruma.patch wrt. latest security fixes
- https://github.com/php/php-src/commit/50f38f9027adfc615eed2c354b0ae3ce90867b5c
- ext/mbstring で、oniguruma.patch にセキュリティ修正を取り込み

## Andrey Hristov: Revert visibility
- https://github.com/php/php-src/commit/7a88f89a90902c4393f96616cb86137309d173af
- [7.2~]
- [4 日の修正](https://qiita.com/sj-i/items/b0eeca1786c4822b4192#andrey-hristov-revert-visibility) を 7.2 以降へバックポート
"java"コマンドラインツールを使用するには...のポップアップを出さない方法


私の環境は以下の通り。

macOS Mojave バージョン 10.14.2

# インストールしたのに出る

このポップアップウィンドウ。
![スクリーンショット 2019-01-10 9.10.30.png](https://qiita-image-store.s3.amazonaws.com/0/335400/fb3a5e0f-cb35-ed79-1944-1ff50b31d5b8.png)

# 原因

[Javaの正式コメント](https://www.java.com/ja/download/faq/yosemite_java.xml)にはこのように書かれていました。

> これは、通常アプリケーションがAppleによって提供されたレガシーのJava 6を必要とするためです。この問題の解決策については、http://support.apple.com/kb/DL1572 を参照してください。

# 対策

上述のリンクに貼られているのはHigh Sierraまでのサポートなので大丈夫なのだろうか、兎にも角にもインストールしてみました。

# 結果

出なくなりました、あい万事済みましたとさ。