OmniAICreator/Qiita-1.07M huggingface dataset:
今後習得したい技術

★目次
1.自己紹介
2.マスターしたい技術
3.現在の業務

【１】
C# WPFをメインで扱う会社。
本年6月より現職
以前は自社でも派遣でも作業するSE会社。
5年間で経験した言語は以下の通り；
C#：  2年5か月
Java：1年6か月
PHP：3か月
HTML・CSS：3か月
Excel VBA：1か月
ラダー    ：1か月（シーケンサ用の組込言語）
C、Mathematica、Matlab（大学時代に少しだけ）

【２】
1.NUnit
2.MVVM
3.Prism
4.Code First（Entity Framework）
5.非同期処理
6.リフレクション
7.追記
■1.NUnit：
単体テスト自動化フレームワーク。使えれば絶対武器になると思っている。
なお、現在の職場は、以前の現場では「結合テスト」と呼んでいたテストを「単体テスト」としている。
私が以前学習（JSTQBテスト認定技術者試験）した、
単体で動くプログラムのテスト－たとえばデバッグによる単一クラスのテスト－
を、通常は「単体テスト」と呼ぶ。
■2.MVVM：
Microsoft の説明が分かりやすい。
https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2009/february/patterns-wpf-apps-with-the-model-view-viewmodel-design-pattern
WPFで画面を閉じる処理が課題だったが、こちらを読みながら作成できた。
■3.Prism：
MVVM用のフレームワーク。職場のVSになぜかインストールできない。
■4.Entity Framework：
職場の環境上、Coreではなく、古いエディションのEntityFramework6を利用している。
DAO（そもそもこの言葉をなんとなくでしか理解できてないが）を作成する手間が減る。
■5.非同期処理：
マルチタスク。以前トライしたことはあるものの、効果的な実用には至らずだった。
当時は例外処理に泣いた。
今度は、その思想まで理解して実用化したい。
■6.リフレクション：
型推論というイメージ。
動的コードの利点は、コード量が減ること。
逆に欠点は、目でコードを見て理解することが難しくなること。
開発期間が厳しい、かつプロジェクトメンバーのレベルが高い場合、このリフレクションが選択肢としてあれば心強い。
■7.追記：
2.MVVM、6.リフレクションについては前職で経験済みだが、理解不足と感じているため。
LINQについても以前は比較的利用していたが、人間使わければ忘れてしまう。
今回、EntityFrameworkにて利用する機会があるのはありがたい。

【３】
現在は研修という名目で、DB更新機能を備えたシステムを一人で作成中。
期間は１か月以上と潤沢。
目的は私の実力を把握するためとのことだが、
私自身は次の２つを目標としている；
・最低限の仕様書を残しながら、プロジェクトを計画から大幅な遅滞なく進めること。
・EntityFramework6、およびNUnit3を利用した開発により、開発時間の短縮、品質の向上を図ること。


以上となります。
ここまで読んでいただき、ありがとうございました。
初めてプロジェクトに参加する人向け　Gitクローンからプルリクエストまで

初めてプロジェクトに参加してGitHubからクローンして、作業をしてプルリクエストを送るまでの一連の流れをまとめました。

#GitHubにアクセスしてクローンする

まずはプロジェクトのURLにアクセスします。
URLにアクセスしたらまずはforkをしておきます。
forkとは他人のリモートリポジトリを自分のアカウントにコピーすることです。

<img width="374" alt="スクリーンショット 2020-07-07 16.53.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593258/c35fb064-b8d1-81b7-5c31-cd27ec6d044c.png">


forkは画面の右上に画像のようなボタンがあるのでそれをクリックします。

forkが済んだらクローンしてみます。

```
$ git clone <URL(これはリモートリポジトリのURL)>
```

#ローカルリポジトリを作成

まずはクローンしてきたディレクトリに移動します。

次のコマンドでリポジトリを作成します。

```
$ git init
```

次にリモートリポジトリを追加します。

```
$ git remote add <追加するリポジトリ名> <追加するリポジトリURL>
```

GitHubアカウントを登録します。

```
$ git config --global user.name <ユーザー名>
```

```
$ git config --global user.email <メールアドレス>
```

#ブランチ

ブランチとはGit の変更履歴を分岐させて記録していくものです。
本番用のmasterブランチにいきなり変更を加えることを避けるために開発用のブランチを用意します。

以下のコマンドで新規のブランチを作成します。

```
$ git branch <ブランチ名>
```

次のコマンドで作成したブランチに移動できます。
基本的にはここで作成したブランチで作業を進めていくことになると思います。


```
$ git checkout <ブランチ名>
```

次のコマンドで作成したブランチの一覧が表示できたら成功です。

```
$ git checkout
```

#コミット

先ほど作成したブランチで作業を行ったらその変更履歴を記録する必要があります。
それを記録する作業をコミットと呼びます。

コミットに先立って、まずはコミットするファイルを選択する作業であるアッドを行います。


```
$ git add <コミットしたいファイル名>
```

変更を全てステージするには以下のコマンド

```
$ git add .
```

アッドが完了したら、変更内容の確認を行う。
以下のコマンド実行することでアッドされているファイルを確認できる。

```
$ git status
```

次のコマンドでファイルの変更箇所を確認できます。

```
$ git diff
```

最後に

```
$ git commit -m <コミットメッセージ>
```

でコミットが終わります。

#プッシュ

変更した履歴をリモートリポジトリにアップロードすることをプッシュと呼びます。

```
$ git push リポジトリ名 ブランチ名
```

コマンドを実行すると完了です。
ブランチ名はheadを選択すると自分がいるリポジトリを選択できるので便利です。

#プルリクエスト

最後にプルリクエストをします。

自分の行った変更を他のメンバーに通知します。

プロジェクトのURLにアクセスし、画像にあるプルリクエストをクリックします。

<img width="902" alt="スクリーンショット 2020-07-07 17.55.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593258/c06d062c-d15f-2d83-5911-720b1f2f7e3a.png">

あとは画面の指示にしたがって行けば完成です。
これを言うと先輩に怒られるよ3選

#はじめに
ITエンジニアはとてもとても~~辛い~~楽しい職種なので、よく先輩からフィードバックを頂けます。
その中でこれを言うと怒られることをあげて見ました。

#その１「エラーが出ました。」
エラーなんてこの仕事をしている以上、人よりも全然出会すわけで、「エラー出ました」って当たり前です。
エラーが出て、どうなのか、困っているのか、めちゃくちゃやばいエラーが出ているのか、伝えてもらわないと困ります。

以下が正しいでしょう。
「エラーが出たんで、◯◯があやしくて、××をしてみたんですが、解決しなくて、助けてください。」

#その２「◯◯について知らないので××できません(でした)。」
なんて辛い仕事なのでしょうか。
知らないこともできないといけないのがこの仕事の特徴です。
そして、知らないことだらけです。
例えば、皆さんPCの電源の入れ方はわかるけど、なんでPCの電源が入るのかわからなくないですか？
まさにggrksの世界。

以下が正しいでしょうか。
「◯◯について知らないので、何かいい勉強の方法か何かもらえますか？」

#その３「こんなレガシーな環境で開発したくありません。」or「この言語で開発したくありません。」
これも言ってはいけません。誰もこんなレガシーでグチャグチャなコードを触りたくありません。
しかし、仕事の中でやらないといけないわけです。お客さんに向かって、「コード汚すぎて無理です」なんて言えないですし、グチャグチャなコードを触れるのは立派なスキルです。

以下が正しいでしょうか。
「このコードの◯◯と××が特に汚いので、このくらいの期間でリファクタしませんか？」


#終わりに
この仕事、辛すぎません？？？
【PHP】 Composer コマンドで tty を Docker につなげて開発したい（TTY as Interactive Shell／対話式シェルで tty）

> `$ composer dev` と打ったら PHP の Docker コンテナを起動して PHP を触りたい。
>
> つまり `composer` の `scripts` 設定で、コンテナにソースコードをマウントしてコンテナ内で開発・デバッグできる状態。
> しかし、`Interactive shell` と表示され終了してしまう。Docker に限らず、他の対話式のシェル・スクリプトでも同じ。

[「composer ユーザーコマンド 対話式 実行 tty interactive shell」でググって](https://www.google.com/search?q=site:qiita.com+composer+%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89+%E5%AF%BE%E8%A9%B1%E5%BC%8F+%E5%AE%9F%E8%A1%8C+tty+interactive+shell&tbs=qdr:y)もドンピシャの Qiita 記事が出てこなかったので、自分のググラビリティとして。

## TL; DR

> `[コマンド] < /dev/tty` で `tty` をコマンドとつなげる。
>
> その際、`Composer\\Config::disableProcessTimeout` も設定しないと、`composer` の[制限で 300 秒で接続が切れてしまう](https://getcomposer.org/doc/articles/scripts.md#writing-custom-commands)。

## TS; DR

以下は３つのユーザー・コマンドを `composer` に設定している例です。ポイントは 3 つ目の `dev` の項目。

```json:composer.json
{
    ...
    "scripts" :{
        "test": [
            "./vendor/bin/phpunit --configuration=./config/phpunit.xml"
        ],
        "compile": [
            "./vendor/bin/box compile --config=./config/box.json"
        ],
        "dev": [
            "Composer\\Config::disableProcessTimeout",
            "docker run --rm --entrypoint='/bin/bash' --workdir='/app' -v $(pwd):/app php:7-cli-alpine < /dev/tty"
        ]
    }
}
```

`composer test` コマンドで PHPUnit を使ってユニット・テストをローカルで実行。`composer compile` コマンドで [Box3](https://qiita.com/KEINOS/items/62653805b554a538d970) を使って `./bin` ディレクトリ設置用の [Phar アーカイブ](https://www.php.net/manual/ja/intro.phar.php)の作成。そして `composer dev` コマンドで Docker の PHP7 コンテナを起動して対話式（`bash` シェル）で触れるようにしている例です。

この時、`composer dev` のメリットは、任意の PHP バージョンで Docker 上で実行できるので、Travis CI で回す前の簡易テストに便利です。

`composer` のユーザー・コマンド経由でターミナルの `tty`（入出力）を Docker に繋げるのがうまく行かなかったのですが、`< /dev/tty` によりターミナルの tty がコンテナに繋がるようになり、SSH した時のような操作感があるので便利です。

> <sup>🐒 &nbsp; <font color=red>注意点</font></sup>
> <sup>ターミナルの種類（macOS のターミナルなど）によってコンテナから `exit` すると `tty` 接続が壊れてターミナルを立ち上げ直さないといけない時があります。これは `composer` が使っている依存パッケージの `symfony` の `console` の仕様です。しかし、VSCode のターミナルからだと `exit` した以降でもローカルに戻ってきます（VSCode を立ち上げ直さなくても大丈夫です）。これは VSCode 側が、戻ってきたらターミナルを初期化をするからです。</sup>

## 参考文献

- [Writing Composer Scripts](https://pantheon.io/blog/writing-composer-scripts) by Greg Anderson @ pantheon.io
- [Interactive PHP script with composer](https://stackoverflow.com/a/57976332/12102603) @ StackOverflow
- [拡張／プラグイン／ユーザーコマンド／カスタム](https://qiita.com/KEINOS/items/86a16b06af6e936a1841#%E6%8B%A1%E5%BC%B5%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0) | 逆引き！Composer コマンド・ライン一覧 @ Qiita
bootstrap3 のタブでfade in

safariでWebアプリを使って頂いているお客様から、iPadのiOSのバージョンを上げたらタブを切り替えると、何も表示されなくなるとの報告を受けた。

言っている意味がわからず、とりあえず手持ちのiPadのiOSのバージョンを上げてみる。
確かに1度は表示さるが、他のタブに行ってから戻ると消えてしまう。

色々試して、原因がtab-paneにつけていた「fade in」であったことが判明。（おそらく）
「fade in」を外したら、消えるという怪現象は起こらなくなった。
Ancestryで親レコードだけ綺麗に取得する方法

Ancestryを使う場合、大半の人がカテゴリーを多層化したいと思うので、モデルは`Category` とします。

## 方法①
シンプルにこう。最上位である親を取得するだけならこれ以外は必要ないのでは？

```rb
# controller or rails console
@category = Category.where(ancestry: nil)
```

https://qiita.com/kazasiki/items/8b5be52da6162b34b2b7

## 方法②
以下のような取得方法もあったが、これだと子カテゴリーをもっていない親カテゴリーが除外されてしまう。

```category_controller.rb

@categroes = Category.where(id: Category.pluck(:ancestry).compact.map { |e| e.split('/') }.flatten.uniq)
```

https://stackoverflow.com/questions/11366663/ancestry-how-to-get-all-parent-without-children

### 解説
:ancestryカラムのID（＝親カテゴリーのID）を抜き出して、そのIDのカテゴリを取得してね、ということをやっている。

```rb
# 基本的な構造は「IDがarrayのものを取得してね」というもの
@categories = Category.where(id: array)
```

以下は下から読んで、1個ずつ何をやっているか紐解いていった方が理解できる。

```rb

> Category.pluck(:ancestry).compact.map { |e| e.split('/') }.flatten.uniq > # uniqで重複を除外
   (0.2ms)  SELECT "categories"."ancestry" FROM "categories"
=> ["27", "49", "50", "8", "88", "90", "91", "93", "94", "95", "96", "97", "98"]

> Category.pluck(:ancestry).compact.map { |e| e.split('/') }.flatten # flattenでネストしている配列を平坦化する
   (0.2ms)  SELECT "categories"."ancestry" FROM "categories"
=> ["27", "27", "49", "50", "50", "50", "50", "50", "8", "8", "88", "88", "88", "88", "90", "90", "90", "90", "90", "91", "91", "91", "91", "91", "93", "93", "93", "93", "93", "94", "95", "95", "95", "95", "95", "95", "96", "96", "96", "96", "97", "97", "98"]

> Category.pluck(:ancestry).compact.map { |e| e.split('/') } # 孫カテゴリーをバラす？ただしmapを使うと返り値が配列になってしまう模様（今回は孫カテゴリーがなかったので意味無し）
   (0.2ms)  SELECT "categories"."ancestry" FROM "categories"
=> [[], ["27"], ["27"], ["49"], ["50"], ["50"], ["50"], ["50"], ["50"], ["8"], ["8"], ["88"], ["88"], ["88"], ["88"], ["90"], ["90"], ["90"], ["90"], ["90"], ["91"], ["91"], ["91"], ["91"], ["91"], ["93"], ["93"], ["93"], ["93"], ["93"], ["94"], ["95"], ["95"], ["95"], ["95"], ["95"], ["95"], ["96"], ["96"], ["96"], ["96"], ["97"], ["97"], ["98"]]

> Category.pluck(:ancestry).compact # compactで:ancestryがnilのものを除外
   (0.2ms)  SELECT "categories"."ancestry" FROM "categories"
=> ["", "27", "27", "49", "50", "50", "50", "50", "50", "8", "8", "88", "88", "88", "88", "90", "90", "90", "90", "90", "91", "91", "91", "91", "91", "93", "93", "93", "93", "93", "94", "95", "95", "95", "95", "95", "95", "96", "96", "96", "96", "97", "97", "98"]

>  Category.pluck(:ancestry) # :ancestryカラムの値を取得する
   (0.3ms)  SELECT "categories"."ancestry" FROM "categories"
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "", "27", "27", "49", "50", "50", "50", "50", "50", "8", "8", "88", "88", "88", "88", "90", "90", "90", "90", "90", "91", "91", "91", "91", "91", "93", "93", "93", "93", "93", "94", "95", "95", "95", "95", "95", "95", "96", "96", "96", "96", "97", "97", "98"]
```

## 方法③
日本語記事だと以下のように、「親カテゴリは上から13個までだから`limit`でやろう」というやり方しか見つからなかったが、親カテゴリを後から追加したくなったりしたときは書き換えないといけないから嫌だった。

```category_controller.rb

@categories = Category.all.order("id ASC").limit(13)
```
Formsのエクセルデータから出席リストを作成するWebアプリケーション

　コロナ禍から，大学などではオンライン講義が積極的に採用されています。
　講義もかなり進み，先生方は受講者の出席や成績をどのようにまとめるかについて考え始めた頃ではないかと思います。
　私が所属する大学ではMicrosoft 365を採用していることから，出席や課題をFormsを利用しています。Forms自体はとても有用なツールですが，各回講義で得られるエクセルファイルをまとめるのは大変な作業になりそうです。もちろん関数を駆使して多数の記録を１つにまとめることは可能ですが，すべての先生方が関数を扱えるわけではありません。
　そこで，Formsから得られたエクセルファイルを１つにまとめ，受講生が回答したか否か（出席に該当），課題を含んでいた場合は合計得点は何点かを要約するWebアプリケーションを作成しました。

https://attendance-summary-with-forms.netlify.app/
![screenshot-attendance-summary-with-forms.netlify.app-2020.07.07-17_27_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381716/0d8fd672-3aba-615d-6bff-383ee61fabb0.png)

# 使い方
1. Formsから得られたエクセルファイルをフィールドにドラッグアンドドロップするか，「Drag and drop files or click here」をクリックして，ファイルを選択する。
2. 「遅刻」の設定をしたい場合は，Dateピッカーなどを利用して時間を指定する。
3. 「Create Summary」をクリックすると，選択されたファイルを１つにまとめたエクセルファイルがダウンロードされます。

# Note
1. 選択されたファイルはすべてローカルで処理されるため，データが外部に送信されることは一切ありません。
2. Microsoft 365にログインしていない（＝メール列が「anonymous」になっている）受講者の記録は集計しません。
3. エクセルファイルの「メール」・「名前」・「開始時刻」・「合計点数」列を抽出し，「メール」を軸として集約・集計します。
4. アプリはサーバーの無料枠で運用しています。利用者が多くなった場合，無料枠を超過して利用できないかもしれません。その場合は月が変わってから再度お試しください。

# ソース
　ソースコードは以下です。
https://github.com/Hironori-Abe/attendance-summary-with-forms
　開発はAngularなどを利用しています。
React npm ERR! 解消メモ

#はじめに
暑くなってきて季節はもう夏ですね。
そんな暑い中エラーが出ると汗がだらだら。自分の代謝を恨みます。
就職を目指す駆け出しエンジニアの記事ですが、見てくださると嬉しいです！

#npm ERR!
React学習途中、npm startを実行するとnpm ERR!が吐かれました。
<img width="749" alt="スクリーンショット 2020-07-07 16.55.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613471/a9c2aed4-2e95-321d-b130-f58806463933.png">

#解消までに試したこと
###To fix the dependency tree, try following the steps below in the exact orderに従ってみる

解決のための手順を示してくれているので、とりあえず1から4まで実行してみました。
**1.package-lock.jsonをprojectフォルダーから消去**
**2.同じくnode-modulesも消去**
**3.package.jsonのdevDependenciesのjestを消去**
**4.パッケージマネージャーを基にnpm install**
#####↓
解決されませんでした。

###jest??
ここで、少しじっくりみるとこの部分が気になりました
<img width="521" alt="スクリーンショット 2020-07-07 17.14.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613471/d6757943-34a2-8869-09aa-14e55ea260ac.png">
jestがエラーを起こしていそうですね。
（ jestはテストに利用していました。)
<img width="584" alt="スクリーンショット 2020-07-07 17.22.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613471/16af756f-029b-9ec3-0e68-1fc32b09d16b.png">
どうやらcreate-react-appを実行した際に、既にnode-modulesのなかにjestがインストールされており、手動でinstallしたjestとバージョン違いが発生していたのかもしれません。
**package.jsonからjestとbabel-jestを消去して、node-modulesも消去後もう一度npm installしてみます。**
#####↓
npm startが通りました
<img width="330" alt="スクリーンショット 2020-07-07 17.27.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613471/a1c7a6d6-d408-4986-895d-b1ba38cff29e.png">

#まとめ
早く解決できて良かった！！
LINE風吹き出しCSS

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="ririli" data-slug-hash="JjGLNvJ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="line-like">
  <span>See the Pen <a href="https://codepen.io/ririli/pen/JjGLNvJ">
  line-like</a> by ririli (<a href="https://codepen.io/ririli">@ririli</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


吹き出しが使いたい場面って結構多いですよね。
でも実装はそんなにシンプルじゃないので画像で済ませちゃう人も多いかも。

わかってみれば意外と難しくないので挑戦してみてください。

## ポイント
なんといっても下にちょっと突き出たとこ、これがやりたいわけですよね。
実装では以下が該当します。

```CSS
.left:after {
  position: absolute;
  content: '';
  top: 100%;
  left: 10px;
  border: 15px solid transparent;
  border-top: 15px solid #e0edff;
  width: 0;
  height: 0;
}
```

具体的にはborderとborder-topですね。
borderで透明な太い線をひきます。
その上にborder-topで上だけに色をつけます。

これで三角の完成です。
あとは適切な場所に配置するだけ。


...とはいかないですよね。


## なんで三角になるわけ？
おそらくborder-topを指定しただけでどうして三角形になるのか疑問が出た人も多いと思います。
かくいう僕もそうでした。

もし手元に試せる環境があったら以下のcssを当ててみてください。

```css
  border-top: 5px solid red;
  border-left: 5px solid blue;
  border-tight: 5px solid green;
  border-bottom: 5px solid yellow;
```

色の違う4本の線で四角形ができたでしょうか？
では線同士がぶつかる角の部分はどうなっているでしょうか？
どちらかで埋まっているのではなく色が半分ずつになっていませんか？

これがborder-topで三角になる理由です。
yahoo web api キーフレーズ タグ 取得

キーフレーズ抽出、タグ付け。
といえば、やっぱりヤフーAPI。

無料で使えて嬉しいなぁ。
guzzle とかで http post 通信しても良いが、イマイチパラメーターの渡し方がわからないので、curlを使いましょう。

これ、タグが一個のときは、Resultが配列で帰ってこないので注意する。


```

$sentence = trim(str_replace(["\r\n", "\r", "\n"], '', strip_tags($body)));


$api = 'https://jlp.yahooapis.jp/KeyphraseService/V1/extract';
$params = [
    'sentence' => $sentence
];

$ch = curl_init($api);
curl_setopt_array($ch,
    [
        CURLOPT_POST           => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_USERAGENT      => "Yahoo AppID: ".config('app.yahoo_web_api_client_id'),//要設定
        CURLOPT_POSTFIELDS     => http_build_query($params),
    ]
);

$result = curl_exec($ch);
$res = simplexml_load_string($result);

curl_close($ch);

return $res;


```

# 結果

```

SimpleXMLElement Object
(
    [Result] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [Keyphrase] => 答え
                    [Score] => 100
                )

            [1] => SimpleXMLElement Object
                (
                    [Keyphrase] => 夢
                    [Score] => 80
                )

        )

)

```


形態素解析のデータの場合、[0]とかいうのがあって、 array_shift でも取り出せないのがある。その場合は、こんな感じで

`(string) $v->surface[0]` ってのが味噌

```

$res = [];
foreach ($data->ma_result->word_list->word as $v) {

    if(!empty((string) $v->surface[0])){
        
    }

}

```
HaskellでFunctorを使って簡単な複素数の足し算プログラムーその2

#HaskellのFunctorで簡単な複素数足し算プログラム

前回の記事（[HaskellでFunctorを使って簡単な複素数の足し算プログラム](https://qiita.com/oskats1987/items/4e0216a6e6a7889008f5)）では、あまりうまくできず、無理矢理なプログラムになりました。
今回は、Applicativeも使ってみました。

ただ、既存のライブラリのFunctorやApllicativeでは、どうしてもできなかったため（方法はあるか？）、その二つのクラスから定義しました。

また、前回の記事でコメントを頂いて、それを参考にさせて頂きました。ありがとうございます。

##プログラム

```haskell:complex.hs
data ComplexNumber n = Z n n

class ComplexFunctor t where
    cfmap :: (a -> b) -> (a -> b) -> t a -> t b

class (ComplexFunctor c) => ComplexApplicative c where
    cpure :: a -> a -> c a
    (<**>) :: c(a -> b) -> c a -> c b

instance ComplexFunctor ComplexNumber where
    cfmap func1 func2 (Z a b) = Z (func1 a) (func2 b)

instance ComplexApplicative ComplexNumber where
    cpure a b = Z a b

    (Z func1 func2) <**> c = cfmap func1 func2 c

main::IO()
main = do
    let ans = cpure (+) (+) <**> Z 1 2 <**> Z 3 4

    let a = (\(Z a b) -> (a,b) ) ans

    print a
```

##解説

```haskell
data ComplexNumber n = Z n n
```

`Z n n`は、実部と虚部をそれぞれ組み合わせた複素数を表しています。

```haskell
class ComplexFunctor t where
    cfmap :: (a -> b) -> (a -> b) -> t a -> t b

class (ComplexFunctor c) => ComplexApplicative c where
    cpure :: a -> a -> c a
    (<**>) :: c(a -> b) -> c a -> c b
```

いろいろと試しましたが、標準ライブラリのFunctorやApplicativeではできなくて、ここから自作することにしました。

```haskell
instance ComplexFunctor ComplexNumber where
    cfmap func1 func2 (Z a b) = Z (func1 a) (func2 b)

instance ComplexApplicative ComplexNumber where
    cpure a b = Z a b

    (Z func1 func2) <**> c = cfmap func1 func2 c
```

インスタンスです。よく見る形をちょっと変えたものです。

```haskell
    let ans = cpure (+) (+) <**> Z 1 2 <**> Z 3 4
```

`main`関数の実際に複素数の足し算をしているプログラムです。
これもよく見る形をちょっと変えたものです。

##分かったこと

今回分かったことは、Haskellは難解だけど、楽しそうだと言うことです。
標準FunctorやApplicativeではできず、自作してしまいましたが、本当に標準でできないかは、もう少し考えて見る必要がありそうです。
`main`関数の

```haskell
    let ans = cpure (+) (+) <**> Z 1 2 <**> Z 3 4
```

の部分で、

```haskell
    let ans = cpure (+) (+) <**> Z 1 2 <**> Z 3 4 <**> Z 5 6
```

はエラーになってしまいます。`Z 3 4`の計算した時点で、3つ目の`<**>`の左辺が関数ではなくなるからです。

```haskell
pure f <*> Just x <*> Just y <*> Just z <*>....
```

あるHaskell解説書では、3つ以上`<*>`が繋げられるようなことも書いてあります。
`f`が、それだけ引数を持っているということですね。
VBA：列の値をループを使わずに一括結合

# Range.formulaArrayを使う。

- **[配列数式](https://support.microsoft.com/ja-jp/office/%E9%85%8D%E5%88%97%E6%95%B0%E5%BC%8F%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B-e43e12e0-afc6-4a12-bc7f-48361075954d)** をVBAのコードで利用する。
- 下記のコードを実行すると、AからD列の文字を一括で結合してF列に設定する。

```vb
Sub joinColValues()
 Sheet1.Range("F2:F10000").FormulaArray = "= A2:A10000 & B2:B10000 & D2:D10000 & E2:E10000"
End Sub

```

- 以下、実行結果。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15972/1fd936aa-2a0b-0fcc-d06e-ada0b793de66.png)

- 数学でいう行列の考え方を利用すると、集合に対して一括で処理を実行できる。
AWSハンズオン実践メモ  〜サーバーレスアーキテクチャで翻訳 Web API を構築する〜

# はじめに
AWS公式の[ハンズオンシリーズ](https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/?trk=aws_blog)の中から、翻訳 Web API の構築を通して、サーバーレスアーキテクチャの基本を学ぶ[ハンズオン](https://pages.awscloud.com/event_JAPAN_Hands-on-for-Beginners-Serverless-2019_LP.html?trk=aws_introduction_page)を実施しました。

本記事は自身のハンズオン学習メモとして投稿します。
# 目次
- [ハンズオンの目的](#ハンズオンの目的)
- [本編](#本編)
- [おわりに](#おわりに)

# ハンズオンの目的

- AWS Lambda, Amazon API Gateway, Amazon DynamoDB の基本を学ぶ
- 上記のサービスを組み合わせて、サーバーレスな Web API を作成する

>翻訳 Web API の構築を通して、サーバーレスアーキテクチャの基本を学んでいただきます。サーバーレスアーキテクチャの特徴とその中核となる AWS サービスの概要をお伝えした上で、実際に手を動かしてその理解を深めることができます。主に取り扱う AWS サービスは AWS Lambda、Amazon API Gateway、Amazon DynamoDB の3つです。

![20200706.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646352/34581638-1efa-3bac-04e9-7d1ffbeb51fe.png)
(https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-hands-on/ より引用)

# 本編

### AWS Lambda ハンズオン① - AWS Lambda を単体で利用する

- Lambda Functionを作成
- IAMロールを自動生成し、付与
- メモリとタイムアウト値を変更
- テストを実行
- log取得のコードを追加

### AWS Lambda ハンズオン② - AWS Lambda から他の AWS サービスを呼び出す

- Python SDK のドキュメントを⾒ながら、Amazon Translate の呼び出しを実装
- IAM ロールを修正
- レスポンスとして、JSON 形式で英語訳を返すようにする
- Lambda 関数をテスト実⾏

### Amazon API Gateway ハンズオン① - Amazon API Gateway を単体で利用する

- Mock データを返す API を作成
    - 新規に API を作成
    - sample リソースを作成し、GETメソッドを作成
    - 統合タイプとして Mock を選択（まだ Lambda 関数との連携は⾏わず、固定の JSON を返す）
    - dev ステージにデプロイする
    - API を試しに実⾏

### Amazon API Gateway ハンズオン② - Amazon API Gateway と AWS Lambda を連携する

- ⼊⼒した⽇本語を英語に翻訳するAPIを作成
    - /translate リソースを作成し、GET メソッドを作成
    - 統合タイプとして Lambda 関数を選択
    - プロキシ統合を設定し、Input / Output をパススルーする
    - メソッドリクエストでクエリパラメータの設定
    - Lambda 関数を修正
    - Lambda 関数をテスト実⾏
    - API をデプロイ

以下のようにクエリ部分にリクエストを入力し送信すると、翻訳結果が返却される。

![20200714_translate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646352/9a3468db-b445-130d-53f6-d781f0aea939.png)



### Amazon DynamoDB ハンズオン① - Amazon DynamoDB テーブルを作成する

- DynamoDB のテーブルを作る
    - Partition Key として timestamp を指定
    - テーブル作成
    - データを⼿動で入力


### Amazon DynamoDB ハンズオン② - AWS Lambda から Amazon DynamoDB に Item を Put する

- 翻訳履歴を DynamoDB にストアするように修正
    - Python SDK のドキュメントを⾒ながらDynamoDB にストアするように Lambda 関数を修正
    - IAM ロール設定を修正
    - API を叩いて確認

以下のように翻訳結果がdynamoDBに蓄積される。

![20200714_dynamodb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646352/4f2579d7-e114-bb5e-2f27-d87a5e5778f5.png)


### 作成した AWS リソースの削除
粛々と削除。特筆すべきことはなし。

#おわりに


Lambda、API Gateway、DynamoDBを触った事がなかったので、いい経験になった。

今回初めてサーバレスアーキテクチャを体験したが、基盤レイヤーを考慮せずにアプリケーション部分のみに集中できるのはやはり便利だと感じた。

Lambdaで軽い処理を入れる、等は今後仕事でも使う機会が多いと思うので、実装に必要となるコーディングスキルも併せて身につけていかなければならないなと感じた。
iOS 13 起動時／終了時メモ

## 従来の処理ができない。
iOS13から次のメソッドが効かなくなったようです。 Xcodeから新規にプロジェクトを作成した時は注意。
 ・ applicationDidBecomeActive
 ・ applicationWillResignActive
 ・ applicationDidEnterBackground
 ・ applicationWillEnterForeground

## 代わりの処理を用意する
NotificationCenterを利用する。起動時／終了時のイベント名がUIScene系列で定義されているのでそれを利用する。

```swift
func application(_ application: UIApplication,
                    didFinishLaunchingWithOptions launchOptions: 
                    [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

    NotificationCenter.default.addObserver(self, 
         selector: #selector(appWillResignActive(_:)), 
         name: UIScene.willDeactivateNotification, object: nil)

    NotificationCenter.default.addObserver(self, 
        selector: #selector(appDidBecomeActive(_:)), 
        name: UIScene.didActivateNotification, object: nil)
        
    return true
}
```

呼び出すメソッドを定義。

```swift
@objc func appWillResignActive(_ application: UIApplication) {
        
}
    
@objc func appDidBecomeActive(_ application: UIApplication) {
        
}
```
テスト自動化エンジニアが読むべき必須書籍一覧

##**テスト自動化エンジニア**が読むべき必須書籍をまとめてみました。:point_down_tone3:

## ①[実践アジャイルテスト](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%83%86%E3%82%B9%E3%83%88-%E3%83%86%E3%82%B9%E3%82%BF%E3%83%BC%E3%81%A8%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%83%81%E3%83%BC%E3%83%A0%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-Architects-Archive%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E3%81%AE%E5%AE%9F%E8%B7%B5-Gregory/dp/4798119970/ref=cm_cr_arp_d_bdcrb_top?ie=UTF8)

絶版本なので見つけたら連絡して下さい！:yum:
**Agile**は基本的に**自動テスト**をベースにし進めるべきだと思う。

##②[テスト駆動開発](https://www.amazon.co.jp/dp/B077D2L69C/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
これは、[**TDD**](https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA)の基礎知識として進める際の良書です。
翻訳し直して再販された。

##③[Agile Testing Condensed](https://www.amazon.co.jp/Agile-Testing-Condensed-Introduction-English-ebook/dp/B07YR4CC4B)
最新の自動テストの話が面白い
②の実践アジャイルテストの本のあとに読むと良い。
**テストピラミッド**の 考え方を一歩進められると思います。

## ④[初めての自動テスト](https://www.oreilly.co.jp/books/9784873118161/)
テスト自動化の全体像をつかめるので、これを最初に読むことをおすすめします。
当社の社員も先ずはこれを読む事からスタートします。
[英語版]
(https://www.amazon.co.jp/Way-Web-Tester-Beginners-Automating/dp/1680501836)

## ⑤[Selenium実践入門](https://gihyo.jp/book/2016/978-4-7741-7894-3)
内容は基本的な事だし、オーソドックスな事ばかりですが、コーディングしながら進められる。
動かして覚えるならこれが一番！
日本語しかありません。

## ⑥[Seleniumデザインパターン & ベストプラクティス](https://www.oreilly.co.jp/books/9784873117423/)
こちらも[Selenium](https://ja.wikipedia.org/wiki/Selenium_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2))の基本。

## ⑦[システムテスト自動化　標準ガイド](https://www.shoeisha.co.jp/book/detail/9784798139210)
こちらもシステムの自動化の基本となる。



**その他は**
[Clean Code アジャイルソフトウェア達人の技]
(https://www.amazon.co.jp/Clean-Code-%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%81%94%E4%BA%BA%E3%81%AE%E6%8A%80-Robert-C-Martin/dp/4048930591/)
[Clean Coder プロフェッショナルプログラマへの道]
(https://www.amazon.co.jp/Clean-Coder-%E3%83%97%E3%83%AD%E3%83%95%E3%82%A7%E3%83%83%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%B8%E3%81%AE%E9%81%93-Robert-C-Martin/dp/4048930648/)



さあ！読んでみましょう！:v_tone2:
[iOS]project.pbxprojなどのマージコンフリクト解消を最速でやるには

### おすすめツール

- Visual Studio Code

project.pbxprojファイルに限らないが、ファイル内にコンフリクトマーカーがある場合、そこを色付けで表示し、一発で飛べる。その上、「Accept Incoming Change」「Accept Current Change」「Accept Both Changes」の各ボタンが用意されており、ワンタッチで「マージされてきたブランチ」「現在のブランチ」「両方のブランチ」の変更を適用する事ができる。その他、軽く使いやすいためおすすめ。

### 解消の考え方

`project.pbxproj`ファイルは、プロジェクト内にあるファイルの定義およびそれらのフォルダ階層構造などを定義している。そのため、マージ（またはチェリーピック）するブランチ同士でファイルの位置が違ったり、新規ファイルを追加したりしていると必ずマージコンフリクトを起こしてしまう。

まず、現在のブランチと、マージによって持ってきたブランチで、ファイル・フォルダの階層構造がどう違っているかを確認する。

その上で、マージ後はどういった階層構造にしたいのかを決める。

その後は、その通りになるように`pbxproj`の記述を編集していけば良い。

どういった状態にしたいかによって、
「現在のブランチの変更を受け入れる」
「持ってきたブランチの変更を受け入れる」
「両方の変更を受け入れる」
で済むこともあるし、変更を手動で調整する必要がある場合もある。

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

#### コンフリクトを全て解消したはずだが、エラーが出る

エラーメッセージを読むと、pbxprojファイルの何に問題があるのか基本的には書いてある。

よくあるのは、同じ名前のファイルが二箇所で重複定義されている、逆に消してしまったはずの存在していないファイルを参照しているなど。マージコンフリクトがあった箇所とは違う箇所にこうしたエラーが生ずるのもよくある。

また、文法が間違っていると言われることがあるが、これはpbxprojファイルを編集中に誤って不要な文字を入れてしまったり、必要な文字まで消してしまったりして、記述の形式がおかしくなっていることが多い。問題のある箇所が何行目かもエラー文で教えてもらえるはずなので、そこを直す。

#### `.xcworkspace`ファイルが開けなくなる

- Xcodeのクリーン、Derived Dataの削除、再起動などを試す。
- `.xcworkspace`を一回消してから作り直す（`pod install`をもう一回叩くなど）
デバイス、Linuxファイルシステム、FHS ①忘備録　パーティションとファイルシステムの作成・ファイルシステムの整合性の保持

##fsckコマンド
![名称未設定5.png 555.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/accaf5dc-5bd3-4021-0f67-677c4953cfde.png)
##ハードディスク
SCSI接続のハードディスク→/dev/sda
カーネル2.6.18より前のIDE接続のハードディスク→・/dev/hda

##dfコマンド
inodeの使用状況はこれで確認できる。
![名称未設定5.png 3333.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/e0816f6b-f3a8-0f17-a0c2-f1d90f0db590.png)


##parted
MBR式、GPT式のパーティションテーブルをサポートするパーティション操作コマンドのこと。

##e2fsckコマンド
e2fsckコマンドは、ext2/ext3/ext4ファイルシステムのチェック、および問題を修復することができます。
![名称未設定5.png11111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/7347f517-89f6-928a-64fa-fd691d132dc5.png)

##debugfs
ファイルシステムの対話的なデバッガとして利用できるコマンドはこれ。
xt2/ext3/ext4ファイルシステムの状態の調査・変更を行えます。

##fsckコマンド
ファイルのシステムチェック、及び問題を修復することができます。


##duコマンド
ファイルやディレクトリが占めている要領はこのコマンドで確認できる。
![名称未設定.pngw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/deab5c58-ecbb-360d-5aaf-541fb37789bd.png)

##partedコマンドで新しいHDDにパーティションを作成するには、以下の手順。
１．パーティションテーブルの指定
mklabel サブコマンドで、パーティションテーブルの方式を指定します。未指定の場合MBR形式として動作します。
mklabel サブコマンドの書式は以下のとおりです。

(parted) mklabel [ パーティションテーブル ]

MBR形式を明示的に指定するには、msdosを指定します。
(parted) mklabel msdos

２．パーティションの作成
mkpartサブコマンドで、パーティションを作成します。
mkpartサブコマンドの書式は以下の通りです。

(parted) mkpart [ パーティションタイプ ファイルシステム種別 パーティション名 ] 開始位置 終了位置

パーティションタイプはMBR形式で指定可能で、primary（基本）、extended（拡張）、logical（論理）を指定します。
先頭にext4ファイルシステムとして利用する一つの1000MBの基本パーティションを作成するには、以下のように指定します。
(parted) mkpart primary ext4 1 1000MB

##gdisk
GPT形式のHDDに置いて、パーティションの作成、削除、変更及び情報表示できるコマンドはこれ。

##fdisk
MBR形式のHDDへのパーティション操作を行うコマンド
fdiskで作成したパーティションを利用するには、パーティションにファイルシステムを作成する必要がある。
①mke2fsでext2/ext3/ext4ファイルシステムを作成できます。
②mkfsコマンドでは「-t」オプションで、ext2/ext3/ext4のみならずreiserfs、xfsなどのファイルシステムを指定し、作成できる。

![名称未設定5.png1111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/5e1c7b57-d1dc-d429-5504-3cf7c0ab11b8.png)


mkfsはデフォでext2を作ってくれる。

![名称未設定.pngクェ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/55e21da0-3fe7-9501-6224-76edce05f656.png)


##XFSファイルシステム
XFSは、シリコングラフィックス社（SGI）が開発したジャーナリングファイルシステム
→ジャーナリングファイルシステムとは、ファイルシステムの種類の一つで、管理領域を変更する際にジャーナルあるいはログと呼ばれる更新履歴を残すことで管理領域の破損を防ぐ機能を持ったもの

ex2はジャーナリングシステムとは言えない。

mkfs.xfsでファイルシステムを作成する。

##fsckとe2fsck
ファイルのシステムチェック、及び問題を修復することができるコマンド。
e2fsckコマンドもext2/ext3/ext4ファイルシステムのチェック
![名称未設定.pngっm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/02affa8a-1f68-a86d-ebff-59ae9e1c01f2.png)

##tuneコマンド
ext2/ext3/ext4ファイルシステムのパラメータを設定するコマンド。
![名称未設定.pngあsd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620109/d37fadda-132c-243f-d379-20c78199649c.png)

tune2fsコマンドでは、ext2から３に変換する際のコマンドで使われる。
ext2/ext3/ext4ファイルシステムのパラメータを設定するコマンドでもある。

※dumpe2fs
ext2/ext3/ext4ファイルシステムの各種情報を表示するコマンドです
railsでrspecを使用中にハマったこと

初心者がrailsでrspecを用いてテストを記述する際にハマったことを残しておきます。

rspecでcontrollerのテストを試みたところエラーが頻発しました。どこを直してもうまくいかなかったので、一度参考サイト通りに記述し、何が問題かを調査することにしました。しかし、それでもうまくいかない。。。
そこで設定を見直したところ、controllerのテストはrails5から非推奨になっており、以下のように変更する必要がありました。

model　　　　　　 →　model(そのまま)
controller　　　　 →　request
画面遷移のテスト　→　system

のようにフォルダを作成する必要があり、rails_helperの設定も上記にならい記述する必要があった。
参考記事はcontrollerとrequestが混在しているため注意する必要がある。

また、最近のrailsではコントローラーのテストは非推奨になり、
create,destroy,edit,updateのテストが記述してあれば十分になったらしい。
【2023年7月最新版】CentOS7(yum)でGitの2系をインストールする

毎回調べて時間がかかるのでメモ
~~今どきCentOS7なんて使ってる人いないよね~~

```bash:
$ sudo yum remove git*
$ sudo yum -y install https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm
$ sudo yum install git
```

# 出典
* https://juejin.cn/post/7071910670056292389
UITabBarItemにシステムアイコンをセットする

## はじめに
掲題の通り、UITabBarItemにシステムアイコンをセットする方法がなかなか見つからなかったため、備忘録として残す

## 設定方法
以下のように引数Imageに　UIImage(systemName: "アイコン名")を設定するだけ
アイコン名は以下から取得可能
https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/system-icons/

```swift
v.tabBarItem = UITabBarItem(title: R.string.localizable.bookList(), image: UIImage(systemName: "book"), tag: 0)
```


以上！！！
railsで開発中にAWSから高額請求されたが、、

はじめに以下の記事にあるように、railsでアプリを開発中に初期設定のミスが原因で高額請求に至った。
https://qiita.com/381704/items/d5216295eadd67eb9e8c

完全に注意不足であり、しっかり利用してしまったあとなので支払うしかないと思っていたが、駄目元でAWSのサポートセンターに以下のようなメールを送ってみた。(本文を載せるのは抵抗があったが、証拠&同じ状況の人の希望になればと思い残しておく)
<img width="816" alt="スクリーンショット 2020-07-07 16.17.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588916/e9b74d8d-1c27-8783-4187-a19dba3d81af.png">

2日後にAWSサポートより返信が来た。返信内容には、現在料金が発生しているRDSのインスタンスとスナップショットの削除をすることとあり、その後に返金が可能かの相談にはいるということだ。
内容通り、RDSの削除をして再度AWSに削除完了のメールを送信した。
その2日後AWSサポートより返答があり、今回に限り返金措置を設けてくださるとのこと！！！

請求料金は合計600＄以上になったが、AWS様より返金をしてくださり、最終的な請求料金は100＄ほどになった。落ち度は完全に私のほうにあるにも関わらず、今回の対応をしてくださったことは本当に感謝してもしきれないほどだ。

離職中だったので金銭的に苦しい状況だったため本当に助かりました。ありがとうございました。
反省として請求アラームを2個付け、UdemyでAWSに関する教材を購入し基礎からAWSの利用法を学び直しました。
これからもサービスを利用させていただきます。
例外処理について

##例外とは
例外は、プログラム上で想定外の動作が行われ、処理が続行できなくなったことを通知するためのオブジェクトです。
例外を使えば、コードの正常処理と以上処理をある程度分離できるため、コードが読みやすくなります。


##エラーと例外の違い
Java実行中のトラブルは,エラーと例外の２種類に分けられます。


**エラー**
実行環境のトラブル等、プログラムから対処不可能な事態。
プログラムが続行できなくなり、強制終了してしまいます。

 **例外**
プログラムから対処可能な事態。
エラーとは違い、動作を終わらせることなくプログラムを続行できます。



##チェック（検査）例外
メソッドを記述する際、例外処理も書かないと怒られるのがチェック例外で、チェック例外は基本的に、正しいプログラムを書いていても避けられない例外です。例えば、参照したいファイルが壊れているとか、DB障害等がこれにあたります。
チェック例外はコンパイラがチェックする例外処理で、Exeptionやそのサブクラス等が対象です。


##非チェック(検査)例外
例外処理を記述したかをコンパイラがチェックしない例外です。
非チェック例外はプログラマーが任意で記述するもので、RuntimeExcepitonクラスやそのサブクラス等が対象です。非チェック例外は基本的には避けられるエラーで、必ず記載しなければならないものではありません。

```main.java
public static void main (String[] args) {

      int[] ary = {1, 2, 3};
    
      System.out.println(ary[3]);
}

```
上記のコードでは、配列aryの要素が3つしか無いのに、4番目を表示するように要求しています。
実行すると以下のようになります。


```
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
```
配列の範囲外を見ようとしているというメッセージが出ました。

これに例外処理を追加して実行してみます。

```main.java
class Main{
    public static void main(String args[]){
        try{
            int[] ary = {1, 2, 3};

            System.out.println(ary[3]);
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("例外です");
        }
    }
}
```
実行結果

```
例外です
```

例外処理が走りました。
##try~catch~finaly文

```sample.java
class Sample {
    public static void main (String[] args) {
        int ary[] = {1, 2, 3};

        System.out.println("開始");

            try{
                for (int i = 0; i < 4; i++){
                    System.out.println(n[i]);
                }
            }
            catch(ArrayIndexOutOfBoundsException e){
                System.out.println("配列の範囲を超えています");
            }
            finally{
                System.out.println("配列を出力");
            }

            System.out.println("処理を終了");
        }
}
```

tryの部分に例外が発生する可能性のある処理を記載し、catchの部分に例外が発生したときの処理を書きます。例外の種類によってcatchブロックをそれぞれに分けることもできます。finalyの部分で最後に実行される処理を記載します。




##throwとthrows
###throw
try~catchでの例外処理以外に、自分で例外を起こせるthrowという例外処理もあります。

```sample.java

    void test (int num) { 
        if(num == 0) { 
            throw new IllegalArgumentException("引数が不正です"); 
        }
    }
```
testメソッドではnumという数値型を引数に指定しているにもかかわらず、if分でnumが0だった時に処理をするように書いています。

実行すると以下のようになります。

```
throw new IllegalArgumentException(“引数が不正です”);
```



###throws
throwと名前は似ていますが処理内容は異なります。
throwsは、例外処理をメソッド内ではなく呼び出し元で行いたい時に、呼び出し元に呼ぶことができます。


```sample.java
import java.io.FileNotFoundException;
import java.io.FileReader;
 
class Sample {
    public static void main (String[] args) {
        System.out.println("例外スロー");
 
        try {
            methodA(); 
        } catch(FileNotFoundException e) {
            System.err.println(e.getMessage());
        } 
    }
 
    void methodA() throws FileNotFoundException {
        FileReader aFile = new FileReader("aFile.txt");
    }
}

```

実行結果

```
aFile.txt (No such file or directory)
処理が終わりました
```
水樹奈々さんの公式サイトがダウンしないのは AWS を上手く使っているからだった。


 （追記）
Qiita / Twitter でいくつかコメントいただきましたので、タイトルに関して補足させてください。
キャッシュを使ってアクセス増加に耐えるスケーラビリティのあるシステムを実現するにはクラウドは相性が良く、水樹奈々さんの公式サイトを構築された方々がAWSを使って素晴らしい設計をしているからこそ可用性が高くなっている、と考えて本記事を書きました。
「クラウドを使えばシステムの可用性は勝手に確保される」「CDNはAWSでしか実装できない」といった考えはありませんでしたが、もし不快に感じた方がいらっしゃいましたら大変申し訳ございません。
タイトルで記事を見に来てくださる方々をミスリードさせようとしたり、オンプレやAWS以外のクラウドを批判するような意図は無かったことをご理解いただけますと幸いです。
（追記2）
タイトルに「上手く」を付けました。


### 水樹奈々さん、結婚！

ネットニュースだけでなくテレビ局の報道でも、水樹奈々さんの結婚でワッショイワッショイ状態です。
当方は職業がIT系なので、水樹奈々さんのファンの方よりも、「公式サイトはダウンしていないかな？」と**事務所の情シスの方へ思いを馳せて**しまいます。（ファンの方、すいません。）

水樹奈々さんの [公式サイト](https://www.mizukinana.jp/) を見に行ったところサクサク見れますし、これだけアクセス激増している状況でもダウンしていないので **AWSクラウドでこんな構成を組んでいるんじゃないかな？** と予想してみたらビンゴでした。（この記事書いている最中も似たことをツイートしてる人が居て、ちょっと笑いました。みんな情シス目線。）

### 予想していた構成図

静的コンテンツ配信の鉄板とも言える構成。

**ユーザー → Route53(DNS) → CloudFront(CDN) → S3(静的Webサイト)**

画像などの静的コンテンツをS3に配置する＆ホスティングして、前段キャッシュでCloudFrontを使って、Route53で名前解決させる。（ちなみに、[AWSの公式ハンズオン](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-StaticWebsiteHosting-2020-reg-event-LP.html?trk=aws_introduction_page)でも同じ構成です。）

さっそく確かめてみました。

### Route53 で名前解決しているか確かめてみた。

ビンゴ。

```

➜  ~ dig www.mizukinana.jp +noall +authority

; <<>> DiG 9.10.6 <<>> www.mizukinana.jp +noall +authority
;; global options: +cmd
mizukinana.jp.		75048	IN	NS	ns-1966.awsdns-53.co.uk.
mizukinana.jp.		75048	IN	NS	ns-1265.awsdns-30.org.
mizukinana.jp.		75048	IN	NS	ns-579.awsdns-08.net.
mizukinana.jp.		75048	IN	NS	ns-290.awsdns-36.com.
➜  ~
```

### CloudFront を挟んでいるか確かめてみた。

ビンゴ。

```
➜  ~ for ipaddress in `dig www.mizukinana.jp +short`
do
dig -x $ipaddress +short
done
server-13-249-171-115.nrt12.r.cloudfront.net.
server-13-249-171-96.nrt12.r.cloudfront.net.
server-13-249-171-93.nrt12.r.cloudfront.net.
server-13-249-171-102.nrt12.r.cloudfront.net.
➜  ~
```

### S3 から配信されているか確かめてみた。

~~ビンゴ。~~
（追記）
本 dig 結果からは、リダイレクトページがS3に配置されている点しか断定は出来ません。
よって、 オリジン(CloudFrontの配信元) = S3 は推測になりますので、打ち消し線で修正しますね。
MovableTypeで作られていて、リダイレクトページはS3に置いてあること、からオリジンがS3と推測しましたが、断定するのは Too Much でした。失礼しました。
コメントいただいた @shin3250 さん、ありがとうございます！

```
➜  ~ for ipaddr in `dig mizukinana.jp +short`
do
dig -x $ipaddr +short
done
s3-website-ap-northeast-1.amazonaws.com.
➜  ~
```

### まとめ

水樹奈々さんは阪神タイガースのファンらしいです。



<br>
<br>
JP1の主要製品について

# 1.JP1の主要製品・分類について

※大まかな分類については、前回投稿した[日立 統合システム運用管理 JP1 について](https://qiita.com/dera_dera/items/3fb817281ef845792c63)で
紹介しています。よろしければ、上記リンクをご参照ください。
<br>

[日立 統合システム運用管理 JP1 について](https://qiita.com/dera_dera/items/3fb817281ef845792c63)でも記載していますが
JP1は主に以下4つに分類され、役割別に各種製品が提供されています。

●Intelligence
└統合管理★
└ITサービス管理
└IT運用自動化

●Intelligent Monitoring
└インフラストラクチャ管理
└パフォーマンス管理★
└ネットワーク管理★

●Intelligent Automation
└ジョブ管理★
└バックアップ管理

●Intelligent Governance
└資産・配布管理
└セキュリティ管理


主に「★」が記載された分類の製品が導入されることが多いです。
「★」記載の製品に着目し、各製品名と使用目的を以下に記載します。

●統合管理
------------------------------------------------------------
＜主製品＞
 - JP1/Base
　　後述のJP1/IM(JP1/IM2)およびJP1/AJS3の前提製品として導入が必要な製品。
　　製品機能としては、認証機能、ログファイル・イベントログ監視
　　イベント管理などが主な機能として挙げられます。<br>
 - JP1/Integrated Management(JP1/IM、JP1/IM2)
　　システムのリソースやイベントを一元管理する製品です。
　　イメージとしては監視ツールだと思っていただければと思います。
　　このイベントを検知したら、特定の処理を実行させるといった
　　自動アクション機能もあります。

●パフォーマンス管理
------------------------------------------------------------
＜主製品＞
 - JP1/Performance Management(JP1/PFM)
　　システムを構成するデータベースやアプリケーションなどを
　　稼働状況を監視する製品です。OSの負荷状況の確認も
　　行うことができます。

●ネットワーク管理
------------------------------------------------------------
＜主製品＞
 - JP1/Network Node Manager i(JP1/NNMi)
　　システム全体のネットワーク状況を監視する製品です。
　　システム全体の死活確認だけでなく、管理機器から発行される
　　SNMPトラップも管理することができます。<br>
 - JP1/SNMP System Observer(JP1/SSO)
　　システム上のサーバリソースやプロセス、サービスの監視を
　　行うことのできる製品です。
　　システムが大規模となると、サーバが高負荷となってくるため
　　細かなサーバリソースを管理することが目的となります。

●ジョブ管理
------------------------------------------------------------
＜主製品＞
 - JP1/Automatic Job Management System 3 Manager/Agent(JP1/AJS3)
　　JP1製品の中で最も利用されている製品であり
　　特定業務の自動化を行うことのできる製品です。
　　定期的に実施する夜間バッチ処理や決まった順序でしなければいけない
　　処理を、自動で処理命令を下す機能を持っています。

<br>

今回は製品分類ごとの主要製品を紹介させていただきました。
次は最も利用されているJP1/AJS3についての機能について紹介します。
[Unity] missing prefabを再度紐づける方法

UnityプロジェクトをGit管理しているときに
うっかりmetaファイルがgitignoreされていて、PULLしてきた時にmetaファイルが更新され、missing prefabになってしまう。
あるあるですよね

<img width="600px" alt="Screen Shot 2020-07-07 at 15.24.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/79a98254-7e6f-d9b5-7e00-392e5ae7de71.png">


`ど゛う゛し゛て゛な゛ん゛だ゛よ゛お゛お゛ぉ゛お゛！゛！゛！゛ん゛あ゛あ゛あ゛あ゛あ゛ぁ゛ぁ゛あ゛あ゛！゛！゛！゛！゛`

metaファイルはignoreされており、metaファイルは一度もコミットされていないので、バックアップなど存在しません。
絶望しかありません。

シーン上のGameObjectをUnpackすれば治る的な記事を見つけましたが、治りませんでした。(赤い文字が白くなっただけ)

再度Prefabを配置し直すという選択肢も、どの値をPrefabにApplyしてあったか、記憶を頼りに復元するしかありません。
(適度にOverrideしましょうね...)

## どうするか

**ymlのguidを直接書き換えましょう**

※自己責任でお願いします。（バックアップをとっておいてください）

Unityのバージョンは
- 2019.3です

新しく生成されたPrefabのmetaファイルをテキストエディタで開きましょう
(一応モザイクで隠しておきましたが、必要なかったかもしれません)

(Item.meta)
<img width="600px" alt="Screen_Shot_2020-07-07_at_15_40_08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/865cbdf1-30c9-3e26-ab6d-7da091a8cf84.png">
こちらのguidの値を控えておきましょう。

続いて、missing prefabが置いてあるシーンファイルをテキストエディタで開きます。
目の前に広がるymlファイル。幻想的ですね

その中からmissing PrefabになっているGameObjectの名前で検索をかけましょう (ItemというGameObject)
以下の画像の緑枠の部分です。

<img width="700px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/8ba8443a-0879-a56a-5c55-a53e2cabe6ab.png">

赤枠のguidの項目(581xxxxx)の部分が複数ありますが、それらを全て先ほど控えたmetaファイルのguidの値(cf1xxxxx)で書き換えましょう
(一つのGameObject名に複数あるようです (- targetの項目分だけ必要?))

その状態でUnityEditorに戻ります。
すると！なんとmissing Prefabが復活しているではありませんか！

<img width="300px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71629/2cf7587b-0d7c-7a33-6290-7ea2383ee28d.png">

私の可愛いPrafabちゃん❤️


--- 

ということで少し面倒ですが、metaファイルのguidを紐付け直してあげれば復活させることが可能でした。
記憶を便りに復活させていくよりは全然マシでしょう。

これでもうmissing prefabになったからといって、泣き寝入りしなくて済みますね！
golangci-lintに自作linterを追加する

## はじめに
[golangci-lint](https://github.com/golangci/golangci-lint)は`golangci-lint run` を実行するだけで、様々なlinterを実行することができます。

これには以下のメリットがあります。

- 各linterの導入方法や設定方法を覚える必要なく、共通の設定で管理できる
- 自分でlinterを探さなくても、良いlinterが日々追加されていく
- 誤検出がある場合に、linterによらず共通の設定方法でその結果を無視することができる


この記事では、golangci-lintに自作linterを追加する方法を公式ドキュメントと実際に[sonatard](https://twitter.com/sonatard)がPRを出したファイルを参考にして紹介します。
[golangci/golangci-lint - Add Noctx #1179](https://github.com/golangci/golangci-lint/pull/1179)

他にも日本の方では [timakin](https://twitter.com/__timakin__)さん作の[bodyclose](https://github.com/timakin/bodyclose)、[nakabonne](https://twitter.com/nakabonne)さん作の[nestif](https://github.com/nakabonne/nestif) がgolangci-lintに採用されています。

 
## 公開Linterをgolangci-lintに追加する

#### 0. Linterを実装する
golangci-lintは [go/analysis](https://pkg.go.dev/golang.org/x/tools/go/analysis) packageを利用していないLinterをマージしないので、必ず利用するようにしましょう。

golangci-lint公式が紹介している[Writing Useful go/analysis Linter](https://disaev.me/p/writing-useful-go-analysis-linter/)や[tenntenn](https://twitter.com/tenntenn)さんが公開されている[資料](https://tenntenn.dev/ja/analysis/)を参考に実装してみてください。

#### 1. fork
https://github.com/golangci/golangci-lint を fork します。

#### 2. テストの追加
Linterのためのテストを実装します。 `test/testdata/{yourlintername}.go` に テストのファイルを追加します。[サンプル](https://github.com/golangci/golangci-lint/pull/1179/files#diff-3cf05950f4df3bc5edc9d7c1fcea4ff9)

そして `T=yourlintername.go make test_linters` を実行して、テストが失敗することを確認します。

#### 3. Linterの追加

`pkg/golinters/{yourlintername}.go` という新しいファイルを追加します。 このディレクトリ内の他のLinterの実装を参考にしてください。 [サンプル](https://github.com/golangci/golangci-lint/pull/1179/files#diff-06fd2409f5ac8660b355d6a8f24b0263) 



`pkg/golinters/{yourlintername}.go` で実装したLinterの新しい構造体を `pkg/lint/lintersdb/manager.go` の `GetAllSupportedLinterConfigs` 関数に追加します。 確実な場合のみデフォルトで有効にしてください。 [サンプル](https://github.com/golangci/golangci-lint/pull/1179/files#diff-03ba2006bf3942719059d8bf1b47bfbc)私が作成した `noctx` はデフォルトではオフになっています。

`T=yourlintername.go make test_linters` でテストが通ることを確認します。

#### 4. Linterのオプションの設定

Linterに設定する必要があるオプションを調べます。例えば、`govet`には `check-shadowing` 1つのオプションしかありません。golangci-lintのユーザーの迷惑にならないようにデフォルト値を選択します。 設定ファイルの例 [.golangci.example.yml](https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml)

golangci-lintプロジェクト向けのgolangci-lintの設定にデフォルト値以外を設定する必要があるのならば [.golangci.yml](https://github.com/golangci/golangci-lint/blob/master/.golangci.yml)に追加します。

[config struct](https://github.com/golangci/golangci-lint/blob/master/pkg/config/config.go) - [pflag](https://github.com/spf13/pflag) が適切な設定ファイルを解析するためのmapstructureタグを忘れないでください。

#### 5. PRを送る

プルリクエストを送ると、CIが走るのですべて通過することを確認します。
またbotによりCLAの同意が求められるので同意する必要があります。

最後にレビューとそのコメントの修正が完了するとマージされて終了になります。

## まとめ

既にテストさえ書いていれば数ファイルを修正するだけで、PRを送ることができます。
自作Linterを作成しても中々使ってもらうことは難しいので「多くの開発者に自作のLinterを使ってもらうことでGoコミュニティをより良くしたい！」と考える方は、是非golangci-lintにPRを送ってみてください。

## 参考
- [How to add a public linter to golangci-lint](https://golangci-lint.run/contributing/new-linters/)
typescriptから直接bundle.jsを作成する方法

本記事ではtypescriptから直接bundle.jsを作成する方法について書いていきます。

＜今までのbundle.jsの作成方法＞
 1.tsファイルをコンパイルしてjsファイルを作成
 2.jsファイルをbundleしbundle.jsを作成

この流れが面倒なので直接やってしまおう。

<h2>1.ts-loaderをインストールする

`npm install --save-dev ts-loader typescript `

<h2>2.webpackの設定ファイルに記述

webpack.config.jsにどのファイルにts-loaderを実行するかを記述する。

```ruby:webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/main.ts',  //最初に読み込ませるファイルもtsファイルに変更

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devtool: 'inline-source-map',

  module: {
    rules: [{
      test: /\.ts$/,　　//どういうファイルに対して
      use: 'ts-loader',　　//何をするか
      exclude: /node_modules/ 　　//このファイルは例外
    }]
  }
}
```

<h2>3.buildしてみる

1.以下のコマンド実行。
`npm run build`

あれ、エラーだけど、、、、
`ERROR in ./src/main.ts
Module not found: Error: Can't resolve './foods.js' in '/Users/*****/*****/******/src'
 @ ./src/main.ts 1:0-35 2:0-5`

ここでのエラーで原因は、main.tsの中でjsファイルをインポートしようとしているため。

```ruby:main.ts
import { Foods } from "./foods.js";

Foods.getInstance();
```

そしたらfoods.tsに書き換えればいいんじゃない？
<img width="972" alt="スクリーンショット 2020-07-07 15.23.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472442/26d714cf-f8c7-b1f7-5ab1-3776b5fbc102.png">

それでもエラーが出てしまいます。

**しかし、Webpackを使用する場合は拡張子は.tsで正解なんです！**

でもエラーが出ているままって気持ち悪いですよね。。。

こうすることで解決できます！

**1.importもとの拡張子を消しちゃいます。**
<img width="972" alt="スクリーンショット 2020-07-07 15.28.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472442/caf48b3d-69e8-5320-5ddf-92bf0b693256.png">
※このままだとbuild時にエラーになります

**2.webpackの設定ファイルに以下を記述します。**

```ruby:webpack.config.js
const path = require('path');

module.exports = {
  entry: './src/main.ts',

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devtool: 'inline-source-map',

  module: {
    rules: [{
      test: /\.ts$/,
      use: 'ts-loader',
      exclude: /node_modules/
    }]
  }
--------ここから--------------------
  resolve: {
    extensions: ['.ts','.js']
  }
}
```
これを書くことで拡張子がなくてもOK。

この記述でインポートしようとした時に拡張子がなかったら左から調べてくれるようになります。

Webpackって本当に便利ですね。。。

<h2>3.再度buildしてみる

以下のコマンド実行。
`npm run build`

今回は無事にエラーなくbundle.jsが作成されましたね！！！



以上になります。
Pythonの文字コードの文字列のリンク集とメモ

# 文字コードについて

#### [新人さんに知ってほしい「文字コードのお話」](https://qiita.com/yuji38kwmt/items/b3a7820b4d3b544da4ff)

符号化文字集合と文字符号化方式の2種類ある

### 符号化文字集合
文字とコードポイントのマッピング

- 例: unicode,  ascii
- python3ではデフォルトunicode

```py

>>> hex(ord("あ"))
'0x3042' # unicodeの"あ"のコードポイント
```

### 文字符号化方式
文字の運用方式、実装方式

- 例: utf-8, shift-jis, euc-jp
- "あ" は utf-8 と utf-16 で符号化すると異なるバイト列になる
  - utf-8:  0xE3 0x81 0x82
  - utf-16: 0x30, 0x42



# Python3での文字の扱い

##### [Python3で文字列を処理する際の心掛け](https://qiita.com/FGtatsuro/items/f45c349e06d6df95839b)
- `'あああ'` のリテラルはunicodeの文字列
- bytesに変換するときは `'あああ'.encode('utf-8')`
- bytesをunicodeに戻すときは `bytes_moji.decode('utf-8')`
- unicodeでファイルに書き込むときと、byteで書き込ときと読むときは関数が異なる
- [Pythonでの文字コードの取り扱い](https://tanishiking24.hatenablog.com/entry/python-charset)

# 一応python2での扱いも

##### [Python2で文字列を処理する際の心掛け](https://qiita.com/FGtatsuro/items/cf178bc44ce7b068d233)

- python2ではbyte化はデフォルトasciiで行われる
  - 日本語文字列をファイルに変換しようとすると、デフォルトasciiでbyteにencodeしようとしてエラーになる
  - utf-8 でencodeするように指定する必要がある
Ansibleについて調べたことの雑多なまとめ

## 変数
[公式ドキュメント - Using Variables](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html)

iniファイル形式でもYAML形式でも記述できるらしい。これはインベントリファイルのことか...？

```ini
# ini形式
[atlanta]
host1
host2

[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
```

```YAML
# YAML形式
atlanta:
  hosts:
    host1:
    host2:
  vars:
    ntp_server: ntp.atlanta.example.com
    proxy: proxy.atlanta.example.com
```

### ホスト変数とグループ変数
インベントリに変数を定義するだけでなく、ホスト変数やグループ変数を定義することができる。
その場合はYAML形式を使用する必要がある模様。
`/etc/ansible/`ディレクトリ配下、カレントディレクトリ配下の`group_vars`、`host_vars`ディレクトリにグループ名/ホスト名のファイルを作成し設定を記述する。

```
/etc/ansible/group_vars/raleigh # ファイルの拡張子は '.yml'、 '.yaml'、 もしくは '.json'
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
```

roleに紐づく変数の定義ファイルなどはちょっと違ったりしそう。`main.yml`だったり。
下記も目を通しておきたい。
[公式ドキュメント - Best Practices](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html)

## 繰り返し処理
`loop`か`with_*`を使って繰り返し処理を実行することができる。
`loop`はAnsibleのバージョン2.5で追加された機能だそうです。
一部のモジュールではパラメータに直接リストを渡すことができるので、タスクをループさせるより効率が良いことがある。モジュールのマニュアルを読むこと。

[公式ドキュメント - Loops](https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html)
### 単純なリストの繰り返し処理
```YAML
- name: add several users
  user:
    name: "{{ item }}"
    state: present
    groups: "wheel"
  loop: # with_items:
     - testuser1
     - testuser2
```

### ハッシュリストの繰り返し処理
```YAML
- name: add several users
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  loop: # with_items:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }
```

### 変数を参照する場合
事前に定義した変数を使用して繰り返し処理を行う場合、`loop`に変数を指定する。
変数は`"{{  }}"`で括らないと変数が参照できない。
注意したほうがいいのは変数名で、暗黙的に宣言されている変数があるので、それとかち合ってる場合はうまく動かなくてハマる。。。`groups`とか。
[公式ドキュメントの特殊変数](https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html)を確認しよう。。。

```YAML
vars:
  users:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }

- name: add several users
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  loop: "{{ users }}"
```

## タスクを管理者ユーザで実行する
rootでSSH接続できない場合、管理者権限でタスクを実行するには`become`を使います。

[公式ドキュメント - Understanding privilege escalation: become](https://docs.ansible.com/ansible/latest/user_guide/become.html)

Playbookに記載する場合は下記のような形で記載する。

```YAML
---
- hosts: all
  become: yes
  become_user: root
  become_method: su
  become_flags: '-s /bin/sh'
```

または変数を設定する。
変数は適用範囲に応じて適切なファイルに指定しておけばいいと思う。

```YAML
---
# group_vars/all.yml
ansible_become: yes
ansible_become_method: su
ansible_become_password: somepassword
```

`become_password`はパスワードハッシュは指定できないみたい。
機微なデータを保護したい場合はAnsible Vaultを使う感じ。

## 実行

### DRY-RUN
`--check`オプションつけて実行する。
`--diff`オプションもあるが何が違うのか...

### 構文チェック
`--syntax-check`オプションつけて実行する。

### タスク一覧の確認
`--list-tasks`オプションつけて実行する。

### 特定のタスクから実行する
`ansible-playbook`コマンドを`--start-at-task`オプション付きで実行する。
ステップ実行するには`--step`オプションをつける。

```
ansible-playbook -i hosts -l hostname site.yml --start-at-task="some task name" --step
```