OmniAICreator/Qiita-1.07M huggingface dataset:
javascriptのMath.max()で-Infinityが返る理由

javascriptは謎仕様の多さで有名だ。

https://twitter.com/cdesio/status/1013166206877163520

その中でも目を引くのがこの仕様。

```javascript
> Math.min() 
< Infinity
> Math.max()
< -Infinity
```

何だこれは、クソ仕様か。   
minが∞でmaxが-∞と。   
時空が歪む。   
   
なぜ天下のjavascript様がこのような素晴らしい仕様を採用しているか調べたところこのような記事が。

https://charlieharvey.org.uk/page/why_math_max_is_less_than_math_min

この記事を読みjavascriptの深淵な仕様が理解できたのでここに記す。   

##Math.min() or Math.max()は要素をn→1へと飛ばす関数
知識豊かな皆さんはすでにMath.min()とMath.max()がどういった関数なのかは百も承知だろう。  

```javascript
const list = [1, 2, 3, 4, 5];
const max = Math.max(...arr);
const min = Math.min(...arr);

console.log(max);
// 5
console.log(min);
// 1
```
複数の要素を入れると最大値or最小値を返す。   
単純明快。   
   
だが待ってほしい。   
javascriptはfunctionalな世界。   
functionとしての彼らの実態を理解しているか？   
といってもそんなに難しいものではない。   
いってしまえばn個の引数から1つを選んで返す関数。しゃぞーと言っても構わない。   
この性質が重要だ。   

##n→1関数としてのreduce
ではn→1な関数を実装するときjavascriptではどう実装するだろうか。   
配列に対して作用する関数はmap、forEach、filter、reduce。   
そのなかでn→1なもの。   
そう、reduceだ。   

```javascript
const list = [1, 2, 3, 4, 5];
const sum = (accumulator, currentValue) => accumulator + currentValue;

console.log(list.reduce(sum, 0))
// 15
```
初期値をもとに複数要素を結合していき最終的に1要素を吐き出す。   
Math.min()とMath.max()の実装にぴったりだ。

##二項演算子 + 単位元 = モノイド
ここで数学のお話。   
別に記事を書くページを間違えたわけじゃない。   
説明に必要なのだ。   
ちなみにモナドとの関係性は不明。   
さあここでWikipediaによるモノイドの定義。

```
集合 S とその上の二項演算 •: S × S → S が与えられ、以下の条件
結合律   
S の任意の元 a, b, c に対して、(a • b) • c = a • (b • c).   
単位元の存在   
S の元 e が存在して、S の任意の元 a に対して e • a = a • e = a.   
を満たすならば、組 (S, •, e) をモノイドという。
```

モノイドの構成に必要なものは任意の集合S、その上での二項演算子、そして単位元。   
二項演算子は四則演算子などの2つの要素に作用し1つの要素を吐き出すもの。   
単位元はそれと他の任意の要素xを二項演算子にかけたとき常にxを吐き出すようなものだ。   
例を挙げよう。   
   
例えば加算演算子+を用いたモノイドの構成。   
+は任意の2つの実数を足した数を吐き出す。（二項演算子）   
そして足し算は順番を変えても結果は同じ。（結合率）   
最後に0は任意の実数$x$に加えても$x$のままである。（単位元）   
よって実数集合$\Re$、演算子+、単位元0の組み合わせ$(\Re,+,0)$はモノイド。   
   
簡単なことを難しく言っただけ。   
なんの関係がと思うかもしれないが、覚えておいてほしい。   

##単位元としての-Infinity
ではいよいよMath.max()を構成していこう。   
順番としては、   
   
1. 2つの要素を比べ大きい方を返す関数の作成

1. 1で作成した関数をreduceで次々に適用

である。   
イメージはバブルソートに近い。   
具体的には、

```javascript
const max = (identity, num) => num > identity ? num : identity;
```

といった関数をreduceで連続して適用すればMath.max()が構成できる。   
これは2つの要素に作用し1つの要素を返すためまさに二項演算子だ。   
ここで注意すべきはreduceの初期値をどうするかということだ。   
reduceの適用1回目は常に入力されたn個の要素の1つめをmaxが返さなければならない。   
言い換えるとmax関数が構成するモノイドの単位元をreduceの初期値としなければならない。   
ではmaxの単位元はなんだろうか？   
そう-Infinityである。   
-Infinityはすべての実数より小さい。   
すなわち-Infinityと任意の実数$x$をmaxにかけるとmaxは常に$x$を返す。   
そしてreduceは入力要素がないと初期値を返す。   
これがMath.max()が-Infinityを返す理由である。   
以下簡易的なMath.max()。

```javascript
const max = (identity, num) => num > identity ? num : identity;
const list = [1, 2, 3, 4, 5];
const nullList = [];

console.log(list.reduce(max, -Infinity));
// 5

console.log(nullList.reduce(max, -Infinity));
// -Inifinity
```

Math.min()は単位元をInfinityとするためほぼロジックは同じ。

##まとめ
個人的にreduceを関数として捉え直すという部分が面白かった。   
なんにせよ生き残っているものには何かしらの理由があるっぽい。   
Thanks for inventing javascript。
Windows10+VirtualBox(CentOS7)で共有フォルダにシンボリックリンクが作れなくてnpm installが失敗する

# 問題

Windows10+VirtualBox(CentOS7)で共有フォルダにシンボリックリンクが作れなくてnpm installが失敗する。

# 解決方法

```sh
vboxmanage setextradata VM_NAME VBoxInternal2/SharedFoldersEnableSymlinksCreate/SHARE_NAME 1
```

`VM_NAME`は`vboxmanage list vms`で確認可能。
`SHARE_NAME`は設定の共有フォルダから確認可能。
`vboxmanage`はVirtualBoxのインストール先にパスが通ってないと駄目で、俺なら`C:\Program Files\Oracle\VirtualBox`なので`vboxmanage`を`"C:\Program Files\Oracle\VirtualBox\vboxmanage.exe"`に置換して実行する。スペースを含む文字列は引用符でくくるのはよく知られる通り。以下でも同様にする。

設定されたかは以下で確認。

```
vBoxmanage getextradata VM_NAME enumerate
```

そして起動。

```
vboxmanage startvm VM_NAME --type headless
```

これで起動するとシンボリックリンクが作れるようになってる。
非管理者権限で起動したVirtualBoxのGUIから起動すると設定が無効になるようなので注意。

念の為`npm install`についても、共有フォルダ内には、VM内の領域へのシンボリックリンクを1つだけ張って、その参照先にインストールするようにした。

```sh
mkdir ~/node_modules 
cd PROJECT_ROOT
ln -s ~/node_modules/ node_modules
```

あと `npm install`はシンボリック対策として別のところで見つけたオプションもつけた。

```sh
npm install --no-bin-links
```

# 文献
http://var.blog.jp/archives/75786730.html
https://kokufu.blogspot.com/2016/01/virtualbox-shared-folders.html
https://github.com/npm/npm/issues/9953#issuecomment-242827385
PHP GDでインデックス透明カラーの8bit PNGを透過ありの32bit PNGに変換する

需要はほとんどなさそうですが、インデックス透明カラーが設定されている8bit PNGを透過情報を残して32bit PNGに変換する方法です。

というのも、インデックス透明カラーは、`imagecolorsforindex`で透明度情報を取得出来ないので、一旦32bit PNGに変換してやろう、という魂胆です。

参考
http://php.net/manual/ja/function.imagecopy.php#73430

```php
<?php
$orgResource = imagepng('path/to/8bit.png');

// 横幅、縦幅を取得する
$width = imagesx($orgResource);
$height = imagesy($orgResource);

// インデックス透明カラーの情報を取得する
$orgTrans = imagecolortransparent($orgResource);
if ($orgTrans >= 0) {
    $orgRgb = imagecolorsforindex($orgResource, $orgTrans);
}

// TrueColorのリソースを用意する
$trueResource = imagecreatetruecolor($width, $height);

// 透明PNGにする
imagealphablending($trueResource, false);
imagesavealpha($trueResource, true);

// TrueColorのリソースに貼り付ける
imagecopy($trueResource, $orgResource, 0, 0, 0, 0, $width, $height);

// インデックス透明カラーがあった場合は、該当の色を透明にする
if ($orgTrans >= 0) {
    for($x=0; $x < $width; $x += 1) {
        for($y=0; $y < $height; $y += 1) {
            $index = imagecolorat($tc, $x, $y);
            $trueRgb = imagecolorsforindex($tc, $index);

            // インデックス透明カラーの情報と比較
            if(
                $orgRgb['red']   === $trueRgb['red'] &&
                $orgRgb['green'] === $trueRgb['green'] &&
                $orgRgb['blue']  === $trueRgb['blue']
            ) {
                // 透明にする（alphaチャンネルを127にする）
                imagesetpixel($trueResource, $x, $y, 127 << 24);
            }
        }
    }
}

// $trueResourceが透過ありの32bit PNG
```
PhpStorm 2018.3(EAP)でPSR-5:PHPDocのジェネリクス構文や交差型がサポートされた

[PhpStorm 2018.3 EAP 183.2635.12 | PhpStorm Blog](https://blog.jetbrains.com/phpstorm/2018/09/phpstorm-2018-3-eap-183-2635-12/)によれば、PhpStorm 2018.3(EAP)で[PSR-5:PHPDoc](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md)のジェネリクス構文や交差型がサポートされたらしい。

## ジェネリクス構文

PhpStorm 2018.3からPHPDocにて`array<Type>`のような型宣言が認識されるようになった。今までは`<>`の中身が型として認識されなかった。

![generics-1.gif](https://qiita-image-store.s3.amazonaws.com/0/889/78753f51-988a-3afc-12da-4da4de879ea1.gif)

ただし、コード補完やインスペクションはジェネリクス構文に対応していないため、現状でコード補完やインスペクションを作動させるには`Type[]`のような書き方をするか、`array<TypeB>|TypeB[]`のような併記をしないとならない。

![generics-2.gif](https://qiita-image-store.s3.amazonaws.com/0/889/43963cfc-04fb-e483-e9d5-7ff7aba0a556.gif)

## 交差型(intersection types)

これまでのPhpStormは、PHPDoc内の共用体型(union types)を認識していたが、2018.3からは交差型(intersection types)も認識してくれる。

![2018-09-26 16-28-38.2018-09-26 16_29_55.gif](https://qiita-image-store.s3.amazonaws.com/0/889/350e4b63-da6e-342b-4fd4-a4a55def4661.gif)

今まで、本当は交差型なのにPhpStormに認識されなかったために共用体型の表記で対処してきた部分は、交差型として書くことができる。

こちらもインスペクションには未対応なので、交差型を満たさない型を渡しても警告が出ない。インスペクションでは共用体型として認識される。

<img width="846" alt="スクリーンショット 2018-09-26 16.40.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/889/f7a801b4-0f65-b10d-4ca3-dcfeeb06962a.png">

## 所感

* PhanやPsalm、PHPStanといった解析ツールを使っている人にとっては喜ばしいアップデートだったかも。
* 今日現在DraftのPSR-19ではジェネリクス型パラメータ宣言のタグ`@template`が盛り込まれておらず、ユーザがジェネリクス型のコードを作れないので、PhpStormがジェネリクスにどこまで対応してくれるか不安が残る。
* コード補完やインスペクションは今後のアップデートに期待したい。
WindowsのサービスにApacheを登録する

# Windowsのサービスに追加

管理者権限でコマンドプロンプトを起動して登録コマンドを実行する

```
httpd -k install -n "サービス名"
```

Apacheの`httpd.conf`を指定する場合は

```
httpd -k install -n "サービス名" -f "path/httpd.conf"
```

# Windowsのサービスから削除

管理者権限でコマンドプロンプトを起動して削除コマンドを実行する

```
httpd -k uninstall -n "サービス名"
```
【iOS】HumanInterFaceGuidelinesのThemesを読む

## 前置き 
今までのんびりAndroidアプリの開発をしていたところ　、iOSアプリ開発に携わることになりました
AndroidでいうListViewのようなものを実装する際に、「これってどのViewで作るんです？」と聞いたところ「UITableViewですね！」と言われ"なるほど！？"と思いました

私にはどのパーツの組み合わせをするのが最適なのかがよくわかっておりません。
きっとUIガイドライン？を読んで見たら少しは理解できるのではないかと思い、まず開いた最初の1ページを読んでまとめました

https://developer.apple.com/ios/human-interface-guidelines/overview/themes/

まずですね、英語なんですね。英語だと(僕は)よくわからない...

## iOS Design Themes(3大テーマ)
### 1. Clarity(わかりやすさ)
 - テキストはあらゆるサイズで見やすい
 - アイコンは正しく見やすい
 - ユーザーのやりたいことをわかりやすくする

### 2. Deference(コンテンツを大事にする)
 - デザインはコンテンツを理解しやすくするためにあるので、コンテンツの邪魔になるようにはしちゃいけない
 - 枠線やグラデーション、ドロップシャドウの使用は最小限にしようね(メンテされてない昔の小学校のHPみたいなのはダメってことですね)
 
### 3. Depth(重なり)
 - 明確な重なり合わせがあると理解力がたかまる
 - 触れたり見つけやすくなることで、ユーザー体験はよくなって次のコンテンツにアクセスしやすくなる
 - 奥行き感大事

**全てはアプリを使う人への配慮ってことですね！**


## Design Principles(アプリの広告力と閲覧数を最大限に伸ばすための6つの原則)

### 1. Aesthetic Integrity(整合性の美学)
- アプリの見た目と中身が一致していること

### 2. Consistency(一貫性)
- アイコンやテキスト、用語や動作までの全てユーザーが期待するような状態になっていること

### 3. Direct Manipulation(直接的な操作)
- 直接操作できるとユーザー自身が起こした行動の結果をすぐに見ることができる
- 画面になるものを直接操作できることで、ユーザーのアプリへの理解力を高められます


### 4. Feedback(フィードバック)
- アクションの後にはフィードバックを返しましょう。(音が鳴ったり色が変わったり・・・)


### 5. Metaphors(比喩)
- 現実世界やデジタルの世界にかかわらず、使い慣れている体験をマネして作りましょう(本をめくったりスイッチを押したり・・・)



### 6. User Control(主導権)
- アプリが人を・・・ではなく人がアプリを動かします
- 一連のアクションの流れを提案したりするのは良いが決定するのはよろしくない
- もし望ましくない結果が待っていそうならば、強制はせず微妙なバランスで避けるような流れにもっていく
- ユーザーが自分でそのアプリを動かしている感覚を与えてあげないといけない

__スマホに操作されてしまう・・・__


## 読んでみて
ここまで読んで気づいたことがあります。
まだ僕が知りたい知りたい内容ではなかったかもしれないと・・・。

しかしながら読んでみて考えさせられることはありました。
自分が担当しているアプリでもFeedBackや、UserControlをないがしろにしているのではないかと。
どのViewで作るとかも大事かもしれませんが、人に対して優しいアプリを作らないといけないなぁと感じさせられた1ページ目でした。
NuxtでWebAssemblyが使えるようになったみたいなので動かしてみた

# 概要
[Nuxt.js v2.0.0がリリースされたので触ってみた【変更点まとめ】](http://studio-andy.hatenablog.com/entry/nuxt-v2)の記事を読んでNuxt v2ではWeb Assemblyがサポートされたらしいので、動かしてみた。

# 動かしてみる

Nuxtの動かし方は[ドキュメントのインストール](https://nuxtjs.org/guide/installation)のページを見れば問題ないので、Nuxtの動かし方についてはあまり言及しない。

話はWebAssemblyのファイルを準備するところから始める。とは、言っても今回うごかすWebAssemblyのファイルは[爆速でjsでWebAssemblyを動かす](https://qiita.com/mk-tool/items/eb537ad0ce9639f58e1f)の記事で作ったものを持ってくる。手持ちのwasmファイルがある方はそちらを利用してもいいと思う。

上記の記事で作成された以下の3つのファイルを用意して話を進める。(`js_hello_world.d.ts`はもしかすると不要かもしれないが、wasm出力の際に以下の3つのファイルが出力されるのため、とりあえず3つ用意する)。これらのファイルの関係について述べておくと、`js_hello_world.js`の中で`js_hello_world_bg.wasm`が呼び出されるようになっている。

- js_hello_world_bg.wasm
- js_hello_world.js
- js_hello_world.d.ts 

そして持ってきたファイルを以下のjsフォルダの中に配置する。

```
-| assets/
----| js/
```

これで、動かすwasmファイルの準備はできたので、次はwasmを読み込むための準備をする。

読み込む側では、まずwasmのインポートを記述する。ただ、wasmファイルの関係性の部分で述べたとおり、`js_hello_world_bg.wasm`は`js_hello_world.js`の中で呼び出されるため、`js_hello_world.js`を読み込む記述をしてあげる。

```javascript
<script>
...
const myWasmModule = import("~/assets/js/greet/js_hello_world");
...
</script>
```

今回利用するwasmファイルについて簡単に説明しておくと、greet()という関数があり、引数として文字列を渡してあげると`Hello, {渡した文字列}!`と表示するalertモーダルが出るようになっている。

今回は、ボタンを用意して、クリックしたらalertモーダルが出るようにする。そのため、callGreet()というメソッドを用意し、クリックしたらcallGreet()が動くようなアプリケーションにする。

ビュー側は以下のようになる。Nuxtのプロジェクト作成時にできたaタグを少し書き換えて`@click="callGreet"`を足してあげるだけだ。

```html
...
<div class="links">
  <a
    @click="callGreet"
    class="button--green"
  >click me</a>
</div>
...
```

クリック時の動作については以下のようになる。こちらも基本的にはNuxtのプロジェクト作成時と変わらず、少しだけ追記をしているだけだ。モジュールはimport()によりを呼び出しているため、Promiseオブジェクトとして関数を取り出してあげる必要がある。そして、取り出した関数に表示したい文字列を渡す。

```javascript

<script>
...
export default {
...
  data() {
    return { 
      myName: 'mk-tool'
    }
  },
  methods: {
    callGreet() {
      myWasmModule.then(myWasmModule => myWasmModule.greet(this.myName));
    },
  },
...
}
</script>
```

やることはたったこれだけだ。プロジェクトを実行してボタンを押すと、WebAssemblyによるモジュールが読み込まれて正常に実行されることが分かる。

![nuxt.png](https://qiita-image-store.s3.amazonaws.com/0/127811/277cb4c4-9ccb-ea68-985d-26f09e932363.png)

ソースコードは[GitHub](https://github.com/mk-tool/wasm_nuxt)にあげています。

# その他
今回は`js_hello_world.js`を読み込んだが、`js_hello_world_bg.wasm`を直接呼び出してもalertモーダルが表示された。しかしながら、こちらの場合は引数部分に渡した文字列が表示されなかった。`js_hello_world.js`の中身を見てみると、webassemblyのgreet()を呼び出し、受け取った引数を関数へ渡したりしていたため、我々人間はおとなしくコンパイラが出力した`js_hello_world.js`経由で`js_hello_world_bg.wasm`にアクセスしたほうが良いんだな、と感じた。

```javascript:wasm直接呼出し
<script>
...
const myWasmModule = import("~/assets/js/greet/js_hello_world_bg");
...
</script>
```


# 参考

- import()がPromiseを返すことについて
[MDN - import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports)
- 今回とはあまり関係はないがwasmのコードの実行については以下の記事が参考になった。
 - [WebAssembly JavaScript API を使用する](https://developer.mozilla.org/ja/docs/WebAssembly/Using_the_JavaScript_API)
 - [WebAssemblyコードのロードと実行](https://developer.mozilla.org/ja/docs/WebAssembly/Loading_and_running)
[perl]モジュールにデータディレクトリを同梱する

これは基礎の基礎なのかもしれませんが、気づいてから解決するまで3日以上ハマってたので共有します。

# 要旨
モジュールにYAMLなどのデータを同梱したディレクトリをつけて配布したい。

# 経緯
[Data::Pokemon::GoというPerlモジュールをリリースした](https://qiita.com/worthmine/items/4a51fd74f31b4a97cf3c)んですけど、インストール時には読み込んでくれる`data/`ディレクトリがイントール後には行方不明になってまして、なにがしかの方法([SCP](https://qiita.com/tommyfms2/items/7d7732c0b681b215d461)など)を使って呼び出し元のスクリプトの近くに相対パスでデータをコピーしてやらないと使えない状態が続いてました。[^1]

調べてみてもなかなか良い記事が見つからず、うーん、こんなに難しいはずがないだろうと思ってました。
[こんな英語の記事](https://www.perl.com/article/66/2014/2/7/3-ways-to-include-data-with-your-Perl-distribution/)は見つけたんですけど、私は[Minilla](https://qiita.com/ishikawa@github/items/e02baedec4990120299d)を使っているので`Build.PL`を直接編集できなかった（しても自動的に戻される）んですね。

で、ようやくたどり着いた記事が[こちら](https://papix.hatenablog.com/entry/2015/06/27/175112)。要するに`data/`という名前が悪くて`share/`ならOKというPerlの仕様だということを突き止めました。

それで、あとは

```　file_share.pl
use File::Share 'dist_dir';
my $dir = dist_dir('Data-Pokemon-Go');
my $data = YAML::XS::LoadFile("$dir/Skill.yaml");
```

のように、モジュール内の`share/`ディレクトリへの絶対パスを取得して読みに行くだけでした。[^2]

# 要約
データは`share/`に入れる。
呼び出すときは`File::Share::dist_dir`を使う。
使わなくてもtest通るから気をつけて。

[^1]: `use Path::Tiny;`してたせいだった。
[^2]: 標準モジュールではないので`cpanm File::Share`してください。
Kibana+ElasticSearchで検索した時Courier Fetch: X of Y shards failedとエラーが出てしまったときの対処

Kibana+ElasticSearchで検索した時、Courier Fetch: X of Y shards failedとエラーが出てしまったときの対処

結論から言うとおかしなインデックスを削除したら直りました。

#### 1. インデックスを確認

```
curl localhost:9200/_cat/shards?v  | awk '{ print $1 }' | sort | uniq
index
.kibana
logstash-2018.09.12
logstash-2018.09.13
logstash-2018.09.14
logstash-2018.09.15
logstash-2018.09.16
logstash-2018.09.17
logstash-2018.09.18
logstash-2018.09.19
logstash-2018.09.20
logstash-2018.09.21
logstash-2018.09.22
logstash-2018.09.23
logstash-2018.09.24
logstash-2018.09.25
logstash-2018.09.26
logstash-503830.12.31 # こんな感じの変なインデックスがある
```

#### 2. インデックスの削除

```
curl -XDELETE localhost:9200/logstash-503830.12.31?pretty
```

#### 3. 再起動

```
service elasticsearch restart
```


こうなった原因ははっきりとはしませんが、直近で大量のドキュメントがElasticSearchに流れ込み、負荷が高い状態が続いた時があったので、そのときにインデックスが変になってしまったのかもしれません。
画像品質評価のPSNR, SSIMの実装と速度比較

# 背景

```python
from skimage.measure import compare_ssim, compare_psnr
```

をすると
`compare_ssim`と`compare_psnr`でSSIMとPSNRの評価ができる。
速度比較がしたい。

# 速度比較
```python
from skimage.measure import compare_ssim, compare_psnr
import cv2
import time

def measurement(func, **kwargs):
    start = time.time()
    val = func(kwargs["img1"], kwargs["img2"])
    end = time.time()
    return val, end-start

img1 = cv2.imread("sample1.png", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("sample2.png", cv2.IMREAD_GRAYSCALE)
print("ssim: %f, time: %lf[sec]" % measurement(compare_ssim, img1=img1, img2=img2))
print("psnr: %f, time: %lf[sec]" % measurement(compare_psnr, img1=img1, img2=img2))

# => ssim: 0.974289, time: 0.806180[sec]
# => psnr: 21.250949, time: 0.053643[sec]
```

# 結論
わかってはいたけどPSNRの方がめっちゃ早い。(15倍ぐらい)

# おまけ
画像間の同じ座標のピクセルと値との差の合計`pixel_diff`との比較をしてみる。

```python
from skimage.measure import compare_ssim, compare_psnr
import cv2
import time
import numpy as np

def pixel_diff(img1, img2):
    return np.sum(np.absolute(img1 - img2))

def measurement(func, **kwargs):
    start = time.time()
    val = func(kwargs["img1"], kwargs["img2"])
    end = time.time()
    return val, end-start

img1 = cv2.imread("sample1.png", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("sample2.png", cv2.IMREAD_GRAYSCALE)
print("ssim: %f, time: %lf[sec]" % measurement(compare_ssim, img1=img1, img2=img2))
print("psnr: %f, time: %lf[sec]" % measurement(compare_psnr, img1=img1, img2=img2))
print("pixel_diff: %f, time: %lf[sec]" % measurement(compare_psnr, img1=img1, img2=img2))

# => ssim: 0.996097, time: 0.734509[sec]
# => psnr: 29.721666, time: 0.046622[sec]
# => pixel_diff: 29.721666, time: 0.045121[sec]
```

# 参考
- [Module: measure — skimage v0.15.dev0 docs](http://scikit-image.org/docs/dev/api/skimage.measure.html)
- [ピーク信号対雑音比 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%94%E3%83%BC%E3%82%AF%E4%BF%A1%E5%8F%B7%E5%AF%BE%E9%9B%91%E9%9F%B3%E6%AF%94)
- [Structural similarity - Wikipedia](https://en.wikipedia.org/wiki/Structural_similarity)
Macでelectronアプリのexe版をdockerを使ってビルドする

## 概要
electron+vue+sqliteでmac向けデスクトップアプリを作ったが、それのwin版をmacでビルドしようとしたら色々ハマったのでそのメモ

## 調査/下準備
[こちら](https://qiita.com/kimura_m_29/items/ee929cbd08daf744bffc)の記事によるとwin版をmacでビルドするためにはwineをインストールする必要があるらしい。
しかし、昔macにwineを入れたらぐちゃぐちゃになった思い出があって、できれば環境を汚さずにwineを入れたいので今回はdockerを使うことにした。

docker hubに[misterpaladin/docker-wine](https://hub.docker.com/r/misterpaladin/docker-wine/~/dockerfile/)というリポジトリがあるが、うまく動かなかったので[node](https://hub.docker.com/_/node/)リポジトリからwineをインストールするDockerfileを用意することにする。

また、今回はdocker-composeを使う。
(普通にdocker buildしてからコンテナを立ち上げてもできるけど、docker-compose使った方がビルド、マウント、実行を一括にできるため)

electronのバージョンやicoファイルはあらかじめ用意しておく。

## 手順
1. 以下のファイル構成にする

    ```
    .
    ├── Dockerfile
    ├── app
    ├── build
    ├── docker-compose.yml
    ├── icon
    ├── node_modules
    ├── package-lock.json
    ├── package.json
    └── readme.md
    ```

2. Dockerfileに下記を記述

    ```Dockerfile:Dockerfile
    FROM node

    RUN dpkg --add-architecture i386 && \
      apt update && \
      apt install -y wine && \
      apt install -y wine32 && \
      npm i -g electron-packager

    WORKDIR /home

    CMD [ "electron-packager",".","app-name","--name=app-name","--platform=win32","--arch=x64","--electronVersion=2.0.5","--out=build","--overwrite","--icon=icon/icon.ico"]
    ```
    CMDを一行で書かなきゃいけないのは見栄えが悪くてツライですね。。


3. docker-compose.ymlに下記を記述

    ```yml:docker-compose.yml
    version: "2"
    services:
      electron-packager:
        build: .
        volumes:
         - .:/home
    ```

4. `docker-compose up`を実行

これでbuild/app-nameにたくさんのファイルとexeファイルができる。

## 最後に
electronってクロスプラットフォームのデスクトップアプリが簡単にできるものだと思っていたら色々ハマりポイントがありましたね。。

まあweb+nodeで簡単にmacアプリ作れるってだけでありがたいですが。

これの他にもelectron+vue+sqliteという組み合わせで色々ハマったので、そのうち記事が書ければ

## 参考
- [Mac環境でElectronのWindows用パッケージングをしたら大変だった話 - Qiita](https://qiita.com/kimura_m_29/items/ee929cbd08daf744bffc)
- [fr/Wine - Debian Wiki](https://wiki.debian.org/fr/Wine)
clasp logs でログを確認する。2018-09-26

# 概要
[`clasp run` しても `Logger.log` の内容は表示されませんでした](https://qiita.com/abetomo/items/59379e26679e342ef6e3#%E5%AE%9F%E8%A1%8C%E7%B5%90%E6%9E%9C%E4%BE%8B)
ログを確認したいときは `clasp logs` で確認します。

その方法を記します。

# ポイント
**`clasp logs` でも `Logger.log` の内容は確認できないようです**
`clasp logs` でログを確認したいときは、 `console.log` でログを書き出します

# `clasp logs`
## 実行結果例 `console.log`:
GASで `console.log('hoge');` と書いた場合の例です

```
% clasp logs
...
DEBUG      2018-09-26T07:43:37.382Z <FUNCTION_NAME> hoge
...
```

## 実行結果例 エラー:
例外が起きた場合のエラーログも確認できます

```
% clasp logs
...
ERROR      2018-09-26T02:00:58.400Z <FUNCTION_NAME> {"context":{"reportLocation":{"functionName":...（略）
...
```

# まとめ
`clasp logs` でGASの実行ログを確認できました
Firebase Crashlytics を Xcode10 で使う場合は Input Files を設定する

Firebaseのドキュメントに下記の記載がありました。

>
Xcode 10 only: Add your app's built Info.plist location to the Build Phase's Input Files field:
`$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)`

https://firebase.google.com/docs/crashlytics/get-started
Excelのファイルからマクロで.sqlファイルを生成する

よくある「このリストのメンバー全員登録しておいて」という依頼に対応するためのノウハウです。

こんなExcelファイルをDBに登録する必要がある、としましょう。

| 社員番号          | メールアドレス       | 名前               |
|:-----------------|:------------------|:------------------|
| 1             | hoge@example.com | 太郎        |
| 2             | fuga@example.com | 次郎        |
| 3             | piyo@example.com | 花子        |

いきなりソースです。
ソースを作ったらExcelのマクロにペーストして実行します。

```vba:hoge
Sub createInsertSQLFile()
Dim workSheet As Worksheet
Set workSheet = ThisWorkbook.Worksheets(1)

Dim dataFile As String
dataFile = "hoge.sql"

Open dataFile For Output As #1

Dim i As Long
i = 2
Do While workSheet.Cells(i, 2).Value <> ""
    Print #1, "INSERT INTO shain(email,emproyee_no,name) VALUES('" & workSheet.Cells(i, 2).Value & "','" & workSheet.Cells(i, 1).Value & "','" & workSheet.Cells(i, 3).Value & "');"
    i = i + 1
Loop

Close #1

MsgBox "完了しました。"

End Sub
```

# 複数のテーブルに跨る場合
※社員の趣味を格納しておくDBなんて聞いたことありませんが気にしないでください。

| 社員番号          | メールアドレス       | 名前               |趣味               |
|:-----------------|:------------------|:------------------|:------------------|
| 1             | hoge@example.com | 太郎        |ゲーム,読書        |
| 2             | fuga@example.com | 次郎        |ゲーム,食べ歩き        |
| 3             | piyo@example.com | 花子        |食べ歩き,ダンス        |

hobbyIdは既にDBに登録済みでそのIDも調査済みであることが前提です。

```vba:fuga
Sub createInsertHobbySQLFile()
Dim workSheet As Worksheet
Set workSheet = ThisWorkbook.Worksheets(1)

Dim dataFile As String
dataFile = "fuga.sql"

Open dataFile For Output As #1

Dim i As Long
i = 2
Do While workSheet.Cells(i, 2).Value <> ""
    Dim hobbyNames As Variant
    hobbyNames = Split(workSheet.Cells(i, 4).Value, ",")

    Dim j As Long
    For j = LBound(hobbyNames) To UBound(hobbyNames)
        Dim hobbyId As Long
        If hobbyNames(j) = "ゲーム" Then
            hobbyId = 5
        ElseIf hobbyNames(j) = "読書" Then
            hobbyId = 6
        ElseIf hobbyNames(j) = "食べ歩き" Then
            hobbyId = 7
        ElseIf hobbyNames(j) = "ダンス" Then
            hobbyId = 8
        Else
            hobbyId = 999
        End If

        Print #1, "INSERT INTO hobbies(shain_id, hobby_id) SELECT id, " & CStr(hobbyId) & " FROM shain WHERE email='" & workSheet.Cells(i, 2).Value & "';"
    Next j
    
    i = i + 1
Loop

Close #1

MsgBox "完了しました。"

End Sub
```

# エラーになる場合
- 文字コードを確認。上記のコードだとShift-jisで保存されてしまうため日本語が含まれているとエラーになる場合があります。Atom等でUTF-8に変換して保存しなおせばいけます。

# 参考
私よりしっかり書いてある例が出ていました・・・
https://utage.headwaters.co.jp/blog/?p=2954
macOS Mojave にアップデートしたら stdio.h がないって言われた

macOS を Mojave (10.14) にアップデートして、C 拡張つきの gem をコンパイルしようとしたら `stdio.h` がないよってエラーがでた。

いろいろ調べたら、Xcode 10 から、デフォルトでは /usr/include にヘッダファイルを置いてくれないらしい。

- [Missing /usr/include w/ Xcode 10 |Apple Developer Forums](https://forums.developer.apple.com/thread/104296)

`/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg` を実行すると `/usr/include` にコピーしてくれるのでこれで解決した。
ComposerをProxy環境下で使えるようにする

# Composerをインストール
[Composerのサイト](https://getcomposer.org/download/)からダウンロードする。
今回はインストーラを使わないので`Manual Download`から`composer.phar`最新版を取得して、ダウンロードした`composer.phar`を`D:\php-7.2.10\`に配置する。

# 環境変数を設定するバッチを作成
`D:\php-7.2.10\comporser.bat`を配置する。

```:composer.bat
@ECHO OFF
set PATH=D:\php-7.2.10
set TEMP=D:\php-7.2.10\temp
set COMPOSER_HOME=D:\php-7.2.10
set HTTP_PROXY=http://<user>:<password>@<proxy>:<port>/
set HTTPS_PROXY=%HTTP_PROXY%
set HTTP_PROXY_REQUEST_FULLURI=0
set HTTPS_PROXY_REQUEST_FULLURI=%HTTP_PROXY_REQUEST_FULLURI%
setlocal DISABLEDELAYEDEXPANSION
%PATH%\php "%COMPOSER_HOME%\composer.phar" %*

```

# コマンドラインからComposerを実行

```
D:\php-7.2.10\composer.bat --version
Composer version 1.7.2 2018-08-01 12:00:00
```
Composerのバージョンが表示されれば完了！
ファイルの存在有無でプロパティを変えたい

formボタンのenable/disable制御を、CGIなどは使わずjavascriptだけで、サーバ側ファイルの有無で切り替えたかった。ので、以下のように実装。

```javascript
var url = window.location.origin;
var url1 = url + "/hoge";
var xhr = new XMLHttpRequest();
xhr.open("GET", url1, false);
xhr.setRequestHeader('Pragma', 'no-cache');
xhr.setRequestHeader('Cache-Control', 'no-cache');
xhr.send(null);
if (xhr.status == 200) {
    document.getElementById("bar").disabled = true;
}
```

XMLHttpRequestについては、
https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest
を参照。以下は注意事項。

- open()のasyncにfalseはホントは非推奨
- setRequestHeader()はopen()の後、send()の前に呼び出す
- ↑でcacheを無効にしてあげないと、おかしいなぁってことになりがち

キャッシュの無効化はブラウザ依存。firefoxのみで確認。
Dockerを使ってPerl製Webアプリケーションを動かしてみる

# はじめに
perlを使った開発に本格的に取り組むことになりそうだったので理解するためにまずはWebアプリケーションを作ってみる。
今回のゴールとしてはリクエストを受けてレスポンスを正常に返すところまでとする。

# Dockerfileの用意

```dockerfile
FROM perl:5.18

WORKDIR /srv/sources

RUN cpanm Server::Starter
RUN cpanm HTTP::Router
RUN cpanm Plack                                                                                                                                                                                                                                                                                                           
RUN cpanm Gazelle
```

本当はcartonを使ってモジュール管理をするのがいいみたいだけども今回はとりあえず一つずつ必要なモジュールをインストールする。
一つのRUNにまとめても良かったが必要になったタイミングでコマンド追加という風にやっていたせいで、都度ビルドを行うと全てのインストールが再度行われて時間がかかりすぎるため、コマンドを分割することにした。

以下、使用するモジュールの用途について。

## Server::Starter
プロセスのHot deployに対応するためのモジュール。
詳しい内容については[こちらの記事](https://blog.shibayu36.org/entry/2012/05/07/201556)で紹介されている。

## HTTP::Router
ルーティングを行うためのモジュール。

## Plack
PSGIサーバモジュール。
PSGIについては[こちらの記事](https://gihyo.jp/dev/serial/01/perl-hackers-hub/000101)を読むといいかもしれない。
これでリクエストの処理やレスポンスの構築などを行う。

## Gazelle
高速なアプリケーションサーバモジュール。
Gazelleについては[こちらの記事](https://qiita.com/kazeburo/items/7fcb19d9319adc599694)で紹介されているのでこちらを参照するといい。

# docker-compose

```docker-compose.yml
version: '3'
services:
  app:
    build: ./docker
    ports:
      - 8080:80
    volumes:
      - ./:/srv/sources
    command: ["start_server", "--port", "80", "--", "plackup", "-I", "src/", "-s", "Gazelle", "-E", "development", "app.psgi"]         
```

アプリケーションのdockerへのマウントはdocker-compose側で行う。（その方が楽だったので）

# app.psgi

```app.psgi
use strict;
use warnings;
use utf8;

use Plack::Request;
use Plack::Response;
use Data::Dumper;
use HTTP::Router::Declare;
 
use API;                                                                                                                                                                                                                                                                                                                  
 
my $router = router {
  match '/', { method => 'GET' }, to { app => \&API::top }
};

sub dispatch {
  my ($req) = @_;
  my $match = $router->match($req) or return $req->new_response(404)->finalize;
  return $match->params->{ app }($req, $match)->finalize;
}

my $app = sub {
  my $req = Plack::Request->new(shift);
  my $r = eval { dispatch($req) };
  my $errstr = $@ or return $r;

  warn $errstr;

  my $res = $req->new_response(503);
  $res->content_type('text/html');
  $res->body('Error');

  return $res->finalize;
};
```

エントリーポイントのファイル。
実処理を書くと無駄に長くなるのでそれは別ファイルに分離。

# APIモジュール
```API.pm
package API;

use strict;
use warnings;
use utf8;

sub top {
  my ($req) = @_;

  my $res = $req->new_response(200);
  $res->content_type('text/html');
  $res->body('Hello');

  return $res;
}

1;      
```

実処理を記述するファイル。
今回は単純にHelloを返すだけにする。

# 戸惑った点

## 開発環境の用意
今まで、PHPやJSぐらいしか書いてこなかったため、エディタや強力なIDEがある環境でやってきたのだけど、いざperlを書こうとした時に良さげなエディタを見つけられずvimで書くことにした。
今までvimも単純にコピペぐらいでしか使っていなかったため、なかなか慣れずに一連のファイルを作るだけでも意外と苦労した。

## モジュールのインストール
composerやnpmなんかは配布されているモジュールをインストールするだけなのだが、今回はインストール時にモジュールのテストも行うため、インストールに非常に時間がかかった。
testを無効にできると知ったのは後の祭り。
Spirng  MVCのプロジェクトインポートで、ビルド失敗"error in opening zip file"(Eclipse 4.7.1)

 :leaves:Spirngプロジェクト雛形作成のエラー解消  https://start.spring.io/:leaves:


* 解決法
  * Spring bootのバージョンを下げて、雛形作成
  * ローカルのgradleのバージョンを確認する

　

##***環境***
***失敗***

| ソフトウェア | Version| 
|:-----------|------------:|
| Eclipse       | Oxygen (4.7.1)      | 
| gradle     |2.2.1    | 
| Java    |    1.8.0_151      | 
| Spring Boot    |   2.1.0 M4       | 

***成功***

| ソフトウェア | Version| 
|:-----------|------------:|
| Eclipse       | Oxygen (4.7.1)      | 
| gradle    |2.2.1    | 
| Java    |    1.8.0_151      | 
| Spring Boot    |   1.5.16       | 

##**エラー内容**
https://start.spring.io/
にてSpring MVCの雛形ダウンロード(依存関係は「Web」、[Thymeleaf])
Eclipse起動後
「Gradle STS」でプロジェクトを、「Build Model」押下時に、エラーが表示される

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198177/99da91fa-4d36-7282-76cf-b987a0110501.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198177/14aff85e-89a9-fe62-7492-64b3ede7c977.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/198177/83a7e40a-fcc5-53f1-a516-0e658c822701.png)