OmniAICreator/Qiita-1.07M huggingface dataset:
エンコーダーモーターを知ろう～ROSでのPID制御に向けて～


DCモーターは、安価ですが、制御が出来ません。
これを克服したのがエンコーダーモーターです。

今回は、容易に手に入る直流エンコーダーモーターを簡単に解説します。

##エンコーダーモーターとは？
モーターの回転速度や、位置情報を出力可能なモーターです。

エンコーダーモーターは、検出用の素子がついています。
この素子は基本５Vで動作しますが、3.3vでも動作するものがあります。

まずは、現物を見てみましょう
![DSC_0139 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/cb0efc99-96ea-5483-019e-fa3818ce8a09.jpeg)
![DSC_0141 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/91265170-eba6-94e2-fead-b74f80876bd6.jpeg)
12VのDCモーターに基板がついています。
中心のコアの周りに2個の素子がありますね。
これがA相、B相に当たる検出素子です
そして、コネクタがありますね。

##コネクタ
私が知っているだけで数種類あります。
今回は、手持ちのXHコネクタ(2.54㎜ピッチ）、PHコネクタ(2㎜ピッチ）を撮影しましたが
ほかにも種類があることとピン配列がモーターごとに異なります。

##ピン配列一例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/d188364e-85aa-fad0-5a31-cfbdb707858f.png)
これ以外にもいろいろあります。
基本は、ケーブルの配線の入れ代えを自分でやる必要があります。
5VとGNDの位置が逆なものは配線を入れ替えれば済みます。
A相とB相については、1信号のみで良い場合は、そのままでいいですしソフトで修正も可能です。

##ケーブル
モーターのコネクタとドライバーボードのコネクタが違う場合、変換コネクタを製作する必要があります。
モーターは購入時に、同じコネクタ同士のケーブルと、製作用に片側が繋がっていないものがついてくることが多いようです

真ん中のものが私が作ったXH⇔PH用のケーブルでKs0193とXHのモーターをつなげるために作ったものです。
![DSC_0146 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/00358faa-9bd9-e508-bf6b-49c73b9281bd.jpeg)
ケーブルを製作することでドライバーボードとモーターのコネクタを考えないで選択可能ですね(ピン配列も）

##エンコーダーモーター対応ドライバーボード
私が入手したのは以下の4つです
KeyStudio　Ks0193　/ RikiRobot Stm32 Robot 4WD V1.4
ARDUINO_HR8833    / 当方製作　STM32F103　4WD　エンコーダーモータードライバー
![DSC_0136 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/bf56987a-aeff-e6ed-7f8a-9b58f8868fc5.jpeg)

左2つがPHコネクタでArduinoUno、右2つがXHコネクタでSTM32です
Ks0193のみ２モーターとなります。

##CPUが必要な理由？
ROSは基本Pub/Sub通信を行っており、Subscriber（購読者）は、Publisher(配信者）からの指示を受けて行動します。
これにより、中央装置（RaspberryPiなど）がすべての処理を行う必要がないというのがメリットのようです。
モータードライバーにCPUを載せるのは、処理を分離したいがためです。
しかしArduinoUnoは8bitのATmega328です。
これですと、様々な処理が行えないという事とROS Serialの帯域等の問題から32bitCPUであるSTM32系を使用したいと言う人が出てきました。
**Turtlebot3はSTM32F7にArduinoを入れています。
これで作られたのが、RikiRobotや当方のモータードライバーです。

近年は、CortexM4が主流であり、CortexM3を使用しているSTM32F103は時代遅れになりつつあるようですが、
そこまで多くの処理をしないのであれば、これで十分だと私は思います。

なお、Jetbotは、JetsonNano自信が処理を行っておりモータードライバーにCPUはついていません。
infomapのPythonのdrawコード

#infomapとは？
Map equationといういい感じにモジュール構造にクラスタリングしてくれるのが実装されたライブラリ。
>くわしくは以下のURLを参考にしてください。
https://www.mapequation.org/index.html
https://mapequation.github.io/infomap/




#問題
infomapを使うときにサンプルにしたコードが動かなかった。
>https://github.com/mapequation/infomap/blob/master/examples/python/example-networkx.py

原因はコードが古いからっぽい。


#解決コード
>(参考にしたサイト)
https://mapequation.github.io/infomap/

```example-networkx.py
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.colors as colors

import infomap

"""
Generate and draw a network with NetworkX, colored
according to the community structure found by Infomap.
"""

def findCommunities(G):
	"""
	Partition network with the Infomap algorithm.
	Annotates nodes with 'community' id and return number of communities found.
	"""
	
	infomapWrapper = infomap.Infomap("--two-level --directed")

	print("Building Infomap network from a NetworkX graph...")
	for e in G.edges():
		infomapWrapper.addLink(*e)

	print("Find communities with Infomap...")
	infomapWrapper.run();

	


	communities = {}
	for node in infomapWrapper.iterTree():
		if node.isLeaf():
			communities[node.physicalId] = node.moduleIndex()

	nx.set_node_attributes(G, name='community', values=communities)
	return infomapWrapper.numTopModules()


def drawNetwork(G):
	# position map
	pos = nx.spring_layout(G)
	# community ids
	communities = [v for k,v in nx.get_node_attributes(G, 'community').items()]
	numCommunities = max(communities) + 1
	# color map from http://colorbrewer2.org/
	cmapLight = colors.ListedColormap(['#a6cee3', '#b2df8a', '#fb9a99', '#fdbf6f', '#cab2d6'], 'indexed', numCommunities)
	cmapDark = colors.ListedColormap(['#1f78b4', '#33a02c', '#e31a1c', '#ff7f00', '#6a3d9a'], 'indexed', numCommunities)

	# edges
	nx.draw_networkx_edges(G, pos)

	# nodes
	nodeCollection = nx.draw_networkx_nodes(G,
		pos = pos,
		node_color = communities,
		cmap = cmapLight
	)
	# set node border color to the darker shade
	darkColors = [cmapDark(v) for v in communities]
	nodeCollection.set_edgecolor(darkColors)

	# Print node labels separately instead
	for n in G.nodes():
		plt.annotate(n,
			xy = pos[n],
			textcoords = 'offset points',
			horizontalalignment = 'center',
			verticalalignment = 'center',
			xytext = [0, 2],
			color = cmapDark(communities[n])
		)

	plt.axis('off')
	# plt.savefig("karate.png")
	plt.show()


G=nx.karate_club_graph()

findCommunities(G)

drawNetwork(G)
```
#最後に
間違っている箇所があれば教えていただけると幸いです。
Windows 10 PCからの疎通確認実行方法

#はじめに
Windows10のPCでWSL（Windows Subsystem for Linux）環境を手に入れてからはWindowsのコマンドを使うことから遠ざかっていたが、最近自分のPC以外で作業することも多く、そう都合よくWSLのUbuntu等が完備されていることは少ない。特に複数人が使う作業用端末には間違いなく導入されていない。
そういう場合、デフォルトで常備されているツールを使うことになるが、Windows PowerShellであればWindowsデフォルトで導入されているため、お手軽に利用できる。

今回はネットワーク疎通確認のための `Test-NetConnection` コマンドの使用例を記載する。


#Test-NetConnectionコマンド
`Test-NetConnection` コマンドはネットワークの疎通確認用のコマンドで、以下オプションが利用可能。

```text:パラメーター
    -CommonTCPPort <string>
    -ComputerName <string>
    -ConstrainInterface <uint32>
    -ConstrainSourceAddress <string>
    -DiagnoseRouting
    -Hops <int>
    -TraceRoute

　　-Port 　<-- Get-Helpでは表示されなかった

```
疎通確認にはポートを指定することが多いので、`Test-NetConnection xxx -Port XX`のような使い方になる。

#疎通確認実行例
実際にgoogle.comに対して実行してみた例を記載する。

```
> Test-NetConnection google.com -Port 80

ComputerName     : google.com
RemoteAddress    : 2404:6800:4004:81e::200e
RemotePort       : 80
InterfaceAlias   : イーサネット 3
SourceAddress    : xxx
TcpTestSucceeded : True

```

ポートが開放されていない場合は以下のように表示され、結果はFalseとなる。

```
> Test-NetConnection google.com -Port 123
警告: TCP connect to (2404:6800:4004:81e::200e : 123) failed
警告: TCP connect to (172.217.175.78 : 123) failed

ComputerName           : google.com
RemoteAddress          : 2404:6800:4004:81e::200e
RemotePort             : 123
InterfaceAlias         : イーサネット 3
SourceAddress          : xxx
PingSucceeded          : True
PingReplyDetails (RTT) : 50 ms
TcpTestSucceeded       : False


```

ちなみに、Ubuntuからcurlでポート指定の疎通確認を実行した場合の表示はこちら。

```
$ curl -v telnet://www.google.com:80
* Rebuilt URL to: telnet://www.google.com:80/
*   Trying 2404:6800:4004:818::2004...
* Connected to www.google.com (2404:6800:4004:818::2004) port 80 (#0)

$
$ curl -v telnet://google.com:123
* Rebuilt URL to: telnet://google.com:123/
*   Trying 2404:6800:4004:81c::200e...
*   Trying 172.217.175.14...
* connect to 2404:6800:4004:81c::200e port 123 failed: Connection refused
* connect to 172.217.175.14 port 123 failed: Connection refused
* Failed to connect to google.com port 123: Connection refused
* Closing connection 0
curl: (7) Failed to connect to google.com port 123: Connection refused
```

curlで実行した場合はすぐに結果が表示されるが、TestNetConnectionコマンドを実行した場合は結果が表示されるまで少し遅く感じた。ポート開放していない場合はタイムアウトを待つため数十秒待った。

#まとめ
いざというときにWindows PowerShellが役に立つ。

（追記）Windows 7 SP1（詳細バージョン不明）にはこのコマンドは含まれていない模様。
よく使うgitコマンド

# first commit

```bash
$ git commit --allow-empty -m "first commit"
```

# 一括削除

既にmaster/developにマージされているローカルブランチを一括で削除するコマンド

```bash
$ git branch --merged|egrep -v '\*|develop|master'|xargs git branch -d
```

リモート上で消したはずが、fetchしてもローカルに残っているブランチを完全に消すコマンド

```bash
$ git fetch --prune
```

# コミット消去（このコミットまで元に戻す | reset）

直前のコミットの歴史を完全に消す

```bash
$ git reset --hard HEAD^
```

特定のコミットまでの歴史を完全に消す

```bash
$ git reset --hard {コミットID}
```

# コミット相殺（コミット適用前に戻す | revert）

直前のコミットの内容を、相殺するコミットをする

```bash
$ git revert HEAD
```

特定のコミットの内容を、相殺するコミットをする

```bash
$ git revert {コミットID}
```

# ファイル相殺（checkout）

特定のファイルを特定のコミットの状態に戻したい場合

```bash
$ git checkout {コミットID} {パス}
```

特定のファイルを直前の状態に戻したい場合

```bash
$ git checkout {パス}
```

# チェリーピック（cherry-pick）

特定のコミットだけ取り込みたい場合

```bash
$ git cherry-pick {コミットID}
```

# リベース（rebase）

メインブランチにマージコミットを残さずに綺麗にマージしたい場合

```bash
$ git rebase {ブランチ名}
```

# 強制プッシュ

ローカルの変更をリモートのブランチに強制的にプッシュさせる

```bash
$ git push -f origin {ブランチ名}
```

# キャッシュ全削除

.gitignoreとかの変更が反映されないときに使う

```bash
$ git rm -r --cached .
```
emotion (emotion.js) のStyled Componentsで作成した要素にカスタム属性を渡したくなったら (shouldForwardProp)

今日ハマったのでメモ。

## Reactはバージョン16から要素に好きに属性を生やせます

Reactはバージョン16から[カスタム属性の利用を認めています。](https://ja.reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html)

たとえば、下記のような属性指定ですね。

```jsx
<a mycustomattr="customvalue">foobar</a>
```

上記の場合だときちんと `mycustomattr="customvalue"` が実際のDOMにレンダリングされます。

もともとReactでは、HTML公認のカスタム属性である `data-**` や、幅広い語彙を持つ `aria-**` は利用を認められていたのですが、その他の自作の属性、あるいはHTML5でいなくなった古い属性(e.g. `<td>` 要素の `align` 属性)は、カスタム属性が使えないと表現できません。

## emotionのStyled Componentsはそのままだとカスタム属性をはたき落とします

そして本題ですが、タイトルの通りemotionのStyled Componentsは、デフォルトでカスタム属性をはたき落とします。

たとえば、

```jsx
const CustomElem = styled.div`
  color: red;
`

// @ts-ignore
return <CustomElem mycustomattr="customvalue">Hello</CustomElem>
```

(`@ts-ignore` はTypeScriptさんが `mycustomattr` なんてないよ！とエラーを出すのを抑制するために入れています。JSの人は要りません。)

上記のコードだと `mycustomattr` がはたき落とされます。基本的には、[is-prop-valid](https://github.com/emotion-js/emotion/tree/master/packages/is-prop-valid)という実装に従って、HTMLに無さそうな属性は自動的に消してくれるようです。

今までのReactであれば、存在しない属性を渡すと警告を出していたので、特に自前propsが無意識に渡されて警告が出がちなStyled Componentsにおいては重要な機能と言えるでしょう。

## emotionでカスタム属性を通す方法

ただ、当然このままだと困るケースもあるわけで、じゃあそういう場合はどうするかというと、[ドキュメント](https://emotion.sh/docs/styled)に書いてあるとおり（←最初からちゃんとドキュメントを読めよ！）、 `shouldForwardProp` を指定して、自分のカスタム属性を通してあげましょう。

```jsx
const CustomElem = styled("div", {
  // mycustomattr と children（子要素） のみ許可する
  shouldForwardProp: (props) => ["mycustomattr", "children"].includes(props)
})`
  color: red;
`

// @ts-ignore
return <CustomElem mycustomattr="customvalue">Hello</CustomElem>
```

ちゃんと結果のDOMに `mycustomattr` がいるはずです。逆に、他の属性を渡しても何もDOMに影響しないはずです。
Eloquentモデルのクラス名から主キーを取得する

## はじめに
既存のDB構成の都合上主キー名が異なるテーブルで条件付きでID一覧をクラスごとに取ろうとしたときにいい方法に出会ったのでそのメモ

## 愚直な方法
クラス名指定で書くと似たような箇所も多く追加でいちいちcaseを増やさないといけなく面倒・・・

```php

// それぞれ主キー名が異なる類似したモデル
use App\Hoge;
use App\Fuga;

function scopedIds(string $className): array
{
    switch ($className) {
        case Hoge::class:
            return Hoge::scope()->pluck('hoge_id');
        case Fuga::class:
            return Fuga::scope()->pluck('fuga_id');
    }
}
```

## Eloquentモデルの`getKeyName`でやってみる
https://laravel.com/api/6.x/Illuminate/Database/Eloquent/Model.html#method_getKeyName
Eloquentモデルのメソッドとして`getKeyName`という主キー名を取得するものがあり、これ活用するとシンプルに済む

```php
function scopedIds(string $className): array
{
    $primaryKey = (new $className())->getKeyName();
    return $className::scope()->pluck($primaryKey);
}
```

## 終わりに
調べてみるとまだまだ便利なメソッドが提供されているので、複雑なDB構造と戦っている時にドキュメントを覗くといいやり方があったりするので、参考にできそうな感じ
macOSの「"FileZilla.app"を開くとコンピューターが破損します。ゴミ箱に入れる必要があります。」を解消する

久しぶりにmacOSでFileZillaを起動したら恐ろしいメッセージが現れてアプリが強制終了した。

<img width="573" alt="スクリーンショット 2020-02-26 0.23.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16060/56ac9472-ebad-7ca5-791c-312825348481.png">

英語環境でのメッセージは「"FileZilla.app" will damage your computer. You should move it to the Trash.」と思われるのでググってみると、公式フォーラムにトピックは見つからなかったが、[Twitterで同様の現象を有料版のサポートアカウントにメンションしている人がいた](https://twitter.com/HotpotDesign/status/1224800023138816000)。が返事がないようだ。

さらに検索すると「[FileZillaを起動したら怖いメッセージが表示されたけど最新版を再インストールしたら直ったわ。よくわからんけどサポートに事例が載ってなかったので共有。（意訳）](https://medium.com/@authorvinod/filezilla-app-will-damage-your-computer-d0584fc1a4a7)」と言っている人が見つかったので、（私の場合はProの)FileZillaの最新版を再ダウンロードしてインストールし直したら正常に起動できるようになった。

# See Also (2020.02.26追記)

macOS版のFileZillaからアドウェアが取り除かれたかもしれない - Qiita
https://qiita.com/studio15/items/5d8cdb5b277627bd5f4d
(実録)高卒の37歳のおじさんが未経験からAIエンジニアに転職した話

![機械学習エンジニアのキャリア_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591434/5eb19959-99e8-5763-4e49-648bd4d41dc8.jpeg)
この記事は[note](https://note.com/01shinji/n/ned058f82f11c)に移動しました。
ビューファイルの作成

ビューファイルはアプリケーションの見た目を定義するファイル。ビューファイルはapp/views/コントローラー名ディレクトリに、二本指クリックで新しいファイルを選択し、アクション名.html.erbで作成される。
アクション名は7つのアクション
ちなみにhamlでのファイル名はアクション名.hamlでOK
apt updateでエラーが出た場合の対処法

# エラー内容

`sudo apt update`をしようとすると以下のエラーが出るようになってしまいました。

```
aqua@aqua-VirtualBox:~$ sudo apt update
Hit:1 http://jp.archive.ubuntu.com/ubuntu bionic InRelease
Hit:2 http://jp.archive.ubuntu.com/ubuntu bionic-updates InRelease             
Hit:3 http://jp.archive.ubuntu.com/ubuntu bionic-backports InRelease           
Ign:4 https://cran.rstudio.com/bin/linux/ubuntu bionic/ InRelease              
Err:5 https://cran.rstudio.com/bin/linux/ubuntu bionic/ Release                
  404  Not Found [IP: 13.35.67.113 443]
Ign:6 http://dl.google.com/linux/chrome/deb stable InRelease                   
Hit:7 http://dl.google.com/linux/chrome/deb stable Release                     
Hit:8 http://ppa.launchpad.net/alessandro-strada/ppa/ubuntu bionic InRelease   
Hit:10 http://security.ubuntu.com/ubuntu bionic-security InRelease             
Reading package lists... Done 
E: The repository 'https://cran.rstudio.com/bin/linux/ubuntu bionic/ Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
```

# 解決方法

```
E: The repository 'https://cran.rstudio.com/bin/linux/ubuntu bionic/ Release' does not have a Release file.
```

より、R関係のパッケージが参照できていないようです。
https://cran.rstudio.com/bin/linux/ubuntu
ここにアクセスしてみると、以下の画像の通り、
`bionic/`
というディレクトリが存在しておらず、代わりに
`bionic-cran35`
というディレクトリが存在しているのが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189802/a3bab916-b6b8-0f6a-a591-643308f9da6a.png)

リポジトリの参照ファイル `etc/apt/sources.list` の中身を見ると、以下のような記述を見つけました。

```/etc/apt/sources.list
## For R package
deb https://cran.rstudio.com/bin/linux/ubuntu bionic/
```

R関係のパッケージは暫く使用する予定がなかったので、今回はこの記述を丸ごと削除しました。


# 補足

```/etc/apt/sources.list
## For R package
deb https://cran.rstudio.com/bin/linux/ubuntu bionic/
```
ここの`bionic`を`bionic-cran35`に書き換えて`apt update`してみましたが、
今度は以下のようなエラーが出て上手くいきませんでした...

```
W: GPG error: https://cran.rstudio.com/bin/linux/ubuntu bionic-cran35/ InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 51716619E084DAB9
E: The repository 'https://cran.rstudio.com/bin/linux/ubuntu bionic-cran35/ InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
```
てんそるふろー、てんさーふろう結局どっちなん(Tensorflowの読み方)

# てんそるふろー？てんさーふろー？
## 最後まで読むと後悔します...(たぶん？)
プログラミングをしていると読み方がわからない英単語に出会うことがよくあるのでそれについてのまとまりのない考察。

## 例: Tensorflow
自分の周りでも「てんさーふろー」と「てんそるふろー」の２通りの読み方をよく聞く。
「強い人」が「てんそるふろー」と読んでいたから自分もそう読むようにしたなんて言う人とかも見たことがある…

そういう人の前で違った読み方をしてしまうと何か思われそうな感じがして相手に合わせようとした経験がある人も多いのではないだろうか。

## 1. Vectorはみんなベクトルと呼ぶ
しかし、Vectorを「ベクター」と呼ぶ人はあまり聞いたことはない。みんな「ベクトル」と呼ぶ。<br>テンソル積なんて言うし、やはり「てんそるふろー」が正解なのだろうか。
## 2. 海外の人はどう発音しているのか
ここでGoogleに発音してもらったり、海外のYoutubeなどを見て確認すると「てんさーふろー」と発音している。<br>やはり「てんそるふろー」と決めつけるのもよくないようだ。

## ？？？
1.から日本ではみんな「Vector」をベクトルと読むし、「てんそるふろー」の読みで良さそうだ。<br>しかし海外の方と議論する時は2.から「てんさーふろー」が良さそう。なので日本にいる人間はどう読んでもよさそうである。ただ、海外に行くと「てんそるふろー」はダメそう。

日本語: 「てんそるふろー」<br>英語: 「てんさーふろー」<br>なのかな....?

## 結論: どっちでもいい
「てんそるふろー」は間違いで、「てんさーふろー」が正しい！と言う人は<br>
f'(x)を「エフダッシュエックス」ではなく「エフプライムエックス」と読みなさいと言う人と似たようなものなのか...?(少し違う気がするが。。)

ここは日本なんだからどっちでもいいじゃんって思います。<br>読み方を気にしている人より凄いのは、Tensorflowを使いこなせる人で、さらに凄いのはTensorflowを作った人であるのには変わらない。

**結論: どっちでもいいし、どうでもいい^^**

### 余談
自分でこの記事を書いてしまい、何かとTensorflowと言う度に意識してしまうので本当に後悔しています。<br>他にこの記事を読んで意識するようになってしまい、人との対話に影響が出てしまった方がいれば本当に申し訳ありませんmm

### コードがないと物足りないので【おまけ】
```python
import tensorflow as tf
```
※~~読み方迷わなくていいしpytorch使えよ自分~~
７つのアクションとは

７つのアクションとはindex、new、create、show、edit、update、destroyのこと。
アクションにより処理が分かれる。
indexはトップページを表示
newは新規投稿ページを表示
createはデータの新規投稿
showは個別詳細ページを表示
editは投稿編集ページを表示
updateはデータの編集
destroyは投稿のデータの削除
これらを作ったVS Codeのcontroller.rbに記述していく
モデル作成時エラー

userモデル、groupモデル、group_userモデルの作成の順番を間違えていろんなエラーを起こしてしまった。
userマイグレーション　　　　　　　　 groupマイグレーション
groupマイグレーション　　　　　　　　group_userマイグレーション
group_userマイグレーション　　　　　userマイグレーション　
右側の順番で作成
中間テーブルがある場合は一番下に作成しなくてはいけない
後何回もモデル、マイグレーション、テーブルを作成してしまいごみ箱に残っているモデル、マイグレーション、テーブルを読み込んでエラーが出ていた。
https://gyazo.com/b063aab44447ad2a35ca59fbbbf9f7a9

今気づいた！
GitHubでプルリクエストの時にgroupマイグレーション、group_userマイグレーション、モデルが消えてる！
明日確認！


rails db:migrate:reset
でデータベースに残ってるマイグレーションを消す
【OnsenUI】画面遷移とアニメーションの設定方法

#画面遷移の方法


```JavaScript:main.js

if (page.id === 'page1') {
  page.querySelector('#switch_button').onclick = function() {
    document.querySelector('#myNavigator').pushPage('page2.html',slide);
  };
} else if (page.id === 'page2') {
  page.querySelector('#return_button').onclick = function() {
    document.querySelector('#myNavigator').popPage(slide);
  };
};
```

画面遷移には、`pushPage` `popPage`メソッドを使用します。
引数に、あらかじめ作成したページとアニメーションを指定します。(`popPage`にはアニメーションのみ)

#アニメーションの設定

```JavaScript:main.js
const slide = {
  animation: 'slide',onTransitionEnd: function(){}
};
```

`animation`には以下の４つが用意されています。

- slide
- lift
- fade
- none

#参考文献
[OnsenUIの基礎-OnsenUI](https://ja.onsen.io/v2/guide/fundamentals.html)
chat-spaceを作ろう①

# アプリケーションを立ち上げる

```ruby:ターミナル
rails new chat-space -d mysql
アプリ立ち上げ　アプリ名　データベース指定
cd ~/ディレクトリを移動

rails db:create
データベース作成
```

#  事前準備
### Hamlを導入する
```ruby:gemfile
gem 'haml-rails'
```
```ruby:ターミナル
bundle install
rails haml:erb2haml
拡張子.erbのファイルを,hamlになる
```
### sassを準備する
app/assets/stylesheets/application.css
の中身を全て削除し、拡張子を.scssに変更

### reset scssの設定（今回はYUI3を使用）
assets/stylesheetsディレクトリ内に部分テンプレート*_reset.scss*ファイルを作成
その中に[YUI3](https://github.com/yui/yui3/releases)をコピペする

```ruby:assets/stylesheets/application.scss
@import "./reset";
作成した_reset.scssファイルを読み込む
```
application.scssに読み込むことでアプリケーション全体に適用される様になる

今日はここまで！
[見本サイト](https://chat-space-sample.herokuapp.com/users/sign_in)
Laravel Horizonのfailed_jobsテーブルを生SQL(PostgreSQL)で追加してみる

## はじめに
Laravel Horizon導入時に失敗したjobを溜め込む`failed_jobs`テーブルが必要ですが、migrateがLaravelとは別で機能しているため、自前でテーブル構成を定義したときの話です

## 環境
|name|ver|
|:-:|:-:|
|PHP|7.3|
|Laravel|6.5|
|PostgreSQL|10.6|

## Laravelでマイグレーションした場合のテーブル構造
既存でPostgreSQLを使ってHorizonを導入しているプロジェクトがあったのでテーブルをみてみるとこんな感じだった

```
hoge=> \d+ failed_jobs
                                                              Table "public.failed_jobs"
   Column   |              Type              | Collation | Nullable |                 Default                 | Storage  | Stats target | Description
------------+--------------------------------+-----------+----------+-----------------------------------------+----------+--------------+-------------
 id         | bigint                         |           | not null | nextval('failed_jobs_id_seq'::regclass) | plain    |              |
 connection | text                           |           | not null |                                         | extended |              |
 queue      | text                           |           | not null |                                         | extended |              |
 payload    | text                           |           | not null |                                         | extended |              |
 exception  | text                           |           | not null |                                         | extended |              |
 failed_at  | timestamp(0) without time zone |           | not null | CURRENT_TIMESTAMP                       | plain    |              |
Indexes:
    "failed_jobs_pkey" PRIMARY KEY, btree (id)
```

念の為新規でLaravelの環境を用意してチュートリアルどおり入れてみても同様なのでこの構成で大丈夫そう
https://readouble.com/laravel/6.x/ja/queues.html

## 実行したSQL
上のテーブル構造から以下のSQLを実行で問題なく作成できた

```sql
CREATE TABLE failed_jobs (
    id         BIGSERIAL PRIMARY KEY,
    connection TEXT NOT NULL,
    queue      TEXT NOT NULL,
    payload    TEXT NOT NULL,
    exception  TEXT NOT NULL,
    failed_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
```

## おわりに
`artisan`コマンドは便利だけど、やっぱり内部実装を理解してから使わないと混乱するので、実験って大事
HTTPメソッドとは

HTTPメソッドとはクライアントから送られたリクエストの種別を表すもの。
GETはページを表示する操作のみを行う時
POSTはデータを登録する操作をする時
PUTはデータを変更する操作をする時
DELETEはデータを削除する操作を行う時
これを参考にルーティングを設定をする。ルーティングは「どのようなリクエスト」=>「どのようなコントローラー・アクション」につなげるのかを設定するという感じの認識で。
ルーティングはroutes.rbに記述。
[HTTPメソッド] '[URIパターン]', to: '[コントローラー名]#[アクション名]'で作られる。
ルーティングを確認はrails routesでアプリケーションのルーティングを確認することができる。
自己証明書のwebサービスをblackbox_exporterで監視する

自己証明書のwebサービスをblackbox_exporterで監視する

[prometheus/blackbox_exporter](https://github.com/prometheus/blackbox_exporter)

以下のように```insecure_skip_verify: true```をconfに書くことでhttpsを使った自己証明書の外径監視ができるようになる。

デフォルトとではfalseになってるので監視としてはエラーとなります。

``` yaml
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2"]
      method: GET
      fail_if_ssl: false
      fail_if_not_ssl: true
      tls_config:
        insecure_skip_verify: true
```

自己証明書の環境を監視する機会はあんまなさそうですがローカルでblackbox_exporterを試す場合なんかは使えそうですね。
PHPばっかりやってきた43才がScala+PlayFrameworkを１から学ぶ

##きっかけ
現在、自社製品の開発からは離れてフロントエンジニアとして活動しています。
開発をしていた頃は主にサーバーサイドのPHPエンジニアでした。
PHPは学習コストがあまりかからないので非常に便利でした。

開発の現場を離れた今、PHPをゴリゴリ調べる事もなくなり、たまには違う言語でもやってみようと思い、流行り？の関数型言語＋お堅い言語をやってみようと思いScala+PlayFrameworkにチャレンジする事にしました。


##sbt
Scalaでいろいろ調べてると必ず出てくる単語。おそらく必須ではないだろうけど、やたら出てくるので調査。
https://www.scala-sbt.org/
https://ja.wikipedia.org/wiki/Sbt
**The interactive build tool**だそうです。ようするにビルドツールですね。

ひとまずsbtが使える環境を準備します。今回はこちらのdockerイメージを利用しました。
https://hub.docker.com/r/hseeberger/scala-sbt/
シンプルに以下のコマンドを実行するとコケます。。。

```
$ docker run -it --rm hseeberger/scala-sbt
docker: Error response from daemon: manifest for hseeberger/scala-sbt:latest not found: manifest unknown: manifest unknown.
```

latestバージョン無いよということで、バージョン指定で起動してみます。

```
$ docker run -it --rm hseeberger/scala-sbt:8u242_1.3.8_2.12.10
```

これで無事に起動できます。sbtコマンドも正常に動作しているようです。

```
root@79794023720c:~# sbt -h
Usage: sbt [options]
  -h | --help         print this message
  -v | --verbose      this runner is chattier
〜略〜
```

##PlayFramework
とりあえず動かしてみます。
https://www.playframework.com/getting-started
**Try the Hello World Tutorial**からzipをダウンロードし、該当のディレクトリへ移動します。
移動後、以下のコマンドでコンテナを起動します。

```
$ docker run -it --rm -v $PWD:/app -p 9000:9000 hseeberger/scala-sbt:8u242_1.3.8_2.12.10 bash
```

コンテナの中に入ったあと以下のコマンドを実行。なにやらビルドが始まります。

```
# cd /app
# sbt run
```

ビルド完了後、ブラウザでアクセスします。
http://localhost:9000

以下の画面が表示されます。
![スクリーンショット 0002-02-25 23.02.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43851/b9308083-2e7d-e5e3-b9f4-361ba424f316.png)

**要調査**
一度コンテナを落として再度コンテナ起動＆コマンド実行をしたら何故かエラーで落ちる。。。

```
# cd /app
# sbt run
[error] sbt.compiler.EvalException: Type error in expression
[error] Use 'last' for the full log.
```
Pythonで関数を作る

Pythonでの関数の作り方を自分用のメモとして置いておきます。
#定義
関数名をfunctionとする。

```py
def function():
    pass
    #引数なし
```
##引数
関数にデータ(int,str,class等)を渡す。
引数(ひきすう)名をargsとする。

```py
def function(args):
    #引数あり
    print(args)

def function2(args1,args2):
    #引数は何個でも取れる
    print(args,args2)

def function3(args="Hello World"):
    #引数に初期値を設定できる
    #呼び出し時に引数がなければargsには"Hello World"が入る
    print(args)
```
##戻り値
関数内の処理の結果を返す。

```py
def function(args):
    #戻り値あり
    n = args * 2 #引数を2倍して返す
    return n

def function2(args,args2):
    a = args + args2
    b = args - args2
    return (a,b) #タプル型で返す
```
返す型は何でもいい

#呼び出し
関数を呼び出すには 関数名() で呼び出せる。

```py
def function():
    print("Hello World")

function()
#------------
#Hello World
#------------
```
引数がない場合は()内に何も書かなくていい。
書くとエラーが出る。


```py
TypeError: function() takes 0 positional arguments but 1 was given
```
##引数
引数は()の中に書く。

```py
def function(args):
    print(args)

function("Hello World")
#------------
#Hello World
#------------
```
引数を設定しないとTypeErrorが起きる。

```py
TypeError: function() missing 1 required positional argument: 'args'
```
##戻り値
戻り値は変数に入れることができる。

```py
def function(args):
    n = args * 2 
    return n

n = function(5)#function関数の戻り値を変数nに代入
print(n)
#--------
#10
#--------
```

##その他
関数内から別の関数を呼ぶこともできる。

```py
def function(args):
    n = function2(args,10)#function関数内からfunction2関数の呼び出し
    print(n)    

def function2(args,args2):
    n = args * args2
    return n

function(5)
#--------
#50
#--------
```
Sequel Proへのデータベース作成

rails db:createで、データベースを作成できる。
VS Codeでdatabase.ymlを見ると運用環境が記述されており、
development、test、productionとある。
developmentは通常、開発をする際に使用する環境。
testはテスト環境。アプリケーションの動作をテストする際に使用する環境。
productionは本番環境。アプリケーションを実際にリリースする際に使用する環境。
rails db:createをターミナルに記述するとSequel Pro(シークエル・プロ)にアプリケーション名developmentとアプリケーション名testが作られる。
家での毎日のピアノ練習時間を可視化する(RaspberryPi + Pixela)

# はじめに
最近、趣味で電子ピアノを弾くようになったのですが、家での毎日の練習時間を
自動で記録できれば良いなと思い、ピアノの練習時間をPixelaで可視化する仕組みを作ってみました。

# システム概要
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154020/2f8d7f4a-95d3-3ca1-4d8c-dfd5e0ed7849.png)

電子ピアノとRaspberryPiをUSBで接続し、USB抜き差し(=ピアノの電源ON/OFF)を
RaspberryPi側で検知します。
ピアノが電源ONとなっている間の時間を計測し、ピアノ練習時間としてPixelaへ記録します。

## 使用環境

* 電子ピアノ YAMAHA ARIUS YDP-S34
* RaspberryPi Zero　(別途、無線LANモジュールを用意)

 * Python 3.7.3
 * python3-pyudev 0.21.0-1

※電子ピアノはUSB接続端子が付いているものを使用します。

## ピアノの電源ON/OFFを検知
Pythonのpyudevというモジュールで、USBの接続状態を確認します。

※以下の記事を参考にしました。
[RaspberryPiでUSBメモリを挿したことをユーザプログラムから認識する](https://uepon.hatenadiary.com/entry/2017/04/16/203934)

USB接続のaction=addを検知した時間から、action=removeを検知した時間までを計測し、
その日のピアノ練習時間とみなすようにします。

## Pixelaに記録
上記で算出したピアノ練習時間を、WebAPI経由でPixelaへ送ります。

同じ日に何回も練習する場合もありえるので、Pixelaから対象日の練習時間を一度取得したあと、
今回分の時間を足してPixelaへ送るようにします。

[Pixela](https://pixe.la/ja)
[Pixela API Document](https://docs.pixe.la/)


まず、事前にPixelaのユーザ作成と、グラフの作成をコマンドラインで行います。
こちらもWebAPI経由で行います。

* ユーザを作成

\<x-user-token>と\<username>は適宜置き換えてください。

```
$ curl -X POST https://pixe.la/v1/users -d '{"token":"<x-user-token>", "username":"<username>", "agreeTermsOfService":"yes", "notMinor":"yes"}'
{"message":"Success.","isSuccess":true}
```

* グラフを作成

グラフidは仮で、"piano-time-graph"としておきます。

```
$ curl -X POST https://pixe.la/v1/users/<username>/graphs -H 'X-USER-TOKEN:<x-user-token>' -d '{"id":"piano-time-graph","name":"piano-time-graph","unit":"minutes","type":"float","color":"shibafu","timezone":"Asia/Tokyo","isSecret":true,"publishOptionalData":true}'
{"message":"Success.","isSuccess":true}
```

プログラムでは、一度、対象日の練習時間を取得(GET)してから、
今回分の時間を足して、Pixelaへ送信(PUT)するようにします。

単に今回分の時間をPixelaへ送信(PUT)するだけだと、
その日にPixelaへ記録されている時間を上書きしてしまいます。

また、Pixelaにその日の時間が記録されていない場合(その日初めて練習する場合)、
時間を取得(GET)しようとしても正しい値が取れません。

```
$ curl -X GET https://pixe.la/v1/users/<username>/graphs/piano-time-graph/20200227 -H 'X-USER-TOKEN:<x-user-token>'
{"message":"Specified pixel not found.","isSuccess":false}
```


# ソースコード全文
以下を参照ください。
https://github.com/hillstop/PianoPracticeTime

# 動かしてみる
PixelaのURLをブラウザで叩きます。
<img width="1090" alt="スクリーンショット 2020-02-25 22.14.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154020/e7007423-64ca-d68f-e8b6-cd7fecda9f78.png">
何日分か記録してみました。
まだまだ全体的に白いですが、1年くらい続けると見栄えが良くなるかな？と思います。 （先は長い・・・）
読書ログ『メタプログラミング Ruby 第2版』3章

## 3章 火曜日: メソッド

### 動的メソッド

- **メソッドを呼び出す**というのは、オブジェクトにメッセージを送ること

### Object#send

- メソッドを呼び出すには、**ドット記法**と**Object#send**がある
  - `obj.send(:my_method, 3)`
- **Object#send**を使うと、どんなメソッドでも呼び出せてしまう
  - privateメソッドを呼び出せるからこそ、sendを使う

### 動的ディスパッチ

- `send`メソッドを使って、呼び出したいメソッド名を引数として、コードの実行時に呼び出すメソッドを決めること

### メソッドを動的に定義する

### Module#define_method

- 実行時にメソッド名を定義できる
- メソッド名とブロックを渡すことで、ブロックがメソッドの本体となる

```ruby
class MyClass
	define_method :my_method do |my_arg|
		my_arg * 3
	end
end

obj = MyClass.new
obj.my_method(2) #=> 6
```

### 手順1: 動的ディスパッチを追加する

### 手順2: メソッドを動的に生成する

### 手順3: コードにイントロスペクションをふりかける

### method_missing

- BasicObjectクラスの、privateインスタンスメソッド
  - NoMethodErrorを返すのが役割

- 指定したメソッドが継承チェーンを遡っても見つからない場合、Rubyは、method_missingを呼び出して負けを認める。

- method_missingが呼び出されると

  ```ruby
  hoge.send :method_missing, :my_method
  => NoMethodError: undefined method 'my_method' for <...>
  ```

- **method_missingをオーバーライドすると、実際には存在しないメソッドを呼び出せる**

```ruby
class Lawyer
  def method_missing(method, *args)
    puts "呼び出した: #{method}(#{args.join(',')})"
    puts "(ブロックも渡した)" if block_given?
  end
end

bob = Lawyer.new
bob.talk_simple('a', 'b') do
	# ブロック
end

=> 呼び出した: talk_simple(a,b)
(ブロックも渡した)
```

### ゴーストメソッド

- method_missingを呼び出す際、通常と同様に見えるが、レシーバ側に対応するメソッドが見当たらないこと。
  - 「君が理解できないことを頼まれたら、これをやっておいてね」という感じ

### 動的プロキシ

- ゴーストメソッドを補足して、他のオブジェクトに転送するオブジェクトのこと。

### respond_to_missing?

- Rubyが、respond_to?にゴーストメソッドを認識させる仕組み
- method_missingをオーバーライドしたときには、respond_to_missing?もオーバーライドすること。

### const_missing

- 存在しない定数を参照すると、Rubyは定数の名前をconst_missingにシンボルとして渡す。
- クラス名は単なる定数なので、不明な参照はModule#const_missingに渡される

### ブランクスレート

- 最小限のメソッドしかない状態のクラスのこと
- ブランクスレートが必要であれば、BasicObjectを直接継承する

### まとめ

**可能であれば動的メソッドを使い、仕方がなければゴーストメソッドを使う**

## 感想

Object#sendを使って、動的にメソッドを呼び出すこと、Module#define_methodを使って、動的にメソッドを定義する、という動的メソッドの存在を知る。

また、BasicObject#method_missingを上書きし、存在しないメソッドをゴーストメソッドとして生成する方法を知る。

一旦は見た際に気づけるかな、という感覚。実際に自分で使うとなると、もう少し慣れや自信が必要かな、という肌感。:sweat:
Elm の Maybe の知見


Elm を書いていて、いい感じにリファクタできた部分を説明する。

# やりたいこと

文字列のリストを受け取って、先頭の文字列を数値に変えた物を返す関数を作る。
この際、途中で Nothing になった場合は 0 を返す。

# はじめに実装したもの

```elm
getFirstNum : List String -> Int
getFirstNum strs = maybeStringToInt <| List.head strs

maybeStringToInt : Maybe String -> Int
maybeStringToInt s =
    case s of
        Nothing ->
            0
        Just str ->
            stringToInt str

stringToInt : String -> Int
stringToInt s =
    let
        n = String.toInt s 
    in
    case n of
        Nothing ->
            0
        Just num ->
            num
```

とりあえず動くものを最初に作ることはよくあるが、これはひどい...。

# リファクタしてみる

## 文字列から数値への変換

Elm の公式ドキュメントをみてみる。
https://package.elm-lang.org/packages/elm/core/latest/Maybe

なるほど Maybe.withDefault というものがあるのか。

```
> Maybe.withDefault
<function> : a -> Maybe a -> a
```

それを使うと

```elm
stringToInt s = Maybe.withDefault 0 <| String.toInt s
```

case を書くことなく記述できる。

## リストの先頭を取得する際の注意

リストから先頭要素をとる時に、空のリストを渡された時は Nothing となる。
つまり List.head は Maybe 型で返却される。

```
> List.head
<function> : List a -> Maybe a
```

## 返り値の型が Maybe である関数を合成したとき

今回やりたいことを実現するには、

* 文字列リストの先頭を取得する
* 文字列を数値に変換する

の二つの関数を合成すればよい。
ここで注意したいのは、両方の処理の返り値の型は Maybe である。

その時 Maybe.andThen というものを使うといい感じにかける。

```
> Maybe.andThen
<function> : (a -> Maybe b) -> Maybe a -> Maybe b
```

この関数は Maybe 型を返す関数と Maybe 型の値を受け取っていい感じに処理をしてくれる関数である。
今回の場合は String.toInt という Maybe 型を返す関数と、リストの先頭を取得した値 Maybe String を渡す。

```elm
Maybe.andThen String.toInt <| List.head strs
```

という感じで書く。
もし、リストの先頭が取れなかった時 (Nothing) は String.toInt の処理ではそのまま Nothing が返却される。リストの先頭が取得できた時 (Just "hoge") は String.toInt の処理で "hoge" が渡される。

これを使うことによって Maybe 型が返却される関数の合成が非常に楽になる。

## それらを組み合わせる

Maybe.withDefault と Maybe.andThen を使って書き直してみる。

```elm
getFirstNum : List String -> Int
getFirstNum strs = Maybe.withDefault 0 <| Maybe.andThen String.toInt <| List.head strs
```

そうすることによって一行で書けるようになった！！

## さらにリファクタ

<| を使うよりも |> の方が処理の順番通りに書けるので読みやすくなる。

```elm
getFirstNum : List String -> Int
getFirstNum strs = List.head strs |> Maybe.andThen String.toInt |> Maybe.withDefault 0
```

また、いちいちパスを書くのは面倒なので import して exposing させる。

```elm
import Maybe exposing (andThen, withDefault)
import String exposing (toInt)
import List exposing (head)

getFirstNum : List String -> Int
getFirstNum strs = head strs |> andThen toInt |> withDefault 0
```

これによってだいぶ読みやすくなった。

# まとめ

withDefault に相当する関数は絶対あるだろうと思って調べたらあったので、ちゃんと調べることは大切だなと感じた(小並感)。
初めてのチーム開発（フリマサイト）その２

# どの様に分担するか
初めてのチーム開発で何から手をつけたらいいのか。
初回でメンバーとざっくり決めたのはフロントから入るというのもでした。
## 初回スプリントレビュー
２週間が経過し初のスプリントレビューです。
メンターからのアドバイス

- サーバーサイドは時間がかかる、担当者しか出来ない
- ビューは装飾なので後からでも大丈夫、誰でもできる

その後メンバーと話をして、html特にformの部分が出来ていればフロントは後回しでもいいという結果に・・・

しかしながら途中になってしまうので現在の割り振られたフロントに付いては５０％程度を目処に作成完了とし、サーバーサイドに着手することとしました。
TypeScript 3.7のNullish Coalescingで少し嵌った話

#概要

TypeScript 3.7で追加されたNullish Coalescingは現場で使用しておりとても重宝しています。
nullとunderstandのみ判定できるので簡単に任意の型にすることが出来るのですが、
今回、愚直に使用した結果、発生した現象がありました。

今回は例文とそれをトランスパイル後の実際に実行されたコードも出して解説？したいと思います。
もし、今後同じようなことは起きる人がいた時にこの記事で解決の糸口になれば良いなとって思います。

# 事象

先ずは実際に意図しない時のコードと同等のコードは

```typescript:typescript

interface MyFavorite {
  lastName?: string;
  firstName?: string;
}

const myFavorite: MyFavorite = {};

const result = myFavorite.lastName && myFavorite.firstName
  ? myFavorite.lastName + " " +  myFavorite.firstName
  : myFavorite.lastName ?? "" + myFavorite.firstName ?? ""
;

console.log(result )

```

とします。
この場合、trueの場合は説明するまでもないと思います。

問題なのはfalse判定だった時です。
この場合、実装者(今回は僕)の期待値としては空文字列を期待していました、

しかし実際に出力された文字は"undefined"と表示されてしました。

もうダメだ。。。
救いはないんですか!?

ってなりました。

# 原因

この現象を見たとき、処理の評価順がどーなっているかを調べました。
TypeScriptをトランスパイルしてJavaScriptに変換してみました。

そしたら以下コードになりました。

```javascript:javaScript

var _a, _b;
const myFavorite = {};
const result = myFavorite.lastName && myFavorite.firstName
    ? myFavorite.lastName + " " + myFavorite.firstName
    : (_b = (_a = myFavorite.lastName, (_a !== null && _a !== void 0 ? _a : "" + myFavorite.firstName)), (_b !== null && _b !== void 0 ? _b : ""));
console.log(result);

```

となりました。

問題のコードは三項演算子のfalseの部分ですね。

```javascript

(
  _b = (
    _a = myFavorite.lastName, (_a !== null && _a !== void 0 ? _a : "" + myFavorite.firstName)
  ),
  (_b !== null && _b !== void 0 ? _b : "")
)

```

これをみた瞬間全てを理解しました。

処理の順番としては
　1. _aにmyFavorite.lastNameを代入(_aにはundefined)
　2. _aがnull又はunderstandではない場合、_aはそのまま(今回はこっちではない)
　3. _aがnull又はunderstandだった場合、空文字列とmyFavorite.firstNameを結合して_aに代入 ← ここ
　4. 以下はそのまま(決してめんどくさいわけではない)
　
つまり僕の脳内では

```typescript
(myFavorite.lastName ?? "") + (myFavorite.firstName ?? "")
```

このようなイメージでいたのですが実際は

```typescript
((myFavorite.lastName ?? "") + myFavorite.firstName) ?? ""
```

このように評価されていたそうです。
~~間違えていたらこっそり教えてください~~

これでは空文字列とunderstandを結合していることになる為、
"understand"の文字列を生成しておりました。

確かに遅延評価なので理解はしましたが、納得はちょっと・・・てなりました。
まぁ～サボって愚直な実装した僕が悪いんですけどね・・・

# 最後に

ちょっと使いなれたからって愚直な実装は良くないですね。
このおかげで学ぶ機会があったので良かったですが、改めて慣れって怖いですね。
皆さんも予期せぬ落とし穴に嵌らないように気を付けましょう！！
tblsでデータベースのスキーマ情報をマークダウンで出力する

# 概要
DBのスキーマ情報をドキュメント化したいと思ったので使用したツールをメモします。

# 使用方法

[tblsのgithub](https://github.com/k1LoW/tbls#)を参考。

dockerイメージの入手

```bash
$ docker pull k1low/tbls:latest
```

1コマンドでデータベースをドキュメント化できる手軽さ。

```bash
$ tbls doc postgres://dbuser:dbpass@hostname:5432/dbname
```

dockerでやる場合は以下です。

```
$ docker run --rm -v $PWD:/work k1low/tbls doc postgres://dbuser:dbpass@hostname:5432/dbname
```

筆者の場合は、mysqlなので、以下です。

```
$ docker run --rm -v $PWD:/work k1low/tbls doc mysql://dbuser:dbpass@hostname:3306/dbname
```
VirtualBox で "Effective UID is not root（実効UIDがrootではない）"と怒られるとき

# はじめに

macOS を Catatalina にしてから VitualBox をインストールしたり、バージョンアップしたりすると、"Effective UID is not root（実効UIDがrootではない）" と怒られることがあります。最近、時々聞かれるのですが、簡単に解決できるので、メモしておきます。

# 解決方法

ターミナルを立ち上げて、以下を実行しましょう。

```
cd /Applications/VirtualBox.app/Contents/MacOS/
sudo chmod u+s VBoxHeadless
sudo chmod u+s VBoxNetAdpCtl
sudo chmod u+s VBoxNetDHCP
sudo chmod u+s VBoxNetNAT
sudo chmod u+s VirtualBoxVM
```

もし、「VirtualBoxVM がない」と怒られたら、下記を実行しましょう。

```
sudo chmod u+s /Applications/VirtualBox.app/Contents/Resources/VirtualBoxVM.app/Contents/MacOS/VirtualBoxVM
```

# 補足

/Applications ではない場所にインストールしている場合は、適宜、読み替えて下さい。

VirtualBox 6.1.2, 6.1.4 あたりのインストーラの不具合のようです。VirtualBox のフォーラムを読むと、次のバージョンで治るようです。
ブラウザでウェブカメラ映像のタッチのから色をRGBY-BK-WH判別

ブラウザでカメラ映像から色を判別するときに利用したチップスをメモ

###ウェブカメラ動画の取得

videoタグ配置しJSでカメラ取得
※localhost,127.0.0.1　や　HTTPS　の環境がないと動作しないでした。。

```html
<video id="videoInput" width="640" height="480" autoplay></video>
```

```js

var video = document.getElementById('videoInput')
navigator.mediaDevices.getUserMedia({
  video: {
    facingMode: "environment",
  },
  audio: false,
})
  .then(function (stream) {
    video.srcObject = stream;
    video.play();
  })
  .catch(function (err) {
    console.error(err);
  });
```

###カンバスへ変換(描画)
HTMLでカンバスを設置

```html
<canvas id="canvasOutputVideo" width="640" height="480"></canvas>
```

IntervalでVideoタグの内容をカンバスへ描画

```js
var canvas = document.getElementById("canvasOutputVideo");
var context = canvas.getContext("2d");
setInterval(updateCap, 100);
function updateCap() {
  context.drawImage(video, 0, 0, 640, 480);
};
```


###タッチ箇所の取得

下記のどれかで取得となるはず


```js

console.log("screen:" + e.screenX + "," + e.screenY);
console.log("client:" + e.clientX + "," + e.clientY);
console.log("offset:" + e.offsetX + "," + e.offsetY);
```

###平均の色を取得
クリック箇所を中心に3*3の9ドットの平均を算出
カンバスから取得

```js

let imageData = document.getElementById("videoCanvas").getContext("2d").getImageData(click.x-1 , click.y-1 , 3, 3);
let rgba = [0, 0, 0, 0];
imageData.data.forEach((v, i) => {
  rgba[i % 4] = rgba[i % 4] + v
});
const r = rgba[0] / (iW * iH);
const g = rgba[1] / (iW * iH);
const b = rgba[2] / (iW * iH);
const a = rgba[3] / (iW * iH);
let resRGBA = [Math.ceil(r), Math.ceil(g), Math.ceil(b), Math.ceil(a)];
```

###RGBをHSVへ変換

色を純粋に判定したい場合はHSVが便利

* H：色相　RGB的な色を判定に利用
* S：彩度　白の判定に利用
* V：明度　黒の判定に利用

```js

function rgb2hsv (rgb) {
  var r = rgb[0] / 255;
  var g = rgb[1] / 255;
  var b = rgb[2] / 255;
  var max = Math.max(r, g, b);
  var min = Math.min(r, g, b);
  var diff = max - min;
  var h = 0;
  switch (min) {
    case max: h = 0; break;
    case r: h = (60 * ((b - g) / diff)) + 180; break;
    case g: h = (60 * ((r - b) / diff)) + 300; break;
    case b: h = (60 * ((g - r) / diff)) + 60; break;
  }
  var s = max == 0 ? 0 : diff / max;
  var v = max;
  return [h, s, v];
}
```

###RGBY,BK,WHに判別

色相0～360、彩度0～1、明度0～1を利用して判別

やんわり力技なので、Sinとか使ってうまいことできないか、模索したが挫折しこの状態へ。。

```js

function checkColor (rgba) {
  var ret = "";
  var hsvRGBA = U.rgb2hsv(rgba);//色相
  var hRGBA = hsvRGBA[0];//色相
  var sRGBA = hsvRGBA[1];//彩度0で白
  var vRGBA = hsvRGBA[2];//明度0で黒
  if (sRGBA < 0.2) {
    ret = "White";
  } else if (vRGBA < 0.2) {
    ret = "Black";
  } else if (
    (315 < hRGBA && hRGBA <= 360) ||
    (0 < hRGBA && hRGBA <= 45)
  ) {
    ret = "Red";
  } else if (
    (45 < hRGBA && hRGBA <= 135)
  ) {
    ret = "Yellow";
  } else if (
    (135 < hRGBA && hRGBA <= 200)
  ) {
    ret = "Green";
  } else if (
    (200 < hRGBA && hRGBA <= 315)
  ) {
    ret = "Blue";
  }
  return ret;
}
```


###参考サイト

HSV色空間
https://www.peko-step.com/html/hsv.html

RGBをHSVに変換する方法
https://lab.syncer.jp/Web/JavaScript/Snippet/66/
Ruby/GTK3 - RadioButton

`gem install gtk3`

# RadioButton

ラジオボタンは、1つのボタンを押すと他のボタンが押されていない状態になり、常に1つのボタンだけが押された状態になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/6551acf4-65da-bf15-008a-d641c3fd6159.png)

> Button 1 was turned off
> Button 2 was turned on
> Button 2 was turned off
> Button 1 was turned on
> Button 1 was turned off
> Button 3 was turned on

```ruby
require 'gtk3'

class RadioButtonWindow < Gtk::Window
  def initialize
    super
    set_title 'RadioButton Demo'
    set_border_width 10

    hbox = Gtk::Box.new(:horizontal, 6)
    add hbox

    button1 = Gtk::RadioButton.new(label: 'Button 1')
    button1.signal_connect('toggled') { |b| on_button_toggled b, 1 }
    hbox.pack_start(button1)

    button2 = Gtk::RadioButton.new(member: button1, label: 'Button 2')
    button2.signal_connect('toggled') { |b| on_button_toggled b, 2 }
    hbox.pack_start(button2)

    button3 = Gtk::RadioButton.new(member: button1, label: 'B_utton 3',
                                   use_underline: true)
    button3.signal_connect('toggled') { |b| on_button_toggled b, 3 }
    hbox.pack_start(button3)
  end

  def on_button_toggled(button, name)
    state = button.active? ? 'on' : 'off'
    puts "Button #{name} was turned #{state}"
  end
end

win = RadioButtonWindow.new
win.signal_connect('destroy') { Gtk.main_quit }
win.show_all
Gtk.main
```

ところで、`member` や `use_underline` といったRuby/GTK3に特徴的なオプションはどこで定義されているのだろうか？
https://github.com/ruby-gnome/ruby-gnome/blob/master/gtk3/lib/gtk3/radio-button.rb
を見ると、どうやらこれらは手動で定義されているようである。

* [Python version](https://python-gtk-3-tutorial.readthedocs.io/en/latest/button_widgets.html#id2)
Windowsでのnpm installの使い方

# サマリ
- npm installでパッケージをインストールする際「-g」オプションの有無による違い
- npm install -gによる資材の配置場所の変更方
- npm installでインストールされたパッケージの確認方法
- npm installでインストールされたパッケージの削除方法

# 目的
node.jsを学習する際、npm installの使い方がわからず挫折しそうになった。
原因として、各記事で「-g」オプションの有無にばらつきがあり、
「-g」オプションの有無による具体的な違いやnpm install実行後の確認方法がまとまって説明されている記事がなかなか見つからなかった。
同じことで困った人の参考として、自分の実行例と合わせて説明を記載する。

# 本文
## 1. npm installコマンドの効果
node.jsで利用するパッケージをダウンロードできる。
ダウンロードしたパッケージはrequireで取得・利用できるようになる。
例）expressをインストールした場合
`var express = require('express')`

## 2. 「-g」オプションの有無による違い

- 「-g」オプションが無い場合
`npm install`を実行したフォルダ配下でのみパッケージを利用可能。

- 「-g」オプションが有る場合
`npm install`を実行したフォルダ配下以外からでもパッケージを利用可能。


## 3. 「-g」オプションの有無によるダウンロード資材の配置場所の違い

- 「-g」オプションが無い場合
`npm install`を実行したフォルダ配下の`node_modules`フォルダ。

- 「-g」オプションが有る場合
`npm config list`コマンドを実行して表示された情報の「prefix」の場所。
以下の実行例の場合は`C:\nodejs\node_modules_global`配下に`node_modules`フォルダ配下にパッケージが配置される。

実行例）

```
> npm config list
; cli configs
metrics-registry = "https://registry.npmjs.org/"
scope = ""
user-agent = "npm/6.13.4 node/v12.14.1 win32 x64"

; userconfig C:\Users\user\.npmrc
prefix = "C:\\nodejs\\node_modules_global"

; builtin config undefined

; node bin location = C:\Program Files\nodejs\node.exe
```

## 4. npm install -gによる資材の配置場所の変更方
`npm config set`コマンドでprefixの設定値を更新することで配置場所を変更可能。

例）C:\nodejs02\node_modules_globalに変更する場合
`> npm config set prefix=C:\nodejs02\node_modules_global`

なお、グローバルパッケージの配置場所を変更した場合、Windowsでは新しい配置場所にpathを通さないとnode.jsの実行時にエラーとなった。

## 5. npm installでインストールされたパッケージの確認方法
`npm list`コマンドで確認できる。`npm ls --depth=0`とすると、依存関係を除いたパッケージ情報のみ表示できる。

- 「-g」オプションを付けずにインストールしたパッケージ（ローカルパッケージ）の確認

```
> npm ls
sample@0.0.0 C:\node_sample\sample　　←　ローカルパッケージの配置場所（npm installコマンドを実行した場所）
+-- cookie-parser@1.4.4
| +-- cookie@0.3.1
| `-- cookie-signature@1.0.6
+-- debug@2.6.9
| `-- ms@2.0.0
+-- express@4.16.4
| +-- accepts@1.3.7
| | +-- mime-types@2.1.26
| | | `-- mime-db@1.43.0
| | `-- negotiator@0.6.2
　：
　：
```

- 「-g」オプションを付けてインストールしたパッケージ（グローバルパッケージ）の確認

```
> npm ls -g
C:\nodejs\node_modules_global    ←　グローバルパッケージの配置場所
+-- express@4.17.1
| +-- accepts@1.3.7
| | +-- mime-types@2.1.26
| | | `-- mime-db@1.43.0
| | `-- negotiator@0.6.2
| +-- array-flatten@1.1.1
| +-- body-parser@1.19.0
| | +-- bytes@3.1.0
| | +-- content-type@1.0.4 deduped
　：
　：
```

## 6. npm installでインストールされたパッケージの削除方法

`npm uninstall`コマンドで削除可能。
`npm ls --depth=0`でインストールパッケージを表示し、表示されたパッケージの@より前の文字列を指定することで削除ができる。

実行例）ローカルパッケージのexpressを削除する場合

```
> npm ls --depth=0
sample@0.0.0 C:\node_sample\sample
+-- cookie-parser@1.4.4
+-- debug@2.6.9
+-- express@4.16.4
+-- http-errors@1.6.3
+-- jade@1.11.0
`-- morgan@1.9.1

> npm uninstall express
```
# 参考にさせていただいたページ

いまさら聞けない！npmのこれだけは知っておきたい基礎知識
https://www.webprofessional.jp/beginners-guide-node-package-manager/

Qiita npmコマンドの使い方
https://qiita.com/yoh-nak/items/8446bf12094c729d00fe
コンテナ上のpython3/mysql-connector-pythonでホストのmysqlにアクセスする

# 概要
[こちら](https://qiita.com/tyariponzu614/items/7bcab83a01d534869638)の記事でWindowsホストのdockerコンテナ上にpython環境を構築しました。

コンテナからホストのmysqlにアクセスした時のメモです。
## 2/28追記
もう少し、簡単に使えるように改良しました。

# 前提
## 環境
| ホストOS | Windows10 |
|:-:|:-:|
| dockerイメージ | python:3 |
※ホストにdocker for windowsがインストールされていること

# mysqlの設定ファイル書き換え
my.cnf内のbind-addressをコメントアウトする。

```
[mysqld]
# bind-address = 127.0.0.1
```

# mysqlにユーザー追加

```
> grant all privileges on [db_name].* to [user_name]@"[ip_address]" identified by '[password]' with grant option;
> select user,host from mysql.user;
> FLUSH PRIVILEGES;
```

# 手順

以下のディレクトリを作成します。

```
.
├── Dockerfile
├── docker-compose.yml
└── sample.py
```

以下を記述します。

```Dockerfile
FROM python:3
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

# install additional utilities
RUN apt-get install -y vim less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

# install mysql utilities
RUN pip install mysql-connector-python

# add sample code
RUN mkdir /sample
ADD . /sample
WORKDIR /sample

CMD /bin/bash ./entrypoint.sh
```

```docker-compose.yaml
version: '3'
services:
  python3:
    restart: always
    build: .
    container_name: 'python3'
    working_dir: '/sample'
    tty: true
    volumes:
      - .:/sample
    extra_hosts:
      - "(ホストのCOMPUTERNAME):(ホストのIPアドレス)"
    ports:
      - 3306:3306
```

```python:mysql_demo.py
import mysql.connector as mydb


conn = mydb.connect(
    host='（ホストのIPアドレス）',
    port='3306',
    user='admin',
    password='password',
    database='sample_db'
)

conn.ping(reconnect=True)
print(conn.is_connected())
cur = conn.cursor()
cur.execute("SELECT * FROM sample_table;")
cur.close
conn.close

rows = cur.fetchall()
for row in rows:
    print(row)
```

## 結果

```
> docker-compose up -d --build
...
> docker container ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                    NAMES
aa4d45f07158        pyodbc_py370_python3   "/bin/sh -c '/bin/ba…"   27 minutes ago      Up 27 minutes       0.0.0.0:3312->3312/tcp   python3
> docker exec -it aa4d45f07158 /bin/bash
/sample# python --version
Python 3.8.1
/sample# pip list
Package                Version
---------------------- -------
dnspython              1.16.0
mysql-connector-python 8.0.19
pip                    20.0.2
protobuf               3.6.1
setuptools             45.2.0 
six                    1.14.0
wheel                  0.34.2
/sample# python sample.py
...SQL結果が表示されます。
```

# 参考
https://qiita.com/yoshiokaCB/items/df4ae185be7cbc4f03ac
GAS (Google Apps Script)でURL先のページをPDFダウンロードする方法

# まえがき

クラウドソーシングサイトに投稿があった依頼で、スプレッドシート上に記載されているURLのリンク先をPDFダウンロードしたいといったものがあったので、GASでのシンプルな実装例を載せておこうと思います。

# コード

```javascript
function myFunction() {
  // PDF取得
  var sheet = SpreadsheetApp.getActiveSheet()
  var url = sheet.getRange(1, 1).getValue()  // あらかじめサンプルのURLを入力している前提
  var pdf = UrlFetchApp.fetch(url).getAs('application/pdf')
  
  // Googleドライブへ保存 (ルートディレクトリに保存)
  DriveApp.createFile(pdf)
  
  // 完了メッセージ
  Browser.msgBox("Complete", Browser.Buttons.OK)
}
```

# 解説

解説するほどの内容ではないですが、
スプレッドシートのシート情報取得（3行目）
↓
シート上のセルからURL文字列を取得（4行目）
↓
fetchメソッドでHTTPリクエストし、getAs('application/pdf')でPDFオブジェクト取得（5行目）
↓
createFileメソッドでファイル保存（8行目）
という流れです。
最後のBrowser.msgBoxメソッドでは処理が終わったことがわかりやすいようにポップアップを出しています。
あとはURLの取得の仕方だったり、保存の仕方(ファイル名指定や保存先の指定)だったりを各々いじっていただければと思います。
Windows10でウィンドウがどっかいった時の処方箋

# はじめに
あまりここで書くもんでも無いけれど、ウィンドウが画面外に行ってしまう事象がごくたまに起きる。また対処法探すのも面倒なのでメモ。

# 手順
1. タスクバーにある対象のウィンドウのアイコンにカーソルを当てる
2. 2秒ぐらいするとプレビュー画面が表示される
3. プレビュー画面を右クリックするとコンテキストメニューが表示される
4. コンテキストメニューの"移動(M)"をクリック
5. するとカーソルが消えるのでそのままクリックし、ドラックをする
6. ドラックするとウィンドウの移動を確認出来ると思うので中央に持ってくる

※ 4で"移動(M)"がクリックできない場合、"元のサイズに戻す(R)"をクリックして最初から試しましょう。
R言語によるSVM(機械学習)

### はじめに
　R言語を用いたサポートベクターマシンにより、テキスト分類を行ってみました。
　テキストのベクトル化などについて、詳しくは、
[リンク(GitHub)](https://github.com/Yoocie/predict_depression_from_Twitter) を参照ください。

### データ
　テキストは、文書内の語の出現頻度の指標である「tf-idf」を用いてベクトル化し、次のような形状のcsvファイルになっています。

```[python]
num,。,が,の,...,おめでとう,くん,笑,group
0,0.000576,0.018227,0.018290,...,0.036156,0.019288,0.012082,ctrl
1,0.012769,0.026343,0.016902,...,0.007307,0.020576,0.013051,dep
2,0.000437,0.000360,0.000364,...,0.002279,0.001640,0.002097,ctrl
...
```
最終列（group列）の、"ctrl" or "dep" が、ラベルです。

### R言語によるサポートベクターマシンの利用

kernlabライブラリの、ksvm関数を用いました。

```[R]
>library(kernlab)

>setwd("//")

>train=read.csv("trainデータの一覧.csv")

>test=read.csv("testデータの一覧.csv")

>svm<-ksvm(group ~., data=train)

>predict<-predict(svm, test)

>predict

>table(predict,test$group)
```
ksvm関数のパラメータをきちんと調整すると、さらに良いかもしれません。

詳しくは、
[リンク(GitHub)](https://github.com/Yoocie/predict_depression_from_Twitter) を参照ください。

### 環境
R version 3.6.1
macOS Catalina 10.15.3
windowsにdockerでpython環境を用意する

# 概要
筆者はwindowsマシンを使用しています。
pythonの実行環境を用意するにあたり、
ホストがwindows、mac、linuxとコロコロ変わるので、環境構築の手軽さや、
ホストを汚したくなかった事もありdockerを使うことにしました。

# 環境
windows10 pro
Hyper-Vの機能を使用出来る必要があるようです。

# docker for windowsインストール
以下を参考にさせて頂きインストール
https://ops.jig-saw.com/tech-cate/docker-for-windows-install

# 設定ファイル記述
## Dockerfile

```:Dockerfile
FROM python:3
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
```

## docker-compose.yml

```yml:docker-compose.yml
version: '3'
services:
  python3:
    restart: always
    build: .
    container_name: 'python3'
    working_dir: '/root/'
    tty: true
    volumes:
      - ./tmp:/root/tmp
    extra_hosts:
      - "(ホストのCOMPUTERNAME):（ホストのIPアドレス）"
    ports:
      - 3306:3306
```

- `volumes`
ホストのパスをコンテナにマウントします。

- `extra_hosts`

ホスト名のマッピングを追加します。
コンテナの`/etc/hosts`に以下と記載されます。

```
162.242.195.82  somehost
50.31.209.229   otherhost
```

- `ports`

(ホスト側ポート):(コンテナ側ポート)


# ビルド

Dockerfile含むビルド方法

```
> docker-compose up -d --build
```

コンテナ停止

```
> docker-compose down
```

# 参考

- [dockerで簡易にpython3の環境を作ってみる](https://qiita.com/reflet/items/4b3f91661a54ec70a7dc)
- [フロントエンド開発者向けのDockerによるPython開発環境構築](https://qiita.com/hikarut/items/b178af2e2440c67c6ac4)
- [docker-compose.ymlリファレンス](https://docs.docker.com/compose/compose-file/)