OmniAICreator/Qiita-1.07M huggingface dataset:
YewでWebアプリ作成に入門した

# 背景
昨今話題になっている”Rust”を勉強していた中で、何かWebアプリを作りたいなと考えていたところ、”Yew”がいい感じらしいので、Yewで簡単なWebアプリを作成しました。

# 使用技術
* Rust
* Yew
* HTML
* Tailwind css ※浅学もいいところでテンプレをコピペしてます

# 作成したアプリ
健康診断が近かったので、BMI計算アプリを作成しました。完成形は下図です。
身長、体重を入力して、「calc」ボタンを押すとBMIが計算され表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662936/1fc3ed18-7ded-6d16-4875-055ce25eaa9d.png)

# ソースコード
コードトレースをするうえで邪魔なので、CSSを除去したコードを下記に記載します。
また、コーディングで気にしたところを記載しておきます

* calcボタンの押下など、なにかアクションをしても、入力された身長、体重と過去BMI計算値は保持したいので、Stateで状態管理する
* 数値以外が入力されたときの分岐をRustで書かないために、HTMLで「input type="number"」とし、数値入力に限定させる


```rust:main.rs
//BMIを計算して表示する
use yew::prelude::*;
use web_sys::{window, wasm_bindgen::JsCast, HtmlInputElement};

//idで値を取得する関数を定義する(JSでいうところのgetElementById)
fn get_value_by_id(id: &str) -> String {
    window().unwrap()
        .document().unwrap()
        .get_element_by_id(id).unwrap()
        .dyn_ref::<HtmlInputElement>().unwrap()
        .value()
}

//BMIを計算する関数を定義する
fn calc_bmi(height: f64, weight: f64) -> f64 {
    let height_m = height / 100.0;
    let bmi = weight / height_m.powf(2.0);
    return bmi;
}



#[function_component(App)]
fn app() -> Html {

    //bmiのステートを管理する
    let bmi = use_state(|| 0.0_f64);
    let element_height = use_state(|| 0.0_f64);
    let element_weight = use_state(|| 0.0_f64);

    //「calc」ボタンを押したら、コンソールに身長、体重を表示させる
    let click_button = {
        let bmi = bmi.clone();
        let element_height = element_height.clone();
        let element_weight = element_weight.clone();

        move |_| {
            let height_by_element = get_value_by_id("height");
            let weight_by_element = get_value_by_id("weight");
            let result = calc_bmi(height_by_element.parse().unwrap(),
                                  weight_by_element.parse().unwrap());
            element_height.set(height_by_element.parse().unwrap());
            element_weight.set(weight_by_element.parse().unwrap());
            bmi.set(result);
        }

    };

    html! {
        <>
            <h1>{ "YOUR BMI" }</h1>
            <form>
                <label for="height">{"height:"}</label>
                    <input type="number" step="0.01" id="height" value={format!("{}",*element_height)}/>
                <label for="weight">{"weight:"}</label>
                    <input type="number" step="0.01" id="weight" value={format!("{}",*element_weight)}/>
                <button type="button" onclick={ click_button }>{"calc"}</button>
            </form>
            <div>{ format!("BMI : {:.2}", *bmi) }</div>
        </>
    }
}

fn main() {
    yew::Renderer::<App>::new().render();
}
```


# 終わりに
今回でHTML要素の値を取得、更新、コールバックの作成など、基本的なWebアプリの仕組みをRustで書く方法をキャッチアップできました。まだまだRust言語、私自身ともに発展途上なので、知見を深めていければと思います。
Javaで「文字列の全体がパターンとマッチするか調べる(Matcher.matches)」の動作を確認してみた

# 概要

Javaで「文字列の全体がパターンとマッチするか調べる(Matcher.matches)」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/regex/index3.html

# 実装

以下のファイルを作成しました。
```JSample3_1.java
import java.util.regex.*;

class JSample3_1{
  public static void main(String[] args){
    String regex = "S.*t";
    Pattern p = Pattern.compile(regex);

    Matcher m1 = p.matcher("JavaScript");
    System.out.println(m1.matches());

    Matcher m2 = p.matcher("Script");
    System.out.println(m2.matches());

    Matcher m3 = p.matcher("Set");
    System.out.println(m3.matches());
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample3_1.java 
$ java JSample3_1 
false
true
true
```

# まとめ

何かの役に立てばと。
【Django】MVT Pattern

# 1\. Django
Django を一言で表すと、Python で構成された Web Application Framework である。Framework が「枠組み」「骨組み」という意味だから、まとめると、Django は Python で Web Application を作成する際に使用できる Framework (枠組み) ということになる。

# 2\. MVT Pattern
Django は、MVT Pattern を採用している。MVT は、それぞれ **Model**、**Template**、**View** を意味する。これらの関係性を図で表すと以下のような形になる。

![Screenshot 2024-08-01 at 22.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841504/12559d3d-0967-3b6b-0413-b2c43d16705e.png)

### 2-1\. Model
Model は、Django Framwork におけるデータベースのテーブルを Python クラスで表現するものである。つまり、Model モジュールを利用して models.py にクラスを作成し、その属性を記入すると、データベース内の一つのテーブルと同じ形式になる。

### 2-2\. Template
Template は、ユーザが直接アクセスできる html のようなページのことで、Web Application におけるコンテンツ表示機能を担当する部分となる。Template には、主に以下のような機能がある。
- コンテンツを表示する。
- ユーザからの request を受け付ける。
- ユーザの request に対する response を表示する。

### 2-3\. View
Template と Model の間でデータの流れをコントロールする役割を担当する。Template から渡されたユーザの request を受け付け、受け付けた request の内容に応じて Model に対してデータの操作 (DB へのデータ登録、更新、削除、参照など) を依頼する。その後、表示させたいデータを目的に合う形式に加工したうえで、Template へ渡す。
※ MVC モデルの V (View) とは異なるため、混同しないように注意する必要がある。

# 3\. Front-End との通信
![Screenshot 2024-08-01 at 22.02.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841504/5dca1a2f-c3e4-876a-fdb8-9742a3a62e6d.png)

### 3-1\. URLs
Client からの request は Front-End を通って urls.py に渡される。urls.py では受け取った URL に基づいて、どの View 関数又は、クラスを呼び出すかを決める。この作業は URL パターンマッチングによって行われる。

<details><summary> Sample code</summary>

```python:urls.py
from django.urls import path
from .views import my_view

urlpatterns = [
    path('my-url/', my_view, name='my_view'),
]
```
</details>

### 3-2\. Views
Views では、URL パターンにマッチする HTTP request を受け取った後、必要な処理を行った上で request を Front-End に返す。その際に、Serializer を使ってデータをシリアル化、又は、逆シリアル化することもできる。

<details><summary> Sample code</summary>

```python:views.py
from django.http import JsonResponse
from .models import MyModel
from .serializers import MyModelSerializer

def my_view(request):
    if request.method == 'GET':
        objects = MyModel.objects.all()
        serializer = MyModelSerializer(objects, many=True)
        return JsonResponse(serializer.data, safe=False)
```
</details>

### 3-3\. Serializer
Serializer は、Django REST framework で提供される機能で、データモデルの object を JSON 形式に変換したり、逆に、JSON 形式をデータモデルの object に変換したりする。

<details><summary> Sample code</summary>

```python:serializers.py
from rest_framework import serializers
from .models import MyModel

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'
```
</details>

### 3-4\. Model
Model は、Django で Database table を定義するのに使用される。各 Model の class は Database の table に該当し、class の field は table の column を表す。また、Model は Database との CRUD (Create, Read, Update, Delete) 作業を行う method を含める。

<details><summary> Sample code</summary>

```python:models.py
from django.db import models

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name
```
</details>
日本のインボイス制度に対応してGitHubが実質値上げ

# Githubからメール

実質値上げか

![スクリーンショット 2024-08-02 3.43.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/648545/94fb8a08-f427-2318-7cce-7d8a47bd27db.png)

Google翻訳：

> GitHubのお客様へ
> 
> 2024年10月1日より、日本の税法に準拠するため、クレジットカードまたはPayPalアカウントでお支払いいただく日本のセルフサービス顧客から消費税（JCT）を徴収することになりましたのでお知らせいたします。日本でセルフサービスで有料サービスを利用する場合は、請求書が更新され、GitHub Inc. の登録番号 (T4700150079306) と、米ドルと日本円での 10% の消費税額が表示されます。
> 
> お買い上げくださってありがとうございます、
> 
> GitHub チーム
【supabase】「レコードの削除中にエラーが発生しました」の対処法

# はじめに

Supabaseのテーブルにあるデータを削除するバッチファイルを作成し、ファイル実行時に一括で削除しようとしたところ下記のエラーが発生しました。

```
レコードの削除中にエラーが発生しました: {
 code: '21000',
 details: null,
 hint: null,
 message: 'DELETE requires a WHERE clause'
}
```
# 問題

エラーメッセージの「DELETE requires a WHERE clause」とあるようにWHERE句がないことが指摘されています。

調べてみると、今回使用しているpostgres SQLにはテーブルデータの安全性を確保するためにWHERE句が使用できないような機能がデフォルトでされている可能性があり、そのことがエラーの原因となっているようでした。この機能自体は意図していない削除が行われないような安全対策のようです。

# 解決法

今回は明示的にWHERE句を要求することで解決することできました。

以下手順です。

まず、削除用のPostgreSQL関数を作成します。

SupabaseのSQLエディタを開いて、以下のクエリをテーブル名を変更して実行します。

```SQL
CREATE OR REPLACE FUNCTION delete_all_records()
RETURNS void LANGUAGE plpgsql AS $$
BEGIN
  DELETE FROM テーブル名 WHERE true;
END;
$$;
```

その後、バッチファイルを下記のように設定します。

```Typescript
import { supabase } from "../src/utils/supabase";

async function cleanupRecords() {
  try {
    console.log("クリーンアップ処理を開始します。");

    const { error } = await supabase.rpc('delete_all_records');

    if (error) {
      console.error("レコードの削除中にエラーが発生しました:", error);
    } else {
      console.log("すべてのレコードが削除されました。");
    }

    console.log("クリーンアップ処理が完了しました。");
  } catch (error) {
    console.error("クリーンアップ処理中にエラーが発生しました:", error);
    process.exit(1);
  }
}

cleanupRecords().catch(error => {
  console.error("予期せぬエラーが発生しました:", error);
  process.exit(1);
});

```

`const { error } = await supabase.rpc('delete_all_records');`で使用しているrpc関数はデータベース上で定義された関数を呼び出すものになります。
今回はdelete_all_records()を上記で作成したものを呼び出して実行をしています。

上記を実行することでエラーの発生がなくなり、指定のテーブルからデータを削除することができました。

# おわりに
今回はエラーの原因はすぐにわかったのですが、解決法があまりなく解消までに時間がかかりましたが、新しくデータベース上で関数定義する方法を学ぶことができました。
同じようなエラーが出た方の参考になれば幸いです。
Error: supabaseUrl is required.が出た時に確認すること

# はじめに
supabaseを利用したアプリをgithubActionsで自動デプロイ設定する際に下記のエラーが出続けていました。
```
Error: supabaseUrl is required.
```

# 問題

これはsupabaseのurlやsupabase anon keyが取得できない時に発生するエラーなのですが、通常はgithubのSettings > Secrets and variables > ActionsからRepository secretsに値を設定しておくことでエラーを回避することができます。

今回は、Repository secretsに値を設定をしていても、値が取れないとのエラーが出続けていました。

# 解決法

今回は、ワークフローの権限設定を変更することで解決ができました。

下記が設定方法です。
①Githubのリポジトリセッティングのページへいき、左のメニューから、Actions>Generalを選択します。
![スクリーンショット 2024-07-31 18.36.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3825671/ebbf64ae-f9bd-5b1c-d0b3-25a85112aa87.png)

②ページ下にスクロールして、Workflow permissionsが「Read Repository contents and packages permissions」にチェックが入っているか確認。もしチェックが入っていたら、その上の「Read and write permissions」にチェックを入れてSaveボタンをクリックし、変更を保存します。

![スクリーンショット 2024-07-31 18.36.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3825671/063ef79e-89e2-0c53-6612-05f72e91a46f.png)

以上でワークフローの権限設定を変更することができました。

「Read-only」権限ではワークフローを実行する際にリポジトリ内を読み取ることができますが、Repository secretsなどの機密情報へのアクセス権が制限されることがあるみたいです。

# おわりに
同じエラーが出続けて何度もRepository secretsに値が設定されているか確認していましたが、そもそもの読み取り設定ができてなかったためのエラーでした。
同じ事象が発生する方は事前に設定を確認することをおすすめします。
SQLServerでJSONの操作をする

最近業務でSQLServerのJSONデータを操作することがありましたので、備忘録代わりに残しておきます。

なお、構成や表記など見づらいかもしれませんが、
初投稿なのでご容赦ください。精進します。

参考にしたページは [参考ページ](#参考ページ) 参照

### 環境
Microsoft SQL Server 2022 - 16.0.1121.4
互換レベル160

#### 使用テーブルの作成

```sql
CREATE TABLE emp_data (
    employee_id INT PRIMARY KEY,
    employee_data NVARCHAR(MAX) -- JSONデータを格納
);

--データ投入
INSERT INTO emp_data (employee_id, employee_data)
VALUES 
(1, N'{
    "name": "Taro",
    "age": 30,
    "skills": ["SQL", "C#", "Azure"],
    "address": {
        "city": "Osaka",
        "prefecture": "Osaka"
    }
}'),
(2, N'{
    "name": "Jiro",
    "age": 25,
    "skills": ["JavaScript", "HTML", "CSS"],
    "address": {
        "city": "Kobe",
        "prefecture": "Hyogo"
    }
}');
```

:::note
SQLServer2022ではJSON型の指定ができないので、NVARCHARを利用しています。
入るデータを厳密にJSONにしたいのであれば、CHECK制約で実現できます。

```sql
ALTER TABLE emp_data
ADD CONSTRAINT chk_employee_data CHECK (
        ISJSON(employee_data) = 1
    );
```
[ISJSON](#データ) : 文字列に有効な JSON が含まれているかどうかをテストします。
:::

#### データ

|employee_id|employee_data|
|--|--|
|1|{    "name": "Taro",    "age": 30,    "skills": ["SQL", "C#", "Azure"],    "address": {        "city": "Osaka",        "prefecture": "Osaka"    }}|
|2|{    "name": "Jiro",    "age": 25,    "skills": ["JavaScript", "HTML", "CSS"],    "address": {        "city": "Kobe",        "prefecture": "Hyogo"    }}|


### JSONデータの追加
#### JSONデータの階層追加
既存のJSONデータに新しい階層構造を追加する例です。
```sql:階層の追加
--追加したい値を一度出して
DECLARE @json_employee_data NVARCHAR(MAX) =
    (SELECT employee_data FROM emp_data WHERE employee_id = 1);

-- contact を追加して
DECLARE @json_inserted NVARCHAR(MAX) =
    JSON_MODIFY(@json_employee_data,'append $.contact', JSON_QUERY('{"phone" : "080-1234-5678","email": "taro@example.foo" }')
);

--データ上書き
UPDATE emp_data
SET employee_data = @json_inserted
WHERE employee_id = 1;
```

:::note warn
JSON_MODIFYは文字列をプレーンテキストとして渡すため、
直接記載すると追加後の値にエスケープ文字(\\)が入ってしまいます。

```sql:ダブルクォーテーションにエスケープ文字が入る例
UPDATE emp_data
SET employee_data = JSON_MODIFY(employee_data,
                                'append $.contact', 
                                '{"phone": "080-1234-5678",
                                  "email": "taro@example.com"}'
                    )
WHERE employee_id = 1;
```
:::

#### JSONデータの配列への追加
既存の配列に新しい要素を追加する例です。
```sql:配列の追加
-- Skillに "Python" を追加
UPDATE emp_data
SET employee_data = JSON_MODIFY(employee_data, 'append $.skills', 'Python')
WHERE employee_id = 1;
```

### JSONデータの更新
#### JSONデータの要素更新
配列内の特定の要素を更新する例です。
```sql:要素の更新
DECLARE @newSkill NVARCHAR(100) = 'TypeScript';

-- JavaScript → TypeScript に変更
UPDATE emp_data
SET employee_data = JSON_MODIFY(employee_data, '$.skills[0]', @newSkill)
WHERE employee_id = 2;
```

### JSONデータの削除
#### JSONデータの階層削除
JSONデータ内の特定の階層を削除する例です。
```sql:階層の削除
UPDATE emp_data
SET employee_data = JSON_MODIFY(employee_data, '$.address', NULL)
WHERE employee_id = 1;
```


### 参考ページ

https://learn.microsoft.com/ja-jp/sql/t-sql/functions/json-functions-transact-sql?view=sql-server-ver16

https://learn.microsoft.com/ja-jp/sql/relational-databases/json/json-data-sql-server?view=sql-server-ver16
新しい技術を学ぶときに

ITエンジニアとなって久しいが、新しい技術を学ぼうとした際にそのきっかけとなるのは開発案件だ。
どの案件が多いとか、どこが人手不足だとか。
ここで重要となるのは使い方で、ひたすら経歴書の充実のために入門サイトを探しては自分のPCにインストールしてサイトのコードやコマンドをコピペして、その動きを見る。
これがずっと続いてきた。

しかしこれは開発者、特にコードを書く人間にとって重要だが、特に基本設計や要件を決めるときにカギとなるのは、その技術を選定するための理由だ。
その技術が生まれた背景や理由。
これを知っておかないと、どうやって開発するか決められない。

まずは知りたい技術のwikipediaを見て、その生まれた背景や理由を理解する。
他のサイトや本を見ることも大いに役立つだろう。
そしてその背景や理由についての知識が増えれば、新しい技術を探すときのきっかけになるかもしれない。
1人のITエンジニアとして心に留めておきたい。
Linuxの基本的なコマンドガイド

# Linuxの基本的なコマンドガイド

## 1. ファイルとディレクトリの操作

### 1.1 `ls`
ディレクトリ内のファイルとフォルダを一覧表示します。
```
ls
```
オプション:
- `-l`: 詳細情報を表示
- `-a`: 隠しファイルも表示

### 1.2 `cd`
ディレクトリを変更します。
```
cd /path/to/directory
```
例:
```
cd /home/user
```

### 1.3 `pwd`
現在の作業ディレクトリのパスを表示します。
```
pwd
```

### 1.4 `mkdir`
新しいディレクトリを作成します。
```
mkdir new_directory
```

### 1.5 `rmdir`
空のディレクトリを削除します。
```
rmdir directory_name
```

### 1.6 `rm`
ファイルやディレクトリを削除します。ディレクトリを削除する場合は、`-r`オプションを使用します。
```
rm filename
rm -r directory_name
```

### 1.7 `cp`
ファイルやディレクトリをコピーします。ディレクトリをコピーする場合は、`-r`オプションを使用します。
```
cp source_file destination
cp -r source_directory destination
```

### 1.8 `mv`
ファイルやディレクトリを移動またはリネームします。
```
mv old_name new_name
```

## 2. ファイルの表示と編集

### 2.1 `cat`
ファイルの内容を表示します。
```
cat filename
```

### 2.2 `less`
ファイルの内容をページ単位で表示します。スクロールして閲覧できます。
```
less filename
```

### 2.3 `head` と `tail`
ファイルの先頭（head）または末尾（tail）の行を表示します。
```
head -n 10 filename
tail -n 10 filename
```
`-n`オプションで表示する行数を指定します。

### 2.4 `nano` と `vim`
コマンドライン上でテキストファイルを編集するためのエディタです。
```
nano filename
vim filename
```

## 3. システム情報とプロセス管理

### 3.1 `top`
システムのリアルタイムなリソース使用状況を表示します。
```
top
```

### 3.2 `ps`
現在実行中のプロセスのリストを表示します。
```
ps aux
```

### 3.3 `kill`
プロセスを終了させます。`ps`コマンドなどでプロセスID（PID）を確認して使用します。
```
kill PID
```

### 3.4 `df`
ディスクの使用状況を表示します。
```
df -h
```
`-h`オプションで、人間に読みやすい形式で表示します。

### 3.5 `free`
メモリの使用状況を表示します。
```
free -h
```

## 4. ユーザー管理とパーミッション

### 4.1 `chmod`
ファイルやディレクトリのパーミッションを変更します。
```
chmod 755 filename
```

### 4.2 `chown`
ファイルやディレクトリの所有者を変更します。
```
chown user:group filename
```

## 5. ネットワーク関連

### 5.1 `ifconfig`
ネットワークインターフェースの設定と状態を表示します。
```
ifconfig
```

### 5.2 `ping`
指定したホストにICMPエコーリクエストを送信し、接続を確認します。
```
ping hostname_or_ip
```

### 5.3 `curl` と `wget`
ウェブからデータを取得するためのコマンドです。
```
curl http://example.com
wget http://example.com
```

## 6. パッケージ管理

### 6.1 `apt`
Debian系のディストリビューション（Ubuntuなど）でパッケージを管理するコマンドです。
```
sudo apt update
sudo apt upgrade
sudo apt install package_name
```

## 7. ヘルプとドキュメント

### 7.1 `man`
コマンドのマニュアルページを表示します。
```
man command_name
```

### 7.2 `--help`
コマンドの使用方法を表示します。
```
command_name --help
```

## まとめ
これらのコマンドは、Linuxシステムの基本操作を理解するための第一歩です。さらに高度なタスクやシステム管理には、これらのコマンドを応用していくことが求められます。習得したコマンドを実際に使いながら、Linuxのシステム操作に慣れていきましょう。
akaSearch: Microsoftのaka.msリンクをお手軽検索できるサイトの紹介

# akaSearch
つい先日､[akaSearch](https://akasearch.net/)という便利なサイトを発見してしまいましたので備忘も兼ねてシェアさせてください｡
Microsoftのaka.msリンクを覚えるのに苦労していませんか？akaSearchはそんな悩みを解決するための素晴らしいツールです。このサイトはコミュニティの力で作られたリンク集で、簡単に必要なリンクを見つけることができます。

# そもそもaka.msとは?
さっきから､aka.msを連呼してしまいましたが､ふんわり説明しますと､aka.msというのは、Microsoftが利用している短縮URLのドメインのことになります｡結構､aka.ms系のリンクは､諸々の場面で提供される場面が個人的には多くあるものの､その場限りのURLみたいになってしまい､一箇所でまとめられていなかったり､検索できないといった課題があったりして､メモもめんどくさいなーとか思ったりしてました｡

# akaSearchの特徴
## 簡単にリンク検索
akaSearchは直感的で使いやすいインターフェースを持っています。例えば、「Visual Studio Code」と検索すれば、関連するaka.msリンクがすぐに見つかります。

## リンクの整理が簡単
自分の重要なaka.msリンクをブックマークして、必要なときにすぐにアクセスできるように整理できます。リンク管理が効率的になり、時間を節約できます。

## 視覚的にわかりやすい
akaSearchのインターフェースは視覚的にわかりやすく、誰でも簡単に操作できます。アイコンやスクリーンショットを活用して、リンクの内容を直感的に確認できます。


# 具体的な使用例
例えば、AIエンジニアがAIに関する設定リンクを探す場合、akaSearchで｢AI」と入力するだけで、関連するリンクがすべて表示されます。また、新しいAI関連のリンクを見つけたら、すぐにコミュニティに共有して他のユーザーも利用できるようになります。

# 結論
Microsoftのaka.msリンク管理に困っているなら、ぜひakaSearchを試してみてください。このツールはリンク管理を簡単にし、効率的に作業を進めるための強力なサポートを提供します。あなたもakaSearchを使って、便利なリンク管理を始めましょう！
【GAS】フォームの回答を取得する"namedValues"がundefined

## どんなエラー？
フォーム送信時イベントをトリガーに設定した関数で、イベントオブジェクト（`e`）を受け取り、送信されたフォームのデータを取得する`e.namedValues`を使っていると、
以下のようなエラーがログに...
`TypeError: Cannot read properties of undefined (reading 'namedValues')`

### 「未定義のプロパティである`namedValues`を読み取ることができないよ」
と言われてしまっています。どうやら今回のイベントオブジェクト（`e`）は`namedValues`というプロパティを持ち合わせていないようです。

そんなバカな...
前にGASを書いたときは使えたのに！？

## Googleフォームか、スプレッドシートか
GASでは関数に対してトリガーを設定しますね。その際には、イベントのソースを選択できます。
![スクリーンショット 2024-08-01 10.53.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676797/960b1a64-42f3-5a91-b5e8-23c5117dacdc.png)

- フォームに連携させたApps Scriptなら **「フォームから」**
- スプレッドシートに連携させたApps Scriptなら **「スプレッドシートから」** 

を選択しましょう。

:::note
#### ここで、スプレッドシートなら **`e.namedValues`** （`e.values`）が使用可能で、フォームなら **`e.response.getItemResponses()`** が使用可能となります。
:::

どのGoogleサービスと連携しているかでイベントオブジェクトのプロパティとそれに対応するメソッドも変わってくるということを学びました。

## 終わりに
それぞれのメソッドについては以下の記事を参考にしましたので皆さんもぜひご一読ください！

https://zenn.dev/gas/articles/8cb18b31507dcf
Ubuntu Serverのsshd_configデフォルト設定ガイド

# Ubuntu Serverのsshd_configデフォルト設定ガイド

## 概要
`/etc/ssh/sshd_config`は、SSHデーモン（`sshd`）の設定ファイルです。このファイルを編集することで、SSH接続の挙動やセキュリティ設定をカスタマイズできます。Ubuntu Serverでは、デフォルトで以下のような設定がされています。

## 主なデフォルト設定項目

### 1. Port
デフォルトではSSH接続は22番ポートを使用します。この設定は以下のように記述されています。
```
#Port 22
```

コメントアウトされている場合は22がデフォルトで使用されますが、ポートを変更する際はコメントを外し、変更したいポート番号を指定します。

### 2. PermitRootLogin
デフォルトでは、ルートユーザーでの直接ログインは許可されています。これを無効にすることで、セキュリティを向上させることができます。

```
PermitRootLogin prohibit-password
```

この設定では、ルートユーザーはパスワードでのログインが禁止され、SSHキー認証が必要となります。

### 3. PubkeyAuthentication
公開鍵認証がデフォルトで有効になっています。これにより、公開鍵を使った安全な認証が可能です。

```
PubkeyAuthentication yes
```

### 4. PasswordAuthentication
デフォルトでは、パスワード認証が許可されています。セキュリティ強化のために、公開鍵認証のみを使用する場合は、以下のように設定します。

```
PasswordAuthentication yes
```

これを`no`に設定することで、パスワード認証を無効化できます。

また、これを`no`にしても反映されない場合はこちらをお試しください。

https://qiita.com/YukiTetsuka/items/a220aa0290642ba5c676

### 5. ChallengeResponseAuthentication
チャレンジレスポンス認証は、デフォルトで無効になっています。これを有効にすると、パスワード以外の認証方法（例: Google Authenticatorなど）を追加できます。

```
ChallengeResponseAuthentication no
```

### 6. UsePAM
PAM (Pluggable Authentication Modules) を使用して、セッション管理や制限を行います。デフォルトで有効です。

```
UsePAM yes
```

### 7. X11Forwarding
X11フォワーディングを有効にすることで、リモートでグラフィカルアプリケーションを実行できます。デフォルトで無効です。

```
X11Forwarding no
```

### 8. AllowTcpForwarding
TCPフォワーディングを許可するかどうかを設定します。デフォルトでは有効です。

```
AllowTcpForwarding yes
```


## 設定の反映
`sshd_config`ファイルを編集した後、SSHデーモンを再起動する必要があります。

```bash
sudo systemctl restart sshd
```

## まとめ
デフォルトの`sshd_config`設定は、Ubuntu Serverでの基本的なSSH接続を提供しますが、セキュリティ強化や機能追加のために適宜設定を変更することが推奨されます。特に、パスワード認証の無効化やルートログインの禁止などは基本的なセキュリティ対策です。SSHの設定はシステムの安全性に直結するため、適切な設定を行うことが重要です。
プログラミング学習者のためのファイル整理整頓術

# 導入

この記事では、ローカルPCに蓄積したソースコードなどを適切に整理・整頓し必要に応じていつでも活用するため、プログラミング学習者が学び始めから現在にわたって使用できるような方法について議論します。環境はWindowsを前提にしていますが、Mac, Linuxユーザでも活用できる内容となっています。

# 要約

私が実践しているディレクトリ構成を下記に示します。

```
.
├─Practice
│  ├─tutorial-1
│  ├─tutorial-2
│  └─...
├─MyCode
│  ├─my-project-1
│  ├─my-project-2
│  └─...
├─GitHub
│  ├─repository-1
│  ├─repository-2
│  └─...
└─Documents
   ├─books
   ├─cheetcheets
   └─LaTeX
```
まずホームディレクトリ (Windowsの場合は `C:\Users\<user>\`, Linuxの場合は `/home/<user>/`) の直下に `Practice`, `MyCode`, `GitHub`, `Documents` というディレクトリを作成します。それぞれのディレクトリの中に、役割に応じてソースコードなどを保存します。

次に、各ディレクトリの詳細について説明します。

# Practice ディレクトリ

`Practice` ディレクトリは、書籍やWeb記事などでプログラミングを学習するときに手本として示されたものを書き写したソースコードを保存する場所です。

ここで私は必ず学習内容ごとに新しいディレクトリを `Practice` ディレクトリ直下に作成するようにしています。例えばDjangoのチュートリアルを学習する場合は `django-tutorial`, 「実践機械学習」のような書籍を学習する場合は `hands-on-ml` というディレクトリを作り、書き写す・実行するソースコードはその中だけで完結させるようにします。

# MyCode ディレクトリ

`MyCode` ディレクトリには、学習した内容をもとに自分で考えた (著作権が自分にある) プログラムのソースコードを保存します。ここでも前節と同様に、たとえ1ファイルで済むような簡単なプログラムでも `MyCode` 直下に新しくディレクトリを作成し、そのワークスペースで作業します。なぜなら、最初は1ファイルだけだと思っていても、アイデアが膨らんだ結果複数ファイルに分割することが必要だったり、そのプロジェクトをGitで管理したくなる可能性があるからです。

# GitHub ディレクトリ

`GitHub` ディレクトリには、GitHub上に公開されている使用してみたいソースコードや、共同開発を行っているリポジトリを置きます。GitHubからダウンロードしたものはすべてここに置くと決めることで、ソースコードの出所をすぐに判断することができます。

ディレクトリ名 (リポジトリ名) を衝突させたくない場合は、自分が所属しているOrganization名などを接尾辞にしたディレクトリ (`GitHubOrgName` など) を作ります。それを `GitHub` と同じ階層に置き分けて管理するとよいです。

# Documents ディレクトリ

`Documents` ディレクトリには、ソースコードではなく文字通り文書全般を保存します。保存するものの例としては、クリエイティブ・コモンズ・ライセンスで提供されているインターネット上の書籍や自分で購入したDRMフリーの電子書籍、ソフトウェアのキーボードショートカット、ライブラリのチートシートなどが挙げられます。私は `Documents` 直下に `books`, `cheatcheets` というディレクトリを作り、そこに書籍とチートシートを整理して保存するようにしています。

さらに、$\LaTeX$ で文書作成を行う場合は、`Documents` 直下に `LaTeX` ディレクトリを作成し、そこに自身で書いた文書を保存します。当然ながら、新しく文書を作り始めるたびに `~\Documents\LaTex` ディレクトリ直下にプロジェクトごとのディレクトリを作成します。

# まとめ

この記事では、ホームディレクトリに4つのディレクトリを作成し、目的に応じてソースコードなどの保存先を選ぶシンプルな整理整頓法について説明しました。もしこの方法に共感していただけたり、改善案を思いつかれた方は、どなたでもぜひコメントしていただけますと幸いです。
Twitterのスパム報告を自動化する（途中）

Twitterがインプレゾンビで荒れ果ててて手動でのスパム報告が追いつかなくなってきたので、Google Chrome前提でスパム報告を自動化する方法をちょっと書いておきます。悪用しないで良い方向に使ってください。

```javascript
// sleep は https://qiita.com/teloppy_com/items/cd483807813af5a4a38aより
const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));

function randrange(min = 500, max = 1000) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

async function block(n){
    document.querySelectorAll('button[data-testid="caret"]')[n].click();
    await sleep(randrange());
    document.querySelectorAll('div[data-testid="report"]')[0].click();
    await sleep(randrange());
    document.querySelectorAll('input[aria-posinset="6"]')[0].click();
    await sleep(randrange());
    document.querySelectorAll('button[data-testid="ChoiceSelectionNextButton"]')[0].click();
    await sleep(randrange());
    document.querySelectorAll('button[role="button"]')[1].click();
}
// block(0);


async function block_spams(){
    var tweets = Array.from(document.querySelectorAll('article[data-testid="tweet"]')).map(i => i.innerText);
    for(i in tweets) if (tweets[i].includes("BSS11") && tweets[i].includes("CX10")) await block(i);
}

block_spams();
```

なおこのスクリプトは途中でスパム報告が効かなくなって止まるので大した効力は無いかもしれません。完全に自動化するにはサブウインドウなりSeleniumなりでリロードを挟めば良いのですが、今回はここに留めておくことにします。

**追記**: 途中で止まるのはレートリミットだったようです。時間をmin=5000, max=6000にしたところ止まらずに動きました。なおツイートリストの更新をどうするかはまだ未定です。
mod7占い (paizaランク S 相当) を無駄に汎用的に解く(JavaScript)

## 問題

https://qiita.com/official-events/9ab96aa95d62fe3cbdd7

これの中にある、

https://paiza.jp/works/mondai/s_rank_skillcheck_sample/mod7

です。

数字が被っていないカードがいっぱいあって、
その中から３枚引いたとき数字の合計が7で割り切れるパターン数を出せ、という問題です。


## 説明

#### 「汎用的に」と題しているのは

これは単純に、

- **「７」で割るとか「３」枚とかの数字は可変にしよう**

という話です。(※問題文にはそんな話はまったく出てきません)

３重のfor文とか再帰呼び出しとかは使わないよ、ということですね。


#### 解き方は無難に

公式の解説にある方法も参考にしています。

- カードは「Nで割った余り」だけ見てその個数を数える。
- 重複を承知で、余りのすべての組み合わせを列挙する。 (例 [0,0,0]〜[6,6,6] 7^3通り)
- 余りの合計がNで割り切れる組み合わせだけを選択する。(例 [0,0,0] [0,3,4] [1,1,5] 等)
- それぞれ余りの個数が足りていることを確認する。 (例 [1,1,5]のとき、余り1のカードは最低2枚必要)
- 同じ余りを複数選択した場合の個数に注意してパターン数を算出。(例 10枚中3枚なら10×9×8になるような調整)
- 最後に、重複していた分を排除する。(枚数の階乗で割ると答えになる)


## コード

JavaScriptを普段使わない人にもどうにか雰囲気が伝わらないかと頑張った結果がこれ。

```JavaScript:count_mod_N.js
// Copyright © 2024 https://qiita.com/tanin_no_sorani
// Released under the CC0 1.0 Universal license.
'use strict';

const N = 7; // mod N
const M = 3; // 組み合わせの枚数
const mod_N = Array(N).fill(0n); // Nで割った余り0〜(N-1)の個数カウント用
let first = true; // 先頭行の判定用

require('node:readline').createInterface({ input: process.stdin })
.on('line', line => {
	if (first) { first = false; return; } // 先頭行は不要
	
	mod_N[parseInt(line) % N]++; // Nで割った余りで分類し、その個数だけを数える
})
.on('close', () => {
	let total = 0n;
	
	// 重複も含めて全ての「余りの組み合わせ」を列挙
	const state    = Array(M).fill(0); // 組み合わせの状態 (例 [0, 0, 0]～[6, 6, 6])
	let   patterns = Math.pow(N, M)  ; // 組み合わせの総数 N^M 通り
	while (patterns--) {
		
		// 組み合わせの値の合計がNで割り切れるか確認 (例 [0, 3, 4] → 7)
		if ((state.reduce((a, b) => (a + b)) % N) === 0) {
			
			// 現在の組み合わせで選択されている余りの回数を数える
			const selected = Array(N).fill(0n); // 選択された余りの回数カウント用
			state.map(i => selected[i]++); // (例 state[1,1,5]のときseletected[0,2,0,0,0,1,0,0])
			
			// それぞれの余りの個数が不足していないことを確認
			if (state.every(i => (selected[i] <= mod_N[i]))) {
				
				// 「余りの組み合わせ」→「余りの個数 - 調整」に置き換え→すべての積を取る
				total += state
					.map(i => (mod_N[i] - (--selected[i]))) // (調整例 3回なら-2,-1,-0となる)
					.reduce((a, b) => (a * b), 1n);
			}
		}
		
		// 次の組み合わせ (繰り上がりの例 [6,0,0]→[0,1,0])
		for (let i = 0; i < M; i++) { // 繰り上がり用のfor
			if ((++state[i] % N) !== 0) { break; } // 1加算し、繰り上がりがなければ抜ける
			else { state[i] = 0; } // 繰り上がる場合、この桁は0に戻して継続
		}
	}
	
	// 最後に重複を排除 (枚数の階乗 M! で割る)
	for (let i = 2; i <= M; i++) { total /= BigInt(i); }
	
	// (※BigIntのまま渡すと末尾に'n'が付くためtoString()が必要)
	console.log(total.toString());
});
```

## 感想

テストはすべて0.05秒だったので速度的には大きな問題はなさそうです。

もっと分かりやすく書けないかとは思うのですが、
コードが一度頭の中で固まってしまうとなかなか難しいんですよね。

最後まで読んでいただいてありがとうございました。
【AWS】一つのメトリクスフィルターが二つのアプリのログを検知してしまう現象の解決方法

# 概要
AWS CloudWatch Logsで一つのメトリクスフィルターが二つのアプリのログを検知してしまう現象が発生。
備忘録も兼ねて、原因と対応方法を紹介します。

# 前提と原因
元々CloudWatch Logsのロググループの下には既存アプリのアプリログに使用中のログストリーム一つしかなかったのですが、今回新規アプリを導入するにあたり新規アプリログ用にログストリームをもう一つ追加しました。アプリごとにログストリームを設けて、それぞれにメトリクスフィルターを適用してあげる、という構成です。

こんなイメージで構成を考えていました。

```
└── app_log_group
    ├── hoge_app_log_stream
    └── foo_app_log_stream
```

しかし、これが問題でした。

なぜなら、CloudWatch Logsのメトリクスフィルターは、特定のロググループに対して設定できますが、特定のログストリームを直接指定することはできないためです。

https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CloudWatchLogsConcepts.html

> Metric filters are assigned to log groups, and all of the filters assigned to a log group are applied to their log streams.

公式ドキュメントには上述の通り`applied to their log streams`とあります。つまり、ロググループの中のログストリームのデータ全てに適用される、という意味です。

# 解決法
解決方法は新たにロググループを作成して、そこにメトリクスフィルターを適用することです。
つまり、以下のイメージです。

```
├── hoge_app_log_group
│   └── hoge_log_stream
└── foo_app_log_group
 　　  └── foo_log_stream
```

これで両方のアプリのメトリクスフィルターが互いに検知してしまう現象が解決できました。
【Yarn】パッケージのバージョンを確認する方法

`yarn info`でパッケージのバージョンを確認できます。

```terminal
$ yarn info eslint                
└─ eslint@npm:8.57.0
   ├─ Version: 8.57.0
   │ 
   ├─ Exported Binaries
   │  └─ eslint
   │ 
   └─ Dependencies
      ├─ @eslint-community/regexpp@npm:^4.6.1 → npm:4.11.0
      ├─ @eslint/eslintrc@npm:^2.1.4 → npm:2.1.4
      ├─ @eslint/js@npm:8.57.0 → npm:8.57.0
      ├─ @humanwhocodes/config-array@npm:^0.11.14 → npm:0.11.14
      ├─ @humanwhocodes/module-importer@npm:^1.0.1 → npm:1.0.1
      ├─ @nodelib/fs.walk@npm:^1.2.8 → npm:1.2.8
      ├─ @ungap/structured-clone@npm:^1.2.0 → npm:1.2.0
      ├─ ajv@npm:^6.12.4 → npm:6.12.6
      ├─ chalk@npm:^4.0.0 → npm:4.1.2
      ├─ cross-spawn@npm:^7.0.2 → npm:7.0.3
      ├─ doctrine@npm:^3.0.0 → npm:3.0.0
      ├─ escape-string-regexp@npm:^4.0.0 → npm:4.0.0
      ├─ eslint-scope@npm:^7.2.2 → npm:7.2.2
      ├─ eslint-visitor-keys@npm:^3.4.3 → npm:3.4.3
      ├─ espree@npm:^9.6.1 → npm:9.6.1
      ├─ esquery@npm:^1.4.2 → npm:1.5.0
      ├─ esutils@npm:^2.0.2 → npm:2.0.3
      ├─ fast-deep-equal@npm:^3.1.3 → npm:3.1.3
      ├─ file-entry-cache@npm:^6.0.1 → npm:6.0.1
      ├─ find-up@npm:^5.0.0 → npm:5.0.0
      ├─ glob-parent@npm:^6.0.2 → npm:6.0.2
      ├─ globals@npm:^13.19.0 → npm:13.20.0
      ├─ graphemer@npm:^1.4.0 → npm:1.4.0
      ├─ ignore@npm:^5.2.0 → npm:5.2.4
      ├─ imurmurhash@npm:^0.1.4 → npm:0.1.4
      ├─ is-glob@npm:^4.0.0 → npm:4.0.3
      ├─ is-path-inside@npm:^3.0.3 → npm:3.0.3
      ├─ js-yaml@npm:^4.1.0 → npm:4.1.0
      ├─ json-stable-stringify-without-jsonify@npm:^1.0.1 → npm:1.0.1
      ├─ levn@npm:^0.4.1 → npm:0.4.1
      ├─ lodash.merge@npm:^4.6.2 → npm:4.6.2
      ├─ minimatch@npm:^3.1.2 → npm:3.1.2
      ├─ natural-compare@npm:^1.4.0 → npm:1.4.0
      ├─ optionator@npm:^0.9.3 → npm:0.9.4
      ├─ strip-ansi@npm:^6.0.1 → npm:6.0.1
      ├─ text-table@npm:^0.2.0 → npm:0.2.0
      ├─ @eslint-community/eslint-utils@npm:^4.2.0 → npm:4.4.0 [4286e]
      └─ debug@npm:^4.3.4 → npm:4.3.4 [e18a7]
      
```

https://yarnpkg.com/cli/info
自動化テストをできるようになろう


## 自動化テストとは


```
何か、ソースコードに対して変更をしたときには、自動的にテストしてくれるような設定をしておこう
```

というもの


## 自動化テストの極意

では、どのような時に、自動化テストを書くのか

巷では、テスト駆動開発、一括テストなど耳にするが、テストはアプリのコードよりも先に書いたほうがいいか、後に書いたほうがいいか、

私の見解は、アプリの挙動が決まっていて、動作させたい機能がはっきりしてる場合は、そのコードを書くべきと思う。


## テスト駆動開発のサイクル

①失敗するテストを最初に書く
②次にアプリケーションのコードを書いて成功させる（パスさせる）
③必要ならリファクタリングする
100-2：CSS基礎の学習（15/91）

# カリキュラム一覧
- <font color="FireBrick"><strong>レスポンシブウェブデザイン 認定講座　　　　　　　　　　　　　　←　今ココ</font>
- JavaScript アルゴリズムとデータ構造 (ベータ版) 認定講座
- フロントエンド開発ライブラリ 認定講座
- データ可視化 認定講座
- リレーショナルデータベース 認定講座
- バックエンド開発と API 認定講座
- 品質保証 認定講座
- Python を用いた科学計算 (ベータ版) 認定講座
- Python を用いたデータ分析 認定講座
- 情報セキュリティ 認定講座
- Python を用いた機械学習 認定講座
- Python を用いた代数学 認定講座

# レスポンシブウェブデザイン　認定講座の内訳
#### コース1
- [x] HTML の学習: 猫の写真アプリを作成する
- [ ] CSS 基礎の学習: カフェメニューを作成する <font color="FireBrick"><strong> ←　進捗：15/91step
- [ ] CSS 色指定の学習: カラーマーカーのセットを作成する
- [ ] HTML フォームの学習: 登録フォームを作成する
- [ ] 認定プロジェクト

#### コース2
- [ ] CSS ボックスモデルの学習: ロスコの絵画を作成する
- [ ] CSS フレックスボックスの学習: フォトギャラリーを作成する
- [ ] タイポグラフィの学習: 栄養成分表示ラベルを作成する
- [ ] アクセシビリティの学習: クイズを作成する
- [ ] 認定プロジェクト

#### コース3
- [ ] CSS 疑似セレクターの学習: バランスシートを作成する
- [ ] CSS 中級の学習: 猫のイラストを作成する
- [ ] レスポンシブウェブデザインの学習: ピアノを作成する
- [ ] 認定プロジェクト

#### コース4
- [ ] 技術ドキュメントページ認定プロジェクト
- [ ] CSS 変数の学習: 都市のスカイラインを作成する
- [ ] CSS グリッドの学習: 雑誌を作成する
- [ ] 認定プロジェクト

#### コース5
- [ ] CSS アニメーションの学習: 観覧車を作成する
- [ ] CSS Transform の学習: ペンギンを作成する
- [ ] 認定プロジェクト

# メモ
- xxx
正規表現のまとめ

1. **任意の一文字**
   - `.` : 任意の一文字に一致します。
   - 例：`a.b` は `a` と `b` の間に任意の一文字がある文字列に一致します（例：`acb`, `a1b`）。

2. **繰り返し**
   - `*` : 0回以上の繰り返しに一致します。
     - 例：`a*` は `a` が0回以上続く文字列に一致します（例：``, `a`, `aaa`）。
   - `+` : 1回以上の繰り返しに一致します。
     - 例：`a+` は `a` が1回以上続く文字列に一致します（例：`a`, `aa`）。
   - `{n}` : 正確に `n` 回の繰り返しに一致します。
     - 例：`a{3}` は `a` が3回続く文字列に一致します（例：`aaa`）。
   - `{n,}` : `n` 回以上の繰り返しに一致します。
     - 例：`a{2,}` は `a` が2回以上続く文字列に一致します（例：`aa`, `aaa`）。
   - `{n,m}` : `n` 回以上 `m` 回以下の繰り返しに一致します。
     - 例：`a{2,4}` は `a` が2回から4回続く文字列に一致します（例：`aa`, `aaa`, `aaaa`）。

3. **文字クラス**
   - `[]` : 文字クラスを作成します。
     - 例：`[abc]` は `a` または `b` または `c` に一致します（例：`a`, `b`, `c`）。
     - `[^abc]` : `a` または `b` または `c` 以外の文字に一致します。
     - `[0-9]` : `0` から `9` までの数字に一致します。
     - `[a-z]` : 小文字のアルファベットに一致します。
     - `[A-Z]` : 大文字のアルファベットに一致します。
     - `[a-zA-Z0-9]` : 半角英数字に一致します。

4. **位置指定**
   - `^` : 文字列の先頭に一致します。
     - 例：`^abc` は `abc` で始まる文字列に一致します。
   - `$` : 文字列の終端に一致します。
     - 例：`abc$` は `abc` で終わる文字列に一致します。

5. **特殊文字**
   - `\w` : 半角英数字とアンダースコアに一致します（ `[a-zA-Z0-9_]` と同等）。
   - `\d` : 数字に一致します（ `[0-9]` と同等）。
   - `\s` : 空白文字に一致します（空白、タブ、改行など）。
   - `\` : エスケープ文字です。特殊文字をリテラルとして使用するために使います。
     - 例：`\.` は `.` に一致します。

6. **グループ化と参照**
   - `()` : 部分文字列をグループ化します。キャプチャグループとしても機能し、後で参照できます。
     - 例：`(abc)` は `abc` に一致し、キャプチャグループとして保存します。
   - `(?:...)` : 非キャプチャグループを作成します。
     - 例：`(?:abc)` は `abc` に一致しますが、キャプチャしません。
   - `\1`, `\2`, ... : 以前のキャプチャグループを参照します。
     - 例：`(abc)\1` は `abcabc` に一致します。

### その他のパターン

1. **選択**
   - `|` : 選択を示します。
     - 例：`abc|def` は `abc` または `def` に一致します。

2. **アサーション**
   - `(?=...)` : 肯定の先読み。条件に一致する場合にその位置に一致します。
     - 例：`a(?=b)` は `a` に続いて `b` がある場合の `a` に一致します。
   - `(?!...)` : 否定の先読み。条件に一致しない場合にその位置に一致します。
     - 例：`a(?!b)` は `a` に続いて `b` がない場合の `a` に一致します。

3. **境界**
   - `\b` : 単語の境界に一致します。
     - 例：`\bword\b` は `word` が単独の単語として存在する場合に一致します。
   - `\B` : 単語の境界でない位置に一致します。
リスト内の全てのオブジェクトを通じて最後に値が入っているプロパティが何番目にあるかを計算する方法【TypeScript】

## 説明

1. `flatMap`: 各オブジェクトのプロパティ値をフラットにして、それぞれのインデックスを計算します。リストの中でプロパティが存在する場合にのみそのインデックスを計算し、`0` でない値を返します。
2. `Math.max`: 全てのインデックスの中から最大のものを取り出します。

```typescript
const list = [
  {
    code1: "A1",
    code2: "A2",
    code3: "",
    code4: "A4",
    code5: "",
    code6: "A6",
    code7: "A7",
  },
  {
    code1: "B1",
    code2: "B2",
    code3: "",
    code4: "B4",
    code5: "",
    code6: "B6",
    code7: "B7",
  },
  {
    code1: "",
    code2: "",
    code3: "C3",
    code4: "",
    code5: "C5",
    code6: "",
    code7: "",
  }
];

const lastFilledIndex = Math.max(
  ...list.flatMap((item, index) =>
    Object.values(item).map((value, i) => (value ? index * 7 + i + 1 : 0))
  )
);

console.log(lastFilledIndex); // 19
```
ホットボンド用スタンドを自作

## ダンボール工作の時間だよ〜！
はい、ホットボンド用スタンドを面倒で家のあった段ボールで作ったbockringです。

この記事は短いです。なぜなら伸びないから。タグ付けは最低限しかしてませんし、付けてもまともなタグがないので1つだけです。

## なぜ作ろうという発想に至ったのか
まず、私はそもそもDAISOのグルーガンを改造したものを使用しています。電源スイッチを手元につけただけですが。
![IMG_0485.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/b76c84a3-2200-46a4-1a2e-9126df0a0f64.jpeg)
これを使用中でも安全に置けるようにしたい訳です。なぜなら、金属の針金でできたスタンドは弱くてすぐ倒れてしまいます。ですから作ろうっていう訳です。

## 製作方法
ホットボンド本体の形を方眼用紙に書き出し、段ボールに当てて切り、ホットボンドで貼り付けるだけです。

## 完成
![IMG_1751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/39c7d93b-1655-8f42-e978-c5dad7e69d33.png)
先の尖っている(？)ところの右側から差し込めます。差し込んだ状態がこちら。
![IMG_1752.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/8ef8e961-bac1-d09a-e371-52dd5d6a0cd7.png)
素晴らしい、ジャストフィットです。実はこの差し込み口の下には抜き差し可能なペーパーホルダーがあり、垂れたボンドはその紙1枚をそのまま引き抜くことで処理できるというちょっとだけ凝った設計になっています。

## 終わりに
遅らしく短い記事でした。実際、この記事の執筆には5分しかかけていません。いつもは何十分とか何時間とか、場合によっては数日かけていますが、どうせ伸びない記事なのでどう書いても同じということで短くしました。

しかしダンボールとはいえ、スタンドがあれば作業性が変わるので是非スタンドがない製品には、耐熱性など安全が担保できる範囲で工作してみてはいかがでしょうが。

それではまた〜
eachメソッドを使わないで繰り返し処理

## 初めに

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

## eachメソッドを使っていないのに一覧を作成できるのはなぜか
```
<% if @example.present? %>
```
このコードのように、複数の要素に対して存在するかどうかのメソッドは繰り返し処理がされる。
繰り返すためのメソッドであるeachを使わなくても繰り返し処理ができる。
JetRacerの環境で９軸センサーで２Dマッピングに挑戦。

jupyter labの環境で位置をプロットさせます。BNO055というセンサーで２Dマッピングさせてみました。まだ速度は、固定です。BNO055は補正できるようですが、加速度センサーでは車体の傾きにより重力により速度を算出するのは誤差が蓄積されるのでならかの方法でマシンから速度を取得する必要がありそうです。

```python
%matplotlib inline

import time
import board
import busio
import adafruit_bno055
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display

i2c = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_bno055.BNO055_I2C(i2c)

# 初期位置と角度
x, y = 0.0, 0.0
theta = 0.0

# 移動距離は毎秒300ミリ（あとでオドメトリで取得するコードを追加する）
distance_per_step = 0.3

# グラフ表示設定
plt.ion()
fig, ax = plt.subplots()
sc = ax.scatter([x], [y])
ax.set_xlim(-300, 300)
ax.set_ylim(-300, 300)
ax.set_xlabel("X(m)")
ax.set_ylabel("Y(m)")
ax.set_title("JetRacer_2D Mapping")
display_handle = display(fig, display_id=True)

def update_position():
    global x, y, theta
    
    x_positions = [x]
    y_positions = [y]

    while True:
        #オイラー角を使用
        euler_angles = sensor.euler
        plt.ion()

        if euler_angles is not None:
            heading, _, _ = euler_angles
            theta = np.deg2rad(heading)

            dx = distance_per_step * np.cos(theta)
            dy = distance_per_step * np.sin(theta)
            
            x -= dx
            y += dy

            x_positions.append(x)
            y_positions.append(y)

            sc.set_offsets(np.c_[x_positions, y_positions])
            ax.set_xlim(min(x_positions) - 1, max(x_positions) + 1)
            ax.set_ylim(min(y_positions) - 1, max(y_positions) + 1)
            plt.draw()
            display_handle.update(fig)
            #plt.pause(0.01)
            
            with open("JetRacer_2d_mapping_data.csv", "a") as f:
                f.write(f"{x},{y},{heading}\n")
            
        else:
            print("Waiting for sensor data...")

        time.sleep(0.01)

if __name__ == "__main__":
    try:
        update_position()
    except KeyboardInterrupt:
        print("Mapping interrupted.")
        plt.ioff()
        plt.show()
```
コンテナを使うなら「Docker」を使ってみた

![docker.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633992/9061e1f7-9c83-d661-27ae-edd06be53f14.jpeg)

エスプリフォートでは、業務内でのシステム開発以外でも、日々アンテナを張りながら仲間同士お互いに技術力を磨き合っています。
そして高めた技術力を顧客のために如何に生かしていくのかということを考え、日々の開発に取り入れることで顧客から頼られる存在としてあり続けています。

今回は「Docker」をご紹介いたします。

# はじめに
最近とある事情があり、[Redmine](https://redmine.jp/)を試したいな、と思いました（Redmineとは、オープンソースのプロジェクト管理ツールです）。

皆さんなら、このような「とあるツールを試してみたい」という時、どうされていますか？
「そのままPCにインストールするの、ちょっとヤだな...」と思ったことはないでしょうか？

例えば、以下のようなケースです｡
* バージョン違いの同じ開発ツールがインストール済
* 他のシステム開発環境に影響が出そう

つまりは『少し試したいだけなのに、PCの既存環境に影響を与えてしまわないか？』というのが気になるところではないでしょうか｡

# こんな時こそ
こんな時に役立つのが「Docker」をはじめとする、仮想環境構築ツールです。

[docker - 開発者とチーム向けの#1コンテナ化ソフトウェア](https://www.docker.com/ja-jp/products/docker-desktop/)

「コンテナ」をざっくりというと、『プログラム環境を閉じ込めておける箱』みたいなものです。
PCの既存環境には影響を与えないので、今回のような用途にはピッタリです。

他に開発面でも、本番環境の違いなく、アプリケーション作成・デプロイ・実行を簡単に実行できる環境を開発や検証を行えることも強みです。

# 「Docker」のメリット・デメリット
:::note info
**メリット**
・アプリケーションの動作が高速
・本番と同じ環境で開発できる
・開発環境とインフラ環境一式を簡単に共有・展開できる
:::

:::note alert
**デメリット**
・Dockerのコンセプトやコマンド、設定方法などを理解する必要がある為、学習コストが高い
・非対応のOSでは起動できない
:::

# 「docker」でやってみよう
実際にdockerを使って、Redmineが動作する環境を作りたいと思います｡

自宅に眠っていたMac mini (Late 2012) のOSをUbuntuに入れ替え、ここにDockerをインストールし、その上に、Redmineのコンテナを作成します｡

図にすると、以下のようなイメージです｡
![kaisou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633992/52631dc2-7e19-8d2c-abae-79f16d26bf13.png)


## 1．PC環境の構築
Ubuntuのインストール、Dockerのインストールは、それぞれ以下のサイトを参考にさせて頂きました｡

* [Macにubuntuをインストール](https://www.maclab.tokyo/document/ubuntu-install/6827/)
* [Install Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/#installation-methods)

## 2. Redmine コンテナの構築
次に、Redmine コンテナを作成し、起動させます｡

今回は、Redmine本体とDB（Postgresを使用します）の２つのコンテナを作成するので、「docker compose」を使用します。

[Docker Compose overview](https://docs.docker.com/compose/)

docker-compose.yml ファイルは、以下のサイトを参照させて頂きました｡

[docker-composeでコンテナ作成(redmine)](https://qiita.com/38pinn/items/3b2418b20d1cefe7320e)

```docker-compose.yml
services:
  redmine:
    image: redmine:5.0.4-bullseye
    ports:
      - 8081:3000
    environment:
      REDMINE_DB_POSTGRES: redmine-db
      REDMINE_DB_DATABASE: redmine
      REDMINE_DB_USERNAME: redmine_user
      REDMINE_DB_PASSWORD: redmine_password
      REDMINE_SECRET_KEY_BASE: supersecretkey
      REDMINE_DB_PORT: 5432
    volumes:
      - vol_redmine:/usr/src/redmine/files

  redmine-db:
    image: postgres:15.1-bullseye
    ports:
      - 5432:5432
    environment:
      POSTGRES_DB: redmine
      POSTGRES_USER: redmine_user
      POSTGRES_PASSWORD: redmine_password
    volumes:
      - vol_redmine_db:/var/lib/postgresql/data

volumes:
  vol_redmine:
  vol_redmine_db:
```

## 3. Redmine の起動確認

コンテナを起動し、動作確認してみます｡

``` コンテナの起動
sudo docker-compose up -d
```

http://Mac miniのIPアドレス/ポート番号(今回は8081)
![redmine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633992/0d7a24b3-9a28-4d2b-c363-bbfccee7cf5a.png)

できました！
作成したコンテナは、好きなタイミングで削除することができます。

# まとめ
コンテナは、今回試したように、ちょっとしたツールの動作を確認するにはとても便利です｡

またそれだけではなく、コンテナには多くの利点がありますので、よければDockerの活用を検討してみては如何でしょうか。

https://www.esprit-fort.co.jp/

https://www.esprit-fort.co.jp/recruit/
D - K-th Nearest【Atcorder】【WriteUp】

# はじめに
茶色コーダーです。しばらく参加してませんが、緑目指して頑張ってみようと思います。

# 問題

[D - K-th Nearest](https://atcoder.jp/contests/abc364/tasks/abc364_d)

### 問題文
数直線上に $N+Q$ 個の点 $A_1,\ldots,A_N,B_1,\ldots,B_Q$ があり、点 $A_i$ の座標は $a_i$ 、点 $B_j$ の座標は $b_j$ です。
$j=1,2,\ldots,Q$ それぞれについて、以下の問題に答えてください。
- 点 $A_1,A_2,\ldots,A_N$ のうち点 $B_j$ との距離が $k_j$ 番目に近い点を $X$ としたとき、点 $X$ と点 $B_j$ との距離を求めよ。より厳密には、点 $A_i$ と点 $B_j$ との距離を $d_i$ として、$(d_1,d_2,\ldots,d_N)$ を昇順に並び替えてできる列を $(d_1^{\prime},d_2^{\prime},\ldots,d_N^′)$ としたとき、$d_{kj}^{\prime}$ を求めよ。

### 制約
- $1≤N,Q≤10^5$
- $−10^8≤a_i,b_j≤10^8$
- $1≤k_j≤N$
- 入力は全て整数

# 解答と解説
難しくて解説みながらやったので、コードが解説と(~~同じ~~)似ています。

### 解説
[「答えを決め打つ」タイプの二分探索](https://betrue12.hateblo.jp/entry/2019/05/11/013403)を用いて解いていきます。
「答えを決め打つ」タイプの二分探索とは記事によると、
1. 「○○という条件を満たす $X$ の最小値を求めよ」という問題において、
2. 「ある値 $X$ が与えられたとき、○○を満たすことはできるか？」という判定問題を考え、
3. その判定問題を繰り返し解くことでYesになる $X$ と $N_o$ になる $X$ の間の境界を特定し、元の問題の答えを求める解法。
です。

今回の問題では $f(x) = (点A_1,\ldots,A_NのうちB_jとの距離がx以下の点がk以上か)$ という判定問題を考え、条件を満たす最小の $k$ を求めるという問題です。
ソートした $A$ に対して上記の判定問題を用いて二分探索を行います。
少し難しいので簡単な例を用いてなぜ解けるかを解説します。

- $A =  \lbrace -3,-1,5,6 \rbrace $
- $B_j = -2$
- $k = 3$

で考えてみます。

$f(x)$ をグラフにすると下のようになります。みてわかる通り単調増加です。
![D - K-th Nearest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310678/5a08fc17-a6b6-444a-1b26-b50e2c402415.png)
グラフを見てわかる通り $x=7$ のときが条件を満たす最小の $x$ です。
この $f(x)$ が $k$ 以上か以下であるかという判定を用いて二分探索を行うと効率よく探索を行えます。

$f(x)$ は$B_j-x$以上$B_j+x$以下の要素がいくつあるかという問題に置き換えることができます。実装はこの置き換えた問題を用いて行います。

### 計算量

- 計算量は最初に $A$ をソートするので $O(N\log{N})$
- $Q$ 個のクエリに対して
  - $f(x)$ を用いた二分探索が $O(\log{A})$ ( $A$ は $A$ の要素が取りうる要素の範囲。つまり $2\times 10^8$ )
  - $f(x)$ の中で要素を数える際に二分探索を行うため $O(\log{N})$

合わせると $O(N\log{N} + Q\log{A}\log{N})$ 

### コード
通常の二分探索では、目的の値を見つけたらその時点で終了かつ境界の遷移はその時点で探索している場所の一つ隣であるため、存在しない場合は $left>=right$ の状態まで遷移します。
今回は境界をみつけるのが目的($left+1=right$ の状態が目的)なのでそれを条件にし、境界の遷移は現在探索している値を代入していきます。
```c++
#include <bits/stdc++.h>

using namespace std;

int main() {
  int N,Q; cin>>N>>Q;
  vector<int> A(N);
  
  for(int i=0;i<N;i++) {
    cin >> A[i];
  }
  
  sort(A.begin(),A.end());
  
  for(int i=0;i<Q;i++) {
    int b,k;cin>>b>>k;
    
    auto f = [&](int x) {
      auto ub = upper_bound(A.begin(),A.end(),b+x);
      auto lb = lower_bound(A.begin(),A.end(),b-x);
      
      return k <= ub-lb;
    };
    
    int left = -1;
    int right = 2e8 + 1;
    int mid = (left+right)/2;
    while(left+1 < right) {
      if(f(mid)) {
        right = mid;
      }else{
        left = mid;
      }
      mid = (left+right)/2;
    }
    cout << right << endl;
  }
}
```

# さいごに
二分探索系の問題いっぱいやってみようと思います！
VSCodeでUnable to connect to VS Code server: Error in request.発生

VS Code Serverにアクセスできないエラーが発生しました。
再現手順は不明ですが、リモートでUbuntuにSSH接続しつつ、WSL2を立ち上げたら発生したような気がします。
```
masami@masami-L /u/src> code .
Unable to connect to VS Code server: Error in request.
Error: connect ENOENT /run/user/1000/vscode-ipc-a8a44a73-0123-4d59-9424-463f68dff262.sock
    at PipeConnectWrap.afterConnect [as oncomplete] (node:net:1606:16) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'connect',
  address: '/run/user/1000/vscode-ipc-a8a44a73-0123-4d59-9424-463f68dff262.sock'
}
```

この障害が起きている場合、ターミナルに警告アイコンが表示されます。
原因により対処は異なると思いますが、私の場合は簡単に対処可能で、
別のターミナルを立ち上げるだけでOKでした。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383255/541ca69a-4f99-9063-25ad-bc9848ee1245.png)

このエラーメッセージで検索すると下記Issueが検索ランキング上位に来ますが、
キャッシュのクリア等、影響が見えにくい処置が多かったですが、
私の場合はそこまでしなくても問題ありませんでした。

https://github.com/microsoft/vscode-remote-release/issues/6997
Spring FrameworkのDIコンテナ

## DIコンテナ(依存性の注入)
DIコンテナとは依存性の注入をしてくれるSpring Frameworkの機能

## 依存とは
##### クラス依存
クラスAとクラスBがあり、クラスAでクラスBのメソッドを使う場合は以下になる。
```java
class A {
  public void methodA() {
    B b = new B();
    b.methodB();
  }
}
```
上記のようにクラスA(使う側)でクラスB(使われる側)のインスタンスを作成してメソッドを実行する。
仕様変更などで、使われる側のクラスがクラスCになった場合は以下のように修正することになる。
```java
class A {
  public void methodA() {
    C c = new C();
    c.methodC();
  }
}
```
このようにインスタンスを作り直してメソッドを実行した。書き換えた箇所を「依存性がある」という。
Bのインスタンを使用している箇所が10箇所や100箇所あった場合、修正にかなり時間がかかってしまう。
Spring FrameworkのDIコンテナを使えば、修正する箇所は最小限にできる。

## DIコンテナを使う
DIコンテナを使えば明示的にインスタンスを生成しなくても、自動的にインスタンスを生成してくれる。
DIコンテナを使う場合はインタフェースを使って依存関係を作る必要があるので、インタフェースを作成する必要がある。以下4つを作成する。

**「動物が鳴く」の役割を持ったインタフェース**
```java
public interface Cry {
  void crying();
}
```
**犬クラス**
```java
public class Dog implements Cry {
  @Override 
  public void crying(){
    System.out.println("わん");
  }
}
```
**猫クラス**
猫クラスのインスタンスをDIコンテナで生成することにする。
生成したいクラスに@Componentアノテーションを付与する。
```java
@Component
public class Cat implements Cry {
  @Override 
  public void crying(){
    System.out.println("にゃあ");
  }
}
```

**使う側クラス**
DIコンテナによって生成されたインスタンスを使用するためには、使用したいクラスで参照を受け取る必要がある。参照を受け取るフィールドを宣言し@Autowiredアノテーションを付与する。
猫クラスのインスタンスを受け取るので「にゃあ」と出力される。
```java
public class Main {
  // ここでDIコンテナによって生成された、猫クラスのインスタンスを受け取る
  @Autowired
  Cry cry;

  public void execute() {
    cry.crying(); //にゃあと出力される
  }
}
```
仕様変更により使われる側クラスを犬クラスに変更する場合は、@Componentアノテーションを猫クラスから犬クラスに付与するだけで良い。
```java
// アノテーション削除
public class Cat implements Cry {
  @Override 
  public void crying(){
    System.out.println("にゃあ");
  }
}
// アノテーション付与
@Component
public class Dog implements Cry {
  @Override 
  public void crying(){
    System.out.println("わん");
  }
}
```
これにより使う側クラスで修正を加えることなく犬クラスに変更することができる。
猫クラスを使う箇所が10箇所や100箇所でもアノテーションを付け替えるだけなので、修正に時間がかからない。
```java
public class Main {
  // 今度は犬クラスのインスタンスを受け取る
  @Autowired
  Cry cry;

  public void execute() {
    cry.crying(); //わんと出力される
  }
}
```

### 終わり
Spring Frameworkの勉強を始めたばかりなので、簡単ではありますがDIコンテナ(依存性の注入)について執筆しました:grinning:
【アップデート】S3が条件付き書き込みをサポートしました

こんばんは。Koderaです。
Amazon S3で条件付き書き込みのサポートが開始されました。
https://aws.amazon.com/about-aws/whats-new/2024/08/amazon-s3-conditional-writes/

## アップデート内容
Amazon S3 では、オブジェクトを作成する前にオブジェクトが実際に存在しているか確認できる条件付き書き込みがサポートされました。
データのアップロード時にアプリケーションが既存のオブジェクトを上書きするのをより簡単に防ぐことができます。
対象は、汎用バケットとディレクトリバケットの両方です。

アップデートのメリットは、複数のクライアントを持つ分散アプリケーションが、共有データセット間でデータを同時並行で更新できるようになったことです。
データをアップロードする前にオブジェクトの存在を確認するために追加のAPIリクエストの利用する必要がなくなります。

## conditional writes（条件付き書き込み）とは
S3への条件付き書き込みでは、書き込みリクエストに追加のヘッダーを使います。
条件付き書き込みの目的は、既存データの上書きの防止です。バケットに同じキー名を持つ既存のオブジェクトがすでに存在しないことを検証します。


条件付き書き込みには、s3:PutObject アクセス許可が必要です。
呼び出し元はバケット内のオブジェクトの存在を確認できます。SDKだと署名付き URL で条件付き書き込みができます。

:::note info
条件付き書き込みを使用するには、HTTPS (TLS) 経由でリクエストを行うか、AWS署名バージョン4を使用してリクエストに署名する必要があります。
:::

また、以下のAPIが条件付き書き込みをサポートしています。
`PutObject`
`CompleteMultipartUpload`

## 条件付き書き込みの挙動について
条件付き書き込みは、バケット内の既存のオブジェクトに対して実在確認がなされます。
当然、バージョニングしている場合は当然同じキー名となるので、どのような挙動になるのか簡単にまとめました。

### バージョニングしていないとき
バケットに同じキー名を持つ既存のオブジェクトがない場合、書き込み操作は成功し、レスポンス200が返されます。
既存のオブジェクトがある場合、書き込み操作は失敗し、412 Precondition Failedが返されます。
同じオブジェクト名に対して複数の条件付き書き込みが発生した場合、最初に終了する書き込み操作は成功します。その後、Amazon S3 は 412 Precondition Failed レスポンスを返すことで、後続の書き込み処理は失敗となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/4da3b2cf-5561-2b03-cb3d-0ccf0f30e70a.png)


### バージョニングしているとき
バージョニングが有効な場合、S3 は条件付き書き込みの評価の一部として、同じ名前の現在のオブジェクトバージョンが存在するかどうかを確認します。同じ名前の現在のオブジェクト・バージョンがない場合、または現在のオブジェクト・バージョンが削除マーカーである場合、書込み操作は成功します。
バージョニングの有効化の有無にかかわらず、412 Precondition Failedが返されます。


また、同時リクエストの場合、レスポンス409 Conflictが返されることもあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3858908/8b363f7e-c381-1220-295e-699153aedd24.png)

## まとめ
Amazon S3 では、オブジェクトを作成する前にオブジェクトが実際に存在しているか確認できる条件付き書き込みがサポートされるようになったので、実際の挙動も踏まえてアップデートを確認してみました。
Visual StudioでJavaScriptのプログラムをデバッグする

# 設定手順
## JavaScriptのデバッグを有効化する
１．Visual Studioを開き、ツール > オプションを押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/35ed5781-3367-23e3-5f2f-78d676aa092b.png)
２．デバッグの中から、「ASP.NET の JavaScript のデバッグを有効にする (Chrome、Edge、IE)」をチェックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/198b0f3f-6e24-7839-e050-92bca15c22e8.png)
３．OKボタン押下で閉じます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/ec063960-f327-6ed7-fa6a-575fe13f310a.png)
## デバッグ用のブラウザを準備する
１．デバッグターゲット > ブラウザーの選択を押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/e67d2653-a374-d622-4342-a68d22856fae.png)
２．追加を押下します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/a232285f-bf04-9b58-f58c-f210910a62a4.png)
３．以下の通り入力し、OKボタンを押下します
プログラム：実行に使用したいブラウザのアプリケーションパス
引数：--remote-debugging-port=任意のポート
表示名：任意の名前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/3a57e202-7741-fb80-9ffe-1044d7cdf0c3.png)
４．作成したブラウザ設定を規定値にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/de4dfbbf-5be5-2abb-5ada-ff2d7d2230ea.png)
５．キャンセルで閉じます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/6e3f9285-a8da-27ba-6384-00c5cc051362.png)

# 動作確認
Razor Pagesアプリケーションで、簡単なプログラムを実行してみます。
```html:Index.cshtml
<button onclick="sampleOnClick()">ボタン</button>
```
```javascript:site.js
function sampleOnClick() {
    alert("デバッグテスト");
}
```

**実行結果**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/ec57dbef-b238-6569-bb96-f18f63fc251e.png)
無事ブレークポイントで止めることができました！
もちろん、変数の中身なども見ることができます。（今回はないですが）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/72569f9c-1d9f-c746-4c4b-215b71e48f6e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/06e6aed5-9961-40c2-7a0f-bba8001e937d.png)

ちなみに、今回作成したブラウザ設定はここから切り替えることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2257421/f7abb95a-8b47-c242-364c-1718de4edf92.png)


# 注意事項
埋め込みのJavaScriptコードはサポートされていないようです。
デバッグしたければ、別ファイルに分ける必要があります。

# 動作環境
* Windows 11 Home（23H2）
* .NET 8.0（SDK 8.0.204）
* Visual Studio 2022

# 参考
https://learn.microsoft.com/ja-jp/visualstudio/javascript/debug-nodejs?view=vs-2022