OmniAICreator/Qiita-1.07M huggingface dataset:
SumとSummingIntくらべ

##実験してみました
比較対象は主にstreamの操作です.

以下では数値リストの足し算に
`mapToInt(v -> v).sum()`を使うか
`collect(Collectors.summingInt(Integer::intValue)))`を使うか

加えて、

中間操作と終端操作の処理内容を別関数に分けるか
すべて一つの関数でまとめるか

について比較しています.

```ProcessingTest.java
package mk42;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

public class ProcessingTest {
	public static void main(String[] args) {
		long startTime = System.nanoTime();
		run(generate.get());
		long endTime = System.nanoTime();
		Mk42.echo.accept("Processing Time : " + (endTime - startTime) + " ns");
	}
	/**
	 * Processing speed test.
	 *
	 * @param list
	 */
	private static void run(List<String> list) {
		try {
			// fastest
			Mk42.echo.accept(list.stream().filter(Objects::nonNull).map(add3.andThen(convertInt)).mapToInt(v -> v).sum());
			// normal
			Mk42.echo.accept(list.stream().filter(Objects::nonNull).map(add3.andThen(convertInt))
					.collect(Collectors.summingInt(Integer::intValue)));
			// bad
			all.accept(list);
		} catch (NumberFormatException e) {
			Mk42.echo.accept(join.apply(list));
		}
	}
	/** A series of processing */
	static Consumer<List<String>> all = v -> {
		Mk42.echo.accept(
				v.stream().filter(Objects::nonNull).map(x -> x + "3").map(Integer::parseInt).mapToInt(z -> z).sum());
	};
	/** Add 3 */
	static UnaryOperator<String> add3 = v -> v + "3";
	/** Convert to Integer */
	static Function<Object, Integer> convertInt = v -> Integer.parseInt(String.valueOf(v));
	/** Join with comma */
	static Function<List<String>, String> join = v -> v.stream().collect(Collectors.joining(","));
	/** Generate List which can convert to Integer */
	static Supplier<List<String>> generate = () -> Arrays.asList(null, "1", "2", "3", "4", "5");
}

```

ちなみにMk42とは

```Mk42.java
package mk42;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Answer to the Ultimate Question of Life, the Universe, and Everything.
 */
public class Mk42 {
	/** echo */
	public static Consumer<Object> echo = v -> System.out.println(v);
	/** not null */
	public static Predicate<Object> notNull = v -> Optional.ofNullable(v).isPresent();
	/** sum list */
	public static Function<List<Integer>, Integer> sum = v -> v.stream().filter(notNull).mapToInt(i -> i).sum();
	/** generate String list */
	public static Supplier<List<String>> strList = () -> Arrays.asList(null, "", " ", "a", "0");
	/** generate Integer list */
	public static Supplier<List<Integer>> intList = () -> Arrays.asList(null, 1, 2, 3, 4, 5);
}

```

##結果
<ul>
<li>操作分割 終端操作mapToIntからのsum<br>
処理時間：2261200 ns
<li>操作分割 終端操作collect<br>
処理時間：3573700 ns
<li>操作結合 終端操作mapToInt<br>
処理時間：16587300 ns
</ul>

##で？
操作の関数を分けたほうが早いみたいです.

今回のメインは終端操作なんですが
mapToIntよりcollectでのCollectors呼び出しのほうが遅いですね
オブジェクト呼び出してるから当たり前っぽいですね

細やかなことかもですが、似ている処理ならどちらのほうが処理速度が速いか
覚えていきたいものです
C#初心者の自分用メモ：最初に出てくるものの解読

#Unity C#にでてくる最初の構文を解読しました
以下、サンプルコード。

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class *** : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
    }
}
```
こちらのコードを部分的に解読しました。

*（注意）自分用のメモのため分かりやすさは追求していないです！！*

##using System.Collections; / using System.Collections.Generic; / using UnityEngine; について

「System.Collections」「System.Collections.Generic」「UnityEngine」は『名前空間』という。

名前空間とはクラスを種類ごとに整理する仕組みのこと。

ざっくり言うと、いろいろな機能があるお道具箱で、「System.Collections」「System.Collections.Generic」「UnityEngine」というお道具箱を使う（using）という意味の一文。

## public class *** : MonoBehaviour について
### public
「~~他のクラスから~~どこからでも見えるようにする」という意味の予約語。
予約語とは「その言語内ですでに役割があるからオリジナルでは定義できない」という約束があるもの。
これが無いと、Unityエディタで使えなかったり、他のクラスから中身が見えない状態になってしまう。
逆に、隠すことを明示する場合はprivateを使う。

### class ***
処理するデータとそれを処理する命令部分(メソッド）をひとつにまとめ（クラス）にするもの。
classに続く***が『クラス名』となり、このクラスを呼び出すことができる。
注意点としてUnityのルールでひとつの.csファイルで、ファイル名と同じクラスをひとつだけ宣言すると定めてあるので、それを守らないとエラーになる。

### : MonoBehaviour
この後にあるクラスから派生していることを示す。
つまりクラス***は次の「MonoBehabiour」と言うクラスから派生しているよ、という意味。
MonoBehaviourは、Unityで作られるゲーム中で出てくる物体などの動作のきっかけ(イベント)で動かす処理のかたまり（メソッド）等をつなぐ役割をする。
Unityで扱うオブジェクトは、このMonoBehaviourから自動的に派生するようになっている。

## void Start()とVoid Update() について
###void Start()
スクリプト起動直後に1度だけ実行したい処理を書く。

###void Update()
アニメーションなど「動かし続けたい」ものや、「ずっと処理し続けたい」ことを書く。
ゲームはフレーム単位ごとに更新され、その更新ごとにUpdate関数内の処理を繰り返してくれる。
nginx の名前解決について

nginx の名前解決について「えっ」という挙動があったのでメモ。
なお、ググると結構類似記事が出ていたので知っている人は知っているのかもしれません

# nginx は DNS レコードを TTL を無視し再起動(restart)もしくは設定更新(configuration realod)までキャッシュする

以下の nginx 公式ブログにも記載があります。

[Using DNS for Service Discovery with NGINX and NGINX Plus](https://www.nginx.com/blog/dns-service-discovery-nginx-plus/)

>NGINX caches the DNS records until the next restart or configuration reload, ignoring the records’ TTL values.

これはどういう時に問題になるかというと nginx から appliication server に接続を行う設定で、ホスト名でアクセスするような場合に問題が発生する可能性があります。

もう少し具体例を記載します。

+ nginx から application server へ example.com というホスト名で接続する
+ example.com で名前解決をすると複数の Priavte IP が返却される（例えば複数のサーバーで冗長構成されている）
+ この状態で一つのサーバーが何らかの原因で応答不能となる
+ 上記により example.com で名前解決をした時の PrivateIP から応答不能になったサーバーがなくなる(A レコードが削除される）
+ nginx は最初に名前解決をした結果をキャッシュする為、接続できない PrivateIP に接続してしまうが、当然応答が得られない
 
上記のようなシナリオが考えられます。
TTL がせっかくあるのでこれを見て欲しいのですが、nginx は見てくれない。。。

# どうするのか

上記ブログにいくつか方法が書いてあります。
自分の場合、`proxy_pass` を使っていたので `resolver` および `set` ディレクティブを利用する方法で上記例のような場合でも継続して接続ができる事が確認出来ました。
この場合、TTL が切れると名前解決するようです。

ブログより抜粋
>When you use a variable to specify the domain name in the proxy_pass directive, NGINX re‑resolves the domain name when its TTL expires. You must include the resolver directive to explicitly specify the name server (NGINX does not refer to /etc/resolv.conf as in the first two methods). 

```bash
# 公式ブログより抜粋
resolver 10.0.0.2 valid=10s;

server {
    location / {
        set $backend_servers backends.example.com;
        proxy_pass http://$backend_servers:8080;
    }
}
```

なお、`resolver`ディレクティブで valid について指定すると TTL を無視して指定した頻度で名前解決をするようです。


ブログより抜粋
>By including the valid parameter to the resolver directive, you can tell NGINX to ignore the TTL and re‑resolve names at a specified frequency instead. Here we tell NGINX to re‑resolve names every 10 seconds.

自分の場合、TTL を設定していたので valid は設定しないようにしました。

# 参考にさせて頂いた記事

+ [Nginxの名前解決についてまとめ](https://ktrysmt.github.io/blog/name-specification-of-nginx/)
+ [nginx の proxy_pass の闇](https://www.subthread.co.jp/blog/20190424/)
Jetson TX2 IP固定化

#Jetson TX2のIP固定化
諸事情でjetsonのIPを固定化する必要があり，ググった記事でまともに動いたものがなかったので
備忘録として....

##環境
●　Jetson TX2 (Ubuntu 16.04 LTS)

##まずやってみたこと
/etc/network/interfaces の編集
```$sudo nano /etc/network/interfaces
```

こんな感じに追記


```bash:/etc/network/interfaces
auto #####
iface ##### inet static
	address 192.168.1.###
	netmask 255.255.255.0
	gateway 192.168.1.1
	dns-nameservers 192.168.1.1
```

rebootしても固定化できてない....
##なんだかんだで最終的にできた方法
●ubuntuの設定（歯車みたいなやつ）の
 Hardware/Network/Wirelessタブから固定したいネットワークの＞をクリックして
 表示された詳細画面からSettingに入る
 connection name でSSIDの末尾に１とか２とか入っていないか確かめる（入っていたら消す）←重要
 あとはIPv4のsettingからお好みで....

##結論
terminalばっかり使ってると他のすばらしいGUIの存在に気付かなくなる
MySQLが死んだらやること Can't connect to local MySQL server through socket '/tmp/mysql.sock'

MySQLが
`Can't connect to local MySQL server through socket '/tmp/mysql.sock'`
だの
`ERROR! The server quit without updating PID file`
だの言われたときにやること。

macOS 10.14.5
MySQL 

#経緯

突然起動しなくなった。

```
$ mysql -u root -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
```
なんでや。

```
$ mysql.server restart
 ERROR! MySQL server PID file could not be found!
Starting MySQL
.. ERROR! The server quit without updating PID file (/usr/local/var/mysql/****.local.pid).
```

ググってみても、だいたいみんな再インストールとか言うやん。

https://qiita.com/carotene4035/items/e00076fe3990b9178cc0

やってみる

`$ sudo touch /tmp/mysql.sock`

見事に
`Can't connect to local MySQL server through socket '/tmp/mysql.sock'(38)　#2だったのが38に`
なりました。

`$ sudo chown mysql:mysql /tmp`

ダメでした。

#やったこと
###示されてるファイル ****.local.pid の確認

`/usr/local/var/mysql/****.local.pid` と言われているので、そのファイルを見に行く。（****は端末名）

```
$ ls /usr/local/var/mysql/
```

`****.local.err` はあるけど `****.local.pid` はない。
この.errファイルを確認する。

###****.local.err に記載のエラーログ確認
```
$ cat /usr/local/var/mysql/****.local.err
```

そうするとエラーの途中でサーバー起動できない理由みたいなのを言ってる。

```
 0 [ERROR] [MY-010270] [Server] Can't start server : Bind on unix socket: Address already in use
 0 [ERROR] [MY-010258] [Server] Do you already have another mysqld server running on socket: /tmp/mysql.sock ?
```

なんか他のプロセスが動いてるかもしれないって言われる。

###プロセスの確認

```
$ ps aux | grep mysql
```
で確認してみるも、`grep mysql` つまりこのコマンド自体しかいないので、実際は他のプロセスが動いてなさそう。

###/tmp/mysql.sock の移動

あちこちで言われている `/tmp/mysql.sock` がなんか悪さしてるようなので、取り除く。
いきなり削除してもいいんだけど、念のため

```
$ sudo mv /tmp/mysql.sock* ~
```
で別のところに退避。

tmp配下にmysql.sockがつくファイルがなくなったので、この状態で再度アクセスしてみる。

```
$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
```

いぇーい！

#結論

`/tmp/mysql.sock` をここから削除、または移動させる。

プログラムとmysqlの通信(unixソケット)を処理してくれるやつに、使っていないはずの接続設定が残ってしまっているので、取り除くことで新規に接続できるようになりました。

https://teratail.com/questions/121735
containerdについて備忘録

「dockerってなに?マジ意味わからん」って思った平成31年n月m日
今までdockerを使って開発していたが実際dockerについて何も知らないことが急に不安になった.
そこからdockerの資料を見てみるとこんな記事を見つけた
https://containerd.io/ この記事を読んで
「dockerの中身ってcontainerdってやつらしい」とわかった.
は?
「docker」いらなくね?って思ったのでcontainerdを触ってみた.

まとめ
dockerの中身が気になって調べたらcontainerdってやつがいい感じにコンテナ作ってることを知って興味が湧いて触ってみたくなった.

## なぜやる
dockerの中身が気になって調べたらcontainerdってやつがいい感じにコンテナ作ってることを知って興味が湧いて触ってみたくなった.

## どうやる
いろいろやる

## containerdとは
コンテナランタイムの一つでdockerの内部でつかわれている

## containerdをinstallする
想定はCentos7
installするならこれだけあれば大丈夫

```bash
$ yum update
$ yum -y install curl wget git vim
```
### containerdをダウンロードする
ちなみに最新版をバージョンを確認してダウンロードしてくるといいと思う
[リリース一覧](https://github.com/containerd/containerd/releases/)
記事を書いてる2019/04/10(水)時点での最新は`containerd 1.2.6`だゾ
構築してるときより進んでる....

```bash
$ wget https://github.com/containerd/containerd/releases/download/v1.2.4/containerd-1.2.4.linux-amd64.tar.gz
```
### ダウンロードしたcontainerdを解凍すると同時にパスが通ってるところに配置する
ここでは/usr/local/配下に配置する

```bash
$ tar zxvf ./containerd-1.2.4.linux-amd64.tar.gz -C /usr/local/
```
ちなみに解凍したファイルの中身は

```bash
$ tar zxvf ./containerd-1.2.4.linux-amd64.tar.gz
bin/
bin/containerd
bin/ctr
bin/containerd-shim-runc-v1
bin/containerd-shim
bin/containerd-stress
```
bin以下に入っているのでbinディレクトリを移動させればそれで良さそう
上書きされそうなので`bin/*`が無難な気がするが....

### containerdを起動させる
起動のやり方はいろいろあると思うけど
今回はserviceで起動できるようにする.　`$ containerd`とかマジ勘弁
serviceは->[containerd.service](https://github.com/containerd/cri/blob/master/contrib/systemd-units/containerd.service)を参考にかく

```bash
$ systemctl start containerd
```
Githubにpushしたときmasterがなかった話

## 概要
​
`git init` するときに気をつけないと、Githubにpushした際おかしなことになるよ、というお話。
​
## 詳細
​
#### sam init するときの通常手順
```
$ mkdir sam_sample && cd sam_sample 
$ sam init --runtime ruby2.5
```
​
この１行目のコマンドで一つ目のディレクトリを作り、２行目のコマンドでsam-appのディレクトリを作ります。
​
### ここで、 `git init` するときに気をつけたいのが、`sam-app` ディレクトリ内で `git init` すること！
​
`sam-app`　のなかでしないと、Githubにプッシュしたときに`master`が表示されないというおかしなことになります。。。
誰も同じことはしないと思いますが、備忘録として！
​
## それでもやっちまったよ！っていう方はこちら↓
​
① まずはリポジトリの中身を消去します。
② 先ほど`git init`したディレクトリ内で、このコマンドを打ちましょう

```
$ rm -rf .git
```
③ `sam-app` （または名前を変更していればそのディレクトリ内）に入り、再度`git init` !
​
これで、再度Githubにpushしましょう！
今度はうまくいくはずです！
CustomToken認証を行う際IAMが絡んでくるケースとその対応

# この記事について
Firebase/AuthenticationでCustomToken認証を行う場合
Tokenの作成方法は大きく3つありそれぞれの作成方法のメリデメ(感じてることベース)や
**Admin SDK にサービス アカウントを検出させる**方法を使用する場合IAMの設定が必要になり実際対応した時に出会したエラーや感じたことを記事にさせていただきました。


# CustomToken認証を使用するケース
Authenticationではメール/パスワード,SMSと言った頻繁に使われてそうなログイン方法や
Facebbook,Twitterなどのソーシャルログインを簡単に実装することができます。

がしかし、
InstagramのようにAuthenticationのログイン方法に用意されていない場合はどうしましょうか？

答えは、
カスタム認証を使用することです。
[Instagram で Firebase ユーザーを認証する](https://developers-jp.googleblog.com/2016/10/authenticate-your-firebase-users-with.html)

<img width="950" alt="スクリーンショット 2019-11-01 16.17.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75593/61e92031-46f8-7cf4-a2ab-18e854639a2a.png">
大まかなやりとりはこんな感じなのかな〜と言った具合の図です:sweat_smile:

# CustomTokenを作成する方法

CustomTokenは署名付きのJWT(Json Web Token)です。
CustomTokenの署名に使用される秘密鍵はGoogleServiceAccountに属しており
Firebase Admin SDKがCustomTokenの署名に使用するGoogleServiceAccountは大きく3つの方法で指定することができます。

## ServiceAccountJSONファイルを使用する


![スクリーンショット 2019-11-01 16.27.26（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75593/8dd2170b-f572-86b6-c68d-c81601bdddf8.png)
ServiceAccountJsonファイルはFirebaseConsole>Settings>全般よりダウンロードできます。

```typescript
const serviceAccount = require('service-account.json')
admin.initializeApp({
	credential: admin.credential.cert(serviceAccount)
})
```

メリット
・ダウンロードして読み込ませるだけなので設定が楽
デメリット
・管理はしっかり(うっかりするとサービスアカウントに関連する情報がみられる)
・Prod, Stg, Devなど複数環境必要とする場合読み込むJsonファイル指定やらの設定が必要(<-めんどい)

## サービス アカウント ID を使用する
```typescript
admin.initializeApp({
    serviceAccountId: 'your_project_id'
})
```

メリット
・ProjectIdを指定するだけなので設定が楽
デメリット
・Prod, Stg, Devなど複数環境必要とする場合読み込むJsonファイル指定やらの設定が必要(<-めんどい)

## Admin SDK にサービス アカウントを検出させる
Cloud FunctionsなどGoogleが管理する環境にデプロイされている場合
Firebase Admin SDKがローカルのメタデータサーバーよりServiceAccountIdを自動検出しIAMサービスと併用することでリモートでトークンに署名することが可能

```typescript
admin.initializeApp()
```

メリット
・Prod, Stg, Devなど複数環境対応が楽(<- 環境が増えるごとにコードを追加する手間からの脱却)
デメリット
・IAMの設定やらのエラーで最初困る(<- この記事を見ればきっと解決w)

# Admin SDK にサービス アカウントを検出させる時のエラー対応
> Error: Identity and Access Management (IAM) API has not been used in project {projectId} before or it is disabled...(省略)



>Enable it by visiting {url}

IAM APIを有効にする必要があります。

Errorの中にこのurlにアクセスしてIAM APIの設定をみてくださいな文が含まれてるので
IAM APIの設定を有効にしましょう
![スクリーンショット 2019-11-01 16.01.50（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75593/9c467fa1-e980-a060-0c9b-ce4c8714939d.png)

>Error: Permission iam.serviceAccounts.signBlob is required to perform this operation on service account projects/-/serviceAccounts/{project_name}@appspot.gserviceaccount.com

IAM APIを有効にしただけではまだ終わりません。
*{project_name}@appspot.gserviceaccount.com*に**サービス アカウント トークン作成者**の役割を付与する必要があります。

こちらはGCPConsoleで役割を付与してください
![スクリーンショット 2019-11-01 16.04.00（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75593/a70e6b84-5d5d-4b89-637c-4a7033f5df88.png)
カメラキャリブレーションを視覚的に理解する

カメラキャリブレーションはレンズの歪み補正などに使われますが、それぞれの係数がどう影響を及ぼしているのかわかりにくく感じます。

そこで直感的に理解できるようにしてみようと思います。

# カメラキャリブレーションとは
理想的なピンホールカメラモデルでない限り、左図のように画像は歪んでいます。
カメラ固有の歪み係数を求めることで、このように歪んだ画像を補正することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/5d7f33a9-b595-b007-118e-982c674e7ce5.png)

## カメラキャリブレーションの仕組み

カメラキャリブレーションを行う際は、チェッカーボードと呼ばれるものを印刷します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/92b49acc-d19c-0aea-39f2-b4e4dcb4980f.png)

パラメータを計測したいカメラでその写真をあらゆる角度から何十枚も撮影します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/4065ea34-e269-32c5-8d2f-f47ff209ba6f.png)


これでカメラの二次元座標 $x$ と空間の三次元座標 $X$ との対応が取れるようになります。

```math
x = P X
```

この $P$ がカメラマトリックスです。3行4列で、連立方程式で求まります。

```math
P = K [R|t]
```

$P$ は上三角行列 $K$ と正規直行行列 $R$ に分解することができて、

$K$ ...... 内部パラメータ、Intrinsic Parameter (焦点距離、光学中心、せん断係数)
$[R|t]$ ... 外部パラメータ、Extrinsic Parameter (カメラの回転と変換)

となります。

## 内部パラメータ

この内部パラメータ $K$ は

```math
K = \begin{pmatrix}
f_x & s & c_x \\
0 & f_y & c_y \\
0 & 0 & 1 \\
\end{pmatrix}
```

となっていて、焦点距離 $(f_x, f_y)$, 光学中心 $(c_x, c_y)$, せん断係数 $s$ を表します。

## 実装

PythonではOpenCVを使って以下のように $K$ (mtx)が求まります。 

```python
# チェッカーボードから点を検出
ret, corners = cv2.findChessboardCorners(gray, (8,6), None)

# キャリブレーション
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img_size,None,None)

# 歪み補正
dst = cv2.undistort(img, mtx, dist, None, newMtx)
```


# 直感的理解
それぞれ焦点距離、光学中心、せん断係数などのパラメータをアニメーションしてみましょう。
求めたカメラマトリックスから、対象のパラメータのみを変化させています。

## 元画像
![test_image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/0b0b198c-07a0-2934-09fc-00b12729b177.jpeg)


## 焦点距離
無限遠→適正焦点距離→小さい

(1) $f_x, f_y$
![cxcy.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/f27b0198-9da5-7a7d-20e0-6b15285ec780.gif)

(2) $f_x$
![fx.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/552076f1-0284-b351-646f-c4436e19a4bd.gif)

(3) $f_y$
![fy.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/f491c3ee-f847-d301-0bbd-9aca9bad680f.gif)

## 光学中心
負→適正位置→正

(1) $c_x$
![cx.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/f6643ebd-2b78-5a88-e883-658644a9efaa.gif)

(1) $c_y$
![cy.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/187493dd-ecb4-27c7-a834-00004e05608b.gif)

## せん断係数
負→適正値→正
![s.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404817/c9157d4b-7543-0fe5-2a7e-2abdea93ffef.gif)
英語ではSkewです。

# まとめ

いかがだったでしょうか。
カメラキャリブレーションは歪みの補正に使われるということがわかりました。

# フューチャーワーク

半径方向の歪み係数、円周方向の歪み係数についてもやりたいです。


# 画像引用
https://github.com/DavidWangWood/Camera-Calibration-Python
https://jp.mathworks.com/help/vision/examples/evaluating-the-accuracy-of-single-camera-calibration.html
uwsgi の uwsgi プロトコル通信を　uwsgi-tools で確認する

メモ。

以下のよう uwsgi を実行すると uwsgi プロトコルによる通信が出来る。

[Putting behind a full webserver](https://uwsgi-docs.readthedocs.io/en/latest/WSGIquickstart.html)

```bash
$uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
```

ただし、上記のような場合、クライアントからの接続テストが面倒そうだなと感じていた。

ググると以下の Github issue を発見

[ how to test uwsgi unix socket ? #1443 ](https://github.com/unbit/uwsgi/issues/1443)

上記に書いてあるように uwsgi-tools というのが便利みたいなので使ってみた。

[andreif/uwsgi-tools](https://github.com/andreif/uwsgi-tools)

# インストール

インストールは `pip` で可能

[uwsgi-tools 1.1.1 ](https://pypi.org/project/uwsgi-tools/)

```bash
$pip install uwsgi-tools
```

# 使い方

基本的な使い方は README に書いてある。

[andreif/uwsgi-tools](https://github.com/andreif/uwsgi-tools)

localhost で uwsgi プロトコルをリッスンしている場合、以下のようにして確認出来る。

```bash
$uwsgi_curl localhost:3031
HTTP/1.1 200 OK
Content-Type: text/html
```

リモートホストの場合にも以下のようにして接続テストが出来る。

```bash
$uwsgi_curl hogefuga:3031
HTTP/1.1 200 OK
Content-Type: text/html
```

# 参考

`import socket`をしており、socket 通信をしている模様。

https://github.com/andreif/uwsgi-tools/blob/master/uwsgi_tools/curl.py#L9

[The uwsgi Protocol](https://uwsgi-docs.readthedocs.io/en/latest/Protocol.html)

>The protocol works mainly via TCP but the master process can bind to a UDP Unicast/Multicast for The embedded SNMP server or cluster management/messaging requests.

以下あたりが勉強になりそう

[pythonでsocket通信を勉強しよう](https://qiita.com/__init__/items/5c89fa5b37b8c5ed32a4)
関数の引数をオプションにするには

#関数の引数をオプションにするには
引数のあとに「?」をつけることでその引数はオプションになる

ex)

```
function metasyntacticVariable(variable1: string, variable2?: string, variable3?: string) {
  return `1:${variable1} 2:${variable2} 3:${variable3}`
}
console.log(metasyntacticVariable())  //コンパイルエラー
console.log(metasyntacticVariable("foo")) //1:foo 2:undefined 3:undefined
console.log(metasyntacticVariable("foo", "bar", "baz")) //1:foo 2:bar 3:baz
```

• オプションにしないと引数が指定されてなかったときにコンパイルエラーが起こってしまう
  （variable1は?がついていない（オプションではない）ため、４行目のように指定していないとコンパイルエラーが起きる）
• オプションにして値が入力されてないとundefinedが出力される
• オプションで指定したものは指定した型だけではなく、undefinedも型推論に含まれる
　（ 指定した型|undefined になる）

##Weak Typeにおけるオプションの注意点
###そもそもWeak Typeとは？
Weak Typeとはオブジェクトを引数にとるときに、全てのプロパティがオプションになっているものを指す

ex)

```
interface Animal = {
 name?: string
 weight?: number
 feed?: array
}

function animalData(animal: Animal) {
 //処理
}
```

###Weak Typeのオプションについて
Weak Typeに、型を定義したものと合致しないもので構成されたオブジェクトを代入してしまうとコンパイルエラーになる
→つまり、型定義したときと同じプロパティが１つはないといけない

###exception
Weak Typeに、{}のような何も中身が入ってないオブジェクトを代入するときは、型定義しているときのプロパティとは一つも被ってないが、エラーにはならない
GCPのjavaクライアントライブラリからStackdriver loggingにエラーを投げてもStackdriver ErrorReportingには入らない

# 超概要
stackdriver loggingのJavaクライアントライブラリからLogbackを使って利用する場合にはErrorをLogに送っても、Stackdriver ErrorReportingの方にはそのまま入らない。（題名通り
通常はStackdriver loggingにError以上のLogを入れるとErrorReportingの方にも入るのだが（それから通知などに使える）
Javaクライントライブラリ（Logback使用)の場合はどうやっても入らなかった。
これにハマって色々と調べるとなかなかつらいことが判明。

## 経緯
時代にさかのぼってる感ありだが、最近Java（正確にはKotlin）で動くデスクトップアプリを制作している。
各ユーザーさんの環境で動くアプリケーションがどのようなエラーを吐いているかを見たいので、クラウドのロギングサービスを導入しようと思った。
ちょうどGCPを色々と試していた＆Stackdriver ErrorReportingはJavaで使ったことあったので、Stackdriver loggingを使うことにした。

## Stackdriver ErrorReportingを使ったとき
→Official
https://cloud.google.com/error-reporting/docs/reference/libraries?hl=ja
このままのコードでやると直接ErrorReportingには飛ばせるのだが、ロガーに追加して投げる処理を追加しないといけない。
これはなんか同じコードが各所で出てきて美しくない。（気がする。
なんとかして`logger.error("hoge error", exception)`
みたいな感じでファイルログと同時にErrorReportingできないものだろうか。

## Stackdriver logging with logback
→official
https://cloud.google.com/logging/docs/setup/java?hl=ja
LogbackのAppenderを作れば、`logger.なんたら`でそのままStackdriver loggingにも入れてくれる。
ここまではOK、ただし
https://cloud.google.com/error-reporting/docs/setup/java?hl=ja
にある通り、
> Stackdriver Logging を使用してエラーデータを Error Reporting に送信することもできます。データのフォーマット要件については、Stackdriver Logging でのエラー メッセージのフォーマットをご覧ください。

とあるんだが、何度やってもLoggingにエラー送ってもErrorReportingには何も入らない。
もうちょっと詳しく見てみると
> データのフォーマット要件については、Stackdriver Logging でのエラー メッセージのフォーマットをご覧ください。

エラーメッセージのフォーマット？
リンク先を見ると

```json
{
  "eventTime": string,
  "serviceContext": {
    "service": string,     // Required.
    "version": string
  },
  "message": string,       // Required. Should contain the full exception
                           // message, including the stack trace.
  "context": {
    "httpRequest": {
      "method": string,
      "url": string,
      "userAgent": string,
      "referrer": string,
      "responseStatusCode": number,
      "remoteIp": string
    },
    "user": string,
    "reportLocation": {    // Required if no stack trace in 'message'.
      "filePath": string,
      "lineNumber": number,
      "functionName": string
    }
  }
}
```

いくつか`required`のフィールドになっているが、Logbackからのloggingには該当するフィールドは入っていない。
(serviceContext > serviceが無いようだった）
たぶんこれかな、ということはわかったのでじゃあ設定でなんとかなるか、と思いきや。
Logbackのxml設定ではserviceContextとかもろもろを設定する項目はない！
ナンテコッタイ

## やろうとしたこと
https://cloud.google.com/logging/docs/setup/java?hl=ja#additional_fields_and_labels
この通り、`LoggingEnhancer`を作成してやればラベルとかは追加できるようだ。
ただこれもGCPのコンソールでの絞り込みで使えるだけでErrorReportingにはいかない。
かといってEnhacerにそれ以上カスタマイズできるようなコードは見当たらない…

## 結局は
さらに色々と調べるとこんなことも
https://github.com/googleapis/google-cloud-java/issues/4179
デフォではできないんかい！
で、このやりとりの中の別のIssueをたどっていくと
https://github.com/logstash/logstash-logback-encoder
こんなのも。
つまり、logbackのencoderのlayoutを直接いじるクラスを作ればErrorReportingに入るLoggingができるそう。
こちらもありました。
https://github.com/kurochan/logback-stackdriver-logging

## 結論
~~クライアントアプリケーションは難しい~~
javaクライアントライブラリがうまく対応してくれると嬉しい。
Ubuntuでlndとbtcdの環境を構築してみる

#はじめに
以前Ubuntuの19.04をインストールしていたが[]()こちらの記事を書くときに初期化して18.04をインストールすることになった。
せっかく初期化したのでbtcdとlndの環境構築をまとめてみる。
もうすでに[]()の[Installation]()でまとめてあるのだが、実際あんなにすんなり進まないこともよく知っている。
なので今回はなるべく[Installation]()通りに進めて詰まった箇所も含めてレポートする。

#環境
PC:Thinkpad X1 Carbon
OS:Ubuntu 18.04.3 LTS（初期化済み）


#Goのインストール

先ずはGo言語の1.11のインストールと書いてあるが最初のトラップがここにある。
Go1.11では確かlndかbtcdのbuildで失敗する。
知ってはいるが今回はわざと引っかかってみる。
めんどくさいって人は最初からGoの1.13以上をインストールすることを勧める。



'golfing-1.11-go'のパッケージが見つからないと出てきた。
これは予想外。とりあえずGoの最新版をインストールしてみる。

```
$ snap info go
```

を実行して最新のGoのversionを確認してみる。
2019/11/01現在では1.13.4がstable版らしい。


```
$ sudo snap install go
```

を実行。インストールが完了する。
バージョンを確認。

```
$ go version
go version go1.13.4 linux/amd64
```

正しくインストールされた。
次に`GOPATH`を設定する。


```
$ export GOPATH=~/gocode
$ export PATH=$PATH:$GOPATH/bin
```

をターミナルで実行。
これはターミナルを開くたびに毎回実行しないといけないのでめんどくさい。
なので、

```
$ vim .bashrc 
```

で`.bashrcファイルを開き、一番下の行に

```
# GOPATH setting
export GOPATH=~/gocode
export PATH=$PATH:$GOPATH/bin
```

を付け足し保存する。
これでGOPATH設定を毎回やらなくて済む。
次に`/gocode`ディレクトリを作る。

```
$ mkdir ~/gocode
```

Goの準備は完了。



# lndのインストール


手順通り、

```
$ go get -d github.com/lightningnetwork/lnd
```

を実行。しばらく待っても何も起こらないので心配になるがかなり時間差でインストールが完了する。

```
$ cd $GOPATH/src/github.com
```

表示されるパッケージ一覧で`lightningnetwork`の文字は見つかっただろうか。
ではbuildを始める。

```
$ cd $GOPATH/src/github.com/lightningnetwork/lnd
$ make && make install
```

エラーも出ず完了した。
`make check`は時間がかかるので割愛。

そのまま

```
$ make btcd
```

でbtcdのインストールとBuildをしてくれるので楽チン。
~~これでbtcdの環境も整った。~~


# 確認


```
$ btcd --testnet --rpcuser=kek --rpcpass=kek
```

でbtcdがtestnetのblockchainのフルノードを同期し始める。
手順どうり、進捗を`btcctl`で確認する。
別ターミナルを開いて

```
$ btcctl --testnet --rpcuserkek --rpcpass=lel getinfo
btcctl: command not found
```

失敗。
環境は整っていなかった…。
やはりbtcdのbuildが必要。

```
$ cd $GOPATH/src/github.com/btcsuite/btcd
$ GO111MODULE=on go install -v . ./cmd/...
```

これでbuild完了。

```
$ cd $GOPATH/src/github.com/lightningnetwork/lnd
$  btcctl --testnet --rpcuserkek --rpcpass=lel getinfo
```

btcctlもうまく動いた。

```
$ lnd --bitcoin.active --bitcoin.testnet --debuglevel=debug --btcd.rpcuser=kek --btcd.rpcpass=kek --externalip=127.0.0.1
```

表示された文字列に`Active chain:Bitcoin`の文字が見つかったらうまくいってるということでおけ。
ruby製静的サイトジェネレータjekyllをdocker-composeで起動する

会社を立ち上げたので会社サイトを作成するために静的サイトジェネレータを使用することにしました！
ruby案件お待ちしております！
使い慣れているrubyとdockerで立ち上げた記録です。

## 事前準備

```dockerfile:Dockerfile
FROM ruby:2.5
RUN apt-get update -qq
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

EXPOSE 4000
```

```yml:docker-compose.yml
version: '3'
services:
  web:
    build: .
    command: bundle exec jekyll serve --host=0.0.0.0
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
    ports:
      - 4000:4000

volumes:
  bundle:
```

`--host=0.0.0.0`がないと、localhostでアクセスできないので要注意です。
jekyllはデフォルトで4000ポートです。

```ruby:Gemfile
source "https://rubygems.org"

gem "jekyll"
```

空のGemfile.lockの作成

```bash
touch Gemfile.lock
```

## セットアップ

```bash
docker-compose build
```

generateコマンドでjekyllファイルを生成
`.`と`--force`でDockerfileなどと同じ階層に作成します。
`jekyll new mysite`のようにすると`mysite`ディレクトリに作成されます。

```bash
docker-compose run --rm web jekyll new . --force
```

```bash
$ pwd
corporate_site

$ ls
404.html  Dockerfile  Gemfile  Gemfile.lock  _config.yml  _posts  _site  about.markdown  docker-compose.yml  index.markdown
```
ファイルが作成されました！

## 起動

docker-composeを使用しているので、下記コマンドで起動可能です。

```bash
docker-compose up
```

http://localhost:4000
にアクセスします

![Screenshot from 2019-11-01 15-59-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93394/50f90855-60c3-4331-f78c-919fc624e905.png)

🎉🎉🎉
pulumiでリソース名にプレフィックスを付けない方法

# 概要

社内のAzure使ったりするときにリソースの命名規則があるので、自動リソース名についてくる`リソース名 + *******`のようなプレフィックスを取っ払いたかった

# 解決方法(TypeScript)

リソースのプロパティで`name`を指定してあげるだけでした。
[公式のドキュメント](https://www.pulumi.com/docs/reference/pkg/nodejs/pulumi/azure/core/#ResourceGroup)にも書いてあるしちゃんと読めよ！って話ですね...

```ts:index.ts
import * as pulumi from "@pulumi/pulumi";
import * as azure from "@pulumi/azure";

//  rg-test******* のようにプレフィックスがついてくる
//  const testResourceGroup = new azure.core.ResourceGroup("rg-test");

//  こっちだと rg-test のままで作成される
const testResourceGroup = new azure.core.ResourceGroup("rg-test", {
  name: "rg-test"
});
```

## まとめ

ドキュメントちゃんと読むようにします...

## 参考

- [Module core](https://www.pulumi.com/docs/reference/pkg/nodejs/pulumi/azure/core/#ResourceGroup)
- [Ability to fully control the name of resources · Issue #1518 · pulumi/pulumi](https://github.com/pulumi/pulumi/issues/1518)
input要素だけでcheckboxをカスタムしたい

```html
<input type="checkbox"/>
```


```SCSS

input[type='checkbox'] {
  appearance: none;
  outline: none;

  display: block;
  position: relative;
  text-align: center;
  cursor: pointer;

  width: 28px;
  height: 28px;
  margin: 0 auto;
}

// チェックボックスのデザイン
input[type='checkbox']::before {
  display: block;
  position: absolute;
  content: '';

  width: 28px;
  height: 28px;
  background: #fff;
  border: solid 2px #01a2c1;
  border-radius: 3px;
}

// チェックボックスの背景をチェック後に変更
input[type='checkbox']:checked::before {
  background-color: #01a2c1;
}

// チェックマークのデザイン
input[type='checkbox']::after {
  display: block;

  content: '';
  position: absolute;
  left: 10px;
  top: 5px;

  width: 8px;
  height: 16px;
  border-right: 3px solid #fff;
  border-bottom: 3px solid #fff;
  transform: rotate(45deg);

  // チェックしてないときは隠す
  opacity: 0;
}

// チェックするとチェックマークの透明化を解除
input[type='checkbox']:checked::after {
  opacity: 1;
}
```
Sapperでホットリローディングが効かない時の対処法

Svelteでウェブアプリをサクッと作ってみようと思ったので、ファイルの置き場所とかある程度決めてくれているSapperフレームワークを使おうとふと思った。

とりあえず[公式サイト](https://sapper.svelte.dev)にあるやり方でサクッとSapperを導入してみる。
導入時のバージョンは `Svelte: 3.12.1`,`Sapper: 0.27.9` 。

```bash
$ npx degit "sveltejs/sapper-template#webpack" my-app
$ cd my-app
$ yarn
$ yarn dev & open http://localhost:3000
```

<img width="996" alt="スクリーンショット 2019-11-01 15.22.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348096/b5456a85-8976-8041-6a7c-e8c36e55779e.png">
動いた。

デモページに `Try editing this file (src/routes/index.svelte) to test live reloading.` と書いてあるので、
その説明文を `Hallo Svelte World!` にでも書き換えて保存してみる。

... が、なぜかブラウザが自動更新してくれない。

ちょっと調べてみたら、どうもWebpackのHot Module ReloadingにSvelteが対応しきれてないっぽい。

- https://github.com/sveltejs/svelte/issues/2377
- https://github.com/sveltejs/sapper/issues/764

Sapper側でも自動読み込みライブラリを用意しているため、
Webpackの自動読み込みをオフにして、そちらを利用してやればいいとのこと。

`package.json`を開いて`scripts`の中の`dev:`プロパティを以下のように書き換えてやる。

```json
"dev": "sapper dev --no-hot"
または
"dev": "sapper dev --hot=false"
```

このコマンドで起動した後に`index.svelte`ファイルの文章を書き換えてみる。
<img width="996" alt="スクリーンショット 2019-11-01 15.34.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348096/b71093d6-346c-360c-8629-f4e199012f91.png">

無事に自動更新で文字が切り替わってくれた。
[ Android ] 画面回転に対応したレイアウト変更

本記事では画面回転によってレイアウトを変更する実装方法について述べる。

##前準備
まず端末の
「**設定**」→「**ディスプレイ**」→「**画面の自動回転**」を**ON**にして頂きたい。
これに気づかず、実行してもうまくいかなかった。
準備ができたら早速実装である。

##実装
　とはいうものの、かなり簡単である。
**「res」にlayout-landディレクトリを作り、
その下に横画面用レイアウトファイルを作る**
だけである。
landは「landscape」の略で、
要するに横画面という意味である。
縦画面用ディレクトリはデフォルトで入っているlayoutである。

・ディレクトリ構造図
res
 - layout 　　　-activity_main.xml（縦画面用レイアウトファイル）
 - layout-land　-activity_main.xml（横画面用レイアウトファイル）

これ以外は何もする必要はない。
（マニフェストなどもいじらない）

実行して、縦横を変えてみると、それに応じた画面が表示される。
以上。
コマンドプロンプトとPowerSHellによるファイルとディレクトリの検索


※文字列の検索にはWindowsの例によって大文字、小文字の区別は行われません。

##コマンドプロンプト##

```
 dir /b /s /A-D ファイル名
 dir /b /s /AD ディレクトリ名
```

####コマンドオプション####
 　/b：（パスを含む)ファイル名のみを表示する。
 　/s：ディレクトリも再帰的に検索する。
 　/A-D：ファイルのみを検索する
 　/AD：ディレクトリのみを検索する。

####ファイル検索####
```:例：index.htmlという名前のファイルを探す

 dir /b /s /A-D index.html
```

```:例2：ファイル名の後ろに「.txt」が含まれるファイルを探す
 dir /b /s /A-D *.txt
```
####ディレクトリ検索####

```:例：tmpという名前のディレクトリを探す
dir /b /s /AD tmp
```

```:例

rem 名前の一部に「system」を含むディレクトリを探す（部分一致検索)
dir /b /s /AD *system*

rem 名前の前方に「system」を含むディレクトリを探す（前方一致検索）
dir /b /s /AD system*

rem 名前の後方に「system」を含むディレクトリを探す（後方一致検索）
dir /b /s /AD *system
```


##【PowerShell】##
```PowerSHell
Get-Childitem -Path 検索開始位置 -Include 検索対象の一部 -Recurse -Name
Get-Childitem 検索対象 -Path 検索開始位置 -Recurse -Name [-Directory]
```

####コマンドオプション####
　-Path：検索開始位置
　-Include：ファイル名、ディレクトリ名の一部を含むもの
　-Recurse：ディレクトリを再帰的に検索する
　-Name：（パスを含む）ファイル名、ディレクトリ名のみを表示する。
　-Directory：検索対象をディレクトリとする。

####ファイル検索####
````PowerSHell:基本形
Get-Childitem 検索ファイル名 -Path c:\ -Recurse -Name
Get-Childitem -include ファイル文字列の一部 -Path c:\ -Recurse -Name
````
```PowerShell:ファイル検索の例
#名前が「windows.txt」のファイルを探す（完全一致）
Get-Childitem windows.txt -path c:\ -Recurse -Name

# 名前の一部に「windows」を含むファイルを探す（部分一致検索)
Get-Childitem -Include *windows* -Path c:\ -Recurse -Name

# 名前の前方に「windows」を含むファイルを探す（前方一致検索）
Get-Childitem -Include windows* -Path c:\ -Recurse -Name 

# 名前の後方に「windows」を含むファイルを探す（後方一致検索）
Get-Childitem -Include *windows -Path c:\ -Recurse -Name
```


####ディレクトリ検索####
````PowerSHell:基本形
Get-Childitem 検索ディレクトリ名 -Path c:\ -Recurse -Name
Get-Childitem -include ディレクトリ文字列の一部 -Path c:\ -Recurse -Name
```

```PowerShell:ディレクトリ検索の例
#名前が「system」のディレクトリを探す（完全一致）
Get-Childitem system -path c:\ -Directory -Recurse -Name

# 名前の一部に「system」を含むディレクトリを探す（部分一致検索)
Get-Childitem -Include system -Path c:\ -Directory -Recurse -Name

# 名前の前方に「system」を含むディレクトリを探す（前方一致検索）
Get-Childitem -Include system* -Path c:\ -Directory -Recurse -Name 

# 名前の後方に「system」を含むディレクトリを探す（後方一致検索）
Get-Childitem -Include *system -Path c:\ -Directory -Recurse -Name
```
バッチファイルでSSHの認証プロキシの設定を有効・無効にする

# バッチファイルでSSHのプロキシ設定を有効・無効にしたい

バッチファイルでSSHのプロキシ設定を有効にしたり、無効にしたりできないか調査したところ、以下の記事を見つけました。

[sshのプロキシ環境を自動切り替え](http://joker.hatenablog.com/entry/2014/11/20/010612)

こちらと同じことをWindowsでもやれないか試してみました。
Macの場合は上記の記事をご参照ください。

# 2種類の `config` ファイルを用意する

SSHの設定ファイルをプロキシ無効時用・有効時用の２種類用意します。

例としてGitHubに接続する場合を考えます。


## `config_no_proxy.txt` を用意する

まず、 `%USERPROFILE%\.ssh\config_no_proxy.txt` というファイルを作成します。これはプロキシ無効時に利用する `config` ファイルです。

```config:config_no_proxy.txt
Host github.com
    HostName ssh.github.com
    User git
    Port 443
    IdentityFile "C:\Users\ユーザー名\.ssh\id_rsa"
```


`IdentityFile` には、 `%USERPROFILE%\.ssh\id_rsa` や `~/.ssh/id_rsa` といった記述は使えず、 `C:\Users\ユーザー名\.ssh\id_rsa` のようにフルパスで記述する必要があります。（少なくとも私の環境ではそうでした）


## `config_proxy.txt` を用意する

次に、 `%USERPROFILE%\.ssh\config_proxy.txt` というファイルを作成します。これはプロキシ有効時に利用する `config` ファイルです。

```config:config_proxy.txt
Host github.com
    HostName ssh.github.com
    User git
    Port 443
    IdentityFile "C:\Users\ユーザー名\.ssh\id_rsa"
    ProxyCommand connect.exe -H ユーザー名:パスワード@ホスト:ポート %h %p
```

`ProxyCommand` という行が追加されています。この行に登場する `ユーザー名` , `パスワード` , `ホスト` , `ポート` には、プロキシの設定値を入力してください。


## バッチファイルでプロキシを無効にする

プロキシを無効にしたい場合は、 `%USERPROFILE%\.ssh\config` のシンボリックリンク先を `config_no_proxy.txt` にします。

以下のバッチファイルを **管理者権限** で実行してください。

```bash:disableProxy.bat
rem 既存のシンボリックリンクを削除する
del %USERPROFILE%\.ssh\config

rem config_no_proxy.txt にリンクを貼る
mklink %USERPROFILE%\.ssh\config %USERPROFILE%\.ssh\config_no_proxy.txt
```

これで、プロキシが無効になりました。


## バッチファイルでプロキシを有効にする

プロキシを有効にしたい場合は、 `%USERPROFILE%\.ssh\config` のシンボリックリンク先を `config_proxy.txt` にします。

以下のバッチファイルを **管理者権限** で実行してください。

```bash:enableProxy.bat
rem 既存のシンボリックリンクを削除する
del %USERPROFILE%\.ssh\config

rem config_proxy.txt にリンクを貼る
mklink %USERPROFILE%\.ssh\config %USERPROFILE%\.ssh\config_proxy.txt
```

これで、プロキシが有効になりました。


# さいごに

バッチファイルでSSHのプロキシ設定を有効にしたり、無効にしたりできるようになりました。

以下の記事を参考にさせていただきました。ありがとうございました。

- [sshのプロキシ環境を自動切り替え](http://joker.hatenablog.com/entry/2014/11/20/010612)
- [22番ポートが使えなくても、SSHでGitしたい！](https://qiita.com/306_san/items/28c36e52346f315d0860)
- [【GitHub】Windows10+プロキシ環境でSSH接続を試みた話](https://qiita.com/_N4H4/items/d48ba7c728f2e1ebd159)
Windows2008 R2 更新プログラムのリモートアンインストール

Windows更新プログラムをインストールしたらログオンできなくなった時のお話しです。
正しくは、ログオンするとブルースクリーン（BSOD）に陥るようになってしまいました。

何度かログオンしているうちに、「GUIログオンしなければ落ちない」ということに気づきました。

古典的ですが、Telnetサーバーでの操作は可能なのでは？と考え、作業に移ります。（残り作業時間 1.5H．．．）

#####１．Telnetサーバーをインストールする簡単なPowershellを作成し、対象サーバーの管理共有に放り込みます。

`Import-module ServerManager`
`Add-WindowsFeature Telnet-Server`

#####２．作業端末のMMCより対象サーバーのタスクスケジューラスナップインを追加

#####３．１のPowershellを実行するタスクを作成する
　　コマンドは powershell パラメータとして１のファイル名
　　（手動実行してしまうのでスケジュールはなんでもよい）

#####４．作成したタスクを右クリックして、「今すぐ実行」

#####５．作業端末のMMCより対象サーバーのサービススナップインを追加

#####６．Telnetサービスは初期状態で無効化されているので、「手動」にし、開始する。

#####７．TeraTermやTelnetクライアントでログオン

#####８．wusaコマンドでパッチのアンインストール
　　wusa /uninstall /KB:<KB番号（数字部分のみ）> /quiet /norestart
　　※wusaコマンドは投入後、すぐに復帰してしまうので、複数アンインストールする場合はstart /waitでwusaの戻りを待機するとよい
　　　例）start /wait wusa /uninstall /KB:4042076 /quiet /norestart

#####９．再起動
　　shutdown /r /t 0

GUIログオン後、動作確認して何とか終了。。。
CloudWatchLogsのログをElasticSearchに流す

# 概要
CloudWatchLogsからElasticSearchにログを流します。
ログを流す際にLambdaを経由する形になります。

<img width="1408" alt="スクリーンショット_2019-11-01_14_49_39.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47882/a5a1be1d-df65-425e-c259-1fd65786c6a5.jpeg">

CloudWatchLogsのアクションからロググループを選んで「Amazon Elasticsearch Serviceへのストリーム」を選択します。

あとは画面に従って設定するだけです。

# 注意点

## ロール
VPC内のElasticSearchに書き込みたい場合はLambdaにAWSLambdaVPCAccessExecutionRoleをつけましょう。

## セキュリティーグループ
ElasticSearchにアクセスできるようにセキュリティグループを設定してください。

## Lambdaの関数が古い
ElasticSearchにCloudWatchLogsのログを投げるNode.jsで書かれているLambdaの関数がES7.xに対応していないのでLogの流し込みに失敗する場合があります。

具体的にはElasticSearchのindexのマッピングをdynamicではなく、自分で指定した場合に、index._typeがlogEvent.logGroupとなっていますが、ElasticSearch7.xでは複数の_typeに対応していないために落ちます。ここは

```js
        var action = { "index": {} };
        action.index._index = indexName;
        action.index._type = '_doc'; // changed for ES 7.x
        action.index._id = logEvent.id;
```
として、変更しておきます。
spdlog(fmtlib)で std::vector を扱う.

## 背景

spdlog(or fmtlib の `fmt::print`) で, std::vector の数値配列をロギングしたり(行列とか)したい.

## 方法

spdlog で, fmtlib を有効にしているものとします.

fmtlib の join を使うのが楽でしょうか.
 
https://github.com/fmtlib/fmt/issues/562

```
std::vector<float> values{0.0f, 0.2f, 0.3f};
fmt::print("values = [{}]", fmt::join(values, ", "));

// values = [0.0, 0.2, 0.3]
```

同様にして, `std::array` も扱うことができます.

ありがとうございます.
[ Android ] レイアウト調整

本記事ではAndroidレイアウトを
実装によって調整する方法を記す。
主にTextViewについて述べる。

##位置
まずは基本中の基本である。以下のようなコードを追加する。
レイアウト内での位置を決めることができる。
・layout_marginStart：左端からx dpの位置
・layout_marginTop  ：上端からx dpの位置

~~~
<TextView
        android:layout_marginStart="2dp"
        android:layout_marginTop="230dp" />
~~~

##幅・高さ
以下のようなコードを追加する。
・layout_width ：横幅を決定
・layout_height：高さを決定

~~~
<TextView
        android:layout_width="406dp"
        android:layout_height="255dp" />
~~~

##文字のセンタリング（中央寄せ）
以下のようなコードを追加する。

~~~
<TextView
        android:gravity="center_horizontal" />
~~~

ここに"left"を指定すると左寄せ、
"center_vertical"を指定することもできる。

##枠の最大幅の指定
以下のようなコードを追加する。
最大幅は40 dpで4行まで表示できる。
文字が最大幅を超えると自動的に改行される

~~~
<TextView
        android：maxWidth =" 40dp "
        android:lines="4" />
~~~

##文字列の改行
指定した位置で改行したい場合は
表示文字列の改行したい部分で\nを入れるだけである。

~~~
<TextView
        android:text="Text\nView" />
~~~

##一行表示
TextViewの最大幅を超える文字列の場合、「…」と表示したい場合がある。
そんな時は以下のようなコードを書く。

~~~
<TextView
        android:ellipsize="end"
        android:singleLine="true" />
~~~

ellipsizeがendの時は文字列の後ろに「…」が表示される。
ellipsizeにはいくつか指定できる。
以下がそのオプションである。

・none   ：表示なし
・start  ：…xxxxx
・middle ：xx…xxx
・end    ：xxxxx…

以下のサイトがとても参考になった。
https://qiita.com/tamappe/items/b90770064007842c06d2

##まとめ
　今回はTextViewについて記したが、ImageViewやButtonにも使えるものがあるので
ぜひ試していただきたい。
　また、本記事では述べていないが、javaファイルから指定出来たりもするので、
参考にして頂けたらと思う。
　以上。
int(num)とmath.trunc(num)とnp.trunc(num)

## `bresenham`を使いたい
座標値がまとまったものを`bresenham.bresenham`に突っ込みたかったが`bresenham`はint型しか受け付けていなかった。

> truncateは0方向に丸める関数


## 検証
計測は[GoogleColab](https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja)を使用
前準備として読み込みとかをする

```python:base.py
import math
import numpy as np

foo = [0.0001* i for i in range(1000000)]
```

### `int(num)`
```python
%%timeit
for i in foo:
    tmp = int(i)
=>10 loops, best of 3: 105 ms per loop
---
type(tmp)
=>int
```

### `math.trunc(num)`

```python
%%timeit
for i in foo:
    tmp = math.trunc(i)
=>10 loops, best of 3: 107 ms per loop
---
type(tmp)
=>int
```

### `np.trunc(num)`

```python
%%timeit
for i in foo:
    tmp = np.trunc(i)
=>1 loop, best of 3: 831 ms per loop
---
type(tmp)
=>numpy.float64
```

### 結果
int(num) ≒ math.trunc(num) >> np.trunc(num)
と考えて良さそう
ディープラーニングのテストの品質保証に関する考察

#あなたは誰？
8年ほどソフトウェアQA→起業、プログラマ経験のあるフリーランスです。
どっちかっていうとIT寄りで、QMSを求められる産業におりました。
AI開発の現場には携わったことはありません。

#この記事を書こうと思ったきっかけ
昨今ディープラーニング(以下、DLという)を活用した様々なサービスが提供されていますが、サービス開発している社長様と「作るのはいいけれど、品質保証はどうするねん？」ということでディスカッション（≒雑談）していました。
ここで、そういえばDLの品質保証ってどういうことが考えられるかな？と気になったのがきっかけです。
ということで、まずは画像認識のディープラーニング製品のテストフェーズという仮定で、テストの品質保証ついて思いつくまま考察してみました。

DLが注目されてから随分時間が経つため数多く議論されている話題かとは思いますが、何かのお役に立てれば幸いです。

#用語の定義
・本投稿におけるテストとは、製品レベルでの検証行為を想定します。プログラムモジュール単体ではありません。
・本投稿における品質保証とは、製品実現のために必要な行為全般の保証を示し、本投稿では専らテスト工程の品質保証について考察したものです。

#免責事項
あくまで第三者から見た考察なため、実際の開発現場の方からは過不足のある部分があるかと思います。その際はご容赦いただき、特に不足部分、誤りについてはコメントなどいただけると幸いです。


#DLのテストの最大の特徴
最大の特徴は、テストにおいて出力の期待結果(基準解)を人間が導出できるか否かではないでしょうか？
DL(画像認識によって猫の顔を認識させる場合)のテスト工程を、ざっくり以下の通り仮定します。

1. 学習用にアノテーションデータを用意する
2. 学習させる
3. テスト用の入力画像によりテスト実行する
4. OK/NG判定　期待解通りに認識しているか否かを確認する



※参考としてTensorflow,Kerasにより猫を認識させた結果を載せます↓
<img width="501" alt="101result.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521602/a7edb06a-11f3-d53e-d66c-615da9f4ba59.png">

#DLのテスト品質保証に関する考察
ここからが本題になります。各工程でどのように保証できるかを考察してみました。

##1. 学習用にアノテーションデータを用意する
・どのアノテーションデータを使用したのか？
・誰が、いつ、どのツールを用いたか？特に、医療画像をアノテーションする場合は適切な人物が実施したかどうかも管理が必要と思われます(専門医などでしょうか？)。

ただし、数百〜数千枚の教師用画像を１枚ずつ記録すると大変なので、100枚ごとに管理するなどまとめるのが現実的ではないでしょうか。


##2. 学習させる
学習に用いたプログラムのバージョンを管理する必要があるでしょう。


##3. テスト用の入力画像を用いてテスト実行する。
この工程では、テストに用いた画像セットが特定できるよう管理しておく必要があります。


##4. OK/NG判定
ここがDLテストの品質保証での悩みどころなのでは無いでしょうか？
というのも、従来のプログラムとは異なり基準解を人間が用意することが困難なためです。
(上図の例でも、catfaceのスコアが幾つになるべきかを手計算で求めるのは困難かと)

ということで、テスト基準解を考えてみます。
私の現状持ち得る案は以下の２通りになります。
i)期待した通りに猫と判別してくれること。上図の場合は、四角で判定してくれること。タグの後ろに導出されるスコアは考慮しない。
ii)期待した通りに猫と判別してくれ、かつ全てのスコアが○○以上であること。

といったところでしょうか。

さらに、テスト用入力データの何％が基準解(i,ii)を満たすべきか、も設定する必要があると思いますが、これはシステムで求められる精度によって決めることになると思います。
例えば、医療画像の診断装置であれば、
　・人間の正答率より高いこと(≒誤診率が人間より低いこと)または
　・あらかじめ正解が分かっているものは100%正答率であること
というところを議論する必要があります。

#まとめ
以上、現時点でのAI製品テストの品質保証に関する考察をまとめてみました。

AIを医療、交通といった社会的なインフラに活用する場合にはどうしても気になってしまうポイントかなと思いました。何かのお役に立てたら幸いです。
初心者に5分でTomcatとApacheの再起動について説明する絵

# 経緯
新人にwarファイルのデプロイ作業を依頼したところ、TomcatとApacheを再起動しようとしました。（手順書が悪いのですが）
そこで、大雑把に仕組みと行うべき作業を絵を描いて説明しました。（ネットにある画像では詳しすぎて難しいので）

# 環境
　アプリケーション・・・JSFで構築
　サーバー1台でApacheとTomcatが同居
　サーバーは共有で他システムも利用している

# 依頼した作業
　手順書を見ながらビルド済みのwarファイルを既存のものと入れ替えて動作テストする

# 行われた手順
　１）サーバーにログイン
　２）warファイルを直接上書き
　３）サービス管理画面でTomcatとApacheを再起動　※他アプリがあると問題

# 伝えたかったこと
　・そもそもApacheとTomcatって何？
　・ApacheとTomcatを再起動すると何が起こるのか（何が問題なのか）
　・どうすればよかったか

# 描いた絵（10分くらいで作成）
![apacheとtomcat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467228/179094e3-256a-7576-8472-7fa6f0fff079.png)


# 最後に
　色々端折ってかなり大雑把に描いています。
　初めて説明する時はこのくらいで良いかなと思いますがどうでしょうか。
MySQL かんたんにテーブルのid番号を1からリセットする方法 

# MySQLのid番号　リセット方法

MySQLには初期設定でauto-increment機能が設定されています。
簡単にいうと「自動連番機能」です。

ただ番号間にあるレコードを消すとそのid番号のみが欠番となったまま、無視され、最後の番号から連番されてしまうため、テーブル管理において不都合なことが生じる場合があります。

そこで本記事では
###「id番号を１から振りなおす方法」をご紹介いたします。

方法のみ知りたい方は以下のリンクをクリック
### [方法へジャンプ](#リセット方法)

## 状況:
たとえばこんな感じのテーブルがあり、id番号が順番に振られています。

| id | name        |
|:---:|:----------:|
| 1   | ANA        | 
| 2   | DELTA      | 
| 3   | JAL        | 
| 4   | UNITED     |
| 5   | VANILA     |
| 6   | PEACH      |

しかし、いくつかレコード削除などによって欠番が生じると下のような順番になります。

| id | name        |
|:---:|:----------|
| 1   | ANA        | 
| 3   | JAL        | 
| 4   | UNITED     |
| 6   | PEACH      |

上の状態でさらにレコードが追加となると下のような連番となります

|  |        |
|:---:|:----------|
| 7   | Sky Mark  　|
| 8   | Jet star   |

歯抜になってしまったid:2と5は欠番となったまま。

静的なテーブルでこのid番号を1から振り直す方法がないものか探した結果、なんとかできる方法に行き着いたのでご紹介します。


# リセット方法
ターミナル上で
### 1.mysqlに入る(コピペするときは$は除いてください)

``` code:terminal 
$ mysql -u root -p 
```

パスワードは基本的には空のままEnterでOK
### 2.データベースを選択

```　code:mysql
mysql> use データベース名
```

### 3.テーブルのidを定義し直す

``` code:mysql 
mysql> set @n:=0;
mysql> update`テーブル名` set id=@n:=@n+1; 
```

### 4.確認

``` code:mysql
mysql> select*from テーブル名; 
```

以上の操作でidの番号を振り直すことができたはずです。

基本的にはレコードが入っているテーブルにて以上の方法を試してみてください。レコード追加のない静的なテーブルでは基本的に以上の方法でOKです。

## がしかし、
レコードが追加されるようなテーブルでは、上記リセットをかけても次のid番号は、もともと最後に入っていたレコードの次の番号からになってしまうため、mysqlのauto_increment自体をリセットする必要があります。

## 方法2
そんな時は以下の２つの方法を状況に応じて試してみてください。


## 1.レコードがすべて空の状態からリセットしたい
レコードが空であれば、

```　code:mysql
ALTER TABLE `テーブル名` auto_increment = 1;
```

でOK。初めのレコードをid:1で始めると言う意味です。
## 2.レコードが複数存在する状態で最後のidの次から連番にしたい
本記事上部の[連番リセット方法](#リセット方法)でレコード番号を振り直しをしたあと、

```　code:mysql
mysql> select*from テーブル名; 
```
でid番号を振り直したテーブルを確認し、例えば下のテーブルなら本記事の[リセット](#リセット方法)のみだとレコードを追加した時、真ん中のような連番になってしまいます。
一番右のようにするためにはmysqlのauto_increment（連番機能）の番号を更新する必要があります。

![無題の図形描画 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513524/f6b96dbf-09b6-4d18-0884-1409af033ec1.png)

### このテーブルのauto_incrementも修正しよう。

```　code:mysql
ALTER TABLE `テーブル名` auto_increment = 開始したいid番号;

つまり今回の場合であれば

ALTER TABLE `テーブル名` auto_increment = 5;
```

でOK。レコードを追加した際、5,6,7,,,,,と連番になるはずです。

＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊
プログラミング初級者が自身の備忘録も兼ねて書いた記事ですのでご指摘等ありましたら気軽にコメントください。なにか同様の問題でお困りの方にお役に立てたら嬉しいです。

テーブルのリレーションによっては本記事の番号振り直し自体がエラーになる場合がありますので、テーブル同士のリレーションおよび関係性を確認して記述の修正、一時コメントアウト等適宜行い、実行してください。
三項演算子

#三項演算子とは？

三項演算子とは、if条件式を1行だけで書く方法です。

基本的な文章は次の通りです。

```
条件式 ? true時の値 : false時の値
```
***2つに分岐する時***に使用することができます。

#具体的な書き方

例えば、以下のような条件式があったとします。

```ruby
if num == 10
 puts "数字は10です"
else
 puts "数字は10ではありません"
end
```

numの値が10かどうかで出力する文章を変える条件式ですが、これを三項演算子で書くと次のようになります。

```ruby
num == 10 ? puts "数字は10です" : puts "数字は10ではありません"
```

という風に短縮して書けます。
プログラミングは短く簡潔に書く事が大事ですので、こういった手法もどんどん取り入れていくと良いです。
B - Card Game for Two　解説

# はじめに
https://atcoder.jp/contests/abc088/tasks/abc088_b
の提出済みの優秀な方(cimaさん)のコードを解説。


# 問題
**【問題概要】**
$N$ 枚のカードがあり、$i$ 枚目のカードには $a_i$ という数が書かれています。
Alice と Bob はこれらのカードを使ってゲームを行います。ゲームでは 2 人が交互に 1 枚ずつカードを取っていきます。Alice が先にカードを取ります。
2 人がすべてのカードを取ったときゲームは終了し、取ったカードの数の合計がその人の得点になります。2 人とも自分の得点を最大化するように最適戦略をとったとき、Alice は Bob より何点多くの得点を獲得できるかを求めてください。

**【制約】**

+ $N$ は $1$ 以上 $100$ 以下の整数
+ $a_i$ は $1$ 以上 $100$ 以下の整数

**【数値例】**
1)
　$N = 3$
　$a = (2, 7, 4)$
　答え: $5$

以下が最適です:

+ 1 ターン目: Alice が 7 を取る
+ 2 ターン目: Bob が 4 を取る
+ 3 ターン目: Alice が 2 を取る

Alice は 7 + 2 = 9 点、Bob は 4 点を獲得するので、その差は 9 - 4 = 5 点です。

-----

# 完成コード
```
input();*a,=sorted(map(int,input().split()))[::-1]
print(sum(a[::2])-sum(a[1::2]))
```

# メモ
"*a,=…"が何を表しているのかわからなかったけどやりたいことはわかったのでメモ。

まず最初のNはいらないのでinput()を空打ちして捨てる。
次の数字列は使うのでmap()とsplit()を使ってint型のリストにしてリストaに格納する
で、これをsorted()[::-1]にぶちこんで降順にソート。
※交互に高い数値からとりあうのであれば降順にとることになるため

ここから先手と後手で交互に数字を取り合うわけだけど、
pythonだとリストの値をskipしながら取れるので
先手は、頭から１つ飛ばしで要素を参照するのでa[::2]
後手は、頭の一つ後から１つ飛ばしで要素を参照するのでa[1::2]
でこれをsum()で合算したものを引き算したら問題の解答が出る。
初めてのVulkanプログラミング step5 シェーダファイルのロード

前回作成した、frag.spv,　vert.spvファイルを読み込みます。まず単純なファイルからバイナリーをロードするヘルパー関数を使います。

```cpp
std::vector<char> ReadFile(const std::string& filename) {
	std::ifstream file(filename, std::ios::ate | std::ios::binary);

	if (!file.is_open()) {
		throw std::runtime_error("Don't read" + filename);
	}
	size_t fileSize = (size_t)file.tellg();
	std::vector<char> fileBuffer(fileSize);
	file.seekg(0);
	file.read(fileBuffer.data(), fileSize);
	file.close();
	return fileBuffer;
}
```

ReadFile関数は、すべてのバイトを読み込み、それをstd::vectorの配列に渡す関数です。

ifstream は、ファイルの読み出しに使うクラスです。
逆に書き込み専用のファイルストリームはofstreamとなります。

- ate : 最後の行から読み込む。
- binary : バイナリーファイルとして読み込む(文字として読み込むのを防ぐ)

ファイルを最後から読んだ理由は、ファイルのサイズを調べることが目的です。file.tellg()を使うことで、現在の読み込み位置を取得できます。

```cpp
    size_t fileSize = (size_t)file.tellg();
    std::vector<char> fileBuffer(fileSize);
```

ファイルの読み込み位置を**seekg(0)**を使い最初からにした後、ファイルを読み込みます。

```cpp
    file.seekg(0);
    file.read(fileBuffer.data(), fileSize);
```

作成した関数を使い２つのシェーダーを呼び出します。

```cpp
void Shader::_init_shaderModule()
{
	std::vector<char> _VertShader;
	std::vector<char> _FragShader;

	_VertShader = ReadFile("vert.spv");
	_FragShader = ReadFile("frag.spv");

}
```
[Xcode] Fabric CrashlyticsのInfo.plistエラー

XcodeでiOSアプリをビルドしようとしたら、FabricのRun Scriptで `Info.plist` が処理できないという内容のエラーが発生しました。

![スクリーンショット 2019-11-01 11.15.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27943/e8d9efe4-e88c-c73c-379a-ac3c5bd0df7e.png)


## 環境

```
❯ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.6
BuildVersion:	18G103

❯ xcodebuild -version
Xcode 11.1
Build version 11A1027
```


## 解決方法

> Running upload-symbols in Build Phase mode
Validating build environment for Crashlytics...
error: Info.plist Error Unable to process Info.plist at path /Users/foo/Library/Developer/Xcode/DerivedData/AppName-ahatoqxnbwihhoeagicyyimrmwbl/Build/Products/Release-iphonesimulator/AppName.app/Info.plist
This could be a timing issue, make sure the Fabric run script build phase is the last build phase and no other scripts have moved AppName.app from the location Xcode generated it. You can also add '＄(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)' as an "Input Files" dependency for your Fabric run script build phase.

タイミングが原因の可能性があるとのことで、以下の解決策が提示されました。

- Run Scriptを `Build Phases` の最後のフェーズに移動
- Run Scriptの `Input Files` に `＄(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)` を追加

自分の環境では、どちらの方法を試してもビルドが通るようになりました。

※ [Fabricは2020年3月末でdeprecatedになる](https://get.fabric.io/roadmap)ため、Firebaseへの移行が必要になります