OmniAICreator/Qiita-1.07M huggingface dataset:
Constants and Variable Declarations

[Previous << Syntax](https://qiita.com/abcdefgac153131/items/29b0617fdfbf652c5425)
[Next >> Type Annotations](https://qiita.com/abcdefgac153131/items/aefb58373b7b6dc956d9)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#cadenceの言語仕様を学ぶ

定数および変数は、値と[型](https://qiita.com/flowcadence/items/48303ea74f8e783d9d06)を識別子(identifer)に結びつける宣言です。定数は値で初期化され、その後再割り当てすることはできません。変数は値で初期化され、後で再割り当てすることができます。宣言はグローバルスコープを含む任意のスコープで作成できます。

定数とは、識別子の関連性が一定であることを意味し、値自体が一定であることを意味するものではありません。値は変更可能であれば、変更することができます。

定数は、`let`キーワードを使用して宣言します。変数は、`var`キーワードを使用して宣言します。キーワードの後に、識別子、オプションの[型アノテーション](https://qiita.com/flowcadence/items/aefb58373b7b6dc956d9)、等号記号`=`、初期値を続けます。
```ruby
/* Declare a constant named `a`. */
let a = 1

/* Invalid: re-assigning to a constant. */
a = 2

/* Declare a variable named `b`. */
var b = 3

/* Assign a new value to the variable named `b`. */
b = 4
```
変数と定数は初期化が必須です。
```ruby
/* Invalid: the constant has no initial value. */
let a
```
各スコープにおける変数または定数の宣言名は、一意でなければなりません。現在のスコープで既に宣言されている名前で別の変数または定数を宣言することは、種類や型に関係なく無効です。
```ruby
/* Declare a constant named `a`. */
let a = 1

/* Invalid: cannot re-declare a constant with name `a`,
 * as it is already used in this scope.
 */
let a = 2

/* Declare a variable named `b`. */
var b = 3

/* Invalid: cannot re-declare a variable with name `b`,
 * as it is already used in this scope.
 */
var b = 4

/* Invalid: cannot declare a variable with the name `a`,
 * as it is already used in this scope,
 * and it is declared as a constant.
 */
var a = 5
```
ただし、サブスコープ内で変数の再宣言が可能です。
```ruby
/* Declare a constant named `a`. */
let a = 1

if true {
    // Declare a constant with the same name `a`.
    // This is valid because it is in a sub-scope.
    // This variable is not visible to the outer scope.

    let a = 2
}

/* `a` is `1` */
```
変数を変数自身の初期値として使用することはできません。
```ruby
/* Invalid: Use of variable in its own initial value. */
let a = a
```


翻訳元

https://cadence-lang.org/docs/language/constants-and-variables

***
<b>[Previous << Syntax](https://qiita.com/abcdefgac153131/items/29b0617fdfbf652c5425)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (Constants and Variable Declarations)

<b>[Next >> Type Annotations](https://qiita.com/abcdefgac153131/items/aefb58373b7b6dc956d9)</b>
Type Annotations

[Previous << Constants and Variable Declarations](https://qiita.com/flowcadence/items/7224da752f0788e6a5e6)
[Next >> Values and Types](https://qiita.com/flowcadence/items/c917af1e35cd46cf6a7f)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#cadenceの言語仕様を学ぶ

定数または変数を宣言する際には、宣言の型を明示するために、オプションで型アノテーションを指定することができます。

型アノテーションが指定されていない場合、宣言の型は[初期値から推論されます](https://qiita.com/flowcadence/items/cf6493f9fd297b677452)。

関数のパラメータには、型アノテーションを指定する必要があります。

```ruby
/* Declare a variable named `boolVarWithAnnotation`, which has an explicit type annotation.
 *
 * `Bool` is the type of booleans.
 */
var boolVarWithAnnotation: Bool = false

/* Declare a constant named `integerWithoutAnnotation`, which has no type annotation
 * and for which the type is inferred to be `Int`, the type of arbitrary-precision integers.
 *
 * This is based on the initial value which is an integer literal.
 * Integer literals are always inferred to be of type `Int`.
 */
let integerWithoutAnnotation = 1

/* Declare a constant named `smallIntegerWithAnnotation`, which has an explicit type annotation.
 * Because of the explicit type annotation, the type is not inferred.
 * This declaration is valid because the integer literal `1` fits into the range of the type `Int8`,
 * the type of 8-bit signed integers.
 */
let smallIntegerWithAnnotation: Int8 = 1
```
型アノテーションが提供されている場合、初期値は必ずその型でなければなりません。変数に割り当てられるすべての新しい値はその型と一致しなければなりません。この型の安全性については、[separateセクション](https://qiita.com/flowcadence/items/48303ea74f8e783d9d06)でさらに詳しく説明します。
```ruby
/* Invalid: declare a variable with an explicit type `Bool`,
 * but the initial value has type `Int`.
 */
let booleanConstant: Bool = 1

/* Declare a variable that has the inferred type `Bool`. */
var booleanVariable = false

/* Invalid: assign a value with type `Int` to a variable which has the inferred type `Bool`. */
booleanVariable = 1
```


翻訳元

https://cadence-lang.org/docs/language/type-annotations

***
<b>[Previous << Constants and Variable Declarations](https://qiita.com/flowcadence/items/7224da752f0788e6a5e6)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (Type Annotations)

<b>[Next >> Values and Types](https://qiita.com/flowcadence/items/c917af1e35cd46cf6a7f)</b>
ゲームエンジン Ren'py(ノベラ作成)を始める｡EP02 メッセージ､画像と音楽の扱い｡

## テスト用プロジェクト
最初にテスト用プロジェクトを作ります｡何分かかります｡骨組みを作ってくれます｡
![r6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23768/6c997ac7-afeb-063a-dabf-ab23cbbaad9a.png)
### メッセージの表示
script.pyを開けて中身すべて消します｡
2行追加します｡
```
label start:
    "これがスタートです｡"
```
メインメニューから"test"を動かしてください｡
メッセージに必要な要素としては､誰が話しているかです｡
次の1行をlabelの上に追加してください｡
メッセージの頭にsを付けてください｡

```
# 定義
define s = Character(_("Sylvie"), color="#adff2f")

label start:
    s "これがスタートです｡"
```
メッセージの頭に定義された"s" Sylvieが表示されます｡

### 背景画像の表示
他のDirから背景画像をコピーします｡
```
/renpy-8.1.3-sdk
    /the_question/game/images/
     コピー(bg uni.jpg
    /test/game/images/
```
label startの1行下にbg uni.jpgの表示します｡
```
# 定義
define s = Character(_("Sylvie"), color="#adff2f")
# スタート
label start:
    scene bg uni
    s "これがスタートです｡"
```

### キャラクターの表示

```
/renpy-8.1.3-sdk
    /the_question/game/images/
     コピー(sylvie blue smile.png
    /test/game/images/
```
    
背景画像下にsylvie blue smile.pngの表示します｡

```
# 定義
define s = Character(_("Sylvie"), color="#adff2f")
# スタート
label start:
    scene bg uni
    show sylvie blue smile
    s "これがスタートです｡"
```
### 音楽の出力

```
/renpy-8.1.3-sdk
    /the_question/game/
     コピー(illurock.opus
    /test/game/audio/
```
    
label start下に play music "illurock.opus"追加する｡

```
# 定義
define s = Character(_("Sylvie"), color="#adff2f")
# スタート
label start:
    play music "illurock.opus"
    scene bg uni
    show sylvie blue smile
    s "これがスタートです｡"
```
音楽が入ります.


以上です｡
ゲームエンジン Ren'py(ノベラ作成)を始める｡EP01 インストール

## 環境
* Linux Mint 21.1
* renpy-8.3.1-sdk
* Python 3.10.12
The Ren'Py Visual Novel Engine
https://ja.renpy.org/index.html

## 概略
以下よりの引用
なぜ Ren'Py なのか?
https://ja.renpy.org/why.html

### なぜ Ren'Py なのか?
> Ren'Py は無料でクロスプラットフォームなデジタルストーリーエンジンです。文字と画像、音声を組み合わせてビジュアルノベルや人生ゲームを簡単に作れます。
:::note info
かなり複雑なプログラムも作れます｡
::::

### 無料、そしてオープンソース
> Ren'Py は、商用・非商用問わず無料でご利用頂けます。あなたの Ren'Py 製ゲームを配布するのに弊社及び第三者に金銭的な対価を支払う必要はありません1。 Ren'Py は既に半ダース以上の商業ゲームで採用されています。

:::note info
このデータは古いです｡もっと多くの商業ゲームが作られているように思われます｡スポンサーの数を見てください｡
::::

### クロスプラットフォーム コンピューターとモバイル
> Ren'Pyの最大の利点の１つは様々なコンピューターで動作するということです。主に3つのプラットフォームをサポートしています。 :
Windows 7+ (x86_64)
Mac OS X 10.10+ (x86_64)
Linux (x86_64, Arm)

> Android と iOS は第二プラットフォームとしてサポートされています。 Ren'Py はそれらのデバイスで動作しますが、開発はコンピューター上でなければなりません。 Ren'Py ゲームはWebAssemblyをサポートするブラウザ上でも動作しますが、ブラウザプロジェクトが改善するまではこのサポートはベータ版となります。

:::note info
開発は3つのプラットフォームで行いAndroidとiOSで動かすということ｡今の時点でもそこそこ動きます｡ここで試してみました｡

* すぐにブラウザで作ってみよう | たのしいゲームサイト　プリシー
https://plicy.net/MypageGameDesigner

LinuxのRenpyでWebAssembly変換かけてAndroidのChromeで動きました｡
::::
### その他
1. 簡単なスクリプト言語,Pythonより簡単なスクリプト言語､Pythonの勉強しておいたほうが良い｡
1. プレーヤーが望む機能,あらかじめ､save､lodaなどの機能を持つ｡
1. 簡単にカスタマイズ・多言語対応, 只今勉強中､カスタマイズは簡単ではない｡
1. 採用実績,海外の方が多い｡



## インストール
### ダウンロード
Ren'Py 8.3.1
https://ja.renpy.org/latest.html

今回はLinux版を使用します｡
エディターも入っています｡

### 設定

1. 好きなdirに解凍する｡
1. 解凍されたrenpy.shを実行できるようにする｡
1. renpy.shを実行する｡
![r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23768/0ca263a8-4417-37d5-aac7-cbe0a3f3f91d.png)

1. preferencesを選択｡(なんでSetupにしてくれない!)

![r3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23768/6f2224ee-4d6d-6160-e8f7-d23aab16897e.png)

1. 言語を選択｡
1. テキストエディタを選択｡
1. 戻る｡

### メインメニューレイアウト
![r4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23768/0ff0632a-6ac4-248b-c551-010338396000.png)

#### 頻繁に使うメニュー
1. プロジェクト (作成するゲームの登録場所)
1. ファイルを編集する｡ (プログラムの一覧)
1. プロジェクトの起動 (ゲームの起動)

はじめに."ザ･クエスチョン"を起動してみてださい｡
日本語を選んでください｡あとは適当に操作してください｡
![r5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23768/d6fad4cb-362b-6587-4c03-a9326041d565.png)

今回はこれで終わりです.

### 参考リンク
非プログラマのRen'Pyノート：はじめに｜みやこ出版｜個人ゲーム開発
https://note.com/akutaba/n/n1e686cf50f20?magazine_key=m91345b9bb420
### リンク
[ゲームエンジン Renpy(ノベラ作成)を始める｡EP02 メッセージ､画像と音楽の扱い｡ #Linux - Qiita](https://qiita.com/bomiura/items/4a908c6dcd38d5459029)

[ゲームエンジン Renpy(ノベラ作成)を始める｡EP03 選択､フラグと判定文の使い方 #Linux - Qiita](https://qiita.com/bomiura/items/7eff5d985142902cf297)
古典コンピュター処理の完成及び、不完全性定理の解決について


#### 古典コンピュータ処理の完成

古典コンピュータの動作は全てが所詮1と0のコードの変換に帰着されるので、最先端研究では、General Code Converterを開発中らしいです。古典的なコンピュータの働きは1と0のコード変換に過ぎない。この視点から見ると、General Code Converterは、あらゆるコードや命令を超えて「1と0」だけで表現可能な情報の究極のコード変換になる。他のアーキテクチャや言語への変換も、ある意味で一種の「翻訳」であり、根本的にはデータの流れと操作を整理しているわけです。このコンバーターがどのようにして変換のルールを取り扱うかは、個々の場合の適合ファイル（もしくはその集合）だと思います。この方式なら、必要な場合に対応する変換ルールを追加していける柔軟なシステムになりそうです。個々のファイルが、コードの再利用や拡張に大きな利便性をもたらす一方で、膨大な数の変換パターンにも対応できそうです。一方、適合ファイル（セット）が膨大な数になるので、個々の場合を抽象化しなくてはいけません。抽象化によって、個別のケースを共通のパターンにし、共通部分を一つのルールとして扱えるようにすることが必要です。この抽象化は、例えばデータ構造の共通点を抽出してパターン化する作業に近いイメージもしくは、観念的に記述できる言語を使う、あるいは、階層化されたレベルでの抽象化が進んでいけば、General Code Converterは理論上どんなアーキテクチャや言語にも対応できる、汎用的な「変換エンジン」として機能しそうです。音楽も、音声も、画像も、動画も、言葉も、記号も、数学体系も、学問の理論体系も、抵抗値も、電流値も、物理の理論体系も、社会現象も、天体の運行も、自然現象も、定量的に記述できる情報も、匂いも、感覚も感情も本能も数値化できそうです。コード化できるありとあらゆるものを処理できるのが理想です。全部は到底無理ですが、範囲を限定すれば全部できるでしょう。チューリングマシンは、無限に長いテープと無限時間の処理時間を持っている。人間のデベロッパーが必要です。結局、コンピュータに餌を食わせてやるのは人間ですが、人間の代わりをする恐ろしいデバイスができるかも知れません。既に、脳に接続するデバイスもできていて、更に研究中です。生体コンピュータ・・・。怖い怖い。倫理的な問題があります。知能では結局コンピュータの方が個人に勝ちそうですが、コンピュータは所詮機械（道具）なので人間の主人になってはいけない。コンピュータは意識や生命を持たないし（意識と生命は同じものかも知れない。まだわかってない）、人間には想像力、創造力があり、（コンピュータにも備わると思うけど）争うとコンピュータと人間のメタメタ競争が続きそうです。道具は使われるべき。人間を道具にしてはいけない。

AIが進んだら、そのうち巨大and/or複雑なプログラムの自動テスト・デバッグもできそうですね。
人間はデザイン専門になる？！

及び、

#### 不完全性定理の解決

コンピュータに不完全性定理を適用して、それ自身で自分の完全性を証明できないから、人間の評価が必要になる？　公理系が処理用と評価用２つあったらいいです。 一貫して無限ではない体系（有限な体系）や極めて単純な系や無矛盾かつ再帰的に列挙可能でない体系では、不完全性定理の影響を受けないから、評価用は有限もしくは、極めて単純もしくは、無矛盾かつ再帰的に列挙可能でない体系であればよいです。古典コンピュータの実物は、メモリも時間も有限ですが、理論的に無限は作れます、というか、チューリングマシンが元型なので理論上は無限です。無限の極めて単純な例は、（while 1　{}、無限ループで無限に加算される値、理想的な、しかし実時間上の終わりのない入力）とかです。無限がなければエラーを検出できます。そういうのを単純な体系と言うのでしょう。これで不完全性定理は解決です。僕は、論理的に証明はできていませんが、別の公理系があれば、自己矛盾を評価できます。ラッセルが単純にしました。十分です。結局自動デバッガに人間の評価は要りません（これは、今の所、コンピュータによる全自動デバッグは可能という仮説です。）が、もう一人のクルト・ゲーデルのような悪魔のように賢い人が出てきて、また新しい理論を発明して、解決不能になるかもしれません。2つ目の公理系が完全で、先に挙げた3つの条件のうち一つも満たしてなければ、不完全性定理にひっくり込まれる恐れがあります。どうもおかしい、不完全性定理は解決できそうだと思っていた。不完全性定理の解決の論理的証明はすでになされていて、大学で教えられている。論理学者さん、教えてくれてありがとう。

ChatGPTの出力

「不完全性定理の否定を教えてください」

「3. 公理系外部からの証明
不完全性定理は「ある公理系の内部で証明不可能な命題が存在する」ことを示していますが、別の体系（たとえば上位の体系）を導入すれば、それによって無矛盾性を証明することが可能になる場合もあります。しかしこれは「内部からの証明」ではないため、不完全性定理の「否定」とは言えません。」

「否定」とは言えないけど、解決と言えるのかな？

四月馬鹿この句は嘘を詠んでいる　公太郎

#### コメント

あと20年もすればパーソナル量子コンピュータが実用になって、子供も量子コンピュータで遊ぶようになるでしょう。古典コンピュータと量子コンピュータは得意分野が違うので、まだまだ両方必要そうです。

ちょっと文章が間違っているかも知れません。
抽象的なことを言い過ぎました。この記事の僕の話し相手は、ChatGPTでした。
すみません、偉そうなこと言って。
SQLパズル　21 　飛行機と飛行士の解法その２　メモ

# 概要
SQLパズル　21 　飛行機と飛行士の解法その２について

Having句を使った関係除算の理解が必要です。

# 要件
待機中の飛行機すべてを操縦できるパイロットをすべて選択したい。

## 関係除算
```
関係演算R÷Sは、関係Rのうち関係Sの全ての項目を含む行の集合を返す演算です。
```
https://qiita.com/lymansouka2017/items/90a7d47c432f372d9122



# SQL

## DDL
```sql
drop table if EXISTS PilotSkills;
drop table if EXISTS Hangar;

CREATE TABLE PilotSkills
(pilot CHAR(15) NOT NULL,
 plane CHAR(15) NOT NULL,
    PRIMARY KEY (pilot, plane));

CREATE TABLE Hangar
(plane CHAR(15) PRIMARY KEY);

INSERT INTO PilotSkills VALUES ('Celko', 'Piper Cub');
INSERT INTO PilotSkills VALUES ('Higgins', 'B-52 Bomber');
INSERT INTO PilotSkills VALUES ('Higgins', 'F-14 Fighter');
INSERT INTO PilotSkills VALUES ('Higgins', 'Piper Cub');
INSERT INTO PilotSkills VALUES ('Jones', 'B-52 Bomber');
INSERT INTO PilotSkills VALUES ('Jones', 'F-14 Bomber');
INSERT INTO PilotSkills VALUES ('Smith', 'B-1 Bomber');
INSERT INTO PilotSkills VALUES ('Smith', 'B-52 Bomber');
INSERT INTO PilotSkills VALUES ('Smith', 'F-14 Fighter');
INSERT INTO PilotSkills VALUES ('Wilson', 'B-1 Bomber');
INSERT INTO PilotSkills VALUES ('Wilson', 'B-52 Bomber');
INSERT INTO PilotSkills VALUES ('Wilson', 'F-14 Fighter');
INSERT INTO PilotSkills VALUES ('Wilson', 'F-17 Fighter');
INSERT INTO PilotSkills VALUES ('KIRIKO', 'F-17 Fighter');

INSERT INTO Hangar VALUES ('B-1 Bomber');
INSERT INTO Hangar VALUES ('B-52 Bomber');
INSERT INTO Hangar VALUES ('F-14 Fighter');
```

## 答えのSQL

```sql
SELECT Pilot
  FROM PilotSkills AS PS1, Hangar AS H1
 WHERE PS1.plane = H1.plane
 GROUP BY PS1.pilot
HAVING COUNT(PS1.plane) = (SELECT COUNT(*) FROM Hangar)	
;

```

## 図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/b311370b-6986-2743-1ae7-cfd2323dc30a.png)

# 分解して考える

## イ
PilotSkillsとHangerのすべての組み合わせを求めた後、
PilotSkillsとHangerのplaneが合致する条件のみを取得する。

この時点で、Celkoは以下理由のため弾かれる
HangerにあるPlaneには乗れないため




### sql
```sql
-- 1 PilotSKillsとHangerのすべての組み合わせを求める
SELECT PS1.*,H1.*
FROM PilotSkills AS PS1, Hangar AS H1
;

-- 2 
SELECT PS1.*,H1.*
  FROM PilotSkills AS PS1, Hangar AS H1
 WHERE PS1.plane = H1.plane
;

```

### 図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/4b963156-8a0a-982c-bfcc-a80db7ce0f1c.png)



## ロ
イで求めたレコードをGroup byとHaving句を使って条件指定する。
Hangerの件数と、pilotのplaneの件数を合致しているパイロットを取得する。

HigginsとJonesとKIRIKOは以下理由で弾かれる。
Hangerの総件数(=3)と同じ値にならないため。

結果、SmithとWillsonのみが残る。

### sql
```sql
-- 2
SELECT PS1.*,H1.*
  FROM PilotSkills AS PS1, Hangar AS H1
 WHERE PS1.plane = H1.plane
;

-- 3
SELECT Pilot
  FROM PilotSkills AS PS1, Hangar AS H1
 WHERE PS1.plane = H1.plane
 GROUP BY PS1.pilot
HAVING COUNT(PS1.plane) = (SELECT COUNT(*) FROM Hangar)	
;
```



### 図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/0cffaca4-cef5-59ef-4e8f-78968be1c33d.png)


# 一言
数の除算は数を割るだけで一発で処理できる分、
関係除算（というか集合の除算？？）は計算するのに数ステップ要るからややこしい。




# 参考

SQLパズル　p91

SQLパズル　サポートページ
https://mickindex.sakura.ne.jp/database/db_support_sqlpuzzle.html#LocalLink-p21

達人に学ぶSQL徹底指南書第２版 p133 column　関係除算
関係除算の定義が複数ある

達人に学ぶSQL徹底指南書第２版 p127 バスケット解析

github コミット分
https://github.com/RYA234/SQL_Puzzle_Learning/commit/9a3690b4e91057cb23ed96ef856c4cfa02baa3dc
GraphDB Kuzu(WebAssembly)をvitestで動かしたメモ

# 概要
[前回](https://qiita.com/hibohiboo/items/78c0d25d8c2a1280855b)はlocalStorageへの永続化を行った。
今回は、kuzu_wasmをテストしてみようとしたところエラーとなったので対応したメモ。
かなり力技で解決したので、もっとスマートな方法があればしりたい。

[この時点のソース](https://github.com/hibohiboo/kartagraph-monorepo/blob/d6e55f5fcc1e1c7877a2fcadb5bf8507c4b324dc/apps/kuzu/tests/createUserNode.test.ts)

# 発生したエラー

```
TypeError: kuzu.Database is not a function
 ❯ Module.getGraphDbClient src/shared/lib/graphdb/kuzu.ts:11:25
      9|   }
     10|   kuzu = await kuzu_wasm();
     11|   const db = await kuzu.Database();
```

# 検討
おそらく、ブラウザではなくNodeと認識している。
そのため、[index.js](https://github.com/unswdb/kuzu-wasm/blob/main/packages/kuzu-wasm/src/index.js)で行われている処理がスキップされてしまっていると考えられる。

# 対応
モック機能を使い、スキップされた処理を補完する。

```ts
/* eslint-disable @typescript-eslint/no-explicit-any */
import { expect, test, describe, vi, beforeAll, afterEach } from 'vitest';
import { createUserNode, initDb } from '../src/feature/user/model/create';
import { getGraphDbClient } from '../src/shared/lib/graphdb/kuzu';
import { initializeWebDatabase, initializeWebConnection } from './mock/helper.mjs';


vi.mock('@kuzu/kuzu-wasm', async () => {
  const { default: originalModule } = (await vi.importActual('@kuzu/kuzu-wasm')) as any;
   return {
    default: async () => {
      const m = await originalModule();
      const Database = () => initializeWebDatabase(m);
      const Connection = (...args: [any, number]) => initializeWebConnection(m, ...args);
      return {
        ...m,
        Database,
        Connection,
      };
    },
  };
});

describe('createUserNode', () => {
  beforeAll(async () => {
    await initDb();
  });
  afterEach(async () => {
    const conn = await getGraphDbClient();
    await conn.execute('MATCH (n) DETACH DELETE n');
  });
  test.each([
    ['test-1', 15],
    ['test-2', 20],
  ])('ユーザを作成できること: %s', async (name, age) => {
    await createUserNode(name, age);
    const conn = await getGraphDbClient();
    const result = await conn.execute('MATCH (u) RETURN (u)');
    const [ret] = getQueryData(result); // [ {"u": {"_ID":{"offset":"1","table":"0"},"_LABEL":"User","name":"test-2","age":"20","population":null}} ]

    expect(ret['u'].name).toBe(name);
    expect(ret['u'].age).toBe(`${age}`);
  });
});
function getQueryData(result: any) {
  if (!result.table) return [];

  return JSON.parse(result.table.toString());
}
```

# 結果
成功するようになった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/09139399-fee0-a491-ca50-55d7ca6d35a2.png)


# 参考
[【Vitest】利用しているライブラリの一部をモックする](https://zenn.dev/fugithora812/articles/767c3a92e79da1)
Auth0の「Audience」とは？

Auth0における「audience」とは、認証の際に生成されるAccess Token（アクセストークン）の対象リソース（APIやサービス）を指定するためのパラメータです。これにより、アクセストークンがどのAPIやサービスに対して有効であるかを明確に示すことができます。

具体的な役割や使い方について、以下のポイントで説明します。

### 1. **Audienceの定義**

- 「audience」とは、Access Tokenが使用されるべき「対象のリソースサーバー」を示します。例えば、Auth0で保護されたAPIや他のサーバーサイドサービスなどが対象です。
- リソースサーバーには通常、APIやバックエンドサービスなどが含まれ、リソースサーバーが受け取るAccess Tokenが「自身のものかどうか」を識別できるようになります。

### 2. **Audienceの指定方法**

- OAuth 2.0またはOpenID Connectを利用してAuth0に認証リクエストを送る際、リクエストのパラメータとして`audience`を指定します。
- `audience`には、APIの識別子（通常はAPIのURLやユニークな文字列）を設定します。例えば、Auth0管理画面で作成したAPIの識別子を設定することが多いです。

```
https://<YOUR_AUTH0_DOMAIN>/authorize? audience=<API_IDENTIFIER>& client_id=<YOUR_CLIENT_ID>& response_type=token& redirect_uri=<YOUR_CALLBACK_URI>& scope=read:messages& state=<STATE>
```

### 3. **Audienceの役割**

- `audience`パラメータを含むリクエストが送られると、Auth0は指定された`audience`に基づき、Access Tokenを発行します。
- `audience`が指定されると、Auth0は通常のIDトークンではなく、APIにアクセスするための「Access Token」を生成し、発行されたトークンは`aud`（audience）クレームにリソースサーバーの識別子を含みます。
- リソースサーバー（APIなど）は、受け取ったトークンの`aud`クレームを検証し、自分のAPIの`audience`が一致するかどうかでトークンの有効性を確認します。

### 4. **例：複数APIとAudience**

- `audience`を利用すると、複数のAPIに対して異なるAccess Tokenを発行できます。たとえば、ユーザーが複数のAPIにアクセスする必要がある場合、それぞれのAPIの`audience`を個別に設定することで、APIごとに認証されたトークンが生成され、セキュリティが強化されます。

### まとめ

Auth0の「audience」は、アクセストークンがどのAPIやリソースサーバーを対象とするのかを明示するための重要なパラメータです。適切に設定することで、APIアクセスの制御が可能になり、セキュリティが向上します。
Homemade Pizza Night: A Flavorful Adventure

There's nothing quite like the satisfaction of biting into a perfectly cooked, homemade pizza. The aroma of fresh dough, the sizzle of cheese, and the burst of flavors – it's a culinary experience that's hard to beat. In this recipe, we'll guide you through the process of creating a delicious homemade pizza, from the dough to the toppings.

![Homemade Pizza.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922435/a8908d94-1178-d6c5-9e5d-e75964e0b444.jpeg)


Ingredients:

For the Dough:

1 cup warm water (105-115°F)
1 teaspoon active dry yeast
1 teaspoon sugar
1 tablespoon olive oil
1 teaspoon salt
2 1/2 cups all-purpose flour
For the Sauce:

1 (15-ounce) can crushed tomatoes
2 cloves garlic, minced
1 teaspoon dried oregano
1/2 teaspoon dried basil
1/4 teaspoon red pepper flakes
Salt and pepper to taste
For the Toppings:

Your favorite cheese (mozzarella, provolone, etc.)
Your favorite toppings (pepperoni, sausage, mushrooms, onions, bell peppers, etc.)
Instructions:

Make the Dough:

Activate the Yeast: In a small bowl, combine warm water, yeast, and sugar. Let it sit for 5-10 minutes, or until foamy.
Combine Ingredients: In a large bowl, whisk together flour and salt. Add the activated yeast mixture and olive oil.
Knead the Dough: Turn the dough onto a lightly floured surface and knead for 8-10 minutes, or until smooth and elastic.
Proof the Dough: Place the dough in a greased bowl, cover it with plastic wrap, and let it rise in a warm place for 1-2 hours, or until doubled in size.
Prepare the Sauce:

Combine Ingredients: In a saucepan, combine crushed tomatoes, garlic, oregano, basil, red pepper flakes, salt, and pepper.
Simmer: Bring the sauce to a simmer and cook for 10-15 minutes, or until thickened.
Assemble and Bake the Pizza:

Preheat Oven: Preheat your oven to 475°F (245°C).
Prepare the Pizza Stone or Baking Sheet: If using a pizza stone, place it on the middle rack of the oven. If using a baking sheet, line it with parchment paper.
Shape the Dough: Roll out the dough on a lightly floured surface to your desired thickness.
Add Sauce and Toppings: Spread the sauce over the dough, leaving a small border. Top with your favorite cheese and toppings.
Bake the Pizza: Place the pizza on the preheated pizza stone or baking sheet. Bake for 10-15 minutes, or until the crust is golden brown and the cheese is bubbly.
Conclusion

Homemade pizza is a delightful culinary adventure that can be tailored to your specific tastes. By following these simple steps, you can create a delicious pizza that's sure to impress your family and friends. Experiment with different toppings and crusts to find your perfect pizza combination. Enjoy!
JavaScriptのArrayBufferとは？

JavaScriptにおける`ArrayBuffer`は、バイナリデータの格納と操作に特化したデータ構造で、主にWeb APIや低レベルなデータ処理のために使用されます。その特徴は以下のとおりです：

### 1. **固定長のメモリ領域**

- `ArrayBuffer`は一定のサイズのメモリ領域を確保します。サイズはバイト単位で指定され、一度生成するとサイズは変更できません。

### 2. **バイナリデータの格納**

- JavaScriptの通常の配列は、任意の型のデータを格納できますが、`ArrayBuffer`は純粋なバイナリデータ（ビットの列）を格納します。
- メモリ効率が高く、大量データを扱う際に便利です。

### 3. **複数のビュー（TypedArray）でデータにアクセス可能**

- `ArrayBuffer`自体にはデータアクセス機能はありません。そのため、`TypedArray`や`DataView`などを使用してバッファ内のデータにアクセスします。
- `Uint8Array`, `Int16Array`, `Float32Array`などの`TypedArray`で整数、浮動小数点、または符号付き・符号なしでデータを処理できます。
- `DataView`を使うと、異なるエンディアン（ビッグエンディアンやリトルエンディアン）を意識したデータ操作も可能です。

### 4. **Web APIやFile APIとの連携**

- `ArrayBuffer`はWeb APIと密接に関連しており、たとえば`fetch()` APIを用いて取得したバイナリレスポンスを`ArrayBuffer`として扱うことが可能です。
- また、`Blob`や`FileReader`などを用いて、ファイルの読み取りや操作に`ArrayBuffer`を使うことが一般的です。

### 5. **効率的なパフォーマンス**

- `ArrayBuffer`は、特に大規模なバイナリデータの処理において、JavaScriptでパフォーマンスを向上させるために使用されます。
- ゲーム開発やWebGLを使った3Dレンダリング、音声・画像データの処理など、高速なデータ操作が求められる場面で多く用いられます。

### 6. **シリアル化とデシリアル化のための利用**

- `ArrayBuffer`は、データをバイナリ形式でシリアル化し、他のシステムやスレッドに送信する際に便利です。
- Web Workersなどの他のスレッドに対してメモリ領域を「移譲」することも可能で、効率的なマルチスレッド処理に役立ちます。

### 使用例

```javascript
// 8バイトのArrayBufferを作成
let buffer = new ArrayBuffer(8);
// Uint32Arrayビューを使ってバッファにアクセス
let view = new Uint32Array(buffer);
view[0] = 42;
console.log(view[0]); // 出力: 42
```

‌

`ArrayBuffer`は、JavaScriptで低レベルデータを扱う上で非常に強力であり、特にパフォーマンスを重視した開発には欠かせない機能です。
【Pythonでゲーム開発】ドット専用ゲームエンジン「Pyxel」のすごさ

## 自己紹介
　ただの情報系大学生です。Pythonでゲームを作るのが好きで、最初はTkinterを使って色々やってました。しかし、ゲームエンジンの存在を知ってからはなんて非効率なことをと嘆く日々です。
　私と同じようにゲームを作りたいと思ったPythonistたちは絶対に同じ轍を踏まないでください。

## Pythonでドット絵のゲームが作りたい！！！
　Pythonでプログラミングをしていて、ゲームが作りたくなることはありませんか？ゲーム好きでプログラミングもするという方なら一度は思うことでしょう。しかし、知識もない3Dゲームは敷居が高い！ゲーム作りといえばUnityだけど、C#はわからん！
　これ、きっとあるあるだと思います（そうじゃなかったらごめんなさい）。そうなると、選択肢は絞られてきますよね。気軽に進める道はやはりドット絵のゲームを作ることです。

## 使うべきGUIライブラリは？
　さて、Pythonでドット絵のゲームを作るとなると、重要なのは何のライブラリを使ってGUIを作るかというところになります。一番簡素かつ有名なのはTkinterですが、あれははっきり言って機能が最低限な上可読性が低いです。まあ、簡単なツールをテストする名目とかが妥当な使い方ではないでしょうか。
　ゲーム作りに使うGUIライブラリはきちんとゲーム作りに特化したもの、つまりゲームエンジンを使いましょう。インターネットでPythonのゲームエンジンを検索してみると、ほとんどが「Pygame」についてのドキュメントであると思います。

## ユーザーの多いPygameとはどんなエンジンか
　シェア率が高かったので、私が最初に触ったゲームエンジンはPygameでした。ところがどっこい、最初の画面を出す、多少の更新処理をやってみるまでは簡単ですが、あのライブラリでは画像処理が主になってしまいます。画像処理でドット絵のゲームを作るのは別に間違ったことではありませんし、Pygameの勉強にももちろんなります。ですが、あのライブラリではレイヤーや更新処理の最適化など考えることが多く、またサポートされているメソッドも非常に多様です。
　そりゃあ便利で細かいところまで組めますよ、でもこれからゲームを作りたいと言う人にとって少々煩雑な部分が多いんです。第一、画像処理でドット絵を構成するって何だかドット絵以外にも対応している分、処理が重くなりそうな感じがしませんか？これは偏見かもしれませんが。
　あ、ちなみにドットじゃない2DゲームはじゃんじゃんPygame使っちゃってください。~~私がドット絵にこだわっているだけというツッコミはなしで。~~

## そこで登場する真打Pyxel

<h4>自作シューティングゲームの画像</h4>
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3850890/80fdc1ec-f3ba-1b08-d8b7-da92ec0bdf6a.png"/>

　ここで、私が推したいのはPyxelというモジュールです。このモジュールは基本的にドット絵しか描画しません。この時点でドット絵が目的の人にとって最高だと思うのです。

### リソースファイル
　まずPyxelはpyxresファイルという独自のリソースファイルを持ち、専用のエディタでそのファイルを編集することができます。これはドット絵のリソース、ドット絵を組み合わせたタイルマップ、音楽のリソース、音楽のリソースを合わせたbgmという四つの項目からなるものです。このファイルをコードから読み込むことによってリソースをファイル内の座標やidで呼び出すことができ、描画のコードがとても簡潔に書けます。もちろんコードから直接図形なんかを描くこともできますし、PyxelUniveralFontという別のモジュールと組み合わせるとテキストもドットで出してくれる優れもの。つまり、レトロなゲームにはうってつけなゲームエンジンであるわけです。
### 実行形式
 Pyxelはpyxappという実行ファイル形式をサポートしていて、これはコマンドラインから実行できるほかにOS依存の普通の実行ファイルやhtml形式にも変換できるようになっています。共有性がすごく高いです。
　また、更新処理も可読性がかなり高いフォーマットであると個人的に感じています。というのも、更新処理を開始する方法がrunメソッドの引数に更新関数と描画関数を渡すというもので、モジュール側からある程度のオブジェクト指向が形成されるような形に誘導されるのです（オブジェクト指向のなんたるかを理解しきれていない若輩者ですので、この点に関しては異論があるかもしれません）。

## 説明は以上。あとは実際に触ってみよう
　ここまで色々と語りましたが、この日本語の塊でPyxelの良さを理解しろというのは無理があるとも思います。ですので、興味を覚えた方はぜひ、いますぐにでも、GithubにあるPyxelのREADMEを読んでいただきたいです。ここには私が今まで述べたPyxelの情報以上のことが全て載っています。かくいう私も、このREADMEの冒頭に載せられた画像・動画に魅せられたクチです。百聞は一見にしかず、下のリンクを踏んで見てみてください。
<a href=https://github.com/kitao/pyxel/blob/main/docs/README.ja.md>https://github.com/kitao/pyxel/blob/main/docs/README.ja.md</a>
Python Streamlit Webアプリ開発

# 目次
1.開発方法
2.アプリ概要
3.開発時の工夫
4.ソースコード


# 1.開発方法
Youtubeにて、以下の動画を参考にしました。
https://youtu.be/zp-kAt1Ih5k?si=6oU4RI2CQH7IfmFO

Pythonライブラリ、Streamlitを用いて様々なコマンドを紹介しています。
この動画での解説を参考に、オリジナルでWebアプリを開発しました。

# 2.アプリ概要
起床時間の記録アプリです。
ボタンを押すとその時刻が記録され、日々の起床時間を表で閲覧できる仕組みです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827197/5ebc3cb1-62e2-1fe7-63bc-fd0d3f25633b.png)

「起床時間を選択してください」という文字の下部に現在時刻が自動で表示され、
「記録する」ボタンを押下すると、ページ下部の表にその日の日付、時刻が記録されます。

プルダウンから月を選択することで、月ごとの記録を閲覧できます。

# 3.開発時の工夫
Youtubeでの学習をもとに、以下の仕組みを活用しました。
・pandas：データ解析を支援するライブラリで、CSVの読み込みやデータの記録の際に活用しています。
・DataFrame：Pandasで使用されるデータ構造で、記録されたデータを表で示すために使います。

その他のソースコードの記載の仕方や、エラー時の対処などはChatGPTを参考にしました。

# 4.ソースコード
```
import streamlit as st
import pandas as pd
from datetime import datetime

# タイトル
st.title("起床時間記録アプリ")

# 日付と時間を入力
wake_up_time = st.time_input("起床時間を選択してください:", datetime.now().time())

# 記録ボタン
if st.button("記録する"):
    # wake_up_times.csvというファイルに記録を保存する
    try:
        df = pd.read_csv("wake_up_times.csv")
    except FileNotFoundError:
        df = pd.DataFrame(columns=["Date", "Time"])

    new_record = {"Date": datetime.now().date(), "Time": wake_up_time}
    df = pd.concat([df, pd.DataFrame([new_record])], ignore_index=True)
    df.to_csv("wake_up_times.csv", index=False)  # インデックスを保存しない
    st.success("起床時間を記録しました！")

# これまでの記録を表示するセクション
st.subheader("これまでの記録")

try:
    df = pd.read_csv("wake_up_times.csv")

    # 日付をdatetime型に変換
    df['Date'] = pd.to_datetime(df['Date'])

    # 月ごとのリストを作成
    months = df['Date'].dt.strftime('%Y-%m').unique()

    # 月を選択するセレクトボックス
    selected_month = st.selectbox("月を選択してください", months)

    # 選択された月のデータをフィルタリング
    filtered_df = df[df['Date'].dt.strftime('%Y-%m') == selected_month]

    # フィルタリングされたデータを表示
    st.write(filtered_df)

except FileNotFoundError:
    st.write("まだ記録がありません")
```
EventBridgeからLambdaに起動日時を連携する

# はじめに
EventBridgeからLambdaを起動する場合、EventBridge⇒Lambdaに日時情報を連携できないか 気になったので実際にリソースを作って調べてみました。


# 結論
EventBridgeから起動されたLambdaでは、`event` パラメータにEventBridgeのイベントの起動時刻（time）が含まれるためこれを利用できそうです。

```:event
{
    ～～～
    'time': '2024-10-29T15:30:00Z',
    ～～～
}
```


# ゴール
EventBridgeから起動したLambdaで、イベントの起動時刻を取得できることを確認します。


# Lambdaの作成

簡単なLambdaを準備します。

```python:lambda_function.py
def lambda_handler(event, context):
   event_time = event['time']
   print(event_time)
```

# EventBrige

下記の手順でEventBrigeのリソースを作成します。

https://qiita.com/enumura1/items/e0a36da923fe1373848a

今回は日次で0時半に起動するように設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/631db930-9813-ad4e-a2a7-edb9f80181fc.png)


# Lambdaの実行ログを確認

CloudWatchログでLambdaの実行結果を見ると、Lambdaのprint()で出力したUTC時間時間（日本時間：+9時間してた時間）が出力されてることを確認できました。

```:CWのログ
2024-10-29T15:30:00Z
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/d202a704-c172-3470-1118-b5ac3ca5983c.png)
サーバーフレームワークh3の8つの特徴

`h3`は、UnJSプロジェクトが開発する軽量なHTTPサーバーフレームワークで、特にサーバーレスアーキテクチャやエッジコンピューティングに適した設計がされています。以下に`h3`の主な特徴をまとめます。

### 1. 軽量かつ高速な設計

- **依存関係を最小限に抑えた設計**により、シンプルで軽量です。
- ハイパフォーマンスを目指し、サーバーレスやエッジコンピューティング環境での高速処理に最適化されています。
- 小規模なリソースで動作するため、低スペックの環境でもスムーズに動作します。

### 2. サーバーレスとエッジ環境に対応

- `h3`は、AWS Lambda、Vercel Edge Functions、Cloudflare Workersなどのサーバーレスおよびエッジ環境をターゲットとして設計されています。
- これにより、デプロイ先や利用環境に左右されず、柔軟なスケールアウトが可能です。
- `h3`はNuxt 3や他のサーバーレスAPIにも対応し、これらと組み合わせることで、スムーズにサーバーレスアプリケーションが構築できます。

### 3. TypeScript対応

- `h3`は**TypeScriptで書かれており、型定義が標準でサポート**されています。
- TypeScriptサポートにより、コードの安全性が向上し、開発中に型チェックが可能であるため、コーディングエラーが減少します。

### 4. シンプルで直感的なAPI

- **シンプルかつ直感的なAPI設計**により、基本的なルーティングやミドルウェアの定義が簡単です。
- `h3`のAPIは、ExpressやKoaに似た設計で、Node.jsに馴染みがある開発者が学習しやすいように工夫されています。

### 5. ミドルウェアのサポート

- ミドルウェアを用いることで、リクエスト処理やレスポンス処理のカスタマイズが容易です。
- ユーザー認証、エラーハンドリング、CORS設定、ロギングなどの処理を追加して柔軟にアプリケーションを構築できます。

### 6. HTTPやHTTP/2に対応

- `h3`は標準でHTTP/2をサポートし、より高速な通信と効率的なリソース配分が可能です。
- HTTP/2の特性を活かすことで、エッジや分散型アーキテクチャにおいても効率的なデータ通信が行えます。

### 7. Nuxt 3やNitroとの統合

- `h3`は特に**Nuxt 3やNitro**と連携が取れるよう設計されています。
- Nuxt 3のバックエンドとして`h3`を使用することで、Nuxtアプリケーション内でAPIを統合的に管理でき、クライアントとサーバー間でシームレスにデータをやり取りできます。

### 8. クリーンな開発体験

- 開発者の生産性を重視した設計で、デバッグやホットリロードが簡単に行えます。
- UnJSエコシステムの他のツールやライブラリと連携して使用することで、バックエンドやAPI開発の効率が向上します。

### まとめ

`h3`は、軽量・高速かつサーバーレスやエッジ環境での使用に特化したHTTPサーバーフレームワークです。シンプルなAPIと柔軟なミドルウェア、TypeScript対応などが特徴で、特にNuxtやNitroと統合して使用するケースに最適です。
Linux上にPiwigo写真管理サーバを構築

## 環境

* OS: Ubuntu 24.04.1 LTS

## Dockerのインストール

Linux上で以下のコマンドを実行する。
```
sudo apt-get install docker.io
sudo apt-get install docker-compose
```

## Piwigo Dockerコンテナの実行ユーザ作成

以下のコマンドを実行する。これにより、piwigoユーザが作成され、docker実行権限が付与される。
```
sudo useradd -m -s /bin/bash piwigo
sudo gpasswd -a piwigo docker
```

## Piwigoの実行環境設定

以下のコマンドを実行し、Piwigo Dockerコンテナに必要なディレクトリを作成する。
```
sudo -u piwigo mkdir -p /home/piwigo/piwigo/gallery
sudo -u piwigo mkdir -p /home/piwigo/piwigo/config
sudo -u piwigo mkdir -p /home/piwigo/piwigo_mariadb
sudo -u piwigo mkdir -p /home/piwigo/docker
```

Piwigoで使用するデータベース(MariaDB)用に、以下の環境ファイルを作成する。
* パス: `/home/piwigo/piwigo_mariadb/env`
* 内容
  ```
  MYSQL_ROOT_PASSWORD=<任意のパスワード>
  MYSQL_DATABASE=piwigo
  MYSQL_USER=piwigo
  MYSQL_PASSWORD=<任意のパスワード>
  ```
* 権限: piwigoユーザのみ読み書き可能
  * 以下のコマンドにより設定できる
  ```
  sudo chown piwigo:piwigo /home/piwigo/piwigo_mariadb/env
  sudo -u piwigo chmod 600  /home/piwigo/piwigo_mariadb/env
  ```

## Piwigo DockerコンテナのDocker Compose作成

以下のDocker Composeファイルを作成する。

* パス: `/home/piwigo/docker/docker-compose.yml`
* 内容
    ```
    version: "3.8"
    services:
      mariadb:
        image: lscr.io/linuxserver/mariadb:10.11.8-r0-ls160
        container_name: piwigo_mariadb
        environment:
          - PUID=<piwigoユーザのUID> ※
          - PGID=<piwigoユーザのGIU> ※
          - TZ=Asia/Tokyo
        volumes:
          - /home/piwigo/piwigo_mariadb:/config
        ports:
          - 3306:3306
        restart: unless-stopped
      piwigo:
        image: lscr.io/linuxserver/piwigo:15.0.0-ls281
        container_name: piwigo
        environment:
          - PUID=<piwigoユーザのUID> ※
          - PGID=<piwigoユーザのGIU> ※
          - TZ=Asia/Tokyo
        volumes:
          - /home/piwigo/piwigo/config:/config
          - /home/piwigo/piwigo/gallery:/gallery
        ports:
          - 8080:80
        restart: unless-stopped
    ```
  * ※ `id piwigo` コマンドを実行することで確認できる

## Piwigo Dockerコンテナの起動・停止

Piwigo Dockerコンテナを起動する場合、以下のコマンドを実行する。
```
sudo su - piwigo
cd /home/piwigo/docker
sudo docker-compose up -d
```

停止する場合は、以下のコマンドを実行する。
```
sudo su - piwigo
cd /home/piwigo/docker
sudo docker-compose down
```

## Piwigo Dockerコンテナのサービス化

以下の設定により、Piwigo Dockerコンテナをsystemdのサービスにして、システム起動時に自動実行させることができる。

まず、サービスの設定ファイルを作成する。
* パス: `/etc/systemd/system/piwigo_docker.service`
* 内容
  ```
  [Unit]
  Description=Piwigo Docker Container Service
  After=docker.service
  Requires=docker.service

  [Service]
  Type=oneshot
  RemainAfterExit=yes
  WorkingDirectory=/home/piwigo/docker
  User=piwigo
  Group=piwigo
  ExecStart=/usr/bin/docker-compose up -d
  ExecStop=/usr/bin/docker-compose down
  TimeoutStartSec=0
  [Install]
  WantedBy=multi-user.target
  ```

以下のコマンドで、サービスを有効化する。
```
sudo systemctl enable piwigo_docker.service
```

なお、以下のコマンドで、サービスの起動・停止を確認できる。
* 起動
  ```
  sudo systemctl start piwigo_docker
  ```
* 停止
  ```
  sudo systemctl stop piwigo_docker
  ```
Express.jsとnodemonとprismaでのバックエンド構築手順

## 前提条件
- Node.js (v14以上)
- npm

## Express.jsとnodemonでのapi作成

まず、新しいプロジェクトを作成し、必要なパッケージをインストールします：

```bash
# プロジェクトディレクトリの作成と初期化
mkdir app-backend
cd app-backend
npm init -y
```
package.jsonファイルのデバッグ"script"を以下の通りに修正する。
```bash
"scripts": {
    "dev": "nodemon server.js"
},
```
server.jsを作成する。
```bash
touch server.js
```
sever.jsファイルは以下の通り。
```javascript
const express = require("express");
const app = express();

const PORT = 5000;

app.listen(PORT, () => console.log(`server is running on port ${PORT}`));
```
```bash
# 必要なパッケージのインストール
npm i express nodemon
```
nodemonが立ち上がることを確認する。
```bash
npm run dev
```

## prisma設定
DB操作のための設定をする。
```bash
npm i install prisma
npx prisma init
```
prismaディレクトリ内にschema.prismaファイルが作成されているはず。

.envファイルでDB操作APIのURLを設定後、マイグレーションを実施
```bash
npx prisma migrate dev --name init
```
migration.sqlファイルが作成されていることを確認する。

modelを追加するときは、schema.prismaファイルに追加して、再度マイグレーションを実施。
```bash
npx prisma migrate dev

? Enter a name for the new migration: » add profile model
```
new migration名を入力してEnterを押下すると、新しいmigration.sqlが作成される。

以下コマンドを実行すると、現状のprismaのモデルが確認できる。
```bash
npx prisma studio
```
誰でも出来る、jmeterでテストシナリオ作成 ~簡単7ステップ！~

1. JMeterの起動
JMeterを起動し、GUIが表示されたら、新規テストプランを作成します。

2. スレッドグループの追加
テストプランを右クリックし、Add > Threads (Users) > Thread Group を選択します。
Thread Groupの設定で以下を行います：
Number of Threads (users): 5（並行リクエスト数を設定します、5人のユーザーを再現する場合は5を設定します。）
Ramp-Up Period (in seconds): 1（全ユーザーが1秒以内にリクエストを開始）
Loop Count: 1（リクエストを送信する回数を設定します）

3. HTTPリクエストの設定
スレッドグループを右クリックし、Add > Sampler > HTTP Request を選択します。
以下のようにHTTPリクエストを設定します：
Server Name or IP: ja.wikipedia.org (wikipediaの場合)
Path:/wiki/メインページ　（wikipediaのスタートページの場合）
Method: POST/GET/PATCH...などなど
Protocol: https or http
Body Dataに、リクエストボディをjson形式で設定する

4. リクエストヘッダーの設定
HTTPリクエストを右クリックし、Add > Config Element > HTTP Header Manager を追加します。
次に各ヘッダーを設定します。
Header NameとValueにリクエストのヘッダーを追加してきます。
※コピペで貼り付けられます。

5. リスナーの追加
結果を確認するために、スレッドグループを右クリックし、Add > Listener > View Results in Table または View Results Tree を追加します。リスナーはリクエスト結果を表示し、パフォーマンスデータを収集します。

6. テストの実行
上記設定が完了したら、Ctrl + R でテストを実行します。
リスナーにリクエストの結果が表示され、各ユーザーのリクエスト状況や応答時間が確認できます。

7. テスト結果の分析
テスト実行後、リスナーに記録された応答時間、エラーレート、スループットなどを確認し、負荷テストのパフォーマンスを分析します。
Androidエミュレータ起動エラー「StartService はエラー 4294967201 により失敗しました」「ControlService FAILED 1062」「Android emulator exited with code -1073741515」


## StartService はエラー 4294967201 により失敗しました

掲題の通りのエラーが出て、Androidエミュレータが起動できない。

```
そのサービスを開始できませんでした。

[SC] DeleteService SUCCESS
[SC] StartService はエラー 4294967201 により失敗しました。
Done
```

端末スペックは下記。
OS: Windows11 Pro 64bit (22H2)
CPU: AMD Ryzen 5 PRO 2500U w/ Radeon Vega Mobile Gfx   2.00 GHz
メモリ: 16.0 GB

厳密にいうとこのエラーは、エミュレーターを起動した時に表示されるのではなく、Androidエミュレーターを使うためにAndroid Emulator hypervisor driver をインストールしようとした時に表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145371/063040d6-cfaf-b05f-624c-91b63b681f9c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145371/613bed2c-71dc-ffc1-25c4-0022d83423cc.png)

Android Studio再起動、Windows再起動等は実施済、install成功するとこのdriverがインストールされた判定になるためアンインストールしようとすると今度は 
```
[SC] ControlService FAILED 1062:

そのサービスを開始できませんでした。
```
と表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145371/9a5d1891-e579-b41c-0c29-486859d61cd2.png)

結構困るので調査しにいく。

## 対処1. 仮想化機能の有効化

エラーコード `4294967201` で調べると、Ryzen CPUの場合に本エラーと遭遇することがしばしばあるようす。仮想化まわりでNGっぽい。

先駆者の皆さんの対応策を確認すると、効果的な対策としては下記2つとのこと。

1.  `Windowsの機能の有効化または無効化`から`Windowsハイパーバイザープラットフォーム`にチェックを付与してWindows再起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145371/76081a19-7c75-1a1d-7273-275b7d5c3769.png)

2. BIOSから仮想化を有効化する(本端末 Thinkpad A285では、BIOS表示のためにPC起動時に表示されるLenovoロゴのところでF1キー連打)

これにて仮想化機能が使用可能になり、だいたいこの時点でエミュレーター起動にこぎつけられるとのこと。

しかし今回は解決せず...

Androidエミュレータを起動しようとしてもこうなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145371/b74137db-922e-05b7-b210-1785743835ac.png)

今回は、VisualStudio上でのFlutterアプリ開発であるため、VsCode側からエミュレータ起動しようとするとまた別のエラーが表示される。

```
[ERR] The Android emulator exited with code -1073741515 during startup
[ERR] Android emulator stderr:
[ERR] Address these issues and try again.
```

どうやったか記憶にございません状態だが、私のメモのは下記のようなエラーも表示されたことがある。

```
Emulator terminated with exit code -1073741515
```

いずれもエラーコード`1073741515`により起動できないようす。

もう絶望だよ。

## 対処2. Androidエミュレータをコマンドラインから起動 ★うまくいった!!★

簡単に諦められもしないので、海外サイトを中心にググり散らかしていると、下記のStackOverflowのQに出会った。「Emulator: Process finished with exit code -1073741515 (0xC0000135)」というタイトルである。

https://stackoverflow.com/questions/62721513/emulator-process-finished-with-exit-code-1073741515-0xc0000135

そこには、「Androidエミュレータをコマンドラインから直接起動してみるとワンチャン上手く起動できるかもね」との回答あり。

早速試してみると、これがなんと上手くいったぞ！

```
cd C:\Users\{username}\AppData\Local\Android\Sdk\emulator\

emulator.exe -list-avds
```
Android SDKのemulatorフォルダに移動後、avds一覧を表示。

すでにAndroidエミュレータを作成済であれば `Pixel_8a_API_34` のようなエミュレータを得ることが出来る。

上記エミュレータ名を取得したら、
```
emulator.exe -avd Pixel_8a_API_34 -verbose -show-kernel
```
のようにコマンドを打つことでエミュレータが起動することを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145371/0fc6985a-e01c-4cbf-ae7e-6b4b300b3f74.png)

VsCodeの`Flutter: Select Device`で問題なくコマンドラインから起動したエミュレーターが表示され、`flutter run`すればアプリがエミュレータ上で起動することを確認。

情報がかなり少なく、調査に時間をかけてしまった...

なお、お気づきの方もいると思うが、残念ながら本件のもともとの原因は解消出来ていない。

「エミュレータを起動したい」というゴールは達成できているが、「4294967201」エラー等は解消出来ていない。もしクリアする方法をご存じの方がいたら是非にコメントを頂きたい。
Reactはじめました。

## 現状
自己紹介します！

・大学を卒業し、新卒で社内SEとして勤務（2年ちょっと）
・システム会社に転職し、派遣先の基幹システムの主に保守を担当（1年）
・プロジェクト移動し、開発案件に参画（1ヶ月）←今ココ
　
運用保守が多かったため、フロントエンドとバックエンド共に開発経験が乏しい...。
勉強しても実際に活かす業務がなく、モチベーションが保てず本も積読...。
構文が分かってデバッグで追うことはできるが、一から作れ！と言われるとう～ん...。

## 学習の動機
職場で開発の柱となっている先輩方を見て、4年目も中盤なのにやばい！自分何もできない！エンジニア名乗れない！変わらないと！と思わされたから。

## 目標
短期：自分がイメージしたものを滞りなく実装できる力をつける！
中期：価値のあるサービスを作る！
長期：自信を持ってよりレベルの高い環境に身を投じられる力をつける！

今後たくさん記事投稿していくつもりですので、同じような境遇の方もそうでない方も見てくださると嬉しいです...!

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
興味のある方は、ぜひホームページをのぞいてみてくださ！
▼▼▼

https://projisou.jp
Catalina.out (エラーMSG)の読み方

# Catalina.outとは
Tomcatサーバの標準出力とエラーログが記録されたファイル
Tomcat の起動や停止の際、Java アプリケーションからのメッセージがこのログに出力される
# 構造
* 日付と時刻：ログの記録が行われた日時
* ログのレベル：INFO、WARN、ERROR などがあり、それぞれ情報、警告、エラーレベルを示す
* メッセージ内容：エラーメッセージやスタックトレースなど

# エラーメッセージの解析
1. エラーメッセージと例外の確認
Catalina.outにエラーが出るときは通常、以下のような構造でエラーメッセージが記録される
```
[日付 時刻] [ERROR] クラス名 - エラーメッセージ
Exception in thread "main" java.lang.ExceptionType: 詳細なエラーメッセージ
    at パッケージ.クラス名.メソッド名(ファイル名.java:行番号)
    at パッケージ.他のクラス名.他のメソッド名(ファイル名.java:行番号)
Caused by: java.lang.CausedExceptionType: 原因に関する詳細メッセージ
    ... (続くスタックトレース)
```

* 最初の [ERROR] で始まる行に注目し、エラーがどこで発生したかを確認
* 次に例外の種類（ExceptionType 部分）とメッセージ内容（「詳細なエラーメッセージ」部分）を確認することで例外の種類で原因を絞り込むことができる
* 「Caused by」 がある場合、その下に「発生源の原因」が記載されているので最初の発生箇所から原因を探るのが効果的

2.スタックトレースの読み方
スタックトレースはエラーが発生した経緯を示す
最も上位にあるエントリが最新の実行部分で、末尾に近いエントリほどエラーの根本原因に近い場所を示す
* 行番号：各行の末尾に「ファイル名.java:行番号」のように記録されている箇所で、エラーの発生位置を特定できる
* クラス名とメソッド名：問題が発生したクラスやメソッドの情報から、どの処理が原因かを推測する
valueを複数持つ辞書を、より便利に作りたい

## 目次
- [はじめに](#はじめに)
- [namedtupleとは](#namedtupleとは)
- [辞書とnamedtupleを組み合わせる](#辞書とnamedtupleを組み合わせる)
- [まとめ](#まとめ)
- [最後に](#最後に)

## はじめに
　Pythonでプログラムを書いていて、辞書に複数のvalueを持たせたい場面があると思います。この際、```key:[value1, value2, ...]```とすることで解決可能ですが、リストの要素の順番を覚えておかなければなりません。これが少し不便に感じたので、リストの代わりに```namedtuple```を用いる方法をここで提案してみます。

## namedtupleとは
　```namedtuple```とは通常のタプルの機能に加えて、インデックス以外に要素の名前でアクセスが可能なタプルです。```collections.namedtuple```と```typing.NamedTuple```の2種類があります。どちらも標準ライブラリですが、```typing```モジュールの方は型に厳密という違いがあります。扱う型が決まっている場合はこちらを用いた方が便利です。今回は前者の方を使っていきます。
 
```namedtuple```について、こちらの記事に詳しく書いてありました。
[namedtupleで美しいpythonを書く！（翻訳）](https://qiita.com/Seny/items/add4d03876f505442136)

 ## 辞書とnamedtupleを組み合わせる
 ```python:test.py
 from collections import namedtuple
Fluits = namedtuple('Fluits', ['name', 'price'])
fluits = {
    '001':Fluits('リンゴ', 300),
    '002':Fluits('ブドウ', 1000),
    #ほかのフルーツ
}
fluit = fluits['001']
print(f'{fluit.name}は{fluit.price}円です')
```
 
 　辞書と```namedtuple```を組み合わせることで上記のように```dictionary[key].〇〇```という風にドットアクセスが可能になります。筆者はRPGの作成で、```magics['101'].MP```、 ```magics['101'].func```のように活用しています。使用感としては、リストを用いるよりも可読性が上がった感じがします。


　ちなみに```namedtuple```は通常のタプルを継承しているため、イミュータブルなオブジェクトです。よってデータの変更はサポートしていません。筆者はプログラムを読み込んだ際に一括で設定しているため、むしろイミュータブルなオブジェクトの方が都合が良いですが、データを書き換えたい場合もあるでしょう。
　その際は```namedtuple```ではなく、自作のクラスを用いれば、同じようなことが可能です。
```python:test.py
class Fluits:
    def __init__(self, name, price):
        self.name = name
        self.price = price
```
　この極めて簡単な構造のクラスはミュータブルなので、```namedtuple```の代わりに用いることでデータの変更に対応可能です。

 ## まとめ
 　辞書のvalueに```namedtuple```を用いることで、一つのキーに対して
  複数のドットアクセス可能なvalueを持たせることができ、可読性の向上が見込める。

## 最後に
　今回は辞書に複数のvalueを持たせる方法としてリストではなく```namedtuple```を用いる方法を提案してみました。メモリ使用効率や実行速度などは考慮していないので業務で使えるかは分かりませんが、個人でプログラムを書いている分には使える方法じゃないかなと思います。
UnJSとは?

UnJSは、サーバーサイドのJavaScript/TypeScript開発向けのツールやライブラリ群を提供するオープンソースプロジェクトで、特に**Nuxt.jsの開発者**が多く関わっています。以下、UnJSの特徴をいくつか紹介します。

### 1. 軽量で高速

UnJSのライブラリは、軽量であることを重視して設計されています。必要最小限の依存関係のみを使用し、ビルド速度やパフォーマンスに影響を与えないよう工夫されています。

### 2. モジュール志向で柔軟

UnJSの各ツールやライブラリは独立して利用可能であり、必要な機能を選んで取り入れることができます。そのため、Nuxt.jsやVue.js以外のプロジェクトにおいても柔軟に活用できます。

### 3. サーバーサイドとエッジコンピューティングに適した設計

UnJSのライブラリは、Node.jsだけでなく、エッジ環境（Cloudflare Workers、Vercel Edge Functionsなど）でも実行しやすい設計がされています。軽量なだけでなく、各プラットフォームの制限を考慮して最適化されています。

### 4. TypeScript対応

UnJSのライブラリは、TypeScriptで書かれており、型定義が充実しています。これにより、開発中に型チェックが可能となり、バグやエラーの発生率を低減できます。

### 5. 特定のニーズに応える多彩なライブラリ

UnJSには、多数の実用的なライブラリがあり、各ライブラリが特定の用途に焦点を当てて開発されています。たとえば、以下のようなものがあります。

- **ohmyfetch**：Nodeやブラウザで共通のAPIを使ってフェッチ処理を行えるライブラリ
- **unfetch**：軽量のfetch代替ライブラリ
- **defu**：オブジェクトの深いマージをシンプルに行うためのユーティリティ
- **h3**：サーバーレスAPIの構築をシンプルにするための軽量HTTPサーバーフレームワーク

### 6. エコシステムとの相性

UnJSのライブラリは、特にNuxtやVite、Vue.jsとの親和性が高く、これらのフレームワークやツールとシームレスに統合して利用できます。また、Evan YouをはじめとしたVue/Nuxtコミュニティからの支援も受けており、Vueエコシステムでの利用がしやすくなっています。

### 7. オープンソース・コミュニティドリブン

UnJSはオープンソースであり、コミュニティによってメンテナンス・改良が進められています。GitHub上で自由にライブラリのソースコードが確認できるほか、PRやIssueを通じてフィードバックが可能です。

---

UnJSは、サーバーサイドJavaScriptにおける効率的でモダンな開発を支援する便利なライブラリ集です。特にNuxt.jsと組み合わせることで、プロジェクトの生産性とパフォーマンスの向上が期待できます。
CGI (Common Gateway Interface) について

# CGI (Common Gateway Interface) について

## 概要

CGI（Common Gateway Interface）は、Webサーバーと外部プログラムを接続する仕組みで、ユーザーからのリクエストに応じて動的なコンテンツを生成するために使用されます。CGIプログラムは、PerlやPython、C、PHPなどの多くのプログラミング言語で書くことができ、フォーム入力などを処理し結果をWebページに反映させることが可能です。

## CGIの仕組み

CGIは以下の流れで動作します：

1. **リクエストの受け取り**：ユーザーがブラウザでリクエストを送信。
2. **WebサーバーからCGIプログラムへの呼び出し**：WebサーバーがCGIプログラムを実行。
3. **CGIプログラムによる処理**：リクエスト内容に基づいてデータの処理や計算を行う。
4. **レスポンスの返却**：CGIプログラムが結果をHTML形式で生成し、Webサーバーを介してユーザーに返す。

## CGIプログラムの例

### Perlスクリプト例

次の例では、Perlスクリプトを使って「Hello, World!」を表示します。

```perl
#!/usr/bin/perl
print "Content-Type: text/html\n\n";
print "<html><body>";
print "<h1>Hello, World!</h1>";
print "</body></html>";
```

このスクリプトでは、`Content-Type: text/html`で出力がHTMLであることをサーバーに伝え、ブラウザに表示します。

### Pythonスクリプト例

PythonでもCGIプログラムを作成できます。次の例では、「Hello, World!」を表示します。

```python
#!/usr/bin/python3
print("Content-Type: text/html")
print()
print("<html><body>")
print("<h1>Hello, World!</h1>")
print("</body></html>")
```

このスクリプトも同様に、HTML形式で出力されます。

### PHPスクリプト例

PHPを使ったCGIプログラムの例です。以下のスクリプトは、ユーザーの名前を受け取って表示します。

```php
<?php
$name = htmlspecialchars($_GET['name']);
echo "Content-Type: text/html\n\n";
echo "<html><body>";
echo "<h1>Hello, $name!</h1>";
echo "</body></html>";
?>
```

この例では、`$_GET['name']`でURLパラメータから名前を取得し、`htmlspecialchars()`関数でXSS攻撃を防ぎます。

## CGIと環境変数

CGIプログラムは、以下の環境変数を使ってリクエスト情報を取得できます：

- **`QUERY_STRING`**：URLクエリパラメータ（例：`?name=John&age=30`）。
- **`REQUEST_METHOD`**：リクエストのHTTPメソッド（GET、POSTなど）。
- **`CONTENT_TYPE`**：リクエストされたデータの形式（例：`application/x-www-form-urlencoded`）。
- **`REMOTE_ADDR`**：リクエスト元のIPアドレス。

### 環境変数を使った例

次に、Pythonで`QUERY_STRING`を使用してリクエストパラメータを取得する例です。

```python
#!/usr/bin/python3
import cgi
form = cgi.FieldStorage()
name = form.getvalue("name", "World")

print("Content-Type: text/html")
print()
print("<html><body>")
print(f"<h1>Hello, {name}!</h1>")
print("</body></html>")
```

この例では、URLに`?name=Alice`と指定すると、「Hello, Alice!」と表示されます。

## CGIの脆弱性とセキュリティ

CGIは、ユーザー入力に基づいて動作するため、不適切な処理を行うと脆弱性が発生しやすくなります。以下に代表的な脆弱性とその例を紹介します。

### 1. コマンドインジェクション

ユーザー入力を適切にフィルタリングしないと、シェルコマンドを注入される危険性があります。次の例では、悪意あるユーザーが`name`パラメータにシェルコマンドを入れることでシステムが攻撃される可能性があります。

#### 脆弱な例

```perl
#!/usr/bin/perl
my $name = $ENV{'QUERY_STRING'};
system("echo Hello, $name");
```

このスクリプトは、`name`に`; rm -rf /`のようなコマンドが含まれていると、サーバーがそのコマンドを実行してしまい、致命的な被害を引き起こす可能性があります。

### 2. クロスサイトスクリプティング（XSS）

CGIプログラムの出力にユーザー入力をそのまま反映すると、XSS攻撃を受ける可能性があります。ユーザーがスクリプトを仕込むと、他のユーザーのブラウザ上で悪意あるコードが実行される危険があります。

#### 脆弱な例

```perl
#!/usr/bin/perl
use CGI;
my $query = CGI->new;
my $message = $query->param('message');

print "Content-Type: text/html\n\n";
print "<html><body>";
print "<p>$message</p>";  # 危険な出力
print "</body></html>";
```

このスクリプトでは、`message`に`<script>alert('XSS');</script>`を含めると、他のユーザーがこのページを開いた際にスクリプトが実行されてしまいます。

### セキュリティ対策

- **入力値のフィルタリング**：特殊文字やコマンドをエスケープ処理し、不正な入力が実行されないようにします。
- **出力のエスケープ**：HTMLやJavaScriptに直接挿入する前にエスケープし、XSSを防ぎます。
- **使用する言語・ライブラリの更新**：最新バージョンを使用し、脆弱性を減らします。

## まとめ

CGIは、Webサーバーと外部プログラムをつなぎ、動的なコンテンツ生成を可能にする便利な技術ですが、適切なセキュリティ対策を行わないと、脆弱性を悪用される危険があります。コマンドインジェクションやXSSなどの代表的な脆弱性を防ぐためには、入力値のフィルタリングと出力のエスケープ処理が必須です。これらを意識して、安心してCGIを活用しましょう。
Form_withとは！

form_withメソッドは、Railsで使うフォームの作成方法。これを使うとデータを入力する画面（フォーム）を簡単に作成できます。

たとえば、「商品を購入する」や「新しいユーザーを登録する」などの機能がある場合、それぞれのデータを入力するフォームが必要です。form_withメソッドは、このようなフォームを作成するのに便利です。

基本の使い方
```ruby
<%= form_with model: @user do |form| %>
  <%= form.text_field :nickname %>
  <%= form.submit "登録" %>
<% end %>
```
model: @user の部分で、どのデータ（この場合はユーザー）を扱うフォームか指定します。
form.text_field :nickname は「ニックネーム」を入力するための箱を作ります。
form.submit "登録" は送信ボタンを作ります。
このように、form_withを使うと、HTMLを直接書かなくてもRailsが自動で適切なフォームを生成してくれます。

form_withでpathを記述するかどうかは、フォームがどこに送信されるかによります。

1. pathを書かない場合
form_with(model: @user)のように書いた場合、Railsは自動的にフォームの送信先を判断します。例えば、新規ユーザー登録ページで@userが新しいユーザーの場合、フォーム送信先はusers#create（ユーザー登録を行うアクション）になります。また、ユーザー情報を編集するページでは、送信先がusers#updateになります。このように、モデルを使うことで、Railsが自動的に適切なパスを選んでくれます。

2. pathを書く場合
明確なURLに送信したい場合や、モデルを使わないときはpathを指定します。たとえば、ログインフォームなど特定のURLに送信したいときはform_with(url: login_path)のようにurlオプションを使って送信先を指定します。

まとめ

pathを書かない → Railsが自動で送信先を決めてくれる。
pathを書く → 自分で送信先を指定したいときに使う。
このように、フォームが「新規作成」か「編集」かを自動で判断してくれるか、自分で送信先を決めたいかによって使い分けます。
enumによって自動生成されるメソッド

## 初めに

疑問に思ったことや上手くいかなかったことのアウトプットをしています。
自分なりの理解でアウトプットしていきます。初学者なので誤りもあると思います。
その際はご指摘いただけると幸いです。

### enumを使うときはモデルに下記のように書きます
```:example.rb
enum state { aaa:0, bbb:1, ccc:3 }
```
上記のようにコードを書くとメソッドが自動生成されます。

### 自動生成されるメソッド
```
example.aaa? #現在のstateがaaaか確認するメソッド
```

```
example.aaa! #stateをaaaに変更するメソッド
```
```
example.state #現在のstateを取得するメソッド
```
```
example.state = stateを変更するメソッド
```
【JavaScript】window.open()でnoopenerやnoreferrerを設定する方法

以下のように記述することで`window.open()`に`noopener`と`noreferrer`を設定できます。

```js
window.open("http://example.com", "_blank", "noreferrer")
```

`noreferrer`しか記述していませんが自動的に`noopener`も適用されます。

https://developer.mozilla.org/ja/docs/Web/API/Window/open#noreferrer