OmniAICreator/Qiita-1.07M huggingface dataset:
[Unity]Material doesn’t have a texture property ‘_MainTex'

# 概要
2D用のShaderGraphを作成して色々編集していたらタイトルのエラーが出るようになり、かなり解決に手こずりました。
どうやって解決したのかを共有したいと思います。
# 本文
Textureを扱ってなくてもどうやらこのエラーは出る様子でした。ShaderGraphのプロパティにTexture2Dを追加して、Referenceに'_MainTex'と入力します。（忘れずに左上のSave Assetを押して変更を保存してください）

![スクリーンショット 2024-06-14 0.55.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/bbd8f18f-a786-8f88-5a52-a808f8462eab.png)

余分なプロパティが一つ増えてしまいますが、これでエラーは発生しなくなりました。

# 補足
ちなみに、この修正で一度エラーが出なくなった後、修正前の状態に戻してもエラーが出なくなっていました。Unityのバグでしょうか・・・？謎です

[参考にした記事](https://discussions.unity.com/t/material-doesnt-have-a-texture-property-_maintex/16343)

:::note info
もしかしたらUnityを再起動するだけでも直るかもしれないです。
:::
Cloud Shell Editor上でプレビューできなくて困った（Streamlit）

# 困ったこと
Google CloudのCloud Shell Editor上で、Streamlitを起動してプレビューしようとしたら、ふにゃふにゃ（スケルトン）になって表示されず焦りました。

![スクリーンショット 2024-06-14 003649.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68673/a586ef6a-68a6-7ce6-ccb7-0edfd3fe31d8.png)

# 解決策
CORSをオフにすることです。

すなわち、Streamlitの起動オプションに、
```
--server.enableCORS=false
```
をつければ良いです。

詳細は、[本家のドキュメント](https://docs.streamlit.io/knowledge-base/deploy/remote-start)のSymptom #2を参考にしてください。

# （記録用）解決までの道のり
味気ないので記録として、残させてください。

## 状況
Cloud Shell Editorの中で環境は作り終え、次のように起動しました。
```
streamlit hello --server.port 8080 
```

8080ポートをCloud Shell Editorではプレビューにデフォルトで対応していたから指定しています。

すると、スケルトンの要素がうにゃうにゃと、蠢くのみ。。。


## 観察
なぜだめなのか？ブラウザの検証で状況を把握しようとしました。

すると、ソースには
```
You need to enable JavaScript to run this app.
```
の文字が。

## 検索 と 実践
このまま検索すると、Streamlitのコミュニティ投稿に当たるも、ピンポイントのものは見つからなかった。
下の方に、公式ドキュメントのページがあるのを見つけ、これがヒット。

とりあえず上から試してみて、
```
# Symptom #1: The app never loads
python -m http.server 8080
```
これはOK。だが、解決ではない。

次、
```
# Symptom #2: The app says "Please wait..." or shows skeleton elements forever
streamlit run app.py --server.port 8080 --server.enableCORS=false
```
ヒット！
あと、そこで初めて、あの”うにょうにょ”がskelton elementsと呼ばれていることを知る。（今日イチの学び）

---
こうして、Cloud Shell EditorがStreamlitの勉強に使えるとわかってホッとしました。Cloud Shell Editorには週50時間という上限があるので、この数字が与える影響次第では、Cloud9でも使っちゃおうかな～と思っています。
【2024マラソン01】マラソンは走りだすのが一番難しい

リンクを整えたり、記事タイトルを直せば公開OK

# これは何？
[Qiita Engineer Festa 2024](https://qiita.com/official-campaigns/engineer-festa/2024) に参加することにしました。
この記事は1個目の記事で、これから書いていこうと思った予定などを書いています。

# あらすじ
昨年冬、一人だけアドカレを完走しました。
その時とてもアウトプット力が鍛えられたので、夏のこの企画も参加してみようと思いました。
あとは、**にっこりQiitanぬいぐるみが長女に大変好評だったので、通常verが入手できたら
次女と一緒にQiitanで楽しく遊んでくれるかな……と。**
~~前回25記事書ききったんだから38記事もいけるやろ。~~
早速出遅れてしまったものの、ゆるゆるとアウトプットしていければと思います。

# 自己紹介
地方中小企業の総務課のヒトです。
何年か先、グループ統合をしたり、システム課を作るかもという話があるので、
その時にそっちの椅子が割り振られるように頑張らないとなぁー……と思っています。

趣味では色んな創作を触ってみるタイプです。
最近はメタバースのひとつ、clusterに出入りするようになった為、
3Dモデリングやアバター作成、3Dアイテムの販売などの創作をはじめました。

我流ではありますが、自分の好きな事を好きなように表現できて受け止めてもらえる。そんなメタバースの良さに助けられて、いろいろなものを作ることができています。
そこでの経験や、創作活動についても書いていこうと思います。

また、幸運なことに抽選キャンペーンでquest2が当選したため、4月からVRゴーグルを使っています。
3Dモデリングや、VRでの作業環境などについても触れられればと思います。

# 最近やってること
相変わらず、仕事では経理・総務事務がメインです。
力技手入力が残っている仕事の効率化が期待されている業務内容になります。
このあたり、通常業務こなしながら子関連の休みも入ると厳しいんですが？……となってますが、
少しずつ効率化が進めばこれ以上の人出はいらんので、現状は力技業務改善を進めています。

# マラソンではなにを書くの？
仕事のことはそこそこに、最近入手したVRツールや、メタバースのことを書いていこうと思います。
予定は下記。

- cluster公式ツールでアクセサリを作った話
- clusterのアクセサリ画像について
- clusterで自作アバターを作った話
- clusterで動かせるアバターの種類
- もくりがさ終してからの作業スペースについて
- メタクエスト2が当選してからのムーブ
- clusterイベントの感想アウトプットについて
- YouTubeとREALITY、clusterの比較
- REALITYの距離感
- YouTubeの距離感
- clusterのライブ感
- クリスタのアニメーション機能を使った差分作成について
- クリスタのオートアクション自作2
- クリスタで、スマホとiPadで競合しつつ作成する方法
- かな入力奮闘記
- 左手テンキーのススメ
- HHKBの現時点での運指
- immersed接続奮闘記
- immersedでできること
- ビートセイバーmod奮闘記
- GRAVITY sketch制作記
- 生成AIの行末と、現行の気になること
- メタバース出社ができたらいいのに！
- PC VRをやりたい！
- バックオフィスエンジニア
- vimのよく使うコマンド
- ノーコード開発を利用するにあたっての注意点
- 現実から作るコード表
- 占われてみて_自分の得意な流れに乗せるということ
- 浮遊アバターの高さやサイズ調整について
- 汚部屋対策奮闘記
- 子との関わり色々
- cluster ワールド制作
- my vketワールド制作

内容を並べてみると、Qiitaよりもnoteで触れられていることが多そうなジャンルに思えます。
でも、今回はQiitaで書くことに決めました。

Qiitaで書く利点として、
- 読んでいる記事の目次が常に確認できるので、記事の読みたい箇所だけをつまみ食いしやすい
- 技術や知見共有をする記事が多いため、1記事毎に完璧に書かなくても公開しやすい
- マラソンといういイベントによって、無理ないペースでアウトプットできる
……という点がnoteよりも書きやすいと感じた為です。

# 結局誰向け？
メタバースやVRのことについて、広く話していこうと思います。

- VRのことやメタバースのことに興味のある方
- VRモデリングや3Dモデリングを触ってみたい方
- VRゴーグルでの作業環境に興味がある方
- ゲーミングPCはないけど、VRゴーグル単騎でVRする環境がある方/用意する予定の方
- 人の作業環境に興味がある方


# おわりに
……アドカレと違って、開幕宣言をする雰囲気じゃなさそうかな？
何も考えず単発技術記事を上げていく方がいいか？……と思いましたが
あえてオープニング記事を書くことにしました。

この記事を書くことによって、
- 目次に書いたことを書かねばとやる気が出る
- 書いていく宣言をしたことで、あとにひけない雰囲気を作る
- 何を書こうと思ったんだっけ？……をなくせる
- マラソンバッジが1つ付くことによって、執筆モチベーションがあがる
- 以降、どれだけ小さな技術記事であってもこの記事よりも有用な情報量が上と思って書ける

──といったメリットがあると考えたためです。

そんなわけで、記事内容はごった煮ですが、
興味のあるお話がありましたら、ぜひお読みいただけると嬉しいです。

ここまでお読みいただきありがとうございました m(_ _m
Go&echoで簡単にAPI作成

作るものは「最低限必要なものを揃えたmain.go」のみ。
ゴールは「local起動し、ブラウザから確認」＆「curlコマンドからAPIを叩けること」です。

## フォルダ構成

めちゃ簡素。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821214/9b373c54-dc1c-34f2-c4ae-9f0cde3afd5a.png)

つくりかた
1. main.go ファイルを作成
1. `go mod init` を実行、 go.mod, go.sum ファイルが生成される

以上！

## main.go の中身
[こちらの記事](https://zenn.dev/def_yuisato/articles/echo-get-started)を参考にそのまま使わせていただきました。
今回はファイル名だけserver.go → main.goとしています。
ミドルウェアについて、それぞれ
```
	e.Use(middleware.Logger())  // ここからlogが取得できる
	e.Use(middleware.Recover()) // サーバが落ちたとき、自動で再起動する
```
という意味らしいです。

## 実行
`go run main.go` で実行

ターミナルが以下のような表示になっていればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821214/d67bc18a-c18e-dbc3-b98e-e9e7a8cbcdbf.png)

#### ～APIが叩けるか確認～

**１．ブラウザから確認**

ブラウザを開き、URLに`http://localhost:1323/`と入力。
Hello,World！と返されていればOK。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821214/a0d76782-18da-d8ff-27fa-2dcd1d34a50b.png)


**２．ターミナルから確認**

別ターミナルを開き、`curl http://localhost:1323/`を実行。

> Hello, World!

と返されていればOK。

また、Hello,World！が返された後に
`go run main.go`を実行したターミナルを見ると
> {"time":"2024-06-14T00:38:55.64143254+09:00","id":"","remote_ip":"127.0.0.1","host":"localhost:1323","method":"GET","uri":"/","user_agent":"curl/7.81.0","status":200,"error":"","latency":5499,"latency_human":"5.499µs","bytes_in":0,"bytes_out":13}

（見やすくすると↓）

>{
    "time":"2024-06-14T00:38:55.64143254+09:00",  
    "id":"",
    "remote_ip":"127.0.0.1",
    "host":"localhost:1323",
    "method":"GET",
    "uri":"/",
    "user_agent":"curl/7.81.0",
    "status":200,
    "error":"",
    "latency":5499,
    "latency_human":"5.499µs",
    "bytes_in":0,
    "bytes_out":13
}

という文字があります。
これがmain.goの
```
e.Use(middleware.Logger())  // ここからlogが取得できる
```
によって吐き出されている部分です。

## 補足

ログを絞る（カスタムする）方法。
main.goにある

```
	e.Use(middleware.Logger())  // ここからlogが取得できる
```
を↓に置き換えます。
```
	e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    	Format: `[${time_rfc3339}] ${method} ${uri} ${status}\n`,
	}))
```
この状態で`go run main.go`を実行し、
別ターミナルを開き`curl http://localhost:1323/`を実行します。
`go run main.go`を実行したターミナルに戻ると、

> [2024-06-14T00:45:52+09:00] GET / 200 \n

というログが確認できます。
元のログが↓だったので、大分スッキリ表示できました。
>{
    "time":"2024-06-14T00:38:55.64143254+09:00",  
    "id":"",
    "remote_ip":"127.0.0.1",
    "host":"localhost:1323",
    "method":"GET",
    "uri":"/",
    "user_agent":"curl/7.81.0",
    "status":200,
    "error":"",
    "latency":5499,
    "latency_human":"5.499µs",
    "bytes_in":0,
    "bytes_out":13
}

## 参考
[【Go】echoを使ってAPIサーバーを3分で構築してみる](https://zenn.dev/def_yuisato/articles/echo-get-started#%E5%AE%9F%E8%A3%85)
HHKB Studioを使い始めてから重宝しているショートカットキー一覧

## 背景
マウスを使わなくなり、手を動かす手間がなくなったことでかなり快適になったが、
ポインティングスティックでの操作を少し不便に感じていた。
スティックの速度調整が可能だが、個人的にはマウスのほうが使いやすい。

## 使用頻度と使用用途
ほぼ毎日。
コードを書いたり、Slackを返したり、調べ物をしたり。

## HHKBのキーマップ設定
デフォルトの状態。

## 一覧
- タブを閉じるとき
    - `Command + w`
- 新規タブを開くとき
    - `Command + t`
- URLを修正したいとき
    - `Command + l`
- タブを複製したいとき
    - `Command + l → Command + Enter`
- タブの切り替え
    - `Command + 数字(左から数えたタブの位置）`
- ブラウザの進む・戻る
    - `Command + ]`
    - `Command + [`

## ショートカットキーを意識し始めて良かったこと
- キーボードから手が離れなくなり、作業に集中できるようになった。
- タブを開き過ぎないようになり、閲覧したいタブを探す手間が減った。
    - 開きすぎると、ショートカットキーでの切り替えが大変になる。
- マウスでの操作を、キーボードで補完できないか意識するようになった。
djangoでMIME type ('text/html') is not executable, and strict MIME type checking is enabled.が出た

# はじめに

djangoをdockerで立ち上げて開発していた時に
![スクリーンショット 2024-06-14 0.05.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/f4533da0-94d6-6b76-08c6-abcf0e86983c.png)

というエラーが出てしまいました。
これはjavascriptのファイルが、本来`text/javascript`と処理されて欲しいのに`text/HTML`と処理されてしまい。適切なMIMEタイプで処理できていないというエラーでした。

>MIMEとは
`Multippurpose Internet Mail Extensions`の略。HTMLや画像ファイルを送る際を送受信する際の標準規格である。
# 対処法
`whitenoise`をインストールして、`setting.py`に

```setting.py
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',#redisサーバー使ってるので必要
]
```
追加したら解決しました。

`whitenoise`は、静的ファイルを適切に処理するためのライブラリで、本番環境等でうまく処理されない静的ファイルを処理できるようにするために使用します。

開発環境であれば、本来ならないはずなのですが、今回はdockerでredisサーバーを使っていたのでそこで適切に静的ファイルが処理できていなかったのが原因かなと考えています(もし違ってたら教えてください）

困ったら参考にしてください。
proxmoxの非特権LXC内でGPU(Nvidia)を認識させる備忘録

# 注意事項
- proxmoxのバージョンは8.2.2
- ホストとLXC内のnvidia-driverバージョンは合わせる

# モチベーション
- 複数の非特権LXCでGPUを共有したい
- VMにGPUパススルーする方法では、vGPUを使わないと複数のコンテナでGPUが共有できない
- vGPUは一般のコンシューマGPU非対応(RTXシリーズなど)

# ホストの初期設定手順
```bash
# /etc/apt/sources.list にproxmoxのベースとなっているDebian 12のリポジトリを追加
[+] deb http://deb.debian.org/debian/ bookworm main contrib non-free non-free-firmware
[+] deb-src http://deb.debian.org/debian/ bookworm main contrib non-free non-free-firmware

## buildツールをインストール
apt update
apt upgrade
apt install pve-headers pve-headers-$(uname -r) build-essential

# nvidia driver インストール
wget {Nvidia-Driver_download_URL}
chmod -x ./NVIDIA-Linux-x86_64-{version}.run
./NVIDIA-Linux-x86_64-{version}.run

# /etc/modules-load.d/modules.conf に以下のに行を追加
[+] nvidia
[+] nvidia_uvm

update-initramfs -u

# 確認
nvidia-smi

# 非特権コンテナからアクセスできるようにする
# /etc/udev/rules.d/70-nvidia.rules に以下の行を追加
[+] KERNEL=="nvidia", RUN+="/bin/bash -c '/usr/bin/nvidia-smi -L && /bin/chmod 666 /dev/nvidia*'"
[+] KERNEL=="nvidia_uvm", RUN+="/bin/bash -c '/usr/bin/nvidia-modprobe -c0 -u && /bin/chmod 0666 /dev/nvidia-uvm*'"
```

# LXCを作成するたびに実施する手順
```bash
modprobe nvidia-uvm
ls /dev/nvidia* -l
# 以下の内容が表示
# crw-rw-rw- 1 root root 195,   0 Jun 13 23:10 /dev/nvidia0
# crw-rw-rw- 1 root root 195, 255 Jun 13 23:10 /dev/nvidiactl
# crw-rw-rw- 1 root root 508,   0 Jun 13 23:10 /dev/nvidia-uvm
# crw-rw-rw- 1 root root 508,   1 Jun 13 23:10 /dev/nvidia-uvm-tools
# /dev/nvidia-caps:
# total 0
# cr-------- 1 root root 511, 1 Jun 13 23:10 nvidia-cap1
# cr--r--r-- 1 root root 511, 2 Jun 13 23:10 nvidia-cap2

# /etc/pve/lxc/<lxc_id>.conf に以下の内容を追記
# <number from previous step>には上記の数値を入力（この例では、195, 508, 511の3つ）
[+] lxc.cgroup.devices.allow: c <number from previous step>:* rwm
[+] lxc.cgroup.devices.allow: c <number from previous step>:* rwm
[+] lxc.cgroup.devices.allow: c <number from previous step>:* rwm
[+] lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
[+] lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
[+] lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file
[+] lxc.mount.entry: /dev/nvidia-modeset dev/nvidia-modeset none bind,optional,create=file
[+] lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-uvm-tools none bind,optional,create=file
[+] lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-caps/nvidia-cap1 none bind,optional,create=file
[+] lxc.mount.entry: /dev/nvidia-uvm-tools dev/nvidia-caps/nvidia-cap2 none bind,optional,create=file
```

# コンテナ内での作業(今回はUbuntu22.04を使用)
```
# Nvidia-Driverをインストール
sudo apt update
sudo apt upgrade
sudo apt install  build-essential
wget {Nvidia-Driver_download_URL}
chmod -x ./NVIDIA-Linux-x86_64-{version}.run
bash ./NVIDIA-Linux-x86_64-{version}.run --no-kernel-module
# 再起動
# 確認
nvidia-smi
```

# 参考記事
- https://gist.github.com/egg82/90164a31db6b71d36fa4f4056bbee2eb
- https://kwatanabe.hatenablog.jp/entry/2020/10/04/202409
【Javascript】4種類の関数の宣言方法 

最近になってJavascriptを書くようになってきたので、そのメモとして。

* 関数宣言
```
 function tax(price) {
 	return Math.trunc(price * 1.1);
 }
```
おなじみ`function`による関数宣言。いつも使ってるのはこれ。
`price`を引数として`Math.trunc`のオブジェトとメソッドで処理をかけて、return文で戻り値を返すという具合。
どこからでも呼び出すことが可能で、スコープも明確。安牌を取るならこれ。

* 関数式
```
 const tax = function(price) {
 	return Math.trunc(price * 1.1)
 }
 ```
`const`による変数宣言での関数の構築。
動作としては`funciton`の関数宣言が無名で行っているが、`const`で宣言した`tax`を代入している。
変数のスコープに限定されているため、`const`で宣言した後じゃないと機能しない。
あと`var`や`let`で変数宣言しないこと。絶対意図しない再宣言が発生するので。

* アロー関数
```
 const tax => (price) => {
 	return Math.trunc(price * 1.1);
 }
 ```
関数の宣言をアロー記号で行うといった具合。
`function`での関数宣言とアロー関数宣言では動作が異なってくるオブジェクトが多数存在する。これについてはまたの機会に調べようと思う。

* 簡易アロー関数
```
 const tax =　price => Math.trunc(price * 1.1);
 ```
return文無しで戻り値を書けるのが便利。
引数とブロック構文が括弧の無い単一なら、この書き方が便利だと思えた。

`function`での関数宣言しかやったことと簡易アロー関数の存在自体知らなかったので、今後のためのメモとして。
でもやっぱり`function`の方がリーダブルになりそう。
あと消費税10%はクソ。
LeetCode挑戦日記：Day7

# はじめに

最近、業務で実装する時間よりも資料作成やレビューをする時間が多くなってきました。
このままでは自身のコーディング能力が落ちそうで怖いので、LeetCodeを始めてみました。

自身の学習の記録 & LeetCodeに興味のある人が挑戦しやすいように、記事に残していきます。
このような競技プログラミングをした経験がないので、ひよってEasyからやっていきます...

# [Medium] 238. Product of Array Except Self

インプット：数値の配列
アウトプット：数値の配列
制約：O(n)

インプットの配列の自要素を除く全ての要素の積をアウトプットとして返す。

## NG例：O(n)制約を無視して実装

### 考え方

1. アウトプットの配列の各要素毎に、インプットの配列の自要素以外の積を入れる

### コーディング

```typescript
function productExceptSelf(nums: number[]): number[] {
    return nums.map((num, index, array) => {
        return array.reduce((accumulator, currentValue, currentIndex) => (index === currentIndex) ? accumulator : accumulator * currentValue, 1);
    });
};
```

### 結果

Time Limit Exceeded

## O(n)制約を踏まえて実装を修正する

### 考え方

* 先にインプットの配列の全ての要素の積を計算しておき、アウトプットの配列を作るときにインプットの配列のその要素だけ除算する
* ただし、0を含むときはこの方法で計算できないため、先に0がある場合の考慮をしておく必要がある
    * 0が1つだけある場合は、0の要素以外は0になる
    * 0が2つ以上ある場合は、全ての要素は0になる

### コーディング

```typescript
function productExceptSelf(nums: number[]): number[] {
    const zeroIndexes = nums.reduce((accumulator, currentValue, currentIndex) => {
        if (currentValue === 0) {
            return [...accumulator, currentIndex];
        } else {
            return accumulator;
        }
    }, []);

    const zeroCount = zeroIndexes.length;
    if (zeroCount === 0) {
        const product = nums.reduce((accumulator, currentValue) => accumulator * currentValue);
        const result = nums.map((num) => product / num);
        return result;
    } else if (zeroCount === 1) {
        const result: number[] = new Array(nums.length);
        result.fill(0);
        result[zeroIndexes[0]] = nums.reduce((accumulator, currentValue, currentIndex) => (zeroIndexes[0] === currentIndex) ? accumulator : accumulator * currentValue, 1);
        return result;
    } else {
        return new Array(nums.length).fill(0);
    }
};
```

### 結果

Runtime：90ms
Beats 94.75% of users with TypeScript

Memory：66.01MB
Beats 44.46% of users with TypeScript

## 他の人の解法

### 考え方

* 自要素までの全要素の積と自要素の後の全要素の積をそれぞれ計算し、それらの積をアウトプットの要素としている
* 0であるときの条件分岐がなく、見通し安いコード

### コーディング

```typescript
function productExceptSelf(nums: number[]): number[] {
    const result: number[] = []
    let rightProd = 1
    let leftProd = 1
    for (let i = 0; i < nums.length; i++) {
        result[i] = leftProd
        leftProd *= nums[i]
    }
    for (let i = nums.length - 1; i >= 0 ; i--) {
        result[i] *= rightProd
        rightProd *= nums[i]
    }
    return result
};
```
【新入社員必見】【脱マウス】PowerShellの活用事例➀～フォルダのツリー表示～

# 概要
前回の記事で脱マウスに欠かせない、コマンドプロンプトの後継アプリ、『PowerShell』について、御紹介いたしました。
勿論、PowerShellはアプリを起動したりするだけではありません。
今回はその活用事例を紹介していきましょう。

# 【活用事例➀】フォルダのツリー表示
PowerShellを使えば、簡単にカレントディレクトリ配下をツリー表示してくれます。
```
tree
```
実行結果は以下のような形です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/575cf60e-9cd1-29da-6615-7def83a0570e.png)

勿論ファイル出力も可能です。
```
tree >> treeDir.txt
```
上記のようにコマンドを打つと、下記の通りファイルに出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/0c36072f-2d61-19ea-80a9-c541dae0a673.png)

:::note alert
<strong>注意！！</strong>
ちなみにファイル出力には種類がありますので、注意しましょう。
　★ファイルに追記
　　tree >> treeDir.txt
　★ファイルに上書き
　　tree > treeDir.txt
:::

# 【活用事例➁】フォルダ内容の一覧表示
仕事をしているとサブフォルダを含め、フォルダ内を一覧表示したいことがあります。
そんなときもPowerShellを使うのがオススメです。

## ディレクトリ一覧の取得
```
dir -Recurse -Directory
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/f837f973-7e50-63d5-2dec-d85942721153.png)


## ファイル一覧
```
dir -Recurse -File
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/5ff83e7c-c2a7-f196-43c5-62c7ccdd92c6.png)

ちなみにファイ名だけ取得する場合は以下のようにします。
```
dir -Recurse -File -Name
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/6dfed006-4be5-dafc-74bd-f16be74bdcc9.png)


## オススメの出力方法
ちなみに私は下記のコマンドを使うようにしております。
下記のコマンドを実行すると、フォルダ配下のデータを、フルパス、ディレクトリパス、ファイル名、拡張子、ファイルサイズ、最終更新日等を一覧表示し、『result.csv』ファイルに出力してくれます。
コピペで使えますので、
```
Get-ChildItem -Recurse -File | Select-Object FullName, DirectoryName, Name, Extension, Length, LastAccessTime, LastWriteTime | Export-Csv -Encoding Default result.csv
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/3df6c377-0001-1bbd-b812-80465e788137.png)

この通りです！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618971/81beb767-acb1-63b4-07fd-0379588a0272.png)

本日は以上です。
是非、試してみてくださいね！！

# 最後に
最後になりますが、この記事が皆さんの成長の少しでも手助けになることを祈って、この記事を閉めたいと思います。
最後までお読みいただきありがとうございました。
データ領域における疫学(今回は短い)

# 一般的なデータ分析
データ分析においてよく「統計学」「機械学習(や数理モデル)」、時に情報工学が使われます。
それは集まったデータに対して結果からどういう事を考えるかを行う分析だからだと考えられ、そこから学習モデルないし数理モデルでシミュレーションや将来予測、発展的にはレコメンドシステムを作るなどがあります。

# 疫学を考慮する
タイトルに疫学を入れていますが、どういうことかというと、統計学がデータを分析する学問だと考えるなら疫学はデータの集め方の学問になります。
例えば、ランダム化比較試験という原因から結果まで追跡する介入研究や、原因から結果を追跡するコホート研究、結果から原因を見る症例対象研究というものが疫学にあります。
挙げた順にエビデンスレベルが高いのですが、この結果からだけでなく原因についても着目するというのは言ってしまえば因果関係を考察するのに非常に役に立ちます。
例えば統計学で「相関」というものがあり、あれは因果のある「相関」と、因果のない「疑似相関」というものがありますが、因果の有無はあっても結果論のデータセットだけだとどっちが原因かは断言できませんし、そもそも交絡因子についても考察しないと因果のある相関かどうかも分かりません(これは疫学でも同じですが)。

# データ分析までの流れ
データ分析は
データの理解→仮説検証
　　　　　　→課題発見と予測
という流れがありますが、データの理解の前に「どのようにデータを集めるか」を考慮する事で使用する仮説検証についてもより詳細に共変量や交絡因子の考慮もしやすくなります。
また、疫学的観点からデータを集めれば説明変数と目的変数ではなく「原因系変数」「結果系変数」としてモデルを作りシミュレーションをすることができます。
なので
データ収集計画→データ収集→データの理解→仮説検証
　　　　　　　　　　　　　　　　　　　　→課題発見と予測
とするとまた説得力が違うデータ分析ができます。
ちなみにですが疫学というと医療で菌やウイルスに暴露だったり薬の投与を原因として発症や効果を結果にしている事がありますが、医療分野だけでなく例えば広告を見せた群と見せていない群を原因系にして結果系を購買とするとマーケティングにも応用できます。

また、疫学には因果関係というものもあり、
・時間的関係
・量反応関係
・強固性
・一致性
・整合性
とあり、これを用いる事で因果推論だけでなく因果関係を求めることもできます。

# まとめ
結果論だけのデータセットだけでなくデータをどう集めるかも考察してみるともっといいデータ分析ができるかもしれません。
addとcommitを同時に行うコマンド

# 初めに
gitで`git add .`して、`git commit -m "コミットメッセージ"`を多くの方はやっていると思います。
このコマンドを一度で行うことができます。

## git commit オプション
git commitには以下のオプションがあります。
- addのオプション
```text
 -a
--all
変更および削除されたファイルを自動的にステージングするようにコマンドに指示しますが、Git に通知していない新しいファイルは影響を受けません。
```

- commitメッセージのオプション
```text
-m "メッセージ"
--message="メッセージ"
指定された <msg> をコミット メッセージとして使用します。複数の-mオプションが指定されている場合、それらの値は個別の段落として連結されます。
```

## addとcommitを同時に行うコマンド
以上から、`git commit -am`というコミットに`-am`というオプションをつければいいのです。
(ただ、このコマンドでは新規作成ファイルはaddすることができないので、その場合はいつものコマンドでaddしたあとにcommitしてもらうしかないです。)

```bash
git commit -am "コミットメッセージ"
```

ぜひ皆さんもやってみてください！
Music Distribution Company India 

Music Distribution Company India 
https://theblackturn.com/
Making music dreams come true.
Your music, global stage."
"Let the world hear your music."
"Seamless distribution, endless possibilities."
"Music distribution that works for you."
"Join India's music distribution revolution.![Digital Music Distribution In India (5).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815649/7e77b34a-4d02-79cb-a3b1-fc11ab4c3514.jpeg)
![uploading...0]()
はじめてのGAS(Google Apps Script)を実行してみた



# スプレッドシートを新規作成する
## Google Driveを開く

## スプレッドシートを作成する
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/da550924-16d3-8f71-14ba-4fa5d93a2d96.png)


## スプレッドシートの名前を変更する
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/db98f62f-78ec-1f2d-8b06-600ea6484fb1.png)
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/6280e474-3171-266d-0dc1-8568a08a92a8.png)

# プロジェクトを新規作成する
## Apps Scriptを開く
![101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/56d0b062-8fd2-92fd-612c-dbfec4d88db1.png)

## プロジェクト名を変更する
![102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/be5330b4-677d-77df-ad15-1763e266043e.png)
![103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/aa60049d-d98a-dda9-cf14-6b2866d9602f.png)
![104.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/d8aa74ed-6c45-9d1d-2382-5c55a00ffff3.png)
![105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/e9650a70-84ac-93d7-6ea9-62e40f6ce818.png)



# スクリプトファイルを新規作成する
## スクリプトをクリックする
![201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/97132051-de4b-8ca1-d273-d7bfc359cb02.png)


## 名前を変更する
![202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/0d88527a-8ad7-1327-af52-e2c5a0230261.png)

![203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/3fb1da83-bea5-069d-75a5-ffb3cb3d56f0.png)

- .gsは自動的につくので01のみ入力する

# Hello Worldを実行する
## Hello Worldを入力する
![301.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/dcaaf726-9a75-0e8f-7194-496747960a9c.png)

```javascript:01.gs
function myFunction() {
  console.log('Hello World!')
}
```
関数名はすでに入力されているので
```
console.log('Hello World!')
```
だけ入力すればいい

## 実行をクリックする
![302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106311/405e8058-e063-6686-851c-28b8e5179508.png)
- 実行ログに表示される
最近よく聞く失敗したプロジェクトの話

# はじめに
私は関西でSAPエンジニアをしています。
関西という狭い業界で動いていると多方面から様々なプロジェクトのお話を聞くことができます。
私は4年ほど関西でSAPプロジェクトにかかわっていますが、**燃えるプロジェクトは燃えるべくして燃えている**と感じます。某グ〇コの話なので最近盛り上がりが出てきているので忘れないうちに感じたことをメモします。

# SAPプロジェクトについて
SAPのプロジェクトのほとんどがウォーターフォール型で行われており各フェーズの完了をもって次のフェーズの作業を行うといったプロジェクトです。最近のPMBOKではアジャイル開発が推奨され始めたりしていますがSAPの現場はアジャイルになることはしばらくなさそうです。
新規の導入であれ、バージョン改修の作業であれ、**裏ですでにお客様が所持しているシステム**が動いています。そのため、経営陣の思惑と実際の現場の思惑がずれていることはよくある話です。

## SAPプロジェクトのいいところ
すでに多くの企業が導入してくださっているのでお客様もどんなシステムが入るのかイメージついてる、つきやすい状態です。ERPのパッケージ商品なのでコンサルや開発陣も基本的にはお客様の業務をパッケージに合わせる方向で動きます。そのため、コンサルや開発側も無茶苦茶な要求はそう発生せず（はず...）あとは納期がどうなるか、お客様特有の箇所をどうするかだけに注力できます。

## ところが...
私が関わったプロジェクトも、聞いたプロジェクトもあまり前述した状況にはなっていないことに気づきました。なぜそのような状況になっていないのか、聞いた橋と実体験をベースにまとめます。

### 経営陣と現場の意識の差
まずここが一番の課題かと思います。基本的に、新たなシステムになるということで、お客様側の経営陣はよくなることを信じて導入してくださります。
ところが、現場の方は経営陣の思惑とは別に慣れ親しんだシステムで行いたい、新しくなってもできること、やることは変わらないことを望んでいます。特にここの意識の差が顕著であればあるほど、本番稼働後に大きな影響が出ているかと思います。

### コンサルタント側の実力不足
経営陣と現場の意識の差なんてなくそうとするのは難しい話でそれにいかに減らせるのかがコンサルの腕前かと私は考えています。とくにPMをされる方や各モジュールの指揮をとられる方がここに意識をされていると、プロジェクトの立て直しが上手く、お客さんとの関係も良好であったと記憶しています。
ただ、最近よく聞くプロジェクトの話やいわゆる**燃えているプロジェクト**ではコンサルやPMの方とお客様の関係が悪かった印象です。
必ずどちらからも不満が発生したまま、プロジェクトが進んでいました。

### 開発者とPM、コンサルの認識齟齬
特に多いのがプログラムの開発を外注している、海外に委託している場合です。
設計書の内容と違うものができる、設計書が不十分なため問題に気付かないまま作成する等々、多くの問が発生しています。私が関わったプロジェクトの中でうまくいっていたプロジェクトは、設計書が不十分なものなどありましたが、自社と関係社だけで開発を行うなど、外注をしていない印象でした。

# 現場はどうすべきなのか
正直、私はまだまだPMやコンサルではなく、プロジェクトの意思決定にかかわる機会は少ないです。それでも、プロジェクトがまずい状態は嫌でも肌感覚で分かってしまいます。
よく聞く話は、まずくなりすぎないうちに別のプロジェクトに移るということです。
私はそれも悪い選択ではないと思いますがまずほかにやれることはないか、私が行った行動をまとめます。

①自らお客さんと話せる立場に上げてもらう
正直これが一番多いです。開発する側もお客さんも第一にいいものを作りたいことは一緒の認識です。
そのため、開発が行き詰っている、要求が難題化しているときほど直接お客さんと話せる機会をいただいています。

②コンサルの方と綿密に計画を練る
お客さんの要望が原因でプロジェクトが遅延している場合はまずはコンサルの方と綿密に話をすり合わせました。当然、コンサルやPMの方もどうすべきか計画を練られているので、その計画の助けになるべく開発者の状況、要望を伝えてました。

# さいごに
あくまで私が感じた内容のメモですので、すべての現場の状況がこれに当てはまるとは思いませんがいずれもコミュニケーションエラーで問題が発生しているかと思います。
私自身もこれからさらに上流部分で仕事するにはこれらの問題にぶつかるかと思います。
その際に、開発者時代に書いたこのメモを思い出せるようにするとともにどう動くのが最適なのかの一助になればと思います。
JavaScript での 対応のある t検定 の実装

# Reactive stat 内部の対応のある t検定 の実装 です

対応のある t検定（paired t-test）は、同一の被験者や対象に対して、2つの異なる条件や時点で測定を行った場合に、2つの測定値の平均に差があるかどうかを検定する手法です。

この記事では対応のある t検定 の概要と、JavaScriptでの実装方法を説明します。

## はじめに

最近、弊社より **[ブラウザだけで使える無料統計ソフト Reactive stat](https://www.emuyn.net/stats)** をリリースしました。
信頼性の高い R で統計解析し、その結果を AI が解説します！
その背景には、統計に苦労している医療者の助けになりたい、という気持ちがあります。
最終的な統計解析は R で行うのですが、レスポンスとサーバー負荷の改善のため、一部の統計計算はブラウザ内で行っています。
そのうち、汎用性の高い部分を共有させていただきたいと思います。
できるだけ R の出力と整合性を持つように javascript をインプリメントしてあるので、参考になれば幸いです。

## 使用したライブラリ

このコードでは、jStatライブラリを使用しています。jStatは、JavaScriptで統計計算を行うための便利なライブラリです。
jStatの詳細については、[公式ドキュメント](https://github.com/jstat/jstat) を参照してください。
全関数の一覧は [jStat v1.9.3 Documentation](https://jstat.github.io/all.html) を参照してください。

## 対応のある t検定の概要

対応のある t検定は以下の手順で行います：

1. 2つのデータセット $A$ と $B$ から、差の値を計算します。$$d_i = A_i - B_i$$

1. 差の平均値を計算します。$$\bar{d} = \frac{1}{n} \sum_{i=1}^n d_i$$

1. 差の標準偏差を計算します。$$s_d = \sqrt{\frac{1}{n-1} \sum_{i=1}^n (d_i - \bar{d})^2}$$

1. t値を計算します。$$t = \frac{\bar{d}}{s_d / \sqrt{n}}$$1. 自由度 $n-1$ の t分布を使用してp値を計算します。

## コード

ライブラリ込みの html にしてありますので、
[jsfiddle](https://jsfiddle.net/) などにコピペして簡単に試せます。

```html:html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Paired T-Test</title>
  <script src="https://cdn.jsdelivr.net/npm/jstat@latest/dist/jstat.min.js"></script>
</head>
<body>
  <h1>Paired T-Test Example</h1>
  <p>Check the console for the result.</p>

  <script>
    function pairedTTest(dataA, dataB) {
        if (dataA.length !== dataB.length) {
            throw new Error("Data arrays must have the same length for a paired t-test.");
        }
        const diff = dataA.map((value, index) => value - dataB[index]);
        return jStat.ttest(jStat.tscore(0, diff), diff.length);
    }

    // サンプルデータ
    const before = [10, 12, 15, 13, 11];
    const after = [12, 14, 16, 15, 13];

    const pValue = pairedTTest(before, after);
    console.log("Paired T-Test p-value: ", pValue);
  </script>
</body>
</html>
```

## 検証用 R コード

[rdrr](https://rdrr.io/snippets/) にコピペして簡単に試せます。

```R:R
# Paired T-Test

# サンプルデータ
before <- c(10, 12, 15, 13, 11)  
after <- c(12, 14, 16, 15, 13)

# 対応のある t検定を実行
result <- t.test(before, after, paired = TRUE)

# 結果を表示
print(result)
```

## 注意点

- このコードは、jStatライブラリに依存しています。jStatを読み込まないと動作しません
- 浮動小数点数の計算では、わずかな誤差が生じる可能性があります
- 対応のあるt検定を行う前に、差の正規性を確認することをおすすめします。差が正規分布に従わない場合は、代わりにウィルコクソンの符号付き順位検定の使用を検討してください

## 最後に

コードの内容はよく吟味し、R との食い違いが極力ないように気を付けていますが、もし間違いに気づかれた場合には指摘していただけますとありがたいです。

ただ、Chat GPT に読ませてその出力を検証もせず「問題があるので修正します」として貼り付けられると、他の方を混乱させてしまうのと、弊社の製品に対する信頼を損ねることにもつながりかねませんので、どうかそのようなことのないようにお願いいたします。

検証のための R のコードもつけてありますので、ご活用いただけますと幸いです。
[GitHub Projects] 私たちのプロジェクト管理方法を紹介 第2弾

## はじめに

こんにちは。株式会社 Panta Rhei のインフラ構築を担当している岸本です。

[前回](https://qiita.com/Antonnion/items/8e3c24663d8257995a1f)に引き続き私たちが採用しているプロジェクト管理方法第2弾をご紹介します。
今回は**最短**でプロジェクト管理ができる手順を紹介します。

皆さんからのコメントやアイデアもお待ちしています。
以下の順序で進めていきます。

1. ボード作成からチケット作成まで
2. 朝会チケット
3. まとめ

## ボード作成からチケット作成まで
はじめに簡単なボード作成から、実際にチケット作成するまでの流れを紹介します。

### ボード作成
以下の赤枠からプロジェクトを作成できます。
![スクリーンショット 2024-06-13 23.17.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/01893be1-3cdb-9bbd-4ad7-4fda00c8eaf1.png)

以下のテンプレートから選択することができます。

![スクリーンショット 2024-06-12 0.17.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/241329bc-0036-346a-5de4-6bd168985583.png)

今回は下から2つ目の「Board」を選択します。

![スクリーンショット 2024-06-12 0.20.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/3a273472-f53b-b218-d314-540783b6cbc4.png)

デフォルトでは、「Todo」、「In Progress」、「Done」しかありません。
しかし、チームメンバーに「レビュー依頼中」や「とりあえずタスクとして置いておきたい」といった列も必要になってきます。
そこで、以下の赤い箇所から「Back Log」と「In Review」の2列追加します。
![スクリーンショット 2024-06-12 0.28.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/21295078-2b3a-73e7-1da5-b56248ca05a0.png)

作成できると以下のようになります。
列は「Back Log」、「In Review」の名前あたりにカーソルを合わせると掴めるので、自由自在に順番を移動できます。
![スクリーンショット 2024-06-12 0.30.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/3a5676a9-061e-4773-b2af-2e4406bb8b37.png)


### チケット作成
次にチケットを作成します。
チケットは列の「Add item」から作成することができます。随時出てきたタスクを追加していきます。
![スクリーンショット 2024-06-13 23.20.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/04e2f45e-9731-2871-b6f1-deacef413a9b.png)

タスク名は目的ファーストで記述します。
![スクリーンショット 2024-06-13 23.23.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/de5e2b08-63ea-11ef-1e5e-7f560c33c06a.png)

チケットのフォーマットは以下のようにしています。

```
## やること

## 背景/前提/課題

## 補足など

## 参考リンク

```
「参考リンク」に関しては、スラックのスレッドリンクや、関連する公式ドキュメントのリンクなども貼ってみての良いでしょう。

これでチケットは完成です。
[前回の記事](https://qiita.com/Antonnion/items/8e3c24663d8257995a1f)にカスタムフィールドの説明をしておりますので、そちらを参考にしてチケットをカスタムしてみてください。

## 朝会チケット
次に私たちが朝会で使用しているチケットについてです。
議事録はとっておきたい。しかし、媒体が散らばるのは嫌だというニーズを散りばめた朝会チケットが以下になります。
![スクリーンショット 2024-06-13 23.30.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775049/703d851f-9f9d-9f3c-54dc-23512f55ffd6.png)

フォーマットは以下のようになっています。
```
## 定例議事録 2024/mm/dd

## Done (前日までに終わったタスク)

- @GitHub_Account_NAME
    - Task (ISUUE URL) 
    - TBD
- @GitHub_Account_NAME
    - Task (ISUUE URL) 
    - TBD

## Doing (来週の定例までにやるタスク)

- @GitHub_Account_NAME
    - Task (ISUUE URL) 
    - TBD
- @GitHub_Account_NAME
    - Task (ISUUE URL)
    - TBD


## その他

- TBD

## 今日のネタ絵

毎週担当変えて貼っていく
意味はない(ある)

```

毎朝これを元に、今週行ったことを振り返ります。

メリットとしては、
- メンバーのやったこと、やっていることが一目でわかる
- 詰まっているところやメンバーの負担を共有できる
- 議事録をチケット1枚で管理することができる
- イシューと紐付けて、チケットを行き来することが少なくなる

チケットの作成する単位はワンスプリント（2週間）で作成しています。
朝会はこのようなチケットで管理してみてはいかがでしょうか？

## まとめ
いかがでしたでしょうか。
私たちはこのようにボード作成、チケット作成、朝会を行っております。
まだまだチップスがあるのでシェアしていこうとおもいます。
また何か他のチップスがあれば共有していただけると幸いです。
弊社ではアジャイル開発に興味のある方やエンジニアの募集を行っています。
GitHub Projects に関することや、採用に関するお問い合わせも、どうぞお気軽にご連絡ください。
アジャイルで忘れてたこと

## はじめに
私はアジャイルで開発を始めて新卒３年目になります。
久しぶりにアジャイルについて見直したことで認識が誤っていたところを復習兼ねて
Qiitaに記事投稿しよう！というモチベーションです。

### タスクはみんなで決めるもの
誤り１つ目。
タスクを決めるのはプロジェクトのリーダーでもスクラムマスターでもない。
みんなで優先順位を決めてみんなで納得するタスクを進めていこう。

### ベロシティは過去実績から算出しない
誤り２つ目。
過去の実績を全てまとめて分析したり、他プロジェクトの実績を参考にしたりはしません。
あくまで毎スプリント改善がなされてその時最善のベロシティをはかろう。

### 大きいストーリーは不確実性が高いし見積もりしずらい
誤り３つ目。
同じようなまとまりでストーリーをまとめたりするとこの作業はどれくらいかかるのか？が見えづらくなる。
あくまで細分化が大事。

### 全てを見積もろう
誤り４つ目。
実施するタスクの全てを見積もることが大切。
一部見積もらないなどをするとベロシティが測れないし次スプリントへの改善もしずらい。

### デイリースクラムは15分のタイムボックス
誤り５つ目。
じっくり腰を据えて実施するものではない。
進捗の刈り取りはせず、あくまでチームの自己組織化を促進するために実施する。

### プロダクトバックログ → スプリントバックログ
誤り６つ目。
同じバックログでもプロダクトバックログとスプリントバックログは実施対象者も目的も異なる。
プロダクトバックログがあってスプリントバックログがある関係性。

### スプリントレビュー → スプリントレトロスペクティブ
誤り７つ目。
必ずしもセットで実施するものではない。
スプリントレトロスペクティブはチーム内改善であり定期開催。

### エンタープライズアジャイルとは
誤り８つ目。
企業全体にアジャイルを適用すること。大規模。

### さいごに
今確認するとなぜ誤った認識をもっていたのかと思うような内容ばかりでした。
アジャイルやスクラムの考え方は今やたくさんの書籍などが出されていてネットでも簡単に知識を仕入れることができるので、一から新しくプロジェクトを始める前やちょっと不安だな〜と思った時には改めて少しネットで調べたりして知識をいつでもアウトプットできる形にしておく必要がありそうです。
【AWS】Cloudformationで既存VPCにセカンダリCIDRを追加する

# 概要

AWS VPCに追加でCIDRブロック範囲を拡張することは、2017年より可能になっています。

https://aws.amazon.com/jp/about-aws/whats-new/2017/08/amazon-virtual-private-cloud-vpc-now-allows-customers-to-expand-their-existing-vpcs/

作成時に割り当てるCIDRブロックがプライマリCIDR、追加する時に割り当てるCIDRブロックをセカンダリCIDRと呼びます。

しかし、「既存のVPCにセカンダリーCIDRを追加する」場合のCloudformationテンプレート例が公式ドキュメントに見当たらず、また、ネット記事にもなかったのでこちらで紹介します。

# Cloudformationテンプレートサンプル

以下がサンプルです。プライマリCIDRとして`'10.0.74.0/23'`があるとします。
既存のVPCは`VpcId`としてExportされている前提です。
（Exportしていない場合でもID指定で参照させることはできます）

```yaml
  VPCSecondaryCidr:
    Type: 'AWS::EC2::VPCCidrBlock'
    Properties:
      VpcId: !ImportValue VpcId
      CidrBlock: '10.0.76.0/23'
```

上記で実施すれば、セカンダリCIDRとして追加されます。
マネジメントコンソールから確認すると、以下のように追加されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/80fcd166-3b81-bfae-b4d8-762127826008.png)


プライマリCIDRは変更することはできません。
もちろん、セカンダリCIDR追加により、プライマリの方のIDが変わってしまったりとか既存のリソースが再作成されるとか、そういったイベントもありません。

ただし、追加時にいくつか制限（注意点）があります。

## 注意点
AWSの仕様的な意味では以下がまず制限事項です。

> 許可されているのは、/28 ネットマスクから /16 ネットマスクの間のブロックサイズです。
CIDR ブロックは、VPC に関連付けられている既存の CIDR ブロックと重複してはいけません。
使用できる IPv4 アドレスの範囲には制限があります。詳細については、「IPv4 CIDR ブロック関連付けの制限」を参照してください。
既存の CIDR ブロックのサイズを増減することはできません。
CIDR ブロックは、VPC ルートテーブルのいずれかのルートの送信先 CIDR 範囲と同じ､またはそれ以上に大きくすることはできません｡ 例えば、プライマリ CIDR ブロックが 10.2.0.0/16 である VPC では、仮想プライベートゲートウェイへの送信先 10.0.0.0/24 を持つルートテーブル内に、既存のルートがあります。10.0.0.0/16 範囲内のセカンダリ CIDR ブロックを関連付けるとします。既存のルートが原因で、10.0.0.0/24 以上の CIDR ブロックを関連付けることはできません。ただし、10.0.0.0/25 以下のセカンダリ CIDR ブロックを関連付けることはできます。
> 公式ドキュメントより：[VPC CIDR ブロック](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-cidr-blocks.html)

上記で言えば、`10.0.74.0/23`は`10.0.74.0 - 10.0.75.255`がIPアドレス範囲なので、新規に追加する`'10.0.76.0/23'`は重複しておらず、追加が成功します。

また、当然ですが、新しいCIDRブロックを追加した後は、ルートテーブルや関連付けなど新規に設定する必要があります。サブネットやRouteTable、Routeなども新しく追加している場合はいつも通りのリソースを準備すれば良いですが、そうではない場合はその点も考慮に入れて設計する必要があると思います。

Subnetも一緒に新規テンプレートで定義する場合、Cloudformationでのスタック更新において、という意味でもう一つ注意点を挙げると、先にSubnetが作成されてしまうと生成順序による依存関係エラーになることがあります。つまり、「セカンダリCIDRブロックが作成される前にサブネットが作成されてしまった」場合です。スタックのイベント欄には、正確には依存関係エラーとして表示されるのではなく、「そのCIDRブロックはinvalidだよ」というエラーが出ます。

その時は、`DependsOn`を使うと良いです（たびたびお世話になります...笑）。
以下のような形で依存関係エラーを解消できます。

```yaml
  PublicSubnet1:
    Type: AWS::EC2::Subnet
    DependsOn: VPCSecondaryCidr # これを追加
    Properties:
      CidrBlock: !Ref Public1Cidr
      AvailabilityZone: !Ref AzName1
      MapPublicIpOnLaunch: false
      VpcId: !ImportValue VpcId
```
latexの図の挿入で1-1、2-1と自動で割り振る方法

# はじめに
大学の授業でlatexでレポートを書かせる授業があったときに、図1-1、図2-1のように画像を提示したかったので、やり方を調べてみました。

# 実際のコード
```
\usepackage{graphicx} 
\usepackage{chngcntr} 
\usepackage{caption} 
\renewcommand{\thefigure}{\thesection-\arabic{figure}}

\counterwithin{figure}{section}
\captionsetup[figure]{labelformat=empty}

\begin{figure}[htbp]
    \centering
    \includegraphics[width=0.5\linewidth]{images/is0662ks_1-1.png}
    \caption{図\thesection-\arabic{figure}物理シミュレーションで観測したい内容}
    \label{fig:fall-start}
    % \label{fig:enter-label}
\end{figure}
```
graphicx: 画像を挿入するためのパッケージです。

chngcntr: カウンタの再設定やカウンタのリセットを行うためのパッケージです。
```
\counterwithin{figure}{section}
```
これはセクションが変わると、図の番号をリセットしています。

caption: キャプションのスタイルやフォーマットを設定するためのパッケージです。以下の箇所で使われていて、labelの内容だけ表示して、図1-1等を表示しません。
```
\captionsetup[figure]{labelformat=empty}
```
`セクション番号-何枚目`の画像という景色で表示しています
```
\caption{図\thesection-\arabic{figure}物理シミュレーションで観測したい内容}
```

ぜひ参考にしてください
計測した温湿度を自分のLineに送信してみる


# はじめに

以下でラズパイと温湿度センサを使って室温と湿度を出力することができた。
今度はそれをLineに通知するようにしてみる。

https://qiita.com/atjjnnn/items/0eb133d3de92f13849ff

ほとんどの内容は以下の記事を参考に実施した。

https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9

# Lineの設定

LINE Notifyを使う。
https://notify-bot.line.me/ja/

まずはアクセストークンの取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529381/d66dd553-d1e2-053f-3455-1ef80a81a69d.png)

適当な名前をつけて発行！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529381/92d40147-3592-76db-ae4b-704eb8fea283.png)

# 実装

ライブラリのインポート

```python
import requests
```

URLと取得したトークンとヘッダーを指定する。

```python
url = "https://notify-api.line.me/api/notify" 
token = "......."
headers = {"Authorization" : "Bearer "+ token}
```

計測した温湿度を含めたメッセージを作成。

```python
message = ['temperature={0:0.1f}degree humidity={1:0.1f}%'.format(temperature, humidity)]
```
メッセージを送る。

```python
payload = {"message" :  message}
r = requests.post(url, headers = headers, params=payload)
```

こんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529381/ff159df5-6627-510e-e649-912fada9ce28.png)

# 実行してみる

Lineに来てたのでうまくいった。
仮でsleep(1)にしてるので約1秒ごとに来ている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2529381/1c06294d-ee5d-4b89-5137-12a7403fc591.png)


# おわりに
出先でも部屋の温度を把握できるようにしたいという目的はこれで一応達成したけど、業務で学んだことと組み合わせてできそうなことが多いので色々試してみようと思う。
【Ruby】文字列演算子 <<

## 概要
この記事では、`<<` 演算子を使用した文字列の連結方法について詳しく見ていきます。
<br>

## 文字列連結方法
Rubyでは文字列の連結にいくつかの方法があります、一般的なのが `+` 演算子、
次に今回の記事のお題にもなっている `<<` 演算子。

**`+` 演算子：**
「str1 + str2」 という形式で使用される。
str1 と str2 を連結した新しい文字列を作成します。
この操作では、元の文字列は変更されず、新しい文字列オブジェクトが毎回生成されます。

**`<<` 演算子：**
「str1 << str2」 という形式で使用される。
str2 の内容を str1 に直接追加します。
この操作は str1 を破壊的に変更し、新しいオブジェクトの生成を伴わないため、メモリ効率が良く、処理速度も速いです。

<br>

## << 演算子の利点
大量の文字列データを扱う際に特に有効で、大きなファイルの内容を読み込んで処理を行いたい場合、 `+` よりも `<<` 演算子を使う方がパフォーマンスが良いです。
理由として、`<<`演算子は元の文字列に直接追加するため、途中に不要な文字列のオブジェクトが生成されないからです。

<br>

## 使用例
```Ruby:Ruby
sentence = ""
words    = ["hello", "world", "from", "ruby"]

words.each do |word|
  sentence << word << " "
end

puts sentence  
# => "hello world from ruby "

```


コメントアウトを追加したバーション※上のコードと全く同じです。
コードの各部分が何をしているのか明確に理解するため。

```Ruby:Ruby
# 空の文字列を初期化する。これが最終的に全ての単語を含む文になる。
sentence = ""

# 単語の配列を定義する。
words    = ["hello", "world", "from", "ruby"]

# each文で配列`words`の各要素`word`に対して繰り返し処理を行う。
words.each do |word|

  # ①sentenceに最初の `hello` 追加。
  # ②`" "` でスペースを1つ追加 ➡ これにより単語と単語の間にスペース挿入。
  # ③２が終了した時点で `sentence` には `hello` とスペースが代入されている
  # ④次は二つ目の `world` を同じように `sentence` に追加していく
  sentence << word << " "
end

# ループが完了した後、`sentence` には全ての単語がスペースで区切られて連結されている。
# 全て連結した文を出力する。
puts sentence  

# => "hello world from ruby "
```
#### 補足説明
①`sentence` で文字列の初期化、これにより最後に文字列を連結するための空の基盤が用意されるのと、プラス後の文字列を代入するためとしても機能する。<br>
②`each`文で配列の繰り返し処理、配列 `words` の各要素 `|word|` を順に取り出していく<br>
③文字列連結、`sentence << word << " "`  は、
現在の単語 `word` とスペース `" "` を `sentence` に連続して追加。
`centence` の内容を直接変更 ➡ `破壊的操作`<br>
④文字列の出力, `puts sentence` で完成した長文を出力 


## まとめ
大量のデータを扱う際や、アプリケーションの効率化を図る際は、メモリとパフォーマンスの観点から `<<` 演算子を使用した方が良さそうです。


### 参考サイト
https://www.tohoho-web.com/ruby/operators.html
![screenshot_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711935/e0913926-a195-d6a1-cd31-da4b97f218bb.png)
いまさらdockerを始めてみる①

# はじめに
QiitaEnginieerFestaの取り組みが面白そうなので、記事の連投に挑戦しようと思いました。
何を書こうかなと考えたところ、エンジニアであるのにdockerを触ったことがなかったので、記録として記事に残しながら触ってみます。

# dockerをinstall
1. dockerの公式のdocumentにアクセス
https://docs.docker.com/guides/getting-started/get-docker-desktop/
1. 私のパソコンはwindowsなので図中赤丸を選択![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/0ca6b1ac-5289-f534-4588-e6e11c43cf96.png)
1. installerを実行。パスやオプションの選択などはなく(shortcut追加するか否かだけ)、5分ぐらいで動作が終了→再起動
1. 再起動後、謎のポップアップが出てきますが、お金を払いたくないのでclose![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/60447d35-bbef-5ec5-4bec-315ad54c97d8.png)
1. コマンドプロンプトを起動し、試しに"docker -h"とたたきます。うまくいったぽい![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/59b4d75e-df3f-ddc9-c664-5c072d57d291.png)
1. documentに記載されている'docker: error during connect: this error may indicate that the docker daemon is not running'をたたく。エラーを吐く![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/46326249-9810-abe1-77d0-3f51a285c27a.png)
1. https://qiita.com/Ooooooomin_365/items/1cea81eccc22b6bcdbb8 に従い、DockerDesktopを起動
1. DockerDesktopを起動すると、先に述べたポップアップが出現。どうやらAcceptしないと先に進めなさそうなのでAccept
1. 初心者なのでrecommended settingを選択![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/ae8b4b4c-60dc-28af-4f58-b928bb966700.png)
1. sing-inはしません![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/92323aa3-8224-0820-67f6-400645855562.png)
1. surveyをskip![7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/4a9467d1-6055-8148-ce32-b1fd854b00b4.png)
1. 謎のエラーに阻まれる
![8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/4d8c28a7-8419-6d1b-4dff-f149020499f5.png)
1. https://forums.docker.com/t/an-unexpected-error-was-encountered-while-executing-a-wsl-command/137525/15 によるとBIOSのSVMが有効になってないのが問題っぽい？
1. BIOSに入りAdvancedCPUSettingのSVMをdisavled->Enabledに
1. 起動した![9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/7abea5d1-a536-44d1-3592-7db30c9f6f5d.png)
1. 再度'docker run -d -p 8080:80 docker/welcome-to-docker'を実行
![10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/21490ef7-a692-bba8-1f66-bd8020843bef.png)
1.出てきた![11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/6fa4c5f7-e81e-9982-b06c-e0e09abbafae.png)
1.DockerDesktopにさっきたてた？dockerが追加されている
![12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269297/d8f3cbd4-1ab4-df87-8665-e99cde6386a3.png)

つかれたので今日はここまで。明日は次のページをやる
課題（014）進捗

お疲れ様です。

先日提出した課題（008）が合格となりましたので、今日からまた別の課題に取り組んでいきます:fist:
今回からはcssが入ってきますので、忘れているところを復習しつつ課題を進めます！
<br>
![2024-06-13 230946.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/fc8c6336-19cc-86af-f45b-610c6c2afaae.png)

![6-13 223356.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/74437dbd-3e48-f203-6b0e-061880d43c6a.png)

![2024-06-13 231034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/cf97190a-aa59-0aae-da95-a39835ab75bb.png)
<br>
新しい課題に目を通しつつ、1時間弱でなんとか形になりました:sweat_smile:
まだまだフォントカラーの指定や、装飾の指定もあるので、最終的に見本通りになるように進めていかなければ。
<br>
そして今回復習しましたのは、em と rem です:writing_hand:
課題の中で「文字の大きさに応じて文字間が1.2倍」との指定があり、多分 em か rem のことなんだろうなとは思いましたが、どちらがどうであったか忘れていましたので、調べなおしました。
<br>
em  は、「親要素」の文字の大きさを元に、サイズを決めるもの。
rem  は、「ルート要素（地の文）」の文字の大きさを元にサイズを決めるもの。
<br>
であることを再度確認し、今回もchatGPT先生に例題を出していきただき、それぞれ見比べてみました。
![2024-06-13 233313.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/fb603f00-24a8-8cec-b7b3-ad7d3bcea518.png)

![2024-06-13 233345.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/955fe3c7-f5dd-229a-505b-fc82aa75f919.png)
<br>
という結果であることが分かりましたが、やはり百聞は一見に如かずという言葉がある通り、説明を聞いただけではピンときませんでしたが、見比べた上でコードの内容を確認するとそういうことか！と理解できました。
冒険して「ここのコードをこうしてみたらどうなる？」ということをもっとやって、失敗パターンと成功パターンを経験せねばと思いました:pensive:
明日は、最後まで装飾を仕上げていきたいと思います。
Tauri+Svelteで設定情報をリアルタイムで反映させるのに躓いた話

# 今回やりたかったこと

学習目的の個人開発にてタイマーアプリを作成しておりまして、その設定ファイルをリアルタイムで反映させるために躓いた点と解消した方法をまとめました。

![tauri_settings_reactive.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552182/21a6f9cb-3e27-0244-c75e-c4ec29782407.gif)

## 躓いた点

Svelteにstoreというreactいうところのstate的なものがあります。通常のSveltekitではstoreはグローバルで管理されるもの思っておりました。

イメージとしては、以下のに各ウィンドウからできるものかと思っていました。
![スライス1@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552182/dc6cd156-d778-76ad-4c60-88680e80a498.png)


しかし、実際には各ウィンドウごとにstoreが生成されるという挙動でした。そのため、設定変更がメインウィンドウへ反映されませんでした。
![スライス2@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552182/f65a6878-dfa0-b9a3-d5e9-dd85fb9890a6.png)


## 解決方法

元々アプリ起動時に、設定ファイルから設定情報を読み取る実装でした。設定変更時に設定ファイルへの書き込み＆Mainウィンドウの設定読み込みイベントを発火することで解決できました。最終的な処理イメージは以下のようになります。

![スライス3@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552182/ceb6d92a-dfc2-2366-65a6-bd8df9488ab1.png)

まず、③④を行うためのイベントをメインで使用する画面に実装します。

```ts
<script lang="ts">
    import settingsStore, { loadSettings } from '$lib/Settings';
    import { listen } from '@tauri-apps/api/event';

	onMount(() => {
         // イベント設定
		listen('settings-changed', async (event) => {
              // 設定読み込み、store更新
			$settingsStore = await loadSettings();
		});
	});
</script>

// Settings.ts
import { readTextFile, writeTextFile, BaseDirectory } from '@tauri-apps/api/fs';

export async function loadSettings() {
	try {
		const config = await readTextFile(FILENAME, { dir: BaseDirectory.AppConfig });
		return JSON.parse(config);
	} catch (error) {
		return defaultSettings;
	}
}
```

設定画面で①②を実装します。スタイリングはdaisyUIを使ってます。
```ts
<script lang="ts">
	import settingsStore from '$lib/Settings';
	import { emit } from '@tauri-apps/api/event';

	let timeDuration = $settingsStore.timeDuration;

	async function save() {
		$settingsStore.timeDuration = timeDuration;
		emit('settings-changed', { $settingsStore });
	}
</script>

<main>
	<div class="p-4 space-y-3">
		Time Duration (minutes)
		<label class="input input-bordered flex items-center gap-4">
			<input type="text" class="grow" bind:value={timeDuration} />
		</label>
	</div>
	<!-- fotter -->
	<div class="p-4 flex justify-end space-x-2">
		<button class="btn btn-primary" on:click={save}>Save</button>
	</div>
</main>

```

## まとめ
これが正しい設計かは分かりませんが、なんとか綺麗にまとまったと思います。ちなみに作成中のタイマーアプリはこちらで紹介してます。現在も激遅アップデートを行っています。

https://qiita.com/mlab/items/1ace9885441f955d6d65
IndentationError: unindent does not match any outer indentation level  というエラー文に出くわす

# はじめに
　FastAPIとstreamlitを使用して会議室予約アプリを作成していた際に困ったのでまとめます。
# 問題
```
File "/Users/my_study/FastAPI/会議室予約システムAPI/app.py", line 117
     submit_button = st.form_submit_button(label='リクエスト送信')
                                                           ^
IndentationError: unindent does not match any outer indentation level
``` 
というエラーに出くわしました。
# 原因
　調べるとインデントが誤った時に出るエラー文でした。自分のコードも単純にインデントが誤っていただけでした。
 https://izanagi-portfolio-site.com/blog/articles/5tijnkzlq/#gsc.tab=0
# 解決
　インデントを修正したらエラー解消されました。
# 終わりに
　調べたらすぐに関連記事が出たので、時間を取られずに済みました。
 
　そして今回の記事が初投稿になります。とにかくアウトプットをしましょうという記事を拝見し、やってみることにしました。果たしてこんなものでも全世界に向けて公開して良いのか疑問ですが、徐々に良くなると信じています。IT業界未経験で転職を目指す私の力になると信じて取り組みたいと思います。頑張ります。
 
 https://qiita.com/Sicut_study/items/40fd5aac278b001a2fee
flutter_maplibre_glが知らない間にpub.devで公開されていてmaplible_glに変わって、ちょっとだけコードの変更が必要なお話

# はじめに

FlutterのMaplIbreのライブラリは以前は[GitHub](https://github.com/maplibre/flutter-maplibre-gl)のみでの配布であったが、ふと新しいリリースがないか覗いてみたら、pub.devで公開したとの書き込みが！

https://pub.dev/packages/maplibre_gl

早速作成中のプログラムに適用してみた。
動作上の問題はありませんが、少しだけ変更点があるので気を付ける必要があります。

# ちょっとだけ気を付けること

大きな変更はないので、ちょっとだけ気を付けることを２つ。

## pubspec.ymlの変更

pub.devで公開されているものを利用したい場合は変更が必要。
といっても、これまでのGitHubの参照を

```yml
  maplibre_gl:
    git:
      url: https://github.com/maplibre/flutter-maplibre-gl.git
      ref: main
```

よくある形式に変えるだけ
```yml
  maplibre_gl: ^0.20.0
```

## 列挙型の名称の変更

リリースノートにあるように、列挙型の名称がキャメルケースに変更となっている。
そのため、Dart Analysisなどを参考に名称を修正する必要がある。
例えば小出までは以下だったものを
```
  MyLocationTrackingMode.TrackingCompass
```

以下のように変更する
```
  MyLocationTrackingMode.trackingCompass
```

## 名称変更でMaplibreMapControllerが非推奨

MaplibreMapController が非推奨になり、代わりに MapLibreMapController を使えとのこと。
名称の変更だけのようです。
他にも MaplibreMap は MapLibreMap など、MaplibreをMapLibreにする変更が入っています。

# 最後に
今回は大した内容ではないですが、pub.devで公開されることになり、導入が少し楽になったかなと思います。
`SupportsComplex` を信じるな

## `float(x)` できるなら `SupportsFloat`

Python には `SupportsFloat` というプロトコル[^abc]がある。

[^abc]: ABC ということになっているがこれはプロトコル言語機能の実装前の言い分であり、実際には継承せずとも動作するためプロトコルとみなすべきだろう。

これは、Python 組み込みの `float` 型ではないが、`float` として扱うことができる型であることを要求する。実際の動作としては、`self.__float__()` をメンバーに持つ、つまり組み込み関数 `float(x)` で変換できることを意味する。`float` ではないが `SupportsFloat` であるような型には NumPy の `np.float64` などがある。

```python
from typing import SupportsFloat

import numpy as np


def func1(x: float) -> float:
    return 2.0 * float(x)


def func2(x: SupportsFloat) -> float:
    return 2.0 * float(x)


x = np.empty((8, 8), dtype=float)
y: np.float64 = x[0, 0]
print(func1(y))  # NG
print(func2(y))  # OK
```

## `complex(x)` できるなら `SupportsComplex`、ではない

同様に `self.__complex__()` を実装していることを意味する `SupportsComplex` がある。`float` 型は `complex(x)` によって `complex` に変換できるため、以下のコードは型チェッカーを通過できるはずだ。

```python
from typing import SupportsComplex


def distance(x: SupportsComplex, y: SupportsComplex) -> float:
    return abs(complex(x) - complex(y))


print(distance(5.0, 3.0))  # NG
```

しかし、このコードは型チェッカーが許さない。なぜだろう?

実は、`float` は `self.__complex__()` を持っていないのだ。**つまり `float` は `SupportsComplex` ではない。**

```python
print(hasattr(5.0, "__complex__"))  # False
```

さらにいえば、[`complex` さえ Python 3.11 まで `SupportsComplex` ではなかった。](https://github.com/python/typeshed/issues/1904)**`SupportsComplex` ってなんだよ。**

ではなぜ `complex(x)` によって変換できるのか?　`complex` 関数(コンストラクタ)の型シグネチャは Pyright によると`complex(real: complex | SupportsComplex | SupportsFloat | SupportsIndex = ..., imag: complex | SupportsFloat | SupportsIndex = ...)` となっている。`SupportsComplex` だけでなく `SupportsFloat` や `SupportsIndex` が指定されていることがわかるだろう。`SupportsIndex` は `operator.index(x)` によって正確な `int` に変換できる、つまり整数とみなせる型であることを意味する。

もしや、`float` や `int` に対して特殊化し、`float(x)` や `operator.index(x)` によって変換できる型はそのようにしてから処理をおこなっているのではないか?　確かめてみよう。

```python
class Foobar:
    def __float__(self) -> float:
        print("called __float__")
        return 0.0


complex(Foobar())  # called __float__
```

間違いない。つまり、`complex(x)` によって変換できることを要求する場合は、例えば以下のようにしなければならない。

```python
from typing import SupportsComplex, SupportsFloat, SupportsIndex, TypeAlias

ConvertibleToComplex: TypeAlias = (
    complex | SupportsComplex | SupportsFloat | SupportsIndex
)


def distance(x: ConvertibleToComplex, y: ConvertibleToComplex) -> float:
    return abs(complex(x) - complex(y))


print(distance(5.0, 3.0))  # OK
```

確かに `float` に変換できるなら `complex` にも変換できるべきなので、`self.__float__()` だけ実装すればいい `complex(x)` の型は理解できる。しかし、`SupportsComplex` というプロトコルの動作が非直感的になっていることは念頭に置かなければいけない。

## おまけ

では、`self.__index__()` `self.__float__()` `self.__complex__()` すべてを実装している場合 `complex(x)` の動作はどうなるのだろう。試してみよう。

```python
class Foobar:
    def __index__(self) -> int:
        print("called __index__")
        return 0

    def __float__(self) -> float:
        print("called __float__")
        return 0.0

    def __complex__(self) -> complex:
        print("called __complex__")
        return complex()


complex(Foobar())  # called __complex__
```

`self.__complex__()`、`self.__float__()`、`self.__index__()` の順で優先されて呼び出されるようだ。