OmniAICreator/Qiita-1.07M huggingface dataset:
Gmailでタスクに登録したいメールを、Gmailの転送機能でTicktickに登録する

こんにちは。はじめまして、Qiita初投稿です。勝手がわかっていませんので変な書き方になっているかも知れませんが、優しい目で見てください笑
## やりたいこと
**Gmailのメールの内容を、できるだけページ遷移せず、Ticktickに書き込みたい**
Gmailで受け取ったメールに対して、なにか行動を起こさなければならない場面ってよくあると思います。その時自分はGmailの内容をコピペして、Ticktickというスケジュール管理アプリに書き込んで、としていたのですが、ちょっと面倒になりました。
なので、GmailさんとTicktickさんの機能で自動的にTicktickに書き込んで頂きます。

## 使用するアプリ
+ Gmail

https://www.google.com/intl/ja/gmail/about/

+ Ticktick（自分は有料版を使っていますが、無料版でも可能なはずです）

https://ticktick.com/

## 操作手順

**Ticktick側**
1. Ticktickの左上の自分自身のアイコン→Settings→Calender＆Mailに遷移

**Gmail側**
1. Mail欄にある自動転送用メールアドレスをコピー（下図の塗りつぶし部分）
![fig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2016894/541e071c-2a0f-756c-471b-729f92773a04.png)

3. Gmailでタスクに追加したいメール画面から、Ticktickの自動転送用メールアドレス宛に転送
Gmailの転送は、メールを開いた画面で`ショートカットキーF`で行うとマウス操作がなくて楽です。転送の際には毎回メールアドレスを入力する必要があるので、`辞書登録`しておくと時短です。

## 動作について
Gmailで転送してからTicktickに反映されるまでの時間は、体感30秒程度です。
もちろん、ご使用の通信状況にもよると思いますが、なかなかスムーズにやってくれていいですね。
## さいごに
こういう連携ってZapierとかのAPI連携ツールを噛ませて行うのが一般的だとおもってました。そうなると、API連携ツールが無料版だと5分くらい反映に時間かかって使い勝手悪いんですよね。Ticktickが自動転送用のメールアドレスを用意してくれているお陰で楽に実現できました。ありがとうTicktickさん。
稚拙な文章だったと思いますが、最後まで読んでくれた方いらっしゃいましたら、ありがとうございました！
Laravel サーバーでのログデバッグ方法まとめ

## 始めに
サーバーのログデバッグ方法（Laravel）について
よく使う、便利な方法を備忘録として記事にしました。
随時更新していきます。

## 環境
| 開発環境    |バージョン |
|-----------|------------|
| __Laravel__ | 8.83.19 |
| __PHP__     | 7.3.10  |

## 通常デバッグ
```PHP:DebugController.php
use Illuminate\Support\Facades\Log;

// 通常デバッグ
Log::debug($value);

// 通常デバッグ（PHP）
var_dump($value);
exit;

// 通常デバッグ（Laravel）
dump($value);
exit;

dd($value);
exit;
```

## デバッグ（マジック定数）
```PHP:DebugController.php
use Illuminate\Support\Facades\Log;

// クラス名の表示（マジック定数）
Log::debug(__CLASS__);

// メソッド名の表示（マジック定数）
Log::debug(__FUNCTION__);
```

## デバッグ（クエリビルダのSQL構文確認）
__クエリビルダで作成したSQL構文、値を確認する__

```PHP:DebugController.php
use Illuminate\Support\Facades\Log;

// SQL作成（例）
$sqlData = DB::table('テーブル名');
    $sqlData->select('カラム1')
    $sqlData->where('カラム2', '絞りたい値')
    $sqlData->where('is_deleted', 1);
$data = $sqlData->first();

Log::error($sqlData->toSql()); // SQL構文取得
Log::error($sqlData->getBindings()); // カラム2の値

```

## 終わりに
閲覧ありがとうございました。
もっといろいろなログデバッグを使いこなしたい今日この頃です。
ご指摘、ご意見等ありましたら、コメントお願いします。
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">

# リリース計画の変更を実施する際に重要な考慮事項

アジャイルはその4つの価値の1つを ["計画に従うことよりも変化への対応を"][ref1]に捧げています。今回、リリース計画の変更を実施する際に重要な考慮事項を紹介します。

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

計画の変更について考える最良の方法は、それを3つの段階に分けることです。

1. 必要な変更を特定する
1. 変更を行うことを決定する
1. 変更を実行する

## 1. 必要な変更を特定する

まず、計画を変更する必要があるかどうかは、どのように判断すればよいのでしょうか。

ここでは、変更候補となりうるプロジェクトの側面として、「スコープ、時間、コスト（またはリソース）」を挙げます。これらは「三つの制約」と呼ばれ、アジャイルや従来のプロジェクトにおける変更を評価するための素晴らしいフレームワークを提供します。


- **<font color="MediumVioletRed">スコープ</font>**
    - ロードマップの内容、バックログの項目、プロジェクトの意図する成果物、意図するユーザーや顧客のことを指す。
    - これは、プロジェクトの「何」である。
- **<font color="MediumVioletRed">時間</font>**
    - 時間的な要素や一定期間の成果物の配置を指す。
    - ロードマップのタイムライン、リリーススケジュール、あるいはスプリントの期間などが含まれる。
    - これは、プロジェクトの「いつ」である。
- **<font color="MediumVioletRed">コストやリソース</font>**
    - 開発チーム、プロジェクトマネージャー、プロダクトオーナー、その他の「ビジネスパーソン」の構成や、成果物を作成するために利用できる設備などを指す。
    - これは、プロジェクトの「方法」である。

アジャイルプロジェクトは、これら3つの領域のいずれにおいても、変更に対してオープンであり、必要な変更は、プロダクトオーナー、プロジェクトマネージャー、スクラムマスター、または開発チーム自身を含む、プロジェクトのあらゆるステークホルダーによって特定される可能性があります。

特定された変更の情報源は以下の通りです。
- 初期プロトタイプに対する顧客フィードバックの結果、新機能が追加され、一部機能が削除される　**（スコープ変更）**。
- レトロスペクティブにより、人員不足のエリアが特定された **（コストまたはリソースの変更）** 。
- プロジェクトの重要な依存関係または成果物の日付がシフトしたため、プロジェクトのロードマップが変更された **（スケジュールまたは時間の変更）**。

## 2. 変更を行うことを決定する

次に、実際に変更させることをどのように決定するのか？意思決定のモデルは数多くあり、参考にすることができます。ここでは、これらのモデルの多くに含まれる基本的なステップを紹介します。

- **<font color="MediumVioletRed">決定権者を特定する。</font>**
    - 一貫性と説明責任を確保するために、プロダクトオーナーや上級ステークホルダーなど、一人の人間が決定者の役割を担うのがベストです。
- 意思決定において重要な要素は何かを検討・共有し、決定者が意思決定するのに役立つ **<font color="MediumVioletRed">データを収集する</font>**。
- **<font color="MediumVioletRed">意思決定のメリットとコスト</font>** をオープンに議論する。不確実性のある領域を特定し、前提条件を把握する。
- 決定を文書化する。

## 3. 変更を実行する

変更が承認されたら、いくつかのことを行うことが重要です。

- **<font color="MediumVioletRed">変更と意思決定のプロセスを文書化する。</font>**
会議のメモ、賛否両論リスト、仮定、プロジェクトの変更を決定するために使用したデータなどを含める。
- **<font color="MediumVioletRed">影響を受けるすべての成果物に変更を記録する。</font>**
ロードマップ、バックログ、人員配置計画、統合期日を更新し、利害関係者が参照できるように、変更元への参照を含める。ドキュメントが変更されたことをチームが明確に認識できるように、影響を受けるドキュメントに「バージョン1.2」や「12月20日更新」などのリビジョンラベルや日付を使用することを検討します。
- **<font color="MediumVioletRed">影響を受けるすべてのステークホルダーと変更内容を共有する。</font>**
ミーティング、文書、ミーティングノート、電子メールによる告知など、さまざまな方法で行うことができます。
- **<font color="MediumVioletRed">一定期間、変更を監視する。</font>**
これにより、チームがサポートされ、変更を認識することができます。

決定段階で変更が承認されなかった場合でも、決定に使用した情報と論理を文書化する必要があります。より信頼性の高い決定を下すために、より多くの情報を待つ間、変更を保留にすることも検討できます。
M1 MACでのDocker環境構築時に『no matching manifest for linux/arm64/v8 in the manifest list entries』

## エラー内容
M1 mac でdocker環境構築時にエラーが発生。

```
no matching manifest for linux/arm64/v8 in the manifest list entries
```

## 対処方法
 `docker-compose.yml`に`platform: linux/x86_64` を に追加する。

```
db:
    platform: linux/x86_64 // 追加する
    image: mysql:5.7
```

## エラー原因
M1チップのプラットフォームはarm64であるのに対し、
mysql5.7のイメージのサポートプラットフォームがAMD64でマッチしていないのが原因だそう。

なお、公式ではRosetta2を入れておくことが推奨されているようです。
```
softwareupdate --install-rosetta
```
https://docs.docker.com/desktop/install/mac-install/#system-requirements
suicredit で売上を計算

suicreditサービスを使っている。

売上明細と売上の数字を合わせる方法は？

# 結論

管理画面 > トランザクション
日時と、SALE , VOID , CB の3つにチェック入れて検索をクリック。

![suikeisanmado2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/e704a710-fb98-07e7-b842-561476058bdf.png)

出力された金額を
SALE + VOID + CB をする
これで、売上明細の数字とぴったり合う。

# 経緯
当該サービスは、売上明細をダウンロードできるのが2ヶ月後になる。
例えば1月なら3月にダウンロード可能。

これだと助成金などの計算が間に合わない。
しかし、そのままレポートを合計しただけでは数字が合わない。

そこれでレポート > 2022-08 をクリックし合計したものと計算しているのが
数字が微妙に合わない。
lambdaでEC2の停止起動をしてみる

内部で作ったサーバ群があるためlambdaを使って停止起動をするプログラムを書いてみることにする。
lambdaを使ったこともないため、lambdaの触りを試しながら実施。


# 試してみる
AWS公式ドキュメントに以下の記事を見つけた。
[Lambda を使用して、Amazon EC2 インスタンスを一定の間隔で停止および起動するにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/start-stop-lambda-eventbridge/)

この記事を元にlambdaを作っていくことにする。

## 起動用lambdaの作成
### 実行ロールの作成
ロール用にポリシー（lambda_ec2_start-stop_policy）をまず作成。
```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Start*",
        "ec2:Stop*"
      ],
      "Resource": "*"
    }
  ]
}
```

作成したポリシーをlambda用ロール（lambda_ec2_start-stop_role）へ許可する。
![2_role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953845/d7a7629f-8b6d-c0f0-b9ad-643e07534037.png)

これでテスト用のロールが完成。

### lambdaの作成
EC2開始用lambdaを作成する。

|項目|設定値|
|:---|:---|
|関数名|start_ec2_instance|
|ランタイム|Python 3.9|
|アーキテクチャ|x86_64|
|既存のロール|lambda_ec2_start-stop_role|

![3_start_lambda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953845/3ce6a3bf-dc7b-b783-f9ba-7f264b3e4a32.png)


AWSドキュメントをコピーしてregionと対象インスタンスIDを変更して作成。
```
import boto3
region = 'ap-northeast-1'
instances = ['i-xxxxxxxxxxx', 'i-xxxxxxxxxxx']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.start_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))
```

### lambdaの実行
lambdaのテストイベントを作成。
|項目|設定値|
|:---|:---|
|イベントアクションをテスト|新しいイベントを作成|
|イベント名|test_start_instance|
|イベント共有の設定|プライベート|

作成したテストイベントを使って作成したlambdaを動かしてみると以下の通り。
指定したインスタンスの起動ができた。
![6_test_evnet_start_ec2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953845/bdcd609e-abb6-a358-c413-f4dee050eac2.png)

## 停止用lambdaの作成
### lambdaの作成
ロールは先ほど作ったものを使いまわせるため、手順を飛ばしEC2停止用lambdaを作成する。

|項目|設定値|
|:---|:---|
|関数名|stop_ec2_instance|
|ランタイム|Python 3.9|
|アーキテクチャ|x86_64|
|既存のロール|lambda_ec2_start-stop_role|

![7_stop_lambda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953845/c3608de0-95dd-579a-8498-bd60843d0df8.png)


AWSドキュメントをコピーしてregionと対象インスタンスIDを変更して作成。
```
import boto3
region = 'ap-northeast-1'
instances = ['i-xxxxxxxxxxx', 'i-xxxxxxxxxxx']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.stop_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))
```

### lambdaの実行
lambdaのテストイベントを作成。
|項目|設定値|
|:---|:---|
|イベントアクションをテスト|新しいイベントを作成|
|イベント名|test_stop_instance|
|イベント共有の設定|プライベート|

作成したテストイベントを使って作成したlambdaを動かしてみると以下の通り。
先ほど起動していた指定したインスタンスの停止ができた。
![10_test_evnet_stop_ec2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953845/effffd38-4bc6-1b61-cc3a-332ddbb0aea8.png)

# まとめ
今回はlambdaを使って指定したインスタンスのみを停止起動することをやったが、
これだけを使うことは少ないだろうと思ったため、
次はEC2インスタンスすべてを起動停止できるようなlambdaを作成してみることにする。

実用的なところまで行くにはタグをつけ、指定したタグをつけているインスタンスのみ、
EventBridgeで指定した時間に停止するなどそのぐらいまで作れるようにしておきたい。
GitHub ActionsをCIに使うとき、マージ先のコードでビルトやテストが行われてしまう

# はじめに
職場でGitHub Actionsを使ってCI構築しているときに、うまくいなかなったことを記事にしてみました。
実験用リポジトリ
https://github.com/kbc18a11/actions-branch
# GitHub ActionsでCIを作ってみた
以下のようなyamlをCIとして構築をしてみました。
CIの目的としては、マージ先で変更した`a.sh`ファイルを実行することです。
```yaml:ci.yml
name: CI

on: pull_request_target

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: 出力！！！！
        run: sh a.sh
```
そして`a.sh`の中身は、マージ元とマージ先それぞれ以下になります。
```sh:マージ元のa.sh
echo moge
```
```sh:マージ先の:a.sh
echo main
```
## CIを実行
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500157/3c05e68a-f132-1546-823d-d853eb19c23f.png)

**えええええええ、マージ元のコードが実行されてるやんけ！！**

# なぜマージ元のコードが実行されたのか？
## 【結論】イベントを`pull_request_target`で指定していたから
```yml
on: pull_request_target
```
`pull_request_target`は`actions/checkout@v3`を実行する際に、マージ先ブランチにチェックアウトされるため、マージ先のコードが実行されました。
# 【解決方法】イベントを`pull_request`に指定する

```yml
on: pull_request
```
イベントを`pull_request`に指定するすることで、`actions/checkout@v3`を実行する際に、マージ元ブランチにチェックアウトされて、マージ元のコードが実行されるようになります。
## 最終的に修正したyaml
```yaml:ci.yml
name: CI

on: pull_request

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: 出力！！！！
        run: sh a.sh
```
……君のような勘のいいZshは嫌いだよ [気をつけるべきBashとZshの違い]

すいません、嘘つきました。Zsh大好きです。
Bashよりも使いやすい（=勘のいい）Zshが憎いです。

# はじめに
先日、FishからZshに乗り換えました。
何故かと言うと、FishがPOSIX非互換だったからです。

とは言えども、 **ZshもPOSIX非互換** なんですよね。まあ、POSIXモードもあるし、できうる限り対応させようという気がありそうなので、Zshを選びました。

しかし！そうは言ってもやっぱりPOSIX非互換。**Bashと共同のスクリプトを使おうとすると、注意しなければならない点** が他のシェルと比べても数多くあります。

この記事では僕が引っかかったところを中心に、備忘録的にそういう点をまとめていきたいと思います。
何かあれば適宜追加していきます。

:::note
いいね、ストック等して頂けると今後の勉強の励みになります。
間違いや不足、書いておくと良いのでは？という項目などあればコメントなどでご指摘いただけると助かります。
:::

# プロンプトを格納する変数が違う
有名な話ですね。

- Bash
**変数```PS1```に格納** します。プロンプト用エスケープ文字はバックスラッシュから始まる2文字です。
- Zsh
**変数```PS1```もしくは```PROMPT```に格納** します。エスケープ文字はパーセントから始まる2文字です。

# プロンプト表示前に実行するコマンドを、指定する方法が違う

- Bash
**変数```PROMPT_COMMAND```にコマンドを格納** します。  
- Zsh
**関数```precmd```に実行内容を格納** します。

# プロンプトでのANSIエスケープシーケンスの書き方が違う
これはなんでかよくわからない

- Bash
**```\[\e[値m\]```と書きます。**
普通に```echo -e```で使うときは```\[\]```は不要です。

- Zsh
**```\e[値m```と書きます。** ただ、色指定は```%F{色番号}文字%f```と書くほうがいいみたい。

# sourceコマンド実行時のスクリプトファイルを指す変数が違う
参考:[https://qiita.com/yudoufu/items/48cb6fb71e5b498b2532](https://qiita.com/yudoufu/items/48cb6fb71e5b498b2532)

例えば、ホームディレクトリで```~/dir/script.sh```を読み込む際に、
```sh
$ pwd
/home/user
$ source ./dir/script.sh
```
を実行したときに、script.sh内で自分自身のパスを取得する時に参照する変数を例とします。

- Bash
```bash:script.sh
echo $0 #-bash と返ってくる（失敗）
echo $BASH_SOURCE #~/dir/script.sh と返ってくる（成功）
```
この場合、```echo $(dirname $0)```とすると、```~/script.shはありません```って怒られます。（←これが厄介）
- Zsh
```zsh:script.sh
echo $0 #~/dir/script.sh と返ってくる（成功）
```

## 解決法
```sh:script.sh
echo ${BASH_SOURCE:-$0}
```
とするといいようです。

# シェルスクリプト内の関数内での$0の値が違う
これが意外と厄介だったりする

以下のスクリプトファイルにおいて、
```sh:script.sh
function() {
　　　　echo $0
}
```
- Bash
```bash
$ source script.sh #スクリプトファイルの読み込み
$ function
script.sh
```
- Zsh
```zsh
% source script.sh #スクリプトファイルの読み込み
% function
function
```

# 変数内の一部の文字列を抜き出すときに"最後まで"を指定する方法が違う
これでエラー出た時「だるっ」て思いました。
- Bash
```bash
$ HOGE="HOGEHOGE"
$ echo ${HOGE:3:$ }
bash: HOGE: $: 構文エラー: オペランドが予期されます（エラーのある構文は"$"）
#エラーになるので、ここは普通に計算しなきゃいけない
$ echo ${HOGE:3:$((${#HOGE} - 3))}
EHOGE
```
- Zsh
```zsh
% HOGE="HOGEHOGE"
% echo ${HOGE:3:$ } #なんかこれで上手くいく
EHOGE
```

# チルダ置換が違う
わっかりずら。って思いました。
- Bash
```bash
$ whoami
user
$ echo ~
/home/user #チルダがホームディレクトリとして展開
$ echo ~user
/home/user #ホームディレクトリに展開
$ echo ~$USER
~user #変数の場合はホームディレクトリは展開されない
$ echo ~"user"
~user #クオートされていても展開されない
$ echo ~\u\s\e\r
~user #エスケープされてても展開されない
$ echo ~存在しないユーザ
~存在しないユーザ #存在しないユーザの場合そのまま
```
- Zsh
```zsh
% whoami
user
% echo ~
/home/user #チルダがホームディレクトリとして展開
% echo ~user
/home/user #ホームディレクトリに展開
% echo ~$USER
/home/user #ホームディレクトリに展開
% echo ~"user"
/home/user #ホームディレクトリに展開
% echo ~\u\s\e\r
/home/user #ホームディレクトリに展開
& echo ~存在しないユーザ
zsh: no such user or named directory: 存在しないユーザ #エラー
```

# 配列のインデックス番号が違う
- Bash
```bash
$ arr=(hoge fuga piyo)
$ echo arr[1]
fuga #0から順にインデックス
```
- Zsh
```zsh
% arr=(hoge fuga piyo)
% echo arr[1]
hoge #1から順にインデックス
```

# おわり
似て非なるところが多すぎて、互換性のあるスクリプトを書くのは難しいですね…
でもFishよりは扱いやすいと思います。Fish、好きなんだけどスクリプトが書けなすぎてねぇ。

Zshに関してはこれも是非是非。（ほぼ個人的備忘録ですが。）

https://qiita.com/alpaca-honke/items/2041012ff5a0291bf084

それから、こちらの記事はBashとZshに限らずPOSIX系のシェルに関する互換性の問題をまとめて下さっていますのでこちらもご参考に！

https://qiita.com/ko1nksm/items/8d28d4f7cb2c325c00fa
Ruby で解く AtCoder ABC012 D Numo::NArray ワーシャル–フロイド法

# はじめに
AtCoder さん、ありがとうございます。
# D - バスと避けられない運命
https://atcoder.jp/contests/abc012/tasks/abc012_4

**ワーシャル–フロイド法**は、最短経路問題で利用されます。

https://ja.wikipedia.org/wiki/%E3%83%AF%E3%83%BC%E3%82%B7%E3%83%A3%E3%83%AB%E2%80%93%E3%83%95%E3%83%AD%E3%82%A4%E3%83%89%E6%B3%95
# Ruby Numo::NArray なし
```rb
n, m = gets.split.map(&:to_i)
ab = Array.new(n) { Array.new(n, 1000000000) }
n.times do |i|
  ab[i][i] = 0
end
m.times do
  a, b, t = gets.split.map(&:to_i)
  ab[a - 1][b - 1] = t
  ab[b - 1][a - 1] = t
end
n.times do |k|
  n.times do |i|
    n.times do |j|
      ab[i][j] = ab[i][k] + ab[k][j] if ab[i][j] > ab[i][k] + ab[k][j]
    end
  end
end
puts ab.map { |e| e.max }.min
```
他のアルゴリズムに比べ、実装が軽くて助かります。
# Ruby Numo::NArray あり
```rb
require 'numo/narray'

n, m = gets.split.map(&:to_i)
ab = Numo::Int64.new(n, n).fill(Numo::Int64::MAX >> 1)
ab.diagonal[true] = 0
m.times do
  a, b, t = gets.split.map(&:to_i)
  ab[a - 1, b - 1] = t
  ab[b - 1, a - 1] = t
end
n.times do |k|
	ab = Numo::Int64.minimum(ab, ab[true, k..k] + ab[k..k, true])
end
puts ab.max(axis: 1).min
```
こちらの記事を参照しました。

https://qiita.com/HMMNRST/items/c6dc37e8d68358588508

いやー、`Numo::NArray` 速いです。
## 1/31 追記
コメント欄にてNArrayの`max`メソッドの使い方を教えていただきました。
# Pypy(7.3.0)
```py
n, m = map(int, input().split())
ab = [[1000000000] * n for _ in range(n)]
for i in range(n):
    ab[i][i] = 0
for _ in range(m):
    a, b, t = map(int, input().split())
    ab[a - 1][b - 1] = t
    ab[b - 1][a - 1] = t
for k in range(n):
    for i in range(n):
        for j in range(n):
            ab[i][j] = min(ab[i][j], ab[i][k] + ab[k][j])
print(min([max(e) for e in ab]))
```
`Pypy` も速いですね。
# Crystal(0.33.0)
```cr
n, m = read_line.split.map(&.to_i)
ab = Array.new(n) { Array.new(n, 1000000000) }
n.times do |i|
  ab[i][i] = 0
end
m.times do
  a, b, t = read_line.split.map(&.to_i)
  ab[a - 1][b - 1] = t
  ab[b - 1][a - 1] = t
end
n.times do |k|
  n.times do |i|
    n.times do |j|
      ab[i][j] = ab[i][k] + ab[k][j] if ab[i][j] > ab[i][k] + ab[k][j]
    end
  end
end
puts ab.map { |e| e.max }.min
```
いつものごとく、これを使用しています。

https://github.com/superrino130/crystal-on-paiza.cloud

流石に、`Crystal`が一番速いです。
||Numo::NArray なし|Numo::NArray あり|PyPy3 (7.3.0)|Crystal (0.33.0)|
|:--:|--:|--:|--:|--:|
|実行時間(ms)|2088|243|523|90|
# まとめ
+ ワーシャル–フロイド法 を学習しました
+ `Numo::NArray` 便利だなと思いました
PuTTYでの行数設定

## 始めに
PuTTYのログ出力画面にて表示可能な出力履歴の行数設定を備忘録として残します。

__背景・理由__
ステージング環境にて、PuTTYを用いて出力する際に出力履歴の
表示可能行数が少なかったため、全ての出力履歴を見ることができなかったため。

## 環境
| 開発環境    |バージョン |
|---------    |----------|
| __PuTTY__   | 0.77     |
| __Windows__ | 11       |


## 設定手順
![PuTTY設定_表示行数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984846/f42c51f3-40d0-086d-c87b-c94084849559.png)

__1, 「 Windows 」を選択します。__
__2, 「 Lines of scrollback 」入力欄に表示したい行数の上限を入力します。__
__3, 「 Open 」ボタンを押下します。__

__以上__

## 終わりに
閲覧ありがとうございました。
PuTTYの設定欄には、まだまだ色々できることがありそうです。
ご指摘、ご意見等ありましたら、コメントお願いします。
AsyncStreamのBufferingPolicyを理解する

AsyncStreamのイニシャライザは`bufferingPolicy`という引数を取ります。

```swift
init(
    _ elementType: Element.Type = Element.self,
    bufferingPolicy limit: AsyncStream<Element>.Continuation.BufferingPolicy = .unbounded,
    _ build: (AsyncStream<Element>.Continuation) -> Void
)
```

<br>

サブスクライバーがストリームをサブスクライブするよりも前に、ストリームに要素が流れる可能性があります。
このため、AsyncStreamには要素をバッファする機能があります。

以下の例では、ストリームには1秒ごとに0からインクリメントされた数字が流れてきます。

ここで、`bufferingPolicy`に`.bufferingNewest(1)`を指定します。
`.bufferingNewest(1)`はストリームに流された最後の要素1つだけをバッファするという指定になります。

for-await-in文は10秒後に実行されるため、ストリームにはすでに0〜9の数字が流れた状態です。
このため、バッファされた9が最初に出力され、その後1秒ごとにインクリメントされた数字が出力されます。

バッファする数を変更すれば、出力内容も変わります。
例えば`.bufferingNewest(5)`とした場合、バッファされた5〜9が最初に出力され、その後1秒ごとにインクリメントされた数字が出力されます。

```swift
let stream = AsyncStream<Int>(bufferingPolicy: .bufferingNewest(1)) { continuation in
    Task.detached {
        for i in 0..<100 {
            try await Task.sleep(nanoseconds: 1 * 1_000_000_000)
            continuation.yield(i)
        }
        continuation.finish()
    }
}

Task.detached {
    try await Task.sleep(nanoseconds: 10 * 1_000_000_000)
    for await i in stream {
        print(i)
    }
}

// 結果
// 9  
// 10
// 11
// ...
```

BufferingPolicy型には他に`bufferingOldest`と`unbounded`があります。

上記の例で`.bufferingOldest(5)`とした場合、バッファされた0〜4が最初に出力され、その後は10から順に出力されます。

```swift
// 結果
// 0
// 1
// 2
// 3
// 4
// 10
// 11
// ...
```

`unbounded`とした場合は全ての要素がバッファされるため、０〜9が最初に出力され、その後は10から順に出力されます。

なお、AsyncStreamのイニシャライザの`bufferingPolicy`のデフォルト値は`unbounded`です。

**※上記例において、タイミングによってバッファされる要素が変わるため、何回か実行を繰り返すと結果が変わることがあります**

# 参考
- https://developer.apple.com/documentation/swift/asyncstream
- https://developer.apple.com/documentation/swift/asyncstream/init(_:bufferingpolicy:_:)
RPA(BizRobo!)でソリティア自動化に挑戦してみました

<p><h2>きっかけ</h2>
@RyoMoriseaさんの以下の記事を拝見し、自分もやってみよう！と思ったのがきっかけです。<br>
<a href="https://qiita.com/RyoMorisea/items/ccd6c8a4bd7486734835">挑戦者求む！ソリティアをRPAで自動化させてみた！</a>
<br>
ちょうど、v11.3がリリースされてからあまり触れていなかったので、練習題材を探していたこともあります。
</p>

<h2>とにかくやってみる</h>

結論から言うとクリアでき、きっかけとなった記事より早く、10分程度でクリアすることに成功しました。
ただ、かなり運の要素が絡むので一概には早くなったとは言えないですし、まだまだ改善の余地はあります。


<iframe width="560" height="315" src="https://www.youtube.com/embed/NjrtSuIRkRY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


今回は下の方に配っているカードをクリックする動きと、上の方の伏せ札をクリックしていく動作をひたすら繰り返していますが、
条件分岐が甘くて途中で止まってしまったり、クリアできなくなってしまったり、意外と試行錯誤が必要な作業でした。

クリック位置の特定も、操作時に位置情報を使って相対的な位置を特定させている部分もありますが、アプリの構造を読み取り、山札等の場所を把握させていたり、状態を確認させているところもあります。

<h2>まとめ</h>

もりしーさんも似たようなことを仰っていたと思いますが、
人間は意識せずとも画面全体を目で見て、判断し、手を動かしていますが、それはとても複雑な動きで、ロボットに再現させるのはとても困難だと改めて感じました。
ロボットを作りながら、ああああここやればすぐにクリアできるのに！となったことは幾度もあります。
日々ロボットを作っていると、人間の能力の高さはすごいと感じますね。

また、昔のBizRobo!のDAは不安定であまり好きになれませんでしたが、新しいバージョンでは、動作条件の設定を間違っていなければ、構造が読み取れずに止まるとか、アプリケーション自体の問題で止まることがなくなり、
操作性もかなり向上が見られ、とても使いやすくなったなぁと感じます。
これからは友達になれるかもしれません。

何か良い題材があればチャレンジしてみたいと思いますので、こんなのやってみてほしいというのがあればぜひ
MybatisのInvalid bound statement (not found)でぼんやりはまった

# Mybatis + Java + SpringBoot4

パッケージ割を変えたら、
Mapper XMLのSQLを実行できなくなった・・・。
JavaのRepositoryで定義したメソッドと紐づけできなくなったらしい。

### エラー内容
Invalid bound statement (not found)

### 原因

MyBatisConfigのJavaクラスで定義している@MapperScanのベースパッケージ

```
@MapperScan(basepackage="com.example.xxx.yyy.zzz")
```

- レポジトリ（Javaクラス）の場所
com.example.xxx.yyy.zzz.aaa.bbbパッケージに配置。
- Mapper XML ファイルの場所
src/main/resource/xxx/yyy/zzz/aaa/bbbフォルダに配置。

### 解決

- Mapper XMLファイルの場所

    MapperScanと同じ階層に配置する
    src/main/resource/xxx/yyy/zzz

### なにがわかったか

- JavaのRepositoryクラスはパッケージをMapperScanより深く配置してもよい。
    - おそらく、@Mapperアノテーションを付与しておくことが前提・・・

- Mapper XMLファイルの場所は、@MapperScanのbasepackageと同階層にすること。
    - より深く掘ると再帰的に探してくれないのでダメ

### 今後の展望

- Mapper XMLファイルを分類してフォルダを分けて管理する方法はあるか。。。？をしりたい。
SageMaker Studio で署名付き URL を SDK を使わずに発行する

## SageMaker Studio をマネジメントコンソールが使えないかつ各種 SDK がない状況から使いたい
みたいなときに書いたコードのメモを供養。

実装は Python だけれども、他の言語でも似たようなことをできる（はず）。

```python
import sys, os, base64, datetime, hashlib, hmac ,requests, json

access_key = 'type your credential or get environment'
secret_key = 'type your credential or get environment'

request_parameters = json.dumps({
    "DomainId": "type your domain",
    "UserProfileName":"type your username"
})

region = 'type your region'

method = 'POST'
service = 'sagemaker'
host = f'api.sagemaker.{region}.amazonaws.com'
endpoint = f'https://api.sagemaker.{region}.amazonaws.com'
content_type = 'application/x-amz-json-1.1'
target = 'SageMaker.CreatePresignedDomainUrl'

def sign(key, msg):
    return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()

def getSignatureKey(key, date_stamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'), date_stamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning

t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
date_stamp = t.strftime('%Y%m%d')

canonical_uri = '/'
canonical_querystring = ''
canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + '\n' + 'x-amz-date:' + amz_date + "\n" + 'x-amz-target:' + target + '\n'
signed_headers = 'content-type;host;x-amz-date;x-amz-target'
payload_hash = hashlib.sha256(request_parameters.encode('utf-8')).hexdigest()
canonical_request = method + '\n' + canonical_uri + '\n' +canonical_querystring + "\n" + canonical_headers + '\n' + signed_headers + '\n' + payload_hash


algorithm = 'AWS4-HMAC-SHA256'
credential_scope = date_stamp + '/' + region + '/' + service + '/' + 'aws4_request'
string_to_sign = algorithm + '\n' +  amz_date + '\n' +  credential_scope + '\n' +  hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
print(string_to_sign)

signing_key = getSignatureKey(secret_key, date_stamp, region, service)

signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
print(signature)

authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' +  'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
headers = {'Content-Type':content_type,
           'X-Amz-Date':amz_date,
           'X-Amz-Target': target,
           'Authorization':authorization_header}

r = requests.post(endpoint, data=request_parameters, headers=headers)

print('\nRESPONSE++++++++++++++++++++++++++++++++++++')
print('Response code: %d\n' % r.status_code)
print(r.text)


```

## 結論
boto3 他各種 SDK は偉大ですね。
【初心者向け】git clone後に生じるアプリケーションのエラーについて

## はじめに
　先日、githubのリポジトリからローカル環境にアプリケーションをクローンし、動作確認をしようとしたところエラーが生じてしまいました。解決策を発見できたので共有します。


## アプリケーションの動作確認
　リポジトリから自作のアプリケーションをクローン。サーバを立ち上げて動作確認をしようとすると・・・
![ツイートアプリケーション課題で出ているエラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116202/69203d9e-819e-c6aa-d515-115ee220a22e.png)


　__あれ・・・？なんで？　　　リポジトリにpushする前はちゃんと動いていたのに・・・__


## 解決策を探る
　いろいろ調べてみると、アプリのディレクトリでbundleをインストールすると問題が解決できる可能性があることが判明しました。さっそく、「bundle exec rake webpacker:install」を実施し、サーバを立ち上げ、アプリを開いてみると・・・

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116202/22567692-2096-e8c6-46ef-4bd7c2a21d23.png)


　__よう、また会ったな。会いたくなかったぜ・・・__

## さらに解決策を探る
　メンターに相談したところ、clone した後はbundleだけではなく、yarn install もしなければいけないとのこと。そこで、「npm install -g yarn」を実施すると・・・。


![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116202/665d3aeb-79d8-fc6b-81a8-53d2bec30631.png)

　__無事成功！やった！__


## おわりに
　というわけで無事に問題を解決できました。
　現段階の私の解釈は、railsに標準装備されていないgemやjsファイルなどのアプリケーション（という表現でいいのでしょうか？）を使用する場合、それを使うための準備をしなければならないという認識です。たとえば、gemを使うならbundle、javascriptを使うならyarnをインストールする、など。
　以上、備忘録を兼ねた報告でした。誤りがあればご教示いただけますと幸いです
PHPの基礎　文字列の出力

PHP で文字列を出力するには echo または print を使います。この 2 つは関数ではなく PHPに言語構造として含まれているものです。言語構造とは「if」や「for」などのように言語の基本的な仕組みとして組み込まれている要素です。ここでは PHP で echo と printを使って文字列を出力する方法について説明します。

# echo

`echo`は1つの文字列も複数の文字列も出力することができます。`echo`の後に半角スペースを入れて出力する文字列を記述します。複数の文字列を出力するには文字列をカンマ（`,`）で区切って記述します。

```PHP
echo 'おはようございます！';
echo '現住所:', '奈良県';
```

# print

`print`は1つの文字列を出力するときに使います。`print`の後に半角スペースを入れて出力する文字列を記述します。`print`は複数の文字列を出力することはできません。

```PHP
print 'こんにちは';
```
1つの文字列を出力する場合は、`echo`でも`print`でも違いはありません。ただ、1つの文字列を出力するときは`print`を使い、複数の文字列を出力するときには`echo`を使うという使い分けは紛らわしいので、特別な事情が無ければ`echo`に統一するのがいいでしょう。

# 練習問題

## 問題1

次のうち、「こんにちは日本」と出力されるプログラムはどれでしょうか？

①
```PHP
echo 'こんにちは', '日本';
```

②
```PHP
echo 'こんにちは,日本';
```

③
```PHP
print 'こんにちは,日本';
```

④
```PHP
print 'こんにちは', '日本';
```

## 解答1
正解は①です。
②と③は文字列を囲む`''`の中にカンマ（`,`）があるので、「こんにちは,日本」と中にカンマが入った状態で出力されます。④は`print`を使っていますが、printは複数の文字列を出力できないのでエラーになります。



PHP で文字列を出力する方法について解説しました。
【React状態管理5】Recoil

# 概要
Reactの状態管理の1つである、`Recoil`について学んだことをメモします。

# 学習内容
- [Recoilとは](#recoilとは)
- [導入方法](#導入方法)
- [selectorを用いる利点](#selectorを用いる利点)

# Recoilとは
Meta製の、Atomsベースの状態管理ライブラリ。
Selectorsを使うことで、複数のatomを合わせた状態を利用することもできる。

![Recoilの構成図](https://res.cloudinary.com/practicaldev/image/fetch/s--8ilIU9z_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jv4d83g1xf9nhn3jewco.png)
[^1](https://dev.to/coleredfearn/atomos-a-new-recoil-visualization-tool-powered-by-react-flow-4b6l)

## 特長
- 比較的容易に利用できる
- Atomベースのため、各データの状態を個別に管理できる


# 導入方法
## インストール方法
```
$ npm install recoil
```
or
```
$ yarn add recoil
```

## 設定方法
1. 最上位の関数を`RecoilRoot`でラップする
    ```javascript
    import React from 'react';
    import {
        RecoilRoot,
        atom,
        selector,
        useRecoilState,
        useRecoilValue,
    } from 'recoil';

    function App() {
        return (
            <RecoilRoot>
                <CharacterCounter />
            </RecoilRoot>
        );
    }
    ```
1. `atom()`メソッドで状態のオブジェクトを追加する
    `key`：atomのキー(アプリ内でユニークである必要がある)
    `default`：状態の初期値
    ```javascript
    const textState = atom({
        key: 'textState', // unique ID (with respect to other atoms/selectors)
        default: '', // default value (aka initial value)
    });    
    ```
1. `useRecoilState`で状態を取得、更新する
    `useRecoilState`の使い方は、基本的に`useState`と同じ。下記では、文字入力により`textState`の状態を更新している。
    ```javascript
    function CharacterCounter() {
        return (
            <div>
                <TextInput />
                <CharacterCount />
            </div>
        );
    }

    function TextInput() {
        const [text, setText] = useRecoilState(textState);

        const onChange = (event) => {
            setText(event.target.value);
        };

        return (
            <div>
                <input type="text" value={text} onChange={onChange} />
                <br />
                Echo: {text}
            </div>
        );
    }
    ```
1. `selector`であるatomの状態を変換し、`useRecoilValue`で取得する
    下記では、文字データ`textState`を`selector`で文字データの長さ`charCountState`に変換し、`useRecoilValue`で取得している。
    ```javascript
    const charCountState = selector({
        key: 'charCountState', // unique ID (with respect to other atoms/selectors)
        get: ({get}) => {
            const text = get(textState);

            return text.length;
        },
    });

    function CharacterCount() {
        const count = useRecoilValue(charCountState);

        return <>Character Count: {count}</>;
    }
    ```

# `selector`を用いる利点
- シンプルに記述できる
- パフォーマンスが向上する
レンダリングを行う場所を更新箇所のみにできる

# 参考
[IT Kingdom](https://it-kingdom.com)
[Recoil公式ページ](https://recoiljs.org)
[ATOMOS](https://dev.to/coleredfearn/atomos-a-new-recoil-visualization-tool-powered-by-react-flow-4b6l)
[GitHubリポジトリ](https://github.com/yamashin01/react_state_management/tree/main/Recoil01)
Pythonのフォルダ監視(Watchdog)は例外で停止する

# Pythonのフォルダ監視(Watchdog)は例外で停止する

## 環境
+ Python 3.11
+ Watchdog 2.1.9

## 要約
PythonのWatchdogパッケージでフォルダ監視を行う時に、予期せぬエラーによる監視終了を避けるには、フォルダイベントに対する処理を別スレッドで行えばよい。

## 現象
Pythonでフォルダ監視というと、標準ライブラリではカバーしておらず[Watchdog](https://pypi.org/project/watchdog/)を使う方法がメジャーだと思われる。フォルダ監視をプログラム実行中永続的に行わせるケースは多いと思われるが、Watchdogから呼び出した命令で予期せぬ例外が発生した場合、フォルダ監視は終了してしまう。

さっと検索した限り、これを問題として取り上げている記事は見つからなかった。

## サンプルコード
```Python
#!/usr/bin/python3
"""例示用."""

import threading
from pathlib import Path
from typing import NoReturn

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer


class TestHandler(FileSystemEventHandler):
    """フォルダ内でファイルが作成されたときの処理を規定するクラス."""

    def irregular(self) -> NoReturn:
        """例外を発生させる."""
        raise Exception("Exception in on_created.")

    def on_created(self, event) -> None:
        """ファイル生成もしくはファイルが移動してきた時の対応."""
        print(f"created: {event.src_path=}")
        self.irregular()
        # threading.Thread(target=self.irregular).start()


if __name__ == '__main__':
    TEST_PATH = "test"
    Path(TEST_PATH).mkdir(parents=True, exist_ok=True)

    observer = Observer()
    observer.schedule(TestHandler(), TEST_PATH, recursive=True)
    observer.start()
    try:
        while observer.is_alive():
            observer.join(1)
    finally:
        observer.stop()
        observer.join()
```

`TEST_PATH`内にファイルを作成すると、例外が発生してプログラムが終了する。当然、もう一つファイルを作成しても何も起こらない。

## 対策
サンプルコード内にコメントアウトしてあるが、`self.irregular()`を`threading.Thread(target=self.irregular).start()`と変更して別スレッドで実行すれば、少なくともフォルダ監視が止まることはなくなる。

## 考察
例外が発生した時に、エラーに気づけるようにプログラムが停止した方がいいのか、エラーを抱えたまま動作を続けた方がいいのかについては議論が分かれることもあると思うが、永続的フォルダ監視の場合、個々のイベントへの対応が独立していて動作の継続の方が重要であるケースは多いのではと思う。

事前にエラーを網羅するのは困難であることを考えれば、動作継続が優先する時に`FileSystemEventHandler`から呼び出す処理を予め別スレッドでの実行となるように書いておくのは方法論として有効だと言える。

エラーの発見は、`TestHandler.irregular()`内の処理を`try ... except`で囲ってログを取るなどの方法で対処できると思われる。

## 余談
余談だが、上記は2023/1/28時点のWatchdog公式[QuickStart](https://python-watchdog.readthedocs.io/en/stable/quickstart.html)のサンプルコードを参考に作成したが、`while observer.is_alive():`が`while observer.isAlive():`になっていたため動作せず、ちょっと戸惑った。

ちなみに[GitHub](https://github.com/gorakhargosh/watchdog)のサンプルコードのように`while True:`でループすると、プログラムは終了していないのにフォルダ監視だけ終了しているという、大変エラーがわかりにくい状態になる。

## 改訂履歴(表現の修正などは除く)
+ 2023/1/28: 初版
CNNの基本

# はじめに
画像等を用いたDeepLearning で使われるConvolutional Neural Netwoek（＝畳み込みNN＝CNN）についてまとめておきます．

Linearでもいいので簡単なモデルを作ったことがある人なら実装部分は詰まらないと思います．ので，知識のお話をできればと思います．
DNNで出てこなかった部分としては，ConvolutionとPoolingです．

また，Convolution層で使えるGradCAMという便利な技術についても紹介します．

# 目次
[1 畳み込み](#1-畳み込み)
[2 プーリング](#2-プーリング)
[3 GradCAM](#3-GradCAM)

# 1 畳み込み
CNNのメイン処理です．
今回は2次元の画像に対して考えていきます．
畳み込み処理には”フィルタ”を使います．下図の赤の部分が処理される画像，青の部分がフィルタです．
![Conv1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/def5c821-0bc3-7606-1273-ce5b711c2a23.png)
まずはこのフィルタを左上3*3の領域に対して掛け合わせた値をとります．
![Conv2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/8b2ac840-a45a-cac7-55db-38e2fe8a17e1.png)
次に，一つ右にずらして同様の処理を行います．
![Conv3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/f2144374-516b-c28a-d687-eb143078b708.png)
次に，一つ右．その次は一段下…というように繰り返していきます．
![Conv4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/c4cc302c-f68c-08e2-dc2b-3ad71284b44d.png)

で，これで何ができるの？ってことですが，特定の色，エッジ，などなどの画像のどこにどんな特徴があるのかを抽出するような役割を持っています．
例えば，”２”と書かれた画像に対して，どこに右肩上がりの情報があるのかをフィルタでやってみます．0,1で表現されているGrayScale画像とします．この時，右肩上がりのフィルタを用意して，これらに畳み込み処理を行うと，右の行列が出力されます．
画像の中で右肩上がりの線がある部分の値が大きくなって，その特徴がない部分の値は小さくなっています．
![Conv5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/63078851-5910-e5ef-4df0-c2d50d187b04.png)
こういったフィルタをたくさん用意して，いろんな特徴をとってやるぜ！というのが畳み込み処理になります．


# 2 プーリング
プーリング処理とは，近傍ピクセルから代表や平均をとることによって，解像度を下げる処理です．これには以下のような効果があります．
- 微弱な位置変化に頑健
- 過学習の抑制
- 計算コスト低下
処理は簡単で，フィルタの中で平均を取ったり（Average Pooling），一番大きい値をとったりします（Max Pooling）．
![AveragePooling.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/979ab182-33ab-9d0b-2153-01876d1fa083.png)
![MaxPooling.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/1ae8ac0a-d7cf-c2a2-434d-792fee1c18af.png)


# 3 GradCAM
GradCAMとは，AIがどこを見て判断しているのかを可視化する手法です．基本的にDeepLeaningはブラックボックスであり，何の特徴を見て機械が判断しているかは分かりません．
ですが，出力層からモデル中の最後のConv層までを誤差逆伝搬して勾配を計算することで，画像中のどの部分を注目しているのかを確認できます．
なんか学習上手くいかんな～って時にAIがどこを見てくれているのか確認したりできるのはありがたいですね．
Pytorchでの実装はGithub等に上がっているので，すぐ実行できます．
![GradCAM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/b274f5bf-b946-8d2f-3671-78792aeccbc0.png)



# さいごに
随時追記予定です．
最近Kaggeleを始めたので，データ分析なども勉強してまとめたいな～と思っています:v:
(BizRobo)直近の指定曜日の日付を抽出する方法

<h2 name="7dDgz">概要</h2><p name="zsdHh">
※こちらの記事は以前noteで投稿していた記事の移植版です。

直近のある曜日の日付を取得する方法です。<br>
例えば、今日は2020/12/28の月曜ですが、この日付から最も近い未来の金曜日、<br>
つまり2021/01/01の日付を取得したい、そんなときどうするか、という記事です。</p><h2 name="SZDS4">

<br>
関連ナレッジ</h2><p name="JGkLn">関連しそうなナレッジ探しておきました。<br>
・システム日付を基準に一日前や一週間前などの日付を取得する方法<br>
<a href="https://knowledge.bizrobo.com/hc/ja/articles/360036293831?" target="_blank" rel="nofollow noopener">https://knowledge.bizrobo.com/hc/ja/articles/360036293831</a></p><p name="RtysS">・DSで日付から曜日を取得する方法<br>
<a href="https://knowledge.bizrobo.com/hc/ja/articles/360031150151?" target="_blank" rel="nofollow noopener">https://knowledge.bizrobo.com/hc/ja/articles/360031150151</a></p><h2 name="Af8GM">

<br>
設定方法</h2><p name="XpQjO">やり方は簡単、まず変数の割当(Assign Variable)ステップを追加します。<br>
値の入力方法を[コンバーター]にし、曜日の値を変数に格納していない場合は、デフォルトで入力されている[変数を取得]を削除します。</p><p name="tXtO5"><img alt="画像2" src="https://i.gyazo.com/a2d57e7dff8d30f4ba17b91dcee56f86.png" width="460" height="356" class="" style="width: 276px; height: 213.6px;"></p><p name="YVYyH">変数に入力しておいたものを使用する場合は曜日が入力された変数を設定してください。<br>
変数を指定せずテキストをベタ打ちする場合は[テキストを追加]で取得したい曜日を入力します。<br>
「金曜日」や「金」の1文字でも構いません。<br>
そして、[日付処理]⇒[日付抽出]でパターン等を設定します。<br>
まずはフォーマットの[+]ボタンを押してフォーマットを設定し、パターンで曜日を示す[E]を入力します。</p><p name="v0McS"><img alt="画像1" src="https://i.gyazo.com/50b123b9043957f72059488632ef7873.png" width="620" height="679" class="" style="width: 372px; height: 407.4px;"></p><p name="grrDL"><img alt="画像3" src="https://i.gyazo.com/a5576dbddb4a54819de1e5f0fee34acf.png" width="620" height="679" class="" style="width: 372px; height: 407.4px;"></p><p name="0dQ5O">曜日名を日本語で入力している場合はロケールを日本語にすることもお忘れなく。<br>
次に詳細タブに移動し、詳細タブでは時間軸の方向を「未来の日付」に設定します。</p><p name="7M7tz"><img alt="画像4" src="https://i.gyazo.com/4eb784afff07bd40353063e652f94dad.png" width="620" height="679" class="" style="width: 372px; height: 407.4px;"></p><p name="ZK6mD">こうすることで、求めたい日付が未来なのか過去なのかが変わります。</p><p name="7hOre">ちなみに2020/12/28に金曜日を求めると2020/12/25になります。<br>
クリスマスですね、皆様どんなクリスマスをお過ごしでしたか？<br>
私は妻とゆっくりケーキを食べて過ごしました。</p><p name="7tgpH">脱線しました…。</p><p name="NCvAU">設定はこれで以上です！<br>
上の画像のようにテスト出力欄が元日になっていることがわかると思います。</p><p name="2ufSS">ちなみに現在の日付を基準にしていますが、もし任意の日付を基準にしたい場合、<br>
Date型の形式の日時を変数に入力しておけばその日付を基準にすることも可能です。<br>
その際は[デフォルトの日付]を「指定した日付」に変更し、日付を格納した変数を指定してあげてください。</p><p name="DRfVL"><img alt="画像5" src="https://i.gyazo.com/5896a05e5ddd3d2779a7694a6c07bfbd.png" width="620" height="679" class="" style="width: 372px; height: 407.4px;"></p><p name="uYXe2">そのまま現在の日付を指定すると、今日を含んだ直近の日付を取得しますが、<br>
今日以降の日付を取得したい場合等には、あらかじめコンバーターの「変更日」で日付を加工してみましょう。</p><p name="6hIX0">全体的にですが、我流でやっているところがありますので、より良い方法や補足等ありましたらご意見いただければ幸いです。
</p>
新規プロジェクトを数年やった振り返り

# 勤め先

優秀なエンジニアと豊富な経験のある、業界のリーダー的企業です。

# プロジェクトの性質

- 他の会社を含め、同じような製品や技術を持っている先駆者がいません。何もかも自分たちで決めていく必要があります。
- お客様に販売する以外にも、自分たちが使うという目的も持ったソフトウエア開発のプロジェクトです。
- 従来の開発プロセスを変革するようなプロジェクトです。
- 社内に学術的・技術的な有識者がほとんどいません。

# 運が良かったと思うこと

## 学術的な面は自分がカバーできた

学術的に不足していると思われたことについては、僕自身が元から持っていた知識に加えて、少し勉強することでカバーできました。

## 技術的な面も自分や他メンバーの頑張りでカバーできた

プログラミングスキルなどの技術的な面についても、お願いしている会社が非常に優秀だったことに加えて、メンバーにもその辺に長けた方がいたので、そこそこいいものになっています。

## 性能的にはいいものができている

学術的・技術的な部分が自分たちでカバーできているので、製品の性能としては非常にいいものが出来上がっています。競合となるベンダーと比べてもぶっちぎりの性能と自信を持って言えます。

# できていないこと

## 業界の動向分析ができていない

開発プロセスを変革するプロジェクトなので、本来は自分たちも含めて将来の動向予測をする必要があるのですが、期限とかいうものによってその時間が取れていませんでした。
どんな機能を入れるにしろ、業界全体の将来像ができていないと必要な機能なのかどうか判別できません。入れたい機能をなんとなく入れるソフト開発になってしまいそうでした。

## ソフトウエアの構成についてはじめの方に真剣に考えるべきだった

業界動向の分析や将来像構築が大前提ですが、これから作っていくソフトウエアをどういう構成で作っていくか、どの部分をライブラリにして、インクルード関係はどうするのか、最初の方にある程度考えておくべきでした。
今になって少しずつ変えていこうとはしていますが、時間がかかって仕方ないです。
どういう構成にしておけば自分たちの相手にしているお客様にリーチできるか、そこからスタートしないと、性能が素晴らしくても躊躇されてしまうと実感しました。

## 宣伝が下手くそ

技術者の集まりだと陥りがちなのでしょうが、表現の正確性にこだわるあまり、実際の性能が他ベンダーより上でも、お客様からしたら同レベルかそれ以下に見えてしまうようです。気をつけてはいたのですが、社内的にも誇張表現を嫌ったり内容の不足がないようにしないといけない派閥の人が多いので、うまくアピールできませんでした。

## お客様もヴィジョンが不明瞭であることを念頭に入れていなかった

先駆者のいないプロジェクトのため、お客様もヴィジョンややりたいことがコロコロ変わってしまいます。失礼ながらやる気あるのか、現実性を考えたことはあるのか問いただしたいこともしょっちゅうです。これのせいで結構な時間を費やしてしまっている気がします。

# まとめ

大企業に入ってくる人の多くは学術的・技術的に優れた人ばかりです。
そんな人たちは入社して安泰だと思っているかもしれないですが、プロジェクト運営や製品の開発計画などについて何もできていません。大企業であるほどその辺に気づくのに遅れてしまいがちな気がします。役職持ちの人たちでさえそのことを真剣に取り組んでいないこともしばしば。

性能的にいいものを作れば勝手に売れてくれるということは絶対にありえません。性能が中途半端でもお客様の欲しいところに届くものが売れるのです。

勘違いを早めに正して、これからも精進します。
iRICの格子生成アルゴリズム 超簡易格子生成ツール "Super Simple Grid Generator"を作ってみた

# はじめに

これまで既存の格子生成ツールの紹介をしてきましたが、今回はオリジナルで格子生成ツールを作ってみました。
作り方の紹介記事は今度作成する予定ですが、ひとまず作ってみた格子生成ツールを紹介しようと思います。

# 作った理由

一番の理由はオリジナルの格子生成ツールを作るときにまずは簡単なものから作ってみようという理由です。

他にはiRICを使ってみて、点群データのマッピング機能とかを試すために「とりあえず格子を作ってみよう！」となったとき、iRICでは[矩形領域の格子を作成](https://iric-gui-user-manual-jp.readthedocs.io/ja/latest/04/05/01_05_rectangular_region.html)や[矩形領域の格子を作成（緯度・経度）](https://iric-gui-user-manual-jp.readthedocs.io/ja/latest/04/05/01_05_rectangular_region.html)、[簡易直線・蛇行水路生成ツール *Simple Straight and Meandering Channel Creator*](https://qiita.com/starfieldKt/items/62f440074cdbce59a023)、[*Simple Grid Generator*](https://qiita.com/starfieldKt/items/d006e7856b887706aa66)など少ない条件で格子を作成できるツールはありますが、いざ使おうとすると意外とパラメータ数が多くて「うっ」とするときはありませんか？私はあります。

なので最低限のパラメータで格子を作成するツールを作ってみました。

実用性は皆無です。なので皆さんが格子生成ツールを作成する時の参考になったりすればいいかなと思います。
格子の標高などを設定する機能等を追加したりすれば意外と使えるかもしれません。

# インストール方法

すでにiRICのver.4がインストールされている状態を想定して解説します。

1. GitHubの[リポジトリ](https://github.com/starfieldKt/super_simple_gridgen)からzipでダウンロードするか、ローカルにクローンして必要なファイルを入手してください。（zipでダウンロードするほうが簡単なので推奨です。）

   ![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/58af1d0f-bae2-df07-1a95-f1306c4f6c68.gif)
   リポジトリのクローンの仕方等は[こちらの記事](https://qiita.com/Kazutake/items/129972790c4d7bea1055)を参考にしました。

1.  ファイルを入手したら(zipは解凍しておく)`install`フォルダを、iRICがインストールされているフォルダの`private`にある`gridcreators`フォルダ（デフォルトでインストールしていたら C:\Users\ユーザー名\iRIC_v4\private\gridcreators )にコピーします。
1.  コピーしたinstallフォルダは好きな名前に変えておいてください。(必須ではないです。)
1.  iRICを起動して適当なソルバを起動、メニューバーの`格子`＞`格子生成アルゴリズム`から出てくる一覧に追加されていればインストール完了です。
    ![Animation3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/c9ad3f65-eb66-0dd7-812c-50089cadc80a.gif)

:::note
iRIC_v4\gridcreatorsにコピーしてもインストールできますが、このフォルダはインストーラーからインストールするものが保存されるフォルダなので、自作の格子生成ツールは\iRIC_v4\private\gridcreatorsに保存しましょう。
:::


# 機能
### 格子生成条件
超簡易格子生成ツールを選択すると以下のような格子生成ツールのパラメータ入力画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/a8f6bfae-d928-6701-4fbe-994cabbc62a2.png)

超簡易格子生成ツールでは条件入力に2つのモードがあり、格子の全長とセルの数を指定する方法と、セルサイズとセルの数を指定する方法が選択できます。
パラメーターの単位はGUIに書き忘れていますが$m$単位です

2つのモードは`格子の全長の設定方法`で選択可能です。

#### 全長を直接入力する
パラメータとしてXY方向それぞれの`格子の全長`と`セルの数`を指定します。
以下のような格子が作成されます。
このときのセルサイズは全長とセルの数から計算されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/e38a1d80-871e-9ac9-e656-13a80cc3a24f.png)

#### セルのサイズと数から計算する
パラメータとしてXY方向それぞれの`セルのサイズ`と`セルの数`を指定します。
以下のような格子が作成されます。
このときの全長はセルの数とセルサイズから計算されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/be6a2d49-aa97-79c5-80b5-f642c6fa8292.png)

# 改変再配布について

ソースコードもGitHubに公開しています。(srcフォルダに入っています)
基本的に改変も再配布もご自由にしてください。なんなら推奨です。

格子生成ツールの基本的な機能だけのものなので、「新しい格子生成ツールを作ってみたい！」という方がいればこのソースをベースにしてもらえれば1から作るよりは楽になるんじゃないかと思っています。

使ってみた感想やソースコード参考にしましたとかのコメントがあれば私が喜びます。
macOSでvpn接続先のNASにアクセスできない

# 状況
macでVPN接続をし、VPN接続自体はうまくいっているように見えたが、接続先のNAS（IPアドレス：192.168.0.XXX）にアクセスができなかった。
またNASアドレスへのpingも通らなかったが、インタフェースをVPNに指定すると通った。
（VPNのインターフェースはppp0。）
```
% ping 192.168.0.XXX -c 5
PING 192.168.0.XXX (192.168.0.XXX): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
...

% ping 192.168.0.XXX -c 5 -b ppp0
PING 192.168.0.XXX (192.168.0.XXX): 56 data bytes
64 bytes from 192.168.0.XXX: icmp_seq=0 ttl=127 time=16.219 ms
...
```

## 環境
macOS 13.1
VPN: L2TP over IPSecでオプションとして「すべてのトラフィックをVPN経由とする」を選択

## 解決策(23/01/29更新)
pingの応答から判断して、自宅のネットワークから抜け出せていない状態だと判断したので、参照[1]を参考に下記コマンドをターミナルで実行。結果NASへのアクセスができたが、再起動すると消えてしまう[3]。
→再起動しても消えないように参照[3]を参考に、VPNの接続先のルーターIPアドレスを指定して設定。（VPNのIPアドレスを192.168.YYY.YYY）

```
# 再起動すると消えてしまう設定
% sudo route add -host 192.168.0.XXX -interface ppp0

# VPNの接続先のルーターIPアドレスを指定して設定
% sudo networksetup -setadditionalroutes ischool 192.168.0.XXX 255.255.255.255 192.168.YYY.YYY
```


## 参照
[1] https://1manit.work/1manit/vpn-routing-mac/
[2] https://qiita.com/ecodrive/items/ec7e32037d7cfd8106a5
[3] https://qiita.com/devzooiiooz/items/93feca542b4ed754c238
rocky linuxでlaravel-websocketsの構築(WSサーバ)

laravelでbroadcast機能を使う際、以下の2パターンとなる
・Pusherjsやablyなどの外部サービスを使う場合
・laravel-websocketsやsocketiなどで自前で用意する場合

外部サービスは制限が有ったりするので自前で用意してみる
[laravel-websockets](https://beyondco.de/docs/laravel-websockets/getting-started/introduction)

今回は別ドメイン(ws.test.jp)で用意する
laravel-websocketsサーバはlocalhost(127.0．0.1)、ポート6001で待ち受ける。
外部からのアクセスはnginxのリバースプロキシーでアクセスさせる。

また、ふぃあるのアクセス権などの設定のため
ユーザー名(rockyos)でnginxグループに追加しておく。

## laravelプロジェクトの作成
rootでフォルダを作ってそのあとアクセス権限などを設定する。
```bash:console
# cd /var/www/html
# composer create-project "laravel/laravel" ws.test.jp
# chown rockyos:nginx -R ./ws.test.jp
$ cd /var/www/html/ws.test.jp
$ find ./storage -type d -exec chmod g+s {} \;
$ find ./bootstrap/cache -type d -exec chmod g+s {} \;
```

## redisサーバを用意
Centos(RHEL)系ならdnfのmodule listにredisがあるのでそちらからインストール

```bash
$ sudo dnf module list redis
$ sudo systemctl enable redis
$ sudo systemctl start redis
```
redisのcliはredis-cliでコマンドラインに入れる。
```
$ redis-cli
127.0.0.1:6379> keys *
```
laravelのイベントを非同期で扱う場合、.envのQUEUE_CONNECTIONをredisに変更する
```bash
QUEUE_CONNECTION=redis
```

PHPのredisライブラリをインストール

```bash
$ composer require predis/predis
```

以下のファイルのREDIS_CLIENTのデフォルト値を変えるか
`.env`ファイルに`REDIS_CLIENT=predis`を追加する
```conf:config/database.php
    'redis' => [
        'client' => env('REDIS_CLIENT', 'predis'), /* 'phpredis' -> 'predis' */
        'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
    ],
```
### イベントを処理するキューワーカーを設定
QUEUE_CONNECTIONをredisやdatabaseに変更すると、要求されたeventやjobは指定されたdbのテーブル(databaseだとjobs)にキューイングされる。
キューイングされたイベントはキューワーカーによって処理をする。
RHEL系だとsupervisorによるデーモン化を行う必要がある。

まず、supervisorデーモンをOSにインストール。
```bash
$ sudo dnf install supervisor
$ sudo systemctl enable supervisor
$ sudo systemctl start supervisor
```
以降、supervisor自体のサービスのrestartなどは行わず、
supervisorctlコマンドで個々のモジュールの起動、停止などを行う。
設置ファイルの置き場は`/etc/supervisord.d/`配下、
ファイル名はとりあえず`laravel-worker.ini`とする
以下はlaravelのキューワーカーの設定例
```conf:/etc/supervisord.d/laravel-worker.ini
[program:laravel-queue-worker]
command=php /var/www/html/app/artisan queue:work --sleep=10 --tries=3
autostart=true
autorestart=true
user=nginx
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/html/app/storage/logs/laravel-worker.log
```
ファイルを格納したら、設定を更新して起動させる
```bash
設定ファイルを変更したら更新させる
$ sudo supervisorctl update
supervisorが管理しているデーモンの状態表示
$ sudo supervisorctl status
laravel-queue-worker:laravel-queue-worker_00                     RUNNING   pid 777495, uptime 1:43:13


デーモンの停止
$ sudo supervisorctl stop laravel-queue-worker:*
laravel-queue-worker:laravel-queue-worker_00: stopped

デーモンの起動
$ sudo supervisorctl start laravel-queue-worker:*
laravel-queue-worker:laravel-queue-worker_00: started
```
キューが捌けない場合はsupervisorctl update(or stop start)するとキューが捌けていくことがある。
OpenFOAMの結果をblenderで可視化してみる#01 openfoamのinstall

# はじめに

OpenFOAMで可視化というと基本paraviewが使われるが，blenderで可視化してみたいと思ったので，そのメモを記録がてらに記録を残します．

ちなみに，いまはやりのchat-gptによると，

:::note info
OpenFOAM (Open Field Operation and Manipulation) は、CFD (Computational Fluid Dynamics, 計算流体力学) のためのオープンソースのソフトウェアパッケージです。流体の流れや熱伝達、燃焼などの様々な物理現象をシミュレートすることができます。C++言語で書かれており、Windows、Linux、MacOSなどの主要なオペレーティングシステムに対応しています。
:::
とのこと，たぶん間違ってない，略称あってるかは不明・・・　

# 前提条件
- windows 11
- wsl2のubuntu環境を使用
- openfoamのインストールはapt を利用
- paraview v5.11 https://www.paraview.org/download/
- blender  v3.4  https://blender.jp

# 方針
とりあえず，下記とかを参考にして，
1. paraviewを使用して，x3d形式のファイルを作成
1. blenderで可視化
で進める．


https://www.rccm.co.jp/icem/pukiwiki/index.php?OpenFOAM%E3%81%AE%E7%B5%90%E6%9E%9C%E3%81%8B%E3%82%89Blender%E3%81%A7%E5%8B%95%E7%94%BB%E4%BD%9C%E6%88%90

https://bluebirdofoz.hatenablog.com/entry/2017/08/20/144643

# OpenFOAMのインストール
面倒なので，apt（コンパイル済みの配布されたもの？）をつかう。
下記を参考に設定する。ソルバーの自作とかはおそらくできない？


https://develop.openfoam.com/Development/openfoam/-/wikis/precompiled/debian
```sh
# Add the repository
$ curl https://dl.openfoam.com/add-debian-repo.sh | sudo bash

# Install preferred package. Eg,
sudo apt-get install openfoam2212-default

# Use the openfoam shell session. Eg,
openfoam2212
```
知らなかったが，openfoamを実行するshell sessionが用意されている。
bashrcにパスを追記するのではなく，`openfoam2212`を実行して，openfoamのコマンドを使う。このあたりは，ソースからビルドした際と，操作方法が若干違う。

:::note info
参考：ソースからコンパイルする例
https://qiita.com/yotakagi77/items/50817527b790111e0705
:::

とりあえず。今日はここまで。
ラジオボタンによってフォームの入力可能・不可能を動的に切り替える方法

<h1>概要</h1>
ラジオボタンをいくつか用意して、そのボタンが押された項目だけ入力可能になり、なおかつデータの送信も選択した物のみしたい場合の行い方です。今回はファイルを分けてjavascriptをimportはせず、全てhtml 内に記述する方法を紹介します。
<h1>背景</h1>
二つの選択肢の内一つを選択してもらい、その内容を回答してもらうフォームを作成しようとして、画面を分けて
<br>１：選択してもらう画面
<br>２：フォームを入力してもらう画面
<br>と分割する手もあったのですが、かっこいいから（動的に画面を表示させたいから）一つの画面で行おうと思い、作成しました。disabled属性をどのように動的に反映させるかを勉強したため、備忘録として記事を掲載します。

<h1>内容</h1>
<h3>HTML</h3>

```html:html
       <form action="./Send" method="post">
            <input type="radio" name="judge" id="data1" onclick="changeDisabled()" required>
            <label for="data1">データ1</label><br>
            内容1<input type="text" name="content1" id="content1"><br>

            <input type="radio" name="judge" id="data2" onclick="changeDisabled()" required>
            <label for="data2">データ2</label><br>
            内容2<input type="text" name="content2" id="content2"><br>
            <input type="submit" value="送信">
        </form>
```
scriptタグの位置は任意ですが、今回はbodyタグ終了後に記述しました。
<h3>javascript</h3>

```javascript:javascript
    <script>
        function changeDisabled(){
            if(document.getElementById("data1").checked){
                document.getElementById("content1").disabled = false;
                document.getElementById("content2").disabled = true;
            }else if(document.getElementById("data2").checked){
                document.getElementById("content1").disabled = true;
                document.getElementById("content2").disabled = false;
            }
        }
    </script>
```

<h1>解説</h1>

```javascript:javascript
function changeDisabled(){
```
function関数を用いて"changeDisabled"という関数を作成します。これが実行されると以下の処理が実行されていきます。

```javascript:javascript
if(document.getElementById("data1").checked){
```
javascript内では、htmlのラジオボタンやテキストボックスの状態を"getElementById"を用いて取得しています。
この部分でid=data1のラジオボタンが押されているか判定します。押されている場合は以下の処理を行います。

```javascript:javascript
document.getElementById("content1").disabled = false;
document.getElementById("content2").disabled = true;
```
ラジオボタンと同様に、"getElementById"を用いてフォームの状態を取得します。
disabled属性はtrueの時、そのフォームを入力不可能な状態にし、またデータの送信も行いません。（0文字の空欄を送る？nullではない）
データ1のラジオボタンを押すと、内容1のフォームを入力、送信可能にしたいため、disabled属性をfalseにします。そして、内容2のフォームのdisabled属性をtrueにすることによって、内容2のフォームは入力、送信不可能に変わります。<br><br>

```javascript:javascript
}else if(document.getElementById("data2").checked){
document.getElementById("content1").disabled = true;
document.getElementById("content2").disabled = false;
```
後半は同様の処理を逆で行っています。<br><br>
最後に、現在作成した"changeDisabled"関数をhtmlのラジオボタンに適応していきます。

```html:html
<input type="radio" name="judge" id="data1" onclick="changeDisabled()" required>
```
このようにタグ内の"onclick"に関数をはめ込むことによって、ラジオボタンが押されるたびに関数が実行されるようになります。