OmniAICreator/Qiita-1.07M huggingface dataset:
SolidJSの世界: プロジェクトのセットアップ #2


## はじめに

はじめまして、WEB フロントエンドエンジニアの nuintee です。

この度かねてより関心があった SolidJS に入門する覚悟が出来たので、
その学習過程をアドベントカレンダーにしてみました。

SolidJS に少しでも興味のある方は、ぜひご覧ください。

## フロントエンドの世界 2024 について

「[フロントエンドの世界 2024](https://qiita.com/advent-calendar/2024/frontend-assort-2024)」は普段 [`Next.js`](https://nextjs.org/) を書いている筆者が、同じフロントエンドライブラリである [`Svelte(Kit)`](https://svelte.jp/docs/introduction), [`Remix`](https://remix.run/docs/en/main) ,[`SolidJS`](https://docs.solidjs.com/), [`Qwik(City)`](https://qwik.dev/)の 4 つにアソート形式で触れ、理解を深めていく様子を収めたアドベントカレンダーです。

![frontend-assort-2024-banner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294810/7666d209-1aef-9ce5-c298-d8e60847e830.png)

## もくじ

- [はじめに](#はじめに)
- [フロントエンドの世界 2024 について](#フロントエンドの世界-2024-について)
- [もくじ](#もくじ)
- [前提](#前提)
- [SolidJS の導入](#solidjs-の導入)
- [Solid プロジェクトの立ち上げ](#solid-プロジェクトの立ち上げ)
- [ブラウザで確認](#ブラウザで確認)
- [おわりに](#おわりに)

## 前提

本シリーズでは [`Turborepo`](https://turbo.build/) によるモノレポ管理を行っています。

単体で `SolidJS` を導入する場合は適宜プロジェクト作成先パスを変更して下さい。

## SolidJS の導入

`apps`配下に`SolidJS`のプロジェクトを作成します。

### プロジェクトのセットアップ

今回はテンプレートから Typescript と TailwindCSS があらかじめ導入されているものを選びます。

```shell
npx degit solidjs/templates/ts-tailwindcss apps/solid-client
```

:::note
solidjs/templates/<テンプレートの種類> でテンプレートの指定が可能です。
(参考: [templates](https://github.com/solidjs/templates))
:::

### package 名の変更

今回は `Turborepo` で管理しやすいように package の名前を`solid-client`に変更します。(任意)

```diff_json:package.json
{
+ "name": "solid-client",
  "version": "0.0.0",
  "description": "",
  "type": "module",
  "scripts": {
    "start": "vite",
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "license": "MIT",
  "devDependencies": {
    "autoprefixer": "^10.4.20",
    "postcss": "^8.4.49",
    "tailwindcss": "^3.4.15",
    "typescript": "^5.7.2",
    "vite": "^6.0.0",
    "vite-plugin-solid": "^2.11.0"
  },
  "dependencies": {
    "solid-js": "^1.9.3"
  }
}
```

### パッケージのインストール

今回は `Turborepo` で管理するので `pnpm` でインストールします。
※ お好みで選んでください。

```shell
# Turborepoの場合 (ルートで実行)
pnpm --filter solid-client install
```

```shell
# 単体の場合
cd apps/solid-client
npm install
```

## Solid プロジェクトの立ち上げ

dev コマンドでローカル環境の立ち上げます。

```shell
# モノレポの場合 (ルートで実行)
pnpm --filter solid-client dev
```

```shell
# 単体の場合
npm run dev
```

:::note warn
↑ のコマンドで立ち上がらない場合は package.json の `name`フィールド が `solid-client` に設定されているか確認して下さい。
:::

## ブラウザで確認

ブラウザで http://localhost:3003 を開くと、"Hello tailwind!" と表示されます。

![solid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294810/66ca9334-cf5d-2330-e636-6fd8ae91302a.png)

## おわりに

導入から立ち上げまで体感 約 10 秒程度で完了してしまう程速かったので、本当に軽量なんだなと実感しました。

またテンプレートの中から用途に合ったものを指定できるので、とりあえず動かしたい時にサクッと立ち上げ出来るのは便利だなと思いました。

また本シリーズを通してお気軽にコメントお待ちしております。
また完走賞も目指しているので是非応援お願いします！

---

この記事は [フロントエンドの世界 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/frontend-assort-2024)の 14 記事目です。
次の記事はこちら [SolidJS の世界: UI 構築とトランジション #3](https://qiita.com/nuinteedev/private/38909bb77ee6bb719854)
AWS CDK のチュートリアルで credentials errorを解決した時のメモ

## これは何？
AWS CDKチュートリアル時に "but no credentials have been configured" エラーで数時間トラブルシューティングした。同じ詰まり方をしている人が見つからなかったため解決策と原因をメモ。

## TL;DR
- ~/.aws/config と ~/.aws/credentials の両方を設定していると、最終的にcredentialsの方の設定が使用される。
- credentialsの方に設定していたTokenが expired していた。
- sso login は成功していたため、気がつかなかった。

## 解決手順

チュートリアルを進めて、 `cdk bootstrap` を行うところでエラー

```
failed bootstrapping: Error: Need to perform AWS calls for account xxxxx, but no credentials have been configured
```

以下コマンドを実行し、verboseを使って詳細なログを見る。
```
cdk bootstrap aws://account_id/region --profile my-profile-name -v
```

そうすると以下のログが見つかった。
```
...
cdk There are expired AWS credentials in your environment. The CDK app will synth without current account information.
...
```

sso loginなどを再度、試してみるが問題なくsso接続できている。
しかし、上記のコマンドだけはエラーを出す。

ググると、 `config` fileの profile_nameの読み込まれ方などによるトラブルシューティングが散見されたため試したが特に変わらず。

ダメもとで、　`credentials`ファイルのTokenを削除したら、成功した。両方のファイルを読み込み、内部的に上書きしているようだった。
複雑な条件文の効率的な書き方

複雑な条件文を書くときに括弧でまとめると便利なので、メモしておきます。

こんな変数があったと仮定
```javascript
const conditionA = true
const conditionB = true
const conditionC = false
```

#### ケース1 Not A & Not B
```javascript
const res1 = !conditionA && !conditionB
// ↓と括弧でまとめられる
const res2 = !(conditionA && conditionB)
// 結果はfalse
```

#### ケース2 Not A or Not B
```javascript
const res3 = !conditionA || !conditionB
// ↓と括弧でまとめられる
const res4 = !(conditionA || conditionB)
// 結果はfalse
```

#### ケース3 A or B & C
```javascript
const res5 = conditionA || (conditionB && conditionC)
```

#### ケース4 A or Not B & Not C
```javascript
const res6 = conditionA || !(conditionB && conditionC)
```

#### ケース5 A & B or C
```javascript
const res7 = conditionA && conditionB || conditionA && conditionC
// ↓の方が見やすい
const res8 = conditionA && (conditionB || conditionC)
```
WebSpeechAPIお試しツール作ってみる

# はじめに

前回はじめてWeb Speech APIを触ってみてみたが、

今回は、Web Speech APIには音量やピッチだけでなく様々な声の設定ができるようなので

自由にWeb Speech APIの設定して出力できるアプリを作ってみる。

前回の記事

https://qiita.com/shisojuice/items/60e95eb099a2bd795960

Web Speech API　とは(参考記事)

https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API

https://developer.mozilla.org/ja/docs/Web/API/SpeechSynthesis


# 成果物の画像

![WebSpeechAPIお試しツール作ってみる01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/35fc8c1b-d159-3ea9-63e7-9fa90a79de6f.jpeg)


![WebSpeechAPIお試しツール作ってみる02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777149/25e63c3e-cb09-9739-e129-d29d9c17cdab.jpeg)

# プロジェクトの作成

今回は、Svelteベースに作成してみる

(だた、筆者がsvelte(ver5)使ってみたかっただけで選定理由はありません🙇‍♂️)

https://svelte.dev/

下記がコードになりますが、

speechSynthesisを扱う際に注意しなければいけないところは、

window.speechSynthesis.getVoices()　は、非同期で読み込まれるため、

Mount時にwindow.speechSynthesis.onvoiceschangedを使用して設定する。

（はじめて使用したときに、このことを知らなくてSelectBoxが空になり焦りました🥲）

```javascript:App.svelte
  // 略
<script>
  import { onMount } from "svelte";

  let voices = $state([]);
  let voiceIx = $state(0);
  let volume = $state(1);
  let pitch = $state(1);
  let rate = $state(1);
  let text = $state("");

  onMount(() => {
    voices = window.speechSynthesis.getVoices();
    if (
      voices.length > 0 &&
      (voiceIx === undefined || voiceIx >= voices.length)
    ) {
      voiceIx = 0;
    }
    window.speechSynthesis.onvoiceschanged = () => {
      voices = window.speechSynthesis.getVoices();
    };   
  });
  const Speech = () => {
    const utterance = new SpeechSynthesisUtterance();
    utterance.voice = voices[voiceIx];
    utterance.lang = voices[voiceIx].lang;
    utterance.volume = volume;
    utterance.pitch = pitch;
    utterance.rate = rate;
    utterance.text = text;
    speechSynthesis.speak(utterance);
  };
</script>
```

```javascript:App.svelte
<main>
  <h1>Web Speech Sample</h1>
  <div class="set">
    <label for="voicetext">VoiceText</label>
    <input type="text" id="voicetext" bind:value={text} />
  </div>
  <div class="set">
    <label for="voice">Voice</label>
    <select name="voice" id="voice" bind:value={voiceIx}>
      {#each voices as voice, i}
        <option value={i}>{voice.name}</option>
      {/each}
    </select>
  </div>
  <div class="set">
    <label for="volume">Volume_{volume}</label>
    <input
      type="range"
      min="0"
      max="1"
      step="0.1"
      id="volume"
      bind:value={volume}
    />
  </div>
  <div class="set">
    <label for="pitch">Pitch_{pitch}</label>
    <input
      type="range"
      min="0"
      max="2"
      step="0.1"
      id="pitch"
      bind:value={pitch}
    />
  </div>
  <div class="set">
    <label for="rate">Rate_{rate}</label>
    <input
      type="range"
      min="0.1"
      max="10"
      step="0.1"
      id="rate"
      bind:value={rate}
    />
  </div>
  <button onclick={Speech}>Speech</button>
</main>

// 略
```

完成！

# 成果物ソース

デモURL

https://shisojuice.github.io/WebSpeechSample/

ソース

https://github.com/shisojuice/WebSpeechSample

# まとめ

Web Speech APIの機能と出力サンプルアプリを実装してみた。

上記で記載した通り、speechSynthesis の voices は非同期で読み込まれるため、

初期化時など注意をして使っていきたい。
言語モデルを使った文章生成、ただし人力

# 言語モデル

言語モデルって、単語列を見せたときに次に来る単語は？の出現確率で～とかなんとかを説明するためのスライドを書いていたときに、こう動きのないスライドで一例を図示するよりいろいろなパターンを見せて分からせたいよね……それじゃアプリ作るか！って勢いで作ったところ、ハルシネーションってこう起こるんだって体感したり、ChatGPTとかたまに変なこと言い出したりする理由が分かったとか、ポチポチ単語を選択するだけで文章が作られていくのが面白いとか、結構好評だったので、ついでにアドベントカレンダーのネタにもしようと。

ちなみにコードはこちら用に新規に適当に書き起こしました。
https://amanorox.github.io/llmplay/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26019/ad8ea734-11d1-3343-03de-07f37dc3bd4d.png)


# プログラム概要
https://github.com/amanorox/llmplay

誰でも気軽に試せて、言語モデルを動かすコストがかからないようにウェブブラウザ内ですべて処理が完結するようにしました。

## 使用ライブラリなど
- Transformers.js
https://huggingface.co/docs/transformers.js/index
- Qwen2.5-0.5B
https://huggingface.co/onnx-community/Qwen2.5-0.5B
- Chart.js
https://www.chartjs.org/

## 採用言語モデルのこと

日本語1文字が複数トークンに分割されていたり、1トークン1文字だけだったりするモデルでは次の語の候補に1文字のものしか出てこないっていうのは面白くないと、日本語をよくサポートしてくれるモデルとして Qwen を、あとはブラウザ内で処理できて軽量なところでと、0.5Bの極小サイズのモデルを採用しました。

いろいろなモデルを試したところ、0.5Bモデルはやっぱり性能が低くて7Bくらいあると様々な文章作るのに楽しい感じがあるなと思います（先発で作成したものは専用の言語モデルサーバーを用意してそっちで大きいモデルを使って推論してました）。

7Bモデルを4ビット量子化してもさほど性能低下は感じないですが、0.5Bモデルの量子化はだいぶ違うと、まともそうな fp16 を選んでいます。デフォルトの量子化モデルをロードして次語の確率表を出すと、日本語の続きにどうして英語の候補が羅列されるの……ってなります。数（パラメータ数）の暴力で性能低下がカバーされてるのかなって思っています。
スクラムチームへTDDを導入した話

この記事は hacomono advent calendar 2024 の13日目の記事です。

## この記事は？

hacomono開発本部でプロダクトエンジニアをしているすがじゅんと申します。
最近私のチームではスクラム開発を始めて、その過程で一部テスト駆動開発を導入してみたので実際にやってみて感じたことや、メリット・デメリットなどを書いていこうと思います。

## TDD is 何?（そんなの知ってますよという方は飛ばしてください）

TDDとはテスト駆動開発（Test-Driven Development）の略称です。
テスト→実装→リファクタリングを繰り返し行っていく開発の手法の一つで、機能実装前にテストコードから書くのが大きな特徴です。ここで細かくは述べませんし、詳細はいくらでも記事があるのでこれくらいにしておきます。

一般的なTDDの進め方としては、

1. 対象機能に対して失敗するテストを書く
2. 1を元に機能実装し、テストをパスさせる
3. リファクタリングを行う

というサイクルを繰り返すというものです。
メリットとしては確実にテストコードが生まれるので、コードの安全性が高まること、後回しにされがちなリファクタリングを都度行えること、バグ発生率の低下、などが挙げられます。

## TDDは死んだのか？

TDD反対の意見があることも理解しています。
一番の理由は開発速度の低下によるアウトプット量減でしょう。何よりスピードを重視する開発において、TDDを選択するケースは稀だと思います。
また、TDDをやってもそもそも全ケース網羅的に書けていないケースもあり、だったらそんなにテストに時間かけなくてよいのでは？という意見もあるかと思います。

ですが私は場面によってTDDを採用することにはメリットがあると思います。その理由をこれから述べていきます。

### 致命的なやり直しが減る

私がTDDで最もメリットに感じる点はここです。
1の工程でまずテスト観点を洗い出すことになると思います。この洗い出し作業がとても重要で、はじめに実装予定の機能についてかなり深掘ることになります。

- ユーザーが本来必要としている要件を満たせているか？
- 別の機能が関わったときに発生するバグはないか？
- 組み合わせのケースは十分か？

などはじめにがっつり洗い出しの時間を取ります。ここが正確であればあるほど、のちの工程でやり直しの発生リスクは減ってくると思います。

結果的に、「8割くらい実装終わったんだけど本来やりたかったことはこうじゃないんだよね」という地獄のような展開を回避することができます。

### QAに情報をシェアできる

これはチーム開発の副次的効果のようなものなのですが、開発の早い段階でQAメンバーに情報を渡すことができる、というのも大きなメリットです。

参考までに私のチームではざっくりと

1. テスト設計
2. 実装
3. テスト実施

のようなサイクルでスプリント内のタスクを進めているのですが、テスト設計はこれまでQAメンバーが単独で行っていました。
TDDでは、前述の観点洗い出し作業を開発者とQAメンバーが一緒に行います。
すると、開発者視点では一人では気付けなかった観点洗い出し漏れに気づける可能性も高まりますし、QA視点では開発者がどのようなケースを想定しているのか理解することができます。
結果として、QA一人で機能をキャッチアップするより早めに設計を完了することができますし、なによりテスト設計の精度が上がります。

### リファクタリングできる

リファクタリングって後回しにされませんか？
実際自分も「xxまでにリリースしたいから、リファクタのチケット切っておいて後でやろう」として1年以上放置したことがあります。1年放置されたらそのチケットが再開されることはもうないでしょう。
TDDでは一つのケースをパスさせたら、一旦リファクタリングを行って（もちろん不要な場合もあります）からまた次のテストを作る、というように小さなサイクルを回して行きます。

そのため、都度リファクタをする機会があります。
実装が増えるに従って、リファクタリングしたくなる箇所はどんどん増えていくと思いますが、その過程でコードも整理されてきれいになっていきます。

サイクルの中にリファクタリングの機会があるのはTDDの大きなメリットであると言えます。

## で、結局TDDはやるべきなの？

冒頭も述べたのですが、現状は「部分的に採用していく」というのが最適解かなと思っています。
具体的には重要なビジネスロジックの変更や複雑なユースケースには適していて、シンプルな変更には過大である、という意見です。

どうしてもタスク完了までのスピードは低下してしまう傾向はあると思うので、リリース時期や重要度、複雑度を加味してやるかどうかを決めていくのが良い落とし所ではないでしょうか。

実際にやってみてこれまで挙げたようなメリットも享受できたので、私は今後もTDDと良い付き合い方をしていこうと思っています。
レガシーコードの本質：読みやすさと持続可能性

## TL;DR

1. すべてのコードは潜在的にレガシーコードである
2. 重要なのは、読みやすく理解しやすいコードを書くこと

## レガシーコードとは何か

「レガシー（legacy）」という言葉は本来、「誰かが残した財産」を意味します。プログラミングの文脈では、以下のように解釈できると考えています：

- 誰かが過去に書いたコード
- 時間の経過とともに理解が難しくなるコード
- 特定の開発者に依存するコード

### 重要な洞察：自己忘却によるレガシー化

興味深いのは、**同じ開発者が書いたコードでさえ、時間が経過すると理解が困難になり、自分にとってもレガシーコードになる** という点です。数ヶ月後に自分のコードを見返したとき、その意図や実装の詳細を忘れていることがよくあります。

[What is the definition of "legacy code"? - Stack Overflow](https://stackoverflow.com/questions/4174867/what-is-the-definition-of-legacy-code) などにも、書いた瞬間にレガシーコードになるという意見が見られます。

## なぜ「レガシーコード」という言葉を使うのか

この用語には謙虚さと自己改善への意志が込められていると、私は考えます：

- 「レガシー」という言葉は通常、否定的なニュアンスを持つ
- 同時に、自分のコードが完璧でないことを率直に認める自己省察の表現でもある
- この言葉を意識的に使うことで、常に改善を心がける謙虚な姿勢を示せる

## レガシーコードを防ぐための実践的アプローチ

コードの持続可能性を高めるために、以下の簡単な習慣を心がけましょう：

### 1. インラインコメント

最小限でも、コードの意図や複雑な部分を簡潔に説明するコメントを追加します。

:::note warn
よくPRのコメントに説明を書くことがありますが、これはその場限りの情報でありコード自体の読みやすさには寄与していないため、注意をしてください。インラインコメントやドキュメントの追加が望ましいです。
:::

### 2. 型の明示

変数や関数の型を明確にすることで、コードの可読性と理解性を向上させます。

### 3. 軽量なドキュメンテーション

ほんの少しでよいのでコードの背景や目的を説明するドキュメントを追加します。

:::note warn
Architecture Decision Record (ADR) などの形式でドキュメントを残すことも有効ですが、毎回完璧なドキュメントを書くことは難しいため、実装方針の検討背景がわかる程度であると望ましいと考えます。

将来的に参入してきたメンバーが、なぜそのような実装に至ったのかを追うことができれば、過去の試行錯誤に新しい技術を適応させることができるためです。ドキュメントがない場合は、新規の技術の採用におわれて、過去の重要な判断を見逃してしまう可能性があります。
:::

## 心構え：継続的な改善

「完璧な」コードは存在しません。重要なのは、常に読みやすさと理解のしやすさを意識することです。

## まとめ

任意のコードは、例外なく時間の経過につれてレガシーコードになります。

重要なのは、どのようなレガシーコードを残せるかということです。


---

## 経験談

私自身も、過去に書いたコードを見返すと、理解が難しい部分が多々あります。そのため、最近は上記のような習慣を意識してコードを書くようにしています。これにより、自分自身が将来の自分を助けることができるだけでなく、他のメンバーにとってもコードの理解が容易になると感じています。

ただ、他の方から過去の実装に対して問い合わせがある場面もあり、そのたびに自分自身のドキュメントの不備や考慮漏れなどを感じます。ただ、問い合わされたタイミングで自分が忘れていても、ある程度のインラインコメントを用意していたため、自分自身の実装がどうなっていたか思い出すことができ、その場で問い合わせを頂いた方に回答することができました。

完璧な状態のレガシーコードを作ることは不可能だと感じていますが、少しでも読みやすく理解しやすいコードを書くことが大切だと実感しています。
テスト観点についてあらためて整理してみた

こんにちは。流浪のQAエンジニア @illypon です。ふと気が付いたらソフトウェアテストや品質保証の仕事に関わって20年が経っていました。もう十分働いたと思うので早いところ引退したいものですね。もうええでしょう。

さて、この記事では、常々まわりで「テスト観点をまとめるのが大変だ」という声を聴くので、今の自分の考えをまとめてみることにしました。誰かのお役に立ったら幸いです。

# テスト観点という言葉の定義

テスト観点という言葉の定義をGoogle先生に聞いてみました。

> テスト観点とは、特定の機能に対してどのようなテストを行うことが有効なのかを考えることを指します。 テストケースを作成するうえで必要不可欠な要素であり、テストの精度を高めて効率的に作業するために必要とされています。

これでは抽象的で何のことかよくわかりませんね。なぜテスト観点が必要なんでしょうか。テスト観点がなくても、基本設計書・要件定義書をテストベースとして結合・総合テスト設計を進めていけばそれで十分なようにも思います。テスト観点というのは、仕様書に記述される期待動作をコピペしただけのものなのでしょうか。そんなわけないですよね。

ということで、ChatGPTに聞いてもうちょっと具体的に答えてもらいましょう。

> テスト観点とは、仕様書そのものに記載された内容をそのまま確認するのではなく、仕様書やシステム要件を元に、実際の利用状況やリスクを考慮して抽出される具体的な視点です。観点抽出の目的は、仕様書に基づかないリスクや曖昧さを補完し、テストケースを効率的かつ網羅的に設計することにあります。
> 
> ご指摘いただいたように、観点を仕様書そのものと混同しないことが重要です。

ちょっと調教をして期待する結論を吐くように仕向けましたが、およそ期待する回答を得られました。つまり、総合的な視野をもって考えることで、テストベースから漏れてしまいがちな部分を効率的に補完して網羅性を高めていくための手段ということですね。

# なぜテスト観点が必要なのか

テスト観点およびそれを作成する作業が必要な理由ですが、およそ以下の通りです。

- 人間には文章を完璧に書く能力はない
- 言葉は人の意図を完全に表現するほど万能なツールではない
- どんなドキュメントもかならずなにか記載漏れ（記載過剰）や更新忘れがある

つまり、設計ドキュメントはどんなにがんばって書いてもけっして完璧にはならないということです。これを補完するものはなんでしょうか。

代表的なものはコミュニケーションです。現場では「文書のどこにも書いてないけど、こういうときどういう動きが仕様として期待動作ですか？」といった会話が大量にされていますよね。とても大切な仕事です。

ただ、そういう会話は無限にできてしまいますし、あまりにも細かい質問をするのも相手の時間を奪ってしまいますし、コスト面からも歓迎されませんね。かといって、大事な質問も遠慮して出てこなくなると大変です。

そこでテスト観点が登場します。テスト設計の補完に役に立つ、具体的で効果的なテストの要素・条件の一覧がテスト観点だといえるでしょう。

# テスト観点の分類と習得

私のいままでの経験によると、テスト観点には以下の3種類があると整理できそうです。

1. （典型観点）そこに着目してテストすると**ありがちなバグ**が見つかりやすいというノウハウ
1. （安全観点）**インパクトの大きいバグ**が発生しないことを確認するためのノウハウ
1. （行間観点）テストべースとなるドキュメントなどへの**記載が漏れがちなもの**を拾うためのノウハウ

テスト観点というのは種類の違いこそあれ、経験に基づいたノウハウです。テスト観点は再利用可能なことが多いので、一番良いのはやはりたくさんプロジェクトの経験を積むことです。

# 未経験でのテスト観点の抽出

とはいえプロジェクトの経験が少ないけれどもテスト設計をしなくてはならないということもあるでしょう。そういった方はまずは**安全観点**、すなわち、**「起きたら困る結果とそこに至る手段」** に着目して観点を出していくとよいでしょう。これならば、サービスの利用者の気持ちになればいくつかは絞り出せるはずです。（典型観点のバグは誰かが見つけるでしょうし、行間観点のバグは見つけても後回しになることが多いのでいったん置いておきましょう。）



以下に簡単に書き出した例を記述します。

### 起きたら困る結果

- 認証できなくなる
- 接続できなくなる
- 起動しなくなる
- 主たる機能が使えなくなる
- 今までのデータが消える／壊れる
- 動作がものすごく遅くなる
- 次に何をしたらいいのかわからなくなってしまう
- その他、運用回避できない不具合で、かつ、影響の大きいもの

### 起きたら困る結果につながるユーザーの操作や処理

- ソフトウェアアップデート
- バージョンが古すぎるアプリからのアクセス
- サポート外のデバイス
- サポートから外れたOS
- ストレージフル
- 破損データ
- 標準仕様を満たしていないデータ
- 意図しない操作
- 同一リソースへの競合操作
- 過負荷
- 低電圧
- 電源ロス
- 弱電界
- 圏外
- ハードウェアの意図しないタイミングでの取り外しや接続
- 断線などの故障・破壊、またそのようなデバイスとの接続

# テスト観点とは、設計観点のことでもある

テスト観点をたくさん知っている人がプログラムの設計をすることで、ロバストなシステムになります。つまり、テスト観点はそのまま設計観点になります。なので、「こういうテスト観点を考えてますよ」というのをVモデルの左上のところでプロジェクトメンバーの間で共有しておくのが大事です。これはドキュメントの品質を上げていくことにもつながるはずです。

抜き打ちテストをしてバグを見つけるはのではなく、はじめからバグを発生させないようにするのが理想ですよね。

# テスト観点は品質基準の決定にも役立つ

テスト観点の整理をすると、そのサービス・製品の品質基準の決定にも役立ちます。わかりやすい例を以下に記載します。

- 例）動作中に電源断した場合の動作は保証しなくてよい
- 例）仕様で決まっている以上の添付ファイルを受信した場合、そのメールを正しく表示できなくてもよい

このように過剰な品質になってしまうのを防いだり、めったに起きないイレギュラーに対してどこまで動作保証するのかを明確にすることができます。

# テスト観点だけあればいいわけではない

テスト観点はあくまでテスト設計を補完するための考え方であって、テスト観点だけをたくさん書き出せばいいということではありません。

テストには品質目標に合わせた目的がありますから、「どのテストレベルで、どのようなテストタイプを実行するか」という点をテスト計画にしっかり盛り込むことがなによりも大切です。

テスト観点はあるテストタイプの中で利用可能な手段のうちのひとつにすぎません。テスト観点をたくさん出して満足してしまいがちですが、大局を見るということから目を背けないようにしてくださいね。
13日目: BinaryIndexedTreeを実装する

[競プロ用ライブラリを作る Advent Calendar 2024](https://qiita.com/advent-calendar/2024/yukkku-ribitol)の13日目です.

https://qiita.com/advent-calendar/2024/yukkku-ribitol

# BinaryIndexedTreeって?

Fenwick Treeとも呼ばれます.

SegmentTreeに制限を付けてデータを減らして定数倍を軽くしたものです.

# 仕組み

普通のセグ木はこういう風に区間の情報を管理します.

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924904/09046e95-7f92-c72d-4a7c-882807d9bd87.png"/>

でも, 列の先頭から始まる区間のクエリしか与えられないなら, 使う区間の数は減らせますね.

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924904/6369ba22-9b84-3571-a7e6-df1bed87c3e3.png"/>

$x_1, x_2, ..., x_N$という列のBinaryIndexedTreeの各要素$y_k$は$[k+1-2^{\operatorname{trailing}(k)},k]$の区間の情報を持つことにします. ここで$\operatorname{trailing}(k)$は$k$を2進法で表記したときの末尾の連続した1の個数を表します. 偶数なら0で, 奇数なら1以上ですね.

これで値の更新をするためにはSegmentTreeのモノイドという条件に加えてさらに幾つか制約が付いてきます.
アーベル群が乗るんですが, ここでは具体例として 

・列の指定した要素の数を増減させる
・指定した区間の和を求める

というクエリの場合を考えます.

```rust
struct SampleBIT {}
```

## 指定した要素の数を増減させる

その要素が含まれる区間を全て同じ量増減させればいいです.

どうすればいいかというと, 2進法で書いた時の一番下の0を1にする操作を繰り返せばいいです.
足し算の繰り上がりを使えば`i |= (i+1) & ~i`という操作でこれを実現できます.
```rust
impl SampleBIT {
    fn add(&mut self, mut index: usize, val: i32) {
        while index < self.data.len() {
            self.data[index] += val;
            // Rustではビット反転は「~」ではなく「!」です
            index |= (index + 1) & !index;
        }
    }
}
```

## 指定した区間の和を求める

例えば区間$[l, r)$の和を求めるには区間$[0, r)$の和から区間$[0, l)$の和を引けばいいです.
という訳で区間の左端が$0$の場合だけを考えます.

閉区間で情報を持っているのでそれに気を付けると, $[0, r)$の区間には$y_{r-1}$が持っている区間を含んでいます. なので結果は$y_{r-1} + $「$[0,r-2^{\operatorname{trailing}(r-1)})$の区間和」です
2進数表記と見比べることで, $r-2^{\operatorname{trailing}(r-1)}$は`r - (r & ~(r-1))`みたいに計算できることが分かります.
```rust
impl SampleBIT {
    fn sum(&mut self, mut index: usize) -> i32 {
        let mut sum = 0;
        while index > 0 {
            sum += self.data[index - 1];
            index -= index & !(index - 1);
        }
        sum
    }
}
```

# 実装

- [`binaryindexedtree.rs`](https://github.com/Yukkku/ribitol/blob/main/src/binaryindexedtree.rs)
抽象化もアーベル群くらい緩いのでやりやすいです.

# まとめ

いかがでしたか?

明日は便利だけど思ったより使用頻度が低いやつを実装します.
ハワイでドローンを飛ばすためにすべき事

昨年、私はハワイでドローンを飛ばしてきた。
今回は事前に私が実施した事 and これからドローンを飛ばす時に実施すべき事をまとめる。
![IMG_7625.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397581/823fd1ae-083d-295a-a5bb-a53b429cd45b.jpeg)

ハワイ、つまりアメリカでドローンを飛ばすためにはアメリカの法律(FAAの規制)や現地の規制に従わなければならない。

なんと**2023年9月16日**以降、
アメリカのドローン飛行に関する法律が変わり、事前準備が増えた。

大きな違いはずばり、**リモートID**の義務化だ。

日本でも2022年6月20日以降、リモートIDが導入された。しかし日本の場合は事前申請によるリモートIDの免除期間があり、まだリモートIDを取り付けていない読者も多いのではないだろうか。

## ハワイでドローンを飛ばすために事前に実施すべき事
(本内容は2024年12月10日時点の最新情報です）

①リモートIDをドローンに装着する
②FAA Drone Zoneにて事前申請(機体登録)
③ハワイの飛行可能エリアを調べる
④ハワイの飛行ルールを調べる
⑤国際便のドローン持込規則を調べる
※海外にドローンを持込む際は、国や航空会社によって規則が異なるので事前確認必須


## ①リモートIDをドローンに装着する
先述の通り、2023年9月16日以降はドローンへのリモートID装着が義務化された。

とは言え、最新型のドローンを持ってる方はリモートIDの送信機能が内蔵されてる可能性もあり、その場合は外付けでリモートIDを装着する必要はない。

DJI社の内蔵リモートID対応機器は[こちら](https://support.dji.com/help/content?customId=ja-jp03400007191&spaceId=34&re=JP&lang=ja)に記載あり。Mavic3以降とのことだ。

## ②FAA Drone Zoneにて事前申請
FAAとは「米国連邦航空局」のことで、アメリカでは**250g以上**のドローンは機体登録が義務化されている。

250g以上25kg未満のドローンは、Web上の申が可能だ。25kg以上の大型ドローンについては書面での申請が必要だが、本ブログでは考慮しない。

Web申請は[こちら](https://faadronezone-access.faa.gov/#/)からできる。
申請時の具体的な登録内容は、ネットで調べるといくつか参考になるブログがあった。
それらを参考に申請するのがよいかも。
なお申請には5ドルかかる。

## ③ハワイの飛行可能エリアを調べる
特にオアフ島では飛行可能なエリアが、厳しく管理されている。ハワイ島もワイピオ溪谷は飛行NGだった。

国立公園などでは現地に「ドローンNG」の看板が置かれているところもあるが、看板がないエリアもあるので事前に地図で調べよう。
![IMG_7676.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397581/0010f468-334b-adff-f497-3b2a045f4500.jpeg)

飛行エリアの確認には「**B4UFLY**」というアプリが便利だ。必ず事前にインストールしておこう。

具合的に、以下は完全にNGエリアだ
・400ft（122m）以上の高度
・空港から8km以内
・イベントなど人の集団の上空
・高速道路の上空
・その他規制場所（刑務所、軍事基地、国立公園内等）

## ④ハワイの飛行ルールを調べる
日本と同様、ハワイにもドローンを飛ばす時の禁止事項がある。
その時の最新版のルールを確認すること。

例えば
・操縦士が13歳以上であること
・目視外飛行は禁止
・他人のプライバシーを侵害しないこと
・そして**飛行禁止エリア**を守ること

## ⑤国際便のドローン持込規則を調べる
まずアメリカはドローンの持込みがOKな国だ。余談だが、国によっては持込むことじたいがNGな場合もある。

航空会社にもよるが、多くの場合
ドローンの機体は手荷物/預け荷物どちらでもOKだが、リチウムイオンバッテリーは手荷物じゃないと飛行機に持ち込めない。

送信機(コントローラ)はバッテリー内蔵だから手荷物なのかな。

ちなみに私は機体も全部手荷物にした。
預け荷物に入れて壊れるのも嫌だったので。

## 最後に現地では
ハワイではドローン映えするスポットがたくさんある。
しかしその分、ルールとマナーを守らない人が出てくるのもまた事実だ。

違反者への罰金ももちろんある。
しかし、それ以前に完全にドローン飛行NGとならないように節度ある行動を心がけたいところだ。

現地の人の迷惑にならないように
Have a good flight!
【VSCode】カーソルの表示を変更する方法

## カーソルのアニメーション

`editor.cursorBlinking`でカーソルのアニメーションを変更できます。

```jsonc:settings.json
"editor.cursorBlinking": "expand"
```

![画面収録 2024-07-01 (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/1e181bda-38e8-f903-ba2a-f0c2c402228d.gif)

## カーソル移動のアニメーション

`editor.cursorSmoothCaretAnimation`を有効にするとカーソルの移動がアニメーションになります。

```jsonc:settings.json
  "editor.cursorSmoothCaretAnimation": true
```

![画面収録 2024-07-01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/e109dbc5-cde4-d1aa-c8f2-2fbd20a69e70.gif)
PubSubHubbub🍼👶🏻改め、WebSubを初心者向けに解説❗️Rubyでの実装例も紹介❗️

この記事は [ex-crowdworks Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ex-cw)の13日目の記事です。

# はじめに
今年、株式会社クラウドワークスを退職した@nisyuuです。これまで食べてきた中で最も美味かったラーメンは、かいすい本店の王府麺です。
エンジニアとしてクラウドワークステック（旧クラウドテック）というフリーランスと企業をマッチングするエージェントサービスを開発していました。

アドカレで技術記事が少ないとの心の声をいただき、僭越ながら技術記事を投稿させていただきます。
よろしくお願いします。

# WebSubとは何か

WebSubは、元々「PubSubHubbub」という名称で開発されたプロトコルで、AtomやRSSなどのウェブフィードをリアルタイムに配信するための仕組みです。このプロトコルの実装により、フィードが更新された際に、読者は即座にその情報を受け取ることが可能となります。「Publisher」「Subscriber」「Hub」の3つの要素から構成されることが特徴です。

## WebSubの構造

1. **Publisher (公開者)**
  - フィードを作成し、更新するエンティティです。Publisherは、作成したフィードをHubに送信しま

2. **Subscriber (読者)**
  - 特定のフィードを読み込むためにHubに購読を求めるエンティティです

3. **Hub (ハブ)**
  - フィードの更新を管理し、Subscriberに通知を送信するサービスです

## WebSubの動作流れ

1. Publisherは新しいフィードを作成し、Hubに送信します
2. SubscriberはHubに特定のフィードを訂購するようにリクエストを出します
3. フィードが更新されるとHubはSubscriberに通知を送信します

この一連のプロセスにより、Subscriberはフィードの更新をポーリングで確認する必要がなくなり、リアルタイムに更新情報を受け取ることが可能です。これは、ブログの更新やニュース記事、ポッドキャストなど、頻繁に更新されるコンテンツの配信に特に有用です。

# WebSubのメリット

1. **リアルタイム性**
  - フィードの更新情報が即座に配信されるため、ユーザーは最新の情報を迅速に得ることができます

2. **効率性**
  - Subscriberはポーリングの必要がなくなるため、サーバーリソースの消費を削減できます

3. **簡単な実装**
  - WebSubは既存のHTTPプロトコルを使用するため、追加の技術的要件が少なく、比較的容易に導入できます

4. **標準化**
  - W3C推奨のプロトコルとして広くサポートされており、さまざまなプラットフォームやサービスで利用可能です

## デメリット

- **Hubへの依存**
  - 更新の通知はHubを通じて行われるため、Hubの可用性や性能に依存します。例えば、Hubがダウンすると通知が遅延したり受信できなくなったりする可能性があります。

- **セキュリティ**
  - WebSubの実装には認証や暗号化が求められる場合があり、適切に設定しないとデータの改ざんや不正アクセスのリスクがあります

# WebSubの実装例

当システムでは、掲載案件が作成・更新・削除される際に、Google WebSub Hubに案件一覧のフィード情報を送信することで、リアルタイムに更新を共有しています。

# WebSubの活用事例

## ニュースサイトの更新通知

大手ニュースサイトでは、記事が公開または更新されるたびにWebSubを使用して購読者にリアルタイムで通知を送っています。これにより、読者は迅速に最新情報を得ることができます。

## ブログプラットフォーム

ブログ作成サービスでは、ユーザーが新しい投稿を公開した際にWebSubを利用して購読者に通知を送信しています。これにより、コンテンツ配信が効率化されています。

## ポッドキャストの配信

ポッドキャストプラットフォームでは、新しいエピソードが公開されるたびにWebSubを使用してリスナーに通知を送信しています。これにより、リスナーは新しいコンテンツを見逃すことがなくなります。

## 開発者向けAPIの利用

APIを提供するサービスでは、データが更新されるたびにWebSubを使用してクライアントに通知を送信しています。これにより、クライアントは効率的に最新データを取得できます。

## Rails を使った WebSub の実装例

以下は、Rubyを用いて Publisher として WebSub を実装するシンプルな例です。

```ruby
require 'net/http'
require 'uri'

class WebSubPublisher
  HUB_URL = 'https://pubsubhubbub.appspot.com/' # 使用するHubのURL

  def self.publish(feed_url)
    uri = URI.parse(HUB_URL)
    response = Net::HTTP.post_form(uri, {
      'hub.mode' => 'publish',
      'hub.url'  => feed_url
    })

    if response.is_a?(Net::HTTPSuccess)
      puts 'Feed successfully published to WebSub Hub'
    else
      puts 'Failed to publish feed'
    end
  end
end

# フィードのURLをHubに送信
feed_url = 'https://example.com/feed'
WebSubPublisher.publish(feed_url)
```

このコードでは、Net::HTTPを使用してHubに対してフィードの更新を通知しています。`HUB_URL`は利用するHubのURLで、GoogleのWebSub Hubを使用しています。`publish`メソッドにフィードのURLを渡すことで、Hubに更新を伝達します。

# おわりに

ミィ！
[rev] luau (CakeCTF 2022) writeup

---

- Source: CakeCTF 2022
- Author: [ptr-yudai](https://x.com/ptrYudai)

---

Luaのreversing問。`main.lua`と`libflag.lua`が与えられる。

`main.lua`から`libflag.lua`を呼び出しているが、`libflag.lua`はLua bytecodeになっており、中身を見ることができない。
```lua
local libflag = require "libflag"
io.write("FLAG: ")
flag = io.read("*l")
if libflag.checkFlag(flag, "CakeCTF 2022") then
   print("Correct!")
else
   print("Wrong...")
end
```

```sh
$ file main.lua
main.lua: ASCII text
$ file libflag.lua
libflag.lua: Lua bytecode, version 5.3
```

Luaを逆アセンブルする方法を探していると[オンラインで逆アセンブルできるサイト](https://luadec.metaworm.site/)が見つかった。`libflag.lua`の逆アセンブル結果はこうなる。
```lua
-- filename: 
-- version: lua53
-- line: [0, 0] id: 0
return {
  checkFlag = function(r0_1, r1_1)
    -- line: [1, 32] id: 1
    local r2_1 = {
      62,
      85,
      25,
      84,
      47,
      56,
      118,
      71,
      109,
      0,
      90,
      71,
      115,
      9,
      30,
      58,
      32,
      101,
      40,
      20,
      66,
      111,
      3,
      92,
      119,
      22,
      90,
      11,
      119,
      35,
      61,
      102,
      102,
      115,
      87,
      89,
      34,
      34
    }
    if #r0_1 ~= #r2_1 then
      return false
    end
    local r3_1 = {}
    local r4_1 = {}
    for r8_1 = 1, #r0_1, 1 do
      r3_1[r8_1] = string.byte(r0_1:sub(r8_1, r8_1 + 1))
    end
    for r8_1 = 1, #r1_1, 1 do
      r4_1[r8_1] = string.byte(r1_1:sub(r8_1, r8_1 + 1))
    end
    for r8_1 = 1, #r3_1, 1 do
      for r12_1 = r8_1 + 1, #r3_1, 1 do
        r3_1[r8_1] = r3_1[r12_1]
        r3_1[r12_1] = r3_1[r8_1]
      end
    end
    for r8_1 = 1, #r3_1, 1 do
      r3_1[r8_1] = r3_1[r8_1] ~ r4_1[1 + (r8_1 - 1) % #r4_1]
      if r3_1[r8_1] ~= r2_1[r8_1] then
        return false
      end
    end
    return true
  end,
}
```

このままでは見にくいので変数名を綺麗にする。
```lua
return {
  checkFlag = function(userInput, key)
    local data = {
      -- (略)
    }
    if #userInput ~= #data then
      return false
    end
    local arr1 = {}
    local arr2 = {}
    for i = 1, #userInput, 1 do
      arr1[i] = string.byte(userInput:sub(i, i + 1))
    end
    for i = 1, #key, 1 do
      arr2[i] = string.byte(key:sub(i, i + 1))
    end
    for i = 1, #arr1, 1 do
      for j = i + 1, #arr1, 1 do
        arr1[i] = arr1[j]
        arr1[j] = arr1[i]
      end
    end
    for i = 1, #r3_1, 1 do
      r3_1[i] = r3_1[i] ~ arr2[1 + (i - 1) % #arr2]
      if r3_1[i] ~= data[i] then
        return false
      end
    end
    return true
  end,
}
```

処理としては引数をbyte列に変換し、配列の隣の値とswapしてからxorを取っているっぽい。swap時に配列の値を直接上書きしているのが気になるが、逆アセンブルの時に省略されてしまったものだと仮定して進める。
```lua
    for i = 1, #arr1, 1 do
      for j = i + 1, #arr1, 1 do
        arr1[i] = arr1[j]
        arr1[j] = arr1[i]
      end
    end
```

solverを書く。
```py
data = [
  62, 85, 25, 84, 47, 56, 118, 71,
  109, 0, 90, 71, 115, 9, 30, 58,
  32, 101, 40, 20, 66, 111, 3, 92,
  119, 22, 90, 11, 119, 35, 61, 102,
  102, 115, 87, 89, 34, 34
]
key = "CakeCTF 2022"

flag = ""
for i in reversed(range(len(data))):
  flag += chr(data[i] ^ ord(key[i % len(key)]))

print(flag)
```

flagが得られた。
`CakeCTF{w4n1w4n1_p4n1c_uh0uh0_g0ll1r4}`
【TypeScript】type-challenges 初級編 3057・push 解説

## お題
タプルに要素を追加する型`Push`（`Array.push`のジェネリックバージョン）を実装する。

## やりたいこと
```typescript
type Result = Push<[1, 2], '3'> // [1, 2, '3']
```

## 解答
```typescript
type Push<T extends unknown[], U> = [...T, U];
```

## 解説
### 処理の流れ
- `<T extends unknown[], U>`
タプルに要素を追加するので、`T`に制限をかける。
- `[...T, U]`
スプレッド構文で展開した`T`の要素と`U`を[]でラッピングし、新たなタプルを作成する。

:::note warn
配列型を扱う注意点
```typescript
type T = number[]; // 配列型
type Result = [...T, boolean]; // エラー
```
:::

### スプレッド構文とは...
https://qiita.com/yuto99999/items/f77e22e0a1e80b867ee5#%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E6%A7%8B%E6%96%87%E3%81%A8%E3%81%AF

## 今回の問題
https://github.com/type-challenges/type-challenges/blob/main/questions/03057-easy-push/README.ja.md
状態管理を学ぶためにNext.jsでTodoアプリを作ってみた

Astroを利用して勤怠管理を作っていくための学習過程をアウトプット中。
これまでの記事はこちら。

https://qiita.com/kuma_radcof/items/ed5a694ed84f0974e519

https://qiita.com/kuma_radcof/items/826bd0956ef8d55a8705

データベース（として利用していたスプレッドシート）に保存することはできたけど、入力したTodoリストはやっぱりトップページにも表示させたいよなぁと思って次の学びのステップへと移行。

Astroはマルチフレームワーク対応なので、reactでコンポーネント作成もできるけど、Next.jsだったら切り分けなくても同じファイル内に記述することもできるようなぁと思い世の中の流れも鑑みてnext.jsでもやってみることに。


## 今回学びたかったのはuseHooksのこと
たくさんHooksはあるけど、とりあえず有名どころというか基本になってるようなuseStateを使ってみることにした。

## コード全容
```next.js:src>app>page.tsx

"use client";
import { useCallback, useState } from "react";

export default function Home() {

  // 入力欄の管理
  const [inputValue, setInputValue] = useState("");

  // タスクのリスト管理
  const [taskList, setTaskList] = useState<string[]>([]);


  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputValue(e.target.value);
  }


  const addTasks = useCallback(() => {
      setTaskList((items) => [...items, inputValue]);
      setInputValue("");
  }, [inputValue]);

  return (
        <div>
          <input 
          type="text"
          value={inputValue}
          onChange={handleInputChange}
          />
          <button onClick={addTasks}>タスクを追加</button>

          <ul>
            {taskList.map((item, key) => {
              return <li key={key}>{item}</li>
            })}
          </ul>
        </div>
    );
}

```

という感じでローカルホストを立ち上げるとtodoリストの更新がトップページ上でできるようになって、リロードしたらリセットされるといったところに行き着いた。
でも、これを一目見ただけだと後から見返したらよくわからんなーというのが正直なところ。
なので、どんな手順で考えたかというのを記録しておこうと思う。

## まず必要なのは、HTMLの入力部分
まずは入力してリストに追加できるような`input`タグと`button`タグを用意する。
この時、inputタグには属性値をいろいろ指定することができるわけだけど、デフォで入っているのはtype属性のみ。
inputタグに入力した文字列・数字を表示させたままにしたり、todoリストの配列に追加したりする目的でvalue属性に一つ変数を入れておく必要があって、**入力値の管理をする**ために一つ目のuseStateが必要になる。
```
const [inputValue, setInputValue] = useState("");

<input 
    type="text"
    value={inputValue}
/>
```
この時、初期値としては空欄にしておきたいので、useStateの引数に""を指定している。

## 次に必要となるのがinputタグの入力値を更新するためのonChange属性
現状のままだとvalue={inputValue}の指定で、初期値を空欄にしてるので、何を入力したとしても空欄のままになってしまう。
この状況を改善するために、入力値を受け取ってinputタグの中を更新しておくという処理が必要になる。
そのためにonChange属性には値を更新させる任意の関数を作る必要がある。
```
const handleInputChange = (e) => {
    setInputValue(e.target.value);
}

<input
    type="text"
    value={inputValue}
    onChange={handleInputChange}
/>
```
が追加されることになる。

## 次に作るのはbuttonタグの押下処理
ここで実装するのは
1. ボタンタグをクリック
1. タスクを配列に追加する任意の関数を実行させる
1. タスクを配列に追加する関数が発火したらタスクリストを更新してHTML要素として出力

といったことになる。今回はそのためにaddTasks関数を用意した。タスクリストの管理、更新を目的として二つ目のuseStateが必要となる。
```

  // タスクのリスト管理
  const [taskList, setTaskList] = useState<string[]>([]);
  
  const addTasks = useCallback(() => {
      setTaskList((items) => [...items, inputValue]);
      setInputValue("");
  }, [inputValue]);

  <button onClick={addTasks}>タスクを追加</button>

  <ul>
    {taskList.map((item, key) => {
      return <li key={key}>{item}</li>
    })}
  </ul>
  
```


あとはHTML要素をフラグメントによって囲っておけばページが表示されるようになる。

## まとめ
今回のように出来上がったものを見るだけではなく、どう考えてコードを上に書いたり下に書いたり、関数の中に入れたりコンポーネントとして切り分けたりといった手順がわかればもっと作りやすくなるなぁと感じた。
同じファイルの中で作れてしまうのでnext.jsは結構やりやすい。
あとはDB連携の部分で慣れてくればNext.jsでもいいのかもなぁ。。
勢いでセキュリティのコミュニティ（Security.any）を立ち上げた話

昨年からセキュリティ業務に新しくチャレンジを始めました。
その関係で、知識や人間関係のアップデートを考え、いくつかセキュリティ含めたエンジニア向けの勉強会やイベントに参加しました。そこで、運営側の苦労や重要性に気づき、自分も運営に貢献したいと思うようになりました。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70168/c9c726b4-65a6-e953-c8ae-0f20bd89ca9a.jpeg">

## 運営の大変さ

自身で社内の勉強会の開催などは行っていたものの、社外向けの勉強会やカンファレンスに参加することで、運営側の苦労を実感しました。準備や進行など、裏方の努力があってこそイベントが成功することを理解し、自分も運営に参加したいと感じました。

## オフラインでの交流の大切さ

オンラインイベントも便利ですが、オフラインで直接交流することの大切さを改めて感じました。顔を合わせることで、より深い情報交換や人脈が築けると思い、オフラインイベントを基本方針にしました。

## セキュリティ関係者の知り合いを増やしたい

私自身、セキュリティに携わっている人と直接交流し、知識を深めたかったです。また、同じ業界の様々な人と情報交換をすることが、双方で新たな気づきにつながると感じています。

## 気軽にLTしたい

Connpassで勉強会を検索してみると、セキュリティについての割合が少ない事に気づきました。私自身も気軽にLTしたいも思っていたため、もっとセキュリティ関係者同士が気軽に知識を共有できる場を増せる動きをしようと考え始めました。

## さいごに
これらの思いから、セキュリティコミュニティ『[Security.any](https://security-any.connpass.com/)』を立ち上げました。オフライン交流やLTの場を提供し、参加者同士が気軽に学び、成長し、人脈を広げることができる環境を作ることを目指しています。

# 告知 第2回イベント告知ページ
Security.any #02 セキュリティあの頃はLT

https://security-any.connpass.com/event/336993/
VSCodeの保管アクションでPrettierを実行する

# はじめに

https://qiita.com/grhg/items/c4caaf78040b4e2c3c35

Prettier を入れても手動で実行するのは面倒ですね。
そこで、VSCode の保管アクションによる自動フォーマットを有効にします。

# 手順

## 拡張機能のインストール

https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode

上記の拡張機能をインストールします。

## 設定の追加

VSCodeの `Settings` を開き、以下を設定します。
(タブは `Workspace`(開いているプロジェクトでのみ有効な設定)としておきます)

### Default Fromatter
1. `default formatter` を検索
2. Editor: Default Fromatter のプルダウンで `Prettier - Code formatter` を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294382/b77d7a13-8335-4627-a052-7471fd209662.png)
3. `format on save` で検索します。
4. `Editor: Format On Save` にチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294382/a931ae89-de17-817d-132f-6683e3fc1da4.png)

# 確認

設定はこれだけです。
実際に保管時に整形されるかどうかを確認してみましょう。

![test3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3294382/d6ce859d-1da3-142b-78b1-d2236cec4fef.gif)

問題なさそうです。
`.prettierrc.yaml` の設定もちゃんと反映されていました。
Re:ゼロから始めるアウトプット生活

# 導入
こんにちは、もんすんです。

Advent Calendar 2024の[はじめてのアドベントカレンダー](https://qiita.com/advent-calendar/2024/first-time)の20日目の記事をお届けします！

今年、私は、初めてアドベントカレンダーに参加しました。:muscle::muscle:
まさにテーマ通り「はじめてのアドベントカレンダー」ということになります。

アニメのように壮大な冒険が始まるわけではありませんが、私自身の「**アウトプット**」という新たな世界への挑戦を描いてみました。

これまでアウトプットを避けていた私が、どのようなきっかけで挑戦を始めたのか。
そして、その挑戦がどのような結果を生んだのか。
そんなお話を綴っていきますので、最後までお付き合いいただけると嬉しいです！

# アドカレと私
## これまでアドベントカレンダーに参加しなかった理由

アドベントカレンダーというイベントの存在は知っていましたが、実はこれまで一度も参加したことがありませんでした。
その理由を振り返ってみると、以下のような要因がありました。

### 技術記事を書くのが苦手だった

文章を書くこと自体には抵抗がなかったのですが、特に技術に関する記事を書くのが苦手でした。
専門的な内容をどうやってわかりやすく説明するか、自分の知識が足りないのではないかと不安に感じ、なかなか筆が進みませんでした。

### そもそも興味がなかった

去年まではアウトプットの必要性を感じておらず、「記事を書く」という行為そのものに魅力を感じていませんでした。
技術的な情報を調べたり、学んだり、実践したりするのは好きでしたが、それを発信しようという意欲がまったく湧かなかったのです。

### 得られるものが少ないと思っていた

「記事を書いても、自分の学びにならない」「大した内容を書けないから、誰かの役に立てる気がしない」といった考えから、時間を割いて記事を書く意義を見出せていませんでした。自分の時間を他の活動に使うほうが価値があると思い込んでいた節もあります。

### アウトプットをしようとしていなかった

総じて、日頃からアウトプットをする習慣がありませんでした。
技術学習や読書などのインプットに力を入れる一方で、それを外部に共有することの価値を理解していなかったのです。

こうして振り返ってみると、参加しなかった理由の多くは「アウトプットへの意識の欠如」だったように思います。
しかし、そんな自分が今年、ついにアドベントカレンダーに挑戦することになりました。

## なぜ今年は参加したのか

では、どうして今年は一歩踏み出してアドベントカレンダーに参加することになったのか。
その背景には、いくつかの大きなきっかけがありました。

### アウトプットの重要性を意識するようになった

去年あたりから、「アウトプットを通じて成長する」という考え方に触れる機会が増えました。
特に印象的だったのは、「アウトプットすることで学びが深まる」という言葉でした。

以下のような気づきが、自分を行動に駆り立てました。

- 知識の整理と定着が進む
- 自分の考え方を可視化できる
- 他者からのフィードバックを得られることで新たな視点が生まれる

このように、アウトプットは単なる自己満足ではなく、学びのサイクルを強化する重要な行動であると実感しました。

### 書く習慣を徐々に身につけた

そういったアウトプットの重要性を意識するようになってから、去年の終盤から今年の前半にかけて、別のブログサイトで、読んだ本の感想や学んだことを記録する習慣を始めました。
技術的なテーマではありませんでしたが、自分の言葉でまとめる経験が「発信する楽しさ」を教えてくれました。

これにより、<font color="red">「とにかく一度書いてみる」</font>という気持ちが芽生えたのです。

### Qiita Engineer Festa 2024への参加

今年の夏、思い切って参加した「Qiita Engineer Festa 2024」は、自分にとって大きな転機となりました。

- **38記事を投稿**して、キャンペーンを完走しました🎉
- **きーたん(Qiitan)のぬいぐるみ**などの達成感を象徴するアイテムを手に入れた
- 多くはないですが、数件「いいね」をもらい、発信する喜びを感じた

アウトプットに対する苦手意識が薄れ、<font color="red">「やればできる！」</font>という自信がついたのは、この経験のおかげです。

:::note warn
きーたんのぬいぐるみは娘が大変気に入ったため、奪われてしまいました。。。
:::

## 1人アドベントカレンダー

ということで、今年はアドベントカレンダーを参加することにしました。
どのアドカレに参加しようかみていると、1人アドカレを作っている方がいらっしゃいました。
それに感化された私は、同様に自分専用の1人アドカレを作成しました。😸


完走できそうな予定なので、見て行ってもらえると嬉しいです！

# 来年の目標(?)

アドベントカレンダーを通じて、アウトプットする楽しさを実感し、技術コミュニティの存在などにも気づくことができました。
そこで、来年はさらにステップアップを目指して、以下の目標を設定しました。

### アウトプットを継続する

アドベントカレンダーは終わっても、Qiitaなどのブログを活用して、技術的な学びを発信し続けようと思います。
1年でどれだけ成長できるか、来年の今頃振り返るのが楽しみです。

### 外部カンファレンスでの発表

これまで参加者として学びを得る側だったカンファレンスで、次は自分が発表者としてステージに立ちたいと考えています。
小さな勉強会からでもチャレンジし、自分の経験や知識を共有する機会を増やしていきたいです。

### カンファレンスのスタッフとしての関わり

運営側の視点でイベントに携わることで、新しいスキルや経験を得たいと思っています。
特に、多くの人と協力して一つのイベントを作り上げる達成感を味わいたいです。

# 最後に

アドベントカレンダーに挑戦してみて、最初は不安もありましたが、やってみれば本当にやってよかったと思っています。
アウトプットに挑戦したいけど迷っている方がいたら、<font color="red">「まずは一歩踏み出しましょう！」</font>とお伝えしたいです！

来年も引き続き挑戦を続けていくので、ぜひ一緒にアウトプットを楽しんでいきましょう！ 💪💪💪💪
【NVIDIA GPU】Transformer Engineを動かしたかった

結論から言うと**ハードウェアが対応しておらず動きませんでした**。しかし環境構築の手順としては間違っていないと思うので書き残しておきます。

# FP8で学習したい
FP8は、8bitで浮動小数点数を表現するデータフォーマットです。深層学習をFP8で行うことのメリットとして、以下が挙げられます。
- 学習速度の向上
- メモリ使用量の削減
- 推論と同一の精度を用いることによる、量子化に伴う誤差の低減

FP8を用いてTransformerモデルの学習を効率的に行うためのNVIDIA謹製オープンソースライブラリが[Transformer Engine](https://github.com/NVIDIA/TransformerEngine)です。[NVIDIAの技術ブログ](https://developer.nvidia.com/ja-jp/blog/introduction-to-fp8-training-using-transformer-engine/)にて詳細な解説がなされています。

# 導入
## 環境
- Ubuntu 22.04 LTS amd64
- GeForce RTX3090
- CUDA 12.3

## cuDNNのインストール
pipでいきなり入れようとしたらcuDNNが無いと怒られたので導入します。
[cuDNN Archive](https://developer.nvidia.com/rdp/cudnn-archive)からダウンロードします(要NVIDIAアカウント)。OSおよびCUDAの環境に合わせてダウンロードしてください。以下はdeb系の場合のコマンドです。
```bash
sudo dpkg -i cudnn-local-repo-ubuntu2204-8.9.7.29_1.0-1_amd64.deb 
sudo cp /var/cudnn-local-repo-*/cudnn-local-*-keyring.gpg /usr/share/keyrings/
sudo apt update
sudo apt install libcudnn8 libcudnn8-dev libcudnn8-samples
```
## Transformer Engineのインストール
pipで導入する場合です。
```bash
pip3 install git+https://github.com/NVIDIA/TransformerEngine.git@stable
```
## 動かない
NVIDIAの技術ブログにあるサンプルコードを動かしてみると、
>File "/usr/local/lib/python3.10/dist-packages/transformer_engine/pytorch/fp8.py", line 539, in fp8_autocast
FP8GlobalStateManager.fp8_autocast_enter(
File "/usr/local/lib/python3.10/dist-packages/transformer_engine/pytorch/fp8.py", line 394, in fp8_autocast_enter
assert fp8_available, reason_for_no_fp8
AssertionError: Device compute capability 8.9 or higher required for FP8 execution.

と表示されました。私の環境では動かないようです。私の調査によるとFP8がコンシューマ向けGPUに搭載されたのは4000番台かららしいので、3090は非対応ということになります。
</br>
</br>
~~いかがでしたか？~~ 研究室の先生におねだりしてFP8が使えるGPUを買ってもらおうと思います。
Project Astraとは何か？

Project Astraは、Google DeepMindが開発中の実験的なAIアシスタントプロジェクトであり、私たちの日常生活に溶け込み、周囲の状況を理解し、さまざまな状況下で支援を行う「ユニバーサルAIアシスタント」の実現を目指しています。  
音声コマンドによる単純な応答にとどまらず、視覚情報や環境コンテキストを踏まえ、ユーザーが何を求めているかを先回りして理解し、自然で直感的な対話を可能にすることがProject Astraのビジョンです。

## マルチモーダル＆コンテキスト対応AIアシスタント

Project Astraの最大の特徴は、音声コマンドに限らず、**マルチモーダルな情報処理**能力を備えている点です。これは、ユーザーが音声、テキスト、画像、動画といった複数の形式で情報を入力し、Astraはこれらを総合的に理解・判断して応答できることを意味します。  
たとえば、歴史的建造物をカメラで捉え、その概要や歴史的背景を質問すると、Astraは画像認識を用いて建物を同定し、関連情報を提示することが可能です。

また、**コンテキスト理解力**も重要な要素です。Astraはユーザーが置かれた状況や会話の流れを踏まえて、より適切で文脈に合った答えを返すことが期待されています。  
たとえば、カーレース現場で特定のマシンについて尋ねれば、Astraはカメラ映像からその車種を認識し、スペックや過去のレース戦績、ドライバー情報などを即座に提示することも可能です。

## 主な特徴

| 特徴 | 説明 |
| ---- | ---- |
| 自然な対話 | 多言語対応や声色・アクセントへの柔軟性、視覚的入力など、直感的なコミュニケーションが可能 |
| 高速応答・自由度の高い会話 | 人間の対話と遜色ない低遅延で素早く返答し、話題を自由に変えられる自然な対話を実現 |
| メモリー機能 | 過去数分間の対話内容を記憶し、これまでの文脈を踏まえた回答が可能 |
| Googleサービスとの連携 | Google検索・マップ・レンズなどと統合し、膨大なナレッジベースへの瞬時アクセスとリアルタイム情報の提供が可能 |
| レイテンシの改善 | 人間同士の会話レベルの反応速度を目指し、ストレスフリーなインタラクションを実現 |
| クロスデバイス機能 | スマートフォンやプロトタイプグラスなど、異なるデバイス間でシームレスに会話を継続可能 |

## 利用シナリオの例

- **クリエイティブツールとして**：  
  写真を見せて、そこから物語の構想や音楽のアイデアを生成するなど、クリエイティブな発想補助ツールとして機能。

- **バーチャルガイドとして**：  
  旅行先で建造物やランドマークをカメラに収め、その歴史的背景や由来を即座に案内。より深い体験を提供。

- **リアルタイム情報提供**：  
  イベント会場などで、目の前の対象物に関する詳細情報を瞬時に取得。興味を持った対象の理解を一層深める。

- **レシピ提案**：  
  冷蔵庫の中身を見せ、利用可能な食材から作れる料理レシピをAstraが提案することで、日常の食事計画が容易に。

## 開発の現状と今後の展望

Project Astraは現在、限定的なテスターによる試験運用段階にあります。ユーザーからのフィードバックをもとに改良を重ね、機能の洗練や応用範囲の拡大が期待されます。また、2024年のGoogle I/OでのデモやGemini 1.5 Flashモデルの導入により、さらなる高速化・高度化を目指す方向性が示されています。

Google DeepMindはAIの責任ある開発を強調しており、Project Astraの発展においても安全性・倫理性を重視。AIの潜在的なバイアスや公平性の確保などの課題にも真摯に取り組んでいます。

## まとめ

Project Astraは、マルチモーダルかつコンテキスト対応の次世代AIアシスタントとして、我々の日常生活に新たな価値をもたらす可能性を秘めています。  
自然言語処理、画像認識、リアルタイム情報取得、Googleサービスとの統合など、多面的な機能を持つAstraは、単なるツールではなく、私たちの創造性や知的好奇心を支える「パートナー」としての役割を担う存在へと進化しつつあります。

今後、Astraが公に利用可能になることで、より多くの人々がこの新しいAI体験を享受できるようになるでしょう。ただし、それに伴う倫理的・社会的課題に対する慎重な対応も不可欠です。Project Astraは、未来のAIアシスタント像を提示するとともに、その実現へ向けた挑戦と責任を示すプロジェクトといえます。

## 関連情報

- [Project Astra - Google DeepMind公式サイト](https://deepmind.google/technologies/project-astra)  
- [Project Astraデモ動画（YouTube）](https://www.youtube.com/watch?v=rL6y0_X0muM)  
- [Gemini 2.0リリース、およびProject Astraアシスタントのさらなる活用事例](https://droid-life.com/2024/12/11/google-launches-gemini-2-0-shows-off-more-project-astra-assistant-with-glasses)
python: icecream.ic で Failed to access the underlying source code for analysis と出たときは

# 背景

単に、微妙ーになんだこれ？ってなった際に調べた記録

いきなりこんなエラーでたら、なんだこれ？ってなりませんか？ってお話

> ic| Error: Failed to access the underlying source code for analysis. Was ic() invoked in a REPL (e.g. from the command line), a frozen application (e.g. packaged with PyInstaller), or did the underlying source code change during execution?


# 結論

実行直後にソース編集とかするとでちゃうので、再度実行すれば OK ってだけみたい


# あとがき

実行時に即座に次の編集せずに、ちょっとは余裕を持ちましょう :laughing: 

VS Code でエラー無ければ自動保存、って感じにしておけば、自ら CTRL+S で保存してこんなことにもなりにくい・・のかな？ :thinking:
AVD構築してみた


# はじめに

AVD構築にチャレンジした際、躓いた点などを備忘録として書いておきます。

# 前提条件

公式ドキュメントは以下

https://learn.microsoft.com/ja-jp/azure/virtual-desktop/prerequisites?tabs=portal

「サポートされる ID シナリオ」の欄がとても重要です。

#### 単語ざっくり説明
◆Microsoft Entra ID  
Azureでアカウントを作ると作成されています。AVDを構築する際「Entra IDのみ」とするのはおすすめしません。

◆ ADDS　
Windows ServerにADの機能を追加したものを指します。
オンプレでも、Azure上のVMでもどちらでもOKです。
別途Entra IDと「Entra Connect」をさせる必要があります。

◆Entra Domain Services
Azureが提供しているADサーバみたいなものです。
これが一番簡単ではないかと思いますが、費用が２万/月くらいします。
GPOの制御などが必要であれば管理用VMを別途立てなければならない点は注意です。

◆私が構築したのはこちら（Entra ID ＋　ADDS)

https://qiita.com/yuyanz/items/69f38e80c798b1caf16f

ユーザはADサーバにRDPして作成したものを使用。

# 構築

https://learn.microsoft.com/ja-jp/azure/virtual-desktop/deploy-azure-virtual-desktop?tabs=portal-session-host-configuration%2Cportal-standard%2Cportal&pivots=host-pool-standard

基本的には上記の通りポチポチ進めれば大丈夫です。

私はとにかく動かしてみたかったため、
シングスセッションで構築することにしたのですが、
デプロイエラーで中々進めることができませんでした。

# 躓きポイント

①アカウントの入力ミス

デプロイエラーの原因はアカウント入力ミスでした。

参加するドメイン
参加するディレクトリを選択する
⇒こちらはADの管理者アカウントを指定

仮想マシンの管理者アカウント
⇒こちらは適当にAVD用に作るアカウントなので何でもOK

AD管理者のアカウントが必要とわからず、躓きました。パスワードが間違えていてもデプロイできないので注意です。

②ゴミが残っている
デプロイ失敗した際は中途半端にデプロイが進むため「ゴミ」が残します。
リソースグループから、中途半端に作られたVMなどを一度削除してからリトライするといいです。
ゴミのせいでうまくいかなかったりすると、原因の特定が非常に難しくなります。
※初心者の頃はデプロイ画面で、デプロイのタスクを削除したら全てクリアされるものだと思い込んでいたので、大量のゴミが発生しました（笑）

③割り当て
私はうまくいかない回数が多かったので、ユーザを作り直したり色々操作した弊害がでました。
過去に割り当てたユーザを削除してしまい、割り当てができなくなってしまうということがありました。

私の場合は
Azure portal>AVD>ホストプール>セッションホスト>割り当て
から割り当て解除＆再割り当てを行うことでうまくいきました。

#最後に

無事割り当てができれば
APから接続してデスクトップが表示されるかと思います。
デフォルトでは英語になっているので日本語にして使うとよいと思います！
.NET のプロジェクトを作成し DockerImage を作成する

# 概要
Microsoftのチュートリアルを参考に.NETのWEB APIプロジェクトの作成からDocerImageを作成する
## ハンズオン内容

minimal WEB API プロジェクトの作成
dotnet による image の発行
DockerFile による Image の発行

## 前提

.NET 8.0
VsCode
Docker
DockerDesktop

## minimal WEB API を作成する

- プロジェクトの作成
```
dotnet new web -o SampleStore -f net8.0
```
- アプリの確認
```
dotnet run
```
ビルドが成功しURLを叩くと"Hello World"が表示されることを確認する

## DockerFile から DockerImage の作成

- Dockerfile をrootに作成

```dockerfile
# ベースイメージとして .NET SDK を使用してビルドステージを定義
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build

# 作業ディレクトリを設定
WORKDIR /app

# プロジェクトファイルをコピーして依存関係を復元
COPY SampleStore.csproj .
RUN dotnet restore

# ソースコードをコピーしてリリースビルドを実行
COPY . .
RUN dotnet publish -c Release -o /out

# 実行用のベースイメージとして ASP.NET Core ランタイムを使用
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /out .

# ポートを公開
EXPOSE 80

# アプリケーションを実行
ENTRYPOINT ["dotnet", "SampleStore.dll"]
```

- Dockerをビルドしてimageの作成
```
docker build ./ -t samplestore:latest
```
- image の確認
```
docker image ls
```
- コンテナの起動
```
docker run -it --rm -p 32001:8080 samplestore
```
- APIを叩き"Hello World"が表示されるのを確認する
http://localhost:32001/

## dotnet publish から DockerImage を作成する

- 以下コマンドにより image を作成する
  dotnet publish /p:PublishProfile=DefaultContainer
- image の確認
  docker image ls
- コンテナの起動
  docker run -it --rm -p 32001:8080 pizzastore
- API の確認
  http://localhost:32001/

# エラーメモ
- DockerfileをDockerFileと作成していてビルド時にエラーがでた


# 参考

minimal API、ASP.NET Core、.NET を使用して Web API をビルドする
https://learn.microsoft.com/ja-jp/training/modules/build-web-api-minimal-api/
.NET を使用して最初のマイクロサービスをビルドする
https://learn.microsoft.com/ja-jp/training/modules/dotnet-microservices/
【Excel】yyyymmdd形式から日付形式に変換する自作関数【LAMBDA関数】

[8桁の数字を日付に変換するには (数式)｜クリエアナブキのちょこテク](https://www.crie.co.jp/chokotech/detail/462/)
`
=TEXT(yyyymmddのセル, "0000!/00!/00")*1
`
メインはこれだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/5451ea24-4ac8-0043-264e-e3a1d5bc7dc1.png)

 
ただ変換して終わらず、日付同士の計算をしたい場合など、
2つも書くと関数が冗長になるので
LAMDA化して使いまわせる形にしておくと楽です。
（ブックをまたいでの使いまわしはできませんが）
 
これで終わりなので
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/46953faa-9019-eea2-a13f-43739c130cbc.png)

日数差を出したいときはこれだけで済みます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/a9b01225-289c-8e99-647e-85caec58cd40.png)

LAMDA関数の作り方
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/bc4e7f9a-40a5-da01-ebe4-7cc8fea9bbff.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/bad95c9d-b44f-3731-5a56-78329e74cead.png)

名前：関数名として表示する部分
アンダースコア（"_"）で始めておくと予測変換で絞り込みやすいです
`_lambda_ymd2Date`
参照範囲：関数の中身
`=LAMBDA(yyyymmdd,TEXT(yyyymmdd,"0000!/00!/00")*1)`
絵日記やりたいけど、手動は負担だった。。そんな課題を生成AIで解決してしまおう / I want to keep a picture diary, but manual operation is too burdensome. Let's solve such a problem with generative AI! (日本語 / 英語)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812041/99c658b3-1c09-aa1a-85e4-34c145501f16.png)

# 日本語
こんばんわ！
Advent Calendar 2024に参加してまして、12日目の記事を書いていこうと思います。
題材は「身の回りの困りごとを楽しく解決！ by Works Human Intelligence Advent Calendar 2024」ということで、生成AIで絵日記を作成した経験について調べていきたいと思います。

### どんなものを作ったか？
AzureのOpenAIで画像生成と文字生成を利用して、フロントにNext.js、バックエンドでFlaskを使用したアプリを作成しました。
他にもAzureのDBや文字分析を使用してアレンジを加えてとても楽しいアプリができたと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812041/40ae60ef-5bd0-c568-c1bf-4d692535df29.png)

### どんな効果があったか
一日に何があったかって意外と大事ですよね！私は大事にしています！

そんな私にとって絵日記を生成してくれるアプリは日々を楽しくし、何かをしようという気持ちになれます！Azureのサービスを色々触ってみたいと始めたアプリでしたがとても学びになったし、ためになったアプリです！

以上です！
ここまで読んでいただきありがとうございます

# ENGLISH
Good evening!
I'm participating in Advent Calendar 2024, and I'm going to write an article for the 12th day.
The subject is “Solving everyday problems in a fun way! by Works Human Intelligence Advent Calendar 2024”, I would like to investigate my experience of creating a picture diary with generative AI.

### What did I create?
We created an app using Azure's OpenAI for image and text generation, with Next.js on the front and Flask on the backend.
We also used Azure's DB and character analysis and arranged them to create a very fun app.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812041/40ae60ef-5bd0-c568-c1bf-4d692535df29.png)

### What effect did it have?
What happened in a day is surprisingly important! I value it!

I started this app to try out Azure services, but it has been a great learning experience for me and has been very beneficial!

That's all!
Thank you for reading this far!
Azure: AI Search で indexer 作成するなら、debug session 使わないとやってられない

# 背景

スキルセットを作ろうとしたところ、なんか上手く動いてくれないことが多い
で、ドキュメントや公式サンプルとにらめっこしていた。

何が難しいって、
- 内部ドキュメントツリーがどう構築されているかわからない
- python SDK ではエラーが出ないことも多く、一見正常終了したように見える

ムズカシーって悩んでたところ、

会社にて felo 使ってないなら使うべき、っていう投稿をみて試してみたところ、debug session なるものがあることに気付いた

https://felo.ai/search

以下公式

https://learn.microsoft.com/ja-jp/azure/search/cognitive-search-how-to-debug-skillset

# debug session はどこに？

![](https://learn.microsoft.com/ja-jp/azure/search/media/cognitive-search-debug/new-debug-session.png)

# 事前準備

- blob に対して、AI Search が操作出来るように RBAC 設定：権限は [ストレージ BLOB データ共同作成者]

# debug session の良いところ

- 内部での[エラー・警告](https://learn.microsoft.com/ja-jp/azure/search/cognitive-search-how-to-debug-skillset#start-with-errors-and-warnings) が見れるので、対処が可能
    - ![](https://learn.microsoft.com/ja-jp/azure/search/media/cognitive-search-debug/debug-session-errors-warnings.png)
- [document source, skill sets, field mappings が見えるか](https://learn.microsoft.com/ja-jp/azure/search/cognitive-search-how-to-debug-skillset#view-enriched-or-generated-content)される
    ![](https://learn.microsoft.com/ja-jp/azure/search/media/cognitive-search-debug/debug-session-expand-details.png)
    - 現在の値もみられる
        ![](https://learn.microsoft.com/ja-jp/azure/search/media/cognitive-search-debug/debug-session-skills-detail-expression-evaluator.png)
        スキルの設定を、GUI上で json 編集すれば、↑の値確認にも反映される

# ちょっとした不満

- python sdk で更新した場合、「設定」⇒「保存」で再設定しないと最新化出来ない？

# あとがき

indexer を作ろうと思うなら、この機能は必須でしょうね。
いや、ほんと、もう少し早く知りたかった :sweat: 

ちなみに、カスタムスキルを作る場合は、以下別の方法になるらしい

https://learn.microsoft.com/ja-jp/azure/search/cognitive-search-how-to-debug-skillset#debug-a-custom-skill-locally
VoIPとSIPを通じてRustを勉強する：RTCP作成編

# はじめに
本記事は自分のためでしかないアドベントカレンダー2024の記事です。
記事は２５記事書くと思いますが期待はせずにお願いします

# RTCPパーサ/ビルダ
本日以降でRTCPのパーサ、ビルダの設計を行っていきたいと思います。

# 方針
記事を見てくださった方は解ると思いますが、最初のビットの構造はほぼ共通です。
ここを共通の構成として、あとは毎日プロトコルに沿って実装していきます。

# 今後の計画
土曜の記事で共通部分を作っていきます。
日曜以降の記事で各RTCPの開発を行う予定です。5日くらいかけて？

# 終わりに
記事が手抜きになっていますね。。。
仕事が炎上しているので。。。
土日に記事執筆がんばります。。。
なんとか25記事書きたい。。。