OmniAICreator/Qiita-1.07M huggingface dataset:
mongoose: Docker上のMongoDBのデータを読む (Read)

## プログラム

```js:mongo_read.js
// ----------------------------------------------------------------
//	mongo_read.js
//
//						Jun/27/2024
// ----------------------------------------------------------------
const mongoose = require('mongoose')

console.error ("*** 開始 ***")
// MongoDB コネクションの設定
const mongoURI = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', function() {
	console.log('MongoDBに接続しました')
})

// データのスキーマ定義
const citySchema = new mongoose.Schema({
	id: String,
	name: String,
	population: Number,
	date_mod: Date
})

// モデルの作成
const City = mongoose.model('City', citySchema, 'saitama')


// データの取得
const getCities = async () => {
	try {
		const cities = await City.find()
		for (it in cities)
			{
			const obj_city = cities[it]
			const json_str = JSON.stringify(obj_city)
			const city = JSON.parse(json_str) 
			var str_out = city.id + "\t" + city.name
			str_out += "\t" + city.population
			str_out += "\t" + city.date_mod
			console.log (str_out)
			}
	} catch (error) {
		console.error('データの取得に失敗しました', error)
	} finally {
		// 接続の切断
		mongoose.connection.close()
		console.error ("*** 終了 ***")
	}
}
// ----------------------------------------------------------------

getCities()
// ----------------------------------------------------------------
```

## 実行

コマンド

```bash:go_read.sh
xport NODE_PATH=/usr/local/lib/node_modules
node mongo_read.js
```

実行結果

```text
$ ./go_read.sh 
*** 開始 ***
MongoDBに接続しました
t1161	さいたま	93154	1950-07-22T14:00:00.000Z
t1162	所沢	28657	1950-05-14T14:00:00.000Z
t1163	越谷	97421	1950-10-01T15:00:00.000Z
t1164	久喜	31864	1950-06-17T14:00:00.000Z
t1165	熊谷	49358	1950-08-13T14:00:00.000Z
t1166	秩父	65792	1950-09-11T15:00:00.000Z
t1167	川越	37256	1950-07-04T14:00:00.000Z
t1168	和光	52384	1950-04-19T15:00:00.000Z
t1169	新座	26897	1950-06-23T14:00:00.000Z
*** 終了 ***
```
【Unity】ファイルとそのメタファイルをなるべく安全に移動したい

スクリプトでファイルと、そのメタファイルを
別のフォルダに移動したい場合は
少し苦戦します。

System.IO.File.Move で移動した場合は
ファイルを先に移動した場合は
メタファイルが移動前に消滅するリスクがありますし
メタファイルを先に移動した場合は
ファイルの移動前にメタファイルが消滅するリスクがあります。

そこで Unity でファイルを移動したい場合は
AssetDatabase.MoveAsset を使用するのが一般的です。

しかしながらこの機能は
個人的に安定しない印象があります。

実行する度に AssetDatabase を更新したとしても
少し遅延させないと安定しない現象が発生しました。

そこで System.IO.File.Move を使用したとしても
安全にファイルと、そのメタファイルを移動できないかと思い
実践する事にしました。

ここではその成果を
報告したいと思います。

***

使用するソースコード

```Csharp:ファイルを安全に移動するメソッド
private void MyMoveFile(string rootFile, string targetFile)
{
    if (rootFile.StartsWith("Assets"))
    {
        rootFile = UnityEngine.Application.dataPath + rootFile.Substring(6);
    }
    if (targetFile.StartsWith("Assets"))
    {
        targetFile = UnityEngine.Application.dataPath + targetFile.Substring(6);
    }
    if (!System.IO.File.Exists(rootFile))
    {
        return;
    }
    if (System.IO.File.Exists(targetFile))
    {
        System.IO.File.Delete(targetFile);
    }
    if (System.IO.File.Exists(rootFile + ".meta"))
    {
        if (System.IO.File.Exists(targetFile + ".meta"))
        {
            System.IO.File.Delete(targetFile + ".meta");
        }
        System.IO.File.Copy(rootFile, targetFile);
        TryFileMove(rootFile + ".meta", targetFile + ".meta");
        System.IO.File.Delete(rootFile);
        if(System.IO.File.Exists(rootFile + ".meta")) //自動で生成された場合に警告を出さないための if 文
        {
            try
            {
                System.IO.File.Delete(rootFile + ".meta"); //自動で削除される可能性があるため try-catch 必須
            }
            catch
            {
            }
        }
    }
    else
    {
        System.IO.File.Move(rootFile, targetFile);
    }
}

private void TryFileMove(string rootFileMeta, string targetFileMeta)
{
    try
    {
        System.IO.File.Move(rootFileMeta, targetFileMeta);
    }
    catch
    {
        System.IO.File.Delete(targetFileMeta);
        TryFileMove(rootFileMeta, targetFileMeta);
    }
}
```

この方式では
メタファイルが存在する場合は
ファイルを先にコピーしています。

するとメタファイルが
勝手に生成されるリスクがありますので
TryFileMove メソッドで
メタファイルの移動に失敗した場合は
削除して再度移動を実行しています。

この方式ならば
meta ファイルが勝手に生成されても
安全に meta ファイルを移動する事ができます。

MyMoveFile に入れるパスは
Assets から始まっていてもかまいません。

現時点では
移動先に既にファイルが存在する場合は削除しています。
ファイル名を変えて保存する等の仕組みが必要ならば
ご自身で実装して下さい。

メタファイルが存在しない場合という if 文は
ドットから始まるファイル名等で必要になります。
それらのファイルはメタファイルが存在しないからです。

MyMoveFile(string rootFile, string targetFile)
メソッドを実行して使用します。

rootFile と targetFile は
メタファイルでない方のパスを入れて下さい。

"Assets/Move.cs" と
"Assets/Move.cs.meta" があるならば
前者のみを入れる事になります。

***

まとめ

以上ファイルと、そのメタファイルを
なるべく安全に移動する仕組みを紹介しました。

個人的に AssetDatabase.MoveAsset が
安定しなかったため記事にする事にしました。

AssetDatabase.MoveAsset が安定している人は
AssetDatabase.MoveAsset を使用して下さい。

この記事を見て
ファイルの移動処理の実装にかかる
無駄な時間を省く事が出来る人が現れたならば
非常に嬉しいです。

皆さんの開発の助けになれますように
閲覧ありがとうございました。
mongoose: Docker上のMongoDBのデータを作成 (Create)

## プログラム

```js:mongo_create.js
#! /usr/bin/node
//
//	mongo_create.js
//
//					Jun/28/2024
//
// ----------------------------------------------------------------
const mongoose = require('mongoose')

// ----------------------------------------------------------------
function dict_append_proc(dict_aa,id_in,name_in,population_in,date_mod_in)
{
	var unit_aa = {}
	unit_aa['name'] = name_in
	unit_aa['population'] = population_in
	unit_aa['date_mod'] = date_mod_in

	dict_aa[id_in] = unit_aa

	return	dict_aa
}
// ----------------------------------------------------------------
function data_prepare_proc ()
{
	var dict_aa = new Object ()

	dict_aa = dict_append_proc (dict_aa,'t1161','さいたま',93154,'1950-7-23')
	dict_aa = dict_append_proc (dict_aa,'t1162','所沢',28657,'1950-5-15')
	dict_aa = dict_append_proc (dict_aa,'t1163','越谷',97421,'1950-10-2')
	dict_aa = dict_append_proc (dict_aa,'t1164','久喜',31864,'1950-6-18')
	dict_aa = dict_append_proc (dict_aa,'t1165','熊谷',49358,'1950-8-14')
	dict_aa = dict_append_proc (dict_aa,'t1166','秩父',65792,'1950-9-12')
	dict_aa = dict_append_proc (dict_aa,'t1167','川越',37256,'1950-7-5')
	dict_aa = dict_append_proc (dict_aa,'t1168','和光',52384,'1950-4-20')
	dict_aa = dict_append_proc (dict_aa,'t1169','新座',26897,'1950-6-24')
	
	return	dict_aa
}

// ----------------------------------------------------------------
async function loop_insert_proc (dict_aa,City)
{
	for (var key in dict_aa)
		{
		console.log(key)
		var unit_aa = dict_aa[key]
		unit_aa['id'] = key
		const city1 = new City(unit_aa)
		await city1.save()
		}
}

// ----------------------------------------------------------------
// var MongoClient = require('mongodb').MongoClient
const assert = require('assert')

console.error ("*** 開始 ***")

const dict_aa = data_prepare_proc ()

const mongoURI = 'mongodb://localhost:27017/city'

// MongoDB への接続
mongoose.connect(mongoURI)

// 接続が確立された時のコールバック
const db = mongoose.connection
db.on('connected', function() {
  console.log('MongoDBに接続しました');
})


// データのスキーマ定義
const citySchema = new mongoose.Schema({
	id: String,
	name: String,
	population: Number,
	date_mod: Date
})

// モデルの作成
const City = mongoose.model('City', citySchema, 'saitama')

// データの保存
const saveCities = async () => {
	try {
		await loop_insert_proc (dict_aa,City)

	} catch (error) {
		console.error('データの保存に失敗しました', error)
	} finally {
		// 接続の切断
		mongoose.connection.close()
		console.error ("*** 終了 ***")
	}
}

// ----------------------------------------------------------------
saveCities()
// ----------------------------------------------------------------
```

## 実行

コマンド

```bash:go_create.sh
export NODE_PATH=/usr/local/lib/node_modules
node mongo_create.js
```

実行結果

```text
$ ./go_create.sh 
*** 開始 ***
t1161
MongoDBに接続しました
t1162
t1163
t1164
t1165
t1166
t1167
t1168
t1169
*** 終了 ***
```

## 確認したバージョン

```text
$ node --version
v22.3.0
```
MySQLの文字列で「NULLも含めて一致しない」条件

## 文字列で「NULLも含めて一致しない」条件
- 環境 : Mysql 8.0.32

とても基本的なことだが「NULL」の比較をすぐに忘れてしまう。

```sql:文字列で「NULLも含めて一致しない」条件
select * from table where not (columnA<=>columnB);
```

### 「<>」は比較対象に「NULL」があると判定結果が「NULL」になってしまう
不等価演算子は、「<>」だが比較対象にNULLがあるとNULLが返却されてしまう。

> =、<、または <> などの算術比較演算子を使用して NULL をテストすることはできません。
> ...省略...
> MySQL では、0 や NULL は false を意味し、それ以外はすべて true を意味します。
> [MySQL :: MySQL 8.0 リファレンスマニュアル :: 3.3.4.6 NULL 値の操作](https://dev.mysql.com/doc/refman/8.0/ja/working-with-null.html)

```sql
select 'a'<>'b','a'<>'','a'<>0,'a'<>false,'a'<>null,null<>null;
```

|'a'<>'b'|'a'<>''|'a'<>0|'a'<>false|'a'<>null|null<>null|
|:--|:--|:--|:--|:--|:--|
|1|1|0|0|« NULL »|« NULL »|

### 「is not null」を使うこともできるが「どらかがNULLでどちらかがNULL以外」を「一致しない」と判定する条件を書くのが面倒くさい
「NULLではない」は「is not null」で確認できる。

```sql
select 'a' is not null,''  is not null,0  is not null,false is not null,null  is not null;
```

|'a' is not null|''  is not null|0  is not null|false is not null|null  is not null|
|:--|:--|:--|:--|:--|
|1|1|1|1|0|

「どらかがNULLでどちらかがNULL以外」を「一致しない」と判定する条件を書くと面倒くさい。

```sql
select * from table where
-- 左辺がnull以外で右辺がnullの場合
(columnA is not null and columnB is null)
or
-- 左辺がnullで右辺がnull以外の場合
(columnA is null and columnB is not null)
or
-- 両方null以外で値が一致しない場合
(columnA is not null and columnB is not null and columnA<>columnB)
;
```

### 「NULLも含めて一致」を確認するには「<=>」を使う
> <=>
> NULL - 安全等価。 この演算子では、= 演算子のように等価比較が実行されますが、両方のオペランドが NULL であれば、NULL でなく 1 が返され、一方のオペランドが NULL の場合は、NULL でなく 0 が返されます。
> [MySQL :: MySQL 8.0 リファレンスマニュアル :: 12.4.2 比較関数と演算子](https://dev.mysql.com/doc/refman/8.0/ja/comparison-operators.html#operator_equal-to)

:::note warn
比較するカラムが文字列でないと判定がうまくいかないので注意。
「0(数値)」「false(ブール)」は対応できない。
:::

```sql
select 'a'<=>'b','a'<=>'','a'<=>0,0<=>0,'a'<=>false,'a'<=>null,null<=>null;
```

|'a'<=>'b'|'a'<=>''|'a'<=>0|0<=>0|'a'<=>false|'a'<=>null|null<=>null|
|:--|:--|:--|:--|:--|:--|:--|
|0|0|1|1|1|0|1|

### 「NULLも含めて一致」を否定して「NULLも含めて一致しない」にする
> NOT, !
> NOT 演算。 オペランドが 0 の場合は 1 に、オペランドがゼロ以外の場合は 0 にそれぞれ評価され、NOT NULL の場合は NULL が返されます。
> [MySQL :: MySQL 8.0 リファレンスマニュアル :: 12.4.3 論理演算子](https://dev.mysql.com/doc/refman/8.0/ja/logical-operators.html#operator_not)

```sql
select not('a'<=>'b'),not('a'<=>''),not('a'<=>0),not(0<=>0),not('a'<=>false),not('a'<=>null),not(null<=>null);
```

|not('a'<=>'b')|not('a'<=>'')|not('a'<=>0)|not(0<=>0)|not('a'<=>false)|not('a'<=>null)|not(null<=>null)|
|:--|:--|:--|:--|:--|:--|:--|
|1|1|0|0|0|1|0|
wslでelixir その149

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題やってみた。

# 練習問題
Livebookで、GPIOを操作したフリをせよ。

# 方針
- ボタンを使う。
- tagged_stream使う。
- Kino.listen使う。

# setup
```
Mix.install([
  {:kino, "~> 0.10.0"}
])
```

# サンプルコード

```
btn5 = Kino.Control.button("GPIO15")
btn6 = Kino.Control.button("GPIO16")
btn7 = Kino.Control.button("GPIO17")
btn8 = Kino.Control.button("GPIO18")
frame = Kino.Frame.new()
  |> Kino.render()
Kino.Frame.render(frame, Kino.Layout.grid(
    [
      Kino.Layout.grid([btn5, btn6], columns: 1),
      Kino.Layout.grid([btn7, btn8], columns: 1)
    ],
    columns: 2
  )
)
```

```
[a: btn5, b: btn6, c: btn7, d: btn8]
|> Kino.Control.tagged_stream()
|> Kino.listen(fn event ->
  {s, _} = event
  cond do
		s == :a ->
			IO.puts("GPIO15")
		s == :b ->
			IO.puts("GPIO16")
		s == :c ->
			IO.puts("GPIO17")
		s == :d ->
			IO.puts("GPIO18")
    end
end)
```

# 写真


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/5ea0ffc0-b1a3-c459-4151-8218e485d2fb.png)



以上。
【React×TypeSctipt】学習5カ月の集大成として簡単にアプリをリリースしてみた

# はじめに
**React個人学習を始めて5カ月**が経過したAKと申します。
今回React学習のまとめとして簡単なアプリを作成してみました。
私が筋トレ大好き人間なので、関連したテーマで作成しています。

# 作成したアプリ

**概要**
ボディメイクに関する投稿ができるアプリ

**使用言語**
React、TypeScript

**UI**
Chakura UI

**DB**
Supabase

**テスト**
Jest
React Testing Library

**その他使用した技術**
React Hook Form
Github
Firebase

### 実装機能

**・記事一覧表示機能（ホーム画面）**

投稿した記事が表示されます。
右上のメニューバーをクリックすると、新規投稿画面への案内が出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/18cfdfea-6b31-fed2-6551-ee78722a0e57.png)

**・カテゴリ絞り込み機能**

カテゴリを選択すると、該当カテゴリの記事のみを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/fee95b44-8626-3a8e-b39d-63536fbe0a6b.png)

**・新規投稿機能**

　全て必須項目にしてあります。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/531e7792-b458-ef3f-ad0f-86c8f1ad113e.png)

入力せずに投稿ボタンを押すとエラーが出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/ef210005-aed9-f353-e5a7-d18663770556.png)

**記事表示機能**

読みたい記事をクリックすると、その記事のページに遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/0b6baee6-992d-b447-9fd8-e56e2374bf05.png)

**記事編集機能**

編集したい記事の編集ボタンを押すと、編集ページに遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/63f52fb7-325f-a4c1-c3b1-66ef1427bbb9.png)

**記事削除機能**

削除したい記事の削除ボタンを押すと、確認ダイアログが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/aa55ef3c-c788-f3c0-280a-2090e80f57e3.png)

**・（おまけ）ライトモード/ダークモード切替**

画面右上の月/太陽のマークを押すと、モードが切り替わります。

ライトモード使用時

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/19bd422c-5407-feaa-cb95-2a189f2db6a6.png)

ダークモード使用時

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/a8725c00-0d21-c967-a5cf-7ca5c2215692.png)

### アプリ作成の背景
**Reactの個人学習を始めて5カ月が経ちましたが、これまでの集大成としてゼロから実装してみたい機能を考えて作成**してみました。
（これまで作成してきたアプリはJISOUの課題として事前に実装する機能が決まっていました。）
従って、**これまでの学習内容を生かせる + 自分にとって興味関心のある分野**で着手しました。
                                                                                
# 作成の流れ
アプリ作成の大まかな流れはこちらです！
**これまでのアプリ作成の流れと全く変わらないので、過去の記事と内容が重複しています。**

１．環境構築（Vite）
２．CI/CD構築（Github Actions）
３．DBの作成・設定（Supabase）
（記事情報・カテゴリ情報・前述した2つの情報の紐づけを行う中間テーブルを作成）

**～ここから先は機能単位でサイクルを回す（1機能作成→テスト→リリース）～**

４．アプリの機能実装
５．テスト作成（Jest）
６・リリース

# 今回の反省点
**作成したいアプリのアイデアが固まり切らず、「無難なTwitter」みたいなアプリが出来上がってしまいました。。**
正直ボディメイク要素はゼロに等しいかなと思います。。
あくまでも今回は「これまでの学習の集大成」であり、**収益化が目的ではない**にせよ、今後個人開発を本格的に進めていくとするならば、もっと具体的にアイデアを落とし込んでいく必要があると思います。
**ゼロからサービスをつくっていくのってめちゃくちゃ大変なんだな。。と実感しました。**
# おわりに
**ここでReact学習は一旦区切りをつけて、次はNext.jsの学習に移ります。**
こちらも学習状況を都度発信していく予定です。

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
気になる方はぜひHPからライン登録お願いします！

https://projisou.jp
HERE Maps API for JavaScriptでマルチポリゴンを表示させるときのtips

以前 ↓ の記事を書いたときポリゴンの表示ができたーと喜んでいたのですが、改めて見たらポリゴンの色がfillColorに指定した`rgba(255, 0, 0, 0.3)`になってない！と気づいたので、訂正と反省を兼ねてマルチポリゴンを描画するときのdisableLegacyModeの大事さについて書きます。
結論を書いてしまうと、HERE Maps API for JavaScriptでマルチポリゴンのGeoJSONを読み込んで表示するならdisableLegacyModeを有効にしましょう、です。

https://qiita.com/4gou/items/76207ebde9f2816c682f

前の記事ではポリゴン表示の部分はこんな感じで書きました。（今は訂正してあります）
``` js
// H.data.geojson.ReaderでURLのGeoJSONを読み込む
const reader = new H.data.geojson.Reader(url, {
  style: function (mapObject) {
    if (mapObject instanceof H.map.Polygon) {
      mapObject.setStyle({
        fillColor: 'rgba(255, 0, 0, 0.3)',
        strokeColor: 'rgba(0, 0, 255, 0.2)',
        lineWidth: 3
      });
    }
  },
  // TODO disableLegacyModeの作用を調べる
  //disableLegacyMode: true
});
```
こういう表示結果でした。ポリゴンの塗りつぶし色が`rgba(255, 0, 0, 0.3)`じゃない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325378/9eca7c2d-e364-f957-dd3f-adbbd72ddeff.png)

こんな文も書いてました。
> H.data.geojson.ReaderのdisableLegacyModeについてもわかってないので理解したいと思います。

何が **TODO disableLegacyModeの作用を調べる** だ、何が **disableLegacyModeについてもわかってないので理解したいと思います** だです。お気楽なことを言ってる場合じゃないです。
過去に戻って自分を引っ叩きたいです。disableLegacyModeこそが大事でした。

# disableLegacyMode?
H.data.geojson.ReaderのdisableLegacyModeが何なのか見てみます。

https://www.here.com/docs/bundle/maps-api-for-javascript-api-reference/page/H.data.geojson.Reader.html#properties_d14e18379

ドキュメントにはこのように書いてあります。
> A flag indicating whether GeoJSON geometry types MultiPoint, MultiLineString, MultiPolygon should be represented respectively by H.geo.MultiPoint, H.geo.MultiLineString and H.geo.MultiPolygon. To maximise compatibility when fetching data from remote services and enabling features like polygon interiors it is recommended to set this flag to true.
For backward compatibility with older releases of the API the default value of the flag is false.

また、disableLegacyModeを指定しないで実行した場合、ブラウザの開発者モードで見てみるとwarningが表示されていました。

:::note warn
VM300:6 H.data.geojson.Reader: Legacy parser is enabled in GeoJSON Reader. Features like Multi-Geometries, Polygon interiors and GeoJSON feature properties might not work as expected. To maximise compatibility with the remote services it is recommended to set the `disableLegacyMode` flag to true.
:::

互換性のためにlegacy parserが有効になっていて、legacy parserではMultiPointやMultiLineString、MultiPolygonなどが期待した通りに動作しないようです。
MultiPointやMultiLineString、MultiPolygonを扱う場合はdisableLegacyModeを設定するのを推奨とありますね。

# マルチポリゴンを表示させるときは disableLegacyMode を有効にする
マルチポリゴンを意図したとおりに表示させるにはdisableLegacyModeをtrueにセットするだけです。
上のコード例ではコメントを外せばOKです。
``` js
// H.data.geojson.ReaderでURLのGeoJSONを読み込む
const reader = new H.data.geojson.Reader(url, {
  style: function (mapObject) {
    if (mapObject instanceof H.map.Polygon) {
      mapObject.setStyle({
        fillColor: 'rgba(255, 0, 0, 0.3)',
        strokeColor: 'rgba(0, 0, 255, 0.2)',
        lineWidth: 3
      });
    }
  },
  disableLegacyMode: true
});
```
ポリゴンの塗りつぶし色が`rgba(255, 0, 0, 0.3)`になりました🎉🎉
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325378/1dd4be34-a670-2918-c83e-9e3e3c9b84ed.png)
【React】{} と {{}} の違いってなに (　ﾟдﾟ)？

## 背景
reactを勉強し始めて、たまに見る`{{}}` ってなに？
`{}` ではいかんのか？

たとえば、`context`で `provider`の`value`をセットする時とか...
```jsx
  const [tasks, setTasks] = useState([]);
  return (
    <AppContext.Provider
      value={{
        tasks,
        setTasks
      }}
    >
      {children}
    </AppContext.Provider>
  );
```

インラインスタイルを適用する時とか
```jsx
const App = () => (
  <div style={{color: 'blue'}}>
    Hello World
  </div>
);
```

これは一体...`{}` とはどう違うのか???
と疑問に思ったことがあったので、学習のために残そうと思いました。

## 違い
**外側の{}はJavaScript として解釈させる特別な構文**
**内側の{}内は単なるJavascriptオブジェクト**


### インラインスタイル
```jsx
<div style={{color: 'blue', backgroundColor: 'lightgray'}}>
```
外側の`{}`は`style`プロパティに`JavaScript`オブジェクトを渡すことを解釈させているので...
```jsx
// 「JavaScriptオブジェクトが来るぞ...!」　と解釈させている
<div style={...}>
```
のようなイメージ

一方で、内側の`{}`は`JavaScript`オブジェクトになる
```jsx
{ color: 'blue', backgroundColor: 'lightgray' }
```

合わせて使うと以下のようになる。
```jsx
<div style={{ color: 'blue', backgroundColor: 'lightgray' }}>
```
この構造により、`React`コンポーネントの`JSX`内で
インラインスタイルを直接設定できる。
そして、これは以下のように書き直すのと同じになる。

```jsx
  const divStyle = {
    color: 'blue',
    backgroundColor: 'lightgray'
  };

  return (
    <div style={divStyle}>
      Hello World
    </div>
  );
```

こう書かれると特に疑問を持たないのですが、
急に`{{}}` とかされるとパニックになりました... 　~_~;
冷静に考えると、「そらそうか...」という感じですね。


### provider での記法

```jsx
  const [tasks, setTasks] = useState([]);
  return (
    <AppContext.Provider
      value={{
        tasks,
        setTasks
      }}
    >
      {children}
    </AppContext.Provider>
  );
```


これも上記と同じように、オブジェクトリテラルなので、`{{}}` が必要です。
が、「{task, setTask}ってオブジェクトじゃなくね ?」 て思いません？
だって キーとバリューがないし...

（僕は最初思いました...(Ｔ＿Ｔ)

どうやら[JavaScriptのショートハンド（短縮記法）](https://qiita.com/lemon2003/items/0b1e0b40588dd0bdb5a2#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E5%90%8D%E3%81%A8%E3%82%AD%E3%83%BC%E3%81%8C%E4%B8%80%E8%87%B4%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B)の一種であり、
以下のように書くのと同じになるのです。

```jsx
<AppContext.Provider
  value={{
    tasks: tasks,
    setTasks: setTasks
  }}
>
```
ここまで来るとインライン記法と同じですね。
`{{}}` を使って、**渡す値をオブジェクトとして一括で定義している** ということです。

## まとめ
ここまで見ていただきありがとうございました。 (＞人＜;)
冷静に考えると「そらそうか...」となる内容でした。

けど喉につっかえた小骨が取れた感覚で満足　😃

## 参考
[「可読性を上げる」ために敢えてショートハンドを使う](https://qiita.com/lemon2003/items/0b1e0b40588dd0bdb5a2#%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E5%90%8D%E3%81%A8%E3%82%AD%E3%83%BC%E3%81%8C%E4%B8%80%E8%87%B4%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B)
2ヶ月間投稿をして感じたこと2024/5~2024/6

## はじめに
初めましての人もそうでない人もこんにちは!

今回は私が毎月2回記事を投稿して思った・感じてきたことを話していきたいと思います！

もしよろしければこの記事だけでも最後まで読んでいただけると幸いです！

## そもそもどうして毎月投稿をはじめたのか？
正直に言うと最初は「就活」のために始めました。

もちろんプログラミング技術の向上も目指して頑張っていましたが始めた当初の気持ち的には就活が最優先されていました。

就活が優先された理由は多くありますが特にサマーインターンに参加するための書類選考でうまくいかなかったことが1番の原因だったかと思います。

私の周りは本当に優秀で「競技プログラミングの大会に参加するのが趣味です！」やら「ハッカソン入賞経験があります！」やらバケモノが集まっているんですよね。

そういった人たちが近くにいるとどうしても悲観的になってしまいどこにも就職できずにニートになってしまいそうで夜しか眠れませんでした。。。

しかし今から競技プログラミングを極めたりするには時間が厳しいし私は陰キャなので誰かと一緒に開発するハッカソンはとてもハードルが高いと感じてました。

競技プログラミングほど敷居が高くなく1人でもできて就活にも活用できることはないかと考えていたところに以前大学の授業の一環ででQiitaに投稿したこと思い出しました。

これなら私でもできそうと思ったのが始まりでした。

### 大学の授業で投稿した記事
https://qiita.com/FrohleinYoshie/items/2003c037df18e73dfc50

https://qiita.com/FrohleinYoshie/items/2fd3685263849c1eeffe

文章やらプログラムやら拙い部分が多いですがぜひご覧ください！

## 感じつつあるメリット
たったの2ヶ月連続投稿ですが少しずつメリットを感じ始めています。

それはサマーインターンに向けた書類選考が少し通りやすくなった気がするということです。

エンジニアのサマーインターンに応募をする上で必ずと言っていいほどGithubのURLやその他自身の成果物を示すためのURLなどを求められます。

以前までの私はほとんど空白なGithubとQiita記事しかなく、ガクチカもほとんどないような状態でした。
「君本当にエンジニアになりたいの？」と言われても言い返すことができないレベルでした

もし「エンジニアになりたいです」と言い返しても周りからしたら「でもエンジニアとしての努力や意志を感じることができない」と言われてもおかしくないような就活生でした。

しかしQiitaをはじめてからは新卒採用担当者から「ふーんたった2ヶ月しか投稿してないけど努力はしているね」と思われる程度には見えるようになったと思います！

あとはエントリーシートが通りやすくなると感じると全く誰も見ていないような記事でも不思議とモチベーションが上がって楽しくなってきます！

```mermaid
graph TD;
    A[記事を書く] --> B[エントリーシートを提出する] --> C[志望企業が記事を見る] --> D[合格をもらう] --> E[モチベーションが上がる] --> F[記事を書くために開発する] --> A;
```
投稿を続ければそのうち、良い就活スパイラルが出来上がると思います！

まだまだ始めたばかりでエントリーシートが通りやすくなったと感じ始めたばかりなのでうまくいくかわかりませんがこれ以降も続けていこうと思っています！

## 変わりはじめた気持ち
私は最初の方でQiitaの投稿を始めた最初の思いとして就活が最優先されてました。
その思いは変わってませんが最初の頃よりも技術力の向上を目指した気持ちが強くなったように感じます！

大学の友人や企業の新卒採用担当者などから様々な意見をもらうことで良いフィードバックをもらい開発に対するモチベーションと技術力が向上したように感じます！

個人的な感想ですが始めるきっかけはなんでも良いです！
技術力をあげたいとか就活のためとか異性にモテたいとか本当になんでもいいです！

続けていれば勝手に技術力の向上を目指して頑張りたくなってくるからです！
## 今後について
今後の目標としては1年間は毎月2回以上投稿を頑張ろうかなと思っています！
というかそうでもしないとバケモノ集団においてしまいます！

あとは定期的に今回みたいな報告記事を投稿したいと考えています！

## さいごに
すごい長丁場なプロジェクトにはなりますが皆さん今後ともよろしくお願いします！

## 2024/5月6月のブログ記事

### 5月投稿

https://qiita.com/FrohleinYoshie/items/16aba090ec8a0c87b860

https://qiita.com/FrohleinYoshie/items/f9e8a458c8ba3f66e5fd

### 6月投稿

https://qiita.com/FrohleinYoshie/items/e07518682772dfb6213a

https://qiita.com/FrohleinYoshie/items/f5409b5cff484ad230ef
create-react-appコマンドで画面が真っ白（React）

# はじめに
　ReactでTodoアプリを作成する講座を受講していた際`create-react-app`コマンドでプロジェクトを作成し`yarn start`コマンドを入力したところ、ブラウザの画面が真っ白で何もでてこない。
# 問題
　画面が真っ白。調べて確認しても真っ白。時間だけが過ぎていき頭も真っ白。
# 原因
　プロジェクトで作成したディレクトリに移動をしていなかったことが判明。
# 解決
　ディレクトリ移動後コマンドを入力すると、無事画面にReactのロゴが出現。元気に回っていらっしゃった。
# 最後に
　React勉強用に作成したフォルダがプロジェクト名と同名になっており、そこに気づけなかった。何気ないディレクトリでも命名に気をつける必要があることを学んだ。
 　同様のミスをする人間がいるのか疑問でしかない。生き恥を晒しているが、成長の記録として残しておくことにする。
Angular materialのカレンダーBodyにある月を非表示にしたい

タイトルの要件が必要だったのでコードを書いて、記録として残す。

# 月表示が邪魔
これ、2024年7月のカレンダーなんだけど、カレンダーBody1行目の`JUL`はいらない。
![Screenshot 2024-06-28 at 9.42.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/03a327e2-abf4-acad-8f8a-d1d8dbb3dca4.png)

# CSSで非表示にする
ng-deepを使ってAngular materialのコンポーネントに対し、スタイルを適用する。
``` code
::ng-deep .mat-calendar-body-label {
    opacity: 0;
        &[colspan="7"] {
        display: none;
    }
}
```

:::note warn
注意
ng-deepは非推奨ですがここでは、やむを得ず使っています。
https://angular.jp/guide/component-styles#%E9%9D%9E%E6%8E%A8%E5%A5%A8-deep---%E3%81%A8-ng-deep-
:::

# 結果
## これが
![Screenshot_2024-06-28_at_9_37_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/38e159f8-173f-f46c-a7c9-e217ff6183a7.png)

## こう
![Screenshot 2024-06-28 at 9.39.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89497/334c16d8-184d-589b-b89b-43ebce482015.png)

# 最後に
ng-deepを使わないでできる方法があれば知りたい。。。

コードはこちら↓↓↓

https://stackblitz.com/edit/stackblitz-starters-4yppkc?file=src%2Fmain.ts
【VSCode】初心者が知っておくべき生産性向上のためのショートカットキー10選【Mac版】

## 読者対象
macユーザーで最近VSCodeを使い始めたプログラミング初心者の方々

## 概要
私が日常的に活用している、便利なショートカットキーを独自の視点で10個ピックアップしました。マウス操作を減らしてコーディングを爆速にしましょう！

## ショートカットキー10選（一覧）
| ショートカットキー        | 機能                             |
|-------------------------|--------------------------------|
| Option + ↑↓            | 行の上下移動                     |
| Shift + Option + ↑↓    | 行の複製                         |
| Cmd + Shift + K        | 行の削除                         |
| Cmd + [ / ]            | インデントの調整                 |
| Cmd + /                | コメントの追加/解除              |
| Cmd + D                | 単語の選択                       |
| Cmd + Shift + L        | 同じ単語を一括選択               |
| Cmd + PgUp/PgDn        | タブの切り替え                   |
| F12（またはCmd + クリック）| 定義へ移動                       |
| Cmd + P                | ファイルのクイックオープン         |

## ショートカットキー10選（詳細）
1. **Option + ↑↓ - 行の上下移動**
   コードの行を上下に素早く移動できます。手動でのカット＆ペーストの手間が省けます。

2. **Shift + Option + ↑↓ - 行の複製**
   現在の行を複製し、上下に挿入します。同じパターンのコードを複数書く際に便利です。

3. **Cmd + Shift + K - 行の削除**
   現在の行を即座に削除します。複数行を選択して一度に削除することも可能です。

4. **Cmd + [ / ] - インデントの調整**
   インデントを増減させることで、コードを見やすく整えることができます。

5. **Cmd + / - コメントの追加/解除**
   コードをコメントアウトまたはコメント解除します。一時的にコードを無効化するのに便利です。

6. **Cmd + D - 単語の選択**
   カーソルが置かれた単語を選択します。Cmd + Dを繰り返すと同じ単語を次々と選択できます。

7. **Cmd + Shift + L - 同じ単語を一括選択**
   カーソル位置の単語と同じ単語を全て選択します。一括で変数名を変更したい時に便利です。

8. **Cmd + PgUp/PgDn - タブの切り替え**
   複数のタブ間を素早く切り替えることができます。

9. **F12（またはCmd + クリック） - 定義へ移動**
   メソッドや変数の定義場所にジャンプします。定義を探す手間を省けます。

10. **Cmd + P - ファイルのクイックオープン**
    ファイル名を入力してすばやく目的のファイルを開けます。大量のファイルを扱う場合に非常に便利です。

## 最後に
以上、VSCode初心者にぜひ覚えてほしいショートカットキー10選でした。これらのショートカットキーを活用して、作業の効率を高めましょう！最後までお読みいただき、ありがとうございました。
QBcore(/ME日本語表示化) 

```
fivem\txData\QBCoreFramework\resources\[qb]\qb-core\client\events.lua
```
224行目が/me関連設定
```
-- Me command
local function Draw3DText(coords, str)
    local onScreen, worldX, worldY = World3dToScreen2d(coords.x, coords.y, coords.z)
    local camCoords = GetGameplayCamCoord()
    local scale = 200 / (GetGameplayCamFov() * #(camCoords - coords))
    if onScreen then
        SetTextScale(1.0, 0.5 * scale)
        SetTextFont(4)をSetTextFont(0)
        SetTextColour(255, 255, 255, 255)
        SetTextEdge(2, 0, 0, 0, 150)
        SetTextProportional(1)
        SetTextOutline()
        SetTextCentre(1)
        BeginTextCommandDisplayText('STRING')
        AddTextComponentSubstringPlayerName(str)
        EndTextCommandDisplayText(worldX, worldY)
    end
end
```
232行目の
```
SetTextFont(4)をSetTextFont(0)
```
にすれば日本語表示可能になる
これでみんな幸せになります。
【TypeScript】インデックスアクセスで時々見かける〇〇[number]ってなんなん？

オブジェクトや配列から値を取り出す際に利用するインデックスアクセスという方法があります。
これはTypeScriptで型の一部にアクセスするための機能です。

:::note warn
インデックスアクセスは、JavaScriptでも利用できる記述ですが、下記のような記述を見かけて「ん？」となりました。
:::

```typescript
type Array = Array[number];
```

初学者が「ん？」とならないためにメモとして残します！

## `〇〇[number]`は数値インデックスアクセスをやっている

わかってしまえばなんてことありませんが、下記の状態と同じことを行なっています！

```typescript
type Array = Array[0];
type Array = Array[1];
```
`〇〇[number]`は、
- APIの返り値が変更された場合でも自動で更新される
- 型を手動で複製する必要がない
- 正確な型情報を維持できる

などのメリットがありますので覚えておけると良いと思います！
少しわかりにくかったと思うので具体的な例を見ておきます！

```typescript
type ApiResponse = {
  products: {
    id: number;
    name: string;
    price: number;
  }[];
}

type Product = ApiResponse['products'][number];

// Productの型
type Product = {
  id: number;
  name: string;
  price: number;
}
```

API側で上記に`age: number`が追加されたとします。

```diff_typescript
type ApiResponse = {
  products: {
    id: number;
    name: string;
    price: number;
+    age: number;
  }[];
}

type Product = ApiResponse['products'][number];

// Productの型
type Product = {
  id: number;
  name: string;
  price: number;
+  age: number;
}
```

新しく追加された分も同じ記述で対応することが可能です！

## 【おまけ】インテックスアクセスを利用した型の取得方法
本題からはそれますが、インデックスアクセスを利用すると様々な方法で型を取得できますので紹介しておきます！

:::note
オブジェクトや配列で定義された型を取得する方法は割愛し、それ以外のインデックスアクセスについて紹介します！
:::

### 複数のキーを使用する例

```typescript
type Product2 = {
  id: number;
  name: string;
  price: number;
}

type Product2Info = Product2['id' | 'price']

const info: Product2Info = 1111 // OK
const info2: Product2Info = '1111'; // エラー
```

Product2の`id`と`price`をインデックスアクセスで型を取得します。
`id`と`price`の方はどちらも`number型`なのでProduct2Infoは`number型`を許容する型になります。
なので文字列を入れようとするとエラーとなります。

### keyof演算子と組み合わせる例

```typescript
type Product3 = {
  id: number;
  name: string;
  price: number;
}

type ProductKeys = keyof Product3;
type ProductValues = Product3[keyof Product3];
```

keyofを利用することによってキーを取得して型とすることもできますし、組み合わせるとキーに対応した型を取得することも可能です！
上記の例だと`ProductKeys`の方は、`id`、`name`、`price`という文字列を許容する型になります。
`ProductValues`はkeyに対応するvalueを取得するので、`nuber`、`string`を許容する型になります。

## 【まとめ】TypeScriptのインデックスアクセス
型のインデックスアクセスを使用することで、既存の型から新しい型を作成したり、特定のプロパティの型を抽出したりできます。

:::note
大きな型から一部の情報だけを使用したい場合や、型の再利用性を高めたい場合に非常に便利です！
:::

初学者が使おうとすると混乱する場合もあるので少しずつ利用して慣れていけると良いと思います！
マイクロサービスのテスト戦略とさらなるパフォーマンス最適化

マイクロサービスアーキテクチャにおいて、各サービスの品質とパフォーマンスを確保するためには、効果的なテスト戦略とパフォーマンス最適化が必要です。今回は、マイクロサービスのテスト戦略とさらなるパフォーマンス最適化について記述します。

### 目次

1. マイクロサービスのテスト戦略
2. パフォーマンス最適化の手法
3. 実践プロジェクトの例

### 1. マイクロサービスのテスト戦略

### ユニットテスト

各マイクロサービスのビジネスロジックをユニットテストで検証します。Laravelでは、PHPUnitを使用してユニットテストを実行します。

`tests/Unit/ExampleTest.php`

```php
namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    public function testBasicTest()
    {
        $this->assertTrue(true);
    }
}
```

### 統合テスト

サービス間の通信やデータの整合性を確認するための統合テストを実行します。

`tests/Feature/IntegrationTest.php`

```php
namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class IntegrationTest extends TestCase
{
    use RefreshDatabase;

    public function testUserCanCreateOrder()
    {
        $user = User::factory()->create();
        $this->actingAs($user, 'api');

        $response = $this->postJson('/api/orders', [
            'product_id' => 1,
            'quantity' => 2,
        ]);

        $response->assertStatus(201);
        $this->assertDatabaseHas('orders', [
            'user_id' => $user->id,
            'product_id' => 1,
            'quantity' => 2,
        ]);
    }
}
```

### コンテナテスト

Dockerコンテナ内でサービスを実行し、エンドツーエンドのテストを実行します。Testcontainersライブラリを使用して、Dockerコンテナを制御します。

```bash
composer require testcontainers/testcontainers-php
```

コンテナテストの例：

`tests/Feature/ContainerTest.php`

```php
namespace Tests\Feature;

use PHPUnit\Framework\TestCase;
use TestContainers\Container;
use GuzzleHttp\Client;

class ContainerTest extends TestCase
{
    public function testServiceIsReachable()
    {
        $container = new Container([
            'image' => 'my-service:latest',
            'ports' => [
                '8080:8080'
            ],
        ]);
        $container->start();

        $client = new Client(['base_uri' => 'http://localhost:8080']);
        $response = $client->get('/api/health');
        $this->assertEquals(200, $response->getStatusCode());

        $container->stop();
    }
}
```

### 2. パフォーマンス最適化の手法

### キャッシュの最適化

RedisやMemcachedを使用して、データベースクエリの結果をキャッシュします。

```php
use Illuminate\Support\Facades\Cache;

$users = Cache::remember('users', 60, function () {
    return User::all();
});
```

### アプリケーションのプロファイリング

TelescopeやBlackfireを使用して、アプリケーションのプロファイリングを行い、パフォーマンスのボトルネックを特定します。

```bash
composer require laravel/telescope
php artisan telescope:install
php artisan migrate
php artisan serve
```

### クエリの最適化

Eloquentの`with`メソッドを使用して、リレーションを一括でロードします。

```php
$users = User::with('posts')->get();
```

### 3. 実践プロジェクトの例

### プロジェクト：最適化されたマイクロサービスとテスト戦略

1. 各マイクロサービスのユニットテストと統合テストを実装
2. Dockerコンテナ内でエンドツーエンドのテストを実行
3. Redisを使用してデータベースクエリのキャッシュを設定
4. Telescopeを使用してアプリケーションのプロファイリングを実施

### まとめ

この記事では、マイクロサービスのテスト戦略とさらなるパフォーマンス最適化について記述しました。効果的なユニットテストと統合テスト、コンテナテストを実行し、キャッシュの最適化とアプリケーションのプロファイリングを通じてパフォーマンスの向上を図る方法を学びました。これらの手法を駆使して、品質とパフォーマンスに優れたマイクロサービスアーキテクチャの構築を目指します。
App Center Analytics廃止に伴い、Application Insightsに変える

# はじめに

いままでアプリの使用状況を分析する機能をApp Center Analyticsを用いて実現していました。
しかし、廃止されるとの通達が来ており、代替できるサービスがないか探していました。

https://learn.microsoft.com/ja-jp/appcenter/retirement

そこで目をつけたのがAzure MonitorのApplication Insightsです。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/app/app-insights-overview

Webアプリ専用かなと思っていましたが、非HTTPアプリケーションであっても利用でき、それが今までのApp Center Analyticsでの使用状況を分析するのと、同じような方法(実装)かつ機能としても同等のことが満たせそうでしたので調査しました。

## App Center Analytics(変更前)

そもそも今までどうしていたかというと、dotnetで開発しているデスクトップアプリケーションに対して、アプリの任意の操作時に以下のようなイベントを通知して、その結果を収集していました。

```cs
Analytics.TrackEvent("イベントの名前", new Dictionary<string, string> {
    { "プロパティ名1", "プロパティ値1" },
    { "プロパティ名2", "プロパティ値2"}
});
```

参考となる[記事](https://qiita.com/kojimadev/items/ce5a0cc7cd38a6716fe7)

## Application Insights(変更後)

デスクトップアプリケーションを対象にするような場合は、`WorkerService`という非HTTPアプリケーション用のSDKがあります。

https://learn.microsoft.com/ja-jp/azure/azure-monitor/app/worker-service

利用方法もApp Center AnalyticsのSecretの文字列指定がApplication Insightsの接続文字列指定に変わり、それを用いて初期化・起動する流れは変わらず、任意の操作時にTrackEventを呼ぶ部分がAnalyticsからTelemetryClientのTrackEventになるだけで置換できそうです。

収集されたログの確認についてはイベントで、App Center Analytics時と同じようなイベント名に対するカウント一覧を見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/6474aa8c-2a5a-b475-46e2-7d580d67ca80.png)

ただ、各イベントのパラメータを使って収集された詳細なログはデフォルトでは表示されるビューがなさそうです。
そのため、クエリで取得して再現するかたちになりそうでした。

TrackEventで通知した情報はログの`customEvents`に収集されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/b6e960dd-c4ab-c6ca-7f87-6dd5751bfa32.png)

そこで、以下のようなクエリでイベントの各引数の値の一覧とそのカウントを表示してみました。

```
customEvents
| where name == "イベント名"
| extend properties = bag_keys(customDimensions)
| mv-expand properties
| project propertyName = tostring(properties), propertyValue = tostring(customDimensions[tostring(properties)])
| summarize propertyCount = count() by propertyName, propertyValue
| order by propertyName, propertyCount desc
```

引数1個だけのイメージですが、例えば以下のように表示されます。

```cs
// スケジュールを指定した際に何が指定されたか記録する
TelemetryClient.TrackEvent("スケジュール指定", new Dictionary<string, string> {
    { "ScheduleType", "Weekly" }
});
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/deac11ff-be13-89cd-0a5f-0bfec62f93bf.png)

ログ画面だけだと毎回の分析が大変なので、ダッシュボードに各クエリの画面を集めれば、App Center Analytics時では1個1個イベント詳細を見に行かないと駄目でしたが、Application Insightsであれば一覧で各イベントの詳細を並べる・・・なんてこともできそうです。

## おわり

代替できそうって話ばっかり書いていますが、無料で使えていたApp Center Analyticsに対して、Application Insightsはログのデータ量に対する従量課金制となるので、料金が発生します。
それを踏まえても乗り換えれると判断できれば代替手段になりそうですが、まだ自分も実際にアプリの利用者1人あたり一月でどの程度ログ記録するのか見積もれていないため検証段階です。
[Rails] Capistranoが不要なので、削除する

# はじめに
元々、`Capistrano`を使用してデプロイをしていたみたいですが、デプロイ方法が変わって、使用されなくなっていました。

なので、調査をした上で、削除する方針に決まりました。
その内容をアウトプットいたします。

:::note warn
本記事では、削除をメインに記載いたします。
Capistranoについて詳しく知りたい方や実装方法は、別記事を参照していただくようお願いいたします。
:::

# Capistrano とは
https://github.com/capistrano/capistrano

簡単にいうと、デプロイを自動化してくれるGemになります。
詳しくは、以下の記事がわかりやすかったです。

https://pikawaka.com/rails/capistrano


# 確認方法
まず、本当に`Capistrano`を使用していないか、確認します。
デプロイに使用する実行コマンドは、以下のようになると思うので、リポジトリ内・外を調査します。

```sh
bundle exec cap production deploy
```

使われていなければ、問題なく削除しましょう。
自分は`AWS CodePipeline`を使用してデプロイをする方法に切り替えていたため、問題なく削除できました。

https://aws.amazon.com/jp/codepipeline/


# 削除
## Gemfile からの削除
以下の記述を削除します。

```rb
group :deployment do
  gem 'capistrano'
  gem 'ecs_deploy', github: "reproio/ecs_deploy"
  gem 'wrapbox'
end
```

削除して後に、忘れずに`bundle install`を実行しましょう。

## 関連するファイルの削除
`Capistrano`を導入した際に、以下のコマンドを実行して、ファイルを生成しているかと思います。

```sh
bundle exec cap install
```

上記で生成されるファイルは、以下になります。

```
- Capfile
- config
    - deploy
        - production.rb
        - staging.rb
    - deploy.rb
- lib
    - capistrano
        - tasks
```

https://github.com/capistrano/capistrano?tab=readme-ov-file#capify-your-project

上記にも記載されています。
この生成されたファイルは、中身を確認した上で削除して良いと判断できます。

:::note warn
`bundle exec cap uninstall` みたいなコマンドがあるか調べましたが、おそらくなさそうでした...。
なので、手動での削除しかなさそうです。
:::

削除自体は、以上で終了になるので、あとは問題なくリリースできるか確認して、作業は終了になります。


# まとめ
デプロイ周りの削除は、結構怖いことだと思います。
なので、削除するためにも、まず自分が扱っているサービスが、どのようにデプロイされているのかを把握する必要があるかと思います。

そこの良い勉強にもなりますし、リポジトリがすっきりするのは気持ちが良いです。
皆さんも不要な記述は、調査した上で削除しましょう。

最後までご覧いただき、ありがとうございました。
JSにおいて関数はオブジェクト扱いされる

## 前提
筆者はJSにはあまり精通しておらず、pythonが少し分かる程度（for文とかif文、関数）。


今回はx,y,zの和を出力する関数で気づいたことを共有。

## JSで最初に書いたもの

```javascript:fomula.js
    const answer = (x, y, z) => {
        return x + y + z;
    };

    answer(3, 4, 5);
    console.log(answer);

```

```:出力結果
    [Function: answer]
```

あれ？しっかり引数も渡してるしなぜ、answerが12にならないのか分からない。
出力結果が文字列な時点で、何かおかしい。JavaScriptにおける関数の扱い方を調べてみた。

## 結果
https://jsprimer.net/basic/function-declaration/

このサイトから、JavaScriptでは関数はオブジェクト扱いされることが分かった。つまり、
console.log(answer)は関数を呼び出したときの処理を出力しているに過ぎなかった。

下記のコードで引数を渡せていると勘違いしてしまっていた,,,

```javascript:fomula.js (抜粋）
    answer(3, 4, 5);
    console.log(answer)
```
    

```javascript:fomula.js
    const answer = (x, y, z) => {
        return x + y + z;
    };

    console.log(answer(3,4,5));
```

これで正しく出力されるコードになった。
visualforceのメールテンプレートで翻訳設定を行う


+ [メールテンプレートに、ユーザーごとの翻訳機能を載せたい](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007epmSVSAY)

**事象の整理**

カスタム表示ラベルを「言語設定 = 英語」のユーザーがLWCにて表示したときに、きちんと英語で表示される。
しかし、visualforceのメールテンプレートで言語をen_USと設定しても日本語が表示される。


**検証**

実際に私も作ってみると言語設定はenでもENでもen_USと同じ扱いになって英語になります。
ということで、languageの設定が正しく機能しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2b83d45b-beca-6c8f-5c63-454c30a65b31.png)

そこで、翻訳言語設定の英語を無効にしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/82c143f1-9552-b86c-6bf4-483c6066df70.png)

無効にしたらen_USと指定しても日本語で表示されました。

どうもLWCではこの設定は関係なさそうですが、visualforceのメールテンプレートでは必要そうです。

# カスタム表示ラベルの設定での注意

名前のところのリンクをクリックしないと、他の言語での値を入力できません。編集ではできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c505f01f-9a74-e6a1-6ab2-c4b490310329.png)
robloxでassistant その116

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
スクリプトだけで、地形を作れ。

# 手順
- ServerScriptServiceに、Scriptを追加。
- スクリプトを書く。

```

local part = Instance.new("Part")
part.Position = Vector3.new(-5, 2, -15)
part.Size = Vector3.new(5, 2, 5)
part.Parent = workspace
game.Workspace.Terrain:FillBlock(part.CFrame, part.Size, Enum.Material.Grass)
part:Destroy()


```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/01d78430-ff80-f7a4-beba-1cc5e064be57.png)


以上。
【PostgreSQL】メタコマンド〜\a〜

## 初めに

Qiita Engineer Festa 2024に参加中。完走目指してます。
他のメタコマンドについては以下から読んでください。

https://qiita.com/dai_chi/items/04f5339d54130f070671

## \aとは

> 現在のテーブルの出力形式が「揃えない」になっていれば「揃える」に、 「揃える」になっていれば「揃えない」に設定します。 このコマンドは後方互換性を保持するためにあります。 より一般的な解決策は`\pset`を参照してください。
> 

[\aについて](https://www.postgresql.jp/docs/15/app-psql.html#:~:text=%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82-,%5Ca,-%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB)

## 試してみた
usersテーブルの出力結果を見比べてみた。

```bash
main=# select * from users;
 id |  name   | age 
----+---------+-----
  1 | Alice   |  30
  2 | Bob     |  25
  3 | Charlie |  35
  4 | Diana   |  30
(4 rows)

main=# \a
Output format is unaligned.

main=# select * from users;
id|name|age
1|Alice|30
2|Bob|25
3|Charlie|35
4|Diana|30
(4 rows)
main=# \a
Output format is aligned.

main=# select * from users;
 id |  name   | age 
----+---------+-----
  1 | Alice   |  30
  2 | Bob     |  25
  3 | Charlie |  35
  4 | Diana   |  30
(4 rows)
```

## まとめ

アンアラインドモードはエクスポートして他のツールなどで利用する際に便利とのことだが、その時はCSVにしちゃうよな〜と思ったり。
robloxでassistant その115

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
スクリプトだけで、三角形を作れ。

# 手順
- ReplicatedFirstに、LocalScriptを追加。
- スクリプトを書く。

```

local wedge = Instance.new("WedgePart", workspace)
wedge.Anchored = true
wedge.TopSurface = Enum.SurfaceType.Smooth
wedge.BottomSurface = Enum.SurfaceType.Smooth
local a = Vector3.new(-10, 0, -10)
local b = Vector3.new(-5, 5, -10)
local c = Vector3.new(-5, -1, -10)
local ab, ac, bc = b - a, c - a, c - b
local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc)
local right = ac:Cross(ab).unit
local up = bc:Cross(right).unit
local back = bc.unit
local height = math.abs(ab:Dot(up))
local w1, w2
w1 = wedge:Clone()
w1.Size = Vector3.new(1, height, math.abs(ab:Dot(back)))
w1.CFrame = CFrame.fromMatrix((a + b) / 2, right, up, back)
w1.Parent = workspace
w2 = wedge:Clone()
w2.Size = Vector3.new(1, height, math.abs(ac:Dot(back)))
w2.CFrame = CFrame.fromMatrix((a + c) / 2, -right, up, -back)
w2.Parent = workspace



```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0db3a0f5-1a47-e59d-f22d-7d69bc51725c.png)


以上。
HTMLのコードが入っている場合のエラー



+ [Attribute "autocomplete" on element <body> is not allowed, or has an invalid value.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmFMB)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7ef1cdca-6ac0-5f98-a813-1b3b1f53fcd8.png)

# タグ？ Attribute "data-ms-editor" on element <body> is not allowed, or has an invalid value

+ [Hi guys is there someone who knows how to solve this issue? I get this error when I try to save my email template.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Pl8ch)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d6750704-637f-6045-fdfe-55af06b543bc.png)

:::note
I found the issue. There was some code in the html source. I deleted it and now it works.

問題が見つかりました。 HTMLソースにコードが入っていました。それを削除しましたが、今は機能します。
:::

+ [Unable to save New Email Template due to an error.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Pf0N9)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b33ecd0c-a040-7640-c7ae-90af27b4d768.png)


:::note
 looks like somebody had a similar issue as you (found here), try creating a new template and copy/paste the content you are trying to add as plain text (Ctrl+Shift+V). 

誰かがあなたと同様の問題を抱えているようです（ここで見つかりました）。新しいテンプレートを作成し、追加しようとしているコンテンツをプレーンテキスト（Ctrl+Shift+V）としてコピーアンドペーストしてみてください。
:::
[ERC7617] 大容量データを小分けにして取得ができる仕組みを理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、**ERC5219**を拡張して、複数のチャンクで構成されたWeb3URLリソースを取得する仕組みを提案している**ERC7617**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-7617

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

# 概要

この規格は、**ERC6860**のweb3URL標準の文脈において、**ERC6944**のresolveモードを拡張する仕組みを提案しています。

:::note info
**ERC6860**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/30bdd75be892cf776b88

:::note info
**ERC6944**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/c8f906536dcb7fe7492d

具体的には、**web3-next-chunk**という新しいオプションのHTTPヘッダーが導入され、このヘッダーには次のデータチャンクを指すweb3URLが含まれます。
レスポンスを返すときに、次のデータチャンクのURLを含めることで、呼び出し元が指定されたURLにアクセスしてデータを取得することができます。
この処理を**web3-next-chunk**ヘッダーが存在する限り繰り返すことで、大量のデータを一度に送らずにチャンクごとに分割して取得することができます。

例えば、大きなファイルをダウンロードする時、呼び出し元は初回の`request()`呼び出しを行い、最初のチャンクとともに**web3-next-chunk**ヘッダーを返します。
呼び出し元はこのヘッダーのURLにアクセスし、次のチャンクを取得するプロセスを繰り返します。
このようにすると、特にオンチェーンにおいては一度に返せるデータに制限があるため便利です。

:::note info
**ERC6944**は、**ERC5219**を拡張していて、`request()`メソッドの呼び出しは**ERC5219**に関連する部分です。
:::

:::note info
**ERC5219**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/a96196b201a34e6eb640

# 動機

Ethereum RPCエンドポイントにはガスコストの制限があり、大容量のコンテンツを提供するときに制限に達してしまう可能性があります。
この規格で提案されているチャンク機能を実装することで、大容量のデータを小分けにした任意のサイズのコンテンツを提供できるようになります。

:::note info
フルオンチェーンなどで特に活用できそうです。
:::

# 仕様

この規格を使用することで、**ERC6944**のresolveモードを拡張して、`request()`メソッドで返される`headers`と`KeyValue`配列に新しいオプションのHTTPヘッダーである**web3-next-chunk**が追加されます。
**web3-next-chunk**の値は、完全なweb3URLか相対URLのcどちらかで、呼び出すコントラクトは**ERC6944**を実装している必要があります。

最初の`request()`呼び出しでデータをリクエストすると、HTTPステータスコード、HTTPヘッダー、bodyを返します。
もし**web3-next-chunk**ヘッダーが存在する場合、まずはURLを無効か有効か検証します。
呼び出すこんとらくとが**ERC6944**を実装していない場合などはエラーを出して処理を終了させます。
有効の場合は、返された`statusCode`を無視して**ERC6944**のresolveモードを使用して再度`request()`メソッドを呼び出します。
**web3-next-chunk**ヘッダーが存在しなくなるまでこの処理を繰り返します。
これにより、大量のデータを小さなチャンクに分割して小分け実行ができて効率的なデータ転送が可能になります。

# 補足

次のチャンクの場所をしているするデータの保管場所としてヘッダーが選ばれたのは、**ERC6944**の`request()`インターフェースを変更する必要がなく、ヘッダーにweb3URLを追加するだけで良いからです。
これにより、柔軟に次のチャンクの情報を提供できます。

# 引用

Qi Zhou (@qizhou), Nicolas Deschildre (@nand2), "ERC-7617: Chunk support for ERC-5219 mode in Web3 URL [DRAFT]," Ethereum Improvement Proposals, no. 7617, February 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7617.

# 最後に

今回は「**ERC5219**を拡張して、複数のチャンクで構成されたWeb3URLリソースを取得する仕組みを提案している**ERC7617**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4
Javaコメントの書き方・種類

# 概要
### このページでわかること
+ コメントの種類と使い方

### 覚えておきたいこと
* コメントの書き方

# コメントとは
+ プログラミングでは、処理と関係のないメモをコメントとして残しておくことができる
+ 使い方
    + どんな処理をしているのかの説明
    + プロジェクトで定められているルールに基づいて
+ コメントがあることで他の人がコードを読みやすくなる（可読性の向上）
+ 時間が経ったあと自分で見返したときにすぐ処理を理解できる

# コメントの種類
+ 本記事では３種類のコメントの書き方を紹介する

```java:１行コメント
// ここはコメントとして処理されます
```

```java:複数行コメント
/*
 * ここも
 * ここも
 * ここもコメントとして処理されます
 */
 ```

 ```java:Javadocコメント
 /**
  *
  * 複数行コメントと同じように
  * コメントとして処理されます
  */
  ```
:::note 
Javadocコメントは、その他のコメントと同じように実行する際に無視されるという点は同じだが、特定のコマンドを実行することでクラスやメソッドに関する詳細なHTMLドキュメントを作成することができる
:::
  + 例えばこんなコードがあってjavadocをつけていると仮定する
```java:コードの例
/**
 * このクラスは、ユーザーを表現します。
 * <p>
 * ユーザーの名前、年齢、およびその他の個人情報を管理します。
 * </p>
 */
public class User {
    private String name;
    private int age;

    /**
     * 新しいユーザーを初期化します。
     *
     * @param name ユーザーの名前
     * @param age ユーザーの年齢
     */
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * ユーザーの名前を取得します。
     *
     * @return ユーザーの名前
     */
    public String getName() {
        return name;
    }

    /**
     * ユーザーの年齢を取得します。
     *
     * @return ユーザーの年齢
     */
    public int getAge() {
        return age;
    }

    /**
     * ユーザーの名前を設定します。
     *
     * @param name ユーザーの新しい名前
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * ユーザーの年齢を設定します。
     *
     * @param age ユーザーの新しい年齢
     * @throws IllegalArgumentException 年齢が負の値の場合
     */
    public void setAge(int age) {
        if (age < 0) {
            throw new IllegalArgumentException("年齢は0以上でなければなりません。");
        }
        this.age = age;
    }

/**
 * 与えられた名前で新しいユーザーを作成します。
 *
 * @param name ユーザーの名前
 * @param age ユーザーの年齢
 * @return 新しく作成されたユーザーオブジェクト
 * @throws IllegalArgumentException 名前がnullまたは空の場合、または年齢が負の値の場合
 */
public User createUser(String name, int age) {
    if (name == null || name.isEmpty()) {
        throw new IllegalArgumentException("名前はnullまたは空であってはなりません。");
    }
    if (age < 0) {
        throw new IllegalArgumentException("年齢は0以上でなければなりません。");
    }
    return new User (name, age);
}
}
```
+ その後下記のコマンドを実行する
`javadoc -d [出力ディレクトリ] [ソースファイルまたはパッケージ]`
そうすることで画像のようなファイルを閲覧できる
![スクリーンショット 2024-06-28 8.12.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821717/34f3297c-0ae6-e3c1-5682-1bc309c455e4.png)

# まとめ
+ コメントをつけることで可読性を上げることができる
+ コメントの付け方には種類がある
+ コメントをつける際はショートカットを利用して素早くつける
    + [VSCodeのショートカット一覧](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf)
(QA) IBM i に接続するクラサバ/Webアプリのレスポンスタイムが遅い

主題のご質問をいただきました。

## システム状況

状況としては最近、OSバージョンアップとシステムハードウェア移行を実施されたお客様です。IBM i の外にWebアプリケーションがあり、Db2 for i をデータベースサーバーとしてアクセスしています。
アプリケーションの改修は行っていません。いくつかのシステム設定値について、旧→新システム間で変わってしまっている可能性があります。

## 考察（当稿の前提）

・アプリ（外部サーバー上のJavaアプリ）は問題ないものと仮定する
・ネットワークも問題ないとする

IBM i 側に何らかの問題があると推察し進めます。

## 確認するべきパフォーマンスに影響あるIBM i 設定等

### ①TCP/IP送受信バッファーサイズ

```
CHGTCPA
```
コマンドでTCP/IPの送信バッファーサイズ・受信バッファーサイズを確認します。
例は以下です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/4db69b4e-af8a-9d2f-20b4-ae852121239a.png)

上記の ***TCPRCVBUFパラメーター*** と ***TCPSNDBUFパラメーター***のデフォルトは 65535バイトです。この値は現代だと小さい事が多いように思います。例のように ***最大値 8388608 (バイト）に変更*** してみてください。

この設定変更は即時適用になります。
システム環境によっては試行してサイズを微調整してもいいと思います。


### ②JDBC/ODBCサーバージョブ QZDASOINIT の起動数を調整する

QZDASOINITは外部のWebサーバーからJDBCリクエストを受付け、処理を行います。プーリングされているので複数のジョブ（Webサーバーからの複数のリクエスト）間で共有されます。デフォルトでは2つのQZDASOINITジョブが起動しています。このとき,同時に3つ以上のJDBCリクエストが発生すると追加のQZADASOINITジョブが開始されます。この際のCPU負荷が相応に高い為、リクエスターへの処理が厳密には遅延しています。）同時実行されるリクエスト数を調べて、2よりもある程度多い場合はQZDASOINITジョブ数を増やすのがよいと思われます。

調整の方法と補足解説が [こちらの記事](https://qiita.com/gomAnomalocaris/items/13d5f4e1cc32393626d2)にあります。

### ③データベース（テーブル）の推奨インデックスを確認する

IBM i OSバージョン(Db2 for i バージョンと同一）が上がる事でSQLエンジンが改良され、結果以前のバージョンでは不要だったインデックスが追加で必要になる場合があります。

推奨インデックスの確認方法は、Qiitaでは書いてなかったと思うのでいずれ書きたいと思いますが、

具体的な手順は [SQLパフォーマンスモニター](https://qiita.com/gomAnomalocaris/items/7b2f74b07a420f44e8c3)を取得し、処理の遅いSQLを特定する、そのSQLの推奨インデックスを確認する、といった流れになります。

以上は効果がある場合、1つのジョブを実行した際にも体感できるレベルで処理速度が向上する場合が多いように思います。

### ④エキスパートキャッシュをオンにする

エキスパートキャッシュはIBM i のメモリで未使用領域がある場合、それをディスクキャッシュとして使用する機能です。
設定・確認は
```
WRKSYSSTS
```
コマンドから実施します。

例は以下です。

WRKSYSSTSコマンドを実行し、PF11キーを複数回押すと、下記のような ***PAGINGオプション欄が表示されます***

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/ed485c38-b30a-355b-b764-121f4f69bf3b.png)

PAGINGオプションのデフォルトは *FIXED　です。この値はエキスパートキャッシュがオフの状態です。***PAGINGオプションを *CALC に変更してエキスパートキャッシュをオンにします。***

この設定変更は即時適用になります。
この設定変更はメモリの割り当て状況やジョブ実行状況等いくつかの条件に影響する為、必ず効果が体感できない場合もあるかもしれません、ですが複数ジョブが実行されている状態では多少なりとも改善されるはずです。副作用もない（経験上も）ので、変更しておいて間違いない設定です。