OmniAICreator/Qiita-1.07M huggingface dataset:
Ebitengineの環境構築にちょっと苦労した話

# 目次
1. [概要](#概要)
1. [課題](#課題)
1. [やったこと](#やったこと)
1. [結論](#結論)
# 概要
Ebitengineの環境構築の確認(https://ebitengine.org/en/documents/install.html)  
をやろうとしたらエラーが出た  
# 課題
```powershell
go run github.com/hajimehoshi/ebiten/v2/examples/rotate@latest
```
で確認する。  
エラーがでた
```
package github.com/hajimehoshi/ebiten/v2/examples/rotate@latest: can only use path@version syntax with 'go get' and 'go install' in module-aware mode
```
# やったこと  
エラーは参照の方法をGOPATHからモジュールにしろっていうことっぽい  
modファイル作ってmain()で動かしてみる。  
``` powershell:powershell
go mod init TestEbiten
go get github.com/hajimehoshi/ebiten/v2/examples/rotate@latest

```
Goのソースコード
``` Go:main.go
package main

import (
    "github.com/hajimehoshi/ebiten/v2/examples/rotate"
)

func main() {
    rotate.Run()
}

```
これもエラーがでた  
```
..\..\go\pkg\mod\github.com\hajimehoshi\ebiten\v2@v2.5.6\examples\2048\main.go:20:2: //go:build comment without // +build comment
..\..\go\pkg\mod\github.com\hajimehoshi\ebiten\v2@v2.5.6\internal\restorable\images.go:20:2: //go:build comment without // +build comment
…
```
パッと見リポジトリの問題っぽいが、特に問題は報告されていないようなので+build commentで検索してみる。  
どうやら、1.16で発生する問題らしい  

# 結論
Goのバージョンの問題(1.16で発生するみたい)  
https://go.dev/doc/install に従ってGoをアップデートしておく  

参考:https://qiita.com/infinity0206/items/2c6a6cbdb906d5fc9f08
'cp932' codec can't decode byte 0x88 in position 41: illegal multibyte sequenceの 対処法

# 'cp932' codec can't decode byte 0x88 in position 41: illegal multibyte sequenceの 対処法

キーワード
windows10
kohya_ss
venv
site.py
sjis
cp932
utf8


## 対処方法
win10にセットアップしたkohya_ssをいじっていた際に、とあるパッケージのダウングレードが必要になったため、requrements.txtを書き換えた。
venvをactivateした状態でpip installした後、pip --versionをするとタイトルのエラーが発生。

tracebackをみるとエラー元はsite.pyの175行目以下の部分。

```python:site.py
    """Process a .pth file within the site-packages directory:
       For each line in the file, either combine it with sitedir to a path
       and add that to known_paths, or execute it if it starts with 'import '.
    """
    if known_paths is None:
        known_paths = _init_pathinfo()
        reset = True
    else:
        reset = False
    fullname = os.path.join(sitedir, name)
    _trace(f"Processing .pth file: {fullname!r}")
    try:
        # locale encoding is not ideal especially on Windows. But we have used
        # it for a long time. setuptools uses the locale encoding too.
        f = io.TextIOWrapper(io.open_code(fullname), encoding="locale")
    except OSError:
        return
    with f:
        for n, line in enumerate(f):
```
エラーの原因は、恐らくpip installした際に、もともとsjis(cp932)だったpthファイルがpip installしたことによってエンコードがutf8に戻ってしまった。
その状態でsite.pyのTextIOWrapper()の箇所にて、utf8のpthファイルをlocale(環境のデフォルトエンコード、つまりsjis)で開いてしまい、pthファイル内に日本語が含まれていたためエラーとなってしまった、と思われる。

今回対象となるpthファイルはvenv環境内の`venv\Lib\site-packages\library.pth`であった。
バックアップを取得後、vscodeで開いてエンコードにsjisを指定して保存すれば問題は解決した。
Macbook Air 11 early 2014  Windows10化

Macbook Air 11 early 2014 を Windows10化します。
本当はWindows11化したいです。
はまりましたので、備忘録です。


 # SSD交換
元々のスペックが4GMメモリ、128GBSSDです。
さすがに、128は小さいと思い、かつ MacOSとWindowsのデュアルブートにしたかったので、SSDを交換しました。
ここがハマリポイントその１です。
ざーっと書きますと、下記な感じです。

### 部材の調達
SSD
→AmazonプライムデーでNVMe 2280 1TBをゲット。買ったのはシリコンパワー。

変換アダプター
→Macbook Air　の SSDのコネクタが独自なのでこれもAmazonプライムデーでゲット。

### 分解と換装
星型ドライバーで裏蓋を外せば、すぐにSSDは交換できます。
などなど、他の人の記事に色々ありますので、ケンサクしてみてくださいませ。

----
というわけで本題です。
# MacOSインストール
互換性のある最新バージョンのOSを入れられるリカバリーモード(Option+Command+R)で起動します。
実は、ここで、一度はまってます。「はまりポイント１」
リカバリーモードはCommand+Rだと思いこんでいて、これで起動すると、なんとYosemiteで起動しました。
そうすると、交換したSSD交換が認識しないのです。
SSDがが壊れているのかと、違うところにつけて試してみたりかなり時間を使いました。
ところが、調べてみると、HighSierra以降でないと、MVNeのSSDが認識しないとこと。
なので、Option+Command+Rです。
これで、BigSurでインストールできます。

## ディスクユーティリティで、パーティション作成
なんとなく、下記３つに分けました。
・MacOS用　450GB
・WORK用　exFat 100GB
・Windows用 未アサイン 残り約450GB 

## MacOS
いい感じでインストールします。
使いなれたMac状態にしてくださいね。
Big Sur なので快適です。

# USBメモリの準備
使ってなかったUSBメモリ16GBを見つけてきました。
ディスクユーティリティで、exFATでフォーマットしておきました。

# Windows 10 のダウンロードとUSBメモリへのコピー
下記、リンクからWindows10のISOファイルを作成できます。
https://www.microsoft.com/ja-jp/software-download/windows10

Mac上で作成したISOファイルを開くとディスクイメージでマウントされますので、中身全部を、USBメモリにコピります。
なんと、これで起動できます。

ここが、「はまりポイント２」です。

### 予期しないエラー
いい感じでインストールが進み、これは楽チンって思っていると「予期しないエラー」が発生します。
何回再起動してもダメです。
困りました。

調べると、先人が解決策を書いてくれています。

１）予期しないエラーの画面で「Shift+F10」を押して、コマンドプロンプトを出す。
２）regedit 起動
3)「HKEY_LOCAL_MACHINE」→「SYSTEM」→「Setup」→「Status」→「ChildComplation」の「Setup.exe」を選ぶ
４）ダブルクリックして、DWORDを「3」に変更する。

だそうです。
更新後、予期しない画面の「OK」を押すと、先にすすみます。やったー！

そして、「はまりポイント３」です。

### ブルースクリーン
今度はブルースクリーンです。
これも調べてみると先人にたどり着きます。

なんと、「Build1803以降だとインストールできない」とのこと。

古いISOを探そう。
ネットをみると、「Rufus」というアプリでできるとか、「Windows ISO Downloader」というアプリでできるとかみつかりますが、古い記事でして、更に調べると、最近は旧バージョンはダウンロードできなくなっているようです。

### ISOファイル探索
昔、VirtualboxにWindowsを入れたときのISOがあったはずということで、バックアップを探します。
ありました。1703です。良かったー。

### インストール
できました。

### Windows Update →失敗
再起動すると22H2になるみたいなところまで行きますが、再起動しても22H2になりません。
「はまりポイント3」です。
ここも調べると先人がいらっしゃいました。

「コントロールパネル」→「電源オプション」→「詳細な電源設定の変更」
↓
「PCI Express」→「リンク状態の電源管理」
これを全部「オフ」にするそうです！

しかも、Windows Updateでなく、メディアからupdateするとのこと。


### InsiderProgram
自分は、MSのInsider Programに入っています。
最初にダウンロードした22H1のISOデモ大丈夫だったのかもしれませんが、ダメだった記憶から なんとなくInsiderのダウンロードサイトから、雰囲気で19045.1826のISOをダウンロードしていました。
これを、WORKのパーティションに保存しました。

### ISOのSetupからバージョンアップ
ISOをダブルクリックすると、マウントされますので、Setupを起動します。
あとは、指示通りに、進みます。

### Windows Update
なんとなく、そのままイキオイでupdateを繰り返したら、22H1になりました。
ちゃんとメモってなかったのですが、19045.1826って、２1H1だったかもです。
Windows詳しくないので、そこまで調べてません・・・・


## Boot Camp のインストール
記憶あいまいですが、これは、このタイミングではなく。1709をインストールしたあとにBootCampをインストールしたかもです。


# 完成

めでたしめでたし。

でも、グラフィックが遅いですね・・　いやいやメモリが4GBなのが問題かも・・
フォートナイトいれたら、カクカクで、止まっているうちにやられます。
前に投稿した、iMacのほうがグラフィック性能がいいです。一応フォートナイトできますので・・。

# 今後

なんとか、Windows 11にしたいと思いますが、とりあえずは、2台のMacをWindows化したので、一旦休憩ですかね・・
SSMセッションマネージャーでのログイン時に自動でbashを叩こうとしたら大失敗してた

## 前書き
SSMセッションマネージャからログインするとき、デフォルトでは Bourne Shell (sh) で接続することになります。これをbashに変更したくていろいろトライしていたのですが、失敗してしまったので備忘録として残しておきます。

## 成功例
本来はめちゃくちゃ簡単にできます。

https://dev.classmethod.jp/articles/ssm-session-manager-change-bash-shell/

こちらの記事にあるように
１，SSMのセッションマネージャー  >　設定　>　編集　を順にクリック
２，対象のshell profileに「/bin/bash」と書く

これだけでOKです。


## 何を失敗したのか
実は以前にも同様の機能を実装しようとしたことがありました。その際に、実験として/home/ssm-user/.bashrc配下にエイリアス(その時はalias k='kubectl')を記述し、bashを読み込むとエイリアスが使えました。ただし、一度セッションが切れてしまうとそのエイリアスは使えませんでした。

そこで、/home/ssm-userを開くたびに、/home/ssm-user/.bashrcを読み込めばいいのではないか？と思いました。ここまではよかったのですが、ここでなぜか/home/ssm-user/.bashrcにsource ~/.bashrcと書けばよいのではないか？と思ってしまいました。

こんな感じです↓
```

h-5.2$ cat .bashrc
# .bashrc
alias k='kubectl'
source ~/.bashrc

・・・

```

今思えば読み込まれてないファイル内で自身のファイルを読み込もうとしている意味不明なコードですが、当時はこれで思った通りのことができる！しかもちょっと前まで意味不明だったシェル触れてる！と浮かれていました。

しかし、当然こんなことを書いても自動で/home/ssm-user/.bashrcは読み込まれませんでした。

そしてそのあとの行動が良くなかったのですが、ほかの作業は特に問題もなく進められたのでこのコードを放置してしまっていました。


## 数か月後
AWSでのインフラ構築も慣れてきて、自分のタスクに少しゆとりが出てきたころにkubectl completion（kubectlで使うコマンドをタブ補完できるツール）を導入することになりました。

その前段階としてSSMセッションマネージャからログインするときに自動でbashが使えるようにしようとしました。上記の記事を見つけて余裕をましていたところ、こんなエラーが出てきてしまいました。

```
/bin/bash
sh-5.2$ /bin/bash
Segmentation fault (コアダンプ)
```


エラーが出てるものの、まあ調べれば何とかなるだろうと思い「SSM　セッションマネージャー　Segmentation fault (コアダンプ)」などで調べてみるも全くヒットせず。

GPT先生に聞いてみると、メモリアクセスやスタックのオーバーフローなどの可能性があると言われました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/87094ae1-0db7-3908-5cae-540acaeb5224.png)

ちょっとよくわからない領域に話が進みだして、これは時間がかかってしまうかも...といういやなセンサーが働き始めました。

実験として、ほかのインスタンスでも同じような状況になるかと思い試してみましたが、問題ありませんでした。また、ssm-userではなくrootで当該インスタンスに入り込んだ時も問題なくbashが使えました。

さらに、メモリの容量も確認してみても余裕がありました。

これは詰んだか...?と思っていた時に数か月前に.bashrcをいじっていたことを思い出しました。そういえばsource ~/.bashrcって書いていたな......
もしかしてループしてる？？だからオーバーフローしてるんじゃない？？と思いつき、この記述を消すとうまくいきました！

ちなみにkubectl completionは以下を参考にすると一瞬で利用できるようになりました

https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/#kubectl%E3%81%AE%E4%BB%BB%E6%84%8F%E3%81%AE%E8%A8%AD%E5%AE%9A

# 感想
今回の失敗をもとに感じたことを4つ挙げようと思います

## うまくいかなかったときは元の状態に戻す
bash自動で読み込めてなさそうやけどほかの機能には影響がないからまあいいや、の精神が数か月後の自分の作業時間を数時間奪ってしまいました。とくに、チーム開発では他者のコードが自分の開発作業に影響してしまうということがあります。実験するのはよいことですが、うまくいかなかったときはきちんと元の状態に戻しておきましょう。

## 始めてやることはまず検索する
今回の失敗はちょっとLinuxを理解し始めて不用意に.bashrcをいじってしまったのが問題でした。.bashrcをいじる前に「SSMセッションマネージャー　bash」などで検索するだけでこの失敗は避けられていたので、今後はまず先人たちの知恵に頼ることにします。
　
## 検索しても解決策が出てこないエラーはその前段階で問題があることが多い
今回はSSMセッションマネージャ特有の問題ではなく、~/.bashrcにsource ~/.bashrcと書いてあることが問題でした。まずは検索することが大事ですが、検索してもめぼしい記事がなかった時はもっと前の段階で問題が発生していることが多いです。特に、以前違和感があったもののほったらかしにしていた何かがあるときはそいつが悪さをしている可能性大です。

## エラー解消は知識を身につけるチャンス
tech系の記事だけでなく、ChatGPTなどの生成系AIが台頭している現代では手順通りにやればそれなりに動く成果物ができます。ものすごくありがたい反面、なんとなく自分の技術として身についている感覚がないのも事実です。エラー解消は同じ文言のエラーでも状況によって解決策が違うことが多いので、自分が必要なエラー解決手順を探すのに一苦労します。すこし骨が折れることもありますが、その分起きたエラーやその周辺の知識は普通に記事を読むより何倍も体にしみこんでいると思います。エラー解消は成長のチャンスだと思って必死に解消しましょう。自力で解決できるとめちゃくちゃ気持ちいいです。
Switchbotで家の各場所の温度を測ってみた

# はじめに
以前、会社の機器の使用電力を取るついでに作っていたままだったのですが、家でもAmazonセールを機に SwitchBot 防水温湿度計を導入してみました。思ったより便利だったので家の各所へ温湿度計を置いて比較するものをつくってみました。
使うのは下記のみです。
- [SwitchBot 防水温湿度計](https://www.amazon.co.jp/gp/product/B0BVMJR34G/)
- [SwitchBot ハブミニ](https://www.amazon.co.jp/gp/product/B07TTH5TMW/)
- Google Spreadsheet
    - Google Apps Script (GAS)で値を取得します

## SwitchBot を使えるようにしておく
- iPhone, Android どちらでも良いのでアプリでセットアップしておく
    - 防水温湿度計はハブミニ経由でクラウドへデータが上がるようにしておく
- アプリ上でAPI用のトークンとclient secretを取得する
    - 詳しくは [【API】新バージョンAPI v1.1を公開しました](https://blog.switchbot.jp/announcement/api-v1-1/) をご覧ください

## GASでSwitchBot APIを呼び出す
SwitchBot API v1.1 へ対応したAPI呼び出しをGASで行うコードを公開しておきます
[7032/gas_switchbot/class_SwitchBot.gs](https://github.com/7032/gas_switchbot/blob/main/Class_Switchbot.gs)

### スクリプトプロパティの設定
1. スプレッドシート→拡張機能→Apps Script (またはスタンドアロンスクリプト)で GAS プロジェクトを作成する
1. 以下のスクリプトプロパティを設定する

| プロパティ名 | 設定する値 | 
|:----:|:----:|
| clientID | トークン |
| clientSecret | トークンと同時に払い出された client secret |


### SwitchBotクラス使い方

#### インスタンス生成
```javascript
const oSwitchBot = new SwitchBot();
```

#### SwitchBot クラスのメソッド
- *メソッド名* `callApiWithPath`
- *機能* API の呼び出し 
```javascript
callApiWithPath(method,url,payload,header)
```
- 引数

| 引数 | 値 |
| :---- | :---- |
| method | HTTP のメソッドを指定。次のいずれか。 `GET` `PUT` `POST` `DELETE` |
| url | 呼び出すAPIのURLを指定。例)  `"https://api.switch-bot.com/v1.1/devices/"` |
| payload | `POST` や `PUT` 利用時に付与するPayloadを指定。`GET` の場合は `null` としておく。 |
| header | API 呼び出し時にヘッダへ付加情報を漬けたい場合に指定。殆どの場合は `null` でOK |

#### 呼び出し例

```javascript
const result = oSwitchBot.callApiWithPath("GET","https://api.switch-bot.com/v1.1/devices/",null,null);
```

あとはGASで好きな様にAPIを呼んで値を呼び出したり、時間で起動するトリガーを設定して定期的に値を取得するなどすれば温度・湿度の監視が出来ます。

GAS API のリファレンスは [OpenWonderLabs/SwitchBotAPI](https://github.com/OpenWonderLabs/SwitchBotAPI) をどうぞ

こんな感じで気温・湿度を拾ってみると良いでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2998428/4097a7b8-c816-08bf-d29d-894402cec58b.png)
Github Actionsを使ってキャッシュが"Cache not found for input keys"が出てた件

# 前提
Github Actionsを使いキャッシュを作成するメリットについて、[Github Docs](https://docs.github.com/ja/actions/using-workflows/caching-dependencies-to-speed-up-workflows#:~:text=GitHub%20%E3%83%9B%E3%82%B9%E3%83%86%E3%83%83%E3%83%89%20%E3%83%A9%E3%83%B3%E3%83%8A%E3%83%BC%E4%B8%8A%E3%81%AE%E3%82%B8%E3%83%A7%E3%83%96%E3%81%AF%E3%80%81%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%81%AA%E3%83%A9%E3%83%B3%E3%83%8A%E3%83%BC%20%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%A7%E9%96%8B%E5%A7%8B%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%81%8C%E3%80%81%E4%BE%9D%E5%AD%98%E9%96%A2%E4%BF%82%E3%82%92%E6%AF%8E%E5%9B%9E%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B%E3%81%9F%E3%82%81%E3%80%81%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E5%88%A9%E7%94%A8%E7%8E%87%E3%81%8C%E5%A2%97%E5%A4%A7%E3%81%97%E3%80%81%E5%AE%9F%E8%A1%8C%E6%99%82%E9%96%93%E3%81%8C%E9%95%B7%E3%81%8F%E3%81%AA%E3%82%8A%E3%80%81%E3%82%B3%E3%82%B9%E3%83%88%E3%81%8C%E9%AB%98%E3%81%8F%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)には以下の記載がある
> GitHub ホステッド ランナー上のジョブは、クリーンなランナー イメージで開始されますが、依存関係を毎回ダウンロードする必要があるため、ネットワークの利用率が増大し、実行時間が長くなり、コストが高くなります。

自分の所属している企業でもテストを書く文化が根付いてきており、それに伴いテスト実行時間が無料枠である[月2000分](https://docs.github.com/ja/billing/managing-billing-for-github-actions/about-billing-for-github-actions#:~:text=500%20MB-,2%2C000,-GitHub%20Pro)を超えてくることが度々生じてきました
その一環として自分もキャッシュを利用してcomposerでインストールされるファイル一式をキャッシュとして保存し、開発者の時間と無料枠の節約を行おうと思い導入していましたが(15~25秒の節約)、タイトルにもある"Cache not found for input keys"というエラーが吐かれてしました

## 吐き出されたエラー
actions/cache@v3というアクションを使用してしていたのですが以下のようなエラーが吐かれていました
![スクリーンショット 2023-08-20 18.42.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715563/26cab3ed-64dc-e1cc-4b84-2b2b8242efa9.png)

## 原因と解決策
答えは[公式ドキュメント](https://docs.github.com/ja/actions/using-workflows/caching-dependencies-to-speed-up-workflows#:~:text=%E3%82%B8%E3%83%A7%E3%83%96%E3%81%8C%E6%AD%A3%E5%B8%B8%E3%81%AB%E5%AE%8C%E4%BA%86%E3%81%99%E3%82%8B%E3%81%A8%E3%80%81%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF%20path%20%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%82%92%E5%90%AB%E3%82%93%E3%81%A0%E6%96%B0%E3%81%97%E3%81%84%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%82%92%E8%87%AA%E5%8B%95%E7%9A%84%E3%81%AB%E4%BD%9C%E6%88%90%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)に書かれていました
> ジョブが正常に完了すると、アクションは path ディレクトリのコンテンツを含んだ新しいキャッシュを自動的に作成します。

つまりジョブが正常に完了しなければ、キャッシュを作成しないということです

今回の場合は先ほどの画像を見ても分かる通り、"Run PHPUnit"が失敗しているためジョブが正常に完了しておらず、その後の"Post Cache composer dependencies"の処理がスキップされています
その結果キャッシュが保存されないため、次回の実行でもキャッシュが見つからなくなっていました
![スクリーンショット 2023-08-20 18.42.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1715563/79eb0f25-09ac-0082-0656-32af34a84f51.png)

適切にキャッシュが保存された場合にはこの"Post Cache composer dependencies"のなかで、"Cache saved successfully"と出力されます
Azure App Serviceを自分なりに整理

# App Serviceとは
Web アプリケーション用に最適化されたフル マネージド ホスティングサービス

参考：サービス比較
https://learn.microsoft.com/ja-jp/azure/container-apps/compare-options


# App Serviceの構成

参考：App Service を構成する主要な要素とそれぞれの役割
https://azure.github.io/jpazpaas/2023/05/10/Appservice-components.html

### Scale Unit
- Data Centerの中にScale Unitというサーバー群が複数存在する
- Scale Unit内にはApp Service PlanとApp Serviceを構成するコンポーネントが配置されている
- Scale Unit内は複数の顧客のApp Service Planが同時に実行されている
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476893/084e2215-049d-3de4-b3ee-7bb5f1f6e1ed.png)
    
    

### FrontEnd
- 受け取ったリクエストをリクエストの内容に応じてそれぞれのApp Service Planに振り分ける
- 1つのスケールユニット内に FrontEnd は複数存在する
- 各FrontEndは独立実行されApp Serviceとの個別の紐づきはない

### File Server
- App Serviceで使用する共有ストレージを管理
- 複数の Worker インスタンス間で共通的に使用できるストレージとして、ローカルストレージ内の home という名称でネットワークストレージが付帯する
- 各アプリで実行されるファイルに関する読み取り/書き込みは全て File Server を通して行われる


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476893/dff3080b-4ed4-ddd6-aa27-4a0e48cacbf6.png)

### Application
- 各アプリは App Service Plan のインスタンス内で実行され、スケールアウトもその単位で行われる
- CPU やメモリなどのコンピューティングリソースは、App Service Plan のインスタンス内で実行されている**各アプリが共用して使用**している
- いずれかのアプリが大量にCPU やメモリを使用した場合、 同一インスタンス内の別のアプリも影響を受ける可能性がある 

App Service Plan の最大アプリ数目安
https://learn.microsoft.com/ja-jp/azure/app-service/overview-hosting-plans#should-i-put-an-app-in-a-new-plan-or-an-existing-plan

| App Service プラン SKU | 最大アプリ数 |
|:-----------|:------------|
| B1、S1、P1v2、I1v1  | 8 |
| B2、S2、P2v2、I2v1  | 16 |
| B3、S3、P3v2、I3v1  | 32 |
| P0v3                | 8 |
| P1v3、I1v2          | 16 |
| P2v3、I2v2、P1mv3   | 32 |
| P3v3、I3v2、P2mv3   | 64 |
| I4v2、I5v2、I6v2    | vCPU 使用率に制限される最大密度 |
| P3mv3、P4mv3、P5mv3 | vCPU 使用率に制限される最大密度 |
Image Scan! For Linux の 使い方

# はじめに
- EPSON製のスキャナー（GT-S600）をLinuxのコマンドラインで操作する方法をメモします。

# 動作環境
- Ubuntu 22.04.2 LTS
- Image Scan! For Linux (Ver. 2.30.4)

# Image Scan! For Linuxのコマンド
## デフォルトでのスキャンの実行
```:Linux
scanimage > image.pnm
```
注：リダイレクションでファイル名を指定しないとエラーになります。

## オプションを指定してスキャンの実行
```:Linux
scanimage --device-name=epkowa --format=tiff --depth=16 --resolution=600 > image.tiff
```
- デバイスのリストを得るには以下を実行
```:Linux
scanimage -L
```
### 注意点
- 本来はビット深度--depth=16（デフォルトでは8）で撮影したいが、勝手にスキャナー側でエラーになります。
- そこで以下のコードで実行する必要があります。

```:Linux
scanimage --device-name=epkowa --format=tiff --resolution=600 > image.tiff
```

# マニュアル
- 詳しいコードについては以下を実行すると参考になります。
```:Linux
man scanimage
```
```:Linux
scanimage --help
```


# おわりに
実際にスキャンを自動化したいというニーズは少ないかもしれませんが、できると便利な研究分野があったりします。

# 参考文献
https://download.ebz.epson.net/dsc/search/01/search/

https://www.takutek.net/Articles/Gadget/UbuntuPrinter.html
macターミナルのmySQLで謎の->が出てきて抜けられなくなったら

①create database
②show databases
とか入力して、
->という謎の記号が出てきてエンターキーとかexitとかquitとか何を押しても抜けられない！

そんなときは ;
を入力してエンターキーを押せば解決します。

私の解釈ですが、どうやら①や②は命令文が終わっていないみたいんだと思われます。

つまり、mySQLの -> を人間語に訳すと、

mySQL: 「ほんで、何なん？」
という感じだと思います。笑

でもこっちからしたら、
「いや、もう終わりやで？」

なので、SQLで命令文の終わりを表す
;
を入力してあげればOKってことみたいです。
ZTE Speed USB Stick U03 を Linux で使う

## はじめに
au および UQ モバイルから発売された USB 接続の LTE モデム、 ZTE Speed USB Stick U03 について、 Linux で使うための情報があまりなかったので備忘録として書いておきます。

この機種は au 回線の nano SIM を挿入することで 4G/LTE 通信が行えます。 APN さえ設定すれば au のサブブランドである UQ モバイルの SIM カードも使用できるため、かなり使い勝手が良いです。

この手のものは古くは L-03D がよく使われていて、情報もよくまとまっていた印象があります。ただ、全く同じ設定ではうまくいかなかったので、有志の情報を頼りに設定を行いました。


## 設定
udev と usb_modeswitch の両方を設定する必要があります。
この手のドングルは最初に CD-ROM として認識されて、その後 eject するとイーサネットとして認識されることが多いようですが、この機種では eject するだけではイーサネットとして認識されませんでした。なので usb_modeswitch の設定が大事なようです。

### udev の設定

**/etc/udev/rules.d/50-zteu03.rules**
```/etc/udev/rules.d/50-zteu03.rules
# ZTE MF871A (U03)
ATTR{idVendor}=="19d2", ATTR{idProduct}=="1484", RUN+="usb_modeswitch '/%k'"
```

### usb_modeswitch の設定

**/etc/usb_modeswitch/19d2:1484**
```
#### Speed USB STICK U03
DefaultVendor=0x19d2
DefaultProduct=0x1484
TargetVendor=0x19d2
TargetProduct=0x1483
MessageContent="5553424312345678000000000000061b000000020000000000000000000000"
MessageContent2="55534243876543212000000080000c85010101180101010101000000000000"
NeedResponse=1
```

（こちらの情報を使わせていただきました: [楽天モバイルで固定回線代用 Part.21 W無](https://lavender.5ch.net/test/read.cgi/phs/1635838257/?v=pc#:~:text=USB%E3%83%89%E3%83%B3%E3%82%B0%E3%83%AB%E3%80%80%E3%80%8C%20Speed%20USB%20STICK%20U03%E3%80%80%E3%80%8D) より）


以上の設定を行うことで Linux 上でデバイスがイーサネットとして認識されました。


## 余談
設定なしの状態では Linux 単体で通信が始まりませんでしたが、 VirtualBox 上の Windows で認識された後は Linux 側でも問題なく通信できていました。（Linux 単体でのやり方が分からなかったときは毎度 Windows を立ち上げていました）
[GIMP]Unityで表示する画像用の枠をGIMPで作る

# 概要
Unity上で画像に枠をつけたい時、GIMPで作成する方法の一例です。
# 本文
## 最初の準備
サンプルでいらすとやさんから画像をお借りしました。サイズは586x761です。
![otaku_girl_fashion.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/f2f6606e-2cbb-a94f-50a1-7c559611eecf.png)
GIMPを起動して新規画像を作成します
**ファイル → 新しい画像**
元画像と同じサイズを指定して、塗りつぶし色は「透明」にしてください。
![スクリーンショット 2023-08-20 17.01.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/fdcf2478-cd0b-e77a-746b-5114d0568da1.png)
## 背景画像の作成
**選択 → すべて選択**
**選択 → 角を丸める**
半径で角の丸みを適度に設定します。（今回は10にしました）
![スクリーンショット 2023-08-20 17.02.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/8d272b84-9419-0cc3-9d70-f183c1f5b0dd.png)
スクショのように選択範囲の四隅が丸くなります。バケツツールで画像中央部分をクリックして白色で塗りつぶします。
![スクリーンショット 2023-08-20 17.03.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/51e3b417-25e6-49cd-bb3f-482b48903f5f.png)

背景画像を保存しておきます。今回は「QiitaBackground.png」にしておきました。
**ファイル → 名前を付けてエクスポート**
## フレーム画像の作成
先程の選択状態のままで
**選択 → 選択範囲の縮小**
画像枠の厚みを設定します。今回は10pxにしました。
![スクリーンショット 2023-08-20 17.04.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/42162f5c-9d33-9b38-7926-816acec6bc20.png)
枠の内側が選択状態になっているのでそのまま中身はくり抜いて透明にしておきます
**選択 → 消去**
![スクリーンショット 2023-08-20 17.04.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/aad0434f-4cdf-a401-4245-1917a3ede3fe.png)
フレーム画像ができたので保存します。今回は「QiitaFrame.png」にしておきました。
**ファイル → 名前を付けてエクスポート**
## Unityでの作業
今回用意した３枚の画像をUnityに取り込んで
![スクリーンショット 2023-08-20 17.49.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/c1d7adcd-4562-3e3d-b784-c3cff36900ab.png)
このようにImageを並べると画像に丸みのついた縁をつけることができました:raised_hands_tone2:
![スクリーンショット 2023-08-20 17.49.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/fc224e3a-9548-dcf1-19a5-053d3e830df5.png)


# 補足
最初の設定では以下のように全部真っ白になりますので
![スクリーンショット 2023-08-20 17.08.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/5f6ebdb2-dc14-4204-b3da-99775300c5fe.png)
背景画像のImageコンポーネントで色をいい感じに調整してください。
![スクリーンショット 2023-08-20 18.06.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/8bffff4a-407f-e2d9-5c95-76ec0f754f14.png)


# 補足２
取り込んだ画像データの設定がうまくいかないときは以下の設定を参考にして違う部分を修正してみてください。
![スクリーンショット 2023-08-20 17.05.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/75cd6db3-8750-f09d-1d2b-ef35031615de.png)

# 補足3
シンプルな手順を書きましたが、枠を色柄にしたりグラデーションをつけたり、アニメーションさせたりと色々応用できると思います！
ユビキタス社会に向けてーインターフェイスの革新ー

## まず初めに
この記事はまだまだペーペーである筆者が自分の考えていたことを後から見直せるように、考えていることを言語化して整理するために書いているものです。なにか勉強になる記事を求めている方は別の記事を読むことを推奨します。

## ユビキタス社会

今の自分の考えに基づき定義します。
この記事においてユビキタス社会とは、コンピュータシステムが人間の明確な指示がなくても自律的に動作し、人間の意識下、非意識下の両方で生活を円滑、最適化出来るようにサポートしてくれている社会と定義します。

## 人間の意識下、非意識下

技術が発展していくほど人が意識するものはどんどん高次の物へと移り変わっていきます。例えば、自動ドアなんかが分かりやすい例だと思います。自動ドアにも小さなコンピュータが搭載されていてセンサで人を感知し適切にモータを回すことでドアの開閉を行っていますが、多くの人はそんなことは意識していません。建物に入るためにドアに近づくことでドアが開くという認識しか持っていません。これは決して悪いことというのではなく、技術の発展により人間の生活が便利になったということです。この便利になるという事の本質的な意味は、人間の脳に置いておかないといけないことを減らし、より高次なものへ脳のリソースを使うことが出来るようになることだと考えます。この例から分かるように、ユビキタス社会の定義で述べた生活を円滑、最適化することは、なるべく人間の意識下に置かないといけないことを非意識下に移行することと考えられそうです。ただし、すべて非意識下でコンピュータが動いているのでは、それはコンピュータに人間の生活を制御されているのと同じであり、あくまでも人間の意思によって行うことを非意識下でサポートすることが重要と考えます。

## インターフェイスの限界

従来のコンピュータへのインターフェースとして代表的なものにGUIがあります。GUIの開発は直感的にコンピュータを操作出来るようになったという意味で革新的な開発でした。しかし、ユビキタス社会を実現するうえではGUIによって行われる情報のやり取りには"情報量"という観点で限界があると考えます。この問題を解決するインターフェースは自然言語の"対話"によるインターフェースであると考えます。この考えを持ったのは、ChatGPTが公開されたときでした。上記のように限界があると考え、何か新しいインターフェースを構築できないかと考えていた時に、ChatGPTが公開され、コンピュータに対して自然言語という情報が圧縮されたものを用いて操作出来ることに感動を覚えました。

## 自然言語の凄さ

とある有名な言葉で「人類最大の発明は"言葉"である」というものがあります。これは、人間は言葉を発明したことで抽象的な事を思考したり表現する能力を獲得し、またこれを後世に残すことが出来るようにしたというものです。僕は"情報量"という観点で、抽象的な事を表せるようになったという事が一番価値が大きいと考えます。世の中に存在するものすごい情報量のものを言葉という短いものに圧縮し、これをつなげることで文脈としてコミュニケーションすることを可能にしたのです。数学の厳密さと自然言語の表すあいまいな概念を比較するとこの"情報量"の多さが分かりやすいと思います。(数学も現実世界の情報を圧縮してあらわしているのですが)こんな多くの情報量を含んだ自然言語を扱う事が出来るのが、ChatGPTで有名なLLMの技術であり、この技術によるインターフェースで既存のソフトウェアは大きな進化を遂げることが出来ると考えます。

## LLMの凄さ

自分は自然言語処理に全く詳しいわけではないのですが、そんな視点から、LLMの最も革新的な所は、言語を理解しているように振る舞う事が出来ることだと考えます。これはすなわち、言語という短いものを使って複雑な概念、意図をコンピュータに伝えることが出来るという事を意味します。また、"対話"が出来ることにより意思の伝達ミスなどを修正していく事が出来ます。これにより、上述の"情報量"の観点でインターフェースに革新を生めると考えます。

## LLMをインターフェースとして使う

一括りにインターフェイスと言っても、LLMが役割を果たすインターフェースは二種類あると考えます。人とコンピュータのインターフェース、そしてコンピュータとコンピュータのインターフェースです。まず、人とコンピュータのインターフェースについては既に述べている通り、LLMは"対話"によって"情報量"に革新を起こせると考えます。面白いのは、コンピュータとコンピュータのインターフェースの方です。今まであまり無かった概念なのではないかと思います。LLMが基盤となり、まるで知能をもった人間のように大きなタスクを実行するために下流のソフトウェアへ処理を流し、時には下流のソフトウェア駆動でコンピュータたちが自立的に連携して動作していく、そうして人の非意識下で人をサポートする。そんな未来を期待したいし、僕自身もそんな世界で価値のあるエンジニアとなれるよう頑張っていきたいです。
pythonで型宣言すると便利だった

# はじめに
プログラミングをしていると、「この変数の型ってなんだっけ？」と疑問に思うことがしばしばある。
特に、大規模なプロジェクトやチームでの開発時に、変数や関数の挙動を正確に把握することは非常に重要である。
CやTypeScriptのように、型を定義できると視覚的にわかり静的型付け言語の良さを感じる。
Pythonでも型を明示的に宣言するとどうなるのか試してみたところ、これが予想以上に便利だったので皆さんに共有したい。

# 対象者
- Pythonを書く上で、変数の型を明示的にしたい方
- CやTypescriptのような静的型付け言語の書き方に慣れている方
- 型の不一致でのバグを早く気づきたい方

# 型宣言例

```python
# 型宣言の基本
name: str = "Alice"
age: int = 30
pi: float = 3.141592653589793

# どんな型でもOKなany型
anything: any = "Data"

# リストやタプルの型宣言
numbers: list[int] = [1, 2, 3, 4, 5]
person: tuple[str, int] = ("Bob", 25)

# Numpyの型も宣言できる
import numpy as np
array: np.ndarray = np.array([1, 2, 3])

# 関数にも型宣言
def greet(person_name: str) -> str:
    return "Hello, " + person_name

# 実際の使用例
print(greet(name))

```
## 型宣言の説明

- 基本型: str, int, float などの基本的な型はそのまま変数の後に: <型名>として定義できる。

- any型: 特定の型を持たない変数にはany型を使う。これにより、変数がどんな型でも受け入れることができる。

- リストやタプル: リストやタプルに対する型宣言は、内包する型も合わせて表現する。例えば、list[int]は整数のリストを表す。

- Numpyの型: Numpyの主要な型であるndarrayも、型宣言の対象として利用できる。これにより、計算やデータ分析のコードも型の安全性を高めることが可能。

- 関数の型: 関数においては、引数の型と戻り値の型の両方を宣言することができる。これにより、関数の振る舞いをより明確にすることができる。

# TypeScriptと同じでは？
Pythonの型宣言に触れていると、「これってTypeScriptと似ているのでは？」と思うかもしれない。確かに、PythonとTypeScriptは型を明示するという点で共通している。しかし、Pythonでは型宣言が実行時の挙動に影響を与えないのに対し、TypeScriptでは型の矛盾があるとコンパイルエラーが出る点で大きく異なる。このような違いから、それぞれが独自の言語環境での最適な型システムを提供しているのが分かる。

# まとめ
Pythonの型宣言を導入することは、コードの可読性や保守性の大きな向上をもたらす。このメリットは、個人開発から小規模チーム開発まで幅広く感じられる。型宣言を使用することで、変数や関数の期待する型を明示的に示すことができ、それにより後のデバッグやコードの改善が容易になる。さらに、Numpyなどのライブラリでの型定義もサポートされているため、さまざまなシチュエーションで利用することができる。

結論として、コードの可読性を向上させるために、Pythonで型宣言を活用することは非常に価値があると実感した。


# 参考
[typing --- 型ヒントのサポート](https://docs.python.org/ja/3/library/typing.html)
MacのFinderでターミナルを開く

# 参考サイト様
MacのFinderでは、空のファイルを作成したりすることができません。
そのため、terminalで開いてからtouchでファイルを開こうと思いました。ですが、Finderで現在いる階層でterminalを開く方法がありません。terminalを開いてから、cdコマンドで移動するしかありませんが、いささか面倒です。そこで以下のサイト様を参考にさせていただき、Finderからterminalを開けるようにいたしました。
詳細に記載されておりますので、サイト様のリンクを記載させていただきます。

https://daeudaeu.com/finder-terminal/
Swiftでfor文を使って配列の順番を変更する方法。

# 読んで欲しい人
・Swift詳しい方。
・この問題を解く前の私。

# 注意！
・[AtCoderのA - Rotateのネタバレあり。](https://atcoder.jp/contests/abc197/tasks/abc197_a)
# 学んだこと
・標準入力から文字列を配列として受け取る。
・配列の要素を追加や削除をしない場合はletでも良い。今回は配列を入れ替えの操作のみ。
・for文でiを利用し、指定した添字（インデックス）を出力する。
・改行しないで出力する方法。

# ACしたコード
```swift
// Array()で標準入力から文字列を配列として受け取る。
let s = Array(readLine()!)
// print(s)
// 添字を利用したいからiを利用し、添字にアクセスできるようにする。
for i in 0..<3 {
    if i != 0{
// terminator: ""で改行しないようにしている
        print(s[i],terminator: "")        
    }
}
//print()には改行が含まれている。    
print(s[0])    
```
<b>標準入力</b>
abc
<b>標準出力</b>
bca

# いいコードにしてみる
・for文でcountプロパティに変更して3文字以外でも動くコードにする。
```swift
let s = Array(readLine()!)
// print(s)
for i in 0..<s.count {
    if i != 0{
        print(s[i],terminator: "")        
    }
}
print(s[0])    
```
<b>標準入力</b>
abc
<b>標準出力</b>
bca

# 実験してみた。
・標準入力に,区切りの整数が与えられた場合、空白区切りで出力、最後の文字のみ改行をして出力する方法。
<b>入力例</b>
1,2,3,4,5,6,7,8,9,10
<b>出力例</b>
2 3 4 5 6 7 8 9 10 1
```swift
// 標準入力から整数を一行受け取る。
let input = readLine()!
print(input)
// 標準入力で受け取った整数を,区切りで配列にする。
let numSplit = input.split(separator: ",")
print(numSplit)
// 配列の要素数の合計値
print(numSplit.count)
// 0から10（配列の要素数の合計）の間、添字が0以外の時、空白区切りの改行無しで出力する。
for i in 0..<numSplit.count {
    if i != 0{
        print(numSplit[i] + " ",terminator: "")   
    } 
}
// 添字の0番目を出力する。
print(numSplit[0])    
```
<b>標準入力</b>
1,2,3,4,5,6,7,8,9,10
<b>標準出力</b>
1,2,3,4,5,6,7,8,9,10
["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
10
2 3 4 5 6 7 8 9 10 1





# 参考にした記事
・[```改行を含めない方法 terminator: ""```](https://capibara1969.com/1351/#:~:text=terminator%3A%20%E3%81%A7%E7%B5%82%E7%AB%AF%E6%96%87%E5%AD%97%E3%82%92,%E3%81%99%E3%82%8B%E4%BA%8B%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)
・[プロパティ、countの使い方](https://www.choge-blog.com/programming/swiftarraycountget/)
gitignoreしていないのに変更・追加した差分が認識されない


# 発生した現象
`rails-react-matching-app`というリポジトリ内で
`backend`というディレクトリを作成し色々とファイルを追加したのですが、
いざgitで差分を確認すると`backend`というディレクトリしか認識されておらず、
その中に追加されたファイルの差分は出ていませんでした。

以前にもハマってその時はなんとか解決したのですが、
解決方法を忘れてしまい2度目のハマりポイントだったので記事にしようと思いました。

## 実行したコマンド
新規リポジトリを作成した後、
ディレクトリと諸々のファイルについてはこんな感じのコマンドで作成しました。

```plaintext
$ mkdir backend && cd backend
$ touch Dockerfile docker-compose.yml entrypoint.sh Gemfile Gemfile.lock
```

## 実際の状態のスクショ
こんな状態でした。

`backend`というディレクトリの差分は出ているのですが、
中身のファイルについては何一つ差分が出ておらず。

![スクリーンショット 2023-08-20 16.19.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259490/21d2f4b5-706c-7db7-8d77-917593243e04.png)

もちろんまずは`.gitignore`の設定を疑ったのですが、
特にいじってなく、実際に無視するように設定していませんでした。

## `.gitignore`の状態
`backend`配下を無視する設定はないです。
Rails newした際に自動で作成されたもので、全くいじってません。

![スクリーンショット 2023-08-20 16.22.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259490/288cc96b-0ffd-1394-dd41-8860ee980723.png)


# 原因
[こちら](https://chico-shikaku.com/2020/08/git-ignore-add-or-change-file/)の記事が解決の糸口になりました。

> Gitリポジトリの管理下に、さらに他のGitリポジトリがあるとき、浅い階層ではその他のGitリポジトリに置かれているファイルを感知しません。

結論、**backendディレクトリ下に`.git`ディレクトリが存在していた**ことが原因でした。

今回は`rails-react-matching-app`というディレクトリを作成しており、
その配下に`backend`というディレクトリを新規作成したのですが、
その`backend`ディレクトリ配下に`.git`ディレクトリが存在していたことが問題でした。

`backend`ディレクトリ配下に`.git`ディレクトリが存在していたため、
`rails-react-matching-app`の中にさらに別のGitリポジトリがあると認識されてしまい、
`backend`ディレクトリの中の差分は認識されなかったということになります。

`.git`は隠しフォルダなのでなかなか気づけませんでした。


##  無事差分が出ました
上記より、`.git`がなければ他のリポジトリだと認識されないので、
単純に`.git`を削除することで解決できました。

![スクリーンショット 2023-08-20 17.09.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259490/0f288b4c-f163-19cf-b80b-22496427e210.png)

# 参考
https://chico-shikaku.com/2020/08/git-ignore-add-or-change-file/

.gitディレクトリとは？という方はこちら。

https://yakst.com/ja/posts/3811
Dockerについて

初めまして。
駆け出しエンジニアのtamura1225です。
7月からエンジニアとして働き始めて、もうすぐ2ヶ月が経とうとしています。
仕事では常に新しいことを身に付けていかなければいけないので大変ですが、その分楽しくもあり、日々成長を感じる毎日です。

今回は仕事をしていく中で勉強したことを、きちんと自分で理解できているか確認するため、また他の駆け出しエンジニアの方でよく分からないなと思っている人に向けて（そこまでの内容を書けるかは分かりませんが）記事を書いていこうと思っています。
もし間違ったことを書いているようでしたらご指摘いただけると勉強になります。


初回である今回はDockerについてまとめていこうと思います。


# Dockerとは
Dockerとは何なのでしょうか。
僕みたいに情報学を学んだわけでもなく、エンジニアも未経験という方はDockerという言葉すら聞いたことないかもしれません。
僕は仕事して初めて知りました。

とりあえずwikiからコピペしてみます。

> Docker（ドッカー）は、コンテナ仮想化を用いてアプリケーションを開発・配置・実行するためのオープンプラットフォームである。
> [Docker - Wikipedia](https://ja.wikipedia.org/wiki/Docker)

よく分からないので、1つ1つ見ていきましょう。

### 言葉の確認
+ コンテナ仮想化
コンテナ仮想化とはコンピュータの中にコンテナと呼ばれる隔離された環境を作ることです。
このコンテナの中で例えばアプリケーションを開発したりします。
コンテナを使う理由としてはいくつかありますが、そのうちの1つに複数人で開発する場合に同一の環境を構築しやすいというのがあります。
どうでも良いですが、Dockerのアイコンはクジラにコンテナが載ってますね。
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328423/77210267-3f12-a82b-80f4-4452dbeaa557.png">


+ オープンプラットフォーム
プラットフォームとは、具体的な説明は難しいのですが、ハードウェアやソフトウェアの基礎的な部分となるものです。
ここでは、アプリケーションを開発・配置・実行するための土台のようなイメージだと思います。
また、ここでいうオープンとはオープンソースのことだと思われます。

つまり、少しくどく言うとDockerとは
「コンピュータの中にコンテナと呼ばれる隔離された環境を作り、アプリケーションの開発・配置・実行を行う土台となるもの。」
となります。


（これはただの感想ですが、何かを説明しようとすると、それを指し示す良い表現が見つからない事があります。これは、もちろん個人の知識不足というのもありますが、共同意識による定義のない言葉であるからというのもあり、後者に関しては使っていくうちにイメージを理解していくしかないのかなと思っています。）


何となく理解はできた気がしますが、言葉だけみても何のことかさっぱりだと思うので、次回はDockerを実際に使ってみようと思います。


# 参考文献・サイト
[Docker](https://www.docker.com)
[Docker - Wikipedia](https://ja.wikipedia.org/wiki/Docker)
[コンテナ型仮想化 - IT用語辞典 e-Words](https://e-words.jp/w/仮想化.html#Section_コンテナ型仮想化)
[プラットフォーム - クラウド・データセンター用語集/IDCフロンティア](https://www.idcf.jp/words/platform.html)
Rust入門者必見！標準入出力の全てをこの記事で解説

# 目的
- 競技プログラミングでの問題解決の効率が良くなること
- ECサイトなどでの複雑な入力方法に対処できるようになること

## 1行で1個の文字列の場合
### 文字列を1行から読み取り、そのまま出力するシンプルな例です。

例
入力：hello
出力：hello

```Rust
use std::io::stdin;
fn main(){
    let a = input();
    println!("{}",a);
}
fn input()->String{
    let mut a = String::new();
    stdin().read_line(&mut a).unwrap();
    return a.trim().parse().unwrap();
}
```
## 1行で1個の数字の場合
### 1行から数字を読み取り、3倍して出力します。

例
入力：3
出力：9

```Rust
use std::io::stdin;
fn main(){
    let a = input();
    println!("{}",a*3);//三倍
}
fn input()->isize{
    let mut a = String::new();
    stdin().read_line(&mut a).unwrap();
    return a.trim().parse().unwrap();
}
```
## 1行でN個の文字列を空白で区切って配列にする場合
### 1行から複数の文字列を読み取り、配列に変換します。
例
入力：a b c d
出力：["a", "b", "c", "d"]

```Rust
use std::io::stdin;
fn main(){
    let a = input();
    println!("{:?}",a);
}
fn input()->Vec<String>{
    let mut a = String::new();
    stdin().read_line(&mut a).unwrap();
    return a.trim().split_whitespace().map(|e| e.parse().ok().unwrap()).collect();
}
``` 
## 1行でN個の数字を空白で区切って配列にする場合
### 1行から複数の数字を読み取り、それぞれ3倍して配列に変換します。
例
入力：1 2 3 4
出力：[3,6,9,12]

```Rust
use std::io::stdin;
fn main(){
    let mut a = input();
    a  = a.iter().map(|x| x*3).collect();//三倍
    println!("{:?}",a);
}
fn input()->Vec<usize>{
    let mut a = String::new();
    stdin().read_line(&mut a).unwrap();
    return a.trim().split_whitespace().map(|e| e.parse().ok().unwrap()).collect();
}
```
## N行でN個の文字列を空白で区切って配列にする場合
### 複数行から複数の文字列を読み取り、二次元配列に変換します。
例
入力：
おはよう　こんにちは　こんばんは
Goodmorning Goodafternoon Goodevening
出力：
[["おはよう", "こんにちは", "こんばんは"],
["Goodmorning", "Goodafternoon", "Goodevening"]]

```Rust
use std::io::stdin;
fn main(){
    let mut vector = Vec::new();
    loop{
        let mut a = input();
        if a.len() == 0  {
            break;
        }
        vector.push(a.clone());        
    }
    println!("{:?}",vector);
}
fn input()->Vec<String>{
    let mut a = String::new();
    stdin().read_line(&mut a).unwrap();
    return a.trim().split_whitespace().map(|e| e.parse().ok().unwrap()).collect();
}
```
## N行でN個の数字を空白で区切って配列にする場合
### 複数行から複数の数字を読み取り、それぞれ3倍して二次元配列に変換します。
例
入力：
1 2 3
4 5 6
出力：
[[3, 6, 9],
[12, 15, 18]]

```Rust
use std::io::stdin;
fn main(){
    let mut vector = Vec::new();
    loop{
        let mut a = input();
        if a.len() == 0  {
            break;
        }
        a = a.iter().map(|e| e*3).collect();
        vector.push(a.clone());
    }
    println!("{:?}",vector);
}
fn input()->Vec<usize>{
    let mut a = String::new();
    stdin().read_line(&mut a).unwrap();
    return a.trim().split_whitespace().map(|e| e.parse().ok().unwrap()).collect();
}
```
esp8266modモジュール書き込み

<h1>ESP8266に簡単に書き込む方法</h1>
<p>esp8266modのモジュールを買ったのはいいもののどんなに調べても出てこないので被害者が増える前にここに書いておく</p>
<p>モジュールとUSBでつなぐ（画質が絶望的でごめんなさい)

![WIN_20230820_17_22_11_Pro.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535657/93fcd7e5-87a1-302e-be0c-0cc12d6c5876.jpeg)
<p>繋げたらIDEを起動してモジュールのcomに設定する(不明っていう名前がそうだ)

![スクリーンショット 2023-08-20 171633.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535657/de66b4cd-c6f8-d180-6c6d-497bac4f3f67.png)
<p>この画面になったらespectro coreを検索して</P>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535657/659dc092-d27a-76e4-dbde-8692bbbbc671.png)

<p>espectro coreがでてくるのでそれを選択すると書き込みができるLちか確認済み
Azure環境へのSQL移行方法

<h1>AzureへのSQL移行方法</h1>
<br>
Azure環境にSQLを移行する場合、下記の3種類があります。
<ul>
    <li>Azure SQL Managed Instance</li>
    <li>Azure SQL Database</li>
    <li>仮想マシンにSQLサーバーデータベースをインストールする</li>
</ul>

<br>

<h2>Azure SQL Managed Instance</h2> 
<br>
特徴…幅広いSQLデータベースエンジンとの互換性(Enterprise　Edition SQL 
Serverデータベースエンジンとの100%近い互換性がある。)。フルマネージドサービスとしてもプラットフォームのすべての利点を兼ね備えている。クエリ実行もSQL Serverと同様の方法で実行可能。
構成…インスタンスにリソースを割り当て、インスタンス内に各データベースを作成する」という構成

<h2>Azure SQL Database</h2> 
<br>
構成…論理サーバの管理単位の中にデータベースが作成。各データベースが独立している。(PaaSモデル)
<br>
<h2>VMにSQLをダウンロード</h2> 
<br>
構成…VMにSQLをダウンロード。SQL ServerとOSを自由に触れることができる。

<br>　<a href="https://zenn.dev/arairyus/articles/8435812be68b39">参考リンク</a>
【GAS】API関連の実装方法まとめ

# はじめに
弊社ではGAS(GoogleAppsScript)を使用して色々自動化しているのですが、GASの処理内でAPIを叩いたりすることもあります。
例えばQiitaのAPIなどもGAS上で叩いていたりするのですが、今回は備忘録的にGAS上でAPIを叩く手順からデータを取得するまでの処理をまとめておこうと思います。

# APIの叩き方
まず叩く際はUrlFetchApp内のfetch関数を使用する形でAPIを叩きます。

```
val jsonResponse = UrlFetchApp.fetch("APIのURL")
```
上記で疎通が可能です、非常にシンプルですね。
次に、受け取ったレスポンスがJSONだった場合にパースする必要があるので、以下手順によりパースします。

```
const jsonObject = JSON.parse(jsonResponse)
```

以上になります。
上記でパースができた状態なので、あとは以下のようにキーを指定して欲しいデータを取得するだけです。

```
const data = jsonObject["欲しいデータのキー"]
```

以上です。
これでAPIを叩いて欲しいデータを取得することが可能です。
非常にシンプルで良いですね！

# さいごに
無駄な手間をかけない為にもできる限り自動化していきたいところですね！
需要があればBitriseやGithubActionsなどの設定に関しても記事にしていきたいと思います。
Rubyでコマンドラインのオプションを扱う"optparse"の使い方

## optparseとは
Rubyでコマンドライン引数を扱うための標準ライブラリです。

例えば、test.rbというファイルを実行するとして、`ruby test.rb -a 100`のようにコマンドライン引数で値を渡すことができます。`-a 100`の中身はファイル内で使用することができます。

今回は説明の題材として、コマンドライン引数から二つの値を受け取り、合計値を返すシンプルなプログラムを作成します。

## optparseの使い方

1. OptionParser オブジェクト opt を生成する。
2. オプションを取り扱うブロックを opt に登録する。
3. opt.parse(ARGV) でコマンドラインを実際に parse する。

[library optparse (Ruby 3.2 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/library/optparse.html:embed:cite)より引用

### 1. OptionParser オブジェクト opt を生成する。

```ruby:sum.rb
require 'optparse'

opt = OptionParser.new
```
`require 'optparse'`でライブラリを読み込み、変数optにOptionParserクラスから生成したインスタンスを格納しています。このインスタンスに対して操作を加えることでオプション引数を扱えるようになります。

## 2. オプションを取り扱うブロックを opt に登録する。

```ruby:sum.rb
require 'optparse'

opt = OptionParser.new

opt.on('-a') {|v| p v }
opt.on('-b') {|v| p v }
```
OptionParser#on メソッドの引数でオプション`-a`と`-b`を定義し、引数が指定された時の処理をブロック` {}`内に記述します。ただしこの時点ではブロックは実行されません。実行されるのは後述するOptionParser#parseが呼ばれた時です。

### 3. opt.parse(ARGV) でコマンドラインを実際に parse する。
OptionParser#parse!を使い、コマンドラインの解析を行います。以下を追記して`ruby sum.rb -a 10 -b 20`を実行します。
```ruby:sum.rb
require 'optparse'

opt = OptionParser.new

opt.on('-a') {|v| p v }
opt.on('-b') {|v| p v }

opt.parse!(ARGV)
p ARGV
```
``` :結果
["10", "20"]
```
コマンドライン引数の値を取得することができました。

ちなみに`opt.parse(ARGV)`とすると値だけでなくオプションも取得することができます。
``` :結果
["-a", "10", "-b", "20"]
```

## 引数の合計値を返す
二つの整数を受け取りその合計を返すプログラムを作成します。

```ruby:sum.rb
require 'optparse'

values = []

opt = OptionParser.new
opt.on('-a int') {|v| values << v.to_i }
opt.on('-b int') {|v| values << v.to_i }

opt.parse!(ARGV)

sum = values.sum
puts "sum :#{sum}"
```

`opt.on('-a int') {|v| values << v.to_i }`ここでは、-aで受け取った数値をブロック内でvalues[]という配列に格納しています。受け取った値は文字列となっており、このままだと計算処理を行えないため`to_i`メソッドでIntagerへ変換しています。この処理は`opt.parse!(ARGV)`時点で実行されます。

その後sumメソッドでvalues[]の合計を算出しています。

無事実装できているか次のコマンドでテストしてみましょう。
`ruby sum.rb -a 10 -b 20`
10 + 20なので30が出力されればOKですね。

``` :結果
sum :30
```

無事出力されました。

以上がrubyのoptparseを使ってコマンドライン引数を扱う手順となります。

## 参考記事
[library optparse (Ruby 3.2 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/library/optparse.html:embed:cite)
【機械学習】学習タスクや手法メモ

## 概要
こんにちは、chikaといいます。
今回は論文探しするなかで耳にした学習の種類、手法についてメモしようと思います。
状況に応じて追記するかもです。

調べたい内容を「キーワード」にまとめてます。

## CV領域
### Object Detection(物体検出)
物体の位置＋物体の種類を検知するタスク
「この画像のこの部分に人が移ってるよ！」っていうのを教えてくれる
物体が複数映ってても検出してくれたりする。

キーワード：YOLO、R-CNN、SSD、DETR（Transformer）

### Classification(画像分類)
画像に映ってる物体の種類を分類するタスク
2クラス分類だったり、多クラス分類だったりする

キーワード：VGG、ResNet、DenseNet、MobileNet、BCE（損失関数）

### Semantic Segmentation(領域分割)
画像のピクセル単位でラベル付けをして学習するタスク

わかりやすい説明　→　[セマンティックセグメンテーション - MATLAB & Simulink](https://jp.mathworks.com/solutions/image-video-processing/semantic-segmentation.html)

### Continual Learning(継続学習)
分類問題とかで、犬猫を分類できるようになったモデルに対して、鳥を学習させると犬猫の特徴を忘れてしまう現象が発生する（これを破壊的忘却という）
いままで学習した内容を忘れずに学習することを目的としている

### Contrastive Learning(対照学習)
自己教師あり学習の１つ
特徴量が似たデータは近くなるように、似てないデータは遠くなるように学習する

参考→[【初学者向け】対照学習（Contrastive Learning）とは？](https://aiacademy.jp/media/?p=1096)
キーワード：SimCLR、PCL、BYOL

### Few-shot Learning（FSL）
良い精度のモデルを作ろうと思ったら膨大な学習データが必要となるが、これは少ない画像データで効率的に学習する手法
他にもzero-shotも存在する

参考→[Few-shot Learning : 少ない画像データで学習する【前編】](https://tech.gmogshd.com/few-shot-learning/)

### 用語：Augmentation（データ拡張）
データを変形させたり、増やしたりする前処理のこと。
画像を切り取ってみたり、別の画像貼ってみたり、画像を重ねてみたり…
諸事情でモデルのアーキテクチャをあまり変えたくない場合はここを頑張ってる

参考→[データ拡張 (Data Augmentation) [画像向け]](https://cvml-expertguide.net/terms/dl/regularization/data-augmentation/)

## 余談と感想
Transformerといったアーキテクチャを画像分類に用いたVision Transformerが出現するなど、自然言語処理分野で使用されたアーキテクチャをコンピュータビジョンの分野で使うこともある。
なるべくトレンドは追っておきたい。

■参考
[画像認識の大革命。AI界で話題爆発中の「Vision Transformer」を解説！](https://qiita.com/omiita/items/0049ade809c4817670d7)
自己情報量　交差エントロピー（Cross-Entropy）　KL情報量（Kullback-Leiblerダイバージェンス）

# 自己情報量

自己情報量
自己情報量は、ある特定の事象が発生する確率に基づいて、その事象がどれだけ「驚くべき」または「予想外」であるかを測る尺度です。数学的には、事象 x の自己情報量 I(x) は以下のように定義されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531332/b626f8dc-fd0c-0c1d-d9bd-9018e1369dc6.png)


ここで、P(x) は事象 x が発生する確率です。自己情報量は、事象が起こる確率が低いほど大きくなります。つまり、予想外の事象ほど、自己情報量は大きくなります。


# エントロピー
エントロピーは、確率分布全体の「不確実性」または「予測の困難さ」を測る尺度です。自己情報量の期待値として定義されます。確率分布 P のエントロピー H(P) は以下のように定義されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531332/13b4233e-45db-0642-22cc-5ceaea99c86a.png)

エントロピーは、確率分布の中でどれだけ多くの事象が高い確率で発生するか、またそれらの事象がどれだけ均等に発生するかに依存します。エントロピーが高いほど、確率分布全体の予測が困難であると言えます。


# 交差エントロピー


交差エントロピー（Cross-Entropy）は、情報理論と機械学習の分野でよく使用される概念です。特に、分類問題の損失関数としてよく使われます。

エントロピーとは
エントロピーは、情報の不確実性や乱雑さを測る指標です。例えば、コイン投げの結果が表か裏かという2つの選択肢がある場合、どちらが出るかは完全に不確実です。このような状況のエントロピーは高いと言います。

交差エントロピーとは
交差エントロピーは、2つの確率分布の間の「違い」を測る指標です。具体的には、ある真の確率分布と、それを近似しようとするモデルの確率分布との間の違いを測ります。

数式での表現
交差エントロピーは以下の数式で表されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531332/55768a39-b5d8-2881-2c2d-80da8ea361ff.png)


ここで、y は真の確率分布（正解ラベル）、


​![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531332/b2788efc-c392-264f-5ac0-9586fc3f06c7.png)はモデルによる確率分布（予測ラベル）です。

機械学習での利用
分類問題において、交差エントロピーは損失関数としてよく使用されます。

モデルの予測が正解に近いほど、交差エントロピーの値は小さくなります。逆に、予測が正解から遠いほど、値は大きくなります。

なぜ交差エントロピーを使うのか
交差エントロピーを使う理由は、モデルの予測が正解にどれだけ近いかを効率的に評価できるからです。予測が正解に近づくほど、損失が急速に減少し、学習が効率的に進行します。

まとめ
交差エントロピーは、2つの確率分布の間の違いを測る指標で、機械学習の分類問題でよく使用されます。モデルの予測が正解にどれだけ近いかを効率的に評価するために使われ、学習の進行を促進します。



# KL情報量（Kullback-Leiblerダイバージェンス）

KL情報量は、2つの確率分布の間の「違い」を測る尺度です。交差エントロピーと似ていますが、こちらはある確率分布を別の確率分布で近似する際の「情報の損失」を測ります。

数式で表すと以下のようになります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531332/4d43ab46-469c-7981-df45-daf010d25517.png)


ここで、
P は真の確率分布、
Q は近似したい確率分布です。この値が0に近いほど、2つの分布は似ていると言えます。

# 交差エントロピーとKL情報量の違い

交差エントロピー: 真の分布 P とモデルの分布 Q の間の違いを直接測ります。

KL情報量: 真の分布 P をモデルの分布 Q で近似する際の情報の損失を測ります。

実際には、KL情報量は交差エントロピーとエントロピー（真の分布の自己情報量）の差として表現されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531332/45ed4eea-e26a-0adc-83be-2fbb30f8f0d7.png)


ここで、H(P) は真の分布 P のエントロピーで、データ自体の不確実性を表します。

# ベイズ推定

ベイズ推定は、統計的な推定の一手法で、確率的な不確実性を取り入れた推定方法です。ベイズ推定では、事前の知識（事前分布）と観測データを組み合わせて、パラメータの確率分布（事後分布）を推定します。

ベイズ推定の基本的な考え方は以下の3つのステップからなります。

事前分布の設定: パラメータに対する事前の信念や知識を確率分布で表します。
尤度関数の計算: 観測データが与えられたときのパラメータの尤もらしさ（尤度）を計算します。
事後分布の計算: 事前分布と尤度関数を組み合わせて、パラメータの新しい確率分布（事後分布）を計算します。これが最終的な推定結果です。
Pythonで文字列から絵文字を処理する demoji

# ライブラリ
https://pypi.org/project/demoji/

# 使い方
### 例文
```python
s = "「目標達成日誌」をつけると成功確率がアップ！🐶👨👩👦"
```
### 辞書型に変換する　findall(string: str) -> Dict[str, str]
```python
demoji.findall(s)

{'👨': 'man', '🐶': 'dog face', '👩': 'woman', '👦': 'boy'}
```
### リストに変換する　findall_list(string: str, desc: bool = True) -> List[str]
```python
demoji.findall_list(s)

['dog face', 'man', 'woman', 'boy']
```
### 絵文字を置換する　replace(string: str, repl: str = "") -> str
```python
demoji.replace(s, " :cat")

'「目標達成日誌」をつけると成功確率がアップ！ :cat :cat :cat :cat'
```
### 説明を追記する　replace(string: str, repl: str = "") -> str
```python
demoji.replace_with_desc(s, " animal:")

'「目標達成日誌」をつけると成功確率がアップ！ animal:dog face animal: animal:man animal: animal:woman animal: animal:boy animal:'
```
Maker Nanoを使う

Arduino Nano Everyを使って遊び慣れたので、勇気を出してArduino互換機とうたっている「Maker Nano」を使ってみました。

## 起動してみる
Maker NanoはUSBケーブルをつなぐとビルドインLEDがチカチカ光り、あのメロディが流れ、テンションが爆上がります。ビクビクしてましたが、初期不良は大丈夫そうです。

## ブザーをミュートする
あのメロディが流れる仕様、最初は楽しいですが3回くらい聞くと飽きるので、Muteしましょう。
ミュートスイッチはUSBケーブルと逆のスイッチで、基板をよく見るとスピーカーオフのアイコンが描かれています。このへんの遊び心も楽しいですよね。

## USBドライバをインストール
さっそくLEDチカチカプログラムを書き込みます。
自分の場合ですが、ただUSBケーブルでつないで`Arduino IDE`を起動すると、ボード欄には「不明」となりますが、ボードマネージャーでArduino Nano を選択します。

またこれだけだとプログラムの書き込みに失敗するので、CytronのオフィシャルWebsite（ https://www.cytron.io/p-maker-nano-simplifying-arduino-for-projects ）を見てみると、
```
CH34X driver
(Please ensure that Maker Nano is connected to the computer's USB port during driver installation)
```
と記載がありますので、こちらをインストールしましょう。
インストール後、再びArduino IDEにてプログラムが書き込めるようになりました。
【Android】文字入力時のキーボード操作のメモ【Kotlin】


# はじめに
Editテキスト入力時のキーボードの操作でエンターキーやバックキーなどのアクションキーが押された時の処理を完全に覚えきれず、何度も調べながら実装するのが面倒になったので　特に使いそうなものを自分の記事に残しておこうと思いました。
# 実装
自分用なのでかなり簡単にではありますが、以下が実装内容です。

     editText.setOnKeyListener(View.OnKeyListener { _, action, event ->
            if (event.action == KeyEvent.ACTION_DOWN) {
                if (action == EditorInfo.IME_ACTION_DONE) {
                    // Enterが押された
                }

                if (action == KeyEvent.KEYCODE_DEL) {
                    // バックスペースが押された
                }
            }
            false
        })

# 参考

https://developer.android.com/reference/android/view/inputmethod/EditorInfo


https://android.suzu-sd.com/2020/07/edittext_action_button_de_tsuuchi/



https://qiita.com/sw20na6se3p/items/948cd59111aaa9d10656
非エンジニアがAI系のプロダクトの営業を受けた時に知っておいた方がいい単語などのメモ

わたしは社で使用するツールを決定する立場ではないのですが、最近は営業さんから「Chat GPTを使った〜」とか「AIを使った〜」などといったプロダクトの提案をされることが増えているような気がします。
そんな時に、出てきそうな単語をまとめました。上司のためにまとめたのですが、もじもじして渡せなかったので、ここに置いておこうと思います。

# 出てきそうな単語
*  GPTとは
Generative Pre-trained Transformer（GPT）のことで、トランスフォーマーと呼ばれるニューラルネットワークを使って、モデルが節の次の単語を予測して作り出す事前訓練を行う
* chatGPT
自然言語（普通の話し言葉）で使用できる、そしてチャット形式で会話ができるテキスト生成AIサービス。
* autoGPT
ChatGPTのさらなる自動化を目指す。ユーザーは目標を入力するとChatGPTと連動し、その目標を達成するための行動を自ら考え、実行する。
ゴール設定が自動
回答を記憶している
調べた内容の記録も可
目的はタスクの自動化
*  baby agi
AGI(Artificial General Intelligence:汎用人工知能の略。
通常、chatGPTで狙いたい回答を得るには複数回のやり取りをする必要がある、これを自動的に複数回のやり取りをしてもらって最適解を得る
* prompting
望ましい行動がより生起されやすくするために、手がかり刺激（プロンプト）を与える方法。AI にタスクを指示すること。
* prompt engineering
より望ましい回答を得るためのプロンプティング技術。
Qiita CLIのテスト（メール来たから試してみた）

# 書いてある通りやりゃいい、けど、、、
```bash
🔰qiita    $ npx qiita publish aboutinterface.md
(node:15333) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Error: 'aboutinterface.md' is not found
```

というエラーが。

aboutinterface.mdというファイルはねぇよという。いや、あるっちゅうねんってはなしなんですが、拡張子が入ってるからダメ。

拡張子は入れずにコマンドは打つべし！

# タグの複数指定
```markdown
tags:
  - cli
  - test
  - テストテスト
```
Linuxディレクトリ

# Linuxのディレクトリ操作について

今、Linux使っているのですが初心者過ぎてよく分かっていないので書いて記録に残してみます。

### よく使うコマンド一覧

|コマンド|説明|
|:---:|:---:|
|pwd|カレントディレクトリのパスを表示する|
|cd ディレクトリ名|カレントディレクトリの移動|
|mkdir ディレクトリ名|ディレクトリの作成|
|rmdir ディレクトリ名|ディレクトリ削除。(ディレクトリが空でないと削除できない。)|
|rm -r ディレクトリ名|ディレクトリが空でなくても削除できる。|


---

①トップは`ルートディレクトリ`「/ (root)」
②`カレントディレクトリ`自分の現在地。pwdで現在地確認できます。
```
$ pwd
```
【Unity】プレハブモードで表示した Prefab の履歴を管理する Editor 拡張

# 概要
プレハブモードで表示した Prefab の Prefab名をボタンで表示し、クリックするとことで再度プレハブモードで Prefab を表示する Editor 拡張です。
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531721/9e663638-fe0e-63c8-9597-88783c0186a6.gif)

# 詳細
プレハブモード関連のコールバックに、PrefabStage.prefabStageOpened というものがあり、このコールバックに履歴の更新、window の更新を設定します。

# コード全文
```csharp
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;

public class PrefabHistoryWindow : EditorWindow
{
    private static PrefabHistoryWindow window;

    [MenuItem( "Window/Prefab History" )]
    private static void Open()
    {
        window = GetWindow<PrefabHistoryWindow>();
    }

    private static void AddHistory( PrefabStage prefabStage )
    {
        if( window == null )
        {
            Open();
        }

        var guid = AssetDatabase.AssetPathToGUID( prefabStage.assetPath );
        var history = window._histories.FirstOrDefault( h => h.guid == guid );
        if( history != default )
        {
            window._histories.Remove( history );
        }
        window._histories.Add( new( Path.GetFileName( prefabStage.assetPath ), guid ) );
        window.Repaint();
    }


    [SerializeField]
    private List<(string name, string guid)> _histories = new();
    private Vector2 _scrollPosition;


    private void OnEnable()
    {
        PrefabStage.prefabStageOpened += AddHistory;
    }

    private void OnGUI()
    {
        _scrollPosition = EditorGUILayout.BeginScrollView( _scrollPosition );


        foreach( var history in _histories.AsEnumerable().Reverse() )
        {
            using( new EditorGUILayout.HorizontalScope() )
            {
                var asset = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( history.guid ), typeof( GameObject ) );
                if( asset == null )
                {
                    continue;
                }

                if( GUILayout.Button( history.name, GUILayout.ExpandWidth( true ) ) )
                {
                    AssetDatabase.OpenAsset( asset );
                }
            }
        }


        EditorGUILayout.EndScrollView();
    }

    private void OnDestroy()
    {
        _histories.Clear();
        PrefabStage.prefabStageOpened -= AddHistory;
        window = null;
    }
}
```

# リファレンス
https://docs.unity3d.com/ja/2021.3/ScriptReference/SceneManagement.PrefabStage.html
【C++】vectorで特定の要素を削除（removeはeraseと組み合わせて使う）

C++のvectorで特定の要素を削除する際に用いるremove関数は、erase関数と組み合わせて使うと安全。

## remove関数だけ用いる場合
remove関数は、指定した要素を取り除くことができる。
第一引数、第二引数でイテレータで範囲を指定して、第三引数に削除したい要素を指定する。
```C++
vector<int> vec = {1, 0, 2, 0, 3, 0, 4, 0};
auto newEnd = remove(vec.begin(), vec.end(), 0);
for(auto it=vec.begin(); it != newEnd; ++it){
    cout << *it << " "; // 1 2 3 4
} 
```
通常、remove関数の戻り値が取り除いた後の有効領域の末尾の次を指すイテレータを返すので、それを用いて続きの処理を行う。

## remove関数の注意点
しかし、関数実行後のコンテナに注目してみると、実際には取り除かれた分が前に詰められるだけで、後ろの要素は無効領域として残ったままになる。

```C++
vector<int> vec = {1, 0, 2, 0, 3, 0, 4, 0};
remove(vec.begin(), vec.end(), 0); // {1, 2, 3, 4, 3, 0, 4, 0}
/* （「3, 0, 4, 0」の部分が無効領域として残る） */
```

つまり、取り除いた後も**コンテナサイズ自体は変わらない**。
コンテナサイズが変わっていないことに気づかずに、end関数や範囲for文を用いて処理を継続すると想定しないエラーを引き起こしてしまうかもしれない。

## erase関数と組み合わせて使う
remove関数実行後の無効領域をerase関数で完全に削除しておくと安全。
```C++
vector<int> vec = {1, 0, 2, 0, 3, 0, 4, 0};
auto newEnd = remove(vec.begin(), vec.end(), 0);
vec.erase(newEnd, vec.end());
for(auto e: vec){ // 範囲for文も使用できる
    cout << e << " "; // 1 2 3 4
} 
```
こちらの方が、要素を取り除いた後の末尾のイテレータ・コンテナサイズが更新されるので、誤って無効領域にアクセスしてしまうことも未然に防ぐことができる。