OmniAICreator/Qiita-1.07M huggingface dataset:
IoTでスポーツのフォームを改善しよう！


スポーツIoTLT　vol.1で発表したネタです

発表資料全体は[こちら](https://speakerdeck.com/9wick/kireina-huomuwo-qiu-mete)

# 背景

**ゴルフって何が難しいんでしょう？**

- ボールは止まってる
- 誰も邪魔してこない
- 駆け引きもない

でもなぜか空振りをします。止まってるボールなのにおかしいですねぇ・・・。

その答え（というかスポーツの根源？）として、武井壮さんのこの言葉が結構印象に残ってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/9704a515-efec-d4a7-9549-5c35121cea6f.png)

逆に言うと、**<font color="red">人は思ったとおりに体を動かせてない</font>**ってことです。
なので空振りをするわけです。

どれぐらい自分が思ったとおりに動かせているのか、Youtubeでプロ人と比較をしてみると・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/92b928bf-d425-0736-f7b1-fc47d5345401.png)

全然駄目ですね。

というわけで、思ったとおりに自分の体を動かすために、
プロの動作の完璧な真似するツールを作ってみます

# つくったもの

プロと同じ動きができているかの判定機を作りました
肘が同じ動きができている→肘の色が黄色に。
肘が違う動きをしている→肘の色を赤にしています。

※youtube動画で再生しながら判定できるのですが、さらに画面録画をしようとするとメモリ不足で無理だったので、動画は止まった状態になっています。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">1ヶ月前に作ったスイング判定機　<a href="https://twitter.com/hashtag/AdventCalendar?src=hash&amp;ref_src=twsrc%5Etfw">#AdventCalendar</a> 用 <a href="https://t.co/Wt1O4orCJa">pic.twitter.com/Wt1O4orCJa</a></p>&mdash; kido@IoTエンジニア (@9wick) <a href="https://twitter.com/9wick/status/1205839394038378496?ref_src=twsrc%5Etfw">December 14, 2019</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# しくみ

メインはTensoreFlowのPosenetをつかっています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/a29b489b-08f2-fa06-bb32-ae12a9526794.png)


1. Posenetを使って、youtube動画の人の骨格を取ります
2. PCのカメラを使って、自分の骨格を取ります。
3. どれだけずれているかを判定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/96dc16ca-24c7-e5b8-18b5-f21cca0a0a4a.png)


これだけだと画面を見ないと同じ動きをしているかどう変わらないので、
振動モータを使って触覚フィードバックを与えてみます。

プロと違う動きをすると振動してお知らせします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/7a1fe98b-cfbe-92c3-cc62-6c960cc28aed.png)



# あとがき

このあと東京モーターショーに言ったらこれのめちゃ高精度版が出てました・・・！
![IMG_6488.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/b3b041f7-e1ed-3137-7f3b-54fc32ba5aac.jpeg)
SalesForceの監査項目の値の設定に関する話その2

前回の投稿でSalesForceのレコードの監査項目にinsert時のみ任意の値を設定できることを書きました。↓

[SalesForceの監査項目の値の設定に関する話](https://qiita.com/bigyoujdb/items/0b8249f223c0926f4c34)

今回は、「監査項目に任意の値を設定したいのはなぜ？」ということについて書きたいと思います。

#ToDoの割り当て通知が来ない
SalesForceLightning上には、画面右上にベルマークのアイコンがあります。

<img width="247" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394418/3d7b3752-ae6c-d8b7-787d-365676d86d35.png">

承認申請やToDoが割り当てられたときに、このベルマークに通知が届くのですが・・・
ToDoの割り当て通知は、通常はToDoの作成時に、ToDoレコードの「担当者」項目に設定されているユーザに通知が届きます。しかし、作成者と担当者が同一ユーザの場合、担当者に割り当ての通知が来ません。
例えば、商談が成立したとき商談レコードの所有者に「ToDo:上司に口頭で報告」を割り当てるApexトリガを実装している場合、Apexトリガを起動させた処理を行ったユーザがToDoレコードの作成者となるため、そのユーザにはToDoの通知が来ません。この場合、自動で作成されているToDoをユーザは認知できないことになります。
このSalesForceの仕様を確認したときに、「ToDoの作成処理で作成者を割り当て者と別のユーザに設定すれば割り当てユーザ（担当者）に通知が届くじゃん」と思ったことが、監査項目の値をいじりたいと思ったきっかけです。

#トリガ実装
以下のトリガを実装してみました。

```
trigger OpportunityTrigger on Opportunity (after update) {
    List<Task> newToDoList = new List<TasK>();
    for (Opportunity obj : Trigger.new) {
        if (Trigger.oldMap.get(obj.Id).StageName != 'Closed Won' && obj.StageName == 'Closed Won') {
            Task newToDo = new Task(
                CreatedById = '0052v00000fZv2vAAC', // ユーザ[検証用ユーザ]を常に作成者に設定
                OwnerId     = '0052v00000cnatoAAA', // 取引先の所有者をToDoの担当者に設定
                Subject     = 'テスト'
            );
            newToDoList.add(newToDO);
        }
    }
    insert newToDoList;
}
```

これで、自動で作成されたToDoでもユーザにベルマークに通知が届く！と、思ったのですが...
ベルマーク通知は届きませんでした。
どうやらToDoの作成時の割り当て通知は、SalesForce標準画面UIからの作成時にしか、届かないみたいです。
ベルマーク通知に関しては、承認プロセスの通知に関しても仕様が少しおかしいところもあるみたいです。残念......

その代わり、Summer'19で実装されたカスタム通知を設定することで、ベルマーク通知の仕様を作りこみことも可能になったみたいです。

#まとめ
SalesForce標準画面での通知のみを頼りにしているシステムはあまりないと思いますが（重要な通知などはだいたいメール通知を設定していると思いますが）、通知の挙動ロジックに整合性がないのは少し、不快感がありますね。どうしてもベルマーク通知を作りこみたいときは、カスタム通知を使用してみてください。
ArrayList

個人的な勉強のためまとめました

##ArrayList

何らかの集合のことを**コレクション**と呼び、配列もそのうちの一つである
Javaには、もっと簡単にコレクションを扱うために、**コレクションAPI**や**コレクション・フレーム**と呼ばれる複数のインターフェイスや、クラスで構成されるクラス群がある
これらのインターフェイスやクラスの多くはjava.utilパッケージに配置されており、**java.util.ArrayListクラス**は**動的配列**とも呼ばれ、配列のように使える

###ArrayListクラスの特徴

①オブジェクトであればどのような型でも使える
②必要に応じて要素数を自動的に増やす
③追加した順に並ぶ
④nullも値として追加できる
⑤重複した値も追加できる
⑥スレッドセーフではない

①、②の特徴は、配列の問題点をカバーするもの
③は配列のように値を番号で管理するため、追加した順に値が並ぶ**リスト構造**である。ただし、任意の場所に挿入することもできる
⑥は並行処理したときに意図しない結果になることを防ぐ機能がついているかどうか
　※スレッドセーフなリストを使いたい場合はjava.util.Vectorを使う

###ジェネリックス

ArrayListの値を追加するaddメソッドの引数や、値を取り出すgetメソッドの戻り値は**Object型**になっているため、何でも扱うことができる
しかし、値が混在するコレクションはダウンキャストするとき例外が発生する可能性がある
そこで、型を指定することで、コレクションが扱える型を制限する**ジェネリックス**という機能がある

例）ジェネリックス
`ArrayList<String> list=new ArrayList<>;`

指定している型のことを**型パラメータ**（例だとStringの部分）、ジェネリックスをより簡潔に書けるように**ダイヤモンド演算子<>**（例だと右の<>）という機能がある
この機能によりインスタンスへの参照を保持する変数がどのような型変数で宣言しているかをコンパイラが判断し、同じ型を使ってインスタンス生成時の型変数を決めれる。これを**型推論**と呼ぶ
【画像処理100本ノックに挑戦】Q.8. Maxプーリング

# 使用したライブラリ
[【画像処理100本ノック】独自の画像入出力クラスを作る](https://qiita.com/jajagacchi/items/834e8425b84f94df8a49)

# Q.8. Maxプーリング
> ここでは平均値でなく最大値でプーリングせよ。
Q.7とほぼ同じですね。

```c++
struct RGB
{
	RGB(int r, int g, int b)
	{
		this->r = r;
		this->g = g;
		this->b = b;
	}
	int r, g, b;
};

int main()
{
	PPM ppm("imori.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();
	PPM ppm2(width, height);

	int N = 16;//分割数
	int P = width / N;

	auto grid_val = [&](int n, int m)//n,m:grid number
	{
		int maxr = 0, maxg = 0, maxb = 0;
		int i0 = P * n;
		int i1 = P * (n + 1);
		int j0 = P * m;
		int j1 = P * (m + 1);
		for(int j=j0; j<j1; j++)
			for (int i = i0; i < i1; i++)
			{
				if (ppm(i, j, 'r') > maxr) maxr = ppm(i, j, 'r');
				if (ppm(i, j, 'g') > maxg) maxg = ppm(i, j, 'g');
				if (ppm(i, j, 'b') > maxb) maxb = ppm(i, j, 'b');
			}
		return RGB(maxr, maxg, maxb);
	};

	for (int j = 0; j < height; j++)
		for (int i = 0; i < width; i++)
		{
			int n = i / P;
			int m = j / P;
			RGB rgb = grid_val(n, m);

			
			ppm2(i, j, 'r') = rgb.r;
			ppm2(i, j, 'g') = rgb.g;
			ppm2(i, j, 'b') = rgb.b;
		}

	ppm2.Flush("out.ppm");
	return 0;
}
```
![imori.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/213f8282-bd26-ec56-59ae-ea8807a1081b.png) ![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/e557b9de-eb20-d46a-2715-d7114c7ede49.png)
Express + Vue.jsでhelloを出してみよう


おはようございますこんにちはこんばんは！

最近Front-endのフレームワークが色々出て流行ってるらしくて、
友達となんかやってみよー！になってはじめました。
最初、どのフレームワークを使おうかと、
'react / vue が人気らしいー何が違う？'とざっと検索してみたら

- Vue
 - テンプレート形式でアプリの制作したいなら
 - 簡単で「一旦動作」ができるのが好きなら
 - 早くて軽量のアプリが作りたいなら
- React
 - 大きい規模のアプリを作るなら
 - もっと大きい情報が欲しいなら

こんな差がありました。
簡単なプロジェクトだから、VueにしようーでVueを選びました。
（実は韓国で何もわからずVueの本を買ってきたので、、最初からvueにしようと決めたこともあり、、笑）

back-endはnode.jsのexpress フレームワークを使います(なんでもjsでやってみよう感)

# やってみましょう^0^

1. node.js install
https://nodejs.org/
installします。ltsの方が安定的らしくてltsの方インストールしました。

2. コマンドラインでインストる確認
`$ node -v`
バージョンが出力されたらok

3. package.jsonでパッケージ管理
package.json生成
`$npm init  `
express 設置 node_modulesというフォルダが生成されます
`$npm install --save express `

4.htmlファイルを置いておくpublic directoryをnode_modulesと一緒の段階に生成
生成
`$mkdir public`
入る
`$cd public` 
index.htmlページ生成
`$vi index.html`

```ruby:index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Vue.js Sample</title>
  </head>
  <body>
    <div id="app">
      <h1>{{ message }}</h1>
        <input v-model='message'>
    </div>
    <!-- vue.js読み込み-->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <script>
      new Vue({
        el: '#app',
        data: {
          message: 'Hello Vue.js!'
        }
      })
    </script>
  </body>
</html>
```

v-modelを使ってinputとtextareaのエレメントに両方向のデーターバインディングの生成が出来ます。
javascriptのjqueryだと inputのvalueを持って、、それをh1に適用して、、みたいなことを
nue Vue ~~　だけで出来ます。

5.node.jsを実行するindex.jsを生成(node_modulesとpublicと一緒の段階)
`$cd ../`
`$vi index.js`


```ruby:index.js
const express = require('express');

const app = express();
const PORT = process.env.PORT = 8000; //port8000に指定、変えてもok

app.use(express.static('public')); //

app.listen(PORT, () => {
  console.log('Server is running at:',PORT);
});

```

6.index.jsのところで実行
` $node index.js`

```ruby:console
Server is running at: 8000
```

表示されたら localhost:8000に接続すると

![스크린샷 2019-12-14 오후 9.52.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320945/abe466bd-854d-6183-9f49-126c80aea435.png)

こういう画面が出て、下のinputに内容を変更するとHello Vue.js!の大文字が変更されます。
とても簡単!

vue.jsの解説なんかより、一応、、画面表示してみよう！になっちゃったんですが、(汗)
これで終わり！

# 参考
https://jp.vuejs.org/index.html
自分は韓国人なので、https://kr.vuejs.org/index.html こちら参照しました (笑)
https://joshua1988.github.io/web_dev/vue-or-react/ 韓国語です (汗)
iOS用OpenVPNの設定ファイルの作り方

iOS版のOpenVPNでもOpenVPNの設定ファイルと秘密鍵などをインポートすると使うことができますが、設定ファイルと秘密鍵など複数のファイルに分かれているとなかなか扱いが面倒だと思います。(iTunesのファイル共有を使ってファイルを転送する必要があるかもしれません。)
OpenVPNの設定ファイルには鍵情報を含めることができますが、PCとiOSによって形式が違うため気をつけないとハマってしまいます。（私のことです…）
備忘録も兼ねて残しておこうと思います。

**設定のファイル内に鍵情報が混在することになるため扱いにはご注意ください。**

# TL;DR
``` OpenVPN.ovpn
#通常通り設定する
client
dev tun
#...
#鍵ファイルの指定はコメントアウトするか消す
#ca ca.crt
#cert client.crt
#key client.key

#tls-auth ta.key 1
#tls-auth使っている場合は下記を追記
key-direction 1

<ca>
-----BEGIN CERTIFICATE-----
CAの証明書
-----END CERTIFICATE-----
</ca>
<key>
-----BEGIN RSA PRIVATE KEY-----
クライアントの秘密鍵
-----END RSA PRIVATE KEY-----
</key>
<cert>
-----BEGIN CERTIFICATE-----
クライアントの証明書
-----END CERTIFICATE-----
</cert>
<tls-auth>
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
TLSAuth用の鍵
-----END OpenVPN Static key V1-----
</tls-auth>
```

# 設定にファイルを組み込む
## ファイルの指定を削除する
通常`ca ca.crt`や`key client.key`などと鍵や証明書のファイルを指定しますがその箇所を削除します。
ただし`tls-auth ta.key 1`と指定している場合は`key-direction 1`に置き換えてください。

## 設定ファイルにファイルを追記する
ファイルの指定を削除した代わりに各ファイルを組み込む必要があります。
XMLのようにタグを使い中にファイルの内容を記載します。
`ca ca.crt`なら`<ca>~</ca>`、
`tls-auth ta.key 1`なら`<tls-auth>~</tls-auth>`のようなタグを使います。

# 生成スクリプト
事前に組み込み前の設定ファイルと鍵ファイル等を用意しているのであれば下記のスクリプトで変換することができます。

``` convovpn
#! /bin/sh
if [ ! "$#" = "1" ];then
  echo Usage: $0 openvpn.conf
fi

# Original config file
confname=$1

# CA cert file
caname=`grep  -e "^ca" ${confname} |sed 's/.* //g'`

# Client cert file
certname=`grep  -e "^cert" ${confname} |sed 's/.* //g'`

# Key file
keyname=`grep  -e "^key" ${confname} |sed 's/.* //g'`

# TLS-Auth key file
tlsauthname=`grep  -e "^tls-auth" ${confname} |sed 's/tls-auth \(.*\) 1/\1/g'`

# New config file
ovpnname="${confname%%.*}.ovpn"
if [ -f "${ovpnname}" ]; then
  printf "Overwrite(${ovpnname})?:"
  read ans
  if [ ! "${ans}" = "Y" -a ! "${ans}" = "y" ]; then
    exit
  fi
fi

# Load original config file
cat ${confname} |grep -v -e "^ca" -e "^cert" -e "^key" | sed 's/^tls-auth .*$/key-direction 1/g' > ${ovpnname}

# Append CA cert
if [ ! "${caname}" = "" -a -f ${caname} ]; then
  echo "<ca>" >> ${ovpnname}
  cat ${caname} >> ${ovpnname}
  echo "</ca>" >> ${ovpnname}
fi

# Append client private key
if [ ! "${keyname}" = "" -a -f ${keyname} ]; then
  echo "<key>" >> ${ovpnname}
  cat ${keyname} >> ${ovpnname}
  echo "</key>" >> ${ovpnname}
fi

# Append client cert
if [ ! "${certname}" = "" -a -f ${certname} ]; then
  echo "<cert>" >> ${ovpnname}
  cat ${certname} >> ${ovpnname}
  echo "</cert>" >> ${ovpnname}
fi

# Append TLS Auth key
if [ ! "${tlsauthname}" = "" -a -f ${tlsauthname} ]; then
  echo "<tls-auth>" >> ${ovpnname}
  cat ${tlsauthname} >> ${ovpnname}
  echo "</tls-auth>" >> ${ovpnname}
fi
```

# あとがき
iOSでOpenVPNを設定する際に苦戦したため記事に残しておきました。
この記事で沼から抜け出せる人がいることを願っています…
もし間違いなどがあればご指摘いただければ幸いです。

# Reference
https://webnetforce.net/ubuntu-openvpn-server/
【画像処理100本ノックに挑戦】Q.7. 平均プーリング

# 使用したライブラリ
[【画像処理100本ノック】独自の画像入出力クラスを作る](https://qiita.com/jajagacchi/items/834e8425b84f94df8a49)

# Q.7. 平均プーリング
> ここでは画像をグリッド分割(ある固定長の領域に分ける)し、かく領域内(セル)の平均値でその領域内の値を埋める。 このようにグリッド分割し、その領域内の代表値を求める操作はPooling(プーリング) と呼ばれる。 これらプーリング操作はCNN(Convolutional Neural Network) において重要な役割を持つ。
これは次式で定義される。
v = 1/|R| * Sum_{i in R} v_i
ここではimori.jpgは128x128なので、8x8にグリッド分割し、平均プーリングせよ。

これも簡単ね。

```c++
struct RGB
{
	RGB(int r, int g, int b)
	{
		this->r = r;
		this->g = g;
		this->b = b;
	}
	int r, g, b;
};

int main()
{
	PPM ppm("imori.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();
	PPM ppm2(width, height);

	int N = 16;//分割数
	int P = width / N;

	auto grid_val = [&](int n, int m)//n,m:grid number
	{
		double r = 0, g = 0, b = 0;
		int i0 = P * n;
		int i1 = P * (n + 1);
		int j0 = P * m;
		int j1 = P * (m + 1);
		for(int j=j0; j<j1; j++)
			for (int i = i0; i < i1; i++)
			{
				r += ppm(i, j, 'r')/(double)(P*P);
				g += ppm(i, j, 'g') / (double)(P * P);
				b += ppm(i, j, 'b') / (double)(P * P);
			}
		return RGB(r, g, b);
	};

	for (int j = 0; j < height; j++)
		for (int i = 0; i < width; i++)
		{
			int n = i / P;
			int m = j / P;
			RGB rgb = grid_val(n, m);

			
			ppm2(i, j, 'r') = rgb.r;
			ppm2(i, j, 'g') = rgb.g;
			ppm2(i, j, 'b') = rgb.b;
		}

	ppm2.Flush("out.ppm");
	return 0;
}
```

![imori.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/02d67479-b643-d97a-df63-f3448dda2cf5.png) ![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/9695a834-f62a-4796-a8e2-94096a09460a.png)

ひとつ荒くすれば
![out-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/80cfca4a-d21e-6a09-ba22-c17ab445085a.png)
ひとつ細かくすれば
![out2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/ba8fdca5-b51a-6882-9909-f3e597f2a3c5.png)
「プログラミングElixir」の次にやること

この記事は、fukuoka.ex Elixir／Phoenix Advent Calendar 2019 の 14日目です。 昨日は @adamu さんの「EElixirを使ってLineのチャットボットを作ろう」でした。

##Elixirに出会う

現職ではC#を使って開発しています。.netframework1.1の頃に開発されたシステムは流石にメンテナンス性が落ち、DDDの導入を進めていました。
社内ではなかなか理解が得られず導入を諦めていた頃、Elixirを知りました。

##Elixirはカンタンな関数型言語
Elixirを知ったきっかけというのは[「Excelから関数型言語マスター1回目：データ行の”並べ替え”と”絞り込み”」](https://qiita.com/piacerex/items/6714e1440e3f25fb46a1) です。

それまでは関数型言語は難しいというイメージがありました。（実際、F#は途中で諦めました）もし、記事通り簡単に習得できるなら、DDDの導入をもう一度トライできるかもしれないと思いました。（うちの会社の場合は、DDDより言語を変える方がハードルは高いですが＾＾；）

DDDの導入の失敗の１つに、ValueObjectのメリットを上手く伝えられなかったことがあります。ValueObjectを作るのは、C#の場合それなりに工数がかかります。関数型であれば最初から副作用が発生しないので、ValueObjectを作らなくて済みます。

その他にもSliverlight+WCFという非同期プログラミングで苦労したり、メモリリークを見つけられず、Empty.exeに頼るという力技で解決？したりしていました。

Elixirであれば並行プログラミングやプロセスの特徴から、このような苦労はせずに済みそうだと感じ興味を惹かれました。その上、習得も容易であるならElixirを習得しない理由はありません。


##「プログラミングElixir」読んでみた

まずはお勧めされている「プログラミングElixir」を読み流してみました。後半になるにつれ理解が追いつかず、特に興味のあった並列プログラミング（14章以降）は完全に置いていかれました。

##今後の予定
読み流すだけでは理解が覚束ないので、年末年始は手を動かすために、もくもく会で購入した「Phoenix入門」を写経しようと思います。

ゆくゆくはOSSで公開されるEsunaに貢献できるぐらいにはElixirを習得したいです。
【画像処理100本ノックに挑戦】Q.6. 減色処理

# 使用したライブラリ
[【画像処理100本ノック】独自の画像入出力クラスを作る](https://qiita.com/jajagacchi/items/834e8425b84f94df8a49)

# Q.6. 減色処理
> ここでは画像の値を256^3から4^3、すなわちR,G,B in {32, 96, 160, 224}の各4値に減色せよ。 これは量子化操作である。

これは簡単ね。

```c++
int _256to4(int val)
{
	int ret;
	if (0 <= val && val < 64) return 32;
	else if (64 <= val && val < 128) return 96;
	else if (128 <= val && val < 192) return 160;
	else return 224;
}

int main()
{
	PPM ppm("imori.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();
	PPM ppm2(width, height);

	for (int j = 0; j < height; j++)
		for (int i = 0; i < width; i++)
		{
			int r = ppm(i, j, 'r');
			int g = ppm(i, j, 'g');
			int b = ppm(i, j, 'b');

			int r2 = _256to4(r);
			int g2 = _256to4(g);
			int b2 = _256to4(b);
			
			ppm2(i, j, 'r') = r2;
			ppm2(i, j, 'g') = g2;
			ppm2(i, j, 'b') = b2;
		}

	ppm2.Flush("out.ppm");
	return 0;
}
```
![imori.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/7043adfc-ab07-8c7b-1338-72559fef0491.jpeg) ![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/f1b59294-f6f9-65f9-3579-81afe17f15be.png)
2019年Expoで辛かったことベスト5

この記事はReact Nativeアドベントカレンダーの14日目の記事です。
当日夜になってしまいましたが、、


## はじめに
こんばんは。ムゾウの渡辺と申します。

ReactNativeでのアプリ開発を3年ほどやっており、
ちょうど1年ほど前からはExpoでの開発を特に多く扱っています。

去年の今頃は、RNのビルドで疲弊していたせいもあり、Expoサイコーという気持ちだったのですが、
1年ほど開発、運用を続けていく中で、なかなかうまくいかない経験だったり、XXXだったらなーということも増えてきている昨今です。

この記事ではそんな1年の振り返りとして、Expoでの辛かった思い出をまとめて見ようと思います。


## Expo辛かったことまとめ
### 1) ネイティブレイヤーでエラーになった時に辛い
究極、これに尽きるのですが、Expoでネイティブ層のエラーに直面するとかなり詰みます。

仕様面の調整や、他の方法で要求を満たすことができないか検討するしかないのですが、
新規の機能開発であればそういった方法も比較的柔軟にとれるものの、
Expoのversionのアップデートなどでそういった事態に遭遇した場合、かなり苦しい状況に追い込まれます、、

今年あった中で一番辛かったものは、、
**Expo34=>35にupgradeしたあと、iosでfcm経由のpush通知が全てクラッシュしてしまう**
でした。

原因は、apnのpayloadでdataとして渡しているものがfcmのクラシックなapi経由ではjson形式で渡されており、34まではそれをjs層のexpo内でdataとして展開していたのですが、35ではネイティブレイヤーで一部解析するようになったためでした。

ネイティブの方のコードにブレークポイントをつけて手元でビルドできるわけでないので、原因を突き止めるまでも辛いのですが、わかったところで改善することもできず、、

この件に関しては、fcmの別のapi経由でapns用にpayloadを設定することで解決できたのですが、かなり時間がかかりました。。

他にも

- expo32 => 33に変えた時に、ReactNativeのcamerarollの内部挙動が変わっており取得した画像の順番がめちゃくちゃになる(ExpoのMedialiblary使うように置き換えて解決)
- Number.prototype.toLocaleString()がandroidで動かない(どっちかというとjscoreの問題?)
- 未だ原因不明のネイティブレイヤーのクラッシュ

などなど、何かあった時に手元でビルドできないことの苦しさを感じることが何度かあった一年でした。

(他のExpo使いの方はこのあたりどう調査しているのでしょうか、、xcodeでクラッシュログ拾ったりadb logcatでみたりの範囲から推定する、、以外ないのでしょうか、、情報求む、です）

### 2) リリースビルドでの確認が必要な機能があると、生ReactNativeよりも生産性おちる
1にも関連するのですが、ビルドが必要な機能があると、実装&確認の時間が効率が落ちてしまします。
自分の場合は、↑にも書いたプロジェクトでpush通知にfcmを利用したケースで、expoアプリでの機能確認ができず、大幅に確認工数をさかれてしまいました。。 

### 3) publishのversion管理が辛い
EXPOの利点として、組み込み済みのOTAアップデートがあるかと思います。
code-pushのように別途アカウントを設定したり、native moduleを組み込んだりすることなく使うことができるので非常に便利！ではあるものの、実際にうごいているコードがどのpublishバージョンなのか、わかりにくくなってしまうことがあるかと思います。

自分のかかわっているプロジェクトでは、別途publishのversionの番号を管理するファイルを作成し、アプリ内で表示するようにしています。

code pushだとこの辺りのバージョン管理がわかりやすく、バージョンを取得するapiもあるのでちょっとexpo側も改善されないかな、、と期待しています。


### 4)Expoのサーバーが落ちている時に遭遇すると絶望する
ダイレクトに遭遇したのは2回ほどですが、たまにExpo落ちていてしばらくビルドが全くできないときがありました。
自分の場合、8月の月末でその日確認予定の機能のビルドを準備していたところ遭遇してしまい、かなり焦りました。

twitterのexpo_statusなどを見ていると、大きな障害のときには情報が乗っていたりするようです。
https://twitter.com/expo_status/status/1167112503991472134


### 5)ReactNativeの方では修正された不具合がExpo同梱のReactNativeに採用されるまでの時差
これももうどうしようもないといえばどうしようもないのですが、、
例えば日本語がAndroidで下が見切れるようになってしまう、などReactNative側でたまにとんでもない不具合が急に噴出していたりするので、そういったものの対応が遅くなると、辛い気持ちが強くなります。
https://github.com/facebook/react-native/issues/25297

とはいえ、expoも定期的に新しいversionが出ていますし、なんせupgradeがそこまで辛くない！ので待てば解決、です。

## 結局Expoでよかったのか
上述したとおり、最初の印象と比べるとデメリットに気づくことも多かった一年ですが、逆にいうとそれ以外は快適に開発を進めることができました。最初のころは生ReactNativeでつかっていたころにnative moduldeのライブラリでやっていたことの置き換えに戸惑ったりもしましたが、ある程度要件の調整で目処が立ってしまうとほぼほぼのアプリはExpoで開発の効率はあがったのではないかなと思います。

特にReactNativeのアップデートと比較すると圧倒的ににupgradeが簡単で、それだけとってもreact-nativeアプリと比較し運用中の負荷は減りました。
（2019年は夏のAndroidX対応などupgradeが必須のイベントが多かったので、だいぶ助けられました）

とはいえ、最近はautolinkにfast reloadにunimoduleにと、生ReactNativeでの開発快適性もだいぶ良くなっていますので、、
今後は案件、要件に応じてExpoも生ReactNativeも両方うまく使っていきたいです。



-
明日は@nitakingさんの「参考にできないAndroidのイケてないrender制御」です
JavaでExpression Problemを解決する方法

#Expression Problemとは
http://maoe.hatenadiary.jp/entry/20101214/1292337923
>静的型付き言語で、再コンパイルなしで、新しいデータ型を追加したり、新しい関数を追加できるようにするにはどうしたらよいか

という問題である。
何も考えずにクラスを設計すると、
1. データ構造は追加しやすいが操作が追加しにくい
2. 操作は追加しやすいがデータ構造は追加しにくい
のどちらかになりやすい。
データ構造も操作も追加すくするにはどうしたらいいか、というのがExpression Problemの問題意識である。

#Javaでの解決方法
HaskellやOCamlやScalaなどで高度な言語機能を用いた解法が既に有名（？）だが、Javaの言語機能でも同様にExpression Problemが解決できることを示す。


1. サブタイピング＋戻り値の共変性を使う方法
2. サブタイピング＋Genericsを使う方法

上記2種類の方法が存在する。この記事では2の方法を紹介する。

##例題
まずは単純なインタプリタを例にして考える。コード簡略化のためLombokを使用しているので注意。

```java
import lombok.AllArgsConstructor;
import lombok.Data;

interface Exp {
    int eval();
}

@Data
@AllArgsConstructor
class Add<E extends Exp> implements Exp {
    private E e1;
    private E e2;

    @Override
    public int eval() {
        return e1.eval() + e2.eval();
    }
}

@Data
@AllArgsConstructor
class Lit implements Exp {
    private int x;

    @Override
    public int eval() {
        return x;
    }
}
```

AddクラスのフィールドがEという型パラメータになっているところがミソ。

##操作の追加
このクラスに対してprint操作の追加を行う。

```java
interface ExpP extends Exp {
    String print();
}

class LitP extends Lit implements ExpP {

    LitP(int x) {
        super(x);
    }

    @Override
    public String print() {
        return String.valueOf(getX());
    }
}

class AddP<E extends ExpP> extends Add<E> implements ExpP {

    AddP(E e1, E e2) {
        super(e1, e2);
    }

    @Override
    public String print() {
        return getE1().print() + " + " + getE2().print();
    }
}
```

既存クラスをいじらずに問題なく追加できた。

##クラスの追加
Sub(引き算)を表すクラスを追加する。

```java
@Data
@AllArgsConstructor
class Sub<E extends Exp> implements Exp {
    private E e1;
    private E e2;

    @Override
    public int eval() {
        return e1.eval() - e2.eval();
    }
}

class SubP<E extends ExpP> extends Sub<E> implements ExpP {

    SubP(E e1, E e2) {
        super(e1, e2);
    }

    @Override
    public String print() {
        return getE1().print() + " - " + getE2().print();
    }
}
```

どちらの場合でも、既存クラスを修正せずに操作の追加/クラスの追加が行えている。
これらを使う側のクラスは以下のようになる。

```java
public class Main {

    public static void main(String[] args) {
        new Add<Exp>(new Lit(1), new Lit(3)).eval();
        new Sub<Exp>(new Lit(1), new Lit(3)).eval();

        new AddP<ExpP>(new LitP(1), new LitP(3)).print();
        new SubP<ExpP>(new LitP(1), new LitP(3)).print();
    }
}
```

高い拡張性が必要な状況（データ構造と操作の両方を拡張することが予想される）では、このデザインパターン（名称不明？）を覚えておいて損はないのではないか、と思う。
なお「サブタイピング＋戻り値の共変性を使う」方法の方にも興味がある方は、下記の参考文献を参照されたし。（※この記事の内容は下記論文の丸パクリです）

#参考文献
[Wang, Yanlin, and Bruno C. D. S. Oliveira. "The expression problem, trivially!." Proceedings of the 15th International Conference on Modularity. ACM, 2016.](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.721.2964&rep=rep1&type=pdf)
初心者によるプログラミング学習ログ 184日目

# 100日チャレンジの184日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

184日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>184日目<br><br>webサイトコーディング課題<br>更新履歴の修正、といいたいところだけどうまくいかなかった<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1205581294270156801?ref_src=twsrc%5Etfw">December 13, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ORMは使ったほうがよいの？SQL

##目的
LaravelのEloquent(エラクエント)を、今まで使用することが多く、SQLを書く際は、Eloquantで表現すると逆に複雑になるときや表現できないときに生SQLを書いていて、どちらのほうがいいんだろうと思い調べてみた。

##ORMの特徴
・特定のクラスとテーブルが一対一になっていて、そのクラスのインターフェースを使用し、データ操作を行える
・データ取得時に、そのデータを元にオブジェクトを生成

ORM（オブジェクト　リレーション　マッピング）を実現する仕組みをORマッパーという
Webフレームワークに標準で装備されていることが多い

##ORMのメリット
・SQL処理が、簡単に短く書ける
・MySQL、PostgreSQL、Oracle、SQLiteなどDBを変えた際（文法が異なる）でもORMがクッションとなり、ORMを使って書いたものは、実行することができる。

##ORMのデメリット
・複雑なクエリをかけない
・複雑なクエリを書く必要があるプロジェクトの場合、ORMとSQLの記述が存在するところがでてきて、統一性が損なわれる
・チューニングを丁寧に行う際に、丁寧なチューニングを行えない可能性がある。
（ORMに慣れ、内部的にどんなSQLが実行されているかわからない場合）

##それぞれの意見
ORM推奨は、ORMで書けないテーブル構成がダメ、オブジェクト指向原理でかける

ORM非推奨は、新人が使う場合、ORMになれると内部的に何が起こっているのかまで目を向けることが少なくなる。また、DBの違いを吸収してくれることを使うのはあまりない。どれだけ考慮しても、ORMでは書けないクエリがあるかも。

##個人的見解

SQLの知識量　＞　ORMの知識量　は絶対守ったほうがいいと思う。

業務ではWebフレームワークを使うことが多いため、ORM使いましょうとなることもよくある。初心者の僕には入りやすかった。ある程度使えたので、そこまで内部について詳しく調べなかった。しかし、DBチューニングをしている人の話を聞いたりすると、内部的なことを把握していて、僕には初耳のことばっかりだった。そこで感じたのが、長いプロジェクトは、テーブル構造などが変わるため、どうしてもORMで表現できず、複雑なSQLを要求される場合が現実的に出てくる。また、小さいプロジェクトでも、改修などの際に困る場合が出てくる。ORMはフレームワークごとの知識だが、SQLは共通。

必ず、ORMを使う際は、SQLが内部で何をしているかを学ばないとと感じた。

#参考にさせていただいたサイト
[O/Rマッピングは百害あって一利なし！](https://qiita.com/gomiryo/items/6d448c500749f91242d2)
[今更ですがormについて教えてください 主にphpフレームワーク](https://teratail.com/questions/44529)
[Ormとの付き合い方](https://www.slideshare.net/chariderpato/orm-74710374)
rubyの機能を活用し、a~zを繋げた文字列を取得するために冗長に書く

## ＊＊＊注意＊＊＊
以下のコードは **かなり冗長** となっています。
「これ`(a..z).to_a.join`でええやん^^;」は**なし**でお願いします。

## 本題
最近友人にRubyを教えていて、これが読めればいいんじゃないかな？ってコードを考えてみたところいい感じのが出来たので置いときます。

### コード
``` ruby
# 可読性上げるためインデント調整してます。
__send__(
  define_method(
    25.times
      .inject(false.to_s[1]) { |s| s + s[s.size.pred].next }.to_sym,
    -> { __method__.to_s }
  )
)
```

### pryでの実行結果
<img width="1064" alt="スクリーンショット 2019-12-14 20.45.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320419/73f7f2f1-224e-6c6b-7ec1-77bbc44a22dd.png">

### ワンライナーでの実行
<img width="1073" alt="スクリーンショット 2019-12-14 21.24.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320419/ce4a9e42-4c07-600a-4177-3e67db7a18a4.png">


## 解説
コード貼り付けただけだとしょっぱいので、内側から解説していきますw

### 25.times
`define_method`の第一引数であるメソッド名(シンボル)を作成していきます。
`25.times`で`Enumerator`オブジェクトを作り、自身をレシーバとした`Enumerable`メソッドの実行回数を決めています。
これにより、`inject`を**25回**実行させることができます。

### inject(false.to_s[1]) { |s| s + s[s.size.pred].next }.to_sym
ここで`(a..z).to_a.join.to_sym`と同様のコードとなるようにします。

引数に`'a'`を与え、ブロックの中で「現在の文字列 + (現在の文字列の最後の文字)の次の文字」を行なっています。

``` ruby
# 中身はこのイメージ
inject('a') {|'a'| 'a' + 'b'}
# 'a'の次は'b'   
inject('ab') {|'ab'| 'ab' + 'c'}
# 'b'の次は'c'
# ..., zを取得するまで繰り返す
```

これにより、次の文字を取得してくっつける処理が25回実行されるためa~zが得られます。

最後に`to_sym`でシンボル化し第一引数は完成です。

### -> { \_\_method__.to_s }
`difine_method`へ渡す第二引数である`Proc`オブジェクトを作成しています。
`__method__`でこのメソッドを呼び出したメソッド名(シンボル)を取得し、Stringオブジェクトに変換します。

### define_method(name, proc)
第一引数にa~zを繋げた文字列のシンボル、プロックを渡しレシーバへメソッド定義をさせます。
そのままでは定義するだけで終わるので何かしらのメソッドで実行させます。

### \_\_send__(symbol)
レシーバに対して引数のメソッド名を実行します。
`define_method`の戻り値が定義したメソッド名のシンボルであることを利用しそのまま渡します。

結果として`-> { __method__.to_s }`が呼ばれ、ここでa~zの文字列が得られました。

他の手段ですが、`method(...).()`でも同じようにできます。
この辺は好みだと思うのでどちらでも大丈夫ですねw

## まとめ
解説は以上です。
このコードでは簡易的ですが、メソッドチェーン、メタプロ、リフレクション、Enumerable、Procオブジェクトが登場します。
脱初心者を目指すにはいい足掛かりにはなるんじゃないでしょうか？(主観100%)
DockerをProxy環境下＆root権限なしでUbuntuに導入する (RootlessのDockerにProxy設定がメイン)

# 前書き
- root権限が無いからUbuntuの環境構築はかどらない！
- なんかroot権限が必要ないDockerがあるらしいぞ！
- 導入したがProxy設定わかんねー！
- あと記事書くの初めてなので優しくしてください

# Root権限が必要ないRootlessモードのDocker
Docker19.03にて、root権限がなくても実行できるRootlessモードが実装されました[^1]。
root権限を持たない身としてはありがたいお話です。
[^1]: https://docs.docker.com/engine/security/rootless
### RootlessモードのDockerインストール
(インストールについては先人の方々の記事or公式ページ[^1]を参考にしていただければ...)

```console
# curlのproxy設定してない場合はcurlrcファイルにproxy設定を書き込む
vi ~/.curlrc

  #以下を書き込む
  proxy=http://proxy.url:port

# Rootless mode Dockerをlocal環境にインストール
$ curl -fsSL https://get.docker.com/rootless | sh

# インストーラ終了時に追加すべきPATHを指示してくれるため、指示されたコマンドを実行する
$ export PATH=/home/testuser:/bin:$PATH
$ export PATH=$PATH:/sbin
$ export DOCKER_HOST=unix:///run/user/1001/docker.sock
```

### Hello Worldで動作確認
恐らくProxyが原因でTimeoutが発生

```console
$ docker run docker/whalesay cowsay Hello World
$ systemctl --user start
docker: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).
```

# Docker daemonにProxy設定

### 詰まった所
本来Docker daemonにproxy設定を行う際は
```/etc/systemd/system/docker.service.d/http-proxy.conf```に設定を書く必要があります[^2]。
(するとdocker.servicの設定に継承される形で適用される...多分)
[^2]: https://docs.docker.com/config/daemon/systemd/#httphttps-proxy
これがRootlessモードの時にどう設定するかわからないという状況で2日かかりました。

### 解法
結論としては、```~/.config/systemd/system/docker.service.d/http-proxy.conf```
に設定することで解決しました。

```console
$ mkdir -p ~/.config/systemd/system/docker.service.d
$ vi ~/.config/systemd/system/docker.service.d/http-proxy.conf

  # 以下2行を書き込み
  [Service]
  Environment="HTTP_PROXY=http://proxy.url:port"

$ systemctl --user daemon-reload
$ systemctl --user restart docker
```

# 再度Hello World
```console
$ docker run docker/whalesay cowsay Hello World
 _____________ 
< Hello World >
 ------------- 
    \
     \
      \     
                    ##        .            
              ## ## ##       ==            
           ## ## ## ##      ===            
       /""""""""""""""""___/ ===        
  ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~   
       \______ o          __/            
        \    \        __/             
          \____\______/ 
```

# 反省
公式ページにdaemon configディレクトリのパス```~/.config/docker```が記載されており[^3]、
```~/.config/systemd```も生成されていた為、冷静に見れはもう少し早くわかったなと反省。
[^3]: https://docs.docker.com/engine/security/rootless/#usage
【画像処理100本ノックに挑戦】Q.5. HSV変換

# 使用したライブラリ
[【画像処理100本ノック】独自の画像入出力クラスを作る](https://qiita.com/jajagacchi/items/834e8425b84f94df8a49)

# Q.5. HSV変換
> HSV変換を実装して、色相Hを反転せよ。

定義式の通りに変換、逆変換するだけです。

```c++

struct HSV
{
	double h, s, v;
};
struct RGB
{
	RGB(int r, int g, int b)
	{
		this->r = r;
		this->g = g;
		this->b = b;
	}
	int r, g, b;
};

HSV RGB2HSV(const RGB &rgb)
{
	HSV hsv;
	int r = rgb.r;
	int g = rgb.g;
	int b = rgb.b;
	int Max = std::max({ r, g, b });
	int Min = std::min({r, g, b});
	if (Min == Max) hsv.h = 0;
	else if (Min == b) hsv.h = 60 * (g - r)  / (double)(Max - Min) + 60;
	else if (Min == r) hsv.h = 60 * (b - g)  / (double)(Max - Min) + 180;
	else if (Min == g) hsv.h = 60 * (r - b)  / (double)(Max - Min) + 300;
	hsv.v = Max / 255.;
	hsv.s = (Max - Min) / 255.;
	return hsv;
}
RGB HSV2RGB(const HSV& hsv)
{
	double r, g, b ;
	double h = hsv.h;
	double s = hsv.s;
	double v = hsv.v;
	double c = s;
	double h2 = h / 60.;
	double x = c * (1 - fabs( fmod(h2,2)  -1 ));
	
	if (0 <= h2 && h2 < 1) r = c, g = x, b = 0;
	else if (1 <= h2 && h2 < 2) r = x, g = c, b = 0;
	else if (2 <= h2 && h2 < 3) r = 0, g = c, b = x;
	else if (3 <= h2 && h2 < 4) r = 0, g = x, b = c;
	else if (4 <= h2 && h2 < 5) r = x, g = 0, b = c;
	else if (5 <= h2 && h2 < 6) r = c, g = 0, b = x;
	else r = g = b = 0;
	r += (v - c);
	g += (v - c);
	b += (v - c);
	
	return RGB(r*255,g*255,b*255);
}

int main()
{
	PPM ppm("imori.pnm");
	int width = ppm.Get_width();
	int height = ppm.Get_height();
	PPM ppm2(width, height);

	for(int j=0; j<height; j++)
		for (int i = 0; i < width; i++)
		{
			int r = ppm(i, j, 'r');
			int g = ppm(i, j, 'g');
			int b = ppm(i, j, 'b');
			
			HSV hsv = RGB2HSV(RGB(r, g, b));
			if (hsv.h > 180)hsv.h -= 180;
			else hsv.h += 180;
			
			RGB rgb = HSV2RGB(hsv);
			ppm2(i, j, 'r') = rgb.r;
			ppm2(i, j, 'g') = rgb.g;
			ppm2(i, j, 'b') = rgb.b;
		}

	ppm2.Flush("out.ppm");
	return 0;
}
```
![imori.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/69142042-f8b6-0e31-4772-9953192c47fe.png) ![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/3f1801cb-c635-7bbb-2cfd-021c76aceae4.png)

# 注意
普段グレースケール画像ばかりいじっている身としてはこういうのは新鮮。あんまりカラー画像に対する処理は興味がなかったのですが、セグメンテーションの色分けとかに使えそうな感じですね。
ついでにお遊びでカラーバーみたいなものを作ろうと思ったときに気が付いた注意点について言及してこの記事を終わりにします。作りたかったのは次のような画像です。
![out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520857/04131f62-8ffc-c939-888f-9a34d8fddcd1.png)
こういう画像を作ろうと思ったとき、RGBでは3チャンネルしかないので困るわけですが、HSVを使えばHを振ることでたくさんの色が作れます。
Q.5ではRGB -> HSV -> RGBと変換したわけですが、今回はHSV -> RGBという変換になります。この際$V \geq S$が成立しなけらばならないことに注意が必要です。これを守らないとRGBに負の値が許されてしまいます。

```c++
int main()
{
	int width = 256, height = width;
	PPM ppm(width, height);

	int N = 6;
	
	for (int i = 0; i < width; i++)
	{
		int n = i / 50;
		HSV hsv;
		hsv.h = 360. / (double)N * n;
		hsv.s = 0.5;
		double dv = (1. - hsv.s) / height;
		for (int j = 0; j < height; j++)
		{
			hsv.v = hsv.s + dv * j;
			RGB rgb = HSV2RGB(hsv);
			int r = rgb.r;
			int g = rgb.g;
			int b = rgb.b;
			ppm(i, j, 'r') = r;
			ppm(i, j, 'g') = g;
			ppm(i, j, 'b') = b;
		}

	}

	ppm.Flush("out.ppm");
	return 0;
}
```
DelphiからODBCでFileMakerに接続する！でも意外にすごいタッグだぞ！

Delphi Advent Calender 2019の22日目の記事です。

## TL;DR

DelphiとFileMakerというともにニッチな開発環境で、さらにFireDACでODBC接続させるというニッチな使い方をしたい。

で、実現しようとしたところとにかく情報がなく、手探りと試行錯誤を繰り返したので、とりあえず正常にできた方法を備忘録を兼ねて書きます。

しかし完成してみると、**意外に最強のタッグかも**という結果が！

## 環境

### OS構成

- FileMakerサーバ: Windows Server 2018
- クライアント: Windows 10 Pro

典型的なサバクラ環境で、LAN接続です。


### 開発環境

- Delphi 10.3 Enterprise
- FireDAC
- FileMaker Server 18.0.2
- FileMaker ODBC(付属のもの)

## インストール

FileMakerをインストールすると、インストールディレクトリにODBCがあるのでインストール。32bit、64bit用がある。

害はないので両方インストールしておくとあとでビット数を変更する場合も楽。

## ODBCの設定

ODBCデータソースにてODBCを設定。もちろん使用するビット数のものを設定。

ちなみに、他のDBのODBCはコマンドラインから自動インストールができますが、**FileMakerはできません**。（コマンドラインからやろうとすると設定ウィンドウが出てしまう）。

多数のクライアントを設定するときに面倒すぎるのでクラリスさんどうにかしてください。


## Delphi+FireDACで接続！

いよいよ本題。

1. DelphiでFDConnectionをフォームに設置
1. FDConnectionをダブルクリックして設定
1. ドライバIDを「ODBC」にする

未知のDBですとついついウィザードを使いたくなりますが、**FileMakerに対してはトラップです**。使うと設定が進まなくなったり、設定できたよう見えてActiveにしようとしても例外発生します。（環境によると思いますが）

設定必須は以下の3点。

|パラメータ|値
|---|---
|User_Name|FileMakerに**書き込み権限のある**アカウント名
|Password|上記ユーザのパスワード
|DataSource|FileMakerのファイル名（FMサーバにアップロードしたDB名。日本語可）

**書き込み権限のある**アカウント名を太字にしましたが、ここを読み取りのみのユーザにするとなぜか接続できないことがありました。

僕の環境の問題かもしれませんが、もしかしたらこちらの知らぬところでステータスなどを書き込んでいるのかもしれません。

ConnectedをONにしてTrueになればOK！

## SQL

FileMakerはSQLの機能がかなり限定的で、構文の注意事項もいくつかあります。

- カラム名はダブルクオーテーションで囲む
- 日本語カラム名もほぼOKだった（サロゲートペアを含むなど、問題のある漢字の挙動は不明）
- 「テキスト」カラムは、DelphiではTMemo型になる（SQLプレビューでは (Memo) になってしまうのでとてもやりづらい）

TDBGridにテキストカラムを出力したときに(Memo)ばかりになる問題は、フィールドのプロパティでDisplayValueをdvClassからdvFullやdvClipなどに変更すれば見えるようになります。

## 最強の連携となる立ち位置

Delphi + FileMakerは、例えばMySQL + Delphiのような組み合わせでの開発と、大きく変わります。

ODBCで使えるSQL構文を見てもあきらかですが、FileMakerは基本的にFileMakerだけで完結できる作りになっているので、外部から何かをするというのはかなり限定的な状態です。

他のDBではデータ管理のみをDBが提供し、あとの全てはクライアント側に任せられます。データ入力、修正、管理など、あらゆるものをクライアント側で作り込まなければなりません。

しかし、FileMakerは非常に高度なUIをDB自身が搭載しているので、**Delphiでは面倒な”管理画面”を作る必要すらない**という点がまず大きな違いです。

管理画面となると、最低でも数画面の設計に、多数のトランザクションが走り、仕様書とくびったけになるのが普通です。それがFileMakerなら、エディットボックスをポトペタして、ダブルクリックでカラム名を指定するだけで完了！

アカウント制御も、トランザクションも、多数のクライアントへの同期も、文字の拡大縮小も、条件付き書式も、マルチデバイス対応も、**デフォルトで搭載**です。**1行も書く必要がない！**

ただ、FileMakerは正規表現でテキストを編集をしながら入力するような複雑処理は苦手です。また、複数のウィンドウやものすごく小さなウィンドウなどは作れません。（僕が知らないだけかもしれません）

**この部分にDelphiを挟み込むと、さらに柔軟な環境を構築できます。**

両者のちょうどよい立ち位置としては、

- FileMakerが管理画面とDB管理
- Delphiがバッチ処理やより複雑なUIの実現

このような役割分担で最強になるのではないでしょうか。

## まとめ

FileMakerは名前だけを知っている状態で、いままで「Accessの延長でしょ」という認識でしたが、社内に取り入れ始めてその能力に驚きの連続です。

基本機能はほとんどFileMakerのみで済んでしまうので、Delphiでは凝ったUIのみを作るようにすれば、工数が激減します。

少人数開発で苦しんでいる方々(笑)は、ぜひこのタッグを試してみてほしいところです。
npmパッケージを公開するならnpが便利！

# よくある困りごと
npmパッケージを公開・更新する場合、手順を忘れがちですよね（少なくとも私はそうです）。
これから紹介するnpコマンドを使えば、楽にnpmパッケージの公開、更新、さらにはGitHubのtagまで切ってくれる。最高です。

# npコマンドの導入
```
yarn global add np
```

npを実行すると、バージョンの選択画面が表示され、major, minor, patchのアップデートかどうかの選択肢が出る。


```bash:patchを選択した場合
$ np
Publish a new version of パッケージ名 (current: 1.0.3)

Commits:
- コミット内容

Commit Range:
v1.0.3...master

? Select semver increment or specify new version patch  1.0.4

  ✔ Prerequisite check
  ✔ Git
  ↓ Cleanup [skipped]
  ✔ Installing dependencies using Yarn
  ✔ Running tests using Yarn
  ✔ Bumping version using Yarn
  ✔ Publishing package using Yarn
  ↓ Pushing tags [skipped]
    → Upstream branch not found; not pushing.
  ✔ Creating release draft on GitHub

 パッケージ名 1.0.4 published 🎉
```

# 参照
https://zellwk.com/blog/publish-to-npm/
diffでテキストファイルの違う行だけ表示したい

## diff
````shell
diff data1.txt data2.txt
````
と普通に使うと

````
--- data1.txt
+++ data2.txt
@@ -1,4 +1,4 @@
 11111
-22222
+22225
 33333
-44444
+44445
````
のように内容が同じ行と違う行とが混じって表示されます。
行数が多い時にはちょっと見づらいなと思いました。

## sed
同じ行の先頭は空白なので、sedでフィルタ(削除)します。

````shell
sed -e '/^ .\+/d'
````
「^ 」先頭が空白で始まる「.\\+」任意の文字列をdで削除という意味です。

diffとパイプでつなぎます。

````shell
diff data1.txt data2.txt | sed -e '/^ .\+/d'
````
すると

````
--- data1.txt
+++ data2.txt
@@ -1,4 +1,4 @@
-22222
+22225
-44444
+44445
````

違う行だけになってスッキリしました。

最近Windows上でbusyboxを使い、シェルの勉強をしているんですが奥が深いです。
ChromeExtentionの開発で役に立った知識

　ChromeExtensionって、ネット上の情報が少ない気がします。そんな訳で、Javascript＆ChromeExtention歴２ヶ月ほどですが役に立った知識を羅列していこうと思います。間違いがあったら教えて下さい。そんなこと知ってるわ！みたいなことがあっても許してください。前提条件として下記のことが挙げられます。
・ECMAScript6環境です。
・JavaScriptの知識もあれば、Extension固有の知識もあります・
・[chrome.storage](https://developer.chrome.com/extensions/storage)を使ったデータベース風なclassを作っていて、そこで躓きまくったので、classに関する話がほどんどです。

##Background.jsではexport/importが使えない
　Background.jsは裏に見えないウインドウを展開して、その中でJavaScriptの処理を行うらしいので、基本的には普通のブラウザと同じようにプログラミングして問題ありません。故にasync/awaitとかも使えるんですが、export/importだけは使えません。原因はわかりませんが、クラスを作ってそれでデータのやり取りをするときに困りました。
###対策
　exportはmanifest.jsonで予めexportしたいファイルを読み込みます。ポイントはbackground.jsより先に読み込みたいファイルを書くことです。

```json
 "background": {
    "scripts": ["js/test.js", "js/test.js", "js/background.js"],
    "persistent": false
  },
```

 importはhtml上で普通に先に読めこめば使えますが、Background.jsでしか使わない関数があったりするので、エラーの原因になりやすくあまりおすすめできません。故に、読み込むよりは共通部分を抜き出してjsファイルにして、先の方法で共通化したjsファイルをbackground.jsに読み込む方が早いと思います。

##classのコンストラクタではawait/asyncが使えない。
　ChromeAPIsは基本何でもコールバック内で処理をさせようとします。故に、かなりの頻度でasync/awaitを使うことになりますが、コンストラクタ内では使えません。
###対策
　staticなinit(初期化）関数を作って、擬似的なコンストラクタとして運用します。privateとかのアクセス修飾子がないので、きちんとコメント書いておかないと事故に繋がります。擬似的にprivateにする方法もあるようですが、可読性が下がる気がして個人的にあまり好きではないです。

```javascript
class Test {
//このコンストラクタは使わない
  constructor() {
    this.name = "amuza";
  };

//コンストラクタの代わりにこちらを使う
  static async init() {
    const test = new Test();
    this.name = await changeName();
    return test;
  };
  async changeName(){ /*中略*/ };
}
```

##class内では定数が作れない
　ChromeExtensionの情報保存手段として、chrome.storageというAPIがあります。JSON形式で保存するのでkeyが必要になります。でも設定とかを保存するので、毎回決まったkeyを使います。そのためkeyが定数だとタイプミスの可能性が減り、プログラムの完成度が上がります。でも、class内ではconstが使えません。

###対策
　getterを使うことで読み込み専用のプロパティを作り、定数として運用します。

```javascript
class Test{
 
 static get GREETING() {
    return "greeting";
 };

 saveGreeting(){
 const obj = {[Test.GREETING]: "hello"};
 chrome.storage.sync.set(obj, () => {
  if (chrome.runtime.lastError) {
          return ;
        } else {
          resolve(objectPlusKey);
        }
      });
    });
}
```

##最後に
　多分今後も色々気づきがありそうなので、その都度加筆するか新しい記事を書きます。あと、１月末くらいまでにはChromeExtentionが一つリリースできそうなので、試してみていただけたら幸いです。リリース時には多分Twitterで告知します。なので、フォローしてくださったらとても嬉しいです。（欲張りな告知）

###参考文献
https://qiita.com/guru_taka/items/37a90766f4f845e963e5
https://qiita.com/k7a/items/26d7a22233ecdf48fed8
https://qiita.com/noriaki/items/e7adaaf440020fbf6836
MacでRaspberry Piにraspbianをインストールする

放置していたRaspberry Piを動かしてpythonを実行するリモートサーバにしたので、メモとしてまとめておく。また、開発・実行はDockerコンテナ内で行うことにした。今回はOSのインストールから簡易な設定まで

## Raspberry PiにRaspbianをインストール

ssh接続を用いればOSのインストールから設定までマウスもキーボードもスクリーンも必要ないらしい。

イメージを焼く〜簡易な設定までは[こちら](https://blog.bnikka.com/raspberrypi/raspberrypi-install.html)と[こちら](https://qiita.com/shippokun/items/9070fc58f69d8c063e44)を参考にした。

まず[RaspbianのOSのイメージをダウロード](https://www.raspberrypi.org/downloads/raspbian/)してくる。デスクトップ+recommended software, デスクトップ, Liteの三種類が存在するが、今回はサーバとして動かす目的でデスクトップは必要ないと思われるので、Liteを選んだ。
SDカードを差し込んだのち、以下のコマンドを実行してSDカードがどこに認識されているかを調べる。


```
$ diskutil list

/dev/disk0 (internal):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                         251.0 GB   disk0
   1:                        EFI EFI                     314.6 MB   disk0s1
   2:                 Apple_APFS Container disk1         250.7 GB   disk0s2

/dev/disk1 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +250.7 GB   disk1
                                 Physical Store disk0s2
   1:                APFS Volume Macintosh HD            234.8 GB   disk1s1
   2:                APFS Volume Preboot                 45.5 MB    disk1s2
   3:                APFS Volume Recovery                528.0 MB   disk1s3
   4:                APFS Volume VM                      3.2 GB     disk1s4

```
SDカードを差し込む前後で表示される内容に差があるので、その新しく追加されたマウントがSDカードである。


`/dev/disk2`にSDカードがマウントされていることがわかったので、フォーマットする。

```
$ diskutil unMountDisk /dev/disk2
$ diskutil eraseDisk FAT32 [デバイス名] /dev/disk2
```
デバイス名は適当に。
ダウロードしてきたイメージを焼く。

```
$ diskutil unMountDisk /dev/disk2
$ sudo dd bs=1m if=2019-09-26-raspbian-buster-lite.img of=/dev/rdisk2 conv=sync
```

このあと焼いたSDカードに空のファイル`/Volume/boot/ssh`を作成する。このファイルを作っておくことで、デフォルトでRaspberry PiにSSHデーモンが立ち上がり、ssh接続ができるようになるらしい。

```
$ touch /Volume/boot/ssh
```

## ssh接続と初期設定

ssh接続するためには、IPアドレスを確認しなければならない。デフォルトでは、DHCP（IPアドレスが動的に割り当てられる方式）でIPアドレスが設定されるので、すぐにはわからない。今回は、たまたまルータの設定アプリからIPアドレスを確認できた。デフォルト`username: pi`, `password: raspberry`でログインすることができる。

```
$ ssh pi@[IPアドレス]
$ pi@[IPアドレス]’s password:
$ pi@raspberrypi ~ 
```

今回は固定IPアドレスを追加しなかったが、追加したい場合は[参考URL](https://blog.bnikka.com/raspberrypi/raspberrypi-install.html)から。

パスワードの設定

```
$ sudo passwd root
```

hoge ユーザの追加

```
$ sudo adduser hoge
```

hogeユーザにsudo権限

```
$ sudo gpasswd -a hoge sudo
```

piユーザをsudoから外す

```
$ sudo gpasswd -d pi sudo
```

今回はここまで、この後Dockerのインストールへと続く
Goで世界のナベアツになるFizzBuzzをつくってみた

# 背景

漠然とGoの勉強をしたいなと思い、Goのチュートリアルを眺めていたが、突然の睡魔が襲ってきた。
そこで、Goの基本的な機能だけを確認して、何か動くものを作って見ようと思い実装へ。

言語習得チュートリアルといえばFizzBuzz！！
と思ったが、それではつまらないなということで、FizzBuzzに応用をこらしたものは何か・・・と考えること約1分。
「世界のナベアツ」のネタが浮かび、実装してみることに。

# 世界のナベアツとは？

- 3の倍数と3が付く数字の時だけあほになる人
  - 個人的な感想として、初めて見た時は笑いが止まらなかった
  - 久しぶりにYOUTUBEとかで動画を見ると面白いww
- 少し調べてみると、どうやら落語家([桂三度(Wikipedia)](https://ja.wikipedia.org/wiki/%E6%A1%82%E4%B8%89%E5%BA%A6))に転身したらしい

# つまり・・

3の倍数と3が付く数字を検出してみた、ただそれだけの話である。

# 実装

簡単に書くことができた。

```fizzbuzz.go
package main

import (
    "fmt"
    "strconv"
    "strings"
)

func main() {
    var input string
    fmt.Print("FizzBuzzの繰り返し回数は？")
    fmt.Scan(&input)

    if isPositiveInteger(input) {
        calc(input)
    } else {
        fmt.Println("自然数を入力してください")
    }
}

// 処理部分
func calc(input string) {
    var intInput int
    intInput, _ = strconv.Atoi(input)

    for i := 1; i <= intInput; i++ {
        var stringI string = strconv.Itoa(i)

        if i%3 == 0 && isHavingThree(stringI) {
            fmt.Println(stringI + ": 3の倍数、3の付く数字")
        } else if i%3 == 0 {
            fmt.Println(stringI + ": 3の倍数")
        } else if isHavingThree(stringI) {
            fmt.Println(stringI + ": 3の付く数字")
        } else {
            fmt.Println(stringI + ":")
        }
    }
}

// 入力値の自然数チェック
func isPositiveInteger(input string) bool {
    var checkInput int
    checkInput, _ = strconv.Atoi(input)
    if checkInput < 1 {
        return false
    }
    return true
}

// 3が付く数字かのチェック
func isHavingThree(stringI string) bool {
    return strings.Contains(stringI, "3")
}
```

# 出力結果

```
FizzBuzzの繰り返し回数は？40
1:
2:
3: 3の倍数、3の付く数字
4:
5:
6: 3の倍数
7:
8:
9: 3の倍数
10:
11:
12: 3の倍数
13: 3の付く数字
14:
15: 3の倍数
16:
17:
18: 3の倍数
19:
20:
21: 3の倍数
22:
23: 3の付く数字
24: 3の倍数
25:
26:
27: 3の倍数
28:
29:
30: 3の倍数、3の付く数字
31: 3の付く数字
32: 3の付く数字
33: 3の倍数、3の付く数字
34: 3の付く数字
35: 3の付く数字
36: 3の倍数、3の付く数字
37: 3の付く数字
38: 3の付く数字
39: 3の倍数、3の付く数字
40:
```

# 実装してみての学び

- Goの基本的な型変換
  - 数値 (int) → 文字列 (string)：strconv.Itoa(123)  // -> "123"
  - 文字列 (String) → 数値 (Int)：strconv.Atoi("123")  // -> 123
- Int型でない値(例えばString型)をInt型に変換してもエラーにならず、Int型の0が返る
  - strconv.Atoi("abc")  // -> 0
- 文字列中に指定文字列が含まれているかの確認方法
  - strings.Contains("123", "3")  // -> true
- Goのビルド方法、簡易走行方法
  - ビルド -> 実行：`go build fizzbuzz.go` -> `./fizzbuzz`
  - 簡易実行：`go run fizzbuzz.go`

#  おわりに

シンプルかつ簡単に実装できて、これがGoの力かと実感。
もっと面白い物をGoで作りたい！

# 参考
- [golang　文字列→数値、数値→文字列変換](https://qiita.com/quicksort/items/c9522793a941edf074fd)
- [[Golang] 文字列操作サンプル](https://qiita.com/tchnkmr/items/b3d0b884db8d7d91fb1b)
はじめての共同開発でGitHubがめっちゃ便利だったって話

<h1>はじめに</H1>
先月、自分が通っていた<a href= https://www.protosolution.co.jp/codebase/>CodeBase</a>というプログラミングスクールの卒業生が参加できる、β版ハッカソンに参加してきました。（β版ハッカソンとはビジネスアイデアはあるけれど技術がない人と技術を学び始めたけれど、まだ実践経験がない人をマッチングしてアプリケーションを開発する場所みたいなものです。）そこで、今まで個人開発でしか使用していなかったGitHubが共同開発で利用するとめちゃくちゃ便利だなと思ったのでここに記しておきます。

<h1>GitHubとは</h1>
GitHubとはソフトウェア開発においてソースコードをオンライン上で管理できるプラットフォームです。ソースコードをオンラインで管理することにより、エンジニアが協同で開発作業を行なったり、レビューをしてソースコードのブラッシュアップしたりできます。

<h1>GitHubが便利だなと思ったポイント</H1>
①ブランチを変更することで、アプリを動かせる状態にしつつ開発を行える
　アプリケーション開発時には、アプリケーションが常に正常に動いているマスターブランチの他にも、複数のブランチに分岐させることで複数の開発や変更を同時に進めることができます。分岐させたブランチは後でマージすることでそれぞれで開発した機能を１つのブランチに統合することができるので、共同での開発がすごく楽になります。

②管理する場所を一元化することで、ファイルの重複を防ぐことができる
　自分的にはこれが1番便利だと思ったポイント。パワポとかで例えるとわかりやすいんですけど、パワポの共同作成っていちいちラインにあげたものをダウンロードして、自分の担当のところを編集して、またラインにあげてってしているうちに、同じような名前のパワポが5とか10とか増えていくんです。そうなってしまったらどれが最新かわからないし、どのファイルでどんな変更したかも分からないからいちいちファイルを開くか、変更した人に詳しく聞くかをしないといけなくなります。GitHubではそんなことなくて、プロジェクトが一元管理されているから、変更した部分だけが更新されて、どこを編集したかもわかりやすいのでそういった問題が起こりにくいんです。

<h1>今回の開発で使いまくったGitコマンド</h1>

```
 git branch -a
 git fetch
 git checkout branch名 origin branch名
 got pull
```

共同開発でメンバーが作ったリモートのリポジトリにアクセスするコマンド群です。これらだけで他人の作ったブランチを簡単に自分のローカルブランチに持ってくることができます。

```
 git add .
 git commit -m ‘コメント’
 git push origin branch名
```
これらは、自分が開発した部分をオンラインに上げることができるコマンドです。変更した部分をすぐにオンラインに共有できたらとても楽ですよね。ちなみに、コメントの部分には自分が開発・変更したことを書くとメンバーにも分かりやすい、効率性のある開発になると思います。

```
 git stash
 git stash apply stash@{番号}

```
これらは、自分が変更を加えている時に、メンバーの変更部分を統合しないといけなくなった時に一度自分の変更した部分を横に置いておくっていうコマンドです。2行目のapplyコマンドを使用することによりこの横に置いていた部分をまた戻して作業を再開することができます。

<H1>共同開発でGitHubを使うときに気をつけるべきポイント</h1>
GitHubを使って共同開発をする上で（ていうか共同開発する上で）気をつけようって思ったポイントもありました。

①インデントを揃える
②無駄な改行やスペースを入れない
③いらないコードやコメントアウトは消す
④自分が書いたコードがなぜこのようになったのかというプロセスをissueに書き残す

上の３つは個人開発の時によくやってしまっていました。特に③が1番多かった。binding pry や　binding irb でシステムの挙動を確認して、また後でやるかもしれないからコメントアウトして置いておくつもりがそのまま忘れてしまうことが多いんですよね。

でも、やっぱり仕事でのシステムやアプリケーション開発って基本的にみんなで一緒に開発していくものだから、誰が見ても見やすい&意味が分かるようなコードの書き方を心がける必要があるなって今回のβ版ハッカソンで強く思いました。

④は何で気をつけるべきかっていうと、自分がなんでこのコードの書き方をしたのかっていうとプロセスを開発メンバーに知っててもらうことで、一緒に開発していくときに生じるズレを少なくしていけるっていうメリットがあります。エンジニアってコミュニケーションのいらない職業って思われがちだけど、システムが動かなくなったり、開発スケジュールの遅延に関わってくることもあるからメンバー同士のコミュニケーションは必須だと思います。

あと、開発の時に詰まったところとその解決策を残しておくことで、後で見返したり、他のメンバーが開発するときの参考になったりするから再現性が高くなるんですよね。

<h1>まとめ</h1>
というわけで色々書き連ねたんですが、「共同開発でGitHub使おうぜ」って感じでまとめとさてください。ちなみに、自分のつくりたいアプリケーションとかシステムがあったらGitHubで探してみてください。結構いろんな書き方があって参考になると思います。（自分は個人開発の時に色々漁ってました。）

あと、β版ハッカソンめっちゃ楽しかった。まだプログラミングを始めて半年も経たないペーペーの意見にも耳を傾けてくれたし、先輩方の考え方や開発の技術も、参考になってとても刺激になりました。是非ともまた参加したい。

沖縄でエンジニアの勉強始めてみたい方、<a href= https://www.protosolution.co.jp/codebase/>CodeBase</a>おすすめなので是非チェックしてみてください。（急な宣伝）
CloudFuntionsで「File ./dist/index.js that is expected to define function doesn't exist」と言われた(TypeScript)

[Google Cloud Functions](https://cloud.google.com/functions/?hl=ja)とTypeScriptを使ってとあるSlackボットを作っていたら、正しく依存関係を指定しているはずなのに「File ./dist/index.js that is expected to define function doesn't exist」というエラーが出てうまくデプロイできず、結構ハマったので原因と解決策を。

(あたりまえですが`./dist/index.js`のところは個人が設定しているエントリポイントによってかわります)

---
## 先に結論。
[GCloud Functions: load error: File ./dist/index.js that is expected to define function doesn't exist - Stack Overflow](https://stackoverflow.com/questions/52062359/gcloud-functions-load-error-file-dist-index-js-that-is-expected-to-define-fu)

ここに書いてあることがすべて

## 構成
```
├── .gitignore
├── README.md
├── dist
│   └── index.ts
├── package-lock.json
├── package.json
├── src
│   └── index.ts
└── tsconfig.json
```

src配下にTypeScriptのファイルが配置されていて、それをコンパイルするとdist配下にJSが吐かれるというよくあるかんじの構成です。

package.jsonの`main`には`dist/index.js`が指定されています。

また、.gitignoreにはdistが指定されています。これもTypeScriptのプロジェクトではよくあることかなと思います。

## デプロイしようとした

完成したのでデプロイしようとして以下のようなコマンドを実行しました。

tscでコンパイルを行い、2行目のgcloudを使ってCloud Functionsへデプロイを実行しました。

```shell
$ npx tsc
$ gcloud functions deploy hoge --runtime nodejs8 --trigger-http --project hoge-proj
```

すると、「File ./dist/index.js that is expected to define function doesn't exist」というエラーが発生しました。

間違いなくdistの下にindex.jsファイルはあるのにおかしいと思い、いろいろ調べたり悩んだ結果たどり着いたのが上記に貼ったStackOverflowでした。

## 原因
`gcloud functions deploy`を実行すると`.gcloudignore`というファイルが自動的に作成されます。

こんなファイルです

```
  
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
#   $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
node_modules
#!include:.gitignore
```

.gitやnode_modulesなど、Cloud Functions側にあげる必要のないファイルを.gitignoreと同じような形式で書いておくことで、無視してくれるようになります。

今回原因となったのは一番最後の行、`#!include:.gitignore`これです。

これは.gitignoreの内容を取り込んでくれるものになります(多分)。今回私は.gitignoreにdistを指定していたため、gcloud function deployを実行しても肝心のdist以下がアップロードされずにエラーが出た、というのが原因でした。

## 解決策
最後の行に`!dist`と書き足すとよいです。これだけでdist以下を読んでくれるようになります。ついでにsrcはあげなくていいので`src`と書き足しておくといいかもしれません。

## まとめ
普通にJS書いてた時はうまくいってたので、油断してたらこんな罠が…と言う感じでした。

FirebaseのFunctionsはfirebase-toolsで初期化するときにTypeScriptを使う選択をすると、自動的にこの辺のファイルとかのテンプレを吐き出してくれるので、困ったことなかったのですが、今回使ったのはGCPの方のFunctionsだったのでハマってしまいました。

調べ方がわるかったのか、なかなか上記StackOverFlowにも辿りつかず、結構苦労しました。

この記事が誰かの役に立つといいなあ。

おわり。