OmniAICreator/Qiita-1.07M huggingface dataset:
不均衡データの取り扱い（oversampling_undersampling）

# はじめに

分類モデルを構築する際の
クラス間で事例の数や割合が極端に異なるデータは不均衡データと呼ばれます。

例：重篤な病気の発症有無、クレジットカードの不正利用予測

不均衡データでそのまま分類モデルを構築してしまうと
正解率 (Accuracy) こそ高いものの、適合率（recall）が低いモデルになることが想定されます。

極端な話、重篤な病気の発症予測であれば、すべて発症なしというモデルを作れば
未発症な人が大多数であるため正解率 (Accuracy)は高くなります。

||発症あり |発症なし|
|---|---|---|
|発症ありと予測|0 |0  |
|発症なしと予測|40  |9960  |

正解率 (Accuracy)→9960/10000 = 0.996

しかし、適合率（recall）は「発症ありと予測した人数/実際に発症あり」という式で
算出するため、発症ありと予測した人数が0人なのでrecall=0となります。

適合率（recall）→0/40 = 0

重篤な病気の発症有無やクレジットカードの不正利用のような例であれば
ある程度間違っていても発症ありの予測や不正利用ありの予測を
取りこぼさずにすることのほうが大切というのが感覚的にわかります。

分類モデルの評価指標はコンペであれば、
AUCやF値（F-measure、F-score）／F1スコア（F1-score）
で評価することが多いためなおさらrecallを上げることは大切といえます。

# UuderSamplingについて

不均衡データのまま分類モデルを構築すると適合率（recall）という事象への
対応策の一つとして「UuderSampling」が挙げられます。

「UuderSampling」は「少数派のデータ群に合わせて多数派のデータ群を削除する」という考えの手法です。

先ほどの重篤な病気の発症予測であれば、発症あり40人に対して、発症なしが5000人と多すぎるので発症なしの人数を減らします。

しかしただ減らすだけではダメで、減らす前と減らした後でデータの分布が変わっていないことが担保される必要があります。

データ数をクラスが9:1に比率になるようにアンダーサンプリングを実施
```php:UuderSampling　pythonで実施
from imblearn.under_sampling import RandomUnderSampler

# クラス1の数を保存
count_train_class_one = y_train.sum()
print("サンプリング実施前")
print(y_train.value_counts()) 

# クラス1が全体の10％になるまでクラス0を減らす
under = RandomUnderSampler(sampling_strategy={0:count_train_class_one*9, 1:count_train_class_one}, random_state=100)

# 学習用データに反映
x_train_under, y_train_under = under.fit_resample(X_train, y_train)

print("サンプリング実施後")
print(y_train_under.value_counts())
-----------------------------------------------------------------
実行結果
サンプリング実施前
0    6687
1     313
Name: 発症有, dtype: int64
サンプリング実施後
0    2817
1     313
Name: 発症有, dtype: int64
```
# OverSamplingについて

不均衡データの対応策の一つとして「UuderSampling」のほかにも
「OverSampling」が挙げられます。

「OverSampling」は「UuderSampling」とは逆に「少数派のデータを多数派に合わせて増やす」という考えの手法です。

```php:OverSampling　pythonで実施
from imblearn.over_sampling import SMOTE

# クラス1の数を保存
print("サンプリング実施前")
print(y_train.value_counts()) 

oversample = SMOTE(random_state=100)
x_train_over, y_train_over = oversample.fit_resample(X_train, y_train)

print("サンプリング実施後")
print(y_train_over.value_counts()) 
-----------------------------------------------------------------
実行結果
サンプリング実施前
0    6687
1     313
Name: 発症有, dtype: int64
サンプリング実施後
0    6687
1    6687
Name: 発症有, dtype: int64
```
# 最後に
「UnderSampling」も「OverSampling」もあくまでモデル構築時の訓練データに対して実施する処理であり
推論時は当手法は使わずにデータをモデルに投入し精度を確認する必要があります。

また2値分類以外のマルチクラス分類でも使用可能な手法となっています。

また実際のコンペの際は
「UnderSampling」と「OverSampling」どちらも使用して精度が上がる方を選択して
使用しています。
AWSの音声・テキスト系サービスの関連性を図解

AWSの音声やテキスト系のサービスについて、こんがらがってしまいそうなので図にまとめました。
tran～やら、Comprehendやら、関係性が分かりづらいなと思ってるのは私だけでしょうか。
AWS認定試験のために勉強していた中でこんがらがったというのも要因です。

生成AIの登場でそれぞれの勢力図も変わってきていますが、ざっくりしたまとめを作ってみました。

## マッピング図
音声、テキスト、画像、動画のデータがある中で、各サービスがどのように使われるのかをまとめてみました。
![AIML_service_map.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431837/d93ec42e-9c52-b5e9-3e6d-06145e710d4a.png)

## 対象サービス
対象としたサービスは、AWSのAI/MLサービスです。
各データの変換や分析によく使われるであろうサービスを選定しました。

「このサービスは何でないの？」ってのがあったら、追記できるか検討してみます。

## 所感
図解して、改めて気づいた点をまとめておきます。
* テキストから画像に変換するサービスはないですね。（2023年1月時点）
今後、Stable DiffusionとかMidjourneyみたいなのが実装される可能性もありそうです。
（2024年8月追記）
と思ってたら、Bedrockが登場して基盤モデルで近しいことができるので追記しました
ただ、Bedrock上で基盤モデルを使って、という形なので、今後新たにマネージドサービスが出る可能性もありそうですね。

* 画像と動画の間を結ぶサービスはないですね。
動画→画像は簡単にできるとして、画像→動画も一般的な動画編集ソフトでできるからでしょうか。
ただ、ディープフェイクのように「ある画像から、その前後を上手く補完しながら動画生成するサービス」がAWSで実装される日も来るのでしょうか。

* 解析サービスとしては、音声データを直接分析するサービスがありません。
発声者の感情や、声の抑揚をとらえるようなサービスが今後出てくるのでしょうか。

# まとめ
AWSの音声やテキスト系のサービスのマッピングを作成しました。
対象となるデータを起点に整理することで、各サービスの関係性を理解できるとともに、AWSでまだ何が実現できてないかを知ることができました。

こういうマッピングは公式ではあまり見たことがないので、関係性が分かりづらくなったり、ニーズがあれば他のサービスでもまとめていこうと思います！
Googleデジタルマーケティング＆Eコマース：ソーシャルメディア・マーケティングの価値

# はじめに

”Googleデジタルマーケティング＆Eコマース プロフェッショナル認定証"　の受講が完了しました(2022/3/3)。私がこのコースから得られた素晴らしい体験を、テーマごとに分割して、わかりやすくご紹介しています。興味を持たれた方は、是非下記を受講してみてください。

https://jp.coursera.org/professional-certificates/google-digital-marketing-ecommerce

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/24ea32fb-2fb3-bdb2-462a-4ffc4d60a96f.png" width="800">

# ソーシャルメディア・マーケティングの価値

ソーシャルメディア・マーケティングとは、エンゲージメントを高め、ビジネスや製品を宣伝するために、さまざまなソーシャルメディア・プラットフォーム向けにコンテンツを作成するプロセスのことを指します。

なぜソーシャルメディアはこれほど効果的なマーケティングツールなのでしょうか？

### <font color="MediumBlue">ブランド認知度の向上</font>

ブランド認知度とは、人々が特定のビジネスや製品にどれだけ親しんでいるかということです。例えば、あるソーシャルメディア上の投稿を見たとき、その投稿が自分の知らないブランドのものだったとしたらどうでしょう。今、そのブランドを思い出せたら、それがブランド認知度です。

### <font color="MediumBlue">新規顧客の獲得</font>

ソーシャルメディアは、世界人口の半数以上と関わっています。Pew Researchの調査によると、ソーシャルメディア・ユーザーの70％以上が、少なくとも1日に1回は自分のアカウントをチェックしているそうです。人々はこれらのプラットフォームを利用して、企業だけでなく友人や家族と交流しているため、ユーザーがログインすればいつでもつながりを持つことができます。このため、ソーシャルメディアは新規顧客をターゲットにするための自然な場となります。

### <font color="MediumBlue">既存顧客との関係強化</font>

信頼関係を築き、問題解決を支援し、ニーズや意見を重視していることを示す機会を提供します。

### <font color="MediumBlue">Webサイトへのトラフィック増加</font>

ソーシャルメディア上でウェブサイトのコンテンツを共有すれば、新しい投稿を公開するたびにユーザーをサイトに誘導することができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/16622ea8-cea1-5d81-a2ed-83d1bd709473.png" width="600">

また、ソーシャルメディアのすべてのプロフィールにWebサイトのアドレスを記載し、貴社についてもっと知りたいと思う人が簡単にアクセスできるようにすることで、Webサイトのトラフィックを増やすことができます。

### <font color="MediumBlue">リードを生み出す</font>

***<font color="MediumVioletRed">『リードとは、潜在的な顧客のこと』</font>***

ソーシャルメディアでは、リードとは、

- フォームへの入力
- 無料トライアルの購読
- 割引コードへのリンクのクリック

など、潜在顧客となる特定の行動を取った人のことを指します。

多くのソーシャルプラットフォームでは、リードの収集に特化した広告フォーマットが提供されています。

### <font color="MediumBlue">価値ある洞察を得る</font>

ソーシャルメディアを通じてターゲットオーディエンスの好き嫌いや興味について学ぶことは、そのオーディエンスに合わせてマーケティング戦略を調整するのに役立ちます。

多くのソーシャルメディアプラットフォームで提供されている分析ツールを使えば、ターゲット層に関する大量のデータを収集することも可能です。

さらに、ソーシャルメディアは、競合他社について知る機会にもなります。競合他社が行っていることを調査することで、競合他社がうまくいっていることを模倣し、そうでないことを改善することができるのです。

### <font color="MediumBlue">費用対効果が高い</font>

ほとんどのソーシャルネットワーキングプラットフォームは、無料でサインアップしてプロフィールを作成することができます。

また、ユーザーの興味や趣味だけでなく、ユーザーがソーシャルメディアプラットフォームで共有することを選択した個人情報や人口統計情報に基づいて、ユーザーにアプローチすることができます。これにより、ターゲットとする顧客を的確に絞り込むことができるため、より多くの顧客に予算を割くことを避けることができるのです。
emmetのいろいろな機能をまとめてみた

# はじめに
もともとは別の方法でコーディングを効率化しようと考えていたのだが、
emmetを編集する方法でもいけるのではないかと思い、調べてみた。
emmetをある程度使っていて、もうちょっと他の使い方がないか探している人向けです。

参考にしたサイトは以下である。

https://code.visualstudio.com/docs/editor/emmet

# 略語の展開にTabキーを使う。
```
"emmet.triggerExpansionOnTab": true
```
# マルチカーソルでemmetを使う。
試しに画像のようにしてみても、emmetは機能する。
![a1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731227/4dc29011-d807-2c3f-3db8-68c67fbd2d60.png)

# コメントを自動で付ける。
「重要なタグ」の前後にコメントを入力することができる。「重要なタグ」はデフォルトでは、「id属性」と「class属性」になっている。
```
div>div#page>p.title+p|c
```
で、
```
<div>
        <div id="page">
            <p class="title"></p>
            <!-- /.title -->
            <p></p>
        </div>
        <!-- /#page -->
    </div>
```
となる。（デフォルト設定の場合）

設定できるのは、
・filter.commentTrigger: コメント出力のトリガーとなるべき属性のリスト。デフォルトはid, class
・filter.commentAfter: 「重要なタグ」の直後に配置されるべきコメント。
・filter.commentBefore: 「重要なタグ」の直前に配置されるべきコメント。
である。

私はコメントが「重要なタグ」の前にある方が好みなので、
setting.jsonには、
```
"emmet.preferences": {
    "filter.commentBefore": "<!-- comment -->\n",
    "filter.commentAfter": ""
}
```
と記入している。
（使う機会はあるのだろうか？という疑問は残る）

# lang="en"を"lang="ja"にする。
setting.jsonに以下を記述する。
```
"emmet.variables": {
    "lang": "ja"
}
```

# まとめ
enをjaに自動化できたことは、効率化に繋がった。
自動でのコメントを置くのも役に立つかもしれない。
!でできる限り入力したいので、User Snippetsなどの変更も視野に入れていきたい。

# 追記
ユーザースニペットについて詳しく書かれたサイトがありましたので、ご紹介します。

https://blanche-toile.com/web/vscode-snippets
ポリモーフィックで実装したモデルを、Rspecでテストする方法

### 自分が勘違いしてしまっていたこと
僕がFactroyBotを定義しようと思っていました。ただ、その場合Typeごとその分定義しないといけません。
なので、今回はRspecの方どのTypeのデータを作成するか設定したいと思います。

### FactoryBotの中身
```
FactoryBot.define do
  factory :surveydo
    title { "アンケートタイトル" }
    description { "MyText" }
  end
end
```

必要な最低限の構成要素のみ定義するようにしました。

### Rspecの方
```
    context "アンケートが存在する場合" do
      let!(:survey) do
        create(
          :survey,
          surveyable_type: "User",
          surveyable_id: user.id,
        )
      end
    end
```
としました。上記のようにletを定義しました。
【Docker】ワークショップ

ワークショップ形式で、Dockerを操作して慣れるための記事です。
チーム内でDocker知識レベルアップ、共有を行うため書きました。

## 参考サイト
ものすごく簡潔に分かりやすく記載されていましたので、使わせてもらいます。
感謝。
https://zenn.dev/naoyuki42/articles/ae215286ba92b2

## 前提条件
Mac
Docker Desktopがインストールされていること

ディレクトリは任意の名前で作成した上で実施

## 1. Nginxのインストールまで
webサーバーとしてlaravelを使うため、Ngnixの作成を実施します。

https://zenn.dev/naoyuki42/articles/ae215286ba92b2#nginx%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E4%BD%9C%E6%88%90

この画面が出るまで参考サイトを見ながら実施
![スクリーンショット 2023-01-27 17.34.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701305/fe78a945-1868-96f5-b799-6c3c141851b4.png)

### ここまでの構築イメージ
![スクリーンショット 2023-01-27 17.48.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701305/1bdfc52e-559d-7570-4132-47abde32825c.png)

＊ Dockerのコンテナのポート80でした！

### ワーク
・docker compose psして中身を確認してみましょう
・NAMEは何が設定されているでしょう？NAMEを変更するにはどうすればいいでしょう？
・8080のポートを変えるとどうなるでしょう？8091に変えると何が起こるでしょう？

## 2. Dockerfileを使って、Nginxを構築
https://zenn.dev/naoyuki42/articles/ae215286ba92b2#nginx%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E4%BD%9C%E6%88%90

### ここまでの構築イメージ
1. と同じ


### ワーク
・1.との違いは？
・Docerfileでコピーしたファイルは何？（nginxの設定値を参照）
・docker-composeのvolumesは何をしているファイル？
・default.confのrootは何をしているファイル？
・Nameには何が指定されているか？

### nginxの設定値
https://qiita.com/leomaro7/items/98d6af85a4e155449aed

https://qiita.com/ShinyaOkazawa/items/789db336f27f0d080152

## 3. PHP~Laravelプロジェクト作成まで構築
https://zenn.dev/naoyuki42/articles/ae215286ba92b2#laravel%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90

この画面が出るまで参考サイトを見ながら実施

![スクリーンショット 2023-01-30 9.49.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701305/c50fb7b4-1243-75d7-dd7e-d345822e1bdd.png)

### ここまでの構築イメージ
ざっくりイメージ
![スクリーンショット 2023-03-13 9.24.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2701305/3f317133-b717-0848-1df4-616072d62b9a.png)




### ワーク
・構築のイメージ図に追加して、自分なりに理解していきましょう。
・dokcer側で作成したはずのlaravelプロジェクトが、ローカルのsrcディレクトリにもあります。なぜでしょう？
・dockerに入ると、「/var/www/html」にいます。なぜでしょう？
・次は、DB接続もしてみましょう。構築イメージを手書きしてみましょう。
https://zenn.dev/naoyuki42/articles/ae215286ba92b2#mysql%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E4%BD%9C%E6%88%90
コードレビューするときの観点

# コドレビューの観点

コドレビューの観点をまとめてみました。チェックリスト的なものになりますた。

## 機能性

* コードが設計通りの機能を有するか？
* データの流れ、取得方法は、設計と一致するか？
* データのチェックの漏れはないか？
* データの生成、修正、加工は、設計と矛盾がないか？
* ループの中で更にSQLなど重い処理を発行するなど、パフォーマンスの懸念はないか？
* 必要な場合、国際化の対応しているか？
* コネクションやリソースは適切な方法で閉じられているか？
* NULLとなる場合や値が取れない場合を考慮しているか？
* NULLをある程度許容したコードになっているか？

## 読みやすさ

* 名前の付け方は、共通認識の範囲か？
* スタイルガイドにそっているか？
* ループ、分岐等の処理記述方法は同じか？

## コード設計

* パラメータ、プロパティなど正しく機能区別されて実装されているか？
* インスタンス等の上書き、重複など考慮されているか？
* 類似コードの共通化を行っているか？
* 複雑なコードを書いていないか？
* 更に、シンプルに記述できる方法はないか？
* メソッド等で機能が適度に分解されているか？(作成、編集、出力、入力、変換、検証、受領)
* 大きい処理は小さい処理メソッドの組み合わせで表現されているか？
* 外部ライブラリの影響範囲、依存関係は限定的か？

## 運用保守

* ログは適切に出力されているか？
* 脆弱性となるコードを記述していないか？
* 定数記述すべきところをベタ書きしていないか？
* デッドロックなどの並行実行時の考慮はされているか？
* 権限外のデータにアクセスできる可能性はないか？
* 個人情報などの機密性のある情報を安易に外部に送信していないか？


## テスト

* テスト項目は機能に対して正しくテストしてあるか？
* テスト項目の網羅性に抜けがないか？
* テストの確認方法に問題はないか？
* 投入データ、生成方法には問題ないか？
* 結果は設計と比べて整合性は取れているか？
* テストの実行時間に問題はないか？
* テストできない、テストしないことが、明確になっているか？
* テスト項目の実施目的が決められた範囲でドキュメント化され、間違えがないか？

## 例外

* プロジェクで定められた記述方法に従って、例外を処理している。
* 起きる可能性が例外処理の抜けがないか？

## ドキュメント

* コードのコメントは適度に書かれているか？
* コードのコメントに間違えはないか？
* コードドキュメントとして問題ないか？

## 参照

https://google.github.io/eng-practices/review/reviewer/
【シェルスクリプト】コマンドがエラーの場合に最大N回までリトライする処理

最近シェルスクリプトを書くことが増えており、その中で書いたリトライ処理のコードについて残しておきます。


# 実現したい動作
1. あるコマンドを実行する
2. 異常終了（エラー発生）の場合はリトライ処理を行う
3. リトライが指定した回数に達した or コマンドが正常終了した場合はリトライ終了

# while文でリトライ
```bash
max_retry_count=3 # リトライ回数
retry_interval=5 # リトライ間隔（秒）

retry_count=0
while true; do
  # your_command -> 実行したいコマンド
  <your_command> && break

  # リトライ回数が上限に達している場合は、エラーメッセージを出力してリトライ終了
  retry_count=$((retry_count + 1))
  if [ $retry_count -eq $max_retry_count ]; then
    echo "Error: command failed after $max_retry_count attempts"
    break
  fi

  # 待機
  echo "Command failed. Retrying in $retry_interval seconds..."
  sleep $retry_interval
done
```

# for文でリトライ
```bash
max_retry_count=3 # リトライ回数
retry_interval=5 # リトライ間隔（秒）

# your_command -> 実行したいコマンド
<your_command>

# リトライ処理の実装
if [ $? != 0 ]; then
  for retry_num in $(seq 1 $max_retry_count)
  do
    # 待機
    echo "Command failed. Retrying in $retry_interval seconds..."
    sleep $retry_interval

    # コマンドが正常に終了した場合は、ループを終了
    <your_command> && break

    # リトライ回数が上限に達している場合は、エラーメッセージを出力
    if [ $retry_num -eq $max_retry_count ]; then
      echo "Error: command failed after $max_retry_count attempts"
    fi
  done
fi
```


# 補足解説
ここで、

```
<your_command> && break
```
の部分についてですが、実行している処理は下記と同義です。

```
<your_command>

if [ $? -eq 0 ]; then
  break
fi
```
bashシェルスクリプトでは `&&` によって複数コマンドのAND演算が可能であり、例えば、
```
command1 && command2
```
というコードは、"command1"が成功したら"command2"を実行するという処理になります（参考：[【Linux】シェルスクリプトにおける && と || の違い](https://qiita.com/ydah/items/528aefd1a1cab51285c3)）。


よって、`&&`の後ろに`break`を書いておくことで、`<your_command>`が成功した場合のみループを抜ける、という処理が可能になります。


以上。
Node.jsでアプリを作成してみた【ログイン機能付き人材派遣会社用アプリ】


## PostgreSQLとは？

- RDBMS(リレーショナルデータベース管理システム)

## Setting Up the Node.js project
```
npm init
//いくつかのライブラリをインストールする
npm i express cors multer pg sequelize fast-csv json2csv
```
- Express - アプリケーションにREST APIを提供するためにExpressを使用
- Cors - バックエンドとフロントエンドのサーバー間でCORS（Cross-Origin Resource Sharing）を設定するために、このライブラリを使用
- Multer - multipart/form-dataの処理に使用するNode.jsのミドルウェアで、主にファイルのアップロードに使用
- Pg - Node.js用のノンブロッキングPostgreSQLクライアント
- Sequelize - Oracle、Postgres、MySQL、MariaDB、SQLite、SQL Serverなど様々なデータベースに対応した最新のTypeScriptおよびNode.js ORM
- Fast-csv - Node.jsでCSVやその他の区切り値のファイルをパースしてフォーマットするためにこのライブラリを使用
- Json2csv - このライブラリを使用して、JSONをカラムタイトルと適切な行末を持つCSVに変換

serverフォルダを作成し、そのディレクトリ内にすべてのコードを追加する。

次に、フロントエンドのReactクライアントを定義する必要があるので、フロントエンドをホストするための別のディレクトリを作成する。
```
npx create-react-app client
```
## Configure a PostgreSQL Database

PostgreSQLのインスタンスをホストして、バックエンドサーバーがそのDBと接続できるように設定する。Docker-compose.ymlファイルを作成することで、PostgreSQLのインスタンスを素早く立ち上げれる。
```
touch docker-compose.yml
```
```docker-compose.yml
version: '3.1'

services:
  db:
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: Welcome123
      POSTGRES_DB: csvdb

```
ローカルにPostgresインスタンスがホストされる。

```
docker-compose up
```
サーバーディレクトリ内にconfig/db.config.jsというファイルを作成し、この接続コードを記述する。

```config/db.config.js
const HOST = "localhost";
const USER = "postgres";
const PASSWORD = "Welcome123";
const DB = "csvdb";
const dialect = "postgres";
const pool = {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
};

export default {
    HOST,
    USER,
    PASSWORD,
    DB,
    dialect,
    pool
};
```
## Defining the Data Model

データベースに保存する Employee データを定義する。modelsフォルダを作成し、その中にモデルファイルemployee.model.jsを作成します。

```models/employee.model.js:
import Sequelize from 'sequelize';
import { sequelize } from '../database/index.js';

const Employee = sequelize.define('employee', {
  id: {
    type: Sequelize.STRING,
    primaryKey: true,
  },
  name: {
    type: Sequelize.STRING,
  },
  email: {
    type: Sequelize.STRING,
  },
  username: {
    type: Sequelize.STRING,
  },
  dob: {
    type: Sequelize.STRING,
  },
  company: {
    type: Sequelize.STRING,
  },
  address: {
    type: Sequelize.STRING,
  },
  location: {
    type: Sequelize.STRING,
  },
  salary: {
    type: Sequelize.STRING,
  },
  about: {
    type: Sequelize.STRING,
  },
  role: {
    type: Sequelize.STRING,
  },
  managedBy: {
    type: Sequelize.STRING,
    references: {
      model: 'employees',
      key: 'id',
    },
  },
  createdAt: {
    type: Sequelize.STRING,
  },
  updatedAt: {
    type: Sequelize.STRING,
  },
  avatar: {
    type: Sequelize.STRING,
  },
});

export default Employee;
```



## 参考サイト
[【PostgreSQL入門】初心者OK！PostgreSQLでデータベースの基礎を学んでみよう【APIの構築まで】](https://www.youtube.com/watch?v=SyVw6Vjsf8E)
[PostgreSQLのダウンロード及びインストール](https://www.javadrive.jp/postgresql/install/index1.html)
[Building a CSV Importer with Node.js](https://reflectoring.io/node-csv-importer/)
ChatGPT APIをHTML+PHPから実行するスクリプト

# 概要
[ChatGPT API](https://openai.com/blog/introducing-chatgpt-and-whisper-apis)を、PHPから動かすためのスクリプトです。

※ 一人用です。会話のログが残る仕様のため、複数ユーザで利用するには向いていません。
※ ストリームには対応していません。回答が一度に出力されるため、長文の場合はレスポンスに5〜10秒程度かかる事があります。
※ また、[OpenAIサーバの混雑具合](https://status.openai.com/)などによりレスポンスに遅延が発生する場合があります。

▼ トップページ画面
![sshot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180923/aebceda1-b6c5-6917-c59e-e1d6b61446c4.jpeg)
フォームに質問を入力してEnterキーを押すと、APIに質問が送られ、以下の様にフォームの下にレスポンスが表示されます。
![sshot 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180923/1bc6e590-e7f0-dc71-90b0-608097a7cc82.jpeg)
会話は「会話をリセット」でクリアしない限り、これまでの話題はそのまま続きます。
![sshot 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180923/e94e2cc9-6118-54f0-05ef-9660146f5a05.jpeg)

# 事前準備
PHP7が動作するWebサーバと、ChatGPT APIのAPIキーを取得しておいてください。
APIキーは[こちら](https://platform.openai.com/account/api-keys)からSign upすることで、取得が可能です。
詳しい方法が不明な場合は「ChatGPT API APIキー取得」などで検索していただければ、方法を画像つきで説明しているサイトがヒットするかと思います。
ローカル環境でもPHP7がインストールされていれば動作します。XAMPPがおすすめです。

# ダウンロード
PHPスクリプト一式は以下からダウンロード可能です。
https://aokikotori.com/download/chatgpt_api_php.zip
zipファイルを解凍し、マニュアルに沿ってインストールしてください。

# インストール
1. php/chatapi.phpの6行目API_KEYを、取得したAPIキーに書き換える
	修正前: define('API_KEY', 'sk-');
	修正後: define('API_KEY', 'sk-*************************');

2. すべてのファイルをアップロード

3. アップロードしたユーザとPHPの実行権限が異なる場合、data/data.txtに書き込み権限を与える

4. https://（アップロードした場所）/index.phpにアクセス

# Q&A

#### 質問を送信しても、回答が表示されない
data/data.txtに書き込み権限が与えられていない可能性があります。
FTPのアカウントとPHPの実行アカウントが異なる事が多いので、不明な場合は data/data.txtのパーミッションを 0666に 設定しておくと良いでしょう。
#### 他の人の質問も見えてしまうのですが…。
このチャットボットは一人用です。data.txtに質問と回答がすべて入る様になっています。
#### 前の会話を維持できますか？
はい。「会話をリセット」するまでの会話はAPIに送信されますので、
任意の話題での会話や、しりとりなどのゲームを楽しむことが出来ます。
#### このPHPを使うとAPIの利用料金が物凄いのですが…。
ChatGPT APIでは、文字数に応じて料金が高くなる仕様です。
適度に「会話をリセット」を実行しないと、表示されている内容をすべて送信するので、料金はご注意ください。（APIの料金ページなどを随時確認のうえ、上限設定などをご利用ください）
#### APIにキャラクターを設定して、ロールプレイを楽しみたい！
php/chatapi.phpの39行目の contentの中身を書き換えてください。

修正前
```php/chatgpt.php
$data["messages"][] = array('role' => 'system', 'content' => "");
````
修正後
```php/chatgpt.php
$data["messages"][] = array('role' => 'system', 'content' => "関西弁で喋りなさい");
````

#### APIに送信するパラメータをいじってみたい
APIでは、生成されるレスポンスのトークンの最大数や、サンプリング温度など、細かく設定できる様です。
php/chatapi.phpの34行目を下の様に追記してください。

修正前
```php/chatgpt.php
$data = array('model' => 'gpt-3.5-turbo');
````
修正後
```php/chatgpt.php
// top_p(サンプリング温度)を0.5、max_tokens(レスポンスのトークン)をmax300に設定
$data = array('model' => 'gpt-3.5-turbo', 'top_p' => 0.5, 'max_tokens' => 300);
````

#### ソースコードの書き方がなってない！
どこで何を処理しているのかを分かりやすくするために、あえてこうしています。
詳しい方は適宜書き換えていただければ幸いです。

#### 動きが違うよね？　だって本家のChatGPTだともっとレスポンスが速くて、1文字ずつチャカチャカ出てくるんですけど？
レスポンスが出力されるまでの時間は、こちらの方法が若干速いです。
本家では回答が1文字ずつ出力されるので、速く見えるのです。

もちろん、本家の様にストリーミングで出力させることも出来ます。
ただ出力にはPHPだけでなく、JavaScriptが必要になりますので、以下のページ上で解説しております。
https://qiita.com/kotonoha0109/items/52e73d500b19363b388f
謎解きの記録アプリを開発してみる #1

# はじめに

この記録は個人で開発するにあたって、アプリの開発過程や仕様決定の流れを残しておこうと思い立ち、いろいろ備忘録的に残そうと思っています。

# 開発の動機

最近謎解きにハマっています。

さて、リアルで開催される謎解きゲームには参加する際のルールがいくつかあります。
その中でも公演のチケットを買う際に気をつけなければならないことが、「同じ公演に2度参加できない」というルールです。
これを逆手に取った「リピーター公演」というものもありますが、基本的には1度参加したら成功までの過程をすべて知ってしまうため、2度目に間違って参加してしまうと他の人にネタバレしないように石と化してやり過ごすしかありません。
チケットを買うときに買っていれば…という後悔をしないためにも、過去の参加した公演を記録しておこうと思いました。
そしてGoogleスプレッドシートで記録を残すことにしたものの、入力が面倒なのが困りもので記録し忘れることがあり、自分がチケットを購入していなかったりすると過去に遡るのは大変。
ついでに参加するといつもやるTwitterへのツイートだったりも簡単にできたらいいなと思い、アプリを開発しようと至りました。

# 競合

https://www.nazo.site

http://www.mchs-u.net/mc/app/dhist/

# 要件定義

ここで開発するアプリの要件を定義する。

- 参加時にすぐ登録できるため、Android/iOS向けのモバイルアプリとして開発する
- 参加した公演がすぐに追加できるUIを実装する
- これから参加する公演名を入れると参加した記録があるかを検索できるUIを実装する
- アプリでは、公演自体の情報と公演への参加記録の情報、を扱う
- 公演情報には、開催する団体、会場、公演概要、開催期間、開催回(開始時刻)の一覧、ツイートハッシュタグを保持する
- 参加記録情報には、参加した公演、成功失敗、感想、を保持する
- 公演情報は参加記録の登録時に新しく追加するか、すでにあるものを選択する
- 参加記録を追加した際にハッシュタグをつけて参加ツイートが簡単にできる

# 基本設計

ここで基本的な設計を全体、UI、データモデルに分けて定義する。

## 開発環境

- App: Flutter
- Database: Firebase
- VCS: Git/GitHub

## UI設計

- アプリを起動したらログイン画面が表示される
- すでにログインしていたらホーム画面を表示する
- ホーム画面には過去の参加公演情報の一覧と追加ボタンが表示される

## データモデル設計

### 公演情報

- 公演名
- 公演ジャンル (ルーム型、ホール型など)
- 開催団体

### 公演回情報

- 公演情報
- 開催日時 (1月5日 10:00回、2月10日 13:00回、など)

### 参加情報

- 参加した公演回
- 成功/失敗
- 感想

# 次回

未定
誤ってhas_manyの後に単数系で記載してしまった後のエラー

```
  1) ::Api::V2::Advisers::OurServeysController GET #index アンケートが存在する場合 レスポンスが返ってくる
     Failure/Error: let!(:survey) { create(:survey, adviser_company: adviser_company) }

     ActiveModel::MissingAttributeError:
       can't write unknown attribute `adviser_company_id`
```
というエラーが出てしまいました。
でもな、ファクトリーボットも間違ってないよね。と思っていたら、

```
    has_many :survey, as: :surveyable, dependent: :destroy
```

モデルの紐付けが単数系になってました。（泣）
確かに取得する時も
```
user.survey
```
と単数になってますね。初歩的なミスでした。
（PHP）PDOでプリペアドステートメントを使わずにヒアドキュメントに直接変数埋め込めばいいじゃんって思ったらちゃんとバグった（※R5.3.14追記）

## やりたいこと
こうインサートしたい。
|  age  |  name  |
| ---- | ---- |
|  15  |  Danji  |

## ヒアドキュメントに変数を直接埋め込んだ
```php:ヒアドキュメント
$pdo = new PDO(
    'pgsql:host=localhost dbname=mydb port=5432',
    'user',
    ''
);

insert(15, 'Denji');

function insert (int $age, string $name)
{
    global $pdo;

    $sql = <<<SQL
    INSERT INTO test_function_args (age, name) VALUES ({$age}, {$name}); -- 直接変数を埋め込む
    SQL;
    $stmt = $pdo->query($sql);
}

// 結果
// インサートできない
```
インサートできませんでした
var_dumpしたら原因すぐわかった

```php
var_dump($sql);
// string(62) "INSERT INTO test_function_args (age, name) VALUES (15, Denji);"
// 'Denji' じゃなくて Denji になってる
```

## プリペアドステートメントでちゃんと書いた
```php:プリペアドステートメント
$pdo = new PDO(
    'pgsql:host=localhost dbname=mydb port=5432',
    'user',
    ''
);

insert(15, 'Denji');

function insert (int $age, string $name)
{
    global $pdo;

    $sql = <<<SQL
    INSERT INTO test_function_args (age, name) VALUES (:age, :name);
    SQL;

    $stmt = $pdo->prepare($sql);
    $stmt->execute([
        ':age' => $age, 
        ':name' => $name
    ]);
}

// 結果
// インサートされる
```

インサートされました。
プリペアドステートメントちゃんと使います。

## （追記）ヒアドキュメントで書けたがそもそも...
単純に変数をシングルクォーテーションで囲めばいい話だった
```php
// 変数を''で囲めば可能
INSERT INTO test_function_args (age, name) VALUES ({$age}, '{$name}');
```

とはいえ、そもそもこれだとSQLインジェクションに対応できていないので、プリペアドステートメントを使いましょう。
読書メーターの利用規約を改訂について

https://media.bookmeter.com/2023/03/info.html

>いつも読書メーターをご利用いただきありがとうございます。
2023年3月10日に利用規約を改訂いたしましたので詳細をお知らせします。
改訂理由
当社は、新しい本との出会いの創出を目指す出版業への貢献として、利用者様が読書メーターにご投稿いただいた感想・レビュー等に基づき作成される統計情報等を活用し、出版業関連の事業者に提供いたします。これらの利用実態に合わせて、読書メーター利用規約第4条第3項を以下に記載のとおり変更いたしました。
なお、これらの利用は感想・レビュー等を統計的に加工したものを想定しており、ご投稿いただいた感想・レビューの販売等を意図したものではありません。
改訂内容
 変更後｜　第4条第3項
利用者は、投稿コンテンツにつき、当社に対して、日本国内外問わず対価の支払いなく、非独占的で自由に利用（複製、改変、頒布、譲渡、貸与、翻訳、翻案、又はこれらに基づき二次的著作物を作成し、販売、上演、展示、公表、公衆送信（送信可能化を含みます。）等できる権利を含みます。）する権利（これらの権利を第三者に再許諾できる権利も含みます。）を、当該著作権の存続期間の満了日まで、許諾したものとします。なお、利用者は当社及び当社が指定する第三者に対して著作者人格権を行使しないものとします。
変更前
利用者は、投稿コンテンツにつき、当社に対して、日本国内外問わず対価の支払いなく、非独占的で自由に使用（複製、改変、頒布、譲渡、貸与、翻訳、翻案、又はこれらに基づき二次的著作物を作成し、上演、展示、公表、公衆送信（送信可能化を含みます。）等できる権利を含みます。）する権利（サブライセンス権も含みます。）を、当該著作権の存続期間の満了日まで、許諾したものとします。なお、利用者は当社に対して著作者人格権を行使しないものとします 。
今後とも、読書メーターをどうぞよろしくお願いいたします。

読書メーターに掲載した内容が、自己著作物からの転載であることを記載してある場合に、この条項がどれほど有効かが分かっていません。　

「著作者人格権」のすべてを行使しないことができるかどうか、よく分かっていません。　

「統計的に加工したもの」は、とても大切なことで、統計処理の妥当性の確認ができるかどうかが大切かもしれません。人工知能を使って加工した場合の、処理の概要については説明があるとよいでしょう。
[MEMO]APIの種類

- RESTful
- gRPC
- GraphQL
- SOAP

# RESTful
RESTの原則に則って構築されたWebシステムのHTTPでの呼び出しインターフェースのこと。

### REST
「REST（REpresentational State Transfer）」（レスト）とは、広く普及したWebのインフラをそのまま利用して、簡易な手順でWebサービスへのアクセスを可能にする仕組み。もともとはHTTPプロトコルの設計者の一人でもあるRoy Fielding氏によって2000年に提唱されたものである。

Representational →具象化された
State →状態の
Transfer →転送

### RESTの原則

1. クライアント/サーバーの分離：クライアントとサーバーは、それぞれ独立して設計されるべきです。クライアントとサーバーの間のインターフェースには、汎用的な標準プロトコル（HTTPなど）が使用されます。

2. ステートレスな通信：RESTの通信はステートレスであるべきです。すなわち、サーバーは、クライアントからの要求を処理するために必要な情報を保存しないように設計されます。そのため、各要求には、必要な情報が含まれる必要があります。

3. キャッシュ可能なデータ：RESTの通信は、キャッシュを有効にすることができます。クライアントは、キャッシュからリソースを取得することで、ネットワーク通信を減らすことができます。

4. 統一インターフェース：RESTの通信には、リソースを一意に識別するURI (Uniform Resource Identifier)が使用されます。また、HTTPメソッド (GET、POST、PUT、DELETEなど) を使用して、リソースに対する操作を表現します。

5. レイヤード・システム：RESTの通信は、分散システムに適したレイヤードアーキテクチャに基づいて設計されるべきです。これにより、各層の変更が他の層に影響を与えず、システム全体を柔軟に拡張することができます。

6. コードオンデマンド (オプション)：RESTの通信には、サーバーからクライアントに対して実行可能なコードを返すことができます。これにより、クライアント側に処理を分散することができます。
通常、REST APIは静的なデータ（XML形式やJSON形式（→★））を応答として返却しますが、しかし場合によっては動的なプログラム（Java Appletなど）を返却する事も可能です。

# gRPC
Googleが2015年に開発したオープンソースのRPCです。

### RPC
RPC(Remote Procedure Call/遠隔手続き呼び出し)とは、ネットワーク上の他端末と通信するための仕組みのことで、これによって他端末のプログラムをリモートで実行することができます。
テキストベースの JSON や XML ではなく、バイナリにシリアル化されたデータでタイプセーフなデータ転送インターフェイスを定義します。また、HTTP/1 よりも信頼性が高く、高速で効率良い HTTP/2 を利用しています。

# 4つのサービスメソッド
gRPC API には4 種類のサービスメソッドがあります。
- Unary: クライアントはサーバーに 1 つのリクエストを送信し、サーバーは 1 つのレスポンスを返します。
- Client-Streaming: クライアントはサーバーに一連のリクエストをストリーミングし、その後ストリームの終了を示すメッセージを送信します。サーバーは 1 つのレスポンスを返します。
- Server-Streaming: クライアントは 1 つずつリクエストを送信し、サーバーは一連のメッセージをストリーミングしてレスポンスを返します。ストリームは、すべてのメッセージが送信されるか、クライアントが切断されるまで継続されます。
- Bidirectional Streaming: クライアントとサーバーの間に接続が確立され、必要に応じてどちらかがメッセージを送信したり、接続を終了できます。


# GraphQL
Facebook(Meta)が開発したAPI向けに作られたクエリ言語およびランタイムです


# SOAP
Simple Object Access Protocol
XML のみを使用してメッセージングサービスを提供します。
Microsoftが開発

リクエスト
```
POST /WebSite1/WebService.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/getHello"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getHello xmlns="http://tempuri.org/">
      <str>string</str>
    </getHello>
  </soap:Body>
</soap:Envelope>
```

レスポンス
```
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getHelloResponse xmlns="http://tempuri.org/">
      <getHelloResult>string</getHelloResult>
    </getHelloResponse>
  </soap:Body>
</soap:Envelope>
```
【まとめ】CKANをDockerで構築するための手順をまとめてみた！

# CKAN CkanExtension

どうも皆様、こんにちは！
今回はオープンデータを公開するために使われているCKANを触ってみたので、ご紹介しようと思います！

## CKANとは・・・？

CKANとはデータのハブやポータルをサポートするための**オープンソースのDMS**(Data Management System)です。CKANは世界中にある何百ものポータルにおいて、**データの配布・共有・活用をより簡単に行える**ようにすることが出来ます。(CKANホームページ訳)

https://ckan.org/

今、流行りのデータ連携基盤で活用するオープンデータの配布に一役買っているOSSになります。

## CKANを使ってみよう

CKAN公式のドキュメントを参考に実際にやっていってみます！

https://docs.ckan.org/en/2.9/maintaining/installing/install-from-docker-compose.html

### 利用した技術

* Docker
    * 今回はローカルの環境を汚さないために利用します
* Python(2.7 , ^3.6)
    * CKANがサポートしている言語になります
    * 今後はPython3系のみのサポートに切り替わる
    * Python3.9以降はまだバグ等が残っているが将来的にはサポートする予定

### ダウンロード

まずは任意のディレクトリにて以下のコマンドを入力し、CKANのCloneを作成します。

```
git clone https://github.com/ckan/ckan.git
```

その後、任意のCKANバージョンに切り替えます。
今回は最新の2.9.7を使っていきます！

1. CKANのディレクトリに移動
    ```
    cd ckan
    ```

2. バージョンの切り替え
    ```
    git checkout tags/ckan-2.9.7
    ```

### コンテナの立ち上げ

以下のコマンドでCKANのコンテナ群を立ち上げます。

1. ```docker-compose.yml```のあるディレクトリに移動
    ```
    cd contrib/docker
    ```

2. ```docker compose```でコンテナの立ち上げ
    ```
    docker compose up -d --build
    ```

※CKANのコンテナがうまく立ち上がらない場合は以下のコマンドで再起動をしてください。

```
docker-compose restart ckan
```

### 便利なパスの登録

こちらの登録をしておくと、開発をする際に便利かもしれません。

```
export VOL_CKAN_HOME=`docker volume inspect docker_ckan_home | jq -r -c '.[] | .Mountpoint'`
```
```
export VOL_CKAN_CONFIG=`docker volume inspect docker_ckan_config | jq -r -c '.[] | .Mountpoint'`
```
```
export VOL_CKAN_STORAGE=`docker volume inspect docker_ckan_storage | jq -r -c '.[] | .Mountpoint'`
```

### Datastoreとdatapusher

Datastoreとdatapusherを有効にする際には事前に設定が必要になります。

1. 以下のコマンドを実行します
    ```
    docker exec ckan /usr/local/bin/ckan -c /etc/ckan/production.ini datastore set-permissions | docker exec -i db psql -U ckan
    ```

2. ```production.ini```を開く
    
    コンテナ内に入る
    ```
    docker exec -it ckan bash
    ```
    ```production.ini```ファイルをvimで開く
    ```
    vim /etc/ckan/production.ini
    ```
    
3. ```production.ini```を編集する

    ```datastore```と```datapusher```を追加
    ```
    ckan.plugins = stats ・・・recline_view datastore datapusher
    ```

    コメントアウトを解除
    ```
    ## Datapusher settings

    # Make sure you have set up the DataStore

    ckan.datapusher.formats = csv xls xlsx tsv application/csv application/vnd.ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    #ckan.datapusher.url = http://127.0.0.1:8800/
    #ckan.datapusher.assume_task_stale_after = 3600
    ```

4. CKANコンテナを再起動
    ```
    docker-compose restart ckan
    ```

### 管理者ユーザーを登録

以下のコマンドを実行して管理者ユーザーを作成しておきます。(名前は任意)
```
docker exec -it ckan /usr/local/bin/ckan -c /etc/ckan/production.ini sysadmin add johndoe
```

これにより登録した名前とパスワードでログインをすることができます。

### CKANへアクセス

以下のURLへアクセスできるようになります。
```
http://localhost:5000
```

## まとめ

いかがでしたでしょうか？
今回の手順に従えば、案外簡単にできたのではないでしょうか？

次回はCKANの拡張機能の開発について記事を書きたいと思います！
公開までお待ちください！
[CKANの拡張機能開発(公開予定)]()

実際にチュートリアルをやってみて、
公式のドキュメントだけでは詰まってしまう場所がいくつかありました。
この記事が皆様のお役に立てることを願います。
機械学習入門

目次

ML モデリングの概要
ML モデルに関する A-E ブック
ステップ 1: 問題定義
ステップ 2: データ収集
ステップ 3: モデルの選択
ステップ 4: データの学習
ステップ 5: モデルのデプロイ

近年のML と AI アプリケーションは、間違いなく指数関数的な速度で成長しています。 このため、ML モデルと、それらを現実世界のシナリオで最新の状態に保つ方法について知ることが重要になります。 結局のところ、誰も取り残されたいとは思いません。 

ML モデルとは

この ML モデルの定義はさまざまですが、基本的には、データを入力として受け取り、学習し、それに応じてトレーニングしてパターンを見つけ、学習に基づいて予測を行うモデル として説明できます。 面白そうですね。

ML モデルとは何かがわかったので、ML モデルが実際にどのように作成され、トレーニングされるかを見てみましょう。

ステップ 1: 解決する必要がある問題または実行する必要があるタスクを理解するという、最も基本的かつ本質的なタスクから始めます。 次に、データを取得し、モデルから必要な出力の種類を理解することを続けます。 ここでは、次のような質問に対する回答を収集します。
私たちの主な目的は何ですか？
どのような入力データが必要で、それが利用可能か?
モデルが使用される実際のシナリオは何ですか?
また、モデルはすでに与えられているデータでトレーニングされ、それに応じた予測を行うことも理解する必要があります。 ただし、日々のシナリオでは、データは変更される可能性があるため、モデルを頻繁に適応させ、最新の状態に保つ必要があります。

ステップ 2: 何をする必要があり、どのデータが必要かがわかったので、そのデータを取得して準備するという実際の作業を開始します。 モデルの精度と信頼性を決定する上で重要な役割を果たすため、高品質のデータを収集することは非常に重要です。
収集されたデータは、データ クリーニングと呼ばれるプロセスを経て、悪いリンゴを除外する必要があります。 面倒な作業のように聞こえるかもしれませんが、モデルの精度を確保するための非常に重要なステップです。 データのクリーニングには、いくつかの手順が含まれます。
モデルにとって役に立たない、不要、重複、または冗長なデータ フィールドを削除します。
データの転送中、または測定や入力中に発生する可能性のある構造エラーを修正します。
場合によってはモデルの精度に影響を与える可能性があるため、不要な外れ値を削除します。
データセット内の空のフィールドまたは欠損値の処理。 過去の経験に基づいて、それらを削除するか、何らかの価値を追加します。

ステップ 3: ここで、要件に基づいて、ニーズに最適なモデルを決定します。 モデルの選択は、数値データ、画像データ、音声データなど、処理されるデータによって異なります。 クラスタリング、回帰、分類、予測など、さまざまなアルゴリズムから選択します。

ステップ 4: 必要なものがすべて揃ったので、収集したデータを使用してモデルをトレーニングします。 より高いレベルの精度を達成できるように、モデルのトレーニングとテストを繰り返します。 データはトレーニング セットとテスト セットに分割され、モデルの検証に使用されます。
このステップでは、より高いレベルの精度と精度を達成しようとします。 場合によっては、目的の結果が得られない場合は、モデルにオーバーフィッティングまたはアンダーフィッティングの問題がある可能性があります。 この場合、モデルは、必要なレベルの精度が得られるまで再トレーニングおよび変更されます。

ステップ 5: これが最後のステップです。モデルを現実の世界で使用して予測を行う準備が整いました。

私たちのモデルが現実世界に出て、ライブデータを処理し、外出先で予測を行うようになったので、間違った結果や不十分な予測が見られるようになるかもしれません。 その背後にある理由を知りたいですか？ これをよりよく理解するために、次のブログまでお付き合いください :)

それまでの間、私と私のチームが本番環境で ML モデルの観察と改善に取り組んでいるオープンソース プロジェクトをチェックしていただき、スターを付けてサポートを示してください ⭐: https://github.com/uptrain-ai/uptrain
プログラミング言語の色々

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はプログラミング言語の色々について更に詳しく調べてみましょう！
![インスタスライド_202303021.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/8a62ab2a-755e-2910-3907-be9b289df716.gif)


# プログラミング言語の色々
・インタプリタ型言語
・コンパイル型言語
・中間言語型
がある

# インタプリタ型言語
ソースコードが読み込まれ、文法チェック後、一行づつステップ実行が行われる。

エラーとなる場合は、ブラウザにエラーの行数が表示されるため、デバッグが容易。

# コンパイル型言語
ソースコードを一度、コンパイルし、オブジェクトモジュールを作成。それを実行させる。
Windowsでは、**.exeファイルがオブジェクトモジュールである。
一度、コンパイル後の実行なので、コンパイル時に最適化処理などが施される事もあり、パフォーマンスが高い。
但し、最適化処理により、ソースコードとの行数がマッチしなくなるため、デバッグは難しい。そのため、
デバッガーツールを使用する事が多い。

# 中間言語型言語
コンパイル型の場合、プラットフォームに依存した形のオブジェクトモジュールが生成させるため、
プラットフォームが変る場合は、再コンパイルが必要になる。

中間言語型の場合は、中間言語を生成するので、プラットフォームに依存しないものが生成される。
Javaの場合、その差異をJavaVMが吸収し動作させる形になる。
 
# まとめ
ー様々なプログラミング言語が存在する。

ーインタプリタ型言語、コンパイル型言語、中間言語型がある


# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
初学者によるAWSクラウドプラクティショナー合格体験記

【前提】
2022.06〜 アプリケーションエンジニアに転職
2023.01〜 AWSを用いた開発に参加
2023.03 AWS-CLF取得

【勉強方法】
❶YouTubeで概要の理解(1週間)
ひとつ3〜5分程度の動画×40本くらいでAWSクラウドプラクティショナーの出題範囲の表面の部分をさらうことができる。

・試験の概要把握
(https://youtube.com/playlist?list=PLPzcoMdqG5nrDBqipym2vSqxCOnW3PhWq)

・クラウドのコンセプト
(https://youtube.com/playlist?list=PLPzcoMdqG5npvpXicqEw1tjMjC725bR6L)

・セキュリティとコンプライアンス
(https://youtube.com/playlist?list=PLPzcoMdqG5nozEs4TskWlPRqYedWQRcZu)

・テクノロジー
(https://youtube.com/playlist?list=PLPzcoMdqG5noLR7rAc552mvPADUmmdSt1)

・請求と料金設定
(https://youtube.com/playlist?list=PLPzcoMdqG5np65rPvCGtYOImTJ1ZPrMsv)


❷Udemyで詳細学習(1週間〜2週間)
・「これだけでok! aws認定クラウドプラクティショナー試験突破講座」
(https://www.udemy.com/course/ok-aws-e/)

このコースの動画を見て、各サービスの詳細を理解する。
一見すると数が多く大変なように見えるが、大半はハンズオンと言って実際のAWS画面の操作方法の動画。体験や画像として記憶できる反面、操作方法までは試験に出ないため省略可能。それらを除く講義系の動画のみの視聴なら1/3〜1/4程度で済む。


❸問題集に取り組む(2週間)
・「この問題だけで合格可能 AWS認定クラウドプラクティショナー 模擬試験問題集」
(https://www.udemy.com/course/aws-4260/)

ある程度知識を蓄えたら、残りの時間はアウトプット→未定着部分のインプットに費やす。

参考までに筆者の得点推移
・模擬試験（基本レベル①）
72%→81%
・模擬試験（基本レベル②）
63%→67%→84%
・模擬試験（本番レベル①）
47%→64%→80%
・模擬試験（本番レベル②）
53%→89%
・模擬試験（本番レベル③）
40%→72%→86%


筆者はこの流れで学習し、約1ヶ月でクラウドプラクティショナー合格することができました。
具体的な試験日程を決めて予約を済ませたあとは、焦りから学習スピードも増え、一気に知識が身についた気がします。
皆さんのご参考になれば幸いです。
[favicon]楽々設定

# faviconの最小構成の忘備録

まずは正方形のfavicon元画像を作成。

svgとpngで出力。
favicon.svg
favicon.png

favicon generatorにfavicon.pngを投げて変換。

https://ao-system.net/favicongenerator/

大量にできますが一部のみ使います。
1. favicon.ico
1. apple-touch-icon-180x180.png
1. icon-192x192.png
1. icon-512x512.png

# 簡単に説明
#### favicon.svg
モダンブラウザ用。軽い

#### favicon.ico
レガシーブラウザ用

#### apple-touch-icon-180x180.png
iphone用

#### icon-192 or icon-512
Android用

# headタグに入れる
```html
<head>
    <link rel='icon' type='image/svg+xml' href='/favicon.svg' />
    <link rel='icon' id='favicon' href='/favicon.ico' sizes='any' />
    <link rel='apple-touch-icon' sizes='180x180' href='/apple-touch-icon-180x180.png' />
    <link rel='manifest' href='/manifest.webmanifest' />
</head>
```

```json:manifest.webmanifest
{
  "icons": [
    { "src": "/icon-192x192.png", "type": "image/png", "sizes": "192x192" },
    { "src": "/icon-512x512.png", "type": "image/png", "sizes": "512x512" }
  ]
}

```

favicon.icoのanyはブラウザがsvg読むようにするため？


# 参考
https://coliss.com/articles/build-websites/operation/work/how-to-favicon.html
[seo] web fontを最適化して100点取る

今回はfontの最適化についてです。
最近は静的なページならastroがかなり強いと思いますがweb fontの最適化は考える余地があります。
今回はそんなfontを最適化する話です。

# 問題
最初はAstroの公式に載っている方法でFontsourceを入れてやっていました。

https://docs.astro.build/ja/guides/fonts/

```js:layout.astro
---
import '@fontsource/noto-sans-jp/400.css'
import '@fontsource/noto-sans-jp/500.css'
import '@fontsource/noto-sans-jp/700.css'
import '@fontsource/noto-serif-jp/700.css'
---
```
## 結果
webfontを入れる前は100点だったのですが、50点に急落。cssがレンダリングブロックしてるとのこと。
これは実は↑で読み込んだfontがバンドルされてるのでファイルが大きくなってるんですね。それにしても10秒近くレンダリングブロックとか行き過ぎでは？
fontsourceの指定を間違っている気もしているので、わかれば教えてください。

![スクリーンショット 2023-03-13 3.58.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/241d233d-6b1d-77c0-cc95-7c0c04c6004f.png)
![スクリーンショット 2023-03-13 3.59.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/3ee2365e-4814-5690-ab71-a16486892f62.png)

# てな感じで頑張ってみます。
### やり方その1
スマホではweb fontを読み込まない。
...
だめか、だめですよね。これは負けた気がします。

### やり方その2
google fontのcdnから遅延ロードする。
```html
    <link rel='preconnect' href='https://fonts.googleapis.com' />
    <link rel='preconnect' href='https://fonts.gstatic.com' crossorigin />
    <link
      rel='preload'
      as='style'
      href='https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700&family=Noto+Serif+JP:wght@700&display=swap'
    />
    <link
      rel='stylesheet'
      media='print'
      onload="this.media='all'"
      href='https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700&family=Noto+Serif+JP:wght@700&display=swap'
    />
    <!-- no-JS fallback -->
    <noscript>
      <link
        rel='stylesheet'
        href='https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700&family=Noto+Serif+JP:wght@700&display=swap'
      />
    </noscript>
```
![スクリーンショット 2023-03-13 4.12.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/aa3e79cc-ad92-8717-743d-14488a405480.png)
![スクリーンショット 2023-03-13 4.13.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/c8e117f5-676a-3535-977d-540d80e9af5b.png)

これでレンダリングブロック解決されることを祈る！！！
...
おしい。でも全然妥協点！

### やり方その3
どうしても不要なものを読み込んでしまいます。

そこで必要なファイルだけ読み込むようにしましょう。
まず、google fontをcdnではなく、ダウンロードしてください。

:::note info
追記
ここからダウンロードしたwoff2を配置した方が早いです。
https://gwfh.mranftl.com/fonts
:::

otfでダウンロードできると思うので3割ほど圧縮されるwoff2に変換しましょう。
cloud convertにえいや。

https://cloudconvert.com/

作成されたwoff2ファイルをfont-faceで読み込みます。

:::note info
mediumのやつが上手く変換できなかったのでバグ流場合はこちらからダウンロードでもよいかも？
https://github.com/ixkaito/NotoSansJP-subset
:::

```html
<style>
    @font-face {
      font-family: 'Noto Sans JP';
      src: url('/fonts/NotoSansJP-Regular.woff2') format('woff2');
      font-weight: normal;
      font-style: normal;
      font-display: swap;
    }
/* 他のも読み込み */
</style>
```

どうだ。

![スクリーンショット 2023-03-13 4.37.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/351c9419-e599-c5e1-f621-0a4df36a5525.png)

無事100点に戻りました🎉

woff2に対応していないブラウザはどうするの？
~~無視。~~ 基本対応しているので大丈夫なはずです。最悪system font読むし？
【個人開発 #1】初学者がrailsでTODOアプリを作ってみる～要件定義、基本設計～

# はじめに
どうも、かずです。
2021/9～エンジニアとして実務をしてから約1年半経ちます。(2023/03/13に書いてます)
自分でアプリを作ったことが無かったので、これを機に挑戦しようと思いました。

※この記事は自分の設計ドキュメントとしても使うので、その都度更新される場合があるのでご了承ください<m(__)m>
## きっかけ
・知識の定着のために簡単なアプリを作ってみたくなった。
・実装とテストしかしてこなかったので、基本設計～保守運用まで一貫してどんなものかやってみたい。
・今後のキャリアの為に成果物を残したい。


## 開発過程も残しちゃえ
いろいろ準備して完成してからQiitaに記事でも書こうと思ったのですが、
要件定義とか基本設計を書き出してる時にふと思いました、、、

「この開発過程も記事にすればいいじゃん・・・！」

これは芸人であり実業家の西野亮廣さんが
ミュージカルの練習風景を映像として販売してたのを思い出してやろうと思いました。

お金にはならんけど、初学者とかこういうの見たいと思ってｗ
あとは自分の振り返りにもとてもいいと思ってます。

自分が3年後もエンジニアしてたら、思い出せるように。

# どんなTODOアプリにするか
* まずはざっくり箇条書きにします。
    * 転職のポートフォリオよりもちょっとハイレベルなイケてるアプリ
    * UIはシンプルで見やすいものとする
    * 設定したTODOの締め切りが近づいたらリマインダーが送信されるようにする
    * 1日の終わりに設定したTODOがどの程度達成されたかを確認できるようにする
    * ユーザーログイン機能つけて、ユーザー毎のTODOアプリにする
    * 無料で作れるレベルにする
    * 機能は比較的簡単にして、レイアウトにはちょっとこだわりたい
    * 社会人向け
    * 資格勉強とか頑張りたい人向け
    * タグ付け機能：TODOにタグをつけて分類できる機能
    * ラベル機能：TODOにラベルをつけて色分けできる機能
    * カレンダー表示機能：カレンダー形式でTODOを表示する機能



# 要件定義

* シンプルで見やすいUIを実装する。
* TODOアイテムには、タイトル、説明、締め切り、優先度、タグ、ラベルを含める。
* 締め切りが近づいた場合、リマインダー通知を送信する機能を実装する。
* 1日の終わりに、設定されたTODOアイテムがどの程度完了したかを確認できるようにする。
* ユーザーログイン機能を実装し、ユーザーごとにTODOアプリを作成する。
* アプリは無料で利用できるようにする。
* タグ付け機能を実装し、TODOアイテムを分類できるようにする。
* ラベル機能を実装し、TODOアイテムを色分けできるようにする。
* カレンダー表示機能を実装し、TODOアイテムをカレンダー形式で表示する。



# 基本設計

### 【UI設計】
* シンプルなUIを実装し、直感的に操作ができるようにする。
* 画面レイアウトは、TODOリストを一覧表示するメイン画面と、TODOアイテムの詳細を表示するサブ画面に分ける。
* メイン画面では、TODOリストをカード形式で表示し、それぞれのカードにはタイトル、説明、優先度、締め切り日、進捗状況、ラベル、タグを表示する。
* カードの並び順は、優先度が高いものから順に表示する。
* カレンダー画面では、TODOアイテムをカレンダー形式で表示する。
* モバイルデバイスからの利用にも配慮し、レスポンシブデザインを採用する。

### 【データモデル設計】
* PostgreSQLを採用する。
* ユーザー情報を格納する「ユーザー」テーブルを作成する。
* 「TODOアイテム」テーブルを作成し、タイトル、説明、優先度、締め切り日、進捗状況、ラベル、タグをカラムに持たせる。
* 「ユーザー」と「TODOアイテム」の関係を1対多の関係にする。
* 通知履歴を格納するための「通知」テーブルを作成し、通知日時、通知先のユーザーID、通知内容などをカラムに持たせる。
* ユーザー情報のパスワードは、ハッシュ化して格納する。

### 【システムフロー設計】
* ユーザーがログインすると、自分のTODOアプリにアクセスできるようになる。
* ユーザーは、TODOアイテムを作成、編集、削除できる。
* TODOアイテムの進捗状況を更新すると、1日の終わりに進捗状況を確認できるようにする。
* 締め切り日が近づいたTODOアイテムに対して、リマインダー通知をSSLを導入して安全に送信する。
* ユーザーは、タグ付けやラベル付けを行い、TODOアイテムを分類することができる。
* ユーザーは、カレンダー画面でTODOアイテムを確認できる。

### 【開発環境】
* 言語: Ruby on Rails、Vue.js
* データベース: PostgreSQL
* エディタ: Visual Studio Code
* デプロイ先: Heroku
* バージョン管理: Git、GitHub

# 課題
* リマインダー通知をSSLを導入して安全に送信する
    * これは余裕があったらでいいかな…難しそう
    * それかパスワードのハッシュ化など別の方法でセキュリティ対策を検討する

# メモ
* cronジョブ
    * リマインダーを実現するためには、cronジョブを使用するとよいでしょう。例えば、5分ごとに「deadlineが近づいたTODOがあるかどうか」を確認するようなジョブを作成します。ジョブはRakeタスクで実行し、ジョブのログはロギング機能を使用して保存します。

* リマインダーメールを送信するために、Action Mailerを使用する
    * eminderアクションを実装します。reminderアクションは、deadlineが近づいたTODOを取得し、リマインダーメールを送信します。
    * SendGrid、Mailgun、SES

* パスワードのハッシュ化
    * ユーザーがパスワードを登録する際に、入力されたパスワードをハッシュ化するための関数を実行します。例えば、Ruby on Railsであれば BCrypt ライブラリを使用することができます。
    * ハッシュ化されたパスワードを、ユーザー情報と一緒にデータベースに格納します。
    * ユーザーがログインする際に、入力されたパスワードを同じハッシュ関数でハッシュ化します。
    * データベースに格納されたハッシュ化されたパスワードと、ログイン時にハッシュ化されたパスワードを比較します。
    * パスワードが一致すれば、ログインが成功したと判断します。
* sa

# おわりに

ひとまずこんなもんで進めていきますー
たぶん全部の設計を再現するのは今の自分には不可能なので、やりやすいところから進めていきます～


Twitterやてます(主に趣味垢)
https://twitter.com/takazu_engineer
2023/3/13主にITとかセキュリティの記事

ライフカードを偽るフィッシング確認、注意を(3/11)
https://news.mynavi.jp/techplus/article/20230311-2617366/

ジェネレーティブAIの進化に潜む「膨大なCO2排出」という不都合な真実(3/11)
https://www.sankei.com/article/20230311-PYWPXLKW3VNFFNDZK6V4BCJ2HI/?ownedutm_source=owned%20site&ownedutm_medium=referral&ownedutm_campaign=ranking&ownedutm_content=%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%96AI%E3%81%AE%E9%80%B2%E5%8C%96%E3%81%AB%E6%BD%9C%E3%82%80%E3%80%8C%E8%86%A8%E5%A4%A7%E3%81%AACO2%E6%8E%92%E5%87%BA%E3%80%8D%E3%81%A8%E3%81%84%E3%81%86%E4%B8%8D%E9%83%BD%E5%90%88%E3%81%AA%E7%9C%9F%E5%AE%9F

クラウドに関する記事のまとめ(2023.3.5～2023.3.11）
https://blogs.itmedia.co.jp/business20/2023/03/2023352023311.html?ref=rss

iPhoneのパスコード盗難リスクを確認せよ、身近なスマホに特大の危機が潜む可能性(3/10)
https://active.nikkeibp.co.jp/atcl/act/19/00432/030600007/
	
Meta、Twitter競合の分散型SNSアプリを計画中と認める(3/12)
https://gunosy.com/articles/evGQz

TikTok全面禁止、米国がしたくてもできない理由(3/11)
https://news.biglobe.ne.jp/international/0311/jbp_230311_0392517494.html

韓国の整形医院の映像流出、「カメラは中国製」で物議―中国メディア(3/10)
https://www.recordchina.co.jp/b910512-s39-c30-d0202.html

5000万円超を引き出した暴力団幹部に有罪判決　ネットバンク不正アクセス事件　那覇地裁(3/11)
https://news.yahoo.co.jp/articles/661e3484b7772e6f55e458ade85476c8c9b53c4d
archLinuxでシステムのレスキュー用USBを作る。


# 事の発端

レスキュー用LiveCDで、満足なものがなかったのが事の発端です。
SystemRescueCDというシステムを試してみたら、Archlinuxだったのですが、日本語環境がなく、他のLinux LiveCDでは不満だったためです。

### 基本archLinuxシステムのインストール

ここを参照してUSBにarchLinuxをインストールしてください。

https://qiita.com/fygar256/items/841d23c94161e9024ca5

### yayのインストール

```
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si
```

### 各種ツールのインストール

```
sudo pacman -S gparted util-linux
yay -S partimage testdisk ddrescue
yay -S k3b
```

### Chromeのインストール

```
yay -S google-chrome
```
【Android】RecyclerViewの基底クラスを作る ~ボイラーテンプレートを減らす努力~

# はじめに
RecyclerViewを書くたびに似たような記載するのが嫌になったので、いつも書くコードをまとめた基底クラスを作りました。

# RecyclerView.ViewHolder

## 基底クラス
ViewHolderの方の基底クラス
Viewの作成を省略できるようにしています
```kotlin:BaseRecyclerViewHolder.kt
abstract class BaseRecyclerViewHolder<T>(view: View) : RecyclerView.ViewHolder(view) {
    // viewを更新するときの処理
    abstract fun bind(data: T)

    companion object {
        // ViewHolderの作成のテンプレート
        inline fun <reified T, VH : BaseRecyclerViewHolder<T>> create(
            parent: ViewGroup,
            layoutResId: Int,
            createViewHolder: (View) -> VH
        ): VH {
            val view = LayoutInflater.from(parent.context).inflate(layoutResId, parent, false)
            return createViewHolder(view).apply {
                itemView.tag = this
            }
        }
    }
}
```

## 使い方
```kotlin:RecyclerListCell
data class CellData(val title: String)

class RecyclerListCell(view: View) : BaseRecyclerViewHolder<CellData>(view) {
    private val title = view.findViewById<TextView>(R.id.text_title)

    override fun bind(data: CellData) {
        title.text = data.title
    }

    companion object {
        // Adapterの方でViewHolderを作る時に呼び出す
        fun create(parent: ViewGroup): RecyclerListCell =
            create(parent, R.layout.title_cell, ::RecyclerListCell)
    }
}
```

# RecyclerView.Adapter
## 基底クラス
Adapterの方の基底クラス
いつも使う機能だけを定義
```kotlin:BaseRecyclerViewAdapter.kt
abstract class BaseRecyclerViewAdapter<T> : RecyclerView.Adapter<BaseRecyclerViewHolder<T>>() {
    abstract val dataList: MutableList<T>

    protected abstract fun bindViewHolder(holder: VH, item: T)

    // 外から更新する際に呼び出す
    fun dataSetChange(newDataList: List<T>) {
        dataList.clear()
        dataList.addAll(newDataList)
        notifyDataSetChanged()
    }

    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<T>, position: Int) {
        bindViewHolder(holder, dataList[position])
    }

    override fun getItemCount() = dataList.size
}
```

## 使い方
```kotlin:RecyclerListAdapter
class RecyclerListAdapter(
    override val dataList: MutableList<CellData>
) : BaseRecyclerViewAdapter<CellData>() {
    override fun bindViewHolder(holder: BaseRecyclerViewHolder<CellData>, item: CellData) {
        holder.bind(item)
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): BaseRecyclerViewHolder<CellData> =
        RecyclerListCell.create(parent)
}
```
【Homebrew】PHP7.4からPHP8.2へアップグレードする

# 目的
HomebrewのPHPパッケージを7.4から8.2へ更新します。7.4と8.2では依存ライブラリ``icu4c``のバージョンが異なるため、反映に一手間必要です。

詳しくは[こちらの記事](https://qiita.com/y_sone/private/f34cd19c6f02d34a9f89#php82%E3%81%A7%E3%81%AF%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%99%E3%82%8B)をご覧ください。

# 動作環境
- MacBook Air M1 2020
- macOS Ventura 13.2.1
- Homebrew 4.0.6
- PHPはHomebrewのパッケージphp@7.4を使用
```bash
% php -v
PHP 7.4.30 (cli) (built: Jun  9 2022 09:20:03) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v3.1.4, Copyright (c) 2002-2022, by Derick Rethans
    with Zend OPcache v7.4.30, Copyright (c), by Zend Technologies
% which php
/opt/homebrew/opt/php@7.4/bin/php
```

# 72系のicu4cをインストール
PHP7.4が使用するicu4cは``70系``ですが、PHP8.2は``72系``を使用します。

72系のicu4cをインストールします。
```bash
# 現在は70系
% brew list icu4c --versions
icu4c 70.1
# 72系をインストール
% brew install icu4c
icu4c 70.1 is already installed but outdated (so it will be upgraded).
# 以下省略
```

インストール時に70.1から72.1へアップグレードされます。インストール後は70.1が消えています。
```bash
% brew list icu4c --versions
icu4c 72.1
```

この時点で``icu4c 72.1``のパッケージが反映されているため、brew linkの実行は不要です。

# PHP7.4の設定を削除
PHP7.4のパッケージを``brew unlink``します。
```bash
% brew unlink php@7.4
Unlinking /opt/homebrew/Cellar/php@7.4/7.4.30... ==> Downloading https://formulae.brew.sh/api/formula.jws.json

25 symlinks removed.
```

ログインシェルの設定ファイルからexportを削除します。
```.zshrc
export PATH="/opt/homebrew/opt/php@7.4/bin:$PATH"
export PATH="/opt/homebrew/opt/php@7.4/sbin:$PATH"
```

設定が削除されたため、この時点でphpコマンドが利用できなくなります。
```bash
 % php -v
zsh: command not found: php
```

# PHP8.2を反映
PHPのパッケージにPHP8.2が反映されている想定です。
brew upgradeの実行後など、PHPのパッケージが最新の状態であればPHP8.2がインストールされていると思います。（2023年3月現在）

PHPのパッケージを``brew link``で反映します。
```bash
% brew link php
Linking /opt/homebrew/Cellar/php/8.2.3... 24 symlinks created.
```

これでPHP8.2が使えるようになりました！
```bash
 % php -v
PHP 8.2.3 (cli) (built: Mar 12 2023 12:08:11) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.3, Copyright (c) Zend Technologies
```

今度は逆にPHP7.4が使えなくなりますが...
PHPは複数のバージョンで確認したいケースもあるので、簡単にバージョンを切り替える方法を模索したいです。

``phpbrew``や``phpenv``が気になります。

https://github.com/phpbrew/phpbrew

https://github.com/phpenv/phpenv

# 採用PR
弊社で一緒に働く仲間を募集しています。

Devトークやってます。お気軽にご応募ください(^^)

https://plus.jobs.qiita.com/dev-talk-company-pickup-vivion/

募集要項はこちらをご覧ください！

https://hrmos.co/pages/vivion/jobs?category=1687770395095928832
対象のViewが画面に表示されているかを判定する方法

# はじめに
ScrollView等で対象のViewが画面に表示されたかを判定する方法を紹介します。

# 結論
対象のViewとScrollView（もしくは画面）のRectを取得し、対象のViewが画面のRectに含まれているかをcontainsメソッドで判定するだけです。

## そもそもRectとは
Viewのleft, top, right, bottomの４つの整数座標を保持するオブジェクトです。
参考: https://developer.android.com/reference/android/graphics/Rect

## 手順
1. Rect取得メソッドを作成
    ```kotlin
    fun View.getRect(): Rect {
        val array = IntArray(2)
        this.getLocationOnScreen(array)
        return Rect(array[0], array[1], array[0] + this.width, array[1] + this.height)
    }
    ```

1. ViewのRectを取得
    ```kotlin:MainActivity.kt
    val scrollViewRect = binding.scrollView.getRect()
    val targetViewRect = binding.targetView.getRect()
    ```

1. 画面に表示されているかを判定
    ```kotlin:MainActivity.kt
    if (scrollViewRect.coutains(targetViewRect)) {
        // 表示されている場合の処理
    } else {
        // 表示されていない場合の処理
    }
    ```
ScrollViewのsetOnScrollChangeListener等と組み合わせて使ってみてください