OmniAICreator/Qiita-1.07M huggingface dataset:
ModuleNotFoundError: No module named 'py4j'

# 結論
**未解決**
# 背景
Dockerfile内で

```Dockerfile
From jupyter/jupyter/pyspark-notebook:~~~~~~~~~
```

としてPysparkを読み込んでいる.

# 環境
```
Python 3.7.6
pyspark 2.4.5

```


### 該当箇所

```python
from pyspark.sql import SparkSession
```

### エラー内容
```python
/usr/local/spark/python/pyspark/__init__.py in <module>
     49 
     50 from pyspark.conf import SparkConf
---> 51 from pyspark.context import SparkContext
     52 from pyspark.rdd import RDD, RDDBarrier
     53 from pyspark.files import SparkFiles

/usr/local/spark/python/pyspark/context.py in <module>
     27 from tempfile import NamedTemporaryFile
     28 
---> 29 from py4j.protocol import Py4JError
     30 
     31 from pyspark import accumulators

ModuleNotFoundError: No module named 'py4j'
```

# 対応方法
支障が出るので今回はjupyter notebook上で

```shell
!pip install py4j
```
と対応した
以下のエラーが出るので、エラーのでない対応方法が分かり次第追記したいと思います

```shell
ERROR: pyspark 2.4.5 has requirement py4j==0.10.7, but you'll have py4j 0.10.9.1 which is incompatible.
```

# 参考
- [PySpark documentation](https://spark.apache.org/docs/2.4.5/api/python/pyspark.sql.html#pyspark.sql.SparkSession)
- [Where’s your code? Debugging ImportError and ModuleNotFoundErrors in your Docker image](https://pythonspeed.com/articles/importerror-docker/)
- [久しぶりで pyspark 立ち上げたら No module named 'py4j' と出た件](https://qiita.com/makainuma/items/9350b62ef72736a448f6)
- [stack overflow: ModuleNotFoundError: No module named 'py4j'
](https://stackoverflow.com/questions/56342655/modulenotfounderror-no-module-named-py4j)
[iOS]Google Mobile ADs（バナー広告）の導入

## 作業

[Firebase を iOS プロジェクトに追加する](https://firebase.google.com/docs/ios/setup)

- 後から行う作業としてApp Store ID追加あり。App Store IDとは、iOSアプリのApp Store上でのID。App Store ConnectのMy Appのところから確認できる他、公開済みのアプリの場合、App Store上でのURLの末尾がApp Store IDとなっている。


[複数のプロジェクトを構成する場合の注意点](https://firebase.google.com/docs/projects/multiprojects)
[使ってみる - Google Mobile ADs SDK](https://firebase.google.com/docs/admob/ios/quick-start?hl=ja)
[バナー広告](https://developers.google.com/admob/ios/banner?hl=ja)

- アプリ公開後にApp Store ID追加あり

## テスト

テストは基本的にテスト専用の広告IDを使うこと。本番用の広告IDを使い、しかもそれをクリックしてしまうとライセンス違反となりアカウントが凍結される恐れがある。

[テスト方法](https://support.google.com/admob/answer/9388275)

## トラブルシューティング

テスト用で広告が出たが、本番用で広告が出なかった。アプリ公開から二週間ほど経っているが・・・

Admob: adView:didFailToReceiveAdWithError: Publisher data not found. <https://support.google.com/admob/answer/9905175#9>
とのエラーが。google ad mob に支払い方法を追加してなかったのが原因。

Safari でgoogle ad mobのマイページを開くと、エラーが表示され支払い方法を登録できなかった。Google Chromeで試したところ、支払い方法を登録することができ、広告が配信された。
Qiitaを使ってみます

ドコモ光に切り替えて、ルータ環境も一新しました。
ネットワーク環境も再構築なので、そういった構築絡みの情報を書き留めてみたいなと考えています。
まずは初めての投稿です、お目汚し申し訳ありません。
Git ローカルリポジトリの歴史をリセットする

# 目的

- 「今コミットした最新コミット取り消したい！！」というときの方法をまとめる

# 前提情報

- 筆者が確認した環境を簡単にまとめる
    1. 任意のディレクトリにgit_testディレクトリを作成し、git_testディレクトリに移動して`$ git init`コマンドを実行した。
    1. 下記コマンドを実行してファーストコミットを実行する。

        ```terminal
        $ git commit -m 'first commit' --allow-empty
        ```
    1. 下記コマンドを実行してgit_testディレクトリ直下にテキストファイルを作成する。

        ```terminal
        $ echo 'aaa' > test.txt
        ```
    1. 下記コマンドを実行して追加したテキストファイルをコミットする。

        ```terminal
        $ git add test.txt
        $ git commit -m 'テキストファイルの追加'
        ```
- ローカルの最新コミットがコミットメッセージ「テキストファイルの追加」のコミットだとする。

    ![Git_ローカルリポジトリの歴史をリセットする_md_—_miriwo_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3e839c00-3d4c-2d3a-6d20-eb5832f3b7aa.png)

- 最新のコミットをなかったことにしてコミットメッセージ「first commit」のコミットまで状態を戻したい。

# 方法

1. ローカルリポジトリ内で下記コマンドを実行してコミットログを出力する。

    ```terminal
    $ git log
    ```
1. 表示されたログの中でその状態まで戻したいコミットのコミットIDをコピーする。（今回はコミットメッセージが「first commit」のコミットまで戻したいので下記をコピーする。）

    ![Git_ローカルリポジトリの歴史をリセットする_md_—_miriwo_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7d81a3df-9a64-d1fa-76ad-0887adaa485d.png)

1. ローカルリポジトリ内で下記コマンドをして最新のコミットをなかったことにし、IDで指定したコミットまで状態を戻す。

    ```terminal
    $ git reset 先程コピーしたコミットID
    ```
1. test.txtを登録したコミットがなくなり、text.txtは存在するがgit管理させる前の状態になる。
PRML 演習問題 7.6 解答

## 問題
> 出力値が$\mathrm{t\in\}${$\mathrm{-1, 1}$}であるロジスティック回帰モデルについて考える. (7.1)という形の$\mathrm{y(x)}$を用いて$\mathrm{p(t=1|y)=\sigma(y)}$とすると尤度関数(の符号を反転したもの)に2乗ノルムの正則化項を加えたものは(7.47)という形を取ることを示せ.
$$
\mathrm{y(x)=w^t\phi(x)+b}
\tag{7.1}
$$
$$
\mathrm{\sum^N_{n=1}E_{LR}(y_nt_n)+\lambda\parallel{w}\parallel^2}
\tag{7.47}
$$

## 方針

　まず$\mathrm{p(t=1|y)=\sigma(y)}$を, データ$\mathrm{(t_1,y_1),(t_2,y_2),...}$に対し一般化し, 尤度関数について考える. 式の変形と整理を行うことで目的の式である(7.47)を導出する.

## 解答

$\mathit{p}$($\mathit{t}$=1|$\mathit{y}$)=$\mathrm{\sigma}$($\mathit{y}$)とすると,$\mathit{t\in\}${$\mathrm{-1, 1}$}より

```math
\begin{align*}
\mathit{p}(\mathit{t}=-1|\mathit{y})=1-\mathit{p}(\mathit{t}=1|\mathit{y})=1-\mathrm{\sigma(}\mathit{y}\mathrm{)}=\mathrm{\sigma(}\mathit{-y})
\end{align*}
```

である.したがって

```math
\begin{align*}
\mathit{p}(\mathit{t|y})=\mathrm{\sigma}(\mathit{yt})
\tag{7.46}
\end{align*}
```

データ($\mathit{t_1, y_1}$), ($\mathit{t_2, y_2}$),...の尤度関数は

```math
\begin{align*}
\mathit{p}(\mathit{t_1,t_2,...|y_1,y_2,...})&=\mathit{p}(\mathit{t_1|y_1})\mathit{p}(\mathit{t_2|y_2})...\\
&=\mathrm{\prod_{i=1}^N\sigma}(\mathit{y_it_i})
\tag{a}
\end{align*}
```

よって(a)の負の対数を取ることで負の対数尤度関数を得る.

```math
\begin{align*}
-\mathrm{ln\prod_{i=1}^N\sigma}(\mathit{y_it_i})
&=-\mathrm{\sum_{i=1}^Nln\sigma}(\mathit{y_it_i})\\
&=-\mathrm{\sum{ln}\frac{1}{1+exp(-\mathit{y_it_i})}}(ロジスティック回帰なので\mathrm{\sigma}の定義より)\\
&=\mathrm{\sum{ln}(1+exp(-\mathit{y_it_i}))}
\end{align*}
```

と上記のように変形を行うことで(b)で示される誤差関数を得る.

```math
\begin{align*}
\mathit{E}=\mathrm{\sum^N_{i=1}ln(1+exp(-\mathit{y_it_i}))}
\tag{b}
\end{align*}
```

二乗ノルムの正則化項を追加すると以下の(c)を得る

```math
\begin{align*}
\mathit{E}=\mathrm{\sum^N_{i=1}ln(1+exp(-\mathit{y_it_i}))+\lambda{\parallel{w}\parallel}}
\tag{c}
\end{align*}
```

ここで(7.48)を用いると
>
$$
\mathit{E_\mathrm{LR}(\mathit{y_nt_n})}=\mathrm{ln(1+exp(-\mathit{yt}))}
\tag{7.48}
$$

(7.47)を得る

```math
\begin{align*}
\mathit{E}=\mathrm{\sum^N_{i=1}}\mathit{E_\mathrm{LR}}(\mathit{y_it_i})+\mathrm{\lambda{\parallel}{w}\parallel}
\tag{7.47}
\end{align*}
```

したがって題意は示された.
Salesforceデータ統合に関するブログをまとめて紹介

XplentyはSalesforceのオブジェクトのデータ読み込みと書き込みの両方をサポートしています。また、異なるSalesforceの組織間のデータを連携するSalesforce to Salesforceの連携も可能です。また、Heroku PostgeSQL DBとHeroku ConnectによりSalesforceと任意のアプリケーション間の大量データのリアルタイム連携を実現するシナリオにも対応しています。

今回のブログでは、Salesforceデータ統合およびHeroku Connectを使用したデータ統合の２つをテーマにしたブログについて紹介したいと思います。**各ブログのタイトルをクリックすると、ブログ本文に遷移します。**

#Salesforce データ統合
##[Salesforceでウェブサイト解析データを活用する際に Xplentyを利用するメリット](https://www.xplenty.com/jp/blog/salesforce-website-analytics-with-xplenty-ja/)
顧客や見込み客がウェブサイトをどのように利用しているかをキャプチャして把握することは、営業とマーケティング間でのループを終わらせ、顧客主導のエンゲージメントを実現するために非常に重要となります。

以下の3つのコンポーネントを深く掘り下げて、Web サイトを活用して Salesforce インスタンスにマーケティングインテリジェンスを導入する方法を見てみましょう
- SalesforceとWebサイト間の共有キー。
- クリックをキャプチャし、ログの共有キーに結びつける Web サイトアプリケーション。
- 大量のログを取得し、Salesforce に転送できる実用的な、もしくは少なくとも理解可能なデータに集計するための手段。

##[Salesforce データマイグレーション入門](https://www.xplenty.com/jp/blog/salesforce-data-migration-ja/)
Xplentyでは、十分な情報に基づき、ビジネスニーズに沿ったテクノロジーを選択できるよう、どういったオプションが利用可能かについて理解を深めていただこうと考えています。 3つの主要なデータ連携戦略を見て、どれが皆さんのアプリケーションに適しているかを見ていきましょう。

##[XplentyによるSalesforce 統合: デベロッパーの生産性を最大化](https://www.xplenty.com/jp/blog/maximize-productivity-xplenty-salesforce-ja/)
Xplentyは、シンプルなドラッグアンドドロップのインターフェースを持つ強力な統合ツールです。  コーディングの経験やスキルがなくても、多くのお客様がコーディングなしで強力な統合を作成するのに使用しています。しかし、ソフトウェアエンジニアの場合はどうでしょうか？確かにエンジニアであればキーボードを取り出して、統合を実装するためにコードを書き始めるのではと思いますよね？  しかしユニオン・ストリート・メディアの場合は違いました。この企業では、2人のソフトウェア・エンジニアがXplentyを使って、統合のためにコードを書くことなく顧客レポートの置き換えを実現しました。

##[Salesforce to Salesforce統合でレコードを共有する方法](https://www.xplenty.com/jp/blog/salesforce-to-salesforce-ja/)
この記事では、Salesforce to Salesforce 統合について知っておくべき点についてすべて説明します。Salesforce to Salesforce 統合を実行する理由について説明した後、データを共有するためのすべてのオプションとベストプラクティスについて説明します。

#Heroku Connect
##[Salesforceのデータ統合にHeroku Connectを利用するメリット](https://www.xplenty.com/jp/blog/heroku-connect-and-salesforce-ja/)
Heroku Connect の紹介をお読みになった方は、Heroku Connect を使用することで、Postgres データベース内にSalesforceのニアリアルタイムのコピーを手に入れることができるのをご存知かと思います。また、Xplentyのグラフィカルなデータパイプラインエディタを使って Postgres データベースからデータを読み書きできることもご存知かもしれません。  しかし、これらのツールがどのようなにフィットするのか疑問に思うかもしれません。XplentyとHeroku Connectがどのように機能するかを説明するために、架空ではありますが一般的なXplentyとHeroku Connectのユースケースを見てみましょう。

##[XplentyとHeroku Connect：完璧なSalesforce統合ソリューション](https://www.xplenty.com/jp/blog/salesforce-heroku-connect-ja/)
Xplentyでは、企業内のデータ統合にHeroku ConnectとXplentyを併用しているお客様が数多くいらっしゃいます。 XplentyとHeroku Connectは、どちらもSalesforceに対して双方向のデータ接続を提供しているため、どちらか一方だけをを使用しなければならないと思われるかもしれません。しかし、私たちの経験から見ると、それぞれのツールが特定の強みを持っており、全体のソリューションを補完することができます。 このブログを通して、XplentyソリューションとHeroku Connect、さらにそれらが連携させることでSalesforceのデータ統合における課題にどのように対処できるのかを見ていきましょう。

##[Xplenty + Heroku Connect : Salesforceとのデータ連携を柔軟に（動画あり）](https://www.xplenty.com/jp/blog/sf-integration-xplenty-heroku-connect-ja/)
今回はHerokuマーケットプレイスで利用可能な3つのAdd-onを使って、外部データをSalesforceにカンタンにほぼリアルタイムで連携する方法についてご紹介します。
スクラム開発で身についたスキル

以前、私はスクラム開発の現場にいました。
今はスクラムでない別の開発現場にいますが、スクラム開発の現場で身についたスキルが活きているなと感じる瞬間がありました。
そのため備忘録として残しておきます。

# 自主性

例えば、Git の運用ルールが明確に決まっていない、という問題点に気付いたとします。
ここで元々チームにいた人とかがまとめてくれるのを待つのではなく、自分からすぐにドキュメントに起こして、まず自分の認識しているルールをまとめます。
そして、ドキュメントを共有して誰でも編集できる状態にしておき、認識が違っていたら別途追記してもらうようにします。
スクラムでは誰かに依存するのではなく、各々が自律的に動くことを求められますので、それが自然と身についていることに気づきました。

# CI/CD などの自動化

スクラム開発、もといアジャイル開発では 1 スプリントの中で要件定義からリリースまでを終える必要があります。
当然ながら時間がないので、自動化を進めていかないと到底終わりません。
そのため CI/CD 環境の構築、テストの自動化などについて関心が高まり、色々調べるようになりました。
もともと Jenkins といったツールの存在は知っていたものの重要性は理解できておらず、実際に導入それらのツールの重要性を理解できました。

# レビュー力

チームメンバー間でレビューをし合うというのを毎日のように行っていました。
嫌でも数が積み重なるので、レビューのスピードや精度が上がりました。

# ペアプロ・モブプロ、ペア設計・モブ設計

ペアプロ・モブプロというのも初めて知りました。
複数人で進めることにより、別の視点を得ることができ、色々と勉強になりました。
常にレビューしてもらいながら進めるので、不安なく進めることができました。
また、プログラミングだけでなく設計も[Miro](https://miro.com/)や[Cacoo](https://cacoo.com/ja/)などを使って複数人で進めていました。

# 様々なツールの知見

効率化をするために、CI/CD などの自動化だけでなく様々なツールを試しました。
その中で使用したツールを挙げておきます。

- [Miro](https://miro.com/)
- [Cacoo](https://cacoo.com/ja/)
- [Typora](https://typora.io/)
- [HackMD](https://hackmd.io/)
- [Appium](http://appium.io/)
- [Postman](http://appium.io/)
- [Docker](https://www.docker.com/)
- [Toggl](https://toggl.com/)
- [Selenium IDE](https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd?hl=ja)
- [Simple URL Copy](https://chrome.google.com/webstore/detail/simple-url-copy/cefkgjbbpagcilodnhboolbppdjlplip)
- [zoom.us](https://zoom.us/jp-jp/meetings.html)
- [Zapier](https://zapier.com/)

# 振り返り

毎スプリントの振り返りには KPT、YWT、Fun/Done/Learn といった手法で振り返りを行っていました。
どれもスクラム開発を通して初めて知りました。
振り返りをすることで良かったことや悪かったことを明らかにし、次スプリントはどうしていくかの方向性を定めることができました。
振り返りの素晴らしさを実感し、今では実生活においても振り返りをするようになりました。

# まとめ

スクラム開発は開発手法として素晴らしいです。
スクラムの進め方や様々な概念（PBL、SBL、ストーリーポイントなど）を知ることができるだけでなく、上述したようなスキルも得られます。
正直得られるスキルが多すぎて、もうスクラム開発しかやりたくなくなるレベルです。
ただし、きちんとスクラムのやり方に則っていることが前提の話なので注意してください。
WebGLでモーフィングしつつ陰影を表現する方法

#はじめに

WebGLで陰影を表現する際、法線ベクトルの情報が必要になる。形が固定されたオブジェクトの場合、Three.jsではcomputeFaceNormalsやcomputeVertexNormals等の関数を用いて法線ベクトルを自動計算させることが出来るが、GLSL内で頂点を移動させる場合はThree.jsの範疇にないのでこれらの関数を使って法線ベクトルを計算することができない。この記事は特定のルールに従って頂点シェーダ内で頂点位置を動かす際の法線ベクトルをGLSL内で計算する方法を実装した際のメモである。

#前提条件

* Three.jsを使う（r121）
* ShaderMaterialを使う（Three.jsで自作シェーダを使用可能にする）
* Chrome、Firefox、Safariで動作する（Edgeでも動作すると思うが未検証）

ChromeとFirefoxはWebGL2対応、SafariはWebGL2非対応で、いずれでも動作させたい

#スクリプトの実際

法線ベクトルを求めるにはGLSLのdFdx関数とdFdy関数を使用する。これらの関数はWebGL2からは標準で利用できるが、WebGLでは拡張機能を有効化しないと利用できない。ShaderMaterialには拡張機能を有効化する手段が提供されている。

```JavaScript
const material	= new THREE.ShaderMaterial({
	'vertexShader'		: vShader,
	'fragmentShader'	: fShader,
	'uniforms'			: uniforms,
	'extensions'		: {
								'derivatives'	: true	//ココ
							}
});
```

最初はこれを見つけられず（意味を理解していなかった）、手動でrendererに対してextensionを登録して、色々と工夫して有効化していたが、これを追加することで全てThree.jsが吸収してくれた（2020.11.01修正）。

```GLSL
varying vec4 vPosition;
//法線ベクトルを求める魔法の関数
vec3 getNormal ( vec3 position ) {
	vec3 dx = dFdx( position );
	vec3 dy = dFdy( position );
	return normalize( cross(dx, dy) );
}
void main () {
	//頂点座標から法線を求める
	vec3 normal = getNormal( gl_FragCoord );
	
	//ここから先の処理は光源の種類で異なる（と思う）
	//平行光を使用した場合の光源の向きをlightとする
	//元の出力色をoriginalColorとする
	float diff		= clamp( dot(light, normal), 0.1, 1.0 );
	gl_FragColor	= clamp( outColor * diff, 0.0, 1.0 );
}
```

getNormal関数でなぜ法線ベクトルが求まるのかはよくわからないが、陰影が出るようになったので取り敢えず良しとした。時間があるときにこの関数の意味を調べたい。

#参考

* https://qiita.com/UsagiLabo/questions/aee36fbdabe5629e55a2
* https://qiita.com/gam0022/items/1878150981494fd66abe
* https://wgld.org/d/glsl/g010.html
* https://wgld.org/d/webgl/w021.html
vuejs-datepickerで動的に多言語対応する方法

# 概要
ユーザーが設定している表示言語設定に応じてvuejs-datepickerの表示言語を動的に変更するという実装をする際、vuejs-datepickerの表示言語を親コンポーネントから制御する方法に詰まったのでメモを残しておくの巻

#困ったこと
親コンポーネントとvuejs-datepickerを使用している子コンポーネントが存在し、親コンポーネントから渡すpropsに応じて子コンポーネント側で使用しているvuejs-datepickerの表示言語を変更すること

#解決策
全ての言語を配列としてimportし、dataオブジェクトの任意のプロパティの値として指定しておきます（下記コードの場合、all_langという名前でimportし、dataオブジェクトのlanguagesというプロパティの値としてall_langを指定しています）。
そして親コンポーネント側から使用したい言語を文字列でpropsとして渡し、その文字列をもとにlanguagesの配列から使用したい言語オブジェクトを抽出し、それをdatepickerのlanguageプロパティに指定すれば解決しました！あとは何らかの方法でjaやenなど言語の識別文字列をどこからか取得するだけ。
ちなみに下記の場合、親コンポーネントからスペイン語を指定しており、デフォルト日本語になっています！

```vuejs:App.vue
<template>
    <calender
        v-model="form.specical_date"
        title="ブロックタイトル"
        placeholder="プレースホルダー"
        language="es"
    />
</template>

<script>
import Calender from './components/Calender.vue';
export default {
    components: {
        Calender,
    },
    data() {
        return {
            form: {
                specical_date: null,
            },
        };
    },
};
</script>
```

```vuejs:Calender.vue
<template>
    <div>
        <span>{{ title }}</span>
        <datepicker
            format="yyyy-MM-dd"
            :language="languages[language]"
            :placeholder="placeholder"
            :clear-button="true"
            @input="updateDate"
        />
    </div>
</template>

<script>
import Datepicker from 'vuejs-datepicker';
import * as all_lang from 'vuejs-datepicker/dist/locale';
export default {
    components: {
        Datepicker
    },
    props: {
        title: {
            type: String,
            default: '',
        },
        placeholder: {
            type: String,
            default: ''
        },
        language: {
            type: String,
            default: 'ja'
        }
    },
    data() {
        return {
            languages: all_lang,
        };
    },
    methods: {
        updateDate(val) {
            this.$emit('input', val);
        },
    }
};
</script>
```
【AWSインフラ運用担当者向け】リリース自動化導入の全体像把握と始め方

こんにちは。
今回はAWSで動くアプリケーションのリリース自動化について書きます。

## 想定読者

①AWS運用（インフラ）しているが、リリースは手動で行っていて、面倒に感じている
②リリース自動化担当になったが、自動化するメリットやどの範囲まで自動化できるのか分かっていない
※①は今の、②は過去の自分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311339/dbb784fc-fffb-30ba-459d-d3a2392fa261.png)



## 記事のテーマ
・【AWS運用担当者向け】リリース自動化導入の全体像把握と始め方
　リリース自動化の威力
　リリース自動化の導入可能な範囲
　リリース自動化導入後のつまずきポイント
　まずは何を学ぶか、どう学んでいけばよいか

秒間数百アクセスの大規模ECサイトのリリース自動化を設計した経験で得た知見を纏めます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311339/25d7ed75-bacb-25c5-7247-0843386997ed.png)

なぜ自動化するのかという点については下記も参考にしてみてください。
（クラウドのベストプラクティス集に自動化必須の旨が記載されています）
[AWS Well-Architected 5本の柱を要約する（運用上の優秀性）](https://qiita.com/toma_shohei/items/3e8338ddfa6aca344c29)

## リリース自動化の威力
自動化というと面倒なことを自動化して運用が楽になるというイメージが先に来ると思うのですが、それだけではなく、システムの品質があがるという効果があります。

物事が簡単にできるということで劇的に変わることの例えです。
EX.水道が無かったら
⇒体を洗うのに川に水を浴びに行かないといけない
　⇒体を洗う頻度は下がる
　　⇒健康を害したり、体臭を気にするようになる
　　　⇒生活の品質が下がる

Ex.リリースに置き換えると
⇒リリースが自動化されて簡単にできるようになったら
　⇒リリースの頻度が変わる
　　⇒細かくリリースするようになる
　　　⇒細かいリリースは品質を上げる

## リリース自動化の導入範囲
リリースフローの中でどの部分が自動化可能か、その中でどれを自動化するべきかを考えます。

案件毎に違うかもしれませんが、リリースの一般的な流れは下記の通りだと思ってます。
　○開発
　　・自分の開発端末での開発（コード修正、試験）
　　・バージョン管理ツール（CodeCommitやGITやSVNなど）へのアップ
　　・コードレビュー
　
　○検証
　　・バージョン管理ツールから検証環境へコピー
　　・検証環境固有の情報の注入
　　・（必要な言語なら）ビルド
　　・新機能の検証、試験の実施
　　・既存機能の検証、試験の実施
　
　○リリース準備
　　・有識者のリリース判定会（検証結果を基に）

　○リリース（サービスイン）
　　・バージョン管理ツールから本番環境へコピー
　　・本番環境固有の情報の注入
　　・（必要な言語なら）ビルド
　　・サービスイン
　　・（可能なら）簡易動作確認

上記の流れの中で自動化できることは
○検証
と
○リリース（サービスイン）
です。
その中でも自動化が困難、不可な部分は諦めます。

## リリース自動化導入後のつまずきポイント
・自動化処理がエラーとなり、手動リリースが行われ、自動化環境のメンテもされず、徐々に自動化が使われなくなる
⇒自動化の設計時に自動化環境の維持をどうするか検討した方が良いです。

・パラメータ変更時に自動テスト用のコードも修正しないといけなくなる。（2重管理状態になる）
⇒何をテストするべきか検討した方が良いです。（多少のリスクはとっても）パラメータの自動試験は行わず、サイトの動作についてのみ自動試験を行うようにした方が良いと考えています。
　※テスト自動化は自分でも最適解が分っていないです。ここはもう少し勉強します。

データベース変更のようなサービス停止が必要なリリースでは自動化使えない？
⇒画像だけが変わる、アプリケーションコードが変わる、サーバ設定が変わる、データベースのテーブル列が増える、色々なリリースパターンを考えてそれぞれの自動化設計を行うようにします。
頻度が少ないリリースパターンなら自動化しないという選択もあるかと思います。
　
## まずは何を学ぶか、どう学んでいくか
Codeシリーズでスクリプト（シェル）をデプロイしてみるのが良いと思っています。
バージョン管理ツール、AWSのCodeシリーズの理解につながります。
色々なツールがありますが、AWSであればまずはGit（or CodeCommit）、CodePipeline、CodeDeployを利用してみてください。
環境固有の情報はSystemsManagerのパラメータストアで管理するようにします。

全体像のイメージは下記のくろかわさんの動画が分かりやすいです。
[【はじめてのCI/CD】AWSでやってみるDevOps最初の一歩、CodeDeploy、CodePipelineを使った自動デプロイのハンズオン](https://www.youtube.com/watch?v=8mPm7jolnVk)

IaCを利用して自動化環境を構築する場合は、下記が大変参考になります。
[aws-samples/aws-cdk-examples/python/codepipeline-docker-build/](https://github.com/aws-samples/aws-cdk-examples/tree/master/python/codepipeline-docker-build)

IaCについては下記に記事を書いていますのでご参考ください。
[AWS自動化の心得（IaC編）](https://qiita.com/toma_shohei/items/1599ea6b6eea1422f3ef)
M5StickC Plusとステッピングモーターで日本を応援する

私は彼から無人で動く搬送ロボットを作ります！
そこで今回は搬送ロボットの製作の第一歩としステッピングモーターを回したいと思います。

##使用した材料
[Quimat Nema 17ステッピングモータ](https://www.amazon.co.jp/gp/product/B06XRFGTR4/ref=ppx_yo_dt_b_asin_title_o03_s02?ie=UTF8&psc=1)

[ステッピングモータドライバモジュール](https://www.amazon.co.jp/HiLetgo-5%E5%80%8B%E3%82%BB%E3%83%83%E3%83%88RepRap-%E3%82%B9%E3%83%86%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%A2%E3%83%BC%E3%82%BF%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB-HR4988-3D%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF%E3%83%BC/dp/B010Q17CAI/ref=pd_bxgy_img_2/357-0050218-4428251?_encoding=UTF8&pd_rd_i=B010Q17CAI&pd_rd_r=a072e781-2881-4baf-b946-07215d61d859&pd_rd_w=6W5gx&pd_rd_wg=WVyr1&pf_rd_p=e64b0a81-ca1b-4802-bd2c-a4b65bccc76e&pf_rd_r=7GC3P6CR642Y88E7XG89&psc=1&refRID=7GC3P6CR642Y88E7XG89)

##配線図
**※コンデンサには極性があるので注意です、破裂します。**
![Untitled Sketch_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206019/27c5cce3-7f8d-faa8-6396-b25bcb28df66.png)


#できたもの 

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">卒業制作の第一歩としてステッピングモータを回してみました。<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/M5stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5stack</a> <a href="https://t.co/bB9LDn6VbR">https://t.co/bB9LDn6VbR</a> <a href="https://t.co/LWDRWbjnIK">pic.twitter.com/LWDRWbjnIK</a></p>&mdash; Toshiki (@Hirasawa1987) <a href="https://twitter.com/Hirasawa1987/status/1316536822500007936?ref_src=twsrc%5Etfw">October 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

###ドライバの調整に苦戦
ステッピングドライバの調整時に参考にさせていただきました。
[Arduino と A4988 でステッピングモーターを制御する方法](https://iot.keicode.com/arduino/arduino-stepper-motor-a4988.php)

販売メーカが動画でも紹介されていてこちらも参考にしました(Youtube)
[Setting the Current Limit on Pololu Stepper Motor Driver Carriers](https://www.youtube.com/watch?v=89BHS9hfSUk&feature=emb_logo)

こんな感じで調整しました。
![IMG_1376[1].JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206019/45ffb2f6-bc62-81f5-70a6-ece9674af8b1.jpeg)

#コード
```js
#include <M5StickCPlus.h>

const int DIR  = 32;
const int STEP = 33;

void setup() {
  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);
  digitalWrite(DIR, LOW);
  digitalWrite(STEP, LOW);
}

void loop() {
  
  digitalWrite(DIR, HIGH);

  for (int i=0; i<200; i++) {
    digitalWrite(STEP, HIGH);
    delayMicroseconds(2000);
    digitalWrite(STEP, LOW);
    delayMicroseconds(2000);
  }

  delay(1000);

  digitalWrite(DIR, LOW);
  
  for (int i=0; i<200; i++) {
    digitalWrite(STEP, HIGH);
    delayMicroseconds(2000);
    digitalWrite(STEP, LOW);
    delayMicroseconds(2000);
  }

  delay(1000);

}
```

##展開


搬送ロボットに使うモーターは4個なので、4個を同時に制御できるように作りこんでいきたい。プログラムに関してもピンの指定を替えただけなので、JSON形式で飛んできたもので制御するなど挑戦していく。
【活性化関数】MishってSwishより精度良いの？

<h1>Mishの利点</h1>
・少しマイナスの情報を保持することでDyingReLU減少が改善された。
・Mishは飽和を避けてくれる。一般的にgradientが0に近いとtrainingのスピードが急激に遅くなる
・マイナスに行く事は強い正規化の効果もある
・ReLUのように特異点がない(連続である)


<h1>Swish Familyを比べてみた</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/1cb2e3df-11e0-4751-5f39-bb68025f269b.png)
Swishに似た活性化関数(Swish Family)を比較してみた。
右図から分かるようにMishとxlog(1+tanh(e^x))がSwishよりやや精度が高い事が分かる。しかし、xlog(1+tanh(e^x))はoverfittingしやすく学習が不安定であった。
よってMishが優秀な事が分かる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/c34a45ea-dd4b-d836-45c1-1eaad2b6a55e.png)

Mishな一次微分を変形してみると(2)のようになる。
∆(x) parameterは前処理のような振る舞いをする。それによって、正規化と勾配をsmoothにしてくれる。Swishに前処理を行うという事はSwishより精度が高くなる可能性があるらしい



<h1>Smoothだと何が良いの？</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/def76c8b-675b-bd09-16e0-927f8d44ed7c.png)

5層のNetworkをランダムにinitializationしReLUとMishを比べてみた。
Mishの方がReLUよりSmoothなのが分かる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/d4873012-efc4-8b5e-56ca-c4a1bb3a7e1e.png)

図から分かるようにMishの最小値の範囲が一番広い。最小値の範囲が広いとgeneralizationに役立つ。
SwishやReLUは複数の最小値がある＝＞overfittingしやすい?!





<h1>実行速度</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/396cbfd0-2fa5-7cb2-0446-c0e63edc6e97.png)
MishはReLUに比べて約3倍遅い。CUDA-baseのimplementationしたMish-CUDAはReLUとほぼ同じ速度になっている。


<h1>結論</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/4e1e592d-c21e-91c4-5bf8-749f8da33db5.png)

論文が主張している通りであれば、理論も結果もReLUやSwishより良さそう。
今後色々な研究で使われるか見ていきたい。


<h1>参考文献</h1>
Mish: A Self Regularized Non-Monotonic Activation Function
https://arxiv.org/pdf/1908.08681v3.pdf
【Rails初心者向け】RSpecの使い方まとめ（概要を掴む）


#RSpecとは？
RSpecとRuby on RailsやRubyでアプリケーションの動作テストを行うgemです。

利用目的として、大規模サービスなど、チェックミスが起きやすいのでコード化してする。
また、アプリケーションの更新時に毎回一からテストを行う手間を省くこともできる。

#導入方法

```ruby
group :development, :test do
  gem "rspec-rails"
end
```
※この時、必ずgroup :development, :testの中に記述する。
あとはbunle installで導入は完了です。

#設定をする
```
% rails g rspec:install
```
こちらをターミナルから実行して、必要なディレクトリを生成します。
ディレクトリに**spec**ディレクトリができたことを確認してください。


```
--format documentation
```
.rspecにこちらを記述することでターミナル上からテストコードの結果をみることができるようになります。

#実際に動かしてみる
今回は簡単なサンプルを作って説明をしていきます。
まず　rails g rspec:installで生成されたspecディレクトリの下にsampleディレクトリを作り、その中にsample_spec.rbファイルを作ります。そこに記述していきます。

```sample_spec.rb
RSpec.describe '何のテストコード？' do
  contenxt '状況説明' do
    it "こうなるはずという結果" do
      処理内容をここに記述
    end
  end
end
```

####・RSpec.describe '何のテストコード？' do　
describeの後に、大きな括りでテスト内容を記述します。
例えば、***新規登録のテスト***や***ログイン機能のテスト***などです。

####・context 'もう少し砕いて状況を説明して' do
2行目のdescribeでは１行目で宣言したテストコードをもう少し砕いて説明をします。
例えば、***新規登録ができる時***や***ログインができない時***などです。


####・it "具体的にはどんな処理？" do
ここでは具体的な処理内容を記述します。
例えば、***名前が入力されていたら新規登録できる***や***パスワードが間違っていたらログインできない***などです。

#具体例を使って説明

```sample_spec.rb
RSpec.describe 'テストの合計点' do
  contenxt '算数が100点、国語が50点の時の合計点' do
    it "算数と国語の点数が足されたら合計150点になる" do
      expect(100 + 50).to eq 150
    end
  end
end
```
ここではテストの合計点についてのテストコードを行っています。
contextでは各点数が何点かという状況説明をしています。
そしてitでは具体的にこうなるはずを説明して、処理内容をitの中で記述しています。


#まとめ
確認内容を言語化して、その処理を実行するという流れです。
次回は処理内容について学んだことを紹介していきたいと思います。
最小二乗法と正規表現(備忘録)



#係数βを使った線形モデル表現

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/5f0f9cfd-24c8-f1fd-d95c-e753b59f88c9.png)

#コスト関数Q()は残差の総和を表す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/e1bd8f19-5832-6ff2-9996-72ebc9c4401b.png)


#コスト関数について

凸関数のコスト関数を微分して0とおく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/2b757cf3-81e5-e44d-540e-047e35ae605d.png)


これを少し変形したものが正規方程式と呼ばれる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/0a35ca6e-3eae-1ce2-a593-84368ae470b8.png)

係数βにかかるのはXの内積
もしXの内積が正則(逆行列を持つ)ならば



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/449ddaa4-2dc9-0afa-264c-22cee707c3f1.png)


として係数βが求まる。
これをβの推定値とする

#βの推定値をつかって

モデルはYを完全に表現できない。
あくまで誤差を最小化するもの

しかしひとまずYと等価とする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/0ace2657-1106-12a8-fc85-d9cc2183f7c5.png)



#モデル(予測)と実測値の間の残差


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275572/1b2697af-3c28-c1b8-f871-7eaa2f332e4b.png)



として表現される
OmronのD6TをRaspberry Piで使う

![IMG_1589.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50780/77226533-4648-9fc1-4228-4e19b34f1cc2.jpeg)

非接触で4x4のマトリックスの温度を取得できるセンサを試してみました。i2cで認識はするものの、なかなかうまくデータを読みだせず、結果的にそのままクローンして使えそうなライブラリ(d6t-grove-raspberrypi)を見つけて、そのまま起動して試すところまでのメモです。配線はdenshi.clubの記述を参考にさせて貰いました。記事最下部に、配線の写真があります（汚いですが…）。

```
i2cdetect -y 1
```

## x 動かない!

https://github.com/avninja/omrond6t

5年前で開発が止まっており、python2.x系のコードしかありませんでした。

https://www.denshi.club/pc/raspi/5raspberry-pi-zeroiot46-4-i2c-d6t-44l-06.html

`IOError Invalid argument` を解消できず。。


## o 動いた！
https://github.com/omron-devhub/d6t-grove-raspberrypi

```
git clone https://github.com/omron-devhub/d6t-grove-raspberrypi.git
cd d6t-grove-raspberrypi
sudo pigpiod
python3 sample_gui_d6t.py
```

![IMG_1590.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50780/9aaec3f0-b538-3e41-64d0-2e8a4ba0cdbb.jpeg)
PHPのログイン機能に関するDBエラー

エラー名
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'aaa@fff.com' for key 'email' in （略...）  Stack trace: #0 (パス...): PDOStatement->execute(Array)　以下略...

・エラー出現
新規登録を押してユーザー登録が成功したが、もう１度更新すると上記エラーが出た。

・なぜ出たか？
１度データベースにnameやらemailやらpassやら入れたのに、再度同じ情報（名前もidもpassも）で更新したから。


・MAMP使いました。
![8EAD5073-F7B7-4E40-B417-16B5E93D8804_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699159/cee7eac0-b8c9-7f24-8892-77cd490600d8.jpeg)

結論
気にしないことにしました。


（初投稿...）
M5Stackで3G通信をやってみた記録

こんなゲームを作ろうと思っています。
草刈り機にセンサーとマイコンをセットし、センシングデータを反映するス◯◯◯ゥーンのような陣取りゲームです。
![EkR2ERLUYAEooq5.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/f77f6bca-fabe-9d59-e04e-5815d9d2724a.jpeg)

さて、いろいろな課題がありますが、
まずは、電波です。

こんなときは、手軽にセルラー通信ができるソラコムさんしかない。


ということで、ソラコムさんの公式にあるとおりにやってみました。
https://dev.soracom.io/jp/start/m5stack/

今回は、何の工夫もない「やってみただけの記事」ですが、今作ろうとしているゲームの第一歩なので記録として残します


##必要なもの

- M5Stack
- [M5Stack用 3G 拡張ボード](https://www.switch-science.com/catalog/4000/)　　
- ソラコムのSIMカード (ナノサイズ）　
　<br> ※プランは plan01s , plan-D 
- 六角レンチ 1.5mm


##私の環境など（本記事の前提条件）
- Windows 10
- すでにArduino IDE で M5Stackの動作設定済み
　<BR>（必要なライブラリのインストール済み）
- ソラコムのアカウント保有

##手順
３G通信モジュールのカバーのネジを六角レンチを使って外し、ソラコムのSIMカードを入れます。

![121225553_3406743592707484_3915760092235825656_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/64ca3293-9655-a168-1abf-d732ea290ee5.jpeg)

M5Stackに３G通信モジュールをセットします。

完成形
![121228322_3406743842707459_8717941044547611889_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/2e9526c4-fb29-a187-5bde-1a2917f549db.jpeg)


３G通信用ライブラリをインストールします.
Arduino IDE の [スケッチ] > [ライブラリをインクルード] > [ライブラリを管理]　で
[TinyGSM by Volodymyr Shymanskyy]　を選択。


[ソラコムさんのサイト](https://dev.soracom.io/jp/start/m5stack/)にあるサンプルコード（　World Time API をHTTP通信（GET)で呼び出す）をコピペします。

ArduinoをPCにつなげます。

ちなみに、PCにつなげた瞬間こんなメッセージ 「<B>No Found sensor</B>」 が出っぱなして、１時間悩みましたが、センサーつなげて無いので当たり前だと思い、無視しても特に問題はなかったです。（実は問題あるって場合は教えて下さい）
![121486154_3406743699374140_6554482257234533259_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/547a00c5-32bd-722a-822f-a3c8b0550df5.jpeg)



コンパイルすると、


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5stackにソラコムの3G拡張ボードをつけてセルラー通信。ソラコムのチュートリアル通りにしたら、とりあえず、なんか通信はできた。　<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://t.co/H9wuDy4yiF">pic.twitter.com/H9wuDy4yiF</a></p>&mdash; たつや (@tatsuya1970) <a href="https://twitter.com/tatsuya1970/status/1316352563353014272?ref_src=twsrc%5Etfw">October 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<br><br>
３G通信ができているらしいです。


お次は、センサーをつなげて、センシングデータをクラウドにあげるのに挑戦します。

<br><br><br>

秋の夜長は電子工作。
（スイッチサイエンスさんの梱包の上蓋の裏）

![image0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/ecaa09a4-7b82-6fe6-0742-44f287282c0e.jpeg)
Chrome拡張Open-as-Popup


1クリックで、表示中のタブをポップアップ表示する。

#概要
- メリット
    - ブラウザのUI（検索ボックス、ツールバー、タブ）を非表示にすることで画面がスッキリする。
- 利用例
    - Web上のドキュメントなど参照系
    - TwitterなどのSNSを常に表示
- オプション設定
    - デフォルト設定でよい
    - 設定するならショートカットを変更するぐらい

#機能
- ツールバー
    - 現在のタブをポップアップしてウインドウ表示する。
- 右クリックのコンテキストメニューの「Open-as-Popup」
    - 「Toggle Open-as-Popup」タブ表示←→ポップアップ表示 をトグル切り替えする。
    - 「Open URL in new popup window」新規にポップアップウインドウ表示する。

#オプション設定
##Position and size of the new popup window
新しいポップアップウィンドウの位置とサイズ

- 「Let the browser internal window manager define position and size.」ブラウザ内部のウィンドウマネージャに位置とサイズを定義させます。
- 「Copy the position and size of the previous window.」ポップアップ前のウインドウ位置とサイズをコピーしてポップアップする。
    - Only if previous window state was normal (not maximized or fullscreen).」最大化やフルスクリーンではない場合に限定する。
- 「Copy previous window state (normal, maximized, fullscreen)」ウインドウのサイズ状態（通常、最大化、フルスクリーン）をコピーする。

##Tab index when attached back to a normal window
元のChromeのタブに戻したときのタブ位置

- 「Before the first tab.」先頭
- 「After the last tab.」最後尾
- 「After the current active tab.」アクティブになっているタブの次の位置

##Keyboard shortcut
タブ表示←→ポップアップ表示 をトグル切り替えするショートカットキーの設定
デフォルトのショートカットは `[Alt]+[0]`
【GitHub Actions】set-envとadd-pathが非推奨になったので対応する

## 何があったか

GitHub Actionsで使用できるコマンドの`set-env`と`add-path`について脆弱性([CVE-2020-15228](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15228))が見つかり、現在非推奨となっています。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">GitHub Actions: Deprecating set-env and add-path commands <a href="https://t.co/t84gDBTGIK">https://t.co/t84gDBTGIK</a></p>&mdash; GitHub Changelog (@GHchangelog) <a href="https://twitter.com/GHchangelog/status/1311715531960078342?ref_src=twsrc%5Etfw">October 1, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

なお、これら非推奨コマンドを使用しているとActionsの実行結果に以下のような警告が表示されるようになりました。

![warning](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317369/ac30f410-19fb-25cd-24a9-60b3a0d34cdf.png)

## 対応方法

### 1. set-env

`echo "{name}={value}" >> $GITHUB_ENV`というかたちで、`$GITHUB_ENV`に書き込みます。

```yaml:修正前
    steps:
      - name: set env for prod
        if: github.ref == 'refs/heads/main'
        env:
          AWS_ACCOUNT_ID: 123456789012
          S3_BUCKET_NAME: deploy-prod
        run: |
          echo "::set-env name=AWS_ACCOUNT_ID::${AWS_ACCOUNT_ID}"
          echo "::set-env name=S3_BUCKET_NAME::${S3_BUCKET_NAME}"
```

```yaml:修正後
    # 略
        run: |
          echo "AWS_ACCOUNT_ID=${AWS_ACCOUNT_ID}" >> $GITHUB_ENV 
          echo "S3_BUCKET_NAME=${S3_BUCKET_NAME}" >> $GITHUB_ENV 
```

### 2. add-path

`echo "{path}" >> $GITHUB_PATH`というかたちで、`$GITHUB_PATH`に書き込みます。

```yaml:修正前
      - name: setup reviewdog
        run: |
          mkdir -p $HOME/bin && curl -sfL https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh| sh -s -- -b $HOME/bin
          echo ::add-path::$HOME/bin
```

```yaml:修正後
          # 略
          echo "$HOME/bin" >> $GITHUB_PATH
```


## 参考

- [GitHub Actions: Deprecating set-env and add-path commands - GitHub Changelog](https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/)

- [Setting an environment variable - Workflow commands for GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable)

- [Adding a system path - Workflow commands for GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#adding-a-system-path)
link_toって奥が深いねって話(原因不明)

アプリ開発中投稿ボタンを押したら投稿ページに遷移するように**link_to**で記述をしていた時

```
  <%= link_to "投稿", 'new_photo_path'%>
```
最初はこのように記述しました。
するといつもの![スクリーンショット 2020-10-15 3.30.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694122/40c3de74-5e3e-107a-7bcb-78f8143f741f.png)
この赤いエラー分が出ました。。
###仮定
**routes.rb**がうまく記述できていない
綴りが間違えてる

####routes.rbを確認しにきました

```routes.rb
resources :photos, except: :index
  root to: 'photos#index'
```
resourcesでindexを除外していること以外に不思議な点はなく

```
rails routes
```
で確認しても問題はなし…

![スクリーンショット 2020-10-15 3.35.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694122/17de401a-0849-e5ca-020f-18de788d3a42.png)

綴りも間違えていない…

##行ったこと
**PrefixではなくController#Actionの方を記述した**
new_photo GET    **/photos/new(.:format)**

```index.html.erb
<%= link_to "投稿", '/photos/new'%>
```
で解決しました…

#追加
@scivola さんからのコメントで原因がわかりました
@scivola さんありがとうございました。
Prefixは``''``で囲むと**文字列**になってしまうようです…
なので自分の場合は文字列として認識されているようです
Beagle Bone BlackでRemote Developmentを使うためにDebian 10をインストール

## 目的
最大の目的はVSCodeのRemote SSHが使えるようにすること。リモート側の必要条件としては以下のようになっている[^1]。
>
requires kernel >= 3.10
glibc >=2.17
libstdc++ >= 3.4.18

配布時にもらった個体には2013年ぐらいのÅngströmが入っていて上記のライブラリを入れるのがめんどくさかった。
ちまちま更新してもいいけど競合してもめんどくさいしこの際OSごと更新してしまうことにした。

## 使用機材
- Beagle Bone Black Rev.C

## 方法

### 1.BBB用のイメージのダウンロード
[BeagleBoneにLinuxをインストールする](https://slowquery.hatenablog.com/entry/2018/02/03/234048) - memorandum
こちらの記事をもとにありがたくインストールさせていただく。

[BeagleBoard.org Latest Firmware Images](https://beagleboard.org/latest-images)
ここから`AM3358 Debian 10.3 2020-04-06 4GB SD IoT`を選択してダウンロードする。

![スクリーンショット 2020-10-15 024739.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703910/a0e79607-4cb3-b239-c056-ff9618fa8c69.png)

### 2.SDカードにイメージを焼きこむ
Raspberry Piなどでも使われているEtcherが使える。Electronを使ったリッチなUIですごい。容量も書き込みツールのわりにすごい。
左端でダウンロードしてきたイメージを選択し、中央で書き込み先、右端が書き込み開始ボタン。
![スクリーンショット 2020-10-15 025149.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703910/31d1ca99-2840-66cb-fb37-dfaaae539cd8.png)

### 3.BBBのeMMC上にDebianを書き込み
BBBにSDカードを差し込み、SDカード付近にあるボタンを押しながら起動する。
LANポート近くの4つのLEDが点灯するまで押し続けること。

適当な時間放置したあと(LEDのちかちかが控えめになったら)SSHでBBBに接続する。
ユーザー名はdebian, パスワードはtemppwd。

ログインしたら1.で紹介したありがたい記事に
>
`/boot/uEnv.txt`を以下のように修正して保存します。
\##enable BBB: eMMC Flasher: cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh

とあるように修正しておく。

その後SDカードを抜かず`sudo reboot sudo shutdown -h now`を実行して、再起動する。
eMMCの書き込みには20分ぐらいかかるのでしばらく放置する。
LEDのちかちかが控えめになったらSSHでアクセスしてみるとうまくいった。

### 4.環境作成
ここからはbeagle bone black上にC/C++コンパイル環境を作成する。
~~ここまでやっておいてあれだがクロスコンパイルのほうが効率いいかも~~

また、今回BBBは完全にネットワークから切り離された組み込みボードとして使用するので常にrootユーザでログインしておいても問題ないはずだ。というわけでrootユーザにパスワードを設定して使用できるようにしておく。パスを設定しないとrootユーザは使用可能にならない模様。なぜでしょうね？Linuxのユーザー関係についてよく理解していない。
**これは必須ではないが楽をするためにやっている。**

1. `sudo passwd root`でパスワードを設定する。

2. 次にrootでsshログインできるようにする。初期設定ではできないためだ。
`/etc/ssh/sshd_config`の
`#PermitRootLogin without-password`のようになっているのを
`#PermitRootLogin yes`とする。
そして`sudo service sshd restart`を実行してsshdを再起動する。

3. sshでrootログインできるようになった。

次に各種ライブラリ・ツールをインストールする。
`apt install build-essential`
`apt install gdb`

ここまでやればあとは[手前みその記事](https://qiita.com/MunoLike/items/3367baadce27a6f418e6)にあるようにすればVSCodeを用いてデバッグ・コンパイルできる。

## 感想
特に詰まらずにデバッグできるようになったのには軽く感動を覚えた。
今後は多数ファイルのプロジェクトをCMakeとNinjaでビルドできるようになりたい。


## 参考文献
[BeagleBoneにLinuxをインストールする](https://slowquery.hatenablog.com/entry/2018/02/03/234048) - memorandum

[^1]: [Developing on Remote Machines using SSH and Visual Studio Code](https://code.visualstudio.com/docs/remote/ssh) - Visual Studio Code
停まれ標識検知　可視化部分の開発part4 物体を検知した時にソケット通信を使って音声で知らせる(複数編)

## 前回まで
前回はスマホに絞って椅子を検知した時に音声で知らせるためのプログラムを書きました.しかし,本以外のものを検知したとしてもそれを知らせることは前回のプログラムではできませんでした.なので今回はスマホじゃないものを検知した時も知らせることができるようにしようというプログラムになります.
## 今回実装した機能
Yolov5上で物体を検知した時➡ソケット通信をする.➡ソケット通信を受けたときに音声を再生する.
※ただこれだけをやっています.今回は複数のものに対応できるようになっています.
##実装部分
（ソケット通知部分を関数にしました）

```detect.py
def socket1():
    host = "192.168.10.4" #Processingで立ち上げたサーバのIPアドレス
    port = 10001       #Processingで設定したポート番号
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s2:
                         s2.connect(('127.0.0.1', 50007))
                         BUFFER_SIZE=1024
                         data1='1'
                         s2.send(data1.encode())
                         print(s2.recv(BUFFER_SIZE).decode())

def socket2():
    host = "192.168.10.4" #Processingで立ち上げたサーバのIPアドレス
    port = 10001       #Processingで設定したポート番号
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s2:
                         s2.connect(('127.0.0.1', 50007))
                         BUFFER_SIZE=1024
                         data1='2'
                         s2.send(data1.encode())
                         print(s2.recv(BUFFER_SIZE).decode())

```
（認識部分）

```detect.py
                    if label1=="cell phone":
                     print("スマホを発見しました")
                     socket1()
                     with open('daystext/'+str(d_today)+'.txt', 'a') as f:
                         dt_now = datetime.datetime.now()
                         f.write(str(dt_now)+"スマホを発見しました"+"\n")
                    if label1=="book":
                     print("本を発見しました")
                     socket2()
                     with open('daystext/'+str(d_today)+'.txt', 'a') as f:
                         dt_now = datetime.datetime.now()
                         f.write(str(dt_now)+"本を発見しました"+"\n")

```
サーバ部分

```server.py
# socket サーバを作成
from playsound import playsound
import socket
cont=1
# AF = IPv4 という意味
# TCP/IP の場合は、SOCK_STREAM を使う
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    # IPアドレスとポートを指定
    s.bind(('127.0.0.1', 50007))
    # 1 接続
    s.listen(1)
    # connection するまで待つ
    while True:
        # 誰かがアクセスしてきたら、コネクションとアドレスを入れる
        conn, addr = s.accept()
        with conn:
            while True:
                # データを受け取る
                data = conn.recv(1024)
                if not data:    
                    break
                else:
                 data2=str(data)
                 data3=(data2.replace('b', ''))
                 conn.sendall(b'Received: ' + data)
                if data3 == "'1'":
                        playsound('2.wav')
                if data3 == "'2'":
                        playsound('3.wav')
```
※これらのコードは全部もしくは一部を載せています.
###問題点
socketを送ったときに2回送ってしまう仕様になっていて,二回しゃべってしまうことになっています.ここを今後改善していくことが課題です.
## 次回へ
・今回のプログラムは問題点も残すことになりましたので今後課題に向けて解決していくためにプログラムを改善していく必要があります.なのでこれについては今後も改善する為のプログラムを書いていくつもりです.
・このシステムを停まれ標識検知に適応させて,より良いシステムを開発していくために,GPSとの連携をしていこうと考えています.
次回はこの辺について書いていくつもりですが,次回は少し重くなりそうなので更新が少し途切れるかもしれませんが宜しくお願いします.
react-cookieで有効期限を指定するのに詰まった

# 何がしたかったのか

https://www.npmjs.com/package/react-cookie
react-cookieで有効期限を指定してcookieを設定したかった。
maxAgeでの指定はうまくいったが、expiresでの指定でエラーが出る。

## 環境

`npm 6.14.6`
`react 16.13.1`
`react-cookie 4.0.3`

# 解決

Dateオブジェクトを生成してtoUTCStringメソッドを呼び出すって書いてたけど、これがダメだった。
https://techacademy.jp/magazine/35735


普通にDataオブジェクト生成だけすればOK。

```js
const cookieExpiration = '2020-11-11 23:59:59'
const cookieDate = new Date(cookieExpiration)
            
setCookie('user_id', data, { expires: cookieDate, path: '/' })
```


https://en.it1352.com/article/0de830993c3844598da151bfa307fb49.html
Goでデータベースの内容を取得する関数を作る

データベースから目的の内容を全て取る関数について今から書きます。すでにデータベースには、なにか入っている状態でします  

[interface{} な変数を型が決まっている関数の引数にする](https://qiita.com/umanoda/items/07887d33ef1155b26ed2)
[「Golang」 ×「Gorm」でシンプルに「Mysql」を操作する](https://qiita.com/stranger1989/items/914bef8cc6ad77ef8350)
[【go + gin + gorm】webアプリにログイン機能を追加してみる](https://qiita.com/dai-maru/items/f7cdd22baf3425a1722d)
[Goでの Mysql接続から構造体へのデータ割り当てまで](https://qiita.com/rihofujino/items/c17a006101374b200c1b)
[Gin と GORM で作るオレオレ構成 API](https://qiita.com/Asuforce/items/0bde8cabb30ac094fcb4)


---

```go:install
import (
    _ "github.com/go-sql-driver/mysql"//　これは、自分で追加が必要
	"github.com/jinzhu/gorm"
)
// ないとき
//go get github.com/jinzhu/gorm
//go get github.com/go-sql-driver/mysql
```
まず、データベースと接続をします

```golang:main.go
func openGormDB() *gorm.DB { // localhost
	DBMS := "mysql"
	USER := "user"//mysqlのユーザー名
	PASS := "password"//パスワード
	PROTOCOL := "tcp(localhost:3306)"
	DBNAME := "sample"//データベース名

	CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=True&loc=Local"
	db, err := gorm.Open(DBMS, CONNECT)
	if err != nil {
		panic(err)
	}
	return db
}
```

これは、データベースの内容

```go:main.go
type ShiromiyaChannelInfos struct {
	//ID              uint64
	ChannelID       string
	ChannelName     string
	ViewCount       uint `gorm:"type:int"`
	SubscriberCount uint `gorm:"type:int"`
	VideoCount      uint `gorm:"type:int"`
	CreatedAt       time.Time
}
```
データベースの内容を取る関数
テーブルごとに書かく

```go:データベースの内容を取る関数
func GetDBShiro() []ShiromiyaChannelInfos/*<=①*/ {
	db := openGormDB()
	var shiroInfo []ShiromiyaChannelInfos/*<=①*/
	db.Find(&shiroInfo)/*<=①*/
	db.Close()
	return shiroInfo/*<=①*/

```
データベースに接続して目的のテーブルの内容を全て取得する関数
2500ドルのプレミアムドメインを購入した話

はじめまして。メテオと申します。普段は[自分のブログ](https://blog.meteor.ne.jp)で技術記事をたくさん書いています。

今回は技術記事ばかりでは面白くないと思い、雑記を書いていきます。技術ネタではありません。

この度、会社のほうで2500ドル（日本円で26万くらい)するドメインを購入しました。

このドメインは、元々他の方が所有しており、ドメインパーキングで管理されていました。

ドメインパーキングとは、使っていないドメインを管理するサービスのことで、ドメインにアクセスしたらキーワード広告がたくさん出てきた経験はみなさんありますか？その広告の実態はドメインパーキングが管理しているドメインなのです。

この広告の収益は、ドメインパーキングを通じて、ドメイン所有者に還元されます。また、ドメインパーキングは広告を出すだけではなく、ドメインの販売も行っています。

ドメイン所有者が希望する金額で、ドメインパーキングは他の人にドメインを販売も行っています。

今回は、ドメインパーキングを通じて、2500ドルもするドメインを購入した話をしていきます。

# 購入に至った経緯
![](https://storage.googleapis.com/zenn-user-upload/auo7toksgo6inyv1rig83w8rttgf)

元々、会社ではJPドメインと呼ばれる .jp で終わるドメインを保有していました。

しかし、JPドメインは海外だとそこまでメジャーじゃない話やSEOの観点からも、グローバルなドメインを持つ必要が出てきました。

そこで、色々ドメインを調べていたのですが、どれも取得されており、最近出てきたTLDなら空いている状態でした。

TLDとは、トップレベルドメインの略称で、 .jp のように一番最後で終わるドメインのことを指します。近年では、TLDを企業でも取得することができるようになり、 .sharp や .google のようなTLDも出現してきました。

その中で唯一見つけたのがプレミアムドメインと呼ばれるものでした。

このプレミアムドメインは前述したドメインパーキングが販売しているドメインのことです。

日本だとGMOインターネットが運営しているお名前.comなどで購入することが出来ます。しかし、手数料があるのか、かなり割増になっています。

私はドメインの所有者が確認できるWhois情報を元に、ドメイン所有者を特定しました。

その結果、ドメインパーキング最大手の[Sedo GmbH社](https://sedo.com/)であることが判明しました。

Sedo GmbH社は、古くからドメインパーキングをやっている会社でして、本社はドイツにあります。

こうして、私はSedoからドメインを購入することになったのでした。

# 購入手続き
![](https://storage.googleapis.com/zenn-user-upload/iho2qle0qf36slicexjxq843qg6e)

Sedoでは、価格をオファーするのと、希望価格をそのまま買う2通りの方法があります。

価格をオファーするのは、いわゆる値下げ交渉です。大抵の場合、値下げに応じてくれるので、オファーが使える場合は値下げ交渉をしたほうがよいでしょう。

今回購入したドメインは、オファーがなく、希望価格で購入する形でしたので、そのまま購入しました。

決済手段には、今回PayPalを利用しました。Sedoは最大手とはいえ、見ず知らずのところにカード情報を登録するリスクを考慮し、PayPal経由で支払いを行いました。ちなみにPayPalで支払うと支払い手数料で数パーセント上乗せされます。

![](https://storage.googleapis.com/zenn-user-upload/ub45nobu8ixmpa2l923sfemeh8z7)

そうして、PayPalを経由して、私は2500ドルを購入しました。高いですが、まあよしとしましょう。

# ドメイン移管
![](https://storage.googleapis.com/zenn-user-upload/cm9tu6lhkjqbbivqifgckp95avt8)

購入すると、Sedoのドメイントランスファー担当者から連絡がきます。

この担当者は、購入者とドメイン所有者を繋ぐ人で、トラブルを防ぐために仲介に入ってくれます。私はドメイン所有者と一度も話していませんが、これも仲介人のおかげですね。

ドメイントランスファー担当者はまず、ドメイン保有者に連絡を行い、Sedoが管理しているレジストラに移管するようにお願いします。ドメインによっては最初からSedoが管理しているレジストラに移管している場合もありましたが、今回は別のレジストラであったため、移管が必要でした。

その次に、Sedoが管理しているレジストラに移管が完了すると、購入者に対してオースコードが発行されます。このオースコードはドメインを移管する際に必要なキーです。これがないとドメイン移管できませんし、流出すると誰でも移管できてしまいます。厳重に管理する必要があります。

このオースコードを購入者が移管したいレジストラのほうで入力します。今回はGoogle Domainsを使いました。ちなみに、移管先のレジストラは事前にSedo側で選択する必要があります。万が一、オースコードが流出しても別のレジストラだった場合弾かれるのかは不明ですが、よしなりにやってくれるのでしょう。

![](https://storage.googleapis.com/zenn-user-upload/1jskj60w8ab9874yt0y7iw1p4tp7)

こうして、移管が終わると、1時間くらい経つとWhois情報がSedoから新しい情報に切り替わりました。

これでドメイン移管はおしまいです。

# 余談
![](https://storage.googleapis.com/zenn-user-upload/7ulvmxstx55y2224c82nzv5twdoz)

Google DomainsでWhois情報を編集していると、都道府県が日本語しか選べないことが判明しました。基本的に国別トップレベルドメインでもない限りは英語で書くことが推奨されるのですが、なぜか日本語になってしまいます。

以前、JPドメインをGoogle Domainsで購入した際に公開窓口が英語でしか書けない現象に遭遇しましたが、Google DomainsのWhois情報は不具合というか実装上多言語を考慮していないケースが多く、改善して欲しいものです。

一応サポートには問い合わせたものの、仕様なので変更できないとの答えが返ってきました。技術的負債なのかもしれません。
Raspberry Pi 4 の Manjaro を Wi-Fi で繋ぐ

# はじめに

```:環境
$ lsb_release -rd
Description:    Manjaro ARM Linux
Release:        20.08
```

NetworkManager は使わずに、`dhcpcd` と `wpa_supplicant` だけで Wi-Fi の設定をするよ。
AP は `WPA2-PSK` + `AES` で `ステルス` 設定のものに繋ぎにいくよ。
IPアドレスは DHCP に頼らず固定するよ。

# NetworkManager は殺す

```
$ sudo systemctl stop NetworkManager
$ sudo systemctl disable NetworkManager
```

# 設定ファイルを作成・編集

ポイントは `wpa_supplicant.conf` ではなく `wpa_supplicant-wlan0.conf` にすること。

```conf:/etc/wpa_supplicant/wpa_supplicant-wlan0.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=network
update_config=1
ap_scan=1
network={
    scan_ssid=1
    ssid="xxxxxxxx"
    psk=xxxxxxxx
    key_mgmt=WPA-PSK
    proto=RSN
    pairwise=CCMP
    group=CCMP
}
```

```conf:/etc/systemd/network/wlan0.network
[Match]
Name=wlan0

[Network]
DHCP=no
```

```conf:/etc/dhcpcd.conf
interface wlan0
static ip_address=192.168.1.123/24
static routers=192.168.1.254
static domain_name_servers=192.168.1.254
```

# systemd で有効化

```
$ sudo systemctl enable wpa_supplicant@wlan0
$ sudo systemctl start wpa_supplicant@wlan0
```
ArgumentParser

# 使い方
## インポートするモジュール名
```python
import argparse
```

## 基本的な使い方
```python
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--test')
args = parser.parse_args()
```
こうすることで、

```python
args.test
```

として、引数「test」にアクセスすることができる。

## いろいろな使い方

```python
# フラグとして使用
parser.add_argument('-f', '--flag', action='store_true', default = False)
```
unicorn立ち上げ時にmaster failed to start, check stderr log for detailsがでて弾かれる

# 今回はアプリケーションサーバーであるunicornを起動した時に見たことないエラーに直面したので解決法を残します
```
[ec2-user@ip-172-31-23-189  アプリ名]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
master failed to start, check stderr log for det
```
master failed to start, check stderr log for det  ??
見たことないエラー。ログを見にいくことに

```
自身のアプリケーションのディレクトリに移動
[ec2-user@ip-172-31-23-189~]$ cd /var/www/アプリケーション名

currentディレクトリに移動
[ec2-user@ip-172-31-23-189 <リポジトリ名>]$ cd current

logディレクトリに移動
[ec2-user@ip-172-31-23-189 current]$ cd log

logの中に入っているファイルの情報を表示
[ec2-user@ip-172-31-23-189 log]$ ls
production.log  unicorn.stderr.log  unicorn.stdout.log
```

今回はunicornの問題なので

```
tail -f unicorn.stderr.log（最新のログを10行分表示）
もしくは
cat log/unicorn.stderr.log（全てのログ表示）
```


僕の場合はtailの方の１０行では確認しきれなかったので、catの方でもログを確認。すると


![スクリーンショット 2020-10-14 17.52.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743908/b3497092-3d3c-08d3-3df1-8470587d7f36.png)
SQLで何か言われている。
## SQLに接続してみることに

```
$ mysql -u root -p
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
```
ソケットファイルがないですというエラー文。なのでソケットファイルを作ってあげます。

```terminal
sudo touch /var/lib/mysql/mysql.sock
```
てことでもう一度接続

```
$ mysql -u root -p
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (13)
```
かっこの中の数字が2から13に変わっただけやん。/var/lib/mysql/mysql.sock というファイルを開く権限がないですてことらしいです。
てことでmysql.sockに権限を付与するコマンド

```
$ sudo chmod 777 /var/lib/mysql/mysql.sock
```
もう一度接続

```
$ mysql -u root
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)
```
こんどは111に変わったけど、これは接続対象が起動していない or 存在しないということらしい
ステータスコマンドで状況を確認

```
$ sudo systemctl status mariadb
```
ここでactiveと表示されていれば接続されている。僕の場合表示されておらず、つまりMariaDBの再起動ができていなかったということがここで判明

```
$ sudo systemctl restart mariadb
```
![スクリーンショット 2020-10-15 1.55.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743908/6ab7ca2d-37b8-d05a-4fef-35722ea67ea7.png)
active！これで無事、unicornを立ち上げることができました。
###今回はEC2のインスタンス再起動時にサーバーの再起動をしていないことが原因でした。
参照：https://saton2.hatenablog.com/entry/2018/10/16/200616
エンジニア採用の鍵

## エンジニア採用の鍵

世界的なIT人材不足の中、エンジニア採用に成功する鍵は2つしかありません。

給料がイケてるか、CTOがイケてるか。

イケてる給料はなかなか難しいし、良くもないと思うので、必然的にイケてるCTO戦略を取るしかないわけですが、私の考えるイケてるCTOとは

- 圧倒的な技術力と知識
- 大いなるVISIONと確固たる技術戦略
- ぶれない判断、発言および行動
- メンバー成長へのコミット
- 権限移譲

です。異論はあることでしょう。

## ベトナムで無名の会社が採用するには

私は現在、東京にいますが、基本的にはベトナムの開発会社の人です。ベトナムは人材不足を補うためのオフショア開発先として人気ですが、採用はぶっちゃけ日本より難しいです。ベトナムでは IT は税制優遇があったりして人気の高い産業で、人材は常に取り合い。ベトナム人は家族に誇れる会社（有名な会社）に入りたい傾向が強いので、日本では有名でもベトナムでは無名の会社に入りたいという人は基本的にはいないわけです。そんな状況下で採用責任者として、割と採用を成功させてきた経験から言えることは、

無名の会社がベトナムで Happy な採用をするには、VISION しかない。

VISION というのは、簡単なようでとても難しくて、どのようにアプローチするか？という具体的なアクションが重要です。言ってるだけだったり、過去の栄光だったり、日本的な精神論・根性論になってしまうと、もうただの綺麗事で、それではベトナム人材市場というレッドオーシャンは渡れません。

という訳で、重要なのは、VISION…を語る人、つまり Manager ということになります。つまり、イケてるCTO。

じゃあ Manager ってどういう人が良いの？どうあるべきなの？って話になるわけですが、15年くらい前に聞いた某AK氏の講演（プライベートな講演会だったので念の為名前は伏せました）のメモに完璧に書かれていました。15年が経ち Managerという役割もそれなりに経験してきて、改めて読み返してみると、言いたいことがこれ以上ないほど見事にまとまっていました。

では、前置きが長くなりましたが、その一部（結論だけ）をご紹介。

## 求められるリーダー像

1. 人に真摯に向き合える人 (ドラッカー: 真摯さよりも、頭のよさを重視するものをマネジメントに任命してはならない)
2. 自らの仕事に高い基準を設定し、情熱をもって自ら行動できる人<br>
→ それが出来ない人は、自身のみならず、マネジメントと組織にあなどりを生む。
3. 優れた価値を素直に吸収する努力に怠りない人<br>
→ 過信は必ず、自らの成長を止め、そして組織の成長を止める
4. 重要な原理・原則で行動できる人 <br>
→ 必要以上に人の評判で行動する人は、人間として弱く、その者に組織を委ねても、組織変革はできない。 <br>
→ 決断の拠り所のない人に、覚悟は生まれない。