OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonで配列や行列の結合

## 配列の結合

配列を結合するときに、appendとextendが使える。
これらは、それぞれ結果が異なる。

```python:unite_list_1.py

a = [1,2,3]
b = [4, 5]

# appendで要素を結合
a1 = a
a1.append(4)
print(a1) # [1, 2, 3, 4]

# appendで配列を結合すると、結合した配列が入れ子になる
a1 = a
a1.append(b)
print(a1) # [1, 2, 3, [4, 5]] 

# extendなら、配列が入れ子にならない
a1 = a
a1.extend(b)
print(a1) # [1, 2, 3, 4, 5]

```


2次元配列を結合したときの結果

```python:unite_list_2.py
a=[[1,2,3],[4,5,6]]
b=[[7,8],[9,10]]

#appendで配列を結合すると、やっぱり入れ子になる
a1 = a
a1.append(b)
print(a1) # [[1, 2, 3], [4, 5, 6], [[7, 8], [9, 10]]]

#extendで結合すると、入れ子にならない
a1 = a
a1.extend(b)
print(a1) # [[1, 2, 3], [4, 5, 6], [7, 8], [9, 10]]

```

## 行列の結合

配列の結合はできたものの、行列の結合のような操作は少し面倒になる。

```python:unite_list_3.py
a=[[1,2,3],[4,5,6]]
b=[[7,8],[9,10]]
a1 = a

for i in range(2):
    a1[i].extend(b[i])

print(a1) # [[1, 2, 3, 7, 8], [4, 5, 6, 9, 10]]
```

そこで、Numpyを使うと簡単にできる。たとえば、行列を列を増やす方向に結合の場合:

```python:numpy_1.py
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
b = np.array([[7,8],[9,10]])

c = np.concatenate((a,b), axis = 1) 
print(c)

#または

c = np.c_[a,b]
print(c)

#または

c = np.hstack([a,b])
print(c)

# 結果:
#  [[ 1  2  3  7  8]
#  [ 4  5  6  9 10]]

```

行を増やす方向の結合:

```python:numpy_1.py
import numpy as np
a = np.array([[1,2,3],[4,5,6]])
b = np.array([[7,8],[9,10]])

c = np.concatenate((a.T,b), axis = 0) 
print(c)

#または

c = np.r_[a.T,b]
print(c)

#または

c = np.vstack([a.T,b])
print(c)

# 結果:
# [[ 1  4]
#  [ 2  5]
#  [ 3  6]
#  [ 7  8]
#  [ 9 10]]

```

Numpyを使う場合でも、行数、列数が合っていないとエラーになるので注意は必要。

## 環境

Windows10 64bit
Python 3.6.4
Conda 4.4.11 (Anaconda 3)


## 参照

[Numpyで行列の連結](https://qiita.com/sotetsuk/items/d0e73afdcffdc8ac3e6b)
CentOS7でownCloudをインストールした


#目的
CentOS7でownCloud10系を動かす。
なおMySQL(mariadb)は別サーバにインストールをしてあるので、クライアントのみインストールを行う。


##ハマったところ
CentOS7のphpは5.4なので、このバージョンではownCloud 10系をインストールしても動作しない。ownCloud 10の要件を満たしていないからだ。ちなみに、php7系をインストールしてもownCloudの画面でエラーが出た。今回のownCloudは自分一人で使うので、phpが遅くてもいいので、5.6をインストールした。

そのため、remiからphp5.6をインストールした。
試行錯誤の結果、以下のパッケージをremiからインストールを行った。

```
php56-php-common-5.6.34-1.el7.remi.x86_64
php56-php-xml-5.6.34-1.el7.remi.x86_64
php56-php-pdo-5.6.34-1.el7.remi.x86_64
php56-php-gd-5.6.34-1.el7.remi.x86_64
php56-runtime-2.3-1.el7.remi.x86_64
php56-php-pecl-jsonc-1.3.10-1.el7.remi.x86_64
php56-php-pecl-zip-1.15.2-1.el7.remi.x86_64
php56-php-process-5.6.34-1.el7.remi.x86_64
php56-php-pear-1.10.5-5.el7.remi.noarch
php56-php-mbstring-5.6.34-1.el7.remi.x86_64
php56-php-cli-5.6.34-1.el7.remi.x86_64
php56-php-5.6.34-1.el7.remi.x86_64
php56-php-intl-5.6.34-1.el7.remi.x86_64
php56-php-mysqlnd-5.6.34-1.el7.remi.x86_64
```

##epelリポジトリの登録方法は以下の通り

```
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
```

これで問題なく動作をした。
Haskell Stack + HSpecで特定のモジュールのテストだけ実行


`Module0Spec`だけ実行したいときです。

```bash
stack test --test-arguments "-m Module0"
```

## 参考
* [haskell - Select which test to run with Hspec and stack - Stack Overflow](https://stackoverflow.com/a/39365910/2885946)
PyMieScatt > LowFrequencyMieQ() > Equation of Qsca

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
gnustep-gui-runtime v0.24.0-3.1
```

### 関連

- [PyMieScatt > LowFrequencyMieQ() > for small size parameter](https://qiita.com/7of9/items/eef138257744e0442c2f)
- [PyMieScatt > LowFrequencyMieQ() > Equation of Qext | 新人応援 > １次情報と実装の乖離](https://qiita.com/7of9/items/c612d72bd5b17b426916)

### Reference

- Bohren C.F. and D. R. Huffman, "Absorption and Scattering of Light by Small Particles", John Wiley, New York, NY (1983)
- PDF: [MATLAB Functions for Mie Scattering and Absorption, Research Report No. 2002-08, June 2002](https://omlc.org/software/mie/maetzlermie/Maetzler2002.pdf) by Christian Mätzler

### Equation of Qsca

http://pymiescatt.readthedocs.io/en/latest/forward.html#LowFrequencyMieQ
https://github.com/bsumlin/PyMieScatt/blob/master/PyMieScatt/Mie.py#L175

LowFrequencyMieQ()のQscaの実装を式に起こすと以下となる。

```math
Q_{sca} = \frac{2}{x^2}\sum(2n+1)\{|a_n|^2 + |b_n|^2\}
```

この式はどこから来たのか?

Bohren and Huffman (1983)
p103

```math
C_{sca} = \frac{W_s}{I_i} = \frac{2\pi}{k^2}\sum_{n=1}^{\infty}(2n+1)(|a_n|^2 + |b_n|^2) ... (4.61)
```

Efficiency QとCross section Cには以下の関係式がある。

```math
Q_{sca} = \frac{C_{sca}}{\pi a^2} ... (1)
```

ここで、aは粒子の半径。

Eq.(4.61)とEq.(1)より

```math
Q_{sca} = \frac{2}{k^2 a^2}\sum_{n=1}^{\infty}(2n+1)(|a_n|^2 + |b_n|^2) ... (2)
```

size parameter Xは以下として定義される (Bohren and Huffman(1983) p100 (Eq. 4.51の下の式)。

```math
x = ka = \frac{2\pi Na}{\lambda} ... (3)
```

Eq. (2)と Eq.(3)より

```math
Q_{sca} = \frac{2}{x^2}\sum(2n+1)\{|a_n|^2 + |b_n|^2\}
```

導出完了。
Java 10 (JDK 10) が2018年3月20日にリリースされたので Hello World してみる

## macOS Sierra に Java SE Development Kit 10 をインストール

[Java SE Development Kit 10\- \- Downloads](http://www.oracle.com/technetwork/java/javase/downloads/jdk10-downloads-4416644.html) から macOS 用 JDK のインストーラ jdk-10_osx-x64_bin.dmg をダウンロード。

![java10_01.png](https://qiita-image-store.s3.amazonaws.com/0/139365/cea09b12-72e0-4ad8-b355-9d6ab1ee6e61.png)

jdk-10_osx-x64_bin.dmg をオープン。
ダブルクリックしてインストール。

![java10_02.png](https://qiita-image-store.s3.amazonaws.com/0/139365/16321a27-e72e-26f7-e55c-1018a1f2121c.png)

700MB以上の空き容量が必要。

![java10_03.png](https://qiita-image-store.s3.amazonaws.com/0/139365/a558ba3f-1118-7563-da92-db258a511467.png)

無事にインストールできたことを確認。

```
$ java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)

$ javac -version
javac 10
```

## Hello World してみる

Java 10 で導入されたらしい型推論 ([JEP 286: Local\-Variable Type Inference](http://openjdk.java.net/jeps/286)) なるものを使うべく、サンプルコード HelloWorld.java を用意。String 型が入るとわかっている変数 message に var を付けて宣言する。

```
public class HelloWorld {

  public static void main(String[] args) {
    var message = args[0];
    System.out.println(message);
  }
}
```

コンパイル。

```
$ javac HelloWorld.java 
```

実行。ちゃんと想定通りの動きをしてくれた。

```
$ java HelloWorld "hello, world"
hello, world
```

## 参考資料

- [JDK 10 Documentation](https://docs.oracle.com/javase/10/)
- [Java SE Development Kit 10\- \- Downloads](http://www.oracle.com/technetwork/java/javase/downloads/jdk10-downloads-4416644.html)
- [Java 10が本日付で正式リリース。ローカル変数の型推論、ガベージコレクタが入れ替え可能、不揮発性メモリ対応など。Java 9は早くもサポート期間終了 － Publickey](http://www.publickey1.jp/blog/18/java_10java_9.html)
- [Java 10新機能まとめ \- Qiita](https://qiita.com/nowokay/items/d9bc4b3f715d17c2830d)
- [JEP 286: Local\-Variable Type Inference](http://openjdk.java.net/jeps/286)
C# でマルチスレッドの実装をするなら知っておくべきこと（メモ）

C# でマルチスレッドの実装を行ってみて、ハマったことや最初に知っておきたかったことのメモ。

1. マルチスレッドの実装で気づいたこと
====================

## 1-1. スレッドの数の上限

Task.Run で同時に動くスレッドの数に限りがあり、限界に達するとタスクが空くのを待つことになる。

限界数は下記で確認可能:

```c#
ThreadPool.GetMaxThreads(out int workerThreads, out int portThreads);
Console.WriteLine("Worker threads={0}, Completion port threads={1}", workerThreads, portThreads)
```

上限数は下記で引き揚げ可能:

```c#
ThreadPool.SetMaxThreads(20, 20);
```


## 1-2. async/await を使うべき

できれば `Task.Run` は `async` / `await` とともに使うべき。
そのほうが CPU を効率よく使うように書きやすい。


## 1-3. 無限ループには終了条件を

Task.Run で無限ループするなら、終了フラグ見て終了する仕組み必須。
これがないと、単体テストの際にもスレッドが終わらずに困るし、システム終了時にも常に強制終了させることになる。


## 1-4. Sleep の代わりに Task.Delay

`Thread.Sleep(500)` のかわりに `await Task.Delay(500)` をつかうべき。


## 1-5. Task.Run の前後にログを

`Task.Run` の前後にログ出力があったほうがいい。
万一、本番で待たされる事態が発生したときにログから追いかけられる。


2. UnitTest(MsTest) の実装で気づいたこと
====================

## 2-1. テストでの無限ループの扱い

Task.Run で無限ループしていると、テストTask終了時ににそのTask（スレッド）が終わらないため（終わらないけどテストは終了するため）、複数テストを走らせた場合のみ、すぐにスレッドプールの上限に達してしまい、著しくテスト速度が劣化するという現象が発生する。
無限ループ部分はモックしてテストでは動かないようにするか、終了フラグなどで無限ループが終了する仕組みが必要。


## 2-2. テストは並列実行される

`static` フィールドなど、テスト間で共有する領域に書き込んでいるなら、テストが並列実行されないようにロックを使った配慮が必要。

例:

```C#
using System.Threading;

public class TestsSynchronization
{
    private static readonly object lockObject = new object();

    public static void Lock()
    {
        //テストが同時に走らないためにロックを使う
        Monitor.Enter(lockObject);
        Console.WriteLine("----- Lock Start");
    }

    public static void Unlock()
    {
        //テストが同時に走らないためのロック解放
        Monitor.Exit(lockObject);
        Console.WriteLine("----- Lock End");
    }
}

[TestClass]
public class MainTests
{
    private static readonly object _lock = new object();

    [TestInitialize]
    public void TestInitialize()
    {
        TestsSynchronization.Lock();
    }

    [TestCleanup]
    public void Cleanup()
    {
        TestsSynchronization.Unlock();
    }
```


## 2-3. 書き込み可能な static フィールド

`static` フィールドはテストが終了後も書き換え後の値が残っていることに注意。
必ずテスト実行時に値が初期化されるようでなければならない。



## 2-2. virtual を使う

メソッドの宣言で `virtual` にしてないと `override` できないため、そのメソッドをモックにできない。
そうなると、そのメソッドの中身を含めてテストを書かなければならず、本来テストしたいところと、そうじゃないところが混ざり込み、テストの記述が複雑になってしまう。
依存関係がテストに現れてしまう。

依存を切るために `public` や `protected` なメソッドは基本 `virtual` にしておいたほうがいい。
[実験] JavaScriptのデフォルトのDateオブジェクトをハックする [考察]

# TL;TD;
JavaScriptのデフォルトのDateオブジェクトは月が0$\sim$11で使いにくいのでES2015から導入されたclassの継承を使ってハックする。

# JavaScriptによるclassの継承
classの継承を使うことで、prototypeを拡張することなくデフォルトのDateオブジェクトをハックする。

```js:modDate.js
module.exports=class extends Date{
    constructor(...args){
        if( args.length<2 ) super(...args);
        else{
            const year=args.shift();
            const month=args.shift()-1;
            super( year, month, ...args);
        }
    }

    getYear(){ return super.getFullYear(); }

    setMonth(month){ super.setMonth(month-1); }
    getMonth(month){ return super.getMonth()+1; }
}
```
Nodeで`module.exports`で名前をつけずexportした。ブラウザ用なら`exports default`である。
月をセットするセッターとコンストラクタは1を引いてデフォルトを呼ぶ。
特にコンストラクターは[rest parameters](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope/rest_parameters)を用いて文字列、[エポック秒](https://ja.wikipedia.org/wiki/UNIX%E6%99%82%E9%96%93)を用いたコンストラクタはデフォルトのコンストラクタにそのまま渡し。月が関わるものだけ、[配列のshift](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)を使って月まで取り出して**残り**はデフォルトのコンストラクタに渡している。
ゲッターは1を足して返すようにしている。
[getYear](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/getYear)は非推奨であり2018=>118というややこしい値を返すので内部で`getFullYear`を返すようにした(同じくsetYearもハックするべきかもしれない)。

# 検証用コード
ここでは同じ名前のDateがブロックスコープを変えることで共存できることも検証したが安全性としては問題が残るので実際に使う場合はより安全な名付けとルール作りが必要である。

```js:testModDate.js
{
    console.log('===== modified Date Object Test START =====');
    const Date=require('modDate');

    const date=new Date();
    console.log(date);
    console.log(date.getYear());

    const monthArr=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ];
    for( const month of monthArr ){
        console.log("Month =", month);
        date.setMonth(month);
        console.log(date);
        console.log("date.getMonth()=", date.getMonth());
        const date2=new Date(1000, month, 10);
        console.log(date2);
    }

    console.log('===== modified Date Object Test FINISH =====');
}

console.log('===== default Date Object Test START =====');
const date=new Date();
console.log(date);
console.log(date.getYear());

const monthArr=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ];
for( const month of monthArr ){
    console.log("Month =", month);
    date.setMonth(month);
    console.log(date);
    console.log("date.getMonth()=", date.getMonth());
}

console.log('===== default Date Object Test FINISH =====');
```

modDateファイルをDateで受けることによりあたかもDateのように使うことができる。また、constなので影響範囲はブロックスコープに限られるので外ではデフォルトのDateとして使える。

# まとめ
classのextends(継承)を使うことで影響範囲を限った形で既存のインスタンスをハックできる。
rest parametersを用いることで様々な値を受けられるコンストラクター(関数)にも簡単に対応できる。
影響範囲が限られているのでガンガン書き換えても問題は大きくならないので例えばgetDayあたりを`日、月、火、....`とかにするのもアリだろうし。toStringをより読みやすい形に変えるなどもできそうである。

### コメントを受けて
`getDay`は`getDayJa`もしくは`getDayStringJa`にするべきだと思う。あえて`getYoubi`とかでもいいかも
`toString`はあえて名前つけルールを標準からずらして`string`もしくは`forLog`とかがありだと思います。
ある場所に入ったらタイムトラッキングサービスtogglのタイマーをスタートする方法

# 概要
- MESHとIFTTTとtogglを使って外出時間をモニターしてみた。
- IFTTT的には、"Start toggl if you enter an area"

# 背景
- togglの時間管理がめんどくさいので、家でたとか、会社ついたってとこだけでも、勝手になんとかしてもらいたい。
- IFTTTにtogglがない。
- MESHにtogglがないけど、APIはたたける
- MESHに位置タグがない

# 作ったもの
- MESHにIFTTTで作ったLocationタグを追加
- MESHにMESH SDKで作ったtoggl APIをたたくタグを追加
（[MESH動きタグとtogglで時間管理 - Qiita](https://qiita.com/iton/items/30a517eae3da41d58023)）
- MESHである位置に入ったらtogglのタイマーをスタートするレシピを追加

# 作る過程
レシピはこんな感じ。
Trigger MESH if you enter an areaとTrigger MESH if you exit an areaを
それぞれ、
start togglとstop togglにつなぐ
<img width="375" alt="IMG_0624.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/184221/4b69d857-1928-9f59-1638-cabbb516fd03.png">

IFTTTでの、MESHの設定はこんな感じ。いろいろある。
MESHアプリの下のほうにでてくるタグの部分で、「連携タグ」の「追加」をタップして、進んでけば追加できる。Locationの他にも、LINEとかGoogle DriveとかEvernoteとかGoogle AssistantとかAmazon Alexaとかある。楽しげ。
<img width="375" alt="IMG_0623.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/184221/ffb3e1b8-a3dc-a63d-0a05-cdb93c6079ed.png">

IFTTTでの、MESHの設定はこんな感じ。Locate an areaを自分ちとかにする
<img width="375" alt="IMG_0619.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/184221/7e2307a1-e214-9857-d0c6-c4c0a041f6e2.png">

以上。簡単。

# 所感
- IFTTTだけで十分なときも、MESHだけで十分なときも多いけど、組み合わせることで、設計の幅がひろがる。
- Locationタグって、デバッグめんどくさい。まあまあ移動しないとトリガーかけられない。
- ただ、スマホを閉じてる状態でちゃんと動いているか、あやしい。他のアプリがメモリ使って、いつの間にかバックグラウンドでの動作が止まって、動作しないってことが起きてそう。
Python2のConfigParserで読み込んだ設定ファイルの内容を辞書型で扱えるようにする

以下のようなINIファイル形式の設定ファイルがあったとします。

```INI
[Section1]
foo=bar
```

Python3のconfigparserモジュールでは読み込んだINIファイルを辞書型で扱えます。

```Python
import configparser
config = configparser.ConfigParser()
print(config["Section1"]["foo"]) #-> "bar"

```

Python2のConfigParserモジュールでは辞書型でのアクセスが用意されておらず、Python3のconfigparserモジュールと同様の事をしようとするとエラーになります。
Python2のConfigParserモジュールではINIファイルの内容を取得するには``ConfigParser.get()``メソッドを使います。

```Python
import ConfigParser
config = Configparser.ConfigParser()
print(config["Section1"]["foo"]) #-> AttributeError!!!
print(config.get("Section1", "foo")) #-> "bar"

```

しかし、辞書型で扱えたほうが便利な事が多々あります。ConfigParserクラスにはセクションの一覧を取得するメソッド``ConfigParser.sections()``と、指定したセクションのそれぞれのオプションの``(name, value)``のペアのリストを取得する``ConfigParser.items()``があるので、これらを使用してひと手間加えることで辞書型での取得が可能になります。

```Python
import ConfigParser
config = Configparser.ConfigParser()
config_dict = {s: {i[0]: i[1] for i in config.items(s)}
               for s in config.sections()}
print(config_dict["Section1"]["foo"]) #-> "bar"
```
フラグを用いたテクニカルなUU集計

## 概要
* DMT用SQLで謎な書き方があった。 
* よくよく考えてみると理にかなっている書き方だった。 
* レコード数削減のためtimestampで格納しているlogテーブルをuser_id単位からsegment単位にしてテーブル作成。
* そのときsegment単位にしているため、毎時or 毎分でのUUがCOUNT(DISTINCT user_id)で求めれないところを、別のやり方でUU算出を可能にしている。

## 謎SQL
テーブルtbl1の中身はlogテーブルで以下のような感じだとする(ユーザーは複数セグメントに割り振られている)。

| user_id | segment | log_time |  log_date | log_hh | log_mm |  
|:-----------|:-----------|:-----------|:-----------|:-----------|:-----------| 
| 100 | 10代 | 2018-03-01 00:01:00 | 2018-03-01 | 00 | 01 | 
| 100 | 10代 | 2018-03-01 00:01:01 | 2018-03-01 | 00 | 01 | 
| 100 | 男性| 2018-03-01 00:01:00 | 2018-03-01 | 00 | 01 | 
| 100 | 男性 | 2018-03-01 00:01:01 | 2018-03-01 | 00 | 01 | 
| 101 | 10代 | 2018-03-01 00:01:00 | 2018-03-01 | 00 | 01 | 
| 101 | 10代 | 2018-03-01 00:01:01 | 2018-03-01 | 00 | 01 | 
| 101 | 男性 | 2018-03-01 00:01:00 | 2018-03-01 | 00 | 01 | 
| 101 | 男性 | 2018-03-01 00:01:01 | 2018-03-01 | 00 | 01 | 
| 200 | 20代 | 2018-03-01 00:01:00 | 2018-03-01 | 00 | 01 | 
| 200 | 20代 | 2018-03-01 00:01:01 | 2018-03-01 | 00 | 01 | 
| 200 | 女性 | 2018-03-01 00:01:00 | 2018-03-01 | 00 | 01 | 
| 200 | 女性 | 2018-03-01 00:01:01 | 2018-03-01 | 00 | 01 | 

問題のSQLは以下。
内容としては、segment毎のPVとユニーク数を出したいっぽい。

```
CREATE TABLE log_dmt
WITH sub1 AS (
	SELECT
		user_id
		,segment
		,log_time
		,log_date
		,log_hh
		,log_mm
	FROM
		log_tbl
	)
,sub2 AS (
	SELECT
		user_id
		,segment
		,log_time
		,log_date
		,log_hh
		,log_mm
		,ROW_NUMBER() OVER ( PARTITION BY
			user_id
			,segment
			,log_date
			,log_hh
        ORDER BY
        	log_time ) AS hh_uu_no
        ,ROW_NUMBER() OVER ( PARTITION BY
			user_id
			,segment
			,log_date
			,log_hh
			,log_mm
        ORDER BY
        	log_time ) AS mm_uu_no
	FROM
		sub1
)
--セグメント単位で集計
SELECT
	segment
	,log_time
	,log_date
	,log_hh
	,log_mm
	,SUM(1) AS tmp_pv
	,COUNT(DISTINCT user_id) AS time_uu
	,SUM(CASE WHEN hh_uu_no = 1 THEN 1 ELSE 0 END) AS tmp_hh_uu
	,SUM(CASE WHEN mm_uu_no = 1 THEN 1 ELSE 0 END) AS tmp_mm_uu
FROM
	sub2
GROUP BY
	segment
	,log_time
	,log_date
	,log_hh
	,log_mm
)
;
```
## 謎な点
* 何故ROW_NUMBER関数を噛ませているか
* その結果の1のものだけで集計してtmp_hh_uu, tmp_mm_uuというものを作っている。

## 謎の意味
tmp_hhがどう使われているか。  
例えば下記のようにして使うとその日の毎時でのsegment毎UUが取れる。

```
SELECT
	segment
	,log_date
	,log_hh
	,SUM(tmp_hh_uu) AS hh_uu
FROM
	log_dmt
GROUP BY
	segment
	,log_date
	,log_hh
;
```

解釈としては、ROW_NUMBER関数によってPARTITION=各user_idがそのsegment, log_date, log_hhにおいての初回ログ（ROW_NUMBER = 1）を数えている。 
各user_idはそのsegment, log_date, log_hhにおいて1であるのは1回だけで、しかも必ず現れる。
そのため、1の数を数える（ROW_NUMBER = 1のものを1、それ以外を0とした初回ログフラグ的なものをSUMする）ことでその日の毎時でのsegment毎UUが取れるということになる。

ちなみに、毎分単位の場合下記になる。

```
SELECT
	segment
	,log_date
	,log_hh
	,log_mm
	,SUM(tmp_mm_uu) AS mm_uu
FROM
	log_dmt
GROUP BY
	segment
	,log_date
	,log_hh
	,log_mm
;
```
## 何故そんな変な作りか
最終的に作られたテーブルは **user_id単位からsegment単位** でのlog_timeログになっている。  
user_idからsegmentになることでレコード数は減っているが、log_timeより荒い時間粒度のlog_day,log_hh単位などにする場合、 **user_idの情報がないため** COUNT(DISTINCT user_id)を使うことでsegment内でのUUを求めることができない。  
しかし、このロジックを使うことでより荒い時間粒度でもUUを求めることができる。  

はじめて見た使い方だけれども、そう考えると合理的な作り方だなーと思った。  
割と普通の書き方なんだろか。
【エディタ拡張】EditorGUILayout.Foldoutに画像を表示する

今回はHierarchyに表示されるComponentやAnimationのAddPropertyにあるこの部分の実装を書きます。
バージョンは2017.3.1f1です。

![2018-03-11_23h38_33~_.png](https://qiita-image-store.s3.amazonaws.com/0/59907/0d763ccd-f9d7-d4c1-d1fd-ead68f59b530.png)

#やり方
やり方はFoldoutの引数にGUIContentクラスを入れるだけです。
GUIContentはテキストやアイコン画像を渡して、何を表示するかを設定できるクラスです。

URL:https://docs.unity3d.com/jp/540/ScriptReference/GUIContent.html

例：transformアイコンがついたFoldoutを表示するクラス

```c#

/// <summary>
/// アイコン付き階層表示
/// </summary>
public class FoldoutWithIcon
{
        //表示しているか
        private bool _isOpened;
        public void OnGUI()
        {
            //型を取得
            Type typeTransform = typeof(Transform);

            //型を元にアイコン画像の取得
            Texture2D icon = AssetPreview.GetMiniTypeThumbnail(typeTransform);
            //型の名前とアイコンを表示するGUIを作成
            GUIContent iconContent = new GUIContent(typeTransform.Name, icon);

            _isOpened = EditorGUILayout.Foldout(_isOpened, iconContent);
        }
}

```

#終わりに
間違っている点やこうした方が良い点などがございましたら教えて頂けると幸いです。
【Unity】標準で用意されているコンポーネントのアイコン画像の取得方法

今回は標準で用意されてるコンポーネントのアイコン画像の取得方法を書こうと思います。内容は短めです。
バージョンは2017.3.1f1です。

![2018-03-21_03h04_36.png](https://qiita-image-store.s3.amazonaws.com/0/59907/d7aaa8dc-ae1a-449f-e949-e79664ba9871.png)

#やり方

やり方はAssetPreviewクラスにあるGetMiniThumbnailの引数に表示したいコンポーネントのインスタンスを入れるだけです。戻り値はTexture2Dで返ってきます。

URL:https://docs.unity3d.com/jp/540/ScriptReference/AssetPreview.GetMiniThumbnail.html

例：transformのアイコンを取得する

```c# 
Texture2D icon = AssetPreview.GetMiniThumbnail(gameObject.transform);
```

また、Typeを渡して取得するGetMiniTypeThumbnailというのもあります。

```c# 
Texture2D icon = AssetPreview.GetMiniTypeThumbnail(typeof(Transform));
```
読みやすい設計書の書き方 〜正しい日本語の使い方など〜

こんにちは。
SIerで仕事している2年目の若手SEになります。

ソースコードとコチャコチャ遊んでいる時間が殆どなので
職業柄、英語に触れ合う期間は長いです。
グローバルなこの社会で世界的公用語である英語という言語の
能力を磨くことは最早、必須ともいえるでしょう。

しかし、web界隈ではどうなのか知りませんが
SIerではそれと同じくらい、
設計者や仕様書に向き合う時間も長く、
膨大な日本語にも触れ合って来ました。

現場によっては文言まで統一された
ガチガチフォーマットもあるのでしょうが、
私が経験して来た現場は割と
フリーフォーマットの緩いところが多かったです。

そうなってくると千差万別、人の数だけ設計書があり、
そこには多種多様な日本語が見受けられて来ました。

個人的に気になることを少しだけ書きたいと思います。

#日本語は文面という手段において有利#

私は日本語というのは文体という世界で
非常に優秀な言語だと思っています。

それは漢字がもたらす恩恵です。
世界に色々な言語はありますが、
「文字」自体に意味を持たせることが可能な
日本語、中国語は文章によるコミュニケーションを
とる際に非常に強力なツールだとおもっています。

しかし本来の日本語のアドバンテージを
履き違えているような日本人の方が散見されます。

#日本語の正しい使い方#
ビジネスにおける熟語の正しい使い方を知っていますか？
何が正しくて、何が正しくないとかあるのか
と思われるかもしれません。

まず、間違った熟語の使い方はこうです。

「**ログインを行ったアカウントが初めてのログインである場合に、
画面Aから画面Bへの画面の遷移処理を実行する事が可能**」

やや大げさには書いてますが、これに近いような
冗長性を塊にしたような設計書をよく見かけます。
個人的にはベテランレガシープログラマーに
多いような気も。

こんな文章は以下のようにかけます。

「**初回ログインのアカウントの場合、
AからBへ画面遷移できる**」

スッキリしましたよね？
ポイントをピックアップして行きます。

##①熟語の使い方##
まず、初めての〜が「初回」の2文字で表現できてますよね？
これが正しい熟語の使い方です。

英単語では略語を使わない限り
どうしても文字数は減らせません。

##②DRY原則##
また、画面、画面、画面とうるさかったのが
画面遷移と書くことで前後のAとBが画面であることを
暗黙に示唆しています。

DRY原則(don't repeat yourself)は
何もメソッドなどに限りません。
同じことを何度も書かない工夫をしましょう。
引用などを使うのもベターです。

##③無駄な単語##
次に個人的に一番嫌いな単語、
処理、実行など。

ほんとに、その言葉必要ですか？

削除処理→削除
変換処理→変換

処理という言葉の
8割くらいは省略できるんじゃないかと思います。

「学校へ行く」ことを「登校」と２文字で
短く簡潔に表せるのが本来の熟語の利点です。

無駄に文字数を増やしていては本末転倒です。

##④ひらがなの効果##
また、敢えて「出来る」を平仮名で書いています。

なんでもかんでも漢字ばっか使うと
お経のようになってしまいますが、
区切りに平仮名を用いる事で
メリハリが生まれて読みやすくなります。

「従業員情報削除処理実行」
よりも
「従業員情報を削除する」
の方が読みやすいですよね。

日本語は難しい言葉を振りかざして
賢ぶる為にあるわけではありません。

「負ける」を表現するだけでも
惜敗、惨敗、完敗…
などたったの2文字で表現豊かに「負け方」を表すことができます。

**短い単語の中に情報量を多く詰める事こそが
本当の美しい日本語の使い方だと思います。**

#見やすい図の描き方#
単体テスト項目書などで使われる
マトリクス図やディシジョンテーブル。
こんな描き方していませんか？

**傘の条件**

晴れ|雨  
:--:|:--:
傘を持っていかない|傘を持っていく 

これでは図を使っている意味がありません。

以下のように描けば見やすくなります。

**傘の条件**        

|晴れ|雨|
:--:|:--:
|×|○|

○: 傘を持っていく

#最後に#
少しの工夫をするだけで
あなたの設計書は途端に見やすくなります。

**設計書は書くものではなく読まれる為にある**ので
再度自分で読み返してみて
無駄のない美しい文章を心がけましょう。

まだまだ私の文章も精査が必要だと思いますが
ここまで読んでいただきありがとうございました。
X11Forwardingがうまくいかない場合の対処

# リモート側 (X client)

```/etc/ssh/sshd_config``` の設定を変更

```
X11DisplayOffset 10
X11Forwarding yes
X11UseLocalhost no
XauthLocation /usr/bin/xauth
```

sshdを再起動

```
[remote-user@remote-host] $ sudo systemctl restart ssh
```

xauthが無い場合はインストール

```
[remote-user@remote-host] $ sudo apt-get install xauth
```

# ローカル側 (X server)

X11Forwarding有効でリモート接続

```
[local-user@local-host] $ ssh -XY user@host
```

ssh接続の際にデバッグ情報を表示

```
[local-user@local-host] $ ssh -XYv user@host
```

# Warning: No xauth data; using fake authentication data for X11 forwarding? が出る場合
認証情報を追加

```
[local-user@local-host] $ xauth generate $DISPLAY
```

# 確認

接続後`xhost`コマンドでリモート側でdisplayが見えるか確認
以下はうまくいっている例

```
[remote-user@remote-host] $ xhost
access control enabled, only authorized clients can connect
INET:localhost
INET:remote-host
INET:192.168.122.1
INET6:ip6-localhost
INET6:xxxx::xxxx:xxxx:xxxx:xxxx
LOCAL:
```

以下はうまくいっていない例

```
[remote-user@remote-host] $ xhost
xhost:  unable to open display ""
```
`eclipse.exe`のファイル名を変更すると、Eclipse Pleiadesが日本語化されない


# 環境
* JDK8.152
* [Eclipse Pleiades 4.7.2](http://mergedoc.osdn.jp/)


# 問題
`eclipse.exe`のファイル名を`eclipse_test.exe`に変更しました。
Eclipseの起動は成功しましたが、メニュバーなどのメッセージが日本語化されていませんでした。


![ファイル名を変えたフォルダ構成](https://qiita-image-store.s3.amazonaws.com/0/37903/b46b7ba5-8a23-aaea-a988-6bce07ccac6b.png)


![日本語化されていないEclipse](https://qiita-image-store.s3.amazonaws.com/0/37903/0c3636cd-7591-1b2c-c23a-899d13f78cd7.png)

# 解決
ファイル名を元に戻しました。

![元のフォルダ構成](https://qiita-image-store.s3.amazonaws.com/0/37903/4ca0f422-c563-9743-e66e-25f6ed4b2548.png)


![通常のEclipse](https://qiita-image-store.s3.amazonaws.com/0/37903/d16c6c88-29bd-10e8-a001-bed8f16fc04a.png)


# 思ったこと
* 日本語化プラグインの内部では、`eclipse.exe`というパスを辿っているのでしょうか。
Angular5 で俺式 KOAN スタック Webアプリ構築（1）

# Angular5 初期設定
Angular5で「俺式KOANスタック」でWebアプリ構築するための個人的な備忘録記事。
概要については「[こちら](https://qiita.com/tomy0610/items/feaf4ced2ccb66373c15)」を参照。

## 事前準備
* [Node.js](https://nodejs.org/ja/) のダウンロード、インストールする（ここでは手順を割愛）
* Node.js 標準のパッケージ管理「npm」を最新化する

```bash:npm最新化コマンド
npm install -g npm
```

``` bash:npmバージョン確認
npm -version
```

* 公式の構築支援ツール「angular-cli」をインストール。`ng`コマンドが使える様になる

```bash
npm install -g @angular/cli
```

※ 本記事が古くなり、angular-cli のバージョンが上がることによって、Angular5以降のバージョンで構築されてしまう可能性があるので、その場合はご自身で対応してください

## Angular バージョン確認
以下のコマンドで、Angular が「5.x」になっているか確認する（「4.x」以下であれば古い）

```bash:Angularバージョン確認
ng -v
```

```bash:コマンド結果
    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/

Angular CLI: 1.7.3
Node: 8.6.0
OS: win32 x64
Angular: 5.2.8　　　← ← ← ←【ここが Angular のバージョン】
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router

@angular/cli: 1.7.3
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.3.2
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.2
@schematics/angular: 0.3.2
@schematics/package-update: 0.3.2
typescript: 2.5.3
webpack: 3.11.0

```

※ まだAngularプロジェクトが未作成で空っぽの場合は、おそらく、上記の様にズラリと結果が出ないため、その場合は気にせず次に進んでください。

## プロジェクト作成

* 任意のディレクトリを作成して、その中に移動し、新規アプリプロジェクトを生成

```bash:新規プロジェクト生成
ng new 任意のプロジェクト名 --style=css --routing=true
```
モジュールのインストール（`npm install`）まで行うため、処理完了までに 3~4分ほどかかる

* オプション
 * `--style`：スタイル言語の指定（CSSの場合は省略可）： `css`, `scss`等
 * `--routing`：ルーティングモジュール付きで生成する場合： `true`（falseの場合は省略可）

## 動作確認

* 作成したディレクトリに移動し、サーバ起動

```bash:サーバ起動
cd 作成したプロジェクト名
ng serve
```
* `http://localhost:4200` でAngularテストページが表示されたら成功。
* `Ctrl + C` でサーバ終了。

---

ここまでが Angular5 の標準的な初期設定。

→ [次に、KOANを前提としたフロントエンドの構築をする](https://qiita.com/tomy0610/items/c51ee4c73bfa238d3473)
Angular5 で俺式 KOAN スタック Webアプリ構築（概要）

Angular5で「俺式KOANスタック」でWebアプリ構築するための個人的な備忘録記事。

## KOAN に辿り着くまでの経緯
事の始まりは、[Angular](https://angular-ja.firebaseapp.com/)を覚えたての自分が、Angularを使ったバックエンドまで開発するWebアプリを作っていた時のこと。
（当時は、いわゆる「Angular2」で開発していた。）
Webアプリ開発のBoilerplate（＝ひな型）の１つである「MEANスタック」という言葉を知ったことがきっかけ。

### MEAN（ミーン）とは
「[MEANスタック](http://mean.io/)」とは、[MongoDB](https://www.mongodb.com/), [Express](http://expressjs.com/ja/), [AngularJS](https://angular-ja.firebaseapp.com/), [Node.js](https://nodejs.org/ja/) のAcronym（＝略）で、Webアプリ開発に用いられるソフトウェアの組み合わせのこと。
『この４つを組み合わせて、体裁の整ったWebアプリを構築できまっせ』ということ。
MongoDB開発者の Valeri Karpovni 氏により、2013年4月30日にWeb上で提唱され、2014年以降、徐々に有名になっていったものらしい。
Valeri Karpovni 氏のブログには、本来の「MEAN」の思想が残されている。
[The MEAN Stack: MongoDB, ExpressJS, AngularJS and Node.js](https://www.mongodb.com/blog/post/the-mean-stack-mongodb-expressjs-angularjs-and)

### Express から Koa へ移行
Expressは、Node.jsのWebフレームワークとして非常に有名だが、当時は開発してたら何だかんだでExpressではコールバックを書かなければいけない処理が目立ってきたので、「他に何か無いかな〜？」って探していたら、ちょうど注目を浴び始めていた「Koa」を知った。

MEANスタックで書いていたWebアプリをKoaで置き換えてみたら、書きやすくて見通しの良いソースコードになったので、これを機にKoaで構築する方向に切り替えていった。

Koaが出た当初は大して注目されなかった様だが、最近ではKoaの「v2」も出てきて、Express使うよりKoaの方が機能も優秀になっている感じになってきたので、Koaを中心に「MEANスタック」みたいなこと出来ないかと考えていた時に、新たに出会ったのが「KOANスタック」だ。（この辺で同時に、Angularも「2」から「4」へ移行することにした）

※ ちなみに、最近調べたExpressの記事みると、コールバック書かなくても出来るみたいなので、もうKoaじゃなくてもいいかもね。

### KOAN（コーン）とは
「[KOANスタック](https://github.com/soygul/koan)」とは、[Koa](http://koajs.com/), AngularJS, Node.js の略で、MEAN同様、Webアプリ開発のひな型の１つ。
「KOAN」を提唱しているGitHubをみると、上記に加えてMongoDBも含めた構成になっている。

## 俺式 KOAN スタックでWebアプリ構築
今回は、MongoDBはとりあえず置いておいて、Koa, AngularJS, Node.js の３つでWebアプリを構築でする構成にした。
フロントエンドについては、これまで個人的に使わなかったAngular開発支援ツール「angular-cli」を使用して「Angular5」で構築する。 angular-cli に設定を書くので、手動でWebpack等はいじらない方向性。
バックエンドについては、こちらもTypeScriptで記述して、他にも必要なライブラリを適宜入れていく。
WebフレームワークはKoaの「v2」を使用し、フロント〜バック間のインターフェースは、フロントエンド側/バックエンド側どちらからも読み込める中間クラスを作成し、そこにインターフェースや汎用処理をまとめてWebアプリを構築する。

尚、コーディングに使用するエディタは最近気に入っている「[Visual Studio Code](https://www.microsoft.com/ja-jp/dev/products/code-vs.aspx)」。フリーだけど結構優秀。

## 実際のWebアプリ構築手順
実際に構築した内容をメモっとく。（作業のリンクから、実手順の記事に飛べます）
パッケージ構成は書きませんので、実際に作って「ふ〜ん」という感じで見てください。

|手順|作業|内容|
|:---:|:---|:---|
|1|[Angular5 初期設定](https://qiita.com/tomy0610/items/898920cfc94744692fa8)|Angularでフロントのベースを構築|
|2|[フロントエンド初期設定](https://qiita.com/tomy0610/items/c51ee4c73bfa238d3473)|KOANスタックを前提に少しフロントをいじる|
|3|[バックエンド初期設定](https://qiita.com/tomy0610/items/bb87e2d19572a03c5df3)|KOANスタックを前提にしたバックエンドを構築する（アプリのdaemon(デーモン)化もここで行う）|
|4|[クラサバ通信部の作成](https://qiita.com/tomy0610/items/f43f75df060da71c09e4)|クラサバ通信ができる様にする。ここまで作ればWebアプリとして動作|
|5|外部通信部の作成（ファイル操作）|書こうと思ってましたが、Angular6 が出てきたのでそっちに移行するのでやめました。（ごめんなさい）<br>結論だけ雑に書くと、ここは mysql やら http やら適当なライブラリを `npm install` してきてリファレンス見ながら適当に書くだけでした。|
|6|環境変数を呼び分けられるようにする|書こうと思ってましたが、Angular6 が出てきたのでそっちに移行するのでやめました。（ごめんなさい）<br>結論だけ雑に書くと、まず config ライブラリをインストール（npm i config）し、 `package.json` にコマンド実行時のオプションで `--NODE_ENV=production` など書いて、いい感じに設定された環境値を利用して config の値を使うだけでした。|
|7|認証とセッション管理機能を導入する|書こうと思ってましたが、Angular6 が出てきたのでそっちに移行するのでやめました。（ごめんなさい）<br>結論だけ雑に書くと、`koa-session` をインストールして、koa ルーティング時に context(ctx) を使用して `ctx.session` などと書いて利用するだけでした。詳しくは `koa-session` のドキュメント見ればOK|
ExcelのSum関数だけで残業時間計算

Excelは、Sum関数だけで残業時間を計算できる。

## 残業時間の計算方法

たとえば、下記のようなXX:XXというフォーマットで残業時間を記入
![image.png](https://qiita-image-store.s3.amazonaws.com/0/80231/3b33a802-c18e-29b0-4752-56655ebfa9d0.png)

C1セルに普通にsum関数で残業時間を合計させる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/80231/d4c4a7a6-3e9e-e730-f6f4-15e85e278fd6.png)

一見計算できていないように見えるが、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/80231/68ecd19a-9459-10b8-7052-5cc802ff5d99.png)

C1セルの書式をユーザー定義の表示形式 [h]:mmに変えると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/80231/844aa1af-d0c6-38a2-b02b-89dd0596d153.png)

ちゃんと残業時間が計算できている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/80231/b1b3544a-c13a-5cc3-e35d-84164acc07bf.png)

## 参考: ユーザー定義の表示形式の設定方法

https://udemy.benesse.co.jp/office-enhance/excel-user-definition.html
【Java】ラムダ式の省略方法まとめ

ラムダ式の省略方法をまとめます。
Java Silverなどの試験で問われるので、受験者の助けになればと思います。
最後に覚え方をまとめています。

そもそもラムダ式がわからない場合はこちらをどうぞ。
[Java8のラムダ式を理解する](https://qiita.com/sano1202/items/64593e8e981e8d6439d3)

まず、ラムダ式の基本形。

```java:基本形
Predicate<String> javaChecker = (String s) -> { return s.equals("Java"); };
```

ここから何をどう省略できるのか見て行きましょう。

## 引数の型
まず、引数の型が省略可能です。

```java
Predicate<String> javaChecker = (s) -> { return s.equals("Java"); };
```
ただし、複数の引数がある場合、片方だけ省略するというのはできません。

```java
// コンパイルエラー
BiFunction<Integer, Integer, Integer> adder = (a, Integer b) -> { return a + b; };
```

## 引数の()
引数の()も省略可能です。

```java
Predicate<String> javaChecker = s -> { return s.equals("Java"); };
```

ただし、条件が2つあります。
まず、型を指定した場合は省略できません。

```java
// コンパイルエラー
Predicate<String> javaChecker = String s -> { return s.equals("Java"); };
```

次に、引数が複数ある場合も省略できません。

```java
// コンパイルエラー
BiFunction<Integer, Integer, Integer> adder = a, b -> { return a + b; };
```

引数が1単語の時のみ()が省略可と覚えると良いと思います。

## メソッドの{}
メソッドの{}も省略可能です。

```java
Consumer<String> buyer = goods -> System.out.println(goods + "を購入しました");
```

こちらも条件があります。
まず、処理が2文以上あると省略できません。

```java
// コンパイルエラー
Consumer<String> buyer = goods -> String message = "私が、" + goods;
                                  System.out.println(message + "を購入しました");
```

次にreturnを記述すると省略できません。

```java
// コンパイルエラー
Predicate<String> javaChecker = s -> return s.equals("Java");
```

ただし、returnも省略すれば正常に実行することができます。

```java
Predicate<String> javaChecker = s -> s.equals("Java");
```

処理が1ステートメントの時のみ{}が省略可、戻り値がある場合はreturnの省略もセットで、と覚えましょう。

## return
上記のようにreturnは省略可能ですが、メソッドの{}を残したままでは省略できません。

```java
// コンパイルエラー
Predicate<String> javaChecker = s ->{ s.equals("Java"); };
```
returnを省略したい時も{}の省略とセットということになります。

## まとめ
まとめると以下のようになります。

|省略部分|条件|
|---|---|
|引数の型|全引数の型を省略すること|
|引数の()|1単語の時のみ|
|メソッドの{}|1ステートメントの時のみ<br>戻り値がある場合、returnの省略とセット|
|return|メソッドの{}の省略とセット|
paiza/atCoder で使うGoコードをテスト環境から実行する

paizaやAtCoderで使うような、標準入力から入力を受けとり、標準出力に結果を出力するようなコードを簡単にテストする環境を作ります。


次のようなヘルパ関数を作ります

```golang

package main_test

import (
	"bytes"
	"fmt"
	"io"
	"strings"
	"testing"
)

func checker(input string, f func(io.Reader, io.Writer)) string {
	reader := strings.NewReader(input)
	writer := bytes.NewBufferString("")
	f(reader, writer)
	return writer.String()
}
```

標準入力と標準出力の代わりにstringを使うようにします。
``func(io.Reader, io.Writer)`` に実際にpaiza/atCoderで使うコードを書くことになります。

以下にコード全体を載せます。


```go
package main_test

import (
	"bytes"
	"fmt"
	"io"
	"strings"
	"testing"
)

func checker(input string, f func(io.Reader, io.Writer)) string {
	reader := strings.NewReader(input)
	writer := bytes.NewBufferString("")
	f(reader, writer)
	return writer.String()
}

func sampleCode(reader io.Reader, writer io.Writer) {
	var a, b, c, d int
	fmt.Fscanf(reader, "%d %d %d %d\n", &a, &b, &c, &d)
	fmt.Fprintf(writer, "%d\n%d\n%d\n%d\n", a, b, c, d)
	fmt.Fscanf(reader, "%d %d %d\n", &a, &b, &c)
	fmt.Fprintf(writer, "%d\n%d\n%d", a, b, c)
}

func TestSample(t *testing.T) {
	inputString :=
		`1 2 3 4
5 6 7`
	expect := `1
2
3
4
5
6
7`
	output := checker(inputString, sampleCode)
	if output != expect {
		t.Errorf("expcet %v,but%v", expect, output)
	}
}

```

実際にpaiza/atCoderに投稿するときは以下のようにします


```Go
package main
import (
"fmt"
"os"
)
func sampleCode(reader io.Reader, writer io.Writer) {
	var a, b, c, d int
	fmt.Fscanf(reader, "%d %d %d %d\n", &a, &b, &c, &d)
	fmt.Fprintf(writer, "%d\n%d\n%d\n%d\n", a, b, c, d)
	fmt.Fscanf(reader, "%d %d %d\n", &a, &b, &c)
	fmt.Fprintf(writer, "%d\n%d\n%d", a, b, c)
}

func main() {
  sampleCode(os.Stdin,os.Stdout)
}
```
GCP向けssh-keygenメモ

# 鍵生成ツール

* PowerShell/Win32-OpenSSH https://github.com/PowerShell/Win32-OpenSSH/releases

# 鍵生成コマンド

* ssh-keygen -t ed25519 -P "PASSPHRASE" -f "keyname"
* cat .\keyname.pub

catの表示をSSH認証鍵のところにコピペする。
このときのgcloudコマンドを参考にすれば同じ鍵のインスタンスを何度でも立てられる。
秘密鍵とPASSPHRASEを適当なクライアントに入れればOK。

PuTTY形式の鍵はssh-keygen -t ecdsa -b 521にした方が無難かも。
Flutter でデバイスの画面サイズを得る MediaQuery

Flutter で、デバイスの画面サイズを得るには [MediaQuery](https://docs.flutter.io/flutter/widgets/MediaQuery-class.html) という Widget を使います。

```dart
@override
Widget build(BuildContext context) {
  final Size size = MediaQuery.of(context).size;
  
  // sizeを使って何かする
  return new Container(
    width: size.width,
    ...
  );
}
```

※画面に表示されるようなものではないですが、こういうのも含めて「みんなWidget」です

また、前提としてコンテキストの先祖に `WidgetsApp` か `MaterialApp` が存在していることが必要です。
.ipaファイルに含まれているProvisioning Profileの内容を出力するシェルスクリプト(Mac)

仕事でEnterprise用のiOSアプリを開発していて、アプリに含まれているProvisioning Profileを確認したい場面に遭遇しました。
手動で.ipaファイルから引っこ抜くこともできるのですが、毎回行うのは地味に手間です。

そこで、.ipaファイルのパスを渡すとそれに含まれているProvisioning Profileの内容を出力するシェルスクリプトを実装しました。

## 環境

- OS：macOS High Sierra 10.13.3

## シェルスクリプト

```bash:output_pp.sh
#!/bin/bash

# ----------------------------------------
# iOSアプリに含まれているProvisioning Profileの内容を出力する
# 引数：$1 .ipaファイルのパス
# 戻値：なし
# 動作条件：パスに改行や日本語が含まれていない
# 　　　　：.app名が.ipa名と同様
# ----------------------------------------

readonly IPA_DIR_PATH=$(dirname $1)
readonly APP_NAME=$(basename $1 .ipa)

# output Provisioning Profile
cp ${IPA_DIR_PATH}/${APP_NAME}.ipa ${APP_NAME}.zip
unzip ${APP_NAME}.zip
security cms -D -i Payload/${APP_NAME}.app/embedded.mobileprovision

# teardown
rm -r Payload
rm ${APP_NAME}.zip


exit
```

## 使い方

デスクトップに `output_pp.sh` と `○○.ipa` が存在する場合の例です。
ターミナルで以下を実行するのみです。

```bash
$ cd ~/Desktop/
$ sh output.sh ○○.ipa
```

## 注意点

- 理由はわかりませんが、拡張子を `.ipa` のまま `unzip` すると `embedded.mobileprovision` が解凍されませんでした。
【備忘録】pipでライブラリインストール時にmemory errorが出たときの対処法

※本エントリは完全に個人の備忘録です。

Raspberry Piで環境構築時に
pythonのライブラリmatplotlabをpipでインストールしようとしたときに下記エラーが出てきた。

```
Exception:
  Traceback (most recent call last):
    File "/usr/local/lib/python2.7/dist-packages/pip/basecommand.py", line 232, in main
      status = self.run(options, args)
    File "/usr/local/lib/python2.7/dist-packages/pip/commands/install.py", line 339, in run
      requirement_set.prepare_files(finder)
    File "/usr/local/lib/python2.7/dist-packages/pip/req/req_set.py", line 355, in prepare_files
      do_download, session=self.session,
    File "/usr/local/lib/python2.7/dist-packages/pip/download.py", line 782, in unpack_url
      session,
    File "/usr/local/lib/python2.7/dist-packages/pip/download.py", line 667, in unpack_http_url
      from_path, content_type = _download_http_url(link, session, temp_dir)
    File "/usr/local/lib/python2.7/dist-packages/pip/download.py", line 843, in _download_http_url
      _download_url(resp, link, content_file)
    File "/usr/local/lib/python2.7/dist-packages/pip/download.py", line 615, in _download_url
      for chunk in progress_indicator(resp_read(4096), 4096):
    File "/usr/local/lib/python2.7/dist-packages/pip/utils/ui.py", line 46, in iter
      for x in it:
    File "/usr/local/lib/python2.7/dist-packages/pip/download.py", line 580, in resp_read
      decode_content=False):
    File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/requests/packages/urllib3/response.py", line 256, in stream
      data = self.read(amt=amt, decode_content=decode_content)
    File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/requests/packages/urllib3/response.py", line 186, in read
      data = self._fp.read(amt)
    File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/cachecontrol/filewrapper.py", line 54, in read
      self.__callback(self.__buf.getvalue())
    File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/cachecontrol/controller.py", line 205, in cache_response
      self.serializer.dumps(request, response, body=body),
    File "/usr/local/lib/python2.7/dist-packages/pip/_vendor/cachecontrol/serialize.py", line 81, in dumps
      ).encode("utf8"),
  MemoryError"
```

なんだこれ？と思い、「pip MemoryError」で検索したらStack Overflowで数多くの投稿が。
どうやら下記オプションを追加すれば良いとのこと。

```
$ pip --no-cache-dir install matplotlib
```
--no-cache-dir はキャッシュを無効化して実行するオプションらしい。
MemoryErrorを引き起こしたのは、インストール開始時に前回キャッシュが残っていたのが原因なのかしら・・・

試しに上記コマンドで再度インストールしてみたら、無事完了しました。よかったよかった。
Pythonでテストを動かす

# やること

今さらだけどPythonでテストを動かす。ここではunittestを使う。

# 環境

- macOS 10.13.3
  - Python 3.6.4
  - Python 2.7

# 実装

## ディレクトリ構成

```
./
 ├ calc.py
 └ tests/
  └ test_calc.py
```

## 本体の実装

```python:calc.py
def add3(n):
    return n + 3
```

## テストの実装

```python:tests/test_calc.py
from unittest import TestCase
from calc import *

class CalcTest(TestCase):
    def test_add3(self):
        self.assertEqual(5, add3(2))
```

# 実行

```sh
# 単一ファイルのテストを実行するとき
$ python -m unittest tests/test_calc.py

# testsディレクトリ以下をまとめて実行するとき
$ python -m unittest discover -s tests

# 困ったとき
$ python -m unittest -h
```

ただし、Python2.7のとき、単一ファイル指定の方法だとImportErrorが発生した。


# まとめ

ここまででは特にハマるようなケースがなかった。

FirebaseとAlgoliaを自動反映させる

本記事は[この](https://qiita.com/Baisel/items/3d96cead2a6d0bd4c20d)記事の内容で使用したものです。

*Firebaseのデータベースに変更があったときにそれを自動でAlgoliaのインデックスに反映してくれるようにします。*

## Node.jsをインストールします。
記事はいくらでもあるので参考にしてください。

```shell:
node -v
v5.11.0
```

### 以下のパッケージを入れます。

```shell
npm install dotenv --save
npm install algoliasearch --save
npm install firebase --save
```

変数名「contactsRef」以下のデータに変化があった場合、それをAlgoliaのインデックスに反映させます。
Nodeが動いていないと働かないのでローカル以外で開発するときは外部サーバでNodeを動かした方がやりやすいです。


```javascript:index.js
const algoliasearch = require('algoliasearch');
const dotenv = require('dotenv');
const firebase = require('firebase/app');

require('firebase/auth');
require('firebase/database');
dotenv.load();

// 接続するFirebaseのデータベースURL
var config = {
  databaseURL: "https://XXXXXXXXXXXX.firebaseio.com",
};
firebase.initializeApp(config);
const database = firebase.database();

// configure algolia
const algolia = algoliasearch(
  "XXXXXXXXXXX",                 //←Algoliaの「Application ID」
  "XXXXXXXXXXXXXXXXXX"           //←Algoliaの「Admin API Key」
);
const index = algolia.initIndex("sample");  //接続するAlgoliaのindex名


const contactsRef = database.ref('/msg'); //変更を反映する範囲を指定する今回は[msg]以下に変化があった場合に反映させている。
contactsRef.on('child_added', addOrUpdateIndexRecord);
contactsRef.on('child_changed', addOrUpdateIndexRecord);
contactsRef.on('child_removed', deleteIndexRecord);

//　「contactsRef」の中で新しいデータが追加されたらAlgoliaのindexに反映する関数。
function addOrUpdateIndexRecord(contact) {
  const record = contact.val();
  record.objectID = contact.key;

  index
    .saveObject(record)
    .then(() => {
      console.log('Firebase object indexed in Algolia', record.objectID);
    })
    .catch(error => {
      console.error('Error when indexing contact into Algolia', error);
      process.exit(1);
    });
}

//　「contactsRef」の中でデータが削除されたらAlgoliaのindexに反映する関数。
function deleteIndexRecord(contact) {
  const objectID = contact.key;

  index
    .deleteObject(objectID)
    .then(() => {
      console.log('Firebase object deleted from Algolia', objectID);
    })
    .catch(error => {
      console.error('Error when deleting contact from Algolia', error);
      process.exit(1);
    });
}
```

```json:package.json
{
  "name": "sample",
  "version": "0.0.0",
  "description": "sample",
  "dependencies": {
    "algoliasearch": "^3.24.9",
    "dotenv": "^4.0.0",
    "firebase-admin": "~5.8.1"
  }
}
```


```shell:
node index.js
```

## まとめ
[公式](https://www.algolia.com/doc/tutorials/indexing/3rd-party-service/firebase-algolia/)の記事を参考に作りましたが、その通りにやるとエラーで動かないので少し変えています。Versionによってはエラーが出る可能性があるので注意してください。
間違い等ありましたら連絡してください。
ブロックチェーンの基礎：ブロックチェーンの定義、種類、技術

#はじめに
前回、[ブロックチェーン基礎の基礎](https://qiita.com/KazukiKawamura/items/68cb6c16a7d95b9c5a02)でブロックチェーンのイメージについて説明したので、ブロックチェーンの定義、種類、技術など、もう少し詳しくブロックチェーンについてみていきます。


#ブロックチェーンの定義
日本ブロックチェーン協会(JBA)では、狭義のブロックチェーンを以下のように定義しています。

> 「ビザンチン障害を含む不特定多数のノードを用い、時間の経過とともにその時点の合意が覆る確率が0へ収束するプロトコル、またはその実装をブロックチェーンと呼ぶ。」

これだけではよく分からないと思いますが、簡単に説明すると、**「嘘をつく可能性がある参加者や、正常に動作していない参加者を含む不特定多数の参加者がいる中であってもこのネットワークで得られた合意は時間が経つにつれて覆る可能性が0に近づく仕組み」**ということになります。

JBAの定義では上のようになってはいますが、この定義に従うものだけがブロックチェーンというわけではなく、いまではかなり広い意味でブロックチェーンという言葉が使われることも多いので参考程度にとどめておいてよいでしょう。


#ブロックチェーンの種類
ブロックチェーンには大きく分けて、以下の2種類あります。

- パブリックチェーン
- プライベートチェーン

パブリックチェーンは、このネットワークに参加する人を制限せず、**誰でも自由に参加することができる**ブロックチェーンで、プライベートチェーンは、参加する人を制限し、**特定の人しか参加することができない**ブロックチェーンです。

これらの2種類のブロックチェーンは、次節で説明しますが、合意に用いられるアルゴリズム(コンセンサスアルゴリズム)や、メリット、デメリットなどもかなり異なっています。

| | パブリックチェーン | プライベートチェーン |
| :--- | :--- | :--- | 
| 参加者 | 誰でも自由に参加可能 | 特定の人のみ参加可能 | 
| メリット | 管理者が不要 <br> 改ざんが不可能| 仕様変更が容易 <br> 取引手数料が不要 |
| コンセンサスアルゴリズム | PoW、PoS | PBFT |
| 使用例 | Bitcoin <br> Ethereum <br> nem | Ripple <br> Ethereum <br> HyperledgerFabric|


#ブロックチェーンを支える技術
ブロックチェーンを構成する技術はたくさんありますが、その中から主なものを説明します。

1. ハッシュ関数
2. 公開鍵暗号方式
3. コンセンサスアルゴリズム

もちろん、ブロックチェーンの一種である**ビットコイン**でもこれらの技術は用いられているので、これらがビットコインにおいてどのように用いられているかについても説明します。

## 1. ハッシュ関数
[前回](https://qiita.com/KazukiKawamura/items/68cb6c16a7d95b9c5a02)も簡単に説明しましたが、ハッシュ関数は、以下のような特徴を持っています。

- 入力データに関わらず出力データ(ハッシュ値)は固定長になる
- ハッシュ値から元の入力データを推定することが非常に困難である
- 同じ入力データを与えるといつも同じハッシュ値を返す

ブロックチェーンでよく用いられるハッシュ関数**SHA256**での一例を示します。

![SHA256.png](https://qiita-image-store.s3.amazonaws.com/0/208575/de09ccc6-db8b-894d-a8df-7fc5676e0600.png)


上の図より、一文字違うだけで、まったく異なったハッシュ値が固定長で返ってくることが分かります。ビットコインにおいては、ユーザーの口座番号である**ビットコインアドレス**として使われています。

## 2. 公開鍵暗号方式

ブロックチェーンでは公開鍵暗号技術として「楕円曲線暗号」がよく用いられます。公開鍵暗号の仕組みについてですが、まず、送信者Aは受信者Bさんの公開鍵で平文を暗号化してBさんに送信します。Bさんの公開鍵で暗号化した平文はBさんの秘密鍵でしか復号することができないので、この仕組みを用いて安全に文書を送信することができます。

![PublicKey.png](https://qiita-image-store.s3.amazonaws.com/0/208575/b1914699-da5c-8dab-1f1a-1e491004dd4e.png)

また、ビットコインではこの技術を使った**デジタル署名**という技術も用いられています。この技術を使うと、AさんからBさんへ送金をおこなった場合、本当にAさんが送金したかどうかの本人確認ができます。

## 3. コンセンサスアルゴリズム

ブロックチェーンは中央集権的に管理されているわけではないので、取引が不正なく正しいことを参加者自身で確認する必要があります。ブロックチェーンの定義のところで述べたように、嘘をつく参加者がいる可能性があることを前提に適切にこの合意の仕組みを決める必要があり、この仕組みのことを**コンセンサスアルゴリズム**と呼びます。

コンセンサスアルゴリズムにはいくつか種類があるのですが、ここではビットコインで用いられている**PoW(Proof of Work)**について説明します。

ビットコインで新しいブロックを生成するとき、無条件に生成するというわけにはいかないので、「先頭に、一定の数以上の0が並んでいる」ハッシュ値を持つブロックのみを正しいブロックであるとみなすようになっています。

ハッシュ値はナンス値からハッシュ関数を用いて求められますが、ハッシュ関数の性質により、このハッシュ値からナンス値を求めることは極めて難しいものとなっています。したがって、ブロックを生成するために必要な条件を満たしたハッシュ値を探すためには、ナンス値を変えていって総当りで探すしか方法がないのです。

このナンス値を探す行為を「マイニング」と呼び、条件に合うナンス値を発見した人には報酬が与えられることになっています。さらに、取引を改ざんして不正なブロックを生成するには、そのブロックだけでなくそれ以降の全てのブロックも改ざんする必要があるので、不正するよりもマイニングに参加して報酬を得る方がコストパフォーマンスがよく、不正を働きにくいということになります。

PoWはナンス値の発見のために大量の電力が必要であるため、この問題を解決するために、ナンス値ではなくコインの保有量などを基準にブロック生成者を決定する**PoS(Proof of Stake)**など、様々なコンセンサスアルゴリズムが存在します。
Google Home用アプリを作ったら、予想外な形でたくさん使ってもらえた

どうも。ひがし（Twitter：[@m_higa4](https://twitter.com/m_higa4)）です。
VUI（Voice User Interface）の未来に魅力を感じ、色々勉強中です。

さて、Google HomeやAmazon Echoが日本で発売されて以来、サードパーティ（GoogleやAmazon以外の会社）によるVUIアプリ（声を使って操作するアプリ）の開発がどんどん進んでいますね！ 今日は自分がリリースしたアプリが、1週間どのように使われたかを共有することで、**みなさんのアプリ企画に対する考えの幅を広げるきっかけ**になればと思っています。


#一瞬だけど、ちょっとバズりました
Google Home用アプリ（正確には「アクション」）である[**"運命のコイントス"**](https://assistant.google.com/services/a/uid/000000973360494a?hl=ja)をリリースしました。 レストランとかで何にしようか迷っていると、大体二択までは絞れるんですけど、そこから結構迷いません？（笑） そんな時に、このアプリを使えば、コイントスで簡単・スピーディーに一択に絞れます！

 ["運命のコイントス"の動画はこちらから](https://twitter.com/m_higa4/status/970261350168518656)
 

さて、3月1日にリリースした後、果たして結果はどうだったのか！？Actions on Google （Google Home用のアプリを管理するサイト）での、Unique Users（2週間）が以下になります。

![データ.png](https://qiita-image-store.s3.amazonaws.com/0/222616/0b266e6f-07dd-9084-d1ce-8d73291b7fc0.png)


なんと、**3月3日には879人にも"運命のコイントス"を使ってもらえた**、という事実はとても嬉しい限りです。（6日以降の減っていくユーザー数については割愛（笑））

ただ、データを見て一番驚いたのは、実は、利用者数ではなく、**「どの端末でアプリを利用したか」**でした。



#アプリを、"Google Home"で使わない
Unique Usersでは使えないのですが、実は他の指標では、どの端末（Home / Mobile）からアプリを利用したのかがわかるのです。一番ユーザーが多かった3月3日の"Conversations"（アプリ側の発言数）は、以下の通りになります。

![Screen Shot 2018-03-19 at 23.11.28.png](https://qiita-image-store.s3.amazonaws.com/0/222616/24dcb0ae-4d9b-8a86-76a9-0a7b1b50ac13.png)


驚くことに、**Mobileからの使用の方がダントツで高い**のです！約25倍の差ってすごいですよね。

実は、今回のアプリは、Google Homeでいち早くアプリを出したい気持ちで作った（そして、GoogleのTシャツが欲しかった）だけでした。ですので、レストランで使うペルソナを作りつつも、「Google Home用に作ったから、ほとんどの人はGoogle Homeを通してVUIアプリを使うんでしょ！」とか勝手に思っていたのです。



#音声を使うシーンは「家」だけではない
僕のように、VUIアプリは、Google Homeからの使用を中心に考えてしまう人は多いのではないでしょうか？ そうなると、アプリ企画・開発時、ペルソナの利用シーンが「家」に縛られてしまいます。また、日本人は外で声を出して機械に話しかけることに抵抗感があるので、あまりVUIは日本では普及しないのでは、と一般的には言われています。



だけど、今回のデータを見て、**スマホを持ち運びながら外とかでVUIアプリを使う人はこれから急激に増えていく**と強く感じました。VUIに馴染みのある人が友達の前でスマホからVUIアプリをいじり、まわりの人がその便利さや楽しさを見て「いいな」と思って、使い始める。そんなサイクルが生み出されていくのではないかなと思います。



そして、みなさんがVUIアプリを企画・開発する際は、**是非利用シーンをもっと自由に発想してほしい**です。恋人とデートしている時、家族でBBQしている時、会社で仕事している時...。VUIで生活を豊かにできるシーンは、想像以上にあります！

※企画・開発する際は、「ペルソナ設定」→「会話」→「実装」の順番を、Googleも公式ページ（[Actions on Google |Guide(https://developers.google.com/actions/extending-the-assistant)）でオススメしています。



「こんなシーンでVUI使ったら面白いんじゃない！」といったアイデアを、自分自身からも発信していきたいですし、みなさんのもたくさん聞きたいです！VUIを一緒に盛り上げていきましょう！
Homebrewでjavaをインストールする

## はじめに
- MacでHomebrewを使ってjavaをインストールする手順メモです。
- Sierra（10.12.2）を利用しています。
- 現時点でどのバージョンのjavaもインストールされていない前提です。

## javaインストール手順
###### 1. brewを更新
```shell
$ brew update
```
###### 2. brewのエラーチェック
```shell
$ brew doctor
```
###### 3. javaインストール
```shell
$ brew cask install java
```
###### 4. javaのバージョン確認
```shell
$ /usr/libexec/java_home -V
```
実行結果

```shell
Matching Java Virtual Machines (1):
    9.0.4, x86_64:	"Java SE 9.0.4"	/Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home
```
###### 5. PATHを通す
bash_profileが存在しない場合は作成します。

```shell
$ touch ~/.bash_profile
```
bash_profileをエディタで開き、以下のように追記します。
環境によりPATHは異なりますので、ご注意を…

```shell
export PATH=$PATH:/Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home/bin
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home
```
sourceコマンドでbash_profileの更新を反映します。

```shell
$ source ~/.bash_profile
```
以下を実行し、先ほど追加したディレクトリが表示されることを確認します。

```shell
$ echo $PATH
$ echo $JAVA_HOME
```

## 参考記事
[macにjava8をインストール](https://qiita.com/yanap/items/186d5bd1118f68f725d8)
[MacでのJava開発環境構築を通して「PATHを通す」意味を学ぶ](https://qiita.com/s_hino/items/a185deb4f9fc31c0f5e2)
[超初心者向け] Railsを使ってると出てくるGemって何？便利なGemリスト

# はじめに
Railsにはウェブアプリケーション開発の構築に必要なライブラリーという機能作成のパッケージみたいなものがあり、コマンド１つでダウンロード、設定して使用可能になるGemというコマンドがあります。ここではそのGemについて研究していきたいと思います。

# 設定環境
- OS
    - Mac OS X
        - 10.12.6
- Software
    - PostgreSQL
        - 10.1
    - Ruby
        - 2.5.0
    - Rails
        - 5.1.5

## 以下が便利Gemリストです。

https://ferret-plus.com/4883
Goutteでリクエスト時にPeer's Certificate issuer is not recognizedというエラーが出る時の対処法

Goutteを利用してリクエストを行った際に

```

[GuzzleHttp\Ring\Exception\RingException]
cURL error 60: Peer's Certificate issuer is not recognized.
```
といったエラーが出る場合、

```php
$client = new \Goutte\Client();
$client = $client->request('GET', $url);
```

から

```php
$client = new \Goutte\Client();
$client->getClient()->setDefaultOption('config/curl/'. CURLOPT_SSL_VERIFYPEER, false);
$client = $client->request('GET', $url);
```

といった形で証明書の検証を回避する必要がある。

・参考
[http://www.phppro.jp/qa/4507](http://www.phppro.jp/qa/4507)