OmniAICreator/Qiita-1.07M huggingface dataset:
MT法でIrisデータ分析

# 投稿した経緯
実験計画法や品質工学の勉強をしていて、パターン認識の手法としてMT法を学んだので自分の復習した内容を投稿しようと思います。

#MT法
MT法はマハラノビス・タグチシステムのことで、マハラノビス距離と呼ばれるデータの変数間の相関を用いて導出されるマハラノビス距離によりパターン認識を行う手法となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386581/dd1fb918-ea5f-9596-4f72-270e650cb54f.png)

上の図のように、サンプルにしたデータから単位空間を作り、マハラノビス距離を求めると点Aと点Bのような一見単位空間の距離の変わらないようなデータの識別が可能になります。

# MT法への疑問
データ分析の経験が少ないため、データの各変数に相関があるという認識がなく本当にパターン認識やデータ分類ができるのか疑問に思いました。
そのためデータ分類のテストとして用いられるIrisデータの分析を行い、確認しようと考えました。

#データ分析の結果
setos種のデータ50個を単位空間にして分析したところ、残り二種を以下の閾値

$$　\sqrt{p +　\frac{3 \sqrt{2 p}}{p} }  $$

$p$:変数の数 4個

$$　\sqrt{4 +　\frac{3 \sqrt{8}}{4} } \simeq 2.47  $$

で判別しました。

結果その他の2種のデータ100個のデータを全て判別することができました。

# 今後のやりたい内容
よくわかるMTシステムで読んだ内容では、MTシステムは多重共線性など数学的な条件が多いため、MT法を利用する場合は初めにT法を適用すべきと書かれている。そのため、T法や計算処理の少ないRT法でのデータ分析を行いと考えています。


# 参考
MT法計算方法
MTシステム （マハラノビス・タグチシステム） ～品質工学におけるパターン認識～
https://note.com/macrok/n/n93a12d88882d
田村希志臣著:「よくわかるMTシステム 品質工学によるパターン認識の新技術」,日本規格協会

閾値の決定
MT システムの研究　永田 靖
https://core.ac.uk/download/pdf/143641129.pdf
2023.7.23 Flutter TODOアプリ進捗

FlutterでTODOアプリ作成進捗メモ

⚫︎追加ボタン（ElevatedButton）を押すと
　TextFieldに入力した文字がTODOの項目として追加される。

![スクリーンショット 2023-07-23 12.21.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3388746/ebc445eb-f4ff-f911-08ef-44d14eef517f.png)

![スクリーンショット 2023-07-23 12.23.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3388746/a8ac5d69-5752-7420-207b-2e4d5e79a547.png)

![スクリーンショット 2023-07-23 12.24.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3388746/e06f66c7-f0a2-2d00-e66a-9efe607c066c.png)


ソースコード
main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}
class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> todoList = []; //予め// リストを作っておいて追加画面で入力された文字を追加していく

@override
Widget build(BuildContext context) {

final myController = TextEditingController();

  return Scaffold(
      appBar: AppBar(
        title: const Text('リスト画面一覧'),
      ),

    body:Column(
      mainAxisAlignment: MainAxisAlignment.center,//中央揃え
      children: <Widget>[
      Row(
        children: <Widget>[
          Flexible(
            child: TextField (
              controller: myController,
              decoration: const InputDecoration(
                labelText: 'TODO',
              ),
                style: const TextStyle(fontSize: 18),
            ),
          ),
          ElevatedButton(
            onPressed: ()  {
              final newListText = myController.text; //FloatingActionButtonを押すと追加画面に遷移
              setState(() {
                todoList.add(newListText); //その文字をtodoListに追加する
              });
            },
            child: const Text("追加"
            )
          ),
        ]
      ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Expanded(
              child: SizedBox(
                height: 350,
                child: ListView.builder(
                  //動的にListViewを作る
                  itemCount: todoList.length, //渡された数だけ作成
                  itemBuilder: (context, index) {
                    return Card(
                      child: ListTile(
                        title: Text(todoList[index]
                        ),
                      )
                    );
                  }
                ),
              ),
            )
          ]
        )
      ]
    )
  );
}
}

参考URL
https://zenn.dev/kotopasi/scraps/3b977edca92357

★ListViewの表示エラーが出た時の対処法
・ListViewの外側にExpandedのWidgetを追加すると、表示できた。
https://qiita.com/umi_mori/items/fb7b67a5c5bb3dda927e
interfaceの定義

プロジェクトのなかにinterfaceが記述されていたので、抽象クラスとの違いを復讐を兼ねてメモする。

抽象クラスは頭に`abstract`、その後に`class クラス名`を記述する。
抽象クラスは抽象メンバ以外に、コンストラクタ引数や、具体的なメンバも定義できる。
ただし、抽象クラスそのものをインスタンスを生成することはできない。
```kotlin
abstract class Business(val name: String){
    abstract var stores: Int
    abstract fun make(some: String): String
    abstract fun sell(item: String): String

    val employees: MutableList<String> = mutableListOf()
    fun employ(employee: String){
        println("${employee}を雇った")
        employees += employee
    }
}
```
> [[Kotlin]抽象クラスとインターフェイスの定義方法](https://pouhon.net/kotlin-interface/3357/)から引用

インタフェースは頭に`interface`をつけて定義する。抽象クラスとは違い、抽象メンバに`open`や`abstract`は不要。算出プロパティの値を参照するためのカスタムゲッターは必須。

```kotlin
class Company(name: String): Enterprise{
    override var stores = 20

    //未完成のメソッドならTODO関数もアリ
    override fun make() {
        TODO("Not yet implemented")
    }

    override fun sell(item: String) = println("${item}を売ります")
}
```
> [[Kotlin]抽象クラスとインターフェイスの定義方法](https://pouhon.net/kotlin-interface/3357/)から引用



#### 参考

https://pouhon.net/kotlin-interface/3357/
Googleフォームと独自HPの連携方法

<h1>Googleフォームと独自HPの連携と確認画面の実装方法</h1>
<p>下記のサイトを活用して実装。</p>

<a href="https://zenn.dev/yurukei20/articles/9741118bfb5ee0">①Google FormをHTML/CSSでデザインしたフォームで運用する方法</a>

<a href="https://lacublog.com/google-form">Googleフォームを自作フォーム(HTML)に紐づけする方法</a>

<a href="https://mixltd.jp/blog/g-form-customize/">Googleフォームと自作フォームを連携させる方法</a>

<a href="https://mixltd.jp/blog/g-form-customize02/">Googleフォームと自作フォームを連携させる方法.2「確認画面と完了画面の作成」</a>

<p>編集途中です。</p>
Laravel Sailを使った開発環境で、phpmyadominエラー

**環境**
macOS Ventura
Laravel Framework 10.15.0
Docker version 24.0.2, build cb74dfc
mysql  Ver 8.0.32 for macos13.0 on x86_64 (Homebrew)

**現象**
Laravel　sailを使った開発環境で、phpmyadominエラー

phpMyAdominを起動するために下記を追加したが、繋がらない。
```
    phpmyadmin:
        image: phpmyadmin/phpmyadmin
        links:
            - mysql:mysql
        ports:
            - 8080:80
        environment:
            #PMA_USER: "${DB_USERNAME}"
            #PMA_PASSWORD: "${DB_PASSWORD}"
            PMA_HOST: mysql
```




**行ったこと**
.envの内容確認(DB_HOST、DB_USERNAME、DB_USERNAME)
dockerのvolumeやimageの削除(余計なvolumeやimageがあると動かないらしい、、、)
DB_USERNAMEとDB_PASSWORDの確認
phpMyAdominを使いたかったので、docker-compose.ymlにphpMyAdominの内容を追加


**エラー内容**

 MySQL サーバにログインできません

 mysqli::real_connect(): php_network_getaddresses: getaddrinfo for mysql failed: Name or service not known

 mysqli::real_connect(): (HY000/2002): php_network_getaddresses: getaddrinfo for mysql failed: Name or service not known

直訳
php_network_getaddresses: mysql の getaddrinfo が失敗しました: 名前またはサービスが不明です

mysqli::real_connect(): (HY000/2002): php_network_getaddresses: mysql の getaddrinfo が失敗しました: 名前またはサービスが不明です


![スクリーンショット 2023-07-21 13.24.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474793/b641d77c-e402-5c56-5c04-e32dbb2345fb.png)

```
    phpmyadmin:
        image: phpmyadmin/phpmyadmin
        links:
            - mysql:mysql
        ports:
            - 8080:80
        environment:
            #PMA_USER: "${DB_USERNAME}"
            #PMA_PASSWORD: "${DB_PASSWORD}"
            PMA_HOST: mysql
        networks:
            - sail

```

docker-compose.ymlの設定ミスでした。
networks:
    -sailを追加後
無事接続成功！！

networksは、ハブのようなものなので、機材に繋げないとそもそも繋がらないので今回、ハブに繋げないで、phpMyAdominを利用しようとしていたことになります。
なので、エラーで教えてくれていました。その上でエラーを読み直すと、サービス名が不明ですというエラーを理解できます。

これは、メンターさんに相談して解決しました！！！
１日かかったのが、1分で解決した、、、、、、、、笑　
神です。
Vueの勉強②

入力した文字を反映させる
v-modelについて
v-on v-bindをまとめて一行で書くためのシンタックスシュガー。
※シンタックスシュガー（糖衣構文）とは
構文と等価でかつ人間に読み書きしやすい構文
調べれば調べるほど用語が、、、、、、

取り敢えず入力したものを反映させるコードです
※一部省略してます

```
<script setup>
import { ref, computed } from "vue";

const message = computed(() => {
  return "ようこそ ' + name.value + 'さん";
});
const name = ref('');
</script>

<template>
  <p>お名前は? : <input type="text" size="30" v-model="myname"></p>
  <p v-html="message" </p>
</template>
```

更新するためには　ref('')　を使うみたいです。
ちなみにrefを使った変数を使う際には.valueを使わないといけないそうです。

個人的に動きがある言語は書いていて楽しいです。
#0005 macでのzip化で余分はファイルが紛れ込む。

## はじめに
- macでfinderからzip化をしたファイルを、windowsで展開すると、`__MACOSX`や`.DS_Store`が紛れ込んだ。
- windows環境のお客様にzipファイルを送付し、展開頂いた際に、「これらはファイルは何ですか？」と聞かれ、「無視してください」というしかなかった。
- これらのファイルを避けてzip化する方法を調べた。

## `__MACOSX`、`.DS_Store`とは？
### `__MACOSX`とは？

- `__MACOSX`はresorce forkと呼ばれるもの
- resorce fork　
    - Classic Mac OS特有のファイルの構造
    - アイコン、ウィンドウの形状、メニューの内容、定義、古くはアプリケーションコード（機械語）などといった、フォーマットがある程度定型化された情報を持つ
    - 逆にデータ部分はdata forkと呼ばれる
- `__MACOSX`はmac osで表示スピードをあげることなどに役立つ
- windowsでは関係のないファイル


参考：[リソースフォーク](https://www.weblio.jp/content/%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%95%E3%82%A9%E3%83%BC%E3%82%AF)


### `.DS_Store`とは？
- ファルダ可視化、アイコン位置などのメタ情報が含まれる
- mac OSで自動的に生成される
- 隠しファイルの一つ
- windowsでは関係のないファイル
- DSとはdesk sreviceの略

参考　: [ .DS_STORE](https://en.wikipedia.org/wiki/.DS_Store)

## zip化で含めない方法

### `__MACOSX`はterminalからのzip化で含めない。

- `__MACOSX`はterminalからのzip化することで含めずにzip化が可能です。

```
# test というディレクトリをzip化する
zip -r test.zip  test/
```

※上記の方法以外にもサードパーティーのツールを使って、`__MACOSX`を含めない方法もあるようですが、割愛します。

### `.DS_Store`はzip化のoptionで含めない。

- `.DS_Store`はzip化のoption(-x)を用いることで、含めずにzip化が可能です。

```
# .DS_Storeを指定して含めない
zip -r test.zip  test/ -x "*.DS_Store"

# 隠しファイルをすべて除外
zip -r test.zip  test/ -x "*.*"
```
スマホ熱中症にご注意を。Bingも含む。


　どうも、カーブミラーです。

　今回は、
　　スマホ熱中症です。

　最近
　　「スマホも熱中症になる」
　　　という記事が、あちこちに
　　　　出てくるようになりました。

　対処方法ですが、
　　**冷蔵庫や保冷剤で
　　　冷やすのは、ＮＧ**だそうです。
　　　　内部に結露ができて、
　　　　　ショートするとか。

　スマホが熱を持ったら、
　　充電をやめ、
　　　アプリを閉じて、
　　　　電源オフするといい、
　　　　　とアドバイス
　　　　　　されています。

　でも、
　　さすがに仕事ツールの
　　　スマホの電源をオフするのは、
　　　　仕事に支障が出ますよね。
　　　　　わかります。

　とにかく、
　　気を付けましょう。
***
　さて、そんなスマホ熱中症ですが、
　　**スマホで、Bingする方へ
　　　注意喚起させてください。**

　私だけならばいいのですが、
　　Bingアプリを起動して
　　　使っていると、スマホが
　　　　かなりの熱を持ちます。

　使う際には、
　　充電は避けましょう。

　相乗効果で
　　熱量アップです。

　仕方なく、
　　充電する場合でも、
　　　満充電は避けた方がいいです。

　持っているのも
　　キツイです。

　車内に置き忘れ、も
　　危険ですよぉ。

　爆発炎上します（可能性）。
　　笑えません。

　いろんな意味で、
　　気を付けましょう。
Poetryを使ってディープラーニング環境を構築する

# はじめに
Pythonでパッケージ管理や環境構築が手間になることがあります。リモートリポジトリをクローンして動かそうとしたら依存関係の問題で動かなかった...というのはよくある話です。
「パッケージを推奨バージョンに合わせたいけど、ローカル環境は汚したくない...」
そんなときに役立つツールがPoetryです。

ここでは、Poetryを使用して、ディープラーニング用の環境を構築する方法について解説します。
GPU対応のPytorchを使えるようにします。

# Poetryを使えるようにする
homebrewを使ってインストールするのが一番楽です。
[このリンク](https://brew.sh/index_ja)からhomebrewのページに飛んで、指示に従ってインストールしてください。
homebrewのインストールができたら、Poetryは以下のコマンドでインストールできます。
```bash
brew install poetry
```

# プロジェクトの作成
新規の場合：
```bash
poetry new project_name
```
既存のプロジェクトをpoetryで管理するには：
```bash
poetry init
```

# Poetryを使用してrequirements.txtからパッケージをインストールする
requirements.txtファイルに記載されたパッケージをPoetryで管理したい場合は、次のコマンド：
```
poetry add $( cat requirements.txt )
```
このコマンドは、requirements.txtファイルの中身を読み込んで、そのパッケージをプロジェクトに追加します。

# GPU対応のPyTorchをPoetryを用いてインストール
この方法はPoetryの新しいバージョン(1.5.1)から可能になった方法です。古いバージョンだと動かないため、まずPoetry自身のアップデートを行っておきましょう。
```
poetry self update
```

次に、GPU対応のPyTorchをインストールします。これは特定のURLから直接PyTorchをインストールするための手順です。以下のコマンドで、PyTorchのインストール先として用いるリポジトリを追加します：
```
poetry source add torch_cu117 --priority=explicit https://download.pytorch.org/whl/cu117
```
URLの「cu117」の部分は自身の使っているcudaのバージョンに応じて変更してください。

その後、次のコマンドでPyTorch、Torchvision、Torchaudioをインストールします：

```
poetry add torch torchvision torchaudio --source torch_cu117
```

これでGPU付きのPytorchをPoetryで使えるようになりました。
仮想環境内に入るには以下のコマンドを実行します。
```
poetry shell
```

実際にGPUが使えるようになっているのか確認するために、以下のような内容が書かれたファイルを用意して実行してみましょう。
```python
import torch

print(torch.cuda.is_available())
```

「True」と返ってくれば成功です。

# おわりに
以前までPoetryを使ってPytorchでGPUを使うには、地味に面倒なやり方を使う必要があって、あまり好きじゃなかったんですが、1.5.1から楽に導入できるようになっていました。
では、皆さんも良いPoetryライフを。
音源データ「.mp3」をcolabで「MIDI」へ変換する方法

<h2><b>・導入</b></h2>
<p>私は現在、ピアノを学習している。<br>
ただ楽譜などは読めないので、synthesiaというツールを用い、勉強中である。<br>

自分の好きな楽曲をsynthesiaで練習するためには「MIDI」というデータを用意しなければなりません。しかし、販売されている音源は「.m4a.」というデータ形式であるので「.m4a.」→「MIDI」へ変換することが必要である。

 <b>「.m4a.」</b>→<b>「MIDI」</b>へ変換することができるソフトウェアは見つからなかったのだが、<b>「.mp3」</b>→<b>「MIDI」</b>へ変換するものは発見したのでそれを利用しようとしたのだが、いかんせん正体不明のソフトウェアを自身のパソコンにインストールするというのは嫌なものなので、今回はGoogle Colaboratoryを使用し、音源データである「.mp3」をsynthesiaで利用できる「MIDI」へ変換する方法を解説する。

<b>※「.m4a.」→「.mp3」への変換の仕方は省略する（iTunesを使用）</b>

<h2><b>・Google Colabでのコード解説</b></h2>
<p>まずffmpegとwgetという2つのパッケージをインストールする。</p>

```python:qiita.rb
!apt install ffmpeg wget
```

<p>次にlibrosaという音声データを解析するためのPythonライブラリをインストールする。これにより音声処理や音楽情報検索などのタスクに使用され、音声データの解析や処理を行うことができるようになる。</p>

```python:qiita.rb
pip install librosa==0.9.2
```

<p>ピアノ演奏の楽譜を推定・変換するためのPythonライブラリをインストールする。音楽の録音や演奏データから、演奏されたピアノの音楽を楽譜として復元したり、譜面データに変換したりすることができる。</p>

```python:qiita.rb
pip install piano_transcription_inference
```
<p>IPython.displayモジュールからAudioクラスをインポートする。
このモジュールを使用すると、音声や画像、ビデオなどのさまざまなデータをブラウザ内で直接再生や表示ができる。</p>

```python:qiita.rb
from IPython.display import Audio
```
<p>ピアノ演奏の音声データをMIDIファイルに変換する。</p>

```python:qiita.rb
from piano_transcription_inference import PianoTranscription, sample_rate, load_audio

def transcribe(audio_path, output_midi_path):
    # Load audio
    audio, _ = load_audio(audio_path, sr=sample_rate, mono=True)

    # Transcriptor
    transcriptor = PianoTranscription(device='cuda', checkpoint_path=None)

    # Transcribe and write out to MIDI file
    transcriptor.transcribe(audio, output_midi_path)
```

<p>ピアノ演奏の音声データをMIDIファイルに変換する</p>

```python:qiita.rb
!wget https://github.com/qiuqiangkong/piano_transcription_inference/raw/master/resources/cut_liszt.mp3
```
<p>IPython環境内で音声ファイル（拡張子が.mp3）を再生するためのIPython.displayモジュールのAudioクラスを使用する。</p>

```python:qiita.rb
Audio('------------.mp3')
```
<p>ピアノ演奏の音声ファイル（拡張子が.mp3）をMIDIファイル（拡張子が.mid）に変換する。</p>

```python:qiita.rb
transcribe('------------.mp3', '------------.mid')
```

「----------------」の部分は自身でダウンロードしたmp3フィルム名を入力する。


すると
↓
![スクリーンショット (1868).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3513767/e98a7d86-b035-6ef3-5af1-31aff03876e5.png)

このように実行され、無事MIDIデータへ変換することができた。
ラジオボタンのチェックを値で設定するときは配列で設定する！！

ラジオボタンの設定をjqueryのスクリプトで行うときにハマるという話です。
## 問題の前提
  ラジオボタンは通常複数の同一name属性をもつ要素が集まってできています。
  ```
<input type="radio" name="post_radio" value="val1" checked>要素１
<input type="radio" name="post_radio" value="val2">要素２
<input type="radio" name="post_radio" value="val3">要素３
```
  
  こんな感じです。
  ここで、要素３にチェックを入れるという設定をjqueryでやりたいという要求があるとします
  まず、
  ```
  let elms=$('input:radio[name="post_radio"]')
 ```
 とやると変数elmsは配列となり、３つの要素が入ります。
  そして、要素３にチェックを入れたいわけです。
##   eqメソッドによる設定
  一つの方法としては
３番目の要素をeqメソッドで特定して、propメソッドでチェックを入れる方法。次のような感じです。
``` 
elms.eq(2).prop('checked',true);
```
  しかし、この方法は「要素３」が３番目にあることがわかっていなければ成立しません。HTMLが書き換わり、要素の数が増えたり、順番が変わるとjqueryも書き換える必要があります。
## 値（value属性）で設定する
  そこで、HTMLが変わってもjquery側に影響を及ぼさない方法としてもう一つの方法があります。
  それはvalue属性で要素を特定するという方法です。もちろんこの方法でもvalue属性が書き換わればjqueryも書き換える必要が生じますが、要素の数が変わったり、順番が変わることの頻度に比べると少ないと思われます。また、スクリプトの可読性も高いと思います（何番目という指定より、〇〇というvalueをもつ要素というほうが分かりやすいでしょ。）。
  そこでこんな書き方をします。
```
  $('input:radio[name="post_radio"]').val(['val3'])
```
  これで要素３にチェックが入るのですが、ここで罠が潜んでいるのです。
  よく見ればわかるのですが、**valメソッドの引数が配列**になっています。これがこの記事の結論です。
  
## ２つの失敗例
```
  $('input:radio[name=post_radio]').val('val3')
```
  これだとチェックは入りません。中途半端に覚えているとこのように文字列を入れてしまうと思いませんか？
  このコードはラジオボタンのvalue属性を変更しようとするものです。これを実行すると、チェックの状態は変わりませんが、全てのラジオボタンのvalue属性は'val3'に変わってしまします。
```
  $('input:radio[name=post_radio]').val(['val3']).prop('checked', true);
```
 これもダメです。これは最後のラジオボタンが選択状態になります。 今回の例はたまたま最後のラジオボタンにチェックを入れようとしているので結果オーライですが２番目に入れようと思って'val2'を指定しても要素３が選択状態になります。これは最初に value="val2" のラジオボタンが選択されるのですが、その後で全てのラジオボタンがチェックされようとします。しかし、ラジオボタンのグループに対して、一度に複数の要素をチェックすることはできません。結果的に最後のラジオボタンだけがチェックされた状態になります。
 
  これ相当ハマりすよ。
  ご注意ください。
Route53フェイルオーバーを試してみた

Route53にはヘルスチェックを利用したフェイルオーバー機能があるが、
CloudWatchアラームを利用したフェイルオーバーを確認したので備忘録として残す。
# 構成
・Network Load Balancer(1a,1c)
・EC2 インスタンス2つ(1a,1c)
# 設定の流れ
1. EC2を適当に作成
Amazon Linuxを利用しEC2を2つ作成。
dnf install httpdしてNetwork Load Balancerからヘルスチェックを受信できるようにする
1. ターゲットグループとNetwork Load Balancerを作成
1.で作成したEC2を対象にする
1. CloudWatchアラームを作成
2.を作成するとCloudWatchメトリクスに「ターゲットグループ、AZ 別メトリクス」が作成されるので、AZ毎のUnhealthyHostCountのアラームを2つ作成する。
1. Route53ヘルスチェックを作成
Route53コンソールからヘルスチェックを作成する。ヘルスチェックは3で作成したCloudWatchアラームを指定する。ヘルスチェックはアラーム毎に作成するため2つ作成する。
1. Route53プライベートホストゾーンとレコードを作成
プライベートホストゾーンを作成し、フェイルオーバータイプのAレコードを作成する。
![スクリーンショット 2023-07-23 9.59.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494237/5983988a-7475-e34d-2d9b-e0051108e8e4.png)
それぞれのレコードのヘルスチェックIDは別のものを設定する。
# 動作確認
・両方のEC2のApacheを起動した状態で名前解決
→プライマリのアドレスが解決される
・AZ 1aのEC2のApacheを停止した状態で名前解決
→セカンダリのアドレスが解決される。解決結果が変わるのに5分程度かかった。アラーム期間とTTLが影響?
・AZ 1cのEC2のApacheを停止した状態で名前解決
→プライマリのアドレスが解決される
・両方のEC2のApacheを停止した状態で名前解決
→プライマリのアドレスが解決される
Typescriptで'encodedInsertableStreams' does not exist in type 'RTCConfiguration'.   を回避する方法


```ts
    const new_pc = new RTCPeerConnection({
      encodedInsertableStreams: true,
      forceEncodedVideoInsertableStreams: true,
    });
```

こうすると下記のようなTypescriptの構文チェッカーでエラーになります。（Javascriptでは動作します）

`'encodedInsertableStreams' does not exist in type 'RTCConfiguration'.`

`RTCPeerConnection`のコンストラクタの引数である`RTCConfiguration`のパラメータにこれらの引数が含まれていないからです。

回避するために、やむなく`RTCConfiguration`を`any`として渡します。

```ts
    const new_pc = new RTCPeerConnection({
      encodedInsertableStreams: true,
      forceEncodedVideoInsertableStreams: true,
    } as any);
```
【Elixir/Phoenix】AI対戦4目並べを作る（強化学習編）

:::note info
ソースコードの整備を進めています。
ソースコードと詳細な説明を合わせて準備していますので、お楽しみにしていてください！

もし、この記事が役立つと感じていただけたら、いいねやストックをしていただけると、私のモチベーションがアップし、ソースコードの整備や説明の作業がさらにはかどります。

どうぞよろしくお願いいたします！
:::



[【Elixir/Phoenix】AI対戦4目並べを作る（GUI編）](https://qiita.com/GeekMasahiro/private/0cc62af5bcc67cbb2b3e)では、人対人の対戦ができる四目並べのGUIを作成しました。対戦相手のAIを強化学習を使って作成しました。

- ゼロから作るDeep Learning 4のDQNをElixir/Axonを使って実装しました。
- 四目並べをDQNで強化学習してみました。
- 程度適切な手が指せるレベルになりました。

強化学習の詳しい事は、ゼロから作るDeep Learning 4を参照してください。

https://www.oreilly.co.jp/books/9784873119755/

[【Elixir/Phoenix】対戦4目並べを作る（AIの動作チェック編）](https://qiita.com/GeekMasahiro/private/09c96ccb8da13e445d70)では、作成したニューラルネットをLivebookを使って動作させてみます。

# 関連記事

https://qiita.com/GeekMasahiro/items/0cc62af5bcc67cbb2b3e

https://qiita.com/GeekMasahiro/items/68396a71aa9408a1c485

https://qiita.com/GeekMasahiro/items/09c96ccb8da13e445d70

https://qiita.com/GeekMasahiro/items/603f1f845018988ec7a7
没になった趣味の電子工作ネタ３つ（憶えてる分のみ）

この記事は自分への備忘録。日記みたいなもんです。

前から趣味で作ろうと思ってたのに放置プレイになってるネタを列挙する。

* デジタル表示の体重計の数字をカメラで読み取ってサーバーにアップしてグラフ表示できるようにするやつ。カメラ付きESP32＋Googleのスプレッドシートで作ろうと思っていた…。
  * →スマホ連動体重計なる製品を購入してしまい、個人的必要性が失せた…
* [4℃ の パロディ品](https://twitter.com/kiyunamura/status/1342024971824975872?s=20)を進化させ、現在温度を表示し設定温度になるとチカチカするようなモノ。
  * →試作用部品を幾つか買ったところで長期保留中。
* PCのスピーカ/マイク端子に挿して、Bluetoothヘッドセットを使えるようにするアダプタ。会社から貸与されてたノートPCが ある日、セキュリティ対策か何かで それまで使えていたBluetoothヘッドセットが接続不可になったことがキッカケ。
  * →ESP32 の bluetoothライブラリを使ってヤれそう、と調べるところで保留。別プロジェクトに移り、貸与PCも変わって、Bluetoothヘッドセットがまた使えるようになったので個人的必要性が失せた。


要はアレですね、思いついたらスグ着手しないと実現まで至らないすね
マインクラフト統合版サーバに鉄千Behavior Packを導入する

# はじめに

マインクラフト統合版サーバに、鉄千のBehavior Packを導入できたので記録しておきます。

## 鉄千とは

https://tetsuonethousand.wixsite.com/tetsusen

## 鉄千拠点についての説明

https://www.youtube.com/watch?v=fywFFEDz4u8

# 実装

## Add-Onをダウンロード

https://drive.google.com/file/d/1EyqBUJtSgfLtlAwKekY9V7ghjPIG7Xw2/view

## ファイルをマイクラサーバにアップロード

functions.mcpack

## Behavior Packのディレクトリを作成

```
cd data/behavior_packs
mkdir iron_thousand
```

## functions.mcpack展開

```shell
cd iron_thousand
mv ~/functions.mcpack .
unzip functions.mcpack
```

## manifest.jsonの内容を確認

```json
{
   "format_version" : 1,
   "header" : {
      "description" : "鉄千の拠点を一瞬で作るパック-マルチ5人用-",
      "name" : "一瞬鉄千拠点-マルチ5人用-",
      "platform_locked" : false,
      "uuid" : "22d20a44-eedd-010d-3492-b0b11dcf7d89",
      "version" : [ 1, 0, 0 ],
      "min_engine_version":[1,8,0]
   },
   "min_engine_version" : [ 0, 0, 1, 1, 2, 5 ],
   "modules" : [
      {
         "type" : "data",
         "uuid" : "7aac64d6-af82-e83e-2fba-6eba77c92a50",
         "version" : [ 1, 0, 0 ]
      }
   ]
}
```

## セーブデータディレクトリに設定ファイルを設置

※World名が `IronThousand` だった場合

```shell
cd data/worlds/IronThousand
vi world_behavior_packs.json
```

```json
[
  {
    "pack_id": "22d20a44-eedd-010d-3492-b0b11dcf7d89",
    "version": [
      1,
      0,
      0
    ]
  }
]
```

## サーバ再起動

## サーバにログインし、マイクラ内で有効化

```
/function iron
```
LangChainのコアパッケージからExperimentalライブラリが分割されます

先週の LangChain Japan Meetup でも Harrison が言っていた「コアをExperimentalやCommunityパッケージに分けていく」という話ですが、実際にExperimentalの分割が開始しているので、LangChainユーザーはチェックしておきましょう。

今後の改善や変更についての考え自体はこちらに掲載されています。

https://github.com/hwchase17/langchain/discussions/7662

詳細は以下に示す各リンクを参照して欲しいですが、サクッと具体的な変更点についてだけ以下に示します。

## なぜLangChainコアを、コアとExperimental(実験的)パッケージに分割するのか

主に以下の3点です。

1. **langchain コアパッケージからCVE(セキュリティ脆弱性)を取り除く。**
1. **実験的なソースコードをコアとExperimentalに明確に区別し、新しいアイデアや論文の実装について、実運用に耐えるコードでなくてもExperimentalに追加しやすくする。**
1. **langchainコアパッケージの実用性を高めるために軽量化する。**

https://twitter.com/hwchase17/status/1682785686729166848?s=20

https://github.com/hwchase17/langchain/discussions/8043

## Experimentalに移行される既存の機能

すでにLangChainコア内にある以下が移行されることがアナウンスされています。

> - langchain/experimental 配下に含まれているもの
> - SQL chain
> - SQL agent
> - CSV agent
> - Pandas agent
> - Python agent

## 移行方法

移行方法は以下にガイダンスされています。

https://github.com/hwchase17/langchain/blob/master/MIGRATE.md

> - インストール方法
いままで `pip install -U langchain`
これから `pip install -U langchain langchain_experimental`
※当然Experimentalを使いたい場合のみ
> - Experimentalパッケージの読込み
いままで `from langchain.experimental import ...`
これから `from langchain_experimental import ...`
> - 各機能の読込み ex) SQLDatabaseChainの場合
いままで `from langchain.chains import SQLDatabaseChain`
これから `from langchain_experimental.sql import SQLDatabaseChain`

## 移行スケジュール

移行スケジュールは上記のアナウンスに記載されている

> 2023年7月21日(金)にリポジトリの構成を変更します。
> 2023年7月28日(金)にlangchain.experimentalの変更を行います。私たちは実験的なコードを独自のパッケージに移動します。このパッケージにはlangchain/experimentalにあるもの全てとCVEがあるものが含まれます。

すでに7/22にlangchain_experimentalパッケージが0.0.1版としてリリースされています
https://pypi.org/project/langchain-experimental/

ただしまだコアライブラリ側からはExperimentalは取り除かれていません。順調にいけば7/28にはこれらはコアから削除されて完全に移行されるそうです。

## まとめ
- LangChainを本番環境で利用するにあたり、不要なライブラリがどんどん取り込まれる効率の悪さ、脆弱性の残置など気になっていた人は多いでしょう。逆に論文の概念レベルのものがどんどん取り込まれることで、LLM界隈の知識としてとても勉強になると考える人が多かったのも事実です。これら両方のメリットを享受するための一歩として大きな飛躍と言えます。
- Experimentalの分割はその第一弾であり、今後ドキュメントの改善やモジュール性、カスタマイズ性の向上、デバッグのしやすさの向上など、大きな変更がいくつか入っていくことが想定されます。ただ使うだけでなく、それらの作業タイムラインと背景にある考えかたを引き続き追っておくことが、より安全に効率的にLangChainを今後も使っていく上で重要であると思えます。
【Python】クラスで簡単なデコレータを作成してみる


## 内容
関数実行時に以下の内容を出力するデコレータをクラスで定義する
- 関数開始メッセージ
- 関数実行時の引数
- 関数終了メッセージ
- 関数実行にかかった時間

## 実装
``` python
from time import *

class logger:
    def __init__(self, func):
        self.func = func
    def __call__(self, *args):
        # 関数開始メッセージ
        print(f"--- {self.func.__name__} start ---")
        # 関数実行時の引数
        print(f"--- args: {args} ---")
        start = time()
        ret = self.func(*args)
        difftime = time() - start
        # 関数終了メッセージ
        print(f"--- {self.func.__name__} end ---")
        # 関数実行にかかった時間
        print(f"--- execute time: {difftime} ---")

        return ret

@logger
def add(a, b):
    # 3秒待機
    sleep(3)
    return a+b

print(add(3, 5))
```

## 結果
```
--- add start ---
--- args: (3, 5) ---
--- add end ---
--- execute time: 3.0143697261810303 ---
8
```

## 参考
https://hombre-nuevo.com/python/python0069/
【Git初心者向け】使い終わったブランチは削除していいの？

プログラミング初学者です。
Gitコマンドについて学習する中で、気になった点を調べたので、備忘録としてまとめておきます。



# ローカルに作成したブランチ、使い終わったら削除していいの？
正直に言いますと、これまでローカルで作成したブランチを残したままにしていましたが、`マージが終わったのなら削除した良い`ということに今更になって気づきました💦

一人でのアプリケーション作成を行なってきたことで、この時期まで「ローカルブランチはとりあず残しておこう」と思ってきました。


# ブランチを残しておくことで起こる弊害

- マージ後のブランチに誤ってcheckoutしてしまう。
- どのブランチがマージ済みなのか分からなくなる。


このように、ブランチが増えると、管理が大変になるという弊害が起きる可能性があります。
なので、通常は、ローカルのマージが完了したブランチは削除してブランチが最低限のものだけ残すという形が良いようです。

# ブランチ削除関連のコマンド

```
$ git branch --merged

# マージが完了しているブランチを表示
```

```
$ git branch -d ブランチ名

# -d　の後にブランチ名を指定することでブランチを削除できます。
# マージが完了していないブランチを削除することはできません。
```

```
$ git branch -D ブランチ名

# マージが完了していないブランチを削除したい場合は、大文字Dを指定します。
# これで、強制的にブランチを削除することも可能です。
# 強制的に削除してしまうため、本当に削除してもよいかどうか、よく考えてから行うのが良い。
```



# ブランチを削除する際に起こりえる問題

- ブランチの誤削除

誰でもブランチの削除が出来ないよう、権限管理するといった対処法をとる企業もあるようです。



# まとめ「マージ後は削除するのが普通。」らしい
初心者のため、Git管理について勉強不足であることを痛感しました💦
現場にアサインされた際に苦労しないよう、事前に知識を定着させていきます。


# 参考サイト

なお、学習する際に、こちらの記事が大変参考になりました。

https://www.sejuku.net/blog/72064


https://teratail.com/questions/210908
MATLAB ONLINEからラズパイを操る

## １．はじめに
少し前の、某CQ出版社雑誌の付録でMATLAB ONLINEの６ヶ月ライセンスを入手された方も多いようです。ここではMATLAB ONLINEからラズパイを操ることについて書きます。

## ２．本家ページ
[MATLABの本家のマニュアルはここにあります](https://jp.mathworks.com/help/supportpkg/raspberrypiio/ug/connect-to-raspberry-pi-hardware-board-in-matlab-online.html?utm_source=pocket_saves)ので、ご参照ください。

## ３．動作環境など
まず、対応していないハードウェアですが、Zeroには対応していません（Zero Wにも対応していない。Zero 2Wには対応しているらしいが確認していません）。
Picoには対応していません（これは、そうでしょう）。
Raspberry piの２から４には対応しています（１には対応していません）。

OSに関しては、最新のBullseyeでは動きません（他社のソフトをMATLABと組合わせて用いる場合、一世代前のものとマッチングが取れていることが多い気がします）。
Bullseyeの一世代前のBusterでの動作を確認できました。
32bitバージョンで動くので、64bitのする必要はないと思われます。
本家マニュアルにありますように、Deployすることを考えると「全部入り」をインストールしたほうがよいです。
```
# OSのバージョン確認
$ lsb_release -a
```

## ４．環境構築
普通にRaspberry PI ImagerでマイクロSDカードに書き込み、インストールします。
本家マニュアルのとおりです。
```
$sudo apt-get update
$sudo apt-get install matlab-rpi
```

そういえば、Desktopバージョンのインストールも簡略化されています。
前は、MATLAB Support Package for Raspberry Pi Hardwareの中でマイクロSDに書き込みしたものを使ったりしていましたが、ラズパイの中（のマイクロSD）にガンガン、インストールしてくる形式になっており、楽になっています。

インストールが終わったら、セットアップします。ここも本家マニュアルどおりに進めればOKです。設定は後で変えられます、と書いてありますね。
MATLAB ONLINEに登録したe-mailアドレスとPasswordが要求されます。これを用いてラズパイとMATLAB ONLINEを紐づけするようです。
```
$sudo matlab-rpi-setup
```
セットアップが終わったら、リブートします。
```
$sudo reboot
```

## ５．MATALB ONLINEへの接続
ラズパイが起動して、オンライン状態になったら、MATLAB ONLINEから状態を確認します。
```matlab
rasplist
```
ansが返ってきて、Statusが”Ready to connect"であれば、使える状況にあります。
ちなみに、rasplistというコマンドは、Desktop版のMATLAB Support Package for Raspberry Pi Hardwareにはありません。
MATLAB ONLINEでは、device Nameとか、SerialNumberで接続先のラズパイを指定するのに対し、Desktop版では、IPAddressで指定するところが異なっています。
```matlab
myPi = raspi
```
で、接続します。プロパティが表示されれば接続できています。
使っているラズパイは4Bなのですが、2Bで認識されてしまっている模様。

```matlab
mypi = 

  raspi のプロパティ:
         DeviceAddress: 'myPi'                        
          SerialNumber: '1000000088xxxxx'            
             BoardName: 'Raspberry Pi 2 Model B'      
         AvailableLEDs: {'led0'}                      
  AvailableDigitalPins: [4,5,6,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]
  AvailableSPIChannels: {'CE0','CE1'}                 
     AvailableI2CBuses: {'i2c-0','i2c-1'}             
      AvailableWebcams: {'mmal service 16.1 (platform:bcm2835-v4l2-0)'}
           I2CBusSpeed: 100000
```
カメラを使って画像の取得をしてみます。
```matlab
mycam = webcam(myPi);
img = snapshot(mycam);
imagesc(img);
```
![WS000381.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434947/309fb274-5c07-34e5-200f-bf005199e95e.jpeg)
よさそうですね。

## ６．MATLAB ONLINE とMATLAB Desktopの両用は可能か？
やってみました。セットアップをやり直せば可能ですが、切り替えて使うことは想定されていない風情です（毎回セットアップをやるのは面倒なので）。


## ７．これ以後の動作のあれこれについて
GPIOでLEDチカチカなどについては、@aoimidoriさんの『[はじめてのMATLAB x Raspberry Pi 連携](https://qiita.com/aoimidori/items/514b069cece37e9be4cf)』を参考にしていただければと思います。


以上です。
なぜ、あなたの仕事は終わらないのか スピードは最強の武器である

https://www.amazon.co.jp/%E3%81%AA%E3%81%9C%E3%80%81%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AF%E7%B5%82%E3%82%8F%E3%82%89%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B-%E3%82%B9%E3%83%94%E3%83%BC%E3%83%89%E3%81%AF%E6%9C%80%E5%BC%B7%E3%81%AE%E6%AD%A6%E5%99%A8%E3%81%A7%E3%81%82%E3%82%8B-%E4%B8%AD%E5%B3%B6%E8%81%A1-ebook/dp/B01GPCKJWK/ref=sr_1_1?adgrpid=52274025534&hvadid=658890751808&hvdev=c&hvlocphy=1009255&hvnetw=g&hvqmt=e&hvrand=5425600678592918101&hvtargid=kwd-335457269198&hydadcr=2759_13670990&jp-ad-ap=0&keywords=%E3%81%AA%E3%81%9C+%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AF%E7%B5%82%E3%82%8F%E3%82%89%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B&qid=1690072551&sr=8-1

本書を手に取った背景
育休中に読み始めた本なんですが、復帰後に仕事を円滑に進められるようになりたいと思ってよみました。
とにかく業務量が多い部署なので、読書をしてる暇があれば業務をやらないとって感じでした。
復帰後にはそれを改善したいと思い、情報収集のために読んだ感じです。


本書のテーマ
極端に行くと、時間術の本です。ノウハウと、たくさんの例とたくさんの比喩、たくさんの概念を織り交ぜて時間そのものの核心に迫っていっているのでわかりやすい。
ただ、エンジニア視点の時間の使い方によってしまうかなという部分はありました。
私は営業職の側面もあり、客との打ち合わせも多めなのでまるっと使える感じではなかったです。

個人的なポイント
１，仕事が遅い人
上司から仕事を受け取ったら直前になってやり始める感じ。そこそこ仕事ができてもこういうことが一回でもあるとできないやつというレッテルを貼られてしまう。時間の使い方が悪い。

２，スキルはあるけど仕事ができない人
才能と馬力がありすぎるがゆえに、締め切り間際に、設計されていない機能をプログラムに追加したりする。上司としては、いったものを作って欲しいのでこれでは困るし、扱いづらい。能力が成果に見合っていない。

３，１のパターンの詳細
仕事が終わらない人は、得てして後半の応用問題を甘く見ています。 応用問題がどのくらいで終わるかは、取り掛かってみないと絶対にわかりません。そして応用問題が終わらなければ仕事は終わりません。 　ですから応用問題に取り掛からないうちは、まだ仕事がどのくらいで終わるか判断できないのです。

４，２割の日程で８割をおわらす
１０日あれば２日のうちに８割を終わらせることができれば、期日までに間に合うかがわかる。

５，２割の日程で８割終わらすために
界王拳を使う。何者にも邪魔されない時間を使って一気に終わらせる。そのあと、期日までに間に合うかを報告・相談する。

６，界王拳を使う時間
朝４時から午前中いっぱい。その時間は完全に集中する。メールはやらない、電話も出ない。気分転換や休憩はOK。

今後やれること
・集中する時間をつくる
・界王拳で終わらせる
・２割の日程時にいつまでに終わりそうかを報告する

まとめ
この考え方を意識しておくことが大事だと痛感した。
これを意識してないと、残りは残業で終わらそうとか、翌朝やろうとか思ってしまうが、８割まで終わらせるという目標をもつことが大事。
要は、ほかから邪魔されない時間をいつ作って、どうやって集中するか。
マインドフルネスや他のタイムマネジメントと併用するとすごくいい感じになると思う。

そして、これがKindle unlimited対象であることがすばらしすぎる
ABC 311 備忘録

## 概要
　今回はABC311（2023年7月23日（土）21:00~22:40）についてポイントと自分の実装について書いていきたいと思う。
## A問題
https://atcoder.jp/contests/abc311/tasks/abc311_a
### ポイント
- 'A', 'B', 'C' について文字数のカウントをそれぞれ行う
### 自分の実装
```Python:ABC_311_A.py
N = int(input())

S = input()

ans = 0

count_ABC = [0, 0, 0]

for i in range(N):
    ans += 1
    if S[i] == 'A':
        count_ABC[0] += 1
    elif S[i] == 'B':
        count_ABC[1] += 1
    else:
        count_ABC[2] += 1
    if count_ABC[0] >= 1 and count_ABC[1] >= 1  and count_ABC[2] >= 1:
        print(ans)
        exit()
```
## B問題
https://atcoder.jp/contests/abc311/tasks/abc311_b
### ポイント
- 各日にちについて各々のスケジュールを確認するので、入力を `numpy` の2次元配列として格納
- 'numpy' の列ごとに `['o','o','o', ...]`と一致するかどうかを判定
- 連続して上の判定式が `True` となるかを確認
- 連続が終了したら、その時点で連続日数を記録・リセット
### 自分の実装
```Python:ABC_311_B.py
import numpy as np

N, D = map(int, input().split())

S = np.array(list(list(input()) for i in range(N)))

free = np.array(['o' for i in range(N)])
ans = 0
continuous = True
count_continuous = 0

for i in range(D):
    S_line = S[:, i]
    if np.array_equal(S_line, free):
        continuous = True
        count_continuous += 1
    else:
        ans = max(ans, count_continuous)
        continuous = False
        count_continuous = 0

ans = max(ans, count_continuous)

print(ans)
```
## C問題
https://atcoder.jp/contests/abc311/tasks/abc311_c
### ポイント
- 有向グラフの閉路検出を行えば良い
- すでに訪れたことのあるノードに達した時点で閉路を返す
### 自分の実装
```Python:ABC_311_C.py
def find_cycle(graph, start):
    stack = [start]
    visited = [False] * (len(graph) + 1)
    while stack:
        current = stack[-1]
        if visited[current]:
            return stack[stack.index(current):]
        visited[current] = True
        next_node = graph[current]
        stack.append(next_node)
    return None

def main():
    N = int(input())
    A = [0] + list(map(int, input().split()))  # 0番目の要素は無視するため0を追加

    cycle = find_cycle(A, 1)  # 頂点1をスタートとして有向閉路を探索

    if cycle:
        M = len(cycle)
        print(M-1)
        print(*cycle[0:-1])
    else:
        print("No cycle found.")

if __name__ == "__main__":
    main()

```

## 感想
　C問題まで解けたが、相変わらずDFS・BFSの実装について全然慣れていなかったので、勉強が必要だと思った、D問題についてもDFSで解けるはずなので解き直したい。
bareboxの使い方

c2kのbareboxで動作確認のためにいろいろ試してみています。

PHYのレジスタ読み込み

```
Barebox-C2K >/ phy read 0 2                          
PHY 0 , Addr 0x2, Val 0x4d
```

QCA8337のPHYが読めています。

GEMAC0のレジスタ直叩き

```
Barebox-C2K >/ mw -l 0x9c200034-0x9c200034 0x600e0000
Barebox-C2K >/ md 0x9c200034-0x9c200038
9c200034: 600ed036 00000000
```

regionは上記のように指定しますが、なんだか動作がおかしいです。
ABC311回答メモ

0.はじめに
　トヨタコンテストなので、難易度高いのかなーと思ったらやっぱり高かったです。
　Bあたりから難易度高めでCは諦めかけましたが何とかクリア。
　D以降は時間的にも気力的にも難易度的にも手が付けられませんでした。。


1.A - First ABC
　リストで、ABCそれぞれに、文字列内に出現したかフラグを持ち
　文字列を先頭からチェック。
　ABCどれかが発生したらフラグを立て、フラグのリスト合計が1になったら
　アドレスを出力して終了としてACでした。

　https://atcoder.jp/contests/abc311/submissions/43830264

2.B - Vacation Together
　N、Dの最大がそれぞれ100だし、B問題なのでTLEは意識しないで行けそうと判断。
　最初にna(現在チェック中の日の範囲で連続o日数を保持)とans(最大連続o日数)を0で初期化
　一日目から、全員がoの日をチェックしていき、全員oの場合、naに+1
　全員がoでない日が出てきたら、ansとnaのうち大きい方をansに保持しnaをクリア
　という感じで実装したところ、例題３がうまくいかない。
　上記実装だと、最終日がすべてoで、naが最高値になる場合に
　ansが更新されないので、ループを抜けた後に最終判定のロジックを
　追加し、ACとなりました。
　
　https://atcoder.jp/contests/abc311/submissions/43840921

3.C - Find it!
　タイトルを見ただけでUnion-Find木を使うんだろうなと思いました。

　閉路判定は、Union-Find木で根を保持しておいて
　これからつなごうとしている頂点が同じ根の時閉路となる
　という前に学んだ知識を活用。
　
　辺を一つずつUnionFind木と、有方辺を辞書にキー始点、値終点として
　登録していき、追加する辺で、閉路判定がされた場合に
　その終点で、辞書を検索
　得た値でまた辞書を検索していき
　最終的に閉路判定がされた始点まで戻ってくるので
　その過程を出力することでAC頂けました。
　

　https://atcoder.jp/contests/abc311/submissions/43861917


以上
LXCで「rm -rf /*」したらshutdownもstopも出来なくなった

作成日：2023年7月23日

[この記事](https://qiita.com/tatmius/items/18032962db0dcdd84e9f)で「rm -rf /*」をやった後に、使い終わったLXCのコンテナを削除するため、proxmoxのweb GUIでshutdownやstopをクリックした所、以下のようなエラーが出て削除できなくなりました。
![Error popup](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327331/757ade3d-150e-59c7-97b1-ed659b56ef55.png)
```
(can't lock file '/run/lock/lxc/pve-config-118.lock' - got timeout (500)　LXC
```

## 対処法1(失敗): `pct unlock {container ID}`
これは別で見つけた対処法ですが、同じようなエラーが出て無理でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327331/a188ec3c-71a0-d690-92c0-4379a4ce0b12.png)

## 対処法2(成功): remove lock file
上記のエラーで表示される lock file 自体を直接削除し、
その後でweb GUIから`stop->remove`が出来ました。

## そもそも lock file とは？
Linuxのlockfileは複数のプロセスが1つのファイルを同時に書き換えてしまわないための、1つ以上のsemaphore fileのだそうです([lockfile(1) - Linux man page](https://linux.die.net/man/1/lockfile))。

なので、これが存在している限り、proxmoxはrmなどの処理ができないのかなという感じです。

が、如何せんLXCに関する情報が少なく具体的な処理フローまでは不明です。
今回はrootfs内が完全に消えたため、コンテナ自体がlockされっぱなしだったのかなと思います。

## ちなみに
今回成功した対処法2はchatGPT-4に教えてもらいました。すごいですね。
![chatGPTの回答](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327331/6fa6bcd7-0ddb-1ada-bda6-32de51e8aa13.png)


## 参考文献
https://bobcares.com/blog/cant-lock-file-proxmox/

https://linuxhandbook.com/file-locking/
Salesforce多要素認証

忘れそうなので、備忘で記載。

### SalesforceのMFAが必須化。（セキュリティ対策を強化のため。）
・ただし、外部ユーザ（顧客）・連携ユーザなどは任意。あくまで社内ユーザが必須。
・Sandbox（＝テスト環境）は任意。
・SSOをした場合、Salesforce側の他要素認証は不要（SSO側でMFAを実施しているという仕切り。）

https://help.salesforce.com/s/articleView?id=000388806&type=1

### そもそも多要素認証とは？
複数の要素を組み合わせた認証。（2要素以上を組み合わせた認証）
要素とは3種類あり。
　①知識・・・パスワード、秘密の質問など、頭に入っている知識の情報
　②生体・・・指紋、静脈など、身体の情報
　③所持・・・携帯電話、ICカードなど所持している物の情報
なので、ID/PW（①）だけや、ID/PW＋秘密の質問（いずれも①）の認証だけだと1要素となってしまい、多要素とならない。（後者のID/PW＋秘密の質問は、多【段階】の認証となる。）
※③は、ワンタイムパスワードが飛んでくるものもあれば、時間内に許可を実行するものなどさまざま（OTP、TOTPなど）

### 具体的な多要素認証の方式例
１．ID/PW＋Salesforce Authenticator　（③所持）　※無料
２．ID/PW＋Google Authenticatorなど3rd Party（③所持）
３．ID/PW＋ユビキー（③所持）
４．ID/PW＋3rd Partyの生体認証（②生体）
※上記以外にSSOなど

https://trailhead.salesforce.com/ja/content/learn/modules/identity_login/identity_login_2fa


### Salesforce Authenticator手順
＜前提＞手元のスマホに「Salesforce Authenticator」をインストール済み
１．（一括で組織にMFAを有効化してよいなら、）設定＞ID検証＞Salesforce 組織へのすべての直接 UI ログインに多要素認証 (MFA) が必要　にチェック
※権限セットを使い、1人1人にMFAの指定も可能。

２．Salesforceにログインしようとすると、手元のSalesforce Authenticatorに、2Wordが表示されるため（例：moderate water）入力を行い、紐づけ。

３．あとはSalesforceにログインする際に、適宜Authenticator側に許可する画面が表示されるので、適宜許可をすることにより認証。

### その他
・スマホを紛失した場合　→システム管理者にて、現状のスマホとの紐づけを切断可能。
・位置情報で自動的にAuthenticator側の許可も可能
・Lightning Loginを使い、パスワードレスでログインも可能（Authenticator側の認可だけ。）
　→Lightning Login は MFA の一種ですか?
はい、Lightning Login を使用することで、Salesforce Platform 上に構築された製品の MFA 要件を満たすことができます。この機能を使用すると、ユーザーは拡張 MFA 環境を使用して、パスワードなしですばやく安全に Salesforce アカウントにアクセスできます。Lightning Login は、Salesforce Authenticator (ユーザーが持っているもの) とモバイルデバイスでの PIN または生体認証スキャン (ユーザーを表す物) という 2 つの認証要素を要求することで、MFA 標準を満たします。詳細は、Salesforce ヘルプの「Lightning Login の有効化によるパスワードを使用しないログイン」を参照してください。
Javaの条件分岐について学習してみた

# 概要

Javaの条件分岐について学習してみました。以下のページを参考にしました。

条件分岐

https://www.javadrive.jp/start/if/

if文を使った条件分岐

https://www.javadrive.jp/start/if/index1.html

switch文を使った条件分岐

https://www.javadrive.jp/start/if/index4.html

# まとめ

何かの役に立てばと。
WSL2 で Docker Version 表示されて service start で starting しても status 見たらnot running

# 経緯
Windows上にLaravel Sailで開発環境を構築しようとした。

# 環境

Windows 11 Home
WSL2
Ubuntu 22.04
Docker 24.0.4

# エラーログ

```/var/logs/docker.log
error="context canceled" module=libcontainerd namespace=plugins.moby
failed to start daemon: Error initializing network controller: error obtaining controller instance: unable to add return rule in DOCKER-ISOLATION-STAGE-1 chain:  (iptables failed: iptables --wait -A DOCKER-ISOLATION-STAGE-1 -j RETURN: iptables v1.8.7 (nf_tables):  RULE_APPEND failed (No such file or directory): rule in chain DOCKER-ISOLATION-STAGE-1
```

# 解決策

```
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
```

# 原因はよくわからん

最初権限回りの問題かと思い、

```
sudo chmod 666 /var/run/docker.sock
```

を叩いたがエラー解消されず。

エラーログを見ると

```
iptables failed:
```

という記述があった。

（iptableとは、ざっくり言うとUbuntuのファイアフォールらしい）


iptables-legacyを使用するように変更したところ、
無事ビルドされた。
Sumatra PDF で漫画を見開き表示する

## Sumatra PDFとは

オープンソースの軽量PDF Viewer
ただ軽量で読めれば良い人には便利です。
[Free PDF Reader - Sumatra PDF](https://www.sumatrapdfreader.org/free-pdf-reader)

日本語で調べると『見開き表示すると表紙がうまく処理されない』『右綴じ本が読めない』等々出てきますが、設定すれば問題なく読めます。

## 見開き表示する

`メニュー->表示->ブックビュー` を選択します。
`見開き` という項目もありますが、こちらは表紙が含まれている場合表示が崩れます。

## 右綴じ本を表示する

`MangaMode`で漫画などの右綴じ本を表示します。

`メニュー->設定->詳細設定` を選択すると、テキストエディタで`SumatraPDF-settings.txt`が開かれます。
`Shortcuts`という項目を探して以下のように編集します。

```txt
Shortcuts [
	[
		Cmd = CmdToggleMangaMode
		Key = Shift + M
	]
]
```
ソフトを再起動後、`Shift + M`で右綴じ本の表示に切り替えます。
AtCoderABC310のA問題解説

# レベル
灰色コーダーの私が私の復習用兼Qiitaの発信練習用に執筆しているので、過不足が激しいです。始めて投稿する記事ですし、この記事を見るのはおすすめしません。
もし億が一この記事を見て間違いなど発見されましたらコメントお願いします。

# AtCoderBegginerContest310
のA問題解説します（誰得？）

https://atcoder.jp/contests/abc310/tasks/abc310_a

# 入力部分
問題文読むと眠くなったり集中力切れたりやる気なくなったりするのでまずは手を動かします。
そのために「入力は以下の形式で・・・」ってところを見ます。

```
N P Q
D1 D2 ... DN
```
入力はすべて整数っていうのが見えたので、c++の**int**を使って宣言していきます。

```c++
int N,P,Q;
```
それぞれに入力します。
```c++
cin >> N >> P >> Q;
```

D1~DNは、整数が何個入るかわからないので、vectorを使って動的配列を作ります。


```c++
vector<int> D(N);
```
pythonでいうところのlistと同じだと思います。
c++の**array**で配列を宣言する場合は、**静的**配列といって格納できる数が予め決まってます。**vector**はそのサイズを増やしたり減らしたりできるので**動的**配列っていうみたいですね。

次にDっていう配列?(配列って呼んでいいのかわからない)にN個の数字を入力するプログラムを書きます。

```c++
for(int i = 0; i < N; i++){
    cin >> D[i];
}
```
N回forループをするので、計算量はオーダーN?な気がする。

# 入力のプログラムがあってるかたしかめる
初心者だと入力部分の実装で手一杯みたいなことありません？なければこの章は飛ばしてもらって大丈夫です。
```c++
cout << N << P << Q;
for(int i = 0; i < N; i++){
    cout << D[i];
 }
cout << endl;
```
入力の逆をやって、入力したやつと同じのが出るかどーか確認します。同じのが出たら上記のプログラムは消します。

# 問題の方針を立てる
頑張って文章読みます。ABCのコンテストは毎週土曜の21時から開催されるので、ご飯食べた後で眠たいですがコーヒーでも飲んで頑張りましょう。

頑張って読んだ結果私たちがやるべきことは
「**P円**と**Q+Di円**の小さい方を出力する」です。

さらに、**Q+Di円**の価格は**i**の数値によって変わってくるので、**Q+Di円**の最小値を先に求めておきたいです。

# Q+Di円の最小値を求める
```c++
//最小値minDを大きめに設定しとく
int minD = 9999999;

for(int i = 0; i < N; i++){
    if(minD > D[i]){
        minD = D[i];
     }
 }   
```
minDとD[1],D[2],D[3]....D[N]を比べて、小さいやつをminDに入れておくことで最小値が求まります。

入力文もforループ使ってここでもforループ使うと冗長なので、合体させます。
```c++
int minD = 9999999;

for(int i = 0; i < N; i++){
    cin >> D[i];
     if(minD > D[i]){
        minD = D[i];
     }
 }
```
あとは、「**P円**と**Q+Di円**の小さい方を出力する」だけです。

# P円Q+Di円の小さい方を出力する

```C++
int Pien = Q + minD;
if(P > Pien){
    cout << Pien << endl;
}else{
    cout << P << endl;
}
```
# 全体プログラム
```c++
#include<bits/stdc++.h>
using namespace std;

int main(){
    int N,P,Q;
    cin >> N >> P >> Q;

    vector<int> D(N);
    int minD = 999999;

    for(int i = 0; i < N; i++){
        cin >> D[i];
        if(minD > D[i]){
            minD = D[i];
        }
    }
    
    int Pien = Q + minD;
    if(P > Pien){
        cout << Pien << endl;
    }else{
        cout << P << endl;
    }
    return 0;
}
```
# 感想
始めてQiitaで記事を書いてみました。HTMLタグを書かずにめちゃくちゃ簡単に書けるので、Qiita楽しいです。

**発信**することは**課題発見**にも繋がりますし、**アウトプット**によって記憶の定着にもなりますのでなんとなく良いことな気がします。

今後も数週間から数カ月は誰得？な記事を発信して自身の成長に繋げて行こうと思います。もし億が一この記事を見てくださっている誰かがいたのなら、私が誰かの役に立てる記事がかけるようになるまで見守っていてください。
【解説】広告ブロックによる損失収益の回復の設定方法【Google Adsense】

## Google Adsenseの広告ブロック対策

Google Adsenseで広告ブロックを検知して、広告を許可するよう促す機能があるのを初めて知ったのでまとめておきます。特に自分は技術ブログなのでITリテラシーの高いユーザ層は広告ブロックを結構利用してるのではないかと推測しています。レポートも出るのでいろいろ参考にしたいですね。


## 広告ブロックによる損失収益の回復の設定方法

&emsp;
Googleアドセンスの「プライバシーとメッセージ」から「広告ブロックによる損失収益の回復」に移動します。
![広告ブロックによる損失収益の回復-設定方法-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/b6dd3506-10ac-c650-3aa7-0a44295c659a.jpeg)

&emsp;
メッセージの作成をクリック
![広告ブロックによる損失収益の回復-設定方法-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/07ae0bd2-353c-66d3-71a0-05aa34c634b9.jpeg)

&emsp;
以下設定を行います。カスタムソリューションで柔軟に対応できるみたいです。
![広告ブロックによる損失収益の回復-設定方法-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/8476681f-118f-475e-c823-e960c68d4d84.jpeg)

![広告ブロックによる損失収益の回復-設定方法-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/f69ed008-da9f-64b9-f451-b9f9dc3f2f83.jpeg)

&emsp;
プレビューで確認できます。自分もたまーにみたことありますね。
![広告ブロックによる損失収益の回復-設定方法-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/f7c80eb1-5dd7-acfa-e79f-476feed90152.jpeg)

&emsp;
ぽちぽち進めます
![広告ブロックによる損失収益の回復-設定方法-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/66adfbc7-c22d-ff10-c9e9-63f9c373c611.jpeg)

&emsp;
作成したメッセージをブログで表示するためには、ブログのheadタグの間に挿入する必要があります。まずは内容をコピーします。
![広告ブロックによる損失収益の回復-設定方法-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/9052065f-c2cf-7a36-4f5c-74925652ac5f.jpeg)

&emsp;
自分はSwellで運営しているので、外観→カスタマイズ→高度な設定に移動し、以下の画面の箇所に貼り付けて完了です。時間をおけば対象の広告ブロック使用ユーザにメッセージが表示されるようになります。
![広告ブロックによる損失収益の回復-設定方法-8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/c61a908a-8c14-f92b-3c63-069848feaf32.jpeg)





## まとめ


Google Adsenseで広告ブロックを検知して、広告を許可するよう促す機能が便利。技術ブログでの広告ブロックの使用率はいかに・・・
【解説】GDPRメッセージの作成方法

## GDPRメッセージの警告が表示された

Googleアドセンスをみたら、GDPRメッセージのつくれという警告が表示されていました。今回は、GDPRメッセージの作成方法を解説していきます。

![GDPRメッセージの警告.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/5325b1a5-bfe2-ae0f-ff98-01cfcafbf026.jpeg)



## GDPRとは
ChatGPTに聞いてみると、以下の通り、GDPRはEU圏内の個人データを保護する法律とのことです。


>GDPRは「General Data Protection Regulation（一般データ保護規則）」の略称で、欧州連合（EU）が2018年に施行したデータ保護に関する法規制です。
GDPRは、EU圏内のすべての個人の「個人データ」を保護することを目的としています。
具体的には、EUの市民や居住者のデータがどのように収集、保管、使用、共有されるかについての厳格な規制を定めています。GDPRは、EU圏内だけでなく、EU圏内の人々のデータを扱うすべての企業や組織に対して適用されます。


## GDPRメッセージの作成方法

GoogleアドセンスでEU圏内のユーザに向けて個人情報の取り扱いに関する同意を得るためのGDPRメッセージを作成します。
基本的にぽちぽちやるだけで終わります。[Google公式サイト](https://support.google.com/adsense/answer/10960768?hl=ja)

&emsp;
まずは「GDPRメッセージを作成」をクリック
![GDPRメッセージの警告.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/5325b1a5-bfe2-ae0f-ff98-01cfcafbf026.jpeg)

&emsp;
「GDPRメッセージを作成」をクリック
![GDPRメッセージの作成方法-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/ba0ac7fd-dbdf-f8cf-9f80-c292ece4fc49.jpeg)

&emsp;
「サイトを選択」をクリック
![GDPRメッセージの作成方法-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/9e967fb0-d6a8-c10d-6d53-6d1cd3dfc4bf.jpeg)

&emsp;
サイト名を入力、プライバシーポリシーのURLを指定し、ロゴを設定します。
![GDPRメッセージの作成方法-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/f6970e79-05a9-f9a5-bd3b-d35df92a7ded.jpeg)

&emsp;
以下のように設定します。
![GDPRメッセージの作成方法-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/97828754-549d-a1ca-ee85-50e7ae1293ab.jpeg)

&emsp;
EU圏内のユーザーには各ユーザの言語が表示されるので、「言語」は自分の確認用で日本語でかまいません。
![GDPRメッセージの作成方法-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/052d2dd1-eee7-b326-baf7-ce6fd951d12b.jpeg)

&emsp;
EU圏内のユーザーに表示されるGDPRメッセージをプレビューで確認できます。基本いじらなくていいと思います。
![GDPRメッセージの作成方法-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/9977560b-6b35-6e03-6f5b-65f7f7de90a0.jpeg)

&emsp;
よければ、右上の公開をクリックします。
![GDPRメッセージの作成方法-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/8aa9e82d-da9e-9baf-198c-34452753fe28.jpeg)

&emsp;
以上でGDPRメッセージの作成できました。GDPRメッセージの表示は作成から1時間ほどラグがあるそうです。
![GDPRメッセージの作成方法-8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3336223/63eee2dd-477a-472b-84b6-82068fab11af.jpeg)


## まとめ


GDPRメッセージはEU圏内の個人データに関する同意を得るために必要になる。
まあEU圏内のユーザなんか自分のブログにくることないですけどね。
Prismaで特定カラムを上手にexcludeする (userのpassword等を返さないようにする)


## はじめに

prismaでクエリを発行する際、passwordカラム等の除外したいカラムを

```ts
 this.prisma.user.findUnique({
      where: userWhereUniqueInput,
      exclude: 'password'
    })
```

と書けたらいいなぁ…という妄想を全人類がしていることだと思う。
これ、[2020年4月からissueがある](https://github.com/prisma/prisma/issues/5042)のに、全く対応される気配がない。

愚直に `select` で

```ts
 this.prisma.user.findUnique({
      where: userWhereUniqueInput,
      select: { id: true, email: true, ... },
    })
```
と書くこともできるのだが、これだとuserテーブルにカラムが増えるたびに
手動ですべての `select` 文をイジることになるのでつらい。

## 対応策

excludeしたいカラム以外のすべてのフィールドを列挙する関数を作り、
selectに指定してあげれば良い。

①以下関数を任意の場所に作成する

```ts
export const prismaExclude = <T extends Models['fields'], ExcludeT extends (keyof T)[]>(
  fields: T,
  exclude: ExcludeT,
) => {
  const keys = Object.keys(fields) as (keyof T)[];
  const excludeSet = new Set(exclude);
  const attributes: Partial<Record<keyof T[][number], boolean>> = {};
  for (const key of keys) {
    if (excludeSet.has(key)) attributes[key] = false;
    else attributes[key] = true;
  }

  type IncludeType = {
    [K in keyof T]: true;
  };
  type Result = Omit<IncludeType, ExcludeT[number]>;
  return attributes as Result;
};

```

②以下のように使う。prismaのfieldsを第一引数、除外したいカラムの配列を第二引数に渡す。
 (例はfindUniqueだが、findMany, create, update, delete 等でも使える)

```ts
 this.prisma.user.findUnique({
      where: userWhereUniqueInput,
      select: prismaExclude(this.prisma.user.fields, ['password'])
    })
```

## 注意

fieldsはPrisma 4.3.0 からPreviewで入り、5.0.0で正式に取り入れられた機能なので、
- 4.3.0未満を使っている人 → 要アップデート
- 4.3.0以上～5.0.0未満を使っている人 → prisma.schemaに以下の記載が必要
  ```
  generator client {
    provider        = "prisma-client-js"
    output          = "./client"
    previewFeatures = ["fieldReference"] // ★追記
  }
  ```


## あとがき

おそらくいつか公式でexcludeに対応する日が来ると思うので、
この記事がそれまでのつなぎになれば幸いだ。

ちなみにこの方法は[上記issueに出てきたこれを参考にした](https://github.com/prisma/prisma/issues/5042#issuecomment-1596250589)
LOG2

毎度毎度Windowsに頼ってばかり　いい加減Linuxを触れるようになりたい
そもそも電化製品全般の仕組みを全く知らない　毎日使っておきながら、不敬極まりない
素材の一部になるレアメタルや鉱物は海外の人を重労働させて手に入れているらしい　不理解、不平等の世界だ
巨大なビルや鉄道網は力仕事で出来ている　上っ面だけの知性、文明に辟易甚だしい
広く世の中を見渡すと、賢愚、貧富、身分の隔たりがある
それはなぜか　福沢諭吉は「学ぶか、学ばないか」によって決まるのであると言った
これは、何も考えないで安楽を享受しようとする自分を戒める為に、日々思い出したい言葉だ
何も知見を広めるのに躊躇する理由はない
venv環境内でpipがFatal errorで動かなくなったときの対処法


# エラー内容

```
C:\work\sample> pip list
Fatal error in launcher: Unable to create 
process using'"C:\work\example\venv\Scripts\python.exe"  
"C:\work\sample\venv\Scripts\pip.exe" ': ??????????????????
```

# 原因
pipを生成した際にpythonへの絶対パスをファイル内に保存している
そのため、ディレクトリの変更があるとpipがpythonを見つけられずエラーを起こす

# 対処法
実行時に`py -m pip list`のように、pathを指定してあげれば動きはするが、毎回打つのはめんどくさい

pipをバージョンアップ、もしくは再インストールすれば解決する


### pipが最新でなくアップグレードできる場合
```powershell
.\venv\Scripts\activate.ps1
py -m pip install -U pip
```
実行できた場合は`deactivate`して再度Activateすることで治る

### すでに最新、もしくは治らなかった場合
```powershell
.\venv\Scripts\activate.ps1
py -m pip uninstall pip
deactivate
py -m venv ./venv/ --copies
```
pipを一度削除したうえで
`--copies`のオプションを利用しグローバルのpipをコピーしてきている

# まとめ

この方法であれば他のライブラリに影響を与えずに修復できる