OmniAICreator/Qiita-1.07M huggingface dataset:
0から始めるポートフォリオRTA

***エンジニアもすなるポートフォリオといふものを私もしてみむとてするなり。***

## 使ったもの
* TypeScript
* React
* Github Pages

## 要約
過去一度だけJavaScriptの勉強をしようとしたもののドットインストールのレッスンすら完遂できずに諦めた大学生が初見のTypeScriptとReactを使ってポートフォリオを4日間で作った話。日記的なものでコードは出てきません。ご了承ください。
完成品は[こちら](https://castachick.github.io/portfolio/)

## 経緯
僕は機械学習などの用途でpythonを日常的に使っているのですが、フロントエンドは全く触ったことがなく、HTMLとCSSを少しだけかける程度でした。11月からアルバイトでwebの開発に携わり始め、フロントに手を出すことになりそうだったので前もって少し触ってみようと思い、重い腰を上げて勉強して、ポートフォリオを作ってみました。TypeScriptとReactという組み合わせはバイト先のプロジェクトがこれで始められていたから同じものを使ってみました。

## 1日目(11/15)
### Reactを初めて見る
バイト先で初期化されたReactのプロジェクトを見ました。初めまして、TypeScript。後で調べて分かったのですが

```shell
$ create-react-app myapp --typescript
```
ってすると良い具合にReactプロジェクトの土台を作ってくれるみたいです。とっても簡単ですね。僕も自分で始める時は同じコマンドで初期化しました。
1日目はバイト先のリポジトリから自分用のブランチを切ってチュートリアルその他、Reactを好き勝手にいじって遊んだだけです。
この夜にバイト先が同じ同期のエンジニアの子とご飯に行っていろいろ話した結果、ポートフォリオを作ることを決心しました。

## 2日目(11/16)
### 外観を作る
作ると決めたは良いものの、外向けに公開するwebサイトのデザインをしたことがなかったので、とりあえずいろんな人のポートフォリオを覗きに行って自分なりにコンテンツや配置を決めました。バイト先でも使っている[Figma](https://www.figma.com/)を使ってみました。

### 配色を決める
色彩感覚も絶望的にないので[Khroma](http://khroma.co/)というサイトで大まかな配色を考えてみました。このサイトは無数に生成される色の中から好きなものを50色選ぶと機械学習でその人に合った配色例を提案してくれます。生成されたものからいくつか選んで自分のポートフォリオの配色の参考にしました。


## 3日目(11/17)
### コンポーネントを作る
触り始めたばかりであまり理解していないのですが、チュートリアルやいろいろな記事を読んで、Reactは小さなコンポーネントから大きなコンポーネントを作って行って最終的に１つのwebサイトにまとめるようなイメージで作ると良いのかなと感じました。とりあえずコンポーネントを作ろうということでFigmaで作ったポートフォリオのデザイン案を小さな要素へと自分なりに分割してそれぞれを実装していく作業をしました。Figmaのグループやレイヤーといった要素でグルーピングしてデザインしていたのでそれを参考にコンポーネントの構成を考えました。これはとっても便利だったのでデザイン段階からマテリアルデザイン的なものを意識すると良いのかなと感じました。基本文法すら手探りの状態でコーディングを進めたので結構時間がかかりましたが、詰まったところを調べる中でなんとなく感覚が掴めてきました。コンポーネントの実装と同時進行で合わせてCSSのスタイルも80%くらいの完成度で書いていったのですが、この方法が正しかったのかはよくわかりません。個人的には目で見ながらデザイン素案にどんどん近づいていくのを確認して実装を進められたので精神衛生上良かったと思っています。

## 4日目(11/18)
### コンポーネントの中身を作る
実装すべきコンポーネントをあらかた作り終わったので内容を書き込んでいく作業をしました。この頃にはReactの書き方に結構慣れて開発スピードは結構上がりました。pythonにおいて、定義しておいたクラスのインスタンスを生成してたくさん配置するようなイメージで作業を進めました。合ってるのかはわからないけど。。。こうしてポートフォリオの雛形を作り終えることができました。

### デプロイする
今回はGithub Pagesのサービスを使ってデプロイしました。前述の同期エンジニアが書いた[この記事](https://qiita.com/110416/items/41cc55f206f74e8b1a76)を参考にデプロイ作業をしました。CLIのコマンドでとても簡単に自動デプロイができてすごいと思いました。

### デザインの修正をする
こうして一応完成したポートフォリオですが、なんとなく芋っぽい感じがして気に食わなかったのでセンスの良さげな友人にアドバイスをもらいながらデザインを修正しました。無地の背景にピンドットを入れたり見出しにアンダーラインを付けたりしてだいぶ良い感じのデザインにすることができました。

### 記事を書く
そして現在(11:30)、この記事を書くに至っています。(公開は日付を跨ぎそう、、、)

## まとめ
フロントエンドを触ったことがない初心者でも4日間でTypeScriptとReactを使ってそれっぽいポートフォリオを作ることができました。今回はReact-routerで静的なSPAを作ってみましたが、バイトではここにサーバーとの通信やCookieの扱いなども加わってくると思います。最近は主に機械学習系の実装をしていたのですが、今後はこれに加えてフロントエンドの勉強も精進して行こうかなと考えています。

最後に、このポートフォリオのコードとurlを以下に置いておくのでもし良かったら覗いてみてください。初めて触ったのでナンセンスな設計、コーディングが多々みられると思います。気になったところはどんどん指摘していただけると嬉しいです。

**それでは！お読みいただき、ありがとうございました！！！**

リポジトリ: https://github.com/CastaChick/portfolio
ポートフォリオ: https://castachick.github.io/portfolio/
ポップなデータ活用事例集

# はじめに

本記事では、機械学習、データ分析、データ可視化、自然言語処理などデータ活用する分野において、“ポップ”なデータを活用した事例が紹介されているウェブサイトやブログの記事などを紹介します。そもそも“ポップ”とは何か。[Weblio辞書](https://www.weblio.jp/)では以下のように説明されています。

[ポップとは何？ Weblio辞書](https://www.weblio.jp/content/%E3%83%9D%E3%83%83%E3%83%97)
> ③広く大衆に受け入れられやすいさま。

つまり、広く大衆に受け入れられやすい内容（＝ポップ）のデータを活用した事例を紹介します。今日、オープンデータとしてさまざまな内容のデータが公開されており、その中でもいわゆるポップなものもありますね。抵抗があるかもしれない機械学習、データ分析、データ可視化、自然言語処理などの理解に役立てると幸いです。本記事は、私自身の備忘録も兼ねているため、気まぐれで随時更新していきます。ご了承ください。自分としては、今後データを活用した“何か”を行うときの参考として蓄積していこうと思います。

もしよろしければ、これらと合わせてご覧ください。
↓
[機械学習の参考リンク集](https://qiita.com/daikikatsuragawa/items/7e102ba5607560f7952a)
[機械学習の用語集](https://qiita.com/daikikatsuragawa/items/dad446105bfd11ff995b)

# ポップなデータ活用事例集

### [【Python】嵐の歌詞をWordCloudで可視化して、結成20年でファンに伝えたかったことを紐解いてみた - Qiita](https://qiita.com/yuuuusuke1997/items/122ca7597c909e73aad5)
キーワード

- 嵐
- 自然言語処理
- WordCloud

最近、公式SNSを解禁して話題の国民的アイドル「嵐」。結成からこれまで20年間でファンに何を伝えたかったのか？という筆者の疑問について歌詞データを分析することにより明らかにします。歌詞データ収集、形態素解析による歌詞の単語化、WordCloudによる利用頻度の高い単語の可視化までの方法を流れで学ぶことができます。筆者が参考にしている記事として、「米津玄師」の歌詞を可視化したものもありますね。（[米津玄師の歌詞をWordCloudで可視化してみた。 - Qiita](https://qiita.com/Senple/items/1ad08b1a7ac9560bef62)）

### [ポケモンデータ解析.py - Qiita](https://qiita.com/maskot1977/items/2680927b58cdc4fad8d4)

キーワード

- ポケモン
- データ分析
- Kaggle

近日、シリーズ最新作である[「ポケットモンスター ソード・シールド」](https://www.pokemon.co.jp/ex/sword_shield/)も発売した国民的ゲーム「ポケットモンスター（以下、ポケモン）」。この記事では、そんなポケモンのタイプや種族値などのデータを対象として、データ分析や機械学習を試行しています。基本的な流れをプログラムも添えてかなり大きいボリュームで紹介しています。ポケモンといった題材のチョイスもあってか、親しみやすく読み進めやすい内容です。また、トレーディングカードゲーム[「遊戯王」](https://www.yugioh-card.com/japan/)を対象とした記事もありますね。（[遊戯王データセット解析 - Qiita](https://qiita.com/toyotomihideyoshi/items/30cad2e6fe7fd40cf81a)）

### [TensorFlowでポケモンの名前から種族値とタイプを予測させる遊び-Qiita](https://qiita.com/shuhei_f/items/01a08bf23ba24076ac08)

キーワード

- ポケモン
- 機械学習
- TensorFlow

既存ポケモンの名前と種族値やタイプを学習し、名前を入力することで種族値やタイプを予測するモデルを生成します。Googleが開発した機械学習のライブラリである[TensorFlow](https://www.tensorflow.org/)が利用されます。個人的にはサンプルとして存在しているポケモン“テンソルフロー”に興味があります。

### [ポケモンの外見的特徴から種族値を勾配ブースティングで予測する - Qiita](https://qiita.com/hiyoko9t/items/2e397301f17acff88a1a)

キーワード

- ポケモン
- 機械学習
- 画像処理
- 勾配ブースティング

[上記の記事](https://qiita.com/shuhei_f/items/01a08bf23ba24076ac08)に対して、こちらは既存ポケモンの外見を学習して、種族値を予測します。途中、デジモンなどポケモンにおける種族値が存在しない画像から種族値を算出していたり、興味深い内容です。
上記の記事と組み合わせることで、オリジナルのポケモンの名前と外見が決まった場合に自動的に種族値やタイプを算出することができますね。個人的には名前から種族値を予測するモデルと、外見から種族値を予測するモデルをアンサンブル学習させても面白いかなと思いました。

### [人工知能でバレンタインチョコが本命か義理かを判別する - Qiita](https://qiita.com/hiyoko9t/items/089c3c828b2d3b04f756)

キーワード

- バレンタインチョコ
- 機械学習
- 画像処理
- 畳み込みニューラルネットワーク

2月14日といえばバレンタインデー。 日本では、女性から男性へチョコレートを贈る日です。一方、男性にとって重要な課題として、本命チョコと義理チョコが判別できないという点が挙げられます。筆者はこのような社会的な問題に取り組みます。個人的にこの記事の興味深い点として、学術研究、論文のような流れ、表現がなされていることです。例えば、既存手法の問題点を挙げ、その解決として手法を提案している部分などです。大学生、大学院生で学術研究、論文の執筆に取り組む方にはそのような点も役に立つところがあるかもしれません。

# おわりに

本記事では、機械学習、データ分析、データ可視化、自然言語処理などデータ活用する分野において、“ポップ”なデータを活用した事例が紹介されているウェブサイトやブログの記事などを紹介しました。本記事、および紹介した各記事を読むことによって、抵抗があるかもしれない機械学習、データ分析、データ可視化、自然言語処理の理解に役立てると幸いです。

もし、他にもオススメのウェブサイトやブログの記事などがありましたら、コメントなどをいただければ幸いです。

個人的にはこの記事を充実させるともにオリジナリティのあるポップなデータ活用に繋げられたらなあと思っております。:triumph:
Golang - Custom Zap Log

```golang

	w := zapcore.AddSync(&lumberjack.Logger{
		Filename:   "app.log",
		MaxSize:    1, // megabytes
		MaxBackups: 30,
		MaxAge:     30, // days
	})

	c := zapcore.EncoderConfig{
		MessageKey:     "msg",
		LevelKey:       "level",
		TimeKey:        "time",
		NameKey:        "logger",
		CallerKey:      "file",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
		EncodeName:     zapcore.FullNameEncoder,
	}

	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(c),
		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), w),
		zap.InfoLevel,
	)

	logger := zap.New(core, zap.AddCaller(), zap.Development())
	
	logger.Sugar()

```

https://marcoma.xyz/2019/03/17/gin-tutorial-7/

https://github.com/sandipb/zap-examples/tree/master/src/customlogger

https://github.com/uber-go/zap/blob/master/example_test.go

https://blog.sandipb.net/2018/05/02/using-zap-simple-use-cases/
list.split("文字")みたいなことをやりたい場合

#　はじめに
pythonのsplit()関数はよく使うが、文字列にしか使えない。
listの時も使いたいと思って調べたが、意外と見つからない。
したがって備忘録がてらコードを書いた。


# やりたいこと
文字列に対して行うsplit()をlistに対してもやりたい。
文字列に対してのsplit()の例は

```
s = "1032"
s.split("0")
# ['1', '32']
```

具体的には

```
a = ["1","0","3","2"]
#これはエラー
#a.split("0")
#[["1"],["3","2"]]
```

みたいなことがしたい。

# コード

``` list_split.py
def list_split(L,moji):

    return_L,tmp = [],[]
    for val in L:
        if val != moji:
            tmp.append(val)
        elif val == moji:
            return_L.append(tmp)
            tmp = []

    return_L.append(tmp)

    return return_L

"""
#this is sample code
if __name__=="__main__":
    a = ["1","0","3","2"]
    print(list_split(a,"0"))
    #[['1'], ['3', '2']]
"""

```

# その他注意事項
最初にlistの要素を結合し文字列にしてからsplit()すれば良いのでは？と思ったが、これはバグる可能性がある。
具体例としては以下のようなケースが挙げられる。

```
a = ["1","0","3","10","2"]
s = "".join(a)
#'103102'
s.split("0")
#['1', '31', '2'] ←間違い
#['1', '3102'] ←意図した出力
```
vivadoでカスタムIPコアを使って回路をつくる

「PYNQで遊ぶシリーズ 第６回 [カスタムIPを作ってPYNQ overlayに組み込む](2019-08-22_FPGA_PYNQ_zynq_ece9f0cc0340763dde61.md)」は、AXIインターフェースをもつ周辺回路のカスタムIPで作って、ZYNQのブロックデザインを作る話をでした。今回は、AXI周辺回路でない一般の回路のIPコアをつくる話です。

今回のvivadoは2018.2です。バージョンによってはバグがとれているかも。

##想定する回路の作りかた
 * 部品を作って、ブロックデザインでつないで回路を組み立てていく
 * 部品はIPコア。ありものがない部品はカスタムIPを作る。
 * カスタムIPはプロジェクトにIP_XXXXのフォルダを作ってそこにおく

### プロジェクトを用意する
1. プロジェクトを作る(略)
2. 開発対象とするFPGAまたはボード情報を選択
<br>(PYNQ-Z1の場合)xc7z020clg400-1を選択、DIGLENT [PYNQ-Z1](https://reference.digilentinc.com/reference/programmable-logic/pynq-z1/start) のDesign ResourceからMaster XDCとZynq Presetsをダウンロードし、あとからボード資源情報をセットする。
<br>(KC-705の場合)(略)

### IP Integratorを用いてブロックデザインを作成する。
略

### カスタムIPコアを既存モジュールから作る方法
1)プロジェクトにカスタムIPコアごとにフォルダ(例えばIP_FOO)を作成し、そのフォルダにsrc/?hdl/やdoc/などのサブフォルダを作成する
2) このサブフォルダにソースやドキュメントを保存する
3) [Tools] メニューから [Create and Package New IP] をクリックするとウイザードがでてくる
4) [Package a new IP for the Vivado IP Catalog]を選択
5) [Packaging as a library core] はチェックしない。<br>なお、チェックするとIP をスタンドアロン IP としては使用できなくなる。「IP リポジトリから IP を参照できるが、IP カタログには表示されない。」とのことだが、それではどうやって使うのかわからん。
5) もろもろソースをチェック

###ブロックデザインからIPコアを作成する方法
ブロックデザインをまるごとIPコアにする。

ただし、この方法はIP Packgerの機能制限により、一旦作ったコアのデバッグがとっても面倒なので、あまりオススメできない。具体的には、後述するようにEdit IP in IP packagerでコアのデバッグができないので、デザインを作ったプロジェクトを保存しておき、それを修正してから毎回最初からIPコアを作り直す作業をすることになる。

## TIPS
###wizardで作ったGTXをカスタムIPに埋め込みたい
src/vhd/の下にwizardで作ったIPのソースをそのままコピーする
### 他のIPコアを含めたい
1) ソースに含めたいIPコアを追加する(IP catalogから追加する or Add Source([+]アイコン)で、既存コアのxciファイルを追加）
※　core container形式(xcixファイル)は対応しない。xcix形式になっている場合は、右クリックしてdisable core containerで分解してxciをとりだす
2) [package IP]タブの[pakaging step]の[File group]を選択し、Synthesisを右クリックし[add files]を選び、含めたいxciを追加する
3) Synthesisのファイル一覧からxciファイルをドラッグして先頭に移動する。
4) xciファイルを右クリックすると現れる[IP File Properties]のName プロパティを絶対パスから、現在のIP packagerのフォルダからの相対パスになるように変更する


##IP Packagerの機能制限やバグ
### デフォルトではリセットの極性が負論理
RSTポートは自動的に負極性に設定されるので、指定しなおす必要がある

1) reset interfaceを右クリックして、Edit Interfaceを選択
2) ParameterにPOLARITYを追加
3) POLARITYにACTIVE_HIGHをセットする
　https://forums.xilinx.com/t5/Design-Entry/Packaged-IP-showing-wrong-reset-polarity/td-p/797472


### portは natural,integerに非対応(2018.2)
naturalはパッケージ作成時にエラーになり、integerはバス幅が31bitになる。このためstd_logic_vectorに変換すること。
 (追加情報)std_logicとstd_logic_vectorにしか対応していないようだ。

### ブロックデザインからIPコアを作成すると、Edit IP in IP packagerでブロックデザインが使えない。
https://forums.xilinx.com/t5/Design-Entry/Packaging-custom-IP-with-block-designs/td-p/558247


##履歴
2019.11.19 新規作成
2019.11.26 更新
Expo watchmanではまった

# 🐈環境🐈
MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
macOS Catalina
バージョン 10.15.1
node, yarn, npm はインストール済

# ハマった時🐈
```
 expo start
```
expo start して`localhost`もたったけど, `Simulator`がちゃんと動いていない。
brew で install した
**watchman**
という奴に問題があったnyann🐈🐈

# エラー表示
`expo start`した時に以下のようなものがコンソール上に...

```
2019-11-18T23:03:40,788: [cli] Failed to open 
/Users/username/Library/LaunchAgents
/com.github.facebook.watchman.plist for write: Permission denied

Watchman:  watchman --no-pretty get-sockname returned with exit
code=null, signal=SIGABRT, stderr= 2019-11-18T23:03:40,788: 
[cli] Failed to open /Users/username/Library/LaunchAgents
/com.github.facebook.watchman.plist for write: Permission denied
```

# 原因： 権限がない
上のエラーの`Permission denied`という所ですね。

# 解決方法
```
username$ sudo chown -R username:staff  ~/Library/LaunchAgents
```
`sudo chown -R whoami:staff ディレクトリ名`でそのディレクトリに権限が付与できます。
`~/`というのをつけておくことで, macで言えば, ターミナル開いた時の最初にいる所にいく事ができるので, そこから`Library/LaunchAgents`を参照しているといった感じです。

`sudo`をつけないと変更権限がないと言われるのでつけましょう。`sudo`つけると自分のmacのパスワード聞かれます。mac開く時のアレです。

`chown`の所は参考にしたURLのせておきます。
https://eng-entrance.com/linux-command-chown#-R--recursive

`username:staff`の所は, `username`だけでなく`:staff`というのもつけておきましょう。
以下のようにすると, そのディレクトリの権限を持っている人がみれますが,
僕の場合はエラーが起きている時は

```
username$ ls -l ~/Library/LaunchAgents
-rw-r--r--  1 root  wheel  1861 11 18 23:24 com.github.facebook.watchman.plist
-rw-r--r--  1 root  wheel   390  5 14  2019 com.microsoft.OneDriveMigrationLauncher.plist
-rw-r--r--@ 1 root  wheel   677  3  3  2019 org.virtualbox.vboxwebsrv.plist

```
**wheel**という役割の**root**という人がそこのディレクトリの権限をもっていました。
なので, この役割と人両方を変更する必要がありました。
**wheel**とか**staff**の話は他の記事でも見てくだちい。

# 🐈終わりに🐈
この記事では`username`というのを使いましたが, 他のサイトとかでは`whoami`がよく使われてますね。僕みたいなLinuxに詳しく無い人だと`whoami`って何？とかなりそうだったので(俺が実際なったんだけどね笑), `username`にしときました。
なのでそこらへん詳しい人は`username`に違和感あったと思うけど(まぁそんな人はこんな記事を見にこないでしょうが)許して笑

あとスタバでエラー理由を暫く探してたんですけど, ちゃんとコンソールとかにあるエラー理由を見るべきでした。とりあえずエラーをコピってググってたんですけど, 蛇足でした。そんな記事あまりなかった。ですね。あるのはあったので下に載せときます。
https://www.code-adviser.com/detail_34245678

うん, とりあえずネコが好き。これ読んでくれたそこの綺麗なお姉さん,僕の事,ネコカフェにでも誘って下さいな。🐈🐈
Golang - How to Get Local Mac and IP Address?

```golang
	//----------------------
	// Get the local machine IP address
	// https://www.socketloop.com/tutorials/golang-get-local-ip-and-mac-address
	//----------------------

	addrs, err := net.InterfaceAddrs()

	if err != nil {
		fmt.Println(err)
	}

	var currentIP, currentNetworkHardwareName string

	for _, address := range addrs {

		// check the address type and if it is not a loopback the display it
		// = GET LOCAL IP ADDRESS
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				fmt.Println("Current IP address : ", ipnet.IP.String())
				currentIP = ipnet.IP.String()
			}
		}
	}

	fmt.Println("------------------------------")
	fmt.Println("We want the interface name that has the current IP address")
	fmt.Println("MUST NOT be binded to 127.0.0.1 ")
	fmt.Println("------------------------------")

	// get all the system's or local machine's network interfaces

	interfaces, _ := net.Interfaces()
	for _, interf := range interfaces {

		if addrs, err := interf.Addrs(); err == nil {
			for index, addr := range addrs {
				fmt.Println("[", index, "]", interf.Name, ">", addr)

				// only interested in the name with current IP address
				if strings.Contains(addr.String(), currentIP) {
					fmt.Println("Use name : ", interf.Name)
					currentNetworkHardwareName = interf.Name
				}
			}
		}
	}

	fmt.Println("------------------------------")

	// extract the hardware information base on the interface name
	// capture above
	netInterface, err := net.InterfaceByName(currentNetworkHardwareName)

	if err != nil {
		fmt.Println(err)
	}

	name := netInterface.Name
	macAddress := netInterface.HardwareAddr

	fmt.Println("Hardware name : ", name)
	fmt.Println("MAC address : ", macAddress)

	// verify if the MAC address can be parsed properly
	hwAddr, err := net.ParseMAC(macAddress.String())

	if err != nil {
		fmt.Println("No able to parse MAC address : ", err)
		os.Exit(-1)
	}

	fmt.Printf("Physical hardware address : %s \n", hwAddr.String())
```

https://www.socketloop.com/tutorials/golang-get-local-ip-and-mac-address
データベース設計その２　テーブルの構成要素

次はエンティティことテーブルについて
内容を書いて行きます。

# テーブルの構成要素

## エンティティ
エンティティとは現実世界の概念をデータベースで扱うデータとした場合の呼び名です。
つまり、「エンティティ = テーブル」と考えてほとんど差し支えありません。

## テーブルの行と列

* テーブルの行（レコード）はエンティティの具体的なデータを表す
* テーブルの列（カラム）はエンティティの属性を表す

### テーブルの行（レコード）

レコードとはエンティティの具体的なデータです。
いわばインスタンスのことで

田中太郎、20歳,男

といった内容のこと

### テーブルの列（カラム）

カラムとはエンティティの属性です。
上の行に合わせて書くと

名前、年齢、性別

といった内容になります、

# データを識別するための特殊な属性値

## キー
   テーブルにおけるキーとはレコードを識別するための特別なカラムのことを指します。

   キーには以下の2種類があります。

* 主キー
* 外部キー

### 主キー
主キーは、テーブルの中で他のレコードとの区別をつける識別子となるカラムです。
例えば、ユーザーテーブルのidカラムが主キーになります。

| id | name | email |
|:-:|:-:|:-:|
| 1 | 山田太郎 | taro@ex.com |
| 2 | 他中次郎 | jiro@ex.com |

### 外部キー

外部キーは関連する他のテーブルのレコードの主キーを値として持つカラムです。
例えば、製品テーブルのuser_idカラムが外部キーになります。

| id | price | user_id |
|:-:|:-:|:-:|
| 1 | 70 | 2 |
| 2 | 90 | 1 |

# 制約

制約とは特定のデータの保存を許さないためのバリデーションです。
同じメールアドレスのユーザーを登録できないようにする
名前のデータが空のユーザーを保存できないようにするといったことができるようになります。

## 制約の種類

* NOT NULL制約・・・空値禁止
* 一意性制約・・・内容重複禁止
* 主キー制約
* 外部キー制約

### NOT NULL制約
NOT NULL制約はテーブルの属性値にNULL（空の値）が入ることを許さない制約です。
Railsでは、マイグレーションファイルでカラムを追加するときに
null: falseと記述することでNOT NULL制約を設定することができます。

```ruby:NOTNULL制約
null: false
```
```ruby:マイグレーションファイル
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name, null: false
      t.timestamps null: false
    end
  end
end

```


### 一意性制約
一意性制約はテーブル内で重複するデータを禁止する制約です。
Railsでは、カラムに対してadd_indexメソッドを用いることで一意性制約を付けることができます。

```ruby:一意性制約
add_index :テーブル名, :カラム名, unique: true
```

```ruby
class AddEmailToUsers < ActiveRecord::Migration
  def change
    add_column :users, :email, :string # カラムの追加
    add_index :users, :email, unique: true # 上記に一意性の追加
  end
end
```

### 主キー制約
主キーに対してNOT NULL制約と一意性制約を両方設定されること
Railsでは主キーはidカラムとして自動で作成されます。

### 外部キー制約
外部キー制約は、外部キーの対応するレコードが必ず存在しなくてはいけないという制約です。
外部キーのカラムに値があっても、その値を主キーとして持つ他のテーブルのレコードがなければいけません。

要は関係のあるテーブルを必ず設定させる制約です。
foreign_key: trueで設定します。

```ruby:外部キー制約
foreign_key: true
```
```ruby:マイグレーションファイル例
class CreateScores < ActiveRecord::Migration
  def change
    create_table :prices do |t|
      t.string :name
      t.integer :price
      t.references :user, foreign_key: true
      t.timestamps null: false
    end
  end
end
```
# インデックス
インデックスとはテーブル内のデータの検索を高速にするための仕組みです。
インデックスはカラムに対して設定します。
なおインデックスを設定することを、「インデックスを貼る」と言います

欠点として

* データを保存・更新する速度が遅くなる
* データベースの容量を使う
があります。

では実際の使用例を

```ruby:マイグレーションファイル
class AddIndexToテーブル名 < ActiveRecord::Migration
  def change
    add_index :テーブル名, :カラム名
  end
end
```
複数のカラムの場合は[]で設定して[,]で区切ります。

```ruby:マイグレーションファイル
class AddIndexToテーブル名 < ActiveRecord::Migration
  def change
    add_index :テーブル名, [:カラム名, :カラム名]
  end
end
```
MongoDBで効率的なクエリを調べるための実験方法

# はじめに

DBで大量データを扱う場合、以下のような調査／検討が必要になることがあります。
本記事では、こういった内容を調査／検討するための **「実験方法」** を記載します。

* どっちのクエリの方が効率的？
* インデックスはどう貼るのがよい？
* どっちデータ構造の方が検索しやすい？

具体的には、簡単に大量データを投入する方法　および　検索処理の詳細確認方法　を記載します。
検索処理の詳細を確認することで、より効率的なクエリを探っていきましょう(๑•̀ㅂ•́)و✧


# 基本操作

### ＜起動処理と終了処理＞

#### mongoDBの起動

```
$ brew services start mongodb
```

#### mongoDBの起動確認

```
$ brew services list
```

#### mongoDBの終了

```
$ brew services stop mongodb
```

#### コンソールの起動

```
$ mongo
```

#### コンソールの終了

```
> exit
```

### ＜DB操作＞

#### DB一覧の表示

```
> show dbs
```

#### 使用DBの指定
※存在しないDBを指定した場合、自動的にDBが作成される（実際に作成されるのはcollection作成時）

```
> use mydb
```

#### DBの削除

```
> db.dropDatabase()
```

#### 今使っているDB情報の表示

```
> db.stats()
```

### ＜collection操作＞

#### collectionの作成

```
> db.createCollection("collection_name")
```

#### collection一覧の表示

```
> show collections
```

#### collectionの削除

```
> db.collection_name.drop();
```

# 実験方法

### ＜データ投入＞

#### collectionへのdocument挿入

```
> db.collection_name.insert( {_id: "000", name: "hoge"} )
```

#### collectionへの "大量" document挿入

```
> db.collection_name.insert( [ {_id: "001", name: "hoge1"}, {_id: "002", name: "hoge2"}, {_id: "003", name: "hoge3"} ] )
```

### ＜検索＞

####リファレンス

https://docs.mongodb.com/manual/reference/method/db.collection.find/index.html

#### documentの検索

```
> db.collection_name.find( { 条件 } )
```
例）db.collection_name.find( { "_id" : "001" } )

### ＜検索結果の分析＞

####リファレンス

https://docs.mongodb.com/manual/reference/explain-results/#explain-results

#### 検索時に参照したdocument数

```
> db.collection_name.find( { 条件 } ).explain("executionStats")
```
→ 上記実行結果で表示される **「totalDocsExamined」** が参照document数
　この値が小さい方が効率的と言える

例）db.collection_name.find( { "_id" : "001" } ).explain("executionStats")

#### 検索時にインデックスが効いているかどうか

```
> db.collection_name.find( { 条件 } ).explain("executionStats")
```
→ 上記実行結果で **「IXSCAN」** が表示されている場合、インデックスが効いている
VBScriptの関数呼び出しの罠

以下の関数を呼び出しを行っているコードは、動きそうな気がしますが、実はエラーになります。

```vb
Sub2(hoge, fuga)
```

一方で、以下のコードは正常に動きます。

```vb
res = Func1(hoge)
res = Func2(hoge, fuga)
Sub1(hoge)
```

これらのコードはほぼ違いがないですが、なぜ片方はエラーになってしまうのでしょうか？

実はこの仕様は色々と複雑なので、順を追って説明したいと思います。

# 括弧の意味
まず、VBScriptの括弧にはいくつかの意味がありますので、それらを説明します。

1. 演算子の優先順位を変更
2. 配列の要素の参照
3. 関数(FunctionやSub)の呼び出し
4. 関数のシグネチャでByRefになっている引数に値渡しをする

```vb
' 1
avg = (a + b) / 2.0

' 2
res = arr(5)

' 3
length = Len("hogehoge")

' 4
Function Func(a ByRef, b ByRef)
  ' なんかしらの処理
End Function
' hogeは参照渡し、fugaは値渡し
Func2(hoge, (fuga))
```

# 関数呼び出しのときのルール
さらに、関数呼び出しのときもいくつかのルールがあります。

1. 戻り値を変数に代入する時は引数を()で囲む必要がある
2. 戻り値を変数に代入せずCallキーワードを使っている時は、引数を()で囲む必要がある
3. 上記の1, 2以外の時には引数を()で囲ってはいけない

```vb
' 1
res = Func1(hoge) ' OK
res = Func1 hoge  ' NG

' 2
Call Sub1(hoge) ' OK
Call Sub1 hoge  ' NG
```

最後に、参照渡しに関するルールです。
参照渡しが可能なケースでは、変数は参照渡しが行われますが、引数が余分な括弧で囲まれている場合は値渡しが行われます。

```vb
' hogeは参照渡し、fugaは値渡し
Func2(hoge, (fuga))
```

# 冒頭のコードの解説

さて、これらのルールを考えることで、冒頭のコードのうち、片方がエラーになり、もう片方が正常に実行できる理由が説明できます。

まずは、以下のコードがエラーになる理由を説明します。
(1)のコードは関数呼び出しのルールに明らかに抵触しているためにエラーになります。
このコードは戻り値を引数に代入していませんし、また、Callキーワードを使っているわけでもありません。

```vb
Sub2(hoge, fuga) ' (1)
```

次に以下の(2)〜(4)の3つが正常に実行できる理由を説明します。
(2)と(3)は関数の戻り値を変数に代入しているために、()で囲っても問題ありませんし、また、()をなくすとエラーになります。
さて、では(4)はどうでしょうか？
一見すると、(1)と同じ理由でエラーになりそうですが、ここで参照渡しに関するルールが適用されるためにエラーになりません。
(4)でhogeを囲っている()は関数呼び出しのための()ではなく、参照渡しを値渡しに変換するための()です。
そして関数呼び出しのための()は省略されています。
そのため、(4)の関数呼び出しはエラーになりません。

```vb
res = Func2(hoge, fuga) ' (2)
res = Func1(hoge)       ' (3)
Sub1(hoge)              ' (4)
```

しかし、これは意図せずに値渡しになってしまっている危険性もあるコードなので、(5)のように書くことによって値渡しにしていることを明示的にしたほうが良いです。

```vb
Call Sub1((hoge))       ' (5)
```


# まとめ
これらのことをまとめると、以下のことがわかります。
以下のコードで、refは参照渡し、valは値渡しで渡される引数です。

```vb
Func1 ref
Call Func1(ref)
result = Func1(ref)
Func2 ref, ref
Call Func2(ref, ref)
result = Func2(ref, ref)

Func1(val)
Call Func1((val))
result = Func1((val))
Func2 (val), ref
Func2 ((val)), ref
Call Func2((val), ref)
result = Func2((val), ref)
```

そして、以下のコードはエラーになります

```vb
Call Func1 hoge
Z = Func1 hoge
Func2(hoge, fuga)
Call Func2 hoge, fuga
Z = Func2 hoge, fuga
```

# 参考
公式ドキュメントのCallステートメントに関する部分にも同様のことが書いてありますが、具体例がなく、分かったような分からないような気がしていたので、自分でまとめてみました。

[Call ステートメント](https://docs.microsoft.com/ja-jp/previous-versions/windows/scripting/cc392440(v=msdn.10))

> プロシージャを呼び出すとき、キーワード Call は省略できます。キーワード Call を使って引数を必要とするプロシージャを呼び出す場合は、引数リスト argumentlist をかっこで囲む必要があります。キーワード Call を省略するときは、引数リスト argumentlist を囲むかっこも省略する必要があります。Call ステートメントの構文で組み込み関数またはユーザー定義型関数を呼び出す場合、その関数の戻り値を取得することはできません。
【G検定合格者】試験当日に手元に準備したもの＋試験時の振る舞い

## はじめに

2019年第３回試験にて合格しました。
<img width="699" alt="jdla-g-19-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181972/b9eba7cb-7030-5137-1907-f12b768ca8c1.png">

では、本文に入ります。

## 必要なもの

- [G検定公式テキスト ※紙媒体推奨](https://www.amazon.co.jp/dp/4798157554/)
- [徹底攻略G検定問題集（通称：黒本） ※紙媒体推奨](https://www.amazon.co.jp/dp/B07NDVCN99)
- 受検用PC
- 検索用PC

## 準備１ 書籍のポイント箇所に付箋を貼る

- 公式テキストと黒本の回答ページのうち、表にまとめられた情報に付箋をはります
- こういった場所は下記の条件を満たしており、試験時に確認する情報として適しています
    - 「暗記したくない」
    - 「見ればすぐに必要な情報がわかる」

## 準備２　書籍のポイント箇所を自分の言葉でまとめる

- 基本的には<font color=red>**情報を思い出す為のインデックスをつける**</font>というスタンスです
- 受検時は時間がありません、Qiitaなどに綺麗にまとめられた記事を読む暇はありません
- <font color=red>**自分の記憶を手助けするようなキーワード**</font>をテキストにまとめておくことが大事です
- 参考までに筆者のメモを載せます（実に雑な感じですね。でも思い出せればいいんです。）

<img width="462" alt="01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181972/f7e20689-f60d-9161-c473-6581831e3d44.png">

<img width="839" alt="02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181972/92714cb2-64fa-994c-63d0-bf74a16f302f.png">

## 準備３　テキストや黒本に載っていない内容のまとめサイトを開いておく＠検索用PC

- 主に下記の内容のサイトを開いておきます
    - テキストに記載されていない<font color=red>DeepLearningに関する新しい情報</font>（最近話題のネットワーク名やその特徴など）をまとめたサイト
    - 覚えにくいものを<font color=red>上手く図解している</font>サイト

## 準備４　Google検索窓を開く＠検索用PC

- ググる準備

## 試験時の振る舞い

下記のような思考パターンで動きました

### 1. 問題を解く（初見）

|問題の分類|リアクション|チェック|
|:--|:-:|:-:|
|普通に分かる|即回答|<font color=blue>しない</font>|
|付箋貼った箇所みれば分かりそう|調べて回答|<font color=blue>しない</font>|
|予め開いたサイトか自分のメモを見れば分かりそう|調べて回答|<font color=blue>しない</font>|
|ググったら分かりそう（人名、キーワードのみ）|調べて回答|<font color=red>自信がなければする</font>|
|ググったら分かりそう（文章の整合性を問う問題、時間かかる）|直感で回答|<font color=red>する</font>|
|分からない|適当に回答|<font color=blue>しない</font>|

**※G検定の試験では問題にチェックをつける＋全問を一覧で表示する機能がついています（チェックも表示される）**

こうすることで、全問回答後に、<br>

- 「調べたらほぼ確実に答えが分かる」
- 「調べるのに時間を要さない」
- 「検索ワードがだいたい想像できる」

という問題しか残らないので、問題の正答率を上げるために、残りの時間を有効に使うことができるはずです。

結果として、私は全問解いた時点で25分ほど余り、チェックをつけた問題を13問程度調べて回答しました。

### 2. チェックをつけた問題を解く

残り時間は、チェックをつけた問題の中でも特に、調べるのに時間がかからないものを優先的に掃除していきました。また、隣接している問題は一つの内容を調べれば同時に答えが決まるような仕様になっていたりするので、「１回ググる→二問同時に埋める」みたいなことを結構やりました
【備忘録】形態素解析からのWordCloud

pythonファイルに入れていた文章を別ファイルへ移行

```textmining_source.txt
scaffoldとは？
Railsの開発に必要なルーティング、コントローラ、ビューの作成に加え、基本的なアクションの設定なども自動ですべてやってくれる便利ツールのこと

【個人的に感じたscaffoldの良さ】
①コントローラの作成だけでなく、7つの基本アクションも自動で設定してくれる
scaffoldで作成されたコントローラには、「index」「show」「new」「edit」「create」「update」「destroy」の7つのアクションが自動で定義されています。そのため、自分でアクションを設定しなくても、すぐにデータの参照や新規作成、変更、削除を行うことができます。

②作成されたコントローラに対応するルーティングも自動で設定してくれる
scaffoldコマンド後のroutes.rbには、「resources :コントローラ名」という記述が追加されており、新たに作成されたコントローラに対応するルーティングが自動で設定されています。

③コントローラで定義されたアクションに対応するビューも全て自動生成してくれる
scaffoldを使用した場合、コントローラで定義されたアクションに対応するビューファイルも全て自動で生成されます。

④必要なモデルおよびマイグレーションファイルも自動生成してくれる
scaffoldでは、コマンド入力時に「カラム名：データ型」を指定すると、指定された情報を含むモデルおよびマイグレーションファイルを自動生成してくれます。
そのため、あとは「$ rake db:migrate」コマンドを入力するだけで、データベースのテーブルも簡単に作成できます。（この辺りの詳細は後ほど）

→もちろん、scaffoldを使って世の中に出すアプリケーションをつくるのはちょっと違う（というより逆に無駄が多い）と思いますが、個人的には興味のある機能を試しに実装するための試作品をつくる上ではめちゃめちゃ便利だなと感じています。

ということで、以下scaffoldを使用したRailsアプリケーションの作成手順について記載します。
本当に簡単なので、もしよかったら実際に使ってみて下さい！
```

そして、いよいよWordCloudを使った可視化

```py
with open('textmining_source.txt') as f:
    text = f.read()

keywords = t.parse(text)

words = []
for x in keywords.split("\n"):
    word = x.split("\t")[0]
    if word == "EOS":
        break
    else:
        category = x.split("\t")[1].split(",")[0]
        if category == "名詞":
                words.append(word)
        else:
            category = x.split("\t")[1].split(",")[0]
            if category == "形容詞":
                words.append(word)

splitted =' '. join(words)
keywords = splitted.replace(',',' ')
 
wordcloud = WordCloud(
    background_color="white",
    stopwords={"もの","これ","ため","それ","ところ","よう","の","たち","こと"},
    font_path="NotoSansCJKjp-hinted/NotoSansCJKjp-Regular.otf",
    width=800,height=600).generate(keywords)
 
 
wordcloud.to_file("./textmining_result.png")
```

＜出力結果＞WordCloud
<img width="791" alt="スクリーンショット 2019-11-19 0.01.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508644/89fae50f-d027-01c0-40ef-ae6d022b86d5.png">

ちなみに、以下はスティーブジョブズの有名なスピーチをWordCloudで可視化したものです。
パッと見ただけでなんとなく話の全体感がつかめそうですね！
※スピーチ内容の参考元：https://kigyotv.jp/news/special16/
１つ目の話
<img width="796" alt="スクリーンショット 2019-11-19 0.37.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508644/05cda19a-ed11-004a-3f6a-ffbf7fa8e4fb.png">

2つ目の話
<img width="792" alt="スクリーンショット 2019-11-19 0.36.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508644/75b7c1fe-6e67-e3bb-0171-e1d8c901853f.png">

3つ目の話
<img width="794" alt="スクリーンショット 2019-11-19 0.34.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508644/e4269df8-fe5b-ca5d-aaf6-7c8340f53639.png">
デフォルト引数の一部にだけ値を渡したい場合

JavaScriptではデフォルトの引数を指定できる。(ES2015~)
### デフォルト引数を指定した引数の一部にだけ値を渡したい場合
デフォルトにしたい値には、値を渡さない　or undefinedを渡せばOK。
（そもそもJavaScriptでは、関数の引数は指定しなければundefinedが渡されている。）

```javascript

function multiply(a　= 2, b = 1) {
  return a * b;
}

console.log(multiply(5, 2));
// expected output: 10

console.log(multiply(5));
// expected output: 5

console.log(multiply(undefined, 5));
// expected output: 10
```
自分用

###jQuery
jQueryとは、JavaScriptのライブラリである。

jQueryには主に3つの機能がある。
 
- DOM
 

DOMとはDocument Object Modelの略でありHTMLを操作するための仕様。
通常HTMLファイルにあるドキュメントは簡易的に操作できないが、jQueryを使うことで簡易的な操作が可能。

 

- アニメーション
 

CSS3に対応していないブラウザでは利用することが出来ないが、jQueryはJavaScriptのライブラリであるため、古いブラウザでも対応することが可能。

 
 - Ajax
 
Ajaxとは外部ファイルを読み込む機能。

jQueryのメリット

- コードを短く書ける

jQueryのデメリット

- 読み込みが遅くなる場合がある

[jQueryのダウンロードサイト]
(https://jquery.com/download/)からダウンロードする。
<img width="1005" alt="スクリーンショット 2019-11-18 23.31.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519544/43ca4d37-87da-acd2-4b15-055857b37e8b.png">

```html:
<script src="js/jquery.min.js"></script>
headタグの中に記述する。
```

```html:
<script>
   $('#セレクター').メソッド('パラメーター');
</script>
```
//htmlやcssを書き換えることが出来る//

###メソッドチェーン
```html:
<script>
  $('#セレクター').html('パラメーター').css('パラメーター');
</script>
```
//セレクターが同じなら、.で繋げることが出来る。//
windows10のゲームモードを使えばデスクトップ動画がいきなり作れる件

# はじめに
Qiitaで記事を書く際に毎度毎度地道に画面キャプチャをしていたが「時代は令和なわけだしもっといい方法がないものか…」と思い、「デスクトップの作業を動画でとれば簡単でいいよね！」と考えて調べたらたどり着いた。

これが思いのほか簡単だったので記録に残す。
世の実況動画の皆さんはこれをしていたのかと今更気づくという衝撃の事実。。。

# 手順
1. ゲームモードの設定確認
2. ゲームモードの起動
3. 動画開始～終了
4. 作成動画の確認

#1. ゲームモードの設定確認
設定画面を開いて「ゲーム」をクリック
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/6f78aa1b-1675-3ebb-b6ee-1ba056f99de7.png)

するとゲームモードの設定確認画面が現れる。
ここで「ゲームバーを使って…」が”オン”担っていることを確認。
これでOK。

ここでキーボードショートカットを確認。
動画を撮りたいなら「記録の開始/停止」に書かれている「Win+Alt+R」であることがわかる。
ちなみにスクリーンショットであれば「Win+Alt+PrtScm」

![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/b4de3cf6-85ad-7c3a-d616-c94424d44592.png)

#3. 動画開始～終了
いざ実践。今日のYahoo!のニューストップまで移動する動画を撮る。
開始、終了ともに「Win+Alt+R」でイケる。

#4. 作成動画の確認
確認方法は２種類ある。
①プレビュー画面で見る
　Win+Gでゲームモード画面へ移動する。
　そこで現れる「キャプチャ」ウィンドウにある、「全キャプチャを表示」をクリックすると、今までにとった全キャプチャをプレビューの形で見ることができる。
※画面取りたかったけどうまく行かなったので言葉の説明のみ。。。

②保管場所へ移動して動画を確認する
デフォルトだと「ビデオ」フォルダに保管されている。
↓↓実際の画面がコチラ↓↓
![キャプチャ 2019_11_18 23_35_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/2e87f5d5-95e3-6397-951f-7e83fe369324.png)

具体的には自分のPCだと

```
C:\Users\watya\Videos\Captures
```
になる。

では、最終的に実際の動画を確認する。
こんな感じでとれる。ゲームモードではアクティブなウィンドウの動画が取れるっぽい。
すごい単純だけどその分やり方も簡単で適当でいいので
あっさりやりたい自分にはいい感じで相性がいい。

オマケ：mp4動画をgif動画に変換する
qiitaにUPするにはmp4はダメなのでgifにする必要がある。
このためだけにアプリを入れるのはちょっと…と思っていたら
オンラインやれる方法が見つかった。
　https://www.aconvert.com/jp/video/mp4-to-gif/

![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/22f6c749-e5c5-b012-9018-3afd945e7d99.png)

mp4ファイルを「ファイルを選択」へD&Dして、「今すぐ変換」クリックしたら
”変換結果”に動画が現れた。これで作業完了。
あとはこの動画をダウンロードすればOK。簡単だ。。。
一点気になったのは意外とサイズ大きい。ということ。

元のmp4ファイルが23秒で18MBに対して、gifファイルは32.1MB。
結局大きすぎてQiitaにUPすることは叶わなかった。残念。

# おわりに
動画をとるというアイデアまではよかったしとても簡単だったけど
これをどうやって保管するか？ってところで課題に感じた。

元々は自分の試したこと理解を記録するために用意したQiitaだし
やりたいことは自分のやってることの記録なわけだし、動画とるなら
YoutubeへUpして残すってのも考えてみたいところ。
クエリで Project Euler Problem 6

## 【お題】
[Problem 6](http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%206 "Problem 6 - PukiWiki")。
> Problem 6 「二乗和の差」 †
> 最初の10個の自然数について, その二乗の和は,
> 
```math
1^2 + 2^2 + ... + 10^2 = 385
```
> 最初の10個の自然数について, その和の二乗は,
> 
```math
(1 + 2 + ... + 10)^2 = 3025
```
> これらの数の差は 3025 - 385 = 2640 となる.
> 
> 同様にして, 最初の100個の自然数について二乗の和と和の二乗の差を求めよ.

## 【環境】
| SQLServer | SQLCMD |
| ---- | ---- |
| 2017 | 14.0.1000.169 |
設定はデフォルト。

## 【数学的に】

```SQL
DECLARE @Max    INT = 100;

PRINT POWER(@Max * (@Max + 1) / 2, 2) - @Max * (@Max + 1) * (2 * @Max + 1) / 6;
GO
25164150
```

## 【クエリ】
敢えてクエリで書けば以下。

```SQL
DECLARE @Max    INT = 100;

;WITH [CTE_Base]([Val]) AS (
    SELECT 1
    UNION ALL
    SELECT [Val] + 1 FROM [CTE_Base] WHERE [Val] < @Max
)
SELECT SUM([Val]) * SUM([Val]) - SUM([Val] * [Val]) FROM [CTE_Base]
OPTION (MAXRECURSION 0)
;
GO

-----------
   25164150

(1 行処理されました)
```
XcodeのUIテスト時にiOSシミュレータのステータスバーを変更する

## iOSシミュレータのステータスバーを変更する方法

Xcode11から `xcrun simctl` コマンドに `status_bar` 機能が追加され、iOS シミュレータのステータスバーの表示を変更できるようになりました。

(参考) [iOSシミュレーターのステータスバーを変更する](https://qiita.com/mishimay/items/6fb3054f12a3dbeedee9)

[fastlane](https://docs.fastlane.tools) の [snapshot](https://docs.fastlane.tools/actions/snapshot) でストア用のスクリーンショット撮影する際などに活躍しそうですね！

## ステータスバーを変更するタイミング

以下のようにして Test 開始前の Pre-actions で設定すると良さそうです。fastlane の snapshot も UI テストを使用するため、この設定で Snapshot が出力するスクリーンショット画像にも反映されます。

1. Edit Scheme... > Test > Pre-actions を選択
2. Run Script を追加
3. Provide build settings from の部分で UIテストのターゲットを選択
4. 図のようにステータスバーの変更のスクリプトを記述

<img width="886" alt="pre.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/46d2a8d6-5cd5-f328-fc87-d967df33a1cf.png">

```sh
xcrun simctl boot "${TARGET_DEVICE_IDENTIFIER}"

xcrun simctl status_bar "${TARGET_DEVICE_IDENTIFIER}" override \
  --time "2010-01-28T09:41:00+09:00" \
  --dataNetwork 4g \
  --wifiMode active \
  --wifiBars 3 \
  --cellularMode active \
  --cellularBars 4 \
  --batteryState discharging \
  --batteryLevel 100
```

同様にして Post-actions の方には設定を元に戻すようにしておく。

<img width="883" alt="post.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16508/7c9af4f5-781e-c0b2-f887-66ffdb944a86.png">

```sh
xcrun simctl boot "${TARGET_DEVICE_IDENTIFIER}"

xcrun simctl status_bar "${TARGET_DEVICE_IDENTIFIER}" clear
```

(参考) https://github.com/fastlane/fastlane/issues/15124

:point_right: fastlane の issue に機能リクエストがあがっているのでそのうち実装されるかも！？

:point_right: fastlane の [snapshot](https://docs.fastlane.tools/actions/snapshot/) 機能に `override_status_bar` というオプションで利用できるようになっていますね。
データベース設計その1

SQLを一通り基礎をまとめたので
次はデータベース設計に手を付けます。

# データベース設計
データベース設計は基本的には現実世界の要素をデータに落としこむ作業です。
要素とは例えばユーザーです。ユーザーをデータベースで管理するには

* 「ユーザーという概念（エンティティ）」
* 「個々のユーザーの持つ情報（属性）」
* 「ユーザーと他情報の関係性（リレーション）」

を決める必要があります。

# データベースを構成する要素

* サービスで扱う概念（エンティティ）
* エンティティの属性
* エンティティ同士の関係性（リレーション）

## エンティティ(テーブル)

エンティティとは、サービスの中で管理する必要のある概念(情報)を指します。
例えば、SNSなどのサービスでは「ユーザー」や「投稿内容」、「コメント」などの情報を管理する必要があります。
これらの情報がエンティティにあたります。

## エンティティの属性(テーブルのカラム内容)

属性とは、エンティティが個別に持つ情報です。ユーザーというエンティティでは
「名前」「アドレス」「パスワード」「プロフィール写真」が属性にあたります。

## リレーション(railsのアソシエーションに近い)

リレーションとは、エンティティとエンティティとの間に存在する関係性のことです。
例えば、料理には、その料理を作った人がいます。こういった場合料理と作った人の
2つのエンティティには関係性があります。

# データベース設計の手順

大雑把に説明すると
1,データベースで管理するデータ（エンティティ）を決める
2,それぞれのデータの持つ属性を決める
3,エンティティ同士の関係性を決める（リレーション）
4,データを実際にデータベースのテーブルとして定義する

## 1,データベースで管理するデータ（エンティティ）を決める
　　　必要なテーブルを考える形
　　　通販ならユーザーと製品のテーブルがまず必要
## 2,それぞれのデータの持つ属性を決める
　　　ユーザーなら・・・・名前、性別、年齢、資金など
　　　製品なら・・・製品名、価格、在庫状況など
　　　右側の項目内容を決めること。
## 3,エンティティ同士の関係性を決める（リレーション）
　　　　出品した、買った製品とはユーザーと繋がっていますので
　　　　その関係にリレーションを設定すします。
## 4,データを実際にデータベースのテーブルとして定義する
　　　　最後に１〜３の手順を元に実際にテーブルを作成することになります。
　　　　エンティティはテーブルに相当し、属性はテーブルが持つカラムに相当します。
【AWS EC2】`find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundler (Gem::GemNotFoundException)


#あなたのターミナルにはこのようなエラーが出ていますか？
```console
[ec2-user@ip-XXX-XX-XX-XXX xxxxxx]$ bundler -v
Traceback (most recent call last):
	2: from /home/ec2-user/.rbenv/versions/2.5.1/bin/bundler:23:in `<main>'
	1: from /home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:308:in `activate_bin_path'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundler (Gem::GemNotFoundException)
```

#入力するコマンド
```console
$ rbenv exec gem install bundler
$ bundle install
```
この順で実行すればOK

#参考記事
[エラーメッセージ] can't find gem bundler (>= 0.a) with executable bundler (Gem::GemNotFoundException)
https://qiita.com/MotohiroSiobara/items/c0d343a160cffc2902ef
Sudachi 同義語辞書をPandasで読み込んで同義語検索してみた

2019年11月11日、形態素解析器[Sudachi](https://github.com/WorksApplications/Sudachi#sudachi-%E6%97%A5%E6%9C%AC%E8%AA%9Ereadme)を開発しているWorksApplicationsから同義語辞書がリリースされました！

同義語辞書の用途は主に、文書検索やチャットボットで表記揺れを吸収するのに使われます。

今回はこの辞書の中身について、PythonのライブラリであるPandasを使って調べてみました。

# 環境
- Ubuntu (Windows 10 WSL)
- Python 3.7.3
- pandas 0.25.3

# Sudachi同義語辞書のダウンロード
```
$ wget https://raw.githubusercontent.com/WorksApplications/SudachiDict/develop/src/main/text/synonyms.txt
```

# 読み込み
[ドキュメント](https://github.com/WorksApplications/SudachiDict/blob/develop/docs/synonyms.md)を見るとcsv形式のようですね！ここからpythonスクリプトを書いていきます。

```python
import pandas as pd

df = pd.read_csv("synonyms.txt", skip_blank_lines=True,
                 names=('group_id', 'type', 'expand', 'vocab_id',         
                'relation', 'abbreviation', 'spelling', 'domain',  
                'surface', 'reserve1', 'reserve2'))
```

空行有りcsvなので`skip_blank_lines`を設定しておきます。`names`は適当です。

# 検索
とりあえず見出しが一致する全ての`df`を表示させる関数を作ってみます。

```python
def search_synonyms(word):
    for row in df[df.surface==word].itertuples():
        print(df[df.group_id==row.group_id].loc[:,['group_id', 'domain', 'surface']])
```

同義語はグループ番号(`group_id`)でまとめられているので、見出し(`surface`)が`word`と一致している行のグループ番号と同じ行をとってくれば大丈夫そうですね！

# 一例
例えば`search_synonyms('巨人')`を実行するとこのようになります！

```
      group_id    domain   surface
5662      3895  (スポーツ)     読売巨人軍
5663      3895  (スポーツ)        巨人
5664      3895  (スポーツ)        読売
5665      3895  (スポーツ)       巨人軍
5666      3895  (スポーツ)  読売ジャイアンツ
5667      3895  (スポーツ)    ジャイアンツ
5668      3895  (スポーツ)    Giants
       group_id domain surface
31690     16305  (人)      巨人
31691     16305  (人)  ジャイアント
31692     16305  (人)   giant
```

球団の「巨人」と一般名詞の「巨人」の様々な表記を取って来ることができました！

# まとめ
今回はSudachiの同義語辞書を覗いてみました。Sudachi本体もこの同義語辞書も今後どんどん更新されていくことでしょう。今後のアップデートから目が離せませんね！
OSSにちょっとだけ恩返しした話

ホントにちょっとだけ。

## `tsconfig.json`の`compilerOptions.paths`
TypeScriptでは`tsconfig.json`という設定ファイルで様々な設定ができますが、その中に`paths`という項目があります。
モジュールロード時のプロジェクト内ディレクトリマッピングを設定するものですが、詳しくは[ここらへん](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping)や[ここらへん](https://qiita.com/nju33/items/cf924f7b6bb513bef8a2)を参照してください。

## Jestで使う
[Jest](https://jestjs.io/ja/)はJavaScriptのテストプラットフォームですが、[ts-jest](https://github.com/kulshekhar/ts-jest)を利用してTypeScriptも使えます。

TypeScript + Jestを使った開発を行なっていたのですが、`paths`を使い始めた時にJestが`paths`を認識しなくて困ったことがありました。
Jestにも設定があり、`paths`に相当する`moduleNameMapper`という項目があるので、これを設定すればいいのですが、同じ設定を複数箇所に書くのは好ましくありません。
どうにかならないものか・・・と思っていたところ、同じことを考えた人がいて、ライブラリとして公開してくれていました。
それが[tsconfig-paths-jest](https://github.com/ryohey/tsconfig-paths-jest)です。
名前の通り、`tsconfig`から`paths`の設定を拾ってJestの`moduleNameMapper`にしてくれるものです。
これで解決、したかに思えました。

## 暗転
ところが、なぜかプロジェクトのコード以外の箇所でエラーが発生する事態に。
結構時間取られてしまったのですが、ようやく分かったのが、`tsconfig-paths-jest`が作ってくれるマッピングがマズイということ。

## 解決・・・？
ローカルで修正することも考えたのですが、同じ問題でハマる人もいるかも知れないので、Issueを作成しつつ、修正プルリクを出しました。

ところが、すぐに[別の方法](https://kulshekhar.github.io/ts-jest/user/config/#paths-mapping)を発見しました。
なんとts-jestに同様のもの（`pathsToModuleNameMapper`）があったのです。
`tsconfig-paths-jest`のオーナーの方も

> Thank you for letting me know. I guess we should use pathsToModuleNameMapper rather than this module.

> （教えてくれてありがとう。このモジュールを使うよりpathsToModuleNameMapperを使った方がよさそうだね）

とのコメント。
そこに別の方が
> Yeah, ts-jest added a helper for this in v23, I'm still on v22 for another issue

> （そう、ts-jestがこのためのヘルパー（pathsToModuleNameMapperのこと）をバージョン23から追加したんだ。僕は別の問題があって、まだバージョン22を使ってるんだ）

そうなのです。理由があって古いバージョンのts-jestを使わなくてはいけない人にとっては、`tsconfig-paths-jest`は有用なツールで、僕の修正が役に立ったのです。

コミュニティ万歳。

その後、利用していた別のライブラリにも[不具合報告](https://github.com/YousefED/typescript-json-schema/issues/263)して、PRを出してマージしてもらいました。
三項演算子 ❏Ruby❏

#複数行のif文を一行で書くことができるすぐれもの。

`(条件式) ? (trueの場合の処理):(falseの場合の処理)`

---

例）

```ruby
if score > 60
  puts "合格"
else
  puts "不合格"
end
```

このif文が

```ruby
puts score > 60 ? "合格":"不合格"
```

こうなる。


<br>
ではまた！
[Elm] typeとtype aliasの違い

#背景
ずっとReactやReact Nativeを使って開発をしていたのですが、最近になってElmを触り始めました。
むむっとなったelm記法のtypeとtype aliasの違いを書いていきます。

#type alias
まずはtype aliasについて書いていきます。
type aliasは`型の別名`をつけることができます。

```elm
hasName : { id : Int, name : String } -> Bool
hasName user = 
    String.length user.name > 0
```
上記のような関数がある時、`{ id : Int, name : String }`の部分が冗長ですし、何を表しているのかわかりません。
そこで`type alias`を使って型に別名をつけてあげます。

```elm
type alias User =
    { id: Int
    , name: String
    }

hasName : User -> Bool
hasName user =
   String.length user.name > 0
```
`type alias`を使ってわかりやすくなりました。
こういったように自分の表現したい型に対して別名をつけることがtype aliasです。

#type
typeはtype aliasとは別の物です。
typeはカスタム型と呼ばれ、新たな型を自分で定義できます。

```elm
type Country = Japan | Korea | China | Thailand | Taiwan
```
上記の例は`Country型`という新たな型を作りました。
注意するべきなのが、Countryは`型`ですが、Japanは`値`ということです。
`Bool`という型は以下のように定義されています。

```elm
type Bool = True | False
```

このように考えるとイメージしやすいです。
またカスタム型は列挙するだけでなく、それぞれに値を保持することもできます。

```elm
type User
    = Member String
    | Guest

user1 : User
user1 = Member "akira"

user2 : User
user2 = Guest

message : User -> String
message user =
    case user of
        Member name ->
            "こんにちは, " ++ name ++ "さん"
        Guest ->
            "こんにちは"
```
上記のような関数が作れます。

#まとめ
type aliasとtypeの違いを書いてみました。
同じような意味合いだと最初は思っていたのですが、全然違いました。
参考になれば幸いです。
AWS上でタイムゾーンを取得するとUTCになる

AWS EC2でタイムゾーンを取得すると全てUTCになる。

```python
# EC2上でPythonを使ってタイムゾーンを取得
>>> from tzlocal import get_localzone
>>> get_localzone()
<UTC>
```
この現象はAWSのデフォルトの設定がUTCとなっているため起こるらしい。
タイムゾーンは以下のファイルで設定されている。
/etc/localtime

```
$ strings /etc/localtime
TZif2
TZif2
UTC0
```


取得したいタイムゾーンが決まっている場合、
「[AWSのタイムゾーン設定でハマった件](https://blog-s.xchange.jp/?p=684 "AWSのタイムゾーン設定でハマった件")」をに設定の変更方法がわかりやすく記載されていました。:smile:


もしWebアプリケーションにEC2を使用していて、
ユーザーの現在地のタイムゾーンを取得したい場合はフロント側で時間を操作するしかない:thinking:？
もしいい方法があれば教えてください。:bow:
CSSでスティッキーフッターを実装する

常にフッターをページの一番下に配置させる、スティッキーフッターの実装をします。

```html:index.html
<body>
  <div class="content">content</div>
  <footer>footer</footer>
</body>
```
```css:style.css
body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.content {
  margin-bottom: auto;
}
```

これで常にフッターをページの一番下に配置させることができます。
GASで画像をbase64でエンコード

# 注意
仕様変更によりスプレッドシートがGoogleドライブの容量にカウントされるようになりました。
エンコードするとサイズが大きくなるので、基本的にはおすすめできないです。
画像で検索してもヒットしないので、隠すことくらいしか利点が無さそうです。

# 目的
GASでする意味あるの？というのは当然の疑問ですが勿論あります。
なんとスプレッドシートはGoogleDriveの容量を使わないんです。
つまり、実質無制限ということです。
画像以外にも使えます。
まぁ欠点はデコードするのが手間だというくらい。
というかそれしかない。
GASでHTML作ってそこにimgタグ入れて一応見れるようにしてるけど実用性はあんまり。
今は使わないけどもしかしたら今後必要になるかも、一応バックアップ取っておこうッていうのに役立つと思います。

# コード

スプレッドシートを用意してA1から右方向に[ファイルの名前、サイズ、タグ、エンコードした文字列]を想定しています。
tagは手動でつけてください。
画像はフォルダを作ってそこに入れておいてください。
エンコードしてらゴミ箱に入れるようにしています。

```javascript:code.js
function encode_img(){
  
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  const folderId = PropertiesService.getScriptProperties().getProperty('folderId');
  const folder = DriveApp.getFolderById(folderId);
  const files = folder.getFiles();
  var file;
  var file_name;
  var blob;
  var encoded;
  var file_size;
  
  while(files.hasNext()) {
    file = files.next();
    file_name = file.getName();
    file_size = Math.round(file.getSize() / 1024);
    blob = file.getBlob();
    encoded = Utilities.base64Encode(blob.getBytes());
    sheet.insertRowAfter(1);
    sheet.getRange(2, 1, 1, 4).setValues([[file_name, file_size,  '', encoded]]);
    folder.removeFile(file);
  }
  return;
}
```

完成したと思って喜んだのですが、サイズの大きなファイルはエラーが発生。
原因はセルは50000文字しか入らないらしい。
それなら分割しようと思い実行すると今度はメモリ上限ですとエラーを吐かれました。
変数に入れれるサイズか、エンコードする文字数か。
正規表現で50000文字ごとに区切ろうとしたのでmacthの文字数制限か。
解決したら記事を編集します。

# コード2
```javascript:code.js
function encode_img(){
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
    const folderId = PropertiesService.getScriptProperties().getProperty('folderId');
    const folder = DriveApp.getFolderById(folderId);
    const files = folder.getFiles();
    var file;
    var file_name;
    var blob;
    var encoded;
    var data = [];
    var file_size;
    var i;
    var num;
  
    while(files.hasNext()) {
      file = files.next();
      file_name = file.getName();
      file_size = Math.round(file.getSize() / 1024);
      blob = file.getBlob();
      encoded = Utilities.base64Encode(blob.getBytes());
      // 50000文字毎に区切る
      num = Math.ceil(encoded.length / 4999);
      for(i = 0; i < num; i++){
        data.push(encoded.substr(i * 49999, 49999));
      }
      sheet.insertRowAfter(1);
      sheet.getRange(2, 1, 1, 3).setValues([[file_name, file_size,  '']]);
      sheet.getRange(2, 4, 1, data.length).setValues([data]);
      folder.removeFile(file);
  }
  return;
}
```

原因はmatchでした。
あと、一つのセルの上限は50000とエラーが出たけど49999っぽい。

【追記】
文字の頭文字によっては。「'」が先頭に挿入されます。
それが原因で文字数が+1されていました。
なのでセルの上限は50000文字です。

# あとがき
今頃だけどローカルでエンコードしてGASで作ったWEBアプリにPOSTした方が便利かも。
9MBの画像をエンコードしてデコードしたら無事見れた。
スプレッドシート開こうとしたらめっちゃ重かった。
ApacheとTomcatとApacheTomcat

### どう違うのか分からんのでメモメモ

####Tomcat

* Java Servletを動かすときに必要なソフト
* つまりサーブレットコンテナのひとつ
* ただし、作ったJava Servletの動作確認ができるように（簡易的な）Webサーバとしての機能も持っている
* EclipseでサーバのところにTomcatを入れるのは↑のためのようだ（簡易的にWebサーバとしても使ってる）
* <b>「Apache Tomcat」というのはこっちのようだ。</b>
* よく見る猫のマークのやつ？

####Apache
* 全世界的に普及しているWebサーバのソフト
* こっちは「Apache Tomcat」ではない。まぎらわしい…
* 本名は<b>Apache HTTP Server</b>らしい。


参考：
https://wa3.i-3-i.info/diff184web.html
日本語プログラミング言語「プロデル」でIrisの分類タスクをやる（SVM編）

昨日，サポートベクタマシンをプロデルで実装したので，使ってみたいと思います。[これ](https://qiita.com/nipo/private/2868b37ca0e7587a20c9)のSVM版をやります。

## はじめに

今回は二値分類です。Irisデータセットは，3クラスなので，データを一部切り捨てて二値分類タスクにします。

## 前処理

前処理の段階で，正解ラベルを2種類に絞ります。

```
※コンソール
「..\行列.rdr」を参照する。
「..\サポートベクタマシン.rdr」を参照する。
「..\文字列操作.rdr」を参照する。
「Produire.File.dll」を利用する。
「Produire.Network.dll」を利用する。

アイリスデータは，HTTPで「https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data」を取得したものの行区切りの1番目から100個切り出したもの。
アイリスデータを適当に並び替える。

正解という行列（80，1）を作る。
訓練データという行列（80，4）を作る。
評価データ用正解という行列（20，1）を作る。
評価データという行列（20，4）を作る。

100回，【カウンタ】にカウントしながら繰り返す
	【一行】は，アイリスデータ（カウンタ）を「,」で分割したもの。
	もしカウンタが80以下なら
		4回，添字にカウントしながら繰り返す
			訓練データの中身（カウンタ）（添字）は，一行（添字）。
		繰り返し終わり
		一行（5）について分岐
			「Iris-setosa」の場合
				正解の中身（カウンタ）は，｛1｝。
			「Iris-versicolor」の場合
				正解の中身（カウンタ）は，｛-1｝。
		分岐終わり
	でないなら
		4回，添字にカウントしながら繰り返す
			評価データの中身（カウンタ-80）（添字）は，一行（添字）。
		繰り返し終わり
		一行（5）について分岐
			「Iris-setosa」の場合
				評価データ用正解の中身（カウンタ-80）は，｛1｝。
			「Iris-versicolor」の場合
				評価データ用正解の中身（カウンタ-80）は，｛-1｝。
		分岐終わり
	もし終わり
繰り返し終わり
```

データをHTTPで取得をするので，繰り返し実行しないで下さい。ダウンロードしたものを使う場合は，`「［ファイル名］」から読み込んだものの行区切りの1番目から100個切り出したもの`と書き換えて下さい。

100個中，80個を訓練データ，20個を評価データとします。従って，先にランダムに並べ替えておきます。あとはニューラルネットワークの時と一緒です。

## 学習・推定をする

線形カーネルを利用します（線形カーネルしか実装していない）。

```
カーネル君という線形カーネル（訓練データ）を作る。
SVM君というサポートベクタマシン（カーネル君）を作る。
訓練データと正解を｛5.00，0.0002｝でSVM君が学習する。
結果は，SVM君が評価データを推定したものを転置したもの。
結果を表示。
評価データ用正解を転置したものを表示。
評価データ用正解を転置したものを結果で比較したものを表示。
```

実行には1分もかかりません。結果は次の通りです。

```
PS C:\> .\アヤメの分類_SVM.exe
80
76.37834
73.94282
71.80421
69.7756
（略）
5.165431
5.112964
5.062041
5.012619
4.96465
-1，1，1，1，-1，1，1，1，-1，1，-1，1，1，1，-1，-1，-1，-1，-1，1
-1，1，1，1，-1，1，1，1，-1，1，-1，1，1，1，-1，-1，-1，-1，-1，1
1
```

最後から3行目が推定した結果，最後から2行目が正解データのラベル，最後の行が正解率です。100%ですね。
（そんなことあるのかなあ・・・どこか間違っているのでは・・・）
pythonのKeyErrorを何とかする

# はじめに
Pythonを触っていて、

```
"KeyError: None"
```

というエラーが出た。原因と修正方法をメモ。（コメントでいただいた内容に修正しました。）

# 原因
`foo['bar']`と、`bar`というキーを指定しているが、そのキーが存在していないと考えられる。

# 修正方法
タイプミスの可能性があるため、自分でキーを把握しているorプログラム内にキーが記述されている場合は見直す。
無い場合は、適切な位置に以下のコードを挿入する。

```python:
...
print(foo.keys())
...#ここでエラーが起こる
```

`['bar']`部分を適切に修正する。
RoboschoolでなくPyBulletを使いましょう

# 始まり

最近久しぶりに[roboschool](https://github.com/openai/roboschool)の入っている強化学習の検証用Dockerimageをビルドし直したんですが、roboschoolをimportするところで以下のようなエラーが出るようになってしましました。

```bash
ImportError: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.28 not found (required by /usr/local/lib/python3.6/dist-packages/roboschool/.libs/libQt5Core.so.5)
```

いろいろ調べてみるとどうやら求めているGLIBCのバージョン2.28がUbuntuに標準インストールされているGLIBCよりも新しいバージョンとなっているようです。

■標準のバージョン

- Ubuntu 16.04 : GLIBC 2.23
- Ubuntu 18.04 : GLIBC 2.27

最終的にこのroboschoolのリポジトリの[issue](https://github.com/openai/roboschool/issues/207)に辿り着き、roboschoolのバージョンを1.0.48に落せば解決するとのことがわかりました。
何のアップデートでバージョンが合わなくなったんだろう？と疑問に思い[roboschoolのリポジトリ](https://github.com/openai/roboschool)を訪れてみたらまさかの文言が・・・

<img width="856" alt="スクリーンショット 2019-11-18 22.12.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392863/5f14272a-1f16-252c-49d7-c98e8b82d2fe.png">

roboschoolが公式にDEPRECATED(非推奨)になってる・・・
前々からPyBulletに置き換えられるんじゃないかという噂はありましたが、全く気付きませんでした。

# ということでPyBulletを使いましょう

公式に勧められた以上、今後はPyBulletを使っていこうと思います。

インストールは以下のようにroboschoolをインストールするところをpybulletに変更すればOKです。

```bash
$ # pip3 install roboschool
$ pip3 install pybullet
```

ソース上ではimportとgym.makeの所をpybullet用に変更すれば無事動きます。
詳しくは[PyBullet Quickstart Guide](https://docs.google.com/document/d/10sXEhzFRSnvFcl3XxNGhnD4N2SedqwdAvK3dsihxVUA/edit#heading=h.wz5to0x8kqmr)をご覧ください。

```python
#import roboschool
import pybullet_envs

# env = gym.make("RoboschoolHumanoid-v1")
env = gym.make("HumanoidBulletEnv-v0")
```

roboschoolに比べてだいぶカラフルなボディーになっていますね！！
<img width="115" alt="スクリーンショット 2019-11-18 22.28.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392863/320802fb-0399-be3e-862a-5003ebf0ce56.png">