OmniAICreator/Qiita-1.07M huggingface dataset:
djangoでフラッシュメッセージを出す方法

# 参考ページ
https://docs.djangoproject.com/ja/5.0/ref/contrib/messages/

## settings.py
INSTAllED_APPS内に```django.contrib.messages```の記述があるか確認
```
INSTAllED_APPS = [
    ...,
    ...,
    'django.contrib.messages',
    ...,
]
```

## view.py
1. ```from django.contrib import messages```する
1. 表示するhtmlに対応したview内methodで下記の表からシチュエーションにあった形のものを使用し、メッセージを設定する


|  区分   |  使用方法/例    |    省略形/例  |
|:-------:|:--------------:|:------:|
| DEBUG   | ```messages.add_message(request, messages.DEBUG, "Hello world.")``` | ```messages.debug(request, "%s SQL statements were executed." % count)``` |
| INFO    | ```messages.add_message(request, messages.INFO, "Hello world.")``` | ```messages.info(request, "Three credits remain in your account.")```     |
| SUCCESS | ```messages.add_message(request, messages.SUCCESS, "Hello world.")``` | ```messages.success(request, "Profile details updated.")```               |
| WARNING | ```messages.add_message(request, messages.WARNING, "Hello world.")``` | ```messages.warning(request, "Your account expires in three days.")```    |
| ERROR   | ```messages.add_message(request, messages.ERROR, "Hello world.")``` | ```messages.error(request, "Document deleted.")```                        |


## html
messages変数を呼び出してメッセージを表示する
```
<!-- メッセージ表示例 -->
{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
```
　以下使える属性
> class Message¶
> テンプレート内のメッセージのリストをループさせると、 Message クラスのインスタンスが得られます。これらのインスタンスにはいくつかの属性しかありません:
> 
> message: メッセージの実際のテキストです。
> level: メッセージのタイプを説明する数値です (詳細は上述の message levels セクション)。
> tags: スペースによって区切られた、全てのメッセージのタグを結合する文字列 (extra_tags と level_tag) です。
> extra_tags: スペースによって区切られた、メッセージのカスタムタグを含む文字列です。空がデフォルトです。
> level_tag: レベルを表す文字列です。デフォルトでは定数名の小文字バージョンですが、MESSAGE_TAGS 設定によって変更できます。
《プログラミングの基礎》をReScriptで読む 第8章

[《プログラミングの基礎》](https://www.amazon.co.jp/dp/4781911609/ "Amazonへのリンク")はとても良い本です。
サンプルプログラムをReScriptで書いて、プログラミングの基礎とReScriptを学びます。
# 環境
* macOS Sonoma(バージョン 14.4.1)
* ReScript 11.1.0-rc.8
* @rescript/core 1.2.0
# 第8章
問題 8.5で駅名の情報を格納する`ekimei_t`型、問題 8.7で駅と駅の接続情報を格納する`ekikan_t`型を定義します。
```ReScript:Ex08_1.res
// 本に関する情報を格納するレコード
type book_t = { 
  title: string,      // タイトル
  author: string,     // 著者
  publisher: string,  // 出版社
  price: int,         // 値段
  isbn: string        // ISBN
} 
```
```ReScript:Ex08_2.res
// お小遣い帳の情報を格納するレコード
type okozukai_t = { 
  mono: string,   // 買ったものの名前
  nedan: int,     // 値段
  basho: string,  // 買った場所
  hizuke: string  // 買った日付け
}
```
```ReScript:Ex08_3.res
// 人に関する情報を格納するレコード
type person_t = {
  name : string,    // 名前
  shincho : float,  // 身長
  taiju : float,    // 体重
  tsuki : int,      // 誕生月
  hi : int,         // 誕生日
  ketsueki : string // 血液型
} 
```
```ReScript:Ex08_4.res
open Ex08_3

// 目的：person_t 型のデータから血液型を示す文を返す
// ketsueki_hyoji : person_t -> string
let ketsueki_hyoji = (person) => switch person {
| {name: n, ketsueki: k} =>
  n ++ "さんの血液型は " ++ k ++ " 型です" 
} 

let person1 = 
  {name: "浅井",
   shincho: 1.72,
   taiju: 58.5,
   tsuki: 9,
   hi: 17,
   ketsueki: "A"
} 
 
let person2 = { 
  name: "宮原",
  shincho: 1.63,
  taiju: 55.0,
  tsuki: 6,
  hi: 30,
  ketsueki: "B"
} 
 
let person3 = { 
  name: "中村",
  shincho: 1.68,
  taiju: 63.0,
  tsuki: 6,
  hi: 6,
  ketsueki: "O" 
} 

// テスト
Console.log(ketsueki_hyoji(person1) == "浅井さんの血液型は A 型です")
Console.log(ketsueki_hyoji(person2) == "宮原さんの血液型は B 型です")
Console.log(ketsueki_hyoji(person3) == "中村さんの血液型は O 型です")
```
```ReScript:Ex08_5.res
// 駅名の情報を格納するレコード型
type ekimei_t = {
  kanji:    string, // 漢字の駅名
  kana:     string, // 読み
  romaji:   string, // ローマ字
  shozoku:  string  // 所属路線名
}
```
```ReScript:Ex08_6.res
// 駅名の情報を格納するレコード型
open Ex08_5

let ekimei1 = {kanji: "茗荷谷", kana: "みょうがだに",
	       romaji: "myogadani", shozoku: "丸ノ内線"}
let ekimei2 = {kanji: "渋谷", kana: "しぶや",
	       romaji: "shibuya", shozoku: "銀座線"}
let ekimei3 = {kanji: "大手町", kana: "おおてまち",
	       romaji: "otemachi", shozoku: "千代田線"} 
 
// 目的：ekimei_t 型のデータを文字列で返す
// hyoji : ekimei_t -> string
let hyoji = (ekimei) => switch ekimei {
| {kanji: k, kana: a, shozoku: s} => 
    s ++ "、" ++ k ++ "（" ++ a ++ "）" 
}

// テスト
Console.log(hyoji(ekimei1) == "丸ノ内線、茗荷谷（みょうがだに）")
Console.log(hyoji(ekimei2) == "銀座線、渋谷（しぶや）")
Console.log(hyoji(ekimei3) ==  "千代田線、大手町（おおてまち）")
```
```ReScript:Ex08_7.res
// 駅間の情報を格納するレコード型
type ekikan_t = {
  kiten:    string, // 起点
  shuten:   string, // 終点
  keiyu:    string, // 経由路線名
  kyori:    float,  // 距離
  jikan:    int,    // 所要時間
}
```
【資格】Oracle DBA Silver 2019（Oracle Database Administration I (1Z0-082-JPN)）に受かりました

# はじめに:writing_hand:
ひさびさに資格を取得したので備忘として、記事にしたいと思います。

[ORACLE MASTER Silver DBA 2019 (Available only in Japan)](https://education.oracle.com/ja/products/trackp_DB19COCA)

# きっかけ:writing_hand:
業務ではSQLを使用するだけで、DB側についてはほぼノータッチなので、理解をもう少し深めたいなと感じて勉強を始めました。
Oracle DBA + SQLの内容を問われる資格なので、うってつけの資格と感じました。

# 勉強方法:writing_hand:
基本的には黒本中心に進めています。

ですが不安のため以下のものも使用しました
- 黒本（メインで使用）
 
https://amzn.asia/d/4afKB3q

- ping-t
    - Oracle DBA Bronze
    - Oracle SQL Silver

https://mondai.ping-t.com/g/question_subjects

- Oracle公式の問題
ORACLE MASTER Bronze/Silver Learning Subscription - JapanONLY

https://education.oracle.com/products/ls_84763

資格の本はこれくらいしかないのでは・・・？
古い規格の資格であれば、他にも参考になるような資格本がありますが、基本的にはこの本だけ完璧に勉強すれば合格できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3086650/ba8e5301-00b3-8957-c884-f32b6ee213b9.png)

# 勉強期間:writing_hand:
おそらく3ヶ月ほどかかっています。
気分転換にコーディングしたりしていたので、少し時間がかかっています。

# 対策:writing_hand:
基本的には黒本の内容をしっかり覚えれば受かる資格です。
ちょっと意地悪な内容もでたりもしますが、ほんの数問です。
SQLは以前にも資格を取っており、問題内容も類似しているので、そこまで難しくは感じなかったです。問題もSQLだけで言えば、SQL Silverのほうが難しいですし、今回合格したこちらのSQLの問題はほぼ正解していました。

やっておいたほうがいい部分は、
と、ポイントであげたいのですが、基本全部わかるようになっておいたほうがいいです。

問題集の内容を

#### 全問合計95％以上 + 選択肢の間違えている理由 + 選択肢の関連する知識

ぐらい、できているようになっていれば受かると思います。

SQLは見て覚えるより書いて覚えて実際に間違っている構文に違和感を感じるようになったほうがいいです。
私は業務でたまに書くので、そのおかげもあり、そこまで学習しなくても大丈夫でした。（SQL Silverも取っているおかげもありますが）

教材を使った順番は
1. 黒本（解説部分、問題含め）
1. ping-t（80％）
1. oracle公式問題（100%）
1. 黒本95％以上目指す
の順です。ping-tは問題数が多いので頑張ってください。

# 終わりに:writing_hand:
DBの知識は業務では使うことは少ないですが、覚えておいたほうがいい内容なので、合格してよかったです。またSQLの問題をあまり勉強せずにとれたので、前回取ったSQL Silverの知識が生きている感じがあってとてもよかったです。資格勉強も無駄ではないと感じました。

ここだけの話、勉強中問題の量が多くて後半飽きてた:scream:

このままの勢いでGoldとか取れたら嬉しいな～♪

それでは:wave:

# 参考にしたサイト

https://qiita.com/miya_hira8/items/de90eba659adbe6c800c

https://qiita.com/rare0b/items/6cc03f4ef38e414cdc08

https://qiita.com/latin3663/items/3cc224a18851a4aeeb8c
コード読むときに何を考えてますか？

# 概要
仕事柄コードを読むことが多い。その中で、コードを読むときにどのようなことを考えているかを知りたくなり、この本を読んだ。

[プログラマー脳](https://www.amazon.co.jp/dp/B0BVDQM5H1)

この本では、認知科学の観点からコードを読む際に頭の中で起きていることを説明している。

書籍の冒頭で長期記憶、短期記憶、ワーキングメモリーを組み合わせていることを説明している。読者にコードを読ませながら、その際にどのような記憶を使っているかを説明しているので、ぜひ機会があれば読んでみてほしい。

以下に私の理解を示す。

- 長記記憶：過去の経験からプログラミング言語の構文やライブラリの使い方、その中の関数の使い方などを思い出す。経験の多いプログラマは、デザインパターンやアルゴリズムを多く帰国しており、コードを読む際にも類似のコードと照らし合わせながら理解している。
- 短期記憶：コードを読む際に、そのコードの意味を理解するために使う。変数の値や関数の戻り値などを一時的に保持する。初めて見るコードを読むときは、頭の中で変数の値を追いかけながらコードを実行し理解している。
- ワーキングメモリー：ワーキングメモリーは処理するための情報を保持する記憶である。コードの意味を考える際にはワーキングメモリーを使っている。このサイズは7±2個と言われている。一般的にも言われているが、多くの人にとってこのサイズは変わらない。

なぜ、熟練のプログラマ（以降熟練者）は、初心者と比較して、コードを読むのが速いのか、そしてより深くコードを理解することができるのか、その理由がこの本に書かれている。

# なぜコードを読むのが早く、深く理解できるのか？
長期記憶の観点から：熟練者は多くの経験を通して、プログラムに関する多くの記憶を持っている。そのため、過去の類似のコードを思い出すことで、コードを理解するのが速い。例えば、デザインパターンやアルゴリズムの知識を持っていることで、そのコードを読む際に、そのコードがどのような目的で書かれたものかを理解するのが速い。

短期記憶の観点から：コード上の変数名、関数名、コメントなどは一時的に短期記憶に保持される。しかし熟練者はコードのどの箇所を記憶すべきかを経験から判断することができる。例えば、Java言語の「public static void main...」のように決まったフレーズや、理解しようとするコードに関係する変数や関数を積極的に短期記憶に保持する。

ワーキングメモリーの観点から：ワーキングメモリーのサイズは人により大きく変わらない。しかし、熟練者は、ワーキングメモリーを効率的に使うことができる。そのため、初心者と比較してコードを読むのが速い。例えば、「クイックソートのこーどだな」とか「OpenCVを使ってカメラのフレームをサイズ変更/色変換してObject detectionの処理に渡しているな」とか、そのコードを読む際に、ワーキングメモリーを使って、そのコードの意味を理解している。一方で初心者は変数や関数の意味を追いかけるためにワーキングメモリーを消費してしまうため、コードを読むのが遅くなる。

# 読みやすく、理解しやすいコードを書くにはどうすればよいのか？

- 良い変数名と関数名を使う(チーム内の命名規則に従う)
- コメントを使う
- 適切なインデントとフォーマット
- シンプルな構造を使う
- 適切なドキュメントを提供する。（関数やクラスの動作、引数、返り値などを明確に記述する）
- テストを書く （コードに期待する動作を示す）

ChatGPTに聞いてみると、上のような答えが返ってきた。確かに、コードを読む際には、上記のようなことが重要だと思う。

さらに、長期記憶/短期記憶/ワーキングメモリーの観点からは以下のように言える。
- 長期記憶：ソフトウェア開発の経験を積むことはさることながら、プロジェクトやチーム内のリポジトリをよく読んで理解しておくことが重要だと思う。同一プロジェクト内では同じようなテストコードが書かれていたり、命名規則などのルールに加えてコードの品質についても共通の理解があることが多く、長期記憶に保持しておくことで、コードを読む際に効率的に使うことができる。
- 短期記憶：コーディング規約にクラス/関数/変数などの命名規則が含まれることが多く、これに従うこと。
- ワーキングメモリー：コメントを使ってコードブロックの意味を説明することが重要だと思う。
セキュリティエンジニアを目指す人へ

こんばんは！
今日は現場の日記やめて
これから中途未経験でセキュリティエンジニアを目指す仲間たちに向けて言いたいことがあるのでよかったら読んでってください。

知識とはかけ離れていますが、、、将来設計に関して役に立つかな、、、

さてさて…
-----

セキュリティエンジニアになりたいといってもセキュリティの領域ってとても広いんですよね。

例えばフォレンジックとかペンテスターとかSOCとか同じセキュリティ領域でもやることが全然違います

なので
ここが固まってないといざ入社してやることになった業務が、、、、
思ってたのと違う！！！！！（CV:狩野英孝）ってことになりかねません。

そうなると一気にモチベーション下がって道をあきらめることになるかもしれません。

そんな悲しい事態を避けるために面談、面接でも自分がやりたいこと、できることをまずちゃんと伝えましょう。

それでも、案件開始の直前まで案件の詳細を伝えられない場合もあるわけです。

そのため入社後二か月くらいまでにあれ？なんかおかしい？？？
と、思うところがあれば多分その勘はあたっているので並行して色々と進めていった方がいいです。




結論
-----
SESでセキュリティエンジニアの最初の一歩踏み出そうとしている人たちに言いたい。

会社選びマジで重要！ここ間違えると営業さんが味方じゃなくなる

小目標
一年後どうなりたいか

中目標
三年後どうなりたいか

大目標
五年後になってる自分

を書き出して面接受けるときに照らし合わせて受かったところから応援してくれそうな会社を選ぶ

こうすることで現実と理想の差異を減らせます。

そのためにおりゃ～！！って突っ走る前に自分がどんなセキュリティエンジニアになりたいのか一度止まって頭に思い浮かべてみてください。

そして、最高のセキュリティライフを踏み出してください、、、

あ、明日は実家に帰るのでもしかしたら更新できないかも、、、

おわり
【Tailwind】ボタンのデザインを調整したい（ホバー、クリック時）

# はじめに
**Tailwind**でボタンのデザイン（ホバーやクリック時）を調整したい人向けの記事です。

# 前提
**shadcn-ci**の**button**を追加していること。
※ していない方はこちらから↓↓↓

https://ui.shadcn.com/docs/components/button

# やり方
**button.tsx**の**variant**内にボタンのcssを書く。

例えば、以下のようなデザインを作りたいとする。


**・初期状態**：グリーン
**・ホバー時**：濃いグリーン
**・クリック時**：下の部分も濃いグリーンに変わる

※ 参考
![ボタン（説明）.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1850625/1aad8af3-40d3-643f-9b74-63c3efa8bc73.gif)

このようなデザインの場合は、variantに以下のように書けば良い。

```tsx:button.tsx
任意の名前:
          "bg-green-500 text-destructive-foreground border-b-4 border-green-600 hover:bg-green-700 active:border-b-0",
```

そして、ボタンコンポーネントを読み込む際にvariantを指定すれば良い。
マージンなど調整したい場合は、calssNameで指定可能。

```tsx:page.tsx
<Button size="lg" variant="任意の名前" className="mt-5">
```
iTunesの起動がおっそい問題 + Wi-fi経由の同期ができない問題の解決策

色々調べたのでまとめてみた。
この問題は「iTunes for Windows」をMicrosoft Storeからダウンロードしたときのみに起こると思う。

## Bonjourサービス

![Bonjour_sa-bisu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1536745/e7e98405-7ffe-e878-78e5-05cf3b70bd9b.png)
Windowsの「サービス」から「Bonjourサービス」を探して起動すると問題が全て直るらしい。
しかしMicrosoft StoreからインストールをするとBonjourはインストールされないとのこと。
なにかしらをしてインストールする必要がある。

## Bonjourのインストール
### iTunesのインストーラーを使用する

![iTunes_sukusyo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1536745/63550266-891c-ae76-51e3-36448cb1b91f.png)
![iTunes_zu-mu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1536745/4b134393-cf83-8379-ffb6-8652c88318fa.png)
[iTunes](https://www.apple.com/jp/itunes/ "iTunes")のページの下にあるこいつからiTunesをインストールをするとBonjourも一緒にインストールされる。
正直これが一番手っ取り早いがなんだか気に食わない。

### Bonjour SDKをApple Developerから直接ダウンロードする。

![Bonjour_esudhi-ke-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1536745/6623ddc9-78aa-5da3-5f11-a3bbe09d636d.png)
[Apple Developer](https://developer.apple.com/download/all/?q=Bonjour%20SDK%20for%20Windows "Apple Developer")から「Bonjour SDK for Windows v3.0」をダウンロードする。(半分英語)
(ダウンロードするにはApple IDのログインが必要)
そのままインストーラーを起動して手順通りに進めるとインストールができる。

## おわり
![iTunes_ittenhati.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1536745/b6642861-90a0-90ac-e733-7d26db0b680d.png)
Appleが対処をしないおかげでレビューがとんでもないことになっている。([Microsoft Store](https://apps.microsoft.com/detail/9pb2mz1zmb1s "iTunes"))
そんな人達にこの情報が届けばいいなと思っています。
TCPって実際なにしてんの？(2.コネクション編)

# これはなに
TCPの勉強をしたので忘れないようにまとめる。
主にヘッダ、コネクション管理、順序制御、再送制御、輻輳制御について書く。
OSI参照モデルの話はみんな書いているので書かない。

今回はコネクション編。

参考文献:WEB+DB PRESS plusシリーズ TCP技術入門
https://gihyo.jp/book/2019/978-4-297-10623-2

### 目次
[1.概要](#1概要)
[2.コネクションの確立](#2コネクションの確立)
[3.コネクションの切断](#3コネクションの切断)
[4.おわりに](#4おわりに)
[5.参考文献](#5参考文献)

# 1.概要
TCPでは通信を始める前に通信路を確立する。
この通信路をコネクションと呼ぶ。
UDPではこれをしないので、相手がバッファいっぱいだったとしても問答無用で送信したりする。
TCPにおけるコネクションにまつわる特徴は以下。
* アプリケーションごとにコネクションを分ける
* 一対一の通信
* 全二重通信

### アプリケーションごとにコネクションを分ける
あなたはPCでYoutubeの音楽を聴きながら、同時にTwitterを見ているとする。
この時Youtubeのサーバとの通信で使うコネクションとTwitterのサーバとの通信で使うコネクションは異なる。
もちろん通信に使っている物理的な線は同じだろうが、プロトコル上の通信路は区別されて運用されている。
こういう状態を論理的な通信路が異なると言う。

### 一対一の通信
TCPではコネクションを確立すると書いたが、これは一対一の通信路である。
もしも複数人に同時送信をしたいならそれぞれに対してコネクションを確立しなければならない。
こういう一対一の送信しかできない送信方法をユニキャストと言う。
ちなみにUDPは一対多に送信ができる。
こういう送信方法をマルチキャストと言う。

### 全二重通信
TCPでコネクションを確立した相手とは送信をしながら受信を同時に行える。
これを全二重通信と呼ぶ。
逆に送信か受信のどっちかしかできない通信を半二重通信と呼ぶ。
全二重通信の方が明らかに便利だが、物理的な通信線を二本必要とするのが欠点。

# 2.コネクションの確立
TCPでコネクションを確立する手順を書く。
AがBと通信を始めたいとする。
1. AがTCPヘッダのSYNフラグを有効化させたセグメントをBに送る
1. BはSYNに対する応答としてACKフラグを有効化すると同時に、Aに対する送信路を確立するためにSYNフラグを有効化させてセグメントを送る
1. AはBからのSYNに対してACKを送る

この手順を3ウェイハンドシェイクと呼ぶ。
三回の通信で終わるのでこの名前になった。

SYNとかACKとかってなんじゃ？と思ったら前回の<a href="https://qiita.com/BEBE4410/items/dad48a6b7836dfb6c905#3%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%95%E3%83%A9%E3%82%B0">ヘッダ編のコントロールフラグ</a>を読んでください。

# 3.コネクションの切断
コネクションを切断する手順を書く。
AがBと通信を終えたいとする。
1. AがFINフラグを有効化させたセグメントをBに送る
1. BはそれにACKを返す
1. AはBへの送信路を切断する
1. BがAへの送信路を切断したいときは逆のことをする

切断も確立と同じようにFIN/ACKを送って3回の通信でやればいいじゃんと思うかもしれない。
しかしまだどちらかのデータ送信が終わってないかもしれないので、データの送信が終わった方から切断する。
~~「子供がまだ食ってる途中でしょうが！」~~
これをハーフクローズと呼ぶ。

# 4.おわりに
今回はコネクションについて書いた。
いろいろ記事が出ている内容なのでつまらなかったかもしれない。
次回は順序制御、再送制御について書く。
次回：<a href="https://qiita.com/BEBE4410/items/5bbea9e2b732c5427c4f">順序制御、再送制御編</a>

# 5.参考文献
WEB+DB PRESS plusシリーズ TCP技術入門
https://gihyo.jp/book/2019/978-4-297-10623-2
データモデリングについて トップダウンでの主キーおよび主要属性の定義

<h3>エンティティの配置ルール</h3>
エンティティの配置ルールにおいて重要なポイントは3点

 1. エンティティを「イベントエンティティ」と「リソースエンティティ」に分ける。
 1. イベントエンティティは、発生順から左から右へとずらしていく。
 1. 一度配置したエンティティルールは、変えないようにする。
 なぜ、これをしなければいけないのかで言えば、「これらをする目的がエンティティの整理」交わらないようにするためであるからである。

 ルールを設定しないと、「エンティティがごちゃごちゃしてしまうからである。」
 また原則の配置があっても、**リレーショナル線**が交わらないようにすることもポイントである。

<h3>主要属性定義</h3>
主要属性定義についてはこの書籍では画面設計図ベースで考えている。

何を属性にして何を表示しているのか、明確にして必要な属性を決定している。

:::note 
POINT
業務要件で定義した内容をもとに、属性を決定する!属性はあくまでも業務要件を満たす要素にすぎない!
:::


<h3>主キー候補の選定</h3>
主キーも、エンティティの一つである。主キーの候補キー配下を基準に考えると良い。

    <h4>主キー設定</h4>
     1. 最初に抽象したカラムの中から主キーを選定する(主キーを既存のカラムが選定する。)
     1. その中から、主キー選定基準に沿ったカラムを選定する
     1. 選定基準に沿って、新しい追記キーを選び代理主キーなどを選び、主キーを決定する。

     <h4>主キー選定基準</h4>
     1. 一意になるキーであること
     1. 値がNULLにならないこと
     1. 複合キーで連結で多くならないこと(5つまで)
     1. キー名が短いもの


<h3>主キーとしてのコード</h3>
主キーとしてどんなコードがベストかを考える。コードには大きく分けて2種類ある。
コード名を見ただけで**意味あるコード**か**意味なしコード**かのいずれかである。

どちらが最適であるか??
意味ありコード メリット コードを見ただけでわかる
意味なしコード メリット 他のコードや属性を見ないとわからない

基本的に**一つの属性に一つの意味を持つことがデータ設計の基本である。**
→その方がRDBでデータを扱う際に利便性が良いからである。

<h3>モデルの見直し</h3>
いきなり、**完璧なモデル**を作成することを目指すよりも徐々に最適なモデルを見つけ出すことがポイントである。

なぜなら、新機能など要望は後からもたくさん出てくることがあるからである。
s3へのアップロードをトリガーにECSタスクを起動する流れ

### はじめに
webアプリケーションを作っていると、高負荷が予想される処理の対応には工夫が必要となります。
今回、ECSを使用している場合にタスクに対する負荷を抑える手法の例を紹介します。

### ケース例
こちら自分が実際に業務で遭遇したケースですが、phpコンテナとnginxコンテナを含んだECSのwebアプリケーションを開発していた際に、ユーザーが顧客データ(数万件)が入っているcsvファイルをアップロードする場面がありました。このデータをDBに格納する際、アプリケーションに対して高負荷が予想されます。

実際のCPU使用率のメトリクス:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474661/cc448614-bd35-8ac6-187a-88426a87a467.png)
csvファイルがアップロードされたタイミングでcpu使用率が急上昇しており、webサーバに対して負荷がかかっています。


### 解決策の例
ECSでcsvファイルのデータをDBに格納する処理のみ別のタスクを起動させて行うようにしました。これによりECSのwebサーバに対する高負荷を抑制することが期待できます。

### 実際のやり方について
詳細に説明すると長くなってしまうので重要な点のみ抜粋します。

#### S3の設定
バケットを作成した後、以下のようにEventBridgeへの通知をオンにしておきます。
S3のバケットに対してファイルのアップロード等が行われることをトリガーとしてEventBridgeにイベントを送信します。
![名称未設定2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474661/b43ed5ec-e04e-131d-4bed-3cd930ac639d.png)

#### EventBridgeの設定
ルールの詳細: イベントパターンを持つルール
として、イベントパターンを以下のようなJSONとします。
'prefix'で指定したパスに含まれるファイルのイベントをEventBridgeで検知します。
```
{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": {
      "name": ["バケット名"]
    },
    "object": {
      "key": [{
        "prefix": "ファイルのパス"
      }]
    }
  }
}
```

ターゲットは、後ほど作成するLambda関数を指定します。
ECSのタスクをターゲットとしていないのは、EventBridgeの送信するイベントのデータをLambda関数において適切に処理してからECSのタスクに渡したいためです。

![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3474661/c9e89f88-ddeb-2d17-6695-61677b08f561.png)


#### Lambda関数の設定
S3のファイルデータをECSのタスクに渡す場合、バケット名とキー(ファイル名を含んだパス)をLambda関数で取り出して環境変数として送ることになります。
Lambda関数はPythonの場合以下のように記述します。
```
import json
import boto3
import os

ecs_client = boto3.client("ecs")

# 環境変数
ECS_CLUSTER = os.environ["ECS_CLUSTER"]
SUBNET_ID = os.environ["SUBNET_ID"]
TASK_DEFINITION = os.environ["TASK_DEFINITION"]

def lambda_handler(event, context):
    # s3の情報を取得
    bucket_name = event['detail']['bucket']['name']
    key = event['detail']['object']['key']
    # 新しいタスクを起動
    ecs_client.run_task(
        cluster=ECS_CLUSTER,
        taskDefinition=TASK_DEFINITION,
        launchType="FARGATE",
        networkConfiguration={
            "awsvpcConfiguration": {
                # ECSのタスクが存在するサブネット
                "subnets": [SUBNET_ID],
                "assignPublicIp": "ENABLED",
            }
        },
    overrides={
        "containerOverrides": [
            {
                "name": "コンテナ名",
                # ECSタスクに環境変数として渡す
                "environment": [
                    {"name": "S3_BUCKET", "value": bucket_name},
                    {"name": "S3_KEY", "value": key},
                ],
            },
        ],
        },

        )
```

#### Laravelを使用している場合の例
Dockerコンテナが起動した際に実行されるシェルスクリプトに以下の内容を記載しました。
```
#!/bin/bash
# 環境変数からバケット名とキーを取得
BUCKET_NAME=$S3_BUCKET
OBJECT_KEY=$S3_KEY

# 環境変数が渡されているか確認
echo "デバッグ"
echo $BUCKET_NAME
echo $OBJECT_KEY

# S3からファイルをダウンロード
aws s3 cp s3://$BUCKET_NAME/$OBJECT_KEY /tmp/data.csv

# Artisanコマンドを実行
php /var/www/html/app/artisan import:csv /tmp/data.csv

```
このシェルスクリプトがコンテナの起動とともに実行され、PHPの関数にS3上のCSVファイルの情報を渡して呼び出すことで高負荷を要する処理のみ別タスクを起動させて処理を行わせることができます。
タスクは実行の終了後に停止されるのでAWSの使用料金を抑えることもでき、一石二鳥ですね。


### おわりに
負荷対策の手法には様々なやり方が考えられるので自分自身勉強を重ねていきたいです。
Snowflakeからステージ上のファイルをパースせずに読み込む

# 経緯

+ 最近、Snowflakeに取り込もうとするデータがちょくちょく怪しい
+ ファイルに対してSelectをかけた後のデータはある意味壊れたデータになる為、元データを確認したい
+ しかし**セキュリティの要件からs3からの直接ダウンロードはできない**…
+ AWS CLIから見に行くのもちょっと手間
+ どうせならSnowsightからみたいよね？

という事がちょくちょく発生しており、同じ事よくありそうだよな？ということでちょっとしたスクリプト

### 実装結果
というわけでまずは実装結果が↓

```:python
import snowflake.snowpark as snowpark
from snowflake.snowpark.files import SnowflakeFile

def main(session: snowpark.Session):
    df = session.sql("SELECT BUILD_SCOPED_FILE_URL(@TEST_STAGE, 'utf_add_2403.csv')")
    file_list = df.toPandas().values.tolist()
    line_count = 2 #　全部読み取る必要はないので行は絞る
    re = []
    with SnowflakeFile.open(file_list[0][0]) as f:
        for i,line in enumerate(f):
            if i > line_count:
                break
            re.append(line.strip())

    rd = session.create_dataframe(re)
    return (rd)
```

↑を実行すると
![スクリーンショット 2024-04-27 19.38.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150914/0c621305-d7ea-8a87-5aa3-f0d0a7837318.png)
こんな感じに1行そのまま出力できるので、データバグってるか、かくにんできるよ！

### ぼやき

元々
https://docs.snowflake.com/en/developer-guide/snowpark/reference/python/1.15.0/files
このあたりのドキュメントがあったので、困った時はこの辺りでできるんだろうなあとおもっていたのですが

…困ったので (´･ω･`)
データ科学のための数学の基礎

# 概要
データサイエンスや確率論、統計学などを勉強する上で、数学上の苦労を少なくするため、基礎的事項がまとまった記事を紹介する. この記事は随時更新する.
# 同値関係、商集合、自然な射影（標準射影、natural projection）と誘導写像(induced map)、写像の分解
以下はコンパクトにまとまっている:
https://www.math.is.tohoku.ac.jp/~obata/student/subject/file/2018-5_douchi.pdf
https://zuxtukokesuuugaku.blog/2024/01/14/nst-28-projection-induced/
https://mathlandscape.com/quotient-set/

以下は図解が多い:
https://www.xmath.ous.ac.jp/~kuroki/geometryII/geometryII_3.pdf

# 線型作用素
仮想化とは？サーバーの仮想化について知らない人向け

# 仮想化とは？
実在するIT資源を論理的に異なる資源であるかのように認識させる技術である。
仮想化できる資源はサーバー、デスクトップ、ストレージ、ネットワークがある。今回はサーバの仮想化について説明する。

# サーバーの仮想化とは？
１台の物理サーバーで**複数**のOSを使用できること。
通常は、1つのサーバーで1つのOSしか動かせないが、仮想化することで複数の別のOSを動かすことが出来る。
例えば、windowsOSのPCをサーバーとすると、macOSとLinux系のcentoOSの2つのOSを仮想化で構築できる。


仮想化は主に３種類ある。


### 1.　ホスト型仮想化システム 
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359890/991eaa25-4f4f-8de9-8161-a5d4be3f7ad2.png">

仮想化アプリケーションを**ホストOS**と呼ばれる物理マシン上で動作させる。
既存のハードウェア内にあるWindowsやMacOSなどのOSを上に仮想化ソフトウェアをインストールする。

ホスト型の仮想化ソフトウェアの製品は[Oracle VM VirtualBox
](https://www.virtualbox.org/)などがある。


:::note info
### ホストOSとゲストOSとは？
**ホストOS**：**ハードウェア上**にインストールされたOSのことを指す。MacbookならMacOS,windowsPCならwindowsOSである。
**ゲストOS**:**仮想化マシン**上で動くOSのことを指す。Windows系OSやLinux系OS、UNIX系OSなど様々なOSをインストールできる
:::


### 2. ハイパーバイザー型仮想化システム
<img width="300" src ="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359890/848261ba-6e9d-8723-2468-612158678278.png">





ハードウェアの上に**ハイパーバイザー**と呼ばれる仮想環境を構築するためのアプリケーションを利用する。
ホストOSを使用せずに、仮想サーバーの構築が可能。
ハイパーバイザーの製品は[Hyper-V](https://learn.microsoft.com/ja-jp/virtualization/hyper-v-on-windows/about/)や[vSphere](https://docs.vmware.com/jp/VMware-vSphere/index.html)などが挙げられる。



### 3. コンテナ型

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359890/4570c26f-8dd7-6a78-28ab-b22dafc21eaf.png">




ホストOS上にコンテナ型仮想化ソフトウェアをインストールし、コンテナ上でアプリケーションを構築することができる。そのため、ゲストOSは不要となり、CPUやメモリ、ストレージなどのリソースも不要となり、動作速度が速い。

**つまりコンテナ上で構築されたアプリケーションはすべて直接ホストOSによって起動される**


:::note warn
直接ホストOSに依存するため、ストOSに未対応のアプリケーションを起動できない。
例えば、OSがMacOSの場合、MacOSに未対応なアプリケーションを構築できないということ。
:::
コンテナ型仮想化ソフトウェアの製品は[Docker](https://www.docker.com/ja-jp/)がある。

* * *



### クラウドコンピューティング（クラウド）との違い
現在ではクラウドでアプリケーションを構築するのが主流になりつつある。
このクラウドも仮想化技術をもとに構築されている。ただ、異なる点がある。
上記で挙げた３種類の仮想化サーバは**PC（物理サーバ）上**で構築されている。
クラウドはそれらと異なり、**インターネット上**に仮想環境を構築している。それぞれ特徴が異なり、開発に合った選択をする必要がある。


## まとめ
### ホスト型
+ ホストOS上の仮想化マシンによって構築される
+ ゲストOSに様々なOSをインストールができる
+ 動作速度が遅く、リソースが必要となる
+ 小規模な開発に向いている

### ハイパーバイザー型
+ ホストOSの代わりにハイパーバイザー上で仮想環境を構築
+ 比較的に速度は速い
+ 大規模開発に向いてる

### コンテナ型
+ ホストOS上の仮想化マシンによって構築される
+ コンテナ上に構築
+ ゲストOSが不要
+ ホストOSに依存する
+ 動作速度が速く、リソースの心配がない

* * *

まだ初学者のため、間違えているところがありましたらご指摘いただけると幸いです。

## 参考

https://zenn.dev/suzuki_hoge/books/2022-03-docker-practice-8ae36c33424b59/viewer/1-2-virtualization
環境構築まとめ：google-cloud-sdkをローカルへ

## 概要

google-cloud-sdkをローカルにDLして正常起動させる方法。

## 手順
gsutil及びbqコマンドのインストール

PC環境：MAC

homeディレクトリが基本

1, インストール
```shell:shell
$ brew install --cask google-cloud-sdk
```

2, pathの修正
```shell:shell
$ vi ~/.zshrc 
$ source '/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.zsh.inc'
$ source '/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.zsh.inc'
$ source ~/.zshrc
```

3, pathの修正
```shell:shell
$ gcloud components list
```
↑ここでデフォルトでinstallされていない「Not Install」は追加インストールしないとコマンド実行した場合エラー

4, ローカルのPCから該当GCPプロジェクト指定
```shell:shell
$ gcloud config set project (ここにプロジェクト名)
```

5, 再認証エラーの場合
```shell:shell
$ gloud auth login `個人のメールアドレス`
```


## まとめ
以上となります。
ありがとうございました。
Androidで円形のリアルタイムBlur効果を付ける(RealtimeBlurView)

# 概要
リアルタイムに円形のViewでBlur効果を実現したので、備忘録としてまとめておきます。

# 完成イメージ
![Screenshot_20240427-181653.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55941/3d57b68f-7e84-d2cb-032e-9e34ec5eb2b9.png)
速度・回転数メータの背景が、黒い円形でBlur効果が付いている事が分かります。

# ベースとなるライブラリ
mmin18氏の「[RealtimeBlurView](https://github.com/mmin18/RealtimeBlurView)」を改造します。
※jcenterがEOLとなり、READMEの通りに導入しようとするとインポート出来ないので[jitpack](https://jitpack.io/#mmin18/RealtimeBlurView/master-SNAPSHOT)から取ります。
```
    dependencies {
            implementation 'com.github.mmin18:RealtimeBlurView:-SNAPSHOT'
    }
```

# コード
```java:BlurCircleView.java
import android.graphics.Canvas;
import android.graphics.Path;
import android.util.AttributeSet;

import androidx.annotation.NonNull;

import com.github.mmin18.widget.RealtimeBlurView;

public class BlurCircleView extends RealtimeBlurView {

    private Path clipPath;

    public BlurCircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        clipPath = new Path();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        updateClipPath(w, h);
    }

    private void updateClipPath(int width, int height) {
        // Calculate radius
        float radius = Math.min(width, height) / 2f;
        // Create a circular path
        clipPath.reset();
        clipPath.addCircle(width / 2f, height / 2f, radius, Path.Direction.CW);
        clipPath.close();
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        // Clip the canvas to the circular path
        canvas.clipPath(clipPath);
        super.onDraw(canvas);
    }
}
```

# 解説
円形のPathを作成して、描画時に切り抜くだけの簡単な処理で出来ます。  
```java
    private void updateClipPath(int width, int height) {
        // Calculate radius
        float radius = Math.min(width, height) / 2f;
        // Create a circular path
        clipPath.reset();
        clipPath.addCircle(width / 2f, height / 2f, radius, Path.Direction.CW);
        clipPath.close();
    }
```
updateClipPathメソッド内でPathの形状を変えると、三角や星などの複雑な形状でも描画出来ます。
正規表現の注意メモ

# 正規表現でハマりやすい場所のメモ
　気が付かないとバグりやすいです。
　注意点を知らないと確認用のテストもなかったりするです。

　筆者はJavaScript、JScript、サクラエディタを特に使っています。
　正規表現は方言が多いので、この記述とは違う実装もあります。

## 1.シングルラインモードとマルチラインモード
　`/pattern/m`　マルチラインモード
　`/pattern/s`　シングルラインモード
デフォルトはマルチラインモードです。

1.任意マッチの`.*`に`\n`が含まれるかどうかが違います。
　マルチライン：`\n`が含まれません
　シングルライン：`\n`が含まれます

これを理解していないと「複数行文字列の行内マッチ」の感覚で
　`/｜.+《.+》/s`
こんなふうに書いてしまう事故にあったりします。
　`/｜[^\r\n]+《[^\r\n]+》/s`
シングルラインモードのまま行を超えないようにするには改行を排除する必要があります。
とくに普段「サクラエディタ」使っている人は行を超えたマッチが起きないので、ハマりやすいです。
※ここではUnicode改行は無視しています。
 
2.`^`と`$`の動作が違う
　マルチライン　：行の先頭、末尾
　シングルライン：データ全体の先頭、末尾

全然マッチするものが違うので、明らかなバグの元です。

## 2.`[^なにがし]`では改行に要注意
上ですでに書いていますが、マルチラインモードの時、`.`には最初から`\n`が排除されています。
ところがその感覚で`[^なにがし]`では改行を排除するとき自分で書く必要があります。
これを知らないと、
　`/《[^《》]+》/`
このように書いてしまい、《》の間のマッチで改行を超えてしまいます。
>いろはにほへと《ちりぬるを[改行]
わかよたれそ》つねならむ[改行]
うゐのおくやま《けふこえて》[改行]
あさきゆめみし　ゑひもせす[改行]

こういうデータで行内のみならず、改行を食べてしまいます。
（もちろん意図的に改行を超えてマッチさせたいときは別です）

## 3.パイプ演算子「|」は左優先
　`/(山田|旭|旭丘|旭丘駅|野木)/`
こういう`|`を使った複数マッチをしたいとき多くの実装で「左優先」です。
バックトラックが発生せず、一番左から順番に試していって、最初にマッチしたものを採用するようになっています。
この例では「旭」にマッチしても「旭丘」「旭丘駅」にはマッチしません。
　`/(山田|旭丘駅|旭丘|旭|野木)/`
このように、左側に長い文字列を置くことで解決することができます。 
　`/(ギルド|デスク|トイレ|バスルーム|バス停|ホテル|仕事場)に/`
　`/(中学|会社|大学|学校|屋敷|教室|玄関|王宮|病院|職場|部室|部屋|階段|高校)/に`
　`/([塾家屋席店門館駅])/に`
長さごとに分離して実装する方法もあります。
また1文字の場合には`[なんちゃら]`のブラケット表記が使えます。中身が大量にある場合、もしかしたら最適化の関係で`[]`のほうが高速に実行される可能性があります。
一文字ずつ`|`入れるのも面倒ですしね。

## 4.バックトラック
　`/.*■.*■.*/`
なんかこういう`*`や`+`とかが複数ある正規表現は場合によって、速度に注意が必要です。
バックトラックといって、一部分だけマッチしたあと、それが最終的に全体がマッチしなかったときに、再度長さを変えてマッチさせようとします。
これ、指数関数的に時間を使う表記が存在していまして、めちゃくちゃパフォーマンスが悪い組み合わせがあります。

## 5.CRLFのデータのハンドリング
多くの正規表現エンジンの改行コードは`\n`のことを指します。
しかし入力データには`\r\n`、`\r`やUnicode改行などがあります。
```JavaScript:replace_to_lf.js
    str = str.replace(/\r\n/g, '\n').replace(/\r/g, /\n/);
```
こういう前処理を必要ならしましょう。

## 6.最長一致の原則
>入力1：あいうえお《かきくけこ《さしすせそ》たちつてと》なにぬねの

こういうデータがあるとして、`/《.+》/`これが何にマッチするかというと、
```text
出力1：《かきくけこ《さしすせそ》たちつてと》
```

こうですね。ところが
>入力2：あいうえお《かきくけこ》さしすせそ《たちつてと》なにぬねの

こういうときでも、
```text
出力2：《かきくけこ》さしすせそ《たちつてと》
```
こうなってしまいます。これが最長一致の原則です。
一番マッチ文字列を短くしたいなら、
　`/《.+?》/`のように`*?`、`+?`、`{1,5}?`のように「長さ指定子」の後ろに`?`を付け足す必要があります。
```text
出力1-2：《かきくけこ《さしすせそ》
```
```text
出力2-2：《かきくけこ》
```
とまあ、こうなります。
ちなみに、二重になっている括弧を数えてどこが終わりか判断するのは、ちょっと簡単ではありません。

「入力1」で一番内側の「《さしすせそ》」を抜き出すにはこうします。
　`/《[^《》\r\n]+》/`

「入力1」で最初に見つけた《から最初の》まで「《かきくけこ《さしすせそ》」を抜き出すにはこうします。
　`/《[^》\r\n]+》/`

## 7.Unicode拡張モード
https://qiita.com/sasao3/items/3b8dc861ed01573f4deb

全種類の文字チェックとかしない数種類だけのテストだと、場合によっては気が付かないことがあります。

phpなどで日本語コードを使う場合はUnicodeモードで使用しないと場合によっては、コード範囲がおかしなります。

　簡易カタカナチェック
　`/[ア-ヴー]+/u`

JavaScriptでもサロゲートペアの範囲までフォローする場合には、同様に拡張モードを使用します。
ES2018で書式が拡張されました。

　新常用漢字の異体字
　`/[曾瘦麵艷龜餠彌篭堽崕葢𥡴咒溯璢填剥頬叱]/u`
　新常用漢字
　`/[曽痩麺艶亀餅弥籠岡崖蓋稽呪遡瑠塡剝頰𠮟]/u`

こんな感じですね。
## 8.忘れやすいgオプション
JavaScriptで「すべて置換」する場合には「gオプションフラグ」が必要です。
テストコードを書くときには、置換対象が2個以上あるテストケースも書きましょう。

```JavaScript:replace_tag.js
    let bad = str.replace(/</, '&lt;').replace(/>/, 'gt;'); 
    let good = str.replace(/</g, '&lt;').replace(/>/g, 'gt;');
```
はい、上でやらかしましたので、備忘録として追記しておきます。
例はあまりよくないですね。他にも`&`自身を先に`&amp;`にエスケープしておく必要があります。

## TODO

・「通常使うカタカナ」一覧の正規表現の研究。
・「通常使うひらがな」一覧の正規表現の研究。
・「最新の漢字」の一覧の正規表現の研究。

(終わり)
M1 Mac C++ Environment Setup with GCC

## First of all

I hate Clang. I'm going to use GCC instead.


## How to GCC

### Install GCC using homebrew
```Terminal:Terminal
brew install gcc
```

### Check your GCC version
```Terminal:Terminal
brew info gcc
```
It will print out something like this.
```Terminal:Terminal
==> gcc: stable 13.2.0 (bottled), HEAD
GNU compiler collection
https://gcc.gnu.org/
...

```

In my case, GCC version is 13.2.0.

### Link GCC

Where is your GCC at?
```Terminal:Terminal
which g++-13
```
That last number number should be changed to your own version.

In most of the cases, it should show up like this.
```Terminal:Terminal
/opt/homebrew/bin/g++-13
```

Link them
```Terminal:Terminal
sudo ln -s /opt/homebrew/bin/g++-12 /usr/local/bin/g++
```
If the Terminal says something like this,
```Terminal:Terminal
ln: /usr/local/bin/g++: File exists
```
Just do this
```Terminal:Terminal
sudo ln -sf /opt/homebrew/bin/g++-13 /usr/local/bin/g++
```

### Finally, check if your GCC is connected from homebrew
```Terminal:Terminal
which g++-13
```
↓
```Terminal:Terminal
/opt/homebrew/bin/gcc-13
```
Yay it works!
【備忘録】HTML＆CSS -meta要素

### meta要素
（そもそもmeta要素とは＝ブラウザや検索エンジンに対して情報を伝えるため設定するもの。）

:sunny:head内に必ず入れたいmeta要素
初期設定に含まれていないものもあるため、覚えておく。


```<meta charset="UTF-8">```
→文字化けを起こさないようにするもの

``` <meta name="viewport" content="width=device-width, initial-scale=1.0">```
→様々なデバイスにおいて、それぞれ対応した大きさで表示されるようにする
　（何も指定しない場合、スマホで開いたときPCのデスクトップサイズで表示されてしまう）

 ```<meta name="description" content="">```
 →content内に入れるのはタイトルの説明。８０〜１００文字程度？

```<meta property=”og:〜” content=”” />```
→メタOGは、正式にはOpen Graph Protcol（ オープン グラフ プロトコル ）といい、SNSでサイトをシェアする際にWEBページのタイトルやイメージ画像など正しく伝えるため設定する。
基本的には下記の一通りで大丈夫:arrow_down:
   ``` <meta property="og:url" content="このサイトのUPL" />```
   ``` <meta property="og:type" content="website" />```
   ```<meta property="og:title" content="タイトル" />```
   ``` <meta property="og:description" content="タイトルの説明" />```
   ```<meta property="og:site_name" content="サイトの名前" />```
   ``` <meta property="og:image" content="サイトのイメージ画像" />```

また、OGPを設定する場合必要な宣言が```prefix=""```で、ほぼ定型ではあるがFacebookを含めるか含めないかで少し変わるため注意
Facebook以外を活用→　```<html lang="ja" prefix=”og:https://ogp.me/ns#”>```
　　　　　　　　　　　　:warning:HTML内に宣言

他にもファビコンやCSS適用もあるが、以上を踏まえて実際に書いたコード
↓↓↓
```html:index.html
<html lang="ja" prefix=”og:https://ogp.me/ns#”>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML&CSS課題①について</title>
    <meta name="description" content="今年の目標を３つ書く">
    <!-- CSS適用 -->
    <link rel="stylesheet" href="style.css">
    <!-- OGP -->
    <meta property="og:url" content="https://HTML&CSS/kadai01/index.himl" />
    <meta property="og:type" content="website" />
    <meta property="og:title" content="HTML&CSS課題①について" />
    <meta property="og:description" content="今年の目標を３つ書く" />
    <meta property="og:site_name" content="研修" />
    <meta property="og:image" content="" />
    <!-- ファビコン -->
    <link rel="icon" type="image/png" href="images/favicon.png">
</head>
```
RaspberryPi zeroが非力すぎてアップデートすらままならないのでSWAPのサイズを変更した

## 経緯
RaspberryPizeroを低消費電力なのを利用してセンサーカメラとして使用しようとしていましたが、非力すぎて最新のRasbian OSでは更新プログラムのアップデートですらハングしてしまいお話にならないので何とか動かせないものかと考えた結果、仮想メモリをとりあえず増やしてみようということになった。
## 手順
1. 現在のSWAPファイルの割り当て容量を確認。
   ```bash
   $ sudo free -h
   ~
   Swap:           99Mi
   ```
   デフォルトだと仮想メモリは100MBしか割り当てられていないようですね。。。そもそも物理メモリも512MBしか積まれていないので、CUIオンリーで使うならまだしもDesktop環境を使うならばこれは厳しいですね。一般的に仮想メモリの変更は物理メモリと同等くらいにするのがセオリーですがそれでも低すぎて辛いので物理メモリの倍の1GBまで増やそうと決めました。
1. まずはSWAPの割り当てを変えるためにSWAPのサービスを止めていきます。
   ```bash
   $ sudo swapoff --all
   $ sudo systemctl stop dphys-swapfile
   $ sudo systemctl disable dphys-swapfile
   ```
1. SWAPが停止したか確認します。
   ```bash
   $ systemctl status dphys-swapfile
     ○ dphys-swapfile.service - dphys-swapfile - set up, mount/unmount, and delete a>
     Loaded: loaded (/lib/systemd/system/dphys-swapfile.service; disabled; pres>
     Active: inactive (dead)
   $ sudo free -h
     ~
     Swap:             0B
   ```
   OK、停止していますね。
1. それでは仮想メモリのサイズを変更します。
   ```bash
   $ sudo vi /etc/dphys-swapfile
   ```
   CONF_SWAPSIZE=100という行があるのでこちらを1GB（CONF_SWAPSIZE=1024）にして保存します。
1. そしてSWAPのサービスをスタートします。
   ```bash
   $ sudo systemctl enable dphys-swapfile
   $ sudo systemctl start dphys-swapfile
   ```
2. SWAPのサービスがスタートしたか確認します。
   ```bash
   $ systemctl status dphys-swapfile
     ● dphys-swapfile.service - dphys-swapfile - set up, mount/unmount, and delete a>
     Loaded: loaded (/lib/systemd/system/dphys-swapfile.service; enabled; prese>
     Active: active (exited) since Sat 2024-04-27 17:50:43 JST; 12s ago
   ```
1. 最後に再度SWAPの割り当てを確認してみます。
   ```bash
   $ sudo free -h
   ~
   Swap:          1.0Gi
   ```
   OK、ですね！
1. そして念の為リブート。
   ```bash
   $ sudo reboot
   ```
初めてLTを聞いて学んだこと【備忘録】

# はじめに

# AWS・RAG機能

- re:Invent→AWSのカンファレンスイベント
- RAG機能→LLMによるテキスト生成＋検索の組み合わせ
- AIは嘘を付く（ハルシネーション）
- サンプルサイトで挙動を見る
- シンプルに

# 検索サイト

- ZENNなどを資料として発表してもOK
- 失敗談もちゃんと分析できていれば面白をおかしくなる

# create.xyz

- AIに色々指示を出して作ってもらうノーコードツール
- ギャグを入れるのもあり

# 炎上案件の話

- やる気がない→とにかく行動
- しくじり
連続的な値の配列

# ```*()```をつける
```rb
irb(main):175:0> b.length
=> 1
irb(main):176:0> b = [*(1..2)]
=> [1, 2]
irb(main):177:0> b.length
=> 2
irb(main):178:0>
```

# 感想
こんな感じでできると思ったけどエラーなるので困ったけどできてよかった。

# 出典
https://qiita.com/ntakuya/items/c82bb6a9b3336ee77a87
railsの環境構築を半日かけて構築した話

こんにちは！初投稿です！
今回は半日近く格闘をしたrailsの環境構築の話を備忘録を兼ねてお話ししたいと思います。
環境はDockerで構築しました。

## Dockerを立ち上げるまで
```
$cd 作業フォルダ
$docker compose build
$docker compose up -d
```
上記で、Dockerを立ち上げていきます。

## Dockerに入る
```
$docker compose exec web bash
```

## 諸々インストール
```
$bundle install
$yarn install
```
上記で、構築に必要なものをインストールしていきます。
bunle⇨ライブラリをインストール
yarn⇨パッケージを一括管理できる

## エラーが起きたコマンド
```
$bin/rails db:create
```
こちらを入力した際、下記のエラーが発生した。
```
Caused by:
Mysql2::Error::ConnectionError: Unknown MySQL server host 'db' (-2)
```
どうやら、'db'なんていうホスト名に接続できないというエラー。
database.yamlとdocker-compose.ymlのホスト名をチェック
```
database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: db
```
```
version: '3'
services:
  db:
    image: mysql:5.7
    platform: linux/amd64
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: password
    volumes:
      - mysql_data:/var/lib/mysql
    ports:
      - 3307:3306
```
合ってそう。。。

## 解決した方法
-MacOSをアップデート
マックOSのversionが１３だったのですが、14だと動いたという情報を見つけアップデート
そして
```
$bin/rails db:create
```
すると、
```
Mysql2::Error: Host '172.21.0.4' is not allowed to connect to this MySQL server
```
違うエラーが出てきた。。。一歩前進したのか後進したのかわからないのですが、情報を集めDockerのimageが古いものを参照している可能性があるとのことで、以下のコマンドを実行
```
$docker volume rm VOLUME NAME
$$bin/rails db:create
```
すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733438/151b3602-a749-cbe0-bf14-5d2c4e45aa91.png)
入れたー！（成功した時のlog撮り忘れちゃいました）

めちゃくちゃ時間がかかりましたが、いろいろな解決策を学べて今回qiitaにも投稿することができたので、結果オーライかなと思います。qiitaの上位にいる方達のように面白い記事が書けたらなーと思います。
Notionで階層化タグを利用する方法

## はじめに
初めての投稿です。この記事では、Notionで階層化タグを利用する方法について解説していきます。より良い方法などがあればコメントで教えていただけると幸いです。

## Notionとは？
**Notion**とは、メモやノート、Todo、プロジェクト管理など様々な機能を備えた**万能メモアプリ**です。
Notionが持つ特徴的な機能の１つとして**データベース**があり、この機能を利用して日々の学習記録を整理しています。

## 何ができるか？
次のように全てのノートにタグ付けをして、一元管理することができます。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771054/8a7b38bc-f5eb-48ca-f3ea-a567a8b622fb.png)

このノートDBを参照しタグでフィルターをかけることで、任意のカテゴリに関するページを作成することができます。
例えば、ねこに関する知識をまとめたり、プログラミングに関する知識をまとめたりするなど、自由に整理した情報を閲覧できます。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771054/343571b9-8a24-4ff2-9b6b-9695303cdf9d.png)
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771054/f9355f37-3494-0f94-754f-ec839e55c2d4.png)

しかし、デフォルトでは階層化タグが使用できないため、上の図のようにプログラミングに関する知識をまとめようとすると、該当タグを全て選ぶ必要がある他、新しいタグが追加されるたびにフィルター設定を変更する必要があります。
そこで、タグを階層化する方法を紹介します。

## 階層化タグの利用方法
### 1.タグデータベースの作成
ノートの分類に使用するタグは、階層化したタグデータベースを参照することにします。
Notionのデータベースには親子関係を作れる「サブアイテム」という機能があるのでこれを使いタグを階層化します。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771054/c82979ae-bef5-b634-bc2f-40e79430e4ee.png)

これだけでは、親タグでのフィルタリングができないので、フィルタリング用の関数プロパティを追加し次のように設定します。
**階層：**
```
prop("親アイテム")?
	[prop("親階層"),prop("タグ")].flat():
	[prop("タグ")]
```

**親階層：**
```
prop("親アイテム").map(current.prop("階層")).flat().unique()
```
:::note info
再帰回数の制限があるので３つ上の階層までしかさかのぼれません。
A/B/C/D/E の場合、Aは参照できません。
:::
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771054/faded5d6-952a-f559-7837-013e8616e5f8.png)


### 2.ノートデータベースの作成
ノートデータベースに、タグと階層を関連付けるプロパティを追加します。
**タグ：** リレーションプロパティでタグDBを参照
**階層：** 数式プロパティでタグDBの階層を参照
```
prop("タグ").map(current.prop("階層")).flat().unique()
```
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771054/cf63bacb-9466-02b7-c2f7-28f701e555c0.png)

これでノートDBに階層タグが関連付けられました。

### 3.表示ページの作成
データベースを表示させたいページで「/linkeddatabase」を用いてノートデータベースを参照します。
これで、階層プロパティを使って任意の粒度でのフィルタリングができるはずです。
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3771054/62c4e7d7-e592-0eec-568f-b35ae7eb3723.png)

## まとめ
階層化タグを用いることで、情報の整理と検索が容易になります。
タグを追加したい場合は、タグDBを編集するだけで、すべてのページのフィルタリングに反映されるので管理もしやすくなります。
各タグにはアイコンが設定できるので、公式ロゴなどを設定すると見やすくなると思います。
Result<(), E>の()て何

# Result<(), E>
`()`てなんやねんと思ったので調べる

# ユニット型
Rustのプリミティブ型の中に**ユニット型**(unit type)というのがある
`Result<(), E`の`()`の正体はこいつ
[ユニット型](https://doc.rust-lang.org/std/primitive.unit.html)

> ()型は暗黙的に使われることが多く、`->`のない関数は暗黙的に`()`を返す
> [unit - Rust](https://doc.rust-lang.org/std/primitive.unit.html)より筆者意訳

戻り値を`Result`型にするとき、エラーが発生した場合は何らかの値を返したいが、成功した際には、成功したことだけが分かればよい時を考える。
そういった場合に、`Result<(), E>`を戻り値にしたくなる
`main関数`などでよく見る

以下がコードの例である
```rust
fn do_something() -> Result<(), String> {
	if some_err {
		return Err("問題発生".to_string());
	}

	Ok(())
}
```

# 参考文献
* [unit - Rust](https://doc.rust-lang.org/std/primitive.unit.html)
* [Result - Rust By Example 日本語版](https://doc.rust-jp.rs/rust-by-example-ja/error/result.html)
TCPって実際なにしてんの？(1.ヘッダ編)

# これはなに
TCPの勉強をしたので忘れないようにまとめる。
主にヘッダ、コネクション管理、順序制御、再送制御、輻輳制御について書く。
OSI参照モデルの話はみんな書いているので書かない。

今回はヘッダ編。

参考文献:WEB+DB PRESS plusシリーズ TCP技術入門
https://gihyo.jp/book/2019/978-4-297-10623-2

### 目次
[1.概要](#1概要)
[2.ヘッダ](#2ヘッダ)
[3.コントロールフラグ](#3コントロールフラグ)
[4.おわりに](#4おわりに)
[5.参考文献](#5参考文献)

# 1.概要
TCPはOSI参照モデルの第四層であるトランスポート層で動作するプロトコル。
特徴として高信頼性が挙げられる。
しかし信頼性が高いと言っても「 **じゃあ実際なにをしてるの？どんな機能があるから信頼性が高いの？** 」という疑問が芽生える。
そこを本記事では書く。
TCPに実装されている主な機能はコネクション管理、順序制御、再送制御、輻輳制御である。

# 2.ヘッダ
TCPでは通信をするとき、送りたい情報にヘッダと呼ばれるメタデータを付加して送信する。
メタデータとは情報に対する情報のことで、例を出すと宛先や送信元、情報本体の長さなどの情報が含まれる。
ここにいろいろなお役立ち情報を書くことでTCPは高信頼性を実現している。
なのでここに何が書いてあるかを知らないと、TCPが何をしているのかを知ることはできない。

### ヘッダの構成
TCPヘッダは以下の構成になっている。
* 送信元ポート番号
* 宛先ポート番号
* シーケンス番号
* 確認応答番号
* データオフセット
* 予約領域
* コントロールフラグ
* ウィンドウサイズ
* チェックサム
* 緊急ポインタ
* オプション
* パディング

大事な物だけ解説する。
##### 送信元ポート番号
読んで字の如く、通信で使う送信元のコンピュータのポート番号が書かれている。
全長16ビット。

##### 宛先ポート番号
宛先のコンピュータのポート番号が書かれている。
全長16ビット。

##### シーケンス番号
送信する情報の順番を表す番号が書かれている。
TCPでは送りたい情報が長すぎる場合、セグメントと呼ばれる単位に分割して送信する。
分割したはいいが順番がごっちゃになると困るのでシーケンス番号が割り振られる。
全長32ビット。

##### 確認応答番号
次に受け取るべきセグメントのシーケンス番号を受信側が書く領域。
シーケンス番号0のセグメントを受信側が受け取ったらここに1と書いて返事をするイメージ。
イメージ的にはそうだが実際はシーケンス番号+受信したデータサイズを返す。
全長32ビット。

##### データオフセット
TCPヘッダの長さが書かれている。
後述のオプション領域が可変長なのでこれが必要となる。
これがないと受信側はどこまでがヘッダで、どこからが本体なのかがわからないので困る。
全長4ビット。

##### 予約領域
将来的に使うかもしれないから空けてある領域。
0で埋める。
全長3ビット。

##### コントロールフラグ
いろいろなフラグが詰め込まれている領域。
全長9ビットで9分割されている。
イメージとしては9個のON/OFFスイッチが詰め込まれている感じ。

##### ウィンドウサイズ
受信側が一度に受信できるデータ量を送信側に通知するための領域。
受信側にはバッファがあり、ある程度はデータを蓄積できるが限度があるため、それを伝える。
送信側はそれを超えるデータ量を送信できない。
全長16ビット。

##### オプション
最大セグメント長や選択制ACKの有無を決めるのに使う領域。
最初の1バイトにオプションの種類を記述し、次の1バイトにオプション領域のサイズを書き、最後に内容を書く。
全長は後述のパディングと合わせて0～320ビットの可変長。

##### パディング
オプション領域長が32ビットの倍数でない場合、ここを0で埋めてキリを良くするための領域。
全長は0～32ビットの可変長。

# 3.コントロールフラグ
ヘッダの中でコントロールフラグという領域が出てきた。
この中に9個のフラグが入っている。
大事なものをいくつか解説する。

##### ACK
確認応答番号領域が有効であることを表す。
TCPにおける通信は基本的に何かに対する応答であるので、通信の初め以外は常に1になっている。

##### RST
強制的に通信路を切断するときに1を格納する。
HTTPの持続的接続している際に、終了時間が来たときなんかに有効化される。
何らかの異常があった時も有効化される。

##### SYN
通信の初めだけ有効化する。
これが有効化されていると受信側はコネクションの確立のための応答を返す。

##### FIN
通信の終わりを示す。
これを有効化したセグメントを送出した側はその後、これに対する応答があったら送信路を切断する。

# 4.おわりに
次回はコネクション管理について書く。
次回：<a href="https://qiita.com/BEBE4410/items/bb85c2aa6afdefb3df44">コネクション管理編</a>

# 5.参考文献
WEB+DB PRESS plusシリーズ TCP技術入門
https://gihyo.jp/book/2019/978-4-297-10623-2
AppleMusicで、CDから取り込んでアップロードしていたファイルを一括でダウンロードする方法

AppleMusicを解約したい場合や、事情でサブスクを続けられなくなった場合に有効な方法です。

まず初めにですが、一括ダウンロード的なボタンはないので、音楽一覧ファイルを選択します。


CloudStatusというソート項目がなければ、設定で、CloudStatusという項目をオンにします。
![Screenshot 2024-04-27 at 17.27.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642727/460f84d8-8146-df47-dd7a-7df40073d930.png)

CloudStatusでは

AppleMusic(聴き放題のやつ)
Uploaded(自分でアップロードした音源)
Matched(自分でアップロードしたけどAppleMusicにあったやつ？)
????(他にもあったけど忘れました。(アップロード失敗してるやつとか？))

おそらくつくらいに分かれていたと思います。

CloudStatusという部分をクリックすればAppleMusic Uploadedが分類されるので、Uploaded部分のみ全て選択して、右クリックでダウンロードを選択してください。

これでダウンロードが開始されます。
保存先は、/Users/[user_name]/Music/Music/Media.localized/Music
です。

私の場合4000ファイルくらいありましたが、全てダウンロードするのに4時間以上かかりました。

ダウンロードが終わって、全てダウンロードが確認できたら、解約するなり、別のサブスクに移るなりしましょう。

ちなみに学生の場合、大学生とかなら、割引で使えますので、お金がなくて解約しようとしてる学生はそれの利用を検討してみてもいいと思います。

では。
S3のクロスリージョンレプリケーション時に削除を反映するパターンと反映しないパターン

# はじめに
災害対策として、別リージョンにS3のレプリケーションをするケースを考えます。
通常、メインリージョンのデータをバックアップ目的でサブリージョンにコピーすることが目的です。ケースによってはメインリージョンでの削除を反映させたい場合と反映させたくない場合が考えられます。どのようなコントロールができるかを考えていきます。

# 削除を反映させるケース
アプリケーションが利用しているデータの場合、ほぼリアルタイムに削除を反映したいというケースがあります。削除が反映されない場合、メインリージョンとサブリージョンでデータの不整合が発生してしまい、リカバリ時に削除済みデータが復元されてしまう可能性があります。この場合は削除を反映させたくありません。

# 削除を反映させないケース
ログや証跡など削除されては困るようなデータのレプリケーションを考えます。この場合、メインリージョンで削除されてしまったとしても、サブリージョンのバックアップには反映されたくありません。メインリージョンでは誤削除や不正の場合が疑われるため、削除を反映させないケースです。削除できないように権限やオブジェクトロックなどをしておくのはもちろんですが、イレギュラーに実施された場合を考え、削除が反映されないようにするのが望ましいでしょう。

# コントロール方法
削除マーカーレプリケーションという機能を利用します。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/delete-marker-replication.html

もともと、S3のレプリケーションを有効化する場合、バージョニングの有効化が必須となり、バージョニングが有効化されたバケットにおいて、削除操作をすると対象バージョンで削除マーカーというフラグが付与され、オブジェクトはコンソール上ならびにGETリクエストでは取得できなくなります。削除マーカーを削除することで、復元が可能になるロジックです。ゴミ箱に入れた状態というのが表現上わかりやすいかもしれません。この削除マーカーをレプリケーションすれば、削除した操作がサブリージョンにも反映されるという代物です。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/Versioning.html

## 削除を反映させるケース
以下のように削除マーカーレプリケーションを有効化します。この設定により、メインリージョンでの削除がリクエストされると、サブリージョンへ削除マーカーがレプリケーションされ、メインリージョン側と同じような状態となります。
アプリケーション側からみると、GETリクエストではオブジェクトの取得ができなくなるため、サブリージョンのデータを利用したとしても同じ状態にすることが可能です。削除マーカーが付与されたオブジェクトは、S3のライフサイクルルールにより、相互のリージョンで一定期間後削除することが可能です。またデータのライフサイクルポリシーもメインリージョン、サブリージョンそれぞれに設定することでほぼ同じタイミングでデータの削除やストレージクラスの移動が可能です。

![スクリーンショット 2024-04-20 15.12.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584167/1be3698b-8f9b-77c7-7f67-a7af32a8d701.png)

## 削除を反映させないケース
削除マーカレプリケーションをオフにするだけです。
これにより、メインリージョンでの削除操作がサブリージョン側に反映されなくなります。メインリージョン側で不正な操作や誤操作があったとしても、サブリージョン側のデータを参照すれば、削除されていない状態のオブジェクトを取得できます。

![スクリーンショット 2024-04-20 15.12.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584167/9dd59b37-6697-3c35-c049-cbdafeccf8e6.png)

# まとめ
メインリージョンでのオブジェクトの削除を反映させるかどうかはバックアップの戻し方や、アプリケーション側の仕様、セキュリティポリシーに応じて判断する必要があります。相互のリージョンで整合性を取る必要がある場合は、有効化する必要がありますが、バックアップとして捉えた場合、削除の反映をせず、常にデータを保管しておく、またはセキュリティ上、削除操作を反映されたくない等の場合、無効化するべきです。また、削除マーカーのレプリケーション有無だけではなく、S3のオブジェクトロック、IAMポリシーによる制御、バケットポリシーによるコントロール、MFA削除など、複数の対策をすることが重要です。
[GitHub] リモートリポジトリからローカル環境にファイルを複製する！🙌（トラッキング）


## 対象

- 未来の自分😊
- 以下の前提に該当する方

## 前提

- Git bashをインストール済み
- Git bashにて、ユーザー名とメールアドレスを登録済み
- GitHubのアカウントを作成済み
- GitHubにて、リモートリポジトリを作成済み

以下のサイトを参考にしています。

https://www.kagoya.jp/howto/it-glossary/develop/howtousegithub/

## 本題
### Gitの初期登録
まず、始めにすることはユーザー名とメールアドレスの登録です。
以下のコマンドで設定状況を確認します。

```bash
# 設定のリストを取得
$ git config --list
```

現在、設定されているuser.nameとuser.emailを確認します。

```bash
$ git config --list
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=C:/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=true
pull.rebase=false
credential.helper=manager
credential.[https://dev.azure.com.usehttppath=true](https://dev.azure.com.usehttppath=true/)
init.defaultbranch=main
# 以下の部分です。
user.name=登録しているユーザー名
user.emai=登録しているメールアドレス
core.editor=code --wait
status.showuntrackedfiles=all
```

今回、私は以前に登録済みだったのでこのまま進めていきます。

### `github` ディレクトリに、`sample` ディレクトリを作成
今回は例として、`githubディレクトリ` の配下に、`sampleディレクトリ` を作成します。ディレクトリ名の `sample` はプロジェクト名です。

後ほど、この `sample` ディレクトリにGitHubから `プル` します。

```bash
# ディレクトリを作成し移動。
$ mkdir github
$ cd github

# その下に再度、ディレクトリを作成し移動。
$ mkdir sample
$ cd sample
```

### ローカルリポジトリを設定
以下コマンドを実行し、作成したリポジトリをローカルリポジトリにします。

```bash
# 現在いる `sample` ディレクトリの配下に `.git` ファイルが作成される。
$ git init
Initialized empty Git repository in C:/Users/ディレクトリ名/github/sample/.git/
```

### リモートリポジトリとローカルリポジトリの紐付け
次に、GitHubのリモートリポジトリとローカルリポジトリを紐付けます。

```bash
# /リモートリポジトリ名.git を指定。
$ git remote add origin https://github.com/user/sample.git
```

### ローカルにファイルの複製（pull）
いよいよ、GitHubのリモートリポジトリからローカル環境にファイルを複製します。

```bash
# 今回は、リモートのmainブランチからローカルのmainブランチに複製。
# origin/ mainの方がリモートブランチ
$ git pull main origin/ main
```

次に、トラッキングの設定をします。
トラッキング（追跡）することで、これ以降、プルをするときにブランチ名を指定しなくて良くなります。詳細は後述します。

### ローカルのリモートリポジトリの最新化
ここでは、ローカルのリモートリポジトリを更新します。

```bash
# リモートリポジトリから最新の情報を取得。
$ git fetch
```

### ローカルリポジトリのトラッキング設定
リモートリポジトリとローカルリポジトリのトラッキング設定をします。

```bash
# リモートブランチとローカルブランチをトラッキング
$ git branch --set-upstream-to=origin/main main
```

## ここからは、トラッキングの方法について整理していきます。

以下の3つのGitコマンドについて説明します。

| コマンド |  場面 | 説明 |
|:-:|:-:|:-:|
|  `git branch --set-upstream-to=[origin/remote-branch] [branch]` | 既存ブランチの設定変更時 |  **既存のローカルブランチ**に対して、特定のリモートブランチを**追跡**するように設定するコマンドです。これは、既に存在するブランチの追跡ブランチを変更するか、新たに追跡関係を設定する際に利用されます。 |
|  `git branch --track [new-branch] [remote-branch]` |  新規ブランチ作成時 |  このコマンドは、指定されたリモートブランチを基に**新しいローカルブランチを作成**し、そのブランチがリモートブランチを**追跡**するように設定します。この操作は、新しいブランチを作成する際に追跡関係も同時に設定するために使われます。 |
|  `git checkout -b [new-branch] [remote-branch]` |  新規ブランチ切り替え時 |  このコマンドは、リモートブランチを基に**新しいローカルブランチを作成**し、その新しいブランチに**直ちに切り替えます**。このコマンドにより、新しいブランチが自動的にリモートブランチを**追跡**するように設定されます。 |


### 追跡ブランチの役割
追跡ブランチの役割は、データ同期とステータス情報を確認できることです。

- **データ同期**：追跡ブランチが設定されていると、`git pull` または `git push` を実行する際にリモートブランチ名を指定する必要がなくなります。これにより、作業効率が向上します。
- **ステータス情報**：`git status` コマンドを使用すると、リモートブランチとの間でのコミットの差異が表示されるため、作業の進行状況が明確になります。
画像のファイルサイズが大きすぎたのでavif変換とリサイズしてちっさくしてみた

先日新卒開発研修が終了した24卒エンジニアです。
開発研修の際に使用した画像ファイルサイズ縮小のためのコードを置いときます。

# 余談
コードは研修中以下のようなモチベーションがあったため、片手間に書いたやつです。
- アプリ内に表示する画像をAPIレスポンスに含まれるバイナリデータからフロントエンド側でconvertし表示する仕様だった
- 画像ファイルが１枚3000px*4000px（3.5MB）くらいあり明らかにサイズが大きすぎた
- 120枚ほどあり手作業でやるのは馬鹿らしかった
- 予めファイルサイズを小さくする必要があった

# 使用したライブラリ
```
pip install pillow
```

## コード
repo: https://github.com/yk-mt12/convert-resize-image-avif

今回は横幅500pxでアスペクト比を固定し、`.avif`形式に変換しています。
```python
import os
from PIL import Image
import pillow_avif

dir_name = 'original'
new_dir_name = 'convert'

files = os.listdir(dir_name)
new_width = 500 # リサイズ後の幅

for file in files:
    file_name = os.path.splitext(os.path.basename(file))[0]
    img = Image.open(os.path.join(dir_name, file))
    width, height = img.size

    # アスペクト比を固定してリサイズ
    new_height = int((new_width / width) * height)
    img_resize = img.resize((new_width, new_height), resample=Image.LANCZOS)
    image = img_resize.convert("RGB")
    img_resize.save(os.path.join(new_dir_name, file_name + ".avif"), format="avif")

```

# before&after

以下のように3.3MBあったファイルサイズが、16KBまで小さくできています。

before
```shell
# ls -lh original/sample.jpg 
3.3MB original/sample.jpg
```

after
```shell
# ls -lh convert/sample.avif 
16KB convert/sample.avif
```