OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】Xサーバをリモートサーバ上のDockerコンテナで使いたい

# 概要
コンピュータビジョン分野のGitHubコードを動かす際に、「**Ubuntuサーバ上のDockerコンテナでXサーバを起動する**」という状況に何度か遭遇しました。
この問題の解決のためにかなり時間がかかったため、備忘録として対処法を記録しておきます。

# 実行環境
**サーバ**
* Ubuntu 20.04

**クライアント**
* Ubuntu 20.04
* Windows 11

**その他**
* Docker Compose バージョン2.3

# 手順
## クライアント側の準備
### Linux(Ubuntu)の場合
クライアントPCにUbuntuを使う場合は、X Windows Systemを使えるように設定が必要なので、以下のコマンドでインストールする。
```
sudo apt-get -y install xserver-xorg
```
動作確認のために以下もインストールして実行する。
```
sudo apt-get -y install x11-apps
xeyes
```
問題が無ければ、目がきょろきょろするウィンドウが表示されるはず。

### Windowsの場合
WindowsはUbuntuのようにコマンド一発ではできず、いくつかステップが必要です。

1. [Cygwin/X](http://x.cygwin.com/)のインストーラをダウンロードする。
1. インストーラを起動後、パッケージ選択画面まで進める。
1. パッケージ選択画面で**X11**の三角をクリックし、「Install」に変更する。
1. パッケージ選択画面で**openssh**の三角をクリックし、バージョンを選択する。
1. インストールを行う。
1. インストール完了後、アプリの中から「Cygwin-X」フォルダを見つけて開き、「XWin Server」を起動する。
1. タスクバーの通知領域に表示された「X」アイコンを右クリックし、「システムツール->XTerm」を起動する。

:::note warn
Windowsは通常のコマンドプロンプトから`ssh -XY`しても、Xサーバに必要なディスプレイが認識されない。XTermからSSH接続を行う事に気を付ける。
:::

## Dockerの設定

リモートDockerコンテナを立てる場合に、以下の点が必要になりました。

1. docker-compose.yamlに`network_mode: host`を記述する。
    * または`docker run`のオプションに`--net=host`を入れるとよいらしい
1. docker-compose.yamlに以下を記述する。
    ```yaml
    environment:
        - DISPLAY=$DISPLAY
    ```
    * または`docker run`のオプションに`-e DISPLAY=$DISPLAY`を記述する。
    * `$DISPLAY`は`echo $DISPLAY`で表示されるものが入る

## SSH接続
クライアントPCからリモートのUbuntuにSSH接続を行う際に、`-XY`オプションを付けます。
例）
```
ssh -XY [リモートサーバ]
```
* `-XY`オプションは、X11 Forwarding（X転送）に必要
* `-X`のみだと失敗する場合がある
* `-Y`を使う場合は、信用できるリモートホストのみにすること

## リモートDockerコンテナでXサーバを起動する
リモートサーバにSSH接続をしたところで、早速Xサーバを起動していきます。

1. `echo $DISPLAY`コマンドを実行し、表示される値をメモ
1. サーバのホスト側で`xauth list`を実行
1. 表示された文字列の中から、サーバのディスプレイに対応するものを**一行丸々コピー**
   * 例）`echo $DISPLAY`コマンドで`<hostname>:10`が表示→`xauth list`コマンド実行で`<hostname>/unix:10 MIT-MAGIC-COOKIE-1 ...`というものが表示されたら、それをコピー
1. Dockerコンテナに入り、以下のコマンドを上から順に実行する。
    ```
    :> ~/.Xauthority
    chmod 600 ~/.Xauthority
    xauth add <3でコピーしたテキスト>
    ```
## その後
後はコード実行時に発生した`ImportError`などを地道にパッケージインストールでつぶしていけば動くのではないかと思います。
筆者は大体以下のパッケージをDockerfileに追加しています。参考になれば幸いです。

```dockerfile
RUN apt-get update -y \
  && apt-get install -y --no-install-recommends \
    build-essential \
    wget \
    unzip \
    git \
    vim \
    sudo \
    libgl1-mesa-glx \
    libglib2.0-0 \
    libopencv-dev  \
    libsm6 \
    libxrender1 \
    libxext6 \
    libgl1-mesa-dev \
    curl \
    xauth \
    libxxf86vm-dev \
    tmux && \
    rm -rf /var/lib/apt/lists/*
```

またターミナル（XTerm, Ubuntuのターミナル）を閉じてしまったり、放置しすぎたりすると、たまにXサーバが認識しなくなります。
その場合は再度[ここ](#リモートdockerコンテナでxサーバを起動する)の作業を行うと動くようになるかもです。

# まとめ
Xサーバめんどくさい部分は多いですが、使えるようになったら便利なことも多いと感じます。
本記事が少しでも参考になれば幸いです。

# 参考サイト
http://ss.sguc.ac.jp/~rider/unix/X.html

https://qiita.com/loftkun/items/37340745f211ea5d7ece

https://blog.amedama.jp/entry/ubuntu-2004-install-gui

https://ecs.kyushu-u.ac.jp/Xsvr/CygwinX.html
AWS EventBridge S3にファイルが格納されたことを起点にlambda関数を実行する（EventBridge）

# 概要

- S3にファイルがアップロードされたことを起点にlambda関数を実行するためにEventBrigdeで必要な設定をまとめる。

# 情報

- EventBridgeに関しての簡単な情報は下記にまとめてある。

https://qiita.com/miriwo/items/ea12cdba9a1856cf6bd8

# 設定

## S3の設定

1. 新規でバケットを作成し、「look」フォルダを作成する。
1. 当該バケットの「プロパティ」のタブに移動する。
1. 「Amazon EventBridge」の設定部分まで移動し「編集」をクリックする。
1. ラジオボタンでONを選択して「変更の保存」をクリックする。

![test-s3-upload-event-bus_-_S3_bucket.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/d1465f7d-e57d-0e68-84c4-adc3ce204675.png)
![test-s3-upload-event-bus_-_S3_bucket.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/76247ef5-905a-d2a8-b02f-ea9dd6ef8da2.png)


## lambdaの設定

1. Node18で関数名「s3_put_test_event_bridge」で関数を作成する。

## イベントバスの設定

1. EventBridgeにのページにアクセスし、左サイドバーの「バス」の「イベントバス」をクリックする。
1. デフォルトのイベントバスの「アクション」をクリックし、「検出を開始する」をクリックする。（下記スクショはクリック前からスキーマの検出が「Started」になっていますが検出ONにしてからスクショを撮影したためです。）

    ![Amazon_EventBridge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/f342b2b7-b4f3-c0a7-36b6-a04cd767b5db.png)

1. 一覧の中でdefaultバスのスキーマの検出が「Started」になっていることを確認する。

## ルールの設定

1. EventBridgeにのページにアクセスし、左サイドバーの「バス」の「ルール」をクリックする。
1. 「ルールを作成」をクリックする。
1. 下記の様に設定する。

    | 項目 | 内容 | 備考 |
    | --- | --- | --- |
    | 名前 | s3-upload-rule |  |
    | 説明 | 記載なし |  |
    | イベントバス | default |  |
    | 選択したイベントパスでルールを有効にする | ON |  |
    | ルールタイプ | イベントパターンを持つルール |  |

1. 「次へ」をクリックする。
1. 下記の様に設定する。

    | 項目 | 内容 | 備考 |
    | --- | --- | --- |
    | イベントソース（送信元） | AWSイベントまたはEvnetBridgeパートナーイベント |  |
    | サンプルイベント | 記載なし |  |
    | 作成のメソッド | パターンフォームを使用する |  |
    | イベントソース | AWSのサービス |  |
    | AWSのサービス | Simple Storage Service(S3) |  |
    | イベントタイプ | すべてのイベント |  |

1. 「次へ」をクリックする。
1. 下記の様に設定する。

    | 項目 | 内容 | 備考 |
    | --- | --- | --- |
    | ターゲットタイプ | AWSのサービス |  |
    | ターゲットを選択 | Lambda関数 |  |
    | 機能 | s3_put_test_event_bridgeを選択 |  |
    | バージョン/エイリアスを設定 | デフォルト |  |
    | 追加設定 | 特に設定しない |  |

1. 「次へ」をクリックする。
1. タグも特に設定しないで「次へ」をクリックする。
1. 最後の画面で作成予定ルールの確認を実施し、問題なければ「ルールの作成」をクリックする。

# 確認

1. S3でlookフォルダを開く。任意のファイルをlookフォルダにアップロードする。
1. 下記の様に移動してEventBridgeの起動状況を確認する。
    1. ルールにて「イベントパスを選択」の部分で「s3-upload-event-bus」を選択する。
    1. 表示されたルールの「s3-upload-rule」をクリックする。
    1. 「モニタリング」をクリックする。

# 参考文献

https://dev.classmethod.jp/articles/s3-object-event-notification-seamlessly-integrated-with-amazon-eventbridge/
今更だけど、AWS cloud shell でS3バケット作ってみた

cloud shellを開く
![cloiudshell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120764/3a4bc1c7-e56d-da20-0b06-9b0f4417d136.png)


バケットを作成、バケット名はmybuckettestformomokukko
```
aws s3 mb s3://mybuckettestformomokukko

[cloudshell-user@ip-10-2-29-165 ~]$ aws s3 mb s3://mybuckettestformomokukko
make_bucket: mybuckettestformomokukko
[cloudshell-user@ip-10-2-29-165 ~]$ 
```

コンソールでバケット確認
![S3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120764/a9beec8d-3d42-f923-5b37-cb25af48024a.png)
CocosはGoogleと提携し、WEB対応ゲームの収益化を支援します。

![40af2d84541b4c7ca2bdd37593a2a9dc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852397/d2676f84-3e8f-034a-910e-1b8f9d6e44f1.png)
Cocos Creatorで作られ、1億人以上のユーザーを持つベンチマークゲーム**Top War**は3年間の運営を経て、新たな成長点が緊急に必要となりました。**River Games**の研究開発チームはCocosエンジンを使用し、わずか1ヶ月ほどでWeb版の開発を完了させました。発売後、短期間で300万人の新規ユーザーを獲得しています。

このケースはWeb版ゲーム市場の巨大な可能性を示すものです。

ここ数年、多くのゲームメーカーがココスエンジンを通じて様々なWebコンテンツを制作しています。UbisoftのマルチプレイヤーオンラインH5ゲームプラットフォーム**Ubisoft Nano**は、クロスプラットフォームのマルチプレイヤーゲームをオリジナルでリリースし続けています。サンジの重厚なSLG **三国志 - Glory of Heroes -** は、Web版とモバイル版が同時に稼働しています。

また、Cocosはweb-side ecologyの構築を引き続き推進し、開発者がマルチサイドゲーム（Web／ミニゲーム／モバイル）を迅速に立ち上げ、HTML5ゲームの成功率を向上させるための支援を行っています。

# 新しい WebGPU – より優れたパフォーマンスを構築。

多くの開発者がマルチプレイヤーゲームを開発するためにCocosを選ぶ理由の一つに効率性がある。ここでいう「効率」とは、ゼロから素早くコンテンツを作成できるだけでなく、パッケージングやビルド、プロジェクトのリリースといったプロセスも含まれます。

Cocos Creatorは主要なプラットフォームをサポートしており、開発者はワンクリックでコンテンツをWeb／ゲーム／ネイティブ・プラットフォームに公開することが可能であり、マルチプラットフォーム版構築のコストも削減できます。

# Top Warをオンラインでプレイ!
River Gamesを例にとると このゲームのWeb版は、企画から開発、正式な発売までわずか1ヶ月しかかかりませんでした。この効率化は、APP版がもともとCocosエンジンを使って開発されていたことも関係していると、R&Dチームは話しています。相互運用の利便性から、コードを書き換えたり、新しいフレームワークを構築する必要はなく、元データをWeb版に転送し、インターフェースの問題を解決するだけで済んだということです。

Cocosは新しいWebパブリッシングを求める開発者の要求に直面し、Game DistributionやPokiを含む、多くの有名なWebゲームプラットフォームにSDKを提供しました。これにより、開発者は対応するプラットフォームへゲームをより便利に発行でき、これらのプラットフォームのトラフィック値で、より多くの露出を得ることができます。

また、開発者はCocos ServiceやCocos Storeを通じて、Xsolla、Vungle、Tradplus、Toponなどのサービスに迅速にアクセスでき、国内外での代金回収や広告の実現が容易にできるようになりました。

**GameDistribution SDK：**
https://store.cocos.com/app/en/detail/3320

**Poki SDK：**
https://store.cocos.com/app/en/detail/3702

同じコンテンツが異なるプラットフォームで忠実度の高いゲーム体験を提供することを保証するために、Cocosはそのエンジンでネイティブ／Webサイドのデュアルコア・アーキテクチャを使用します。これにより、開発チームはプラットフォームの正確で改善された最適化を行います。

デュアルコアエンジンのもう一つの利点は、Cocosのネイティブ空間でのブレークスルーがWebAssemblyとWebGPU技術を通じてWebコンテンツ開発に適用され、より洗練されたグラフィックス、滑らかな動作速度、よりリアルな物理シミュレーションをユーザーにもたらすことができることです。

WebGPUは、最新のレンダリング・パイプライン・インターフェースを提供するブラウザーベースのグラフィックスAPIのセットであり、Web上でGPUハードウェアのパワーを解き放ちます。これにより、開発者はTypeScriptとJavaScriptを使用し、ネイティブに近いパフォーマンスシーンを開発し、Web上により広範囲で複雑な3Dシーン表現を実現できます。

Cocos Creator3.6.2にはWebGPUが追加されています。プロジェクトがプラットフォームビルドになったとき、開発者がWebDesktopビルドプラットフォームを選択すると、サブオプションにWebGPUのチェックボックスが表示されるようになっています。ワンクリックで有効にすることができます。

同期インターフェースの一部はまだ調整中ですが、将来的にエンジンはWebGPUバックエンドに基づくComputeShaderなどの機能に徐々にアクセスできます。Webプラットフォームのレンダリング機能もさらに強化される予定です。

# Google AdSense
最近、CocosとGoogleはゲームの輸出に関する技術協力に達しました。Cocos CreatorはプラグインとしてGoogle AdSenseに統合される予定です。将来、開発者はエンジンを通じて直接Webプラットフォームにゲームを公開し、Google AdSenseを通じて直接キャッシュアウトすることができる予定です。

Google AdSenseはGoogleの無料Web広告キャッシングツールで、国内外においてWebベースのゲームキャッシングに広く利用されています。Google AdSenseとCocosの連携は、Webゲームの事業化を強力にサポートします。

また、キャッシュの創出力を左右する要因として、広告フォーマットが挙げられます。通常の広告フォーマットに加え、新たにWeb版挿入広告とインセンティブビデオ広告2つのWeb広告フォーマットが用意されています。広告モデルの多様化により、開発者はより多くの選択肢を得ることができ、ゲーム内広告のキャッシュ創出能力が向上します。

Google AdSenseは現在、Cocos Storeで正式に提供されており、開発者は無料でダウンロードして使用することができます。

**Google AdSense Plugin Download:**
https://store.cocos.com/app/en/detail/4173

モバイル市場の成長が鈍化する中、新たな成長ポイントを見つけることは国内外のゲームメーカーにとって共通の課題となっています。Cocosは多様な端末コンテンツの開発・実現を支援するツールとして、より多くの優れたコンテンツが世界のWebステージに進出できるよう、今後もその役割を担っていきます。

[引用元](https://www.cocos.com/en/post/u2KQUoTM5oayGRq916gApUKRBR1uxlAt)
デジタル庁の登記所備付地図データ変換コンバータをWebアプリ化した

# はじめに
法務省法務局登記所備付地図データがオープンデータ化されました。
https://www.moj.go.jp/MINJI/minji05_00494.html

これに合わせてデジタル庁から登記所備付地図データ変換コンバータがOSSで公開されました。

https://github.com/JDA-DM/mojxml2geojson/

https://data-gov.note.jp/n/n367f1e368d22

## コンバータのAPI化
デジタル庁のコンバータはpip installしてCUI上から使用するもので、ITエンジニアならちょちょっと使えますが、地図データを望んでいた多くの方々はさっぱりわからん状態で使えていないのが現状です。

そこで、誰でも簡単に使えるようにWebアプリにしてしまおうと思ったのが今回のAPI化のきっかけです。

作ったWebアプリがこちら

https://mojxml2geojson.web.app

フレームワークとしてはフロントエンドは適当にVueで作って、APIはFlaskを使いました。

## ソースコード
ソースコードはこちらに公開しています。
MIT Licenceですので比較的自由に使えると思います。

https://github.com/SohMitian/mojxml2geojosonAPI

## 最後に
法務省がオープンデータを公開し、デジタル庁がツールをOSSで提供する流れは非常に好ましいので、微力ながら貢献させていただきました。
Error previewing graph. Please run `pip3 install cfn-lint pydot --upgrade` の対処法

# エラー内容

VScodeの拡張機能 `CloudFormation Linter` でプレビューを表示しようとするとエラーになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/6fd4e49f-27be-0e1e-23e4-6c3b92de3a69.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/7f78dc68-8638-f60c-75df-8560db862662.png)


# 原因
1. 必要なパッケージがインストールされていない
2. VScodeの `CFn Lint: Path` が違う

# 対処法
## 1. 必要なパッケージがインストールされていないの対処法
エラーで提示された以下のコマンドを実行する。
```
pip3 install cfn-lint pydot --upgrade
```

## 2. VScodeの `CFn Lint: Path` が違う
- 以下のコマンドから `cfn-lint` のパスを取得する。
```shell:Windowsの場合
where.exe cfn-lint
```
```shell:Mac または Linuxの場合
which cfn-lint
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/30fd49d2-33bb-fa68-7158-d66360ff6ffb.png)

- VScodeの設定から `CFn Lint: Path` を変更する。
    - VScodeの設定はWindowsは `ctrl + ,`、 Macは `command + ,`
    - 検索に `@ext:kddejong.vscode-cfn-lint` と入力すると設定が出てくる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/7aff21ce-6933-a689-5b73-298560570e5b.png)
17.セレクタ



```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf8">
    <title>はじめてのCSS</title>
    <meta name="description" content="初めてCSSを勉強するサイトです。">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <p class="underline">おはよう！</p>
    <p>こんにちは！</p>
    <p class="message">こんばんわ！</p>
</body>
</html>
```

```style.css
.message {
  color: green;
}

.underline {
  text-decoration: underline;
}
```
16.CSSとは？


```index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf8">
    <title>はじめてのCSS</title>
    <meta name="description" content="初めてCSSを勉強するサイトです。">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <p>こんにちは！</p>
    <h2>こんばんわ！<h2>
</body>
</html>

```

```style.css
p {
  color: red;
}

h2 {
  color: green;
}
```
草莽Erlang ── 39. lists:member

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## lists:member/2

[lists:member/2](https://www.erlang.org/doc/man/lists.html#member-2)は、リストに指定した値の要素が含まれている場合は`true`を、そうでない場合は`false`を返します。判定には厳密な比較が実施されます。例として`1`と`1.0`は厳密には型が異なります。

```erlang
> lists:member(2, [1, 2, 3, 4]).
true

> lists:member(2.0, [1, 2, 3, 4]).
false

> lists:member({b, 2}, [{a, 1}, {b, 2}, {c, 3}]).
true
```

タプルのリストに対して検索する場合は、それ専用の[lists:keymember/3](https://www.erlang.org/doc/man/lists.html#keymember-3)があります。

## lists:keymember/3

```
keymember(term, integer, [tuple]) -> boolean
keymember(検索ワード, タプルの要素の位置, タプルのリスト) -> boolean
```

[lists:keymember/3](https://www.erlang.org/doc/man/lists.html#keymember-3)は、指定された位置の要素が検索ワードと等しいタプルを探します。見つかった場合は`true`を、そうでない場合は`false`を返します。判定には厳密な比較が実施されます。例として`1`と`1.0`は厳密には型が異なります。

```erlang
% タプルの最初の要素が「b」であるリスト要素は存在するか
> lists:keymember(b, 1, [{a, 10}, {b, 20}, {c, 30}]).
true

% タプルの二つ目の要素が「30」であるリスト要素は存在するか
> lists:keymember(30, 2, [{a, 10}, {b, 20}, {c, 30}]).
true

% タプルの二つ目の要素が「foo」であるリスト要素は存在するか
> lists:keymember(foo, 2, [{a, 10}, {b, 20}, {c, 30}]).
false
```

[listsモジュール](https://www.erlang.org/doc/man/lists.html)には他にもリスト処理のための関数がたくさんあります。

## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1
phpの配列について基本的なことを実際試してみた

# 概要
ドキュメント見ればわかることをあえてやってみた

# なぜ今更？
- ふと、javaではArrayとArrayListってのがあったよなと思いだした
- 混乱して何気なく書いていたphpの配列が急にどんな書き方していたかわからなくなった

# 結論
①配列だと思っていたものはほとんど連想配列だった
②インデックスにする値は型を一定にしておかなければ大変なことになりそう

# 本文
## 初期化してない配列の50番目とかにいきなり値を突っ込んだらどうなるのか
こんなコードを動かしてみた
```php:array.php
$array = [];
$array[50] = true;
print var_export($array, true);
```
出力結果
```
array (
  50 => true,
)
```
**連想配列やん**
じゃあこうしたら...？
```php:array.php
$array = [];
$array[50] = true;
print $array[10];
```
結果...
```
PHP Notice:  Undefined offset: 10 in X:\array.php on line 3
Notice: Undefined offset: 10 in X:\array.php on line 3
```
**それはそう**

## インデックス指定せずに代入したら
```php:array.php
$array[] = true;
print var_export($array, true);
```
結果...
```
array (
  0 => true,
)
```
当然そうなる
じゃあその後にインデックス（？）指定したら...？
```php:array.php
$array[] = true;
$array[50] = false;
print var_export($array, true);
```
結果
```
array (
  0 => true,
  50 => false,
)
```
`$array[] = true;`で自動的に振られたインデックス'0'は普通に連想配列のキー扱いだった
それならさらにこの後自動でインデックス振らせたらどっちになるのか
```php:array.php
$array[] = true;
$array[50] = false;
$array[] = 'bool';
print var_export($array, true);
```
結果...
```
array (
  0 => true,
  50 => false,
  51 => 'bool',
)
```
一番でかいやつの次の値になる

## 突然文字列をキーに指定してみたり
```php:array.php
$array[] = true;
$array[50] = false;
$array[] = 'bool';
$array['key'] = 'value';
print var_export($array, true);
```
```
array (
  0 => true,
  50 => false,
  51 => 'bool',
  'key' => 'value',
)
```
普通に混在する

じゃあその後にキー指定せずに代入すると
```php:array.php
$array[] = true;
$array[50] = false;
$array[] = 'bool';
$array['key'] = 'value';
$array[] = 'next';
print var_export($array, true);
```
```
array (
  0 => true,
  50 => false,
  51 => 'bool',
  'key' => 'value',
  52 => 'next',
)
```
文字列のキー無視された

## 感想
適当に書いたらバグがいっぱい湧きそうだとおもいました
今回は一旦満足したのでこれくらいにしておくけれど、キーの自動型変換とかも一旦試した方が理解が確実になりそうなのでまたやります
CAPTCHA とは

## 勉強前イメージ

自動化されたアクセスを拒否するやつ！

## 調査

### CAPTCHA とは

Completely Automated Public Turing test to tell Computers and Humans Apart の略でキャプチャと読みます。

webページの入力フォームなどで人間が入力しているかどうか確認するために
歪んだ画像が表示されて入力を促されたり、特定のものが写っている写真を選んだりするテストになります。
ログイン等で大量にリクエストがされたら困るところで人間かボットかを調べるために用いられます。
最近は文字の自動認識が向上して以前よりは効果は減少したと言われていますが
自動認識でも難解な画像を用いるところもあるようです。

### CAPTCHA の方式

- 文字認証

上でも記載してますが、文字が歪んだりわざと見えないようにしたテキストを入力する方法です。

- チェックボックス

よくあるのは 私はロボットではありません と書かれたチェックボックスにチェックを入れる方法です。

- 音声認証

ランダムな音声を流して文字列を入力する方法です。

- スライダー型

つまみを指定されたところに動かして人間と認識させる方法。

- 画像認証

上でも記載してますが、バスが写ってる写真にチェックをいれなさい、などいくつかの紛らわしい画像を出して
指定のものが写ってる写真だけを選択させる方法です。

- パズル型

画像認証やチェックボックス同様よく使われているもので
パズルのピースを動かして当てはめる方法です。

- ミニゲーム型

スライダー型の進化系でちょっとしたミニゲームでドラッグ操作を行って人間だと認識させる方法です。

- クイズ型

単語の種類などを簡単な問題に答える認証方法です。
AIなどの進化で突破される可能性が高いなどの課題もあってあまり普及していないみたいです。

## 勉強後イメージ

文字認証型って結構人間でもどっちやろこれ・・・・って思うこと多いよね。

## 参考

- [CAPTCHA認証の方式8つを紹介！活用目的3つや問題点3つも詳しく解説](https://www.fenet.jp/infla/column/technology/captcha%E3%81%A8%E3%81%AF%EF%BC%9Fcaptcha%E8%AA%8D%E8%A8%BC%E3%81%AE%E6%96%B9%E5%BC%8F8%E3%81%A4%E3%81%A8%E7%9B%AE%E7%9A%84%E4%BE%8B3%E3%81%A4/)
- [CAPTCHA【Completely Automated Public Turing test to tell Computers and Humans Apart】](https://e-words.jp/w/CAPTCHA.html)
【Go言語】コマンドについて

こんにちは。
新卒入社3年目文系出身のエンジニアです。
今回は、goのコマンドについてお話していきたいと思います。

#### 環境変数の確認
このコマンドを入力すると、goファイルの環境変数を一覧で表示してくれます。
```
go env
```
また、環境変数を何かしらの値で変更したいときは、以下のコマンドを使用します。
```
go env -w 変更したい環境変数名=値
```

#### ソースコードの整形
インデントの乱れがあるファイルに、「go fmt」を入力すると、
綺麗にコードが整形でき、大変便利です。
```
go fmt 実行したいファイル名
```

#### テスト実行
「go test」を入力すると、テスト結果が返ってきます。
「go test -v」を入力すると、テストの結果がさらに詳しく表示されます。
```
go test
```
```
go test -v
``` 

#### モジュール関連
開発の最初に以下のようなコマンドを入力します。
```
go mod init モジュール名
```
以下のように、go.modというファイル名が出来上がります。
このファイルの中に必要なモジュールが自動的に表示されます。
必要なモジュールが欲しい場合にgo.modが生きてきます。
```go:go.mod
module lesson

go 1.19
```

また、以下のコマンドを入力すると、go.modの中のモジュール情報を整形してくれます。また、関係ないモジュールを自動的に削除してくれます。
```
go mod tidy モジュール名
```

#### 最後に
ざっくりとではありますが、goのコマンドについてまとめてみました。
知識の定着と復習のために書き留めています笑
goを初めて触る方に少しでも参考になっていただければ幸いです。。

#### 参考URL
https://zenn.dev/ryo_yamaoka/articles/595cf9e69229f9

https://zenn.dev/spiegel/articles/20210223-go-module-aware-mode

https://qiita.com/propella/items/e49bccc88f3cc2407745#:~:text=rsc.io%2Fquote%20%E3%81%AF%20Go%20Modules%20%E3%81%AE%E8%AA%AC%E6%98%8E%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AB%E4%BD%9C%E3%82%89%E3%82%8C%E3%81%9F%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%88%E3%81%86%E3%81%A7%E3%81%99%E3%80%82%20package%20main,import%20%28%22fmt%22%20%22rsc.io%2Fquote%22%29%20func%20main%28%29%20%7B%20fmt.Println%28quote.Opt%28%29%29%20%7D

https://kazuhira-r.hatenablog.com/entry/2021/01/03/222459
Ruby クラスとインスタンス2

ターミナルで以下のように出力させるために、コーディングしていきます。<br>

```
# ターミナル
著者: 太郎
タイトル: プログラミングについて
本文: プログラミングを学ぼう！
```

```ruby
class Article

  def initialize(author, title, content)
    @author = author
    @title = title
    @content = content
  end

  def author
    @author
  end

  def title
    @title
  end

  def content
    @content
  end
end
article = Article.new("太郎", "プログラミングについて", "プログラミングを学ぼう!")

puts "著者: #{article.author}"
puts "タイトル: #{article.title}"
puts "本文: #{article.content}"
```
***Article.new***で変数articleに代入しています。
（）の中に実引数。

initializeメソッド内に、インスタンス変数を宣言しています。
インスタンス変数は頭に@がつきますね。

("太郎", "プログラミングについて", "プログラミングを学ぼう!")
この３つの値が、initializeメソッドで宣言されたインスタンス変数（@author, @title, @content）に代入されます。

```ruby
def author
    @author
  end

  def title
    @title
  end

  def content
    @content
  end
  ```
この部分は、インスタンス変数の値を返すための専用メソッドを定義しています。

最後のputs3行は、定義したメソッドを呼び出して、ターミナルに出力されるようになっています。

# initializeメソッド
initializeメソッドとは、インスタンスが定義されたときに、そのインスタンスが自動的に実行処理を定義するインスタンスメソッドです。
【WinUI3】マウスオーバー時のボタンの色を変える方法


<h2>                   
スタックパネルのボタンのマウスオーバー時の色を変えるには
リソースを書き換える
</h2>

<hr>

<pre>
&lt;StackPanel&gt;
    &lt;StackPanel.Resources&gt;
        &lt;SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="Yellow" /&gt;
    &lt;/StackPanel.Resources&gt;
    &lt;Button Content="Test"&gt;&lt;/Button&gt;
&lt;/StackPanel&gt;

</pre>
Github Actionsで詳細なログを出力する（ACTIONS_RUNNER_DEBUGとACTIONS_STEP_DEBUG）

## 必要な設定
早速結論ですが、Secretで下記2つの設定を`true`にします。これら2つを設定することで、デバッグログを出力して、実行の詳細を記録することができます

### ACTIONS_RUNNER_DEBUG
Runnerの実行ログ

### ACTIONS_STEP_DEBUG
Step毎の実行ログ



※ Managing workflow runs（ドキュメント）
https://docs.github.com/en/actions/managing-workflow-runs

## 設定手順
詳細なログを出力したいRepositoryで、Settingタブをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270253/76d0f7db-6919-5d15-04fb-f115b77ddab0.png)
左のメニューから「Secret and Variables」をクリックすると、「Actions」が出てくるので、こちらをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270253/17ac5d11-b176-4c5b-8544-fc63a5295d27.png)
画面左上に表示されている緑色のボタン「New repository secret」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270253/804d8357-709a-c6ad-fe46-7dd7a8e64d54.png)
下記画像のように「Name」に「ACTIONS_RUNNER_DEBUG」、「Secret」に「true」を入れます。そのあとは「Add secret」をクリックし、追加します

「ACTIONS_STEP_DEBUG」についても同様の操作を行います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270253/8eb3d958-73af-2ed2-cded-98c4c52a7712.png)

これで設定は完了です
リバースブルートフォース とは

## 勉強前イメージ

ブルートフォース攻撃が返ってくる？
リバースとか聞くとタイムアウトで時間かけてアクセスを溢れ出すやつってイメージある

## 調査

### リバースブルートフォース とは

逆総当たり攻撃とも呼ばれていて、不正ログインを行う手段の一つになります。

元々 [ブルートフォースアタック](https://qiita.com/miyuki_samitani/items/96087f8a754629c76b9c) と呼ばれるものがありますが
ブルートフォースアタックとは総当たり攻撃とも呼ばれいて
パスワードや暗号に関してありえるパターンをすべて入力し、突破する方法です。
詳細は [こちら](https://qiita.com/miyuki_samitani/items/96087f8a754629c76b9c) をご覧ください

リバースブルートフォースとはブルートフォース、総当たり攻撃の逆で
よく使われるようなパスワード固定でユーザIDを総当りで不正ログインを行います。

ブルートフォースだったらパスワードを総当りで攻撃を行いますが、アカウントロックという何回かパスワードを間違えるとロックが掛かる機能があると厄介です。
特にユーザを指定しない、誰でもいい場合は逆にユーザを変えて総当たりを行うというイメージです。
リバートブルートフォースはアカウントでは基本1回しか間違えないのでアカウントロック機能が無効化されてしまうのです。
これがリバートブルートフォースになります。

### リバートブルートフォースの対策

#### サーバ側

- CAPTCHAの実装

自動化されたアクセスを拒否する実装を行うことで対策となります。

- IPアドレスでの制限

特定のIPアドレスからのログインを見て、連続失敗の閾値を設けてアクセス制限を行うことで
総当たり攻撃をすべてできないようにします。

- パスワードの種類や文字数を増やす

文字数を多くしたりや特殊文字を必須にすることで被害に合うリスクを軽減できます。

#### ユーザ側

- 二段階認証を有効にする

[二段階認証](https://qiita.com/miyuki_samitani/items/d223cf31beb4ba548abe) を行うことで
万が一パスワードがわかってしまったとしてもアカウントを乗っ取られることを防ぐことができます。

- わかりやすいパスワードにしない

ユーザIDと一緒やよく使われるパスワードにしないのが得策です

## 勉強後イメージ

ユーザIDを総当りするのね。

## 参考

- [リバースブルートフォース攻撃｜セキュリティ用語解説](https://www.shiftsecurity.jp/cloud-blog/20210820)
- [リバースブルートフォース攻撃とは？手口や事例・対策法を解説](https://office110.jp/security/knowledge/cyber-attack/reverse-brute-force)
- [リバースブルートフォース攻撃とは？仕組みや危険性、対策について徹底解説](https://cybersecurity-jp.com/column/40622)
🔰機械学習のはじめかた

# はじめに
来年度研究室に入ってくる機械学習未学習の学生に向けて，まとめないとなぁと思ったので，さっそく行動してみました:runner:
Python・機械学習したことないよって人向けにどう勉強していくのかをまとめました．

この記事は以下の人におすすめです．
- 機械学習どうやって勉強すればいいの？
- Pythonの実行環境わからない:crying_cat_face:
- 触りだけでいいから機械学習してみたい！


# 目次
[1. Pythonの環境構築をする](#1.Pythonの環境構築)
[2. Pythonの基本的な書き方について学ぶ](#2.Pythonの基本文法)
[3. 機械学習の基礎を学ぶ](#3.機械学習の基礎)
[4. Kaggeleで実際にモデルを書いてみよう！](#4.実際にモデルを書こう！)

## 1.Pythonの環境構築
まずはPythonを動作させる環境をつくりましょう．
環境構築に必要なものは以下の2つです．
- Anaconda
- VSCode

先人たちが記事をたくさん上げてくれているので，それを見てインストールしてください．
[Anaconda・VSCode　インストール方法](https://qiita.com/manamana/items/38e963ce04f24de4bbe4)

因みにですが，環境構築しなくてもGoogleColabolatoryというGoogle Drive上で気軽にPythonが動かせるものもあります．ですがGPUの使用制限がありますし，自分の環境で動かすわけではないので，守秘義務があるようなデータを使う際は使わない方がいいです．
簡単なモデルなら全然動くので，めんどくさい人は使ってみてください．これからがっつり機械学習するよって人はちゃんとAnacondaをインストールしてくださいね．
[Google Colab 使い方](https://qiita.com/shoji9x9/items/0ff0f6f603df18d631ab)

## 2.Pythonの基本文法
まずはPythonについてお勉強をしましょう．
Pythonの書き方は知ってるって人は飛ばしてください．（DeepわからないのにPythonわかる人がどれくらいいるのかはわからないけど…）
探せば山のように出てきますが，本当に簡単なものだけだと自分は[練習問題55本ノック](https://gotutiyan.hatenablog.com/entry/2020/04/14/174030)をやりました．
後は，[Numpy100本ノック](https://github.com/rougier/numpy-100/blob/master/100_Numpy_exercises.md)・[Pandas100本ノック](https://qiita.com/kunishou/items/bd5fad9a334f4f5be51c)等たくさんノックをしてくれます．
どこかの監督と違ってちゃんとしたノックなので，自分に必要なものをこなしておきましょう．
（え明日試合？）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/5a26f610-daf4-cf48-9c61-2d7db8df05c6.jpeg" width="100">
後は競技プログラミング等にトライするのも良いと思います．AOJやAtcoderですね．
Atcoderは緑ランクくらいになると就活でも好印象だと聞いたことがありますよ👂


## 3.機械学習の基礎
次にDeepLeaningの基礎知識を学びましょう．

概念的な部分は，Qiitaの別記事でまとめてあります．


コードについては調べればたくさん出てくると思います．
Pythonには機械学習用の様々なライブラリが用意されています．大体は,PytorchかTensorflowのどちらかを使います．Chainerで書いてるコードもたまにありますが，あれはオススメしません…（メジャーアップデートが終了したとも聞きました👂）
私はPytorch派閥なので，ここではPytorchについてお話します．最近の論文に付属しているコードもPytorchの方が多い気がします．これも先人の記事を拝借しましょう．[Pytorch超入門](https://qiita.com/miyamotok0105/items/1fd1d5c3532b174720cd)
私のQiitaにもPytorchで様々なタイプのDeepを書いたコードを載せています．参考程度に確認するのはいいかもしれません．

因みにですが，DeepLearning （深層学習）は機械学習に内包されています．AI ⊃ 機械学習 ⊃ 深層学習　のイメージです．
![AI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/5928a6b9-46c3-5f8e-7d52-0ec21bada345.png)


## 4.実際にモデルを書こう！
では実際にモデルを書いてみましょう．
こういう時には大体MNISTが使われますが，あれはデータ前処理なしでそのまま入れればそこそこいい結果がでます．研究等では，元のデータそのままでは上手くいかないことが多いと思います．そのため，データ解析→データ前処理→モデルへ導入　という流れが必要です．

それを学ぶために[Kaggele](https://www.kaggle.com/)のチュートリアル的なコンペである[Titanic - Machine Learning from Disaster](https://www.kaggle.com/c/titanic)をやってみましょう．

https://www.kaggle.com/c/titanic

このコンペはタイタニック号の乗客に関するデータを用いて，事故で生存したか否かを予測するタスクです．データには欠損値が多かったり，予測に必要のない特徴量があったりと，良い精度を出すにはデータの解析と前処理が必要です．このデータ解析・前処理は非常に良い勉強になると思います．また，Kaggeleでは他の人が公開しているコードを見ることもできます．上級者のコードをみて勉強するのも◎です．

https://www.kaggle.com/competitions/titanic/code

精度80%程度で上位2%くらいには入るので（チュートリアル的なコンペなので，みんなガチじゃないだけかもだけど），それくらいを目指してコードを書いてみましょう．

Kaggeleには，画像処理タスクなどもありますので，様々なモデルを学ぶことができます．どんなタスクに対してもモデルを考えられるようになればカンペキですね👍



# さいごに
はじめてQiitaを書きました！
今後もNNについて学んだことをまとめがてら共有する記事を書いていく予定です:hugging:
ServiceNow Flow Designerを再起動させる方法

# Flow Designerを再起動させる方法
Workflowの後継であるFlow Designerですが、
Flow Designerの処理は一方通行で処理を前段階に戻すという事が出来なくなっています。
Workflowはその辺自由に設定できたので、少し不便です。
どうしてもFlow Designerで処理を戻したい場合、稼働中のFlowを一旦終了してから
再起動させる、というスクリプトで強引ですが対処は可能です。
（再起動時はフラグ等セットしておいてifアクティビティと組み合わせる事で任意の箇所からスタートさせる、といったFlow側制御は必要になってくるかと思います） 弊社ブログへも[同様の記事を投稿](https://alpcom.co.jp/blog/20230127-2/?utm_source=Qiita&utm_medium=post&utm_campaign=ysi&utm_id=20230127-2)しております。

以下、スクリプト例です。

```javascript
		// 稼働中フローの終了
		var flow = new GlideRecord("sys_flow_context");
		flow.addQuery("source_record", "フローを修了させたいレコードのsys_id");
		flow.addQuery("state", "WAITING");
		flow.query();
		if (flow.next()) {
			sn_fd.FlowAPI.cancel(flow.getUniqueValue(), 'Canceling Flows');
		} 

		// フローを再稼働
		try {

			// 引数inputsはフローのTriggerごとに異なる。TriggerがService Catalogであれば以下をセット
			var inputs = {};
			inputs['request_item'] = "フローを再稼働させたいsc_req_itemのGlide Record";
			inputs['table_name'] = "sc_req_item";

			var contextId = sn_fd.FlowAPI.startFlow("稼働させたいFlowのname", inputs);	

		} catch (ex) {
			var message = ex.getMessage();
			gs.info(message);  
		}
 }
```

引数inputsが詳細な解説ページが無いのでちょっとわかりづらいですが、おそらく[公式Doc](https://docs.servicenow.com/en-US/bundle/tokyo-servicenow-platform/page/administer/flow-designer/reference/flow-triggers.html)の
「Data pills available by trigger type」に記載されているものをセットすればよさそうです。

また、もしFlow内でAsk for Approvalアクションを用いてグループ承認レコード（sysapproval_group）を作成している場合、フローキャンセルとあわせてそのレコードの承認状況（approval）もrejectedに更新してあげる必要がありました。どうやらフロー再起動時、生きている状態のグループ承認レコードが残っているとAsk for Approvalアクションで承認レコードが作成されないみたいです。

参考
[Flow Designer trigger types](https://docs.servicenow.com/en-US/bundle/tokyo-servicenow-platform/page/administer/flow-designer/reference/flow-triggers.html)
[FlowAPI - Scoped, Global](https://developer.servicenow.com/dev.do#!/reference/api/tokyo/server/sn_fd-namespace/ScriptableFlowAPI)
【GoogleColaboratory】無料でRAMの上限を引き上げる

# はじめに
StableDiffusionのモデルをCoreMLに変換する作業行いたくて、
最初はローカルで試してたのですが、メモリ不足でキルされてしまいうまくいきませんでした。
次にGoogleColaboratoryで試してみたのですが、こちらもメモリ不足でキルされてしまいます。
調べると無料でメモリ上限を上げることができると書いてあったので試してみたら本当に上限が上がったので記録しておきます。

# やりかた
### 書き換える
① 「ファイル」を選択します
② 「ダウンロード」を選択します
③ 「.ipynbをダウンロード」を選択します
![スクリーンショット 2023-01-27 19.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e1a314cd-5d82-a3a5-362b-0969fb14ce5e.png)

JSONとして開きます。(私はXcodeで開いた)
![スクリーンショット 2023-01-27 20.00.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1f6f3fe3-a988-efd5-79fe-f36ff95c9114.png)

`provenance`の下に以下をコピペします。
```json
"machine_shape": "hm"
```
こんな感じになります。
![スクリーンショット 2023-01-27 20.01.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/aba9e1a9-3555-fd43-7810-3e32362e587f.png)

### 読み込む
[こちら](https://colab.research.google.com/)からGoogleColaboratoryにはいります。
① 「アップロード」を選択します
② 「ファイルを選択」を選択します
![スクリーンショット 2023-01-27 20.04.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/72504a8c-b510-05e5-76e9-689e823d0ddc.png)
③ 先ほど書き換えたファイルを選択します
④ 「開く」を選択します
![スクリーンショット 2023-01-27 20.05.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/9e408436-8e4f-0615-342b-4ca17ab1322a.png)

# 確認する
RAMのところにカーソルを合わせると詳細が表示されます。
12.68GBから25.45GBに上限が上がってるのが確認できます。
|設定前|設定後|
|-|-|
|![スクリーンショット 2023-01-27 19.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/605078b8-06b1-5958-1e58-f938fc8837d0.png)|![スクリーンショット 2023-01-27 19.46.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/154d161d-9d36-362d-a6f9-5bdf4bc0d3ef.png)|

# 参考記事
https://zenn.dev/hashito/articles/713ad03a2e0950283297
windowsのコマンドについて少し勉強する記事

こんにちは。
最後に投稿した日から7年経っててガクガクしているyuwaitaです。

ある日、ファイル名変更のためのwindowsのコマンドについて、teratailで質問してみたんですよ。

https://teratail.com/questions/21ti1826t8yhmn

すると直ぐに素晴らしい回答を頂いて感謝しかなかったです。

しかし全く理解できないコードだったので、勉強のため再びQiitaを開きました。回答頂いたコードは以下。

```
for /l %%I in (1,1,100) do call :RENAME %%I
exit /b

:RENAME
set /a J=1000+%1
ren *(%1).html %J:~1,3%.html
exit /b
```

これを読み解いていくためのページです。
※間違っていることが書いてあったらご指摘いただけるとありがたいです。

# 読み解く

### for /l %%I in (<開始値>, <増分>, <終了値>) do <実行コマンド>
値をループする構文です。
`%%I`というやつは変数。

### call <実行するバッチ>
バッチやラベルを呼び出す構文です。

### :RENAME
コロン（:）を一番前につけるとラベルになるらしい。
2つともを`:RENAMESURUYO`とかにしても問題なく動きます（あたりまえ）。
2つめの`:RENAME`のあとに書かれたことを20回ループするのですね。ふむふむ。
しかしなぜ`:RENAME %%I`と、あとに変数がつくのかよくわかりません。とりあえず次へ。

### exit /b
処理を終了させるコマンドです。`/b`が無いと全終了しちゃう。詳しくは参考URLを。
無くても動くけど入れとくと親切的なもの。

### set [オプション] [環境変数名=[値]]
環境変数を設定する構文です。
`/a`はオプションで、値を数式として評価するためのもの。ふむふむ。
`J`は環境変数名。
`1000+%1` これなに。わかんない。とりあえず次へ。

### ren <変更前ファイル名> <変更後ファイル名>
ファイル名やディレクトリ名を変更する構文です。つまり
`*(%1).html`
から
`%J:~1,3%.html`
へ変更する。なるほど・・・？

### このバッチは何をやっているのか

ここで、このバッチが実際に何をやっているのか、画面上で内容を見てみたいと思って調べると
`cmd /k`が、指定したコマンドを実行した後に、起動したコマンドプロンプトを終了しないでいる構文でした。
`exit /b`を消して、for　の次の行に`cmd /k`を設置して動かしてやると。。こんな表示が。
```
C:>for /L %I in (1 1 100) do call :RENAME %I

C:\>call :RENAME 1
C:\>set /a J=1000+1
C:\>ren *(1).html 001.html

C:\>call :RENAME 2
C:\>set /a J=1000+2
C:\>ren *(2).html 002.html

以下100まで続く
```

これで、だいたい仕組みがわかってきました。

### もっと詳しく調べる

前にパーセント（%）を前に付けると、環境変数を呼び出すことができるとのこと。
`%J`というのはつまり、setで定義したJの変数を呼び出しているのですね。ふむふむ。

`%1`というのは、引数で、コマンドに引き渡すことができる。。。？

。。。🤔

あっ！そうか。おそらく、`:RENAME %%I`の`%%I`が引き渡す元となるものかな。
つまり、%%I　が　1　のときは、%1　は　1、%%I　が　50　のときは　%1　は　50
になるってことですね。ふむふむ。

`%J:~1,3%.html`は、J　に入っているのが　1001　だとするとこれを　001　にするためのものですね。
%J%　で　J　に入っているものを取り出せるので、:~1,3　というのは、1桁から3桁までを取り出す・・といった指定なのでしょう（予想）。


### もう一ついただいた回答について

上のほかに、もう一つ別の回答例をいただいていました。
ここまで調べた上で改めて見てみると、何を書いてるか全くわからなかったのに、今ではだいぶわかってきていて面白いです。

```
for %%F in (*^(*^).html) do call :RENAME %%F
exit /b

:RENAME
set A=%1
set B=%A:*(=%
set C=%B:).html=%
set /a D=1000+C
ren %1 %D:~1,3%.html
exit /b
```

こちらの例では、1から100までのループではなく
ファイル名そのものをループしていく内容になっているようです。
ファイル名を分解していき、C に数字のみを取り出している様子がうかがえます🤔

というわけで、コマンドについて知見を深められました。
今までバッチ処理について検索しても、まったく情報を得ることができず苦労していましたが、
この記事を書くために調べる過程で「どのようなワードで検索すれば良いか」がわかってきて、
次回からはやりたいことを自分で調べて書けそうな自信がつきました（自信だけ）。

ファイル名変更については、今まではソフトでなんとかしてたのですが、
バッチ処理がわかってくるとちょっと楽になるので、どんどん使っていきたい所存です。

# 参考URL

https://teratail.com/questions/21ti1826t8yhmn

https://windows.command-ref.com/

https://jj-blues.com/cms/wantto-exitb/

https://www.pg-fl.jp/program/dos/doscmd/str_colon.htm

https://www.pg-fl.jp/program/dos/doscmd/str_percent.htm

https://jj-blues.com/cms/coomand-argument/

https://jj-blues.com/cms/wantto-cutstring/

https://jj-blues.com/cms/column-spaceinbatfile/
DockerコマンドだけでWekanを起動する

## はじめに
ローカルで自分の管理用などに簡単に立てたいと思った。
docker-composeなどを使用した方法はころがっているが、そんなのいらない。コマンドだけでやりたい。

それでは、早速。
#### 1. まずは、MongoDBを起動
```sh
docker run -d --restart=always --name wekan-db mongo
```


#### 2. 次に、Wekanを起動

```sh
docker run -d --restart=always --name wekan --link "wekan-db:db" -e "WITH_API=true" -e "MONGO_URL=mongodb://wekan-db:27017/wekan" -e "ROOT_URL=http://localhost:8080" -p 8080:8080 wekanteam/wekan
```


`http://localhost:8080/`アクセスしてみる。




## ドキュメント

ここに方法が乗っている。

https://github.com/wekan/wekan/wiki/Docker#development
アクション抑止に作用したコントロール(旧ガードレール)の特定方法　The following hook(s) failed: [ControlTower::Guard::Hook]

## 発生した事象について
ECSタスク定義を作成しようとしたところ、エラーが発生して作成できませんでした。
メッセージより<strong>ControlTower</strong>の何かがエラー原因のようです。

![Inkedimage (42)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2988434/28270b1f-5de6-cd47-3ab7-0050e2f10bd9.jpeg)

The following hook(s) failed: [ControlTower::Guard::Hook]



## 困ったこと
有効化したコントロールが<strong>300個以上</strong>もあるため原因が特定できません！
ネットを探しても情報が無く、CloudtrailでECSのログを探しても見つからないので困りました。

## 解決へ
サポートに問い合わせたところ、すぐに回答が返ってきました！
どうやら<strong>Cloudwatchロググループのcfn-hooks/ControlTowerGuardHook</strong>で確認できるようです。

![image (54).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2988434/46ec3287-b972-59b1-8459-7c35da794891.png)


[CT.ECS.PR.6]: Require Amazon ECS containers to allow read-only access to the root filesystem
[Fix]: Set the 'ReadonlyRootFilesystem' property to 'true' for all 'ContainerDefinitions'


アクション抑止に作用したコントロールと、その修正方法まで記載されてますね！

## まとめ
アクション抑止に作用したコントロールの特定方法を知ることが出来ました。
公式ドキュメントにもまだ載せていない情報のようなので、同じように困っている方の参考になれば幸いです。

## 補足情報
- [Amazon ECSとは](https://aws.amazon.com/jp/ecs/)
- [AWS Control Towerとは](https://aws.amazon.com/jp/controltower/)
- [コントロール(旧ガードレール)とは](https://docs.aws.amazon.com/ja_jp/controltower/latest/userguide/guardrails.html)
Stream#max() 

max,minは、Comparatorを渡す
```java
public class Outer {
    public static void main(String[] args) {
        List<String> l = List.of("C","X","A");
        l.stream().max((a,b) -> a.compareTo(b)).ifPresent(System.out::println);
        l.stream().min((a,b) -> a.compareTo(b)).ifPresent(System.out::println);
    }
}
```
```
X
A
```
RailsでMySQLの全文検索をいい感じに書きたい


バージョン Rails7.0, MySQL8.0

(AND -(OR) + OR -(OR)) みたいなことをやりたいなと思って、色々こねくり回したらこんなコードができました。

直接ANDとORをかけると途端に遅くなってしまう(MySQLが一度に使えるインデックスのなんかの制約に引っかかっているぽい？ 要調査）ので、サブクエリを使って一度全体を引いた後に、ANDがあれば絞り込むみたいな挙動にしてみました。

モデルに直接書いたけどconcernぽくもできそう。


```ruby

class Item < ApplicationRecord
  SUB_T = 'sub'

  class << self
    # 前提: search_target_column には検索対象となる文字列が入っていて、fulltext indexが貼られている

    # 作りたいSQL
    # select
    #   T1.*
    # from
    #   (
    #     select
    #       *
    #     from
    #       items
    #     where
    #       match(search_target_column) against ('ケーキ チョコレート YY支店 XX支店' in boolean mode)
    #   ) as T1
    # where
    #   match(T1.search_target_column) against ('+ケーキ +チョコレート -ガム -キャンディ' in boolean mode)
    #   or match(T1.search_target_column) against ('YY支店 XX支店 -ガム -キャンディ' in boolean mode);

    # and: 'ケーキ チョコレート' or:'YY支店 XX支店' ignore:'ガム キャンディ'
    def search(and_search_text: '', or_search_text: '', ignore_text: '')
      and_targets = and_search_text.split(' ')
      or_targets = or_search_text.split(' ')
      ignores = ignore_text.split(' ')

      sub_query = or_where(
        targets: and_targets + or_targets,
        ignores:,
        table_name:,
      )

      model = from("(#{sub_query.to_sql}) AS #{SUB_T}")

      model.and_where(targets: and_targets, ignores:, table_name: SUB_T)
           .or(model.or_where(targets: or_targets, ignores:, table_name: SUB_T))
           .select("#{SUB_T}.*")
    end

    def and_where(**kwargs)
      fulltext_where(**kwargs.to_h.merge(operator: '+'))
    end

    def or_where(**kwargs)
      fulltext_where(**kwargs.to_h.merge(operator: ''))
    end

    def fulltext_where(operator:, targets:, ignores:, table_name:)
      targt_words = targets.map { |word| "#{operator}#{word}" }
      ignore_words = ignores.map { |word| "-#{word}" }
      matcher = (targt_words + ignore_words).join(' ')

      where("match(#{table_name}.search_target_column) against (? in boolean mode)", matcher)
    end
  end
end

```

こういう雰囲気のコード書くの久しぶりなので、頭の体操になって楽しかった〜
String#compareTo()

sortに渡すComparatorのbaseになる考え方
returnが1以上になるとsortはひっくり返す

```java
public class Outer {
    public static void main(String[] args) {
        String s1 = new String("A");
        String s2 = new String("B");
        System.out.println(s1.compareTo(s2));
        System.out.println(s1.compareTo(s1));
        System.out.println(s2.compareTo(s1));
    }
}
```
```
-1
0
1
```
findAny findFirst method with parallelStream

findFirstは1個目の要素が保証される
findAnyは1個目の要素が保証されない
```java
public class Outer {
    public static void main(String[] args) {
        List<Integer> l = List.of(1,2,3,4,5);
        l.parallelStream().findAny().ifPresent(System.out::println);
        l.parallelStream().findFirst().ifPresent(System.out::println);
    }
}
```
```
3
1
```
stream map method

Function interfaceを渡す
return type is Stream\<R>
```java
public class Outer {
    public static void main(String[] args) {
        List<Integer> l = List.of(1,2,3,4,5);
        l.stream().<String>map(a -> String.valueOf(a) + "xxx").forEach(System.out::println);
    }
}
```
```
1xxx
2xxx
3xxx
4xxx
5xxx
```
【PHP】配列の存在チェック    if(!empty(array_filter($配列))){

連想配列内でどれか一つでも要素が存在するかをチェック

# コード
```PHP
<?php 
$fruits_data = [$fruits['apple'],$fruits['grape'],$fruits['peaches'],$fruits['orange']];?>
if(!empty(array_filter($fruits_data))){?>
    <table>
        <tr>
            <th>りんご</th>
            <th>ぶどう</th>
            <th>ピーチ</th>
            <th>オレンジ</th>
        </tr>
        <tr>
            <td><?php echo $fruits['apple']?:'売り切れ'; ?></td>
            <td><?php echo $fruits['grape']?:'売り切れ'; ?></td>
            <td><?php echo $fruits['peaches']?: '売り切れ'; ?></td>
            <td><?php echo $fruits['orange']?: '売り切れ'; ?></td>
        </tr>
    </table><?php 
}?>
webエンジニアを目指して

現在、SES(客先常駐)企業でフロントエンドエンジニアをしているbachikoriです。

今日からwebエンジニアへを目指して頑張ったことや気づいたことを投稿できたらと思います。
初めの投稿となりますので自己紹介や現在のスキルなどを綴りたいと思います。

# 自己紹介
現在、22新卒でSESの企業に所属しています。
大学は文系科目で情報系の学部に入りましたが、当時はプログラミングにあまり興味が持てませんでした。大学３年生後半に友達と受けたプログラミングの授業をきっかけにJavaScriptを勉強しはじめ、大阪から上京してきました。

# 現在のスキル
- HTML/CSS
- JavaScript
- React(useState, useEffect, react-router-domが使える程度)
- ruby on rails(progateの課題を全て完了した程度)

これからこちらの[gitihub](https://github.com/bachikori)に新しく学んだことを共有していきます。

# さいごに
まだまだ未熟者ですが少しづつ成長していくので見守っていただければと思います。

技術内容やそれ以外でも興味があれば、ぜひお声がけください！
stream reduce method

reduce methodは、BinalyOperatorを引き渡し累積的に処理する
return type はOperator＜T＞
初期値を渡すと、初期値の型を返す

```java
public class Outer {
    public static void main(String[] args) {
        List<Integer> l = List.of(1,2,3,4,5);
        l.stream().reduce((a,b) -> {
            System.out.print("a:" + a);
            System.out.println(" b:" + b);
            return a+b;
        }).ifPresent(System.out::println);
        int sum = l.stream().reduce(100,(a,b) -> {
            System.out.print("a:" + a);
            System.out.println(" b:" + b);
            return a+b;
        });
        System.out.println(sum);
    }
}
```
```
a:1 b:2
a:3 b:3
a:6 b:4
a:10 b:5
15
a:100 b:1
a:101 b:2
a:103 b:3
a:106 b:4
a:110 b:5
115
```
Vue3 / Nuxt3 – 子コンポーネントのカウントを合算して親コンポーネントに表示する、リセットする

無理矢理な実装かもしれないのでもっと良い方法があるかも

# 要点

- 親では配列としてカウンタの値の器を複数持っておく
- 子では対応する親のカウンタ値を直接カウントアップする
- 親では全カウンタの合算値を表示する

# 親 ( IncrementParent.vue )

```html
<!-- https://teratail.com/questions/k9a3uom29j319c -->

<template>
  <div>
    <div>
      Total Count
      {{ totalCount }}
    </div>
    <button @click="reset">Reset</button>

    <div v-for="numbering in numberings" v-bind:key="numbering">
      <CountupChild :numbering="numbering"></CountupChild>
    </div>
  </div>
</template>

<script>
import CountupChild from '../components/CountupChild.vue'

const countupLoop = 3; // 子コンポーネントを作る数
const defaultNumbers = [...Array(countupLoop)].map((_, i) => 0); // [0,0,0] のような初期値

export default {
  data() {
    return {
      numbers: defaultNumbers,
      numberings: [...Array(countupLoop)].map((_, i) => i)
    }
  },
  // カウンターの値を全て合算
  computed: {
    totalCount: function () {
      return this.numbers.reduce(function (sum, element) {
          return sum + element;
        }, 0)
    }
  },
  methods: {
    reset() {
      this.numbers = [...Array(countupLoop)].map((_, i) => 0)
    }
  },
  components: {
    CountupChild
  }
}
</script>
```

# 子 ( CountupChild.vue )

```html
<template>
  <div>
    <p>Count ({{ $parent.numbers[this.numbering] }})</p>
    <button @click="increment">+1</button>
  </div>
</template>
<script>
export default {
  props: {
    numbering: {
      type: Number,
    }
  },
  methods: {
    increment() {
      this.$parent.numbers[this.numbering] += 1;
    },
  }
}
</script>
```

# 動作例


子のカウントアップの合計値が親に表示されている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/1864700b-7cad-9c82-746d-4318cb7bb3d3.png)


リセットすると全てゼロになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89618/07ccd915-356a-45cc-9483-1ba3f860a930.png)


# 環境

- nuxt@3.0.0

# チャットメンバー募集


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

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


# Twitter

https://twitter.com/YumaInaura
Googleプロジェクト管理：スクラムボード

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/1c9e3622-d11d-e6dd-1bb7-f12b3fef8845.png" width="800">

# カンバンボードとは

[以前、バーンダウンチャートを使って進捗を視覚化することの重要性について学びました。][ref1]そして朗報です。スプリント中のチームの進捗を支援する視覚的なツールは他にもあります。それは、「カンバンボード」です。

[ref1]: https://qiita.com/mapami/items/870a06c08ea701413955

チームによっては、これをカンバンボードではなく、 ***<font color="MediumBlue">スクラムボード</font>*** と呼ぶこともあります。この2つには細かい違いはありますが、基本的には同じツールを指しています。

# ３つの主要な機能

スクラムガイドでは、スクラムボードが何であるかは正確に規定されていませんが、市場で入手可能ないくつかのスクラムツールは、カンバンボードにいくつかの機能を追加したボードを提供しています。これらの機能は、特にスクラムに適しています。どのボードも、スクラムチームにとって素晴らしいスプリント追跡ツールになる3つの主要な機能を持っています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/24fb874c-1b8b-1b72-5113-f1e1f1b5e821.png" width="600">


### 1.可視化

可視化は、学習と追跡のための重要な戦略となりえます。

このカンバンボードは、私たちが知るべきすべてのことを一目で伝えることができます。ボード上の議論したい特定の作業項目を指さしたり、作業項目をチェックインするときにバリエーションや色、大きさのある画像を使用したり、チームのどこに課題があるのかに気づいたりすることができます。このように見える化しないと、どこを改善すればいいのか、なかなか見えてきません。

### 2.WIP制限

***<font color="MediumVioletRed">『WIP制限は、チームが常にアクティブに作業している作業項目の数を制限するもの』</font>***

このボードを使えば、WIP制限がどこにあるのか、簡単に気づくことができますこれは、[スクラムの価値の1つであるチームの集中][ref1]を提供します。

[ref1]: https://qiita.com/masami-atwvn/items/defb8bbabfd12159c898

マルチタスクなんてありえないという考えを聞いたことがありますか？ スクラムでは、それはとても正しいことです。そして、***<font color="MediumBlue">仕事が多ければ多いほど、効率は悪くなります。</font>*** カンバンやスクラムボードを使うとき、各チームは自分たちの構成や文脈に基づいてWIPの制限を設定することができます。こうすることで、チームがWIPリミットを超えているときに、本当に明白に気づくことができるのです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/d75a8f50-c95c-0b72-6e7b-dcab05bd42b8.png" width="600">

### 3.仕事の流れ

そして最後に、カンバンボードを使うことで、チームの実行プロセスを通じた仕事の流れをよりよく理解することができます。

カンバンボードを使い、チームは

- **To do**
- **Doing**
- **Done**

という段階を経てアイテムを移動させます。

この作業はしばしばデイリースクラムで行われるが、チームはいつでもアイテムを移動させることができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/8f73f696-65d1-4bd7-d5bd-c40aa6cc270c.png" width="600">
Googleプロジェクト管理：ベロシティ

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/1c9e3622-d11d-e6dd-1bb7-f12b3fef8845.png" width="800">

スクラムチームがスプリントとプロダクトバックログ全体の進捗に合わせて作業を管理するための、2つの非常に重要な概念があります。

その2つの概念とは、
- バーンダウンチャート
- ベロシティ

です。

今回、ベロシティをご紹介します。

# ベロシティとは

***<font color="MediumVioletRed">『ベロシティとは、1つのスプリントで、平均して何ポイントを費やしたかを示す指標である』</font>***

スプリントプランニングを行うとき、チームは ***<font color="MediumBlue">少なくとも3回のスプリントの平均ベロシティ</font>*** を使って、スプリントバックログにどれだけのアイテムを安全に追加できるかを決定します。

# ベロシティを計算する際の注意点

#### 注意点１

***<font color="MediumBlue">良いベロシティや悪いベロシティというものはありません。</font>*** ベロシティは、チームが歴史的に決められたタイムボックスで達成できたことを意味します。 

もしチームがベロシティを気にすることで、自分たちのパフォーマンスが低下しているように見えるとしたら、結果としてチームの文化が損なわれてしまうかもしれません。

#### 注意点2

***<font color="MediumBlue">自分のチームのベロシティを他チームのベロシティと比較することは無意味です。</font>*** 

例えば、私は現在3人のチームに所属していますが、1週間のスプリントで70ポイントを消費しているので、ベロシティは70です。しかし、以前いた5人のチームでは、2週間のスプリントのベロシティは120ポイントしかありませんでした。あるチームが他より優れていたのでしょうか？　いいえ。ただ、違うだけです。

安定したベロシティと、優先順位と見積もりを含む洗練されたバックログを手に入れたら、信じられないほど貴重なスーパーパワーを解き放つことができるのです。

#### 注意点3

あなたは、ステークホルダーとスポンサーに2つの重要なことを伝えることができます。

- ***<font color="MediumBlue">プロダクトバックログ全体を完成させるのにかかる時間</font>*** 
- ***<font color="MediumBlue">特定の時間までにバックログのどれだけの部分を完成させることができるか</font>*** 

物事がいつ完了するかを自信を持って予測する能力は、アジャイルとスクラムの最も強力なツールの1つです。

# ベロシティを使った強力な見積もり

あるチームが過去3ヶ月間、毎月のスプリントで平均200ポイントを獲得していると想像してみましょう。

このチームは、プロダクトバックログに1500ポイントが残っています。彼らは、プロダクトバックログ全体を完成させるのに、およそ7、8スプリントかかると言うことができるでしょう。

7月になって、チームが1月1日までに何ができるかを知りたいとしたらどうでしょう？問題ありません。それは5ヶ月先です。バックログを上から順に見ていき、1000ポイントに達したら線を引くだけでいいのです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/7ac768dc-b3ae-acf6-3c59-11ee3bc8cf63.png" width="700">

これは、チームの過去の実績に基づいた、かなり自信のある見積もりです。かなり強力です。

### 注意点

- ベロシティは、製品の発売日を決めたい外部のステークホルダーから圧力として使われる可能性があります。
- ベロシティは、チームが見積もり期日に間に合わなかったときに、誤った期待や厳しい競争文化を生み出す可能性もあります。
    - なぜなら、チームが各イテレーションで何を提供できるかを本当に理解するには、数スプリントを要するからです。
    - また、あまりに多くの日程を事前に計画すると、発生する変化や問題を考慮できなくなります。

したがって、***<font color="MediumBlue">納品予定日をコミットメントとして使用しない</font>*** ように注意する必要があります。


# 安定したベロシティ

スプリントを開始した時点では、1スプリントで完了した平均ポイント数を計算するための歴史的根拠がないため、ベロシティを正確に判断することはできません。最初のスプリントでは、チームはどれだけのアイテムを完成させることができるか、大まかな予測を立ててスタートします。

どのチームでも、安定したベロシティに達するまでに複数のスプリントが必要になることがありますが、それは全く普通のことです。チームが見積もりや共同作業に慣れるにつれて、ベロシティは安定し始めるはずです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/07f56306-74cf-775e-1d52-178e80583f0a.png" width="700">
Laravelのクエリビルダーの戻り値まとめ


| メソッド |型|戻り値|
|:-----------|------------:|:------------:|
| create      | object        | 作成レコード         |
| insert    | boolean      | true,false       |
| update       | integer        | 影響を与えたレコード数         |
| delete         | integer          | 影響を与えたレコード数           |
| save       | boolean       | true,false       |



```hoge.php
/**
 * @return bool
 * 
public function hoge(): bool
{
    $result = User::whereName('太郎')->delete();

    return $result;
}
```
phpdocが警告してくれて調べたら、delete()の戻り値は真偽値ではありませんでした。

参考：https://readouble.com/laravel/8.x/ja/queries.html
laravelでwebapiを使ってjsonでデータを全件受け渡す

## はじめに
laravelだったりのバックエンド側をやっていると、通常コントローラで書き書きしてビュー側にデータを渡すことが多い。
```
$posts = Post::get();
return view('posts.index', compact('posts'));
```
のような感じで。

ただ場合によってビューに返す場合以外に、`json`で返すこともある。
バックエンドで完結する場合ではなく、Reactだったりのフロントでビュー側を作成する場合だ。
この場合はとってきたデータをビューに返すのではなく、jsonで返してあげる必要がある。

今回はそんなjsonでの返し方について書いていく。

## なぜフロントとバックエンドを分けるのか
- よりモダンなWEBサイトを作成するため
- バックエンド側とフロント側で分けて作業ができるようになるので効率的に作業を進められる

などそれ以上に分けるメリットと理由があるのだが、ものすごく理解しているわけではないので今回はこのくらいの理解で。
またいつか改めてSPAとかまとめていきたい。

## WebAPIの作り方
現状やっている事的にはこれまでにLaravelでやってきたことと大きく変わることでもなさそう。
ビューに返していたデータをjsonで返せばいいだけ。
ルーティング書く場所とか若干違うためそのあたり変える。

### ルーティング
Laravelを扱っていると基本的にルーティングは`route/web.php`にまとめていく。
ただWEBAPIの場合は、同じconfigにある`route/api.php`にまとめていく。
書き方はどちらも同じような形。
```api.php
<?php

use App\Http\Controllers\PostController;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::get('/index', [PostController::class, 'index']);
```

### コントローラ
コントローラの書き方も基本的には変わらない。
返し先がビューではなく`json`となるだけ。
```postController.php
public function index()
    {
        $posts = Post::get();
        return response()->json($posts);
    }
```

書き方はクエリビルダ通りにかけるので、
SELECT句やWHERE句なども使って書くことができます。

上記のような形でデータを送ってあげると
json形式で送られます。

```
[
  {
    "id": 1,
    "name": "hoge",
    "item": "apple"
  },
  {
    "id": 2,
    "name": "hogehoge",
    "item": "banana"
  }
]
```

以上