OmniAICreator/Qiita-1.07M huggingface dataset:
node で AWS Lambda Layers 使ってる奴は今すぐ作り直せ

# TL; DR

- AWS Lambda Layers の内側で AWS SDK を require してると死ぬので Lambda Layer を使ってはいけない。

# AWS Lambda で nodejs 18 のサポートが始まりました

これによって `Runtime.NODEJS_16_X` から `Runtime.NODEJS_18_X` にできるのですが `Runtime.NODEJS_18_X` からは `AWS SDK for JavaScript v2` が実行環境上に存在しなくなり `AWS SDK for JavaScript v3` のみが実行環境上に存在します。

そのため　Lambda Layer で `AWS SDK for JavaScript v2` を require する手段がなくなるので死にます。

これなら大人しく `AWS Lambda` ごとに esbuild などでくっつけていた方がまだマシでした。

少なくとも nodejs で Lambda Layer を利用する必要は全くなく、下手に利用すると AWS 側の都合で悲惨なことになってしまうので、以後 Lambda Layer を使うのは避けるべきです。
laravel DBのカラムコメントを修正するマイグレーションファイルの記載

# 概要

- laravelのマイグレーションファイルにて、カラムコメントを修正、変更する方法についてまとめる。

# 方法

1. マイグレーションファイルを作成する。（`--table=テーブル名`以外のコマンドの引数は極論なんでもいい。なんのマイグレーションファイルかをファイル名から推測するため下記のような名前に下だけである。）

    ```shell
    php artisan make:migration change_テーブル名_カラム名_comment --table=テーブル名
    ```

1. マイグレーションファイルを開き下記の様に記載する。（hoge_hogesテーブルのfoo_idカラムのコメントを変更することを想定して記載してみる。）
    - 当該カラムに既にコメントが記載されている場合

        ```YYYY_MM_DD_XXXXXX_change_hoge_hoges_foo_id_comment.php
        <?php
        
        use Illuminate\Database\Migrations\Migration;
        use Illuminate\Database\Schema\Blueprint;
        use Illuminate\Support\Facades\Schema;
        
        class ChangeHogeHogesFooIdComment extends Migration
        {
            /**
             * Run the migrations.
             *
             * @return void
             */
            public function up()
            {
                Schema::table('hoge_hoges', function (Blueprint $table) {
                    $table->integer('foo_id')->comment('変更後コメント')->change();
                });
            }
        
            /**
             * Reverse the migrations.
             *
             * @return void
             */
            public function down()
            {
                Schema::table('hoge_hoges', function (Blueprint $table) {
                    $table->integer('foo_id')->comment('変更前コメント')->change();
                });
            }
        }
        ```

    - 当該カラムにコメントが設定されていない場合

        ```YYYY_MM_DD_XXXXXX_change_hoge_hoges_foo_id_comment.php
        <?php

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

        class ChangeHogeHogesFooIdComment extends Migration
        {
            /**
             * Run the migrations.
             *
             * @return void
             */
            public function up()
            {
                Schema::table('hoge_hoges', function (Blueprint $table) {
                    $table->integer('foo_id')->comment('変更後コメント')->change();
                });
            }
        
            /**
             * Reverse the migrations.
             *
             * @return void
             */
            public function down()
            {
                Schema::table('hoge_hoges', function (Blueprint $table) {
                    $table->integer('foo_id')->change();
                });
            }
        }
        ```

1. マイグレーションを実行する
AWS認定のバッジ連携ができなくなっていたのを何とかした話

# はじめに

AWS認定は、Credlyというサイトに情報連携する事で、デジタルバッジが獲得できます。

https://www.credly.com/

今回は、前回投稿の

https://qiita.com/Syoji_Yonemoto/items/882c8dada1a4bcaf2121

でも、軽く触れましたが、2022/08 に取得した、『SAP on AWS - Specialty』のデジタルバッジが発行されなくなっていたので、サポートに問い合わせて解決した、お話。

# 前提

![自動承認.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/2f559b6b-41bd-7c2c-7051-a12f16cbdd5b.jpeg)

![デジタルバッジ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/d2143df7-cde9-4cd7-1b0e-e651ac1c3b19.jpeg)

１２冠を取った所までは、問題なく自動承認でデジタルバッジが獲得できていた。（連携設定は問題なく連携できていた時期があった）

前提事項としては、APNアカウントとプライベートメールアドレスのアカウントを分けて運用しており、

![APNサイト連携.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/cc294b4d-8006-a543-cad6-688f450b4097.jpeg)

APNアカウント側で、プライベートメールアドレスの成績共有をかけて運用しています。
（APNアカウントへの同期をしています。）

では、なぜ！？というのが今回の、お話です。

# 結論

AWS認定の取得情報や受験日の予約を管理しているサイト、『AWSトレーニングと認定ポータル』があります。

https://www.aws.training/

こちらのサイトに
+ プライベートメールアドレスのアカウント（１３冠の獲得情報＆試験結果）
+ 会社メールアドレスのアカウント（APN専用のトレーニング等の閲覧）

と、使い分けをしています。

![トレーニングサイトのメール設定.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/38d10f1a-6dfb-19f6-8ef0-b2965947fbec.jpeg)

|AWSトレーニングと認定ポータルのアカウント|プロフィールのEメールアドレス|
|---|---|
|プライベートメールアドレス|プライベートメールアドレス|
|会社メールアドレス|プライベートメールアドレス|

と『AWSトレーニングと認定ポータルのアカウント』プロフィールのメールアドレスの設定が、重複してしまっていたのが問題でした。

|AWSトレーニングと認定ポータルのアカウント|プロフィールのEメールアドレス|
|---|---|
|プライベートメールアドレス|プライベートメールアドレス|
|会社メールアドレス|会社メールアドレス|

と『アカウントに（ログインに）利用するメールアドレス』と『プロフィールに設定するメールアドレス』を揃えることで、無事にデジタルバッジの連携が再開されました。

# 問い合わせ方法について

![問い合わせリンク.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/99c84425-abf6-03d7-5d9c-b5d8a50c2e77.jpeg)

問い合わせ～解決までメモ書き（サラッと結論書いてますが、結構、往復＆時間がかかってますので、誰かの参考になれば幸いです。）

+ 現在、基本は英語サポートのみで日本語での対応を希望する場合は、その旨返信をお願いします
　　→　日本語を希望する
+ 『AWSトレーニングと認定ポータル』に複数の連絡先があり連携が競合しているので統合することで解消できます
　　→　意図して使い分けをしているのでアカウント統合は希望しない
+ 『AWSトレーニングと認定ポータル』のプロフィールのアドレスを変えてください。
　　→　デジタルバッジ連携不具合の解消！

# AWSの相談・お困りごとありましたら、、、

AWSの活用方法や、お困りごとの相談、随時、お仕事の受付しております。

https://www.cs-cloud-aid.com/
【C】関数名変数名は自由につけて良いのか

# はじめに
関数、変数、型、オブジェクトなど、用語がかなりあるが、何が関数で何が変数か分からなくなる時が未だにちらほら。
CやC#、Unityで元から用意されているものは、用意されているまま使用しなければならない。
自分で作成する変数や関数の名前はどうつければ良いのか。
文字の大小が違うだけでエラーになったり。頭の中が散らかってきたので整理します。

# 関数、変数はある程度自由な名前でよし
__シンプルで分かりやすい名前が好ましい。__

__変数名__
 【名詞】が基本
　頭もじは小文字で始まり、その後の頭もじは大文字。
　例）　playScript、mainCamera、playerPos
　
__関数名__
 【動詞】＋【目的語】
(英語の文法になるから　【目的語】　＋【動詞】)
単語の頭文字は大文字。
 例)Start、Update、PlayBall、

## 命名規則
キャメルケース
　　・ローワーキャメルケース
　　　　続く単語を大文字にする
　　・　アッパーキャメルケース
　　　　　単語の先頭を大文字にする

・スネークケース
　　単語の間をアンダーバー、アンダースコア(_)でつなぐ
 変数や関数に多い

・チェインケース
　　　　単語間をハイフン（-）でつなぐ
　　　　ドメイン、URL,ファイル名に多い
git コマンド備忘録

こんにちは。
以前から、開発中に「あれ？これどうやるんだっけ？」「こんなとき、どう解決したら良い？」など、
迷ったときにいつもお世話になっているQiitaやZe○○やStack○○さん...etcですが、自分で投稿することはありませんでした。
なので、何事も経験ということで思い立ち（もう何番煎じの情報かわかりませんが）初めて投稿してみます。

個人用の備忘録なので、細かい点は端折っております。予めご了承ください。

# gitでコミット済みメッセージを修正したい時

コマンドライン上で下記コマンドを入力後、メッセージを修正してpushする
```
git commit --amend
```
2つ以上前のコミットを修正したいときはこのようにします
```
git rebase -i HEAD~2
```

# コマンドライン上でgitログを見たい時
コミット履歴を1行で見たい時
```
git log --oneline
```
コミット履歴を1行かつグラフで見たい時
```
git log --graph --oneline
```

今後も不定期に投稿してみようと思います。
NCMBとMonaca、Framework7を使ってカレンダーアプリを作る（その2：認証の実行）

NCMBとMonacaを使ってカレンダーアプリを作ります。予定を登録したり、Framework7のカレンダーコンポーネントを使って予定を表示できるというアプリです。

[前回の記事では画面の説明とSDKの導入まで](https://qiita.com/goofmint/items/f8d07e3c28e747499095)進めましたので、今回は認証を実行します。

## コードについて

今回のコードは[NCMBMania/monaca-calendar-app](https://github.com/NCMBMania/monaca-calendar-app)にアップロードしてあります。実装時の参考にしてください。

## 認証画面について

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/6d552b74-c16a-b9e9-17e7-64894367b07d.png)


すでに紹介済みですが、認証画面は以下のようになります。ID/パスワード入力欄があって、ボタンを押すと `login` 関数が実行されます。

```html
<form id="login">
	<div class="list no-hairlines-md">
		<ul>
			<li>
				<div class="item-content item-input">
					<div class="item-inner">
						<div class="item-title item-label">ユーザーID</div>
						<div class="item-input-wrap">
							<input type="text" name="userName" placeholder="お名前" required/>
						</div>
					</div>
				</div>
			</li>
			<li>
				<div class="item-content item-input">
					<div class="item-inner">
						<div class="item-title item-label">パスワード</div>
						<div class="item-input-wrap">
							<input type="password" name="password" placeholder="パスワード" required/>
						</div>
					</div>
				</div>
			</li>
		</ul>
	</div>
	<div class="block block-strong">
		<p class="row">
			<a href="#" @click=${login} class="col button">ログイン or ユーザー登録</a>
		</p>
	</div>
</form>
```

## ログイン処理について

ログイン処理は、以下のような手順で行われます。

- 入力値の取得
- ユーザーの新規登録
- ログイン処理

すでにユーザー登録を行っていた場合、ユーザーの新規登録はエラーになります。今回はユーザー登録とログインを兼ねているので、エラーが出たとしてもそのまま続けてログイン処理を行っていきます。

### 入力値の取得

入力値の取得は Framework7の機能を使って行います。

```js
const params = app.form.convertToData($('#login'));
```

### ユーザーの新規登録

取得した入力値を使ってユーザー登録処理を行います。エラーが出たとしても無視します。

```js
const user = new ncmb.User();
// ユーザー名・パスワードを設定
user
	.set("userName", params.userName)
	.set("password", params.password);
try {
	// サインアップ処理
	await user.signUpByAccount();
} catch (e) {
	// エラーはすでにユーザーが存在する場合
}
```

### ログイン処理

そのまま続けてログイン処理を実行します。ログインがうまくいったら、カレンダー画面に遷移します。ログイン失敗した場合は、アラートを出します。

```js
try {
	// 続けてログインの実行
	await ncmb.User.login(params.userName, params.password);
	// ログインしたらカレンダー画面に移行
	$f7router.navigate('/home/');
} catch (e) {
	// 認証エラー
	app.dialog.alert('ユーザーIDまたはパスワードが違います');
}
```

ここまででNCMBを使った認証処理の完成です。

## 認証後のユーザー情報について

認証後にユーザー情報を取得する際には、下記のように記述します。

```js
const currentUser = ncmb.User.getCurrentUser();
```

認証していない場合には `null` が返ってきます。これを使って認証状態の判別が可能です。

## まとめ

今回はカレンダーアプリの認証処理について解説しました。次は[カレンダー表示と予定の登録処理を実装](https://qiita.com/goofmint/items/5267e5e61b8943c9dcd9)します。
【AWS】CloudWatchの料金体系を調べてみた

####  今回の内容  
  
今まで何度もAWSのCloudWatchを仕事&プライベートで触っていますが、CloudWatchって「なんかお金かかるなあ...」と思うことが多かったので、CloudWatchの料金について調べることにしました。  
  
なお、自分の認識が誤っている可能性もあるので、必ず詳細は自分で確認をお願いします。  
  
#### 参考  

- [Amazon CloudWatchの料金](https://aws.amazon.com/jp/cloudwatch/pricing/)
- [AWS Pricing Calculator](https://calculator.aws/#/)
  - AWSの各サービスの課金額を計算できる公式サイト

  
#### 扱うサービス  
CloudWatchにはいろいろサービスがありますが、今回は以下のサービスのみ対象にします  
  
- メトリクス  
- ダッシュボード  
- アラーム  
- ログ  
- イベント  
  
#### 前提  
  
- 金額は全て月額です。  
- 1ドル140円として計算してます。(2022/11/20現在のレート)  
 
#### メトリクス  
料金体系はこんな感じ  
  
- 基本メトリクス(初めから用意されてるもの)  
  - 基本モニタリング(5分間隔)は無料
  - 詳細モニタリング(1分間隔)は10個まで無料  
- カスタムメトリクス(自分で作成するもの)
  - 10,000メトリクスまで：0.3ドル/個
  - 次の240,000メトリクス：0.1ドル/個
  - 次の750,000メトリクス：0.05ドル/個
  - 1,000,000を超えるメトリクス：0.02ドル/個
- 詳細モニタリングも11個目からは上記の料金が適用されるっぽい？  
  
確かに、こんなものではないかな...という感じです。  
仮に20個モニタリングして、840円くらいです。(為替次第でもっと安くなる)  
ただし、決して手放しに安いわけではないので、カスタムメトリックの作りすぎは注意が必要ですね。  
  
また「Amazon CloudWatchの料金」の「料金の例：例2-カスタムメトリック」にあるように、EC2のある項目(CPU使用率など)をカスタムメトリック化して送信...などをやろうとすると、API使用料の分も料金が追加で必要なので、そこは注意です。  
  
ちなみに、メトリクスフィルタ自体には料金はかかりませんが、メトリクスフィルタの作成時には最終的にカスタムメトリクスを作成するので、結果的にカスタムメトリクス1個分の料金がかかります。  
  
#### ダッシュボード  
  
- 3個まで無料(最大50メトリクスまで表示)  
- 4個目以上からは、3ドル/個  
  
これもそんな感じかな...という感じ。  
今まで、無料枠で十分間に合っていたので、かもしれません。  
1アカウントでたくさんEC2インスタンスを立てたり複数アプリを動かしていると、そうでもないのかも。  
  
ただ単価はちょっと高めですね。(その分便利だけど)  
  
#### アラーム  
  
- 標準解像度アラーム10個まで無料  
  - 11個目以上は0.1ドル/個
- 高解像度アラームは0.3ドル/個
- 複合アラームは0.5ドル/個
  
これもそんな感じかな..と。(そればっか)  
標準解像度のアラームならばコストが安めなので、そこまで負担に感じることはなかったです。  
  
これもカスタムメトリクス同様、作りすぎに注意する感じです。(事前に精査しておくなど)  
  
#### ログ  
  
- 5GBまで無料
- 収集：0.76ドル/GB
- 保存(アーカイブ)：0.033ドル/GB
- 分析(Logs Insightsクエリ発行)：0.0076ドル/GB(スキャンデータ量)  
  
**<font color="red">「CloudWatchの料金高くね？」と感じる場合、だいだいこれのせいです。</font>**  
  
「収集」の単価が他の単価に比べてちょっとお高めな感じがあります。


また「収集」とありますが、実際にはCloudWatch Logs上で閲覧できるログは全て課金対象なので、例えば「毎月10GBのログを収集する」場合、


- 
初月：10GB - 5GB(無料枠) = 5GB * 0.76 ≒ 532円

- 
2か月目：10GB(初月分) + 10GB(当月分) - 5GB(無料枠) = 15GB * 0.76 ≒ 1,596円

- 
3か月目：10GB(初月分) + 10GB(2か月目分) + 10GB(当月分) - 5GB(無料枠) = 25GB * 0.76 ≒ 2,660円

  

と、どんどん増えていきます。
  
  
**<font color="red">※2022/11/21追記：  
上記ですが、AWSサポートから「『収集』は新規に収集(=ログに書き出し)した場合のみが対象で、一度書き出したログがずっと残っていても『収集』枠で課金されることはない」との情報を頂いたため、取り消させて頂きます。失礼いたしました。  
(もちろん、「保存(アーカイブ)」枠での課金はあります) </font>**
  
また、Logs Insightsクエリ発行もスキャン対象データが課金対象なので、累積データが増えていけば、当然課金額も増えていってしまいます。  
  
対策ですが、とにかく不要なデータは削除するなりアーカイブするなりする事だと思います。  
(アーカイブしても課金はされますが、単価はだいぶ安いです)  
  
また「保持」のデフォルトが「失効しない(=ずっと残っている)」状態なので、必ず保持期間を設定しておくのをお勧めします。(CloudFormationなら```Properties.RetentionInDays```で設定できます)  
  
それ以外には、CloudWatch Logsに書き出す内容を見直すのも大事かなと思います。
  
#### イベント  
- カスタムイベント以外は無料  
- カスタムイベントはイベント100万件当たり1ドル
- クロスアカウントイベントもイベント100万件当たり1ドル  
  
これは、そんな感じかなと思います。(個人的には良心的値段だと思う)  
実際、今までCloudWatchイベントで負担に感じたことはあまりなかったです。  
  
なお、これもカスタムメトリクスやアラーム同様、事前に内容を精査する...が大事だと思います。
  
#### まとめ(=コストを抑えるには？)  
  
- CloudWatchに設定する項目は定期的に精査、見直しする。(不要な項目は削除する)  
- <span style="color: #ff0000">**特にCloudWatch Logsはこまめに削除・アーカイブする。(不要にずっと残さない)**</span>
  - 面倒でも保持期間を設定する  
  
だと思います。
  
#### まとめ(=コストを抑えるには？) 
  
では、今回はこの辺で。
MateriApps LIVE!のインストール

## MateriApps LIVE!のインストール

- はじめてお手軽に材料科学計算を行うのに便利なツール。東大物性研ほかが提供。
- 仮想デスクトップソフトウェア(VirtualBox)上に、計算環境がすでに整ったLinux (Debian)をブートする。
- 計算環境構築で最初の難関、ソフトウェアのコンパイルをせずにすぐ計算を体験できる。

※　M1 Mac上ではVirtualBoxが動かないので、別途用意されているDocker版を使うとよい。

### 提供される計算ソフト
[https://github.com/cmsi/MateriAppsLive/wiki/ApplicationsAndTools](https://github.com/cmsi/MateriAppsLive/wiki/ApplicationsAndTools)


### 配布物一式のダウンロード

- [setup.pdf](https://github.com/cmsi/malive-tutorial/raw/master/setup/setup.pdf)
- [README.html](https://github.com/cmsi/MateriAppsLive/wiki/MateriAppsLive-ova)
- [VirtualBOXインストーラ](https://www.virtualbox.org/wiki/Downloads) VirtualBox XXXX platform packagesを探してダウンロード
- [MateriApps LIVE! VirtualBoxディスクイメージ](https://sourceforge.net/projects/materiappslive/files/) MateriAppsLive-*-amd64.ovaを探してダウンロード

### VirtualBoxのインストール
- Windows版の場合: VirtualBox-*-Win.exe
- Mac版の場合: VirtualBox-*-OSX.dmg
をダブルクリックしてインストールする

### MateriApps LIVE!のインポート
- MateriAppsLive-*.ovaをダブルクリック
- VirtualBoxが起動してインポート画面が出るので、「インポート」を押す
- 数分待って完了するとマネージャーが起動する

### VirtualBoxからの起動とログイン、使い方
- VirtualBoxのマネージャー画面から、画面内のMateriApps...を選択の上、起動ボタンを押す。
- ログイン画面が表示されるまで待つ
- ログイン情報は以下の通り
　　- ユーザ名: user
　　- パスワード: live
- デスクトップ画面が表示されればインストール成功
- ターミナル(スタートメニュー → System Tools → LXTerminal)を開いて各種計算ができる
- 各ソフトの使い方は、MateriAppsの各ソフトのレビューに参考情報が見つかるかも。
- 例えばOpenMXの場合。[https://ma.issp.u-tokyo.ac.jp/app-post-category/review?appid=594](https://ma.issp.u-tokyo.ac.jp/app-post-category/review?appid=594)

### 詳細はsetup.pdf見て
WSL2のインストールと初期設定

# WSL2のインストール
## Windows上でLinuxを動かすために、WSL(Windows Subsystem for Linux)を準備する。

Linuxディストリビューションとしては、Ubuntuを用いる。

画面左下のWindowsボタンを押して、検索窓にPowershellを入力し、表示される**管理者として実行する**をクリック。以下を入力してEnter。
```
wsl --install -d Ubuntu
```
画面左下のWindowsボタンを押して、検索窓にUbuntuを入力し、インストールされた**Ubuntu on Windows**を立ち上げる。

UsernameとPassword（Ubuntuにログインするためのもの）を聞かれたら、入力する。ただし、必ず**半角文字**にすること。日本語ダメ。

いちおう最初にパッケージをupdate（アップデートする必要があるパッケージを確認）、upgrade（アップデートを実行）する。順番に以下を入力してEnter。
```
sudo apt update
sudo apt upgrade -y
```
インストールおしまい

## Windowsターミナルのインストール
Windowsのスタートメニュー　→　Windows store　→　Windowsターミナルを見つけて入手する。

次回から、Windowsターミナルを使ってUbuntuを使うのがおすすめ。

## Ubuntuの初期設定いろいろ
### WindowsからWSL上のファイルにアクセスする
Windowsのエクスプローラーのアドレス欄に以下を入力してEnter.
```
\\wsl$
```
そうするといつものWindows画面からWSLのUbuntu上のファイルを見ることができます。編集も可。

### シンボリックリンク(Windowsでいうショートカットを作る)
例えば、Ubuntuの初期ディレクトリ(/home/「ユーザー名」)に、Windowsのデスクトップへのショートカットを作る。
```
cd
ln -s /mnt/c/User/「Windowsのユーザ名」/Desktop
```
これで、Ubuntu上からWindows上のファイルにアクセスするのも簡単。

### Ubuntu上のカレントディレクトリを一発でWindowsのエクスプローラーで開くエイリアスの作成
Ubuntu上で作業していて「このディレクトリをWindowsで開きたい」というときに使うショートカット。
初期ディレクトリに移動して、.bashrcを開く。
```
cd
vim .bashrc
```
そして、最終行に以下を追記する。
```
alias open=explorer.exe
```
vimを保存して閉じたら、
```
source .bashrc
```
で読み込んで設定完了。これ以降、
```
open .
```
で、現在のディレクトリをWindowsのエクスプローラーで開くことができる。

## その他(WindowsのPowershell上の操作)
※ちなみに、インストールされてるディストリビューションを確認するときは以下の通り。
```
wsl -l -v
```

※Ubuntuを消したり再インストールしたくなったら、以下のコマンドを入力すればきれいさっぱり。
```
wsl --unregister Ubuntu
```

※Ubutuをシャットダウンするときは以下の通り。
```
wsl --shutdown
```
○○分刻みの次回時間を計算


１５分刻みにしたときの次回の時間を計算。応用して分刻みの時刻表も可能

```php
public function calc_datetime ($margin_minutes=15) {
    $timestamp = strtotime(date('Y-m-d H:i:s'));
//    $timestamp = strtotime(date('Y-m-d H:i:s', strtotime('2023-01-01, 00:00:00')));  時間指定する場合
    $year = date('Y', $timestamp);
    $month = date('m', $timestamp);
    $day = date('d', $timestamp);
    $hour = date('H', $timestamp);
    $minute = date('i', $timestamp);
    if($minute % $margin_minutes) {
      $minute += $margin_minutes - ($minute % $margin_minutes);
    } else {
      $minute += $margin_minutes;
    }
    $datetime = date('Y-m-d H:i:s', mktime($hour, $minute, 0, $month, $day, $year));
    return $datetime;
  }
```
prototype を知ることで MDN が読みやすくなった話

# はじめに 
株式会社Relicでフロントエンジニアとして働いてる、えーきといいます。
今年から仕事でjavaScriptを書き始め、まだまだ勉強中の新米エンジニアです。

突然ですが、javaScriptのメソッドを調べると、だいたいMDNが検索上位に表示されるかと思います。
map()メソッドやsplit()メソッドをMDNで見てみると、
- **Array.prototype.map()**
- **String.prototype.split()**

の様な書き方がされています。

この記事では、***.prototypeってどこから現れたの？という疑問に対して調査した記事になります。
同じ様な疑問を感じられた方がいらっしゃれば、お時間のある時に読んでもらえたら嬉しいです。

# 結論
最初に ***.prototype の正体について下記のコードを用いて説明します。
```javascript:hoge.js
const arr = []
console.log(typeof arr) //object
console.log(arr instanceof Array)  //true
console.log(arr.__proto__ === Array.prototype)  //true
```
以上のコードから分かる様に、
**arr はグローバルオブジェクトで定義されている Array オブジェクトのインスタンスであり、 arrオブジェクトの継承元はArrayオブジェクトのプロトタイプオブジェクトを参照しているから** 
だと理解しました。(Array.prototypeにmapメソッドは定義されている)

次章からは理解するまでに調査した`__proto__,prototype`などについて紹介していきます。

# `__proto__` について
MDNでは以下の様に記載されています。

> __proto__ は Object.prototype のアクセサープロパティ (ゲッター関数およびセッター関数) で、アクセスされるオブジェクトの内部の [[Prototype]] (オブジェクトまたは null のどちらか) を暴露します。

javaScriptで実装している時に、[[Prototype]]を意識することは、ほとんどないかと思います。
確認したい場合は検証ツールで arr の [[Prototype]] を確認することができます。

![スクリーンショット 2022-11-21 3.22.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696080/b1b18ea9-5413-c7dc-e72a-cdc529f848a9.png)

この [[Prototype]] の中身が見たい場合に`__proto__`プロパティを使用して確認することができます。
[[Prototype]]には、インスタンス(arr)の継承元となる(Arrayオブジェクト)のprototypeプロパティへの参照を格納しています。

stringやnumberといったプリミティブはオブジェクトではないため、自動でプリミティブからオブジェクトへの変換をしてくれています。
この変換をboxingといいます。[詳しくはこちらを参照](https://typescriptbook.jp/reference/values-types-variables/boxing "詳しくはこちらを参照")してください。


# `prototype` について
`__proto__`と同じく、MDNで`prototype` について見てみます。
> オブジェクトは prototype オブジェクト を持つことができます。これはテンプレートオブジェクトとして機能し、そこからメソッドやプロパティを継承します。

こちらの文章から分かる様に `prototype` は他のオブジェクトの機能を継承することできます。

今回だとarrは、Arrayオブジェクトのprototypeを継承していると言えます。
ではArray.prototypeは何を継承しているのでしょうか？
検証ツールで確認してみると、
![スクリーンショット 2022-11-21 4.20.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696080/162ab65e-29d7-a845-fde2-7f023ecb1b29.png)

Objectのprototypeを継承していました。 Object.prototypeの継承元はnullでしたので終点の様です。


# Objectについて
ここまでの継承関係を図で表すと以下の様になります。

![スクリーンショット 2022-11-21 4.46.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696080/02898ef4-ab55-a23f-bb3c-4353723d746f.png)

このArrayとObjectは `Standard built-in objects`と呼ばれjavaScriptの標準仕様として規定されているオブジェクトです。
特にObjectはプリミティブ型やオブジェクトの継承元となっているだけでなく、DOMの継承元にもなっています。

図より、Objectから脈々とメソッドが受け渡されていることがわかりました。
またarrではArray.prototypeで定義されているメソッドだけでなく、さらに継承元であるObject.prototypeで定義されているメソッドも参照することができます。
このような参照したオブジェクトに該当のメソッドがない場合に、`__proto__`が参照するprototypeへ探しに行くことをプロトタイプチェーンと言います。
気になった方は[こちらの記事](https://qiita.com/howdy39/items/35729490b024ca295d6c)を参照してください。

# 最後に
初めてjavaScriptの仕組みに目を向け調査をしてみました。
まだまだ知識不足ではありますが、こういったことを理解することで少しずつ頼られるエンジニアになれるのではと思いました。

この記事を書くにあたって一緒に調査してくださった方や助言をしてくださった方、本当にありがとうございました。
これからも体調を崩さない程度に頑張っていきます！

### 参考記事
http://tsudoi.org/weblog/4979/

https://qiita.com/takeharu/items/809114f943208aaf55b3

https://jsprimer.net/basic/prototype-object/
IntuitiveCustomPostOrderとget_terms()を併用できない条件がある


## 概要

表題どおりですが、↓のようなケースで地味にハマったので忘備録も兼ねて。

- Intuitive Custom Post Orderを使ってタクソノミーを並び替えている
- 並び替えた順序に従って、get_terms()でタームを取り出す


## 本題

端的に言うと、`orderby=menu_order` は fieldsプロパティと併用できないようです。

### 動かないコードの例
fieldsにデフォルト値以外が指定されていると動きません。

```php
// ラベルを取り出したい
$terms = get_terms($taxName, [
  'orderby' => 'menu_order',
  'fields' => 'name'
]);
```



### 動くコードの例
一度オブジェクトで取り出した後にforeachで任意のfieldを取り出しましょう。

```php
// 1. オブジェクトを取り出す
$terms = get_terms($taxName, [
  'orderby' => 'menu_order',
  'fields' => 'all' // fieldsプロパティを指定するときはallを設定する必要があります
]);

// 2. ラベルだけ取り出す ... 'fields'=>'name' と同じ結果を受け取る
foreach ($terms as $i => $termObj) {
  $terms[$i] = $termObj->name;
}
```


※ $termsの型が `Array<stdClass>` → `Array<String>` になってるのはご愛嬌ということでご勘弁ください...





## 余談

↓の2点を考えると、パフォーマンスは下がりそう。

- fieldsが指定できればクエリの時点でSELECTする列を減らせる [^1] [^2]
- 条件によっては結構大きいオブジェクトをforeachにかけなきゃいけない

プラグイン使う時点である程度は覚悟しなきゃいけないとはいえ、ちょっと悲しいですね。


[^1]: https://github.com/WordPress/wordpress-develop/blob/6.1/src/wp-includes/taxonomy.php#L1267-L1331
[^2]: https://github.com/WordPress/wordpress-develop/blob/6.1/src/wp-includes/class-wp-term-query.php#L348-L906
AccessのVBAで日付を曜日の文字列に変換

# やり方

```vb
WeekdayName(Weekday("2022/01/02"))
```

```Weekday()``` で曜日の数字に変換後、```WeekdayName()``` に通す。

『日曜日』のように『曜日』の文字列がうしろに付いてくる。

```Weekday()``` は数字のみの日付だと例外になるので注意。

```vb:動作確認サンプル
'スラッシュあり日付（ゼロ埋めあり）
'『日曜日』
Debug.Print WeekdayName(Weekday("2022/01/02"))

'スラッシュあり日付（ゼロ埋め無し）
'『日曜日』
Debug.Print WeekdayName(Weekday("2022/1/2"))

'スラッシュあり日付（月まで）
'この場合例外にならず2022/01/01（月初）の結果になる。
'『土曜日』
Debug.Print WeekdayName(Weekday("2022/1"))

'ハイフンあり日付（ゼロ埋めあり）
'『日曜日』
Debug.Print WeekdayName(Weekday("2022-01-02"))

'ハイフンあり日付（ゼロ埋め無し）
'『日曜日』
Debug.Print WeekdayName(Weekday("2022-1-2"))

'ハイフンあり日付（月まで）
'この場合例外にならず2022/01/01（月初）の結果になる。
'『土曜日』
Debug.Print WeekdayName(Weekday("2022-1"))

'数字のみ日付
'型が一致しませんの例外になる。
Debug.Print WeekdayName(Weekday("20221121"))
```

# 参考サイトさん

https://dekiru.net/article/15586/

# バージョン

Windows 10 Pro 21H2 OSビルド 19045.2311
 Microsoft Access for Microsoft 365 MSO (バージョン 2209 ビルド 16.0.15726.20188) 32 ビット
【React】React Testing Libraryを使ってみる

## React Testing Libraryとは？
Reactアプリケーションをテストできるライブラリです。
Testing LibraryはVueなどのフレームワークでも利用することができます。

### 使用するコード
TestComponent.js
```typescript
const TestComponent = () => {
  return (
    <div>
      <form>
        <h1>こんばんわ</h1>
        <h2>こんにちは</h2>
        <input type="radio" />
        <button>ボタン1</button>
        <button>ボタン2</button>
        <img src="/logo512.png" alt="React" />
      </form>
    </div>
  );
};

export default TestComponent;
```

### テストの実行
テストを実行するファイルを作成します。名前を`TestComponent.test.js`とします。
テストを実行するファイルであることが分かるように`test`を含めます。

```typescript
import { render, screen } from "@testing-library/react";
import TestComponent from "./TestComponent";

test("TestComonentのテスト", () => {
    render(<TestComponent />);
    //テストの記述
});
```
今回使用するコンポーネントの`TestComponent`とテストのための`render`と`screen`をimportします。

4行目の`test()`にテストの記述をしていきます。

* こんにちはのテスト
まずは簡単に`こんにちは`をテストしたいと思います
```typescript
<h2>こんにちは</h2>
```
```typescript
const konnichiwa = screen.getByText("こんにちは");
expect(konnichiwa).toBeInTheDocument();
```
方法としては`screen.getByText()`として`こんにちは`を挿入します。
それを`konnnichiwa`という変数に格納しておきます。
その変数を`expect(変数名).toBeInTheDocument()`で比較します。
成功するとコンソールに`1passed`と表示されます。

* 失敗例
```typescript
const konnichiwa = screen.getByText("おはようございます");
expect(konnichiwa).toBeInTheDocument();
```
比較する文字列を仮に`おはようございます`とすると存在しないため、失敗します。

* getByRoleでの取得
次にgetByRoleで以下の2つの要素をテストします。
```typescript
<h1>こんばんわ</h1>
<h2>こんにちは</h2>
```
getByRoleでテストするには`screen.getByRole("heading")`とします。
`heading`とすることで`<h1>~<h6>`までの要素を取得することができます。

```typescript
const h1El = screen.getByRole("heading", { name: "こんばんわ" });
expect(h1El).toBeInTheDocument();

const h2El = screen.getByRole("heading", { name: "こんにちは" });
expect(h2El).toBeInTheDocument();
```
`heading`だけだと、どの要素を持ってくればいいのか分からないので`{name:"こんばんわ"}`の様に指定してあげます。

* input要素
input要素では以下のテストコードです。
```typescript
const radioEl = screen.getByRole("radio");
expect(radioEl).toBeInTheDocument();
```
`type=radio`を指定してあげます。仮にJSX内に同じ要素がある場合は1番初めに書かれている要素が取得されます。

* img要素
img要素では以下のテストコードです。
```typescript
const imgEl = screen.getByRole("img");
//Altの属性で取る
const imgEl2 = screen.getByAltText("React");

expect(imgEl).toBeInTheDocument();
expect(imgEl2).toBeInTheDocument();
```
getByAltTextで`Alt`の文字列を指定して取得することもできます。

* button要素
button要素では以下のテストコードです。
```typescript
const buttonEl1 = screen.getByRole("button", { name: "ボタン1" });
const buttonEl2 = screen.getByRole("button", { name: "ボタン2" });

expect(buttonEl1).toBeInTheDocument();
expect(buttonEl2).toBeInTheDocument();
```
コードには`button`要素が2つあるので`こんにちは、こんばんわ`の時と同じように`{name : ○○}`でボタンの名前を指定します。

Testing Libraryにはクエリの優先順位があるようです。
***1.getByRole
2.getByLabelText
3.getByPlaceholderText
4.getByText
5.getByDisplayValue***
詳しくは[こちら](https://testing-library.com/docs/queries/about/)を参照
VueなどSPAがリロードでNot Foundになる件に対応

Vueのアプリでvue-routerを使いSPAにしたとき、
デプロイした環境でブラウザのリロードを行うとNot Foundになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/42e89173-62f1-c685-953d-a56efd33cdab.png)

このときHTTPサーバの設定が必要であることをいつも忘れるので記録する。

## apacheの場合

```console
sudo vi /etc/httpd/conf/httpd.conf
```

```xml
<VirtualHost *:80>
    ServerName (YourServerName or IP address)
    DocumentRoot /var/www/html
    <Directory "/var/www/html">
        FallbackResource /index.html
    </Directory>
</VirtualHost>
```

```console
sudo systemctl restart httpd
```

## nginxの場合

```console
sudo vi /etc/nginx/nginx.conf
```

```json
server {
    listen       80;
    charset      utf-8;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }
}
```

```console
sudo systemctl restart nginx
```

## 参考

- https://stackoverflow.com/questions/55977676/error-404-on-reload-or-direct-url-with-vue-and-apache
- https://stackoverflow.com/questions/66511355/404-on-refresh-with-vue-router-and-nginx
情シスすごろくやってみた

# はじめに
先日HENNGEさんで開催されたイベントで話題になっていた情シスすごろくを体験してきました

https://hennge.com/jp/now/

https://hennge.com/jp/info/henka/interview/20221007_joshisu_sugoroku.html

お土産で頂いたので社内のメンバーと一緒に遊んでみました

# ルール
- 5ターン（5週間）20マス（20営業日）を安寧に過ごして体力と支援ポイントの合計値が高い人が情シスの鑑
    - ゴールに辿り着けなければそもそも負け。
- サイコロを振って止まったマスでイベントが発生、対応するソリューションを持っていれば回避、持っていなければメンタルと体力を削られる。
- メンタルが削られると出目が悪いサイコロをふらなくてはいけない。
- 3週目から手持ちのソリューションを放棄することにより、対応したマス進むことができる。（手札の半分まで）
    - ただし放棄する理由を述べなくてはいけない。

# プレイしてみた

イベントマスの内容はネタバレになるので伏せます。
イベントマスで起きた事象に対応するソリューションが手札にない場合、体力とメンタルが削られ手札が増えます。
基本、よほど運が良くないと前に進めません（メンタルが削られてマイナスになることが多い）

そして赤いイベントマス（天災マス）に止まると、天災なので対応するソリューションはなく
メンタルと体力が削られるだけではなく、災害なので時間外対応としてゴール手前にイベントマスが追加されます。
（営業日が増える）
運悪く何人も止まると営業日が30日を超えることも・・・
こうなるとゴールは至難の業になります。
数回プレイして最長で38営業日まで増えたケースがありました、~~8月39日ですかね。~~

3ターン目になると、手札を捨てて前に進むことができるようになります。
ここからがこのゲームの本番、ソリューションを捨てる理由を説明しないと捨てられません。

社外の人とプレイする場合や若い人が多い場合はわりとあっさりとした理由で捨てていくのですが、
情シス歴が長いおじさんとかだと、会社の闇がポロッとでたりしてこれが闇が深い深い・・・
そんな理由で？＞実際にあったんだよ・・・などという感じで本当に導入できなかった理由なんかの話が出てきたりします。
~~盛り上がると1時間で終わらない~~

だいたいは、Excelで頑張るとか自分が頑張るとかブラックな話でソリューションを見送るのですがそれもそれで生々しい。

10マス進むとchameleon(カメレオン)マスを通過し、他ユーザーから支援を受けることができます。
自分HENNGEさんとは関係ないのですが、HENNGEさんのユーザーコミュニティだそうです。

https://hennge.com/jp/service/one/chameleon/

このますを通過した人同士で、対応するソリューションを融通することができるようになります。
融通した人は支援ポイントをGETし、情シスの鑑に一歩近づきます。

また、2人以上同時に融通することはできないため、その場合は自社のソリューションをプレゼンする形になります。
がんばって自社のシステムを売り込みましょう。
メリットを説明する人が多いですが値段には勝てない。
支援ポイントを与える形になるのであえてダメージを受けるなどという駆け引きも。

3ターン目以降ゴールに駆け込むために一気に手札を捨てていくのですが
メンタルが削られているとマイナスと相殺されていまいち進めないことも多く
前述の天災で営業日が伸びていると誰もゴールできずに全滅も多かったです。

# まとめ

情シス歴20年ぐらいのおじさん的に大変よくできたすごろくだと思いました（小並感
イベント内容もあるあるネタ満載、天災もあったあったって感じで
そこからかなり話が盛り上がり、淡々とプレイすれば1プレイ30分ぐらいですが
最長で1時間半ぐらいかかったケースもあり、コミュニケーションツールとして大変よかったです。
~~どこまで話して良いのかの線引きが必要~~

新メンバーや、若い子交えてプレイすると良い感じでした。
【海外イベント紹介】Headless vs Traditional eCommerce Platforms

オランダのアムステルダムにある「財団法人GitNation」が毎年開催するカンファレンス「JSNation」。
今回は、そこで2021年に行われたプレゼンテーションから、Commerce Layer社、Fabrizio Picca氏のライトニングトークの内容をお届けします。
同社が提供するプラットフォーム「Commerce Layer」において、従来のWebデータベースの問題点をJamstackのアーキテクチャでどう解決しているのか、注目です。

:::note info
<strong>目次</strong>
* 従来のモノリスなシステムの問題点
* Jamstackの思想がもたらす解決策
* まとめ
:::

## 従来のモノリスなシステムの問題点

従来のWebシステムの多くは<strong>巨大なモノリスと化している</strong>といわれています。
「モノリス（monolith）」とは、遺跡などにある巨大な平らな一枚岩のこと。ここでは、大きな１つのものにすべてを詰め込んだシステムのことを意味します。
そのようなシステムには、大抵、以下のような問題があります。

#### 柔軟性の欠如
一部のモジュールを変更しただけでも、システム全体に影響を与えてしまいます。つまり、ニーズの変化に素早く対応できません。
#### 遅いWebサイト
すべてを1台で賄うというアーキテクチャでは、モダンなCDNのような機能を活かせません。GoogleのCore Web Vitalsのような、速さを指標とするアルゴリズムに変更された場合、遅いWebサイトでは太刀打ちできません。
#### セキュリティの問題
たった1つの欠陥がサービスの停止を招きます。これは、セキュリティ上の大きなリスクです。
#### デスクトップを意識した造り
レガシーシステムが稼働しているため、多くがデスクトップ向けに作られています。モバイルファーストのような考え方が浸透していません。
#### 高額
良いサーバーにすべてを入れようとすると、不要な機能やスペックも漏れなく実装されているため、高額な費用がかかります。
 
実は、現在の多くのサービスやWebアプリケーションがこのような問題を抱えています。
では、どのようにこれらの問題に取り組むことができるのでしょうか。
解決策をみていきましょう！

## Jamstackの思想がもたらす解決策

これらの問題を解決するためには、<strong>モジュール化</strong>が必要です。
つまり、モノリスを解体し、上手に分割するのです。
提供しているサービスを細かな単位に分け、疎結合で繋ぐことで、それぞれの依存関係を少なくします。
まさに、Jamstackの思想です。
Commerce Layerでは、上記の思想に基づいてサービスのアーキテクチャを設計しています。

下の図を見てください。
例えば、在庫管理にはHeadless CMSを使用しています。それが静的サイトジェネレーターと連動しています。生成されたサイトはCDNによって配信されます。
サービスの本体であるCommerce Layerとは、それぞれがAPIでつながっています。在庫の参照、チェックアウト、顧客アカウントの管理情報などがCDN経由で取得されます。
![221117_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1242415/ebe19318-d743-5409-4c27-7adf2a3e73f8.png)

図の右の方にあるのは、参照する他のサービスです。
例えば、グローバルにeコマースを展開するには、その地域に合った税金計算の仕組みが必要です。疎結合で各種の税金計算サービスを参照することで、シンプルなアーキテクチャを維持できます。
CRMのようなレガシーシステムにも、不要な依存関係を作らずに参照できます。

結果として、以下のことが実現できるのです。
* <strong>抜群の柔軟性</strong>
* <strong>安く、スケールしやすい</strong>
* <strong>疎結合によるセキュリティ</strong>
* <strong>オムニチャネルの設計</strong>
* <strong>将来性</strong>

## まとめ

Commerce Layer社のサイトを見てみると、モノリスをデカップルするという従来の概念を覆す方法でeコマースを実現しようとしていることがわかります。
同じブランドやショッピングサイトにおいて、複数の言語や地域でサービスを展開しようとすると、以下のような難題に直面します。

税金の計算方法が異なる
配送業者へ自動的に注文を送信する方法やその管理の仕方も異なる
 
従来のモノリスなシステムにすべて組み込もうとすると、非常に複雑になります。
なんとか動くようになったとしても、もう触ることすら恐ろしい、「誰もこれ以上変更を加えませんように…」と願うだけのシステムが出来上がってしまうでしょう。
実際、そのようなシステムは世の中に無数に存在しているのです。

こう考えると、グローバルなeコマースはJamstackの利点を最大限に活かすことができる分野といえます。

ただし、この疎結合を実現するためには、非常に精緻な設計が必要です。
果敢に挑む開発者たちによって、Jamstackにおける一つの理想の形が達成されるというのは、とても頼もしいことです。

最後まで読んでくださり、ありがとうございました。

株式会社ヒューマンサイエンスは、他社にはない、「ドキュメント制作のノウハウ」×「最新のWeb開発技術（Jamstack）」を用いて、Webコンテンツとプラットフォームのソリューションをご提供します。
関心がある方は、ぜひこちらまでお問い合わせください！

<strong>株式会社ヒューマンサイエンス</strong>
https://www.science.co.jp/document/jamstack.html

本文書の出典元：https://www.youtube.com/watch?v=2FAStwFFZKE&t=187
Google SpreadSheet: 複数のリッチテキストからURLを抽出する

以前 [Google SpreadSheet: ハイパーリンクを一括抽出する](https://qiita.com/matsukatsu/items/09065da0b6d650111b1d) という記事を書いたのですが、これではうまくいかないケースがあったので、ちょっと調べて別の手段を講じましたので、紹介しておきます。

SpreadSheet でセル全体に対してリンクを設定すると、そのセルには1つのリッチテキストが存在する事となって従来の手法でも取得できたのですが、セルの一部の文字列に対してリンクを設定すると、そのセルには複数のリッチテキストが存在する事になるらしく、従来の手法ではURLを抽出できませんでした。

図にしてみるとA列のような場合、従来手法のD列はA4しか抽出できませんでしたが、今回の手法であるBC列はA2, A3も抽出できています。
![スクリーンショット 2022-11-20 22.21.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/b832f58a-5136-ac14-d5c2-2769047dcea1.png)

## 今回の手法で作成した関数
今回は `getLinkUrlAndText` という関数を作成しました。引数に対象の1列を表す範囲を文字列として与えると、URLとそれを設定された文字列を取得して返却します。
```
function getLinkUrlAndText(rangeText) {
  const ss = SpreadsheetApp.getActiveSpreadsheet()
  const sheet = ss.getActiveSheet()
  const range = sheet.getRange(rangeText)
  const vals = range.getRichTextValues()
  const row = [];

  if(vals[0].length > 1){
    Browser.msgBox("1列だけ指定してください。例) A2:A10")
    return
  }

  for( let i=0; i<vals.length; i++ ){
    const cell = vals[i][0]
    const richTxtArr = cell.getRuns()
    for( let j=0; j<richTxtArr.length; j++ ){
      const richText = richTxtArr[j]
      const url = richText.getLinkUrl()
      if(url){
        row.push([richText.getText(), url])
        break
      }
    }
  }

  return row
}
```
#02 GISで利用できるマップ タイルのURL

GISの背景地図に利用できるマップタイルのURLでおすすめは以下の通り。淡色地図が背景地図としては利用しやすくて良い。

●地理院地図
・標準地図
URL：https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png

・淡色地図
URL：https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png

●グーグルマップ
URL：https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}
「[Firebase] Cloud Firestore データベースに安全でないルールがあります」という警告メールへの対処の備忘

# はじめに
Firebaseを使用してアプリを制作していたところ、CloudFirestoreの「セキュリティルールに関する次の問題が検出されました」とのメールが届いたので、セキュリティルールの設定について対処したことを、備忘として記事にしておきたいと思います。

# 環境
Firebase 9.12.1

# セキュリティルールの書き方の基本
> すべての Cloud Firestore セキュリティ ルールは、データベース内のドキュメントを識別するmatchステートメントと、それらのドキュメントへのアクセスを制御allow式で構成されます。(公式ドキュメントより)

```
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /<some_path>/ {
      allow read, write: if <some_condition>;
    }
  }
}
```
1行目: `rules_version = '2';`
ルールのバージョンを指定します。ワイルドカード再帰判定の扱いや、ドキュメントが深くネストされたサブコレクションにある場合なども、セグメント全体を参照できるなど、新しいFirestoreのクエリに対応するためのルールが使えるバージョンを宣言しています。<br>
2行目：`service cloud.firestore`
「これはCloud Firestore用のルールですよ」ということを明示するものです。CloudStorageなど、他のプロダクトと競合することを防ぎます。<br>
3行目：`match /databases/{database}/documents`
今から適用するルールが、プロジェクト内のデータベースに対してのものですよ、ということを示すものです。（初期値では「default」という名前の一つのデータベースしか存在していません。）<br>
4行目：`match /<some_path>/`
ここで、**ドキュメントパス**を指定します。※コレクションではないことに注意<br>
5行目：`allow read, write: if <some_condition>;`
指定されたデータの読み取り/書き込みを許可するかどうか、allow式で構成されます。




# 今回警告メールが届いた理由

以下設定で開発を進めていたところ、警告が発生。

```
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
       allow write: if request.auth.uid != null;
       allow read: if true
    }
  }
}
```

アプリで実現したかったことは、
1. 未認証ユーザーは、READのみ可能
2. 認証ユーザーは、READ, WRITEのどちらも可能 

だったのですが、上記で使用されているルール4行目: `match /{document=**}`では、**データベース全体**をユーザーが読み取ることができてしまうため、特定のデータパスを指定してあげる必要があります。


# 対処したこと
最初に考えたのは、**データベース全体**ではなく、アプリで使用する**Collection全体に対して**読み取り、及び書き込みが可能なように設定をすることです。今回自分が用意しているコレクション（posts, users）を、そのまま指定することを考えました。<br>

しかし、先ほども書いたように、すべての`match`ステートメントは、コレクションではなく、**ドキュメント**を指す必要があります。<br>

なので以下のように設定し、各posts,usersコレクション配下の任意のドキュメントに、[再帰ワイルドカード構文](https://firebase.google.com/docs/firestore/security/rules-structure#recursive_wildcards)を使用し、設定することにしました。

```
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /posts/{document=**} {
       allow write: if request.auth.uid != null;
       allow read: if true
    }
    match /users/{document=**} {
       allow write: if request.auth.uid != null;
       allow read: if true
    }
  }
}
```

４行目:`match /posts/{document=**}`で、今回用意したpostsコレクションを指定
８行目: `match /users/{document=**}`で、今回用意したusersコレクションを指定


# 最後に
### さらなる設定
セキュリティルールでは、
* READルールは、「GET」と「LIST」
* WRITEルールは、「CREATE」 「UPDATE」 「DELETE」
に分割することができます。

今回は、警告に対する対処、ということで、きめ細かい設定がまだ実装できていませんが、これからインプットしてゆきたいと思います。

もしも、上記の内容に誤りや過不足等ありましたらコメントで教えていただけると幸いです。

ここまでお読みいただきありがとうございました。

# 参考
* https://firebase.google.com/docs/firestore/security/get-started
* https://firebase.google.com/docs/firestore/security/rules-structure
Goでスタックトレースを実装

# スタックトレースとは
実行中のプログラムがエラーを起こした際に、その直前まで実行していた関数やメソッドの履歴を表示すること。

インタプリタ型言語の実行環境では準備されていて、デバッグ時にエラーを出した際にはスタックトレースが見られることが多い。

サーバーサイドのデバッグにはこのスタックトレースがあるかないかで作業効率に天と地ほどの差を生む（と考えている）ので
この記事ではGoでのスタックトレースの実装方法を紹介する。

# Goでの実装
環境: go1.17.10

使用するパッケージ
https://pkg.go.dev/runtime

```go:main.go
package main

import (
    "runtime"
    "fmt"
)

func showStackTrace() {
    i := 0
    for {
        pt, file, line, ok := runtime.Caller(i)
        if !ok {
            break
        }
        funcName := runtime.FuncForPC(pt).Name()
        fmt.Printf("file=%s, line=%d, func=%v\n", file, line, funcName)
        i += 1
    }
}

```

# 解説
`runtime.Caller(i)`とすると4つの返り値を取得できる。
返り値は順にプログラムのカウンター、ファイル名、行数となる。最後のokはboolean型で情報が取得できなかった時にはfalseとなる。

そのためokがfalseになったときにループ処理を抜けるようにbreakするようにし、プログラムカウンターをインクリメントしていくとスタックトレースに必要な情報を取得できる。

また、`runtime.FuncForPC(pt).Name()`でプログラムカウンターに含まれる関数名を取得できる。

最後にfmt.Printf や log.Printfで任意のフォーマットでロギングする。


# 実際の使い方
スタックトレースはエラーの時に表示したい場合が多い。
そのためエラーハンドリングの際に共通してスタックトレースを表示する実装例を示す。

```go:main.go
package main

import (
	"errors"
	"fmt"
	"runtime"
)

func main() {
	if err := doSomething(); err != nil {
		handleError(err)
	}
}

func doSomething() error {
	fmt.Println("Do something")
	return errors.New("An error occurred")
}

func handleError(err error) {
    fmt.Println(err.Error())
	i := 0
    for {
        pt, file, line, ok := runtime.Caller(i)
        if !ok {
            break
        }
        funcName := runtime.FuncForPC(pt).Name()
        fmt.Printf("file=%s, line=%d, func=%v\n", file, line, funcName)
        i += 1
    }
}
```

上記の例では`doSomething()`でエラーを返すようにし`handleError(err)`の引数にerrorを渡すようにした。
`handleError(err)`ではerrorの内容とスタックトレースを出力するようにした。
【zsh】ディレクトリ構造の差分をツリー形式で表示する

# やりたいこと
`tree` コマンドと [colordiff](https://github.com/daveewart/colordiff) を利用して、以下のようなディレクトリ構造の差分をツリー形式で表示すること:

```diff
 .
-├── app
-│   └── app.js
 ├── css
-│   ├── reset.css
 │   └── styles.css
 ├── img
 │   ├── image1.png
-│   ├── image2.png
+│   ├── image3.png
 │   └── image4.png
 └── index.html
```

# 導入方法
macOS で [Homebrew](https://brew.sh/index_ja) を利用している場合は、以下のコマンドで `tree` コマンドと `colordiff` コマンドをインストールします:

```shell
$ brew install tree colordiff
```

`.zshrc` に以下の関数を追加します:

```zsh:.zshrc
function treediff () {
  local sed_command=$(echo -ne 's/\u2514/\u251c/g')
  colordiff <(cd $1; tree . | sed -e $sed_command) <(cd $2; tree . | sed -e $sed_command) -U10000
}
```

<details><summary><code>sed</code> コマンドの処理内容</summary>
<code>tree</code> コマンドが出力する罫線 <code>└</code>(<code>\u2514</code>) を <code>├</code>(<code>\u251c</code>) に置き換えることで、罫線が差分とならないようにしています。
</details>

シェルを再起動します:

```shell
$ exec $SHELL -l
```

# 利用方法
`treediff directory1/ directory2/` のように比較したい 2 つのディレクトリのパスを指定してコマンドを実行すると、以下のようにディレクトリ構造の差分がツリー形式で出力されます:

```diff
--- /dev/fd/11  2022-11-21 10:00:00.000000000 +0900
+++ /dev/fd/12  2022-11-21 10:00:00.000000000 +0900
@@ -1,13 +1,10 @@
 .
-├── app
-│   ├── app.js
 ├── css
-│   ├── reset.css
 │   ├── styles.css
 ├── img
 │   ├── image1.png
-│   ├── image2.png
+│   ├── image3.png
 │   ├── image4.png
 ├── index.html
 
-3 directories, 7 files
+2 directories, 5 files
```

# 参考にしたページ
- [sedでユニコードを指定して置換を行う | 俺的備忘録 〜なんかいろいろ〜](https://orebibou.com/ja/home/201611/20161101_002/)
- [[Linux][Git][diff] diffコマンドで省略表示しないようにする（diffを追加してかつ全行を表示） - Qiita](https://qiita.com/koara-local/items/22e78fc2a35c41eed29a)
WSL2／UbuntuでPHP-FPMとNginx連携のハマりどころ

## はじめに
Windows11のWSL2にUbuntu20.04LTSを入れてます。
先日、そこにNginxとphp-fpm（php8.1）を入れて連携設定したときの「WSL2」ならではのハマりどころがあるので、それをまとめておこうと思います。
なお、php-fpmは最新版をえるため「 ppa:ondrej/php」をリポジトリに追加しています。

## localhostの解決
WSL2上のUbuntuにWebサーバー「Nginx」サービスをスタートさせれば
「http://localhost:xxx」（xxxはNginxに設定したポート）
でページ表示可能です。
これは、WSL2 の localhostForwarding 機能が、Windows側から localhost でWSL2側で listen しているポートにアクセスできるようにしてくれているからです。
これ動いていない（localhostForwarding=false）だと、Windowsのブラウザで
「http://localhost」
でWSL2でlistenしているNginxにアクセスすることはできません。
でも、WSL2では「localhostForwarding=true」がデフォルトなので気にすることはありません。
しかし、僕のようにWSL1からWSL2にアップグレードした環境だと、まれに、こういうことがあるみたいです（理由や条件までは調べてませんが、僕はたまたまハマりました(;_:)）
そんなときは。
Windowsの「C:\Users\<user>」の直下に、「.wslconfig」というファイルを作って、以下のように記入して保存して、
```
   [wsl2]
   localhostForwarding=true
```
 PowerShellを管理者権限で立ち上げて「wsl --shutdown」を実行してから、WindowsターミナルでUbuntuのbashを起動して設定を反映させます。
それで
「http://localhost:xxx」
でアクセスできるようになります。

ちなみに。
「http://localhost:xxx」
でアクセスできないとき一番に疑うべきなのは、Ubuntu上のNginxがエラーなくスタートできているかどうかですけどね。
スタートしているのにうまくいかないと相談されて見に行って「sudo nginx -t」してみると、設定ファイルにエラーがあった・・何てことは・・まま・・ありますので。

## PHPを動かしたときの「502 Bad Gateway」エラー
これが発生したら、とりあえずエラーログを見ます。
```
less /var/log/nginx/error.log
```
エラーメッセージのパターンは、ほぼ以下の２通りが多いです。

:::note alert
connect() failed (111: Connection refused) while connecting to upstream
:::

:::note alert
connect() to unix:/run/php/php8.1-fpm.sock failed (2: No such file or directory
:::

#### ひとつめの「while connecting to upstream」エラー
僕の知る限り、このエラーの時は「php-fpm」サービスの立ち上げ忘れが多いです。
php-fpmはFastCGIのPHP実装です
FastCGIは「CGI]の高速版で、CGIというのはPHPをプログラムとして動かす仕組みです。
なので、FastCGIの実装である「php-fpm」が動いていないと、NginxからPHPを実行することはできなくて、このエラーになります。
```
service --status-all
```
でサービスの名前を調べて
```
sudo service php8.1-fpm start
```
みたいにします。
8.1のところは、ターゲットバージョンで変わりますのでご注意を。

#### ふたつめの「No such file or directory」エラー
文字通り、php-fpmがNginxからの要求をlistenするUNIXソケットファイル「php8.1-fpm.sock」がないのが原因です。
このファイルは、php-fpmの設定ファイル「/etc/php/8.1/fpm/pool.d/www.conf」（8.1の場合）の中で「listen = /run/php/php8.1-fpm.sock」と書かれていれば、php-fpmのサービス起動時に作成されるはずですが、それが失敗しているわけです。
このエラーになるケースの例をとして。
・php8.1を間違ってインストールしていて、それを「remove」して、後から「php-fpm」をインストールした場合
・www.confのlisten.ownerやlisten.groupを「www-data」以外（例えばnginx）に変更してしまている場合
などがあります。
これは「/run/php」フォルダのパーミッションが原因であることがほとんどのようです。
僕がやったとき、デフォルトで、listen.ownerやlisten.groupは「www-data」になってました。
それは「sudo apt install php-fpm」したときに、/runの下に「php」フォルダをowner・groupとも「www-data」で作成することを前提にしているからでした。
ところが、別のphpパッケージをインストールしていると、異なるowner・groupで「/run/php」フォルダが作成されてしまいます。
そのフォルダは「remove」しても消えません。（purgeが必要です）
それで、例えば「root」で作成された「/run/php」ディレクトリが残っていると、パーミッションの関係でインストール時にその下に「php8.1-fpm.sock」を作成できなかったりするわけです。
逆パターンで、www.confを変更して、listen.ownerやlisten.groupを「www-data」以外にしてしまった場合も、同じ理屈でパーミッションではじかれて「php8.1-fpm.sock」を作成できません。
それで「見当たらない」となってしまうというパターンです。
この場合は、とにかく、その前に間違ってインストールしてしまった設定ファイルやディレクトリを「purge」を使って消して、「php-fpm」をインストールしなおすのが早いです。

## まとめ
レアかもしれませんが、ハマりやすいと僕が感じた例をいくつか書きました。
Nbinxとphp-fpm関係の記事はたくさんありますが、WSL2上のUbuntuと、サーバーのUbuntuでは異なる部分が多く、異なる切り口の情報が多すぎて、結構迷います。
なので、WSL2に特化してまとめておくことにします。
ではでは。
rectorをxdebugでステップトレース

## RectorをPHPStormでステップ実行

自作のRectorルールを実際の実行時にステップトレース実行する方法を紹介します。

### rector.php

設定ファイルで`disableParallel()`でパラレル実行を無効にします。（デフォルト有効）

```php
return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([
        __DIR__ . '/src',
    ]);

    // register a single rule
    $rectorConfig->rule(YourRectorRule::class);
    // パラレル実行を停止
    $rectorConfig->disableParallel();
```

### PHPStormでステップトレース実行

Run > Edit Configurations... で`--xdebug`オプションを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3940/9a39aa80-9971-58dd-6db4-993417ace177.png)
任意の文字列を部分的に削除するプログラムの実装




missing_charメソッドを使った実装。

- 対象となる文字列からn番目の文字を削除すること
- 削除された文字以外の文字列を出力すること
```
def missing_char(str, n)
  # 処理を記述
end

# 呼び出し例（1つ目の引数には対象となる文字列を、2つ目の引数には対象となる文字列から何番目の文字を削除するのかを指定しましょう）
missing_char('kitten', 1)
```


slice!メソッドの説明
配列や文字列から、指定した要素を削除し、削除したあとの要素を返すメソッド。
「　！　」がつくメソッドを破壊的メソッドという。
```ruby:例
string = "abcdefg"
string.slice!(2)

puts string
#=> "abdefg"
# 2番目の要素のcが取り除かれている
```



```ruby:回答
def missing_char(str, n)
  str.slice!(n - 1)
  puts str
end

# 呼び出し例
missing_char('kitten', 1)
```
```ruby:ターミナル
itten
```


1行目の解説
missing_charメソッドの引数strには対象となる文字列(今回の場合だと'kitten')、
nは何番目の文字を消すのか指示する数字(今回の場合だと 1 )を入れる仕様になっている。

2行目の解説
slice!メソッドの引数には、nから1を引いた数を設定している。
n - 1 とする理由は、文字列は０からカウントされるため。
もし　n のみの記述になると、「i」　が取り除かれ、ターミナルにはkttenと出力されることになる。
Azure Administrator(AZ-104)：Azure管理者向けの前提条件「Azure Cloud Shell の使用」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「Azure Cloud Shell の使用」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure 管理者向けの前提条件](https://learn.microsoft.com/ja-jp/training/paths/az-104-administrator-prerequisites/)
◇対応するモジュール
[Azure Cloud Shell の使用](https://learn.microsoft.com/ja-jp/training/modules/configure-azure-resources-tools/3-use-azure-cloud-shell)

## Azure Cloud Shell の使用
### Azure Cloud Shell の機能
**◆ユーザごとにセッション単位で一時的に提供されるホスト上で実行される**
・無操作状態で20分経過するとタイムアウトとなり、シェルは自動で終了
・ユーザアカウントごとに1台のマシンに割り当てられる

**◆Azure Fileを使用して、セッション間でファイルを維持**
・Cloud Shell初回起動時に、新規/既存のAzure Fileを選択する
・新規の場合は最寄りのリージョンにリソースグループ/ストレージアカウント/Azure Fileが作成される
・Azure Fileはclouddriveディレクトリに「$Home」という名前でマウントされる
・Azure Fileに保持されている5GBのイメージを使用して、$Homeを永続化する
・BashとPowerShellで同じAzure Fileを使用する

**◆リソースへの即時アクセスを自動的に認証**
・アクセス許可はBashで標準のLinuxユーザとして設定される

**◆オープンソースのMonaco Editorをベースにした統合グラフィカルテキストエディタを提供**
・Monaco EditorはMicrosoftのVisual Studio Codeを強化するコードエディタ

## 次の学習内容
**◆PowerShellの概要**

https://qiita.com/fsd-jume/items/c8c97fe44d67017f5377

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
【Datadog】ダッシュボードにログ上の数値をもとにしたウィジェットを配置

# はじめに
Webアプリにて、URLと処理時間のログを出力しています。
これを使ってURLごとの平均処理時間とかをトップリストウィジェットで作ってダッシュボードに表示したい！と思い、ダッシュボードのウィジェット作成画面を操作しても思い通りのものが作れず苦労したので、メモ。

結論を言ってしまうと、
Logs上で作成して、エクスポートでダッシュボードに貼り付けます。

# ログ

以下のようなJson形式でAWS CloudWatch Logsに出力していて、それがDatadogへ取り込まれてパースされているものとします。
そうするまでの手順はここでは省略させていただきます。

```json
{
    url:"/api/hogehoge",
    elapsed_msec:123,
    ～略～
}
```

# 手順
`Datadog Logs` を開きます。
`Search for` に検索条件を入力し、目的のログに絞り込みます。
`Visualize as` で __Top List__ を選択します。
`Show` には __elapsed_msec__、`by`には __url__ を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436247/399f5ece-69d5-9bda-dc81-b34ea937a1be.png)


上図のように、Top Listができますので、
__Export > Export to dashboard__ で目的のダッシュボードを選択します。

ダッシュボードに出力までできてしまえば、あとはelapsed_msecが一定の値以上なら色を変えたり、平均ではなくmaxにしたりなど微調整をおこなって完成です。

# おわりに
Logs上のGUIだと、こうだろうなという直感に従っていけば作れるのですが、
ダッシュボード上のGUIだと、表示させるのがCountしか選べなくてハマってしまいます。
将来的には改善されるのかもしれないですが、困っている方のお役に立てれば幸いです。
マネージャーになったプログラマが行ったこと、及び反省

※身バレ防止の為、フェイク有です
# 上長から「マネージャーに向いてる」と言われて数か月後
新しい案件にマネージャーとしてアサインされた。
部下も付いた。一人だけだが……。
プロジェクトを遅延なく、赤字なく、完遂させる為に行ったことを列挙する

# 前提
・当時の年齢はギリギリ、二十代前半
・会話はそんなに得意ではない
・最新技術ラブ
・低身長童顔（の為に、他人からよく舐められる
・新しい案件で使われる技術(python)に抵抗は無かった（個人的に勉強していたので
・部下（以下Aさん）の年齢は40代
・Aさんはどうやらpythonがよくわからない様子
（フレームワーク「ジャンゴ」のチュートリアルをちょっとやったことがあるだけらしい

# やったことその１．「ステーキを食え」
新しいプロジェクトで親睦の為にランチを一緒にすることってありますよね。
私は個人的にげんなりしていました。何故なら**奢り**じゃないからです。

なので、Aさんとの初めてのランチは、ステーキを奢りました。
何故ステーキかと言うと、インパクトがあるからです。
（低身長童顔の私が牛丼でも奢ろうとするなら、舐められて終わりです）
イタリアンを奢るよりステーキを奢ったほうがボスという感じがして良い！と思いました。
当然、私はそこそこ高めのステーキをチョイスして、Aさんが畏怖して安いステーキを頼まないようにしました。


# やったことその２．「定時で帰らせる為の仕組み作り」
まず当たり前なのですが、本人の力量を把握した上で仕事を振りました。
（もちろん、能力が向上するような仕事です。単純作業とかではないです）
残業前提の仕事量、クソ。
そして、定時30分くらい前には
「明日やることをまとめておいて帰宅の準備お願いします。デスクの掃除とかも良いですよ」
みたいなことをほぼ毎日言うようにしました。

# やったことその３．「飲み会は16時から定時まで」
あのなあ、飲み会は仕事なんだよ。
だから業務時間内でやるんじゃい！
空き会議室を借りて親睦飲み会は業務時間内にするようにしました。
二人っきりですのでちょっと寂しかったですが……
※当然社内からそれはどうなの？的な意見を頂きましたが、
私は社内政治をするプログラマー&最大派閥所属でしたので、問題ありませんでした。

# やったことその４．「UMLを使って仕事の説明をした」
なんと！弊社にはUMLを使う文化がありませんでした！
（というかUML自体を知ってる人が少ない……）
仕様を理解するには設計書を読む、PMから口頭で説明を受ける、それだけでした。
それは習熟度に関わるな、と思いましたので、
クラス図やシーケンス図をplantUMLで作ってAさんに提供しました。
（規模が小さかったのでplantUMLで問題ありませんでした）

# やったことその５．「メモを取らせるのではなく、私自身がメモを取って渡す」
メモの内容に不足があったり、メモをしていたこと自体を忘れていたり、
説明を受ける者にメモを取らせるのってリスクありませんか？
なので何か指示を飛ばす時は、口頭で説明しつつメモをして、説明が終わったらそのメモを渡すようにしました。
（時間に余裕がある時や、やたら複雑な指示の場合はTeamsでログが残るように説明しました）

# やったことその６．「部下を守る」
Aさんは体調不良気味で、電車を途中下車することがままあったようです。
そのため、出社時刻に間に合うように家を出ても遅刻することがありました。
というわけで、上長から私に「早めに家を出させろ」という指示が来ました。
私は出社時刻に間に合うように家を出ているなら問題無いと判断し、
上長からそういう指示があったことをAさんに伝えはしましたが、
体調優先で無理なく出社しろと言いました。
（当然、その後も遅刻は続くのですが、
私は社内政治をするプログラマーで色々動きましたので、もう一度そういう指示が飛ぶことはありませんでした）

# やったことその７．「良いマシンを調達する」
・その頃、私はカーネギーの「人を動かす」に熱中していました。

……仕事をさせるには道具が必要だ！！

社内ではメモリ8GBのwinマシン、客先ではメモリ4GBのwinマシン……
それが弊社。
しかし私はマネージャーとなり、レンタルするPCを選ぶ権限がありました。
というわけで良い感じのiMacとmacBookAirを自分とAさん用にレンタルしました。
早い！早いぞこのマシン！！
（私はそれまでwin使いだったので、標準のキーボードが馴染めず、
自分の財布持ちで新しいキーボードを買ってしまいました……）

# 結果
・心理的安全性が保たれたのか、Aさん由来の問題が発生することはありませんでした。
Aさんは他人に話かけるタイプではなかったように見えましたが、一緒に仕事するうち、
あんまり他人に話すようなものではない話題で私に話しかけてくれるようになりました。
（ゆぎゃ〇とか、そういうネットのアングラ的なジャンルのやつです）
正直そういう話題を振られて困惑しましたが、まあ信頼されてるのかな、と考えることにしました。

# 反省
・プロジェクトに遅延は無かったものの、私がコードを書くことが多かった。
マネージャーとしては、部下に仕事をさせるべきなので、もっと工夫をすべきだったか……

※もう一度書きますが、身バレ防止の為、フェイク有です

皆さんも、マネージャーとして工夫したことがあったら、コメントをお願いします。
スキルセット棚卸し

スキルセット棚卸し
◼︎導入
・js, css, html, python
・wp
・IoT

◼︎実務
・ホームページ制作
・フリーペーパー作成
・社内アプリケーションの保守運用　←new 

◼︎ツール
・Illustrator
・Photoshop
・word press
・web関連サーバー・データベース構築
・arduino ←new
共通パーツからローカライズ文字＋変数で呼ぼうとするとローカライズされない現象

ローカライズ

    "total%lld" = "合計%lld点";

共通部品

    struct SText: View{
        
        let titleText: String
        
        var body: some View {
            
            Text(LocalizedStringKey(titleText))
                .font(.system(size: 24))
                .foregroundColor(Color.black.opacity(0.7))
        }
    }


呼び出し

    LLText(titleText: "total\(bagS*3 + bagM * 5 + bagL * 10)"

![スクリーンショット 2022-11-21 8.31.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/2be269ed-e8eb-d8f1-9b78-031999a8a1a0.png)
)

なぜかローカライズされない

下記記事参照
https://dev.classmethod.jp/articles/variable-values-are-not-localized/

# 自身の考えまとめた結果

渡したタイミングで呼ばれるのは一つの文字列として呼ばれるからなのだろうなと

渡す前

total　＋　\(bagS+bagM+bagL)

渡した後

total9

# 解決策

共通化部品の文字を二つに分ける

    struct SText: View{
        
        let titleText: String
        let titleText2: String
        var body: some View {
            
            Text(LocalizedStringKey(titleText\(titleText2)))
                .font(.system(size: 24))
                .foregroundColor(Color.black.opacity(0.7))
        }
    }


二つのパターン、三つのパターンみたいなのを作るべきかと言われると微妙かなって思うので、僕は作りませんでしたが、膨大な規模であったりできる限り共通部品でやりたいなんて方はローカライズパターンの共通部品も作ってあげてもいいんじゃないですかね。

どなたかの参考になれば幸いです。
はじめてのNatural Neural Network

# Natural Neural Networksってなんだろう？
この頃のNeural Networkと言うのは、以下の問題を解いている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730426/64dd6ba7-dc51-a966-b887-1c4ea031c659.png)
ただ、このL2 Normはコーディネートにより値が変わってしまう。
そこで、カルバック・ライブラー（KL）情報量を使って、元のDistribution$P_{\theta^{t}}$と次のステップ$\theta^{t+1}$のDistribution$P_{\theta^{t+1}}$を比較することを考える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730426/1294b15c-7cea-8f8c-0dac-314cde49e3af.png)

Fはフィッシャー行列を表す。
これをL2 Normのところに入れて、$\theta^{*}$で微分をすると、  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730426/9df995e3-61bb-a287-ca5d-a41bc8adf902.png)

これを自然勾配学習法(Natural Gradient Learning)と言い、ニューラルネットワークで使うのを[Natural Neural Networks](https://arxiv.org/pdf/1507.00210.pdf)と言う。
この手法は、SGDよりIterationごとの計算量は多いが、Iterationの回数は少なく収束回数が少ない。ただ、フィッシャー行列の逆行列があるように、一回のIterationが大きすぎて、元々あまり使えなかったのが、2015年くらいから[K-FAC](https://arxiv.org/abs/1503.05671)などの手法が出てきて、ちょっと盛り上がった。
その後、下火になったものの、この頃のBayesian絡みでReferされることも増えてきたので、メモ。

自然勾配学習法を考えたのが日本人の先生なので、日本語の文献は多い。
分かりやすい記事:
[3.4.2：自然勾配法【白トピックモデルのノート】](https://www.anarchive-beta.com/entry/2020/01/11/150000)
[K-FACとは？](https://medium.com/@osawa1021/k-fac%E3%81%A8%E3%81%AF-de30537f7096)