OmniAICreator/Qiita-1.07M huggingface dataset:
画像認識での出退勤管理を「Teachable Machine」を使って、作ってみた。


# ご挨拶

こんにちは。先日初めて「LINE Bot」の記事を書き、Qiitaデビューを無事果たしました、
とある小売業で働くものです。
今回は、「Teachable Machine」と「Node-RED」を使った制作に挑戦しました。
まず、率直に感じたことは「機械学習」ってすごい！です。これを使えば、日々困っている
業務の問題も、解決へのアプローチの幅がぐっと広がるなぁと思いました！
早速、その試行錯誤の軌跡を記事にしましたので、読んでいただけたら幸いです。

「LINE Bot」の記事はこちら👇
https://qiita.com/kou-n/items/9e8a5870500c4209cb51

# 制作の意図
私の会社では、出退勤時に従業員カードを機械にスキャンすることで、出退勤時刻を記録してます。
その際、わざわざカードを出して、スキャンして・・・それを入店⇒出勤⇒退勤⇒退店と、
計4回、毎日・・・。
「あれ？これって、ちょっと面倒だなぁ」もっと楽に出来ないのか？と思いました。
機械学習で自分の顔を覚えさせて、出退勤スキャンが出来ればいいなぁと思ったので、
「Teachable Machine」を使って作ってみました。
（その後、Node-REDに連携して、管理もやってしまおう！と思ってそれも追加）

# 制作の注意点
①今回使用した画像は、サンプルです。（photoAC写真のフリー素材サイトに登録して入手）
②実際に出退勤スキャンの機械にカメラが付いていて、勤怠システム連携がされ、出退勤の記録が管理できればベストですが、今回は、「時間と従業員名を出力し、出退勤管理をスプレッドシートにする」というもので制作しました。

# 理想とする完成型
出退勤の機械にカメラが付いていて、機械学習させたAIによる顔認識⇒勤怠システムへ連携し、当日の出退勤を記録⇒共有のフォルダ内で同部署の従業員の出退勤を確認できる。
（今回はPCでのスキャンを想定）
そうすることで、結構多いカードのスキャン漏れも防げるし、わざわざカードを出して
スキャンする手間も省ける。また、上司が会議中などで直接退勤の挨拶が出来ない時などに、共有フォルダから上司が自分で部下が帰ったかなどを確認できるというメリットも付与。

# 使用したツール
Teachable Machine
Node-RED

# 完成図
★Teachable Machineでの顔認証
https://twitter.com/kou_n2405/status/1574335305649655808

★Node-RED
Teachable Machineノードで顔認証⇒日時を出力⇒Google Sheetsへ出力
https://twitter.com/kou_n2405/status/1574337798999773185

![完成図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/23567f11-068a-710a-cfeb-ac19205cbed3.jpeg)
本来は、従業員名・日時がGoogle Sheetsへ、下に下に足されていくようなものを制作したかった。
しかし、今回は画像認識・日時出力はデバッグとして表示されたが、Google Sheetsへの書き出しまでは至らなかった。

# 制作の過程（プロセス）
①Teachable Machineで人物の画像を機械学習させる（従業員画像はサンプル）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/50092158-b8e4-565f-9bcb-e13e3316a1cd.png)
②モデルをエクスポートして、URLをnote-redのTeachable Machineノードに入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/2982cf6e-f79e-8b0b-97fe-c75493399f8d.png)
③changeノードを使って、「person:従業員A」が出力されるように設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/1bc00215-efb6-d937-6bef-daf102e1339f.png)

④Date/TimeFormatterノードを使って、日時が出力されるように設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/b9226f8a-8b16-83d5-9296-f5c03c39c148.png)


⑤顔認証のあと、氏名・日時がスプレッドシートに出力されるようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/234c01a6-9637-2dcc-582c-58ac0d281192.png)

# 試行錯誤の失敗例
最初はCSV出力を考えていたり、日時がうまく出力されなかったり、試行錯誤ありましたので、ここで少し失敗例を一部紹介。
①日時の出力がうまくいかなかった・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/ae6248ea-60be-b74e-b380-b8d33f707342.png)
②日時と従業員名は出力されたが、タイムスタンプとカメラノードが分かれていて、実用的ではない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2815209/a13dc438-40d7-0985-1145-99a3c0d5468d.png)

# 総括
今回制作した「顔認証勤怠管理フロー」は、日常業務の中で聞こえてきた何気ない上司の会話がきっかけになりました。
上司：「あれ？〇〇さんは？」
部下A：「先ほど帰りましたよ」
上司：「そっかぁー、なら明日でいいか」
会議か何かで席を外していた上司が、机に戻ってきた際に言われた内容ですが、その時従業員の出退勤をどこか共有で見れたら解決できるのでは？
そう考えて、顔認証による出退勤スキャン+出退勤情報の共有化を思いつきました。
「Node-REDでの顔認証から、日時と氏名を出力して、それをGoogle Sheetsに書き出す」という流れは構築できたものの、ノードの中身設定が中々うまくいかず、試行錯誤した結果、デバック出力することは出来ましたが、Google Sheetsに書き出すというところには至りませんでした。今回学んだ「Teachable Machine」「Node-RED」は、本当に一部の基本的なものでしたが、もっと知識を深めればさらに高度なものが制作できると思います。
今後もできるだけ多くの情報を取り入れていきたいと思います。
【初心者向け】SQL文のまとめ

 # よく使うSQL文の一覧
基本的に4種類の命令文に分けられる
「**SELECT**」
条件を指定してデータを検索し、結果を表示する
「**INSERT**」
指定した値でテータを挿入できる
「**UPDATE**」
登録されているデータの値を変更する際に使用する
「**DELETE**」
指定した条件データを消去できる


 ## データベース領域一覧を表示したい
**SHOW DATABASES;**
 ## データベース領域の作成
**CREATE DATABASES;**
 ## データベース領域の選択
**USE　（データベース領域名）**
 ## 現在利用しているデータベース領域を確認
**SELECT DATABASE();**
 ## テーブルを作成
**CREATE TABLE (作りたいテーブル名);**
 ## テーブル一覧の表示
**SHOW TABLES;**
 ## フィールドの構成を調べる
**SHOW * FROM (テーブル名);**
**DESC (テーブル名);**
 ## レコードを追加する
**INSERT INTO (テーブル名);**
 ## データを取得する
全フィールド
**SELECT FROM (テーブル名);**

フィールド指定
**SELECT (フィールド名1),(フィールド名2) FROM (テーブル名);**

条件指定
**SELECT (フィールド名1),(フィールド名2) FROM (テーブル名) WHERE (条件文);**
 ## データを変更する
**UPDATE (テーブル名)
SET (フィールド名1)=値1,(フィールド名2)=値2,
WHERE (条件文);**
※WHEREを忘れると全レコードが同じ内容に書き換えられてしまう
 ## データを消去する
**DELETE FROM (テーブル名)　WHERE 条件文;**
ソリューションアーキテクト対策_EFS篇

## はじめに
試験勉強した際のメモを自分用に記事化。
内容は公式やBlack Beltの写経ですので目新しいことはありません:pray:

## EFSへのアクセスが急増する可能性があるケースの対応策
EFSを利用して、複数のEC2インスタンスでファイルを共有するアプリケーションを構築している場合。

ファイルアクセスにかかるリクエスト数が一定ではなく、突然増加する場合は`バーストスループットモード`を選択する。

### バーストスループットモード
スループットがファイルサイズに合わせてスケールされ、ファイルベースの多数のワークロードの不規則な性質に対応するために、必要に応じて動的にバーストされる。
これによって、EFSは一時的な高負荷に対応できるパフォーマンスを発揮することができる。

他にも汎用モード、最大I/Oモードがある。

### 汎用モード
一般的な用途を想定したモード。デフォルトでは汎用モードとなり、推奨されている。
レイテンシーが最も低く、1秒あたりのファイルシステム操作が7000に制限されている。

#### 最大I/Oモード
何十〜何千というクライアントからの同時アクセスが必要な大規模構築に利用する。
合計スループットを優先してスケールし、より高いレベルの集計スループットと1秒あたりの操作にスケールできるが、レイテンシーが多少長くなる。

## バーストのスループット
ピーク時にクレジットを消費してバーストを実行、一時的な性能を向上させる方式。
最大スループットとバースト時間に制限がある。また、スループット性能向上にはストレージ容量の増大が必要。

## プロビジョンドスループット
一貫したスループットを事前に設定する方式。API/AWS CLI/マネジメントコンソールにより制御する。
また、1日に1回だけスループット性能を減少することができる。

デフォルトのバーストモードより高い専用スループットを必要とするアプリケーションをサポートするように設計されており、ファイルシステムに格納されているデータの量とは関係なく設定することができる。

## おわりに
引き続き追記します。

以上です。
数行書くだけでできる CLS対策 (jqueryバージョン)

```
<noscript>
<style>
    body{
        display :block!important;
    }
</style>
</noscript>
<style>
     body{
        display :none;
 }
 </style>
<script type="text/javascript">
    $(document).ready(function(){
        $("body").show();
    });
</script>
```
PyCaret参考記事まとめ

PyCaret関連で参考になった記事を備忘録的にまとめていきます。

## create_modelのパラメータ
- fold：クロスバリデーションでの分割数（デフォルト：10）
- cross_validation：クロスバリデーションを実行しない場合にはFalseにする（単にhold-out法を実行したい場合など）
精度はテストセットで評価される（おそらく）*
- probability_threshold：分類の閾値の設定
- その他、各モデルのハイパーパラメータを指定可能
```py 
# ロジスティック回帰でモデルの学習と性能評価を実行してみる。
lr = create_model('lr')

# クロスバリデーションの分割数を指定可能
lr = create_model('lr',fold = 5)

# クロスバリデーションを行わない場合
lr = create_model('lr', cross_validation = False)

# 閾値を調整する。
lr = create_model('lr', probability_threshold = 0.25)

# ハイパーパラメータを設定することも可能
dt = create_model('dt', max_depth = 5)

# 検証の結果は`pull`で呼び出し可能
dt_results = pull()
```
https://datadriven-rnd.com/pycaret/


# ハイパーパラメータの最適化
次に、ハイパーパラメータの最適化を行います。

- 第一引数：モデルの名称
- 第二引数：ランダムグリッドサーチの回数
- 第三引数：最適化の対象
```py
# Random Forestのモデルを最適化
tuned_rf = tune_model('rf', n_iter = 500, optimize = 'r2')
```

https://rightcode.co.jp/blog/information-technology/machine-learning-automation-pycaret

# ハイパーパラメータの最適化2

tune_model関数の第一引数にモデル（作成したランダムフォレストモデル）を指定します。

optimize引数には対象となる指標を指定します。今回はR2を設定しています。

```py
tuned_rf = tune_model(rf, optimize = "r2", fold = 10)
tuned_rf
```
https://ailog.site/2022/02/15/2022/0215/

# ハイパーパラメータの最適化3
【ハイパーパラメータ調整】
●n_iter：学習時のイテレーションの回数設定
●optimize：評価指標の選択
●custom_grid：自分でハイパーパラメータの項目・値範囲を指定
●search_library/search_algorithm{default:RandomGridSearch}：最適化アルゴリズムの変更（scikit-optimize、optunaなど）
●return_tuner{defalut:False}：最適化アルゴリズムを確認できるよう変数出力
●choose_better{defalut:False}：tuned_modelで性能が改善されなかった場合は調整前の結果を選択する
https://note.com/kiyo_ai_note/n/n97d94a946c68


# 公式
https://pycaret.readthedocs.io/en/latest/api/regression.html

# その他
https://torch.classcat.com/2020/12/18/pycaret-2-2-tutorials-regression-reg101/


実際にハイパーパラメータの引数を調整してうまいこと改善していっているような記事があれば良いんだけどなぁ…
「今回は引数なしで…」が多い
【Rails】countメソッドにカラムを指定してエラーを回避

## 環境
Rails 6.0.1
Ruby 2.6.3
PostgreSQL 11.16

## 状況

relationでjoinしている```posts```に```count```したら下記のエラーが発生し```count```できない。
```ruby
posts = Post.joins(:users)
=>Post::ActiveRecord_Relation

posts.count
=>ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR:  syntax error at or near "AS"
```

## 解決法

ActiveRecordのcountメソッドは引数にカラムを指定できるのでそれを使うとcountできる。

```ruby
posts = Post.joins(:users)
posts.count(:posts)
=> 4
```

## 参考

https://railsdoc.com/page/count
CloudRunのデプロイを管理コンソールから切り戻しする方法

リリースしたけれど、何かしらの不具合があって切り戻しが必要になったとき。
CloudRunなら管理コンソールから簡単に切り戻しが可能です。

この機能自体は切り戻し用、というよりは複数のバージョン(リビジョン)を一定の割合で配置して変更のインパクトを抑えつつリリースする、みたいのが本来の趣旨かなとは思いますが、切り戻しにも使えます。
その流れを以下に記載します。

なお、環境や状況によってはこの方法での切り戻しが正解にはならない場合がある点はあらかじめご了承ください。

# (1) リビジョンタブを表示する
該当のインスタンスを選択して「リビジョン」のタブを選択しましょう。
ここにこれまでにリリースされてきた一連のリビジョンを確認することができます。

この現在〜過去のリビジョンのいずれかを指定することで簡単に切り戻しが可能です。
「デプロイしました」の項目にタイムスタンプがあるのがわかりやすくていいですね。

![378128955371f88bda812b86db0c659a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10138/9ce3e80c-3f6c-be0f-4f05-7bfcdacb0ad2.png)


# (2) 「トラフィックを管理」を選択する
右側の「操作」のボタンを押して「トラフィックを管理」を選択しましょう。

![21293672f95fb2e8fb1b15852a2afa5f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10138/2b2b097c-61e6-d6db-ba58-6a46e5762a67.png)

![b2b09ee285b22302009a925e5f54168f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10138/381f9528-70ed-bdc5-d56e-823cd5eaadb9.png)

# (3) 切り戻し先を選択する
ここで表示されたダイアログで、「切り戻し先」のリビジョンを指定します。
そして、振り分けを100として保存しましょう。

![06722985f17e0838777c046a5a567a50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10138/1869a1b7-2d81-97b3-0b6e-6dcd44f21849.png)


以上で完了です。少し待つと、指定したリビジョンに切り替わります。

早い！

リポジトリをrevertとかして再びデプロイ、とかより断然早いと思います。

# 補足
さて、切り戻しをした後に不具合などを修正して再リリースすると思いますが、今のままではデプロイが完了しても最新のリビジョンに**自動的には切り替わりません**。
上記の手順同様にトラフィックの管理で「Latest healthy version」を指定して100に振り分けしておきましょう。

![914844295afb5a15d497d3904999bca0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10138/bcaa1665-7db7-95ab-f109-f2c9e1a098c9.png)


切り戻しが発生しないように開発をするのが一番ですが、それでも起きる時には起きちゃいます。
緊急時にサッと戻せるのでとても便利ですね。
DBeaverからDb2 on Cloudにアクセスする

`「Db2 on Cloudを使ってみる」シリーズ`

当記事はOSSのDB Tool [DBeaver](https://dbeaver.io/)からDb2 on Cloudに接続する方法について説明します。
尚、Db2 Warehouse on Cloudも同様の方法で接続可能です。
この検証はMac版で行っています。

# 1. 接続情報の準備

DB接続用の
- userid
- password
- ホスト名
- ポート番号
- データベース名

を準備してください。

取得方法が不明の場合はこちらの[Db2 on CloudのDB接続情報取得](https://qiita.com/nishikyon/items/69fee851849e7ef7e163)を参照お願いします。

上記に方法は2つ書いていますが後半の「[IBM Cloudコンソールから資格情報を作成・参照](https://qiita.com/nishikyon/items/69fee851849e7ef7e163#ibm-cloud%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%8B%E3%82%89%E8%B3%87%E6%A0%BC%E6%83%85%E5%A0%B1%E3%82%92%E4%BD%9C%E6%88%90%E5%8F%82%E7%85%A7lite%E3%83%97%E3%83%A9%E3%83%B3%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%AF%E3%81%93%E3%82%8C%E3%81%AE%E3%81%BF)」が管理者権限をもっているならよいと思います。


# 2.　DBeaverを開き、接続を作成

### 2-1.上部メニューから「データベース」→「新しい接続」を開く
### 2-2.　DB2 LUWのアイコンをクリックし、「次へ」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/2a5eac5c-6b5d-b8f5-8d00-5e1c7566af26.png)

### 2-3. DB2 LUW接続設定を入力
まずは、「接続の詳細」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/11117627-a2e6-8a06-40a9-aa823351eab8.png)

接続名にわかりやすい名前を入れ,「戻る」をクリック
(そのままでもOKですが、たくさん作成するとわからなくなるのでわかりやすい名前にした方がよいです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/5c770253-c448-bd1a-0b29-d97170b3aea9.png)




次に [1. 接続情報の準備](#1-接続情報の準備)で取得したAPIKEY, 接続情報を入力します。
#### [一般]タブ
- Host: ホスト名
- Port: ポート番号
- Database: データベース名
- ユーザー名: userid
- パスワード: password
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/0efac54b-34dc-a6b8-e583-215b67bdc471.png)


#### [ドライバのプロパティ]タブ
左下の＋印をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/33909679-b32f-8014-6651-14e32010d831.png)
プロパティ名に`sslConnection`と入力、OKをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/b32a9166-1623-5a15-6344-6c512adaf973.png)

`sslConnection`をクリックして、`true`を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/861ccaba-657a-84a0-1e28-dd751bf67a4a.png)

最後に「テスト接続」をクリックして設定を確認します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/b7adcdf6-8f9a-8bb9-d394-2203f91055a0.png)

接続が確認できました! 「OK」をクリックしてダイアログを閉じます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/374505dd-8213-4019-824f-bb6ee19c75e9.png)

右下の「終了」をクリックしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/e3b946f7-1b31-9ffb-89a1-d8af420d0fc2.png)


無事データベースナビゲータに表示されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/1a4f5ad2-c7ac-0756-b15e-6ebb5aecbfbc.png)

以上です。
パーシャルとは？

# パーシャルとは？
```レンダリング処理を扱いやすい単位に分割```するしくみです。

## パーシャルの表記方法
パーシャルを```ビューの一部としてレンダリング```するには、ビュー内で以下のようにrender メソッドを使います。
```html
<%= render "menu" %>
```
## パーシャルのファイルの名前の注意点
レンダリングされるビュー内に置かれている上のコードは、その場所で_menu.html.erbという名前のファイルをレンダリングします。```パーシャルファイル名の冒頭にはアンダースコアが付いている```ことにご注意ください。

### _(アンダースコア）をつけない場合もある
アンダースコアは通常のビューと区別するために付けられていますが、アンダースコアなしで参照されることもあります。```これは他のフォルダの下にあるパーシャルを取り込む場合```も同様です。

```html
<%= render "shared/menu" %>
```
上のコードは、app/views/shared/_menu.html.erbパーシャルをその位置に取り込みます。

## パーシャルをサブルーチンのように扱う
パーシャルをサブルーチンと同様に扱うことです。表示の詳細をパーシャル化してビューから追い出し、コードを読みやすくします。

```html
<%= render "shared/ad_banner" %>

<h1>Products</h1>

<p>Here are a few of our fine products:</p>
...

<%= render "shared/footer" %>
```
# パーシャルレイアウト
ビューにレイアウトがあるのと同様に、```パーシャルでも独自のレイアウトファイルを利用できます```。
```html
<%= render partial: "link_area", layout: "graybar" %>
```
## 上のコードの意味
上のコードは、```_link_area.html.erbという名前のパーシャルを探索```し、```_graybar.html.erbという名前のレイアウトでレンダリング```します。
```:layoutなどの追加オプションも渡す場合は、:partialオプションも明示的に指定```する必要があります。

### パーシャル用のレイアウトファイルにもアンダースコアをつける
パーシャル用のレイアウトファイルは、```対応する通常のパーシャルと同様、パーシャル名の冒頭にアンダースコアを追加```する。

### パーシャルファイルの位置
（マスターのlayoutsディレクトリではなく）そのレイアウトが属している```パーシャルファイルと同じディレクトリに配置```します。

## パーシャルにローカル変数を渡す
パーシャルにローカル変数を渡すことで、パーシャルがさらに強力かつ柔軟になります。たとえば、以下のようにnewページとeditページの違いがごくわずかしかない場合は、この手法でコードの重複を解消できます。

```html
<h1>New zone</h1>
<%= render partial: "form", locals: {zone: @zone} %>
```

```html
<h1>Editing zone</h1>
<%= render partial: "form", locals: {zone: @zone} %>
```

```html
<%= form_with model: zone do |form| %>
  <p>
    <b>Zone name</b><br>
    <%= form.text_field :name %>
  </p>
  <p>
    <%= form.submit %>
  </p>
<% end %>
```
### 状況に応じてローカル変数を渡す local_assigns
index.html.erb
```html
<%= render user.articles %>
```
show.html.erb

```html
<%= render article, full: true %>
```
_article.html.erb
```html
<h2><%= article.title %></h2>

<% if local_assigns[:full] %>
  <%= simple_format article.body %>
<% else %>
  <%= truncate article.body %>
<% end %>
```
これにより、```すべてのローカル変数を宣言せずにパーシャルを使える```ようになります。

# yieldとは？
レイアウトのコンテキスト内では、```ビューのコンテンツを挿入する位置をyieldで指定```します。
yieldの最もシンプルな使い方は、以下のようにyieldを1個だけ使って、現在```レンダリングされているビューのコンテンツ全体をその位置に挿入```することです。

```html
<html>
  <head>
  </head>
  <body>
  <%= yield %>
  </body>
</html>
```
# 気づき
まだ```yield```を理解できていないがこれからまた勉強して理解できるようになる。
これをもとにパーシャルを使えるようになる。
そしてまだ理解できていないことを理解できていないと思っている。
これからまた上書きもしくは、さらに記事にしたいと思う。
とりあえず```render```でパーシャルを試してみたい。

# 出典 
https://railsguides.jp/layouts_and_rendering.html#%E3%83%91%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E3%82%92%E4%BD%BF%E3%81%86
Mattermot APIのPHPドライバを Laravel で実行する手順

# 概要
[Mattermost API](https://api.mattermost.com/) には、以下のドライバ群がありますが、ここでは PHP Driver を Laravel 上で実行する手順を整理したいと思います。

* Official Drivers
  * [Mattermost JavaScript Driver](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.ts)
  * [Mattermost Golang Driver](https://github.com/mattermost/mattermost-server/blob/master/model/client4.go)
* Community-built Drivers
  * [PHP Driver](https://github.com/gnello/php-mattermost-driver) - built by @gnello and @prixone
  * [Python Driver](https://github.com/Vaelor/python-mattermost-driver) - built by @Vaelor

# Mattermost PHP Driver ソースコードの簡単な解説

## フォルダ構成
大きく分けると以下の３部構成です。

* src/Driver.php
  * ユーザフロントのDriverクラスが定義されており、セッション情報を管理しています。
  * ログインするとこのDriverクラスインスタンスがトークンが登録されますので、
  * 以降はこのトークンを利用してAPIコールが可能になります。
* src/Client.php
  * PHPのデファクト？のライブラリ`GuzzleHttp`をラップしたクラスです。
  * ここでREST APIを発行しています。
* src/Models/*.php
  * Mattermost APIの種別ごとにクラス定義されています。
  * このクラスを利用して、簡単にMattermost APIをコールできます。

## 使い方
Laravel, PHP 玄人なら、github の [README](https://github.com/gnello/php-mattermost-driver)を見てすぐに使えるのかな？と思われます。

ただ、自分にはちょっと壁があったので、自分なりにソース解釈して手順を整理したほうが良さそうだと思った次第です。

# Mattermostってそもそもどうやってインストールする？
Mattermosの導入手順は、[こちら](https://qiita.com/kanetugu2018/items/51cdab279d81ae06aa70)をご参照ください。

# Mattermot APIのPHPドライバを Laravel で実行する手順
今回整理した成果は以下のリポジトリで一般公開しております。

https://github.com/tmori/tutorial_mattermost

上記では、環境はすべて docker-composeベースで行っておりますので、Dockerfileを見ていただければ、本番のテスト環境構築にも役立つと思います。

また、Laravelでのサンプルコード作成では、Laravelのコマンドで実装しておりますので、bash 等で負荷テストスクリプト化も用意に実現できます。

現時点では、以下のサンプルコードを公開しております。
* ユーザのログインサンプル
* ユーザの新規追加サンプル
* チームの新規追加サンプル
* チャネルの新規追加サンプル
* チームへのユーザ登録サンプル
* チャネルへのユーザ登録サンプル
* チャネルへのメッセージ投稿サンプル

# 最後に
なぜPHPでやっているの？と思われる方がいらっしゃるかもしれません。
その答えは、単に自分が、PHPを勉強したかったからです〜。
A lock file already exists in the repository, which blocks this operation from completingの（個人的）解決法

# 動作環境
- MacBook Pro Intel Core i5 Monterey version 12.0.1 
- GitHub Desktop Version 3.0.7 (x64)

# 背景
`arfoundation-paintGame`というリポジトリでGitHub Desktopを使って、あるブランチにコミットしようとしたら`A lock file already exists in the repository, which blocks this operation from completing`のエラーが出た。

# 解決方法
![スクリーンショット 2022-09-21 16.16.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2700137/bb902dc6-ae56-015c-0430-e3b79151bc14.png)
対象リポジトリで隠しファイルを表示（Macの場合`command`＋`shift`＋`.`）して、.gitの中にある`index.lock`を消せば解決した。
flashに任意のキーをセットして表示するには

## 環境
Rails 5.2
Ubuntu20.4

## はじめに
flashにはオプションとして、**notice**と**alert**の２つのキーが用意されていますが、任意でnoticeとalert以外のキーを設定して、取り出して表示することもできるようになっています。

## 普通のやり方
標準的な使い方をする場合は、noticeとalertだけを使います。コントローラーでflashにメッセージを設定します。
```test_controller.rb
flash[:alert] = "アラートです。"
flash[:notice] = "注意事項です"
redirect_to test_url
```

flashの変数の中身を見ると、alertとnoticeに値が正しくセットされていることが確認できます。
```
#<ActionDispatch::Flash::FlashHash:0x00007fb89c859f88 @discard=#<Set: {}>, @flashes={"alert"=>"アラートです。", "notice"=>"注意事項です"}, @now=nil>
```

alertとnoticeの内容はビューの中で次のようにして表示します。
```application.html.slim
- if flash.alert.present?
    .alert.alert-danger = flash.alert

- if flash.notice.present?
    .alert.alert-success = flash.notice
```

BootstrapのAlertに次のように表示されました。
![無題1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/33e328c2-61b8-e4ed-b207-99abfc041650.png)

## 任意のキーを作成

flashにnotice1、notice2というキーを作成して値をセットしました。notice1、notice2というキーは、flashで標準で用意されていないキーです。
```test_controller.rb
flash[:notice1] = "注意事項その１"
flash[:notice2] = "注意事項その２"
redirect_to test_url
```

flashの変数の中身を見ると、ちゃんとnotice1とnotice2に値がセットされていることが確認できます。
```
#<ActionDispatch::Flash::FlashHash:0x00007fb8a324fa00 @discard=#<Set: {}>, @flashes={"notice1"=>"注意事項その１", "notice2"=>"注意事項その２"}, @now=nil>
```

notice1とnotice2の内容をビューで表示させようとしたところ、１行目で次のエラーが表示されました。
>undefined method 'notice1'

flashにはハッシュのnoticeキーと同じ名前のnoticeメソッドが用意されているようです。ハッシュのnotice1キーは自作したキーであるため、この名前のメソッドは標準では用意されていません。よって、notice1というメソッドは存在していませんというエラーが出てきたということです。
```application.html.slim
- if flash.notice1.present?
    .alert.alert-success = flash.notice1

- if flash.notice2.present?
    .alert.alert-success = flash.notice2
```

ハッシュのキーを指定することなく、ハッシュのセットされている値を全て表示させるには、次のようにすると表示することができます。
```application.html.slim
- flash.each do |key, value| 
    div.alert.alert-success
        = value
```

notice1とnotice2の値がビューに表示されました。
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94029/fa3d4c2f-7ed3-14b6-3f13-08fb6564c79a.png)
誰でもわかるNR-Flex

# この記事について

NewRelicにはNR-Flexという機能があります。
https://docs.newrelic.com/jp/docs/infrastructure/host-integrations/host-integrations-list/flex-integration-tool-build-your-own-integration/

NR-Flexが何かよくわかっていない人がNR-Flexを理解して、一からNR-Flexを用いたモニタリングができるようになるための最低限の情報をここにまとめます。

# 対象読者

- NewRelicを使い始めたばかりの方
- NR-Flexが何かわからない方
- NR-Flexを使ったことがない方


# NR-Flexとは

端的にいうと`NewRelicにメトリクスを送信するためのツール`です。

NewRelicでは通常インテグレーションを用いて、データ(メトリクスなど)を収集します。
AWSではAWSインテグレーションを利用することでCloudwatchメトリクスをNewRelicに送信して、AWSの監視をNewRelicで行うことが可能になります。
インテグレーションの種類は多岐に渡り、基本的なモニタリングはインテグレーションを利用することで実現可能です。

ただ
- モニタリングしたいものに対応するインテグレーションがない
- インテグレーションはあるが、そのインテグレーションでは取得したいメトリクスを取得できない
というケースがあります。

そんな時に利用するのがNR-Flexです。
NR-Flexを利用すれば自分の取得したいメトリクスを自由に定義して、NewRelicに送信することが可能になります。

もしNR-Flexがなければ、NewRelicのエンドポイントにメトリクスを送信するプログラム(スクリプト)を用意して、それをcronで実行させて....というような実装が必要になります。
NR-Flexを利用することで、ユーザはノーコードもしくはローコードでNewRelicにメトリクスを送信することができます。

# どうやって使うの？

NR-Flexを利用するためには、NewRelic Infrastrucreエージェントがインストールされたホストが必要です。
https://docs.newrelic.com/jp/docs/infrastructure/install-infrastructure-agent/get-started/install-infrastructure-agent/

NewRelic Infrastructureエージェントがインストールされたホストさえあれば、あとはyamlファイルを作成するだけでNR-Flexを利用することができます。

# 使ってみる

## 事前準備

- EC2 ( AMIはAmazon Linux2 )を用意
- EC2にNewRelic Infrastructure agentをインストール

## NR-Flexファイルの作成

NewRelic Infrastructure agentをインストールしたら、`/etc/newrelic-infra/integrations.d`ディレクトリが作成されます。

このディレクトリ配下にyaml形式でNR-Flexの設定を定義したファイルを作成します。(作成したあとは、`systemctl restart newrelic-infra.service`を実行しておきましょう)

```plaintext:/etc/newrelic-infra/integrations.d/sample-nrflex.yml
integrations:
  - name: nri-flex
    interval: 60s
    config:
      name: Hogehoge
      apis:
        - name: Hogehoge
          commands:
            - run: echo hoge 1
              split: horizontal
              split_by: \s+
              set_header: [sample-string, sample-number]
```

上記が何を意味しているか簡単に解説します。

以下のコマンドを60秒毎に実行し、
```
echo hoge 1
```

その標準出力である`hoge 1`をNewRelicに送信します。

送信する際に、`hoge 1`をスペースで分割して、それぞれ別のメトリクスとしております。(splitとsplit_byの定義内容をもとに処理されます)

`hoge`にはsample-stringというヘッダーが、`1`にはsample-numberというヘッダーが付与されます。

integrations.config.apis.commandsを指定すると、infrastrucutre agentをインストールしたホストにてコマンドを実行し、そのコマンドの出力を加工して、NewRelicに送信することができます。

## NewRelic側でメトリクスを確認する。

NewRelicではNR-Flexで送信したメトリクスは、integrations.config.apis.nameに指定した名前のEventから確認することが可能です。


Hogehogeと指定していたので、HogehogeSampleというEventができているはずです。

ではNewRelicのData explorerを見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435280/acc6a3d1-c1bc-2fcf-54f4-ac072077197a.png)


From HogehogeSampleからメトリクスを取得すると、Sample-NumberとSample-Stringというヘッダーができており、その中に`hoge`と`1`が記録されています。

このようにNR-Flexを利用すれば、ユーザが送信したいメトリクスをNewRelicに簡単に送信することが可能になります。

# NR-Flexを本格的に利用するには

NR-Flexファイルを作り込む必要があります。
中身のパラメータについては以下リンクを参照してください。
https://github.com/newrelic/nri-flex/blob/master/docs/basics/configure.md

覚えることはあまり多くありません。
実行させるコマンド/スクリプトがしっかり動けば、意図したメトリクスをNewRelicに送信することができます。

# 参考

https://newrelic.com/jp/blog/how-to-relic/how-to-use-new-relic-flex
Create Account Page Layouts Module


どうもページレイアウトが１つしかない時はレコードタイプを指示通り作ってないことが原因みたい。
似たようなトレイルがあるので注意 --> [Support Plan 関係](https://qiita.com/Keiji_otsubo/items/339e8f0d8e894834068e)

+ [Create Account Page Layouts Module](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000Jde49SAB)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/db4faaec-a4aa-a1c4-7959-48c88bc5f6ea.png)

+ [Customer Account column is missing from account page layout](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Ph75JSAR)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e0f46916-a51b-68b5-72fe-079f2b931c0d.png)

:::note
have you done the previous unit ?

https://trailhead.salesforce.com/fr/content/learn/projects/customize-a-salesforce-object/create-record-types
:::
PHP フォルダ　削除関数

### 完成イメージ図
![tttt0001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478380/9f829c82-5a24-4af7-1fec-ae2e9e0b2457.png)

### ソースコード

```PHP:
 //*********************** */
        //**************** DB カラム 削除 関数 */
    //*********************** */
    function DB_delete_column($p_h) {

        // *** エックスサーバー用 接続情報
        $dsn = 'mysql:dbname=サーバー;host=localhost;port=3306';
        $user = '';
        $password = '';

        try{

            // PDO オブジェクト作成
            $pdo = new PDO($dsn, $user, $password);

            // ======  （トランザクション） トランザクション開始 ======
            $pdo->beginTransaction();
            
            //***** GET の末尾の　URL を取って、　最新の１件　取得 */
            $stmt = $pdo->prepare("DELETE FROM valid_table WHERE pass_hh = :pass_hh");
            
            // パスワード　ハッシュ値
            $stmt->bindParam(':pass_hh', $p_h, PDO::PARAM_STR);

            $stmt->execute();

            // ======= (トランザクション) コミット =========
            $pdo->commit();
        
        }catch (PDOException $e){
            print('Error:'.$e->getMessage());

            // ======= (トランザクション) ロールバック =========
            $pdo->rollBack();

            die();
        }
    
            
            $pdo = null;
            // ****** データベースの接続解除 ******
         /**========== DB 接続 END =========== */

    } // =========================== END function DB_delete_column()
AWS CloudFrontとS3とRoute53でwww.ありドメイン名をwww.なしドメイン名にリダイレクトする

ドメイン名でWebページを表示できるようになって気づきました。
ドメイン名は「www.」無しで取得して設定もしたので、「www.」ってつけても大丈夫なのかなと。

早速試して見たところ。。。。
#### 見事にタイムアウトでした。。。

じゃあ「www.」つけてもアクセスできるようにする必要があるよね、ということで。

今回は下記のページを参考に項番2から実施してみました。
https://techblog.finatext.com/redirecting-www-subdomains-with-cloudfront-and-s3-8330a616dbc0

# まずはS3で静的ホスティング機能の設定
1. 「www.ドメイン名.com」というバケットを作成
2. 静的ウェブサイトホスティングで「ドメイン名.com」にリダイレクトするように設定

これでS3の設定は終わり

# 次にCloudFrontの設定
1. オリジンドメインに同様にURLを選択
1. ビューワープロトコルポリシーはRedirect HTTP to HTTPSを選択して作成
1. 「ディストリビューションドメイン名」を覚えておく（メモしておく）

これでCloudFrontの設定は終わり

# 次はRoute53の設定
1. レコード名には「www」を入力
1. レコードタイプは「A – IPv4 アドレスと一部の AWS リソースにトラフィックをルーティングします。」を選択
1. エイリアスをONにして、トラフィックのルーティング先は「CloudFront ディストリビューションへのエイリアス」を選択
1. ディストリビューションは先ほどメモした「ディストリビューションドメイン名」を選択
1. ルーティングポリシーはシンプルルーティングのまま
1. レコードを作成

これでRoute53の設定は完了

# 「www.ドメイン名.com]を打ち込んで確認

### 無事Webページにアクセスできました！
割り込み処理

# PSW(Program Status World)
プログラム状態語と呼ばれる。```実行中のプログラムの状態を示す数バイトの領域```

# 割り込みマスク(mask)
```割り込みに優先順位を与える機能```。割り込みが発生したとき、その割込みを受け入れか禁止するかを指定する。

# 内部割り込みと外部割り込みの違い
割り込みは、```プログラムの実行に起因して発生```する「内部割込み」と```プログラムの実行とは無関係に発生```する「外部割り込み」とに分類される。
出典　
http://r-o-y.info/tyusyo/tyusyo_7_interrupt.html#:~:text=%E5%89%B2%E3%82%8A%E8%BE%BC%E3%81%BF%E3%81%AF%E3%80%81%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E5%AE%9F%E8%A1%8C,%E3%81%A8%E3%81%AB%E5%88%86%E9%A1%9E%E3%81%95%E3%82%8C%E3%82%8B%E3%80%82&text=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E5%AE%9F%E8%A1%8C%E3%81%AB%E8%B5%B7%E5%9B%A0%E3%81%97%E3%81%A6%E7%99%BA%E7%94%9F%E3%81%99%E3%82%8B%E5%89%B2%E3%82%8A%E8%BE%BC%E3%81%BF%E3%80%82

# 内部割り込み
* プログラム割り込み
オーバフロー、存在しないページへのアクセス、書き込みできない主記憶装置に書き込もうとした時に生じる

* SVC（Super Visor Call)割り込み
入出力処理を要求する、カーネル呼び出し命令が発行された時に生じる

# 外部割り込み
* 入出力割り込み
入出力装置の動作完了時や中断時に生じる

* 機械チェック割込み
電源の異常や主記憶装置の障害など、ハードウェアの異常発生時に生じる

* コンソール割り込み
オペレータ（利用者)による介入が行われた時に生じる

* タイマ割り込み
規定の時間を過ぎた時に生じる割り込み


# 出典 

https://qiita.com/masatom86650860/items/55a45bba0edd7cb3ab8a

https://gihyo.jp/book/2022/978-4-297-12375-8
フローコアアクションの設定


[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


何を設定したらいいのかが分からないことこの上ない。

# ナレッジ記事を公開
[フローのアクション「ナレッジ記事を公開」について](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Jyw7jSAB)

先ほどの設定にしてArticle Version IDを割り当てるとエラーは表示されなくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/22ecaf52-a113-6dc0-71f0-186adc278848.png)

# カスタム通知を送信

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/37d1efac-7a64-bbf8-55bb-c190cd659767.png)

CustomAlertId : カスタムアラートのIdを取得すること。
UserIds2 : コレクション変数　複数人に通知できるということかな？

+ [カスタム通知をクリックした際に、アプリケーションのホーム画面に遷移できるようにしたいです。](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000O8HWW)

```
{type: "standard__objectPage",attributes: {objectApiName: "Task",actionName: "list"},state:{filterName:"Recent"}}
```

# Slackチャンネルにユーザを招待

注意点
アクションは失敗します。また、フローを開始するユーザと、アクションの影響を受けるユーザは、少なくとも 1 回は Salesforce Slack アプリケーションにログインしている必要があります。

[コアアクション「Slackチャンネルにユーザを招待」の挙動について](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JzG78SAF)

# 新しい Send Slack Message コア アクションの View API Name のオプションは何ですか?

スクリーンショットに表示されているビュー API 名の入力パラメーターは、[Slack ビュー機能](https://developer.salesforce.com/docs/platform/salesforce-slack-sdk/guide/views_create.html)に関連しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8787d9e2-2e75-2e77-5efa-6df4db52385b.png)


# メールを送信

+ [管理者以外のプロファイルでフローのコアアクション「メールを送信」が機能しません](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgkM4)

このコアアクションは
フローを実行したユーザの「ユーザの検証済みメール」が有効になっていないと送信できないようです。

https://help.salesforce.com/s/articleView?id=release-notes.rn_sales_productivity_email_verification.htm&release=236&type=5

テキストテンプレートでHYPERLINKが使えない

```
 _HL_ENCODED_https://google.com_HL_Google Website_HL__blank_HL_
```

https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000C30CrSAJ

https://issues.salesforce.com/issue/a028c00000gAzSEAA0/hyperlink-formula-displaying-_hl_encoded_-when-referencing-another-formula-field

+ [フローのコアアクション「メールを送信」の本文にHYPERLINKは使えません](https://qiita.com/Keiji_otsubo/items/278fa2a2d003fc563643)
【Android Wear】Wearエミュレータとスマホ実機の接続方法

# はじめに
Wearエミュレータ(Android Wear)とスマホ実機(Android)の接続方法について記述。

# 手順

### Wearエミュレータ側の設定
以下の方法でADB Debuggingを有効化する。Wear OS API 30の設定を記述。
`Settings -> System -> About -> Versions -> Build numberを7回タップ`
`Settings -> Developer options -> ADB debuggingがONになっていることを確認`

### Wearとスマホの接続
スマホとPCをUSB接続。
`adb -d forward tcp:5601 tcp:5601`をTerminal上に入力。

### スマホ実機側の設定
[Wear OSアプリ](https://play.google.com/store/apps/details?id=com.google.android.wearable.app)をインストール後、起動してエミュレータと接続。

参考サイト：

https://developer.android.com/training/wearables/apps/creating.html#SetupEmulator

http://shokai.org/blog/archives/9794
deno fmt をコードの中で呼ぶ

deno のバージョン `1.25.3` 時点の話

```ts:format.ts
const process = Deno.run({
  cmd: [Deno.execPath(), "fmt", "-"],
  stdin: "piped",
  stdout: "piped",
});

await process.stdin.write(
  new TextEncoder().encode("const a: number =28; console.log(20,(3+4      *  10)     )")
);
process.stdin.writable.close();

console.log(new TextDecoder().decode(await process.output()));

```

実行コマンド
```ps1
deno run --allow-run --allow-read ./format.ts
```


出力
```
const a: number = 28;
console.log(20, 3 + 4 * 10);

```

Runtime API として使えるようになれば, `--allow-run` のフラグはつけなくて良くなりそう

↓ 追加するかの議論
https://github.com/denoland/deno/issues/10731
【SAA-C03】文系新卒SAA合格記【1カ月半】

## はじめに
先日9/17にSAA-C03の試験を受け、見事合格できました。
この記事では、自分が効果のあったと思う勉強法を中心にまとめていきます！

## 受検時の状態

- 入社4カ月
- IT知識は軽くある（基本情報技術者取得済み）
- AWS未経験

## 勉強期間
1ヶ月半

## 勉強時間

- 労働時間の中で勉強できました
- 1ヶ月　平日5時間　休日なし
- 試験前の2週間　平日：仕事中6時間 / 業務外2時間　休日：6時間

## 使ったもの

:::note 
 **これだけでOK！AWS認定ソリューションアーキテクトーアソシエイト試験突破講座** 
:::
:::note
 **【C03へと更新中】AWS認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）** 
:::
::: note
 [ **A-com【AWS認定資格 試験対策】AWS各種サービス** ](https://aws-community.com/aws_services_for_exams/)
:::

- 勉強期間の前半は1つ目のUdemyでゆっくりハンズオンをしながら理解をし、後半は2つ目のUdemyで、ひたすら問題を解いてサービスを調べてまとめるのを繰り返していきました。
- サービスの概要や頻出ポイントを理解するのにA-comのサイトが非常に役に立ちました。
- 前日に解いた模試が、正答率66％で焦りましたがなんとか合格できました。


## 本番のスケジュール
14:45 会場着　本人確認や写真撮影を済ませる

15:00-17:20　受検
 ~~受検後に合格の文字が出ると教わったのですが、見逃しました...笑~~
→SAA-C02まであった、試験終了後に即合格の文字が出る仕様はどうやら無くなったようです。（11月に受検した先輩談）
 
18:38にバッジ認定メール
→この段階でAWSのサイト行ったらスコアレポート見れました。
2日後の明け方4時にスコアレポートのメールが来ました。（結果：736点　ギリギリ…）

## 本番の問題への印象

- 上記、SAA-C02の問題集での対策で十分対応できると思います。SAA-C03になってからの変化はあまり感じられず、全く見たことのないサービスや問題はなかった印象です。
- 一問一答のような単純な問題は少ないです。問題文も選択肢も長い問題が多かったです。
- [CloudTech](https://kws-cloud-tech.com/)より難しく、Udemy（【C03へと更新中】AWS認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問））の高難度の問題より、やや易しい感じがしました。
    - Udemyより、選択肢に紛らわしいものが少なく感じました。

## 効果があったと感じたこと

#### 1.  わからないサービスをノートにまとめていく
高難度の問題を繰り返し解いて、わからなかったサービスをノートにまとめていきました。自分は、PCで勉強するより紙に書く方が覚えるタイプなので、この方法は合っていたと思います。

特にストレージなど、類似のサービスが多い場合は、近くのページにして、違いを見やすくしたのもよかったです。（例：S3,EBS,EFSは同じページにまとめてました。）

#### 2. 説明しながら解く
SAAはベストな提案をすることを求められるので、四択××◎×ではなく、四択×〇◎△のなかから◎を選ばなくてはならない問題も出ます。

なぜ誤答なのかを説明しながら理解する癖をつけたことで、正答を選ぶスピード・質が上がったように思います。

#### 3.正答になりにくいサービスを暗記する
すでに終了しているサービスや旧型のサービスも出題されるので、それを暗記して、即消去していけたのはよかったです。

例）
 **CLB**　・・・旧タイプのロードバランサー。基本ELBの問題はALB・NLBが正解になることが多いです。
 **Amazon SWF**　・・・ワークフローのサービス。現在ではAWS Step Functionsを利用することが推奨されています。
 **スケジュールドリザーブドインスタンス** 　・・・現在は廃止されており、オンデマンドインスタンスのキャパシティー予約が推奨されています。

#### 4.直前はストレージ・DBを特訓
特にS3,RDS,DynamoDB,EFSなど
問題を解いて、徹底的に違いやユースケースを頭に叩き込みました。
結構出題されたので勉強した甲斐がありました。

#### 5.本番中に小休憩を挟む
Udemyの模試を解いているとき、全65問中30問以降に、集中力が切れて正答率が落ちていたことがわかったので、5問解いて目を休めるというルーティンで解きました。最後まで丁寧に問題が解けたので良かったと思います。

## やっておけばよかったこと
#### 1.ネットワークの基礎知識を身に着ける
複数サービスの連携の問題が多いので、システムの全体像を理解する力が必要だと感じました。
これは今後勉強していきたいです。

#### 2.図やキーワードを書きながら解く癖をつける
本番はホワイトボードとペンを支給されます。私は本番中に、図やキーワードを書きながら解いていったのですが、それがすごい自分に合っていたと感じました。試験問題の日本語は読みにくく、読むだけで体力を使うので、ホワイトボードを活用すると効率的に問題文を理解できると思います。

以上です。ありがとうございました。
WordPress【WooCommerce】アップセル自動相互登録機能

おすすめ商品の「アップセル」を、勝手に自動で相互登録していくphp。
一方の商品でアップセルを登録すると、登録された商品にもそのおすすめが登録されていく。

例）Aのアップセル（B・C・D）で登録すると、
　　Bのアップセル＝A・C・D
　　Cのアップセル＝A・B・D
　　Dのアップセル＝A・B・C

ただし、どの商品にもこれを適応させると、無限に増えるので
今回は商品カテゴリーを「new-colection」と「set」に限定している。

add_actionの設置場所がわからず、とりあえず商品ページのフッター読み込み時にしている。なので、一度商品ページのプレビューは読み込まないと相互登録されない。

アップセルもできるのでクロスセルも同じくできるはず。

```function.php

//アップセル商品を自動で相互登録する（どこで発火させるのかわからなかったのでとりあえずフッター読み込み時に）
add_action( 'wp_footer', 'show_up_sell_in_single_product' );

    function show_up_sell_in_single_product(){

	$terms = get_the_terms( get_the_ID(), 'product_cat' );

	//商品カテゴリー「new-collection」か「set」
	if(( $terms[0]->slug == 'new-colection' || $terms[0]->slug == 'set') ){

		//アップセルの商品取得
		$upsells = get_post_meta( get_the_ID(), '_upsell_ids',true);
		
		if(is_array($upsells)){

			foreach( $upsells as $upsell){
				$upsell_up = get_post_meta( $upsell , '_upsell_ids',true);
	
				//アップセルの商品にすでにアップセルがある場合
				if(is_array($upsell_up)){

					//$upsellのアップセルにそのページの商品を追加
					array_push($upsell_up,get_the_ID());

					//さらにほかのアップセルも追加
					$upsells_merge = array_merge($upsell_up , $upsells);

					//アップセルに同じ商品が出ないように削除する
					$key = array_search($upsell,$upsells_merge);
					unset($upsells_merge[$key]);

					//キーを連番に振り直し
					$upsells_merge = array_values($upsells_merge);
					update_post_meta( $upsell, '_upsell_ids', array_unique($upsells_merge));

					//削除した商品を戻す
					array_push($upsell_up,$upsell);
			
				
				}else{

					//アップセルに同じ商品が出ないように削除する
					$key = array_search($upsell,$upsells);
					unset($upsells[$key]);

					//キーを連番に振り直し
					$upsells = array_values($upsells);
					update_post_meta( $upsell, '_upsell_ids' ,array_unique($upsells));

					//削除した商品を戻す
					array_push($upsells,$upsell);

				}
			}	
		}
	}
}
```
【Django】モデルフィールドのnullとblankオプションの違い

# nullとblankオプションの違い
Djangoのモデルフィールドを設定する際に、オプションで設定するnullとblankはどう違のか。

一般的には

「**nullはデータベースの中身が空かどうか、blankはフォーム送信時の入力が空であるかどうか**」

であるとされています。

デフォルトではnullもblankもどちらもFalseで、それぞれデータベースの中身が空でないこと、フォーム送信時の入力が必須であると要求していることになります。ではなぜ、別々にオプションを設定する必要があるのでしょうか、以下の4パターンを事例に整理してみます。

## 1.null=False, blank=Falseの場合(デフォルト)
直訳すると「フォーム送信時にこのフィールドの入力は必須です。データベースに格納されるデータも空であってはいけません」ということになります。
ユーザー情報の入力画面で、Emailなどの必須項目のフィールド設定を行う際にはよく使うオプション設定になります。この設定はデフォルトになっているので、**入力必須フィールドはnullとblankのオプション設定は特に必要ない**ということになります。

## 2.null=True, blank=Trueの場合
直訳すると「フォーム送信時にこのフィールド入力は必須ではありません。データベースに格納されるデータも空で問題ありません」ということになります。
ユーザー情報の入力画面で外部リンクなど任意項目のフィールド設定を行う際によく使うオプションになります。

## 3.null=False, blank=Trueの場合
直訳すると「フォーム送信時にこのフィールドの入力は必須ではありません。しかしデータベースに格納されるデータは空(null)であってはいけません」ということになります。
これは特殊な例で、未入力のフィールドを送信するとImageFieldやDateFieldなどはデータベースにnullが格納されてしまいます。一方でCharFieldやTextFieldなどの文字列型である場合は、空の値はnullではなく、空文字列として格納されます。そのため文字列を扱うフィールドに限り使用可能なオプション設定であると言えます。

## 4.null=True, blank=Falseの場合
直訳すると「フォーム送信時にこのフィールドの入力は必須です。しかしデータベースに格納されるデータは空であっても構いません」ということになります。
このパターンも使う機会が非常に少ないのではないかと思います。

# まとめ
- nullはデータベースに格納される値が空(null)でもいいかどうか、blankはフォーム送信時に入力必須フィールドであるかどうか。
- デフォルトではnull、blankオプションはどちらもFalseで、入力必須フィールドであるとともに、データベースに(null以外の)何かしらの値が入っている必要がある。
- 必須項目でなく、任意項目のフィールドにはnull、blankオプションをどちらもTrueに設定する。
- 基本的にはnull、blankどちらもFalseかTrueで統一されて使われる場面が多い


# 参考
https://djangobrothers.com/blogs/django_null_blank/
リーダブルコードまとめ(第5章:コメントすべきことを知る)

# 第5章:コメントすべきことを知る
## 概要
コメントをすべきであるということと、コメントの目的が、書き手の意図を読み手に知らせるということであることを伝えている。また、コメントの機能である「コードの動作を説明すること」はコメント機能のごく一部でしかないことを伝えている、加えて、説明は「コメントすべきではないことを知る」「コードを書いている時の自分の考えを記録する」「読み手の立場になって何が必要になるかを考える」という3つの着眼点から貝瀬接してくれている。

### まとめ
・コメントの目的は、「コードの意図を読み手に理解してもらうこと」である。
・とにかくまずは、コメントを書いてみる。そこから、抽象的なことを書いているのであれば、具体的に書き直せばいい。
・「記録すべきではないことは書かない」「記録すべき自分の考える」「読み手の立場になって考える」これらが本章では大事である。

### 学んだ点
・コメントには、そのコメントを読むだけの価値を持たせるべきである。要するに、本来コードを読むことが多いにもかかわらず、コメントも書くと読むべきものが多くなりすぎるということ。
・すぐにわかるようなことは書くと無駄になるだけ
・コメントは、ひどい変数名を解説するために使うべきではない。
・関数等の命名でその関数等が自身を説明できるのであれば、わざわざコメントする必要はない。それを簡単に表せるのは、「優れたコード > ひどいコード + 優れたコメント 」
・優れたコメントは「考えを記録する」ためのものである。
・コード作成中によく使う記法について、「TOTDO 意味:後で手を入れる」「FIXME 意味:既知の不具合があるコード」「HACK 意味:あまり綺麗じゃない解決案」「XXX 意味:大きな問題点あり」等を用いる。
・これからコードをどうしたいかを考えてコメントを残しておき、解決の方向性を共有する。
・定数の値を決めた時に頭の中で考えていたことを記録することが大切である。
・自分よりもそのプロジェクトを理解していない人のためにコメントを書く必要がある。そのためには、「質問されそうなことを想像すること」や「ハマりそうな罠を告知すること」、「全体像のコメントをすること」、「要約コメントをすること」が重要である。
・「全体像のコメントをすること」がなぜ重要かというと、プロジェクトにアサインされてコードを読み進める際に、どのようにクラスとクラスがつながっているのか把握する時間的コストが高いためである。
・ライターズブロックを乗り越える。そのために、とりあえず思っていることをコメントに書いてみる。そして、その後に抽象的なことがあるとわかれば、具体的に誰でもわかるように編集すればいい。とにかく、コメントしてみることが大事である。

### 感想と振り返り
自身の時間ベースで、「コメントをしたら行が増えて読みにくいんじゃないか？」と考えることが多かった。しかし、むしろ逆でどのような意図で書いたかを理解してもらうことが目的なのであれば、コメントを1、2行増えることは大したことないということを学べました。
また、今後実装をどんどん進めていくと思いますが、その際はのちにアサインされた人がコードの意図をすぐに理解できるようなコメントや変数を記述していきたいですね！
CSSの勝手に余白が入るバグが勝手に治った話

ただのHTMLにバニラでCSSを書いていて、どうしても左端に変な余白が出来てハマりました。
この時読み込んでいたのでは50行あるかないかの小さなCSSだけ。HTMLタグのstyle属性は使っていなかった。
このページにリスト要素は使っていない。
ページはローカル環境で開いていた。
この時Apachを使わずにFinderから直接ブラウザに読み込ませていた。

この現象はChromeで開くと起きるがSafariでは起きないバグだった。

対策１
resetのため、style.cssの先頭にpaddingとmarginの全消しを入れる。

```
* {
    margin: 0;
    padding: 0;
}
```

たいていこれで直るけど治らなかった。

対策２
読み込んでいるjsを全部切る。

治らなかった。

対策3
ずれている要素の子要素を全部消してまだ何かuser-agentが悪さをしていないかみる。

全然わからない。

対策４
Chromeの「キャッシュの消去とハード再読み込み」　（ctrl+Rより強力なキャッシュクリア）を実行

治らなかった。

対策？
ちょうど昼休みの時間だったので一旦諦めて昼寝した。
約１時間後、
起きて戻ってきたら勝手に治っていた:open_mouth:。

なんだろう？まだ変なキャッシュが残っていたんだろうか。

レアケースだと思うけど、ページ内に要素がdivやmainタグ１個しかなくて、marginとpaddingを打ち消し消しているのに余白が消えない人は放置してみるとか、chromeを完全に閉じて開き直すとか、macを再起動するとかしたら治る可能性があるかもしれない。
using Module.new ってなに？

## はじめに

調べ物をしている際に、`using Module.new {}`というコードを見たのでどういう処理をするんだろうと思い調べてみた備忘録です。

## そもそも無名モジュールってなに？
無名モジュールは、その名の通り名前のついていないモジュールのことです。`Module.new`で作成したモジュールは無名モジュールとなるらしいです。 
~~もちろん無名なので、includeなどで指定することが出来ませんので他のファイルから呼び出すこともできません、多分...~~。Mix-inすることできますね...(@scivolaありがとうございます)


```ruby
mod = Module.new {
  def self.anonymous
    puts "anonymous module"
  end
}

mod.name
# => nil

mod.anonymous
# => anonymous module

MyClass = Class.new do
    include mod
end

MyClass.ancestors
# => [MyClass, #<Module:0x000001fb1163dc48>, Object, Kernel, BasicObject]
```

わざわざ無名で作成してるので、名前をつけたくなることがあるかは分かりませんが...  
変数を参照することで名前を与えることができます。

```ruby
mod = Module.new {
  def self.named
    puts "Named"
  end
}

Foo = mod

mod.name
# => Foo

Foo.named
# => Named
```

また、無名モジュールを返すメソッドを作成しincludeすることも可能です。

```ruby
def anonymous_module(val)
  Module.new {
    define_method "#{val}" do
      puts "#{val}"
    end
  }
end


class MyClass
  include anonymous_module('hey')
end

MyClass.new.hey
# => hey
```


## どのような時に使うのか？
タイトルから脱線していますが、そもそも`using Module.new`はどのようにしようするのか？

クラス拡張をして**他のファイルには影響を与えたくない**ときや、sendで**外部から呼ばれたくない**し、**他のファイルでは使わないけどメソッドでまとめておきたい**時に使用するらしいです。  

例えば、String#reverseを書き換えたいけど、このファイルのみでしか使わないんだよなーってときに

```ruby: anonymous.rb
using Module.new {
  refine String do
    def reverse
      "xxxx#{super}xxxx"
    end
  end
}

puts "abc".reverse
# => xxxxcbaxxxx
```
これで、String#reverseを書き換えることが出来ました。

ですが、先程のファイルを別ファイルに読込んでも拡張したString#reverseは使用することは出来ません。

```ruby: other_file.rb
require './anonymous'

puts "abc".reverse
# => cba
```

んー他に使い方があるのかな...何かわかれば追記していきます。

### 参考文献
[Rubyで、今いるファイルでだけヤンチャする機能](https://zenn.dev/ksss/articles/721c95581bff1fbc1bb1)
[ksss/lib](https://gist.github.com/ksss/e2f31e8743540c3009a1)
AWSのRoute53とEC2を使って独自で取得したドメイン名でWebページにアクセスできるようにした

自分で作成したWebページを公開した場合に自分独自のドメイン名で公開したいですよね。
「xxxxxxx.com」とか「xxxxxxxxxx.net」とか。

そこで、ムームードメインで取得したドメイン名をAWSのRoute53を使って紐づけることにしました。

こんな偉そうなこと言ってますけども、下記のページそのまんまです（笑）
本当に皆さんありがとうございます。。。
https://100webdesign.jp/services/web_knowhow/aws-site/web_knowhow-21161/

# まずは兎にも角にもドメイン名を取得
まだドメイン名を取得していない方はドメイン名を取得して下さい。

# Route53でホストゾーンの作成
1. ドメイン名に取得したドメイン名を入力
1. タイプは「パブリックホストゾーンを選択」
1. 「ホストゾーンの作成」を押す

# IPアドレスとの結びつけ（レコードの作成）
1. EC2メニューを開き、該当のEC2インスタンスのElastic IPをコピー
1. Route53に戻り、先ほど作成したホストゾーンをクリック
1. レコードの作成をクリック
1. レコード名は空白でOK
1. レコードタイプは「A – IPv4 アドレスと一部の AWS リソースにトラフィックをルーティングします。」を選択
1. エイリアスはOFFのままで、値欄に1でコピーしたIPアドレスを入力
1. ルーティングポリシーはシンプルルーティングのまま
1. 「レコードを作成」をクリック
1. レコードに今作成したレコードがあることを確認

以上でRoute53の設定は完了

# ドメインを取得したサービス側のネームサーバーの設定
1. ホストゾーン詳細画面に表示されているNS情報4つ（下図参照）を、ドメインを取得したサービス側のネームサーバーに登録
![ネームサーバーへの登録.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684763/02061e2d-2e0c-69e3-e0ff-ec7920b19cf9.png)

ネームサーバーへの登録方法はサービスによって異なるので調べてください！

2.しばらくしてドメイン名でアクセスすると


### 無事ドメイン名からアクセスすることができました！
Oracle なぜセーブポイントは削除されるのか

# 疑問
>「ROLLBACK TO」文を使って特定のセーブポイントにロールバックした場合、そのセーブポイント以降に作成されたセーブポイントは削除される

というところで、


削除するって物理的に行が削除されるの？
なんで削除されるの？
削除されないとどうなるの？


とたくさんの疑問がわいてきたので、調べた内容を共有します

### どのように削除されるのか
「物理的にファイルからその行が削除される」のではなく、発行されたSQLによって設定された SAVEPOINT  が論理消去されます。

### なんで削除されるのか？
SAVEPOINT まで ROLLBACK すると トランザクションが終了ます。すなわち、そこまでの処理は正常終了しているということです。したがってROLLBACK した SAVEPOINT 以降に設定された SAVEPOINT は不要になるためで消去されます。
削除されないと何か良くないというより、いらないものなので仕様上削除される。という認識です。（間違っていたら修正お願いします）

## まとめ
SQLって意外と奥が深いです。。。

Rails使っていた時は、アクティブレコードで勝手にSQL発行されていて意識することはなかったのですが、javaでプログラムするとSQLも書かないといけません。

全部書くので細かいところまで微調整できたり、
なんせすべて自分で書くので、処理の流れが見えてきます。

そのうえSQLは言語が変わっても使えるので、使える人材は重宝されると聞きます。

より学習に気合が入りますね！！！🔥

一緒に頑張りましょう！！

[参考資料](https://docs.oracle.com/cd/E57425_01/121/ZZPRE/GUID-DCC1B0F8-5945-470B-BCBE-8C5290920249.htm)
【Laravel+Heroku】Herokuデプロイ時に500エラーで画面が表示されない問題【APP_KEY未設定】

自分自身の備忘録として、LaravelプロジェクトをHerokuにデプロイした際の
500エラーの解消方法を残しておきます。
結論としては、APP_KEYが設定されていなかったことが原因です。
その他にも様々な原因があるかとは思いますが、解決策の一手段として確認してみてください。

## ■開発環境
OS：windows10
Laravel 8.83.14
Vue.js 2.6.12

## ■エラーの原因
Laravel Projectをcomposer create-projectコマンドで作成していたのに、
「heroku config:set APP_KEY=$(php artisan --no-ansi key:generate --show)」で
別の新規APP_KEYを作成しようとし、APP_KEYに値が登録されない状況が発生。
その結果、Heroku上でLaravelが動かない状況が発生し、500エラー。

composer create-projectコマンドでLaravelプロジェクトを作成すると、
その段階で自動的にAPP_KEYが作成される。



## ■解決策
### ①コマンドプロンプトでheroku configで設定状況を確認する
```
$ heroku config
```
### ②APP_KEYが設定されている場合
APP_KEY:の続きに値が入っていると設定されている（下記の場合だと123456789）ため、
入力されているAPP_KEYが正しいかどうかを④の方法で確認する。
```
$heroku config
 === herokuアプリ名 Config Vars
 APP_ENV: heroku
 APP_KEY: 123456789
以下省略
```
### ③APP_KEYが設定されていない場合
APP_KEY:の後ろに何も値が表示されていない。この場合はAPP_KEYが入っていない。
```
$heroku config
 === herokuアプリ名 Config Vars
 APP_ENV: heroku
 APP_KEY: 
以下省略
```

### ④APP_KEYを確認する
Laravelプロジェクト直下（package.jsonとかがあるディレクトリ）の.envファイルを開き、
上から3行目のAPP_KEYの=より右側を確認
```.env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=123456789
APP_DEBUG=true
APP_URL=http://sample.test
以下省略
```
### ⑤Heroku configにAPP_KEYをセットする
```
$heroku config:set APP_KEY=123456789
```
### ⑥Heroku configをもう一度確認する
これで、APP_KEYに.envのAPP_KEYと同じ値が入っていればOK。
```
$heroku config
```
### ⑦500エラーが解消されているか確認する
heroku openでwebページを開きなおし、500エラーが解消されているかどうかを確認
```
$heroku open
```

## ■まとめ
500エラーには様々な原因があるので、解決が難しいと思います。
今回の場合は、作成したwebアプリ上で、500エラー専用ページを作っていました。
そのため、専用エラーページが表示されず、Laravelデフォルトの500エラーページに
飛ばされた段階で、そもそも作成したアプリケーションが読み込まれていないことに気が付きました。
リーダブルコードまとめ(第4章:美しさ)

# 第4章:美しさ
## 概要
本章のメインテーマは、優れたコードは「美しい」コードでなければならないという考えのもと、それを達成するため「読み手が慣れているパターンと一貫性のあるレイアウトを使う」「似ているコードは似ているように見せる」「関連するコードをまとめてブロックにする」ということを説明している。

### まとめ
最終的には、「一貫性のあるスタイルは正しいスタイルよりも大切である」ということであった。兎にも角にも、コードを書くときは「整える」「まとめる」「揃える」を意識することが大事である。

### 学んだ点
・具体的なコードを用いて、「インデントが揃っている」や「変数等がブロックごとにまとめて記述されている」等の重要性を可視化できた。
・プログラミングは、コードを読むことに時間をかけるものという前提から、見た目が美しい方が使いやすい読みやすいことを学べた。
・コードの見た目を一貫性のあるものにするには、適切な改行を入れ、コメントも整列させる。
・見た目を良くすることで、コードの構造も改善することができ一石二鳥である。テストコードの導入等も簡単になる。
・線を真っ直ぐする。要するに、インデントを揃えるところは揃える。階層にすべきところは改行する。
・似たようなコードが複数ある場合、一貫性と意味のある並びに変えることが美しいコード作りに有効である。具体的には、「対応するHTMLフォームの<input>フィールドと同じ並びにする」「最重要なものから重要度順に並べる」「アルファベット順nに並べる」
・宣言をブロックにまとめることで、人間の「グループや階層を1つのまとまりと考える」という認知機能をうまく使う。
・一貫性のあるスタイルは「正しい」スタイルよりも大切である。

### 感想と振り返り
最終的には、「一貫性のあるスタイルは『正しい』スタイルよりも大切であるということ」でありましたが、僕的にはそんなに自分の書き方を主張したいわけでもないので、既存のコードに合わせてコード作成することを念頭に置いています。（できているかどうかは別としてw）
要するにこの章のまとめは、「郷に従え」ということですか？
フォントサイズ関連


フォントに関して悩むことがあり、自分がよく躓く部分、調べなおす部分を追記していこうと思う。
先ずは１つから

---

## 【ブラウザワイドが狭まると同時にフォントサイズを縮小させたい時】
#### 　→　画像に文字を載せた時のように文字も縮小させたい

```:scss
【vwはブラウザ幅に対して1/100のサイズを保つ】

font-size: 1vw;

```

#### 　＜使用例＞
　レスポンシブでは、
　　・PCサイズは通常指定
　　・タブレットサイズ(tab)で使用するのがおススメ
　　・スマホサイズ(sp)でvwを使用してしまうと小さくなりすぎるので通常指定

#### 　＜きっかけ＞

・背景に画像を持ってきたい
・ブラウザ全面を背景にしたいのではなく素材の高さや幅が全部見えていないとなりたたない背景
・長文のテキストを載せたい
・テキストは自分で打ち込み、背景だけ画像素材で用意

上記の状態に対して心配したのが

・レスポンシブでタブレットサイズはワイドが動的で背景に収まってた文章もワイドが狭まると文章がしたに伸びるはみ出るので対策したい
Android HTTP通信を行う(HttpUrlConnection)

# はじめに
学習記録。
Android開発で外部サーバーのCSVファイルやJSONを参照するためにHTTP通信を行う必要があったのでメモとして残す。

# 前提
アプリをインターネットに接続する許可を与えるためmanifestタグ内に以下2つのタグを追加。
```java:AndroidManifest.xml
<manifest …>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <application
    //以下省略
```
# 実装
```java:
fun startHttpRequest() {
    // URLオブジェクトを作成
    val url = URL("参照するURL")
    // HttpURLConnectionオブジェクトを取得
    val connection = url.openConnection() as? HttpURLConnection
    connection?.let {
        try {
            // 接続に使用する時間を設定(ミリ秒単位)
            it.connectTimeout = 2000
            // データ取得に使用する時間を設定(ミリ秒単位)
            it.readTimeout = 2000
            // HTTPリクエストメソッドの設定
            it.requestMethod = "GET"
            // 接続
            it.connect()
            // HttpURLConnectionオブジェクトからレスポンスデータを取得
            val stream = it.inputStream
            stream.close()
        } catch (ex: SocketTimeoutException) {
            Log.w(DEBUG_TAG, "通信タイムアウト", ex)
        }
        // // HttpURLConnectionオブジェクト解放
        it.disconnect()
    }
}
```
これでHTTP通信を行い、レスポンスを取得することができる。あとはレスポンスデータを加工する処理を追加して使用すれば良い。

# 注意点
通信処理をメインスレッドで行ってしまうとエラーが発生してしまうため、こちらの処理はワーカースレッドで行う必要があります。
実際開発の際も、こちらの処理はCoroutineを使用した非同期処理で実装をしていました。

# 参考
https://developer.android.com/reference/java/net/HttpURLConnection  
https://toronavi.com/connection-httpurlconnection
【Laravel】シーダーファイルで投稿時刻と更新時刻を出したい

`php artisan db:seed --class=PostsTableSeeder`したら怒られた。

# 開発環境

MySQL 5.7.38
PHP 7.3.33
Laravel 6.20.44

# エラー文

```:Terminal
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value
: '1658634263' for column 'created_at' at row 1
 (SQL: insert into `posts` (`user_id`, `title`, `body`, `created_at`, `updated_at`)
 values (2, title1, body1, 1658634263, 1658634263))
```

# 何が起こっている？

時間の型が違う。
当初、シーダーファイルでは
```:PoststableSeeder.php
'created_at' => time(),
'updated_at' => time()
```
としていた。

が、マイグレーションファイルに設定されているtimestamp型は 'YYYY-mm-dd HH:MM:SS'という形。
これに対し上記time型は 'HH:MM:SS'という形だったことによるアンマッチ。

# どうしたらいい？

DateTime型を指定する。
つまりシーダーファイルの怒られていた部分を
```:PostsTableSeeder.php
'created_at' => new DateTime(),
'updated_at' => new DateTime()
```
としてやればよい。

参照）
・[日付型と時刻型(DATE, TIME, DATETIME, TIMESTAMP, YEAR)](https://www.javadrive.jp/mysql/type/index4.html#:~:text=TIMESTAMP%20%E5%9E%8B%E3%81%AF%E6%97%A5%E4%BB%98%E3%81%A8,%E3%81%99%E3%82%8B%E7%9B%AE%E7%9A%84%E3%81%8C%E7%95%B0%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)
・[MySQLの不正な日時値エラーを修正する方法](https://sebhastian.com/mysql-incorrect-datetime-value/#:~:text=The%20MySQL%20Incorrect%20datetime%20value,or%20YYYYMMDDhhmmss%20for%20integer%20type.)


そうしてから改めて
```:Terminal
php artisan db:seed --class=PostsTableSeeder
```
 すると・・・

できた～！！！＼(^o^)／