OmniAICreator/Qiita-1.07M huggingface dataset:
GitHub ActionsでGo 1.20使用時に `go mod tidy` が失敗した場合

# TL; DR

バージョンはクオーテーションで囲みましょう :innocent:

```yaml
go-version: '1.20'
```

# はじめに

Go1.20を使ってGitHub Actionsを実行していたら、`go mod tidy` が以下のエラーで失敗してしまいました。

```
go mod tidy: exit status 2; output: go: unknown subcommand "mod"
```

`mod` がなぜか認識されない...?

```yaml:.github/workflows/release.yml
name: release
jobs:
  goreleaser:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v3
        with:
          # Goのバージョン
          go-version: 1.20
```

# 原因

バージョンを数値で指定したので、Go `1.2` がインストールされてしまったのが原因でした。それは `go mod` 使えなくても仕方がない :angel:

```
Run actions/setup-go@v3
  with:
    go-version: 1.2
    check-latest: false
    token: ***
    cache: false
Setup go version spec 1.2
Attempting to download 1.2...
matching 1.2...
Not found in manifest.  Falling back to download directly from Go
Install from dist
Acquiring go1.2.2 from https://storage.googleapis.com/golang/go1.2.2.linux-amd64.tar.gz
```

正しくは文字列で以下のように指定します。

```yaml:.github/workflows/release.yml
      - name: Setup Go
        uses: actions/setup-go@v3
        with:
          # これで末尾の0が消えることは無い
          go-version: '1.20'
```


~~ただのポカミスですね...~~
エラー理由に一瞬ぎょっとしたので、忘れないように記事にしました。**yamlを書くときは文字列のクオーテーションを忘れずに！**
ZenHubのissueのリポジトリを変更する方法

本記事では、ZenHubでissueを別のリポジトリに移動する方法について説明します。

## ZenHub上ではリポジトリの変更ができない

ZenHubでは、issueのリポジトリを後から変更できません。GitHub上で行う必要があります。

## issueを移動する2つの方法

issueを移動する方法は次の2つがあります。

- GitHubのUIで移動する
- `gh`コマンドで移動する

## リポジトリ移動の注意点

issueをリポジトリを超えて移動すると、次の情報が消えることが分かっています。

- パイプラインステップ
- ラベル (移動先リポジトリに存在しないラベルは剥がされる)
- スプリント
- エピック
- ストーリーポイント

これらは移動する前に情報を控えておき、手動で復元する必要があります。

## `gh`コマンドで移動する

ghコマンドを用いて、sourceリポジトリからtargetリポジトリにissueを移動する手順を説明します。

### 必要なもの

この手順を行うのに必要なツールは次のとおりです。

- git
- [gh](https://cli.github.com/manual/installation) ─ `brew install gh`

### sourceリポジトリをクローンする

まず、sourceリポジトリをローカルにクローンしてください。

```bash
git clone git@github.com:my-org/source.git
```

クローンしたらリポジトリのルートディレクトリに移動してください。

```bash
cd source
```

### 移動したいissue番号を調べる

ZenHubなどで移動したいissue番号を控えてください。たとえば、#123の「123」の部分です。

### ghコマンドで移動する

次のコマンドを実行すると、リポジトリを移動できます。

```bash
gh issue transfer <issue番号> <移動先リポジトリ>
```

たとえば、#123をmy-org/targetに移動する場合は次のようなコマンドになります。

```bash
gh issue transfer 123 my-org/target
```
MySQLの色々その２Readとロックの色々

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はMySQLの色々その１として、Readとロックの色々について更に詳しく調べてみましょう！

![インスタスライド_202302032.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/7472f542-2f13-8ce4-0cf4-b048eb8f614c.gif)


# Readの種類
ダーティリード【Dirty Reads】
並列実行中の他のトランザクションが書き込んだ未コミットのデータを読み込む。

ノンリピータブルリード【Non-repeatable Reads】
並列実行中の他のトランザクションが更新しコミットしたデータを読み込んでしまうため、以前読み込んだデータを再度読み込むと異なる値となる。

ファントムリード【Phantom Reads】
並列実行中の他のトランザクションが挿入しコミットしたレコードを読み込んでしまうため、以前存在しなかった行データが読めてしまう。

# MySQLでは
MySQLのInnoDBでは、

分離レベルは Repeatable read でファントムリード等の間違ったReadが発生しないよう工夫が施されています。

この仕組みがネクストキーロックと呼ばれるアルゴリズムです。

# ネクストキーロック
Where句で指定したデータとインデックスの隙間（ギャップ）のギャップロック
直近のデータのロック（レコードロック）

この２つをあわせてネクストキーロックという

# まとめ
ーReadで色々な種類があり、　MySQLでもその対策がされている

ーMySQLでは、where句以外のデータもロックされる

ーロックの範囲を知ればロック対象を減らせてパフォーマンスが上がる

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
RemixでCookie length will exceed browser maximumエラーが発生した際の話

`remix-auth`で提供されている`Authenticator`インスタンスの`authenticate()`を実行してログイン処理を行なっていたら、あるときブラウザのクッキーの許容量を超えてしまい、次のようなエラーが発生した。

```shell
Error: Cookie length will exceed browser maximum. Length: 5174
    at Object.commitSession (/workspaces/example-app/node_modules/@remix-run/server-runtime/dist/sessions/cookieStorage.js:41:15)
    at FormStrategy.success (/workspaces/example-app/node_modules/remix-auth/build/strategy.js:68:38)
    at action4 (/workspaces/example-app/app/core/ui/components/PasswordTextInput.tsx:25:7)
    at Object.callRouteActionRR (/workspaces/example-app/node_modules/@remix-run/server-runtime/dist/data.js:24:16)
    at callLoaderOrAction (/workspaces/example-app/node_modules/@remix-run/router/router.ts:3061:14)
    at submit (/workspaces/example-app/node_modules/@remix-run/router/router.ts:2568:16)
    at queryImpl (/workspaces/example-app/node_modules/@remix-run/router/router.ts:2503:22)
    at Object.queryRoute (/workspaces/example-app/node_modules/@remix-run/router/router.ts:2453:18)
    at handleDataRequestRR (/workspaces/example-app/node_modules/@remix-run/server-runtime/dist/server.js:81:20)
    at requestHandler (/workspaces/example-app/node_modules/@remix-run/server-runtime/dist/server.js:55:18)
    at /workspaces/example-app/node_modules/@remix-run/express/dist/server.js:39:22
POST /login?_data=routes%2Flogin 500 - - 98.592 ms
```

これは、`authenticator.use()`に渡す`verify()`コールバック関数内で返す値がクッキーに保存するには大きすぎるために発生するエラーであることがわかった。

なので、必要なデータだけを取り出して返すようにするとエラーが解消された。

```ts
authenticator.use(
  new FormStrategy(async ({ form }) => {
    const userRepository = container.resolve<UserRepository>("UserRepository");
    const email = `${form.get("email")}`;
    const password = `${form.get("password")}`;
    ...
    const result = await userRepository.verifyLogin(email, password);
    ...
    const { id } = result.data;
    return {
      id,
    };
  }),
  "user-pass"
);
```
５分で紹介「情報セキュリティの敗北史」

# はじめに
この記事は **「情報セキュリティの敗北史：脆弱性はどこから来たのか」** を５分で**この本の魅力や大まかな内容**を理解することを目的とした記事です。
この記事で少しでも興味を持ってこの本を読むきっかけになれば幸いです。

<img width="300" alt="名称未設定のアートワーク 1.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2921163/b39a3334-3985-34d2-1687-80cb839d51b3.jpeg">

# 目次
**・概要
・個人的な感想
・参考文献**

## 概要
この本は  **「情報セキュリティの歴史」** を振り返りながら、
**「なぜ情報セキュリティは失敗の連続なのか」** を知ることができる本です。

本の構成は **９つの章** から構成されています。
それぞれの章では過去の事例を挙げ、
当時の時代背景などと共にシステムの脆弱性に触れて、
 **「なぜその取り組みが失敗に終わってしまったのか」** が書かれています。

全体を通して、新しい技術や情報を取り扱う内容は少なく、
過去の事例を振り返ることで、
 **なぜ今の現状がこのようになっているのか** を理解するとともに、
 **これからどのように進んでいくべきかを考えること** ができるような内容になっています。

## 個人的な感想
個人的にはこの本は **情報セキュリティに興味がある人** や、
**ある程度情報セキュリティについて知識がある人**におすすめできる本だと思いました。

逆に**あまり情報セキュリティに興味がない人**や、
**情報セキュリティ初心者の人**にはあまりおすすめできません。

その理由はこの本は**全406ページ**あり、
少し長めなので情報セキュリティについて興味がないと、
最後まで読み切るのは少し大変だと思ったからです。

しかし、情報セキュリティについて興味がある人にとっては、
**一冊で情報セキュリティの歴史の全体像**をつかむことができ、
より**情報セキュリティの奥深さ**を知ることができる本だと思います。

# 引用
>著　アンドリュー・スチュアート　訳　小林哲倫
情報セキュリティの敗北:脆弱性はどこから来たのか.
2022/10/12



https://www.amazon.co.jp/%E6%83%85%E5%A0%B1%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%81%AE%E6%95%97%E5%8C%97%E5%8F%B2-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%AF%E3%81%A9%E3%81%93%E3%81%8B%E3%82%89%E6%9D%A5%E3%81%9F%E3%81%AE%E3%81%8B-%E3%82%A2%E3%83%B3%E3%83%89%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%BB%E3%82%B9%E3%83%81%E3%83%A5%E3%83%AF%E3%83%BC%E3%83%88/dp/4826902433
2023/2/27主にITとかセキュリティの記事

npmに1万5,000超の偽のパッケージが登録、フィッシングに悪用(2/25)
https://news.mynavi.jp/techplus/article/20230225-2600581/

ChatGPTにだまされない、フィッシングメールを見破る6つのポイント(2/25)
https://news.mynavi.jp/techplus/article/20230225-2601016/

新たなインフォスティーラ型マルウェア「Stealc」に注意、充実した管理画面も(2/25)
https://news.mynavi.jp/techplus/article/20230225-2599735/

ChatGPTの話題を悪用したサイバー詐欺が横行中、注意を(2/25)
https://news.mynavi.jp/techplus/article/20230225-2600638/

【Laravel / PHP】研修期間に受けたコードレビューから学んだ事(2/24)
https://qiita.com/yun-yzrh/items/eb5475a0112d45d09bfa

”ルフィ事件”で注目を集めた通信アプリ「テレグラム」をヤクザも重宝している「納得の理由」(2/25)
https://news.yahoo.co.jp/articles/fe4601be3be82c88972bff68988f6c6189f3f6c7?source=rss

欧州委員会もTikTok禁止、職員に業務用端末からのアプリ削除を指示(2/25)
https://forbesjapan.com/articles/detail/61233

世界中で選挙を操作してきた「イスラエルの秘密組織」は、世論をどのように動かしているのか(2/25)
https://news.yahoo.co.jp/articles/bc7d35ec445a3c2ef627087e08893eb35a033428?source=rss

新EU Directiveによるサイバーセキュリティ規制のパラダイムシフト(2/25)
https://www.gmp-platform.com/article_detail.html?id=18459&lang=ja

【仮想通貨初心者向け】ビットコイン取引の始め方とおすすめの取引所(2/25)
https://crypto-times.jp/start-bitcoin/

北陸新幹線の駅舎見学会に応募した132人の個人情報漏えい　福井県越前市、18日間閲覧できる状態に(2/25)
https://www.fukuishimbun.co.jp/articles/-/1732400

成績データ管理にクラウド活用へ　教員宅で処理、業務効率化(2/24)
https://www.tokyo-np.co.jp/article/232987
【UiPath】Computer VisionでCJK OCR(中日韓)を使い画面表示文字を取得する

# はじめに

Computer Visionで新しい日本語対応のOCR「CJK OCR(中日韓)」が利用可能になり、色々と試して見たので備忘録として残していきます。
尚、CJK OCR(中日韓)のエンドポイントはUiPath Document Understandingですので、UiPath Document Understandingも同じ仕様です。
結論から言うとUiPathで標準搭載していたOCRの中では、高い精度で日本語の文字を読取ります。UiPath Document Understandingの日本語精度が飛躍的に良くなったと言うのは、これですね。

# CV画面スコープの設定
CV画面スコープの設定は下記のブログを参考にしてください。

https://qiita.com/Jun96427231/items/11f91e9279497deec449

# Computer Visionで画面からテキストを取得

参考にですがUiPath Demoサイトの経費照会画面で登録した項目を読み取ってみた結果です。
Computer Visionで指定した要素にある１つ１つの文字は正しく読み取れてそうですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/55392c55-3533-e498-5e63-b5368dbca42d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/3f5a0046-a363-849b-87e8-ac597f1e171e.png)


# 仕様を考察

ここから備忘録です。
CJK OCR(中日韓)の読取りの仕様が公開されていないので、実際に使って見て蓄積するしかなさそうです。
まだ、これ以外にあると思うので、参考として見てください。

漢字、ひらがな、カタカナと
。、・「」
の文字を便宜上、CJK文字として表現します。

| 読取り対象 | 読取り後 |
|:-----------|:-----------|
| 英数字（半角）| ○ |
| 英数字（全角）| 全て半角に変換される。変換された数字の間には半角スペースが入る。 |
| CJK文字 | 文字の間に半角スペースが入る。 |
| カタカナ（半角） | カタカナ（全角）に変換される。文字の間に半角スペースが入る。 |
| 英数字（半角）の直後にCJK文字 | 半角スペースが入る。 |
| CJK文字の直後に英数字（半角） | 半角スペースが入る。 |
| CJK文字の間に連続したスペースを入れる | 半角スペース１つに変換される。 |
| 英数字（半角）の間に連続したスペースを入れる | 半角スペース１つに変換される。 |

# 後処理のサンプル

取得したテキストを、どう使うかにもよりますが、一部、例で記載しようと思います。

1. CJK文字間、英数字（半角）直後にCJK文字、CJK文字直後に英数字（半角）の半角スペースを削除（置換）する正規表現

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/87380f6e-8b93-5305-f7f8-89073d6c637d.png)


```
\x20(?=[ぁ-んァ-ヶー一-龯。、・「」])|(?<=[ぁ-んァ-ヶー一-龯。、・「」])\x20
```

:::note info
テキストボックスの要素から文字列を取得するなら、「選択-すべてのテキスト」もしくは「選択-テキストの行」を指定して取得するのがお勧めです。これはコピー/貼り付けアクションをシミュレートし、選択可能なテキスト、ローカルまたはリモートセッションで、そのままのテキストを持ってこれるので、後処理が不要で、かつ確実です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/48be16b8-74e0-a323-d7ee-69684dad18a9.png)

### 取得可能なテキストの例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/b38ab482-3a86-bea6-b7c3-a209065d506d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/fcb8c9ea-c194-de66-6c90-c6491204077e.png)
:::


# おわりに
読み取りの仕様について、今後、追加情報があれば更新して行きたいと思います。

https://qiita.com/Jun96427231/items/11f91e9279497deec449

https://qiita.com/Jun96427231/items/82116becf2340d89f572
VOICEVOXをC#でREST-API経由で喋らせる（その１　発話）

# 概要
VOICEVOXをC#で使う記事が少ないため作成

- 以下の点は参考サイトから導入してください
    - VOICEVOXのインストール
    - VOICEVOXの起動
    - コンソールプロジェクトの作成

## 環境
VOICEVOX Ver. 0.14.1
Visual Studio 2022
.net7.0
コンソール アプリ

# 流れ
- 音声クエリを生成
- 音声合成
- 音声を保存
- 音声再生する
NuGetからSystem.Windows.Extensionを追加する

# 参考文献
https://qiita.com/A_T_B/items/1531d78944d8b796b9fa

https://qiita.com/Haruyama_Dev/items/5b8ac0260cdfeff47121

https://github.com/VOICEVOX/voicevox_engine#http-%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%A7%E9%9F%B3%E5%A3%B0%E5%90%88%E6%88%90%E3%81%99%E3%82%8B%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89

https://takabus.com/tips/77/

https://curl.olsh.me/

https://newnakashima.hatenablog.com/entry/2017/05/16/131816#:~:text=await%20response.Content.ReadAsStringAsync()%3B

https://teratail.com/questions/188397#:~:text=using%20(var%20fileStream,20

https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/630soundwaveplay/soundwaveplay.html#:~:text=%C2%A0%C2%A0%C2%A0%20wavePlayer.PlaySync()%3B




# プログラム
```c#:console.cs
using System.Media;
using System.Net.Http.Headers;

using (var httpClient = new HttpClient())
{
    string query;
    int speaker = 1;
    string text = "あかさたな";

    // 音声クエリを生成
    using (var request = new HttpRequestMessage(new HttpMethod("POST"), $"http://localhost:50021/audio_query?text={text}&speaker={speaker}"))
    {
        request.Headers.TryAddWithoutValidation("accept", "application/json");

        request.Content = new StringContent("");
        request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");

        var response = await httpClient.SendAsync(request);

        query = response.Content.ReadAsStringAsync().Result;
        Console.WriteLine(query);
    }

    // 音声クエリから音声合成
    using (var request = new HttpRequestMessage(new HttpMethod("POST"), "http://localhost:50021/synthesis?speaker=1&enable_interrogative_upspeak=true"))
    {
        request.Headers.TryAddWithoutValidation("accept", "audio/wav");

        request.Content = new StringContent(query);
        request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

        var response = await httpClient.SendAsync(request);

        // 音声を保存
        using (var fileStream = System.IO.File.Create("test.wav"))
        {
            using (var httpStream = await response.Content.ReadAsStreamAsync())
            {
                httpStream.CopyTo(fileStream);
                fileStream.Flush();
            }
        }
    }
}

//読み込む
var player = new SoundPlayer("test.wav");
//再生する
player.PlaySync();
Console.WriteLine("再生完了");
```
## そのまま再生
```c#:
using (var httpStream = await response.Content.ReadAsStreamAsync())
{
    //読み込む
    var player = new SoundPlayer(httpStream);
    //再生する
    player.Play();
}
```

# 備考
## 時間計測
Ryzen 7 3700X
”あかさたな”
(初起動時)音声クエリ生成...2秒程度
(2回目)音声クエリ生成...0.05秒程度
音声クエリから音声合成..0.4秒程度
laravelの422エラーの解決例

## 何があった？
requestファイルを使ってvalidationを作ったら422エラーが返ってきました。

## エラーの原因
requestファイルのvalidationを組んでいるキーを間違ってdbのカラム名にして組んでいたため、存在しないものをチェックしておりエラーを出しました。

```php:TestStoreRequest.php（動かない書き方）
// ==== 前略 ====
    public function rules(): array
    {
        return [
            'name'  => [ // ここの書き方が間違っている
                'required',
                'max:15',
            ],
        ];
    }
// ==== 後略 ====
```


## 解決方法
requestファイルのvalidationを組んでいるキーをinputタグのnameに揃えることで解決します。

```php:TestStoreRequest.php（動く書き方）
// ==== 前略 ====
    public function rules(): array
    {
        return [
            'test_name'  => [ // ここを修正
                'required',
                'max:15',
            ],
        ];
    }
// ==== 後略 ====
```
Running network tunnel under TCP is horrible idea

This passage is to explain why running network tunnel under TCP (for example running OpenVPN under TCP) is horrible idea.

# Characteristic of TCP

1. **Stateful**: sequence number is marked on every packet, so receiver can reconstruct the data stream ever if packet is received out of sequence

1. **Lossless**: receiver need to acknowledge which packet is received, otherwise sender will resend it. Furthermore flow control mechanism is also implemented in TCP, sender will limit number of packet send if resend mechanism is triggered.

# Why it is horrible idea

Stateful and lossless are not necessary for network tunnel protocol. Sequence maintenance of packet of TCP increase the latency of tunnel traffic because tunnel destination must wait for packet with small sequence number before sending already received packet with large sequence number.

Lossless is useless because packet tracing will be handled by destination (if TCP is used).

Furthermore, flow control mechanism makes thing worse. For example, current throughput of tunnel is 1Mbps, if one of the packet is lost (packet loss is very common in network), the throughput will drop significantly due to number of packet send is limited in resend mechanism. As a result tunnel buffer is full and packet will be dropped.
【 AWS 】 アーキテクチャ作成

## ■想定
シンプルなWebアプリケーションサービスをイメージして組んでみました。
※障害が発生した場合にも継続してサービスを提供できるように高可用性を意識しました。

## ■アーキテクチャ
![【個人目標】AWSアーキテクチャ.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192922/db9c82b1-108f-bd3b-dde8-e75c8fa62e80.png)


## ■意識したポイント
**○ELB**
　・ELBを設定することで、片方のEC2にだけトラフィックがかからないよう負荷分散を実現。
これによりシステムダウンでサービス提供が止まるといったケースを避けれると考えました。
　・EC2で障害が発生している場合、ELBからEC2へのヘルスチェックにエラーがます。
この場合、ELBはエラーとなったEC2に通信は振り分けず、正常なEC2にのみ通信を振り分けるため、継続的にサービスを提供することができます。

**○EC2**
　・障害が発生しEC2が停止した時に対応できるように、別アベイラビリティゾーンにもう1つEC2を設定しています。(※マルチAZ構成)

**○RDS**
　・EC2同様マルチAZ構成で組んでおります。
シングルAZだとユーザ側でデータの復元が必要なこと、再起動までのダウンタイムが発生することからマルチAZとしました。
マルチAZではマスターのRDSに障害が発生した場合に、スタンバイにフェイルオーバーが行われます。
マスターとスタンバイのデータは常に同期されているため、ユーザ側でのデータ復旧は必要ありません。
これにより、シングルよりダウンタイムの時間が短いためサービス復旧までが早くなります。
大規模言語モデルに関する論文①

## Scaling Laws for Neural Language Models
[[Kaplan+, 2020]](https://arxiv.org/abs/2001.08361) (OpenAI)

Transformer機構を用いた言語モデルの性能は、パラメータ数N・データセットサイズD・計算予算Cを変数とした冪乗則に従うという法則が示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614092/e3f806d6-71e4-d577-bbc3-6a5212ef0896.png)

例えば上図の**左のグラフ**は、データセットモデルパラメーターのサイズがボトルネックになっていない場合 (自由にサイズを増やし続けられる場合)に、計算予算を変化させたときのTest Lossの推移です。

PF-daysは、AIの計算に使われる単位の一つです。1 PF-dayは、$10^{15}$回（ペタフロップ）の演算を1秒間に行うコンピュータノードが1日間稼働したときの計算量を表します。
例えば、1750億パラメーターのGPT-3は、3640 PF-dayかかって訓練されました。


## Training Compute-Optimal Large Language Models
[[Hoffmann+, 2022]](https://arxiv.org/pdf/2203.15556.pdf) (DeepMind)

この論文は、**与えられた計算予算の下**で、Transformer言語モデルの最適なモデルサイズと学習トークン数のトレードオフを最適化したものです。
実験的に、70M以下から16B以上のパラメータ、5Bから400B以上のトークンで学習させた400以上のモデルの損失に基づいて、最適なモデルサイズと学習トークン数を推定しました。
Gopher (280B) と同じ計算予算で、70Bのパラメータと4倍以上の訓練データで学習させたChinchillaモデルは、Gopherを上回る精度を示しました。
3つのアプローチを提案しています。

### アプローチ1
一定のモデル群（パラメータ数70Mから10B以上）に対して、学習ステップ数を変化させ、各モデルを4種類の学習シーケンス数で学習させました。
これらの実行から、与えられた学習FLOP数で達成される最小損失の推定値を直接抽出することができます。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614092/16d6db01-da2a-339c-6e42-3e314e1f6c2b.png width=700>

Figure 2 の左はモデルサイズを変えたときの訓練損失カーブを表しています。
このうち訓練損失が最小となる灰色の点に対応するパラメータ数とトークン数を真ん中と右の図に示しています。


### アプローチ2
学習FLOP数を固定（9パターン）し、モデルサイズを変化させたときの訓練損失カーブを調べます。
損失カーブの谷となるモデルサイズを取り出し、対応するトークン数を取得します。
FLOP一定のときにモデルサイズが大きくなると、訓練できるトークン数が少なるため、このようなカーブを描きます。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614092/08b5975f-bee5-f25f-f0cf-bd4b39128742.png width=700>


### アプローチ3
アプローチ1と2の実験からのすべての最終的な損失を、モデルパラメータ数と確認したトークンの数のパラメトリック関数としてモデル化します。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614092/040af665-fb94-7ac4-6583-603d58166a46.png width=700>



### 結果

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614092/cbc27bc6-e917-a9b9-e558-28968015a082.png width=500>

提案法で最適なモデルパラメータ数と学習トークン数を特定して学習させたChinchillaは、同じFLOPsで他手法と比較したときに少ないパラメータ数を実現していることがわかります。（データ数は他の手法の4倍くらいです）
なお、点線は300億トークンに固定してモデルサイズを大きくしていった既存研究です。


<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614092/8901573e-3188-4225-e46a-5c9b3a5e16ad.png width=700>

また、様々なタスクにおいて既存法のGopherよりも高い精度となっています。
これは、同じFLOPsでモデルパラメータ数と学習トークン数のバランスを最適化した提案法の有効性を示しています。
学習トークン数がこれより多くなるとFLOPs一定の制約によりモデルパラメータ数を小さくする必要があり、トータルでは精度が下がります。
また、学習トークン数がこれより少なくなると、Gopherのようにパラメータ数は大きくできますが、トータルでは精度が下がります。


### 議論
学習には300Bトークンが広く使われますが、これまでは300Bトークンを固定としてモデルサイズを大きくし続けていました。
このアプローチはある一定のモデルサイズまでは有効ですが、それ以上のモデルサイズでは精度の伸びが鈍化してしまいます（べき乗則に従わなくなります）。
そこで、提案法により適切なモデルサイズを得ることが可能になります。


なお、学習はすべて1エポック未満のデータで行われたものです。
そのため、数エポックの学習の影響については今後の課題となります。
VBAを用いた文字列処理の備忘録

# Excelで下記の処理を行うVBAを用いた文字列処理の備忘録

## 行いたい処理としては：
### (1) 文字(漢字、平仮名)と半角数字からなる文字列 (例. あいう123え4567) を先頭から"え"までと下4桁の数字に分解したい。
### (2) 上の例に示した文字列の場合、"え"の箇所は必ず任意の1文字の平仮名であり、カタカナに変換 (例の場合"エ")したい。
### (3) 下4桁の数字の桁数は、1桁から4桁の数字になり得る。なお、4桁に満たない場合、･ (半角中黒) を挿入したい。

### (4) 選択したセルの1つ右隣のセルに(1)と(2)の処理結果を出力

```vb:RemoveRightDigits()
Sub RemoveRightDigits()
    Dim cell As Range
    For Each cell In Selection.Cells
        Dim str As String
        str = cell.Value
        Dim i As Integer
        For i = Len(str) To 1 Step -1
            If isNumeric(Right(str, i)) And i <= 4 Then
                cell.Offset(0, 1).Value = Left(str, Len(str) - i - 1) & StrConv(Mid(str, Len(str) - i, 1), vbKatakana)
                Exit For
            End If
        Next i
    Next cell
End Sub
```

### (5) 選択したセルの2つ右隣のセルに(1)と(3)の処理結果を出力

```vb:ExtractNumber()
Sub ExtractNumber()
    Dim rng As Range
    Dim str As String
    Dim i As Integer, j As Integer
    Dim num As String
    Dim cell As Range
    
    Set rng = Selection
    
    For Each cell In rng
        str = cell.Value
        
        For i = Len(str) To 1 Step -1
            If isNumeric(Mid(str, i, 1)) Then
                num = Mid(str, i, 1) & num
                j = j + 1
            Else
                If j > 0 And j < 5 Then
                    cell.Offset(0, 2).Value = num
                    Exit For
                End If
                num = ""
                j = 0
            End If
        Next i
        
        num = ""
        j = 0
    Next cell
End Sub
```

```vb:AddDotToShortNum()
Sub AddDotToShortNum()
    Dim r As Range
    Dim cell As Range
    Dim num As String
    
    Set r = Selection.Offset(0, 2)
    
    For Each cell In r.Cells
        num = Right(cell.Value, 4)
        If isNumeric(num) And Len(num) < 4 Then
            num = String(4 - Len(num), "･") & num
            cell.Offset(0, 0).Value = num
            Else
            cell.Offset(0, 0).Value = cell.Value
        End If
    Next cell
End Sub
```

### (6) (4), (5)の文字列を結合した処理結果を選択したセルの3つ右隣のセルに出力

```vb:ConcatenateNextCellValues()
Sub ConcatenateNextCellValues()
    Dim rng As Range
    Dim cell As Range
    
    Set rng = Selection
    
    For Each cell In rng
        If Not cell.Offset(0, 1).Value = "" And Not cell.Offset(0, 2).Value = "" Then
            cell.Offset(0, 3).Value = cell.Offset(0, 1).Value & cell.Offset(0, 2).Value
        End If
    Next cell
End Sub
```

### (7) 一連の処理を連続して実行する

```vb:連続実行()
Sub 連続実行()
    Call RemoveRightDigits
    Call ExtractNumber
    Call AddDotToShortNum
    Call ConcatenateNextCellValues
End Sub
```


## このVBAの実行方法
全てのコードを入力後、変換したい文字列が入力されているセルを選択して、"連続実行()"を実行することで結果が得られる。
Cisco の CML を使ってみた

### 1.はじめに
ansibleとかpyATSとかRobotFrameworksとかいろいろいじってみたいのに、被設定機器の用意がままならい、というジレンマがあり中々手を付けられずにいましたが、何を思ったかCMLをポチってしまったので、まずは環境整備から。

### 2.環境整備　
まずPC買いました。M2 MBA MEM24Gです。仮想環境を入れる前提でメモリ多め。　
次にVMwareFusion。これは個人向け無償ライセンスを用意しました。　
さてこのVMwareFusionに、CiscoのページからCMLをダウンロードしてきてデプロイして起動！　
しかし、、何回やっても起動しない。
デプロイするovaのファイル名をよく見ると、cml2_2.4.1-34_amd64-13.ovaとある。amd64、、そりゃM2(AppleSilicon)で動くはずがない。。　
仕方ないので、先輩機のIntelMBPに同じような環境を作る。今度はすんなり起動、web画面にログインもできた。

というわけで次はライセンス。これはCisco公式によりほぼ問題なく終了。　
しかし、右下のServerDisconnectの表示が消えない。色々調べた結果ここのLinuxカーネル周りの設定変更にて回避。

https://learningnetwork.cisco.com/s/question/0D56e0000CETkIoCQL/can-anyone-verify-that-cml-works-with-mac-os-monterey-they-have-a-note-that-reads-note-that-if-you-run-a-cml-vm-on-an-apple-system-you-should-use-the-latest-supported-version-of-os-x-catalina-do-not-use-big-sur-no-mention-of-monterey?fbclid=IwAR1GtlNNWiZoarP63XH9FrVGVytU0E4cuRgRtORWBkccd_YoLOYqmw3QPVA

トポロジーフィールドに配置したノードがSTARTさせてもなかなか起動されないのは、safari→Chromeで解決。

※QiitaというかMarkdown 3年ぶりくらいなので追々見易くしていきますー。
低スペグラボ GTX1660Ti 6GB で LoRAで画像を学習させるときにハマったこと【stable diffusion】

自分の使ってるグラボが大分前に発売された **GTX1660Ti VRAM6GB** なのですが、このグラボだと有名wikiやブログで紹介されているようなLoRAの設定だと、トレーニングの実行はできるんですが、学習されていない、というような現象が発生したため、その解決方法をメモがてら残しときます


**LoRAで学習を試したくてグラボも最新のものを持っている、というような人にこの記事は向いてないです**

一度試してみて学習されない現象が発生したときに、もしかしたら解決の糸口になるかもしれない、という記事です

# LoRA学習環境作る

## インストール

derrian-distro/LoRA_Easy_Training_Scripts　を使って環境作るのがとても楽です
これ一つで完結します

適当なディレクトリを切ってそこに以下から `install_sd_scripts_v5.bat` をDLして設置
実行します
以上で環境構築は完了

https://github.com/derrian-distro/LoRA_Easy_Training_Scripts/releases/tag/installers-v5

## 学習元になる画像を用意する

この辺を参考に用意します

https://seesaawiki.jp/nai_ch/d/Dreambooth-LoRA#content_5

# Windowsの場合、ページングファイルを大きくする

Windowsデフォルトだと自分の場合仮想メモリが足らなくなりました
以下を参考に、ページングファイルを100GB程度まで拡張しました（要再起動

https://keep-loving-python.hatenablog.com/entry/2022/10/16/125216

# 学習の設定　（最重要＆ハマりポイント）

`run_command_line.bat` を使うと実行開始なのですが、
学習の設定は`ArgsList.py` にかきます

ベースモデルや画像フォルダなど設定します

が、、GTX1660Ti VRAM6GBというLoRA動作ギリギリのグラボ。それだけではダメでした


結論から言うとGTX1660Ti VRAM6GBでは
```
# self.mixed_precision: str = "fp16"
# ↓
self.mixed_precision: str = "no"
```

こうしないとトレーニングは成功するが、学習されませんでした

別の方法で環境を作った人も、`mixed_precision`（名前はちょっと違う可能性あり）を設定する部分があると思うので、見直してみてください

同じ状況になった人は試してみてください

# LoRA学習にかかる時間

- AdaFactor
- optimizer_args: Union[dict[str:str], None] = {"relative_step": True, "scale_parameter": True, "warmup_init": False}
- learning_rate:1e-3
- net_dim:32
- alpha:16
- batch_size:2
- xformers:true
- mem_eff_attn:false

で学習ステップ580（バッチ2なので実質1160）に2時間弱という感じです
AdamW8bitなら1時間ちょっとくらいでしょうか

これくらいで一旦どの程度学習できてるか確認するのがいい感じです
ひよっこによるGIT運用　気を付けたことまとめ

### 自己紹介
初めまして、プログラマ2年目（実務経験は1年と少し）のひよっこです。
最近GIT運用を任されて、そこで学んだことをメモとして起してます。
**※qiitaにいる先輩たち記事をたくさん参考にしてます。**

よければ閲覧してください。

## 気を付けたことまとめ
### 機能ごとにブランチを作成しよう
機能ごとにブランチを作成しよう！！
**developブランチ**へ一斉にCOMMIT・PUSH指示をすると以下の危険性をはらみます。

#### 危険性
1. どこの機能が追加されたのかわからない。 
2. 尋常じゃないほどコンフリクトする。
3. コンフリクト解決の際、**ソースの差分**を見ても**どの機能の実装で追加されたコード**なのか
不明で、実装者に質問しまくることになる。

#### ブランチ運用の参考リンク
各ブランチの役割は以下の記事を参考にしました。
とてもおすすめ。
<https://qiita.com/gold-kou/items/7f6a3b46e2781b0dd4a0>

### コミットメッセージの先頭には何をしたか書きましょう
コミットメッセージの先頭には何をしたか書きましょう！！
「**とりあえずコミット**」とか書かれてもわかんねえです！！
修正ならFIX、機能追加ならUPDATE、画面追加ならADD等、先頭に書いてくれるとありがたいです！！

#### コミットメッセージの書き方参考
コミットメッセージのルール決定にあたり以下の記事を参考にしました。
とてもおすすめ。（2回目）
<https://qiita.com/itosho/items/9565c6ad2ffc24c09364>


### 他人のfeaturesブランチを更新する際は一声かける
→モデルの内容などの共通部分が更新
→それを**featuresへ**反映させたかったので勝手にpullする
→怒られる。
ということがありました。

**他者のブランチに対して自分のソースを取り込んでほしい**ときは
チャットなり口頭なりで一声伝えてみましょう。
**粛々と描いていたコードに見覚えのない変更があったら驚きますよね。。すいません。**

## 参考記事

* いまさらだけどGitを基本から分かりやすくまとめてみた
    * <https://qiita.com/gold-kou/items/7f6a3b46e2781b0dd4a0>

* Gitのコミットメッセージの書き方
    * <https://qiita.com/itosho/items/9565c6ad2ffc24c09364>
EC-CUBE4 EntityTypeのデータを使って分岐したい

# はじめに
この記事は開発初心者の筆者が、開発時にやりたかったことをどう実現したかを書いています。

:::note warn
初心者ゆえ、至らない点や誤った情報を書いているかもしれませんが、その際はコメント等でご指摘頂けたら幸いです。
:::

# やりたいこと
formTypeにEntityタイプで追加した要素の各フィールドを取得して条件分岐したい。
本記事では、下記を例に書いていこうかと思います。
>例）受注登録で支払方法に応じてあれこれしたい

# 環境
・EC-CUBE　4.2.0
・Symfony　5.4.12
・PHP　7.4.26


# 書き方

受注登録画面に使われているOrderTypeに、下記のようにして支払方法のセレクトボックスが追加されている。
src/Eccube/Form/Type/Admin/OrderType.php
~~~php:OrderType.php
('Payment', EntityType::class, [
    'requred' => false,
    'class' => Payment::class,
    'choise_label' => function(Payment $Payment){
        return $Payment->isVisible()
            ? $Payment->getMethod()
            : $Payment->getMethod().trans('admin.common.hidden_label');
    },
    'query_builder' => function($er){
        return $er->createQueryBuilder('p')
            ->orderBy('p.visible', 'DESC')
            ->addOrderBy('p.sort_no', 'ASC');
    },
    'constraints' => [
        new Assert\NotBlank(),
    ],
])
~~~
　　
例えば、支払方法が「代金引換」の時に何か処理をしたい場合は、twig上では下記のように記述する。
~~~php:.twig
{% if form.Payment.vars.data.Method == '代金引換' %}
    // ここに処理
{% endif %}
~~~
　　
Entityのフィールドを取得する記述
~~~php
form.Payment.vars.data.{Entityで宣言したフィールド変数名}
~~~
　　
こうすることで、コントローラからわざわざEntityを返したりしなくても、formだけで解決することが出来た。


# 備考
「\*.vars.data.\*」とは別に「*.vars.value」があるが、これはセレクトボックスのセレクト値を取得することができる。
今回の例でいうと、dtb_paymentに登録されているidがセレクト値になっているので「代金引換」の場合は、"4"の値が取得できる。
Discordの荒らし対応

本記事の対象者はDiscordの基本的な使い方を知りたい管理者/モデレータ向けです。
管理しているDiscordサーバにて荒らしが入ってきた（テキスト連投/VCでいかがわしい音声を流す）時の対応手順です。
本稿の執筆者も勉強中のため、誤りがあればご指摘いただけると幸いです。


## タイムアウト
タイムアウトされた人は一時的にボイスチャンネルへの接続、テキスト投稿ができなくなります。
明らかな荒らしの場合は即BANでもOKですが、判断が難しい場合はいったんタイムアウトして本人に確認しましょう。

* 明らかなケース：アカウントの作成日が最近（ユーザ名をクリックで確認できます）、Discordに参加して即迷惑行為をしている
* 判断が難しいケース：前から入っているメンバーがテキスト連投などをしている

#### やり方
ユーザ名を右クリック→タイムアウト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/6d9d8379-8ac1-8d9f-0edb-263128b4505d.png)
期間を選択してタイムアウトをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/7640904f-d75d-0c78-8406-61171e90a766.png)


## BAN
悪意があり荒らし行為を行っていることが明らかな場合は対象ユーザをBANしましょう。
「追放」とは違い、BANされたサーバに再度参加することはできないため、注意してください。

#### やり方
ユーザ名を右クリック→BAN
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/48438b3a-c8b5-e394-2f24-dcba5a4eb7c5.png)
BANの確認画面でメッセージ履歴の削除の設定ができます。
また、BANの「理由」>「その他」から詳細な理由を記述できます。後で確認したい場合は記入しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/cd7bb07d-b998-930d-5e91-d727d8b63236.png)

間違ってBANした場合は「サーバー設定」>「BANしたユーザ」から取り消すことができます。


## 集団で荒らし行為を行っている場合
よっぽど無いとは思いますが、荒らしを行っているユーザが一度に多数入ってきており、一つずつ対応していては追いつかない場合は全員のテキスト送信/VC発言権をオフにしてから先述のBANを一人ずつ実施しましょう。
※他ユーザの権限も一時的に制限する操作のため、事前にサーバ管理者間で相談しておくことをオススメします

#### やり方
画面左上のサーバ名をクリック→「サーバー設定」をクリック 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/c943ccbd-7082-eae8-b598-c05d18120349.png)
「ロール」>「デフォルトの権限」をクリック
※Discord参加時に承認済みロールなどを付与している場合はそのロールをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/de99a129-a2bf-52d2-162d-640d4a655ae7.png)
「メッセージを送信」をオフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/3ed37166-3682-e172-12fe-e20d8ed611af.png)
「発言」をオフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/1b3be26f-a14a-9668-537c-c104785148ef.png)


## 招待URL無効化
荒らしをBANしてもサブアカウントで入ってくる場合もあるため、一時的に招待URLを無効化することをオススメします。

#### やり方
画面左上のサーバ名をクリック→「サーバー設定」をクリック 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/c943ccbd-7082-eae8-b598-c05d18120349.png)
「招待」をクリック→該当の招待リンク右上の「×」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/dd3d6ede-719a-a9fb-84a4-0ba7c9e3ce87.png)


## 禁止ワード追加
事態が収束した後の対応になります。
テキスト連投の対策として、禁止ワード追加を行うことができます。
画面左上のサーバ名をクリック→「サーバー設定」をクリック 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/c943ccbd-7082-eae8-b598-c05d18120349.png)
「AutoMod」>「カスタムワードをブロック」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/99c9e336-30e4-81e8-eeb2-81b3dedbd7c7.png)
「語句を選択」に禁止ワードを追加して、「変更を保存する」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194609/3dafd0ab-d2b3-1192-ba69-707c32822a41.png)


## 収束後
荒らし対応で一時的にテキスト送信権/VC発言権の編集をした場合は元に戻しましょう。
「集団で荒らし行為を行っている場合」でオフにした箇所を再度オンにすればOKです。
公開している招待URLを一時的に無効化した場合は再度発行しましょう。
bash5.2がリリースされてた。

自分用の栞

https://savannah.gnu.org/git/?group=bash
https://git.savannah.gnu.org/cgit/bash.git
https://git.savannah.gnu.org/cgit/bash.git/commit/?id=ec8113b9861375e4e17b3307372569d429dec814 ... bash5.2.patch15

GitBashもbash5.2対応済み、と、、、
※最近、gitforwindows.orgの最新化対応が早い、、、

```bash
$ bash --version
GNU bash, version 5.2.12(1)-release (x86_64-pc-msys)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
```
（Nostrプロトコルの）リレーサーバ実装 strfry について調べた

　
どうも、ryo_gridです。

strfryなるNostrプロトコルのリレーサーバ実装が、他の複数のリレーサーバからデータを受信したり、クライアントから送信されたデータをフォワードすることで、クライアントは自分だけに接続すればいいぞー、みたいなことできるらしいと耳にして、それはクライアントの負荷も減るしええやん、とドキュメントとコードを読んで分かったことを共有します。


https://github.com/hoytech/strfry

注:同じようなGitHubリポジトリへのリンクが表示されていますが、ページ内リンクがついていてそれぞれ飛び先は異なります

# リレーサーバのデーモンとしては単体で完結するような作りになっている模様
- 自身に接続してきたクライアントの相手を普通に行うのが基本で、その中で受け取ったイベントデータは自身のDBに格納する。

# 他のリレーサーバとのやりとりはCLIなコマンドが用意されていて、それを用いて行う
- 主には、イベントデータの受信およびイベントデータの送信
    - $ ./strfry stream wss://relay.example.com --dir both
    - とかすれば1つのWebsocketコネクションで双方向にデータを送受信しあい、受信したデータはDBに追加するらしい
    - 少なくとも受信はイベントの生成日時関係なく受信可能なものは全て受信すると思われる（ちょっと自信がない）

https://github.com/hoytech/strfry#stream



- そもそも、strfryは自身のDB内において、他のリレーサーバのデータが同期されていればいいじゃん、と考えているようで、それを効率的に行う仕組みを作りこんでいる模様
    - $ ./strfry sync wss://relay.example.com
    - というのが受信方向に対応するコマンド
    - $ ./strfry sync wss://relay.example.com --dir both
    - こっちは双方向で行うコマンド。しかし coming soon であるとのこと


https://github.com/hoytech/strfry#sync:embed:cite


- データの同期に関しては元々リレーサーバ間の連携のために設計されたyesstrなるプロトコルあって、それを拡張したものの実装である Quadrable というものを（自分たちで作りつつ）用いて行うのだとか
- しかし、Quadrableのリポジトリの説明を読むと、Nostrというキーワードは出てこず、マルチバージョンなデータベースで、効率的に他のデータベースインスタンスと同期できるところが特徴である、みたいなことが書いてある。うーん？


https://github.com/hoytech/quadrable

# その他
- 自身のDB内にイベントデータを格納する時点で重複を排除するので、クライアントが複数のリレーサーバからデータを受信するよう設定している場合（Nostrではこれが普通）に、通常、発生してしまう同一のイベントデータの重複受信は起こらないようになるようです
    - つまり、クライアントにおいては、通信量が減ることになります
- リレーサーバがどれだけの期間データを保持するかは、個々のリレーサーバ次第で、クライアントからはコントロールできませんが、自身で strfry をホストすることで、ストレージの容量が許す限り残しておくことが可能なはずです

# お願い
- 記述内容に誤りがあるようでしたら、コメント欄でご指摘いただけるとありがたいです！

# 追記（220301）
- 調査結果で分かったことの（少なくとも個人的に）重要なところは、プロキシ的な運用ができると言っても、クライアントが投げたイベント情報をフォーワードする、サブスクライブ要求をフォーワードするという考え方での作りにはなっていないという点です
  - クライアントの面倒は基本的に全て自身がやるという作りで、（内部処理的に一部例外はあるようであるものの）受信したイベントデータは自身のDB内に格納し、サブスクライブ要求への応答も自信のDB内のデータに基づいて行うという形になっています
  - しかしながら、自身のDBの内容を他のリレーサーバのそれと雑に言えば同期させる機能をオプションとして持っていて、それを用いた同期がリアルタイムに近い早さで行われていれば、結果的にクライアントからはプロキシのように見えるということになります
  - 同期処理においては、メタデータからクライアントクライアントが他に接続しているリレーサーバを確認して、その情報を意識するといったことはなく、strfryを運用している者が固定的に設定したリレーサーバとの間でしか行われないため、運用者が設定したリレーサーバからの読み込み、へのの書き込みだけでは困るというクライアント（ユーザ）にとっては、"自身だけに接続すればOK!" とはなりません
    - 聞くところによると [filter.nostr.wine](https://nostr-wine.github.io/filter-relay/) というリレーサーバは、有料でプロキシ的な役割を提供いますが、サーバ実装としてはstrfryを利用しているらしく、サービスの説明のところには、仲介をする（ように見える）リレーサーバがリストされています

enjoy!
AppDelegateで@EnvironmentObjectを使用する方法

SceneDelegate.swiftに、ContentViewに渡すEnvironmentObjectを生成するコードを追加します。


```
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    var appState = AppState()
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // アプリケーションの初期化処理を行う
        let contentView = ContentView().environmentObject(appState)
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: contentView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
}

```

ContentViewに、@EnvironmentObjectで参照するAppStateを指定します。


```
struct ContentView: View {
    @EnvironmentObject var appState: AppState

    var body: some View {
        // Viewの定義
    }
}

```

ContentViewをSceneDelegateから生成するとき、environmentObjectメソッドを使用して、appStateオブジェクトを渡します。

```
let contentView = ContentView().environmentObject(appState)

```
以上の手順で、AppDelegateで生成したappStateオブジェクトを、ContentViewの@EnvironmentObjectで参照できるようになります。@EnvironmentObjectを使用することで、複数のViewで同じオブジェクトを参照できるため、便利にアプリケーションの状態管理を行うことができます。
【UiPath】Computer Visionのアクティビティの記述子に変数を埋め込んでUIを操作する

# はじめに

UiPath Computer Visionのアクティビティは記述子に変数を埋め込んでUI操作ができます。
下記の投稿はペイントブラシの画像を使ってページ繰りと表クリックを順に実行してますが、これは変数を埋め込んでやってます（笑）
本ブログでは、Computer Visionのアクティビティの記述子に変数を埋め込む方法を具体例を用いて解説したいと思います。

【参考】

https://twitter.com/Jun96427231/status/1624289474812452865

# 前提
※UiPath Studioはv2022.10.5で記載します。
※UiAutomstionアクティビティv22.10.5で記載します。

# ワークフローを作成する

ここからRPA Challenge（日本語）のサイトを使って、具体的な利用方法を解説して行きます。
利用する画面はInvoice Exstractionです。

https://rpachallengeocr.azurewebsites.net/

## CV画面スコープの設定

対象の画面は英語なので、必ずしも日本語OCRの設定は必要ありませんが、本ブログでは日本語OCRを利用しています。CV画面スコープの設定は下記のブログを参考にしてください。

https://qiita.com/Jun96427231/items/11f91e9279497deec449

## Computer Visionで変数を埋め込んで表のページ繰りをして見よう

「CV画面スコープ」の画面を下記の様に指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/93acd85f-bfde-5fa3-1c52-9bc8415acd13.png)

下記の様なワークフローを作成します。
参考なので、ここでは固定の３ページ目までクリックさせます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/be428c0a-e6e3-be91-8f4b-7ee632f9bed4.png)

「CVクリック」の画面上の指定ではアンカーを設定します。上手く設定出来ない場合は、一度登録してから「画面上で編集」で登録できる様になったりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/0c9b76ea-c5f3-c8d4-b855-32c69b71d73e.png)

:::note warn
注釈

「1」のテキストを指定しないと、下記の様に記述子がInputBox(入力ボックス)で登録されてしまいページの変数の埋め込みが出来ないので注意してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/12ce78f9-d5ab-0719-e809-96f65ea3f48e.png)

:::

「CVクリック」の記述子を下記の様に編集し、変数を埋め込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/9637f65a-d16e-ac47-f98e-4cd886bb96bc.png)


実行すると３ページ目までクリックできます。

## Computer Visionで変数を埋め込んで表の項目をクリックして見よう

下記の様なワークフローを作成します。
参考なので、ここでは固定の４行目目までクリックさせます。
尚、「繰り返し（指定回数）」の開始の値は２から設定してください。１はタイトル行になってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/6d6555bc-5d01-c9d0-a352-43092e6fb6b6.png)


「CVクリック」の画面上の指定で表の部分にカーソルを移動すると表として認識します。下記のステップで指定していきます。

### ステップ１
カラム「Invoice」の１行目の項目をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/570ba7cc-af2b-aa10-a44a-a35f5cecdad7.png)

### ステップ２
行は変動させるので、欄外に表示されている「行」を指定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/2bca959a-8986-0b88-b1c2-f7ad36012a1d.png)

「CVクリック」の記述子を下記の様に編集し、変数を埋め込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/0fe5e437-ed49-411b-1b71-3bc46492e939.png)

実行するとカラム「Invoice」の１行目からクリックして行きます。

# おわりに
Computer Visionでも変数を埋め込んで操作できるとは、ちょっと驚きです。
UiPathのAI Computer Visionは、ここまで使える様になってきたんですね！

https://qiita.com/Jun96427231/items/11f91e9279497deec449

https://qiita.com/Jun96427231/items/5596e5b8f4b4dddd660f
Python全く分からん自分のアウトプット　その5

5日目：ちょっと日が空いてしまったけどはりきっていくぞ！！！！
今日はPythonコース3を一通り駆け抜けてみる。



◎以下調べたこと、疑問に思ったこととかのメモ◎


関数をつくる・・・「def 関数名()：」この形

引数・・・上の()の中に「仮引数」を指定する。例えば「def hello(name):」

引数を渡す・・・例↓
def hello(name)：
print("hello"+name)
hello("John")←下にこいつらを追加する
hello("kate")←下にこいつらを追加する

スコープ・・・見えない枠組み(認識はできる)以外のところで変数を使用しても領域外だからエラーが起きる。

複数の引数・・・「def hello(name,message):」のようにコンマで区切る。

引数の初期値・・・例えば上のmessageを「message="こんにちは"」とかで初期値を与えていれば、引数が省略された時に初期値が表示される。

戻り値・・・「return False」とか「return True」。間に「else:」入れる。

return・・・性質上それ以降の関数の処理は実行されない。

モジュール・・・pythonの書かれたコードのことを言う。「script.py」とか「utils.py」とか。

import・・・これを使うことでモジュールを読み込むことができる。例えば「import utils」とかでコロンとかはいらない。

モジュールの使い方・・・「モジュール,関数名()」の形にする。

ライブラリ・・・便利なやつ。「math」は複雑な演算のモジュール、「random」はランダムな値を生成するモジュール、「datetime」は日付や時間データを操作するためのモジュール。


ｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰ

Pythonコース３は一通り全部通してやってみたけどけっこう頭こんがらがった。けどひとまず終わりまで通せたからよかったと思う。(けっこう答え見ちゃったけど)
やり方を変えて一通り通してから復習がてらメモを書いてみたけどこっちのほうがやり方的にいいかもしれない。
忘れないように空いている時間にこのメモを読み返していこう。
時間を無駄にしない行動、大事！！！！！
【Docker】GUIでボリュームのバックアップを取る方法

## 拡張機能をインストール

Docker DesktopのExtensions Marketplaceで`Volumes Backup & Share`をインストールすることでGUIでボリュームのバックアップを取れるようになります。

Docker Desktopを開いて`Add Extensions`をクリックします。

![スクリーンショット 2023-02-26 23.56.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/cde2400d-fafa-3a23-7038-306a91707fb0.png)


`Volumes Backup & Share`を検索してインストールします。

![スクリーンショット 2023-02-27 0.01.44のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/28393918-cbde-7a39-7aab-7c4188d1921f.png)

`Open`をクリックします。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323334323434332f34393537353261302d353161362d333136652d376434632d6238646166333263313163642e706e67のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/17c28a4e-26fc-77f4-b9fc-15ad2d30433e.png)


## バックアップの作成

インストール後`Volumes Backup & Share`を開きした画像の赤枠内のボタンをクリックしてボリュームをホストにエクスポートします。

![スクリーンショット 2023-02-26 23.50.31のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/a3a255b5-a1cc-4c27-9219-43d1299917e6.png)



## 新しいボリュームとしてリストア

画面右上の`import into new volume`をクリックしてバックアップの際に作成したファイルを選択してリストアします。

![スクリーンショット 2023-02-26 23.50.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/eca2b68d-dcf8-6d53-8866-8d7cc36b56e3.png)
CarrierWave NoMethodError (undefined method `map' for #<ActionDispatch:

# 問題点
React (FormData) と Rails (CarrierWave) を使用して、
フロントエンド側から複数の画像を配列にまとめてバックエンド側に送信し、画像を保存しようとしたところ、
以下のエラーが発生しました。

```
NoMethodError (undefined method `map' for #<ActionDispatch::Http::UploadedFile:0x0000000113821568 @tempfile=#<Tempfile:/var/folders/wc/bdwclb6j70qd2qbrhj4xbz_w0000gn/T/RackMultipart20230111-78142-3co5tx.png>, @original_filename="スクリーンショット 2022-11-19 20.29.07.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"post[image][]\"; filename=\"\xE3\x82\xB9\xE3\x82\xAF\xE3\x83\xAA\xE3\x83\xBC\xE3\x83\xB3\xE3\x82\xB7\xE3\x83\xA7\xE3\x83\x83\xE3\x83\x88 2022-11-19 20.29.07.png\"\r\nContent-Type: image/png\r\n">
      @uploaders = new_files.map do |new_file|
                            ^^^^
Did you mean?  tap):
```
React側のコードは以下のようになっています。
```react:react
    const data = new FormData();
    images.map((image) => {
      data.append("post[image][]", image);
    });
```
Rails 側のコードは以下のようになっています。
```ruby:rails
  def create    
    post_params[:image].each do |image|
      post = Post.new(image: image)
      if post.save
      else
        render json: post.errors
      end
    end
  end

  private
  def post_params
    params.require(:post).permit({image: []})
  end
```

# 解決方法
CarrierWave の mount_uploaders を mount_uploader に変更することで、このエラーを解決できます。
配列内の画像を分解して保存する場合は、mount_uploaderのsを取る必要があるようです。
```ruby:post model
class Post < ApplicationRecord

  mount_uploader :image, ImageUploader #←mount_uploadersではなくmount_uploaderにする
  
  validates :image, presence: true
end
```

以上が、CarrierWave の NoMethodError (undefined method `map' for #<ActionDispatch: の解決方法でした。

# 参考
https://github.com/carrierwaveuploader/carrierwave/issues/2164
Network limitation of Blink security camera

# Network limitation of Blink security camera

1. it supports IPv4 only
1. the MTU of all sections of network to its API server must equal or greater than 1500 (for example it will not work if a section is tunneled by pptp, which MTU is 1450)
1. it uses HTTPS (tcp port 443) to upload video stream (boths real time and motion detection) and thumbnail
GitHub 検索の便利なコマンド

# GitHub での検索方法

[GitHub 公式の検索方法はこちら](https://docs.github.com/ja/search-github)

GitHub 検索に便利なコマンドを書いておく。
Github の検索ウィンドウに、下記のコマンドを打ち込むと、検索することができる。

## Issue または Pull Request検索

### Issue または Pull Request に絞って検索

`is` または `type` で issue または pull request に検索対象を絞る。

| コマンド | 説明 |
|:-:|:-:|
| type:pr<br>is:pr | pull request を検索 |
| type:issue<br>is:issue | issue を検索 |

例)
[pandas type:pr](https://github.com/search?q=pandas+type%3Apr&type=Issues)  
"pandas"という単語を含むpull requestを検索

### タイトル、本文、コメントで検索  

`in`で検索対象を絞る。

| コマンド | 説明 |
|:-:|:-:|
| in:title | タイトルを検索 |
| in:body | 本文を検索 |
| in:comments | コメントを検索 |

`in:title,body` のように複数指定も可。

例)
[warning in:title](https://github.com/search?q=warning+in%3Atitle&type=Issues)  
タイトルに"warning"を含むissueを検索

### ユーザー、会社(Organization) のリポジトリ内を検索  

| コマンド | 説明 |
|:-:|:-:|
| user:USERNAME | USERNAME所有のリポジトリ内を検索 |
| org:ORGNAME | ORGNAME所有のリポジトリ内を検索 |
| repo:USERNAME/REPOSITORY | USERNAME/REPOSITORYリポジトリ内を検索 |

### オープン、クローズで検索

`state`または`is`でステートを絞って検索。

| コマンド | 説明 |
|:-:|:-:|
| state:open<br>is:open | オープンで検索 |
| state:close<br>is:close | クローズで検索 |

### 人で検索  

`author`, `assignee`, `mentions`, `commenter`, `involves`で人を絞る。

| コマンド | 説明 |
|:-:|:-:|
| author:USERNAME | 作成した人で検索 |
| assignee:USERNAME | アサインされた人で検索 |
| mentions:USERNAME | メンションされた人で検索 |
| commenter:USERNAME | コメントした人で検索 |
| involves:USERNAME | 関係した人で検索 |

`involves`は、`author`, `assignee`, `mentions`, `commenter`の論理OR  
`USERNAME`はGitHubのログインユーザー名

例)
[same author:takadappara](https://github.com/search?q=same+author%3Atakadappara&type=Issues)  
@takadappara が作成した、"same" という単語を含むissueを検索

## コードの検索

コードの検索は複雑なため、検索には一定の制限がある。  
- コード検索用のインデックスが作成されるのは、"既定のブランチ"のみ
- 384KB より小さいファイルのみ検索可能
- 検索結果で同一ファイルから取り出される部分は2つまで。

などなど。

### ファイルの内容またはファイルパスで検索

| コマンド | 説明 |
|:-:|:-:|
| in:file | ファイルの内容で検索 |
| in:path | ファイルパスで検索 |

### ユーザー、会社(Organization) のリポジトリ内を検索  

Issue、Pull Request の場合と同じ。

### ファイルの場所で検索

| コマンド | 説明 |
|:-:|:-:|
| path:/ | リポジトリのルート(/)で検索 |
| path:DIRECTORY | DIRECTORY内で検索 |
| path:PATH/TO/DIRECTORY | PATH/TO/DIRECTORY内で検索 |

### ファイルの種類で検索

| コマンド | 説明 |
|:-:|:-:|
| language:LANGUAGE | 言語で検索 |
| size:n | ファイルサイズで検索<br> ex) size:>10000 (10KB) |
|filename:FILENAME | ファイル名で検索 |
| extension:EXTENSION | 拡張子で検索 |




## ユーザー検索

| コマンド | 説明 |
|:-:|:-:|
| type:user | ユーザーを検索 |
| type:org  | 会社(Organization)を検索 |

例)
[takadappara in:name type:user](https://github.com/search?q=takadappara+in%3Aname+type%3Auser&type=Users)
名前に "takadappara" を含むユーザーを検索

### アカウント名、フルネームやメールで検索  

| コマンド | 説明 |
|:-:|:-:|
| user:USERNAME | ユーザー(USERNAME)を検索 |
| org:ORGNAME | 会社(ORGNAME)を検索 |
| in:login | ユーザー名で検索 |
| in:name | 本名で検索 |
| in:email | メールで検索 |

例)
[user:takadappara](https://github.com/search?q=user%3Atakadappara&type=Users)
ユーザー名"takadappara"を検索
[takada in:login](https://github.com/search?q=takada+in%3Alogin&type=Users)
ユーザー名に"takada"を含むユーザーを検索
【React】exportについて

# この記事の目的
- Reactの理解とアウトプット、振り返り用
- Reactでよく使われている基本的な技術を言語化できるようする
- exportについて

## exportは２種類ある『default』と『named』

- **default export**：export default　 
- **named export**：export const

exportの書き方によって、import時の記載が変わってきたりと、よくわからずに触っていたので少し調べてみました。

## 違いについて
- import時に、{}がつくかつかないか

## 記載方法default export 

```React:Component1.js
import React from "react";

const Component1 = () => {
  return 
     <div>
       default export用コンポーネント１です
     </div>
};

export default Component1;
```

```React:App.js
//import コンポーネント名(自由) from 'ファイルパス'
import Component2 from "./components/Component2";
```

## 記載方法named export
```React:Component2.js
import React from "react";

export const Component2 = () => {
  return 
     <div>
        named export用コンポーネント２です
     </div>
};
```
```React:App.js
//import { 関数名(固定) } from 'ファイルパス'
import { Component2 } from "./components/Component2";
```

# まとめ
- import時には、{}がつくかつかないかの違いがある
- export default したものを import するときには {} を使わない
- 1ファイル1コンポーネントであれば、 `export default` を使う方がいいけど基本namedほうが良さそう
Serializable with input check/ writeReplace, readResolve

https://qiita.com/Natukasi/items/20f8756e9e956684396c
の改良版。
readObjectはconstructorを通さないために、入力チェックを使用できない
writeReplace/readResolveを使用することで、constructorを通すことができる。
このサンプルには入れていないが、constructor内に入力チェックを仕込んでおく
```java
            return new Value2(this.name,this.price, this.val);
```
```
write replace
read resolve
v2-name:v2x v2.price:200v1-name:v1xv1-price:100
```
ChromeCustomTabs for BottomSheet

Androidやってるめっしです(Twitter：https://twitter.com/0601messi)
先日こちらのChromeCustomTabsの記事を見て気になったので調べてみました

https://android-developers.googleblog.com/2023/02/bringing-best-of-chrome-to-android-developers-and-users.html


# 概要
AndroidアプリでWebURLをタップした際に、ブラウザーを起動するかWebViewを使用して独自のアプリ内ブラウザーを作るなどがあります。
その他の方法として、ネイティブコンテンツとWebコンテンツ間の遷移がよりシームレスになるChromeCustomTabsというものがあります。

https://developer.chrome.com/docs/android/custom-tabs/

そんなChromeCustomTabsが新たにBottomSheetで表示できるようになりました。
では、やってみます。

# 実装

### ライブラリの追加
``` build.gradle.kts
implementation(androidx.browser:browser:1.5.0) // 最新バージョンを
```

### ChromeCustomTabsの呼び出し
```SampleFragment.kt
private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
  // 閉じた時に呼ばれるコールバック。ChromeCustomTabsを閉じた時に何か処理をしたい時はこちらに
}

// 呼び出したいところでlaunchする。
binding.button.setOnClickListener {
  val builder = CustomTabsIntent.Builder()
    .setInitialActivityHeightPx(800) // カスタムタブの初回起動の高さを指定できます
    .setToolbarCornerRadiusDp(16) // ツールバーの上隅角の丸みのサイズを指定できます
  val customTabsIntent = builder.build().intent.apply {
    // 表示させたいURLの設定
    data = Uri.parse("https://developer.android.com/")
  }
  startForResult.launch(customTabsIntent)
}

```

### 完成
| 通常 | 半分展開 | 全展開 |
|:-:|:-:|:-:|
| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188385/a51ce87b-20c2-5155-23b6-9d2c8e65bbde.png" width=300 />  | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188385/98c22cd8-6cdb-43bb-007a-60abfc99a420.png" width=300 />  | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188385/10d821c2-3520-f22f-2382-239688cecc9f.png" width=300 />  |


### 注意・補足
- 以下の書き方だとBottomSheetにならなかったのでstartActivityForResultで呼ぶ必要がある。
```Fail.kt
val url = "https://google.com/"
val builder = CustomTabsIntent.Builder()
val customTabsIntent = builder.build()
customTabsIntent.launchUrl(this, Uri.parse(url))
```

- `setInitialActivityHeightPx`の設定は必須。こちらもないと通常のViewになる。
- 同じコードでもAndroid10だと通常のView。12だとBottomSheetになった。
- CustomTabsIntentのオプションで他にもタイトルや色等の設定できる。
  - https://developer.android.com/reference/androidx/browser/customtabs/CustomTabsIntent.Builder

# おわり
面白いUI系の新機能探してます。
WSL2/K8s(minikube)をWin11対応

色々あって、先延ばしにしていたWindows11アップデートとWSL2ベースのローカルコンテナ環境も対応した
→ついでに、もろもろ最新化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1349578/6de5b62e-b55a-8345-0d2c-80bd5d16d3c0.png)

〇やったこと
　■WSL2を、最新化（WinStore版を利用、WSLイメージが不安定になったのでコマンドで復旧）
　■WSL/Ubuntuを、最新化（Ubuntu 22LTSへ）
　■DockerDesktopから、WSL2/UbuntuのDockerへ（多分、コマンドしか使わないしね、、、）
　　□もろもろ、半自動起動・自動起動化
　■K8sは、適切に手動取得して最新化
　■WindowsTerminalもWinStoreから取得した最新のものへ（Windows11にアップデートしたところ、動かなくなった？模様）
　　□minikubeのアイコンもきれいに表示できるようになりました。😊

〇残対応
　■minikubeがなんか古い＜ここ2年ぐらいDockerDesktopの K8S で満足してたのでほったらかしていた。
ROOM実装時のエラー

ROOM実装時、ビルドエラーとなったのでメモ。

■エラーメッセージ：
Schema export directory is not provided to the annotation processor so we cannot export the schema

■対応：
データベースクラスの、＠Databaseアノテーションに「exportSchema = false」を追加することで解消。

@Database(entities = [Task::class], version = 1, exportSchema = false)



参考：
https://pg.akihiro-takeda.com/android-room-error/#toc1
https://developer.android.com/training/data-storage/room?hl=ja