OmniAICreator/Qiita-1.07M huggingface dataset:
【Socket.io】HTTP上で使用していたCookieの情報をWebSocketで使用する方法

# 背景
WebSocketでも、HTTPと同様にcookieの情報を授受できるようにしたかったが、それなりに苦戦したため、備忘録程度に記事として残しておきます。
WebSocket上のcookieの授受だけでなく、 **HTTP** 上で使用していたcookieの送信も可能になるため、開発の柔軟性が上がるかと思います。

今回は `Express.js` と `Svelte`、`socket.io` を使用して行っています。

# 結論
CORSの設定をしてあげることでcookieの情報授受が可能になりました。
socketの初期化時に、オプション項目で **`withCredentials`** または **`credentials`** というのがあるので、それらを `true` にすることでcookieの送受信が可能になります。


- **クライアントサイド**
```svelte:+page.svelte
<script lang="ts">
  import { io } from 'socket.io-client';

  const socket = io(`ws://localhost:3000`, {
    withCredentials: true, // 先頭にwithが必要
  })
</script>
```

- **サーバーサイド**
```typescript:index.ts
import express from 'express';
import { createServer } from 'http';
import { Server } from 'socket.io';

const app = express();
const server = createServer(app);
const port = 3000;
const io = new Server(server, {
  cors: {
    origin: 'http://localhost:8080',
    credentials: true, // NOTE: サーバー側ではwithはいらない(2024/10/17現在)
  },
  // ちなみに下の設定を行うことで、WebSocket上のCookieもこちらで設定ができるみたいです（確認していないのでわからないが）
  // この設定がなくてもHTTP上のcookieは使用できます
  cookie: {
    name: '_socket_session_id',
  },
})

```

### 参考文献

https://qiita.com/error484/items/c3047277fe9b4aa03f8d

https://socket.io/docs/v3/handling-cors/
CSS クラス名とIDとHTMLタグを使った指定方法

# クラス名 id タグそれぞれを指定する方法

```index.html
<p class="container" id="box">ボックス1</p>
```
このようにあった場合はCSSで指定する方法は以下の通りです

```style.css
p{
    font-size: 20px;
    font-family: sans-serif;

}

#box{
    background-color: aqua;
    width: auto;
    height: auto;
    border-width: 2px;
    border-color:black ;
}

.container{
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
}
```

# タグ　クラス idをセットで指定する方法

以下のように続けて記入します

```style.css
p#box.container {
    font-size: 20px;
    font-family: sans-serif;
    background-color: aqua;
    width: auto;
    height: auto;
    border-width: 2px;
    border-color: black;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
}

```




参考書籍
"1冊ですべて身につくHTML&CSSとWebデザイン入門講座"
GoogleFonts使い方と活用方法

**Google Fontsの使い方と活用方法**
Google Fontsは、Googleが提供する無料のWebフォントサービスで、ウェブサイトやアプリケーションのデザインに手軽に使えるフォントを提供しています。シンプルな導入方法と豊富なフォントのラインナップが特徴で、プロジェクトに応じて様々なフォントを利用できます。

この記事では、Google Fontsの概要、導入方法、使い方、そして選ぶ際のポイントについて解説します。

# 1. Google Fontsとは？
Google Fontsは、誰でも無料で使えるWebフォントを提供するサービスです。開発者はGoogleが提供するリンクを使用するだけで、特定のフォントを簡単にWebサイトに適用できます。

**主な特徴**
無料で使用可能：商用・非商用問わず利用できます。
多言語対応：日本語を含む多くの言語のフォントが提供されています。
Webフォント最適化：ウェブページにフォントが迅速にロードされるよう最適化されています。
# 2. Google Fontsの利用方法
Google Fontsを使ったWebフォントの導入は非常に簡単です。以下の手順で、自分のウェブサイトやプロジェクトに適用することができます。

**2.1 Google Fontsサイトからフォントを選ぶ**
Google Fonts にアクセスします。
お好みのフォントを探します。
言語フィルタを使って、日本語や英語などのフォントを絞り込むことができます。
使用するフォントをクリックし、「Select this style」または「Select this family」を選択します。
**2.2 HTMLにGoogle Fontsを導入する**
Google Fontsでは、フォントのリンクをHTMLに追加することで簡単に利用できます。

1. フォントのリンクをHTMLに追加
選択したフォントの「Embed」タブで、HTMLの<head>に貼り付けるコードが表示されます。

html
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
```

2. CSSでフォントを適用
HTMLファイルのCSSで、対象の要素にフォントを指定します。

```css
body {
  font-family: 'Roboto', sans-serif;
}
```

2.3 CSSのみでGoogle Fontsを利用する
HTMLに直接リンクを貼りたくない場合は、CSSに@importを使う方法もあります。

```css
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

h1 {
  font-family: 'Roboto', sans-serif;
}
```

# 3. 日本語フォントの活用
Google Fontsには、Noto Sans JPやNoto Serif JPといった日本語フォントも提供されています。日本語フォントは、文字数が多いため通常の英字フォントよりも重くなりがちですが、Google Fontsは自動的に最適化されたフォントファイルを提供します。

例：Noto Sans JPの導入
```html
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">

body {
  font-family: 'Noto Sans JP', sans-serif;
}
```

# 4. フォントの選び方とポイント
**4.1 読みやすさを優先**
サイトの目的やターゲットユーザーに応じて、視認性が高く読みやすいフォントを選ぶことが重要です。たとえば、ブログやニュースサイトでは、視認性の良い「Sans-serif」系フォントが推奨されます。

4.2 ページの表示速度を考慮
あまり多くのフォントスタイル（weightやitalic）を使うと、ページの読み込み速度が遅くなります。必要なスタイルだけを選択し、最小限のフォントで運用しましょう。

4.3 ブランドに合ったデザイン
フォントはサイトの雰囲気を左右します。ブランドのトーンに合ったフォントを選び、サイト全体の統一感を保つようにしましょう。

# 5. Google Fontsの応用例
5.1 複数のフォントを組み合わせる
Google Fontsでは、複数のフォントを同時に読み込むことが可能です。たとえば、見出しと本文で異なるフォントを使用することが一般的です。

```html
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&family=Lora:wght@400&display=swap" rel="stylesheet">

h1 {
  font-family: 'Lora', serif;
}

p {
  font-family: 'Roboto', sans-serif;
}
```

5.2 レスポンシブデザインへの活用
フォントサイズをレスポンシブに調整することで、モバイル端末でも見やすいレイアウトを実現できます。
```css
body {
  font-family: 'Roboto', sans-serif;
  font-size: 16px;
}

@media (max-width: 768px) {
  body {
    font-size: 14px;
  }
}
```

# 6. Google Fontsのメリットとデメリット
**メリット**
無料で使える：商用利用も無料。
種類が豊富：多言語に対応したフォントを多数提供。
Web最適化済み：ページ表示が高速化されるように工夫されている。
デメリット
一部のフォントは重い：日本語フォントなど、大量の文字を含むフォントはページの読み込み速度に影響することがある。
デザインの制約：提供されているフォントの種類には限りがある。

# 7. まとめ
Google Fontsは、簡単にWebサイトやアプリに美しいフォントを追加できる無料サービスです。多言語対応やシンプルな導入手順により、多くの開発者やデザイナーに利用されています。

フォントを正しく選択し、適切に活用することで、Webサイトの**ユーザーエクスペリエンス（UX）**を向上させ、ブランドイメージを強化することができます。次回のプロジェクトでは、ぜひGoogle Fontsを活用してみてください。

**毎日更新していますので、@y-t0910をフォロー、いいねしていただけると嬉しいです。**
「問題発見」できる人になる

## 本の内容(抜粋)
### 最も学びになったこと
「問題解決」ができるだけでなく、「問題発見」ができる人を目指していく必要がある。

### 問題解決と問題発見
* 問題解決
与えられた問題を適切な方法で解決すること。
問題を与えられる前提で、相手に逆らわない「優等生」が向いている。
→学校や従来の組織で評価を得やすい能力。<br><br>

* 問題発見
問題を発見して明確に定義すること。
そもそもの問題を疑ってかかり、自分の頭で考えられる人が向いている。
→従来の社会では評価を得にくかった能力。

### 問題発見の価値
AIの台頭やDXの高まりにより、「問題解決」よりも「問題発見」が求められるようになってきている。
→問題解決はAIでも可能な一方で、問題発見では人間の思考力が求められるため。
また、問題解決と問題発見では求められる能力が逆であり、学校などでは「問題解決」能力が評価される傾向にあった。
→思考力がある人は「問題発見」が得意な傾向にあり、今後の社会で評価される能力と言える。

## 所感
まさに、自分は「問題解決」の側にしか立てていない人間だと感じました。
→目的や方法がある程度与えられたうえでその条件に沿って進むということは比較的得意。
逆に、目的や方法を自分で判断して定義する必要がある状況では、どうすることが正しいのか分からなくなってしまう。
「問題発見」を能動的に行う姿勢が重要になってくる という言葉もあったので、「問題発見」できる人が備えている要素は何なのか を考えながら、まずは「問題発見」の作業に取り組む機会を増やしていきたいと思います。

## 本の情報
**タイトル**
入門『地頭力を鍛える』 32のキーワードで学ぶ思考法

**著者**
細谷 功

**内容**
思考力とは「自分の頭」で考えること。
思考力を身に着けるための32のキーワードを、定義や使い方と合わせて紹介する。
キーワード例：ロジカルシンキング / 二項対立 / メタ認知
AFLをdockerを使って動かす

# 動機
macでAFL動かそうと思ったら環境依存っぽいエラーが出たので「それならdocker使ってみよう」と思い立ちました
# やったこと
dockerコンテナ内で[AFL](http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz)を動かした

# ソースコード
[github](https://github.com/umiyuri777/AFL_in_docker)にあげました

# やり方
1. リポジトリをcloneしてくる
    
    ```sh
    git clone https://github.com/umiyuri777/AFL_in_docker.git
    ```

2. docker でビルド（コンパイルまで自動で行う）

    ```sh
    docker buildx build --platform linux/amd64 -t afl-in-docker .
    ```

3. dockerコンテナを起動

    ```sh
    docker run -itd afl-in-docker 
    ```

4. コンテナ内に入る

    ```sh
    # 起動したコンテナのコンテナIDを確認
    docker ps
    
    #コンテナの中に入る
    docker exec -i -t <確認したコンテナID> /bin/bash 
    ```

5. AFLを起動

    ```sh
    afl-fuzz -i test_in -o test_out -m none -- ./a.out
    ```

6. 止めて結果を見る

    ```sh
    # test_outフォルダの中に結果が入るようになってる
    cd test_out
    ```

7. 結果を利用して好きなように分析

# 出来なかったこと
- [IPAの資料７ページ目](https://www.ipa.go.jp/security/vuln/fuzzing/ug65p9000001986g-att/000081408.pdf)では、仮想環境内でRAMディスクを作成して方がSSDとかへのダメージが少ないとか書いてあったけどうまいこと行かなかった
（残骸がコメントアウトして残ってます）
- コンテナを起動するとそのままファジングも実行して、コンテナ終了した後にエクスプローラーから実行結果が見れるようにしたかった

# 参考
[ご注文は American Fuzzy Lop ですか？](https://qiita.com/binzume/items/8e985e7bd01a6e4000d3#%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89)

[AFL実践資料(AFL編)](https://www.ipa.go.jp/security/vuln/fuzzing/ug65p9000001986g-att/000081408.pdf)

[Dockerコンテナ上でAFLを実行できるようにした (ハズ)](https://hub.docker.com/r/yusakukato/afl-docker)

[dockerのコンテナの中に入る](https://qiita.com/Keitaroooo/items/a30bf4eb9310d7b3f7cd)

[Dockerのコンテナを起動したままにする](https://qiita.com/reflet/items/dd65f9ffef2a2fcfcf30)
react-router-domで "switch" が使えない？

### react-routerとは
Reactアプリケーションでルーティング(ページ間の移動)を管理するためのライブラリです。
異なるURLに応じて表示するコンポーネントを切り替えることができる。

### Switchとは
React Routerのコンポーネントの1つで、**<font color="Yellow">最初に一致したルートだけ</font>** をレンダリングする役割を持ちます。

### なぜ "Switch" が使えなかったか
一言でいうと**<font color="Yellow">バージョンの違い</font>**です。

"Switch"はバージョン５までの機能で、バージョン６以降は"Routes"に置き換わっています。

### npm install react-router-dom でインストールした人注意！
    npm install react-router-dom
上記でインストールすると、"Switch"が使用できないバージョンでインストールされる。

### 解決策：バージョンを確認し、<br>５までは"Switch",６以降は"Routes"を使いましょう。


### Routesの注意点
switchの場合は下記のように使用していたが、
```
<Switch>
  <Route path="/" >
    <Home/ >
  </Route>
</Switch>
```
しかしRoutesでは下記のように使用する。
```
<Routes>
  <Route path="/" element ={<Home/>}>
</Routes>
```
version6では、<Routes>の中に配置できる要素は<Route>コンポーネントまたは<React.Fragment>だけです。
<Routes>の子要素としてコンポーネントを直接渡すことはできません。代わりに、<Route>のelementプロパティにコンポーネントを指定する必要がある。


## 
参考サイト　
https://youonly.net/react-router-dom-switch/#toc1
実機にふれてみよう VLAN間の疎通(Ciscoスイッチ)

基本ですが、VLANの設定をしていきます。
VLAN100とVLAN200の通信制限を検証していきます。

同じネットワーク内に〇〇部と△△部が存在して、
〇〇部が「△△部に大事なデータを見られたくないよ〜
な状況をイメージしています。

# 使用するもの
- PCA(192.168.1.20)
- PCB(192.168.1.30)
- Ciscoスイッチ
- Ethernetケーブル
# 物理的な接続
物理的な接続はこちらと変わりません。
(VLAN設定していない比較としても参考に)
https://qiita.com/kawano-y/items/2d31e71ae3fef8453a79
# VLAN設定
- VLAN100：Fa0/1
- VLAN200：Fa0/2
VLANを作成→希望するポートを作成したVLANに割り当てるイメージです。

VLAN100のみ設定する場合

特権EXECモードへ
``enable``
グローバルコンフィギュレーションモードへ
``configure terminal``
VLAN100の作成
``vlan 100``
設定を終了
``exit``
ポートコンフィギュレーションモードへ
``interface FastEthernet0/1``
ポートをVLAN100に割り当てる
``switchport mode access``
``switchport access vlan 100``

![vlan設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3803710/6ca77d20-0d65-aaee-ef53-01148cec49c4.png)
# VLANの確認
設定できているか確認しましょう
特権EXECモードから
``show vlan brief``
![ブリーフコマンド.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3803710/7a2c7d63-3942-c826-bf45-c59e745a18b6.png)
# 疎通確認
PCAからPCBにpingコマンドを実行してみましょう
![VLAN ping.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3803710/e63a2cfc-5412-bd55-81ef-8f5088c087e6.png)
通信ができていないことが確認できました！
# 最後に
VLANの仕組みや設定について、初めてネットワークを学習した時に理解できなかったことを思い出しました。
簡単な設定ですが、もう絶対に忘れたくない・・・という気持ちが入っています。
これで○○部は△△部にデータを見られないので安心ですね♪
まぁ私しか触らないのですが・・・
PHPでcsvファイルのすべての値にダブルクォーテーションをつける

## はじめに
こんにちは。
気分転換したくて全然業務と関係ないし、需要も無さそうな記事を書きました。
5分で読めます。

## ところでcsvファイルって何

恥ずかしながらIT業界に入るまでcsvというファイル形式を知らずに生きてきました。

:::note info
CSVファイルとは、Comma Separated Valuesの略で、各項目がカンマ（,）で区切られたテキストデータのことです。
データの容量が軽く、読み書きや編集が容易であるという特徴があります。
:::

[こちらの記事](https://am.arara.com/blog/028)が大変分かりやすいです。感謝。

## 本題

案件でcsvファイルを使ってのデータのインポート機能を作ったのですが、csvファイルはダブルクォーテーションで囲まれている必要がありました。
ただ、インポートするためのcsvファイルをExcelで開いて編集するとダブルクォーテーションが消えてしまうということを経験しました。
（常識なのかもしれません。ポンコツですみません）

テキストエディタで置換する方法は結構あったのですが、だるすぎたのでPHPでやってみたいなと思い作ってみました。

```php:quote_double.php

<?php

$inputFile = $argv[1];  // 読み込みたいCSVファイル名
$outputFile = 'output_' . $argv[1]; // 出力するCSVファイル名


// 入力ファイルを開く
if (($inputHandle = fopen($inputFile, 'r')) !== FALSE) {
    // 出力ファイルを開く
    if (($outputHandle = fopen($outputFile, 'w')) !== FALSE) {
        // 入力ファイルの各行を読み込む
        while (($row = fgetcsv($inputHandle)) !== FALSE) {
            // 各フィールドを強制的にダブルクォーテーションで囲む
            $quotedRow = array_map(function($field) {
                return '"' . str_replace('"', '""', $field) . '"';
            }, $row);

            // 行全体をCSVフォーマットとして出力
            fwrite($outputHandle, implode(',', $quotedRow) . "\n");
        }

        // 出力ファイルを閉じる
        fclose($outputHandle);
    }

    // 入力ファイルを閉じる
    fclose($inputHandle);
}

echo "完了したよ！\n";

```

以下コマンドで実行します。

```php
php quote_double.php <ダブルクオーテーションをつけたいcsvファイルのパス>

// 例
php quote_double.php sample.csv
```


## 結果

変換前
```text:sample.csv
1,2,3,4,5,6
ゲンガー,ミミッキュ,ムウマージ,ヨノワール,ユキメノコ
```


変換後
```text:output_sample.csv
"1","2","3","4","5","6"
"ゲンガー","ミミッキュ","ムウマージ","ソウブレイズ","ユキメノコ","コレクレー"
```

output_sample.csvが作成され、すべての値がダブルクォーテーションで囲まれました！
やったね！
Storybookのストーリー数を取得する方法

## 背景

- 運用中のStorybookのストーリー数が知りたかった。
- でもGoogleで検索したりChatGPTに聞いたりしても、知る方法を見つけられなかった。
    - (ChatGPTは近いことを教えてくれましたが、Storybook6系以前の方法となっていたため断念)
- 対象は100件以上が存在するため、自分で数えるのは難しい。そこで自作プログラムを書いてみることにした。

※ ここでの"ストーリー"とは`*.stories.js`に`export const Primary = {}`のように書いている記述のことです。
## 注意書き

- 正攻法ではありません。「役立ったらラッキー」くらいでお願いします。

## 動作確認した環境

記事を投稿した時点の最新バージョンです。

- Node: `22.9.0`
- storybook: `8.3.5` (恐らく7〜8系なら動きます)

## 手順

1. Storybookの静的ファイルを生成する
2. 生成された`index.json`に記述されている`"type": "story"`を数える

### 1. Storybookの静的ファイルを生成する

以下を実行すると`storybook-static`に静的ファイルが生成されます。
(Storybookのマニュアル通りにセットアップしてある場合)

- npmの場合: `npm run build-storybook`
- yarnの場合: `yarn build-storybook`

### 2. 生成された`index.json`の`"type": "story"`を数える

ここでは生成された`storybook-static/index.json` というファイルを使用します。
このファイルには全てのストーリーやドキュメントなどの情報が記述されています。ここから`"type": "story"`と書かれている記述を数えていきます。

以下のJavaScriptを実行するとストーリー数を取得することができます。
ここでは`node -e '${JavaScriptのコード}'`によって実行していますが、JavaScriptの実行方法は任意です。

```bash:bash
node -e '
const jsonData = require("./storybook-static/index.json");
let storyCount = 0

if (jsonData.v !== 5) {
  console.log("動作確認していないバージョンです。動作しない可能性があります。");
}

for (const key in jsonData.entries) {
  if (jsonData.entries[key].type === "story") {
    storyCount++;
  }
}

console.log(`ストーリー数: ${storyCount}`);
'

# (実行結果の一例)
# ストーリー数: 8
```

### `index.json`の内容

ちなみに`index.json`の中身は以下のようになっています。

<details><summary>storybook-static/index.json</summary>

```json:storybook-static/index.json
{
  "v": 5,
  "entries": {
    "atoms-button--docs": {
      "id": "atoms-button--docs",
      "title": "Atoms/Button",
      "name": "Docs",
      "importPath": "./src/components/atoms/Button/Button.stories.ts",
      "type": "docs",
      "tags": ["dev", "test", "autodocs"],
      "storiesImports": []
    },
    "atoms-button--primary": {
      "type": "story",
      "id": "atoms-button--primary",
      "name": "Primary",
      "title": "Atoms/Button",
      "importPath": "./src/components/atoms/Button/Button.stories.ts",
      "componentPath": "./src/components/atoms/Button/Button.tsx",
      "tags": ["dev", "test", "autodocs"]
    },
    "atoms-button--secondary": {
      "type": "story",
      "id": "atoms-button--secondary",
      "name": "Secondary",
      "title": "Atoms/Button",
      "importPath": "./src/components/atoms/Button/Button.stories.ts",
      "componentPath": "./src/components/atoms/Button/Button.tsx",
      "tags": ["dev", "test", "autodocs"]
    }
  }
}
```
</details>

## (余談) なぜストーリー数が必要になったのか

Chromaticの導入検討にあたって、ストーリー数(＝1回のビルドで撮影されるスナップショット数)を使用して月額費用を試算したかったためでした。
ぷよぷよsteam版でAIを動かす

![スクリーンショット 2024-10-09 22.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/8ce41d48-9b49-f992-e0a7-e85bd2cf3976.png)

https://qiita.com/educational-ai/items/a474449f2ca2093ca778

https://qiita.com/educational-ai/items/59642e9a6900b764be6d

https://qiita.com/educational-ai/items/426bc6460a4eb2da879a

https://qiita.com/educational-ai/items/c8df71eb574919da2d0e

4つの記事をまとめたものになります。

## 準備編
### パソコンの準備
　windows、Macのパソコンを準備します。Linuxは注意が必要です。steamが動くか確認しましょう。  
　steamがchromebookにどこまで対応しているのか分かりません。ipadとスマホも同じです。ipadとスマホは、対象外と考えたほうが賢明です。

### ぷよぷよsteam版の購入

こちらから購入できます。

https://store.steampowered.com/app/971620/_e/?l=japanese


### pythonをPCにインストール
　macOSは既にインストールされているので不要です。windowsは、直接インストールするのが楽です。anacondaは微妙です。wslはpyautoguiで画面取得できませんでした。  
　wslがダメなのは、windowsからみると仮想環境なので、windows画面情報を渡せないためと推測されます。  

　windowsへのpythonインストールは、こちらのサイトにまとめてあります。

https://qiita.com/educational-ai/items/219939e278fccef42842

### VS codeのインストール（推奨）
　開発環境として便利です。特にjupyter labを起動しなくても、jupyter notebookを編集・実行できるので、推奨します。

### python libraryのインストール

```
> pip install numpy pyautogui pillow keyboard opencv-python pygetwindow
 
```
仮想ゲームパッドを使用するならば、vgamepadが良さそうです。

## 実行編

https://qiita.com/educational-ai/items/59642e9a6900b764be6d

https://qiita.com/educational-ai/items/426bc6460a4eb2da879a

https://qiita.com/educational-ai/items/c8df71eb574919da2d0e

3つの記事を参考にすれば、ゲーム画面から欲しいデータを取得できます。チュートリアルを参考にして、AIを作るといいでしょう。

https://qiita.com/educational-ai/items/88feaf91bdda0b5e0d25


## 実行にあたっての注意点
### 画像と動画の公開
ぷよぷよesportsのプレイ動画規約があります。

https://puyo.sega.jp/PuyoPuyo_eSports/agreement/index.html

### ぷよぷよeSportsへの配慮

https://esports.sega.jp/puyo/

ぷよぷよeSportsは、人が動かして楽しむeスポーツ大会を主催しています。  
その参加資格として、スコアアタックを活用していました。
人工知能が簡単に、人の能力を超えてしまうのは、将棋などを観てもよく分かります。
いろいろなテストでも、人工知能の禁止が言われています。

先行する３つの記事の内容は、webサイトで調べればすぐに分かるものばかりです。それでも、組み合わせてキレイに並び替えて、使いやすくしすぎると、容易に偽装することができるでしょう。  
これは、テストのカンニングに近い行為であり、ぷよぷよeSportsには好ましくない行為だと思います。  

ゲームの自動処理は、個人で楽しむのはいいけれど、公開などに当たっては十分な注意が必要です。

***

![puyopuyo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900427/1fdf8221-96c5-fcfa-3a52-383422a6fdc3.gif)
　ぷよぷよプログラミングAI学習システムは、中高生の自己調整学習に向けて開発されました。
　どうやって、Chromebookで、１０分で、素敵な人工知能を作れるのでしょうか？
　秘密は、３つ。
　１　jupyter liteで、webクライアントがpythonコードを実行
　２　超軽量な機械学習フレームワークdezeroを採用
　３　ぷよぷよのstageとactionがコンパクト

### Github&X

https://github.com/Lunanaedu/jupyterlite-puyopuyo

https://github.com/Lunanaedu/puyopuyo-kai

https://x.com/educationai_ai

### ぷよぷよプログラミングAI学習用まとめ

https://qiita.com/educational-ai/items/50c0fa689c01794d145e
cannot import name　の解決方法一覧　（特に別フォルダのモジュールを参照したい時）

# cannot import name　の解決方法一覧
**cannot import name**エラーが発生したら、まず疑うべきは循環参照（circular import）の発生です。Qiitaで**cannot import name**を検索すると大体循環参照が出てきますし、大体循環参照が原因です。
その他考えられる原因は、
1 インポートするファイル名と、Pythonの標準ライブラリや既存のモジュール名が同じ場合
2 スペルミス
3 相対パスのミス
4　モジュールの定義の順序によって、インポートされる側のモジュールがまだ完全に初期化されていない場合
5 古いバージョンのPythonまたはライブラリを使用している
6 モジュールや関数が存在しない
くらいですかね。ほかにあったら教えてください。

今回詳しく説明するのは、別のフォルダのモジュールを参照しようとしてしまっているケースです。
# 別フォルダのモジュールを参照したいとき（本題）


## まずなぜ他フォルダのモジュールを参照できないか
pythonは怠け者なので、通常、以下の場所でのみモジュールを探します。
**・現在の作業ディレクトリ（実行中のスクリプトのディレクトリ）
・sys.pathにリストされているディレクトリ
・PYTHONPATH環境変数に指定されたディレクトリ**
なので、野生のフォルダに含まれるファイル内のモジュールを自動で参照することはありません。

## ではどうするか
色々方法があります。ただ手動でsys.pathに入れたり、現在の作業ディレクトリにわざわざファイルを新しく作ったりは面倒なので、簡単な方法だけを紹介します。ちなみにVSCodeを使ってるので、他だとまた変わるかもしれません。


1 ルートディレクトリに「.vscode」という名前のフォルダを作る。フォルダ内に「settings.json」ファイルを作る
 「settings.json」ファイルの中身は↓　
（FOLDERNAMEを参照したいコードの位置するフォルダの名前に変えてください）
```json:settings.json
{
    
    "python.analysis.extraPaths": [
        "./FOLDERNAME" 
    ]
}
```

2 使いたいコードの頭に↓のコードを入れたら完成。（CLASS１を実際に使いたいクラス、関数名、変数等に置き換える。）
```python:Test.py
sys.path.append(r'FOLDERNAMEの絶対パス')
from FOLDERNAME import CLASS１
```

こうすることで、Test.py実行時にpythonはFOLDERNAME内も検索するようになって、エラーが解消されます。

## まとめ
多分ほかにもいい方法があるのかもしれないし、VScode以外だとまた方法も違ってくると思うので、今後追加するかもしれません。
Markdown AIを使ってお薦めの高校の総合英語本を挙げていただきました

# はじめに
Markdown AIを使って、高校生向けの総合英語参考書を5冊挙げてくれるプロンプトを作り、実行しました。

## プロンプトの内容
プロンプトの内容は以下です。
>高校の総合英語参考書を5冊挙げてください

## プロンプトの結果

プロンプトの結果です。

以下は高校生向けの総合英語参考書の例です： 
**『総合英語 Evergreen』** 
- 英文法や語彙、リーディング、リスニングなど幅広くカバーしている参考書です。 

**『総合英語 Forest』** 
- 文法や表現を体系的に学ぶことができる、定評のある参考書です。

**『英語総合問題集』** 
- 各種問題を通じて実践的な英語力を養うための問題集です。 

**『英語の基礎がしっかり身につく本』** 
- 基礎から応用まで段階的に学べる参考書で、特に文法に重点を置いています。 
 
**『英語表現の基礎』** 
- 英語の表現力を高めるための参考書で、実際の会話や文章作成に役立つ内容が含まれています。 これらの参考書は、文法、語彙、リーディング、リスニングなど、英語の総合的な力を向上させるために役立ちます。

## 実行結果のスクリーンショット
スクリーンショットの内容です

![result.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055346/c2c2b853-af25-88d4-384d-33c40232a76d.jpeg)

# 最後に
Markdown AIを使ってみました。
Windows11 曜日を追加する方法

　年金生活をしていると、日にちというのはほとんど気にならないけど、曜日は気になるんです。木曜日は近くの八百屋さんが休みとか。

 ### こんな複雑な仕様を作ったのは誰？

 　タスクバーには、デフォルトでは時刻と日付けが表示されていますが、曜日がないです。

  画面右下の日付の項目を右クリックし「日時を調整する」をクリックします。
  （画面ではすでに曜日は追加されています）

<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/4e3cb0ac-178d-5081-75d6-5cc9ef567513.png">
  

  
  　一番下にある その他の時計 をクリックします。
   
   ![date102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/f91c481a-be09-705e-c2c4-37514a3f8271.png)

   日付と時刻 タブをクリックし、その画面の 日付と時刻の変更（D）をクリックします。
   

   <img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/56829710-6f7c-acdc-948c-62552c6044be.png">


　出てきた画面の左下の カレンダーの設定の変更 をクリックします 

<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/164d734b-fd98-bbc6-6506-ff15b7f29e12.png">


　日付（短い形式）(S) のyyyy/MM/ddの後ろに/ddddを追加して、OKを押して、たくさんの画面を閉じていくと、曜日が追加されているのが確認できます。

<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/3fae0619-9c27-7dcb-fd99-cca902c18433.png">



　Windows10では、2024/10/17が24/10/17だったので、みやすくなりました。
cline (旧：Claude-dev) 向けPowerShellシステムプロンプトの開発

## 概要

cline（旧：Claude-dev）の機能を拡張し、Windows環境でのPowerShellサポートを実現するための新しいシステムプロンプトを開発しました。この更新により、WindowsユーザーもPowerShellを通じてclineの高度な機能を活用できるようになりました。

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">OpenAI Swarm要件定義書✖cline (旧：Claude-dev)でSwarmのコード一式を作成してもらった！<br>なんか普通に良さそうだぞ！<br>これでcompany as languageに一歩近づいたか！！！ <a href="https://t.co/8IM12VN3MD">https://t.co/8IM12VN3MD</a> <a href="https://t.co/6fNES7FKro">pic.twitter.com/6fNES7FKro</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1846872209924804667?ref_src=twsrc%5Etfw">October 17, 2024</a></blockquote> 

## 主な特徴

1. **PowerShellへの対応**: Windows環境でのclineの使用が可能になりました。

2. **コマンド連結の最適化**: PowerShellの仕様に合わせて、コマンドの連結方法を変更しました。
   - `&&`の代わりに`;`を使用してコマンドを連結します。
   - 例: `command1; command2; command3`

3. **トークン数の節約**: コマンドを連結して一括実行することで、APIリクエストの効率化とトークン使用量の削減を実現しました。

4. **日本語サポート**: システムプロンプトに日本語での応答を指示し、日本語ユーザーの利便性を向上させました。

5. **Git操作の強化**: 
   - ファイル変更時の自動コミット機能を実装
   - 絵文字を用いた視認性の高いコミットメッセージの生成
   - Gitflowに基づいたブランチ戦略とコミットルールの導入

## システムプロンプトの主要コンポーネント

1. **言語設定**: 日本語での応答を基本とします。

2. **Git操作**:
   - ファイル変更時の自動コミット
   - 絵文字を含む日本語のコミットメッセージ
   - 必要に応じたブランチ作成の提案

3. **PowerShell環境設定**:
   - コマンド連結にはセミコロン(`;`)を使用
   - PowerShell固有の制約を考慮したコマンド構築

4. **Gitコミットルール**:
   - Gitflowに基づいたブランチ戦略
   - 定型化されたコミットメッセージ形式
   - コミットタイプの明確化（feat, fix, docs など）

## 利点

1. **Windows環境での完全サポート**: PowerShellを通じてclineの全機能が利用可能に。

2. **効率的なコマンド実行**: コマンドの連結により、複数の操作を一度のリクエストで実行。

3. **トークン使用量の最適化**: 効率的なコマンド構造により、APIコストを削減。

4. **日本語ユーザーの使いやすさ向上**: 日本語でのレスポンスにより、理解と操作が容易に。

5. **一貫性のあるGit操作**: 標準化されたコミットメッセージとブランチ戦略により、プロジェクト管理が向上。


## プロンプト

https://github.com/Sunwood-ai-labs/MysticLibrary/blob/main/prompts/coding/CLAUDE-DEV-SYSTEM-PROMT-PS.md

## まとめ

この新しいPowerShell用システムプロンプトの開発により、cline（旧：Claude-dev）はWindows環境でより強力かつ効率的なツールとなりました。PowerShellの特性を活かしたコマンド構造の最適化と、日本語サポートの強化により、幅広いユーザーにとってアクセシブルなAI開発アシスタントとなっています。今後も継続的な改善を行い、より多くの開発者のニーズに応えていく予定です。


<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【Java】Stringクラスのメソッド

## startWith

文字が特定の文字で始まるかを判定するメソッド。戻り値はboolean型。

```Java
public static void main(String[] args){
  String sample = "abcd";
  boolean target = sample.startWith("a");
  System.oout.println(target); // true
}
```

## endWith

特定の文字で終わるか判定し、boolean型を返す

```Java
public static void main(String[] args){
  String sample = "abcd";
  boolean target = sample.endWith("d");
  System.oout.println(target); // true
}
```

## indexOf

StringのindexOfメソッドを使用する

```Java
class Test{
  public static void main(String[] args){
    String text = "あいうえお";
    int target = text.indexOf("あ");
    System.out.print(target); // 0
  }
}
```

もし該当の文字列が存在しない場合は-1を返す。

```Java
class Test{
  public static void main(String[] args){
    String text = "あいうえお";
    int target = text.indexOf("あほ");
    System.out.print(target); // −１
  }
}
```

## replace

文字の置き換えを行うメソッド。よく使うのは空欄削除など。

```Java
public static void main(String[] args){
  String sample = "Hello World";
  sample = sample.replace(" ", "");
  System.out.println(sample); // HelloWorld
}
```

## substring

特定の文字を抽出することができる。

第一引数に開始点、第二引数に終了点を指定する。第二引数を指定しなかった場合は、第一引数から後ろすべてが抽出の対象となる。

(n, m) であれば、n + 1文字目からm文字目までを抽出することになる

```Java
class Test{

public static void main(String[] args){

	String text = "Hello World"; //　最初の文字は0番目扱い
	String target1 = text.substring(0,5); // Hello
	String target2 = text.substring(6); // World
	String target3 = text.subString(0,text.indexOf(" ")); //Hello
	
	}
}
```

## valueOf

受け取った値を文字列に変換する。

```Java
public static void main(String[] args){
  private int value = 1;
  String valueString = String.valueOf(value);
  System.out.println(valueString instanceof String); // true
}
```

## concat

文字の連結に使用するメソッド。stringBuilderクラスにはappendメソッドが存在するので、間違えないように。

```Java
public static void main(String[] args){
  String sample = "abc";
  sample = sample.concat("efg");
  System.out.print(sample); // abcdef
}
```

## contains

Stringのcontainsメソッドを用いる。結果はbooleanを返す。

```Java

class Test{
  public static void main(Streing[] args){

    String text = "Hello World";
    System.out.print(text.contains(" ")); // true
  }
}

```

## charAt

特定の文字を１文字抜き出す。

```Java
public static void main(String[] args){
  String sample = "abcde";
  sample.charAt(3); // d
}
```
なぜChatGPTではなくAI回答エンジンなのか？

AI技術は私たちの生活のあらゆる場面に深く根付いています。生成AI(ChatGPT、Claude、MS Copilot、Google Gemini)は私たちの生活で広く活用されており、メール作成、コード生成、創造的な文章作成、各種法律文書の分析、契約書の作成など、様々な面で大きな助けとなっています。しかし、日常生活における法律問題のような複雑な状況では、生成AIの限界は明らかです。生成AIは創造的なコンテンツの生成には強みを持っていますが、現在のデータを基にリアルタイムで変化する情報を反映することには制約があります。特に、法律分野では新しい判例や法改正など、正確で最新のデータを反映することが非常に重要です。さらに、生成AIは結果の出典を明確に示さないことが多く、情報の信頼性に疑問が投げかけられることもあります。

このような理由から、AI回答エンジンである「Perplexity AI」が登場し、その役割が次第に重要になってきています。AI回答エンジンは、既存の膨大なウェブサイトを活用してユーザーの質問に正確な答えを提供し、リアルタイムで変化する情報も迅速に反映できる能力を持っています。

AI回答エンジンは、法律分野だけでなく、大学入試、健康など、リアルタイムの回答が求められる様々な分野で卓越した性能を発揮します。例えば、大学入試では急速に変化する入試政策や各大学の選抜情報をリアルタイムで反映し、受験生に最新のカスタマイズされた情報を提供できます。健康分野では、最新の医学研究の成果や治療法を反映した正確な情報を提供できるため、ユーザーが信頼できる健康情報を得るのに役立ちます。
このように、AI回答エンジンは、日常生活における法律問題のような複雑な状況だけでなく、リアルタイムの情報更新が重要な様々な分野で中心的な役割を果たしています。ユーザーは、これを通じて迅速かつ正確な情報を得ることで、より良い意思決定ができるようになりました。

AI回答エンジンの基本原理と活用について説明します。

AI回答エンジンは、簡単に言えばユーザーの質問に対して最適な回答を提供するシステムです。代表的なAI回答エンジンとして「Perplexity AI」サービスがあります。例えば、ユーザーが「賃貸借契約の更新請求権の行使期間はいつですか?」と質問すると、Perplexity AIは膨大なデータを基に借地借家法の関連条項や最新の改正事項を反映した正確な回答を提供します。

AI回答エンジンと生成型AIは目的と動作方式に違いがあります。生成型AIは新しいコンテンツを作り出すことに重点を置いています。例えば、特定の法律事例に対する仮想のシナリオを作成したり、法律文書の草案を作成したりすることが可能です。一方、AI回答エンジンは既存の膨大なデータベースから最も適切な情報を見つけて提供する役割を果たします。
AI回答エンジンはリアルタイムで情報を処理できる点で非常に有用です。法律は継続的に改正され新しい判例が生まれるため、最新の情報を反映することが重要です。例えば、最近改正された労働基準法について質問すると、AIはこれらの変更事項をリアルタイムで反映してユーザーに最も適切な回答を提示します。

AI回答エンジンはまた、個別化された情報を提供する強みを持っています。各ユーザーの状況、関連法律、地域などを総合的に分析し、個人に合わせた最適な法律情報を提示します。例えば、東京に住む賃借人が賃貸借契約に関する質問をした場合、AI回答エンジンは東京都の特定条例や政策、そして最近の判例などを考慮してカスタマイズされた回答を提供できます。

AI回答エンジンは生成型AIとは異なり、情報の出典を明確に示すことで結果の信頼性を高めます。例えば、Perplexity AIは回答に使用された法律、判例、ニュース記事などの出典を一緒に提供し、ユーザーが情報の正確性を直接確認できるようにします。これは生成型AIでしばしば発生する「幻覚」現象、つまり事実でない情報をあたかも事実であるかのように提示する問題を防ぐのに役立ちます。

[Perplexity AI の 活用 法律問題解決編: 日常生活の法律問題、 AI回答エンジンで解決] - https://amzn.to/3Uamhx2
Vue.js3で「ctrl+z」「ctrl+shift+z」の処理を実装する

# 経緯
先日Undo/Redo機能の実装をする機会がありました。
ついでにショートカットキーで実装できないものかChatGPT 4oに聞いたところ教えてくれたので備忘録として残します。

# 実装

```
<script setup>
import { onMounted } from "vue";

// キーボードショートカットのハンドラー
// ※undo(), redo()の中身の処理は省略
const handleKeydown = (e) => {
    if (e.ctrlKey || e.metaKey) {
        if (e.key === 'z') {
            undo(); // Ctrl+Z (Undo)
        } else if (e.key === 'Z') {
            redo(); // Ctrl+Shift+Z (Redo)
        }
        e.preventDefault(); // デフォルトの動作を無効化
    }
};

// イベントリスナーを登録する
onMounted(() => {
    window.addEventListener('keydown', handleKeydown);
});

</script>
```

# 参考記事

- [JavaScriptにおけるfunction(e)の「e」とは何なのか？](https://qiita.com/wada1355/items/05aba1f1be2b467abc85)
- [KeyboardEvent: key プロパティ](https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent/key)
190日目 CloudFormationでAWSbackupを設定してみた 社畜L

## 🔍前置き
皆さんAWSbackup使ってますか？
AWSbackupは名前の通りAWSにおける様々なリソースのバックアップをサポートしてくれる便利な機能です。
今回はそれをCloudFormationで構築する機会があったので記事にしてみました。

## 🔍早速CloudFormationテンプレート全文
まず何はともあれタイトルにもある通りCloudFormationテンプレート(.yml)を見せます。
簡単に説明すると
バックアップボールト、バックアッププラン、バックアップルール、IAMロール
が作成されます。
```yaml
#バージョン指定
AWSTemplateFormatVersion: "2010-09-09"

#スタックの説明(コメント)
Description:
  Create_BackupPlan

#パラメータ
Parameters:
  #BackupRoleName
  BackupRoleName:
      Type: String
      Default: Backup-Role
      
  #BackupRule_name
  BackupRuleName:
    Type: String
    Default: BackupRule

  #BackupVault_name
  BackupVaultName:
    Type: String
    Default: BackupVault
  
  #BackupPlan_name
  BackupPlanName:
    Type: String
    Default: BackupPlan

  #Date
  storageday:
    Type: String
    Default: 15 #保管日数15日(max35日)

  #backupstart
  backupstart:
    Type: String
    Default: cron(0 16 * * ? *)  # 日本時間１時からバックアップ

  #BackupTag
  Backuptag:
    Type: String
    Default: Backup #バックアップしたいリソースにつけるタグ
    
  #Backupkey
  Backupkey:
    Type: String
    Default: true  #タグにつけるキー

#リソースの定義
Resources:
  BackupRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName : !Ref BackupRoleName
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - backup.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup
        - arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores
        - 
  Vault:
    Type: AWS::Backup::BackupVault
    Properties:
      BackupVaultName: !Ref BackupVaultName

  Plan:
    Type: AWS::Backup::BackupPlan
    Properties:
      BackupPlan:
        BackupPlanName: !Ref BackupPlanName
        BackupPlanRule:
          - RuleName: !Ref BackupRuleName
            TargetBackupVault: !Ref Vault
            ScheduleExpression: cron(0 16 * * ? *) 
            StartWindowMinutes: 60 
            Lifecycle:
              DeleteAfterDays: !Ref storageday

  BackupSelection:
    Type: AWS::Backup::BackupSelection
    Properties:
      BackupPlanId: !Ref Plan
      BackupSelection:
        SelectionName: BackupSelection
        IamRoleArn: !Ref BackupRole
        ListOfTags:
          - ConditionType: STRINGEQUALS
            ConditionKey: !Ref Backuptag
            ConditionValue: !Ref Backupkey
    DependsOn: Plan
```
## 🔍使い方
難しい仕様なんかは抜きにして…まずは使い方！
デフォルトで全部入れてあるので、
名前や保管期間など変更したいものを変更してCloudFormationを実行してください！
無事作成されたら、バックアップを取りたいリソースにBackuptagでつけたタグをつけて
Backupkeyで指定したキーをつけてください！
それだけで自動的にバックアップが行われて、バックアップボールトに保管されます！

どのリソースでもAWSbackupがサポートさえしていればバックアップ可能です！

## 🔍AWSbackupの細かい仕様
ここはどういう理屈でって話になるので、もういいよって人は読み飛ばしてもらって大丈夫です。
AWSbackupは簡単に言うと、AWSbackupの**バックアップルールの持つタグ**と同じタグを持つリソースのバックアップをその**リソースにあったバックアップ形式を自動で判断**しバックアップを行ってくれる機能です。
そのためユーザーはバックアップの種類を意識することなくバックアップを管理できます。

## 🔍まとめ
今回はAWSbackupについてまとめました。
AWSbackupはかなり簡単に使えるのに役立つサービスなのでぜひ使ってくださいね！
GitHub Actionsでスケジュールされたバッチ処理の自動実行

毎朝6時にsupabaseのテーブルを自動でリセットしたい！ということで
①毎朝6時にトリガーされる.ymlで
②supabaseの指定したテーブルを全部削除する.tsを実行することにしました

```yml:①最終的に書いたコード
name: Delete Users Batch

on:
  workflow_dispatch:' # 手動でトリガーして動作を確認するため
  schedule:
    - cron: '0 6 * * *' # 毎朝6時に実行

jobs:
  delete-users:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm install

      - name: Delete all users
        env:
          VITE_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
          VITE_SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
        run: npx tsx batch/index.ts
```

```ts:②最終的に書いたコード
import { createClient } from '@supabase/supabase-js';

// Supabaseクライアントの作成
const supabaseUrl = process.env.VITE_SUPABASE_URL!;
const supabaseKey = process.env.VITE_SUPABASE_ANON_KEY!;
const supabase = createClient(supabaseUrl, supabaseKey);

async function deleteAllData() {
  try {
    // user_skillテーブルの全データを削除
    const { error: userSkillError } = await supabase
      .from('user_skill')
      .delete()
      .not('id', 'is', null); // idがnullでない行を削除

    if (userSkillError) {
      throw userSkillError;
    }

    // usersテーブルの全データを削除
    const { error: usersError } = await supabase
      .from('users')
      .delete()
      .not('user_id', 'is', null); // user_idがnullでない行を削除

    if (usersError) {
      throw usersError;
    }

    console.log('All data from users and user_skill tables deleted successfully.');
  } catch (error) {
    console.error('Error deleting data:', error);
  }
}
// 関数の実行
deleteAllData();
```
## 完成までにした試行錯誤
```yml:
run: npx ts-node --esm batch/index.ts
# だとTypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" のようなエラーが出るので
run: npx tsx batch/index.ts　
# にした
```
TypeScriptでNode.jsアプリケーションを実行する方法としてts-nodeを使用しようとしていましたが
esm形式として認識させるオプションを付けても.tsファイルをesmとして認識してくれません。
パッケージの詳細情報を確認しましょう。

```
npm info ts-node
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784604/7fcf68c9-26e6-cf10-fcfd-48b77e6eeec1.png)

今回はNode.jsのバージョンが18だったためts-nodeは互換性がありませんでした。
そのため、.tsファイルでもesmとして実行できるケースが多いtsxを使用しました。
【Amazon Connect Customer Profiles】データソースの統合

### はじめに
Customer Profilesは、Amazon Connect（コールセンターサービス）で使用できる顧客情報の集約サービスです。例えば、顧客の電話番号や氏名、性別、過去の問い合わせ履歴などの情報を、顧客からの着信時に表示することができます。個人的にはAmazon ConnectのCRM（顧客関係管理）だと思っています。
本記事では顧客情報のデータソース統合について紹介します。

## 本記事の注意点

本記事では以下のように使い分けをしています。

- **Customer Profiles**：サービスの名称
- **顧客情報**：Customer Profilesに登録する顧客データ


### 統合できるデータソース

Customer Profilesは、さまざまなデータソースと統合することで、顧客情報を一元管理できます。主なデータソースは以下の通りです。

- **Amazon S3**
- **Salesforce**
- **ServiceNow**
- **Zendesk**
- **Marketo**
- **カスタムコネクタ**

#### 注意点
一部データソースとの連携はAppFlowを利用して実施することになります。
AppFlowには処理できるデータ量に制限がありますので、ご注意ください。

https://docs.aws.amazon.com/appflow/latest/userguide/service-quotas.html

## 実際のデータソース統合の方法

### 注意点
以下はAmazon Connectインスタンス作成やCustomer Profilesの有効化設定がされていることを前提としております。
また、データソースはS3を例としております。

### 統合の手順
1. S3配置するデータの作成
1. データの配置
1. データソースの統合を追加

### データの作成

S3に配置するデータはCSV形式で作成します。
UTF-8でエンコードします。

### CSVデータの配置

S3にCSVデータを配置します。
オブジェクト構成は任意で問題ありません。

S3に顧客情報を配置するため、セキュリティや権限の最小化は考慮する必要があります。

#### データサンプル
| AccountNumber | PartyType  | FirstName | BirthDate | Gender | PhoneNumber  | EmailAddress  | Address1  | Address2       |
|---------------|------------|-----------|-----------|--------|----------------|-------------------|---------------|----------------|
| 001 | INDIVIDUAL | ウフル| 1999/1/1  | 男 | +815017431945  | customerprofiles@test.jp   | 〒111-2222 | 東京都港区1-1-1 |

### データソース統合を追加

Amazon Connectインスタンスのサイドバーの「お客様のプロフィール」をクリック

下部にある「データソースの統合を追加」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717693/ebbb4ef1-1d32-17df-a530-07dd7a4eceb1.png)


データソースでS3を選択し、S3に配置したCSVファイルを選択
![スクリーンショット 2024-10-16 161951.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717693/537ea62f-6e96-9c30-bbb9-a8039b3ca85a.png)


マッピングで「マッピングを自動生成」を選択
![スクリーンショット 2024-10-16 162025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717693/2afeb5be-5dbb-85c7-3fa8-5186d7b5b242.png)

マッピングが正常に生成されたことを確認し、「データソース統合を追加」をクリック
![スクリーンショット 2024-10-16 162204.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717693/e8c9e769-031d-0672-0696-eefbc46159a2.png)


データソースの統合に「Amazon S3」が表示されていること、ステータスが保留中になっていることを確認
![スクリーンショット 2024-10-16 162230.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717693/6b0c0ed4-2ad5-b6c0-9564-c8c2e03b7337.png)


数分すると、ステータスが「アクティブ」に変わります。
![スクリーンショット 2024-10-16 162853.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717693/d3ca912d-153b-41ec-c2ce-29e5f76b963b.png)


そして、プロファイルメトリクスが1件になっていることを確認できます。
![スクリーンショット 2024-10-16 162917.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3717693/d6e4fd8a-94c1-e9fd-39d4-6e9ae628f09f.png)
Teams Webhookサービス終了に関連するURL更新のお知らせと対応

## Webhookに関する通知
TeamsのWebhook機能の終了が告知されてから3か月ほど経ちました。
ぼちぼち移行に向けて動いていたところ、ちょうど数日前から既存のTeams Webhook機能を利用していたチャネルの通知に以下のメッセージが表示されるようになりました。

>**Important**
You must update your Webhook URL for this connection in order for your notifications to keep posting into Microsoft Teams. [Learn more about this update](https://learn.microsoft.com/ja-jp/microsoftteams/m365-custom-connectors#update-connectors-url)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969669/210a34aa-9ad7-4461-b5b5-e32b20844ab6.png)

こちら内容を確認したところ、既存のコネクタを使い続ける場合はURLの更新が必須なようです。

https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/
>Webhook-based connectors within the O365 Connectors service in Teams are transitioning to a new URL structure due to the implementation of further service hardening updates. During this transition, you may receive notifications to update your configured connector to use the new URL. We strongly recommend that you update your connector immediately to prevent any disruption to connector services. URLs for all webhook-based connectors must be updated by January 31, 2025 for the connectors to continue posting messages into Teams.

>Teams の O365 コネクタ サービス内の Webhook ベースのコネクタは、サービス強化のさらなる更新の実装により、新しい URL 構造に移行しています。この移行中に、新しい URL を使用するように構成されたコネクタを更新するように通知が届く場合があります。コネクタ サービスの中断を防ぐために、コネクタをすぐに更新することを強くお勧めします。コネクタが Teams にメッセージを投稿し続けるには、すべての Webhook ベースのコネクタの URL を 2025 年 1 月 31 日までに更新する必要があります。

ということで、実際にやってみました。

## URL更新の流れ
①対象のTeamsチャネルの三点リーダーから「**チャネルを管理**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969669/51418bfe-311d-9398-e8af-c6bcee72e64c.png)

②コネクタの「**編集**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969669/4c58ef46-b5e6-9429-5e71-9b6b35e7852d.png)

③対象のコネクタの「**Manage**」をクリック
※更新対応が必要なものには赤字で<font color="red">**Action required**</font>と出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969669/48956b40-e44c-e268-cdc9-7bd36e07e534.png)

④「**Update URL**」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969669/85d07484-7c39-dbca-fe76-abee41fe0951.png)

⑤URLが更新され、「Url is up-to-date.」と表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969669/be63be38-83c5-b539-6436-7a08be462368.png)

## 注意点
### 更新後は以前のwebhook URLが利用できない
当たり前かもしれないですが、このボタンを押すと旧URLは更新されて削除されてしまいます。
そのため、新旧URLで平行運用などは出来ないのでご注意ください。

### 更新前の状態に戻せない
更新してしまうと、元のURLに戻すことは出来ません。
この作業をする前に、旧URLを利用しているシステムについてもしっかり確認して、影響ないことを確認してから更新するようにしてください。

### Wenhookを作成した人しか更新ができない
Teamsのコネクタの仕様ですが、Webhookを作成した人しかこの更新ボタンを押せないようです。
また、クリップボードへのコピーが出来るのも、作成者のみです。
『いざ更新しようとしたら、当時の担当者がいなかった』という場合、Webhookの継続利用が出来ずに詰む可能性もあるので、事前に対象の作成者については確認しておきましょう。
（Configuredの画面で、各コネクタを追加したメンバーは確認できます）
「Snowflake×dbt Cloudでデータ変換処理を開発してみよう！初めての方向けハンズオンセミナー」に参加した

読者の方へ：これを読んでも得られるものはないと思います。

# セミナー概要
【10/3（木）】Snowflake社共催！Snowflake×dbt Cloudでデータ変換処理を開発してみよう！初めての方向けハンズオンセミナー

https://events.classmethod.jp/seminar/8bb49c4f-bb88-4091-9e24-e00476c0afb9/

2週間経過してしまいましたが、このハンズオンセミナーに参加してきました。＠Snowflake本社
AWSとかSnowflakeでちょっと調べようとググった時にだいたいHitするクラスメソッドさんが主催です。
Snowflakeは会場貸しみたいな感じでしょうか。

# 参加目的
現状、S3に吐き出してもらったJSONとかParquetファイルを、外部ステージ経由でCOPY INTOで定期的にロードするという、Snowflakeだけでできている状況です。
そのため、dbtとかtoroccoとかfivetranとかよく聞くけどまだいまいち必要性がわかっていません。
dbtを使うと何がいいのか体験したくて参加しました。

# 内容
ざっくり書くと
1. クラスメソッドさんの会社紹介
1. Snowflakeの説明、dbtの説明
1. ハンズオン
でした。

# ハンズオン
https://docs.getdbt.com/guides/snowflake?step=1

このdbtのQuickStartの内容に沿って説明してもらいながら実際に手を動かしました。
※事前にdbt cloudのDeveloperアカウントを作っておくよう指示が来ていたので準備済み
![スクリーンショット 2024-10-17 175913.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3487310/5239ab62-c244-0106-3474-48faca3874fc.png)
Developerというのを選べばFreeです。

ハンズオン自体、特に躓くところもなく最後までできました。

# 感想
## ポジティブな感想
- dbt cloud側で書いたsqlでSnowflake側にテーブルができたりViewができたり、なるほどどいう感じ。
- データのテストを入れられて、uniqueとかnot nullとか許可できる値をlistで設定できたりする。
- ref関数というものでsql同士の流れが可視化できる。これはわかりやすい。

## ネガティブな感想
- SQLのことをモデルと呼ぶのがしっくりきていない。
- まだdbtの必要性を感じるところまでは行かず。（Snowflakeだけでできたほうが楽なのでは？とまだ思っている）

ネガティブな感想部分は自分の理解力が足りてないのが大きいと思うので、QuickStartのページに沿ってもう一回一人でやってみようとも思ってます。
プロジェクト ウォーターフォールとアジャイルの違い

こんにちは、小磯と申します。
プロジェクトには2種類の開発手法があります。
ウォーターフォール開発とアジャイル開発の違いについて纏めようと思います。
初めて業務を行うPM(PMO)の方へ参考になればと思います。

### ウォーターフォール開発とアジャイル開発

ウォーターフォール開発とアジャイル開発の大きな違いは開発プロセスの進め方にあります。
どちらの開発手法なのかを理解していないと失敗してしまう可能性があります。

## 1.ウォーターフォール開発

上から下に各工程を後戻りしない前提で進めていく手法です。
仕様が決まっており変更が起きづらいシステムの開発に適しています。
何を作るかの全体像を決め、全体を設計してから開発します。

## 2.アジャイル開発

機能単位で小さくすばやく開発を繰り返していく手法です。
仕様や要件が固まっておらず、変更が起きやすいシステム開発に適しています。
時代の変化スピードが加速するにつれ、素早い仕様変更が求められるシステム開発に適しています。

## 3.メリットとデメリット

- ウォーターフォール開発（大規模開発向け）
　①メリット
　　→各フェーズ毎に分担して開発出来る。
　　　スケジュールの管理がしやすい。
　②デメリット
　　→仕様変更が出来ない。
　　　ドキュメント作成に時間が掛かる。

- アジャイル開発（小規模開発向け）
　①メリット
　　→仕様変更が柔軟に対応できる。
　②デメリット
　　→メンバー全員に設計からテストまでのスキルが必要。
　　　厳格なドキュメントが残せない。


- まとめ
目的やプロジェクトの規模などに合わせて、適した開発手法で対応することが重要です。
どちらの開発手法も経験するとどちらが自分に合っているのか、今後に活かせると思います。

以上、小磯でした。
アルゴリズム

# どういうアルゴリズムなのか？
グラフ内の２つのノード間の最短経路を求めるアルゴリズム

# グラフの形
ノードがエッジで繋がってるグラフ

# 最短距離、最短経路を求めるまで
* ノードの個数はN、Nは２以上
* 始点のノード番号を１とし、１から始まる連続する
* ノード番号はV1,V2,V3,V4...VN
* 他のノードを経由せずにエッジで繋がっている時は「隣接する」という
* 隣接するノード間の距離は正の数値を取る
##### 最短距離
* エッジに付けられた距離の和が最小の距離を最短距離という
##### 最短経路
* 始点から終点までの最短距離となる経路を最短経路という

##### 始点ノード距離
* 始点からそのノードまでの距離を始点ノード距離という
* 始点の始点ノード距離は０にする

##### 始点ノード距離の特徴
* 始点ノード距離のデフォルト値はとても大きな数値

##### 更新起点ノードとは
* 始点との距離を算出する基準となるノードを更新起点ノードという

##### 1.更新起点ノードを決定
>最短距離が確定していないノードの中で、始点ノード距離が最小のノードを更新起点ノードとして選び、その時の始点ノード距離の値で、当該更新起点ノードの最短距離を確定する

 ←最短距離が確定していないノードの中で更新基点ノードを選ぶ。更新基点ノードの距離で最短距離を確定する
 
>当該更新起点ノードを選ぶ際に、始点ノード距離が最小となるノードが複数ある場合は、その中の任意のノードを更新起点ノードとして選ぶ。

← 最短距離のノードが複数あった場合は、どれかを選ぶ。（後にまた計算をし直すのだろう）

##### 2.更新起点ノードが終点ならばアルゴリズムは終わる
> 更新起点ノードが終点があれば、終了する

← ここでアルゴリズムは終わる

##### 3.更新基点ノードを介した始点ノード距離を計算する
>1.で選択した更新基点ノードに隣接しており、かつ、最短距離が確定していない全てのノードについて、更新基点ノードを経由した場合の始点ノード距離を計算する

← 隣接していて更新起点ノードになっていないノードに対して更新起点ノードを経由した始点ノード距離を計算する

>ここで計算した始点ノード距離が、そのノードの現在までの始点ノード距離よりも小さい場合はには、そのノードの現在までの始点ノード距離を更新する

← 同ノードが改めて始点ノード距離を計算し前回の始点ノード距離の値より小さい場合は始点ノード距離を更新する

```rb
dist[1]←0 # 始点ノードの始点ノード距離が０だから
while (true)
    minDist ← INF # INFに初期化される
    for (kを１からNまで1ずつ増やす）# 
        if(done[k]が０かつ　イ＜dist[k]がminDistより小さい＞　）# 最短距離が確定していない且つ始点ノード距離を比べて小さければ
            minDist ← ウ＜dist[k]＞　# 更新起点ノードを代入する
            curNode ← k　# 更新起点ノードを代入する
        endif
    endfor
    done[curNode] ← 1
    if (curNodeがGOALと等しい）# 手順２の終点ノードであれば終了
        return dist[curNode]
    endif
    for(kを１からNまで１ずつ増やす）
        if(　＜エ＞　がdist[k]より小さい かつ done[k]が０）# 同ノードが改めて始点ノード距離を計算し前回の始点ノード距離の値より小さい場合
            dist[k] ←　＜エ＞ # 最短距離を更新する
        end
    endfor
endwhile
```
##### dist[]
始点ノード距離。初期値はINF、要素番号はノード番号を表す
##### minDist
更新起点ノードを求める使用する一時変数
##### done
初期値は０、最短距離が確定したら１を入れる
##### curNode
更新起点ノードのノード番号

### 間違えたところ
```rb
if(＜エ＞がdist[k]より小さい かつ done[k]が０)# 同ノードが改めて始点ノード距離を計算し前回の始点ノード距離の値より小さい場合
```
最短距離が前回よりも小さければ値が更新される処理を表している

更新起点ノードの始点ノード距離とk（最短距離が確定していないノードの番号）

##### edge[m,n]
ノードmからノードnへの距離を格納、２つのノードが隣接していない場合にはINFを格納

curNodeは更新起点ノードを距離を取得できる。
curNodeからkの距離をedgeで取得する。

dist[curNode]+edge[curNode, k]で上書きするのか

#
>直前に経由したノード番号をviaNodeに格納する代入分を一つ、図2のプログラムの行＜オ＞の直後に挿入する。

`viaNode[k] ← curNode`
25行目だった。行番号については、最も小さい番号を答える

>終点のノード番号を起点として＜カ＞辿ることで、最短経路のノード番号を逆順に出力する

ア　

# 感想
少しずつアルゴリズムを解けるようになりたい。
後の問題は書くのが疲れた。
デスクトップ小技 Teraterm ログイン編

Teratermの利用時に有用な小技をいくつかまとめます。

## Teratermマクロを使ったログイン
Teraterm用にログイン情報をマクロファイル(.ttl)に設定しておくことで、毎回のサーバー接続時の作業 (ターミナルの起動→接続先(アドレス/ポート)の入力→接続IDの指定, パスワードの入力またはキーファイルの指定)がマクロの実行だけで済みます。

ログイン操作は、connectを使用します。
connect [アドレス]:[ポート] /ssh /auth=(publickey|password)/user=userid (/passwd=パスワード,  /keyfile=.pemファイル名)
#### Teratermマクロに記載する例
```:キーファイル(.pem)でのログイン
connect ec2-11-22-33-44.ap-northeast-1.compute.amazonaws.com:22 /ssh /2 /auth=publickey /user=ec2-user/keyfile=C:\work\keyfile\ec2-key.pem
```
```:パスワードでのログイン
connect '22.33.44.55:22 /ssh /auth=password /user=test-user /passwd=password'
```
#### マクロファイル(.ttl)の関連付け
.ttlファイルをTeratermマクロttpmacro.exeと関連付けすることで、.ttlファイルをダブルクリックするだけでログインできます。
プログラムから開く> 別のプログラムを選択 > アプリを選択して.ttlファイルを開く > PCでアプリを選択する　を選択後、ttpmacro.exeを選択します。

![スクリーンショット 2024-10-04 102224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802444/3d9faadd-45e8-110a-b643-7064651f48ee.png)



## Teraterm設定内容の保管
Teratermの設定はメニューから変更できますが、変更内容は Teratermを終了すると消えてしまいます。
Teraterm終了後も変更内容を継続して利用する場合は、変更をTeraterm.iniファイルに保存できます。

Teratermのメニューから、

## Teraterm起動時 iniファイルの指定
次回起動時に、このファイルが読み込まれることで、ファイル保管時の変更(例えばフォント、色/背景色、ウインドウのサイズや接続席の履歴等)を、利用することができます。
```:INIファイルの指定を追加
connect '22.33.44.55:22 /ssh /auth=password /user=test-user /passwd=password' /F=C:\Teraterm\teraterm.ini 
```

## ログイン後のキー入力

```:プロンプト表示後のSSHコマンド打鍵例
connect '22.33.44.55:22 /ssh /auth=password /user=test-user /passwd=password' /F=C:\Teraterm\teraterm.ini 

if result <> 2 then
    messagebox 'It could not be connected.' 'Connected error'
    end
endif

;; 10秒以内にプロンプトが表示されない場合終了
timeout = 10
wait '$' '#'
if result = 0 then
    disconnect
    end
endif

;; backservにtestuserでSSH接続
sendln 'ssh testuser@backserv'
;; 「password:」が表示されたらパスワードを入力
wait 'password:'
sendln 'hogehoge'
wait '$' '#'
```
内容はTERATERMマクロのファイル(.ttl)として保管。

## 拡張子をttpmacro.exeに関連付け
teratermマクロの実行時は、`ttpmacro.exe [マクロファイル].ttl` で実行できますが、この拡張子`.ttl` をttpmacro.exeと関連付けしておくことで、ファイルのダブルクリックでログインできるようになります。
Emacs org-modeのエクスポート設定を文書ファイルと同じディレクトリで管理する方法


Emacsのorg-modeには多様な文書形式 (PDF, OpenDocument, markdown, ePubなどなど) に対応した豊富なエクスポート機能があります。エクスポート形式に合わせて出力を調整する必要がありますが、それらの設定はinit.elなどのEmacsの初期設定ファイルに記述するのは一般的です。しかし、エクスポート設定は文書ごとに設定し、文書と一緒に管理できたほうが便利だと思います。この記事では、エクスポート設定ファイルを出力元のorg文書と同じディレクトリにおく方法を示します。

# エクスポート設定の課題

org-modeでのエクスポートでは、文書の種類や目的に応じて設定を調整する必要があります。通常、これらの設定はinit.elに記述しますが、多様なエクスポートに対応するうちにファイルが肥大化し、管理が煩雑になります。また、設定変更のたびにEmacsを再起動する必要があり、効率が悪いです。あまり長大になると起動時間にも影響しそうです。

# org-export-async-init-file を使った非同期エクスポート

init.elの肥大化を防ぐ解決策が非同期エクスポートです。init.elとは別にエクスポート設定を記述したファイル (org-export-async-init-file) 用意して、バックグラウンドでエクスポートを行えます。これなら設定を変える度にEmacsを再起動してinit.elを再読み込みする必要もないし、エクスポート中に他の作業を進めることができる利点もあります。非同期エクスポートのためにはinit.elに以下の二つの変数を設定します。

``` emacs-lisp: init.el
(setq org-export-in-background t)
(setq org-export-async-init-file "/path/to/your/init/file")
```

# async-init-fileを文書ごとに切り替えたい

しかし、エクスポート設定をinit.elから分離したとしても、org-export-async-init-fileも、多様なエクスポート設定を追加していくと結局はorg-export-async-init-fileが長くなり、管理が煩雑になってしまいます。それに、実際のエクスポートのプロセスでは、その長大な設定の中のたったひとつしか使わないのです。なのにすべての設定を含めたorg-export-async-init-fileを参照するのは無駄に思えます。

そもそも、org文書をどの文書タイプにどのようにエクスポートするかの設定は、中央管理するより、むしろ文書ごとに切り替えたいのが普通じゃないでしょうか。文書と一緒にエクスポート設定を同じディレクトリで管理できればとても便利です。

.dir-locals.elを使えば、それが可能です。.dir-locals.elは、特定のディレクトリ内のファイルに適用されるEmacsのローカル設定を定義するためのファイルです。このファイルに書かれた設定は、そのディレクトリ内のすべてのファイルを対象とし、個別のプロジェクトやフォルダごとに異なる設定を適用する際に便利です。ここに、次のように書くと、ディレクトリ直下の org-export-async-init.el というファイルが、同じディレクトリにあるorgファイルのエクスポート設定ファイルとして指定されます。

``` emacs-lisp: .dir-locals.el
((org-mode
  (org-export-in-background . t)
  (eval . (setq org-export-async-init-file
                (expand-file-name "org-export-async-init.el" (file-name-directory (or load-file-name buffer-file-name)))))))
```

こうしてエクスポート設定を文書と紐付けて管理すれば、その文書に対して不要な設定を書かずにすむので設定ファイルが短くなり、視認性が高まります。また、文書のポータビリティが増します。
C++で文字列を連結する時につまづいたこと

## 環境
M1 MacBook
Sonoma 14.6.1

## 何につまづいたのか
文字列の連結をC++で実装する時につまづきました。クエリを受け取り、それに応じて文字列を生成してスタックするという処理です。

## どこでつまづいたのか
```c++
...
string ans = "";
string S = flw[i];
for (const auto &v: S)
    ans += v + " ";
out.push_back(ans);
...
```
上が該当のコードです。outにスタックされた文字列は、処理の最後にまとめて出力されます。しかしながら、このプログラムを実行しても、何も出力されませんでした。

## 原因
原因は、文字型と文字列型の混同でした。C++は、文字列同士を「+」演算子で連結できます。

```c++
string a = "abc" + "def";
cout << a << endl;
```
```console
abcdef
```

しかしながら、私は次の様なコードを書いてしまいました。

```c++
...
ans += v + " ";
...
```

2024/10/18 修正

この時、vがstring型であれば、問題なく連結されます。しかし、vはchar型でしたので、意図しない動作が発生しました。

~~しかし、上の実装を見るとわかりますように、for文で文字列型の要素である文字型を取り出していますので、この式は「文字型」と「文字列型」の連結を行おうとしてしまいます。本来であれば、コンパイラがエラーを示してくれるはずですが、for文内部でauto型を使ってしまったせいで、コンパイラも気が付かなかった様です。~~
(コンパイラは正しく型推論を行なっています)


## 改善

2024/10/18 修正

~~**to_string**関数を用いて~~string関数を用いて文字型を文字列型に変換しました。これで、文字が問題なく連結されるようになりました。
```c++
ans += string(1, v) + " ";
```

## 未だわからないところ・予想など
コメントより、上記のコードは問題なく動作するとの指摘を受けましたので、一度実験を行いました。

```c++
string ans = "";
const char &v = 'a';
const char* space = " ";
space += v;
ans += space;
cout << ans << endl;
```
```console
$ ./a.out
$ ?
```

文字がうまく連結されませんでした。もしかしたら、コメント投稿者の方と環境が異なったり、私のプログラムがよくないのかもしれません。ただ、まだ気になりましたので、もう少し実験を行いました。

出力結果に「？」と表示されたところが気になりました。文字型に間違えて数字を足しますと、時々文字がずれて、このような結果になります。もしかしたら、文字同士がASCIIの数字で足し算されているのではないかと予想しました。

### 実験1
```c++
print(" " + 'a');
print(" " + 97);
``` 
```console
$ ./a.out 
[空白]
[空白]
```

### 実験2
```cpp
print("" + 'a');
print("" + 97);
```
```console
$ ./a.out 
???????<
???????<
```

あくまでも知識不足の私の予想なのですが、もしかしたら文字が整数値に変換されてしまい、上のような挙動が起きたのではないかと思います。整数を文字列に足すことで、ポインタ操作が行われてしまったのかもしれません。いずれにせよ、未だよくわからない領域です。引き続き、勉強してまいります。

## 参考
https://techis.jp/guide/cpp/cpp_strings_concat

https://cpprefjp.github.io/reference/string.html

https://www.smartbowwow.com/2018/08/cchar.html

http://www3.nit.ac.jp/~tamura/ex2/ascii.html