OmniAICreator/Qiita-1.07M huggingface dataset:
Cockpit (CMS) の初期設定の注意点

# Cockpit (Headless CMS)

フロントエンドはスクラッチで開発したい場合、ヘッドレスCMSを使うことになりますが、小規模なサイトだと `Strapi` では仕掛けが重すぎたり、リクエストが多いXserverなどのレンタルサーバーへの設置だとPHPで動くものの方が良かったりします

`Wordpress` をヘッドレスCMSとして利用しても良いのですが、そもそもなぜフロントエンドはスクラッチで開発となったのか考えた時、若干の疑問が生じてきます

弊社では `Strapi` で実装できない場合や小規模サイトの場合、動作と仕掛けが軽いので、`Cockpit` (Linuxの管理システムではないコックピット) を採用してます

ただ、そのまま設置するとセキュリティ上の疑念が出てくるため、その初期設定についてここでまとめて公開します（まとめてと言うほどたいそうなことではないですが、備忘録に近いです）

ちなみにいま `Cockpit` について興味を持たれた方や簡単な使い方は、他の記事を参考にしてください

https://codit.pages.dev/notes/avglr3cbaro47z6luq2l/

https://labor.ewigleere.net/2023/05/25/cockpit-cms-installation-and-test-api/

## サイトへの設置

まずは公式サイトの下部からソースコードをダウンロードして、設置するディレクトリで `unzip` します

https://getcockpit.com/

次に初期設定ですが、`<PATH_TO_COCKPIT>/install` にアクセスして、`user = admin` と `password = admin` でログインし、右上にあるハンバーガーの設定メニューからユーザー名・パスワードとその他必要事項を変更して保存します

設置は基本的にはこれだけです...が、**この状態だと問題が出てきます**

## やっておいた方が良いこと

### `install` ディレクトリの消去

`Wordpress` でも同じですが、インストール関連は消しておいた方が無難です

### `CLI` コマンドのパーミッション設定

`Cockpit` には `tower` っていうCLI用の管理コマンドが付属していて、これを上位フォルダに移動すると正常に動かないので、そのままだと外部に晒され続けます（アクセスしてもソースが読まれるだけで動作はしなさそうなので放っておいても良いかもしれませんが、気味が悪いです）

なので、パーミッション設定で所有者のみ実行できるように700で設定しておきます[^1]

[^1]:グループの実行を許す場合は750とかアレンジしてください

```
$ chmod 0700 tower
```

### `bootstrap.php`へのアクセス禁止

`bootstrap.php` も外部からアクセスできる状態である必要は**多分**ありませんので、`.htaccess` でアクセスを禁止しておきます[^2]（`tower` へのアクセスを同じ方法で制限しても良いです）

[^2]:もしエラーが出た場合は、この設定を疑ってみてください

```
# Deny access to bootstrap.php
<FilesMatch "^bootstrap\.php$">
    Order Allow,Deny
    Deny from all
</FilesMatch>
```

### Composer用のJSONへのアクセス禁止

さらに、`composer.json` や `package.json` も外部から見えてしまう状態になっているので、アクセスできないように、以下のような記述をデフォルトの`.htaccess` に追加しておきます

```
# Deny access to JSON files
<FilesMatch "\.json$">
    Order Allow,Deny
    Deny from all
</FilesMatch>
```

### おわり

以上でひとまずの初期設定は完了です、あとはAPI鍵を生成してフロントエンドとつなげてください！
Androidで画面にタップしている箇所を表示する方法

開発している人に不具合を報告する際に、再現方法が複雑な場合や、画面録画で再現方法を説明することなどがあると思います。

その際にどこをタップしているかわかると便利ですよね。

Androidの設定で表示させることができます。

# 設定方法

開発者向けオプションをまず表示させます。

ビルド番号を７回連続でタップします。（設定画面のデバイス情報にあります。）

開発者向けオプションを開きます

![Screenshot_20240316_200604.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/0a483985-e4b7-bd27-90cf-11f1ea40e63f.png)

タップを表示をONにすると表示されるようになります。
[Gmail API] Javaでメールボックスのユーザープロフィールを取得する

Gmail API v1（Java）を使用して、
Gmailのメールボックスのユーザープロフィールを取得する
についてご紹介します。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Gmail API] JavaでGmail APIを使う](https://qiita.com/doran/items/a078e966bfd93c4b19c2)
を参照ください。
:::

本文中の引数にある「メールアドレス」の指定は、
OAuth 2.0使用の場合は「me」（自身）と指定してください。
「me」は認証されたユーザーを示します。

|No||目次|
|---|---|---|
|1||[プロフィールを取得](#1-プロフィールを取得)|
||1|[スコープ](#11-スコープ)|
||2|[実行](#12-実行)|
||3|[レスポンスの内容](#13-レスポンスの内容)|


## 1. プロフィールを取得
ユーザーのプロフィールを取得します。

### 1.1. スコープ
このAPIを実行するには、以下のいずれかのスコープを指定してください。
```
GmailScopes.MAIL_GOOGLE_COM
GmailScopes.GMAIL_MODIFY
GmailScopes.GMAIL_COMPOSE
GmailScopes.GMAIL_READONLY
GmailScopes.GMAIL_METADATA
```
[⧉[Gmail API] JavaでGmail APIを使う(2.2 Gmailインスタンスを取得)](https://qiita.com/doran/items/a078e966bfd93c4b19c2#22-gmailインスタンスを取得)
でスコープを指定してください。
### 1.2. 実行

```java
public static void main(String[] args) throws Exception{
	Gmail gmail = getGmail();
	Gmail.Users users = gmail.users();

	Gmail.Users.GetProfile profile = users.getProfile("メールアドレス");

	Profile res = profile.execute();
	System.out.println(res);
}
```
#### 1.2.1. HTTPリクエスト
GET:　https:\//gmail.googleapis.com/gmail/v1/users/{メールアドレス}/profile
が実行されます。

#### 1.2.2. クエリパラメータ
クエリパラメータはありません。

### 1.3. レスポンスの内容

#### Profile

|メソッド|戻り値|説明|
|---|---|---|
|getEmailAddress|String|ユーザーの電子メールアドレス|
|getMessagesTotal|Integer|メールボックス内のメッセージの総数|
|getThreadsTotal|Integer|メールボックス内のスレッドの総数|
|getHistoryId|String|メールボックスの現在の履歴レコードID|
shadcn/ui+react-hook-form+zodを使ったサジェストフォームの作り方

基本的には、shadcn/uiを使ったサジェストフォームの簡単なサンプルとして、下記のデモサイトがありますが、こちらをコピペすればよいです。
https://www.armand-salle.fr/post/autocomplete-select-shadcn-ui 

このサイトを運営しているarmandさんの[githubのソースコード](https://github.com/armandsalle/my-site/blob/main/src/components/autocomplete.tsx)

今個人開発している[プレイスオブ](https://placeof.app/)というサイトの物件のスペックを入力する画面でこの実装を~~ほぼコピペさせてもらっている~~のですが、何点か追加実装が必要だったのでメモしておきます。何かしらの参考になれば幸いです。

# 完成図
![](https://storage.googleapis.com/zenn-user-upload/c8e88d9a05ab-20240316.gif)

## suggestのロジックの変更
上記実装で使われている、shadcn/uiの[Combobox](https://ui.shadcn.com/docs/components/combobox) は[cmdk](https://github.com/pacocoursey/cmdk/)のComboboxをwrapしたものです。suggestのロジックを変更したかった(+日本語だと上手くいかない気がした)ので、cmdkのドキュメントに記載されている通りfilterに独自実装を追加してます。sortとかも出来るようです。
```
<Command
  filter={(value, search) => {
    if (value.includes(search)) return 1
    return 0
  }}
/>
```

## keyの値でvalueのバリデーションをする
### keyの追加時の処理
keyとvalueの2つのフォームがあり、keyの値でvalueの値をvalidationする必要するときの実装です。suggestをするkeyが[handleKeyDown](https://github.com/armandsalle/my-site/blob/01392f3860b093209dd0b8a2d7355656ef204c83/src/components/autocomplete.tsx#L55)などで確定するときに、onValueChangeで親のComponentの関数を呼び出していますが、そのときに、
```
 onValueChange={(key: SuggestKey) => {
    form.setValue("suggestKeyId", key.suggestKeyId)
    form.setValue("suggestValueType", key.valueType)
}}
```
のようにreact-hook-formのsetValue関数を使い、確定したkeyをformに追加します。なお、このときに下記のようにreact-hook-formのformが定義されています。
```
  type Inputs = z.infer<typeof SuggestKeyFormSchema>
  const form = useForm<Inputs>({
    resolver: zodResolver(SuggestKeyFormSchema),
    defaultValues: defaultValues,
  })
```
### valueの追加時の処理
下記のようにvalueをregisterします。
```
    <FormItem>
      <FormControl>
        {specKey?.valueType === SpecValueType.TEXTAREA ? ((
          <Input
            aria-invalid={!!form.formState.errors.value}
            {...form.register("value")}
          />
        )}
      </FormControl>
    </FormItem>
```
そして、下記のようにzodのsuperRefineを使ってvalidateします。このときkeyを追加したときのvalueTypeが使われます。
```
export const SuggestKeyFormSchema = z
  .object({
    suggestKeyId: z.string().min(1),
    valueType: SuggestValueTypeSchema,
    value: z.string().min(1),
  })
  .superRefine((values, ctx) => {
    if (
      values.valueType === SuggestValueTypeSchema.STRING &&
      values.value.length >= 20
    ) {
      ctx.addIssue({
        message: "need to be less than 20 words",
        code: z.ZodIssueCode.custom,
        path: ["value"],
      })
    }

   ....
  })
```
### i18n
ちなみに、keyはi18nのファイルを参照するようにして表示しています。

suggest一覧の変換箇所
https://github.com/armandsalle/my-site/blob/main/src/components/autocomplete.tsx#L36

確定したkeyの変換箇所
https://github.com/armandsalle/my-site/blob/main/src/components/autocomplete.tsx#L128

## サーバーからデータを取得
サーバーからデータを取得する場合は、こちらのやり方が参考になるかと思います
https://zenn.dev/mktu/articles/2f9166374d09a0

# まとめ
もっと完成度を高めて物件のありとあらゆるスペックが入力できるフォームにしていきたいので、何かあれば教えて下さい。
認識齟齬の起きにくいテキストコミュニケーションの３つのコツ

リモートワークが増え、SlackやBacklogなどのツールのコメントでのやり取りが増えた昨今、テキストコミュニケーションは仕事をする上で欠かせない能力です。

ただし口頭でのコミュニケーションと比べるとテンポが遅くなるので、ちょっと違和感があってもスルーしてしまって、後々認識齟齬に気づく、といったことが往々にしてあります。
チャットならまだしも、メールやツールのコメントでのやり取りでは一回あたりの文量も多くなりがちで、より「まぁいいか、こういうことだろう」と確認を怠りがちです。

認識齟齬が起きにくいテキストコミュニケーションのTipsをまとめます。

※システム開発中のシチュエーションを想定した内容です

# 抽象的な表現は控え、具体的に
:::note alert
ここのフォントサイズはもう少し大きくして欲しいです
:::
:::note info
ここのフォントサイズはこのページのこの文言のサイズに合わせて欲しいです
:::
:::note info
ここのフォントサイズは**今10pt**だと思いますが、**12pt**にして欲しいです
:::
---
:::note alert
本日期限のタスクですが、レビューで指摘があったのでもう少しかかりそうです
:::
:::note info
本日期限のタスクですが、レビューで指摘があり修正に**2-3時間**かかりそうなので、**明日の午前いっぱい**かかりそうです
:::
---
:::note alert
昨日報告してくれた資料、指摘書いといたから修正して早めに部長に出しといて
:::
:::note info
昨日報告してくれた資料、指摘書いといた。**明日の16時の会議で使いたい**から**明日の午前中**に部長に出しといて。
:::

# 何を指しているのか分かり易いように引用やリンクを
:::note alert
本件、以前提案してくれた方針のうち工数が小さい方で進めて欲しいです。
:::
:::note info
本件、以前提案してくれた下記の方針で進めて欲しいです。
> 二つ目の案は〜〜〜〜を〜〜〜〜とする方法です。
この方法は今後ユーザー数がXX万人規模に増えると処理速度面で不安がありますが、小規模な修正（２人日程度）で課題が解消できます。
:::
---
:::note alert
今回やった作業、マニュアルに追記しといて。
:::
:::note info
今回やった〜〜〜から〜〜〜までの作業、[マニュアル](https://qiita.com/)に追記しといて。
:::
※リンクはダミーでQiitaのTOPを設定しています。実際は資料のリンクを貼ります。

---
:::note alert
前にやったXXXX画面の不具合修正と同じような対応になるので２人日程度かと思います。
:::
:::note info
前にやった[XXXX画面の不具合修正](https://qiita.com/)と同じような対応になるので２人日程度かと思います。
:::
※リンクはダミーでQiitaのTOPを設定しています。実際は該当のチケットへのリンクを貼ります。

# 画像で補足する
:::note alert
HOME画面の左に表示しているユーザーランキングの文字の下に`Organizationのランキングはこちら`のリンクを追加してください。
:::
:::note info
HOME画面の左に表示しているユーザーランキングの文字の下に`Organizationのランキングはこちら`のリンクを追加してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736028/08f8429d-6651-b972-321d-b579adf0011a.png)
:::
【IKEv2 VPN】スマホとかの標準機能だけで繋がるお手軽VPNサーバーを立てる

IKEv2/IPSecのVPNサーバーをDockerを使って簡単に立てる記事。

# なぜIKEv2なのか
現代的で安全とされる方式かつ、クライアント端末のOSの標準機能で対応していることが多く接続に追加のソフトのインストールが不要だから。

VPNと言えばOpenVPNが有名だったりするが、これは各クライアント端末に専用のソフトをインストールしないといけないので面倒だしなんか嫌だった。そこでこれまでずっとSoftether VPNによるL2TP/IPSecサーバを立てていた。L2TP/IPSecはAndoridやWindowsなど多くのOSの標準機能として対応しており、クライアントには追加のソフトのインストールが不要である。しかし最近（と言っても数年前だが）Androidでは新しくL2TP/IPSecのVPN接続が新規作成できなくなった。L2TP/IPSecはセキュリティー的にあまり良くはないという事らしい。ということで同じように多くのOSが標準で対応しているが、より現代的な方式であるIKEv2/IPSecのVPNサーバーを立てる。

# 前提

```console
$ head -n1 /etc/os-release
NAME="Arch Linux"
$ docker --version
Docker version 24.0.7, build afdd53b4e3
```

UDPの500番と4500番ポートで待ち受けるので接続できるようにポート開放等しておく。

# 使用するサーバーソフトウェア
以下のDockerイメージを使う。ドキュメントが充実しているので、セットアップの詳細はドキュメントを読むのが良い。

https://github.com/hwdsl2/setup-ipsec-vpn/tree/master

# サーバー起動
上をDocker Composeで起動させる。以下の`compose.yaml`ファイルを作成する。

```yaml:compose.yaml
services:
  vpnserver:
    image: hwdsl2/ipsec-vpn-server
    ports:
      - 500:500/udp
      - 4500:4500/udp
    volumes:
      - ./ikev2-vpn-data:/etc/ipsec.d
      - /lib/modules:/lib/modules:ro
    privileged: true
    environment:
      - VPN_IKEV2_ONLY=yes
      # - VPN_DNS_NAME=vpn.example.com # サーバーにDNS名でアクセスする場合は名前を必ず指定する。
      # - VPN_DNS_SRV1=1.1.1.1 # 接続したクライアントが使うDNSサーバー名を指定できる。指定しないとGoogle Public DNSが使われる。
      # - VPN_DNS_SRV2=1.0.0.1
    restart: unless-stopped
```

`$ docker compose up` で起動する。初回起動時は初期化の処理に少し時間がかかるので待つ。

初期化が完了するとマウントした`./ikev2-vpn-data`ディレクトリの中に設定や証明書等のファイルが生成される。中でも`vpnclient.p12`ファイルを使っていく。このファイルには秘密鍵が含まれているので扱いには注意。

# クライアントセットアップ
OSごとのセットアップ方法は以下のドキュメントに書いてある。ここではAndroidの場合だけを紹介するが、他のほとんどのOSでも同様にOSの標準機能だけで接続できる。

https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/ikev2-howto.md#configure-ikev2-vpn-clients

1. 前セクションで得た`vpnclient.p12`ファイルを安全な方法でAndoridに転送する。
1. 設定アプリで「証明書」等で検索して「証明書のインストール」画面を開く
1. 「VPNとアプリユーザー証明書」を選択
1. 転送した`vpnclient.p12`ファイルを選択
1. 好きな名前を付けてOKを押す
1. 設定アプリで「VPN」等で検索してVPNの設定画面を開く
1. 新しい接続を追加し以下の画像のように設定する
    - 「サーバーアドレス」は立てたサーバーのIPアドレス（またはDNS名）を入れる
    - 「IPSecユーザー証明書」と「IPSec CA証明書」は先ほどインストールしたものを選ぶ
    - 「IPSec ID」は使用されないので何でもよい（でも入力必須になっているのはAndroidのバグらしい）

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/17699d5f-df99-7893-104c-48d18d8f86d9.jpeg)

以上で追加したVPN接続を有効化すれば接続できるはず。
IPAファイルがApp StoreにアップできないAsset validation failed (90771) Missing Info.plist value.の解決法

# IPAファイルがApp Storeにアップできない
Fastlaneなどでビルドからストアにアップロードまで自動化しているのですが、ストアにアップロードする部分でエラーになりました。。。

https://docs.fastlane.tools/getting-started/cross-platform/flutter/



```console
ERROR: [ContentDelivery.Uploader] Asset validation failed (90771) Missing Info.plist value. The Info.plist key 'BGTaskSchedulerPermittedIdentifiers' must contain a list of identifiers used to submit and handle tasks when 'UIBackgroundModes' has a value of 'processing'.
```

どうやらinfo.plist？の設定の問題か？と思ったが、、
どうやらXcodeの設定を変えれば大丈夫そうでした！
`Signing & Capabilities > Background Modes`を開いて

**Background Fetchにチェックをつけ、Background processingのチェックを外します。**


![Screenshot 2024-03-08 at 14.39.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/4ee5093b-fcb2-5a7d-78d8-bbf20811f8cb.png)

これで再度ビルドすれば解決しました！！！

# 参考

https://github.com/fluttercommunity/flutter_workmanager/issues/105
C++でラムダ式っぽい [&]{}() こいつに出会って学んだこと

## ネタバレ
`[&]{}();` ←ラムダ式でした．

# はじめに
普段競技プログラミングをしているNafmoというものです．

今回，色んな人のコードを読んで勉強していたときに出会った `[&]{}()` の話をまとめて残しておこうと思い記事を書いています．

私と同じような困惑に遭遇する人がいたときのことを考えて，初めてのQiitaをやっていきます．

::: note warn
普段雰囲気でC++を書いているため，間違っている箇所があれば指摘していただけると助かります！
:::

# 発端
ある方のコードを読んでいるときのツイートが発端でした．

https://twitter.com/Nafmo2/status/1767003045706256478

より具体的には 
```cpp
auto x = [&]{

    // 何らかの処理

    return result; // 計算結果の返却
}();
```

というコードに出会い，どういう処理をしているのか初見で分からず困った感じでした．

# 分かったことと分からなかったこと
ラムダ式っぽいので一旦ググって [cpprefjp - ラムダ式](https://cpprefjp.github.io/lang/cpp11/lambda_expressions.html) を読みました
### 分かった(調べた)こと
 - `[&](){}` の `[&]` はラムダ式のキャプチャの指定っぽそう
 - `[](){}` は引数がない場合 `[]{}` と省略できる

### わからないこと
 - `[&](){}` を省略すると `[&]{}` とはなるが，`[&]{}()` とはならない気がする
     - `()` がワープしてる？この書き方知らないな...

なにこれ！となりました

# `x = [&]{}();` が示す意味
これを省略しないで書くとこのようになると教えていただきました
```cpp
auto f = [&](){
    // 計算
    return res;
};
auto x = f();
```
つまり， `f == [&](){}` と思うとスッキリしそうです．
そこで定義したラムダ式をすぐ呼び出して使い捨てている，というように理解しました．

ラムダ式を名前を付けずに使っているだけでした．分かってしまえば簡単に見えますが，自分の知らない記法があるのか！？と疑ってしまって固まっていたので，大変助かりました．

# 変数のスコープを縮める
これだけなら記事にまとめないのですが，リーダブルコードの9章に乗っていたのでその情報と合わせてまとめたいと思います．

このコードによって変数のスコープを縮めることができます．
```cpp
auto x = [&]{
    // x を決めるのに使うローカル変数は x を計算し終わったら寿命が尽きる
}();
```
波括弧でブロックを作るのと同じような効果があると思います．
変数の影響範囲が短いと，同時に考える変数が減るなどしてコードが読みやすくなると思います．そういった効果が期待されますね．

個人的には，波括弧を使うときとの違いは早期リターン(リーダブルコードではガード節と呼ばれているやつ)ができるなどして，分岐を浅くしやすいというところにあるのかな？なんて考えたりしました．

# まとめ
 - `auto x = [&]{~~~~}();` はラムダ式を即座に実行して，結果を `x` に代入するよ！
 - このコードにはスコープを縮める意味があって，それがリーダブルコードに乗っていたよ
 
 ということになります．ありがとうございました


# おわりに

C++，私が知らないだけでいろんな書き方があると思っているのが良くなかったかもしれませんね．

あとVSCodeのintellisense で 代入されてる側が，返り値と同じ型だったところから気づけても良かったのかなと思いました．反省．

~~中括弧って言い方廃止？されたんですね，JISにはないらしい~~

# 参考文献(?)

- [リーダブルコード](https://www.oreilly.co.jp/books/9784873115658/) 9章 p.118 JavaScriptで「プライベート変数」を作る
- あぷりしあさん
 
 https://twitter.com/aplysiaSheep/status/1767004163031134527

- みどりむしさん
 
 https://twitter.com/KakurenboUni/status/1767004731090641208
「現代数理統計学の基礎」演習問題解法メモ　第7章問1～2 

第7章に入りました。
問2は難問です。一度終わったと思ったら不足していて、そのためページ追加のため飛んでいます。途中式を極力飛ばさずに記載しています。
![第7章問1 (1)①.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/c958949e-0d91-37a3-0143-b766d650ed93.jpeg)
![第7章問1 (1)②.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/4b265b34-edd3-1212-815b-d7abc73932a9.jpeg)
![第7章問1 (1)③.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/873edccc-af7e-33d5-c733-03e993845c8f.jpeg)
![第7章問1 (2)①.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/a4c915b3-77b5-5529-a567-72587997934f.jpeg)
![第7章問1 (2)②.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/d75d016b-e189-9732-25a3-0e95b6466884.jpeg)
![第7章問1 (2)③.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/80f2d229-9ce1-5607-e770-f1087f8798f1.jpeg)
![第7章問2 P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/b099f575-4253-feb0-b360-fcd25776b30f.jpeg)
![第7章問2 P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/3e7f32ba-4746-c2d0-b903-6218a1430a0e.jpeg)
![第7章問2 P3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/b9831e31-c6b1-2534-a047-62f24f365ec9.jpeg)
![第7章問2 P4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/5f4e1bef-8db6-1fca-4a36-a9bfef6f1e4f.jpeg)
AtCoder Beginner Contest 344 振り返り

前回のAtCoderの振り返りです。
## 今回の結果

A,B 2完でした。

![スクリーンショット 2024-03-16 17.34.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167729/d5bb26f7-1be3-898f-3f02-6b551917b3d7.png)

![スクリーンショット 2024-03-16 17.31.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167729/06b311c4-eb10-cb07-2220-83db9bd8e69b.png)

## 各問題の振り返り

### A - Spoiler

splitして先頭と最後尾を繋げるだけです。

- [問題](https://atcoder.jp/contests/abc344/tasks/abc344_a)
- [自分の回答](https://atcoder.jp/contests/abc344/submissions/51045570)

```haskell
main :: IO ()
main = do
  s <- getLine
  let splitted = splitOn "|" s

  putStrLn $ head splitted ++ last splitted
```

### B - Delimiter

- [問題](https://atcoder.jp/contests/abc344/tasks/abc344_b)
- [自分の回答](https://atcoder.jp/contests/abc344/submissions/51074447)

最後が0というのがポイントで、0になったら標準出力する、で解くことができます。

```haskell
main :: IO ()
main = readNumbers []

readNumbers :: [Int] -> IO ()
readNumbers nums = do
  n <- readLn @Int
  if n == 0
    then mapM_ print (0 : nums)
    else readNumbers (n : nums)
```

### C - A+B+C 

- [問題](https://atcoder.jp/contests/abc344/tasks/abc344_c)
- [自分の回答(upsolved)](https://atcoder.jp/contests/abc344/submissions/51190702)

制約条件の`1≤N,M,L≤100`がポイントです。あらかじめ全て計算してHashSetに値を入れておき、その値が存在した場合はそれが解になります。

```haskell
main :: IO ()
main = do
  _ <- readLn @Int
  as <- readInputInts
  _ <- readLn @Int
  bs <- readInputInts
  _ <- readLn @Int
  cs <- readInputInts
  _ <- readLn @Int
  xs <- readInputInts

  let sums = HS.fromList [x + y + z | x <- as, y <- bs, z <- cs]

  forM_ xs (\x -> putStrLn if HS.member x sums then "Yes" else "No")
```

## 全体を振り返って

最近忙しくてあまり練習できてなかったのですが、またぼちぼちやっていきます。
Azure Key Vaultからシークレットの値を取得する

## 環境

Azure Virtual Machine - CentOS 8.2
Azure Cli - 2.38.1

今回はVMから取得するが、ロールが割り当てられた状態であればどこからでも可能。  

## 前提

* Key Vaultのシークレットが取得できるようにロールが設定できていること
* `キーコンテナーシークレットユーザー` があればよい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3018916/489424c9-aa65-218f-ed3d-fa1518787421.png)

## az keyvault secret show コマンド

`az keyvault secret show --vault-name <Key Vault名> --name <シークレット名> [--output table]`

|オプション|設定値|
|-|-|
|--vault-name|Key Vaultのリソース名|
|--name|シークレットの名前|
|--output table|省略可能。指定するとテーブル形式で出力される|

* すべてのシークレットを一度に取得するオプションは存在しない模様
* もしやるなら、`az keyvault secret list` でシークレットの一覧を取得してからlistの数だけコマンドを実行すればよい

### 実行例

今回は、`my-key-dev-001` の `SECRET_PASSWORD` を取得してみる。  

```bash
# サインイン
$ az login --identity --username xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxx
{
  "attributes": {
    "created": "2024-03-16T06:33:18+00:00",
    ...
    }
}

# 取得
$ az keyvault secret show --vault-name my-key-dev-001 --name SECRET_PASSWORD
{
  "attributes": {
    "created": "2024-03-16T06:33:18+00:00",
    "enabled": true,
    "expires": null,
    "notBefore": null,
    "recoveryLevel": "CustomizedRecoverable+Purgeable",
    "updated": "2024-03-16T06:33:18+00:00"
  },
  "contentType": null,
  "id": "https://my-key-dev-001.vault.azure.net/secrets/SECRET_PASSWORD/xxxxxxxxxxxxxxxxxxxxxxxxx",
  "kid": null,
  "managed": null,
  "name": "SECRET_PASSWORD",
  "tags": {},
  "value": "Password-Value"
}

# テーブルにするとこのように出力される
$ az keyvault secret show --vault-name my-key-dev-001 --name SECRET_PASSWORD --output table
Name             Value
---------------  --------------
SECRET_PASSWORD  Password-Value
```

シークレットの設定値 `Password-Value` が取得できた。  

## (補足)ポータルからも参照は可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3018916/d7da152c-1d72-3d57-dd8d-bee3bc32e0e5.png)
Wordpress SiteGuard のplugin でadmin 画面に入れなくなった

この前、wordpress でサイトを作り始めて、いきなり管理画面に入れなくなったので、ちょっと焦って解決した時のお話です。

その時にWordpress のplugin でSiteGuard を使用したので、そこで設定を施したことによって、入れなくなったみたいでした。


# 環境
local fly
wordpress

# 事象

wp-admin でアクセス何回もしたのですが、なんで？？？

![wp-site-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2988737/27a67abb-1992-7352-ff32-f18efae886c7.png)


これはどうやって解決するんだと思って、調べていくと、まずは.htaccess に書いてあるやつをコメントアウトしてみます。

```
#SITEGUARD_PLUGIN_SETTINGS_START
#==== SITEGUARD_RENAME_LOGIN_SETTINGS_START
# <IfModule mod_rewrite.c>
#     RewriteEngine on
#     RewriteBase /
#     RewriteRule ^wp-signup\.php 404-siteguard [L]
#     RewriteRule ^wp-activate\.php 404-siteguard [L]
#     RewriteRule ^login_xxxxx(.*)$ wp-login.php$1 [L]
# </IfModule>
#==== SITEGUARD_RENAME_LOGIN_SETTINGS_END
#SITEGUARD_PLUGIN_SETTINGS_END
```

そしてもう一度、開いてみると、やっぱり同じ画面になります
一時的な解決方法ですが、plugin を一度削除するというので、何とかログインすることができました。かなりパワープレイなので、あまりおすすめしませんが、これで一時的に解決できるようです。


# まとめ
SiteGuard は確かに便利ですが、本番運用する前にログイン方法や設定方法をきちんと把握することが必要だなと思いました。セキュリティはかなり高まる気がするので、ぜひ色々調べてみるといいかもしれません。
localホストをcommand promptで作る。

# 初めに
皆さんはlocalhost(ローカルホスト)というものを知っていますでしょうか。
今回はローカルホストをcommand promptで立ち上げる方法を紹介していきます。
# 注意
今回はpythonを使用します。まだソフトをダウンロードしていない場合は、[pythonの公式サイト](https://www.python.org/downloads/ "Download Python | Python.org")からpythonの最新版をダウンロードしてください。（自分はpython3.9を使用しています。）
# ローカルホストを起動させる（python3以降）
python3.0より上のバージョン（python3.0~python3.9)を利用している方は、この方法で起動できます。
まず、コマンドプロンプトを開いて、自分がローカルホストを起動させる場所（ファイルパス）を入力してください。(今回はDドライブ上で起動させます。)
```:command prompt
cd D:
```
次に、以下のように入力して、ローカルホストを起動します。
```:command prompt
python3 -m http.server 8000
```
これで、ローカルホストが起動できました。[localhost:8000](http://localhost:8000 "localhost:8000")にアクセスすると、Directory listing for /というタイトルの画面が表示されるはずです。
ちなみに、8000の場所は他のポート番号に変更できます。（何も入力しない場合、自動的に8000番ポートで立ち上げられます。）
# ローカルホストを起動させる（python2.x）
python2.xを使用している人は、これで起動できます。
まず、コマンドプロンプトで、ローカルホストを起動させる場所（ファイルパス）を指定します。(今回はDドライブ上で起動させます。)
```:command prompt
cd D:
```
次に、以下のコードをコピペします。
```:command prompt
$ python -m SimpleHTTPServer 8000
```
これで、[localhost:8000](http://localhost:8000 "localhost:8000")にアクセスすると、Directory listing for /という画面が表示されるはずです。
ちなみに、これも、python3以降と同じようにポート番号を変更できます（何も入力しなかった場合、デフォルトで8000番ポートで起動します。）
# 最後に
いかがだったでしょうか。今回はコマンドプロンプトでローカルホストを起動させる方法についてご紹介しました。ちなみに、今回の方法は、管理者権限を持っていなくても実行できるので、ぜひ試してみてください。それでは、またお会いしましょう！
【ImageJ】フォルダ内の画像の輪郭を赤線で強調する

    //処理を行うフォルダと保存先のフォルダを選択//
    showMessage("Select Open Folder");
    openDir = getDirectory("Choose a Directory");
    showMessage("Select Save Folder");
    saveDir = getDirectory("Choose a Directory");
    list = getFileList(openDir);


    //ファイルの数だけ処理を行う//
    for (i=0; i<list.length-1;i++){

    	//ファイル名の取得
    	open(openDir+list[i]);
    	name = getTitle;
    	dotIndex = indexOf(name, ".");
    	title = substring(name, 0, dotIndex);

    	//ここから下に処理コードを追加
    	run("8-bit");
    	setOption("BlackBackground", true);
    	run("Convert to Mask");
    	run("Find Edges");
    	run("Merge Channels...", "c1=" + name);
    	open(name);
    	run("8-bit");
    	imageCalculator("Difference" ,name, "RGB");
    	imageCalculator("OR","RGB" , name);
    	newname = title+"_Edge";
    	saveAs("jpeg", saveDir+newname);
    	saveAs("Results", saveDir+newname+".csv");
    	close();
    	close();

    }
Kaggleの生成AIコンペ：LLM Prompt Recovery

最近Kaggleで新しい生成AIコンペ：LLM Prompt Recoveryが開催されました。⇩

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/9a94ab87-71a1-913c-13c3-788cfe59374e.png)

このコンペで取り組むことは、元の文章とLLMで生成された書き換え文章に基づいて、その書き換え文章を生成するのに用いられたprompt文を復元することです。

実際のデータ例を見ると理解しやすいと思いますが、⇩のように元の文章（original_text）と生成された文章（rewritten_text）があり、それらを使ってプロンプト文を復元するコンペになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/083bd93f-e009-61f9-5808-e2df70a2f679.png)


学習データのイメージは⇩です。（復元するプロンプト文はrewrite_prompt）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/f60893d3-cabd-3bde-3951-3367304217a2.png)
（なお、学習データは上記の1行しかないため、自分で用意する必要があります。）

使用されているモデルはGemma-7B-instructで、評価指標は文章間のコサイン類似度であり、sentence-t5-baseモデルで計算されます。

現在、主に2つのアプローチが主流となっています。

1つは最も一般的なアプローチで、文章復元用のモデルをファインチューニングする方法です。しかし、この方法でやると、精度はわずか0.47程度にとどまっています。私もデータ探して、モデルをトレーニングしましたが、精度があまり高くはなくて、何度が改善しても精度は0.5程度です。これからは、Gemmaでトレーニングデータを生成し、MoE（混合エキスパートモデル）を試してみたいと思います。

もう1つのアプローチは、コサイン類似度を逆算するトリッキーな方法です。このコンペでは、文章をより良く書き換え用prompt文を推測するために、testデータにおけるprompt文の多くは"improve the text to this"という文章が含まれています。なので、prompt文を予測せず全部回答をこの"improve the text to this"にしても、なんと類似度が0.58にもなるんです。そのために、今多くの参加者がコサイン類似度の変化から逆算して元の文章内にあるキーワードを見つけ出すことに注力しています。

ただし、この方法でやっても最後精度が高いわけではありません。パブリックスコアで用意されているtestデータは全データの15%しかないため、残りのデータには"improve the text to this"という文章がそれほど多くない可能性もあります。そうすると、最終的には大きなshakeが起きる可能性が非常に高いです。

ですので、まだ誰も良い対策が見つかっていないのが現状で、上位者のスコアは非常に近づいています。0.62が銀メダル、0.61が銅メダル、0.63以上が金メダルといった感じです。加えて、このコンペではスコアが小数点以下2桁までしか表示されないため、異なる方法間の優劣を見極めるのも難しいです。私が最近提出した新しいモデルの結果はいずれも0.61で、それらの間には違いがあるはずですが、ランキングは変わってなかったので、どれが良いのかも判断することはできませんでした。(⇩)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/44176d60-81ef-598e-8ee4-d65e32b70355.png)



興味ある方：

今回のコンペについて

https://www.kaggle.com/competitions/llm-prompt-recovery
Skill Builder でAWS初心者が学べること

# はじめに

この記事では、AWS初心者としてSkill Builderを使ってAWSの学習を開始してから約9か月経った(記事公開時点)ので、これまでに受講してきたコースで受講してよかったと感じたものを紹介します。
※公開後もコースを随時追加していく予定です。

#### Skill Builder公式サイト
https://aws.amazon.com/jp/training/digital/

# これから学習を始める方向けのコース

## ***"[AWS Skill Builder Learner Guide](https://explore.skillbuilder.aws/learn/course/18443/AWS%2520Skill%2520Builder%2520Learner%2520Guide)"***
**対象者**
Skill Builderについて、
・基本的な使い方やtipsを知りたい
・ホームやマイコースなどの画面操作方法を知りたい
といった要望をお持ちの方など。

※英語版しか用意されていないです。

## ***"○○(サービス名) Primer (Japanese)"***
**対象者**
特定のサービスについて、
・基本的な内容やデモンストレーションを動画で学習したい
・確認テストで理解度を試したい
といった要望をお持ちの方など。

**コース例**
・[Amazon Elastic Block Store (Amazon EBS) Primer (Japanese)](https://explore.skillbuilder.aws/learn/course/9383/amazon-elastic-block-store-amazon-ebs-primer-japanese)
・[Amazon Elastic Container Service (ECS) Primer (Japanese) (VO) 日本語 AI 音声版](https://explore.skillbuilder.aws/learn/course/83/amazon-elastic-container-service-ecs-primer-japanese-vo-ri-ben-yu-ai-yin-sheng-ban)

一つ一つのコースは短い時間に収まっているので、まとまった時間が取れなくても手軽に受講いただける点も特徴です。


## ***"Introduction to ○○(サービス名) (Japanese)"***
**対象者**
Skill Builderの講義などを通して、AWSの各種サービスの概念や役割は理解できたけど
・実際に画面でどのように操作するかイメージできない
・手を動かしてさらに理解を深めたい
といった課題をお持ちの方など。

**コース例**
・[Introduction to Amazon EC2 (Japanese)](https://explore.skillbuilder.aws/learn/course/7506/introduction-to-amazon-ec2-japanese)
・[Introduction to AWS Identity and Access Management (IAM) (Japanese)](https://explore.skillbuilder.aws/learn/course/7487/introduction-to-aws-identity-and-access-management-iam-japanese )


# AWS認定資格に向けて準備したい方向けのコース

## ***"○○(トピック・サービス名など) - Knowledge Badge Readiness Path"***
**対象者**
Skill Builderを使ってAWSを学習するにあたって、
・特定のサービスだけじゃなく、「SAA試験関連」「サーバーレス」などの特定のトピックに紐づいたコースをまとめて受講したい
・「SAA試験関連」「サーバーレス」などの特定のトピックに紐づいたコースの全容がわからず、受講するコースやその順番が決められない
といった課題をお持ちの方など。

**コース例**
・[Compute - Knowledge Badge Readiness Path](https://explore.skillbuilder.aws/learn/learning_plan/view/1985/compute-knowledge-badge-readiness-path)
・[Solutions Architect - Knowledge Badge Readiness Path](https://explore.skillbuilder.aws/learn/lp/1044/Solutions%2520Architect%2520-%2520Knowledge%2520Badge%2520Readiness%2520Path)


## ***"○○(認定試験名) Official Practice Question Set (xx(認定試験コード) - Japanese)"***

折角Skill Builderでコースを受講しているので、AWSの認定試験に興味がある！そこで、
・受験準備として模擬試験を解きたい
もしくは、認定試験は受けるつもりがないが、
・自分の理解度を認定試験の問題で測りたい
といった要望をお持ちの方など。

**コース例**
・[AWS Certified Cloud Practitioner Official Practice Question Set (CLF-C02- Japanese)](https://explore.skillbuilder.aws/learn/course/internal/view/elearning/16792/aws-certified-cloud-practitioner-official-practice-question-set-clf-c02-japanese)
・[AWS Certified Solutions Architect – Associate Official Practice Question Set (SAA-C03 - Japanese)](https://explore.skillbuilder.aws/learn/course/internal/view/elearning/13269/aws-certified-solutions-architect-associate-official-practice-question-set-saa-c03-japanese)


# まとめ
この記事では、AWS初心者としてSkill Builderを使って学習するにあたって参考にしていただきたいコースについて、ご紹介しました。

ここで紹介したSkill Builderのコースでの学習を通じて、AWSの各種サービスの特徴や、ご自身が担当される業務におけるAWSサービスの役割・新たな活用方法などを理解し、AWS初心者がAWSプロフェッショナルに成長する後押しになれば、と思います。
Laravelのroute/web.phpの認証をroute/api.phpでも適用する

完全honaki用
悪しからず

## 困っていたこと
Laravel×VueでSPAなwebアプリを作成中に
Laravelの「route/web.php」で行うようなログインなどのユーザー認証をして、ユーザーIDを取得→該当登録者のみに表示などの機能を「route/api.php」でも同じような処理をしたかったが、
「route/api.php」でいつものように「route/web.php」で記載しているログイン系の処理を記載しても401エラーでユーザー情報の取得をできなかった。

## 解決方法
https://qiita.com/namazu777/items/787c7eb0798c6c3fd860

## 補足
⭐️の箇所の追記を必ず以下のコードより上にする。
そうしないと「Laravelのroute/web.phpの認証をroute/api.phpでも適用できない」
```
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
```
```app/Http/Kernel.php
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            // ⭐️追記:こいつら5個を絶対上にする
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            
            'throttle:60,1',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];
```

## 追記
コメントでいただきました通り他の方法があるみたいなので、参考程度にお願いします！
XR（クロスリアリティ）って何？！

# XR(クロスリアリティ)とは
AR(拡張現実),VR(仮想現実),MR(複合現実)などを包括的に表現する用語です。
英語表記に習い、エクステンデッド・リアリティとする場合もあります。

日本語wikiによるとXRのXを様々な技術を表す変数としてxRと表記する事もあるそうです。

# 参考記事

https://ja.wikipedia.org/wiki/%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%86%E3%83%B3%E3%83%87%E3%83%83%E3%83%89%E3%83%BB%E3%83%AA%E3%82%A2%E3%83%AA%E3%83%86%E3%82%A3

https://en.wikipedia.org/wiki/Extended_reality

https://gamemo.confidence-media.jp/1299

https://time-space.kddi.com/ict-keywords/20180816/2406

https://en.wikipedia.org/wiki/Virtual_reality
postgresql transationの分離レベルについて

サーバー2台を用意。トランザクションの分離性について調べた。
ダーティリード、反復不能読取、ファントムリードについて。

# ダーティリード
```:S1
1.begin;
select * from tbl;
 id | count 
----+-------
  1 |    5
  2 |    8
3.update tbl set count=10 where id=2;
commit;
```

```:S2
2.begin;
4.select * from tbl;
 id | count 
----+-------
  1 |    5
  2 |    8
commit;
```
postgresqlではダーティリードが起こらなかった。つまり、commit前の変更結果がS2で見たときに反映されていなかった。これはpostgresql.confのtransaction_isolationがread_committedになっていたからである。
```
postgres=# show transaction_isolation;
 transaction_isolation 
-----------------------
 read committed
(1 row)
```
しかし、postgresqlではRead_uncommittedにしてもダーティリードが起きないようになっている。このことからpostgresqlの運用にあたり、commit仕切るまでのtransaction結果を他サーバーに見せることがなくなるので安心である。（更新途中のデータを閲覧してしまうとかがなくなる）


# 反復不能読取
```:S1
1.begin;
select * from tbl;
 id | count 
----+-------
  1 |    5
  2 |    8
3.update tbl set count=10 where id=2;
4.commit;
```

```:S2
2.begin;
5.select * from tbl;
 id | count 
----+-------
  1 |    5
  2 |    10
commit;
```
S1のcommit後に確認すると、S2でset count=10 where id=2;の結果が見えてしまう。
ポイントはS1のcommit後というところ。DBを更新した後だから見えてしまうのも無理ないでしょという感じ。ただ、他サーバーから見ると実行結果が変わったように映ってしまう。更新前の結果を使って、他サーバーで処理させていた場合ミスが生じる可能性もあるのでそういったときはRepeatable readやSerialzableに設定し、分離性を上げることが賢明。

# ファントムリード
反復不能読み取りのinsert版。
```:S1
1.begin;
3.select * from tbl;
 id | count 
----+-------
  1 |    5
  2 |    10
5. insert into tbl values(3,100);
6. commit;
```

```:S2
2.begin;
4. select * from tbl;
 id | count 
----+-------
  1 |    5
  2 |    10
7. select * from tbl;
 id | count 
----+-------
  1 |    5
  2 |    10
  3 |    100
8. commit;
```
S1のinsert→commitのあとにS2でtblを見てみるという流れ。
S2からすると同じコマンドを打っているのに行が追加されたように感じてしまう。反復不能読取と同様更新前の結果を使って処理してる場合は注意が必要。対処法はこちらも同様文れレベルをあげることである。

# 直列化異常
反復不能読み取り（commitが実行されるまで変更を受け付けない）のために起きてしまう。ファントムリードと原理は同じ。
```:S1
1.begin;
2.select * from tbl;
 id | count 
----+-------
  1 |     5
  2 |    10
  1 |    12
  3 |   100
(4 rows)
3. insert into tbl select 1,sum(count) from tbl where id=2;
4. select * from tbl;
 id | count 
----+-------
  1 |     5
  2 |    10
  1 |    12
  3 |   100
  1 |    10
6. commit;
```

```:S2
2.begin;
5. select * from tbl;
 id | count 
----+-------
  1 |     5
  2 |    10
  1 |    12
  3 |   100
(4 rows)
6. insert into tbl select 1,sum(count) from tbl where id=1;
7. select * from tbl;
 id | count 
----+-------
  1 |     5
  2 |    10
  1 |    12
  3 |   100
  1 |    17
8. commit;
```
S1 の４番とS2の７番を見れば明らか。結果が反映されず別々でinsertされている。同時編集をすることで多大なビジネス的な問題が起こるのであればtransaction_isolationをSerializableに設定するのが良い。

# まとめ
４つのトランザクション設定における影響を説明した。
分離レベルは
Read_uncommited Read_committed Repeatable_read Serializableというように大きくなるとDBのパフォーマンスに影響するので一概に分離レベルがMaxがいいというわけではない。個人的に小規模開発、小規模利用なら分離レベルはMAXでもいいと思うが、大規模になるとロックする必要が出てきたりはすると思う。
Flutter 〜Containerの基礎の基礎〜

●Containerとは
透明の箱のウィジェット。色、サイズ、childの位置を指定することが可能。
コンテナの中にコンテナを入れることも可能。

●サンプル
黄色い100x100のサイズのコンテナの中に黒色の10x10のコンテナを入れる。

```dart
// FlutterのMaterialデザインライブラリをインポート
import 'package:flutter/material.dart';

// メイン関数: Flutterアプリケーションのエントリーポイント
void main() {
  // 中心に配置された黒色の小さいコンテナウィジェットを作成
  final con = Center(
      child: Container(
    color: Colors.black, // コンテナの背景色を黒に設定
    width: 10, // コンテナの幅を10に設定
    height: 10, // コンテナの高さを10に設定
  ));
  // 黒色のコンテナを子に持つ、大きいamber色のコンテナウィジェットを作成
  final con2 = Container(
    color: Colors.amber, // コンテナの背景色をamberに設定
    width: 100, // コンテナの幅を100に設定
    height: 100, // コンテナの高さを100に設定
    child: con, // 上で定義した小さい黒色のコンテナを子ウィジェットとして設定
  );

  // アプリケーションのルートウィジェットを定義
  final a = MaterialApp(
    home: Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min, // 列の主軸サイズを最小限に設定
          children: [
            const Text('test1'), // 最初のテキストウィジェット
            con2, // 上で定義したamber色のコンテナウィジェット
            const Text('test2'), // 二番目のテキストウィジェット
          ],
        ),
      ),
    ),
  );
  // runApp関数により、作成したウィジェットツリーをアプリケーションとして実行
  runApp(a);
}

```

●実行結果1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/164325f4-f59d-3c04-02d6-c4c6f4992599.png)

●位置の指定
パラメーターalignmentでchildに指定するウィジェットの位置を指定可能。
サンプルとしてAlignment.bottomCenterを指定して下側の中央に黒色コンテナを表示する。

●サンプル
```dart
import 'package:flutter/material.dart';

void main() {
  final con = Container(
    color: Colors.black,
    width: 10,
    height: 10,
  );
  final con2 = Container(
    color: Colors.amber,
    width: 100,
    height: 100,
    alignment: Alignment.bottomCenter,//下側の中央に表示
    child: con,
  );

  final a = MaterialApp(
    home: Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Text('test1'),
            con2,
            const Text('test2'),
          ],
        ),
      ),
    ),
  );
  runApp(a);
}

```

●実行結果2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3743467/f90a089f-254e-00af-5610-b1d97a75c6d1.png)
[初心者向け]1年でホワイトハッカーになる方法

はじめに
-
これからセキュリティ業界で働きたい人向けに書きます。
私も初心者です。一緒に頑張りましょう！！！

ハッカーになる一般的な手順
-
**1.プログラミングの方法を学ぶ**
-
プログラミングの概念を理解することが大切です。何がどのように設計されたかを理解できれば、脆弱性がどこにあるかがわかります。以下の言語を、皆さんが学ぶべきだと思う順番にランク付けしてみました。


* **HTML**：ハッキングには直接適用できませんが、ウェブが何の上に成り立っているかの基本を教えてくれるので、エラーに対する大きな耐性を持ち、素早く目に見えるものを作りたい人にとっては、入門言語として最適です。これらのWebページを輝かせるために、CSSを追加するのが最適です。  

<br>
  
* **PHP**：PHPを使用すると、Webアプリケーションを退屈な静的Webサイトから、バックエンド主導のおしゃれな主力製品に変えることができます。データなどを保存するための便利なアプリケーションを作成できるようになります。この言語の欠点は、ASPX などの厳密な言語では許可されないいくつかのことが許可されることです。しかし、PHP アプリケーションを簡単にデプロイでき、エラー許容度がもう少し向上するという事実を考えると、大きな利点です。

<br>

* **Python**：Pythonは、ハッカーがピンチで簡単なスクリプトを作成するために使用できる汎用言語です。Pythonはマルチプラットフォームであるため、Pythonをサポートするすべてのオペレーティングシステムで実行されますが、Javaなどの他のかさばる言語とは異なり、はるかに手軽に実行できます。また、エンドユーザーにとってはそれほど厳格ではありませんが、その設計によってコードをクリーンで読みやすいものにすることを余儀なくされます。

<br>

**2.Linuxの実行方法と使用方法を学ぶ**
-
人気のあるツールの多くはUnixベースのシステム上に構築されているため、Linuxはハッキングに非常に不可欠であるため、多くのハッカーはそのオープンな性質とカスタマイズ性のためにUnixに固執しているため、その恐れを乗り越えてください。Windowsシステムでハックすることはできますが、ほとんどのチュートリアルや一般的なツールはUnix用に書かれているため、最初は少し難しいでしょう。
**まずはTry Hack Me のLinux Fundamentalsを完了させましょう。**
[Try Hack Me Linux Fundamentals](https://tryhackme.com/module/linux-fundamentals)

<br>

**3. ネットワーキングの基本を学ぶ**
-
ネットワーク内で何が起こっているかを知ることは非常に重要です。最終的には、このトラフィックを解釈して慎重に分析する方法を学ぶ必要があるため、パケットが 1 台のコンピューターから別のコンピューターにどのように送信されるかを学ぶ必要があります。これが、このスキルを早期に開始することが本当に報われる理由です。自宅で独自のワイヤレスネットワークを設定する方法を学ぶなどの基本的なことから始めることを強くお勧めします。これは基本だけでなく、ワイヤレスアクセスポイントのインストールに固執する必要はありませんが、ファイアウォール設定やポートフォワーディングなどを試してみることができます。慣れてきたら、他のネットワークの分析を開始します。
**まずはTry Hack Me のNetwork Exploitation Basicsを完了させましょう。**
[Try Hack Me Network Exploitation Basics](https://tryhackme.com/module/intro-to-networking)

<br>

**4. Webアプリケーションのハッキングを学ぶ**
-
Webアプリケーションのハッキングは狭い分野のように思えるかもしれませんが、多くの選択肢につながる可能性があります。バグバウンティハンティングで他のハッカーに対して運とスキルレベルを試すか、侵入テストなどのより安定した仕事に就くことができます。Webアプリケーションのハッキングの優れた点は、ビジネスロジックの欠陥などの非常に機能的なエクスプロイトと、安全でないデシリアライゼーションなどの非常に技術的なエクスプロイト、およびその間のあらゆるものに侵入できることです。
**まずはTry Hack Me のWeb Hacking Fundamentalsを完了させましょう。**
[Try Hack Me Web Hacking Fundamentals](https://tryhackme.com/module/web-hacking-1)

<br>

**5.ネットワークハッキングを学ぶ**
-

ネットワークのハッキングは非常に技術的であり、この専門分野を追求すると、ペネトレーションテスターまたはシステムオペレーションセンター管理になり、基本的にネットワークを担当してインシデントを保護、管理、対応することができます。そのためには、シスコのCCNAなどの基本証明書を使用してネットワークエンジニアリングに集中する必要がありますが、セキュリティに重点を置くのではなく、一般的なネットワーク知識に重点を置きます。セキュリティ面では、hack-the-boxやvulnhubなどのサイトを試して、ハッキングスキルを練習してから、eJPTやOSCPなどのセキュリティ証明書を取得することができます。
**まずはTry Hack Me のJr Penetration Testerを完了させましょう。**
[Try Hack Me Jr Penetration Tester](https://tryhackme.com/paths)

<br>

**6.マルウェア分析を学ぶ**
-

マルウェアの分析は少し大変ですが、その見返りははるかに大きいです。ハッカーは、学習が中心的な役割を果たす、より専門的な仕事を期待できます。ここまで来るには、静的コード分析とアプリケーションの逆コンパイルにもっと焦点を当てる必要があります。
**まずはTry Hack Me のMAL: Malware Introductoryを完了させましょう。**
[Try Hack Me Malware Introductory](https://tryhackme.com/room/malmalintroductory)

<br>

結論
-
上記から、ハッキングとは何か、ハッカーになるために何が必要かについての洞察を与えることができたことを願っています。献身と努力があれば、この分野に参入することができます。始めるのに遅すぎることはなく、時間がかかるかもしれませんが、毎日一歩踏み出せば、1年でハッカーになることができます。
【Xcode】IDEPreferLogStreaming=YESへ環境変数を追加する方法

環境:Xcode15

Xcodeで実行した時、このようなメッセージに遭遇しました。

::: note alert
Logging Error: Failed to initialize logging system. Log messages may be missing. If this issue persists, try setting IDEPreferLogStreaming=YES in the active scheme actions environment variables.
:::

IDEPreferLogStreamingの設定手順を紹介します。

# 手順
1. メニューバーのProduct
2. Scheme
2. Edit Scheme
2. Run
2. Arguments
2. Environment Variable
2. +をクリック
2. Nameに「IDEPreferLogStreaming」と入力
2. Valueに「YES」と入力

これでエラーが出なくなりました。

# 参考
https://stackoverflow.com/questions/78129981/logging-error-failed-to-initialize-logging-system-log-messages-may-be-missing
[Apple]EUのデジタルサービス法(DSA)による「デジタルサービス法のコンプライアンス」の選択について

## はじめに
3月からApple　Store Connectに入るとアラート「デジタルサービス法に基づいて、アカウントに関する情報を提供および確認しなければなりません。これを怠ると、特定の国または地域において、支払いに遅れが生じたり、コンテンツが配信から削除されたりする場合があります」が表示されるようになリマした。

そのため対応方法を備忘録メモします。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109862/984a4248-1fe2-de96-3d13-36904dafcadf.png)

## デジタルサービス法（DSA）
2024年2月17日、DSA（Digital Services Act, デジタルサービス法）のEU加盟国内での全面適用が開始。

- 概要
```
• DSAはデジタル・サービス・パッケージの一部であり、デジタル・サービスを規制する必要性に対応するため、欧州委員会が2020年12月に提出
した立法構想である。
• DSAは、マーケットプレイス、ソーシャルネットワーク、コンテンツ共有プラットフォーム、アプリストア、オンライン旅行および宿泊プラットフォームなど
のオンライン仲介者およびプラットフォームを規制。
• 主な目的は、オンラインでの違法で有害な活動や偽情報の拡散防止。ユーザーの安全を確保し、基本的権利を保護し、公正でオープンなオ
ンラインプラットフォーム環境を構築する。
```
引用元(総務省)
https://www.soumu.go.jp/main_content/000932295.pdf

- つまり
オンラインの安全性と透明性を高めてユーザーと企業の責任を明確にすることを目的にした規制です。

## Appleは3月のどこかから対応して開発者に二択を迫っている

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109862/f3c57658-6fbb-9328-9da4-5790dcde962a.png)

```
デジタルサービス法のコンプライアンス
EU法に関して、トレーダーとノントレーダーのいずれの立場でコンテンツを配信するのかを指定してください
```

選択肢1
```
トレーダーのプロバイダアカウントです
EU法に従って、Appleはデベロッパアカウントに関連付けられた確認済みの住所や連絡先情報をApp Storeに公開します。
```
こちらは個人、法人ともに有料アプリ(EU含む)、アプリ内課金あり(EUを含む)を配信、または今後する予定がある場合はこちらを選択する必要がありそうです。

選択肢2
```
ノントレーダーのプロバイダアカウントです
EU法に従って、Appleはデベロッパアカウントに関連付けられた確認済みの住所や連絡先情報をApp Storeに公開しません。
```
こちらは個人、法人ともに有料アプリ（EU除く）、アプリ内課金あり(EU除く)、無料アプリ(EU含む場合もOK)の場合はこちらを選択すれば良さそうです。なので無料アプリであれば広告収入ありに問わずこちらでOK。

## 「トレーダーのプロバイダアカウントです」の場合
記載の通り、EUにのみ登録した住所や連絡先が公開されます。

トレーダーを選んだ場合に登録を促される情報（ここらが公開されそう）
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109862/82f8168c-7fde-8403-7830-0077873b3cce.png)
日本には関係ないので公開されない。がその気になれば日本からでも確認はできちゃいそう。
法人ならパブリックなので良いが個人の場合は少し懸念があるかな。

## どうするか
できることなら個人は特に「トレーダーのプロバイダアカウントです」を選択しない方が無難だと思います。（個人的になので情報公開に懸念がないのであれば良いですが。）EUに配信していてそこからの収益が大きい場合以外は「ノントレーダーのプロバイダアカウントです」を選択したほうがいいです。
そのため条件に合うように有料アプリ、アプリ内課金ありのアプリを配信している場合は全てのアプリをEUから外しましょう。
ヨーロッパを一括で外すチェックボックスがあるので楽です。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109862/0b35df8d-b971-87f4-6cb9-a60ffd4fcd10.png)
反映に2時間ほどかかるらしいので念の為待ちます。

そして、さいごに「ノントレーダーのプロバイダアカウントです」を選択する。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109862/06d02c65-fe08-4be0-5a7e-ab479fcba339.png)

そうすると問題ない旨のメッセージが表示されました。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109862/5a97baad-88e8-5d70-da0c-0057d2bddbcb.png)

## 変更は後からできるのか
今の所その項目が見つからないため（多分）できない？と思います。そのため選択を間違えないようにしましょう。

## さいごに
早めにやらないとアプリが削除されるリスクがあるため後回しにしないほうが良いでしょう。

何か間違えてる情報などあればコメントください
RJ45のトラブル

ケーブルの爪が折れることはよくあります。

![写真（2024-03-16 16.03）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/9c632f19-1bff-ab7a-72fb-bb7c50863de0.jpeg)

コネクタ側の引っ掛けも割れることがあります。

![写真（2024-03-16 16.02）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d18fcb0a-a9b4-7641-cf7c-21f91d5ab768.jpeg)

ワインのコルク栓を小さく切ってくさびにして押さえるようにしてみました。

![写真（2024-03-16 16.04）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/2b8e8881-ef76-5dcb-96bb-cdd48e6934c4.jpeg)
Swift Concurrencyの要 "Actor" を理解したい

## はじめに

Swift Concurrency使ってますか。非同期処理がスッキリ記述できて良いですよね。
そんな中なんとなくの理解でActorを使っていたのですが、この度理解を深められましたので、私が理解できていなかった部分ベースで解説したいと思います。


### Actorって何？

Swift Concurrencyの一部で排他的アクセスを保証するクラスです。
インスタンス化した際に特定のスレッドにバインドされ、そのスレッド以外からはアクセスできませんが、実行された関数は１つずつ順番に実行され排他制御されます。

### classとactorの違いとは

* class
  * インスタンスはどのスレッドからでもアクセス可能
  * 並列処理時にはロックなどで排他制御が必要
  * 継承可能
* actor
  * インスタンスは特定のスレッドにバインドされる
  * 内部のプロパティ、メソッドは排他アクセスが保証される
  * アクター間ではスレッドセーフが求められる
  * 継承不可だが、プロトコル準拠は可能

つまり従来は自前で対応が必要だった排他制御はactorを使えば簡単に実現できます。
ただactorはデメリットもあり、完全に排他制御を行うためパフォーマンスが落ちる可能性もあります。

### isolatedとnonisolatedって何？

actorのインスタンスメソッドに付けられる属性です。これはメソッドが並列処理の制御をどう扱うか決定します。

* isolated 
  * isolatedメソッドは、メソッド呼び出しごとに1つずつ処理が行われ、前の処理が完了するまで次の処理は実行されません。指定しない場合はこちらになります。
* nonisolated 
  * このメソッドには並列処理の制御が行われません。つまり同時に複数の呼び出しが実行可能です。nonisolatedメソッドはスレッドセーフにはなりません。

### プロトコルを使ったclassでisolatedの警告が出てしまう理由

以下のようにプロトコルに準拠させつつ、@MainActorを定義している場合以下の警告が出ます。

**Main actor-isolated instance method 'didSearchTextChange' cannot be used to satisfy nonisolated protocol requirement**

```swift
protocol SearchUsersPresenterInput {
    func didSearchTextChange(_ text: String)
}

@MainActor
class SearchUsersPresenter: SearchUsersPresenterInput {
    func didSearchTextChange(_ text: String) {
        省略
    }
}
```

理由としてはactorの特性で`継承不可だが、プロトコル準拠は可能`というものがありましたが、その都合でプロトコルも記載していないメソッドはisolatedになるわけです。
それをMainActorなclassで実装したので、スレッドセーフには使えませんよとなるわけです。

そのためクラスに準拠させるならプロトコル側でnonisolatedをつける必要があります。クラス側にも付けられますがactorで使わないならプロトコルにつけましょう。

```swift
protocol SearchUsersPresenterInput {
    nonisolated func didSearchTextChange(_ text: String)
}
```

## 最後に

何かしら役に立つものはあったでしょうか。
なんとなくでも動いてしまうのですが、頻繁に使うようなこういった技術はちゃんと理解して使うべきですね。読んでいただきありがとうございました。
UE5 陽炎ポストプロセスマテリアルを作成

# 概要
今回は砂漠や夏のアスファルトに出現する陽炎をポストプロセスで表現していきます。

# 実装

### ノイズテクスチャをスクロールさせる
スターターコンテンツにある「T_Perlin_Noise_M」を使用してノイズをV方向にスクロールさせます。
スクロールさせたノイズをUVに加算することで陽炎を表現していきます。
![Noise.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156053/fe073243-ab7a-7bda-910b-ffbf165088b1.jpeg)

### 指定の距離に陽炎を乗せる
そのままだと画面全体に陽炎が乗ってしまうので、深度テクスチャを用いて指定の距離にだけ陽炎が乗るように実装していきましょう。
![Depth.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156053/4699dd16-d041-db48-3804-564e98f94343.jpeg)

### マテリアル全体像
![Material.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156053/90df6854-14aa-717e-6ed5-8c18514d20a5.jpeg)


# 結果
![K.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156053/25eb8d5d-13a0-d98b-ade3-22b731659796.gif)

# まとめ
ゲーム空間が熱く感じますね。
TypeScript Webアプリケーションの構築コンポーネント

> 💡 主題：このTypeScriptシリーズブログを続けます。今度は、どうやってTypeScriptを使って、コンポーネントは開発を紹介します。このブログで、TypeScriptの「クラス」と「インターフェース」について学び、そして、簡単な商品リストのコンポーネントを作成します。
- [1 クラス](#クラス)
    - [1.1 クラスの定義とインスタンス化](#クラスの定義とインスタンス化)
    - [1.2 コンストラクタ](#コンストラクタ)
    - [1.3 属性とメソッド](#属性とメソッド)
- [2 クラスの特性](#クラスの特性)
    - [2.1 abstractキーワード](#abstractキーワード)
    - [2.2 インターフェイス](#インターフェイス)
    - [2.3 継承](#継承)

# クラス
## クラスの定義とインスタンス化
TypeScriptでのクラスは、`class`キーワードを使って定義されます。例えば、以下の通り、Productを定義します。
```TypeScript
class Product {
}
```

## コンストラクタ

コンストラクタは、インスタンスが作成されるときに自動的に呼び出される特別な関数です。`constructor`キーワードを使用して定義され、クラスの属性を初期化するために使用されます。

```TypeScript
class Product {
        constructor(public id: number, public name: string, public price: number) {}

}
```
## 属性とメソッド
属性とメソッドは、クラス内で直接定義されます。属性には、クラスのインスタンス変数や定数を定義し、メソッドには、クラスの振る舞いや機能を定義します。

```TypeScript
class Product {
    constructor(public id: number, public name: string, public price: number) {}

    display(): string {
        return `${this.name}: $${this.price}`;
    }
}

```
# クラスの特性
## abstractキーワード
### 抽象クラス：
インスタンス化できないクラスで、通常は他のクラスの基底クラスとして機能します。`abstract`キーワードを使用してマークされます。

### 抽象メソッド：
クラス内で宣言されるが実装されないメソッドです。抽象クラス内の抽象メソッドは、派生クラスで実装されなければなりません。
```TypeScript
abstract class AbstractDataSource {
    constructor(public name: string) {}

    getProducts(): Products[] {
        return Promise.resolve([
            { "id": 1, name: "P1", category: "Watersports",
                description: "P1 (Watersports)", price: 3 },
            { "id": 2, name: "P2", category: "Watersports",
                description: "P2 (Watersports)", price: 4 }
        ])
    }

    abstract storeOrder(): Promise<number>;
}
```

## インターフェイス
インターフェイスは、実装を提供せずにオブジェクトの構造や型シグネチャを定義するために主に使用されます。それはオブジェクトが従うべき規格を定義し、そのインターフェースを実装するクラスが同じ構造に従うことを保証します。
```TypeScript
interface Movable {
    move(): void;
}

class Car implements Movable {
    move() {
        console.log("Car is moving");
    }
}
```
## 継承
継承は、あるクラスが別のクラスの属性やメソッドを継承することを可能にします。継承を実現するためには`extends`キーワードを使用します。

先に定義した抽象クラス`DataSource`、現在はファイルに保存しているデータを使う`LoadDataSource`を作成します。そして、抽象クラスを継承し、抽象メソッドを実装されます。
```TypeScript
import { AbstractDataSource } from "./abstractDataSource";
import { Product } from "./entities";

export class LoadDataSource extends AbstractDataSource {

    storeOrder(): Promise<number> {
        console.log("Store Order");
        console.log(JSON.stringify(this.order));
        return Promise.resolve(1);
    }
    
}
```
一つのゲームオブジェクトで複数トリガーの通知を分別したい

「MonoBehaviourのOnTriggerEnterだと二つのどちらのトリガーから通知されているのか分別することが基本的にできないよね？」

「UniRxの(collider).OnTriggerEnterAsObservable()で別々に監視できなかったっけ？」

という会話があったので検証メモ。

# 検証
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520042/be03d969-1b9a-a150-4621-083515e7b825.png)

**できないらしい...**

ソースを読む感じ、コライダーがついてるコンポーネントのOnTriggerEnterを監視しているみたい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520042/a16d9434-69ef-a48d-f1af-5e674a4dd48c.png)

2*2の計4回通知が呼ばれちゃってる。

``` csharp:TriggerTest
    [SerializeField] private Collider _collider1;
    [SerializeField] private Collider _collider2;

    private void Awake()
    {
        _collider1.OnTriggerEnterAsObservable().Subscribe(_ => Debug.Log("collider1にぶつかった"));
        _collider2.OnTriggerEnterAsObservable().Subscribe(_ => Debug.Log("collider2にぶつかった"));
    }

    private void OnTriggerEnter(Collider other)
    {
        Debug.Log("なにかにぶつかってる");
    }
```
### 対処法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520042/fec92f56-2043-f981-57c7-44692c237d29.png)

**それぞれトリガーをのゲームオブジェクトを子に持てばok**
(コードは同じ)

UnityのOnTriggerEnterは子オブジェクトのトリガーにも反応しちゃうのね..
「お父さん、Cookieとセッションってなにがちがうの？」

## 突然の質問
小学1年生の子供に、「お父さん、Cookieとセッションってなにがちがうの？」と聞かれたらどうしますか？
小学1年生にも分かりやすく教えてあげられますか？

僕はできません。（子供もいません。）<br>
そもそも駆け出しなので、違いを明確に言語化できる自信がありません。

誰にでも説明できる状態まで理解すべし！ってよく言われますよね。
「小学1年生が理解できるまで」とはいかないかもですが、駆け出しエンジニアくらいにはスッと入ってくるように言語化してみようと思います。
<br>

## それでは説明！
一言で言うと、
「Cookieはブラウザ側に保存されてるけど、セッションはサーバー側で管理しているんだよ～」です。

小学生がイメージしやすいように言い換えると、
「Cookieはみんなに配られるものだけど、セッションは職員室にあって、その鍵を持った人しか開けられない箱なんだよ～」
ですかね。

さらに補足すると、
「セッションの鍵にはよくCookieが使われるんだよ～」
ともいえる気がします。
<br>
要するに、値を保存している場所が違うのです。

CookieはChromeやEdgeなどのブラウザ（クライアント側）に保存されますが、セッションはサーバー側で管理されるものです。
（クライアント..？サーバー..？ってなった人は[こちら](https://wa3.i-3-i.info/word12356.html)を見ると分かりやすいかもしれません）

他にも保存期間など違いはあるのですが、一番大きな違いはここだと思っています。

### おわりに
とはいっても自分自身まだまだひよっこなので、興味がある人はちゃんと調べましょう！


## 参考
https://qiita.com/sasamuku/items/ca23cd4b15a46bf18ce7

https://www.engilaboo.com/definitely-understand-cookie-session/