OmniAICreator/Qiita-1.07M huggingface dataset:
Makefile relink について

この記事を読んだ後の姿: リリンクしないMakefileの書き方を実装できて、人に説明することができる。人と一緒に解決することが出来る。

対象読者: なんとなくMakefileは書ける。動く仕組みは分からない。リリンクしてしまった時に、回消する為の思考プロセスが理解できない。

## そもそもMakeとは

Makefile の目的はこちらを読んで欲しい

https://www.gnu.org/software/make/

まとめると
1. Makeは、プログラムのソースファイルから実行ファイルやその他の非ソースファイルの生成を制御するツール
2. Make を使えば、エンドユーザはどのようにビルドやインストールが行われるかの詳細を知らなくても、あなたのパッケージをビルドしてインストールすることができます -1. なぜなら、これらの詳細はあなたが提供する makefile に記録されているから
3. Make は、どのソースファイルが変更されたかに基づいて、 どのファイルを更新する必要があるかを自動的に判断します。また、ある非ソースファイルが別の非ソースファイルに依存している場合に備えて、ファイルを更新する適切な順序も自動的に決定する
4. その結果、いくつかのソースファイルを変更してから Make を実行しても、プログラムのすべてを再コンパイルする必要はありません。変更したソースファイルに直接または間接的に依存している非ソースファイルのみを更新します

とある。
このうち、3, 4の要素に関わるのが リリンクである。
リリンクというとリンク処理のことだけを指しているが、要は解決されたターゲットを再生成しようとビルド処理するのが無駄だということだ。
リリンクしないように注意する点を紹介する

そもそもMake は、Makeにある
target: source
の依存関係を参照し解決する。
解決の仕方は、そのtarget やsource のタイムスタンプの比較によって行われる。

実行は以下の流れで行われる
1. 実行されたtarget の source をtargetに make を実行する
2.
  a. target が存在しない, あるいは source が target より新しい場合、コマンドを実行する
  b. source が target より古い場合、何もしない

1 のステップの時点で再起的に実行されているのがわかるだろうか。

relink は target と source の設定が間違っていることで発生する。

## 例

### コマンドがターゲットを生成しないケース
```
target: source
    echo "hello"
```
これでは、target が生成されないため、コマンドが毎回実行される
また、上は分かりやすいが

```
target: source
    gcc -o target.out source.c
```
このような場合も、厳密には target名と生成されるファイル名が一致していないために コマンドが毎回実行されてしまう

対策としては
- $@ を使う
- make の変数を利用する

```
target: source
    gcc -o $@ $^
```
$@ はコマンドのターゲット名を表すのでコーディングミスを防ぐことができる

```
TARGET = target

$(TARGET): source
    gcc -o $(TARGET) source.c
```

このように、するのも良いだろう。2つの解決策を利用すると、生成するファイル名を変更したい場合に、編集箇所が1箇所になる。
Single Source of Truth　の考え方は、どのような場面でも有効である。

### source が存在しないケース
```
target: source
    gcc -o $@ 

source:
    echo "hello"
```

この場合、source が存在しないため、source のルールが毎回実行され、target のルールも毎回実行される
また、複数のmakefile で管理されているプロジェクトでは

```
target: source
    gcc -o $@ source

source:
    make -C ./source
```

といった記述があるかもしれない。
make -C で実行したスクリプトではちゃんと "source" という名前のファイルが生成されている場合でも、リリンクは発生する。
なぜなら、カレントディレクトリに "source" というファイルが存在しないためである。

対策としては
- source にディレクトリ名を含める
- source を生成後、moveしてカレントディレクトリに移動する

```
source = ./source/source

target: $(source)
    gcc -o $@ $^

$(source):
    make -C ./source
```

```
source = source
source_dir = ./source

target: $(source)
    gcc -o $@ $^

$(source):
    make -C $(source_dir)
    mv $(source_dir)/$(source) .
```

など。

## まとめ
リリンクを防ぐためには、ターゲット名と生成されるファイル名が一致しているかを確認することが重要である。
細かいところ間違ってるかもしれないが、ベースがあれば知識を繋いだり繋げ直したりすることが出来る。一回理解するのは大事。結局問題を解決できればいい。
TypeScriptの実行環境をDockerで作る

## はじめに

Typescriptの勉強を始めたので、まずは実行環境を作りました。

nodejsの環境を作るだけですが、どなたかの参考になれば幸いです。

## やりたいこと

Typescriptの実行環境を作りたい

## 方法
Dockerfileでコンテナを起動



## Dockerfileの中身
NODE_VERでバージョン指定できます

```
ARG NODE_VER=20.10.0
FROM node:${NODE_VER}

WORKDIR /usr/src/app

# コンテナ内で必要パッケージを追加
RUN npm install -g typescript ts-node ts-node-dev

 ```

 ## docker-compose.ymlの中身

```
ARG NODE_VER=20.10.0
FROM node:${NODE_VER}

WORKDIR /usr/src/app

# コンテナ内で必要パッケージを追加
RUN npm install -g typescript ts-node ts-node-dev
```



## buildしてコンテナの中に入る
```
docker-compose up -d --build
docker-compose exec node-dev /bin/bash
```

## コンパイルと実行
```
tsc --strictNullchecks sayHello.ts
node sayHello.js
```


### ソースコード
・[github](https://github.com/mtamura0422/typescript/tree/main)
PythonでCSVをPDFに変換する

CSVファイルは、通常、大量のデータを保存するために使用され、PDFファイルは、他の人と共有し、印刷しやすいユニバーサルドキュメントフォーマットです。CSVファイルをPDFファイルに変換することで、データをよりよく管理し、提示することができます。この記事では、Pythonプログラミングを通じてCSVファイルをPDFファイルにエクスポートする方法を紹介します。

## Pythonエクセルライブラリの紹介とインストール
Pythonでは、我々はCSVからPDFへの迅速な変換を達成するためにサードパーティ製のライブラリ[**Spire.XLS for Python**](https://www.e-iceblue.com/Introduce/xls-for-python.html)を使用することができます。このライブラリは、Excelファイルの作成、読み取り、編集、変換などに使用することができますシンプルで便利なExcel操作インターフェイスの様々な提供しています。

変換のためのスクリプトを書く前に、次のpipコマンドを使用してSpire.XLS for Pythonライブラリをインストールする必要があります。
> pip install Spire.Xls


## Python - CSVをPDFに変換する
>**主なステップ:**

1\. **`Workbook`** オブジェクトを作成します。
2\. **`LoadFromFile(`** メソッドを使用して、CSVファイルをExcelワークブックにロードします。
3\. **`Workbook.ConverterSetting.SheetFitToPage`** プロパティを通して、ワークシートのページへのフィットを設定し、ワークシートデータが1つのPDFページにレンダリングされるようにします。
4\.	最初のワークシートを取得し、その各列を繰り返し処理し、オートフィット列幅を設定します。
5\.	読み込んだCSVファイルを、**`SaveToFile()`** メソッドを使ってPDFとして保存します。


>**Pythonコード：**
```csharp
from spire.xls import *
from spire.xls.common import *
 
# CSVファイルを読み込む
workbook = Workbook()
workbook.LoadFromFile("sample.csv", ",", 1, 1)
 
# ワークシートをページに合わせる
workbook.ConverterSetting.SheetFitToPage = True
 
# 最初のワークシートの取得
sheet = workbook.Worksheets[0]
 
# 列幅の自動調整
i = 1
while i < sheet.Columns.Length:
    sheet.AutoFitColumn(i)
    i += 1
 
# CSVファイルをPDFに変換する
workbook.SaveToFile("CSVtoPDF.pdf", FileFormat.PDF)
workbook.Dispose()
```

上記のコードによって、CSVデータを読みやすく共有しやすいPDFファイルに変換することができます。出力結果を以下に示します：
![CSV-PDF日.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/8dc31dd7-798f-b277-fdbc-b6639e2afa30.png)

* * *

**ウォーターマークを削除するには、クリックしてください：**

https://www.e-iceblue.com/TemLicense.html
React✖️TypeScript

# React✖️TypeScript
## TypeScriptとは
- JavaScriptに型の概念を追加したもの
- 型の概念があるため、下記のメリットがある
  - 安全にコードを書ける
  - 用語の補完や関数定義のジャンプなどができ、開発効率も上がる
  - 他の人が書いたコードが理解しやすい
- npm, babel, webpackなどとの親和性が高い
- Reactとの相性も非常に良い

## 基本的な型指定
- boolean
`let bool: boolean = true;`
- number
`let num: number = 0;`
- string
`let srt: string = "string";`
- Array
`let arr1: Array<number> = [0, 1, 2];`
`let arr2: number[] = [0, 1, 2];`

- any
`let any1: any = false;`
  - なるべく使わない

- void
``` ts
const funcA = (): void => {
  const test = "TEST";
}
```
- null
`let null1: null  = null;`

- undefined
`let undefined1: undefined = undefined;`

- object
``` ts
let obj1: { id: number, name: string} = {id: 1, name: "Name"};
```

## 型指定方法
### 変数の型指定
- 変数名の後にコロン(:)と型名を追加する
- 例
``` ts
let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";
```

### 関数の引数の型指定
- パラメータ名の後にコロン(:)と型名を追加する
- 例
``` ts
function greet(name: string) {
    console.log("Hello, " + name);
}
```

### 関数の返却値の型指定
- 引数リストの後の括弧(())の後にコロンと型名を追加する
- 例
``` ts
function getFavoriteNumber(): number {
    return 26;
}
```

## tsconfigについて
- TypeScriptプロジェクトのルートディレクトリに配置されるファイル
- このファイルによって下記などの様々な設定を行える
  - どのファイルをコンパイルするか
  - どのファイルを無視するか
  - コンパイラが適用すべき様々な設定
ChatGPT-3.5先生へ「sympyでsin(t)をcos(2t)を使って表現して下さい。」を聞きました。

**パイソニスタの方へ**
・ChatGPT-3.5先生へ。どのような聞き方がおすすめですか。

# ChatGPT-3.5先生へ

***●user***
```
sympyでsin(t)をcos(2t)を使って表現して下さい。
```

***ChatGPT-3.5***
```python
import sympy as sp

# 変数 t を定義
t = sp.symbols('t')

# sin(t) を cos(2t) を使って表現
expr_cos = sp.sqrt((1 - sp.cos(2*t)) / 2)

# 結果を表示
print(expr_cos)
```

# 以下、私が修正しました。 
```python
# sympyでsin(t)をcos(2t)を使って表現
from sympy import *
t = symbols('t')
print("#",sqrt((1 - cos(2*t)) / 2))
# sqrt(1/2 - cos(2*t)/2)
```

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

・以下ができたら、助かります。指定と全部です

https://qiita.com/mrrclb48z/items/555d85face87552c34fb

https://qiita.com/mrrclb48z/items/5f57eac92aaca30e85c0

# いつもと違うおすすめです。
Githubチートシート


# GitHub チートシート

## リポジトリ操作
- **新しいリポジトリを作成**: GitHubの「New」ボタンをクリックして新規リポジトリを作成
- **リポジトリをクローン**: `git clone [https://github.com/ユーザー名/リポジトリ名.git]`
- **ローカルリポジトリをGitHubにプッシュ**:
  - `git remote add origin [https://github.com/ユーザー名/リポジトリ名.git]`
  - `git push -u origin master`

## コラボレーション
- **フォーク (Fork)**: 他のリポジトリを自分のアカウントにコピーして作業を開始
- **プルリクエスト (Pull Request)**: 自分のリポジトリの変更を元のリポジトリに提案する
- **プルリクエストの作成**: GitHubのウェブインターフェースでプルリクエストを提出
- **プルリクエストのマージ**: プルリクエストの変更をレビューして統合する
- **プルリクエストのレビュー**: プルリクエストに対してコメントや変更依頼を行う
- **イシュー (Issue)**: バグや機能追加の提案などを追跡するためのツール
- **イシューの作成**: 「Issues」タブから「New Issue」ボタンをクリックして新しいイシューを作成

## GitHub Actions
- **GitHub Actionsの設定**: `.github/workflows/`ディレクトリにYAMLファイルを追加してCI/CDを設定
- **ワークフローのトリガー**: コミットやプルリクエストに応じてCI/CDパイプラインを自動実行
- **ステータスバッジの追加**: プロジェクトのREADMEにワークフローのステータスバッジを表示

## GitHub Pages
- **GitHub Pagesの設定**: 「Settings」 > 「Pages」でGitHub Pagesを有効化
- **静的サイトのデプロイ**: GitHub Pagesを使って静的ウェブサイトをホスティング
- **カスタムドメインの設定**: `CNAME`ファイルを追加して独自ドメインを設定

## トラブルシューティング
- **リポジトリの削除**: 「Settings」タブの「Danger Zone」からリポジトリを削除
- **SSHキーの設定**: GitHubにSSHキーを追加してセキュアな認証を実行
- **アクセス権の管理**: リポジトリの「Settings」からコラボレーターを追加・削除

## チームコラボレーション
- **チームの作成**: GitHub Organizationsでチームを作成してアクセス権を管理
- **ブランチ保護ルールの設定**: 「Settings」 > 「Branches」でプルリクエストのルールを強制するブランチ保護を設定

## GitHub CLI
- **GitHub CLIのインストール**: `brew install gh` などでGitHub CLIをインストール
- **リポジトリの作成**: `gh repo create [name]`
- **プルリクエストの作成**: `gh pr create --title "PRタイトル" --body "説明"`
- **イシューの作成**: `gh issue create --title "イシュータイトル" --body "説明"`
- **ワークフローの実行**: `gh workflow run [workflow-name]`

## その他便利な操作
- **リリースの作成**: 「Releases」タブから新しいリリースを作成し、タグやリリースノートを追加
- **タグ付けとリリース**:
  - `git tag [version]`
  - `git push origin [version]`
- **プロジェクトボード**: 「Projects」タブからプロジェクトボードを作成してタスク管理を行う
Gitチートシート


# Git チートシート
### 自分用にGitのチートシートを作成しました。共有します。

## リポジトリ操作
- `git init`: 新しいGitリポジトリを初期化する
- `git clone [url]`: リモートリポジトリをクローン（複製）する
- `git remote add origin [url]`: リモートリポジトリを追加する
- `git remote -v`: リモートリポジトリの情報を表示する

## コミット関連操作
- `git add [file]`: ファイルをステージング（コミット対象に追加）する
- `git add .`: すべての変更をステージングする
- `git commit -m "[message]"`: ステージングされた変更をメッセージ付きでコミットする
- `git commit --amend -m "[message]"`: 最後のコミットを修正して新しいメッセージを追加する
- `git log`: コミット履歴を表示する

## ブランチ操作
- `git branch`: ローカルブランチの一覧を表示する
- `git branch [branch-name]`: 新しいブランチを作成する
- `git checkout [branch-name]`: 指定したブランチに切り替える
- `git checkout -b [branch-name]`: 新しいブランチを作成してそのブランチに切り替える
- `git merge [branch-name]`: 現在のブランチに指定したブランチをマージする
- `git branch -d [branch-name]`: ブランチを削除する

## リモートリポジトリ操作
- `git push origin [branch-name]`: リモートリポジトリにブランチをプッシュする
- `git pull origin [branch-name]`: リモートリポジトリから変更を取得してマージする
- `git fetch`: リモートリポジトリから変更を取得するが、マージはしない
- `git push origin --delete [branch-name]`: リモートリポジトリからブランチを削除する

## 状態確認・差分表示
- `git status`: 作業ディレクトリの状態を表示する
- `git diff`: 作業ディレクトリと最後のコミットの間の差分を表示する
- `git diff [branch-name]`: 現在のブランチと別のブランチの間の差分を表示する
- `git log --oneline`: 簡潔なコミット履歴を表示する

## 変更の取り消し
- `git reset --hard [commit-hash]`: 指定したコミットまで履歴をリセットする
- `git reset [file]`: ステージングからファイルを除外する
- `git checkout -- [file]`: ファイルの変更を取り消す
- `git revert [commit-hash]`: 指定したコミットを取り消すための新しいコミットを作成する

## 便利なコマンド
- `git stash`: 変更を一時的に保存する
- `git stash pop`: 保存した変更を元に戻す
- `git tag [tag-name]`: タグを作成する
- `git log --graph --oneline`: 簡潔なコミット履歴をグラフ形式で表示する
Colaboratory上で pysparkを使用してDeltaフォーマットのデータを読み取るサンプル

Databricksの標準データ形式のDeltaフォーマットのデータをGoogle Colaboratory上で扱ってみたいと思います。
Azure EventhubsのデータについてはADLS gen2上のDeltaフォーマットで出力できるので、そちらで試しています。

## 1: pysparkのインストール

```
!pip install pyspark
```

### SparkSessionの設定

`io.delta.sql.DeltaSparkSessionExtension` とパッケージを設定

```python
from pyspark.sql import SparkSession

spark = (
  SparkSession.builder.appName("Delta on ADLS Gen2")
    .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension")
    .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog")
    .config("spark.jars.packages", "io.delta:delta-spark_2.12:3.1.0,org.apache.hadoop:hadoop-azure:3.3.4,org.apache.hadoop:hadoop-azure-datalake:3.3.4,com.microsoft.azure:azure-storage:7.0.1")
    .getOrCreate()
)
```

## 3: ADLS gen2用のアカウントキーを設定

キーの部分は変更してください。

```python
spark.conf.set(
  "fs.azure.account.key.eventhubsteststoragegen2.dfs.core.windows.net",
  "AbCdEfGhiJkLmNoPqRsT/uVwXyZaBcDe+FgH1a2b3c="
)
```

## 4: Deltaフォーマットで読み込み

ADLS gen2のコンテナ名とテーブル名は適宜指定してください。

```python
df = spark.read.format("delta").load(
  "abfss://eventhubs-container-name@eventhubsteststoragegen2.dfs.core.windows.net/test-eventhub-gen2"
)
```

## 5: データフレーム表示

```python
display(df)
```

以下の感じで表示されます。

```
+---+---------------------+-----------+--------------------+
|aaa|EventProcessedUtcTime|PartitionId|EventEnqueuedUtcTime|
+---+---------------------+-----------+--------------------+
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
|ccc| 2024-09-21 13:03:...|          0|2024-09-21 13:03:...|
+---+---------------------+-----------+--------------------+
```

## まとめ

Colaboratory上で pysparkを使用してDeltaフォーマットのデータを読み取る方法を記載しました。
Dockerfileチートシート!

# Dockerfile Cheat Sheet
### 自分用にdockerのチートシートを作成したので共有します。

## 基本コマンド

### `FROM`
ベースとなるDockerイメージを指定します。
```dockerfile
FROM ubuntu:20.04
```

### `COPY`
ホストのファイルやディレクトリをコンテナ内にコピーします。
```dockerfile
COPY ./localfile /app/containerfile
```

### `ADD`
`COPY`に似ていますが、圧縮ファイルの解凍やURLからのダウンロードもサポートします。
```dockerfile
ADD ./localfile.tar.gz /app/
```

### `RUN`
コンテナ内でコマンドを実行します。通常、ソフトウェアのインストールに使用します。
```dockerfile
RUN apt-get update && apt-get install -y python3
```

### `CMD`
コンテナが実行される際にデフォルトで実行されるコマンドを指定します。`ENTRYPOINT`との違いは上書きできることです。
```dockerfile
CMD ["python3", "app.py"]
```

### `ENTRYPOINT`
コンテナの実行時に必ず実行されるコマンドを指定します。通常は、引数を渡すときに使います。
```dockerfile
ENTRYPOINT ["python3", "app.py"]
```

### `WORKDIR`
コンテナ内の作業ディレクトリを指定します。
```dockerfile
WORKDIR /app
```

### `ENV`
環境変数を設定します。
```dockerfile
ENV APP_ENV=production
```

### `EXPOSE`
コンテナがリッスンするポートを指定します。これにより外部に公開できます。
```dockerfile
EXPOSE 8080
```

### `USER`
コマンドの実行時に使用するユーザーを指定します。
```dockerfile
USER appuser
```

### `VOLUME`
ホストとコンテナの間でディレクトリをマウントします。データの永続化に使用されます。
```dockerfile
VOLUME ["/data"]
```

### `ARG`
ビルド時に渡す引数を定義します。
```dockerfile
ARG APP_VERSION
RUN echo "Version: $APP_VERSION"
```

---

## 最終例

```dockerfile
# ベースイメージの指定
FROM node:14

# 作業ディレクトリの設定
WORKDIR /app

# 依存関係のインストール
COPY package*.json ./
RUN npm install

# アプリケーションのコピー
COPY . .

# ポートの公開
EXPOSE 3000

# デフォルトで実行するコマンド
CMD ["npm", "start"]
```

---
[Python] バブルソート

# バブルソート
バブルソートとは、**すべての隣接する2つの要素の値を比較して、小さい方が前になるように交換していき、昇順に並べ替えるアルゴリズム**です。ただし、総当たりで繰り返し比較交換していくので、**データが大量にあると処理に時間がかかってしまいます**。たいていのプログラミング言語にはソートするための関数があるので、いちいちバブルソートを自分で書くことは少ないと思いますが、頭の体操？として書いてみます。
# 二重ループを使った書き方　その１
末尾から2つの値を比較するやり方で書いてみます。ちなみにPythonでは変数tmpを使わなくても書けますが、最初は変数tmpを使ってみます。
~~~Python:Bubble1.py
lis = [5, 1, 7, 8, 4, 2, 9, 0] # 元のリスト
n = len(lis) # リストの長さ（要素数）

for i in range(n - 1): # 調べる範囲の開始位置を１つずつ後ろへ移動していく
    for j in range(n - 1, i, -1): # 末尾から隣接する2つの値を比較
        if lis[j] < lis[j - 1]: # 隣接する2つの値の末尾側が小さかったら交換
            tmp = lis[j]
            lis[j] = lis[j - 1]
            lis[j - 1] = tmp

print(lis)
# 昇順にソートされたリストが出力されました！
# [0, 1, 2, 4, 5, 7, 8, 9]
~~~
# 二重ループを使った書き方　その２
もちろん先頭から比較していってもOKです。
面倒なので(笑)、今度は変数tmpを使わずに書いてみます。
~~~Python:Bubble2.py
lis = [5, 1, 7, 8, 4, 2, 9, 0] # 元のリスト
n = len(lis) # リストの長さ（要素数）

for i in range(n):
        for j in range(n - i - 1):
            if lis[j] > lis[j + 1] :
                lis[j], lis[j + 1] = lis[j + 1], lis[j]

print(lis)
# 昇順にソートされたリストが出力されました！
# [0, 1, 2, 4, 5, 7, 8, 9]
~~~
# whileも使った書き方
最後にwhileも使い、フラグも設定した書き方で書いてみます。

~~~Python:Bubble3.py
lis = [5, 1, 7, 8, 4, 2, 9, 0] # 元のリスト
n = len(lis) # リストの長さ（要素数）
swapped = True # forループ内で交換が発生したか監視するフラグを設定

while swapped:
    swapped = False
    for i in range(1, n):
        if lis[i - 1] > lis[i]:
            lis[i - 1], lis[i] = lis[i], lis[i - 1]
            swapped = True

print(lis)
# 昇順にソートされたリストが出力されました！
# [0, 1, 2, 4, 5, 7, 8, 9]
~~~
Azure EventHubsのKafka通信をGoogle ColaboratoryでKafkaConsumerを使って手軽に確認する方法

本記事では、Google Colaboratoryを使って、KafkaConsumerでAzure EventHubsのKafka通信をすぐに確認する方法を紹介します。

## 1: Azure EventHubs Namespaceの作成

AzureポータルでEvent Hubs 名前空間を作成します。名前空間の作成時に、価格レベルを「標準（Standard）」以上にすることでKafkaエンドポイントを有効にすることが可能です。

## 2: Event Hubの作成
作成した名前空間内にEvent Hubを作成します。

## 3: 接続文字列の取得
名前空間の"Shared access policies"から、"RootManageSharedAccessKey"ポリシーの接続文字列を取得します。

## 4: Google Colaboratoryノートブックの作成
Google Colaboratoryで新しいノートブックを作成します。

## 5: 必要なライブラリのインストール
Google Colaboratoryノートブック上で以下のコマンドを実行して、必要なライブラリをインストールします。

```bash
!pip install kafka-python
```

## 6: Kafkaコンシューマーの実装

以下のコードをノートブックに追加し、接続文字列、Event Hubの名前などを適切に置き換えます。

```python
# Event Hubs configuration
# Event Hubs 名前空間名
EH_NAMESPACE                    = "eventhubs-namespace"
# Event Hubs インスタンス名
EH_NAME                         = "eventhub-name"


EH_CONN_SHARED_ACCESS_KEY_NAME  = "RootManageSharedAccessKey"
# Event Hubs 名前空間の 設定 > 共有アクセスポリシーのプライマリーキー
EH_CONN_SHARED_ACCESS_KEY_VALUE = "AbCdEfGhiJkLmNoPqRsT/uVwXyZaBcDe+FgH1a2b3c="


EH_CONN_STR                     = f"Endpoint=sb://{EH_NAMESPACE}.servicebus.windows.net/;SharedAccessKeyName={EH_CONN_SHARED_ACCESS_KEY_NAME};SharedAccessKey={EH_CONN_SHARED_ACCESS_KEY_VALUE}"
```

KafkaConsumerを使用した10秒間のデータ取得を以下で実施できます。

```python
from kafka import KafkaConsumer
import pandas as pd
import json


consumer = KafkaConsumer(
   EH_NAME,
   bootstrap_servers=[f"{EH_NAMESPACE}.servicebus.windows.net:9093"],
   security_protocol="SASL_SSL",
   sasl_mechanism="PLAIN",
   sasl_plain_username="$ConnectionString",
   sasl_plain_password=EH_CONN_STR
)


# データを格納するリスト
data = []


# 10秒間データを取得
import time
start_time = time.time()
while time.time() - start_time < 10:
   for message in consumer:
       data.append(message.value)
       print(message.value)
       if time.time() - start_time >= 10:
           break


# データをPandas DataFrameに変換
df = pd.DataFrame(data)
```

ノートブック実行の10秒間の間にEventhubsにデータを送信すると、以下のような表示となり、動作が確認できます。

```
WARNING:kafka.coordinator.consumer:group_id is None: disabling auto-commit.
b'aaa bbb ccc'
b'aaa bbb ccc'
b'aaa bbb ccc'
b'aaa bbb ccc'
b'aaa bbb ccc'
b'aaa bbb ccc'
b'aaa bbb ccc'
```

## まとめ

この記事では、Google ColaboratoryとKafkaConsumerを使ってAzure EventHubsのKafka通信を簡単に確認する方法を紹介しました。
【BootStrap】Gridシステムのキソのキソ

## Gridシステムとは
テキストボックスやフォームなどの各要素の大きさを調整することが出来る。
パソコンとスマホなど、異なるデバイスでレイアウトが崩れないように出来る。

## 分母は12
分母は「12」です。

下記はフォームのテキストボックスです。

```HTML:top.html
<div class="col-12 col-sm-6 col-md-4">
	<input type="text" th:field="*{monthlyIncome}" class="form-control"><br>
</div>
```

上記の```<div class="col-12 col-sm-6 col-md-4">```がGridシステムの肝です。

<table>
<caption>各項目について</caption>
  <thead>
    <tr>
    </tr>
  </thead>
    <td>col</td>  <td>Gridシステムであることを示すクラス</td>
  <tr>
    <td> sm,md </td> <td>画面サイズ</td>
  </tr>
  <tr>
    <td> 12,6,4 </td> <td>分母12に対して画面の何割占めるか</td>
  </tr>
</table>

sm, mdは、それぞれ画面サイズを指定しています。
「ブレイクポイント」といいます。

https://getbootstrap.jp/docs/5.3/layout/breakpoints/

smは、幅 576px 以上の画面（スマートフォン程度）
mdは、幅 768px 以上の画面（タブレット程度）となります。

そのため、実際のデバイスの画面サイズによって、適用される割合が変わります。
下記の通りです。

<table>
  <thead>
    <tr>
    </tr>
  </thead>
    <td>576px以下</td>  <td>col-12</td>
  <tr>
    <td> 576~767px </td> <td>col-6</td>
  </tr>
  <tr>
    <td>768px以上</td> <td>col-4</td>
  </tr>
</table>

768px以上では、画面の横幅に対して、
12分の4の大きさのテキストボックスが配置されることになります。

## 使用例

下記の例では、
「月収は？」という項目の説明と、テキストボックスを横一列に並べています。

```HTML
<div class="col-12 col-sm-6 col-md-4">
    <label for="monthlyIncome" class="form-label">月収は？</label>
</div>
<div class="col-12 col-sm-6 col-md-8">
    <input type="text" id = "monthlyIncome" th:field="*{monthlyIncome}">
</div>
```



* 576px以下では、各項目が12/12で横幅いっぱいを占めます。（=2列になる）
* 576~767pxでは、各項目が横幅の6/12ずつ(半分ずつ)占めます（=1列)
* 768px以上では、「月収は？」が4/12、テキストボックスが8/12占めます。(=1列）
Databricksアシスタントで@を使ったテーブル参照

こちらのアップデートです。

https://docs.databricks.com/en/release-notes/product/2024/september.html#use--to-reference-tables-in-databricks-assistant-prompts

**Use @ to reference tables in Databricks Assistant prompts**

> アシスタントのプロンプトでクイックにテーブルを参照するには、`@`記号を使います。[@を用いたプロンプト内でのテーブル参照](https://docs.databricks.com/ja/notebooks/use-databricks-assistant.html#reference-tables-in-prompts-using-)をご覧ください。

セルのアシスタントを開きます。
![Screenshot 2024-09-27 at 14.25.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1e6b1403-fde3-8f9a-6cee-f1c4112b4ede.png)

`@`を入力して、アクセスしたいテーブル名などを入力していくと候補が表示されます。
![Screenshot 2024-09-27 at 14.26.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e413d2b9-06b2-c852-7f6d-412ab05b7763.png)

クリックするとオブジェクトが確定します。以降は従来通り日本語で指示していきます。
![Screenshot 2024-09-27 at 14.27.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/9287ce6c-1bad-4b17-5fcc-272f9d4fc1a8.png)
![Screenshot 2024-09-27 at 14.28.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/b3427c43-1e04-c657-452f-3d4653316f22.png)

おおー。そして、**提案を実行**ボタンも表示されてます。
![Screenshot 2024-09-27 at 14.29.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/cd7b4104-2784-e2f8-e6ca-b973363b0282.png)
![Screenshot 2024-09-27 at 14.29.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ece3f77a-c5a0-9ba1-00e5-af12999a1195.png)

複数のテーブルを操作することもできます。
![Screenshot 2024-09-27 at 14.30.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5dfdf1b6-7104-f4dd-9dc9-19c275fef2dd.png)

ちゃんとjoinしてくれます。
![Screenshot 2024-09-27 at 14.30.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e0f4fd33-b291-38fa-c59f-687fcc73a5fb.png)
![Screenshot 2024-09-27 at 14.31.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/98fd2f45-29cf-77f7-0c5e-a6de913c4da7.png)

アシスタントペインでも同様にテーブルにアクセスできます。
![Screenshot 2024-09-27 at 14.32.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1257805c-7f04-251f-aac8-69e3f55af7a7.png)

SQLエディタでも。
![Screenshot 2024-09-27 at 14.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/28f71a39-7b94-8bed-17af-b94445d7ef9b.png)
![Screenshot 2024-09-27 at 14.33.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/dad9c67a-d4e8-04fb-3488-a030f3b2ddce.png)

明示的にテーブルをプロンプトに埋め込めるので、是非ご活用ください！

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
Oracleパッチの適用について

OPatchは$ORACLE_HOME/OPatch以下にある。
念のため、このディレクトリをまるごとバックアップしてから展開。

`
cp -pr $ORACLE_HOME/OPatch  $ORACLE_HOME/OPatch_old
cd $ORACLE_HOME
unzip /tmp/p6880880_180000_Linux-x86-64.zip
`

途中で聞かれるが、A（All）を選択。

確認
`
$ ./OPatch/opatch version
OPatch Version: 12.2.0.1.43

OPatch succeeded.
`
Nextcloud Hub 9 リリース！と変更点等

# 0. はじめに

Nextcloud Hub 9が9月14日にリリースされました。

Be connected with Nextcloud Hub 9 \- Nextcloud 
https://nextcloud.com/blog/nextcloud-hub9/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/a4d53169-0f56-bc60-0f7d-2470297c5906.png)

Hub 9の内容について書きたいと思います。

# 1. UI的な変更

インストールしてみた印象としては、これまでよりも柔らかい感じのUIになっています。角がまるくなっていたり、アイコンも分かりやすく、なっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/94dd66d6-d765-b4bb-eee1-cee13a5b590f.png)

赤枠の所にフォルダーのツリー表示が追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/4e15c05f-ba3d-6544-6f0e-a706c934529c.png)

これまでもよく「フォルダーのツリー表示はないんですか？」と聞かれていましたが、ようやく実装されました。JavaScriptのフレームワークをVueにして扱いやすくなったのかもしれません。

あと、全体的に動作がキビキビしますね。

更新日時やファイルタイプでフィルターできるようになったのも便利ポイントです。

# 2. 管理機能

基本的に変更はありませんが、アカウントリストがLazyローディングになったそうです。
アカウント管理画面で表示設定が変更できるようになったのは地味に嬉しいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/0bf5d10f-4ad9-710f-f66a-c34490ebf976.png)

# 3. 生成AI機能

前のHub 8にも搭載されていましたが、生成AIの機能が洗練されているようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/e0458887-e263-11cd-a9fd-8a2bc0213ace.png)

プロンプトでシステムプロンプト等を変更できなかったのですが、変更できるようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/abf3e018-1d4b-3977-8405-4c48a881c4d5.png)

# 4. Talk機能について

Talkのメッセージが後から編集できるようになったのが大きなポイントですね。
メッセージが編集できるのは、一定時間内に限られて、それを過ぎると編集できなくなるそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/b9940c3b-fb67-0279-cae0-6784faca0884.png)


# 5. Nextcloud Hub 9リリースパーティについて
## 5-1. 開催概要
Nextcloud Hub 9リリースを記念して、コミュニティーイベントが開催されます。

今回はNextcloudの創設者Frank KarlitschekさんとデザイナーのJan-Christoph Borchardtさんがドイツから来日されて講演いただきます。

Nextcloud Hub 9は、9月14日に公開されました。生成AI機能の追加やノーコードツールのFlow機能が追加されて、自動化ツールとしても利用できるようになります。ホワイトボードが新たに追加され、コラボレーション機能が高まっています。待ち望まれていたフォルダーのツリー機能がサイドバーに表示されるようになりました。メールやカレンダー機能も強化されています。これらの内容をギュッと凝縮して解説いただきます。
通訳もありますので、聞きたいことを直接Frankさんにぶつけることもできます。

他にも介護現場でNextcloudが使われている事例紹介や、アプリ開発の話など日本での活用事例の講演もあります。

 Nextcloudのユーザーや貢献者、Nextcloudに興味がある方は、ぜひこの機会にご参加ください！

## 5-2. 開催概要
* 日時：2024年10月8日（火）19:00-21:00
* 場所：Pleasanter Lounge（株式会社インプリムさんのイベントスペース）
　　　東京都中野区中野2-30-5(中野アーバンビル7F)
* アクセス：JR中野駅南口から徒歩2分
https://osm.org/go/7Q5yF2PLM--?m=
* 参加費：1000円（ピザなどの費用です）
* 主催：Nextcloud JPコミュニティ

## 5-3. 以下のConnpassから参加登録をお願いいたします。

Nextcloud Meetup Tokyo #04(Hub 9リリースパーティ) - connpass 
https://nextcloudjp.connpass.com/event/328885/

## 5-4. プログラム（登壇者敬称略）
19:00  司会挨拶
19:05  フランクさんの講演/Frank's Session（英語・逐次通訳あり）
19:45  休憩
19:50  事例紹介:Kenta Ito、Poe Poe Mon：Nextcloudへの移行と環境構築の事例
20:10  そばっしー：Nextcloud App開発のすゝめ
20:20  フランクさんを囲んで懇親会（ピザパーティ）
20:50  クロージング

# 6. まとめ

Nextcloud Hub 9はいつにも増して意欲的なリリースになっています。
不具合もあると思いますが、使って使えるようにしていきたいですね。
Copilot を使って Power Apps の関数を学ぼう！

## はじめに
はじめまして、いのうえです。
皆さんは、普段どのようにして Power Apps の学習を行っていますでしょうか？
私は文系大学出身で、もともと IT 知識がなかったため、Power Apps だと特に関数の知識をどうやって身につけていけば良いのかわからずに困ったことがあります。

どの関数を使えばいいのか、やりたい処理に適した関数は何のか、関数自体を知らないと
なかなか難しいところがあります。

今回は Copilot を使って、基本的な関数を知るための方法をご紹介します！

## 用意したもの
リストを 1 つ用意しました。こちらを使用していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/7c85ffe3-3340-2794-2f59-38452e9965d6.png)

## アプリを作成
まず、アプリを作成していきたいと思います。
今回は SharePoint からアプリを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/849a1557-3995-ec71-8a3f-586286fb45ba.png)

サイトを選択して、用意しておいたリストを選んで接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/27921e0d-39c8-6dd4-bcf7-93ac2c2ba90e.png)

アプリが作成されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/e63e4728-3320-ea77-3ede-8a22be9117f1.png)

## アプリの式を見てみる
試しに「＋」アイコンを選択して、どのような式が書かれているのか見てましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/5b98553d-d843-d969-559e-20815311eef5.png)

OnSelect プロパティに画像のような式が書いてあります。
初めてアプリ作成している人にとっては、どういう意味なのかわからないと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/dbebd936-83ec-e923-d347-4db8b87c4372.png)

ここで Copilot に式を説明してもらいましょう！
「この式を説明する」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/da19db44-1be6-a449-6d21-05254b8560df.png)

そうしますと、式の説明が出てきました。
この説明から NewForm 関数は新規作成で使うもの、Navigate 関数は画面遷移に使うものということがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/7f70320f-09a9-3a1a-7a38-7c428de73a8e.png)

今回のように SharePoint からアプリを自動で作ってみますと、
基本的な機能を持っているアプリが作成されます。
よく使う関数が各オブジェクトに設定されていますので、
1. 気になる式を見つける
1. Copilot に説明してもらう
1. 使い方を知りたい関数の公式ページを見てみる

といった流れで、関数の知識を身につけていくと良いと思います！

公式ページには、関数の説明はもちろん、書き方の例もありますのでご活用ください♪

## おわりに
Power Platform を始めたころにこの機能があったらどれほど助かったか...笑
皆さんもどうやって学んでいったのかぜひ教えてくださいね！
Android Studioで中間パッケージを収縮せずに表示する方法

# なぜ書いたか
Google Play Consoleでアプリをaabファイルでアプリをアップロードした時に、「com.example.〇〇（アプリ名）」のパッケージ名が使えないらしい。
（たぶんexampleに問題がある）
その時に、Android Studioで表示されているディレクトリが「com.example.〇〇」でまとめられていたので困った。（このままだとパッケージ名（exampleの部分）が変更できない）

AIに質問したが、「設定から～、〇〇で～」と別のやり方を指示されて2,3時間迷ったので、そういう人を無くすべく、記事を書いた。

# 環境
Android Studio Koala | 2024.1.1 Patch 2（新UI）

# やり方
1. プロジェクトを開いている状態で、ディレクトリの上の部分を右クリック
2. 「ツリーの外観」から「中間パッケージを収縮」のチェックを外す
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624480/8e42858f-7d83-6495-7ed8-5056c1e6086d.png)

3. こんな感じで、短縮表示されなくなる
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624480/711f3b7e-6ea9-6024-ae63-716e90586fa2.png)

---
以上！誰かの役に立てたら嬉しいな。
役に立ったら、ハートマークお願いします！
アプリケーション層プロトコル完全ガイド：HTTP, FTP, DNS, DHCP, メールプロトコルを一挙解説！

#### 概要
アプリケーション層プロトコルは、ユーザーが直接触れる部分の通信を支える重要なプロトコルです。この記事では、代表的なプロトコルであるHTTP/HTTPS、FTP、DNS、DHCP、そしてメールプロトコル（SMTP, IMAP, POP3）について、それぞれの役割と特徴を解説します。

---

#### 1. HTTP/HTTPS

- **説明**: HTTP（Hypertext Transfer Protocol）は、Webページをブラウザで表示するためのプロトコルです。HTTPSは、その上にSSL/TLS暗号化を追加したセキュアなバージョンです。
- **特徴**: HTTPは高速だがセキュリティが弱い。HTTPSは暗号化されているため、セキュリティが強化されている。
- **用途**: Webブラウジング。

#### 2. FTP（File Transfer Protocol）

- **説明**: FTPは、ファイルをサーバーとクライアント間で転送するためのプロトコルです。ユーザーは、リモートサーバー上のファイルをダウンロードしたり、アップロードしたりできます。
- **特徴**: 簡単にファイルを転送できるが、セキュリティ面で脆弱な部分がある。
- **用途**: サーバーへのファイルアップロード、ダウンロード。

#### 3. DNS（Domain Name System）

- **説明**: DNSは、ドメイン名をIPアドレスに変換するプロトコルです。ユーザーが覚えやすいドメイン名を使ってWebサイトにアクセスできるようにするために使用されます。
DNSサーバーには、ドメイン名とIPアドレスを紐づける情報が設定されており、これを「DNSレコード（リソースレコード）」といいます。
- **特徴**: 人間が理解しやすい名前を使って、IPアドレスを自動的に解決する。
- **用途**: Webサイトのアクセス。

#### 4. DHCP（Dynamic Host Configuration Protocol）

- **説明**: DHCPは、ネットワーク上のデバイスに自動的にIPアドレスを割り当てるプロトコルです。これにより、手動で設定を行わなくても、デバイスはネットワークに接続できるようになります。
- **特徴**: 自動的にIPアドレスを割り当てるため、管理が簡単。
頻繁に更新する必要があるクライアントのIPアドレス変更を効率的に処理できる
- **用途**: LAN環境でのデバイス接続。

#### 5. メールプロトコル（SMTP, IMAP, POP3）

- **説明**: 
  - **SMTP**: メールを送信するためのプロトコル。
  - **IMAP**: メールをサーバー上で管理するプロトコル。
  - **POP3**: メールをサーバーからダウンロードして、クライアントで管理するプロトコル。
- **特徴**: メール送受信に使われる複数のプロトコル。
- **用途**: メールサービス全般。

---

#### 総括
アプリケーション層プロトコルは、ユーザーが直接利用する通信の基盤を形成しており、Web、ファイル転送、ドメイン名解決、IPアドレスの割り当て、メール送受信などに不可欠です。各プロトコルの役割を理解することで、ネットワーク通信の全体像がつかめます。
トランスポート層プロトコル：TCPとUDPの違いとその使いどころを徹底解説！

#### 概要
トランスポート層は、データが正しく送信され、受信されることを保証する役割を担うネットワーク層です。この記事では、トランスポート層の代表的なプロトコルであるTCPとUDPの違いと、それぞれの特性や使用例を解説します。

---

#### 1. TCP（Transmission Control Protocol）

- **説明**: TCPは、信頼性の高い接続型のプロトコルで、データの完全性や順序を保証し、エラーの検出と修正を行います。データが正しく送信されたか確認し、再送を行う機能があります。
- **特徴**: 信頼性が高く、データ転送の順序が保証されるが、オーバーヘッドが大きい。
相手との接続（コネクション）を事前に確立し、通信相手ごとに通信の状態を管理する「コネクション型」と呼ばれる方式を採用している。
通信コスト（負荷）が高いという特徴がある。
- **用途**: Webブラウジング（HTTP/HTTPS）、ファイル転送（FTP）、メール（SMTP）など。

#### 2. UDP（User Datagram Protocol）

- **説明**: UDPは、接続を確立せずにデータを送信する非接続型のプロトコルです。エラーチェックやデータ再送の機能がないため、軽量で高速ですが、データの信頼性が保証されません。
1つのパケットで情報をやりとりできるため、数多くの通信相手に対して短時間（TCPの約3分の1）で応答を返すことができる。
- **特徴**: 軽量でリアルタイム性が高いが、データの損失や順序が保証されない。
相手との接続確立を行わずにデータを送信する「コネクションレス型」と呼ばれる方式を採用している。
送信者アドレスの偽装が容易であるため、DDoS攻撃という形で悪用される機会も生じている。
- **用途**: 音声通話（VoIP）、動画ストリーミング、オンラインゲーム、ビデオ会議など。

---

#### 総括
TCPとUDPは、それぞれ異なる特徴を持ち、使用する用途も異なります。TCPは信頼性を重視するアプリケーションに適し、UDPはリアルタイム性やスピードを重視するアプリケーションに適しています。どちらのプロトコルを使用するかは、ネットワークの要求に応じて選択することが重要です。
WYSIWYG - 入力フォームとプレビューが一体化した「見たままモード」を英語で言うと ( What You See Is What You Get )

毎回のように分からなくなり、ググってもヒットしにくいので備忘録


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
ルーティングプロトコル完全ガイド：静的ルーティングと動的ルーティング（OSPF, BGP, RIP）の違いを徹底解説！

#### 概要
ルーティングプロトコルは、ネットワーク上のデバイスがデータをどの経路で送信するかを決定するためのルールです。この記事では、静的ルーティングと動的ルーティングの違い、さらにOSPF、BGP、RIPなどの代表的な動的ルーティングプロトコルについて詳しく解説します。

---

#### 1. 静的ルーティング

- **説明**: 静的ルーティングは、管理者が手動でルートを設定し、それに従ってデータを転送する方式です。固定された経路を使うため、シンプルで管理が簡単ですが、ネットワークが変化した際には手動で再設定が必要です。
- **特徴**: シンプルでトラフィックの管理がしやすいが、スケーラビリティに欠ける。
ルーターに負荷がかからない。
- **用途**: 小規模ネットワークや安定したネットワーク環境。

#### 2. 動的ルーティング

動的ルーティングは、ネットワーク状況に応じてルートを自動的に選択する方式で、以下のプロトコルが代表的です。

##### OSPF（Open Shortest Path First）
- **説明**: OSPFはリンクステート型のルーティングプロトコルで、ネットワーク内の全ルーターがネットワークの全体像を保持し、最短経路を計算します。
- **特徴**: 大規模ネットワークに適しており、高速な収束が可能。
ネットワークの変更にすぐに対応できるため不具合が発生しにくい。
- **用途**: 企業内ネットワークや大規模なLAN環境。

##### BGP（Border Gateway Protocol）
- **説明**: BGPは、異なるネットワーク間（AS間）のルーティングを行うプロトコルです。インターネットの中核を担い、AS（自律システム）間の経路を選択します。
外部 BGP ルーターは、自律システムをグローバルインターネットに接続します。
内部 BGP はシステム内のデータをルーティングします。
- **特徴**: 複雑な経路選択が可能で、インターネットの主要なルーティングプロトコル。
- **用途**: ISPやクラウド環境。

##### RIP（Routing Information Protocol）
- **説明**: RIPは、ディスタンスベクター型のルーティングプロトコルで、最もシンプルなルーティング方式の1つです。ルーター間でホップ数を基準に経路を選択します。
- **特徴**: 簡単で設定が容易ですが、最大ホップ数が15と制限があり、大規模ネットワークには向かない。
経路選択の条件がシンプルで、CPUやメモリの負荷が少ない
- **用途**: 小規模ネットワーク。

---

#### 総括
ルーティングプロトコルは、ネットワークの規模や用途に応じて選択する必要があります。静的ルーティングは小規模で安定したネットワークに適し、動的ルーティングは大規模で動的なネットワークに適しています。特に、OSPFやBGPなどのプロトコルはインターネットの中核を支える重要な役割を果たしています。
【デザインパターン】Singletonパターンについて学習

# はじめに

デザインパターンの Singleton を学習した際の内容を整理しました。

# Singleton パターン

シングルトンパターンは、クラスのインスタンスが 1 つしか存在しないことを保証するデザインパターン。

# 利用目的

アプリケーション全体で一つのインスタンスだけが必要な場合に使用する。
具体的な利用例は次に掲げるものなど。

- 設定管理や構成データの共有
  例えば、アプリケーション設定や環境変数を一つのインスタンスで管理し、全体で共有する場合。
- データベース接続の管理
  データベース接続プールを１つのインスタンスとして保持し、それを複数の部分で再利用する場合にシングルトンパターンを使う。こうすることで、無駄な接続が作成されることを防ぎ、リソースを効率的に利用できる。
- グローバルにアクセスするリソース
  グローバルにアクセスされるリソース、例えばプリンターやファイルシステム、外部 API のクライアントなどを 1 つのインスタンスで共有し、管理する際に使用する。

# 注意点

- テストが難しい
  シングルトンはグローバルな状態を持つため、ユニットテストでテストがしにくい場合がある。モック化が難しく、テストの独立性が損なわれることがある。
- 依存関係が増える
  シングルトンに依存しすぎると、システム全体の結合度が高くなり、柔軟性が失われることがある。

# 実装
```java:Singleton.java
public class Singleton {
    // 唯一のインスタンスを保持する静的フィールド
    private static Singleton instance;

    // コンストラクタをprivateにして外部からのインスタンス生成を防ぐ
    private Singleton() {
    }

    // インスタンスを取得するための静的メソッド
    public static Singleton getInstance() {
        if (instance == null) {
            // 初回のみインスタンスを生成
            instance = new Singleton();
        }
        return instance;
    }

    // シングルトンインスタンスに対するメソッド
    public void showMessage() {
        System.out.println("Hello singleton World!");
    }
}
```
```java:App.java
public class App {
    public static void main(String[] args) throws Exception {
        Singleton singleton = Singleton.getInstance();

        singleton.showMessage();
    }
}
```

# クラス図
![Singleton_class_diagram.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845328/7fe2b3d5-b048-5aaa-85c2-c51c34570f61.jpeg)
dockerで一回コンテナから出てから作業して、また入り直す。

# コンテナから出て作業するのってどうすれば？
と思ったので書こうと思いました。結論としては、

 *コンテナ内から出る*

まず、現在コンテナ内にいる場合は、exit コマンドを実行してシェルを終了し、ホストマシンに戻ります。
```
 exit
```
/ここで諸々作業する
   
*再度コンテナに入る*
   その後、以下のコマンドを使って、元の作業していたコンテナに再度入ります。
```   
docker exec -it コンテナ名 /bin/sh
```   
### 流れ
- exit でコンテナ内のシェルから抜ける。
- コンテナが実行中であれば、*docker exec -it コンテナ名 /bin/sh* で再度シェルに接続できる。
これで問題なくコンテナ内に再度入れます！
Azure AppServiceへのGitを使用したデプロイ手順

## 概要
   <br>本技術文書では、ローカル環境からAppServiceへGitを使用してNode.jsアプリケーションをデプロイする手順について説明します。</br>
   <br>このプロセスは、Azureポータルの構成、ローカルGitリポジトリの準備、デプロイ資格情報の設定、および発生した問題への対処を含みます。</br>

## 前提条件および手順
### Step1. パラメータシートの作成

お客様の要件に基づいてパラメータシートを作成することが、最初のステップとなります。そのため、必要な値を設定します。**本文に記載された値は、あくまで例として示されています。**

### ネットワーク設定
#### 仮想ネットワークおよびアドレス空間
| 項目 | 値 |
|:-----------|------------:|
| 仮想ネットワーク |	vnet-training-prod |
| サブネット |	subnet-training-prod |
| アドレス空間 |	10.0.0.0/26 |
| リソース |	StorageAccount、AppService |


#### リソースの接続
| 項目	|値|
|:-----------|------------:|
| App Service <-> Storage Account | プライベートエンドポイントを使用 |
| パブリックアクセス制限 | IBM VPN (129.41.57.0/24) からのみ許可 |

#### DNSおよび環境変数
|項目	|値|
|:-----------|------------:|
| DNS設定 |	プライベートDNS統合と統合する　|
| AZURE_STORAGE_ACCOUNT_NAME | sttrainingprod001 |
| ACCESS_KEY | <Storageアカウントにアクセスするためのアクセスキー> |
| CONTAINER_NAME | files |


### Step2. Azure Webアプリケーションの準備
**1. AzureポータルでのWebアプリケーション作成**
   <br> - Azureポータルにアクセスし、新規AppServiceを作成する。</br>
   <br> - AppServiceの基本設定として、事前に作成したパラメータシートに基づいて設定する。</br>

**2. 仮想ネットワーク(Vnet)とサブネットの設定**
   <br> - vnet-training-prod という仮想ネットワークを作成し、`10.0.0.0/26` のアドレス空間を設定する。</br>
   <br> - App ServiceのVNet統合用のサブネットと、プライベートエンドポイント用のサブネットを作成する。</br>
   <br> - App Serviceは直接で、ストレージアカウントはプライベートエンドポイントを介して接続する。</br>

**3. Storage Account設定**
   <br> - リソース作成時にネットワークアクセスを**無効**にする。</br>
   <br> - アクセス制限設定のパブリックネットワークアクセスを選択した仮想ネットワークとIPアドレスからのパブリックアクセスを**有効**にする。</br>
   <br> - AppServiceとストレージ間の通信を**プライベートエンドポイント**で保護する。</br>

**4. Git 対応アプリを作成する**

   <br> - ローカルGitを用いたデプロイにはAzureのデプロイ資格情報が必要なため、Azure CLIを使用して資格情報を設定する。</br>

```ruby:qitta.rb
az webapp deployment list-publishing-profiles --resource-group <group-name> --name <app-name>
```
   <br> - 出力には、https://<deployment-username>@<app-name>.scm.azurewebsites.net/<app-name>.git のような URL が含まれている。**このURLは後で使用するのでメモしておく。**</br>

### Step3. ローカルGitのコミットとデプロイ

**1. リモートリポジトリの設定**
   <br> - Azure WebアプリケーションのGitエンドポイントをリモートとして追加する。**(返してくれたURLを利用する)**</br>
   ```ruby:qitta.rb
   git remote add azure https://<username>@app-training-prod-001.scm.azurewebsites.net/app-training-prod-001.git
   ```

**2. コードの追加とコミット**
   <br> - プロジェクトのコードをGitに追加し、コミットする。</br>
   ```ruby:qota.rb
   git add .
   git commit -m
   ```

**3. リモートリポジトリへのプッシュ**
   <br> - コードをAzureにデプロイするために、git push コマンドでリモートリポジトリにプッシュする。</br>
   ```ruby:qota.rb
   git push azure main:master
   ```

   <br>これでデプロイが完了する。IBMVPNに接続した上で、Appserviceのドメインにアクセスする。</br>

### 問題点及び対応
**1. 仮想ネットワークのサブネット設定**
   <br>サブネットサイズを設定する際、Azure portalで仮想ネットワークとの統合の一部としてサブネットを作成する場合、**必要な最小サイズは`/27`であること**を注意する。</br>

**2. 認証エラー**
   <br>Git push の際に`Authentication failed`エラーが発生する可能性がある。
   <br>対策 : デプロイ資格情報が正しく設定されているか確認し、再設定を行う。例：Azureポータルでプラットフォームの設定、`SCM基本認証の発行資格情報`と`FTP基本認証の発行資格情報`をオンにする。</br>
Pythonでよく使うコード

# vscode の python 設定

* pythonの拡張機能が入っていることが前提です。

```~/.vscode/settings.json
{
    "python.analysis.extraPaths": [
        //Djangoライブラリの格納ディレクトリ
        "/Users/user_name/.pyenv/versions/3.9.0/lib/python3.9/site-packages",        
        //プロジェクトのルートディレクトリ
        "/Users/user_name/workspace/project_name",
    ]
}
```

# pyコマンドでVersion切り替え
```cmd
// バージョン一覧を表示
C:\Users\J\Desktop>py -0p
 -V:3.13          C:\Users\J\AppData\Local\Programs\Python\Python313\python.exe
 -V:3.12 *        C:\Users\J\AppData\Local\Programs\Python\Python312\python.exe

//3.13を指定して実行
# py -3.13 main.py

```
<details>
<summary>デフォルトのpython Versionを変更する方法</summary>

1. 環境変数を開く
1. システム環境変数の新規ボタンをクリック（下の環境変数）
1. 変数名：PY_PYTHON
1. 値：3.12
1. 以上
</details>

# 例外の詳細情報を取得
```py
# 例外を一旦受け取って再送しているファイルを想定
import sys

try:
    result = 1 / 0  # ZeroDivisionErrorが起きる
except Exception as e:
    exception_type, exception_object, exception_traceback = sys.exc_info()
    filename = exception_traceback.tb_frame.f_code.co_filename
    line_no = exception_traceback.tb_lineno
    raise Exception(f"{filname}の{line_no}行目でエラーが発生しました。詳細：{e}")
```

# logging
```py
import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

format = "%(asctime)s %(levelname)-9s [%(filename)s:%(lineno)d] %(message)s"

st_handler = logging.StreamHandler()
st_handler.setLevel(logging.DEBUG)
# StreamHandlerによる出力フォーマットを先で定義した'format'に設定
st_handler.setFormatter(logging.Formatter(format))

fl_handler = logging.FileHandler(filename="sample9.log", encoding="utf-8")
fl_handler.setLevel(logging.WARNING)
# FileHandlerによる出力フォーマットを先で定義した'format'に設定
fl_handler.setFormatter(logging.Formatter(format))

logger.addHandler(st_handler)
logger.addHandler(fl_handler)

logger.info("I am info log.")
logger.warning("I am warning log.")
```

# Selenium-Select
```py
from selenium.webdriver.support.select import Select

select_element = d.find_element(By.NAME, 'selectomatic')
select = Select(select_element)

select.select_by_value('two')
```
[Unity] Chinemachineでワールド空間上のUIを手前に表示する

# はじめに
UnityのChinemachineモジュールを使って3Dのゲームを作成しています。
UIを手前に表示することを手間取ったので、メモを残しておきます。

https://docs.unity3d.com/Packages/com.unity.cinemachine@3.1/manual/index.html

# 条件
- UIを描画するCanvasのRenderModeは`Screen Space - Camera`にしたい
- UIを描画するカメラもプレイヤーを追随するようにしたい

# 方針
プレイヤーを描画するカメラとUIを描画するカメラを分けて、どちらも同じ動きをするようにする。

# 手順
## BaseとなるカメラとVirtualCameraを作成する
Main Cameraに`CinemachineBrain`コンポーネントをアタッチします。
次に適当なオブジェクトに`CinemachineVirtualCamera`をアタッチし、Follow->Look Atにカメラに映したいオブジェクトを設定します。
以下の記事に詳しい手順が書いてあります。

https://light11.hatenadiary.com/entry/2019/07/23/210040

## UIを描画するためのカメラを作成する
シーン上に新しくCameraを作成し、`CinemachineBrain`をアタッチします。
Render Type を `Overlay` にします。
InspectorのLayerをクリックし、`Add Layer...` から`UI`を作成します。
Rendering -> Culling Mask を `UI` に設定します。
また、Rendering -> Post Processing はオフにしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289319/7576741f-66cc-f77a-b023-12f171662f41.png)

## UIを描画するカメラのVirtualCameraを作成する
Baseカメラを作成した際に作成した、VirtualCameraをコピー&ペーストして、Layerを`UI`に変更します。
（今回VirtualCameraはプレイヤーのプレハブの子として作成しました。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289319/a6019246-99c9-2e31-2fc2-7e8ad4a69039.png)

## BaseカメラのStackにUIカメラを設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3289319/65eeb13e-6ffe-b3de-8083-5ff8281e64e0.png)


# 参考記事

https://nekojara.city/unity-cinemachine-multi

https://unity-senpai.hatenablog.com/entry/2020/06/20/202936

https://zenn.dev/tuu33/articles/e1ecfa11164731
株式会社ゆめみの2024サマーインターンの感想

## はじめに
動画像処理系の研究をしている大学院1年生です。
株式会社ゆめみのサマーインターンにサーバサイドのプロジェクトリードとしてに2週間参加してきました。
その期間の内容とどう感じたのかを残しておきたいと思います！
他の人も書いてそうなので内容より、感じたこと重視!!

## 2週間の内容
### 毎日あること
始業時間なく、朝5時から〜22時までで8時間働けば良いというフレック制でした。
ただ、11時から朝会があったので大体11時には皆働いてたと思います。
あとは、17時からフロントエンドとバックエンドに分かれてKFCCという良かったこと(good)，失敗したこと(Failure)，挑戦したいこと(Challenge)，他の人を褒めたいこと(Cekebrate)をして、17時30からバディと1対1で今思ってるモヤモヤを話す時間でした。

バディとの1対1対は、心が折れそうな自分を励ましてくれる本当に良い時間でした！

### Day1
午前中は、今回参加するフロントエンドチーム(4人)とバックエンドチーム(3人)合計7人で自己紹介などをしておしゃべりしてました
午後は、社内で使用しているアプリの課題提示してもらったので、それの実装準備をしました。apiの仕様書を書いたり、環境構築したり

### Day2, Day3
今回取り組んだアプリは、社内の案件サイトです。課題の提示の内容は、案件サイトは募集期間が終了しても表示されるので、一つフィールドを追加して、募集期間終了したらわかるようにするでした。
ただ、バックエンドはRustでアーキテクチャとしてはDDD＋オニオンアーキテクチャを採用していました。😭
少しはRustの勉強をしたのですが、Rustでアプリ開発やったことなかったのでコードが読めない。そして、アーキテクチャをこれまであまり考えずやっていたのでどこに何を書いてあるのかが分からない状態でした！
ただ、Day3の最後にはみんなに手伝ってもらいながら課題を完了しました。
あとは、昼頃に実際に求人サイトを使用している人たちにインタビューをして、現在の不満を聞きました。

### Day4 
学会のため休みました

### Day5
Day3に聞いたインタビューからどんな課題があるのかをフロントと交えて話しあい、どの機能を追加したら良いかを決めました

### Day6
午前中は、POに機能の提案するためにスライドの作成
午後は、POに提案をし、意見をもらいもう一度皆で話あった。

### Day7
POにもう一度提案を行い、作業に取り組んだ
この日は、API定義を書いた。
機能については、
- 求人のスキルがどこまでかの温度感が分からないので必須と推奨に分ける
- 工数がトップページで見られるようにしてほしい

### Day8
この二つの実装をサーバサイド二人で行いました。自分はプレゼンテーション層とアプリケーション層を担当にもう一人がドメイン層とインフラ層に分かれて書きました。
分からないことだらけだったので、ペアプロなどで教えてもらったりしてました
ずっと通話してたかも笑

### Day9
1日中通話しながらコードを書いてた。
この層には、これを書くというのはわかっていたが、どのように書くの？やどう渡せば良いの？などでエラー連発
なので、他の人の足をひっぱった(チームの人ごめん！)

### Day10
結局、求人のスキルがどこまでかの温度感が分からないので必須と推奨に分けるしか終わらなかった。フロントエンドも全て終わってる訳ではなかった。
最後に、社員さんにこの一週間の発表をして、みんなで反省会して、最後に懇親会！

## 感じたこと
この二週間を通して、まず自分が井の中の蛙ということを知った。
最近、あまりアプリを作成してなかった部分はあったがそれでも、アーキテクチャについての理解や、エラーの読み方は他の人と比べて全然だと感じた。
また、型定義についてもRust特有な書き方に戸惑った。
ただ、今回のサーバサイドは、APIの定義を書いて、このエンドポイントの時は、DBに接続をして、ごちゃごちゃして値をjsonにつめて返す。これをやってるだけ。今回自分が他の人より劣っていると思ったレベルの差は、これまでどれくらいアプリを作ってきたのかとRustの書き方なだと思う。なので、勉強すれば良いのねって思ったら気が楽になった。
他には、エンジニアはコードをかけるというのは前提で、他の部分での付加価値を磨かないといけないと思った。例えば、要件を深く知り、どのようなユーザを対象といて、どの機能を追加すれば良いのかなどをちゃんと明確にする。
プロジェクトリードとしては、工数の見積などコード以外の部分にも色々やらないといけないと思った。


一方で、自分の強みは、チームでの立ち回りだと思っている。みんなでやるよとかの声かけや、チームの雰囲気が悪くならないような立ち回りは、12年間野球をしてたことや大学で多くの人と遊んできたことで備わったと思っている。また、説明をするときに、結論を言って、他の人でもわかりやすい言葉で話す。言葉のレベルを下げられるのも良さだと感じた。


何度も心が折れた二週間ではあったが、自分の実力、自分の良さ、これからどのようなことを考えてやらないといけないかを教えてくれる二週間であった。本当にためになったと思っている！

### 最後に
多分、これを見てる人は、株式会社ゆめみのインターンを参加しようか迷っている人だと思います。
株式会社ゆめみのインターンに参加しようと思っている人は、自分の力を試したい人、アプリ開発をゴリゴリやってない人やチーム開発をしたい人にはおすすめです！
自分は、エンジニアとしての成長や、心の保ち方を学ぶことができて、本当にインターンに参加できてよかったと思っています！是非迷っている人は応募する人ことをお勧めします！
日本語が下手ですみません😞
flaskでSQLalchemyの実行ログを確認する方法

# sqlalchemyが実行したsql文を確認したい
ロギングで以下の設定をアプリに追加する
```
import logging

    logging.basicConfig()
    logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
```

この設定を行うことで、gunicornなどでアプリ立ち上げ時に、実行されたsql文を確認することができる。
【DAY18】使用するフォントの変更(Laravel)

## デフォルトのフォントの確認
私はLaravel breezeを使用しており、TailwindCSSで装飾をしているため、フォントはapp.blade.phpのクラス名に書かれています。
```app.blade.php
<body class="font-sans">
...
</body>
```

tailwindCSSの設定ファイルであるtailwind.config.jsには以下のように記述されています。
```tailwind.config.js
fontFamily: {
    'sans': ["Figtree", ...defaultTheme.fontFamily.sans],
},
```
これは、sansという名前のフォントファミリーに新しいフォント「Figtree」を追加し、Tailwind CSSのデフォルトのサンセリフフォント（defaultTheme.fontFamily.sans）も引き続き使うという設定のようです。
公式ドキュメントによると、デフォルトのサンセリフフォントは以下のように指定されています。
```
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
```
これでデフォルトのフォントが確認できました。

## フォントの選択
Google Fontsで使用するフォントを選びます。
今回は、h1タグのタイトルとボディでフォントを変えて2種類のフォントを使いたいと思います。
Google Fontsでフォントの選択をした後、Get embed codeでコードを取得します。
まずHTML用のコードをコピーしてapp.blade.phpのheadタグにペーストします。
```app.blade.php
<head>
    <!-- 追記 -->
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link href="https://fonts.googleapis.com/css2?family=Concert+One&family=M+PLUS+Rounded+1c:wght@400;500;700;800;900&display=swap" rel="stylesheet" />
</head>
```
CSSについてはtalilwindCSSを用いているため、tailwind.config.jsにてフォントファミリーを設定します。
```tailwind.config.js
fontFamily: {
    'sans': ["Figtree", ...defaultTheme.fontFamily.sans],
    // 追記
    'title': ['"Concert One"', 'sans-serif'],
    'body': ['"M PLUS Rounded 1c"', 'sans-serif'],
},
```
あとはフォントを反映させたいところにクラス名を記述します。
```html
<h1 class="font-title">タイトル</h1>

<main class="font-body"></main>
```
これでフォントの変更ができました。
Google FontsのCSSのコードではfont-weightやfont-styleも指定していましたが。今回はこれらについてはデフォルト値を採用するため指定していません。
Thymeleafのバリデーションエラー時にIllegalStateException発生した

## 解決法
### 自分で考えた解
`th:object`に入れる変数を、バリデートを設定しているクラス名(キャメルケース)に合わせる

### コメントでいただいた解法
「追記：コメントから」の項目とコメント参照


## 事象
- 以下1～3を実装し、バリデートにかかる状態で「登録」を押すと例外が発生してしまった
- 例外は `java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'newForm' available as request attribute`(newFormがダメなようなエラー)

## 修正前の実装

### 1. Formクラス
- nameに「1以下のサイズを許可」するバリデートを設定
```Java
@Data
public class SampleForm {
	@Size(max = 1)
	private String name;
}
```
### 2. Controllerクラス
- 1.のFormクラスを使って画面表示と入力内容の取得をしている
- Formクラスは「newForm」という属性名になっている
```Java
	//新規登録画面を表示
	@GetMapping("/sample")
	public String displayadd(Model model) {
		model.addAttribute("newForm", new SampleForm());

		return "common/sample";
	}

	//新規登録処理
	@PostMapping("/sample/create")
	public String createUser(@Validated SampleForm newForm, BindingResult result, Model model) {
		if (result.hasErrors()) {
            // バリデートにかかったら元の画面を表示
			return "common/sample";
		}

		//	新規登録する処理を入れる
		return "complete";
	}
```
### 3. 新規登録画面html(thymeleaf)
```html
<form th:object="${newForm}">
	<div>
		<input type="text" th:field="*{name}">
		<div th:errors="*{name}"></div>
	</div>
	<input type="submit" th:formaction="@{/sample/create}" th:formmethod="post" value="登録">
</form>
```

## 修正方法
- 以下のように修正することで正常に動くようになった
    - 「3.新規登録画面html」の`th:object="${newForm}"`を`th:object="${sampleForm}"`に修正
    - 「2.Controllerクラス」の`newForm`を`sampleForm`に修正
- ★別解
	- 「3.新規登録画面html」のエラーメッセージを出す部分を、以下の通り「sampleFormというオブジェクトからとる」「sampleForm」がない時は表示しない、となる変更をす
	`<div th:if="${sampleForm}" th:errors="${sampleForm.name}"></div>`
	- 「2.Controllerクラス」新規登録処理のif内に、`model.addAttribute("newForm", newForm);`を追加

## 事象整理
- th.errorsの値は、`${バリデート設定しているFormクラスの名前(キャメルケース).フィールド名}`にする必要がある。
- 別解の「2.Controllerクラス」のみを対応すると、例外は出ないがエラーメッセージも出ない状態になった
- 「★別解」のときに、`th:if="${sampleForm}"`を入れないと、新規登録画面表示時に例外が発生する。(修正前の登録押下時の例外と同じ種類で、sampleFormでダメなようなエラー)
- 「★別解」で「2.Controllerクラス」のほうの修正がないと、修正前と同じエラーが同じタイミングで発生する

## 考察
- バリデーションエラーにかかるとき、BindingResultか何かで<br>`model.addAttribute("{Formクラスの名前(キャメルケース)}", {入力情報やバリデートエラーメッセージ});`<br>的なのが自動で設定されているのではないか？と思った
- 画面表示時に渡している`model.addAttribute`の属性名が「Formクラス名(キャメルケース)」と等しければ、登録処理から帰って来る時と同じ属性名になるので、入力値が保持されるしエラーメッセージもちゃんと出る

## 追記：コメントから
下記コメントで原因を理解しました。
- リクエストパラメータの引数の前に`@ModellAttribute("任意の属性名")`をつけると、そのリクエストパラメータに対してモデル属性名を付けられる
- エラーが起きていた時のように、このアノテーションをつけなければルールに沿って自動で命名されていた
### 原因
> この場合のエラーの直接の原因はcreateUserの引数に「newForm」という名前で指定された@ModelAttributeが存在しないことです。
### 解決法
> @ModellAttributeはリクエストのパラメーターと引数のオブジェクトの変換を指定します。
### 失敗していた時に起きていたこと
@ModelAttributeを指定されていないとき、Springが規約に従って暗黙的に変換していた
【Laravel】DBツールのA5:SQLでカラムの論理名とコメントをそれぞれマイグレーションする方法

## はじめに
A5:SQLを使用するユーザーにとっては、テーブルカラム設定を参照すると論理名とコメントの列がそれぞれ表示されるため、使い分けたい時があると思います。

よくあるテーブル定義のように論理名と用途としてのコメントを分けて管理したいところですが、Laravelのマイグレーションでは`comment()`しかないため、単純に文字列を指定しても論理名のみに反映されるようになってしまいます。
（初学者であった当初は「commentなのに論理名に反映されるんかい…」と思いました）

A5:SQLで論理名のみにではなく、コメントの列にも反映させる方法を説明していきます。

## 解決方法
`comment()`に入れる文字列を、以下のようなルールにするだけ。

:::note info
論理名:コメント
:::
`:`で区切ることにより、A5:SQLでは左部が論理名、右部がコメントとして認識されます。
一応migrationファイルの記載例も置いておきます。
```php:yyyy_MM_dd_HHmmss_create_users_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name')->comment('名前:フルネームで姓名間にスペースなし');
            $table->string('email')->comment('メールアドレス:gmailとキャリアメールのみ');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

```

## 補足
この解決方法は、**あくまでLaravelのマイグレーション機能の話ではなく、`:`で表示内容を仕分ける仕様を持ったA5:SQLに合わせた解決方法**です。

他のDBツールでは、そもそも論理名とコメントで仕分けられていなかったり、読み取り方法が違うなど仕様が異なるかと思われますのでご容赦ください。