OmniAICreator/Qiita-1.07M huggingface dataset:
【厨二】コンソール起動時の表示をいじる

#ハッキングツールキットの起動画面はかっこいい
僕はセキュリティを専門に勉強しているわけでもありませんし、ハッカーやクラッカーを目指しているわけでもありません。
しかしながらやはりこの業界に入った人たちは一度は憧れたのではないでしょうか？海外映画やドラマでクラッカーが真っ黒な画面を前にカタカタコマンドを打つ姿に。
「そんなの厨二だ！」とおっしゃる方もいらっしゃるでしょう。ええ、そうですとも。僕はまだ厨二が抜けていません！笑
未だにカタカタ攻防を繰り広げるハッカーには憧れますし、エナジードリンク片手に真っ暗な部屋で顔も知らないハッカーとコマンド上のチャットで「中国のサーバーに入ったぞ！」みたいなこと言ってみたいです（偏見がすごい）。

vimさえまともに使えない厨二病の僕ですが、どうにかハッカー気分を味わいたいということで、今回はターミナルを起動したらツールキットの起動画面みたいなのが表示されるように設定をいじりたいと思います。

##目標物
こんな感じのAA（アスキーアートに分類していいのか）が表示されればかっこいいなあと思う次第です。
画像はBrutalと言うツールキットらしいです。詳しくは知りません（）

![Brutal_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/00db2c45-3c0b-74e7-1382-078ec715cbef.png)

#まずは簡単な文字から
いきなりイラストのAAは難易度が高いのでまずは文字だけ表示してみます。
ターミナル起動時に何か処理をさせたい場合はユーザーのホームディレクトリ直下に`.bash_profile`を作成し、この中にシェルスクリプトを書いていきます。

表示する文字ですが、とりあえず『welcome.』とかにしておきましょう。
そうは言ってもただ文字を`echo`で出すのはつまらないのでこれもAAのような感じで表示させようと思います。

##テキストのアスキーアートをコマンドで生成する
『welcome.』のAAなんて僕には到底作れませんから、これはコマンドに任せましょう。

```
$ brew install figlet
```
brewでインストールできるAA生成コマンドがあります。
![スクリーンショット 2019-07-22 8.28.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/51137e87-76e2-48a6-a5e2-f00e8ef82da8.png)

こんな感じですね。簡単です。このコマンドには色々オプションがあるみたいなので興味のある方はぜひ検索してみてください。

##シェルスクリプトを書く
いよいよシェルを書いていきます。
先ほども言った通り、vimが使えないのでnanoで書いていきます。

![スクリーンショット 2019-07-22 8.31.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/3c247b21-df38-e640-7292-9a924b6b9750.png)

難しいことはないです。基本的にはコピペでOK。
注意すべき点として、バックスラッシュはバックスラッシュでエスケープしましょう。

##ターミナルを起動してみる
さて、スクリプトを保存して、ターミナルを再起動してみます。

![スクリーンショット 2019-07-22 8.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333871/703d9141-f080-5e4d-13d0-8362e781829d.png)

おおお！いい感じです。
もはやこれだけでいいのでは、、、？

ドクロの横顔に関してはもう気合いで書くだけなので、、、。
とりあえず今回はここで終了です。
php-master-changes 2019-07-21

今日はビルドシステムのリファクタリング、ドキュメントの更新、テストこけの修正、typo の修正、sapi/litespeed の更新があった！

# 2019-07-21
## petk: Remove HAVE_LOCALE_H and locale.h check
- https://github.com/php/php-src/commit/605386e394f52557a07bbf2116ca40aac8f50df9
- ビルドシステムで、locale.h のチェックと HAVE_LOCALE_H の削除
- C89 に入ってるでしょ系

## petk: Update changelog
- https://github.com/php/php-src/commit/24fbda050594cb1f75f08d9ac802be1645d46c72
- UPGRADING.INTERNALS に↑を追記

## petk: Move HAVE_SQLITE3_CLOSE_V2 to pdo_sqlite
- https://github.com/php/php-src/commit/f5227c5863a79cb219902f32aaebacac77a6e133
- [7.4~]
- HAVE_SQLITE3_CLOSE_V2 の定義が間違って ext/sqlite3 にあったのを ext/pdo_sqlite へ移動

## petk: Fix failed tests for phar
- https://github.com/php/php-src/commit/b1643e166d039057cdefb9a5a5420d165f2b2e05
- [7.4~]
- ext/phar で、テストこけの修正

## staabm: Fix typos
- https://github.com/php/php-src/commit/577ed5bfa481b617b109badb967bb06346a8856d
- [7.4~]
- ext/pcre で、typo の修正

## Girgias: Renamed MySQLi test to remove duplicate 'mysqli_'
- https://github.com/php/php-src/commit/1a031a242cb1e23ee1858d1d1d520f076e10e036
- [7.4~]
- ext/mysqli で、テストの名前が mysqli_ でなく mysqli_mysqli_ と、[何で2回言うねん状態](https://ja.wikipedia.org/wiki/HUNTER%C3%97HUNTER)だったのを修正

## George Wang: Checked in LiteSpeed SAPI 7.5, addressed two main problems in "clean shutdown" introduced in 7.4.3,
- https://github.com/php/php-src/commit/eb7e45f662bb8bba292caaa03f93759912bcddf0
- [7.2~]
- sapi/litespeed を更新
- シャットダウン処理を修正してなんか無限ループが起きたりするとかエラー出力が出まくるとかへ対応しているもよう

## petk: Remove HAVE_LIBZIP
- https://github.com/php/php-src/commit/15782b27b8ad34204470d4ce9f464a7be0e4e1a6
- [7.4~]
- ext/zip で、HAVE_LIBZIP の削除
- [非バンドル化](https://qiita.com/sj-i/items/951e46693d1af57adf2a#nikic-remove-bundled-libzip)で常時システムの奴を持ってくるようになったため

## petk: Remove some unused HAVE_* symbols
- https://github.com/php/php-src/commit/1b969a74d08bff4dc13b613230658245de8d68c8
- [7.4~]
- ビルドシステムで、使われていない HAVE_* の削除

## petk: Remove build.mk usage
- https://github.com/php/php-src/commit/ef165b4422f4cef60f963833dddffa26fe1b2759
- [7.4~]
- ビルドシステムで、build.mk の削除
- buildconf で autoconf や autoheader を起動するのに使われていた Makefile
- [PR:4437](https://github.com/php/php-src/pull/4437) の流れ、単純化に加えて若干速くもなるっぽいのかな
docker toolboxをmacにインストールするとエラーになった

公式サイトでインストールしてきたんですが
https://docs.docker.com/toolbox/toolbox_install_mac/

素直にそのままインストールしても、virtualboxでエラー。。。
virtualboxをアンインストールしてみてもだめ。

仕方ないのでhomebrew経由でインストールしてみた。
```brew cask install docker-toolbox```

それも以下のエラー。。。
```Error: Download failed on Cask 'docker-toolbox' with message: Download failed: https://github.com/docker/toolbox/releases/download/v18.06.1-ce/DockerToolbox-18.06.1-ce.pkg```

homebrew経由でvirtualboxはインストール成功してたので、
それで改めてもう一回公式サイトでpkg落としてきてインストールしたら成功した。。。
ほぼ新人があふれる意欲で毎朝の勉強会を立ち上げて成り上がる話

# はじめに
私のプロジェクトとは別のプロジェクトに、仲のいい後輩(仮にU君とします)がいます。
U君は、開発経験半年にして、プロジェクト内のベテランたちを相手にReactの勉強会を立ち上げ、確固たる地位を築きました。その勉強会のやり方と地位を築くまでのプロセスが素晴らしいと思ったので紹介します。
また、U君が自分の地位を築いた手法が、若手の方々にとって参考になれば幸いです。

# U君とは
入社して1年3ヶ月のほぼ新人で、開発経験はたった半年の若手です。入社時点ではJavascriptを全く知らない状態でしたが、半年間でJavascriptとCSSとReactをひたすら勉強していました。
そして本人の意欲がとても凄いです。社内に「社内版Qiita」みたいなものがあるのですが、そこに学習した内容を次々と投稿しています。若手の中ではU君がダントツで投稿数No.1です。一般的に、学習効率を高めるためにアウトプットは有効と言われているため、たくさん投稿したことが成長を加速させたのだと思います。
そして今回のReact勉強会は、U君のプロジェクト内でReactの技術を持っている人が少ないこともあり、U君が勉強会を提案して毎朝実施することなりました。(ちなみに、参加者は全員U君より年上でベテラン社員も含みます)

# 勉強会の実施方法
## 毎朝アウトプットを伴う勉強会
参加者全員にノートPCを持ってきてもらって、その場でプログラミングさせて動くものを作らせるというアウトプット形式で実施しています。毎朝30分実施しています。
「よくある勉強会の形式」として「発表資料を作ってその資料の内容を紹介」というものがあります。そういう「よくある勉強会の形式」でなく、アウトプット形式にした理由をU君に尋ねると「実際に手を動かしてアウトプットしないと技術は身に付きません。だからアウトプットさせる勉強会が一番理にかなっています。」とのこと。素晴らしい。

ちなみに、私も自分のプロジェクトで毎朝、アウトプット勉強会を実施しています(詳細は以下)。
[毎朝15分の勉強会で若手の行動が驚くほど改善した話](https://qiita.com/kojimadev/items/cd5dd5332e33b3ef46a6)
[毎朝15分の勉強会で若手の設計力がメキメキアップした話](https://qiita.com/kojimadev/items/99d2aa1c9bc67a835480)

## 勉強会の資料はインデックスのみ作る
特に凄いなと思ったのは、この点です。勉強会を継続的に実施する上で、一番ネックになるのが「資料の作成時間を確保する」という点だと思います。勉強会を実施したくても、そのための資料を作るのが億劫で、なかなか勉強会を頻度よく実施できないことはよくあります。
それに対して、U君が出した答えは「勉強会の資料はインデックスのみ作る」というものです。
具体的には、Reactでの開発に必要な学習項目とそのポイントだけを列挙します。例えば、「条件付きレンダー」と「高階コンポーネント」という学習項目の場合、以下のように「学習する上でのポイント」だけを記載し、詳細は勉強会の中でコードを見せながら説明します。

- 条件付きレンダー
    - 描画するコンポーネントを変数に代入して、JSX 内でその変数を利用
    - && 演算子や三項演算子を使用して JSX のインラインで分岐を記述
- 高階コンポーネント(Higher Order Component)
    - 高階コンポーネント(HOC)の目的
    - React のライブラリでHOCが使われている例

上記のように、「学習項目の一覧」と「ポイント」のみを事前に作成するだけとすることで、勉強会の事前準備時間を極限まで減らしました。
この方式は、講師の頭の中に、しっかりと知識が入っていないと実施できないと思いますが、それができるほど半年間でしっかり学習したのは素晴らしいと思いました。しかも、参加者の反応を見ながら、理解不足に見える点を補足説明したり、実際の開発でよく使うノウハウを説明したり、柔軟に対応していました。

## 事前に勉強会の内容をシミュレーション
U君は自信家でありながらも用意周到です。
毎朝の勉強会の前に、その日に実施する勉強会の内容を脳内でシミュレーションします。その時に、理解が不十分な項目は、調べて理解し直してから勉強会に臨みます。

## 勉強会で作成するプログラム
勉強会で作成するプログラムは、ToDoアプリをベースに、そのアプリをどんどん成長させていく形式としています。毎回違うアプリを作るよりも、1つのアプリを成長させていく方が、効率が良いとのことです。

# 別のプロジェクトも育成
実施中の勉強会は、3ヶ月くらいで一区切りがつくそうです。そして勉強会で得た様々なフィードバック(勉強会のやり方や資料の改善点など)を「次」にも活かしたいと言っていました。
「次」というのは、別のプロジェクトのメンバーに、第2期、第3期の勉強会を実施していくことです。そうして社内でWebエンジニアをどんどん育成していくという構想でした。なお、第2期 勉強会に、私のプロジェクトを誘ってくれました（なんと素晴らしい後輩でしょう）。

# まとめ
今後、U君は勉強会を通して次々とWebエンジニアを育成していくことでしょう。そうして、社内にU君の教えで育った「U君チルドレン」をたくさん排出することで、社内での確固たる地位を築いて成り上がっていくことでしょう(私もU君チルドレンになる予定です)。

今は別々のプロジェクトですが、いつかU君と一緒に開発してみたいです。ちなみに私は [Lightning Review というレビュー支援ツール](https://www.lightning-review.com/) を作ったりしています。
Twitterでも情報発信しています → [@kojimadev](https://twitter.com/kojimadev)
スタートアップの新卒エンジニアが3ヶ月間でやったこと

新卒エンジニアが3ヶ月間でやってきたことを、自分の振り返りも兼ねてまとめます。(Qiita書いてみたかっただけ)

##入社時点のレベル
- C言語の構造体、ポインタがギリギリわかる
- **linuxコマンド**は使ったことない(黒い画面はテレビの世界のお話だと思ってた)
- **Git**も使ったことない
- **html**、**css**は少し触ったことがある

上からわかるように、完全に初心者。本気出せば1日でたどり着けるレベル。本気出せなくてもたどり着ける。僕は何事も気合いでなんとかなると思っているような人間なので、根性論が嫌いな方は頭悪いなコイツくらいに思っておいてください。

##開発環境の構築
入社初日にやったことは、開発環境の構築。
**Vagrant**と**Virtualbox**を使って開発環境を作った。正直何がなんだか全く理解出来ないまま、コマンドを打っていった。ssh出来た時はやりきった感があった。(特になにもやっていないけど)
実は今の開発環境は**Docker**を使っているけど、、、

##JavaScript(ES6)
『とりあえずJS勉強しといて』と言われ、言われるがまま**JavaScript**の勉強を始めた。
勉強方法は調べる、書いてみる、動くか確認してみるの繰り返しで、```Click```とか```Submit```で発生するイベントを実装していった。
**Ruby on Rails**で**JS**を使っていて、ハマったところは、

- **turbolinks**というGemでうまく**JS**が機能しない　→　`turbolinks:load`イベントで実行されるようにする。

- ES6がRailsでprecompileが通らない　→　`production.rb`の設定を変更する。

下のページを参考にしました。

- [Turbolinks5についてまとめてみる](https://qiita.com/saboyutaka/items/bb089e8208239bf6fdc0)
- [RailsでES6の機能を使うとプリコンパイルが通らない（Uglifierがエラーを吐く）問題](https://qiita.com/Thort/items/18c44604aba65303c221)

##Ruby on Rails
JSの勉強をしながら、『あれ、使ってるのRailsじゃね？』
と思い、**Rails**の勉強を始めました。**Ruby**も触ったことなかったのでRubyの勉強から始めました。
Rubyを触って思ったこと、

- 型ないのか(なんか気持ち悪い)
- `if文`に`then`とか`end`あるんだ　→　数週間後、`then`省略できるんだ
- とにかく、**色々簡潔にかける**
- Rubyは初心者から入りやすいって聞くけど、慣れてしまうと後々苦労しそう

##React.js
上司が**Material-UI**使いたかったらしい。
『これ、すごくね？』といってくる上司はまるで小学生だった。
**Material-UI**は、さっと作りたい時に便利だと思います。デザインも豊富だし、カスタマイズもできる。つまり、**超便利！**

##MySQL
データベースは**MySQL**を使いました。
最初はSQL文を覚えられず、苦労しました。コマンドは覚えようとしなくていいと思います。毎回、調べてたら、調べるのがめんどくさくなって、**勝手に覚えてます。**
データベースをしっかり設計していないと後でだるい。
Railsの方でも**バリデーション**していないと空のデータが入ったりして、エラーの原因になってしまう。

##Docker
開発環境を変えようということになり、**Dockerfile**を書いていったのですがとにかく動かない。社内にもわかる人はいない。(みんなDocker初めましてだったので)
結局、他者のエンジニアの方に助言を頂き、無事にDockerに移行することが出来ました。
**外部の繋がりって大事だな**とすごく感じました。

##AWS
自分のサイトを作ろうと思い手を出したのが**AWS**でした。無料だし、周りに聞けるしね。
Railsでデプロイするなら下のページがすごく丁寧でわかりやすい。

[世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで](https://qiita.com/naoki_mochizuki/items/f795fe3e661a3349a7ce)

##最後に
自分で記事を見返したら、**めちゃめちゃ文字!**
まぁ、いいか、**最初はみんな初心者なんで**
プロセスの終了の仕方 ～ top & kill

研究室内の仲間とUbuntuでいろいろなことをしていると、「プロセスの終了の仕方が分からない」人が多いので、ここいらでまとめときます。

あと、「そのサーバーで回っている実験やプログラムが見たい」とか「過負荷どうなってるの？」とかも聞かれることが多いので、ここらへんの人にも役に立つはずです。

## 想定環境
- Windows Subsystem for Linux
- または Linux や Linux Server

## 問題の起こし方

さて、問題を具体的に見ていくために、上記の環境を持っている人は nyancat というタイマーを用意しましょう。

端末に以下のように打ち込みましょう。

```bash:端末
$ sudo apt install nyancat
```

Linuxの「端末」というのは、WSLにおけるUbuntuや、Hyper, Cmderといったアプリです。

これで nyancat がインストールされました。
では起動してみましょう。

```bash:端末
$ nyancat
```

すると、コンソール画面に以下のように表示されるはずです。

![nyancat.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296126/5e477160-548d-5d11-440d-d7fea566fb45.png)

これは、とても楽しいタイマーなのですが、どうやってこの画面を抜けるか、で問題が起こります。

「Ctrl + C」で抜けましょう。

しかし、もし「Ctrl + Z」で抜けたとします。
すると、「$ exit 」として端末を閉じようとしたとき、すぐに閉じられなくなります。

![nyancat2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296126/b1315ba3-e55d-4f32-ac9a-0ee1beac10df.png)

この状況を簡単に言うと、「いまこの端末で一時停止しているプロセスを殺さないと終了できない」という状況です。

「Ctrl + Z」はプロセスの一時停止なので、nyancat はバックグラウンドに回ってしまうのです。

もう一度、nyancat コマンドを実行しても、新しい nyancat のプロセスが生成されるだけで、昔の nyancat は消えてくれません。

このへんの挙動の違いを詳しくまとめている記事は[こちら](https://qiita.com/toshihirock/items/bc6a9a4091afa9bb61f1)。

さて、こうなってしまったプロセスや、バックグラウンドに回ってしまったプロセスを殺すために、まずは実行中のプロセスを見ましょう。

## top コマンドの見方
top コマンドはプロセスによるシステムの過負荷などの情報がリアルタイムで見れます。

```bash:端末
$ top
```

以下が実行画面です。

![top.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296126/4bae2515-59b9-e3c1-35ce-a709680fd6b2.png)

黒い画面べた張りで申し訳ないです。

「q」を押すと止めれます。

一番上の load average ってのが、誤解を恐れずにいうと、CPUに処理されるのを待っている仕事の数で、仕事がなくて暇なほど小さくなります。

左から、1分、5分、15分の平均の値です。

ここの値に関しては、コア数とかにもよるけど、旧世代のノーパソで負荷かけたときは 10 超えてて、ファンがウィンウィンまわってました。

あとはプロセスのID、実行時間やCPU使用率などが見れるので、サーバを触る人は重宝してるコマンドだと思います。

## ps コマンド
ps コマンドは実行中のプロセスを表示するコマンドです。

私はこのコマンドをバックグラウンドで走っているプログラムを見るときによく使います。

計算機実験などで使用するサーバーでは、他の人の負荷にならないようにまずはそのサーバーで何が起こっているのかを知る必要がありますから。

```bash:端末
$ ps ax
```

- a : 表示にほかの端末も含める。
- x : 現在実行しているプロセスの表示

これで実行中のプロセスの最低限の情報は取れます。

![ps.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296126/713d58ef-f2fe-0b3e-5ffb-8f62a5c4d8b4.png)

このオプションなら、プロセスのIDやそのプロセスの状態が見れます。

nyancat のプロセスについてだけ表示させたいなら

```bash:端末
$ ps ax | grep "nyancat"
```

とすれば、出せます。

STATを見れば、プロセスの状態が分かります。

ゾンビになってるプロセスだけ表示させたいときとかにも使えます。

私はよく「$ ps aux」として使います。

- u：ユーザー名と開始時刻を表示する

## kill コマンドの使い方

kill コマンドは、プロセスを強制終了するためのコマンドです。

さて、top か ps コマンドで問題の nyancat のプロセスIDが取れたと思います。

取得したプロセスIDをもとに、以下のように実行します。

```bash:端末
$ kill "プロセスID"
```

今回の場合では、「$ kill 182」とすれば、無事 nyancat を終了させることができます。

お疲れさまでした。
Swift/Metalで3週間で3Dアクションゲームを作った

#3Dアクションゲームを作った
2019年７月から3Dアクションゲームを作り始めました。
自分のスペックは10年前にDEAというゲーム専門学校でゲーム開発を学び、１年間現場でゲームプログラマをしていました。
その後は趣味でAndroid向けゲームを2本公開しています。
直近では2DパズルゲームをSwiftで作成し公開しています。

####まずは何か表示させてみようという所から始めました。
- まずは立方体を表示。
- 次に、ポイントスプライトを表示。
- MetalのViewの中にUILabelを表示する仕方が分からなかったので、ポイントスプライトを使って8×8ピクセルのアルファベットのフォントを作成。
- 立方体の角を取ったベベルキューブを作成。
- イラストから3Dにキャラクターを起こして、ゲーム画面に表示

<img width="375" alt="IMG_0255.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215739/69e2a705-e6dd-e204-75e8-a29f5f81d6b0.png"><img width="375" alt="IMG_0256.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215739/f3c03c9f-8a27-92f7-9c3c-bf8bc2086c4e.png">


####パズルゲームを作ろうかと思っていました。
キャラクターが登場するパズルゲームを作ろうと思っていたのですが、ゲーム的に面白くならなさそうだと思い、アクションゲームに変更しました。


##Metalのシェーダー
[[point_size]] というのをシェーダーに追加してポイントスプライトの大きさ変更に使っていました。
あと、ポイントスプライト用にOriginalPosition という引数を追加してポイントスプライトの位置を変更していました。

~~~metal
struct InOut2 {
    float4 position [[position]];
    float pointSize [[point_size]];
    float4 color;
    float3 normal;
    float3 light;
};

vertex InOut2 vertex_func(constant InOut *vertices [[buffer(0)]],
                          uint vid [[vertex_id]],
                          constant Uniforms & uniforms [[ buffer(1) ]],
                          constant OriginalPositions & origins [[ buffer(2) ]]
                          ) {
    InOut2 out;
    out.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * (vertices[vid].position + float4(origins.position, 1.0));
    out.color = vertices[vid].color;
    out.normal = ( uniforms.projectionMatrix * uniforms.modelViewMatrix * float4(vertices[vid].normal, 1.0) ).xyz;
    out.light = uniforms.lightPosition;
    out.pointSize = 8.0;
    return out;
}
~~~

ShaderType.h

~~~h
typedef NS_ENUM(NSInteger, BufferIndex)
{
    BufferIndexMeshPositions = 0,
    //    BufferIndexMeshGenerics  = 1,
    BufferIndexUniforms      = 1,
    
    BufferIndexOriginalPositions = 2,//今回これを追加
};

// 下記も追加
typedef struct
{
    vector_float3 position;
} OriginalPositions;

~~~

最終的にポイントスプライトは使いませんでしたが、自分のはこんなシェーダーになりました。

##シーン遷移
プロジェクトを新規作成した時点でRendererクラスが用意されており、そのRendererでシェーダーの呼び出しまで描画が出来るようになっています。
そのRenedererの中でにシーン(画面)を切り替えるクラスを作ります。
MTKViewにUIを登録してボタンなどを表示するのですが、シーン切替ごとにボタンの登録削除、新規登録を行います。
BaseSceneを作り、このクラスを継承する各シーンクラスがステージ１、ステージ２などになります。



##エディタを作った
ステージやキャラクターを作るためのエディタを作りました。
最終的に使いませんでした。


##キャラクタを作った
キャラクタはポイントスプライトで8×8ピクセルのアルファベットを作った要領でボクセルキャラクターをポチポチと作っていきました。
しかし、この作り方はキャラクタを量産させるには不便なやり方だと感じたので、今後はエディタを作り直してエディタを使ってキャラ作成しようと思います。


##当たり判定
今回はy方向ジャンプとz方向ジャンプがあるアクションゲームだったので難しい当たり判定になるかなと思っていましたが、y方向ジャンプだけのゲームと作り方は変わりませんでした。


##課題
- スクリーンサイズとUI表示位置を合わせる。
- 汎用的な当たり判定クラスを作っておく。


#まとめ
2019年7月26日にリリースする目標で最終調整していきます。
<img width="768" alt="IMG_0003.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215739/df74b535-5a55-7fb7-7293-4d5368d71f3a.png">

1本アクションゲームを作れたので完成させるノウハウが少し身に付きました。
キャラクタやステージをバリエーション豊富にさせることができるのは優秀なエディタだと思います。
今回使わなかったけど、エディタ大事
大事な事なのでもう１度、エディタ大事
ローカル環境と本番環境でのサーバの違い＆理解できた用語

#＜ローカル開発環境と本番環境でのサーバーの違い＞

**ローカル開発環境**
・サーバー
rails sコマンドでappサーバー(puma)が起動する。
・リクエスト
ブラウザからlocalhostにアクセスする。
・control　+　c　→　サーバーをシャットダウンする。


**本番環境**
・サーバー
Unicorn(appサーバー)を起動する。
・リクエスト
ブラウザからドメイン名(IPアドレスを文字化したもの)にアクセスする。
・killコマンド　＋ unicorn rails masterのPID →サーバーをシャットダウンする。

#理解できた用語

**リージョン**とは、AWSの物理的なサーバの場所を指定するものであり、世界各地に10箇所以上存在する(東京もそのうちの一つ)。


**EC2インスタンス（「仮想マシン」と呼ばれるソフトウェア）**とは、仮想的に一つのLinuxサーバを利用できる仕組みのこと。

**環境変数**とは、データベースのパスワードなどセキュリティのためにGithubにアップロードすることができない情報を設定するもの。
ElmでHtml.Events.onを使ってクリック座標を取得する

リファレンス見ても全く意味がわからなかったので、試行錯誤した結果のメモ
https://package.elm-lang.org/packages/elm-lang/html/latest/Html-Events

### コード
Json.Decode.Pipeline使った場合はこんな感じ
https://github.com/NoRedInk/elm-json-decode-pipeline

```elm
import Json.Decode.Pipeline

type Msg
    = Clicked Int Int
    | TouchStart
    | TouchEnd
    | OtherMessges

onClickDecoder : Decoder Msg
onClickDecoder =
    Json.Decode.succeed Clicked
    |> Json.Decode.Pipeline.required "offsetX" Json.Decode.int
    |> Json.Decode.Pipeline.required "offsetY" Json.Decode.int

-- 数字を使うときはこう
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Clicked x y ->
            ({ model | xPos = x, yPos = y}, Cmd.none )
        TouchStart ->
            -- TouchStart時にやりたいことがTouchStartCmdに定義されている場合
            (model, TouchStartCmd )
        TouchEnd ->
            -- TouchEnd時にやりたいことがTouchEndCmdに定義されている場合
            (model, TouchEndCmd )


--　呼び出すときはこう
div
    [ Html.Events.on "click" onClickDecoder 
    , Html.Events.on "touchstart" (Json.Decode.succeed TouchStart)
    , Html.Events.on "touchend" (Json.Decode.succeed TouchEnd)
    ]
    []
```

### 説明

* クリック時の座標取得などjsのaddEventListenerで取れそうなものの取得が必要な場合は、それを取得するためのDecoderと受け取るためのMsgを用意する
    * Decoder側では"offsetX"など、取得する要素名を記載する必要があるが、これは`addEventlistener("event", function(e){})`におけるeのプロパティなら記載できる様子
* タッチしたかどうかの判定など、詳細な情報はいらないけどそのイベントが発火したことだけを知りたい場合はDecoderを用意しなくても `Json.Decode.succeed Msg` で対応したMsgが発火される

### 他の選択肢
自力実装しなくてもこの辺りをよしなにしてくれそうなライブラリもある。
ただし、ライセンスがMozilla Public License 2.0なので、使うときはちょっと注意
https://github.com/mpizenberg/elm-pointer-events
kerasモデルからedgeTPUモデルへの変換方法

# 目的
Coral USBアクセラレータを用いて推論を高速化しようと。
すると、kerasで特定のタスク用に転移学習(transfer learning)したモデルをCoralのedgetpu用に変換させる必要があります。

※コードは十分検証していますが、素人ですので誤りや説明に過不足がありましたら、ご指摘いただきますと幸いです。

### 手順
1. keras(tensorflow)モデルを量子化(8bit)のtensorflow-lite(tflite)形式のモデルに変換。
2. tfliteモデルを専用コンパイラでedgetpuモデルに変換。

### 試したこと

@iwatake2222 さんの以下の記事の方法(tflite_convertツール使用)ではうまくできませんでした。
[Deep Learningアプリケーション開発 (7) TensorFlow Lite with Python on Raspberry Pi and Edge TPU](https://qiita.com/iwatake2222/items/6aeab468c326ecc21563)
最終的にedgetpuモデルの変換までできましたが、推論の結果がみんな全部同じ値となってしまいました（自分があまり理解できず、パラメータの調整が下手くそだっただけかもしれません）。

# 解決策

tensorflow 2.0(Beta版)のTFLiteConverter.from_keras_model_fileのAPIを使用して、tfliteモデルに変換してから、edgetpuモデルに変換するとうまくいきました。

### tfliteモデルへの変換

```
converter = tf.compat.v1.lite.TFLiteConverter.from_keras_model_file(kerasモデルパスの指定)
converter.representative_dataset = representative_dataset_gen  ← 量子化のキャリブレーション用のデータを生成する関数
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_model = converter.convert()

```

量子化のキャリブレーション用のデータを生成する関数。

```
def representative_dataset_gen():
    for i in range(サンプル数):
        yield [サンプルデータ[i: i + 1]]
```

ファイルに書き出します。

```
with open(model_name + '.tflite', 'wb') as o_:
    o_.write(tflite_model)
```

### edgetpuモデルへの変換

```
edgetpu_compiler tfliteモデルパスの指定
```

※edgetpuのインストールが必要。

# サンプルコード

githubにアップしています（google colab用)。
https://github.com/seeouy/edgetpu_model_converter

※サンプルコードには、fashion_mnistのカスタムモデルを作成していますが、すでにトレーニング済みのモデルがある場合は、読み飛ばしてください。

# 精度の劣化

基本的に、edgetpuモデルは量子化（重み等の情報を通常の32ビットから8ビットに落とす）が必要なため、オリジナルモデルと比べると若干精度(accuracy)が劣ります。

### 検証

サンプルコードのモデルを用いて、オリジナルのkerasモデルおよびedgetpuモデルに変換した後の精度を評価しました。

| モデル       |       accuracy |
|:-----------------:|------------------:|
| オリジナル | 0.6538 |
| edgetpu(サンプル数=100) | 0.6535 |
| edgetpu(サンプル数=1000) | 0.6537 |

以上の結果から、サンプル数を増やせば、オリジナルのaccuracyに近づけることができると考えられます。

※サンプル数とは、量子化のキャリブレーション用のデータを生成するときのサンプル数のこと。



# 参考
https://github.com/tensorflow/tensorflow/issues/27880?fbclid=IwAR15O-jjgU0TvGk0KioaUEOclJCN42UHU3Z0XGyOJW-XdM_6k0CEzYsxjQM
Linuxのドライブ増設時に必要な最小限の設定

# はじめに
HDDやSSDの増設を行った際，パーティションを設定し，マウントをする必要があります．
その際必要な最小限の設定に関する手順について示します．

# 環境
Ubuntu 18.04

# 手順
流れとしては
1. パーティションの作成
2. フォーマット
3. マウント
です．

以下の手順をターミナルで行うことでマウントが可能になります．

## マウントしたいデバイス名を調べる
```bash
%sudo df -h
```
HDDやSSDは通常`/dev/sd(アルファベット1文字)`というデバイス名になっています．
ここでは対象のファイルシステムを`/dev/sda`とします．以降，置き換えて読んでください．

## パーティション
**GNU Parted**というパーティショニングツールを使い，パーティションの作成を行います．

### GNU Partedのインタラクティブモードに入る．
コマンドラインモードも存在しますが，インタラクティブモードの方が簡単に設定が行なえるため，こちらを使用します．

```bash
%sudo parted /dev/sda
```
コマンドラインプロンプトの先頭が`(parted)`になったら，正しくインタラクティブモードに入れています．


### パーティションの作成
パーティションとは1つのドライブ内を分割する**仕切り**のようなものです．
ドライブには**最低1つ以上のパーティション**を用意する必要があります．
ここでは，1つのパーティションを作成します．

```bash
(parted) mklabel gpt 
(parted) mkpart primary ext4 0% 100%
(parted) quit    # インタラクティブモードを抜ける
```

ここでしていることは
1. パーティションテーブルの作成(`mklabel`)
2. パーティションの作成(`mkpart`)
です．
パーティションテーブルには`MBR`と`GPT`という2つの形式が存在します．`MBR`は2TBを超えるパーティションの作成ができないなどの制限がありますので，`GPT`を使います．

パーティションの作成では，**パーティションタイプ**，**ファイルシステム**，**パーティション位置**の指定を行っています．
**パーティションタイプ**は`primary(基本領域)`と`extended(拡張領域)`が存在しますが，`extended`は特殊な領域ですので，`primary`を選択します．
**ファイルシステム**はLinux標準の`ext4`を指定しています．
**パーティション位置**は全体に対する割合(%)で指定します．今回は1つのパーティションのみを作成するので，`0%~100%`を指定します．

以上の操作によって, `/dev/sda1`というデバイス名のパーティションを作成できました．

## フォーマット
作成したパーティションのフォーマットを行います．
`-L`はラベル名の指定です．これによって，デバイス名ではなく，ラベル名で管理することになります．任意のものを指定してください．
ラベル名で管理することで，ドライブの追加やデバイス名の変更による影響を受けなくなります．

```bash
%sudo mkfs.ext4 -L hdd /dev/sda1
```

## マウント
マウントを行います．任意のフォルダを作成し(マウントポイント)，そこにマウントすることでファイルの読み書きが行えるようになります．`/mnt`や`/media`といったところにマウントすることが多いです．今回は，`/mnt/hdd`というディレクトリを作成し，マウントします．

これで，一応使えるようにはなりますが，これだとマシンを起動するたびに手動でマウントを行わなければならないため，自動でマウントするように`/etc/fstab`という設定ファイルに追記します．

```bash
 $ sudo mount /dev/sda1 /mnt/hdd 
 $ sudo chown [user]:[group] /mnt/hdd # オプション：必要な場合は所有者を変更
 $ sudo vim /etc/fstab
```

```bash:/etc/fstab
# 末尾に以下を追記
label=hdd          /mnt/hdd                ext4    defaults        0 0
```

再起動して正しくマウントできていれば設定完了です．お疲れ様でした．
ancestryで多段階カテゴリーを使う為のseeds.rb作成

#概要
某アプリの３段階カテゴリーの実装手順をまとめて行きます。
カテゴリーは１０００個以上あるので、手動でやるのは地味過ぎるのでチャチャっと終わらせます。
手順はざっくり、
・各カテゴリー毎に、HTMLを取ってきてVScodeフル活用して整形
・Rubyで処理を書き、期待した配列を作る
・each文でいい感じに、DBに入れる
の３段階でやって行きます。
今回、上の２つは他の方の記事がわかりやすくまとまっているのでseedファイルの作成部分だけ軽くやって行きます。

※初投稿、初めて２ヶ月の初学者なので、お手柔らかにお願い致します！

#参考資料
配列作成の参考
https://qiita.com/haruki127/items/e17f6fc7072389f0f6e3
ancestryのgithub
https://github.com/stefankroes/ancestry

#カテゴリー配列の作成
上の参考記事を元に期待の配列を作成しました。
いくつかやり方はあると思いますが、今回のこの配列を作り、each文でやるのが楽だと思います。
もっと簡単な方法があれば教えてください！


#seed.rbに記述する
今回期待するテーブルの形を再度確認してみます

| id| name | ancestry |
|:-:|:-:|:-:|
| 1  | レディース  |   null|
| 2  |  トップス | 1  |
|  3 |  Tシャツ |  1/2 |
| 4  | パーカー |  1/2 |

1/2を私は勘違いして、二分の一かと思っていましたが、親カテゴリーと子カテゴリーのidが入っているだけでした。
これを難しく考えすぎて、１時間くらい無駄にしてしまいました…

本題に戻って、ひとまず親カテゴリーはそのまま入れれば問題ありません

```ruby:seeds.rb

parents.each do |parent|
  Category.create!(
    name: parent,
  )
end
```
これで問題なく、親カテゴリーは入ると思います。
続いて子カテゴリーですが、ancestryのメソッドである.childrenを使ってDBに入れます。
既に親カテゴリーは作成されているのと、紐づく親カテゴリーは配列に入っているので、以下の様なコードになると思います。

```ruby:seeds.rb

children.each do |child,num|
  parent = Category.find(num)
  parent.children.create!(
    name: child,
  )
end
```
孫カテゴリーも全く同じ要領でやって行きます。

```ruby:seeds.rb
grandchildren.each do |grandchild,num|
  child = Category.find(num)
  child.children.create!(
    name: grandchild,
  )
end
```

以上を、記述したらファイルを実行すれば、完成！

#まとめ
プログラミングを使えば単調な作業を一瞬で終えることが出来る良い例だと思い、記事にしました。
（これをコピペで頑張ってる人もいるとかいないとか…）
gemは必ず公式を一回みることをオススメします。見てもわからないって人もいると思いますが騙されたと思って毎回みましょう。
今後は軽めの記事を沢山のあげて行きたいと思っているので、参考にしたよ！って人いたらいいね！お願いします！
pythonのimportをはじめて勉強してたときのメモ

まだよくわかってない


# `__name__` とかと、importの基本
importされる人をモジュールと呼ぶらしい。


同じ階層に置く

```console
$ ls -l
-rw-r--r--  1 book  staff  60 Apr  6 00:34 app.py
-rw-r--r--  1 book  staff  58 Apr  6 00:35 run.py
```

```py:app.py 
def app():
  print 123

if __name__ == "__main__":
  app()
```

```console
$ python app.py 
123
```

これをimportする

```py:run.py 
import app
```

```
book:py book$ python run.py 
```

何もでない。`__name__`のとこがimportだと実行されない。

実行部を足すと出る。

```py:run.py 
import app

if __name__ == "__main__":
  app.app()
```

```console
$ python run.py 
123
```

import app は、 import (同じ階層にある)app(.pyと言うなのファイル） として解釈される。

*pythonで実行されたscriptは、同じ階層にある .py ファイルをファイル名から拡張子を除いた名前で import することができる。
なんでやねん。import app.py のほうが2万倍わかりやすいやん・・・

importにはimportとfrom - import - の2種類あって、階層をどこからたぐるかが違う。
↑の例ではapp.pyをappと言う名で読み込んでいる。

```
app.py
 |- def app
```

これをこうだとすると、

```
app.py(1)
 |- def app(2)
```

import app(1)　で from app(1) import app(2) ってことになるらしい。
だから app.app() は app(1).app(2)() で app() は app(2) ってことになる。
いちいちapp.app() てapp.をつけるの面土井時は、fromを使う。

```py:run.py 
from app import app

if __name__ == "__main__":
  app()
```

```console
$ python run.py 
123
```

# モジュールの階層化
app.pyを ./modules フォルダに入れてみる。

```
.
├── modules
│   ├── app.py
└── run.py
```

こうすると走らない。importは同じ階層にしか効かない。不便な奴だ・・・・pathとfile名でincludeできるphpを見習って欲しい・・・・

サブディレクトリをimportしたい場合はおまじないを使う。

```
.
├── modules
│   ├── __init__.py
│   ├── app.py
└── run.py
```

pythonは、実行されたscriptと同じ階層にあるdirectoryを探して、その中に `__init__.py` があると、其のフォルダの中をimport対象として認識する。
`__init__.py`は空でいい。 `$ touch __init__.py` でいい。なんだこの残念仕様。まるでapacheの.htaccessみたいな。残念な仕様だ。

サブディレクトリになると、importはこうなる。

```py:run.py 
import modules.app

if __name__ == "__main__":
  modules.app.app()
```

```console
$ python run.py 
123
```

modules.app.app()って残念すぎません？ サブディレクトリになるとこうしてどんどん深くなっていくので、みんなfromを使い出す。

```py:run.py 
from modules.app import app    <---- [modulesディレクトリ内の app.py] の中の [def app():] をimportしている

if __name__ == "__main__":
  app()
```

```console
$ python run.py 
123
```

わかってきた。

# `__init__.py` とは
`__init__.py`にはpythonコードが書ける。

```py:modules/__init__.py
print "__init__desu"
```

```py:run.py 
import modules.app
```

```console
$ python run.py 
__init__desu
```

# `__init__.py` でimportできるわけではない

scriptは其の周りの`__init__.py`も実行してしまうのなら、ここでipmortすれば他に書かなくてもいいんじゃないか、って思ったけどだめだった

```py:modules/__init__.py
print "__init__desu"
import os
book:py book$ cat modules/app.py
def app():
  print 123

if __name__ == "__main__":
  app()
  print os.listdir() 

book:py book$ cat run.py 
import modules.app

if __name__ == "__main__":
  print os.listdir()
```

```py:modules/app.py
def app():
  print 123

if __name__ == "__main__":
  app()
  print os.listdir() 
```

```console
$ python run.py 
__init__desu
Traceback (most recent call last):
  File "run.py", line 4, in <module>
    print os.listdir()
NameError: name 'os' is not defined
```

ここらへんがphperには辛い事実。pythonのimportは.pyひとつひとつ独立してる。一回動き始めたscriptはあっちでincludeしてればこっちでも使えるが通用しない。辛い・・・

# `__init__.py` に変数がかけるわけでもない？
global とかやっても全然使えなかった。辛い
箱ひげ図の「ひげ」の上端と下端の値を知りたいので関数を自作した

# この記事を書いたきっかけ

統計を勉強し始めると棒グラフにも色々なグラフがあることを知ります。
その中でも初期に出てくるであろう箱ひげ図があります。

<img width="592" alt="スクリーンショット 2019-07-21 23.28.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282698/fcf1aef4-788a-206e-84e9-5d08d5a1c269.png">


箱ひげ図は「最小値, 第一四分位数, 中央値, 第三四分位数, 最大値」を示します。
ただ上記のグラフのようにひげは外れ値がなければひげの上端・下端が最大・最小値になるのですが、男性のように外れ値があると髭の長さは上記のどれにも当てはまりません。

Rやpythonではコードを書くと自動的にひげ（あれば外れ値も）をつけてくれますがひげの上端（下端）の値が実際何なんなのか？が気になったのでRで調べてみました。

# ひげの定義

ひげの定義を`ggplot2`の`geom_boxplot`のヘルプで確認します。

```R
?geom_boxplot
```

> ###A box and whiskers plot (in the style of Tukey)
>（中略）
>The upper whisker extends from the hinge to the largest value no further than 1.5 * IQR from the hinge (where IQR is the inter-quartile range or distance between the first and third quartiles). The lower whisker extends from the hinge to the smallest value at most 1.5 * IQR of the hinge. Data beyond the end of the whiskers are called "outlying" points and are plotted individually.

（要約）
ひげの上端は`箱の上端 + 1.5 * IQRの範囲内にあるデータの最大値`
ひげの下端は`箱の下端 - 1.5 * IQRの範囲内にあるデータの最小値`
IQRは`箱の上端 - 箱の下端`
ひげの外にあるデータは"外れ値"として個別に表示

# Rで関数を作ってみる

```R
wisker <- function(x){
  x_iqr <- IQR(x) #IQR関数でIQRを求める
  wisker_max <- quantile(x, 0.75) + IQR(x) * 1.5 # 上端のひげの取りうる最大値を求める
  wisker_higher <- max(x[x <= wisker_max]) # ひげの範囲内の最大値を求める
  wisker_min <- quantile(x, 0.25) - IQR(x) * 1.5 # 下端のひげの取りうる最小値を求める
  wisker_lower <- min(x[x >= wisker_min]) # ひげの範囲内の最小値を求める
  wisker <- c(wisker_low = wisker_lower, wisker_high = wisker_higher) # 名前をつけて結果をwiskerという変数に入れる
  print(wisker)
}
```

# 実際のデータで試してみる

架空のデータを作る

```R
n_male <- 130
n_female <- 70
set.seed(2019)
height <- round(c(rnorm(n_female, 157, 5), rnorm(n_male, 173, 10)), 0)
sex <- c(rep("female", n_female), rep("male", n_male))
dat <- data.frame(height, sex)
```

箱ひげ図を`ggplot2`の`geom_boxplot`で書く

```R
# tidyverseパッケージをインストールしていない場合は先にインストール
install.packages("tidyverse") 

# インストール後tidyverseパッケージを読み込む
library(tidyverse) # tidyverseパッケージのインストール

# 箱ひげ図を書く
ggplot(data = dat, aes(x = sex, y = height))+
  geom_boxplot()
```

<img width="585" alt="スクリーンショット 2019-07-21 23.12.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282698/9d0fe3b3-42c5-f80d-2bbd-f667fe102c69.png">


自作のwisker関数を使ってみる

```R
# 女性
wisker(dat$height[sex == "female"])
# 男性
wisker(dat$height[sex == "male"])
```

# まとめ（結果）

<img width="288" alt="スクリーンショット 2019-07-21 23.15.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282698/8714cabf-d056-9fa1-394f-d5eee03011ab.png">

外れ値がない女性はひげの上端・下端が最大・最小値になり、外れ値のある男性はグラフのひげと同じ位置を示してくれました。

# おしらせ

統計・プログラミング未経験者向けのRのサイトを運営しています。
[独学で始める統計×データサイエンス](http://www.restorative-pt.tokyo/)

ggplot2を使った箱ひげ図の作り方は[【3-6】Rのggplot2で箱ひげ図を作るgeom_boxplot関数](http://www.restorative-pt.tokyo/archives/18975023.html)で紹介しています。

# 参考

[4-3. 外れ値検出のある箱ひげ図](https://bellcurve.jp/statistics/course/5222.html)（統計web）
CentOS7 & Vagrant & VirtualBox でRails sするまで

世の中にはたくさんこれ系のめもがあるが、
なぜだか一発で環境構築できないことが多いので自分用のめも。

ホストPC：Mac

#VirtualBoxのインストール
公式サイトからインストール
https://www.virtualbox.org/

#Vagrantのインストール
公式サイトからインストール
https://www.vagrantup.com/

#CentOS7を入れる
作業用のフォルダを作成しVagrantfileを作成
vagrant init

Vagrantfileを修正（ipの変更はお好みで）
vi Vagrantfile
config.vm.box = "centos/7"
config.vm.network "private_network", ip: "192.168.33.11"
config.vm.synced_folder ".", "/vagrant", type: "virtualbox"

vagrant up
vagrant ssh
sudo yum -y update

#Gitを入れる
sudo yum -y install git

#rbenvを入れる
git clone https://github.com/rbenv/rbenv.git ~/.rbenv

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

sudo yum install -y openssl-devel readline-devel zlib-devel
sudo yum install gcc

echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile

echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

exec $SHELL -l

rbenvが入ったか確認
rbenv -v

#rubyをインストール
rbenv install --list
好きなバージョン選択
rbenv install 2.6.3
rbenv rehash

インストールされているバージョンを確認
rbenv versions
rbenv global 2.6.3
ruby -v

#Railsを入れる
gem install -N rails
gem install bundler
rails -v

#mysqlを入れる
sudo yum remove mariadb-libs
sudo rm -rf /var/lib/mysql

バージョンを確認
cat /etc/redhat-release

バージョンにあった物を以下で確認してURLをコピーする
https://dev.mysql.com/downloads/repo/yum/

getの後ろにコピーしたURL
yum install https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm

追加パッケージを入れる
sudo yum -y install mysql-community-server

インストールされたかを確認
mysqld --version

sudo systemctl start mysqld.service
sudo systemctl enable mysqld.service

パスワードを取得
sudo cat /var/log/mysqld.log | grep password
パスワードを変更
mysql_secure_installation
全部yで進む

mysqlにログインしてみる
mysql -u root -p

文字コードを修正
sudo vi /etc/my.cnf
2行追加
character_set_server=utf8
skip-character-set-client-handshake

再起動
sudo systemctl restart mysqld.service

sudo yum install mysql-devel

#Rails sする
sudo yum install sqlite-devel
sudo yum install gcc-c++

rails new first_app
cd first_app/
vi Gemfile
以下を追加
gem 'therubyracer', platforms: :ruby

bundle install

rails起動
rails s -b '192.168.33.11'

http://192.168.33.11:3000
にアクセスで立ち上がっているのがわかる

参考：
https://qiita.com/kawa18/items/1ffe398490242d89cf6b
Terminalのカスタマイズ

#はじめに

新しいMacを買ったり、会社のMacがリース切れになって新しくなった時のTerminalのカスタマイズメモです。
毎回ググるのでまとめました。

# テーマをicebergに設定する

[【Mac】ターミナルの設定](http://www.stdio.jp/entry/mac/terminal-setting)を参照します。

# vimのカラースキームを変更する

[vimのカラースキームにhyridを設定する](https://pc.tokuvin.net/vim-hybrid/)を参照します。

#フォントをRicty Diminishedにして、プロンプト表示を変更する

[【Mac】ターミナルの設定](http://www.stdio.jp/entry/mac/terminal-setting#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E7%94%A8%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88Ricty-Diminished%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)を参照する。

フォントは別にインストールしなくてもSF MonoかMenloでもいい。
フォントサイズは14or18じゃないと見にくい。

あとは、好みのaliasを設定して終わり。
素のjavascriptでモーダルメニュー

js理解のためのモーダルウィンドウ

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="open">
        詳細を見る
      </div>
    
      <div id="mask" class="hidden"></div>
    
      <section id="modal" class="hidden">
        <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
        <div id="close">
          閉じる
        </div>
      </section>
     
    <script src="main.js"></script>
</body>
</html>
```
```style.css
body {
    font-size: 14px;
  }
  
  #open, #close {
    cursor: pointer;
    width: 200px;
    border: 1px solid #ccc;
    border-radius: 4px;
    text-align: center;
    padding: 12px 0;
    margin: 16px auto 0;
  }
  
  #mask {
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
    background: rgba(0, 0, 0, 0.4);

  }
  
  #modal {
    background: #fff;
    width: 300px;
    padding: 20px;
    border-radius: 4px;
    position: absolute;
    top: 40px;
    left: 0;
    right: 0;
    margin: 0 auto;
  }
  
  #modal p {
    margin: 0 0 20px;
  }
  
  #mask.hidden {
    display: none;
  }
  
  #modal.hidden {
    transform: translate(0, -500px);
  }
```

```main.js
'use strict';
{
    const open =document.getElementById('open');
    const mask = document.getElementById('mask');

    const modal= document.getElementById('modal');
    const close =document.getElementById('close');
 //openがクリックされたらmask,modalが出てくる。
  open.addEventListener('click',()=>{
    modal.classList.remove('hidden');
    mask.classList.remove('hidden');
  });

  
  close.addEventListener('click',()=>{
    modal.classList.add('hidden');
    mask.classList.add('hidden');
  });
  mask.addEventListener('click',()=>{
    // modal.classList.add('hidden');
    // mask.classList.add('hidden');
    close.click();
  });
}
```
laravelで中間テーブルの論理削除を実装

多対多のモデルを作成するときに、中間テーブルを作成することがあると思います。
中間テーブル自体の作成は簡単ですし、論理削除はlaravelではとても簡単にできようになっています。


しかし中間テーブル(pivotテーブル)の論理削除は、laravelで用意されているものではできなかったため、紹介します。

##AppUserとcouponが多対多で紐づいている

model,controllerそれぞれはAppUser側からみたものです。

coupon側から見たければ逆にしたらOKです

**AppUser,Couponの二つを紐づけるapp_user_couponテーブルでは、deleted_atのカラムを作成しておいてください。**

ここが、nullでなければ（日時が入っていれば）削除済み
という形になります。

###コントローラー

コントローラーは以下のようになります。
論理削除ですので、
app_user_couponテーブルのdeleted_atカラムに現在時刻を入れます。

```php:AppUserController.php

  $app_user = AppUser::find($id);
  $result = DB::table('app_user_coupon')
                ->where('app_user_id', $app_user->id)
                ->where('coupon_id', $request->coupon_id)
                ->update(array('deleted_at' => DB::raw('NOW()')));

```




「論理削除」機能はこれでOKなのですが、例えばAppUserにひもづくcouponを中間テーブルを介して取得したいときなどは、その両者の関係が論理削除であるという前提にたちモデルに条件を実装した上で、取得する必要があります。

###モデル

```php:app/AppUser.php

    public function coupons()
    {
        //中間テーブルで論理削除するために、AppUserにひもづくcouponを取得する時は、app_user_couponのdeleted_atがNULLのものを取得する
        return $this->belongsToMany('App\Coupon')->whereNull('app_user_coupon.deleted_at')->withPivot('get_at', 'use_at')->withTimestamps();
    }

```

中間テーブルから取得したい値がidと作成、更新日時だけであるならば、これだけでいいですが、

```
return $this->belongsToMany('App\Coupon')->whereNull('app_user_coupon.deleted_at')->withTimestamps();
```

もし、中間テーブルのカラムに取得したいものが他にあるならば、以下のように明記する必要があります。

以下は、app_user_couponテーブルにあるget_atとuse_atのカラムを取得する時の例です。

```
return $this->belongsToMany('App\Coupon')->whereNull('app_user_coupon.deleted_at')->withPivot('get_at', 'use_at')->withTimestamps();
```
ソフトウェアの品質管理

プログラムの品質を安定させたい。
安定させるためには、基準が品質の基準を決める必要がある。
品質の基準チェック項目を考えたい。

以下、ykptにコードレビューチェックシートがあったので、これを参考にまとめてみた。
https://yakst.com/ja/posts/1569

| 一般 | コードは動作するか |
|:--|:--|
|  | 想定した役割をはたすか？ |
|  | ロジックは正しいか？ |
|  | すべてのコードは理解しやすいか？ |
|  | 同意されているコード規約に従っているか？|
|  | カッコの位置 |
|  | 関数名 |
|  | 変数名 |
|  | 行の長さ|
|  | インデックスの数|
|  | フォーマット |
|  | コメント |
|  | 冗長、重複されたコードは含まれてないか? |
|  | 可能なが限りモジュール化されているか |
|  | 置き換え可能なグローバル変数はないか。 |
|  | コメントアウトされたままのこーどはないか |
|  | ループ回数は決まっているか？あるいは終了条件は正しいか？ |
|  | ライブラリ関数で置き換え可能なコードはないか。 |
|  | ロギング、デバッグ用のコードは削除されて |
| セキュリティ | 型 |
|  | 長さ |
|  | ファーマット |
|  | エンコードが正しいか？ |
|  | サードパーティ製のユーティリティを使っている場合、えされるエラーを拾って |
|  | 出力値はチェックされ、エンコードされているか？ |
|  | 不正なパラメータの扱いがかかれているか？ |
| ドキュメント | コメントは存在していて、かつコードの意図がきじゅつされているか？ |
|  | すべての関数にコメントは付いているか？ |
|  | 通常と違う振る舞いや特殊な場合の扱いについて、、触れているか？ |
|  | データ構造や数値の単位は説明されているか？ |
|  | 中途半端になっているコードはないか？ |
|  | その場合、その部分は削除されるべるべきか |
|  | あるいはTO DOのような適切な目印でふらくをたてておくべきか？ |
|  | コードはテスト可能か？ |
|  | オブジェクトが初期化出来なくないか？ |
|  | テストフレームワークがメソッドを使えるか？ |
|  | テストが存在しており、かつ理解できるものか？ |
|  | 少なくとも同意されたコードガバレッジを守る程度はあるか？ |
|  | ユニットテストはコードが意図した機能を実現しているよう動作しているかどうかをテストしているか？ |
|  | 配列のout of bound (範囲外のアクセス)エラーはチェックされているか？ |
vagrantでxdebugを使用する方法

#xdebugの仕組み

php本体（vagtrantの中にある）とphp storm(PC本体)を**リモートで接続して**デバックを制御しています。
今回はvagrantにあるphp,xdebugを使い、local（自分のPC）をデバッグしたいので、

```
vagrantのhost(vagrantfileに記載されているもの) => localのPC
```

をデバッグするという機構になります

より詳しい説明はこちらを参考に
https://qiita.com/castaneai/items/d5fdf577a348012ed8af


#xdebugのインストール

```shell
$ sudo yum install --enablerepo=remi-php72 php-xdebug -y
```

#php.iniの設定

####Xdebugモジュールの場所を確認

```shell
$ sudo find / -name "xdebug.so"
```
上記を参考にphp.iniの編集

```shell
$ sudo vi /etc/php.ini
```

```php.ini
[xdebug]
zend_extension=/path/to/Xdebugモジュール(上で確認したやつ)
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.remote_host=10.0.2.2 ;*デバッグ接続するPCのIPアドレス。
xdebug.remote_port=9001 #9000番だとうまくいかないことがあるらしいので
xdebug.idekey="PHPSTORM"
```
各値の詳しい説明はこちらを参考に
https://qiita.com/castaneai/items/d5fdf577a348012ed8af

*デバッグ接続するPCのIPアドレス。
つまり、vagrantから見た、macのhostnameのことですが、「10.0.2.2」と指定するのがお約束らしいです。
これは、「vagrantから見た」なのでdockerなどの他のものを使っているのであれば、この値にはならない（と思います）

####php-fpmの再起動

```shell
$ sudo systemctl restart php-fpm
```

#PHP STORM側の設定

ここからは自分のPCにあるPHP STORMでの設定。

画面の上部の
**PHPStorm -> Preferences**
を選び、

まずは、以下のように

**Languages & Frameworks > Debug**からDebug portの設定をします

ここの9001番はphp.iniに記述したものと同じにします。

<img width="602" alt="スクリーンショット 2019-07-18 9.49.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388525/215ac683-eb50-3266-1c50-44cacede4b86.png">


次に、
上記「Debug」のすぐ下の「Servers」にいき、
vagrantfileで設定しているhostを設定する。

<img width="943" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3338383532352f33613137346533362d356664362d653666342d663533362d3331323732363062336236312e706e67.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388525/aa8b0169-8e7d-b680-33da-785d5d359a33.png">


次にlocalのPCとvagrantのディレクトリをマウントしているのであればその設定を記述。
これもvagrantfileの通り。


<img width="633" alt="スクリーンショット 2019-07-18 10.04.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388525/25c00d2a-69aa-e1fd-2ab1-0526e476b7b0.png">

参考までにvagrantfileは以下のものです。

```ruby:Vagrantfile
Vagrant.configure("2") do |config|

  config.vm.define "app" do |node|
    node.vm.box = "bento/amazonlinux-2"
    node.vm.box_version = "1.0.0"
    node.vm.hostname = "app"
    node.vm.synced_folder "app", "/var/www" #ここと
    node.vm.network :private_network, ip: "192.168.33.10" #ここ 

    node.vm.provider "virtualbox" do |vb|
       vb.memory = "2048"
    end

  end
end
```

次に、今作成したサーバー情報を元に、debugのための設定をしていきます。

メニューの**Run > Edit Configurations**
左上の「+」から、「PHP Remote Debug」を選択し、設定を追加します

以下のような画面になると思いますので、

<img width="741" alt="スクリーンショット 2019-07-18 10.29.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388525/849626a1-3e2f-59d6-6294-55c17b060ca9.png">

Name:好きなもの
Servers:先ほど作成したものをプルダウンから選択
(選択するときは、Filter debug connection by IDE key にチェックを入れてからでないと、選択できません。)
ide key:PHPSTORM

というように作成してください

以上で設定が終わりました。
これでxdebugが使えるようになるはずです。
php html タグから生成

#タグ入力後tab で生成
php storm Emmet　html.css等入力の短縮を補助

簡単に説明すると、
div(a)*2   +`tab`
上記入力で、下記の文が生成される。

```
<div><a href=""></a></div>
<div><a href=""></a></div>
```

ここから本題、
簡単にHTML文を作る分を
テンプレート化


###基本
`html((head)+(body))`

```
<html>
<head></head>
<body></body>
</html>
```
ｐｈｐショートカット

検索
`shift２度押し`

行のブックマーク
`Ctrl + F11`


自動成型系

function Hoge　
`Ctrl + Shift + Enter`


自動成型系
`Ctrl + Alt + L`
設定場所
`[Preferences] - [Editor] - [Code Style] - [PHP]`

足りないパーツ自動生成
ゲッターセッターオーバーライド
`Alt + insert`


HTML操作
コード一括コメントアウト
`Code→Comment with Line Comment` を選択すると

クラス・メソッドドキュメントを表示
`control + j`

選択した行を特定のタグで囲む
`command + alt + t`
https://breaktimes.hatenablog.com/entry/2016/03/11/083648
AWS CLIでSignatureDoesNotMatchになった

# <font color="red">公式の Issue に顛末や対応が載ったので追記します(2020/07/11)</font>

SignatureDoesNotMatch error
https://github.com/aws/aws-cli/issues/602#issuecomment-648952330

* OSとシークレットアクセスキーに含まれた特殊文字の組み合わせによっては、`SignatureDoesNotMatch`に遭遇する
* 最も手軽な対応は、[AWS公式のトラブルシュート](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-troubleshooting.html)にも追記された通り、<b>秘密鍵を再作成して特殊文字が含まれないものを使用する</b>
* このエラーについて情報提供してくれる場合はGithubに[Issueテンプレート](https://github.com/aws/aws-cli/issues/new?assignees=&labels=needs-triage&template=---signaturedoesnotmatch-error.md&title=SignatureDoesNotMatch+error+report)が用意されているのでそれを使ってね

<font color="red">追記ここまで。ここまで読めば問題無いと思います。</font>

# これは何？

AWS CLIでハマったので、対応をメモ。原因は推測。

# エラーの概要

この例では、IAMユーザーをリスト表示しようとして`aws iam list-users`でエラー。
他のコマンドでも、おおむね同じようにエラー。

```
PS C:\dev\terraform> aws iam list-users
An error occurred (SignatureDoesNotMatch) when calling the ListUsers operation: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
```
要するに「署名が合わないからシークレットアクセスキーを確認しろ」と言われている。

# tl;dr

* `C:\Users\$USER\.aws`の`config`、`credentials`を一度削除した
* アクセスキーを新しくした
* キーに特殊文字が入っていると、NGになることがある？

# 環境

* Win10Pro 64bit
* PowerShellからAWS CLI使用
* aws-cli/1.16.201 Python/3.6.0 Windows/10 botocore/1.12.191

# エラーになるまでにやったこと

1. 新しいIAMユーザーを作成し、アクセスキーを発行した
2. `aws configure`コマンドでアクセスキーなどの情報を設定
3. AWS CLIのコマンド発行すると、エラー

# 調べたこと

### 特殊文字？

* [SignatureDoesNotMatch error #602](https://github.com/aws/aws-cli/issues/602)

同じようなエラーについてのissuesを見つけた。
**シークレットアクセスキーに特殊文字が入っているとうまくいかない場合がある**という話が5年も続いている。

私は先頭が`=+`で`/`も含むシークレットアクセスキーを使っていて`SignatureDoesNotMatch`になったが、キーの再作成後は正常動いた。

issuesから一部のコメント。

>I can confirm that recreating my access keys until I got one without special characters in it, worked. What a ridiculous bug, wow.
Seeing as this is such a long running issue, would it not be intelligent to update the error messaging to give users a link to a potential fix, like rebuilding your keys? Instead of something which makes out that the issue is far more complex than "yeah we error out when your keys have special chars in them, sorry!".

>特殊文字が含まれていないアクセスキーを取得するまでアクセスキーを再作成してもうまくいったことを確認できます。 なんてばかげたバグ、すごい。
これは非常に長期にわたる問題であるため、エラーメッセージを更新してユーザーにキーの再構築などの潜在的な修正へのリンクを提供するのは賢明ではないでしょうか。 問題が「あなたの鍵に特別な文字が含まれているとエラーになる」というよりもはるかに複雑であることが判明したものではなく、残念です。

### 環境にもよる？

Windows10では起きた、Macでは同じキーを使っても起きなかった、と言ってる人も。
>Got the same error today, currently using Windows 10. However, when I use the same access key on another laptop (mac), it works fine for me. Then I tried the access key within WSL, which is also fine. Not sure the reason, and there is no special character in the aws key.

>現在Windows 10を使用している、今日も同じエラーが発生しました。ただし、別のラップトップ（Mac）で同じアクセスキーを使用すると、問題なく動作します。それから私はWSL内でアクセスキーを試しましたが、これも問題ありません。その理由はわかりません。awsキーに特殊文字はありません。

# おわり

あんまり詳しくないけどエンコードで勝手に文字追加される類の話なのかなあ。つかれた。
goのhot reloadingにはreflexが便利だった

##### 参考
- [ファイルの変更を検知してなんらかのコマンドを走らせるreflexが便利](https://arata.hatenadiary.com/entry/2017/06/22/201909)
- [ファイルの変更検知と自動ビルドにおすすめのreflex](https://yoru9zine.hatenablog.com/entry/2016/12/06/2139120)
- [Go Docker dev environment with Go Modules and live code reloading
](https://threedots.tech/post/go-docker-dev-environment-with-go-modules-and-live-code-reloading/)

### はじめに

goで自動ビルド&実行探しておりこれでいいやんっていうのを見つけたのでご紹介です

### 結論

[cespare/reflex](https://github.com/cespare/reflex) を使います。これだけ！

```
$ go install github.com/cespare/reflex@latest
$ reflex -r '(\.go$|go\.mod)' -s go run cmd/server/main.go
```

### その他
goのホットリローディングではよく

- [codegangsta/gin](https://github.com/codegangsta/gin)
- [githubnemo/CompileDaemon](https://github.com/githubnemo/CompileDaemon)
- [oxequa/realize](https://github.com/oxequa/realize)

が挙げられているのですがGo Modulesを使っていた場合にすぐ動作しなかったりconfigファイルの準備が必要だったりと面倒だなと言うのが正直な印象でしたの。
reflexはGo以外の言語でも使用できかつ、1ラインでホットリローディングを実現できるのは結構便利です
Entity Framework で Procedure をコールしても、デフォルトの追跡状態だと再取得した値が変わらないよ

[追跡と追跡なしのクエリ - EF Core | Microsoft Docs](https://docs.microsoft.com/ja-jp/ef/core/querying/tracking)

一度値を取得してから Procedure で値を更新して、再度値を取得しても変わらなかったことがありませんか？

原因は EF の追跡機能なので、対策方法は公式に書いてあるとおり `AsNoTracking` を使うか `QueryTrackingBehavior.NoTracking` を使いましょう。 EF Core だけでなく .NET Framework の Entity Framework も同じ動きです。

```csharp
using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .AsNoTracking()
        .ToList();
}
```

```csharp
using (var context = new BloggingContext())
{
    context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

    var blogs = context.Blogs.ToList();
}
```

ちなみに FromSql や ExecuteSqlCommand で Procedure をコール `EXECUTE xxxProc @params` した場合以外にも、生 SQL クエリ (`UPDATE xxxTable SET xxxColmun = @value`) で Update した場合も追跡を解除しないと (たぶん) ダメです。
EF を使う場合はテストコードを書くときくらいしか 生 SQL クエリでデータを追加更新をしないと思うのですが、念の為補足です。

生 SQL の扱いは [生 SQL クエリ - EF Core | Microsoft Docs](https://docs.microsoft.com/ja-jp/ef/core/querying/raw-sql) に記載されています。
AtCoder Beginner Contest 001

## A - 積雪深差

・開始10秒で1敗

```py
print(input()-input())
```

・input()で計算する時は 数値型のキャストを忘れずに

```py
print(int(input())-int(input()))
```

・他のAC
⇒ open関数でもinput関数と同等の事が出来る事を知る（要調査）

```py
a,b=map(int,open(0));print(a-b)
```

## B - 視程の通報

if文書けるマンだからいけた

```py
i = int(input())
s = str()
if (i < 100):
  s = "00"
elif (i <= 5000):
  s = str(int(i / 100))
  s = s.zfill(2)
elif (i <= 30000):
  s = int(i / 1000 + 50)
elif (i <= 70000):
  s = int((i / 1000 - 30) / 5 + 80)
else :
  s = "89"
print(s)
```

・他のAC
⇒ 商のみ表示は // で良かった。(確かにintで括るの面倒だった…)

```py
n=int(input());m=n//100;
print(["%02d"%m,m//10+50,m//50+74,89][(m>50)+(m>300)+(n>70000)])
```
## C - 風力観測

問題文通り、丸め誤差にかなり躓く。
最後のテストケースがACいかんのはなんでじゃ？
（調査中）

```py
def my_round(val, digit=0):
    p = 10 ** digit
    return (val * p * 2 + 1) // 2 / p
 
d, w = map(int, input().split())
i = 0
win_val = ['N','NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW']
win_dict = dict(zip([i for i in range(16)],win_val))
win_spe = my_round((w / 60), 1)
huusoku = [0.25,1.55,3.35,5.45,7.95,10.75,13.85,17.15,20.75,24.45,28.45,32.65]
win_pow = "12"
for i in range(12):
  if win_spe < huusoku[i]:
    win_pow = i
    break
if (win_pow == 0):
  print('C', 0)
else:
  if d < 113:
    print(win_val[0], win_pow)
  else:
    print(win_dict.get(my_round(float(d / 10) / 22.5)), win_pow)
```
AnsibleでWindows向け自作module_utilsの動作確認メモ

AnsibleのWindows向け自作モジュールを作る時に共通処理はmodule_utilsにまとめておきたいと思って簡単な動作確認メモです。

# 各モジュール

動作確認する例モジュールは以下のものです。

```powershell:example.ps1
#Requires -Module Ansible.ModuleUtils.ExampleUtil
#AnsibleRequires -CSharpUtil Ansible.Basic

$spec = @{
    options = @{
        name = @{ type="str"; required=$true; }
    }
    supports_check_mode = $false
}
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)

$r = ReturnTest $module.Params.name

$module.Result.value = $r
$module.ExitJson()
```

動作確認するmodule_utilsは以下のものです。

```powershell:Ansible.ModuleUtils.ExampleUtil.psm1
Function ReturnTest($arg) {
    <#
    .SYNOPSIS
    Function that just return arg
    #>

    return $arg
}
```

単純に `name` 引数で渡された値が `RetrunTest` 関数で戻されて戻り値に入るだけの単純なものです。

ディレクトリ構造は以下のようになっています。

```shell-session
(venv) [root@localhost test]# tree .
.
├── inventory
├── library
│   └── example.ps1
├── main.yml
└── module_utils
    └── Ansible.ModuleUtils.ExampleUtil.psm1
```

# Playbook

main.ymlは以下のように書いています。

```yaml:main.yml
---
- name: Example modul_utils test
  hosts: windows
  gather_facts: no
  tasks:
    - name: example module test
      example:
        name: "Hello, World"
      register: r

    - debug: var=r
```

# 実行

実行してみます。

```shell-session
(venv) [root@localhost test]# ansible-playbook -i inventory main.yml

PLAY [Example modul_utils test] *************************************************************************************************************************************

TASK [example module test] ******************************************************************************************************************************************
ok: [windows01]

TASK [debug] ********************************************************************************************************************************************************
ok: [windows01] => {
    "r": {
        "changed": false,
        "failed": false,
        "value": "Hello, World"
    }
}

PLAY RECAP **********************************************************************************************************************************************************
windows01                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

`module_utils` にある `Ansible.ModuleUtils.ExampleUtil.psm1` の `ReturnTest` 関数が呼び出されて問題なく実行できました。
こんな感じで `module_utils` は作れそう。