OmniAICreator/Qiita-1.07M huggingface dataset:
Windows11でWiiリモコンとペアリングする

Windows11で(最近のWindows10も？)WiiリモコンとペアリングしようとしたらPINの入力を求められて詰んでしまったのでメモしておきます。

### 前提
WiiリモコンとPCをペアリングするとき、PINがないにもかかわらず入力`求められるが、Windows11の設定アプリではペアリング時にPINの入力を回避することができない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935008/25e63686-268c-1f15-6457-c12a399769a8.png)

コントロールパネルからデバイスを追加すればよかったが、Windows11ではこのリンクをクリックしても設定アプリに飛ばされてしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935008/ac630c78-96ba-242b-c582-2fcb33ba3168.png)

### 解決策
「デバイスを追加」で従来表示されていた画面を手動で出す。

「デバイスを追加」で表示されていた画面の実体は、以下の場所にある実行ファイルなので、これを直接起動することでペアリングする。

```
C:\Windows\System32\DevicePairingWizard.exe
```

1. 「Win」+「R」を押してファイル名を指定して実行を表示する
1. 名前に`DevicePairingWizard.exe`と入力して「OK」を押す![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935008/3238bf3a-80d7-bb79-3059-508042beca83.png)
1. Wiiリモコンの「1」と「2」を同時に押してペアリングモードにする
1. PINを入力せずに「次へ」を押す![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2935008/3cd4dca5-fb1b-f741-2313-f298e6a3903b.png)

これでペアリングは完了。
Error: Missing Supabase environment variables

# はじめに
Next.jsのアプリの中でバッチ処理をするためにスクリプトを作成し実行しようとしたところ、以下のエラーが発生しました。

```
Error: Missing Supabase environment variables
```
バッチ処理の中でSupabaseにデータを保存しにいく場所があるのですが、「Supabaseの環境変数がない」というエラーが出ています。

# 問題
調べてみるとpackage.jsonのスクリプトから.envの環境変数を読み込みにいく時にはスクリプト内に設定をしないといけないようでした。



# 解決方法
いくつか方法があったようなのですが、私が調べた時にはdotenv-cliを使う方法を見つけたので今回は以下のサイトからダウンロードを実施してスクリプトの一部を以下のように変更し解決ができました。

https://www.npmjs.com/package/dotenv-cli

```
{
  "scripts": {
    "start:batch": "dotenv -e .env tsx バッチファイルディレクトリ" 
  }
}
```
-eを入れることで明確に読み込んで欲しいenvファイルを指定することができるようです。

# おわりに
環境変数を設定しているのになぜ読み込めないのか？という問題にpackage.jsonのスクリプトから指定をしているという観点から解決をするまでに時間がかかってしまいました。


# 参考
https://zenn.dev/tatsuyasusukida/articles/dotenv-package-json#%E6%96%B9%E6%B3%952%EF%BC%9Adotenv-cli%E3%82%92%E4%BD%BF%E3%81%86
Viteでimportの@エイリアスが利かないときの解決法

Vite環境でimportのパスに@エイリアスが使用できず少しはまったので解決方法のメモです。

以下のようにパスを設定できるようにします。

```tsx
// Before
import { moduleA } from '../../moduleA';
// After
import { moduleA } from '@/src/moduleA';
```

Viteの環境構築は公式に従います。
[最初の Vite プロジェクトを生成する](https://ja.vite.dev/guide/#%E6%9C%80%E5%88%9D%E3%81%AE-vite-%E3%83%95%E3%82%9A%E3%83%AD%E3%82%B7%E3%82%99%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B)

また
- Vite + Vue3 + TypeScript
- Vite + TypeScript

で設定方法が違ったため、2パターン記載しています。

## Vite + Vue3 + TypeScript

### 環境を構築する

1. 任意のディレクトリで``` npm create vite@latest ```を実行
2. Vue を選択
3. TypeScript を選択
4. npm install

`npm run dev`を実行し表示されたURLにアクセスして画面が表示されたらOKです。

### tsconfigの設定

まずimportのパスに@を使用できるようにします。
tsconfig.json、tsconfig.app.json、tsconfig.node.jsonの３つありややこしいですが、

- tsconfig.app.json
  - ```"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]```
  - こちらはtsはもとよりvueファイルをTypeScriptで書くための設定ファイル
- tsconfig.node.json
  - ```"include": ["vite.config.ts"]```
  - こちらはviteの設定ファイルをTypeScriptで書くための設定ファイル
- tsconfig.json
  - 2つのts.xxx.jsonを集約する

というすみわけです。
ということなので、tsconfig.app.jsonに以下を追加します。
```json
{
  "compilerOptions": {
    // 追加
    "paths": {
     "@/*": ["./*"]
    },
    ...省略
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}
```

### Viteの設定

"paths"の設定はあくまでTypeScriptのコード間でimportの解決をしてくれるだけのようで、実行時のパスはそのまま'@/src/moduleA'となってしまうようです。

vite.config.tsにresolveを追加します。
``` typescript
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': '/src',
    },
  },
});
```

これで再度`npm run dev`を実行するとパスが解決されてエラーがなくなります。

## Vite + TypeScript

### Vite環境を構築する

1. 任意のディレクトリで``` npm create vite@latest ```を実行
2. vanilla を選択
3. TypeScript を選択
4. npm install

`npm run dev`を実行し表示されたURLにアクセスして画面が表示されたらOKです。

### tsconfigの設定

まずimportのパスに@を使用できるようにするため、tsconfigに"paths"の設定を追加します。

```json
{
  "compilerOptions": {
    // 追加
    "paths": {
     "@/*": ["./*"]
    },
    ...省略
  },
  "include": ["src"]
}
```


### Viteの設定

vite-tsconfig-pathsをインストール

"paths"の設定はあくまでTypeScriptのコード間でimportの解決をしてくれるだけのようで、実行時のパスはそのまま'@/src/moduleA'となってしまうようです。

これはTypeScriptの仕様みたいなので、実行時のパスの解決のためvite-tsconfig-pathsをインストールします。

https://www.npmjs.com/package/vite-tsconfig-paths

```
npm install --save-dev vite-tsconfig-paths
```

つづいてvite.config.tsを追加します。

``` typescript
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig({
  plugins: [tsconfigPaths()],
});
```

これで再度`npm run dev`を実行するとパスが解決されてエラーがなくなります。

参考サイト

https://stackoverflow.com/questions/77249074/how-do-i-use-typescript-path-aliases-in-vite
paizaラーニング問題集「【部分列】最長減少部分列」を解いてみた

https://paiza.jp/works/mondai/dp_primer/dp_primer_lis_boss

▼感想

前問「最長部分増加列」と考え方は同じかと思います。
a_j(jは1～i-1) > a_i が成り立つとき、
最初が木a_jであるような減少部分列の末尾に木をくっつけて、
dp[i]+1の減少部分列を作ることができる。

▼コード
```py
########## 処理0(準備) インプット,リスト定義など ###########

n = int(input())

a = [0]*n

########## 処理1 漸化式の定義、計算、出力 ##########

dp = [0]*n

dp[0] = 1

for i in range(n):
    a[i] = int(input())

for i in range(1,n):
    dp[i] = 1
    for j in range(i):
        if a[j] > a[i]:
            dp[i] = max(dp[i],dp[j]+1)

print(max(dp))
```
【42Tokyo】first circle前半の感想

## 1. はじめに <a name="はじめに"></a>
　私は現在、以下の教育機関に所属しています。入学後約半年で義務過程(first circleと呼ばれる)の半分を終了したので、その感想をまとめようと思います。学校の規約で課題の詳細については述べられないことをご了承ください。

https://42tokyo.jp

後半はこちら

https://qiita.com/FR1SK_noob/items/2a8899b9abd08a6ed43b

### 対象読者
- 42Tokyoに興味がある方
- Computer Scienceの体系的な学習に興味がある方

### 本記事で述べること
- 42Tokyo本科課題に関する以下の内容
- 課題で筆者が学んだ要素
- 課題のつまづきポイント
- その他感想

### 本記事で述べないこと
- 本科課題の詳細設定
- 本科課題の解法、解答コード
- 本科課題の参考資料
- その他課題を実際に進めるために有益な情報
---

## 2. libft <a name="libft"></a>

### 概要
libftは、標準Cライブラリを模倣する基本的な関数に加えて、標準には存在しないが汎用で有用な関数を自作する課題です。

### この課題から学べること
- エラーハンドリング、エラーハンドリング、エラーハンドリング!!!!
- メモリリークの対処
- 本科のレビューがPiscineから次元が違う厳格さになること(課題が単純なので何ならまだぬるい)
- 同期入学の半分以上があっさり来なくなること

---

## 3. ft_printf <a name="ft_printf"></a>

### 概要
ft_printfは、標準ライブラリの`printf`関数を自作する過程で可変長引数の使い方を学びます。

### この課題から学べること
- フォーマット指定子や可変長引数の処理方法
---

## 4. get_next_line <a name="get_next_line"></a>

### 概要
get_next_lineは、ファイルから1行ずつ読み取る関数を実装する過程で、より厳密にメモリリークを対処することとstatic変数の扱い方を学びます。

### この課題から学べること
- static変数とはなにか
- メモリとはなにか
- メモリリークとはなにか
- スタック？ヒープ？

---

## 5. Born2beroot <a name="Born2beroot"></a>

### 概要
Born2berootは、仮想マシンを使ってLinuxサーバーを構築する課題です。

### この課題から学べること
- サーバー管理やLinuxの基本的なコマンドライン操作
- 仮想環境構築の初歩の初歩

### 感想
急にコーディングではなく座学が必要になる影響か、モチベが保てず来なくなる同期が多発します。

---

## 6. push_swap <a name="push_swap"></a>

### 概要
push_swapは、スタックを使って数列を並び替えるアルゴリズムを実装する課題です。

### この課題から学べること
- 要件を満たすアルゴリズムを考える力
- 計算量の削減や最適化技術について調査する力

---

## 7. fdf <a name="fdf"></a>

### 概要
fdfは、3Dグラフィックスを扱う課題で、42の独自ライブラリを提供された状態でワイヤーフレームを描画します。

### この課題から学べること
- 2Dから3Dの座標変換の実装

### 感想
　これまでさんざんライブラリを縛られていたのに急に外部ライブラリを使用するため、エラーハンドリングに手間取りました。ただ、これまで自分の実装でどうハンドリングするべきかを考えていたために「こういうエラーハンドリングだろうなあ」という仮説思考が先に湧いてきたのでなんとかなりました。

---

## 8. pipex <a name="pipex"></a>

### 概要
pipexは、パイプとプロセスの間でデータを渡す仕組みを実装する過程でプロセス間通信とファイルディスクリプターの管理について学ぶ課題です。

### この課題から学べること
- シェルやプロセス間通信の基本
- パイプ、ファイルディスクリプタ、システムコールの扱い方
- システムコールのエラーハンドリング

### 感想
　一番理解に苦しみました。一番インプットが重かったと思います。ここでちゃんと勉強しておくと後述するminishellが楽に理解できると思います。

---

## 9. minishell <a name="minishell"></a>

### 概要
minishellは、小規模なBashを実装する課題です。本科に入って初めてのチーム課題です。

### この課題から学べること
- シェルの構造
- シグナル処理
- チーム開発のノウハウ
- shellのリダイレクト処理
- 複雑で巨大なプログラムのエラーハンドリング

### 感想
　おそらく多くの人にとって本科first circleの中ボスに位置する課題です。平均2～3ヶ月、長い人は5ヶ月近くかかるそうです。正直これを完了出来る人はどこでもサバイブできると思わせるほどの大変な課題でした。ペアに恵まれたおかげで非常に楽しかったです！

---

## 10. philosophers <a name="philosophers"></a>

### 概要
philosophersは、哲学者の食事問題を解決する課題で、並行処理とデッドロック回避がテーマです。

### この課題から学べること
- マルチスレッドプログラミング
- デッドロックとはなにか
- デッドロックを回避するには

---

## 11. おわりに <a name="おわりに"></a>
　ここまでお読み頂きありがとうございました。フルコミット出来る環境にいられる幸運さと家族や友人に感謝し続ける毎日です。入学した同期の80%くらいがほとんど校舎に来ないような状況で寂しくなる一方ですが、自分は自分自身とまだ来ている同期達を鼓舞して後半も楽しく学び続ける所存です。

　これを読んで42Tokyoに興味が湧いた方はPiscineという入学テストの受験を検討されてみてはいかがでしょうか。いかなる金銭的な価値に変えられない貴重な体験が得られることを保証します。

---
Pythonにおけるエラー処理の構文

# はじめに
Pythonのコードを実行中にさまざまなエラーや例外が発生することがある。それらの場合を想定して、エラー処理を適切に行えるように、本記事では、Pythonのエラー処理構文についてまとめる。

# エラー処理の基本構文
Pythonでは、エラー処理のために```try```と```except```を使用する。基本的な構文を次に示す。

```py
try:
    # エラーが発生する可能性のある処理
except エラーの種類:
    # エラーが発生した場合の処理
```

次に例を示す。

```py
try:
    result = 10 / 0
except ZeroDivisionError:
    print("ゼロで除算することはできません。")
```

このコードを実行すると、ゼロ除算を試みた際に```ZeroDivisionError```が発生し、対応する```except```ブロックが実行される。

# 複数種類のエラー処理
次のコードで複数の異なるエラーを個別に処理することができる。

```py
try:
    # エラーが発生する可能性のある処理

# ゼロで除算しようとした場合
except ZeroDivisionError:
    print("ゼロで除算することはできません。")

# 指定されたファイルが見つからない場合
except FileNotFoundError:
    print("ファイルが見つかりませんでした。")

# その他のエラーが発生した場合
except Exception as e:
    print(f"予期しないエラーが発生しました: {e}")
```
「その他のエラーが発生した場合」について、汎用的な```Exception```クラスを使用している。

# ```else```と```finally```
```else```ブロックは```try```ブロックが成功した場合に、```finally```ブロックは例外の有無にかかわらず必ず実行される。

```py
try:
    result = 10 / 2
except ZeroDivisionError:
    print("ゼロで除算することはできません。")
else:
    print(f"計算結果は: {result}")
finally:
    print("処理が終了しました。")
```
上記のコードは次のような挙動となる。
- エラーが発生しない場合にelseブロックが実行される
- 例外の有無にかかわらず、finallyブロックが実行される

# 参考
https://techplay.jp/column/1831
gdbのかんたんシートシート

# GDBのチートシート(ターミナルでやるとき版)

- gdb <ファイル名>
    - ファイルをgdbで開く
- dissass ＜関数名＞
    - 関数名のディスアセンブル結果を表示する
     どこにブレークポイントを入れるかをみることができるよ
     一部地域では、objdump -M intel -d と同じ結果が出るらしいと言い伝えられている
- break *＜関数名＞+＜行数＞
    - どこにブレークポイントを置くか決める
    　[POINT] ブレークポイントが置かれる前までで処理が止まることを忘れないように！
- delete ＜ブレークポイントナンバー＞
    - ブレークポイントを削除するよ
- next
    - アセンブラを一行ずつ実行する。callされた場合は、**その関数の中には入らない**
- stepi
    - アセンブラを一行ずつ実行する。callされた場合は、**その関数の中に入る**
- continue
    - 次のブレークポイントまで実行。
- finish
    - 現在の関数の終了まで実行
- until
    - 現在のループが終了するまで実行
- run 
    - mainの頭から初めのブレークポイントまで実行
- print ＜var＞
    -　p var:varの値を確認する
    -　print var=3:varの値を３に書き換える
    -　他にも色々機能あるらしい（諸説あり）
- x
    - メモリの値を確認する
    - x array:arrayのアドレスをダンプする

### 今日掴んだgdbの順序
1. gdbにファイルを読み込ませる
2. ダンプしたいところを見つける
3. ブレークポイントを置く
4. 実行を続ける
5. flagを回収
【React × TypeScript】デジタル名刺を作成できるアプリを開発

# はじめに
React学習を始めて、２か月立ちました。
今回はデジタル名刺アプリを開発しました。
アプリの詳細とどのような技術を使用したかなどを紹介していきたいと思います。

# デジタル名刺アプリ
今回開発したデジタルアプリの説明を簡単にしたいと思います。
このアプリはデジタル名刺を作成、表示できるアプリです。

まず、新規登録はこちらをクリックし、名刺を登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/b7ab4a16-06b3-344d-33bf-a020b71b7b68.png)

新規登録で検索用の英単語（ID）や自分の名前、自己紹介、好きな技術、各種アカウントIDを入力していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/7d82fc57-eb6b-85f8-f8c1-99311434835a.png)

登録が完了すると、トップページに戻るので、先ほど登録したIDを検索IDに入力し、名刺検索を行います。

検索したIDのデジタル名刺が表示されます。
外部リンクをクリックすると、それぞれのIDのアカウントに飛ぶことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/2e0e40b4-27cc-1e6d-48ae-1e02e721b6ce.png)

# 使用技術
以下が使用した技術です。
| 名前 | 説明 |
|:-:|:-:|
| **使用言語**  | React, TypeScript  |
| **UI**  | [ChaKra UI](https://v2.chakra-ui.com/) |
| **データベース**  | [Supabase](https://supabase.com/)  |
| **サーバーサイド** | [Firebase](https://firebase.google.com/?hl=ja) |
| **CICD構築**  | GithubActions |

# 今回のアプリ開発で成長したと実感したこと
今回のアプリ開発で以下の2つが主に成長したと実感しました。
- react-router-domのuseNavigate
- Github Actionsの使用方法

react-router-domのuseNavigateを多用し、登録したらトップページ、検索ボタンを押したら詳細ページと、ページ遷移の処理の理解が深まりました。
複数のページの相互関係を構築するには、useNavigateは重要な機能なので押さえておきたいですね。

また、前日のデータを削除する処理を入れました。
データの削除にはGithubActionsのscheduleを使用しました。
毎朝6時になると、バッチ処理が動き、前日作成した名刺情報を削除してくれます。
今まで使用したことがないものでしたが、比較的簡単にymlファイルの記述は作成することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1328154/f52c4f37-38bf-ac46-a18f-0fb78a6deb81.png)


# ここに詰まってしまった
　Github Actionsのymlの記述自体はすぐにできましたが、バッチ処理のtsファイル実行時に環境変数エラーがでてうまく実行できないことがありました。
エラー記事を調べたり、gptに聞いてみたりしなんとか解決することができました。
次にtsファイルを実行するときはいくつかやり方も学べたので、うまくできると思います。

　また、GithubActionsのscheduleはタイムラグがあるようで、実行してほしい時刻になっても実行されず、5分遅れで実行されたりということがありました。
どこか記述が悪いのかと焦りました、、
<font color="red">補足ですが、scheduleの時刻はUTCタイムなので、日本時間で指定してしまうとまったく違う時間になります。</font>

# 意外とエラーの解決記事はある
見たことないエラーに遭遇して、エラーを調べてみてもヒットしないということがあると思います。

でも、意外と調べ方を変えて、エラーの一部を検索、エラーに関係ありそうな単語で検索等するとヒットします。
詰まってしまったと悩んでいることは、ほかの誰かもある程度経験しています。

**もし、エラーの原因が分からないという方がいたら、調べ方を変えてみるのを意識するといいかもしれないです！**

# 終わりに
ここ最近思ったのですが、昔の自分だったら技術書を読んでそこから何のアプリ開発しようかと考えてと、実際に手を動かすまで時間がかなりかかっていたと思います。

今は、アプトプット中心に変えて、振り返った時に「これができるようになった」ということが増えました。
基礎の段階では技術書を読むことは大事だと思います。
ただ、実際に学んでいくにはやはり手を動かすのはすごく大事だと感じています。

さらにReactを習熟できるように学習を進めていきます。

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからお願いします👇

https://projisou.jp
Google Cloud サービスアカウントの秘密鍵の確認・取得方法

## サービスアカウントの秘密鍵（JSON）の確認・取得方法
**1. Google Cloud コンソールにログイン**

[Google Cloud コンソール](https://cloud.google.com/cloud-console?hl=ja)
        
**2. プロジェクトを選択**

**3.「IAM と管理」をクリック**

![スクリーンショット 2024-09-29 18.05.48（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535387/9d378855-127c-7fee-254d-35d4b651680e.png)

**4. サービスアカウントを選択**

①右側にあるメニュー（3つのドットアイコン）をクリック
②「鍵の管理」を選択
![スクリーンショット 2024-09-29 18.32.22（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535387/15381b96-2a49-7f0c-d433-8c3ccb7335ce.png)

**5. 新しい鍵を作成**

「鍵を追加」ボタンをクリックし、「新しい鍵を作成」を選択します。
![スクリーンショット 2024-09-29 18.45.12（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535387/8c86ef3d-be7f-3f8d-5fff-f824e05655e3.png)


**6. JSON形式を選択して鍵を作成**

「JSON」を選択して「作成」ボタンをクリックします。これにより、サービスアカウントの秘密鍵が自動的にダウンロードされます。

![スクリーンショット 2024-09-29 18.45.26（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535387/3deb4ad4-50ac-8e62-4dac-a87599c3a631.png)


**7. 秘密鍵の確認**

ダウンロードされた JSON ファイルを開くと、サービスアカウントの秘密鍵情報が記載されています。この内容をコピーし、GitHub Secrets に追加します。
GitHub Secrets に追加後は、ローカルPCからJSONファイルを削除してOKです。

最後までお読みいただきまして、ありがとうございます！
PowerApps　制限時間タイマーを表示する

<iframe width="560" height="400" src="https://www.youtube.com/embed/qcxO5YQv8GM?si=ALiqHAoRnoYl1QH_" 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>
⇧戦国武将クイズアプリを作る　その4
動画内で制限時間を付ける方法を解説しました。

使用したのはタイマー。
長さをミリ秒で設定して、Startプロパティをtrueにすると、時間が進んでいくコントロールです。

そこでタイマーのTextプロパティに以下の数式を入れて、カウントダウンさせました。
```
Int((Self.Duration - Self.Value)*0.001+0.99)
```
Self.Duration=タイマー自身の長さ
Self.Value=タイマーの経過時間
ミリ秒なので、表示を秒にするため0.001を掛けています。
それだと小数点以下が表示されてしまうのでINTで整数にしています。

もしくは
```
Text((Self.Duration-Self.Value)+990,"s")
```
としても表示は同じですので、お好みで
最後に0.9秒足してるのは一瞬でも０が表示されて欲しかったから

あとは、OnTimerEndプロパティにタイムオーバー時の処理を入れればOK
私はクイズアプリに使用したので、解答ボタンの不正解時の処理と同じものを入れました。

カウントダウン開始は、次の問題を表示するボタン「Next」のOnselectプロパティに設定
```
UpdateContext({_Think:true})
```
変数_ThinkはタイマーのStartプロパティに設定しているので、「Next」ボタンを押すことでカウントダウンが始まります。

以上
AIで気になるあの子の気持ちをオープンにするアプリを作りました！【QiitaHackathon2024 参加体験談】

# はじめに

こんにちは！
今回は、ハッカソンイベントQiitaHackathon2024に参加してきたので、参加体験談と作成したアプリの紹介をさせていただきます！

私たちのチームは、
LINEのトーク画像のスクショをアップロードすることで、相手からの好感度を知ることができるアプリ「MoodKey」を開発しました！

![モック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3893220/ede71d47-d4f4-c70d-c4c2-a8801b77a12e.png)

# 参加したハッカソン
今回、Qiita主催のQiita Hackathon2024の予選に参加しました！
大学時代の同期3人での参加で、みんなIT関連の企業で働いております！

https://qiita.com/official-campaigns/hackathon/2024

Qiita Hackathonは本戦と予選に分かれており、２日間で開発からプレゼンまでを行うと流れです。
結論、私たちのチームは予選通過できませんでしたが、備忘録として記事にしたいと思います！

### テーマ
テーマは1日目の午前に発表されます。
今回のテーマは、、、、、「**オープン**」でした！

最初聞いた時に、パッと何も思いつかないくらい抽象的でしたので、アイデア出しが難しかったです😢


# アイデアを決める
アイデア出しとしては、
1. 「オープン」から連想できることをたくさん書き出す
1. 書き出した内容に対して存在する課題を考える
1. 解題に対する解決策を出す

というフローで進めました！

最終的に、
気になる子とLINEをしているけど、「相手の気持ちが分からず、一歩踏みだす勇気が出ない」という課題に対して、AIによって相手の気持ちをオープンにして次の一歩に繋げるようなアプリを作ろう。

となりました！

# 開発していく
完成までの流れとしては、
1. Figmaでラフのデザインを起こす
1. アイデアを形にするためのアーキテクチャを考える
1. ラフのデザインで実装（その間に最終デザインも作成）
1. 最終デザインを反映

となりました！
２日間でかなりハードでしたが、うまく分担して作りきりました（ほぼ寝れませんでしたが、、、）

### デザイン
以下のようなデザインにしました！
工夫ポイントとしては、
+ 背景色にはピンクと紫のグラデーションを使用し、暗い状態から気持ちが晴れていく（オープン）印象を与えるようなカラー
+ ステータスバーを表示することで結果が分かるまでのフローをユーザーに可視化
+ 画像をアップロードしてない状態では「診断開始ボタン」の色がグレーとなり、次に進めないことを知らせる
+ 分析中のフローを入れることでユーザーを不安にさせない

![最終デザイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3893220/3ffd8586-08eb-4122-fc14-dad4828ca627.png)


### アーキテクチャ
以下の図のようなアーキテクチャで実装しました。
フロントエンド：TypeScript（React）
バックエンド　：TypeScript（Node,js）、Python（Flask）

![アーキテクチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3893220/6de82764-f55b-8084-4026-ef3f3bd138a5.png)

システムの大まかな流れとしては、
1. ユーザーがアップロードしたトーク画像を文字起こし（Cloud Vision API）
1. 文字起こししたテキストの感情分析でポジティブスコアを獲得（Transformer）
1. テキストとスコアの情報をもとにスコアの理由とアドバイスを生成（Gemini）

となります。
工夫ポイントとしては、
+ LINEなどはトークを全てコピーできないため、スクショ画像を文字起こしする処理を入れてユーザーの手間を減らす
+ スコアの計算を生成AIに行わせず、transformerに行わせる（生成AIにスコアリングさせるよりも、感情分析用に学習されたモデルの数値の方が信頼できると考えた）

# 完成したアプリ

完成したアプリのgifを以下に貼りました！

主な画面構成としては、
+ 画像アップロード画面
+ AI分析中画面
+ 結果表示画面

となってます。

![gif-output-Sun29Sep2024100113GMT.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3893220/88c5d2d1-c448-f30e-28cc-0e7677939ce4.gif)


作成したアプリを振り返ってみると、
+ 好感度が必ずしもポジティブ度合いと一致はしない
+ 診断結果のアドバイスを構造化して見やすく表示できた方が良い

などについては、さらに改善できるかなと思っています。
特に「好感度が必ずしもポジティブ度合いと一致はしない」については「会話頻度」、「共感」、「相手からの興味・関心」など、好感度に関連しそうな複数観点をもとに評価することで結果の質が上がるかなと考えています。

# まとめ
今回は、Qiita Hackathonへの参加体験談と実際に作成したアプリの紹介をさせていただきました。

デザイン〜実装までを約1.5日間で完成させるのは非常にハードでほぼ睡眠はできませんでしたが、チームでプロダクトを作り切るという経験ができてよかったです！

機会があれば、また参加したいと思います！

それでは、また！
Linux Swapまとめ

以下はlinux使いによるめも書きです
ご自由にお使いください

### First of all

以下で状態確認
```sh
sudo swapon -s
```

これでオン/オフ
-pオプションはpriorityで高いデバイスが優先して使われる
```sh
sudo swapon /dev/sdaX -p -2
sudo swapoff /dev/sdaX
```


### 簡易的なスワップファイルによるスワップの有効化

スワップファイルによるスワップは以下のようにする(例は1GiBのファイル)
本来なら/swapfileではなくパーティション/dev/sdaXなどにすべきだがパーティションをいじるのがやや面倒くさいクラウド環境等では重宝する
```sh
sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```

### 永続化
/etc/fstab に追加
```
/swapfile none  swap   sw  0      0
```

有効化
```
sudo swapon -a
free -h
```

#### swappiness
swappinessはおおきくなるほど不要なメモリーをディスクに追い出すようになる
デフォルトだとおおきくすぎてメモリーが余っていてもスワッピングしてしまうのでちいさくする
/etc/sysctl.d/local.conf
```
vm.swappiness = 10
```

以下で有効化
```sh
sudo sysctl -p /etc/sysctl.d/local.conf
```

確認
```sh
sysctl -n vm.swappiness
```

一時的であれば以下でもよい
```sh
sudo sysctl -w vm.swappiness=10
```

/proc/sys/vm/swappinessで設定することも可能だがやや古い書き方だと思う

### zram
CPUを使った圧縮により、より多くのメモリーが載っているように見せるモジュール

以前はzswapもあったが取り扱いのしにくさから現在はzramが主流のよう

標準で入ってることもある

[zram](https://wiki.archlinux.jp/index.php/Zram)
[ZRAMCTL(8)](https://man.archlinux.org/man/zramctl.8)

以下で確認
なお普通にマウント/アンマウントできる
マウントされていない場合は2つ目のコマンドでみつけられる
```sh
zramctl

zramctl --find
```

再設定する場合は以下でまずリセット
```sh
sudo swapoff /dev/zram0
sudo zramctl -r /dev/zram0
```

以下で使われていないzramデバイスを探し出して設定する
```sh
sudo zramctl --find -a lz4 --size 512M --streams 4
sudo mkswap /dev/zram0
sudo swapon /dev/zram0 -p 100
```

アルゴリズムは以下で確認/設定できる
```sh
cat /sys/block/zram0/comp_algorithm
```

```
lzo lzo-rle [lz4] lz4hc 842 zstd
```

#### 永続化

起動時に自動でzramをセットアップするサービスが存在する
/etc/systemd/zram-generator.conf

```
[zram0]
zram-fraction = 1.0
max-zram-size = 512
swap-priority = 100
compression-algorithm = lz4
```

起動中に再設定するにはswapoffした後以下のコマンドを実行する
```sh
sudo /usr/lib/systemd/system-generators/zram-generator --reset-device zram0
sudo systemctl daemon-reload
sudo systemctl start systemd-zram-setup@zram0.service
```

以下でloadされているか確認
```sh
sudo systemctl status systemd-zram-setup@zram0.service
```


#### lz4 (おまけ)

lz4は高速性に重きをおいた圧縮アルゴリズムである
圧縮はしたいが速度を犠牲にしたくない場面でよく用いられる
最近はzstd(ZStandard)も人気
高速な圧縮はsnappyなどがはじまりだろうと思う
[ドラゴンクエストXは「世界は一つ」を実現するためにどのようなサーバ構成にしているのか？](https://gigazine.net/news/20120824-dragonquest-backstage-cedec2012/)
[『大乱闘スマッシュブラザーズ SPECIAL』容量とビルド時間圧縮に立ち向う方法が語られたCEDECセッションレポ【CEDEC 2019】](https://www.gamebusiness.jp/article/2019/11/12/16438.html)
[DSIRNLP #3 LZ4 の速さの秘密に迫ってみる | PPT](https://www.slideshare.net/slideshow/dsirnlp-3-lz4/14522650)


### earlyoom

linuxにはOOM(Out of Memory)機能がありメモリーが満杯になると不要なプロセスをキルするようになっているがギリギリにならないと機能しない等あまり使い勝手がよくないので予防的にOOMするデーモンが存在する(Fedora等には標準搭載)

/etc/default/earlyoom
```
EARLYOOM_ARGS="-r 0 -m 7,1 -s 10 --prefer '^(process_name_low_priority)$' --avoid '^(process_name_high_priority)$'"
```
ハイブリッド型発表会のストレス

昨今のご事情により、
新卒研修の最後に行う成果発表会であったり、
社内勉強会でのLT大会など、
今まで現地会場で行っていた発表会が、
現地　＋　リモート　のいわゆるハイブリッド型となったケースも
増えてきているのではないでしょうか？

そして、今更戻ることも考えにくく、
今後もこの形態は継続していくことが予想されます。

便利な世の中だなと感じる一方で、
ストレスの溜まる発表会も多いのが事実。

今日はハイブリッド型発表会におけるストレスと、
その原因を掘り下げます。

## ハイブリッド型発表会とは
ハイブリッド型発表会は、
現地 + リモートを同時進行する発表会です。

現地会場では、
プロジェクターやスクリーンを使用して、
発表内容を投影し、
リモートへは、Zoom　や　Teams　、　Google　Meetなどの
リモート会議ツールの画面共有を使用して、
投影内容を共有します。

※技術カンファレンスなどでは、
Youtube Liveを使用したり、
OBSを活用したり、
ATEM Miniといった専用機材を導入しているところもあります。

こういうツールを活用すると、発表の品質は高まりますが、
　
- 機材が意外と高い
- 使い方がよくわからない
- そもそも年1,2回しかやらない

だと、小規模な発表会ほど、
中々、投資しづらいというのが本音ではないでしょうか。

## ハイブリッド型発表会のストレス

こうした、現地からリモートへの配信スタイルで行う発表会、
簡単な用で意外とクオリティを保つのは大変です。

### ストレス1　時間通りに進まない進行

ハイブリッド型の発表会でよく見られるのは、スケジュールが押してしまうケースです。

機材トラブルなど原因は様々ですが、一番良く見られるのは、スピーカーの切り替えに時間がかかってしまうことではないでしょうか。

もちろん、タイムテーブルを組む側も、もちろん切り替え時間を考慮する（だいたい２〜5分程度）のですが、
想定以上に時間がかかってしまうケースが多いのではないかと思います。

スピーカーの切り替えと言っても細分化すると、

- 退場・登壇
- HDMIケーブルの抜き差し
- 会場投影内容の調整（発表者ビューの切り替え 等）
- 画面共有の切り替え
- 音声調整（ミュート解除、スピーカーの切り替え 等）
（会場セッティングにもよって変わります）

となります。スムーズに執り行なえば、2分でも十分ですが、たとえ事前にリハーサル等をしたとしても、意外とうまく行かないこともあります。ちょっとしたトラブルが起こるだけでも、5分くらいすぐ経過してしまいます。

（だからといって、時間を長めに取るのも、タイムテーブルとしてスカスカになってしまいます・・・）

### ストレス2　音声トラベル（ハウリング）

また、スピーカーの切り替えを行うときに、ハウリングが起こってしまったということはありませんか？　急に大きな音がなったり、聞いている方からするとストレスに感じますよね。また、スピーカーがテンパってしまう要因にもなってしまいます。

ハウリングは、同じ会場内で複数のマイク・スピーカーがオンになっていると発生する可能性があります。

※同じ会場内の他のスピーカーから発せられた音を、自分のPCのマイクで拾ってしまうと発生します

ハウリングの対応方法や原因を理解できていないと、

- 解消に時間がかかってしまう
- またはリモートの音声のオンオフを切り替えながら行うハメになる

となります。

そして残念なケースでは、リモート音声をオフにしたまま進めた結果、発表後質疑応答でリモートからの質問に答えそびれた、という話も聞いたことがあります。

## よくある構成の問題点

実はこういったトラブルは、
「よくある構成」が原因となっています。

### よくある構成

一番よく目にする構成は、
発表者のPCから会場とリモートに配信する構成です。音声と映像を発表者がコントロールするので、ある種自然な構成といえます。

![スクリーンショット 2022-11-16 17.25.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215071/13c4fac3-4ecf-eff9-c21c-96a2f46ae04a.png)

### 問題点

しかし、この構成には、問題点が多いです。

- 発表者交代時に、ケーブルを抜き差ししてPCを変える必要がある
    - 時間ロスが発生する
    - 設定がPC
- 発表者交代時に、マイクのオンオフを切り替える必要がある
- ハウリング防止のため、発表者PCを経由して会場音声を流す必要がある。

## これがお手軽ハイブリッド発表会だ
![スクリーンショット 2024-09-29 18.49.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215071/e4399ac1-78bf-99b1-47ef-819136d139e1.png)


ポイントとしては、

 - 音声の入力と出力を同じデバイス(投影用のPC)から行うこと
 - 登壇者は自身のPCで画面共有経由で資料を投影する
 - 会場の映像もZoomの画面のみを投影する

となります。
こうすることで、ハウリングを防ぎ、
かつ、ケーブルの抜き差しによる余計な時間を削ることが可能です。

スピーカーが複数いる場合でも、
マイクを工夫し、入力を一つにまとめることが重要です。

たとえば、
 - スピーカーフォン
 - 送信機が2つ以上あるワイヤレスマイク
活用することで解決できます
（安いものであれば数千円で解決できます）

もちろん、品質という意味では、
満点ではなく及第点ですが、
スムーズな運営という意味ではこれ以上ない方法だと思っています。

今更ですが、少しでも参考になれば幸いです。
classって何?

# Javaにおけるclassの役割

筆者はC言語からプログラミング言語を学習していった人間である。classとは無縁だし、せいぜい作るとしてヘッダーファイルくらいだし、ヘッダーファイルを手動で読み込ませるのもおっくうだなと感じる人間であった。
そんな人間でもクラスとかオブジェクト指向を学ぶとめちゃ便利って感じることが多いように思える。
特に便利だなとか使いやすいなと感じる機会が多かったのがグローバル変数をめったに使わなくなったことでが多いと思う。C言語の場合、多重配列の変数を戻り値に設定する場合出来ず、ポインターで変数を変えるのもと考えるときにグローバル変数で戻してしまうことが多かったように感じるが、Javaだとそれもほぼほぼないと感じる。Javaは実務で書くようになって、C言語は趣味で書いていたというのもあるだろうが。
クラスの一番のメリットは他のクラスへの継承等ができるところであると思う。ヘッダーファイルを作って他のヘッダーファイルにコピーしようと思ったら、ベタ書きで書くなどの方法しか筆者は思いつかない。（あとは継承元のヘッダーファイルを読み込ませるとかはありそうではあるが）。
その辺を簡単にしてくれるのがクラス。

# クラスの継承元はクラスだけ？

結論インターフェースも継承できる。ただし、クラスの場合は１つのクラスを継承できないが、インターフェースに関しては複数のクラスを継承することができる

# 余談
ネタを仕込みつつ、毎週更新を目指す。
WSL2のUbuntuにtinet導入してみた（体験しながら学ぶネットワーク技術入門）

# サマリ
[体験しながら学ぶネットワーク技術入門](https://www.sbcr.jp/product/4815618599/)
の前段の環境構築（tinet導入）をしました。

:::note warn
注意
本書籍用のセットアップスクリプトを実行するだけのシンプルな手順なので、公式ページからダウンロードする１からのtinet導入手順でないことにご注意下さい
:::

# 背景
ネットワーク技術を基礎から学ぼうと思い、
[体験しながら学ぶネットワーク技術入門](https://www.sbcr.jp/product/4815618599/)という書籍を購入しました。
まずは環境構築としてtinet導入までやりました。
（やったというほどのものではないですが。。）

# ゴール
WSL2のインストール、DockerとtinetのWSLインスタンスへのインストールをする
（ただし本書籍用のセットアップスクリプトを実行するものとする）

# 対象読者
- 体験しながら学ぶネットワーク技術の書籍を購入した方

# 前提
必須：PC、インターネット環境
推奨：基本的なコマンド操作に関する理解
# 環境
- ホストOS：Window10 Home
- 仮想環境：Ubuntu 20.04
# 手順
そもそもtinetとは…

> TINET は、苫小牧高専情報工学科において開発された ITRON TCP/IP API仕様 に準拠したコンパクトな TCP/IP プロトコルスタックです。TINET は FreeBSD のコードをベースとしているため、その使用にあたっては、TOPPERSライセン スに加えて、FreeBSD のライセンス条件にも従う必要があります。

[公式ページ](https://www.toppers.jp/tinet.html)より引用

高専で開発されたのすごいですね（何の話
ネットワーク系のツールってあまりない印象なので、
ありがたいです。

### WSL2のインストール

```wssl --install --distribution Ubuntu-20.04```
で、仮想マシンプラットフォーム、WSL、WSLインスタンスなどWSL2でUbuntu20.04を利用するために必要な機能がすべて入るためこれ一発でOKのようです。

自分はPowerShellで上記コマンドを打ちました。

細かいですが、その後UbuntuのユーザやrootユーザのPW設定を実施しました。

### セットアップスクリプトの実行（Docker・tinetのインストール）
SBクリエイティブのページにてインストールに必要なファイルがあるので、
ダウンロードして、書籍所定の場所（Cドライブ直下）に配置しました。

setup.shファイルをUbuntuのrootユーザで実行します。

```bash /mnt/c/tinet/setup.sh```

このスクリプトにはDockerやtinetのインストールだけでなく、DNSクライアントの設定やwsl.confの設定等、
本書籍の検証に必要な処理が一括で実施されるようになっているので
めちゃくちゃ便利です。

# 結果
問題なく導入完了できました。

# まとめ
今回はすでに準備されたスクリプトの実行だけだったのであまり大きな問題もなく完了できました。
大きなエラーもなく完了したのであまり汎用的・有用な記事にはなっていないですが、
お許しください。。

環境構築のハードルが低いのは初学者にとって本当にいいことだと思うのでありがたい限りです。
大事なのはどのように使って習熟していくかだと思うので、これから頑張ります…！
M5 Servo-360 Unit

# はじめに

[PCN渋谷](https://www.instagram.com/pcn.shibuya/)にて、ワークショップとしてイライラ棒ゲームを作成しました。ゲームの妨害機構にモーターを使った回転動作を加え、難易度を調整しています。

# 開発環境

- VSCode (エディター)
- PlatformIO (組み込み開発に特化したVSCode拡張機能)

https://qiita.com/koyochan/items/a8abfb97c000fb233b27

# 使用デバイス
- [M5StickCPlus2](https://shop.m5stack.com/products/m5stickc-plus2-esp32-mini-iot-development-kit?srsltid=AfmBOooQERm9Eml_6gWcg5AaHppBS0W1R1cSrqTAYbA2mVfDP1sda6OA)
- [Servo Kit 360](https://shop.m5stack.com/products/servo-kit-360?srsltid=AfmBOoquvfr6MZlRg23Nenj92U0w3bF0klOzPFgNvtd5rXtuTkSUrXKn)

# 使用言語
- C++

# 実行Flow
1\. 上記の記事より、開発環境を構築する(VSCode PlatformIO環境が存在する場合省略可)
2\. [GitHub](https://github.com/koyochan/Qiita/tree/main/Servo-360-Unit)からコードをクローンする
3\. クローンしたディレクトリに移動`cd Servo-360-Unit`
4\. **Terminal**から`pio run --target upload && pio device monitor`を実行する

# Servo-360-Unit仕様

| パラメータ | 値 |
|:-:|:-:|
| PWM  |  50Hz/0.5~2.5MS |
|  電圧 |  4.8~6.0V |
| デューティ比  |  0 ~ 0.705 |

:::note warn
電圧が一定でないため、同秒数、同速度でも常に同じ角度にはならないことがあります。
:::
:::note info
角度の制御をしたい場合は、[Servo kit 180](https://shop.m5stack.com/products/servo-kit-180?srsltid=AfmBOorpTK3me6nHA7EUHxvO28euzxtSSZunEDnajqWohJ5YEkbjTZ4K)を使用してください。
:::





https://docs.m5stack.com/en/accessory/servo_kit

### PWM制御
サーボモーターの動作はPWM (パルス幅変調) を使用して制御します。PWM信号を送ることで、モーターの回転速度と方向を制御します。



https://dotstud.io/docs/pulse-width-modulation/



### デューティ比

PWM制御における「オン」と「オフ」の比率をデューティ比と呼びます。サーボモーターに送るパルスの幅がデューティ比を決め、これがモーターの回転速度と方向に影響します。今回使用するServo kitでは、0~0.705の範囲で制御します。


https://www2.denshi.numazu-ct.ac.jp/mirsdoc/mirs97/01/shousai/elec/sp/duty.html

# 解説

以下のコードに書いてある通り1500から7500までの値がそれぞれ回転速度や方向を示します。

```
#define ROTATE_RIGHT_HIGH_SPEED 1500 // 右回転早め
#define ROTATE_RIGHT_LOW_SPEED 4500 // 右回転ゆっくり
#define COUNT_STOP 5000 // 回転停止
#define ROTATE_LEFT_HIGH_SPEED 5500 // 左回転早め
#define ROTATE_LEFT_LOW_SPEED 7500 // 左回転ゆっくり
```
これらの定義された値は、PWM信号のパルス幅を示しており、ledcWrite 関数を使ってサーボモーターに適用されます。

以下のようにしてモーターに値を送信します。

```ledcWrite(1, ROTATE_RIGHT_HIGH_SPEED);```

- ledcWrite(1, value) の第1引数 1 はPWMチャンネルを指定し、第2引数 value は回転速度や方向を決める値です
- 値が1500の場合、右方向に高速で回転します。4500にすると右方向にゆっくり回転し、5000で停止。さらに、5500以上の値では左方向に回転します

# まとめ

本プロジェクトでは、M5StickCPlus2を使ってServo Kit 360をPWM制御し、イライラ棒ゲームに回転動作を加えました。今回の例では、簡単な速度と方向の制御を示しましたが、用途に応じた応用も可能です。

このようにして、関数 ledcWrite の動作や、各定義された定数がPWMの値をどのように影響しているかを説明する形にしました。

ご不明な点や質問がございましたら、どうぞお気軽にご連絡ください。
【Python練習問題】関数の基本編

今回は関数編です。
基本的な関数の使い方から、
間違いやすいポイントまで抑えています。

## 1.関数の基本

### Q.1-1:次のコード内 XX　に当てはまる内容を答えなさい

```python
# 与えられた数が偶数かどうか判定する
def is_even(x):
    return x % 2 == 0 

# 使用例
print(XX(5))  # 出力: False

```

### Q.1-2:与えられた数の2乗を計算して返す関数を作成してください。

```python
# 与えられた数の2乗を計算して返す


# 使用例
print(square(5))  # 出力: 25

```

### Q.1-3:次のコードを実行した結果を答えなさい

```python
def add(a, b):
    return a + b

# 使用例
result = add(10, 20)
print("足した結果は"+ str(result) +"です") 
```

### Q.1-4:次のコードを実行した結果を答えなさい

```python
def add(a, b, c):
    return a + b + c

# 使用例
print(add(30, 20, 20)) 
```

### Q.1-5:次のコードを実行した結果を答えなさい

```python
def concatenate(s1, s2):
    return s1 + s2

# 使用例
print(concatenate("Hello, ", "World!")) 

```

### Q.1-6:次のコードを実行した結果を答えなさい

```python
def countdown(n):
    for i in range(n, 0, -1):
        print(i)

# 使用例
countdown(5) 
```

### Q.1-7:次のコードを実行した結果を答えなさい

```python
def janken(hand):
    if hand == "グー":
        return "勝ち!"
    elif hand == "チョキ":
        return "あいこ。もう一回。"
    else:
        return "負け・・・・"
    
# 使用例
hand = "グー"
print("結果は・・・・" + janken(hand)) 
```

### Q.1-8:指定された人に挨拶をする関数を作成した。"Hello Yamada"という文字を出力したい場合、どのように呼び出せばよいか、a〜dから選びなさい。

```python
def greeting(to):
    print("Hello " + to)
```

a.

```python
greeting("Yamada")
```

b.

```python
print(greeting("Yamada"))
```

c.

```python
greeting()
```

d.

```python
print(greeting())
```

### Q.1-9:次のコードを実行した結果を答えなさい

```python
# 定義前に実行した場合
print(add(10, 20)) 

def add(a, b):
    return a + b
```
Jest と React Testing Library を使った Next.js + TypeScript プロジェクトのテスト環境構築

# はじめに
Next.js のテスト環境構築に関する情報は多いものの、TypeScript対応の記事はあまり見かけなかったため、備忘録としてまとめました。この記事では、TypeScript対応の Next.js プロジェクトで Jest と React Testing Library を導入し、テスト環境をセットアップする方法を整理しました。

# 参考
https://qiita.com/masakiwakabayashi/items/204ed2b32254bbc9a5c1

https://zenn.dev/c_shiraga/articles/056e7196b41c08

# 手順１　 Next.js プロジェクトの作成
まず、TypeScript対応の Next.js プロジェクトを作成します。

``` ターミナル上
npx create-next-app@latest --typescript
```

# 手順 2: 必要なパッケージをインストール
次に、Jest と React Testing Library、ts-jest などの必要なパッケージをインストールします。
``` bash
npm install --save-dev jest @testing-library/react @testing-library/jest-dom @testing-library/user-event @types/jest ts-jest ts-node jest-environment-jsdom
```

# 手順 3: Jest の設定を追加
プロジェクトのルートディレクトリに jest.config.ts ファイルを作成し、以下の設定を追加します。

```jest.config.ts
const nextJest = require('next/jest');

const createJestConfig = nextJest({
  dir: './', // Next.js プロジェクトのルートディレクトリ
});

const customJestConfig = {
  testEnvironment: 'jest-environment-jsdom', // jsdomを使ったブラウザ環境をシミュレート
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'], // カスタムマッチャーをセットアップ
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1', // エイリアスの設定
  },
  transform: {
    '^.+\\.(ts|tsx)$': 'ts-jest', // TypeScript ファイルを ts-jest で変換
  },
};

module.exports = createJestConfig(customJestConfig);
```

# 手順 4: カスタムマッチャーのセットアップ
jest.setup.ts ファイルを作成し、以下のコードを追加します。
```jest.setup.ts
import '@testing-library/jest-dom';
```

#手順 5: テストファイルの作成
テスト対象となるコンポーネントを作成します。例として、src/components/HelloWorld.tsx ファイルを作成します。
```HelloWorld.tsx
import React from 'react';

const HelloWorld: React.FC = () => {
  return (
    <div>
      <h1>Title</h1>
      <p>content</p>
    </div>
  );
};

export default HelloWorld;
```

次に、そのコンポーネントのテストファイルを作成します。src/components/HelloWorld.test.tsx ファイルに以下のコードを追加します。
```HelloWorld.test.tsx
import { render, screen } from '@testing-library/react';
import HelloWorld from './HelloWorld';
import '@testing-library/jest-dom';

describe('HelloWorld Component', () => {
  it('renders the title and content', () => {
    render(<HelloWorld />);
    const titleElement = screen.getByRole('heading', { level: 1 });
    expect(titleElement).toHaveTextContent('Title');

    const contentElement = screen.getByText('content');
    expect(contentElement).toBeInTheDocument();
  });
});
```

# 手順 6: package.json にテストスクリプトを追加
```package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test:watch": "jest --watchAll -env=jsdom --verbose"
  }
}
```

# 手順 7: テストの実行
テストを実行するには、以下のコマンドを使用します。
```terminal
npm run test:watch
```

これで、テストが自動的に実行され、リアルタイムで結果を確認できます。


# 終わりに
この記事では、Next.js + TypeScript プロジェクトに Jest と React Testing Library を導入してテスト環境を構築する方法を解説しました。これにより、プロジェクトのテストがよりスムーズに行えるようになります。ぜひご参考ください。
【AWS】EBSボリュームを削除する方法

## この記事の内容
AWSユーザ向けに、EBSボリュームの削除方法について紹介します。

## 時間がない方はこちら
AWSの公式サイトにもやり方が紹介されていますので、リンクを貼っておきます。

https://docs.aws.amazon.com/ja_jp/ebs/latest/userguide/ebs-deleting-volume.html

## きっかけ
あるとき、気まぐれにAWSのダッシュボードを確認したところ身に覚えのない請求が来ていることに気づきました。

▼請求管理ダッシュボード
![スクリーンショット 2024-09-29 17.36.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1071545/d1e1234e-8d36-6ea8-30d5-4c30b22c089f.png)

## EBSって何だ..？
私がAWSで使用しているサービスはEC2だけなのですが、そこにぶら下がる形でEBSというサービスから**USD 0.66**の請求が来ています。
EBSって何だ...？
少額ですが、身に覚えのない請求は怖いので調べてみました。

## EBSはストレージサービス
どうやらEBSとはAWSのストレージサービスのようです。
▼詳しく知りたい方はこちら

https://aws.amazon.com/jp/ebs/

私が使っていたEC2上の仮想マシンにEBSボリュームが割り当てられており、そこに発生した料金だったようです。
公式サイトによると、このEBSボリュームは**EC2インスタンスを立ち上げていなくても課金されてしまう**ものらしいです...！
> Amazon EBS では、アカウントにプロビジョニングされたストレージの量に対して、ギガバイト/月単位で課金されます。Amazon EC2 インスタンスは、稼働している場合にのみ料金が発生します。ただし、インスタンスにアタッチされた EBS ボリュームは、インスタンスが停止した場合でも引き続き情報を保持し、料金が発生します。詳細については、「Amazon EBS の料金」を参照してください。


## EBSボリュームを削除したい

理由がわかったところで、自分にはこのストレージを保持する必要がなく、ムダな出費なのですぐにでも課金を止めたいところです。
以下の手順でEBSボリュームを削除できました。

### 1. EC2ダッシュボードからボリューム一覧画面を表示する
▼EC2ダッシュボードのサイドメニューから、Elastic Block Store > ボリューム を選択
![スクリーンショット 2024-09-29 17.52.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1071545/69a5e8c0-3d24-34dc-a35d-e8c91c01d586.png)

### 2. ボリュームをデタッチする
該当のボリュームを選択し、「アクション」ボタン > 「ボリュームのデタッチ」を選択します。
（使っている画像は削除後のものなのでdisabledになってしまっています。すみません。。）
![スクリーンショット 2024-09-29 17.53.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1071545/538b3a3d-0b5a-84af-62c0-54f94b1030a2.png)

しばらくしてからリロードすると、デタッチが完了します。

### 3. ボリュームを削除する
ボリュームのデタッチが完了すると、「アクション」 > 「ボリュームの削除」が選択できるようになります。
ここからボリュームを削除すれば完了です！

## 最後に
おそらく、これでEBSの課金は止められるのではないかと思います。
最後まで読んでくださりありがとうございました。
【ネットワーク入門】DNSの仕組み

# DNSの概要

ブラウザにドメインを入力するとアプリにアクセスできる。そんなことは当たり前ですが、アプリケーションを動かしているサーバーなどは本来IPアドレスによって居場所が管理されているはずです。

それにも関わらず、ドメインを入力して目的のサーバーに到達できる仕組みがDNS(Domain Name System)です。

本記事ではDNSの仕組みについて解説してみたいと思います。


# DNSの仕組み
本記事では`taka_2525.com`というドメインが名前解決される例を取り扱っていきます(筆者のQiitaアカウント名から採用しました)。
`taka_2525.com`がブラウザに入力されてからIPアドレスが返却されるまでの大まかな流れが以下の図です。

![見出し (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576260/20feaf59-030e-d358-cbf4-552ee085d6fb.png)


## 第1章: DNSリゾルバ

まず、ブラウザにドメインが入力されたらDNSリゾルバにアクセスします。

DNSリゾルバの役割は、

- ここから色々なサーバーに問い合わせをして、目的のドメインのIPアドレスを取得する
- 取得したIPアドレスをクライアントに返却する
- 名前解決の結果をキャッシュする

です。

つまり、ブラウザがIPアドレスを探しにいくのではなく、DNSリゾルバがIPアドレスを探しにいってくれます。

ただし、DNSリゾルバにキャッシュがある場合は、IPアドレスを探しに行く過程をすっ飛ばしてブラウザにIPアドレスを返却します(上の図の②〜⑦がスキップされる)。

ここからIPアドレスを取得するための旅が始まります。

## 第2章: ルートサーバー

DNSリゾルバは、まず最初にルートサーバーに問い合わせます。ただし、ルートサーバー自身は`taka_2525.com`のIPアドレスを返却してくれません。なぜなら`taka_2525.com`の情報の保持を他のサーバーに委任しているからです。

ルートサーバーはcomの情報を委任しているサーバー(権威サーバー)の情報を返却してくれます。つまり「自分に聞かれてもわからないのでBさんに聞くといいよー」と教えてくれます。

## 第3章: TLDの権威サーバー

ルートサーバーに問い合わせたのち、次は`com`の権威サーバーへの問い合わせを行います。

このように、名前解決はドメインの右側から行われるのがポイントです。`com`や`jp`のように一番右側にある箇所をTLD(top level domain)と言います。また、それ以降の箇所は右から順に2LD(second level domain), 3LD(third level domain)...と呼ばれます。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576260/2b307ae8-7151-6150-e5d8-6fc94d87d3d6.png' width=300>


しかし、TLDの権威サーバーも目的のIPアドレスは返却してくれません。そのかわりに2LDの情報を教えてくれます。先ほどと同じように「自分に聞かれてもわからないのでCさんに聞くといいよー」と教えてくれるのです。

## 第4章: 2LDの権威サーバー

上記の流れでようやくtaka_2525の権威サーバーに到達しました。このサーバーは`taka_2525.com`のIPアドレスを持っているので、DNSリゾルバにIPアドレスを返却します。

今回の例では2LDまでの例でしたが、ドメインがもっと長い場合は3LD, 4LD…と問い合わせが続いていきます。

# 感想
DNSについてはぼんやりと理解してましたが、図に書いてみると整理されてより理解が深まりました。これだけの通信が一瞬の内に行われるなんてすごいですね。
docker-compose.yml の volumes によるマウントの挙動を確認

# 目的
[`docker cp`コマンド](https://qiita.com/ShiroatoHiro/items/4d30a7ebdd11ff51c89a)、[Dockerfile の `COPY`](https://qiita.com/ShiroatoHiro/items/d079cee47999b07522e8)に続いて、docker-compose.yml ファイルの volumes によるマウントの挙動を確認する。

# 結論
`docker cp`コマンド と違って、迷う個所はない。

## ディレクトリのマウント
ホストマシンの`./web/handler/`ディレクトリの**中身**が、ホストマシンの`/GoBackend/web/handler/`の**中身**と同期する。
```
services:
  web:
...(省略)
    volumes:
      - ./web/handler/:/GoBackend/web/handler/
```

## ファイルのマウント
ホストマシンの`./web/go.mod`ファイルと、コンテナの`/GoBackend/web/go.mod`ファイルが同期する。
※ コンテナ起動時に、マウントを開始するが、そのときにホストマシンに該当ファイルがないと、同名の空ディレクトリが作成されてしまうので注意。
```
services:
  web:
...(省略)
    volumes:
      - ./web/go.mod:/GoBackend/web/go.mod
```
Unity：メインカメラで見える視界を薄暗くするやり方

# はじめに
- Unityでいつもよく見える視界を少し薄暗くできないかと試行錯誤してみました
- Objectをメインカメラの目の前に設置し、そのObjectのシェーダを半透明のようにするスクリプトとすることで実現させています
# できること
- Unity上で見えるメインカメラの視界を薄暗くします
- 下のような薄暗いメインカメラになります
    - 薄暗くした場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310502/a88b0f81-3139-b0f9-501d-24c2e5c2d16e.png)
    - 通常の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310502/61a6288f-9850-83d4-1a74-55b00465de19.png)
- VRHMDなど360度見渡せるような環境においては未確認ですが、おそらく正面のみ(Objectのサイズ範囲のみ)半透明のように見えると思われます
- ３６０度半透明にする場合は、おそらく作成したObjectをメインカメラの正面だけでなく、後ろ、左右、上下と設置することで実現できるのではないかと思われます（メインカメラとの距離の調整が大変かもしれませんね…）


# 前提条件
- Unity 2022.3.3

# やり方
- Unityの新規プロジェクトを作成します
- Materialをassetファイルのどこでもよいので作成します
- Unityエディターで右クリック ＞ Create ＞ Shader ＞ UnlitShaderを選択します
- 作成したシェーダーに以下のコードで書き換えます
    ・サンプルとしてファイル名を「TransparentOverlay」としassetフォルダ直下に作成しました
    ```
    Shader "Custom/TransparentOverlay"
    {
        Properties
        {
            _Color("Color", Color) = (0,0,0,0.5)
        }
            SubShader
        {
            Tags {"Queue" = "Transparent" "RenderType" = "Transparent"}
            LOD 100

            CGPROGRAM
            #pragma surface surf Lambert alpha

            fixed4 _Color;

            struct Input
            {
                float2 uv_MainTex;
            };

            void surf(Input IN, inout SurfaceOutput o)
            {
                o.Albedo = _Color.rgb;
                o.Alpha = _Color.a;
            }
            ENDCG
        }
            FallBack "Diffuse"
    }    
    ```
- 新しく作成しておいたMaterialに上記で作成したシェーダーをアタッチします
    - シェーダファイルをMaterialのところでドラックアンドドロップします

- Materialを選択して、Inspectorから「Color」を選択して色や透明度を変更します
    - 今回は色を黒として、透明度を210として実施しました
    - この際に、hierarchyにQuadを追加して、作成したMaterialをアタッチする。そしてそのQuadをメインカメラの目の前(座標的には0.1だけずらすようにしておく)におくと色を変えたときに確認しやすくなります
kintoneでPDFを出力する

# 仕様の検討
kintoneのプラグインなどいろいろ探せば有償無償をふくむめてあると思いますが、今回はPDF-libを使う方法を試してみました。

# PDF-libを動かすための準備
kintoneの「アプリの設定」ー「JavaScript / CSSでカスタマイズ」にて以下のライブラリを登録します。
https://unpkg.com/pdf-lib
https://unpkg.com/@pdf-lib/fontkit/dist/fontkit.umd.js

こちらから日本語フォントをダウンロードしました。
http://jikasei.me/font/rounded-mgenplus/
今回はrounded-mgenplus-1m-regular.ttfを使用させていただきました。

テンプレートとなるPDFを準備します。
template.pdf

# テンプレートとなるPDFとフォントをbase64でエンコード
kintone上にPDFやフォントファイルを登録することが出来ないので、いろいろ考えた結果、base64に変換しJavascript内に埋め込むことにしました。以下のような感じで文字列にします。サイズの大きなファイルになるので注意します。base64への変換は別途自作のツールを作成しました。

```template.js
const pdf64 = 'JVBERi・・（省略）・・SVFT0Y=';
```

```font.js
const font64 = 'AAEAAA・・（省略）・・GSf9A=';
```

# Javascriptのサンプル
Javascriptからは以下のような感じで利用すればよさそうです。

```sample.js
const encodeBinaryString = binaryString => Uint8Array.from(
  binaryString,
  binaryChar => binaryChar.charCodeAt(0),
);
      
const pdfBytes = encodeBinaryString(atob(pdf64));
const pdf = await PDFLib.PDFDocument.load(pdfBytes);
    
pdf.registerFontkit(fontkit);
const font = await pdf.embedFont(encodeBinaryString(atob(font64)));

const pages = pdf.getPages();
const page = pages[0];

page.drawText('あいうえお', { font: font, size: 7, x: 512, y: 786.5 });

・・（省略）・・

window.open(URL.createObjectURL(new Blob([await pdf.save()], { type: 'application/pdf' })), 'pdf');
```

# kintone上の設定
![スクリーンショット 2024-09-29 175552.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576228/bde74cda-07f1-720b-b780-3a1eaeaf8308.png)


# 感想
base64で記述したPDFのテンプレートやフォントを読み込んで変換するのに多少の時間がかかりますが、無事に動作させることが出来ました。kintone以外のサーバーに別途テンプレートを配置してもよいのですが、クロスドメインになるため、CORSとbasic認証などの相性の関係で断念しました。テンプレートからPDFを作成できるといろいろ便利なので、これからキントーンを活用する場面が広がりそうです。
cookieとは

# cookieとは
>HTTPとはステートレスなプロトコルであるため、webブラウザとwebサーバーの一連のやりとりにおいて、状態を保持し管理する仕組みがありません。そのため、ショッピングサイトなどで状態を保持し管理する必要がある場合には`Cookieと呼ばれるデータ`が用いられます。

https://www.sbcr.jp/product/4797388817/

### ステートレスとは
>「サーバがクライアントのアプリケーション状態を保存しない」制約のこと

https://gihyo.jp/book/2010/978-4-7741-4204-3

# どうやって情報を受け渡すのか?
>Cookieの送信にはメッセージヘッダーが利用されます。Webサーバーは`httpレスポンスに「Set-Cookie」ヘッダーを含めることでCookieを送信`でき、Webブラウザは`httpリクエストに「Cookie」ヘッダーを含めることで送信`できます。

https://www.sbcr.jp/product/4797388817/

ヘッダーによって情報を移すのか

# Set-CookieやCookieはどのような情報を受け渡すのか？
### Set-Cookieとは
>Set-Cookie は HTTP のレスポンスヘッダーで、`サーバーからユーザーエージェントへクッキーを送信する`ために使用され、ユーザーエージェントはそれを後でサーバーに送り返すことができます。 複数のクッキーを送信するには、複数の Set-Cookie ヘッダーを同じレスポンスで送信してください。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Set-Cookie#:~:text=Set%2DCookie%20%E3%81%AF%20HTTP%20%E3%81%AE%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%81%A7%E3%80%81%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%8B%E3%82%89%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%81%B8%E3%82%AF%E3%83%83%E3%82%AD%E3%83%BC%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB%E4%BD%BF%E7%94%A8%E3%81%95%E3%82%8C%E3%80%81%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%81%AF%E3%81%9D%E3%82%8C%E3%82%92%E5%BE%8C%E3%81%A7%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AB%E9%80%81%E3%82%8A%E8%BF%94%E3%81%99%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82%20%E8%A4%87%E6%95%B0%E3%81%AE%E3%82%AF%E3%83%83%E3%82%AD%E3%83%BC%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%E3%80%81%E8%A4%87%E6%95%B0%E3%81%AE%20Set%2DCookie%20%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%82%92%E5%90%8C%E3%81%98%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9%E3%81%A7%E9%80%81%E4%BF%A1%E3%81%97%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82

### Cookieとは
>Cookie は HTTP のリクエストヘッダーで、以前`サーバーが Set-Cookie ヘッダーで送信し、保存された HTTP クッキーを含みます`。
>
>Cookie ヘッダーは任意であり、例えば、ブラウザーのプライバシー設定で`クッキーをブロックしている場合などは省略`できます。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cookie#:~:text=Cookie%20%E3%81%AF%20HTTP,%E7%9C%81%E7%95%A5%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82

# 感想
cookieはヘッダーを使ってサーバ、クライアント間でデータを取得する。
ヘッダーのパラメータ的なものも見つかった。これによって送る内容を設定できるようだ。
他にもセッションcookieというものがあるので調べてみたい。

これから理解できるだろう。

https://xtech.nikkei.com/it/members/NOS/TROUBLE/20020313/1/
【Discord.js】BOTのメッセージの送信時に「●●が入力中...」と表示する方法！

こんにちは、りょうです〜
先日病院行って脳のCT撮ったら思ったより高くてビビりました(ーー;)
では本題へれっつごー

## 入力中表示ってなんぞや
これですね。
一般ユーザーがメッセージ入力してるときに出てくるあれをBOTでもやろうぜって記事です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/11d80b9a-9dad-9fd3-e78b-425996de7c69.png)

## 表示させるためのコード
```typing.js
const { Events } = require('discord.js');

module.exports = {
    name: Events.MessageCreate,
    async execute(message) {
        if (message.author.bot) return;

        if (message.content === 'こんにちは') {
            await message.channel.sendTyping();

            setTimeout(() => {
                message.channel.send('こんにちは！');
            }, 3000);
        }
    }
};
```
discord.js v13,14で「●●が入力中...」を表示するためには **``channel.sendTyping()``** メソッドを使用します。
その後`setTimeout`で指定した時間待機(入力中を表示)してからメッセージを送信するようになっています。
ここではユーザーの「こんにちは」というメッセージを受け取ってから「入力中...」を2秒間表示した後、「こんにちは！」と送信するように設定しています。

v12までは`.stopTyping()`が必要でしたが、v13でなくなりました。

## まとめ
今回は送信時の入力中の表示方法の紹介でした。
AIを搭載した会話BOTなども増えてきているのでこういう機能はいいと思いますね〜
今回は短いですがこれで終わりです()

わからないことあったら書いてくれれば答えていきます。

**Discordにいる荒らしの情報や対策方法の共有をしている自鯖です**
ぜひ参加お願いします↓↓↓↓

https://discord.com/invite/ESRGwGQhxc
確率の偏りは存在するのか？（ポーカー、コイントス、ジャンケン）

## はじめに
私はポーカーが好きで「ポーカーチェイス」というゲームをよくやるのだが、良いハンド（手札）が続くときや、逆に悪いハンドが続くときがよくある。
シャッフルしたトランプカードが配られているので、恣意性は全くないはず。
では、私の感じたことは勘違いなのだろうか…検証してみよう。

## シンプルにしてみる
シャッフルしたカードが配られるということは、つまり、ランダムであるということ。
スート（スペード等の柄のこと）を排除すると、ランダムに発生する数字に偏りが出るかが論点となる。
この類のゲームで最もシンプルなのはコイントスだ。
表を「0」、裏を「1」と捉えれば似ていることが分かるだろう。

## 検証用のプログラム
実際にコイントスを何千回もやるわけにはいかないので、検証用のプログラム（Python）を作成した。
自分で試してみたいという人のために掲載しておくが、内容が分からなくても問題はないので、興味がない人は読み飛ばしてほしい。

```python
import random
from collections import Counter

# 変数を定義
choices = ["表", "裏"]
trial_count = 100
random_nums = []
msg = ""
digit = len(str(trial_count))
result = None

# n個のランダムな数値を取得(シミュレーションを実施)
random_nums = [random.randint(0, len(choices) - 1) for _ in range(trial_count)]

# シミュレーション過程を表示
for i, num in enumerate(random_nums):
    count = i + 1
    msg += f"{count:>{digit}}: {choices[num]}"

    if count % 10 == 0:
        print(msg)
        msg = ""
        continue

    msg += ", "

# シミュレーション結果を集計
result = Counter(random_nums)
print("-" * 50)

# シミュレーション結果を表示
for i in range(len(choices)):
    count = result[i]
    per = count / trial_count * 100

    # パーセンテージは小数点第3位で四捨五入
    print(f"{choices[i]}: {count:>{digit}}回, {per:.2f}%")
```

## 検証結果（コイントス）
いくつかのバリエーション（n回コイントスを試行×10セット）を用意してみた。
ちなみに、コイントスで表が出る理論上の割合は50%である。

![コイントスの検証結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675088/714d8532-342c-6441-a72e-3426b2004a17.jpeg)

試行回数が少なすぎると極端に偏りが出る。6回連続で表が出るとか…（試行回数6回・2セット目）
試行回数10回ではかなり偏りがあり（min 20% ~ max 80%）、試行回数50回でもまだ偏っている（min 34% ~ max 56%）。
試行回数100回でややバランスが取れてきており（min 44% ~ max 57%）、試行回数1,000回で安定してきている印象を受ける。
試行回数10,000回以上になると割合にほとんど差がない（min 49.59% ~ max 51.2%）

## 選択肢を増やしてみる
コイントスの場合は2択であったが、ジャンケンの場合はどうなるだろうか。
コイントスのときと同じく、グーを「0」、チョキを「1」、パーを「2」として同類のゲームと捉えて検証してみる。
検証用のプログラムは同じものを使用し、選択肢のみ変更する。

```python
choices = ["グー", "チョキ", "パー"]
```

## 検証結果（ジャンケン）
こちらも同じバリエーションを用意した。
なお、シンプルにするため、人の意志は入っていないジャンケンと仮定して検証を行う。
ジャンケンで相手がグーを出す理論上の割合は約33.33%である。

![ジャンケンの検証結果.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675088/da6f3b6e-f875-ea1b-3ef1-2f6f282cf9a9.jpeg)

やや分かりづらいので、次で深堀りする。

## 検証結果を比較してみる
両者を比較するため、まずは割合から標準偏差を計算する。
標準偏差とは、データが平均値からどれくらい離れているかを表す数値である（0に近づくほど偏りが少ない）。
なお、標準偏差の計算については、プログラムを作成するよりもChatGPTを使った方が早い。

### コイントスの標準偏差
理論上の平均値50%からどれくらい離れているか。
- 試行回数6回の場合：約22.36
- 試行回数10回の場合：約16.12
- 試行回数50回の場合：約7.46
- 試行回数100回の場合：約5.01
- 試行回数1,000回の場合：約2.35
- 試行回数10,000回の場合：約0.55
- 試行回数100,000回の場合：約0.27

### ジャンケンの標準偏差
理論上の平均値33.33%(1/3)からどれくらい離れているか。
- 試行回数6回の場合：約19.00
- 試行回数10回の場合：約15.63
- 試行回数50回の場合：約7.71
- 試行回数100回の場合：約4.84
- 試行回数1,000回の場合：約1.68
- 試行回数10,000回の場合：約0.45
- 試行回数100,000回の場合：約0.15

どちらの結果もそこまで大きく変わらない印象を受ける。
試行回数1,000回以上で安定しているので、偏りがなくなるまでにはかなりの回数が必要だということが分かる。
ラッキーが重なることもあれば、逆も然りであり、長い目で見れば理論上の平均値に収束する。

## 結論
選択肢が増えたとしても、標準偏差（確率の偏り）の遷移にそこまで大きな差はなかった。
いずれの場合も、試行回数が少ない（〜50回）と結果にかなりの偏りがあり、結果が安定するまでに1,000回程度の試行が必要あることが分かった。
さらに、理論上の平均値（割合）に収束するためには10,000回もの試行が必要であることも分かった。
ポーカーの場合は選択肢（カード枚数）が多いとはいえ、根本的な部分は共通しているので、良いハンド（悪いハンド）が続くことは充分にあり得る。
ただし、前述のとおり長期的には理論上の平均値に収束するので、良いハンドが続いたときは大きくベットし、悪いハンドが続いたときは焦る気持ちを抑えてフォールドすることが重要になってくると考える（ブラフベットについては今回の論点から逸れるので言及しない）。

最後まで読んでくださって、ありがとうございます。
面白いと思った方は、下にある「いいね」ボタンのタップをお願いします。
JobSystemと、UpdateAfter等で決められる優先順位



メモとして残します。

[UpdateBefore(typeof(SystemB))] や [UpdateAfter(typeof(SystemB))] などの属性は システムの実行順序 を定義するためのものです。一方で、JobHandle や Dependency は ジョブの実行順序 を定義するために使用されます。

優先順位について
システムの実行順序 ([UpdateBefore] / [UpdateAfter]) は、各システムが実行される順番を決定します。システム自体の実行順序を保証するために役立ちますが、それぞれのシステムの中でスケジュールされるジョブに関しては、これだけでは制御できません。

ジョブの依存関係 (JobHandle や Dependency) は、実際にジョブが実行される順番を制御します。システムがジョブをスケジュールした後、ジョブがいつ実行されるか（あるジョブが他のジョブの完了を待つかどうか）は、JobHandle や Dependency によって管理されます。

具体的な流れ
[UpdateBefore] / [UpdateAfter] によってシステムの実行順序が決定されますが、そのシステム内でスケジュールされたジョブの実行順序は、JobHandle や Dependency によってさらに細かく管理されます。

もし、SystemA が SystemB よりも後に実行されると定義されていたとしても、SystemB 内のジョブが SystemA のジョブに依存するように JobHandle が設定されている場合、SystemB のジョブは SystemA のジョブが完了するまで実行されません。逆に言えば、JobHandle で依存関係が定義されている場合、その依存関係が優先されます。

まとめ
システム実行順序 は [UpdateBefore] や [UpdateAfter] によって制御されますが、これはあくまでシステムがジョブをスケジュールする順序です。
ジョブ実行順序 は JobHandle と Dependency によって制御され、これが最終的にジョブがいつ実行されるかを決定します。
結果として、ジョブの依存関係 (JobHandle や Dependency) の方が実行順序の優先度が高いということになります。
Java JDKインストール Ubuntu

JDKをUbuntuへのインストール方法を共有いたします。
環境：Apple M1 computer

cat /etc/os-relase
PRETTY_NAME="Ubuntu 24.04.1 LTS"

システムを更新する。
$ sudo apt update

JDKバージョンを確認する。
$ apt-cache search openjdk

openjdk-17-jdk, openjdk-8-jdk, openjdk-21-jdkがありますけれど、21を選ぶ。

$ sudo apt install -y openjdk-21-jdk
OpenJDK version "21.0.4" 2024-07-16
OpenJDK Runtime Environment 
OpenJDK 64-bit Server VM

$ javac -version
javac 21.0.4

テスト用のJavaコード
$ cat Hello.java
public class Hello{
    public static void main(String[] args){
        System.out.println("Hello");
    }
}

$ javac Hello.java
$ java Hello
Hello

$ which java
/usr/bin/java

インストール完了
vimの操作方法

Vimは基本的に覚えていないと、操作に苦労します。
整理するために、覚えておきたいと思ったvimの操作方法をまとめます。

# まず覚えるもの
## モードについて
ノーマルモードと編集モードがあることを理解する
1. ノーマルモード
    1. コマンドなどを使って効率的にエディターの操作を行うモード
1. 挿入モード
    1. 一般的なエディターのようにテキストの編集を行うモード
### エディタのモード切り替え方法

| モード | 切り替え方 |
|---|---|
| ノーマルモード | Esc |
| 挿入モード | i |

## Vimの基本カーソル移動
| コマンド | 移動先 |
|---|---|
| j | 下へ1行 |
| k | 上へ1行 |
| h | 左へ1文字 |
| l | 右へ1文字 |
| gg | ファイルの先頭 |
| G | ファイルの末尾 |
| :行番号 | 指定行の先頭 (例: :5) |
| 行番号G | 指定行の先頭 (例: 5G) |
| ^ | 行の先頭 |
| $ | 行の末尾 |

## 編集編
| コマンド | 操作 |
|---|---|
| dd | 行削除 |
| D | カーソルから行末まで削除 |
| yy | 行コピー |
| p | 次の行にペースト |
| P | 前の行にペースト |
| u | 元に戻す |
| Ctrl+r | やり直す |

## 検索編
/文字列で文字列検索が可能です。nで次のワードに移ります。

## 設定編
下記を.vimrcに書いておくと少し快適になります。
- :set nu
    - 行番号の表示
- :set ic
    - 大文字小文字を区別しないで検索
- :set is
    - インクリメンタルサーチを有効化
- :set showmode
    - 通常モードか挿入モードかがわかる