OmniAICreator/Qiita-1.07M huggingface dataset:
コマンドを監視して終了時や停止時などにSlackの通知を送信する

![example image](https://i.stack.imgur.com/fIh5J.png)
## 概要
卒論用に作ったのですが、便利だったのでパッケージ化して`pip`でインストールできるようにしました。

https://pypi.org/project/lookout-python/

コマンドが
1. 正常に終了した
2. エラーを発生した
3. 指定時間を超えて出力がない
4. 指定した正規表現とマッチした

場合にSlackの通知を送信します。



## 使用例
走らせたいコマンドの前に`lookout`と書くだけです。
```sh:シンプルな使い方
$ lookout python kusodeka_program.py arg1 arg2
```
正規表現でも通知を設定できます。下はcondaでパッケージをインストールする際の`([y]/n)?`にマッチして通知を送る例です。
```sh:condaのインストール待ち
$ lookout --regex "\(\[y\]\/n\)\?" conda install opencv
```
また、Slackのインストールも不要です。例えばサーバで大きなプログラムを動かしている場合、
```sh:バックグラウンドで走らせる例
$ nohup lookout python train.py
```
とすればバックグラウンド実行でコマンドが終わった時やエラー発生時に通知が送信されます。

## インストール
```sh:インストール
$ pip install lookout-python
```
でインストールします。Slackのインストールは不要です。初回起動時にブラウザでSlackの認証を求められます。画面に従うと認証用コードが表示されるので、それをコピペして下さい。


## オプション
#### タイムアウト通知の制限時間を設定
```sh
--hangthreshold 秒数
```
「プロセスが止まってるかもしれません」という通知を送るまでの時間の設定です。設定は保存され次回以降も適用されます。

#### 正規表現を設定
```sh
--regex "正規表現"
```
正規表現を設定すると出力がマッチした場合に通知を送ります。記号は`\`でエスケープするのを忘れないようにしてください。正規表現がshと干渉しない場合はダブルクオートは不要です。

複数個設定したい場合は正規表現の`|`を使って下さい。



#### チャンネルを変更
```sh
$ lookout --change
```
スラックの認証をやり直します。

#### リセット
```sh
$ lookout --reset
```
初期化します。

## 制限
- 出力の色が再現されないことがあります。出力の処理のためにpipeを通しているのですが、プログラムによっては出力先が実際のターミナルではない場合にANSIエスケープシーケンスを出力してくれないことが理由です。
- 正規表現の通知は改行を待たないため、通知に表示される最終行はマッチした正規表現以降が欠けています。これは、入力を求めるプロンプトなどが改行を含まない場合にも対応するためです。
Power Apps で出張旅費精算業務を部分最適化しよう

# はじめに

出張によく行く人からすると、旅費精算業務ほど面倒くさい、憂鬱になる業務はないかもしれません。。
出来る限り自動化したいものの、例えば、以下のような理由で全体最適化できない場合もあると思います。

* 旅費精算のシステムがレガシーなシステムで自動化するのが難しい
* 旅費精算のシステムの入力項目が複雑というか条件分岐が多すぎて自動化するのが難しい
* 旅費精算のシステムはクラウド化されているが、Power Platform から接続できない

実は、私も同じです。。。
そのため、今回は、部分最適した例についてお話しします。

# Power Apps で出張旅費精算業務を部分最適化

## 旅費精算の流れと私をいつも悩ませていたこと

まず、ざっくり言うと以下のような感じの旅費精算となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ea426137-ce09-4696-e787-538ad72fc104.png)

色々手入力する部分などを AI Builder と Power Apps、Power Automate らを組み合わせて旅費精算のシステムに自動入力できたら理想なのですが、諸事情により一旦断念しています。

そのため、入力以外で私をいつも悩ませていた、領収書のコピー (写真) の添付作業を効率化 (部分最適化) することにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/4590f56c-5fe3-a31b-0e20-69603f828a3f.png)

一応補足すると、例えば、**iPhone で写真を撮ってそれをメールや Teams で自分に送った場合、ファイル名からはどの領収書か判断が難しいため、一度写真を開き、その上で、一旦ファイルに保存する必要があるのが地味に面倒でした。**

特に、数泊するような出張の場合、それなりの数の領収書があるので、領収書の添付間違いがないよう一個一個慎重にファイルを開いて確認した上で保存していたため、結構時間を要していました。

## 作成したアプリ

物凄くシンプルです。単に、行先を入力し、領収書種別を選び写真を撮るかファイルを選択して自分の OneDrive に指定したフォーマット (ファイルを開かなくてもどの領収書か判断が出来る名前) で保存してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/eee04432-2266-538d-1eb6-dd0db0c45264.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/4809c973-bda5-1428-b132-481c0244ef59.png)

※金額は支払方法次第では自動で反映されるので、一旦入力項目からは省いています

送信ボタンを押した際の処理は以下のような感じです。

```
UpdateContext(
    {
        locPowerAutomateResult: 領収書保存フロー.Run(
            dtpDate.SelectedDate,
            txtDestination.Text,
            drpReciptType.Selected.Value,
            {
                file: {
                    name: Concatenate(
                        "recipt_",
                        Text(
                            Now(),
                            "yyMMddhhmmss"
                        ),
                        ".png"
                    ),
                    contentBytes: gblReciptPhoto
                }
            }
        )
    }
);
If(
    locPowerAutomateResult.result = "0",
    //成功した場合
    Notify(
        "領収書ファイルの保存に成功しました",
        NotificationType.Success
    );
    
    ,
//失敗した場合
    Notify(
        "領収書ファイルの保存に失敗しました",
        NotificationType.Error
    )
);
```

Power Automate 側も以下のような感じで非常に簡単です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/3306f61c-2375-a180-f082-adeb7383492e.png)

# まとめ

Power Apps で出張旅費精算業務を部分最適化する例について紹介しました。
凄くシンプルなアプリで、作成時間はかなり短いですが、個人的に最近遠方に出張することもちょくちょくあるため、毎回かなり助けられており、出張精算の負担が少なからず減っています。

全体最適化出来るに越したことはないですが、難しい場合は、今回のアプリのように、Power Platform で部分最適化してみることもご検討ください。
【OpenCV】作ってみる自動運転。車載カメラからの白線検出（二値化・Hough変換）

# はじめに
画像処理を学習する機会に恵まれたので、昨今話題の自動運転関係の遊びをやってみます。
白線などの誘導の目印になるものに沿って、車体を走らせるのが定番アイデアのようです。そのため、今回は白線を検出することを目指します。

今回のゴールは下図。
![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902761/4e9a188c-e257-c5c6-1b73-5550493e3f57.png)
画像処理の流れは、３ステップ。
白線を直線として検出できないか？という定番の作戦です。
* 入力画像をグレースケールに変換
* グレースケール画像の二値化
* 直線(線分)を検出する

# コードを書いていく
## Step0. 準備
Python 3.10.8、opencv 4.7.0を利用します。まずimportしていく。
~~~python
import cv2
import numpy as np
from matplotlib import pyplot as plt
~~~
## Step1. 入力画像をグレースケールに変換する
入力画像を読み込み、グレースケールに変換します。
（分析に活用するため、ヒストグラムも一応取得します）
~~~python
# 画像の読み込み
img = cv2.imread("input_img.jpg")
# グレースケールに変換
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# ヒストグラムの取得
# 引数：入力画像、チャンネル指定、マスク画像(利用する場合)、BINの数、画素値の範囲[0〜256]
img_hist_cv = cv2.calcHist([gray_img], [0], None, [256], [0, 256])
~~~
## Step2. 二値化
グレースケール画像を二値化します。白線を残していきます。
~~~python
# 二値化する画素値のしきい値設定
thresh = 180

# 引数：グレースケール画像、しきい値、しきい値以上の画素に割り当てる値、処理内容。
# 返り値：retval、2値画像
# 判別分析法を利用しない場合は、retval = (入力したしきい値)
ret, bin_img = cv2.threshold(gray_img, thresh, 255, cv2.THRESH_BINARY)
~~~
## Step3. Hough変換による、直線検出（線分検出）
白線は、画像中では直線（線分）とみなすことができるはずです。
直線（線分）の検出には、Hough変換を利用します。

~~~python
# Hough変換による直線検出
# rho：投票空間の距離分解能
# theta：投票空間の角度分解能
# threshold : 直線とする投票数のしきい値
# minLineLength : 最小の線分の長さ
# maxLineGap : 2点が同一線分上にあるとみなす最大間隔
# 返り値は、線分情報(始点のxy座標、終点のxy座標の値)
lines = cv2.HoughLinesP(bin_img, rho=1, theta=np.pi/360, threshold=80, minLineLength=80, maxLineGap=1)

# 入力画像に検出した直線を赤線で引く。
for line in lines:
    x1, y1, x2, y2 = line[0]# lineの要素は座標配列[x1、y1、x2、y2]のみ
    red_lines_img = cv2.line(img, (x1,y1), (x2,y2), (0,0,255), 3)
~~~
## Step4. 各処理結果を描画する
OpenCVは、画像のチャンネルを「BGR」として扱っています。一方、matplotlibは「RGB」で扱うことに注意が必要です。
えっ？色おかしくない？と何度もなりました。

~~~python
# --- グレースケール ---
plt.subplot(321)
plt.imshow(cv2.cvtColor(gray_img, cv2.COLOR_BGR2RGB))
plt.title('Input image (Gray scale)')

# --- 二値化 ---
plt.subplot(323)
plt.imshow(cv2.cvtColor(bin_img, cv2.COLOR_BGR2RGB))
plt.title('Binary image')

# --- Hough変換 ---
plt.subplot(325)
plt.imshow(cv2.cvtColor(red_lines_img, cv2.COLOR_BGR2RGB))
plt.title('Hough transform')

# --- Histogram ---
plt.subplot(324)
plt.plot(img_hist_cv, label="histogram")
plt.axvline(x=ret,color='orange',linestyle='--', label="threshold") # しきい値はオレンジ色の破線で描画
plt.legend(fontsize=7)# 凡例の表示
plt.title('Histogram & Threshold')

plt.tight_layout()# 図やグラフ同士が重ならないようにする。
plt.savefig("result.png")# 出力結果を画像で保存する
plt.show()
~~~
# おわりに
今回は白線を検出してみました。しかし、空やガードレールも直線（線分）として検出され、白線だけ綺麗に検出できませんでした。仮に誤検出した空に沿って走行した場合、すぐにガードレールに直撃してしまいますね。
入力画像やパラメーター設定など、工夫が必要だとわかりました。


（参考）入力画像には、[写真素材ルーム](https://photo-room.net{:target="_blank"})様の素材を利用いたしました。
Web環境でのプログラム

# Javascript
```Webブラウザ上で動作するオブジェクト指向のスクリプト言語```の一種です。
```HTML内にプログラムを埋め込むことで動的なWebページの構築```を可能になる。

# Javaアプレット
ネットワークを通してWebブラウザにダウンロードされ、```Webブラウザ上で動作するJavaプログラム```のこと

# Javaサーブレット
Webブラウザ上で動作するJavaアプレットとは違い、```クライアントからの要求に応じてWebサーバ上で実行されるJavaプログラム```です。

# VBScript
マイクロソフト社のプログラミング言語であるVisual Basicをベースに作られたスクリプト言語です。

スクリプト言語とは、```コンパイルが不要で簡易なプログラミングを特徴とする言語処理系のこと```で、代表的な言語にPerlやJavaScript、PHP、Pythonなどがあります。

# 出典
https://gihyo.jp/book/2022/978-4-297-13178-4
ChatGPTにCypherクエリの作成を助けてもらった

# 紹介したいこと
- 最近、個人的にグラフデータベースに関心を持ち、Neo4jでデータの可視化を試みました。しかし、初心者なので、グラフデータベースのクエリ(Cypher)を入力するのは非常に時間がかかる上に、ミスもしやすいため、効率的に入力する方法を探していました。

- そこで、自然言語処理の分野で注目されている**ChatGPTを使って、文章からCypherクエリを生成する**ことを試してみました。ChatGPTを活用事例をみて、Neo4jでのグラフDBのノード、関係性の作成、検索にも活かせないかと思ったのです。

# Cypherとは
Cypherは、グラフデータベースにおける検索、追加、削除、更新などの操作を行うためのクエリ言語です。Cypherは、テーブル構造のデータベースではなく、ノードや関係性からなるグラフデータベースに対して最適化されたクエリ言語です。Cypherは直感的で読みやすく、グラフデータベースの特徴を生かしたパターンマッチング機能や、グラフ分析に必要な統計処理などをサポートしており、グラフデータベースの利用を容易にします。

# 変換したい文章

Cypherに変換する文章の例をChatGPTに考えてもらった

```
Johnはニューヨークに住んでいて、プログラマーです。彼はラーメンが好きで、よく近所のラーメン店に行きます。
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/99d962f4-327d-64b1-57ae-03fb8c164756.png)

# 文章からCypherを作成してもらった結果
```
CREATE (john:Person {name: 'John'})
CREATE (newyork:City {name: 'New York'})
CREATE (programmer:Job {name: 'Programmer'})
CREATE (ramen:Food {name: 'Ramen'})
CREATE (ramen_shop:Restaurant {name: 'Nearby Ramen Shop'})

CREATE (john)-[:LIVES_IN]->(newyork)
CREATE (john)-[:WORKS_AS]->(programmer)
CREATE (john)-[:LIKES]->(ramen)
CREATE (john)-[:GOES_TO]->(ramen_shop)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/0368a8ca-9f1f-aca5-10cf-bdc2c8e7dc72.png)

# 動作確認
アカウントを作成すれば、無料で一時的なNeo4jの環境を構築できるAuraDBでDBを利用して動作確認した。
["AuraDBとは"](https://www.creationline.com/lab/53077#:~:text=AuraDB%E3%81%AF%E3%83%95%E3%83%AB%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%89%E3%81%AE,%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%82%B9%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)

作成したDBにログインしてQueryの画面で作成したもらったクエリを実行してみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/84053a65-24c3-3d39-fc47-a3f92fa1a5e5.png)

Bloomの画面関係性を確認したところ、以下のように正しく表現できていた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/332793b5-67e5-d530-a0e2-21ec3aa27775.png)

# まとめ
- **簡単な文章であれば、ChatGPTは文章からCypherに変換してくれた。**自分でGoogleで検索しながら作業するよりも**とても効率的**であった。自力でやるより、感覚だが、2倍以上のスピードが上がってると思う。あまり知らないものに対して、サポートしてもらって簡単な実装するにはChatGPTは強力だ！
- 変換だけでなく、わからなくなったら、ChatGPTに聞いて解決できることも良かった。
- ときどき、ChatGPTで間違ったクエリが提示されるが、間違ってる部分の修正をお願いしるようなやり取りすれば、訂正したクエリがかえってくるやりとりもできた。

# 所感
- OpenAIのAPIにも同様のリクエストはできるので、文章 to Cypher 変換はできそう。文章から、その状況をグラフデータベースで可視化したい場合には活用できそう。だいたいの状況を知りたいケースなど。ただし、OpenAIに送るデータにビジネス用途の秘密情報が含まれる場合などは、より検討が必要である。今回はあくまでも、公開されてる、秘密でない情報での変換を前提としている。
- データオーケストレーションツール、ETLなどから、データの変換を検知して、AIのAPIを活用して、グラフDBに蓄積していくなどのシステム構成も考えられると思った。時間があれば試してみたい。

# 参考
- Neo4jの公式のtwitterでもすでに話題になってました・・・。やっぱ活用したくなりますよね！

https://twitter.com/neo4j/status/1625827353489207296

- Azure OpenAI Service
AzureでRest APIから使用できるサービスがある。Micorosoftが提供する基盤で使用できるのもいい。モデルをカスタマイズモデルするなど試してみたい。一般公開してほしい。(2023年2月時点)

https://learn.microsoft.com/ja-jp/azure/cognitive-services/openai/
Perforce(Helix Core)のローカルお試し環境をDockerで作ってみる


UnrealEngineを使った開発をする際に問題になるバージョン管理。
私は今までgitを使った開発しかしてこなかったのですが、gitではバイナリファイルの多いUEプロジェクトとは相性が悪く、業界ではperforceが使われることも多いそうです(伝聞)。
そこで今回はDockerを使ってローカルにhelix core serverを構築したいと思います。
※詳細な設定やデプロイまでは取り扱いません。

## ドキュメント
まずは公式のドキュメントです。基本的にはこちらの手順に従って構築します。

https://www.perforce.com/manuals/p4sag/Content/P4SAG/install.linux.packages.install.html

https://www.perforce.com/manuals/p4sag/Content/P4SAG/install.linux.packages.configure.html

## Dockerfileを作成する

今回は`For APT (Ubuntu)`の手順をDockerfile化していきます。
Installの1の手順はそのままだとうまくいかなかったのでgpcコマンドの-oオプションを使って書き換えています。
`your_password`の部分は好きなパスワードを入れてください。

```dockerfile:Dockerfile
FROM ubuntu:focal

RUN apt-get update && \
    apt-get install -y wget gnupg && \
    wget -qO - https://package.perforce.com/perforce.pubkey | gpg --dearmor -o /usr/share/keyrings/perforce.gpg && \
    echo "deb [signed-by=/usr/share/keyrings/perforce.gpg] https://package.perforce.com/apt/ubuntu focal release" > /etc/apt/sources.list.d/perforce.list && \
    apt-get update && \
    apt-get install -y helix-p4d && \
    /opt/perforce/sbin/configure-helix-p4d.sh master -n -P {your_password} --unicode

CMD p4dctl start master && tail -F /opt/perforce/servers/master/logs/log

```

## ビルド&起動する

接続には1666番ポートを使うのでマッピングしておきます。

```
$ docker build -t helix-core-server .
$ docker run -p 1666:1666 helix-core-server
```

## 接続する
クライアントは公式からダウンロードしておきます。

https://www.perforce.com/ja/zhipin/helix-core-apps/helix-visual-client-p4v

### ログイン

起動直後は`super`ユーザだけが存在するので、Dockerfileに記載したパスワードでログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360735/5b911484-f044-c296-73c5-d982e81e0115.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/360735/5d04679f-aae9-8863-c513-ab7bd2293fce.png)

接続できました！

言うまでもないことですが、Docker上で動いているHelixCoreサーバはコンテナが消えるとデータも消えてしまいますのであくまでお試し用ということでお願いします。

以上です。
【PowerShell】再帰を使わずに入れ子のフォルダのサイズを取得する

# はじめに

[フォルダのサイズを取得する](https://qiita.com/MaruiMisato/items/5e5163c7ede9a4a5d23c)という記事では、フォルダが入れ子になっている場合、C#だと再帰処理を使わないとフォルダのサイズ（合計）を取得できないと書かれていました。

確かPowerShellだとユーザー自身が再帰を使わなくても入れ子のフォルダを取得できたはず...と思い、調べてみた結果を記事としてまとめてみました。

# Get-ChildItemの活用

* `Get-ChildItem`というコマンドレットのパラメーターとして`-Recurse`を付けると、指定したフォルダの中を再帰的に探索した結果を得ることが出来ます。
 * これを使えば、ユーザー自身が再帰処理を書く必要は無さそうです。
* ただしフォルダ名は不要なので、ファイルのみを抽出する必要があります。

```powershell:作成したコード 
(Get-ChildItem C:\test -Recurse).FullName
```

```text:実行結果
C:\test\test1
C:\test\test2
C:\test\test3
C:\test\a.txt
C:\test\b.txt
C:\test\c.txt
C:\test\test1\test1-1
C:\test\test1\test1-2
C:\test\test1\123.txt
C:\test\test1\test1-1\abc.txt
C:\test\test1\test1-1\def.txt
C:\test\test1\test1-2\xyz.txt
C:\test\test2\aaa.txt
C:\test\test3\bbb.txt
```

# 出来上がったコード

* `Get-ChildItem`で得られた結果（リスト）をループで回して、ファイルサイズ（`$file.Length`）を加算するだけのコードです。
  * 自分で再帰処理を書く必要がないので、コードがかなりスッキリした印象です。
* `Get-ChildItem`のパラメーターに`-File`を加えると、ファイルのみを取得することができます。
  * これは非常に分かりやすく、なおかつありがたい機能でした。
* エクスプローラーの表示と同じ「45628バイト」を求めることが出来ました。

```powershell:作成したコード
$targetFolder = "C:\test"

$fileList = (Get-ChildItem $targetFolder -Recurse -File)
$fileSize = 0

foreach($file in $fileList) {
	#Write-Host "$($file.FullName): $($file.Length)"
	$fileSize += $file.Length
}

Write-Host "$($targetFolder)のサイズは$($fileSize)バイトです。"
```

```text:実行結果
C:\testのサイズは45628バイトです。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/c7901ffc-b3c1-8522-5b45-f0a7bd245ef0.png)


# 参考URL

* [フォルダのサイズを取得する](https://qiita.com/MaruiMisato/items/5e5163c7ede9a4a5d23c)
* [Get-ChildItem](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7.3)
第１正規形

# 第１正規系形の定義
```一つのセルの中には一つの値しか含まない```というものです。
つまり
リレーショナルデータベースでは```一つのセルに複数の値を入れ込むことは重大な規則違反```

一つのセルに一つだけの値が含まれているとき、この値のことを```スカラ値(scaler value)```と呼びます。

# エンティティがはっきりしていないと
2つのエンティティが一つのテーブルに含まれてしまうことがある。
そうすると
キーの一部にNULLが含まれてしまう。

```キーは一部であってもNULLを含んではならない。```

しかし
テーブルにエンティティごとに分けることでキーにNULLを含まないようになる。

# なぜ一つのセルに複数の値を入れてはダメなのか？
```セルに複数の値を許せば、主キーが各列の値を一意に決定できないから```
これは主キーの定義に反する

実は正規化とは、テーブルのすべての列が```関数従属性```を満たすように整理していくことなのです。

## 関数従属性
X=5と定めれば、Y＝１０のようにXに対してYが一つに決まります。
これを```YはXに従属する```と表現する。

これを以下のように表現します。
```
{X} → {Y}
```
```X列の値を決めれば、Y列の値が一つに決まる```という、数学の関数と同じことを意味します。

# 出典
https://www.shoeisha.co.jp/book/detail/9784798124704
初めてやるReact Router v6導入

React Routerを理解するためにシンプルなルーティング処理を作成する

# React Routerとは
複数のページがあるReactアプリケーションを構築する際にページ遷移を簡単に行うためのライブラリ


# プロジェクト作成
```zsh
$ npx create-react-app router-tutorial --template typescript
```
### React Router導入
```zsh
$ npm install react-router-dom
```
# App.tsxにルーターの設定
以下のように設定する
`<Route path="パス" element={<コンポーネント名 />} />`

```App.tsx
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import ArticleLists from './pages/ArticleLists';

const App: React.FC = () => {
  return (
    <>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="ArticleLists" element={<ArticleLists />} />
        </Routes>
      </BrowserRouter>
    </>
  );
};

export default App;
```

# 各コンポーネント作成
遷移したい先を以下のように設定する
`<Link to="Routesで設定したパス">任意の名称</Link>`

### Homeコンポーネント

```src/pages/Home.tsx
import React from 'react';
import { Link } from 'react-router-dom';

const Home: React.FC = () => {
  return (
    <>
      <h1>Home</h1>
      <ul>
        <li>
          <Link to="/">ホーム</Link>
        </li>
        <li>
          <Link to="/ArticleLists">記事一覧</Link>
        </li>
      </ul>
    </>
  );
};

export default Home;
```

### ArticleListsコンポーネント
```src/pages/ArticleLists.tsx
import React from 'react';
import { Link } from 'react-router-dom';

const ArticleLists: React.FC = () => {
  return (
    <>
      <h2>List</h2>
      <ul>
        <li>記事1</li>
        <li>記事2</li>
        <li>記事3</li>
        <li>
          <Link to="/">ホーム</Link>
        </li>
      </ul>
    </>
  );
};

export default ArticleLists;
```

# 完成系
![スクリーンショット 2023-02-19 14.52.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2860566/5482fd8a-34a9-dd62-7f98-7895b81666ad.png)

![スクリーンショット 2023-02-19 14.53.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2860566/c5e319cf-a7fa-ab5e-5cd2-0e4c0bc59494.png)
モジュラ逆数をニュートン法で求める

# はじめに
『べき乗数を法としたモジュラ逆数はニュートン法で求められる』ということを知ったので、コードに落としてみました。

# モジュラ逆数とは
モジュラ逆数についてよく知っている人はこの章を読み飛ばして結構です。
モジュラ逆数とは、魔法の数です…という説明では何も分からないと思います。とりあえず下記のコードを実行してみてください。

```rust
use std::num::Wrapping;

fn main() {
    let c = Wrapping::<u32>(0xaaaa_aaab);
    println!("c = 0x{:x}", c);
    for i in 0..20 {
        let i = Wrapping::<u32>(i);
        println!("c * {} = {}", i, c * i);
    }
}
```

補足ですが、Wrappingは、算術オーバーフローが発生したときのエラーを無視するための記述です。
結果も置いておきます。

```text
c = 0xaaaaaaab
c * 0 = 0
c * 1 = 2863311531
c * 2 = 1431655766
c * 3 = 1
c * 4 = 2863311532
c * 5 = 1431655767
c * 6 = 2
c * 7 = 2863311533
c * 8 = 1431655768
c * 9 = 3
c * 10 = 2863311534
c * 11 = 1431655769
c * 12 = 4
c * 13 = 2863311535
c * 14 = 1431655770
c * 15 = 5
c * 16 = 2863311536
c * 17 = 1431655771
c * 18 = 6
c * 19 = 2863311537
```

乗算しか使っていないのに、3で割る処理が実現していることが分かりますね。 
`0xaaaaaaab`が法$2^{32}$における3のモジュラ逆数だからです。
法nにおけるaのモジュラ逆数というのは、nで割った余りを考えたときに、aの逆数のような働きをする数を指しています。
現代的なコンピュータは、オーバーフローが発生したときに$2^{32},2^{64}$といった2のべき乗で割った余りを返せるため、モジュラ逆数をかけることで除算が実現できるのです。
[ここ](https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%82%B4%E3%83%A1%E3%83%AA%E4%B9%97%E7%AE%97)とか[ここ](https://qiita.com/negi-drums/items/054cb231b88bc7040e03#%E4%BA%8C%E4%B9%97%E5%92%8C%E4%B8%89%E4%B9%97%E5%92%8C)で応用例を見ることができるでしょう。

# ニュートン法
以下の漸化式は、実数$a$の逆数をニュートン法で求める式です。
$$x_{n+1} = x_n(2 - ax_n)$$
誤差を$x_n = d_n + a^{-1}$と置いてみるこんな感じです。
```math
d_{n+1} + a^{-1} = (d_n + a^{-1})(1 - ad_n) \\
d_{n+1} = -a{d_n}^2
```
従って、実数の場合には初期条件の誤差が$|x_0 - a^{-1}| < a^{-1}$であれば収束するのですが、モジュラ逆数の場合は少々事情が違います。
$d_0\in 偶数$のとき同様に漸化式を適用すると、$d_1 \in 4の倍数$、$d_2 \in 2^{4}の倍数$、$d_3 \in 2^{8}の倍数$…となって一見すると誤差が増えていくように見えます。
ところが、法$2^{32}$の場合は$d_5$以降が突如$0$になって収束します。
また、$d_0\in 奇数$だったり、法が2のべき乗でなかったり、$a^{-1}$が存在しない場合などは収束しないこともあります。
ともあれ、法$2^{32}$の場合は以下のコードでモジュラ逆数が計算できます。

```rust
use std::num::Wrapping;

fn modular_inv(a: Wrapping<u32>) -> Option<Wrapping<u32>> {
    if a.0 % 2 == 0 {
        return None;
    }
    let mut x = a;
    for _ in 0..4 {
        x = x * (Wrapping(2) - a * x);
    }
    Some(x)
}
```

# まとめ
法nが$2^{32}$のとき、ニュートン法でモジュラ逆数を求めるプログラムを示しました。
べき乗以外のときにも効率的なアルゴリズムはあるんでしょうか?

# 参考
https://qiita.com/qnighy/items/ba7e6cb6e321972bebf2
大規模プロジェクトにおける複数のプロジェクトのNuGetパッケージのバージョンを同期する技術


NuGetパッケージは、.NETエコシステムの重要な構成要素であり、再利用可能なコードと依存関係を提供し、開発者がより効率的にアプリケーションを開発できるようにします。大規模プロジェクトでは、複数のプロジェクトが同じNuGetパッケージに依存する可能性があり、異なるプロジェクトが異なるバージョンを使用する可能性があります。これはバージョンの衝突や不一致性の問題を引き起こす可能性があります。

本文では、`Directory.Build.targets`を使用して、複数のプロジェクトのNuGetパッケージのバージョンを同期する技術について説明します。

## Visual Studioのパッケージ管理と.NET CLIパッケージ管理の制限

Visual Studioでは、NuGetパッケージマネージャーを使用して、簡単にNuGetパッケージを追加、削除、更新できますが、大規模プロジェクトでは、Visual Studioでコンパイルしない場合があり、.NET CLIパッケージマネージャーを使用する必要があります。


この場合、NuGetパッケージのバージョンを手動でコマンドラインに入力する必要があり、簡単にエラーが発生する可能性があり、このプロセスはブラックボックスであり、コントロールできません。また、依存関係が複雑な場合、処理が非常に面倒になります。

## `Directory.Build.targets`を使用してバージョンを同期する


工程のルートディレクトリに`Directory.Build.targets`を新規作成し、`<PackageReference Update="Newtonsoft.Json" Version="12.0.3" />` を追加してください。

- `Directory.Build.targets`

```xml
<Project>
    <ItemGroup>
        <PackageReference Update="Newtonsoft.Json" 
                          Version="12.0.3" />
    </ItemGroup>
</Project>
```

これにより、現在のプロジェクトで使用されている`Newtonsoft.Json`のバージョンが全て`12.0.3`に設定されます。


これで、`Demo.csproj`のバージョン番号を削除できます。

- `Demo.csproj`の変更

```xml
<Project>
    <ItemGroup>
        <PackageReference Include="Newtonsoft.Json" 
                          Version="12.0.3" />
    </ItemGroup>
</Project>
```

->

```xml
<Project>
    <ItemGroup>
        <PackageReference Include="Newtonsoft.Json" />
    </ItemGroup>
</Project>
```

### 補足

複数のディレクトリにまたがって、`Directory.Build.targets`が他のファイルによって上書きされる場合があります。

上書きであることに注意し、以下のコードを使用して外部ファイルを取り込むことができます：

```xml
<Project>
    <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />
</Project>
```

プロジェクトのパス構造が複雑でない場合は、以下のコードを使用することもできます：

```xml
<Project>
    <Import Project="../Directory.Build.targets" />
</Project>
```

## まとめ

大規模プロジェクトにおいて、複数のプロジェクトで同じNuGetパッケージを使用する場合、バージョンの同期が重要です。この問題を解決するために、`Directory.Build.targets`を使用することができます。この方法を使用すると、NuGetパッケージのバージョンを一元化し、コードの衝突を減らし、コードの管理を容易にすることができます。
今ここ何番地？（法務省地図 on MapLibre GL JS）というサイトを作ってみました。

https://office-shirado.github.io/Moj_Maps/

令和５年１月２３日（月） 法務省地図が公開されました！！

データ形式は「地図ＸＭＬ」という形式で、私としては慣れているデータでしたが、あくまでローカル（ＣＡＤ・Ｓｈａｐｅ）で使う事ばかりでした。

同日、
AMX-a（https://github.com/amx-project/0）
が発足し、有志によるアダプトプロジェクト（データを預かり・育て・活用を見出すプロジェクト）が始まりました。

＜プロジェクトの流れ＞
　・Ｇ空間情報センターから全部のデータをダウンロードし、ミラーニングサイトを作る。
　・バイナリベクトルタイルを作り、公開する。
　・その他いろいろ

そして、そのバイナリベクトルタイル（PMTiles）を活用し、Leafletで表示しましたが、「他にもないかな？」という事でFacebookで質問したところ、「MapLibre GL JS」というオープンソースのWebGISに出会いました。

MapLibreは動きも軽快で、今後が楽しみです。

＜サイトのコンセプト＞
　・誰でも簡単に法務省地図（公共座標）と地理院タイルを表示できる。
　・今いる場所がすぐ分かる。
　・ＰＣ、スマホ、タブレットの環境問わず、表示できる。
　・難しくしない。（機能限定）
　・簡単、楽しい


そして、今の悩みは、「自分でベクトルタイルを作成できるようになる」。
なかなか手強そうですｗ
Swaggerページを最速で準備する方法

# はじめに
最近もっぱらサーバー側の開発にべったりですが、その過程でAPIのドキュメントをSwaggerで作成しています。
今回は恐らく最速であろうSwaggerページの準備手順を備忘録的に残しておこうと思います。

# ①SwaggerUIディレクトリをcloneする
SwaggerUIのディレクトリは以下になります。
https://github.com/swagger-api/swagger-ui

すでにymlなどのswaggerドキュメントは作成している前提で進めますが、公開するためにはjsやhtml、cssなどを用意する必要があります。
上記SwaggerUIディレクトリの中にdistというディレクトリがありますが、このディレクトリ内にすでに公開に必要なコードが用意されているので、こちらを使用します。

# ②distディレクトリを任意のプロジェクトに追加する
私はintelijを使用しているのですが、任意のプロジェクト内にdistディレクトリをそのまま追加していただければと思います。

# ③作成したymlファイルを追加し、設定を変更する
あらかじめ記載したymlファイルをdist直下に追加し、dist直下にあるswagger-initializerを修正します。

```swagger-initializer.js
window.onload = function() {
  //<editor-fold desc="Changeable Configuration Block">

  // the following lines will be replaced by docker/configurator, when it runs in a docker-container
  window.ui = SwaggerUIBundle({
    url: "読み込みたいymlを指定してください",
    dom_id: '#swagger-ui',
    deepLinking: true,
    presets: [
      SwaggerUIBundle.presets.apis,
      SwaggerUIStandalonePreset
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl
    ],
    layout: "StandaloneLayout"
  });

  //</editor-fold>
};
```
上記コードのURLパラメータに先ほど追加したymlファイルを指定する形になります。
これで調整は以上です、ymlファイルに誤りがなければdist直下のindex.htmlを表示することでドキュメントとして確認が可能です。

# さいごに
swagger、とても優秀ですよね。
プラグインなどを駆使することでそのままコードにも落とし込めますし、もはやなくてはならない存在と言えます。
InteliJは便利なプラグインがたくさんありますので、どこかで紹介したいと思います。
【Rails】特定のマイグレーションファイルをロールバックして削除する方法

複数のマイグレーションファイルが存在していて、特定のファイルのみを指定して、ロールバック→削除する方法。
不要なマイグレーションファイルを作成してしまった際に、どうやって削除するだったっけ？と毎度忘れてしまうので、備忘録として書いておきます。

## 環境
```
Rails 6.0.6.1
ruby 2.6.5
mysql  Ver 14.14 Distrib 5.7.40, for osx10.18 (x86_64) using  EditLine wrapper
```

## ①マイグレーションファイルの状態を確認

先ずはマイグレーションの状態を確認するために下記コマンドを実行。
```
% rails db:migrate:status
```
今回削除したいマイグレーションファイルは`20230212080029  Create user prefectures`で、statusはupの状態。
```
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20230204081040  Devise create users
   up     20230205061907  Create destinations
   up     20230212080029  Create user prefectures
   up     20230214022600  Create histories
   up     20230214045454  Create user histories
```

## ②削除したいマイグレーションファイルを指定してロールバック

マイグレーションファイルを削除するためには、statusをdownにする必要がある為、下記コマンドを実行。
```
％ rails db:migrate:down VERSION=20230212080029
```
コマンド実行後、無事に削除したいファイルのみをdownすることに成功。
```
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20230204081040  Devise create users
   up     20230205061907  Create destinations
  down    20230212080029  Create user prefectures
   up     20230214022600  Create histories
   up     20230214045454  Create user histories
```

## ③downしたマイグレーションファイルを削除
downしたマイグレーションファイル名を下記コマンドで指定し、実行することでファイルを削除。
```
 % rm db/migrate/20230212080029_create_user_prefectures.rb 
```

マイグレーションファイルを削除した後に、念の為`rails db:migrate status`コマンドを実行。
問題なくデータを削除できていることを確認し、削除作業完了。
```
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20230204081040  Devise create users
   up     20230205061907  Create destinations
   up     20230214022600  Create histories
   up     20230214045454  Create user histories
```
pandasでJSONファイルを読み込む＆CSVに書き出す方法メモ

# 概要
とあるJSONファイルのデータを加工しようと思い、pandasで読み込もうとしたけどいろいろとミスって時間がかかってしまったので、忘備録としてここにうまくいった方法をメモっときます。
# サンプルJSONファイル
```json:sample.json
{
	"tanaka": {"id": 123, "age": 30},
	"sizuki": {"id": 456,"age": 24},
	"satou": {"id": 789, "age": 47}
}
```
# 手順
#### １．pandasライブラリ、jsonモジュールのインポート
```python
import pandas as pd
import json
```
#### ２．ファイル読み込み
```python
data = open('sample.json')
```
#### ３．pd.read_json()でDataFrameとしてデータ読み込み
```python
df = pd.read_json(data)
```
#### ４．print(df)でデータ確認
```python
print(df)

#こんな感じの表が表示されるはず

#     tanaka  sizuki  satou
#id      123     456    789
#age      30      24     47
```
#### ５．to_csv()でCSVファイルに書き出す
```python
df.to_csv('sample.csv')
```
以上です。
LinuxでUSB Wi-Fiアダプターを使用する方法

今回はUSBのWi-FiアダプターをLinuxで使用してみます。

今回使用するのは[Archer T2U Nano](https://www.amazon.co.jp/TP-Link-433Mbps-Archer-T2U-Nano/dp/B07MXHJ6KB/ref=sr_1_7?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2JXZZL1GPA1S7&keywords=wifi+usb&qid=1676780293&sprefix=wifi+usb%2Caps%2C172&sr=8-7)です。
使用するOSはArch Linuxです。

# パッケージ等のインストール

```shell:Terminal
sudo pacman -S iwd networkmanager
```
これではUSBのWi-Fiアダプターを認識することができないのでWi-Fiドライバーをインストールします。
```shell:Terminal
yay -S rtl88xxau-aircrack-dkms-git
```
参考文献にあるページから目的にあったドライバーをインストールしてください。
あとは`reboot`して`iwctl`や`nmtui`などでWi-Fiに接続します。

## トラブルシューティング

```shell
$ lsusb -v
```
を実行して接続されているか確認してください。
もしない場合は再起動や違うポートに挿してみてください。
```shell
$ dmesg | grep usbcore
```
を実行してドライバーがあったているか確認してください。

詳しくは下のWikiを参考にしてください。

他のディストロでもドライバーをgit cloneなどしてインストールしたりして認識させてください。

以上です。

## 参考文献
https://wiki.archlinux.jp/index.php/%E3%83%AF%E3%82%A4%E3%83%A4%E3%83%AC%E3%82%B9%E8%A8%AD%E5%AE%9A#Ralink.2FMediatek
【Laravel】Blade

# Blade
テンプレートエンジン

↓保存先
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/30bf2b97-d36b-659a-11c2-72205d442b97.png)

## Bladeディレクティブ
@if ~ @endif　という方法書く構文

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/1c205fe0-081b-248a-a09e-d3ed317aef1c.png)

{{}}エコー文
　XSS攻撃を防ぐために、PHPもhtmlspecialchars関数を投資手自動的に送信。

XSS攻撃(クロスサイトスクリプティング)→Webサイトの脆弱性を利用し、HTMLに悪質なスクリプトを埋め込む攻撃。サイトに設置されたフォームに悪質なHTMLスクリプトを埋め込みが実行。入力された情報に加えCookie情報も取られてしまう。

## CSREフィールド
CSRF保護
@csrf Bladeディレクてぃぶを使用してトークンフィールドを生成。ミドルウェアがリクエストをバリデーションできるように、フォームに隠しCSRFトークンフィールドを含める。

※POST通信時は必ず書かないとエラーがでる
```
<form method="POST" action="/profile">
    @csrf

    ...
</form>
```



# 追記
Laravel7~ コンポーネントが追加
Livewire PHPで動的に書ける
Inertial(Vue.js/React)
Linux: 大文字小文字変換方法

たまに必要となるのでメモ。

###### 実施環境：

```Linux:Linux
[testuser@testhost ~]$ uname -a
Linux testhost 4.18.0-147.8.1.el8_1.x86_64 #1 SMP Thu Apr 9 13:49:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[testuser@testhost ~]$ echo $SHELL
/bin/bash
```

Linuxは基本的に、大文字/小文字を明確に区別します。
そのため、文字列の大文字/小文字を意図的に揃えたい場合がしばしば発生します。
それを実現する方法を4つ紹介します。

# 1. trコマンド

一番単純なのは、trコマンドを使用することです。
小文字a-zの組と大文字A-Zの組の変換の他、
大文字/小文字のセットを表す`[:upper:]`及び`[:lower:]`でも変換可能。

```Linux:Linux
[testuser@testhost ~]$ echo "Hello World!"
Hello World!
[testuser@testhost ~]$ echo "Hello World!" | tr [a-z] [A-Z]
HELLO WORLD!
[testuser@testhost ~]$ echo "Hello World!" | tr [A-Z] [a-z]
hello world!
[testuser@testhost ~]$ echo "Hello World!" | tr [:lower:] [:upper:]
HELLO WORLD!
[testuser@testhost ~]$ echo "Hello World!" | tr [:upper:] [:lower:]
hello world!
```

# 2. sedコマンド

sedコマンドでも大文字/小文字変換が可能です。
文字列全体を表す`.*`を()で括って一纏めにして
後方参照`\1`で参照、参照した文字列を`\U`または`\L`で大文字/小文字にして
変換前の文字列全体と変換後の文字列全体を置き換えます。

```Linux:Linux
[testuser@testhost ~]$ echo "Hello World!" | sed "s/\(.*\)/\U\1/"
HELLO WORLD!
[testuser@testhost ~]$ echo "Hello World!" | sed "s/\(.*\)/\L\1/"
hello world!
```

# 3. awkコマンド

awkコマンドでも変換できます。
awk内の関数であるtoupper/tolower関数に文字列全体を表す`$0`を与えて、
その結果を出力します。

```Linux:Linux
[testuser@testhost ~]$ echo "Hello World!" | awk '{print toupper($0)}'
HELLO WORLD!
[testuser@testhost ~]$ echo "Hello World!" | sed '{print tolower($0)}'
hello world!
```

# 4. bash内の機能

bash4.0以降の場合は、変数に代入した値から変換することも可能です。
`${変数名^^}`で大文字に、`${変数名,,}`で小文字に変換できます。

```Linux:Linux
[testuser@testhost ~]$ STR="Hello World!"
[testuser@testhost ~]$ echo $STR
Hello World!
[testuser@testhost ~]$ echo ${STR^^}
HELLO WORLD!
[testuser@testhost ~]$ echo ${STR,,}
hello world!
```
【Laravel】MVCモデル記述方法/DBの情報取得/ファサード

# MVCモデル記述
ルーティング->コントローラ->ビューでコードを書いていく

```php:routes/web.php
// 使うコントローラの記述
use App\Http\Controllers\TestController;

// 配列で書く(Laravel8 ~)
// 第一引数にURL、第二引数にコントローラとメソッド
Route::get('tests/test',[TestController::class, 'index']);
```

```php:App/Http/Controllers/TestContoroller.php
class TestController extends Controller
{
    // ここから追記
    public function index()
    {
    // view()はヘルパ関数
    return view('tests.test');
    }
}

```
フォルダとファイルを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/e6d30fcf-87b3-cf51-81a2-3a96bcc6fba2.png)


```php:resources/views/tests/test.blade.php
// 表示したい内容
test
```

# DBの情報を取得
DBの情報取得する方法は2つ
## 方法1 Eloquent
コントローラからモデルにアクセスしてDBの情報を取得

```php:App/Http/Controllers/TestController.php
//使うモデルの読み込み
use App\Models\Test;

public function index()
{
  
    //全件取得 allでコレクション型
    $values = Test::all();

    $count = Test::count();

    // 指定したidのインスタンスを返す
    $first = Test::findOrFail(1);

    // 条件指定
    $whereBBB = Test::where('text', '=', 'bbb');

    // 処理を止めて内容確認
    dd($values, $count, $first, $whereBBB);


    //compact()でViewに変数を渡す
    return view('tests.test', compact('values'));
}
```
↓　実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/49b78604-6606-3c07-6467-2e8a856d05f0.png)


### コントローラからビューへ
 ```php:resources/views/tests/test.blade.php

@foreach($values as $value)
    {{ $value->id }} <br>
    {{ $value->text }} <br>
@endforeach
```
↓表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/5b1d1511-e4b9-0ccb-c08f-06c49e724766.png)

## 方法2 クエリビルダ
SQLに近い構文(raw→生のSQLが欠ける)
PDOパラメーターバインディングを使用し、SQLインジェクション攻撃からアプリケーションを保護。

SQLインジェクション攻撃→SQLコマンドを悪用し、不正にDBへアクセスし、情報を搾取、改ざん、削除する攻撃。
```php:App/Http/Controllers/TestController.php
// 追記
use Illuminate\Support\Facades\DB;

public function index()
{
    // DBファサード
    // getでコレクション型
    $queryBuilder = DB::table('tests')
    ->where('text', '=', 'aaa')
    ->select('id', 'text')
    ->get();

    dd($queryBuilder);
}
```
↓ 実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/423eef40-1a27-a426-4e25-82b78f2993f5.png)

※エロクアントの方がクエリビルダよりも処理速度が多少遅いが、使用メリットが多い。リレーション(複数のテーブルの連帯)、スコープ(クエリの分割)が使用できるため。

# ファサード
複雑なクラス群を簡単に使用するための窓口

設定が書かれているファイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/d2563396-800c-2562-8728-0e1def9d4087.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/48e642c6-e5c9-618a-2395-90fa5894a351.png)

↓ 細かい設定は Illuminate\Support\Facades\Facade
※一部
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/395e03a8-c987-c997-3d0b-c402c65cbc93.png)

※追加設定はconfig/app.phpに書く
Googleフォームの回答スプレッドシートにUUIDを付与する

Googleフォームの回答をスプレッドシートに記録するときに、回答一つひとつにUUIDを付与する方法です。

次の手順で設定していきます。

1. Googleフォームを作る
1. 回答用スプレッドシートを作る
1. 回答用スプレッドシートのApps ScriptでUUIDを付与するスクリプトを作成する
1. 回答用スプレッドシートのトリガーを設定する

# Googleフォームを作る

いつものようにGoogleフォームを作ります。今回は承認アプリをイメージして、申請内容と承認者のメールアドレスを記入します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/6387d891-fd23-1dd8-f4a8-f42c401eb9a9.png)

# 回答用スプレッドシートを作る

Googleフォームの回答タブで、新規でスプレッドシートを作ります。説明を簡単にするために新規にしていますが、既存のスプレッドシートを選択しても構いません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/199d8782-942f-fe82-56c7-10ecc01cbee4.png)

スプレッドシートを作成したら、UUIDを記録するため、最後の列に「ID」列を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/864f55df-ff01-4b72-84d3-b330325bf34e.png)

# 回答用スプレッドシートのApps ScriptでUUIDを付与するスクリプトを作成する

上記で作成した回答用スプレッドシートの上部メニュー「拡張機能」から「Apps Script」を選択して、スクリプトエディターを起動します。

以下のコードを記入して、保存します。

```javascript
function onFormSubmit(e) {
  const range = e.range;
  const sheet = range.getSheet();
  sheet.getRange(range.getRow(), range.getLastColumn() + 1).setValue(Utilities.getUuid());
}
```

Googleスプレッドシートのイベントのうち、[フォーム送信のイベント](https://developers.google.com/apps-script/guides/triggers/events?hl=ja#form-submit)を受け取り、追加した行の末尾にUUIDを付与するスクリプトです。

# 回答用スプレッドシートのトリガーを設定する

スクリプトエディターにトリガーを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/7f3c61c5-b8f5-6fde-0576-8c6cfad80246.png)

- 実行する関数を選択
  - <b>onFormSubmit</b>
- 実行するデプロイを選択
  - HEAD
- イベントのソースを選択
  - <b>スプレッドシートから</b>
- イベントの種類を選択
  - <b>フォーム送信時</b>
- エラー通知設定
  - <b>今すぐ通知を受け取る</b>

これで設定は完了です。Googleフォームで入力した情報が回答のスプレッドシートに表示されるとき、最後のID列にUUIDが記載されることを確認してください。
React.FCってなんぞや？

## はじめに
前職ではTypescriptやReactに触れる事もなく、素のjsやvue.jsを触ることが多く転職を機にReactを触る機会が
大分増えてきました。
そして、他にもコードを追う上で**jsx.element**などとの違いなど、使い分けなど興味が湧いてきたので
自分の勉強と備忘録を兼ねてまとめようと思います。

## そもそもReactって何？
Reactとは、Facebook社が開発したWebサイト上のUIパーツを構築するためのJavaScriptライブラリのことを言います。
Facebookは勿論のこと、Instagram・Yahoo!・Slack・Netflixや自社含め世界的なWebサイト・Webアプリ、日本含めReactが採用されています。
ReactはJavaScript用の**フレームワークと勘違い**されることがありますが、実際には上述の通りライブラリとなります。
因みにVue.jsはフレームワークになります(今度フレームワークとライブラリの違いについてもまとめようかな)。

## React.FCとは
React.FCは、constによる型定義でコンポーネントを定義できる型です。
コンポーネントというのはReact独自のタグで、オリジナルのタグを作成し、タグの中で他のタグをまとめて定義できるものです。

```tsx
const Children: React.FC = () => {
  return <div>こんにちは</div>
};

const Parent: React.FC = () => {
  return <Children />
};
```
コンポーネントの中は、returnで返ったタグがレンダリング(描画)されます。
constで定義したタグはそのまま他のコンポーネントで呼び出して使う事ができます。
また、次のコードで使用しますがモジュール機能のimport、exportを使用することで、

- **ファイルを再利用することが出来**
- **コードの保守性を高め、管理しやすくなる**
- **何のためのファイルなのかはっきりさせる**
といったメリットがあります。

### タグに属性値を渡すことができ、親コンポーネントのpropsを使うことが出来る
コンポーネントに属性値を渡してその内容をレンダリングしてみます。
下に例を出します。
```tsx:src/ChildrenComponent.tsx
import React from "react"

interface Props{
    name:string;
    age:number;
  }

const ChildrenComponent:  React.FC<Props> = (props) => {
    return(
      <div>
        <p>名前:{props.name}</p>
        <p>年齢:{props.age}歳</p>
      </div>
    )
}

export default ChildrenComponent
```
上記ではinterfaceで型を付けています(typeでも可)。



```tsx:src/ParentComponent.tsx
import React from "react"
import ChildrenComponent from "./ChildrenComponent.tsx"

const ParentComponent:  React.FC = () => {
    return(
      <div className="app">
        <ChildrenComponent name="Yamada Taro" age= {25} />
      </div>
    )
}

export default ParentComponent
```
属性値には複数の引数を定義することができます。 属性値の型にはstring以外にも様々な型を渡すことが可能で、どんな型でも入れることが出来ます。
文字列の場合は、""で定義しますが、変数やそれ以外のリテラル型やboolean型(true/falseの真偽値)は{}で囲います。

上記の通り、propsは省略可能です。

### jsx.elementとReact.FCの違い
jsx.elementとの違いとしてはjsx.elementは引数と返り値の型を2箇所書く必要があります。
また、childrenにおいてですがReact.FCでは関数コンポーネントの**Props**に**children**が元から入っています。
逆に言うとchildrenが必要がない場合でも、childrenに値を入れることができます。
ですので、childrenを使用する場合は**React.FC**を使用する場合はchildrenがない場合は**jsx.element**を使う等の使い分けをするとわかりやすいのかなと思います。

**※react18からReact.FCに暗黙的に含まれていた children が除かれました**

## 最後に
コンポーネントに型をつける際に、React.FCやjsx.elementなどの選択肢が複数ありますがReact.FCだけでほとんど対応は出来ますが用途に応じて使い分けたり統一することが良いプロダクトを作ることにも繋がるのかなと感じました。

今回扱いきれなかった内容も多くあるので、またReact関連の記事についてまとめようかなと思います。


## 参考記事
[わかりやすいかも知れないReact.FCの使い方](https://interrupt.co.jp/blog/entry/2021/03/05/133925)
[Reactとは？注目されている背景や特徴・メリットを解説](https://www.kagoya.jp/howto/it-glossary/develop/react/)
[【React】{children}でコンポーネントを受け渡す](https://bonoponz.hatenablog.com/entry/2020/06/23/%E3%80%90React%E3%80%91%7Bchildren%7D%E3%81%A7%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%92%E5%8F%97%E3%81%91%E6%B8%A1%E3%81%99)
Jupyter カーネル上で実行されたら .ipynb  を .py でエクスポートするようにしておく


.ipynb上で試作・研究したものを .py で実装することがしばしばあります。

バグフィックスは .ipynb で試すのですが、最後に pyをエクスポートし忘れると
.ipynb と .py の内容がずれたままになってします。

意識的に.pyでエクスポートするのが面倒なので .ipynb で実行したら自らを.py で出力するようにしました。

```py
import sys
import subprocess

if 'ipykernel' in sys.modules:
	subprocess.run(['jupyter', 'nbconvert', '--to', 'python', '*.ipynb']).check_returncode()
```


メイン関数の中に入れておくのがいいかもしれません
```py
if __name__ == '__main__':
    # ↑ のコードを書いておく
```
競プロ未経験者が、Elixir、LivebookでAtCoderに初参加してみたらアウトプットの機会として良かった話

AtCoderにElixirで参加してみました。

AtCoder自体初心者なので、その点は、今後慣れていくとして、Elixirでやってみて気づいたことを書いてみます。

# Livebookでコーディング

Regular Contestに予習なしで参加するのは、無謀なので[Beginners Selectionの問題](https://atcoder.jp/contests/abs/tasks)をやってみました。

Livebookでいろいろ試しながらできたらいいんじゃないか？ということでこの環境を整えてみました。

標準入力からデータを読み込む必要がありますが、Livebookで再現する方法がみあたりませんでした。
私がたどり着いた方法は、

- 回答のプログラムは文字列を引数とするsolve/1に作成する。
- main()で標準入力から読み込んで、solve/1を呼び出す。
- 開発は文字列を入力にしたsolve/1で行う。

```Elixir
  def main() do
    solve(IO.read(:stdio, :all))
  end
```

動作確認は、Livebook上で、次の様に書けます
```Elixir
"""
10
20 30
abc
"""
|> Main.solve()
```

# 入力データの扱い

入力されたテキストデータを適切に変換する必要があります。
Beginners Selectionをやってみて、次の関数を使いました。

|関数|用途|
|---|----|
|String.split()   |"\n"や" "での分割|
|String.trim()   |入力データに、適用したほうがいい|
|String.to_integer|数値への変換必須|
|String.to_charlist|"110101"のようなデータをリストに変換等|
|tl/1              |先頭がデータ件数の場合が多い。これを除く時便利|
|Enumの関数全部        |chunk_every等、知ってると楽|

このあたりの関数をパイプを使って並べて、気持ちよく書けると思います。

パターンマッチを使った`[a,b] = String.split(input, " ")`も大活躍です。

AtCoderの常識なんだとおもいますが、入力データにはString.trim()を必ずかけるようにしたほうがいいです。
行末の改行の有無違いによるものだと思いますが、Beginners Selectionの問題でこれをしないとパスできない問題がありました。

# 出力

結果の出力は、
IO.putsで行う。

```Elixir
IO.puts("#{a + b + c} #{s}")
```

数値を出力するだけだったら、IO.inspectでもできるとおもいます。

この辺りは、気分で。

# Elixirの再帰処理をフル活用

[この問題](https://atcoder.jp/contests/abs/tasks/abc087_b)では、再帰で書いてくださいと言わんばかりの問題だと思いました。
いざ書いてみると、うまく行かなくて、勉強になりました。
ガード節は大活躍でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/6b1182e0-6fd3-535f-cd3c-c3c5be2cce99.png)

# Bitwiseに巡り合えた

たぶん、AtCoderやらなかったら、ガリガリのBit演算することもなかったかも。
偶数、奇数の判定は、rem(x, 2)しか語彙にありませんでした。
Bitwiseを使えば、C言語のbit演算なみの事はできるし、なにより、ガード節にbit演算を書けるではないですか！
Elixirがまた楽しくなりました。

# AtCoder Regular Contest 156 に参加

Aの問題に挑戦。問題なくプログラムを作れて、サンプルのデータではOK
しかしテストデータのいくつかで不正解この原因がわからない。
なんとか、残り、５分で、原因がわかって400点でした。
競プロって難しいんだなぁと実感しました。もうちょっと修行します。

# その他

AtCoderで動作しているElixirは1.10.2と少し古いです。
バージョンの違いでエラーになる事もあるかもしれません。
今のところ、気づいた事は、then/2が使えない事です

# 感想

- 再帰での記述など、関数型に慣れる事ができる
- Bitwiseなど新たな機能を知るきっかけになった
- 新しい言語を学んだあと、アウトプットの機会としてAtCoderは手ごろ
- Elixirは楽しい！
既に動いている処理の共通化の是非

ソースコードに同じ処理が複数あるのは宜しくないです。

例えばバグ対応した時のレビュー指摘で、
「処理を共通化して下さい。」と言われる事があります。
共通化すると「今まで動いていた処理」を再テストする必要があります。
（場合によりますが、あるとしましょう。。）

そうすると、共通化＋再テストが必要なので、
リリースするまでに時間が掛かるのと、
再テストでバグが残ってしまった場合品質が落ちます。

もし、共通化しなかった場合、
「今まで動いていた処理」は再テストしなくていいので、
実装が早くてバグも少ないです。

どちらが正しいでしょうか？
もしお客さんに納品するものだったら、
処理なんてどうでもよくて、安く（早く）て品質が良い方がいいです。

開発側からすると、今後２つの同じ処理をメンテナンスするので、
なんか気持ち悪いしバグにも繋がり易いので共通化したいです。

私は開発者なので後者寄りの考えですが。
必ずしも共通化が正しいとは限らないと思います。
という話でした。
C#からGoogle Cloud Storageにアップロードする

# はじめに
C#でGoogle Cloud Storage（以下GCS）にアップロードする方法が乗った記事が古かったり、複数の記事に散在していたので一連の流れをまとめます。公式から情報を読み取って出来る人は公式に添ってやったほうが良いです（雰囲気知りたいだけの人は纏まってる方が良いよねと思ったのでこの記事書いてます）

https://cloud.google.com/storage/docs/uploading-objects?hl=ja

# GCSでバケットを作成する

以下のページに添って作成します。バケット名はあとで利用します。

https://cloud.google.com/storage/docs/creating-buckets?hl=ja

# サービスアカウントを作成する

以下のページに添って作成します。サービスアカウントキーは必ず作成してください。キー情報が含まれたJSONファイルはあとで利用します。

https://cloud.google.com/docs/authentication/getting-started?hl=ja#creating_a_service_account

# バケットの権限を有効にする
プリンシパルに先ほど作成したサービスアカウント名を入力します。ロールは「Storage オブジェクト管理者」を指定します※ロールに関しては用途に合わせて設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496802/6da2e7e6-d384-8873-7426-1dcdaedb030a.png)

この作業を行わないと権限がなくアップロードした際に403エラーになります。

# .NETプロジェクトを作成する

今回はconsoleアプリで作成します。

```C#
dotnet new console
```

GCPクライアントライブラリをインストールします

```C#
dotnet add package Google.Cloud.Storage.V1
```

# サービスアカウントのキーファイルをビルド時にファイルコピーする

.NETプロジェクトを作成するで作成したcsprojファイルにサービスアカウントの作成で生成したキーファイル（JSON）を設定します。JSONはプロジェクトファイルと同じ位置に配置してください。
```xml
<ItemGroup>
　　<None Update="wide-memento-xxxxxxx.json">
　　　　<CopyToOutputDirectory>Always</CopyToOutputDirectory>
　　</None>
</ItemGroup>
```

# ファイルをアップロードする

いきなり雑になってしまいましたが、以下の通りにプログラムを作成します。環境変数を設定しないとアップロード出来ないので`SetEnvironmentVariable`は必ず設定してください。PCで環境変数を設定している場合は不要です。

※サンプルは最上位レベルのステートメントのテンプレートを利用しています。慣れない人は`dotnet new console --use-program-main`を使って生成してください

```C#
// See https://aka.ms/new-console-template for more information
using Google.Cloud.Storage.V1;

// 環境変数を設定する
// ref. https://cloud.google.com/docs/authentication/getting-started?hl=ja#setting_the_environment_variable
Environment.SetEnvironmentVariable(
            "GOOGLE_APPLICATION_CREDENTIALS",
            Path.Combine(AppContext.BaseDirectory, "wide-memento-xxxxxxxxx.json"));

// ローカルファイルのパス
var localPath = "";
// バケット名
var bucketName = "";
// ファイル名
var fileName = "";
var storage = StorageClient.Create();
using var fileStream = File.OpenRead(localPath);
storage.UploadObject(bucketName, fileName, null, fileStream);
```

サンプルは以下に置いています

https://github.com/ikuosaito1989/cloud_storage_c-_sample

# さいごに

意外にも一連の流れでGCSを利用する方法を述べている記事が少なかったのでまとめてみました。今更感ある内容でしたが誰かのご参考になれば幸いです。

# 参考

https://cloud.google.com/docs/authentication/getting-started?hl=ja
https://learn.microsoft.com/ja-jp/dotnet/api/system.environment.setenvironmentvariable?view=net-7.0
https://cloud.google.com/storage/docs/uploading-objects?hl=ja
[M5Staack]ArduinoJson.h が見つからないとエラーが出る[VSCode]

## 環境
PC:MacBookPro(2021)
OS:macOS Monterey 12.6.1
EDITOR:VSCode


## 解決策
Arduino開発環境をインストールした場所を拡張機能のsettings.jsonに追記する

### 1. Arduinoの拡張機能設定を開く
![スクリーンショット 2023-02-19 11.39.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125452/c6bd4cd0-5395-ba0b-c7cd-b069caeda878.png)

### 2.settings.jsonに追記する

一番下までスクロールするとArduino:Pathがあるのでそこに自分でインストールした環境の場所(Path)を指定する。(自分の場合は~/Documents/Arduinoに構築してある)
![スクリーンショット 2023-02-19 11.47.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125452/e3435c5b-bca4-052d-5cde-da7a7e8ed791.png)



右上のファイルマークから直接編集することもできる
![スクリーンショット 2023-02-19 11.51.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125452/1c5fa73b-5512-773a-984e-e98140cc05e8.png)
0xL4ugh CTF 23' Web

# 0xL4ugh CTF 23'Writeup[Web]
2/18
## Brush(Basic)

```index.php
<?php

$servername = "127.0.0.1";
$username = "ctf";
$dbname = "login";
$password = "ctf123";

// Create connection
$conn = new mysqli($servername, $username, $password,$dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

if(!empty($_GET['username']) && !empty($_GET['password']))
{
    $username=mysqli_real_escape_string($conn,$_GET['username']);
    $password=mysqli_real_escape_string($conn,$_GET['password']);
    if ($username=="admin" && $_SERVER['REMOTE_ADDR']!=="127.0.0.1")
    {
        die("Admins login are allowed locally only");
    }
    else
    {
        $res=$conn->query("select * from users where username='$username' and password='$password'"); # admin admin
        if($res->num_rows > 0)
        {
            $user=$res->fetch_assoc();
            echo ($user['username']==="admin")?"0xL4ugh{test_flag}":"sorry u r not admin";
        }
        else
        {
            echo "Error : Wrong Creds";
        }

    }
}
else
{
    echo "Please Fill All Fields";
}
?>
```
usernameがadmin以外か、$_SERVER['REMOTE_ADDR']がローカルからのアクセスだったら、queryを実行する

    [url]?username=Admin&password=admin
sqlクエリは大文字小文字を区別しないので通る
FLAGゲット

## 403 Bypass
Forbidden 403エラーになりアクセスすることができない
時間内に解けなかった

Internet Archiveで過去のページが見れたそう

https://archive.org/

## Evil oR nOt

問題の写真を撮り忘れた
入力したものをevalしてくれるサイト
blacklistがあり[system|exec|open|file|show]などのほとんどが正規表現でマッチした場合evalが実行されないようになっていた。
バックスペースが使えたので

    $p=`ls /` ;echo <p>$p</p>;
RCEができた
/ディレクトリにflag_xxxx.txtがあったので、続けて

    $p=`cat /flag_xxxx.txt` ;echo <p>$p</p>;

FLAGゲット
AWS re:Postに回答してみた

# はじめに
先日、AWS re:Postに初めて回答を投稿しました。主に英語なコミュニティでしたが、何とか投稿できたので、その旨記事にしました。

# 得られた知見・マインド

- 英語も、Google翻訳とDeepLがあればなんとかなる（と思う）
- 間違った回答でも、試してすぐに気づいてもらえる（はず）だから、重大な事態にはならない
    - リスクが小さいなら、ドンドンやってみるが吉
    - いつでもゴメンナサイできる心の準備をしておく

# re:Postとは

AWSを対象とした技術者の方々のコミュニティサイトになります。詳細は以下のページが参考になります。

https://dev.classmethod.jp/articles/how-to-start-re-post/

昨年末に、AWSアカウントだけでなく、AWS Builder IDで利用できるようになりました。

https://dev.classmethod.jp/articles/aws-repost-builder-id/

私もこの機会にBuilder IDを作成してメンバーになりました。

質問は英語ばかりですが、日本語での質問・回答をしている方々もいらっしゃいます。

# 回答する
## きっかけ
re:Postを見るのを習慣化させようと眺めていたところ、自分でも回答できそうな質問が投稿されていました。
英語だったのと就寝前だったのでしばらく様子見していたのですが、回答が投稿されることもなかったため、後日時間を作って挑戦してみました。

## 英作文
自分は英語がダメダメなので、文明の利器を使って、以下のようにして回答文を作りました。

1. 日本語で作文
1. Google翻訳で英文に変換
1. 変換された英文を、DeepLで日本語に変換
1. 上記日本語が、自分の伝えたい内容になっているか確認

一文ごとに、以下のように英文に変換し、確認していきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/20027ae7-0e1e-5ce4-ed96-165d534d46b0.png)


またre:Postでは回答を入力した後、プレビュー画面にできるので、そこに対してDeepL翻訳して、最後の確認を行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/1d399a7d-42dc-e7b8-23c5-4280e823a44a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553680/aa71ba04-d386-7559-4d13-fdc3f544c7d4.png)

:::note
先頭に"Hi"などの挨拶がない回答も多かったため、自分もそれに倣い挨拶などは入れませんでした。
:::


あとは勇気をもって「回答を投稿する」をクリックします。
色々心配がありクリックをためらいましたが、以下のような心持ち・考えに変わり、投稿にチャレンジしました。

- （技術系なので）書かれたことを試し、その段階で誤っているかはわかるはず。
    - すぐに間違いがわかるので、きっと重大な問題にはならないだろう
- ダメだったら、ゴメンナサイしよう


# おわりに
今回はre:Postで初めて回答をしてみたので、方法や心持ちについて書きました。
参加するのにためらっている方の後押しになれば幸いです。re:Postコワクナイヨー。
【Laravel】Model/Migration/tinker/Controller

# Model

Laravelが採用するMVCモデルのうちの一つ

Model データベースとのやりとり
View　見た目
Controllwe 処理

## Eloquent

＜ORM/ORマッパー＞
DBとのやりとりを他の言語で書ける
(Java、Ruby、Python同様)

# モデルファイルの作成
ファイル作成コマンド
```
php artisan make:model Test
```
↓ファイルが自動生成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/f9330a80-3182-b3cb-f037-5eae0e53e39f.png)

※コントローラとマイグレーションも同時生成
```
php artisan make:model Test -mc
```

# Mifration
DBテーブルの履歴管理

↓ファイル場所
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/065e26df-43ac-e76a-8238-4d6884ff0b1a.png)

モデルは単数形、マイグレーションは複製形で書く
→Laravelが自動判定

ファイル作成
```
php artisan make:migration create_tests_table
```
↓作成時の時間を含んだファイル名が自動生成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/d49651e7-4a17-aac3-53e1-8f5449046368.png)

ファイルの中身
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/396bb818-ba06-2847-7d85-2d52f61681a6.png)

↓書き足し

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/8d29f6f1-dd4a-581b-3735-2dd2f1f0c4f7.png)

DBに適応させる
```
php artisan migrate
```

確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/381d7389-da10-8f5b-39de-d7672201c6a1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/c28d0721-f791-ca2e-94a6-a834c7bd0f63.png)

## その他のコマンド
テーブルを全て削除
```
php artisan migrate:fresh
```
ロールバックして再生成
```
php artisan migrate:refresh
```

# tinker (DB簡易接続)
コマンド入力でデータを保存・閲覧できる
```
php artisan tinker
```
保存
```
//　インスタンス化したものを変数へ代入
$test = new App\Models\Test;
$test->text = "hoge";
$test->save();

//全件表示
// Eloquent(ORマッパーの仕組み)
App\Models\Test::all();
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/c67276b3-2ace-0d73-9c3c-ac6701093ca2.png)

# Controller
Laravelが採用するMVCモデルのうちの一つ

Model データベースとのやりとり
View　見た目
Controllwe 処理

# ファイル生成
```
php artisan make:controller TestController
```
↓自動生成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/6ece54ba-a298-c250-45bb-f117335b12fc.png)
【Docker】Docker-Compose 「volume」とは

# はじめに
DockerやDocker-composeを使い始めて暫く経つが

volumeについてふと気になったため

自分用のメモとして載せておく。

# volumeとは

・データを永続化できる場所のことを指す。

作成したコンテナを破棄すると当然コンテナ内で作成していたファイル等は消えてしまう。

ここでいう永続化は

もし

コンテナを破棄してもデータは自分のローカルフォルダには残しておける

と理解してもいいかもしれない。




volumesの記述方法は以下に記載した通りになる。


```docker-compose.yml
    php:
      build: ./php
        volumes:
        - ./自分で決められる任意のローカルフォルダ:サーバーのパス
```


:::note info

左側のローカルフォルダの割り当ては「相対パス」であると望ましい。

:::


# まとめ

```docker-compose.yml
    volumes:
    - ./any_folder/:server_path
```



webサーバーの構成によるが

「volumes」の定義として

左側には自分で決められるローカル上のフォルダを割り当てて

右側には永続化したいサーバーフォルダを割り当てることが

なんとなくわかった。