OmniAICreator/Qiita-1.07M huggingface dataset:
genkit + vertexAIでTool使う

通常のgenerate

```ts
import { genkit } from 'genkit';
import { vertexAI } from '@genkit-ai/vertexai';

const ai = genkit({
  plugins: [
    vertexAI({ location: 'asia-northeast1' }),
  ],
});

const response = await ai.generate({
  model,
  prompt
});
```

ユーザからの問い合わせに香水に関することがあったら、香水のデータを検索して使えるようにします

まずはツールの定義

```ts
import {z} from "zod";

const fetchPerfumeTool = ai.defineTool(
  {
    name: "fetchPerfume",
    description: "香水を検索します",
    inputSchema: z.object({
      maker: z.string().describe('香水のメーカー')
    }),
    outputSchema: z.object({
      lists: z.array(
        z.object({
          name: z.string(), description: z.string()
        })
      )
    }),
  },
  async (input) => {

    // DB検索したことにする。
    logger.log(input.maker)
    await new Promise(resolve => setTimeout(resolve, 300))


    return {lists: [
      {name: '香水1', description: 'さわやかな香り。柑橘系です'},
      {name: '香水2', description: 'スイカみてぇな匂いがします'},
      {name: '香水3', description: 'どこかハワイっぽいです'},
      {name: '香水4', description: 'スパイシーな感じです'},
      {name: '香水5', description: '木みてぇな匂いです'},
      {name: '香水6', description: '匂いませんが、肌によさそうです'},
    ]}
  }
);
```

input.makerにはメーカー情報が入ります

例えば「ディオールの香水で、さわやかなやつねぇ？」って聞いたら"ディオール"が入っています


定義したツールは以下のように使用します

```ts
const response = await ai.generate({
  model,
  prompt,
  tools: [fetchPerfumeTool]
});
```
自作言語用のCC+(旧ChainCC) 最新バージョン！　※公開はしません


　「ChainCCをもっと、自作言語に特化させたい！」

　そういう思いから、[ChainCC 2.1](https://github.com/MueLangDeveloper/ChainCC-Ver.2.1)を元に、「コマンドの見直し」、「開発言語F#との連携の強化」などを行い、ついに...

　**ChainCC 3が完成しました！**

# なぜ「CC+」なのか
　ChainCCの「Chain」にもある通り、**鎖のように処理をある程度まとめられます**

　しかし、大幅にコマンドを削除したり、今あるコマンドを拡張したりしたため、まとまりのようなものが生まれるのが、~~`ref`コマンドだけです~~　なくなりました

　なので、名前を「**CC+(Compiler Creation Plus)**」に改めました

# CC+でできるようになったこと
　[ChainCC 2.1](https://github.com/MueLangDeveloper/ChainCC-Ver.2.1)から新たに

・他のオブジェクト(`CCPlus`オブジェクト)の実行
・登録したF#の関数を実行

　をすることができるようになりました

　特に後者は、CC+で成し得ないことをF#で実装することにより、それが可能になったのです(前者は保守性向上です)

# 終わりに
　~~現在、自作言語にCC+を組み込んで開発中です。がんばります！~~
2025年に追加されたJavaScriptのIterator機能、どこに使える？

元々もJavaScriptにIterator機能はありましたが、2025年になって大きな修正が入りました。

新しく追加された便利なメソッドで、コードをもっと簡潔に書けるようになりましたので記事でまとめてみました。

## 2025年追加のIterator機能

2025年のECMAScript仕様では、イテレーターに以下のような便利なメソッドが追加されました！

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Iterator

### 最初n個の操作
- `take(n)`: 最初のn要素だけを取得
- `drop(n)`: 最初のn要素をスキップ

### Arrayのような操作
- `filter(predicate)`: 条件に合う要素だけをフィルタリング
- `map(callback)`: 各要素を変換
- `flatMap(callback)`: 各要素を変換し、結果を平坦化
- `reduce(callback, initialValue)`: 要素を集約
- `forEach(callback)`: 各要素に対して処理を実行

### 変換系
- `toArray()`: イテレーターを配列に変換

## `take`の活用例

`take`メソッドは特に便利で、今回は`take`の使い方から変わった書き心地を見ていきたいと思います。

`take`は最初のn個の要素だけを取り出すことができます。
これで今までのArrayの操作と違って、全要素を処理せずに必要な部分だけを取得できるのでパフォーマンスを上げることができます。

### 簡単例

```javascript
// 大きな配列から最初の5要素だけを取得して処理
const hugeLargeArray = Array.from({ length: 10000 }, (_, i) => i + 1);
```

``` js
// 従来の方法
// sliceだと10000個を全部まわらないといけない
const first5Legacy = hugeLargeArray.slice(0, 5);

// for文でも書けるが、一手間かかる

const first5WithForLoop = [];

for (let i = 0; i < hugeLargeArray.length && i < 5; i++) {
  first5WithForLoop.push(hugeLargeArray[i]);
}
```

``` js
// 新しいtakeメソッドを使用
const first5WithTake = [...hugeLargeArray[Symbol.iterator]().take(5)];
// もっと短く書くことも可能
const first5Simple = [...hugeLargeArray.values().take(5)];
```

### 実用例

以下のように条件に一致する最初のn個の要素だけを取得する時、もっと関数型プログラミングぽくかけるようになりますね！

```javascript
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 最初の3つの偶数だけを取得
const firstThreeEven = [...numbers
  .values()
  .filter(n => n % 2 === 0)
  .take(3)];

console.log("最初の3つの偶数:", firstThreeEven); // [2, 4, 6]
```

## おわりに
あまり他の言語をいっぱい触ってきてはいませんが、Rustのようなiteratorの操作がこれからもできるようになっていくイメージでうかね~

新しく追加された`Promise.try`も気になるのでブログでまとめてみたいところ
短期間での退職について、採用側の視点から考えてみる

昔は「仕事は最低3年続けろ」と言われていましたが、最近はあまり聞かなくなってきました。
むしろ、XなどのSNSでは「すぐに辞めていい」という意見をよく見かけるような気がします。

最近は退職代行のサービスもあり、新入社員が1日目で退職代行サービスを使用したことも話題になりました。

すぐに辞めた方がいい場合もありますが、短期間での退職は転職活動で不利になることもあります。
私は転職希望者の面接への同席など少しですが採用業務に関わることがありますので、採用側の視点から短期間での退職について話してみます。

## なぜ短期間での退職は転職に不利になるのか？
短期間での退職が転職で不利になる理由、それは会社側としては社員になるべく長く勤めてほしいからです。
なぜ長く勤めてほしいか、それは人の採用・育成には「お金」と「手間」がかかるからです。

## 人の採用にはお金がかかる
転職サイトを利用したことがある方も多いと思いますが、企業が転職サイトに求人を掲載するにもお金がかかります。
採用したら発生する成果報酬型だったり、採用できなくても費用が発生したりなどサービスやプランによって異なりますが、企業側が求人掲載するのはお金がかかります。

また、上記のような直接的な費用だけでなく採用活動には人件費も発生します。
採用担当者はもちろんですが、面接に同席したり転職サイトに載せるインタビューを受けたりなど一般社員にも人件費が発生しています。

## 人の採用には手間がかかる
採用活動は、転職サイトに求人を掲載したらあとは放置というわけではありません。
転職サイトの担当者との打ち合わせ、記事をリライトやスカウトの送付、転職希望者と日程調整、もちろん書類選考や面談でも時間を使います。

面談に採用担当者以外の既存の社員が同席することはよくありますが、あれも本業は別にあって時間や業務を調整しています。
また、小さな会社だと採用業務と他の業務を兼務している場合もあります。

このように、人の採用には非常に手間がかかります。

## 採用してからもお金と手間がかかる
これまでは採用時のお金や手間について書いてきましたが、採用してからもお金と手間は発生します。

採用が決まり入社したら経理担当者は税金や社会保険関連の業務が発生しますし、総務や情シスはPCや社内で使用する各種アカウントの準備があります。
研修を行う場合もありますし、入社してから1ヶ月ぐらいは他の社員の人が質問に答えたりするので時間を使います。

スキルや経験が十分な人でもある程度キャッチアップ期間が必要ですが、経験が浅い・未経験の場合は成果を出せるようになるまでさらに時間がかかります。

## まとめ
このように、人の採用には非常にお金と手間がかかります。
たくさんお金と手間をかけたのに、すぐに転職されてしまっては正直たまったもんじゃありません。

半年〜1年ぐらいのスパンでの転職を繰り返している場合、「うちの会社もすぐに辞めてしまうのではないか」とリスクと思います。
特に未経験や経験が浅い場合は即戦力というわけにはいかないので、なおさら躊躇します。

パワハラ上司がいたり仕事が激務で体調を崩したなどすぐに転職した方がよいケースもあると思いますが、短期間での退職はリスクもあることをご認識いただけると幸いです。
[writeup] picoCTF "Bookmarklet"

# 今回の問題
picoCTFより"Bookmarklet"を解いていきます。

# 実際に解いていく
### 1. 問題文にあるWebサイトに移動する
![Bookmarklet_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945501/97515211-bbae-49e1-bf18-dde560203b3b.png)
うん。ヒントというか答えが書いてますね。
プログラム部分をクリックしてコピーします。

### 2. [Console]タブでプログラムを実行する
![Bookmarklet_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945501/9e5872dd-22af-4c21-9d53-8ebb0ea1661e.png)
Webインスペクタを開きます。
[Elements]タブから、[Console]タブに移動します。
コピーしたプログラムを貼り付けて、Enterキーで実行！

### 3. FLAG獲得！
![Bookmarklet_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945501/ce169c59-6db7-4b47-a726-f70248106395.png)
無事にFLAGを獲得することができました！

# もう少し考えてみる
すでにFLAGは獲得しましたが、どのような暗号を使っていたかが気になるのでJavaScriptの中身を見ていきます。

### 1. JavaScriptを見る
```javascript
        javascript:(function() {
            var encryptedFlag = "àÒÆÞ¦È¬ëÙ£ÖÓÚåÛÑ¢ÕÓ¡ÒÅ¤í";
            var key = "picoctf";
            var decryptedFlag = "";
            for (var i = 0; i < encryptedFlag.length; i++) {
                decryptedFlag += String.fromCharCode((encryptedFlag.charCodeAt(i) - key.charCodeAt(i % key.length) + 256) % 256);
            }
            alert(decryptedFlag);
        })();
```
なるほど。すごくシンプルな暗号です。

### 2. 暗号の解読
暗号を解読していきます。暗号の流れはこんな感じです。

1. encryptedFlagに"àÒÆÞ¦È¬ëÙ£ÖÓÚåÛÑ¢ÕÓ¡ÒÅ¤í"という暗号化された文字列があります
1. keyに"picoctf"という鍵があります
1. forループで
・暗号化された一文字ごとに
・（暗号化された文字コード - 鍵の文字コード）/ 256 をして
・decryptedFlagに入れる

以上です。上の式では省略していますが、鍵の文字コードに+256されています。おそらく、最後に256で割った時に、負の値になってしまうのを防ぐためです。

# まとめ
今回の問題は簡単でした。
暗号に関しても、鍵を使用して各文字の文字コードを変換する簡易的な暗号でした。古典的な暗号化手法（シーザー暗号など）に似ているように思えます。

# 補足
・今回はBookmarkletを使わずに、コンソールに直接JavaScriptを貼り付けて実行しました。
・Bookmarletとは、ざっくりいうと「ブラウザのブックマークから、JavaScriptを実行する」仕組みです。拡張機能とは異なるので注意してください。
音声認識モジュールの比較

#### 初めに
近年、オフライン音声認識モジュールが安価で入手できるようになりました。
ただ、購入してみて中国語のコマンドしか入っていなくて がっかりしたり ウエイクワードやコマンドワードをどのように変更すればよいか思案することもあると思います。
そこで、今まで試してみた音声認識モジュールについて比較してみます。
#### HLK-V20
英語のコマンドが入っているものを購入しました。
入力距離は 0～1m と 1～5m が選択できる。 
ウエイクワード無しで動作するコマンドもあり。
ウエイクワードやコマンドワードを変更し書込む方法は情報不足で確認出来ませんでした。　☜　最近、見つけたので最後のメーカーサイト他に追加しました。

#### LD3320
最初に手にした自分でプログラム可能なモジュールです。
LD3320 の内部レジスターを読み書きすることで音声認識が可能となります。　
よってマイコンとペアで動作します。　
mp3の再生機能も持っていてステレオ再生も可能です。
ただ、音声認識ワードは中国語（ピンイン）で入力するので基本は中国語となります。
日本語や英語もピンイン表とにらっめっこして似た発音を探すことになりますが、どうしても限られた単語になってしまいます。
#### ASRPRO
ブロックでプログラム作成でき、モードを切り替えればVSCODEでのプログラムも可能です。
いろんなサンプルプログラムも用意されており、中国語ではありますが学習ビデオもあります。
ただ、実際にモデルを作成するには実名認証が必要になり中国本土の携帯番号が必要になります。
ユーザー名とパスワード設定でログインはできるので、そこから開発者フォーラムに入ってホワイトリストへの追加をお願いすればモデル作成も可能となります。
長距離入力、音声再生中の中断、割込み等も対応されています。
まだ、日本語には対応されていません。
書込み回路とマイクが搭載された開発基板と、搭載されないASRPRO-CORE基板があり それぞれ FLASH 2Mと４M の物があります。

#### CI-03T
M5Stack Unit ASR に組み込まれているモジュールです。
ノーコードでプログラムし、書込むことができます。
具体的にはウエイクワード、コマンドワードを決め 後は、項目ごとに設定入力していけば自動的にプログラムが作成されます。
色んな場面を想定したサンプルが用意されているので比較的簡単にプログラムし動作確認することができます。
日本語サンプルがあるのもありがたいです。　ただ、日本語TTSは今一です。
wavやmp3ファイルへの変更もできるので そちらで検討するのが良いかもしれません。
ここまでは、ユーザー名とパスワードでログインできますが SDKをダウンロードして本格的にとなると実名認証が必要となるので中国の携帯番号が必要となります。
ブロックでプログラム作成も可能なようですが そのダウンロードにも実名認証を求められます。
CI-03T は FLASH 2M ですが ４M となると名前が変わります。
2個目のマイク端子も引出されているので２マイクでの動作確認もできます。

CI13XX,CI123XX の種類
![chipintelli_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4045440/8163fd69-9025-4cc2-b684-73ce8ce8ce53.png)
![chipintelli_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4045440/0eb80cb4-4c07-46dc-8d6b-979069f812e1.png)

#### SU-03T
CI-03T と同様な方法でプログラム作成、書き込みができるようです。

#### その他
alliexpressで探してみると その他にもいくつか見つけることができます。
SW入力でコマンドワードを登録できるものもあります。

#### 最後に
日本語対応で選ぶと CI-03T 一択となりますが、10語程度であれば ASRPRO の自学習で登録することも考えられます。　
個人的には ASRPRO が2.54㎜ピッチの基板で使いやすく、プログラムの書込みも安定しています。
ひと昔前は、特定の人の数語を認識するだけでも高価で大きな基板（装置）が必要だったことを思うと、切手よりも小さな基板で音声認識が可能になったのは驚きです。

#### メーカーサイト他
LD3320
http://www.icroute.com/web_cn/ICRoute_index.html
https://github.com/libdriver/ld3320/

HLK-V20
https://www.hlktech.com/Goods-98.html
https://www.youtube.com/watch?v=mWg7piM9wAE&t=17s
HLK-V20 Manual
http://www.robotsforfun.com/webpages/HLK-V20%20User%20Manual%20EH.pdf

https://h.hlktech.com/mobile/download/fdetail/93
https://aitendo3.sakura.ne.jp/aitendo_data/product_img/audio/voice/HLK/hlk-v20.pdf

音声認識モジュールHLK-V20プログラミング
https://blog.csdn.net/Fhgh964/article/details/134765123

HLK-V20/HLK-V20S 规格书
https://h.hlktech.com/download/HLK-V20_V20S/1/HLK-V20%E5%92%8CHLK-V20S%E8%A7%84%E6%A0%BC%E4%B9%A6%20V2.1.pdf

ASRPRO
https://www.cnblogs.com/jeikerxiao/p/18276982
http://www.gdwrobot.com/courses/outline/commonTechDoc/offlineSpeechRecognizeASRPRO01.html

CI-03T
https://www.smartpi.cn/#/
https://help.aimachip.com/docs/offline_ci03t

SU-03T
https://docs.aimachip.com/zh-cn/latest/file/offlineVoice/SU03T.html
https://blog.csdn.net/yychuyu/article/details/135888115
VRChat Gesture Managerの使い方

## ⭐️インストール

https://github.com/BlackStartx/VRC-Gesture-Manager

![スクリーンショット 2025-04-27 18.10.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/14d797b0-fbd5-495d-8958-169ab4753097.png)


## ⭐️参考

https://vrnavi.jp/gesture-manager-dounyuu/

## ⭐️使い方

### ☂️セット

![スクリーンショット 2025-04-27 17.25.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/2b144079-dd85-48da-951f-a2ce581df39b.png)

ツールから開く

### ☂️呼び出す

![スクリーンショット 2025-04-27 17.25.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/75fb0b17-bf45-42d0-9dc8-8acbe8d029af.png)

![スクリーンショット 2025-04-27 17.29.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/98766b81-d3c2-4a69-8657-b1c45b3fdf8d.png)


### ☂️カメラをセット

![スクリーンショット 2025-04-27 17.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/ae7b3e89-32ad-4dff-b569-c10bf240b763.png)

mainカメラの設定を忘れないように

### ☂️動かしたいモーションを選ぶ

![スクリーンショット 2025-04-27 17.25.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/9cb1e892-bff7-4bfb-b668-38cdd8a81d6d.png)

![スクリーンショット 2025-04-27 17.25.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/429e45f9-e0dd-4414-8ec8-193db95950d9.png)

この状態にするのを忘れないように

### ☂️終わり方

![スクリーンショット 2025-04-27 17.35.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/01e36ec7-7a5f-4952-88e0-eb030432c5a3.png)

チェックを外す


![スクリーンショット 2025-04-27 17.35.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/0f7f368a-36f6-4b86-a544-c30b9c5f8258.png)

exitする

もしくは再生ボタンを止める

### ☂️ポーズを座ったり, 寝かせたり, 中腰にさせたり

https://qiita.com/YukiLulu0229/items/9b333af1032ca7b084fe
KotlinのRandomをmockにする

# この記事の内容

自作のアプリで`kotlin.random.Random` を使った関数のテストを書きたくなったときに意外と苦労した備忘録。

Spring Bootを利用したwebアプリケーションで、テストコードにはJunit、Mockito-Kotlinなどを使用しています。

# 例えばこんなコード

```kotlin
@Service
class SomeService {
    // この関数をテストする
    fun someFunction(): Int {
        // 1から100までの乱数を生成
        val randomValue = Random.nextInt(1, 101)

        // ゾロ目の時だけ10倍して返す
        return if(randomValue % 11 == 0) {
            randomValue * 10
        } else {
            randomValue
        }
    }
}
```

# テストを書こう

この関数のテストで、以下の点を確かめます。
- 1から100までの乱数を生成していること（すなわち`Random.nextInt(1, 101)`を呼び出していること）
- 11の倍数のときには10倍の値を返すこと

`Random` のテストのためにシードを固定ような方法もありますが、mockを使えば解決しそう、ということで以下のようなコードを書きました。


```kotlin
class SomeServiceTest {
    @Mock
    private lateinit var random: Random
    @InjectMocks
    private lateinit var someService: SomeService

    @Test
    fun testSomeFunction() {
        whenever(random.nextInt(1, 101)).thenReturn(11)

        val actual = someService.someFunction()

        verify(random).nextInt(1, 101)  // ①
        assertThat(actual).isEqualTo(110)  // ②
    }

     // それ以外のテストケースは省略
}
```

これでテストケースをパスすると思いきや、①では、`random.nextInt(1, 101)` は呼び出されていないことになっており、②の`actual`の値は`whenever ~ thenReturn`で設定したものと異なる値が入っていました。

# 何が問題か
`Random.nextInt()`がstaticな関数であったため、mockと置き換えられていなかったようです。

というわけで、Serviceの実装部分でDIを使うように書き直しました。

まず、Beanを登録。
```config.kt
@Configuration
class Config {
    @Bean
    fun random(): Random = Random.Default
}
```

そして、ServiceクラスではこのBeanを使う
```kotlin
@Service
class SomeService {
    @Autowired
    private lateinit var random: Random

    fun someFunction(): Int {
        // クラスのフィールドのrandomを使うように修正
        val randomValue = random.nextInt(1, 101)

        return if(randomValue % 11 == 0) {
            randomValue * 10
        } else {
            randomValue
        }
    }
}
```

これで先ほど書いたテストコードをパスするようになりました。

# まとめ
他にも `mockStatic` を利用する方法があるようです。今回は`verify`（呼び出し回数のテスト）がうまく動かなくてやめました。
テストのために実装を変える形ではあるので、やや不満があります。良い方法をご存知の方は教えていただけると喜びます。
個人開発したサービスを公開して2ヶ月で学んだことまとめ

# <font color="red">🚀はじめに</font>
今年2月に公開したWebサービスについて、リリースから2ヶ月が経過したということで、ここまで自分のサービスを運用してきたことで見つけた自分なりの発見を記事として共有しようと思います！これから個人開発を始めようと思っている方や、個人開発に興味があるという方は是非お読みいただけると嬉しいです！

 - **公開したWebサービス↓**

https://vtune.jp

- **リリース時に公開した記事↓**

https://qiita.com/Kei-dev-1213/items/b3d5873a5af64b86fb43

# <font color="blue">🔍️発見・得られたこと</font>

この2ヶ月間で見つけた発見や得られたものを4つほどご紹介いたします！

- ### <font color="red">1.自分が作ったサービスを人が使ってくれるのは普通に嬉しい</font>
  まずはやっぱりこれですね。`転職するためだけにポートフォリオとしてなにか作る`ことを目標にするのも良いとは思うのですが、せっかく自分が手を動かして作るのであれば、作るだけ作って放置、というよりも`人に触れてもらうことを目的にした方がやってて面白い`と思いますし、よりモチベーションも湧いてくるのではないでしょうか（実際作るよりも作った後に運用する方が学ぶことが多いです）。私の場合は運が良く、リリースしてすぐに沢山の人に使っていただき、フィードバックやサービスの修正依頼などを頂きました。実際の感想を貰えると刺激になったり、自分では気づかなかった改善点などの意見を貰えるので非常に勉強になります。これは動画教材や技術書の勉強では得られない経験ですね。　

<br/>

- ### <font color="green">2.人に見せることでアピールになる</font>
  このWebサービス、公開してから職場の人や会社の同僚に見てもらいましたが、まず`個人開発したWebサービスを運用している`こと自体を普通に評価してもらえます。
  そして、私の場合は技術記事をQiitaに投稿もしているので（最近サボってるので頑張ります^^;）、これも人に対して大きくアピールできるポイントになります。
  `資格の数や読んだ技術書の数がこれだけあります！`とアピールするよりも、`個人開発したWebサービスを実際に運用していて、技術的な発見や学びは定期的に記事にまとめています`と伝える方が、他の人との差別化につながるポイントだと思います。また、サービスを継続的に運用することで、技術面だけでなく、ユーザー視点やサービス運営の観点も身につきます。これはエンジニアとしてだけでなく、プロダクト全体を見渡す力にもつながります。

<br/>

- ###  <font color="blue">3.自然とアウトプット志向になれる</font>
  個人的にエンジニアあるあるだと思っているのですが、`自分が今勉強していること`について、`あれ？俺今これやってていいんだっけ？`と疑問に思ったことはないでしょうか。例えば今読んでいる技術書について、`これ読んでても業務に活かせなくね？`と読んでて疑問になってきて途中で読むのを辞めるとか私はしょっちゅうやってました。
  ただ、自分のWebサービスを運用し始めてからは、こういった悩みはかなり減りました。今では、時間があるときには自分のサービスをいろいろといじってみて、`この機能使いにくいからこうした方が良いかな`だったり、`こういう機能があったら人は使ってくれそうだな`と考えながら、自分のサービスをより良くするために時間を使うようになりました。そのため、`今勉強していること自体への悩み`については考えなくなりました。
  この変化の理由は、`自分のサービス`という具体的なアウトプットがあることで、学んだことをすぐに試したり、実際に役立てたりできるからだと思います。学びが直接自分のプロダクトに結びつくことで、勉強の目的が明確になり、`今やっていることは無駄ではない`と実感できるようになりました。

<br/>

- ###  <font color="orange">4.学んだことを業務にも活かせる</font>
  こちらのWebサービス、技術スタックの面で今私が参画している案件とは異なるものであるため、技術的に直接学んだことを活かせているかというと正直微妙ですが、Webサービスを運用することで発生する`予期しないトラブル`や`ユーザーからの問い合わせに対するコミュニケーションの工夫、データのバックアップやセキュリティ対策`など、日々の運用を通じて得た経験は、業務においても役立つものと思います。
  例えば、新機能を実装した際に、デグレが発生しないように気を付けてコーディングしたり実際の運用を意識したテストをするなどといった経験は、このような実践的な取り組みでしか経験できないものと思います（繰り返しになりますがこのような経験も非常に良いアピールになると思います）。こういった運用面に造詣があるかないかでエンジニアとしての価値は大きく変わってきます。

# <font color="green">✏️おわりに</font>
いかがだったでしょうか。
こちらのWebサービス、自分一人で企画から設計・実装・リリースまで担当したのですが、一番大変だなと思っているのは意外とリリース後だったりします。というのも、私はエンジニアとしてコーディングするのは今まで経験してきたのである程度分かるのですが、`どうやって人に使ってもらうように工夫していくか`については完全に未経験であるためです。ここについては色々試行錯誤していくしかないのかなと思っていますが、正直なところ、サービスを「作る」ことと「届ける」ことは全く別のスキルセットが必要だと痛感しました。一方、実際にユーザーの声を聞くことで、開発中には気付かなかった課題や新しいアイデアが生まれることも多く、サービスを育てていく面白さも感じています。

今後もユーザー目線を大切にしながら、より多くの方に使ってもらえるように、改善と発信を続けていきたいと思います。そしてぜひ私のサービスもお使いいただければ非常に嬉しいです！
ここまでお読み頂きありがとうございました！

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

https://projisou.jp/
NAND 演算の基本 !(A & B)

「0と1だけでこんなに奥深い世界があるなんて…！」
Paizaで出会ったNAND（ナンド）演算、正直ナメてた。でもコイツ、実は論理界のチートキャラだった！

問題概要

`0` または `1` の整数 `A` と `B` が与えられ、`A NAND B` を求めるというシンプルなお題。
※ `NAND` = `!(A & B)` のこと。

<br>例）
```
入力: 1 1
出力: 0
```
<br>

https://paiza.jp/works/mondai/logical_operation/logical_operation__basic_step5



## NG例
```js
const [A, B] = input.split(' ');
console.log(!(A & B)); // → true/false（数値じゃない）
```

## <br>OK例
```js
const [A, B] = input.split(' ').map(Number); //.map(Number)はなくてもよい
console.log(Number(!(A & B)));  // NAND = NOT (A AND B)
// → 0 or 1（数値）
```

## <br>まとめ
- `NAND`は「`NOT(AND)`」の略
- 数値変換をする
- `NAND`だけで全論理ゲート作れる → 「万能ゲート」と呼ばれる



<br><br>[🐻僕の失敗談(´;ω;｀)と解決話！🚀🐈](https://paizabeginner.wordpress.com/2025/04/27/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bcnand-%e6%bc%94%e7%ae%97%e3%81%ae%e5%9f%ba%e6%9c%ac-a-b/)

## <br> おまけ　
`NAND`だけで他の論理演算が作れる！
→ これを「万能ゲート」って言うらしい。

代表的なやつ：

`NOT A` = `A NAND A`

`A AND B` = `(A NAND B)` を `NOT`

`A OR B` = `(A NAND A) NAND (B NAND B)`

`A XOR B = (A NAND B) AND (A OR B)`

<br>

```js
// 論理否定（NOT A）
const notA = Number(!(A & A)); // NOT A = A NAND A


// 論理積（A AND B）
const nand = Number(!(A & B));
const and = Number(!nand); // A AND B = NOT (A NAND B)


// 論理和（A OR B）
const notA_for_or = Number(!(A & A));
const notB_for_or = Number(!(B & B));
const or = Number(!(notA_for_or & notB_for_or)); // A OR B = (A NAND A) NAND (B NAND B)


// 排他的論理和（A XOR B）
const xor = Number(!( !(nand & or) )); // A XOR B = (A NAND B) AND (A OR B)
```
Androidで画面を開いたまま明るく保つ


# 方法
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

開いたままにしたい画面のActivityで FLAG_KEEP_SCREEN_ON フラグを設定します。

# 参考

https://developer.android.com/develop/background-work/background-tasks/awake/screen-on?hl=ja
~交流会などで使える!!~ オンラインですぐに名刺が作れるアプリケーションを作ってみた

## アプリケーションのコンセプト

エンジニア交流会や勉強会のような場面で、
「名刺を渡すほどではないんだよな...」
「でも、参加者同士で簡単にプロフィールは共有したい..」
という時って結構ありませんか？
そのようなニーズに応えるために開発した名刺管理アプリです。

一時的かつ気軽に、必要最低限の情報を交換できる仕組みを目指しました。

## 技術スタック

以下の技術を用いて開発しました

### フロントエンド
- **React**（UI構築）
- **TypeScript**（型安全な開発）
- **React Router**（画面遷移）
- **React Hook Form**（フォーム管理）
- **Chakra UI**（UIコンポーネント）

### バックエンド／運用
- **Firebase**（認証・DB）
- **GitHub Actions**（自動ジョブ）

👉 [GitHub リポジトリはこちら](https://github.com/arunbababa/buisiness-card-application)

👉 [アプリケーションはこちら](https://buisiness-card-app.web.app/)

## 実装機能

### 📝 自分のプロフィールを登録する
- 自己紹介文や好きな技術スタック、各種snsアカウントの登録ができます。

![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909033/7e3529f6-ee45-453c-898d-d2e7bda09c88.gif)

- 入力後は検索画面へ遷移

![Videotogif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909033/462ee850-75c8-4599-9694-102eb7802e01.gif)

### 🔍 ユーザ検索
- 他の人のプロフィールをユーザ名で検索し閲覧できます。

![Videotogif (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909033/4c250f01-69ca-4ea2-8412-2fb8ce80fe0c.gif)

## 工夫点

### ✅ ユーザ登録のバリデーション
**React Hook Form** を用いたバリデーションをしています。
基本的にはDBと整合性が取れるように入力値に制限を書けています。

![Videotogif (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909033/38863949-f89b-4a3c-b2d5-dd5db51a6bbe.gif)


### 🔄 データの自動削除（GitHub Actionsによる定時実行）

- GitHub Actions による Cron ジョブを用い、**毎日定刻にDBのデータを削除**する運用を導入しています。
- このアプリは「一時的な用途での利用」を前提としているため

  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909033/70838097-b140-4552-9b83-d942eb93db34.png)

## 今後の改善ポイント

- 🔐 **セキュリティの強化**
  - ユーザ認証や管理者権限の細分化などを追加予定です。

- 🎨 **UI/UX の改善**
  - Chakra UI をベースに、さらに使いやすく直感的なインターフェースを模索中です。

## 気づき・学び

- **自身の成長**
  - これぐらいのアプリケーションであれば、ざっくりと「何をすべきか」を頭の中で組み立てられるようになれました。
  - もともとフロントエンド未経験だった自分にとって、大きな成長を感じています。

- **本当に使ってもらえるのは難しい**
  - このアプリケーションでも確かに使える特場面はあるかもしれないが、セキュリティ、UI/UX、認知拡大など、多くのユーザーに価値を届けるにはまだまだ課題が多いと感じました。
  - ただ、そういった視点を持てるようになったこと自体は良い成長だったと思いました。

## 🚀 最後に軽く宣伝！

### 🎯 JISOUメンバー募集中！

- 実はこちらのアプリ、僕が参加しているモダン技術を学べるスクールの課題の一環として作成したものになります。
- 経験者向け専門ではありますが、未経験者でもガッツとコツコツ継続できれば、これぐらいのアプリケーションはスッと作れる実力が身につく環境です。
- プログラミングコーチング「**JISOU**」では、現在新たなメンバーを募集中です！

👉 [公式サイトはこちら！](https://projisou.jp/)
【Next.js】Cloudinaryへ動画をアップロードする方法

## 概要

Next.jsにて動画をCloudinaryにアップロードして管理するアプリを作成したので、
どのように実装したかについて投稿します。

## 前準備編

### Cloudinaryアカウント作成

まずはCloudinaryのアカウントを作成します

https://cloudinary.com/



作成できたらクラウド名、APIキー、シークレットキーを控えておきます。



### プレセット作成

Cloudinaryの設定画面で「Upload」→ 「Upload Presets」に移動して、
新しいプレセットを作成します。





### Next.js側準備

以下コマンドでCloudinaryが定期用しているパッケージをインストールします。

```bash
   $ npm install cloudinary
```



## アップロード機能の実装方法

### 環境変数ファイル作成

.env.localファイルを作成して控えたクラウド名、APIキー、シークレットキーと作成したプレセット名を記載します。

```bash
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
CLOUDINARY_UPLOAD_PRESET=preset_name
```

### 実装する処理フロー

1. クライアント側でユーザがアップロードファイルを指定する
1. 指定されたファイルをアプリ側（サーバサイド）へ渡す
1. サーバーサイド側でクライアント側から受信したファイルを取得
1. サーバーサイド側で認証関連（APIキーなど）を使用してCloudinary APIを使用してアップロード
1. 結果をクライアント側へ渡す


### クライアント側実装方法

src/lib/cloudinary.tsを作成し、
実装する処理フロー１、２を実装します。

```typescript
export const uploadVideo = async (file: File) => {
  try {
    const formData = new FormData();
    formData.append('file', file); // ユーザのファイルを取得

    const response = await fetch('/api/cloudinary', {
      method: 'POST',
      body: formData,
    }); // サーバサイドの/api/cloudinaryへ送信

    if (!response.ok) {
      throw new Error('Failed to upload video');
    }

    const data = await response.json();
    return {
      url: data.secure_url,
      publicId: data.public_id,
    };
  } catch (error) {
    console.error('Error uploading video:', error);
    throw error;
  }
};
```



### サーバーサイド側の実装

クライアント側から受け取るAPI（/api/cloudinary/route.tsx）を作成し、
処理フロー３、４、５を実装します。

```typescript
import { NextResponse } from 'next/server';
import { v2 as cloudinary } from 'cloudinary';

// サーバー側でのみCloudinaryの設定を行う
cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
});

export async function POST(request: Request) {
  try {
    const formData = await request.formData();
    const file = formData.get('file') as File;
    
    if (!file) {
      return NextResponse.json(
        { error: 'ファイルが指定されていません' },
        { status: 400 }
      );
    }

    const arrayBuffer = await file.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);

    // サーバー側でCloudinaryのAPIを呼び出し
    const result = await new Promise((resolve, reject) => {
      cloudinary.uploader
        .upload_stream(
          {
            resource_type: 'video',
          },
          (error, result) => {
            if (error) {
              reject(error);
            } else {
              resolve(result);
            }
          }
        )
        .end(buffer);
    });

    return NextResponse.json(result);
  } catch (error) {
    console.error('Cloudinary upload error:', error);
    return NextResponse.json(
      { error: '動画のアップロードに失敗しました' },
      { status: 500 }
    );
  }
} 
```



## まとめ

クライアント側でファイル取得してサーバ側でアップロードを実装するというやり方は、
確かにセキュリティ上はそっちの方がいいよねって思いました。

学習の一環など実際に運用するわけではないから使えればいいやってなってたので、
今後何か作る時に認証周りがある場合はクライアント側、サーバー側で何をするかは
考えていく必要がありそうです。
エンジニアの原点—楽しみながら、いいモノを作る

### トピック１：仕事は楽しむこと
「世界一流エンジニアの思考法」を前回の投稿から少しずつ読み進めています。その中で、「インターナショナルな考え方としてメンバーが楽しんでいるかが重視され、メンバーが楽しめる仕事をプロとして実施して主体的に考えるほうがやらされる仕事よりも生産性がある」と筆者の牛尾氏は述べています。この言葉を目にしたとき、私が力を入れて応援している日本ハムファイターズで監督を務められている新庄監督の「頑張るのではなく楽しむんだ」という言葉を思い出しました。
私はエンジニアとして３年目を迎え、自分なりに仕事へ向き合う時間がより一層増えてきました。その中で、どうしてもエンドユーザのことではなく協力会社様やプロジェクトの上流の方々からの指摘や叱責の言葉に気を取られてしまい、自分がなぜエンジニアになったのかがわからなくなることがありました。
そんな自分に対して、この「楽しむ」と言う言葉は一流と呼ばれる人でも使う言葉なのだとハッとさせられ、勇気と気づきを与えてくれました。

### トピック２：いいモノづくり＝楽しい・面白い
私は新卒でIT業界へ足を踏み入れる前に心の中でうっすらと思い浮かべていたことがあります。
それは、**"いいモノづくりをしたい"** という気持ちです。
ここからは少し私の過去について話したいと思います。
私は小さなころから段ボールや木片を活用して自分の想像で小さな町を作ったり、粘土で想像の中の魚を生み出して透明な折り紙を使った水族館など、いいモノ（面白いもの）を作ることが好きで夢中になっていました。
もっといいモノを作るにはどうしたらいいかを子供ながらに考えて取り入れることが好きで、小さな町の建物の看板には食料品や家電製品の梱包物に書かれているマークを切り取って使ったり、電車のおもちゃ「プラレール」を使って地上と地下を行き来するようにしたらなんかワクワクするから小さな町に取り入れてみようと思い、おもむろに家の段ボールをかき集めて実現したこともありました。
その時に感じていた「モノ（作品）作りの面白みや楽しさ」は私自身がエンジニアとしてシステムの開発に携わる上での礎となっています。
牛尾氏や新庄監督の言葉は私の中に眠るモノづくりの楽しみや面白みといった気持ちを改めて刺激してくれました。
### トピック３：ユーザが求める仕様を主体的に考えることがものづくりの楽しさへとつながる
先週開催されたQiita Conferenceにて多くの登壇者が触れており改めて認識させられた言葉があります。それは、「ユーザが本当に求めるものにフォーカスをする」ということです。この点は今回取り上げた楽しみながらいいモノづくりをするというテーマにも結びつけることができると思いました。
私のエンジニアとしての主な作業としては一つの画面や帳票を仕様に沿ってカスタマイズすることです。その中でも、ユーザがその機能をもっと使いやすくするために、提案をすることがあります。下請け企業のため大きな権限はないため軸となる機能への提案はできませんが小さな機能の仕様については提案することができます。まだまだひよっこなため、説得力やお客様の求めるものへの認識が浅く、却下されることも多くあります。しかしながら、ユーザの使い勝手を意識した設計の時間は難しさを感じることもありますが、面白みも強く感じています。
対して、上から流れてきた仕様をユーザの気持ちを考えないで疑問を持たずに実装へと反映させる仕事は、システムが出来上がった時の達成感はありますが、受動的なものづくりとなり、やらされている間が強いためモノを作る楽しさはユーザへ向けた開発時よりも小さくなっていると感じます。
このような点から、 **"ユーザがいいと感じるモノ"** を作るために **"自分自身が主体的に考えて取り組むこと"** が結果としてエンジニアの仕事の面白さや楽しさへとつながるのだと思います。

### まとめ
トピック１から３まで、「世界一流エンジニアの思考法」の筆者である牛尾氏や新庄監督、QiitaConferenceの登壇者の皆様からの言葉も拝借しながらエンジニアとしての仕事へ向かうマインドやいいモノづくりについて考えてきました。その中で、 **"いいモノづくりとはユーザのために行われるものであって、ユーザが求めるものを主体的に考えて作り上げていくことで面白みや楽しさを必然的に感じることができるのだ"** と気づくことができました。
このような、気づきを与えていただいた方々への感謝の気持ちを持ちながら一流のエンジニアとなれるよう今後もコツコツとキャリアを積み重ねていきます。
PHPのextract()をもとに、シンボルテーブルについて深堀りしてみた

## はじめに

PHPで`extract()`関数を使ったとき、解説に

> キーを変数として現在のシンボルテーブルにインポートします

と書かれていて、「シンボルテーブルって何？」と疑問に思いました。
そこで、少し深堀りしてみました。

## シンボルテーブルとは？

- どんな変数が今使えるのかを管理している場所
- しかもグローバルスコープや関数スコープなど、それぞれのスコープごとに存在している

つまり、これまでよく耳にしていた「変数が使えるスコープ」という話も、  
要するに「そのスコープのシンボルテーブルに登録されているかどうか」ということなんだ、と腑に落ちました。

普段、変数を定義しているときに「シンボルテーブルで管理されている」なんて意識したことはなかったので、今回仕組みを学べたのはすごく良い気づきでした。

---

## 気づきと学びまとめ

- `extract()`は「今のスコープのシンボルテーブルに変数を追加する」関数
- シンボルテーブルは「どんな変数が使えるか」をスコープごとに管理している
- スコープ＝シンボルテーブルの範囲

---

## 感想

ちょっとした気づきかもしれませんが、  
こういう知識が増えると、プログラムを書くときに**データの動きがイメージできる**ようになって、  思った通りにコードを動かせる感覚が少しずつ積み上がっていきます。

データの流れや動きをイメージできると僕はよりプログラミングが楽しく感じるので、
こういう小さな疑問を大切にして、これからも知識を積み重ねていこうと想います。
SESの面談の流れとよく受ける質問

SESでどこかの現場で常駐して働く場合、参画前にその現場の方との面談があります。
面談で問題がなければ晴れてその現場で働けるのですが、面談の流れや面談でよく受ける質問をご紹介します。


## 面談の流れ
面談の流れは、大体以下のようになります。
1. 案件についての説明を受ける
2. 案件についての質疑応答
3. 自分の経歴や経験についての説明する
4. 自分の経歴や経験についての質疑応答

### 案件についての説明を受ける
まず、その現場の社員の方から案件についての説明を受けます。
大体以下のようなことが説明されます。

- システム・サービスについて
- エンドユーザーについて
- 参画期間はどれくらいか
- プロジェクト規模
- 求められる役割・スキル
- 出社・フルリモートの割合
- 開発言語や環境
- 業務の流れ

### 案件についての質疑応答
上記の案件についての説明が終わったあと、こちらから質問をできることが多いです。
参画してからミスマッチなどで早期での契約終了となるとお互いに不幸なので、ここで疑問点は解消しておきましょう。

私は説明がなかった場合は以下のようなことを質問をします

- 開発言語・フレームワークのバージョン
- コードレビューはあるか
- テストコードは書くか
- プロジェクト規模
- PCは貸与いただけるか
- 参画する場合に事前準備しておくこと

### 自分の経歴や経験についての説明する
案件についての質疑応答が終わったら、次は自分の経歴や経験について説明します。
面談の時間は限られているので、直近の2案件や説明を受けた案件と関連するような案件(開発言語やフレームワークが同じ案件、同じ業界や似たようなサービスの案件など)を説明します。

私は以下のようなことを説明しています。

- どのようなシステム・サービスか
- 案件規模
- 自分の役割
- 開発言語・フレームワーク
- 開発した画面や機能

### 自分の経歴や経験についての質疑応答
経歴や経験についての説明が終わると、それについての質問を受けるので答えます。
以下のような質問を受けることが多いです。

- 〇〇の経験はありますか？
- 今後の目標やどのようなエンジニアになりたいか
- 過去の業務で辛かった経験とそれをどのように乗り越えたか
- システム開発の工程で自分が得意なこと・苦手なこと
- コードレビューの際に意識しているポイント
- 長期での参画でも問題ないか？(案件が長期の場合)

## 経歴や経験についての質疑応答のポイント
### 嘘をつくのは絶対にNG!
「〇〇の経験はありますか？」の質問に対して、経験がないのにも関わらず「あります！」と答えるなど、嘘をつくのは絶対にNGです！

仮に嘘をついて案件に参画しても、スキル不足と判断されたら短期間で契約終了になることもありますし、嘘をついたことが問題視されて今後他の案件の紹介がなくなる可能性もあります。
また、転職と同じくSESでも短期間で現場がコロコロ変わっているとスキル不足や「何か業務態度に問題があるのでは？」と判断されて案件に入りにくくなります。

嘘は絶対やめましょう。

### ポジティブな言い方にする
質問に対して嘘をつくのはNGですが、なるべくポジティブに答えましょう。
例えば、「〇〇の経験はありますか？」の質問に対しては以下のように答えると良いです。

- ❌：経験はありません
- ⭕：経験はありませんが参画後キャッチアップできるので問題ありません
雰囲気で使いがちな &:メソッド名 って何？初心者がSymbol to Procを調べてみた

# 自己紹介
はじめまして。にっしーといいます。
私は４月１４日から、山浦 清透さんが主催するアプレンティスの９期生としてWebエンジニアになるべく日々勉強を行っています！アプレンティスシップの課題や学習中に気になったことを投稿していたらと思っています！

アプレンティスについて、気になる方は👇のリンクから概要等見てみてください！

https://apprentice.jp/lp

# はじめに
Ruby関連のコードを書いたり、記事を読んだりしているとちょこちょこ出てくる`(&:メソッド名)`について、「こういう書き方もできるんだ〜」くらいに思っている方も多いのではないでしょうか？

```ruby:loop.rb
['hoge','fuga','piyo'].each(&:upcase!)
=> ["HOGE", "FUGA", "PIYO"]
```

私自身も、Rubocop(自動でコードの修正案を出してくれるやつ)に👇の画像のように指摘を受けたことはありましたが、原理等は気にせずコードだけ修正してしまったことがあります💦

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4072067/0074c30a-ffcb-4f65-bdd7-a8ec1b30a70c.png)

# いろいろ調べてみた
調べてみた結果、Rubyのさまざまな要素を組み合わせることで、成り立っている構文であることがわかった。
大まかな要素は👇の通りで、それぞれ深掘りしていく！

1.Enumerableモジュールのメソッド
2.&演算子
3.procオブジェクト
4.Symboleクラスのto_procメソッド

## Enumerableモジュールのメソッド
Rubyでよく使う`each`や`map`などは、**Enumerableモジュール**に定義されたメソッド群です。
これらのメソッドは**ブロック引数を受け取って**、繰り返し処理や変換処理を行うことができます。

→この要素で大事なことは**ブロック引数を受け取る**ことです！

## &演算子
Rubyの`&演算子`には様々な役割があるのですが、今回はProcオブジェクトをブロックに変換する用途で使用している！

> 公式ドキュメント参照
> xxx(&b)
> Proc オブジェクトをブロックとして使う。メソッド呼び出し(super・ブロック付き・yield)/ブロック付きメソッド呼び出し を参照。

> to_proc メソッドを持つオブジェクトならば、`&' 修飾した引数として渡すことができます。デフォルトで Proc、Method オブジェクトは共に to_proc メソッドを持ちます。to_proc はメソッド呼び出し時に実行され、Proc オブジェクトを返すことが期待されます。

→&演算子を使うと、**ブロック引数の代わりにProcオブジェクトを渡す**ことができる！
さらに、`to_proc`メソッドが定義されている場合、**そのオブジェクトを`to_proc`メソッドでProcオブジェクトに変換し、ブロック引数として渡すことができる！**

## Procオブジェクト
ブロック（処理をひとまとまりにしたもの）をあらかじめ定義し、変数として保存できるオブジェクトです。
よく使う処理をあらかじめ変数に保存しておくことで、さまざまな場所で繰り返し呼び出して利用することができる！

> 公式ドキュメント参照
> ブロックの部分だけを先に定義して変数に保存しておき、後からブロック付きメソッドに渡すことも出来ます。 それを実現するのが手続きオブジェクト(Proc)です。それをブロックとして渡すにはブロック付きメソッドの最後の引数として `&' で修飾した手続きオブジェクトを渡します。

### Procオブジェクト・&演算子使ってみた
```ruby:proc.rb
# 処理をあらかじめProcオブジェクトとして作成し、変数output_strに保存
output_str = proc { |output| puts output }

#Procオブジェクトを&演算子でブロックに変換して、eachメソッドに渡す
['hoge','fuga','piyo'].each(&output_str)
=>  hoge
    fuga
    piyo
```
→Procオブジェクトは処理をまとめて、&演算子をつけることでブロック引数として実行することができる！

## Symbolクラスのto_procメソッド
これまでの説明だけだと、
「実際は、Procオブジェクトではなくただのシンボルを渡しているのに、なぜ実行されるの！？」
と思うかもしれません。

**その理由は、Symbolクラスが`to_proc`メソッドを持っているからです！**

`Symbol#to_proc`は、呼び出したシンボルと同じ名前のメソッドを、引数に対して呼び出すProcオブジェクトを作成する機能を持っています。
これにより、たとえば次のようなコードが動くわけです。

```ruby:symbol_to_proc.rb
# :upcaseをto_procで変換することでupcaseメソッドを実行するProcオブジェクトが作成される。
:upcase.to_proc.call("hoge")
=> HOGE
```
→このように、シンボルを渡しているように見えて、内部ではto_procによってブロック（Procオブジェクト）に変換され、それがブロックとして実行されているのです！

# まとめ
`&:メソッド名`を渡した際は、👇のような流れで変換されてから、実行されます。
1.`&演算子`が`:メソッド名`をProcオブジェクトに変換する。
2.Procオブジェクトをブロックとしてメソッドに渡す。
3.受け取ったブロック引数を使ってメソッドを実行する。

# おわりに
今回、初めて技術投稿の記事を書いてみました。

内容の修正などご指摘等ございましたらコメントいただけたら幸いです。

# 参考
・公式ドキュメント
[Enumerableモジュール](https://rurema.clear-code.com/3.4/class/Enumerable.html "Enumerableモジュール")
[&演算子](https://docs.ruby-lang.org/ja/3.4/doc/symref.html#and "&演算子")
[Symbol#to_proc](https://rurema.clear-code.com/3.4/method/Symbol/i/to_proc.html "Symbol#to_proc")

・書籍
プロを目指す人のためのRuby入門［改訂2版］ 言語仕様からテスト駆動開発・デバッグ技法まで
GoPro動画からフレームドロップを検知する方法【ffprobe活用】


やったことを忘れないようにするためのメモです。

## 🎥 はじめに
GoProなどのアクションカメラで撮影した動画では、**フレームドロップ**（一部のフレームが記録されない現象）が発生することがあります。  
本記事では、**ffprobe**を使って各フレームの**タイムスタンプ**を取得し、**フレームドロップを検知する方法**をまとめます！(文章のほとんどはChatGPTで作っています。)


---

## 🛠 環境構築

```bash
# Condaで新しい環境を作成
conda create -n ffmpeg-env ffmpeg
conda activate ffmpeg-env
```

- OS: Linux (WSL2でも可)
- 使用ツール: `ffprobe`（`ffmpeg`に含まれます）

---

## 🔍 フレーム単位でタイムスタンプを取得する

### 1. ffprobeコマンド実行

動画ファイル（例：`hero8.mp4`）に対して、以下のコマンドを実行します。

```bash
ffprobe -select_streams v -show_frames -print_format json samples/hero8.mp4 > output.txt
```

オプション説明：
- `-select_streams v` : 映像ストリームのみ対象
- `-show_frames` : 各フレーム情報をすべて出力
- `-print_format json` : JSON形式で出力
- `> output.txt` : ファイルに保存

これで、**全フレーム情報**が`output.txt`に記録されます！

---

### 2. 出力結果の確認

`output.txt`を見ると、各フレームについて次のような情報が記録されています。

```json
{
    "media_type": "video",
    "stream_index": 0,
    "pts_time": "0.000000",
    ...
},
{
    "media_type": "video",
    "stream_index": 0,
    "pts_time": "0.033367",
    ...
}
```

**`pts_time`** が、**各フレームのタイムスタンプ（秒単位）**を示しています！**`pts_time`** は最初のフレームからの経過タイムスタンプを表しているので、そのフレームが何時何分何秒に撮影されたかを復元するには **`tmcd`** を確認し、**`pts_time`** の値を加えることで復元することができます。(Tentacle SYNCなどで記録されたタイムコードはこちらに入る)

---

## 📈 フレームドロップ検出の流れ

### 流れまとめ
1. `pts_time`のリストを取得する
2. 隣接する2つの`pts_time`の差分（Δt）を計算する
3. 理想的なフレーム間隔（例：0.033367秒）と比較する
4. Δtが異常に大きい場合 ⇒ **フレームドロップ発生！**

---

### 実際の例

正常な場合（30fps前後）：

| フレーム番号 | pts_time | Δt (秒) |
|:---|:---|:---|
| 1 | 0.000000 | - |
| 2 | 0.033367 | 0.033367 |
| 3 | 0.066733 | 0.033366 |
| 4 | 0.100100 | 0.033367 |

異常があった場合：

| フレーム番号 | pts_time | Δt (秒) |
|:---|:---|:---|
| 100 | 3.333000 | - |
| 101 | 3.399000 | **0.066000** （※大きすぎる！） |

---

## ⚠️ 注意ポイント
- fps数は撮影モード（FPS設定）によって異なるので、必ず事前に確認！
- 撮影時のブレや熱暴走、保存メディアエラーなどがフレームドロップの原因になります

---

## 🏁 まとめ

本記事では、
- **ffprobeで各フレームのタイムスタンプを取得**
- **フレーム間の間隔からドロップを検出**
という手順を紹介しました。

この方法を使えば、**動画の品質検査**や**データ解析前の事前チェック**が確実にできるようになります！

---

## 📚 参考

- [ffprobe Documentation](https://ffmpeg.org/ffprobe.html)
- [GoPro GPMF仕様リファレンス](https://github.com/gopro/gpmf-parser)
[nodejs] Prismaで始めるデータベース管理

# はじめに
この記事では、TypeScriptとPrismaを組み合わせて使用する方法と、その組み合わせがNode.jsアプリケーションのデータベース管理をどのように改善するかを説明します。

TypeScriptの型安全性とPrismaの強力なデータモデリング機能を利用することで、開発プロセスが効率化され、エラーが減少します。

# 必要な環境
1. Node.jsがインストールされた開発環境
2. TypeScriptの基本的な知識
3. 使用するデータベースシステムへのアクセス（例: PostgreSQL, MySQL）

# プロジェクトのセットアップ
### ①プロジェクトのフォルダを作成する
```
mkdir my-prisma-ts-app
```
プロジェクトのフォルダに移動する
```
cd my-prisma-ts-app
```
package.jsonなどを初期化する
```
npm init -y
```
### ②typescriptのセットアップ
下記の記事をご参照ください。

https://qiita.com/oharu121/items/3aadafdd5daa8dc53c64

### ③Prismaのセットアップ
Prismaのインストール
```
npm install prisma --save-dev
npm install @prisma/client
```
Prismaの初期設定
```
npx prisma init
```
# データベーススキーマの設計
schema.prismaにモデルを定義し、データベースとの同期を行います。ユーザーモデルの例：
```
model User {
  id    Int     @id @default(autoincrement())
  name  String
  email String  @unique
}
```
# データベースとの同期
Prisma Migrateを使用してデータベーススキーマを更新：
```
npx prisma migrate dev --name init
```
# アプリケーションへの統合
TypeScriptでPrismaクライアントを使用してデータベース操作を行う例：
```
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  const newUser = await prisma.user.create({
    data: {
      name: 'Alice',
      email: 'alice@example.com'
    }
  });
  console.log('Created new user:', newUser);
}

main()
  .catch(e => {
    throw e;
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
```
# まとめ
TypeScriptとPrismaの組み合わせにより、Node.jsアプリケーションのデータベース管理がより安全で効率的になります。このセットアップは、開発プロセスを加速させ、エラーのリスクを最小化するため、特に大規模なアプリケーション開発において非常に有効です
Github Codespaces でシークレットキーを安全に管理する

# 目的
Azure Storage のアクセスキー（接続文字列）を安全に管理しながら、Github Codespaces でC# アプリケーションをデバッグしたい。

# 対策
Github Secrets にアクセスキーを登録し、C#コードは環境変数として読み込む。

# 手順
1. Github の Settings から Codespaces を開く
1. Secrets の Codespace user secrets にアクセスキー（接続文字列）を登録する
1. Github Codespaces でデバッグしたいC#アプリケーションのリポジトリを開く
1. [Code] - […] - [Configure dev container] を選択する
1. .devcontainer ディレクトリの devcontainer.json に設定を追加する  
今回は環境変数名とシークレット名がどちらも「STORAGE_CONNECTION_STRING」
   ```
     "remoteEnv": {
       "STORAGE_CONNECTION_STRING": "${secrets.STORAGE_CONNECTION_STRING}"
     },
   ```
1. 開発コンテナーをリビルドする

1. 環境変数（今回は「STORAGE_CONNECTION_STRING」）から接続文字列を取得する様にプログラムを修正する
   ```
   string? storageConnectionString = Environment.GetEnvironmentVariable("STORAGE_CONNECTION_STRING");
   ```

# 参考サイト

GitHub Codespaces のアカウント固有のシークレットの管理

https://docs.github.com/ja/codespaces/managing-your-codespaces/managing-your-account-specific-secrets-for-github-codespaces

開発コンテナーの概要

https://docs.github.com/ja/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers

GitHub Codespaces 用に C# (.NET) プロジェクトを設定する

https://docs.github.com/ja/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/setting-up-your-dotnet-project-for-codespaces

codespace でのコンテナーのリビルド

https://docs.github.com/ja/enterprise-cloud@latest/codespaces/developing-in-a-codespace/rebuilding-the-container-in-a-codespace
AWSのElastic IP アドレス（EIP）を設定してみた

# はじめに

筆者は数ヶ月前に業務でAWSを使用してサービスを公開する機会があり、そこから本格的にAWSを触り始めたAWS初心者です🙇‍♂️

ある時サービスが表示されないということが起こりました。

原因はサービスのスケールアップやインスタンスの停止・再起動を行う度に、毎回パブリックIPv4アドレスが変更されていたことでした。

そのたびにnginxの設定やDNSの設定を変更する手間がかかり、運用上の負担を感じていました。

そこで、インスタンスのIPアドレスを固定化できる仕組みがないか調べたところ、**Elastic IP（EIP）** というAWSの機能があることを知り、今回設定してみたので設定方法について紹介します。


## EIP（Elastic IP）とは？

Elastic IP（EIP）は、Amazon Web Services（AWS）で提供される静的なIPアドレスのことです。


通常、EC2インスタンスは停止するとパブリックIPアドレスが変更されてしまいますが、Elastic IPを使うと、インスタンスが停止したり再起動したりしても同じIPアドレスを使い続けることができます。

これにより、例えばnginxやDNS設定を固定のIPアドレスに基づいて設定することが可能になります。

インスタンスの変更や再起動があってもIPアドレスが変わらないため、運用が楽になります👌

ドキュメント➡️https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html

## EIPの設定方法
### 1. Elastic IPを作成する
まず、Elastic IPを作成する手順を説明します。

#### 1.1 AWS Management Consoleにログイン
AWS Management Consoleにログインし、EC2ダッシュボードに移動します。

#### 1.2 Elastic IPを割り当てる
 左側のメニューから「Elastic IP」を選択します

![スクリーンショット 2025-04-27 15.09.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/d07766fe-17f3-4fab-81d3-da25fdff1e32.png)


「Elastic IPアドレスを割り振る」をクリックします

![スクリーンショット 2025-04-27 15.13.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/7b84a5ee-e179-4e5e-ba05-f4c50d61eee0.png)


ネットワークボーダーグループが利用しているものかを確認してから「割り振る」をクリック
![スクリーンショット 2025-04-27 15.17.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/5579e715-d61e-4457-a6ff-ef0b17b46307.png)

これで、新しいElastic IPが作成されます。

![スクリーンショット 2025-04-27 15.20.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/aae3a745-6eae-4ba6-a4a9-b6acb1f6d8af.png)


### 2. Elastic IPをEC2インスタンスに関連付ける
次に、作成したElastic IPをEC2インスタンスに関連付ける手順を紹介します。

#### 2.1 Elastic IPを選択する
「Elastic IP」ページで新しく割り当てたIPアドレスを選択します。

「アクション」ボタンをクリックし、「Elastic IP アドレスを関連付ける」を選択します。

![スクリーンショット 2025-04-27 15.24.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/2ded6645-13a8-4ffc-93f6-f3fd44864163.png)


#### 2.2 インスタンスを選択する
「リソースタイプ」で「インスタンス」を選択します。

関連付けたいインスタンスを選びます。

![スクリーンショット 2025-04-27 15.30.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/2552a93d-4929-444b-96d1-485276656a59.png)


#### 2.3 Elastic IPの関連付け
「関連付け」をクリックして、Elastic IPがインスタンスに関連付けられます。


![スクリーンショット 2025-04-27 15.32.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/2622b8ec-908c-494e-8da4-1284b5a5ad9c.png)


### 3. Elastic IPの確認
Elastic IPがEC2インスタンスに関連付けられたことを確認するためには、以下の手順を実行します。

EC2ダッシュボードの「インスタンス」セクションに移動します。

対象のインスタンスを選択し、「詳細」セクションに表示される「IPv4 パブリック IP」を確認します。


![スクリーンショット 2025-04-27 15.41.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/e48f33c8-3d22-4e49-ac15-3068869ea1b8.png)


ここにElastic IPが表示されていれば、設定は完了です。

## まとめ

Elastic IPを使用することで、インスタンスのIPアドレスが固定化され、運用の負担を軽減することができました🙌

スケールアップや再起動が頻繁なサービスでは特に有用な機能です。

ぜひ、Elastic IPを活用してインフラ管理を効率化してみてください。
PCの画像をXcodeのシミュレータへ渡す方法

PCの画像をXcodeのシミュレータへ渡す方法です。


シミュレータの画面上にドラッグ＆ドロップします。
シミュレータに保存されます。

以上です。

思っていたよりも簡単にできますね。
Android開発を始めた頃はADBコマンド使っていたので、シミュレータにドラッグ＆ドロップするとでできるのは簡単ですね。
micro:bitに300円でボイスコマンド機能を追加する

## はじめに

micro:bitでの工作の際に「特定の言葉（ウエイクワード）でプログラムを起動させたい」と思ったことはありませんか？

例えば、ベッドで動けないケガをした人のために、「ライトをつけて」と声で命令したら部屋の照明が点灯したり、サーボモーターが作動して物理的なスイッチを押してくれたり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181708/c6682da4-4f6e-4bb6-a020-b31eda56162e.png)


実は、micro:bitにたった300円の部品を追加するだけで、このような「声」をトリガーにしたアクションを実現できるんです！この記事ではその具体的な方法を紹介します。

## キーデバイス：ダイソー「ボイスコントロールライト」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181708/4a4ddb18-d49c-4ba9-a036-39d6dc04275c.png)
![](./images/daiso-voice-light.jpg) 

このアイデアの核となるのが、ダイソーから300円（税抜）で販売されている「ボイスコントロールライト」です。

### ボイスコントロールライトとは？

この製品は、USBに接続するとライトが点灯し、特定の音声コマンドでライトのオン・オフができるという、300円とは思えない画期的なガジェットです。

**製品説明（パッケージより抜粋）**

* あなたの言葉にライトが反応する。話しかけてね。音声操作ライト。
* 電圧：DC5V
* 電流：0.2A
* **【はじめに】** 本品をUSB Type-Aコネクタに差し込むとライトが点きます。ライトに向かって「スマートライト」と呼びかけると、音声を認識した合図でライトが１回点滅します。
* **【ライトの消し方】** 「ライトを消して」という言葉をかけると、ライトが消えます。
* **【ライトの点け方】** 「ライトを点けて」という言葉をかけると、ライトが点きます。

つまり、「スマートライト」というウェイクワードの後に、「ライトを点けて」「ライトを消して」というコマンドで、内蔵LEDを制御できる仕組みになっています。

## micro:bitと組み合わせる仕組み

今回のアイデアは、このボイスコントロールライトの「声に反応して光る（または消える）」という特性と、micro:bitの「明るさセンサー」機能を組み合わせることで実現します。

micro:bitのLEDディスプレイ部分は、実は光センサーとしても機能します。

**処理フロー**

1.  ユーザーが「スマートライト」⇒「ライトを点けて」と発声する。
2.  ダイソーのボイスコントロールライトが反応して**光る**。
3.  micro:bitの明るさセンサー（LED画面）が、ボイスコントロールライトの光を**検知**する。
4.  micro:bitが光の変化（明るくなったこと）をトリガーとして、あらかじめプログラムされた**特定の処理を実行**する（例：ブザーを鳴らす、サーボモーターを動かす、別のLEDを光らせるなど）。

![mermaid-diagram-2025-04-27-155316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181708/741cb9c5-aafb-45af-95cc-698212d59473.png)

<iframe width="560" height="315" src="https://www.youtube.com/embed/lo9dUuysv8Q?si=k-mOYe-cf2_mP2El" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

# コード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181708/5c156857-645d-4388-b0db-dbdf9124574c.png)

```JavaScript:qiita.js
basic.showIcon(IconNames.Heart)
let isLED_ON = 0
music.setVolume(60)
basic.forever(function () {
    if (input.lightLevel() >= 100) {
        isLED_ON += 1
    } else {
        isLED_ON = 0
    }
    basic.pause(100)
    if (isLED_ON >= 3) {
        music.ringTone(330)
    } else {
        music.stopAllSounds()
    }
})

```
jupyter notebook初期設定

# summary

* open browser from remote client
* set password

# generate config file

```
jupyter notebook --generate-config
```

.jupyter/jupyter_notebook_config.py ができる。これを編集する。

## browserをサーバ上で開かない

```.jupyter/jupyter_notebook_config.py
## Whether to open in a browser after starting.
#  See also: ExtensionApp.open_browser
c.JupyterNotebookApp.open_browser = False
```

## source ip

```.jupyter/jupyter_notebook_config.py
## The IP address the Jupyter server will listen on.
#  Default: 'localhost'
c.ServerApp.ip = '0.0.0.0'
```

接続元端末を書く。
特に制限しない場合は0.0.0.0のままにする

## server port

```.jupyter/jupyter_notebook_config.py
## The port the server will listen on (env: JUPYTER_PORT).
#  Default: 0
c.ServerApp.port = 8080
```

サーバのポートを指定する

## directory

```.jupyter/jupyter_notebook_config.py
## The directory to use for notebooks and kernels.
#  Default: ''
c.ServerApp.root_dir = '/path/to/target'
```

起動時に表示したいディレクトリがあればここに設定する

## password

```
jupyter notebook password
```

# jupyter notebookを起動する

```
jupyter notebook
```

これでurlからtokenを省略できるようになる

## 起動後の接続先はこんな形

http://{server ip}:8080/tree
bit演算の総まとめ[例題付き]

### 基本のbit演算まとめ

演算|	記号	|説明	|例
|--|--|--|--|
AND（論理積）|	&	|両方1なら1、それ以外は0	| 1101 & 1011 = 1001
OR（論理和）|	\|	|どっちか1なら1	| 1101 \| 1101=1101
XOR（排他的論理和）	| ^ | 	違ってたら1、同じなら0	| 1101 ^ 1011 = 0110
NOT（否定）| 	~	| 0と1を反転する| 	~1101 = 0010
左シフト|	<<	| 左にビットをずらす（×2）	| 0011 << 1 = 0110
右シフト| 	>> | 	右にビットをずらす（÷2）| 	0110 >> 1 = 0011

### 詳細
① AND（&）
```cpp:cpp
int a = 5; // 5 = 0101
int b = 3; // 3 = 0011
cout << (a & b) << endl; // 出力：1（= 0001）
```


② OR（\|）
```cpp:cpp
int a = 5; // 0101
int b = 3; // 0011

cout << (a | b) << endl; // 出力：7（= 0111）
```

③ XOR（^）
```cpp:cpp
int a = 5; // 0101
int b = 3; // 0011

cout << (a ^ b) << endl; // 出力：6（= 0110）
```

④ NOT（~）
```cpp:cpp
int a = 5; // 0101

cout << (~a) << endl; // 出力：-6（コンピュータの内部表現の都合で負の数になる）
```
⑤ 左シフト（<<）
```cpp:cpp
int a = 3; // 0011

cout << (a << 1) << endl; // 出力：6（= 0110）
cout << (a << 2) << endl; // 出力：12（= 1100）
```

a << 1 → 2倍

a << 2 → 4倍

a << 3 → 8倍
みたいにどんどん大きくなる！

⑥ 右シフト（>>）
```cpp:cpp
int a = 12; // 1100

cout << (a >> 1) << endl; // 出力：6（= 0110）
cout << (a >> 2) << endl; // 出力：3（= 0011）
```

a >> 1 → 2で割った値

a >> 2 → 4で割った値

### 補足

書き方 |	意味 |
|---|---|
a << K |	aを左にKビットシフトするだけ（a自体は変わらない）
a <<= K|	aを左にKビットシフトして、その結果をaに代入する（aが変わる！）

### bit演算に関するAtCoderのリンク一覧
[2^N](https://atcoder.jp/contests/abc256/tasks/abc256_a)

[Maximum Sum](https://atcoder.jp/contests/abc096/tasks/abc096_b)

[Base 2](https://atcoder.jp/contests/abc306/tasks/abc306_b)

[Binary Representation](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_d)

[CTZ](https://atcoder.jp/contests/abc336/tasks/abc336_b)

[1-2-4 Test](https://atcoder.jp/contests/abc270/tasks/abc270_a)

[Bitwise Exclusive](https://atcoder.jp/contests/abc213/tasks/abc213_a)

[Bit Operation Ⅰ](https://onlinejudge.u-aizu.ac.jp/problems/ITP2_10_A)

[Bit Operation Ⅱ](https://onlinejudge.u-aizu.ac.jp/problems/ITP2_10_B)
C++のmapまとめてみた．




### mapの概要
C++のmapはとてもよく使われる標準ライブラリコンテナの一つで，
「キーと値のペア」を管理するデータ構造です．


### 使い方
```cpp: cpp
#include <iostream>
#include <map>
using namespace std;

int main() {
    map<string, int> m;

    // 要素を追加
    m["apple"] = 3;
    m["banana"] = 5;
    m["orange"] = 2;

    // 要素にアクセス
    cout << m["apple"] << endl; // 出力: 3

    // 全要素をループ
    for (auto it = m.begin(); it != m.end(); ++it) {
        cout << it->first << " => " << it->second << endl;
    }

    // 要素の検索
    if (m.find("banana") != m.end()) {
        cout << "bananaは存在します" << endl;
    }

    return 0;
}

```

### ポイントのまとめ
操作 | 方法
|---|---|
要素追加 | m[key] = value;
要素取得 | value = m[key];
要素削除 | m.erase(key);
要素数取得 | m.size();
すべてループ | for (auto& p : m) { p.first, p.second }
検索 | m.find(key) != m.end()
全削除 | m.clear();

### 詳しく
mapは自動的にキーの昇順に並びます（内部では赤黒木という木構造で管理）．
同じキーは2回入れられない（上書きされる）．
もし「同じキーを複数持ちたい」なら、multimapを使います．
挿入・検索はだいたい O(log N) の速さ．





### 例題
[AtCoderABC394-Cより](https://atcoder.jp/contests/abc393/tasks/abc393_c)
頂点に1からNの，辺に1からMの番号がついたN頂点M辺の無向グラフが与えられます.
そのグラフが，自己ループや多重辺のない単純グラフになるためには，少なくとも何本の辺を取り除く必要があるか．

イメージ（頂点N=3，辺M=5で，入力の詳細は省略）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457930/a3ea7453-ce45-4a34-bf08-89df31e69f09.png)

### 解説

```c++: 回答.cpp
#include <iostream>
#include <map>
using namespace std;
int main() {
  cin.tie(0)->sync_with_stdio(0);
  int N, M;
  cin >> N >> M;
  int ans = 0;
  map<pair<int, int>, int> m;
  for (int i = 0; i < M; i++) {
    int u, v;
    cin >> u >> v;
    if (u == v) {
      ans++;
      continue;
    }
    if (u > v) swap(u, v);
    m[{u, v}]++;
  }
  for (auto& [edge, k] : m) ans += k - 1;
  cout << ans << "\n";
}
```

ここで，map< pair< int, int >, int > m;
は，keyがpair< int, int >であり，頂点1と頂点2をそれぞれ表している．
そのkeyに対応するvalueも同じく，intで指定されている．
つまり，map< keyの型, valueの型 > map名;
という形．

問題の解説としては，そのmapの中から，頂点1と頂点2が同じだった場合，つまり自己ループはans++をする．
また，
```cpp: cpp
    if (u > v) swap(u, v);
    m[{u, v}]++;
```
ここでは，同方向のグラフを，カウントしている（（3,2)も（2,3）も同じだから）．
カウントしているというのは，  m[{u, v}]++; のところ．
ここでは，key{u, v}に対するvalueである，m[{u, v}]を追加している．

公式の解説は[こちら](https://atcoder.jp/contests/abc393/editorial/12242)


### 補足
型 | 例
|---|---|
|数値（int, double） | map< string, int >, map< int, double > |
文字列（string） | map< int, string >
配列やベクター（vector） | map< int, vector< int >>
別のmapやset | map< int, map< int, int> みたいなネストもできる
自分で作ったクラスや構造体 | map< int, MyClass > もOK