OmniAICreator/Qiita-1.07M huggingface dataset:
TCAで親子・孫・ひ孫・玄孫...でstateを同期させる

## まえがき

The Composable Architecture(以下からTCA)で、
親子や孫..のStateの共有をノード間で自動的に同期するためには
どうすればよいか備忘録として書き留めます。

## おおまかに何がやりたいか

孫で更新された情報と、
親で更新された共有データ親に即座に更新される状態を作りたい。
TCAでSingletonを使うようなイメージ。

## 手順

### 共通に持ちたいSharedDataを定義

``` swift
struct SharedData: Equatable {
    var isFirstUser: Bool = false
}

```

共有の情報をSharedDataとして定義し、

``` swift
struct AppState: Equatable {
    var sharedData: SharedData
    var _homeState: HomeState
}

extension AppState {
    var homeState: HomeState {
        get {
            return _homeState.with(sharedData: sharedData)
        }
        set {
            _homeState = newValue
            sharedData = newValue.sharedData
        }
    }
}

extension AppState {
    static func initial(sharedData: SharedData) -> AppState {
        AppState(
            sharedData: sharedData,
            _homeState: .initial(sharedData: sharedData)
        )
    }
}
```

他の画面に遷移するときに、
Stateを初期化時にsharedStateを渡し、
更新があるたびにsetterを通じてsharedDataを更新します。

Rootに共通のStateを定義し、それを共有したいStateを初期化する時に注入し、
そのStateが更新されると共通のStateも更新させるようにすることで実現します。

``` swift
struct HomeState: Equatable {
    var sharedData: SharedData
}

extension HomeState {
    static func initial(sharedData: SharedData) -> HomeState {
        HomeState(sharedData: sharedData)
    }
}

extension HomeState {
    func with(sharedData: SharedData) -> Self {
        var result = self
        result.sharedData = sharedData
        return result
    }
}
```

### 上記コードをPlaygroundで試すと

``` swift
var appState = AppState.initial()
appState.sharedData.isFirstUser // print true
// homeStateのsharedData経由でisFirstUserを更新させる。
appState.homeState.sharedData.isFirstUser = false
appState.sharedData.isFirstUser // print false
```

## あとがき

Stateのノードのどこから更新しても更新できるようにするやり方でした。
本来ならAction経由でStateを更新するのが筋かもしれませんが、
一例として参考にしていただけたら幸いです。

SwiftUI x The Composable Architecture(TCA) x Firestoreでのお仕事募集中です〜！
M1 Mac1でAWS SAM CLI　ちょっとハマった

#

いいかげんローカルでの開発にも飽きてきたのでしばらく放置していたAWSを活用しようとおもって[公式チュートリアル](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html)をやってみた。

# 環境
* Macbook Air (M1 2020)
* Docker 20.10.16 (limaにて、[参考](https://qiita.com/nyaao/items/5ca99d28842bb0331d63　"タイトル")）
* SAM 1.52.0

# ローカルでテスト

ローカルにデプロイするには`sam deploy --guided`ではなく、`sam local start-app`でdockerコンテナが起動する。
公式に従って、`curl http://127.0.0.1:3000/hello`とすると、
```
{"message":"Internal server error"}
```
あれ、、、うまくいってない。簡単なチュートリアルなのにっ！！

# 解決

いろいろ調べたり、template.yamlをみているうちに、アーキテクチャの違いに気づいて以下の対応

```
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        # - x86_64 削除
        - arm64　　　　#追加
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get
```

無事、`{"message": "hello world"}%`が帰ってきました。
そりゃそうだよねって感じかもしれませんが、参考まで。 AWSにデプロイするときにはx86_64なのかな。
共通利用のgemでRubyの複数バージョンテストを行う

# 背景
社内で利用している共通gemがあり、今まではCircleCIによってrspecを回していた。
その際最新のRubyバージョンでのみCIを回すようにしていたのでコード修正やライブラリの更新などで不意に古いバージョンのRubyで動かなくなるのではという懸念があった。
(今の所利用しているシステムが少ないからなんとかなっているが今後増える可能性があるのでバージョン上げると動かなくなるという話がまぁまぁきそう)

# 目指すところ
複数のRubyバージョンでrspecを回すことで古いRubyでも問題なく動作することを継続的に確認し、安全にgemのバージョンアップを行う地盤を作る。
ついでに github action に載せ替える

小さいながらもOSS的な観点を持って開発をする(古いバージョンへ配慮したコードの書き方etc)
=> ゆくゆくはOSSにしてもいいかなという気もしている

# 結果
github actionをつかうと簡単にできました

```.github/workflows/rspec.yml
name: rspec

on:
  - push

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        ruby-version: ['head', '3.1', '3.0', '2.7', '2.6', '2.5']
    steps:
      - uses: actions/checkout@v2
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby-version }}
          bundler-cache: true
      - run: bundle exec rspec
```

![スクリーンショット 2022-06-11 11.19.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280595/8ecc3ee6-756d-1e77-a9ab-c81790904caf.png)


# ポイント
* matrix でruby-versionを複数設定することで複数のケースでCIを回す
* `ruby/setup-ruby@v1` の `ruby-version` で `${{ matrix.ruby-version }}` を指定することで実行するRubyのバージョンを変える

# 参考
https://docs.github.com/ja/actions/using-jobs/using-a-matrix-for-your-jobs
【Salesforce】【フロー】ワークフロールール・プロセスビルダーの廃止とフロー移行について知見まとめ


2022年、ぴえ含め多くのSalesforce管理者・開発者が直面している
ワークフロールール・プロセスビルダーの廃止とそれに伴うフロー移行に関する知見をまとめる記事です。

～～ほとぼり冷めるまでは随時更新します(^^)/～～

# ワークフロールール・プロセスビルダーの廃止

2021年10月の公式発表

https://admin.salesforce.com/blog/2021/go-with-the-flow-whats-happening-with-workflow-rules-and-process-builder

上記発表の概要
- Winter‘23からワークフロールールとプロセスビルダーの新規作成ができなくなる
- ワークフロールール→フローの移行機能がSpring‘22にリリースされる　（次の章を参考）
- プロセスビルダー→フローの移行ツールがSumeer‘22にリリース予定　（ぴえは未確認）

# リリースされた機能や現在の時点で分かっていること

### ワークフロールール→フローの移行機能
Spring‘22にワークフロールールをフローに自動で変換してくれる機能がリリースされました。
こちらの記事でキャプチャ付きで手順を説明しています。

https://qiita.com/piepie1231/items/c8050c78de3902431980

### フローのテスト機能（ベータ版）
Summer’22にフローのテスト機能がリリースされました。詳細は[リリースノート](https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_debug_tests.htm&type=5&release=238#numberOfResults=1000)をご確認ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/2e36616c-dc04-fc07-df12-5a14efe660a0.png)

メタデータは[FlowTest](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_flowtest.htm)です。APIバージョン55.0～

ベータ版なので？まだまだ制限事項が多い印象です。
ぴえのDEもバージョンアップしたら使ってみた記事を書く予定です。

### フローのエントリ条件に数式が利用可能になった
Summer’22でフローのエントリ条件で「数式の評価が True になる」が設定できるようになりました。
こちらも詳細は[リリースノート](https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_builder_use_formulas_as_flow_entry_conditions.htm&type=5&release=238#numberOfResults=1000)をご確認ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/03107bf2-c565-e5a4-62ed-a118d8905083.png)
このバージョンアップで多くのワークフロールールが移行機能で失敗しなくなりました。

### その他の関連情報
- [トリガと実行の順序](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm
)
移行する前に一読するべしです。


# まだ分かっていないこと

- 既存のワークフロールールとプロセスビルダーが**更新**できなくなるのはいつなのか
- 既存のワークフロールールとプロセスビルダーが**使用**できなくなるのはいつなのか


# ぴえの考え

- 今後、標準機能で自動処理の実装がある場合はフローを検討する
- 既存のワークフロールールとプロセスビルダーをリストアップする

移行ツールやフローの機能拡張がこれからまだありそうなので、（2022年6月現在）今すぐ急いでフロー移行するのは得策ではないかなと考えています。すくなくともSummer’22のバージョンアップ後をおすすめします。
ただ、廃止自体は確定事項なので直前にバタバタしないように備えも必要です。既存の処理はリスト化して仕様をまとめておくといいと思います。
フロー移行する場合は単純に元と同じものを作るのではなく、実行順や条件を考慮してまとめられるものは一つのフローにまとめるべきだと思います。
また移行先をフローに限定するのではなく、Apexトリガを検討する、そもそも必要なロジックか再確認するなど柔軟に進めていきたいですね。

この記事は重要な更新のたびに通知するので良かったらストックしてください(^^)/


（（これは余談ですが、
承認プロセスについては一言も出てきてないので今のところ廃止はないのではないかと考えています。そもそも移行先にできる機能がないし、、））
【Laravel Sail】ブラウザ上でXdebugを止めたい

ブラウザ上でDocker上のxdebugを止めたい場合の記録

sailをdown
```terminal:terminal
./vendor/bin/sail down

```
.envに追加
```env:.env
SAIL_XDEBUG_MODE=develop,debug
```
.dockerに下記追加
```dockerfile:プロジェクト名/vendor/laravel/sail/runtimes/8.1/Dockerfile
RUN apt-get update \
php8.1-memcached php8.1-pcov php8.1-xdebug
```

ターミナルで下記コマンドを順に実行

```terminal:terminal
./vendor/bin/sail build --no-cache
./vendor/bin/sail up -d 
./vendor/bin/sail artisan sail:publish
./vendor/bin/sail stop
./vendor/bin/sail up
```
vscodeの設定

launchjsonに下記追加
```json:launch.json
       {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9003,
            "pathMappings": {
                "/var/www/html": "${workspaceFolder}"
            },
            "hostname": "localhost",
            "xdebugSettings": {
                "max_data": 65535,
                "show_hidden": 1,
                "max_children": 100,
                "max_depth": 5
            }
        },
```

デバッガー起動

ブラウザでlocalhost起動

指定した箇所でブレークポイントが止まる。
AWS RDSのバックアップ・リカバリを試してみた

# はじめに
今回はRDSのバックアップおよびリカバリについて試してみましたので、手順などを含め整理していきたいと思います。まずは、設定周りを調べてみて印象に残った点を備忘としてまとめます。
※バックアップには手動と自動の2種類方法がありますが今回は自動バックアップについて記載しています。

# メモ
- バックアップウィンドウは自動バックアップのスケジュール設定のこと。例えば、日次22時にバックアップを取得するようなことができるが、RDSの停止時はバックアップが開始されない。

- 自動バックアップは初回はフルバックアップ、次回以降は差分バックアップとなる。各バックアップ(スナップショット)のサイズを確認する方法はなさそう。

- 自動バックアップはデータベースストレージサイズと同じサイズまではバックアップ領域として提供され、コストはかからない。

- MySQLの自動バックアップはInnoDBストレージエンジンのみサポートされている。

- バックアップウィンドウでは「開始時間」、「期間」を設定可能。例えば、開始時間を「9:00」、期間を「30分」で設定した場合は「9:00〜9:30」の間に自動バックアップが「開始」されることになる。

- メンテナンスウィンドウはパッチの適用など、システム変更の適用に関するスケジュール設定のこと。開始時刻はバックアップウィンドウの開始時刻と重複できない。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html

# 自動バックアップ設定
RDSインスタンス作成時に自動バックアップを有効にしました。
![スクリーンショット 2022-06-10 9.33.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/bcb07634-7cb7-9e6d-ca1d-e5a549b1d88e.png)
上記だと、日次の3:00-3:30 JSTの間に自動バックアップが取得され、保持期間は1日になります。


# リカバリを試してみる
次に、取得したバックアップからRDSインスタンスを復元できることを確認します。

- RDSインスタンスを削除します
![スクリーンショット 2022-06-10 8.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/43e788f1-f164-2cfe-e8ee-ad7131dd9ea9.png)

- 自動で取得されたバックアップから復元するので今回は最終スナップショットを取得しません。
![スクリーンショット 2022-06-10 8.33.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/31911851-ef50-1a1c-dd2f-dc670b41ae05.png)

- システムスナップショットのバックアップを選択し、アクションから「スナップショットを復元」を押下します
![スクリーンショット 2022-06-10 8.54.28 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/6ebc1d3a-0ca1-8718-2205-bebc24c47c32.png)

- スナップショットの復元ページに遷移するので設定値を確認していきます。おおよそ削除前のインスタンス設定が入力されています。
![スクリーンショット 2022-06-10 8.56.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/b348e57b-9b4c-5859-dfd2-29be6dce0bea.png)

![スクリーンショット 2022-06-10 8.57.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/cfe70131-0822-873e-590b-1b493e6ccadc.png)

![スクリーンショット 2022-06-10 8.57.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/a2f85d7c-244f-aab5-4988-a67c1b9399ee.png)

- 「DBインスタンスを復元」を押下します。
![スクリーンショット 2022-06-10 8.57.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/5a01cd2d-c320-86c3-6fd0-d6ef510acb90.png)

- RDSインスタンスが復元されました。復元時にVPC、サブネットグループ、セキュリティグループなど変更していなければ、既存のWeb/APサーバなどからの接続も復旧しているはずです。
![スクリーンショット 2022-06-10 9.12.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/776861c4-e733-e70e-b0eb-6961fb1afe11.png)

# まとめ
マネージドサービスであり、操作としては簡単な手順でバックアップ・リカバリができることを確認できました。

以上、最後まで読んで頂きありがとうございました！
【Salesforce】【フロー】ワークフロールールをフローに変換する機能を使ってみた



# リリースノート
[Spring'22](https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_mgmt.htm&type=5&release=236)
[Summer'22](https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_mgmt.htm&type=5&release=238)
※該当ページのリンクになっていますが、リリースノートはリダイレクトする場合があるようです。あしからず。

# 実際につかってみます

### 既存のワークフロールールを確認
すでに作成済みのワークフロールールが２つあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/2361ae9c-58be-8a7d-8147-86535044745e.png)

### フローに移行
「フローに移行」の画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/4e524a4e-4441-a066-2fc9-c3bd11fdca5a.png)

移行したいワークフロールールを選択し、「Migrate To Flow」ボタンを押下します。
ちなみにこの画面で複数のワークフロールールを選択することはできないので1件ずつ行う必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/a0edcd3d-4d13-739e-8522-9901c9f0034a.png)

成功すると以下のポップアップが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/6c9ab707-68df-38ee-9d61-c71ae0328ef7.png)
このときまだワークフロールールが有効で、フローが無効な状態です。
有効を切り替えたい場合は「Switch Activations」ボタンを押下します。

### 作成されたフローの確認
フローの一覧のページに遷移すると変換で作成されたフローが表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/eb11d011-29f5-96fa-7d7f-632eaf0f5b98.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/46d6fa17-a370-1bde-b927-79fa1f4fc61f.png)
API名は自動変換らしい命名になっています。気になる場合は修正します。
※フローAPI名は編集できないので「別名で保存」をする必要があります。

### ワークフロールールの仕様やSalesforce組織のバージョンによって変換エラーが出る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461666/fe97ba0d-0751-65ab-a341-c13f4c56576c.png)
Spring’22ではかなりの割合でエラーが出ました。
Summer’22でだいぶ解消された印象があります。
※キャプチャの環境はSpring’22

# まとめ
- 1件ずつしか変換できない
- 有効化を切り替える必要がある
- 変換できない場合がある
てな感じです。
【JavaScript関数ドリル】中級編のchunk関数の実装アウトプット

## chunk関数の課題内容

_.chunk関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#chunk

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/chunk/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうと思った。


## 課題に取り組んだ後の状態

- 解答例では第二引数が想定通りでない場合の処理を記述していたので、勉強になった。
- 解答例ではWhile文とsplice関数を使用してシンプルに記述されているので、こういった記述ができるように参考にしたい。


## chunk関数の実装コード（答えを見る前）
```javascript
function chunk(array, size = 1) {
  const chunkArray = [];
  let tempArray = [];
  let currentLen = 0;

  for (let i = 0; i < array.length; i++) {
    if (currentLen < size) {
      tempArray.push(array[i]);
      currentLen++;
    } else {
      chunkArray.push(tempArray);
      currentLen = 0;
      tempArray = [];
      tempArray.push(array[i]);
    }
    if (i == array.length - 1) {
      chunkArray.push(tempArray);
    }
  }
  return chunkArray;
}

console.log(chunk(["a", "b", "c", "d"], 2));
// => [['a', 'b'], ['c', 'd']]

console.log(chunk(["a", "b", "c", "d"], 3));
// => [['a', 'b', 'c'], ['d']]
```

## chunk関数の実装コード（答えを見た後）
```javascript
function chunk(array, size = 1) {
    const copiedArray = [...array];
    const chunkedArray = [];

    if (size < 1) {
        throw new Error("Please choose a number greater than 0");
    }

    while (copiedArray.length > 0) {
        chunkedArray.push(copiedArray.splice(0, size))
    }

    return chunkedArray;
}
```
[Docker / docker-compose] 削除系コマンド実行時に Device or resource busy 発生

# 症状

dockerコンテナ内で以下のようなコマンドを実行すると、

```bash
$ pipenv --rm
Removing virtualenv (/app/.venv)...
⠏ Running...Error:  An error occurred while removing /app/.venv!
[Errno 16] Device or resource busy: '/app/.venv'
$ rm -r .venv
/bin/rm: cannot remove '.venv': Device or resource busy
```

このように
`Device or resource busy`
というエラーが出る

# 原因

docker の `volume` として指定しているディレクトリ（おそらくファイルも？）を削除しようとすると、このようなエラーが表示されるということがわかった。

自分の場合、`docker-compose.yml`がこうなってた。

```yaml:docker-compose.yml
version: '3'
services:
  app:
    build:
      ...
    volumes:
      # NOTE: .venvは`volume`としてdockerが作成している
      - hoge_volume:/app/.venv/
volumes:
  hoge_volume:
```

# 結論

dockerがvolumeとして作成したディレクトリを削除しようとすると、`Device or resource busy`というエラーが表示されるようだ。

ただし、他の原因のせいでこのエラーが表示されることもある。

dockerのvolumeとして作成したわけではないディレクトリやファイルが削除できない場合は、以下を参考にしてもいいかもしれない。

# 関連記事

- [Device or resource busyが原因でrm削除できない！！解決法はmountやmvではなく、〇〇だ！！](https://japan-challenge.net/device-or-resource-busyが原因でrm削除できない！！解決法はmountやmvで/)
MySQL Workbenchでテーブルをエクスポート・インポートする方法

## 概要
MySQL Workbenchでテーブルをエクスポート・インポートする必要があったため、簡単に整理しました。

## 準備
MySQL Workbenchで使うmysqldumpのバージョンを確認する
http://devlabo.blogspot.com/2013/06/mysqlworkbentch.html

## エクスポート及びインポートについて
以下を参考に設定する
https://hacknote.jp/archives/6030/
view-lock-mode

<!-- $Id: view-lock-mode.org,v 1.9 2022-06-11 08:52:19+09 fubuki Exp fubuki $ -*- mode: org -*- -->
# view-lock-mode
view-mode のとき、しばらく触らないと印字キーをロックする拡張です。
事故防止等で view-mode にしておいたのを忘れて、  少し経って編集しようとして素のキーにバインドされている isearch を動かしてしまったり、  `q` でウィンドウを閉じてしまったりして、迷子になるのを防止するためのものです。
<!--  テキスト破壊事故防止で view-mode にしておいたのに view-mode で迷子という事故になる。 -->

# 使い方
  [ここ](https://github.com/s-fubuki/view-lock-mode)から落とし `load-path` の通った位置に置きます。
```emacs-lisp:init.el
 (require 'view-lock-mode)
```

  ロードされると `view-read-only` を `t` にします。
  *C-x C-q* で `read-only-mode` にすると  `view-mode` になり、  モードラインの `View` インジケータに色がつきます。

![vl-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239081/e6d85513-f789-0a63-0e9a-37159a5c3615.png)

  `view-mode` のとき 5分間タイプがないと文字キーがロックされ `View` インジケータの色が変わります。
  文字キー(または改行)を打つと文字が打てずエコーエリアに その旨のメッセージが表示されるようになります。

![vl-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239081/776624f4-54b1-298c-1979-f52cad114457.png)


  ロックされるのは印字キーと改行キーだけなので、  コントロール系は勿論カーソル等ファンクション系のキーは素通りします。

  解除するには *C-x C-q* または *M-q* を押します。 view-mode, read-only-mode 共々 view-lock-mode が終了し、  バッファが編集できるようになります(view-lock-quit)。

  このとき prefix を付けると `view-lock-mode` だけが終了し `view-mode` のままになり、再びロックまでのタイマーがスタートします
  [^1]。

# カスタマイズ
## カスタム変数
### view-lock-start-time
キーに触れなくなってからロック開始するまでの秒数を整数で指定します。
デフォルトは 300(5分)です。

### view-lock-current-input-method
non-nil だとロック時に IME を切ります(これも入れたままなのを忘れているので)。
デフォルトは `t` です。SKK でしか効力がないかもしれません。

### view-lock-vc-faces
VC に `read-only-mode` と連動させた部分があるので、    モードラインの VC ステイタス表示が、フェイス `view-lock-vc` になるようにしてあります。

この変数でリスト指定した VC のフェイスが対象になります[^2]。
不要な場合やVCフェイス側で設定する場合は `nil` にすると無効になります。
デフォルトは \(vc-up-to-date-state vc-locked-state) です。

![vl-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239081/f4865d9d-8340-a05e-0429-e12127f26fd0.png)

![vl-8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239081/505fe1a3-6600-3c9b-b6a4-1d91b8d7fe17.png)

![vl-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239081/ba96317a-24f9-5ec7-e1f8-08af4d740419.png)

RCS 等の Lock系の場合、自分がリポジトリをロックしていない状態だと (つまり編集できない状態なら) VC インジケータに色がつきます(-)。
Git 等のマージ系なら未編集なら着色され(-)で更新すると消灯します(:)。
共にワークファイルが未編集だと点灯しているということになります。

### view-lock-lighter
view-lock-mode のインジケータ・ラベル文字列。
先頭にスペースをひとつ入れてください。
`view-lock-lock-highlight` により "View" インジケータを灯火するだけでいいなら、`nil` にしておけばこちらは出なくなります。

## フェイス
### view-lock-highlight
mode-line に表示される "View" マイナーモード・インジケータのフェイス.

### view-lock-lock-highlight
ロック時の "View" のフェイス。

### view-lock-vc
カスタム変数 `view-lock-vc-faces` で指定されたフェイス属性をこのフェイスのものにします。
`view-lock-highlight` からボールド属性を取り除いたものになっています。

# 動作環境
> GNU Emacs 29.0.50 (build 1, x86_64-w64-mingw32) of 2022-04-03

<!-- foot note -->

[^1]:  これは *C-x C-q* を2回打つのと同じで、その方が楽なので覚える必要はないでしょう。
[^2]: VC face かどうかの整合性はチェックしていないのでスペルミスには注意してください。
DockerでMySQL接続時にHost xxx is not allowed to connect to this MySQL serverが出た時の対処法

## 概要
DockerでMySQL接続時にタイトルのエラーが出たので、原因と対処法を整理しました。

## 確認した内容

以下を実行してみる

```sql
select Host, User, authentication_string from mysql.user;
```

Hostがlocalhostとなっていました。

## 対処法

以下を実行し、Hostがワイルドカードなユーザを作成する

```sql
CREATE USER 'root' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
```

上記コマンドにより、以下のユーザが作成される

```
User：root
password : なし
Host：%
```

## 参考
https://zenn.dev/ryo_kawamata/articles/mysql-connect-error
【JavaScript関数ドリル】中級編のconcat関数の実装アウトプット

## concat関数の課題内容

_.concat関数を自分で実装する課題。
https://lodash.com/docs/4.17.15#concat

「課題内容」/「解説動画」/「解答例」を確認したい場合は、以下リンク先のページを参照。
https://js-drills.com/blog/concat/


## 課題に取り組む前の状態

- 解答例を見なくてもできそうと思った。


## 課題に取り組んだ後の状態

- 解答例ではforループ内でも変数をしようしているのを除いては、同じように実装できたので、よかった。


## concat関数の実装コード（答えを見る前）
```javascript
function concat(array, ...values) {
    const concatenatedArray = [...array];

    for (let i = 0; i < values.length; i++) {
        if (Array.isArray(values[i])) {

            concatenatedArray.push(...values[i]);
        } else {
            concatenatedArray.push(values[i]);
        }
    }

    return concatenatedArray;
}

var array = [1];
var other = concat(array, 2, [3], [[4]]);
 
console.log(other);
// => [1, 2, 3, [4]]
 
console.log(array);
// => [1]
```

## concat関数の実装コード（答えを見た後）
```javascript
// 同じ
```
Haskell の関数定義を検索するスクリプトを作ってみました

Haskell 入門中です。関数定義を検索する `h` コマンドを作ってみました。

# ダウンロード

- [h (gist)](https://gist.github.com/toyboot4e/4f45136c4724bd09b3150664f3e2d91e)
- [h (キャッシュ付き curl 使用版)](https://github.com/toyboot4e/toy-scripts/blob/main/h) 、 [ccurl](anbox.cc/)

# 使い方

`h` コマンドで関数定義を検索すると、

```sh
$ h zipWith
```

ソース (ソース閲覧用 html) をダウンロードして `bat` で開いてくれます:

![h-zipWith.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594390/96f63d68-2193-27f5-1e5c-15fc096c3a85.png)

本当はローカルの Haskell レポジトリから検索した方が良いとは思います。

# 動機

[hoogle] では関数やデータ型の検索ができます:

[hoogle]: https://github.com/ndmitchell/hoogle

```sh
$ hoogle print -n1
Prelude print :: Show a => a -> IO ()
-- plus more results not shown, pass --count=11 to see more
```

`-i` オプション (info) を渡すと、より詳細な解説やコード例を出力してくれます:

```sh
$ hoogle -i print
print :: Show a => a -> IO ()
base Prelude
The print function outputs a value of any printable type to the
standard output device. Printable types are those that are instances

~~ 省略 ~~
```

しかし `print` に関しては関数定義を出してくれた方がストレートで嬉しいです:

```hs
print           :: Show a => a -> IO ()
print x         =  putStrLn (show x)
```

そこで強引に関数定義を探す小さなコマンドを作ってみました。

# 作り方

まず [hoogle] コマンドで hackage へのリンクを探します:

```sh
$ hoogle search --json -n1 "print"
[{"docs":"The <a>print</a> function outputs a value of any printable type to the\nstandard output device. Printable types are those that are instances\nof class <a>Show</a>; <a>print</a> converts values to strings for\noutput using the <a>show</a> operation and adds a newline.\n\nFor example, a program to print the first 20 integers and their powers\nof 2 could be written as:\n\n<pre>\nmain = print ([(n, 2^n) | n &lt;- [0..19]])\n</pre>\n","item":"print :: Show a => a -> IO ()","module":{"name":"Prelude","url":"https://hackage.haskell.org/package/base/docs/Prelude.html"},"package":{"name":"base","url":"https://hackage.haskell.org/package/base"},"type":"","url":"https://hackage.haskell.org/package/base/docs/Prelude.html#v:print"}]

$ hoogle search --json -n1 "print" | jq .[].url
"https://hackage.haskell.org/package/base/docs/Prelude.html#v:print"

$ hoogle search --json -n1 "print" | jq .[].url | sed 's;";;g'
https://hackage.haskell.org/package/base/docs/Prelude.html#v:print
```

このリンクを開くと Hackage の関連ページに来ることができます [^1]:

![hackage-print.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594390/efea747f-0d89-1d84-34f5-de7d93844c52.png)

右上の [Source ボタンを押すと](https://hackage.haskell.org/package/base-4.16.1.0/docs/src/System-IO.html#print) 、ソース閲覧用ページに飛べます:

![print-def.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594390/e893e0d4-1d58-eff8-4377-f15b8f1ab528.png)

この html ページをダウンロードして `bat` に渡します:

```sh
printf '%s' "$source" | bat -l haskell --pager "less -RF --pattern=$word.*::"
```

![h-zipWith.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594390/96f63d68-2193-27f5-1e5c-15fc096c3a85.png)

[^1]: Slack で教えていただきました。ありがとうございました。
同時ライブ配信時に注意すべきMediaStoreの上限(クォータ)について

## はじめに

通常のライブ配信のケースでは特に意識する必要はありませんが、
同時に多数のライブ配信を行う際に注意すべき点をまとめておきます。

これは実際に私が経験した内容で、テスト配信では問題がなかったものの本番配信ではこの事象が起きたので、その様子を振り返りながら、原因や対策を整理していきます。

## 構成図

ライブ配信環境は以下のスタンダードな構成です。

MediaLive(Single Pipeline) -> MediaStore -> CloudFront

少し特殊だったのが、本番では同時に32チャンネルで配信する必要があったため、
これを1セットとして、32チャンネル分を用意していました。

![ScreenShot 2022-06-10 9.31.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277934/f3e550dd-5ee0-17b1-bd10-908634ade688.png)

## 当時の状況

同時に32チャンネルのライブ配信を行ったところ、
数秒おきに止まっては復帰を繰り返す状況がみられました。

最初は配信現場の通信環境や送出される映像ソースの問題とも考えましたが、
MediaLive Channelでは NetworkIn や Dropped Frames などの異常は確認されませんでした。

その後、MediaLive ChannelのAlertメッセージを見ると、
下記のような見慣れないメッセージが多数出力されていることが分かりました。

メッセージ内容から、MediaLiveからMediaStoreにファイルを書き込む処理で
何らかの問題が起きているようだ、と分かってきました。

以下はそのAlertメッセージの一部抜粋です。

```
Alert Type : Failed to Close or Finalize the Output
Message : MPEGTS muxer for mediaID [3] unable to close output or stream.

Alert Type : Failed to Create Output File or Socket
Message : MPEGTS muxer for mediaID [3] unable to open output or stream [mediastoressl://xxxxxxxxxxx.data.mediastore.ap-northeast-1.amazonaws.com/live_2m.m3u8].

Alert Type : Failed to Write to Output
Message : SegmenterAppleLive OutputData Write failed

Alert Type : Failed to Write to Output
Message : OutputDataBackground failed to send file for URL [mediastoressl://xxxxxxxxxxx.data.mediastore.ap-northeast-1.amazonaws.com/live_2m_xxxxx.ts]

Alert Type : Large Upload Cache Backlog
Message : Upload speeds slower than real time detected when uploading URL [mediastoressl://xxxxxxxxxxx.data.mediastore.ap-northeast-1.amazonaws.com/live_2m.m3u8]
```

## 原因

調べてみると、MediaStoreの **PutObjectの上限(クォータ)に抵触している** 可能性が考えられました。
https://docs.aws.amazon.com/ja_jp/mediastore/latest/ug/quotas.html

>・PutObject – Standard Upload Availability : 100 TPS
>The maximum number of operation requests that you can make per second. Additional requests are throttled.

動画が完全に視聴できない状態ではなく、止まっては復帰を繰り返す状況に当てはめても、
「上限に引っかかり、リクエストが制限されてスロットリングが発生していた」と考えると説明がつきます。

具体的な数値を計算してみます。

・同時に使用していたチャンネル数：32チャンネル
・セグメントの長さ：2秒
・ABR：5M/2M/1M/500K の計4つ

tsとm3u8がそれぞれ2秒ごとに生成されるため、TPSで換算すると

4 × 32ch = 128TPS

**PutObject のデフォルト上限値は 100TPS** なので、
これがどうやら上限(クォータ)を上回っているようでした。

## 対処

AWSコンソールの Service Quotasから 利用しているリージョンを選択し、
MediaStore ページから、対象の設定項目である「PutObject」の引き上げ申請を行いました。

>※実際の名称は下記となっていました。
>「Rate of PutObject API requests for standard upload availability」

その後、AWSサポートから 使用チャンネル数 や セグメントの長さ に関する情報提供の依頼があり、
サポートケースから返答を行いました。

しばらくすると、Service Quotasの引き上げリクエストが完了され、
「適用されたクォータ値」が指定した値に引き上げられていることが確認できました。

### 補足

MediaStoreクォータのTPSは、基本的にアカウント毎に割り当てられています。
AWSサポートに依頼することで、個々のコンテナにクォータを割り当てることも可能です。

## おわりに

Service Quota の設定値は見落としがちとはいえ、
今回の事象は本番に近い状態で事前テストを入念に行うことで気づけたと反省があるため、今後に生かしたいと思います。

ABRの設定にもよりますが、計算上
ABR4本の場合は25チャンネル以上を同時に配信する際に、PutObjectの上限引き上げを事前に行っておくと安心です。

また、MediaLive ChannelのAlertメッセージはAWSコンソール上で確認できるものの、
現状では古いメッセージは表示されなくなり、後から見れなくなるという点も気をつけたいところです。

その対策として、Alertメッセージはslackに出力させて、後からでも追えるようにしています。
この仕組みだと異常に気がつきやすくなるため、トラブルシューティングの観点から設定をお勧めします。

この記事が誰かのお役に立てれば幸いです。
RustでTCP Serverを立てる

## 概要

RustでシンプルなTCPサーバを立ててみる手順のメモです。


## 参照

https://doc.rust-lang.org/std/net/struct.TcpListener.html


## プロジェクトの作成

```console
% cargo new tcp_server_hello_world 
% tcp_server_hello_world
% cargo run                                                                                                      
   Compiling tcp_server_hello_world v0.1.0 (/.../tcp_server_hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 0.86s
     Running `target/debug/tcp_server_hello_world`
Hello, world!
```


## 接続してすぐcloseするTCP Serverの作成

```rust
use std::net::{TcpListener, TcpStream};

fn handle_client(_stream: TcpStream) {
}

fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080")?;

    for stream in listener.incoming() {
        handle_client(stream?);
    }

    Ok(())
}
```

サーバを起動します。
```console
% cargo run  
```

telnetで接続してみると、繋がった後、すぐcloseされました。
```console
% telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
```

## TCP Serverからメッセージを返す

`handle_client` を少し変更してメッセージを返すようにします。
```rust
use std::net::{TcpListener, TcpStream};
use std::io::Write;

fn handle_client(mut stream: TcpStream) {
    stream.write("Hello World!\n".as_bytes()).unwrap();
}

fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080")?;

    for stream in listener.incoming() {
        handle_client(stream?);
    }

    Ok(())
}
```

サーバを起動し接続してみると、次のようにメッセージが返ってきます。
```console
% telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World!
Connection closed by foreign host.
```

### TCP Serverにメッセージを送信し、同じメッセージを返す

```rust
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};

fn handle_client(mut stream: TcpStream) {
    let mut buf = [0u8; 1024];
    stream.read(&mut buf).unwrap();
    stream.write(&buf).unwrap();
}

fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080")?;

    for stream in listener.incoming() {
        handle_client(stream?);
    }

    Ok(())
}
```

このような結果になり、期待どおりに動きました。
```console
% telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Hello World!                              // 入力したメッセージ
Hello World!                              // 返されたメッセージ
Connection closed by foreign host.
```
メモ：四元数の大円

　素人のメモ書き。
　理解していない。間違ってるかも。

　四元数には向きの自由度が3つあるので、極座標(向きの自由度が2つ)の大円を求めようとしてもLerpやSlerpだけではうまく求められない?
　一旦2本のベクトルに変換し、ベクトルのクロス積で回転軸を求め、ドット積で回転角を求める。それを使って四元数を作って、最初の四元数とかけることで大円の姿勢が得られる。

```c#
public static (Quaternion, Quaternion) GrateCircle(Quaternion q, Quaternion p)
{
    var v1 = Vector3.Transform(Vector3.UnitX, q);
    var v2 = Vector3.Transform(Vector3.UnitX, p);
    return (q,
        Quaternion.CreateFromAxisAngle(
            Vector3.Normalize(Vector3.Cross(v1, v2)),
            MathF.Acos(Vector3.Dot(v1, v2))) * q);
}
```

![log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264452/f3a47d67-a9fa-4687-fde3-db8452ae3d15.png)

　白い線は極座標から作った四元数を直接Quaternion.Lerpに渡して補間したもの(Slerpも同様の結果)。緑の線はGrateCircleで再生成した四元数をQuaternion.Lerpに渡して補間したもの。
　Google Earthで線を引くと緑の線に近い経路をたどる。

　地図上で2点間の大圏コースを引くとかなり違和感のある形になるけど、人工衛星の軌道だと思って見てみると、そんなに違和感ない気もする。

***

　なんで大円を求めるのに四元数とか使ってるんだ、というツッコミは御容赦を。。。Google Earthでわかりやすいように地図を表示しているが、元々は地理関係以外で使う予定だったのでインターフェースが四元数になっている。

　地図のデータはNASAの画像を使用した
　[Blue Marble: Land Surface, Shallow Water, and Shaded Topography](https://visibleearth.nasa.gov/images/57752/blue-marble-land-surface-shallow-water-and-shaded-topography/57756l)
STM32G031のボリュームの入力でサーボ出力2(Servo.h使用)



x OBでGPIOがわかる人むけ


目的
アナログサーボ信号で遊ぶ

1 ADC 
2 VDD
3 GND
4 SERIAL

8 SWD
7 SWD
6
5 PWM


PA8 ピン番号3 5ピン

サーボの初期化
fs90r.attach(

値の設定
fs90r.write(val);

fs90rは、360度　無限回転サーボらしい
サンプルを改造


```c++


/*
 Use servo library to control a FS90R motor

 Motor information :
   http://www.feetechrc.com/product/analog-servo/micro-1-3kg-cm-360-degree-continuous-rotation-servo-fs90r/
   Must respect the pulse range in order not to damage servo.

*/

#include <Servo.h>

Servo fs90r;  // create servo object to control a servo

//int potpin = 0;   // analog pin used to connect the potentiometer
int val;          // variable to read the value from the analog pin
//int servopin = 9; // pin used to connect the servo
int servopin = 3; // pin used to connect the servo

void setup() {

  delay(3000); //not delete

  Serial.setTx(PA2_ALT1);
  Serial.setHalfDuplex();
  Serial.begin(9600);

  fs90r.attach(servopin, 900, 2100); // attaches the servo on pin 9 to the servo object
                                     // Be careful to min and max values...
}//setup

void loop() {
  //val = analogRead(potpin);        // reads the value of the potentiometer (value between 0 and 1023)
  val = analogRead(A9); // PB7 PIN1
  val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180, at 90,
                                   // motor is stopped)

  Serial.print("val = ");
  Serial.println(val);

  fs90r.write(val);                // sets the servo speed according to the scaled value
  delay(15);
}//loop



```
【Git】fatal: not a git repository (or any of the parent directories): .git解消法

## 原因
`git remote add`や`git branch`、`git commit`実行時に以下のようなエラーが出る場合があります。
```:ターミナル
$ git remote add origin .....
fatal: not a git repository (or any of the parent directories): .git
```

これは初期設定が不十分な場合に発生します。

## 解消法
ユーザーに関する設定ができていない場合には以下のコマンドを実行して設定します。
```:ターミナル
$ git config --global user.name "UserName"
$ git config --global user.email "sample@email.com"
```
設定できているか以下のコマンドで確認します。
```:ターミナル
$ cat ~/.gitconfig
[user]
  email = sample@email.com
  name = UserName
```

次にgitの初期化をします。
```:ターミナル
$ git init
Initialized empty Git repository in sample-app/.git/
```

これで正常にコマンドが実行できるようになります。
EC2にRailsアプリをデプロイするための事前知識　――パッケージ管理ツールとパッケージ


## はじめに
スクールの課題で、「まずEC2にアプリをデプロイしてみよう。」というものが出された。
調べれば新しいものから古いものまで、いろんな情報が出てくる。
とりあえず見たままコマンドコピペして進めていたけれど、一体今何をやろうとしているのか分からない、エラーがまるで意味不明
という状況になり、挫折。時間はかかるが、ある程度の基礎知識を身に着けながら進めたほうが早そうと判断。
課題も無事終えたので、復習がてら、とり貯めたメモをベースに整理。


## パッケージのインストール時に適当に打ったコマンド
```
$ sudo yum -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel
```

```
$ curl -sL https://rpm.nodesource.com/setup_16.x | sudo bash -
$ sudo yum install -y nodejs
$ curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
$ sudo yum install -y yarn
```
Node.jsもyumもyarnも最初は「???」で、とりあえずググって出てきたコマンドを実行してインストールしてた。

## 以下まとめ
#### Linux
Linuxのパッケージ管理ツールとして、yum、dnfがある(dnfが後継)。

#### Javascript
JavascriptをOS上で実行するための環境を用意してくれるのがNode.js。
(本来JavascriptはWebブラウザ上でのみ動作するものなので、こいつを用意する必要がある)
Javascriptのパッケージ管理ツールとして、npm、yarnがある。
Railsに深く関わるパッケージの例として、webpack(というか今は必須)。
なお、Node.jsのバージョン管理人として、nvmがある。

#### Ruby
Rubyのパッケージ管理ツールとして、Gemがある。RubyGemsと呼んだりもする。
(パッケージ群そのものをGemと呼ぶこともあって、紛らわしい)
パッケージ同士の依存関係の面倒まで見てくれるパッケージ管理ツールとして、Bundlerがある。
BundlerもGem(パッケージ)の一つ。
rubyのバージョン管理人としてrbenvがある。
ruby-buildはrbenvのプラグイン。このプラグインを入れると、`$ rbenv install <version>`コマンドが打てるようになり、特定のバージョンを選択してインストールし、バージョン切替が自由にできるようになる。

## 参考
* Javascript、Node.js、npm、nvmなど
[Node.jsとはなにか？なぜみんな使っているのか？](https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb)
[そもそもnpmからわからない](https://zenn.dev/antez/articles/a9d9d12178b7b2#nvm%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9)
[いまさら聞けない！npmのこれだけは知っておきたい基礎知識](https://www.webprofessional.jp/beginners-guide-node-package-manager/)

* RubyのGem
[Rubyのgemとは？概要から使い方までの解説まとめ](https://techplay.jp/column/529)

* rbenvとruby-build
[Ubuntuでのrbenv,ruby-buildの使い方と事前準備に必要なaptパッケージ](https://qiita.com/tatsurou313/items/2a67075ae2416922bff0)

* ここに登場したLinuxコマンド
[curlコマンドの使い方　～GET、POST、REST（json）の確認と、windowsでの利用手順](https://viral-community.com/security/curl-8263/)
[curl option 覚え書き](https://qiita.com/takayukioda/items/edf371b3566bea64d046#-s-%E9%80%B2%E6%8D%97%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%82%92%E3%81%97%E3%81%AA%E3%81%84)
[LinuxコマンドでWEBからファイルをダウンロードする方法 (wget, curl)](https://weblabo.oscasierra.net/linux-file-download/)

* 今からデプロイの参考にさせていただくとしたら
[【　Ruby on Rails 6.0　】AWS + Nginx + Unicornでデプロイ①](https://qiita.com/anago1030/items/854252bc9b728fe90beb)

#### ひとこと
勉強すること、多くない?
上に載せた以外にも、倍くらいの記事とかサイトに当たってると思う。
楽しいんだけど、仕事しながらだと体力勝負って感じ。
課題やったら知らないことが増えた。
Eigen3を利用したソースコードをcmakeを用いてビルドする

# はじめに
- この文書ではEigen3を利用したc++のソースコードをcmakeを用いてビルドする方法を説明します．
- EigenのサイトでのCMakeLists.txtの説明と同じですが[( Using Eigen in CMake Projects )](https://eigen.tuxfamily.org/dox/TopicCMakeGuide.html)，英語だと理解に時間がかかるので備忘録的に日本語でこの文書を作成しました．

# 開発環境
- 標準的なlinux環境 (Ubuntu18.04.5 LTSを利用)
- Eigen3 (3.3.4-4を利用)
　- インストール方法```sudo apt install libeigen3-dev```
- cmake (3.10.2-1を利用)
　- インストール方法```sudo apt install cmake```

# ビルド手順
- 開発ディレクトリにEigen3を用いたソースコード (例: sample.cpp) を作成する
- 開発ディレクトリに以下で説明するCMakeLists.txtを作成する
- 開発ディレクトリの下にビルドディレクトリ (例: build) を作成する(```mkdir build```)．(ビルドディレクトリの作成は必須ではないが，cmakeの作業ファイルで開発ディレクトリをうるさくしないため)
- ビルドディレクトリに移動する (```cd build```)
- ビルドディレクトリでcmakeを実行する (```cmake ..```)と，Makefileが生成される
- makeを実行する (```make```)
- ビルドディレクトに実行ファイル (例：```sample```) が生成される

# sample.cpp
``` cpp: sample.cpp
#include <iostream>
#include <Eigen/Core>
int main( ) {
    Eigen::Vector3d v( 0.0, 0.0, 1.0 );
    Eigen::Matrix3d m;
    m << 0.0, -1.0, -1.0, 1.0, 0.0, -2.0, 0.0, 0.0, 1.0;
    std::cout << m * v << std::endl;
    return ( 0 );
}
```

# Eigen3のためのCMakeLists.txt
```cmake: CMakeLists.txt
cmake_minimum_required( VERSION 3.0 )
project( proj CXX )
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
add_executable( sample sample.cpp )
target_link_libraries( sample Eigen3::Eigen )
```

# 実行結果
``` terminal
> ./sample 
-1
-2
 1
```

# CMakeLists.txtの内容の説明
- 1行目: cmakeの最低バージョンの指定
- 2行目: プロジェクト名 (proj) と使用言語の指定 (CXX = c++) (省略可能)
- 3行目: Eigen3の利用を宣言 (主にinclude pathの設定)
- 4行目: 実行形式名(sample)とそのソースコード (sample.cpp) の指定
- 5行目: 実行形式に対する追加のリンクライブラリを指定 (Eigen::Eigen) 

# おわりに
- Eigenを利用したソースコードのビルドはインクルードパスの指定が面倒ですよね．
- cmakeを導入すると，Eigenを利用するときの典型的なCMakeLists.txtをテンプレートして利用することで，簡単にビルド (make) ができるようになります．
ユースケース駆動開発について

# これは何
ドメイン知識が複雑で特定の人しか把握していない仕様があり、他のメンバーが仕様が把握しやすいようにする必要がありました。

勉強会で見かけたユースケース駆動開発に興味があり、本を読んでみてユースケースモデリングとドメインモデリングについて書いてみました。

# ユースケース駆動開発について
ユースケース駆動開発とは、システムの機能を利用者から見たシステムの振る舞いを記述したもの（ユースケース）に分割し、それを基に要求分析から実装までの工程を進めていく開発手法です。

本はこちら
[ユースケース駆動開発実践ガイド](https://www.amazon.co.jp/%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-OOP-Foundations-%E3%83%80%E3%82%B0%E3%83%BB%E3%83%AD%E3%83%BC%E3%82%BC%E3%83%B3%E3%83%90%E3%83%BC%E3%82%B0/dp/4798114456)

この本の第2章の「ドメインモデリング」と第3章「ユースケースモデリング」を参照しました。

ユースケース駆動開発自体は古くからあり書籍も古いが、現在でも十分通用する内容だと思います。

ユースケース駆動開発の拡張（と本の中では定義されている）として、TDD駆動開発も可能になるそう。
これは、ユーザー視点で設計していく開発手法なので納得できますね。

### ドメインモデリング
ドメインモデリングの目的は、問題領域に対する共通の用語集を作成することによって、プロダクトのコミュニケーションミスによる問題を解決する。

> **DDDのドメインモデリングとの違い**
DDDにもドメインモデリングがあり、ユースケース駆動開発と似たような概念になっているので、DDDの導入を検討する際にも役に立ちそうです。
>
> 厳密には、DDDのドメインモデリングとユースケースモデリングは違い、DDDのドメインモデリングはクラス図に近い形で書きます。
>
> [ドメイン駆動設計の2つのモデリング手法　ユースケース図とドメインモデル図をどう作る？ - ログミーTech](https://logmi.jp/tech/articles/322835)

#### ドメインモデル図について

作成するにあたっては、以下のルールで作成するのを心がける。

- 作業は2時間に限定する。
    - ICONIXプロセスではドメインモデルを完璧に作成するのではなく、以降のプロセスで成り立たせていく。
- あくまで、現実世界のオブジェクトに焦点を合わる。
    - データベースモデルやクラス設計ではない。
- 属性や振る舞いは記述せず、シンプルにドメイン名のみ。
- 汎化（is-a）・集約（has-a）関係を用いる。

### ユースケースモデリング
ユースケースモデリングの目的は、`ユーザーの操作` に対する `システムの応答`を明らかにし、正常系（基本コース）と異常系（代替コース）を洗い出すこと。

ユースケース図とユースケース記述を作成する。

ユースケース図よりも、ユースケース記述がより重要。

ユースケース記述時のポイント
- ドメインモデルの用語を用いる。
- バウンダリクラス（主に画面名）の名前を使う。
- ユーザーとシステムの対話の両側を記述する。
- 指示的ではなく叙述的に書く。
  - 例
  `×ユーザーは著者名で検索できる。`
  `○ユーザーが著者名を入力して「検索」ボタンを押す。システムは著者名に一致する書籍一覧を検索結果画面に表示する。`
- 基本コース（いわゆる正常系）と代替コース（いわゆる異常系）を記述する。
- ユースケース図上の「関係」を正確に記述することを頑張らない。
ほとんどの場合、ユースケース図の関係は invokes、precedes で十分で、extends や includes が必要になる機会は少ない。

#### ユースケース記述がなぜ重要か
ユースケース記述は`ユーザーガイドを書くのに似ている`とのこと。

「ユースケース駆動」は、「まずユーザーガイドを書き、それからコードを書く」というように要約できるらしい。

「ユースケース駆動」の目的は、ユーザーの操作に対する振る舞い要求を実現するためなので、ユーザーの視点でシステムの振る舞いを記述すれば、設計や単体テストもユーザーの視点になる

レガシーシステムにも適用できる。
その際は、ユーザーガイドから開始するのがよいとのこと。
既存の機能を分析し、ユーザーガイドからユースケースを導き出すと、自然と基礎的なコンポーネントにブレイクダウンする（と言う理論らしい）。

###  ドメインモデリングとユースケースモデリングについて
いきなりユースケース図から作成する (ユースケースモデリングする)のではなく、ドメインモデリングから開始する。

理由は、ユースケースは抽象的に書くのではなく、設計するシステムに近いものであるべき(と著者が言っている)。

※ユースケースを抽象的に書くことが、一般では多いが、ユースケース駆動開発(ICONIXプロセス)では、それとは正反対。

ユースケースは動的な部分の基礎を形作り、ドメインモデルは静的な部分の基礎を形作る。
静的な部分は構造を定義し、動的な部分は振る舞いを定義する。

# ICONIXプロセス

ICONIXプロセスでは、ロバストネス分析が肝になるそうなので、厳密にユースケース駆動開発を実践するには、ロバストネス分析以降のステップも含め、実践する事が重要です。

ICONIXプロセス（ロバストネス分析）については、ここでは書きませんので、ご了承ください。

![iconixprocess-feature-image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35613/4b0721c9-94e1-be74-627b-2cc96669ae0b.png)

ユースケース駆動開発およびICONIXプロセスの読解は、以下のサイトが割とわかりやすかったです。
[読んだ : ユースケース駆動開発実践ガイド - ひだまりソケットは壊れない](https://vividcode.hatenablog.com/entry/book/use-case-driven-object-modeling)
[明日から使えるDDDのためのユースケース駆動開発（ICONIXプロセス） - Qiita](https://qiita.com/hirodragon/items/e2330edc1d1a329d17f5)
discord.pyでmessage.contentが取得されない

# 経緯
Discordのアップデートによって、ボイスチャンネルにそれ専用のテキストチャンネルが追加されていた。
このテキストチャンネル、現行のPython Package Indexに含まれているバージョンのdiscord.pyのバージョン1.7.3において、見かけ上ではボイスチャンネルとされているため、
```python
await send(content=None, *, tts=False, embed=None, ...)
```
を用いたテキストチャンネルへのメッセージ送信ができない。
これをどうにかする。

# この問題の原因
- discord.pyのバージョン
- DiscordのIntents設定のし忘れ

この二つ。

# 解決方法
## discord.pyのバージョンを上げる
まずこれ。
そもそも現行バージョンではVoiceChannelのオブジェクト自体にsend()メソッドが**ない**。
バージョンアップせざるを得ない。
```shell
python3 -m pip install git+https://github.com/Rapptz/discord.py
```
Gitからそのままインストール。
旧バージョンが見つかれば勝手に削除される。

## Intentsの設定
### DEVELOPER PORTAL
DiscordのDEVELOPER PORTALのアプリケーションを開き、Botの箇所を開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707356/f603b416-f8ce-b11a-9128-228a3fcd465c.png)
ここの**Privileged Gateway Intents**を好みに設定する。

### スクリプト
```python
TOKEN = 'Your token here'
client = discord.Client(intents=discord.Intents.all())

# process here

client.run(TOKEN)
```
バージョンアップに伴ってdiscord.Client()の引数にIntentsを指定する。

　
この二つの操作をすれば`message.content`が空じゃなくなる。

# さいごに
エラーはこれで出なくなるうえに機能するようになるが、discord.pyのバージョンを無理やり上げたうえで実行しているため、正直やめるべき。（Pypiにあるv1.7.3を使うべき）
ただ公式のBotでもない身内間で使う限りは構わないだろうと思ってしまう。
公式の見解では、そもそもこのイベントのみを待機するBotは今後サポートしなくなるようだ。discord.extを用いたコマンドのBotを全面サポートする方向性に変えていきたいらしい。
aws-nukeでつまづいたこと

個人用備忘録


以下のConfigでaws-nukeを実行したが、エラーが発生した。
```
Your account ID 'XXXXXXXXXX' isn't listed in the config. Aborting.
```

```config.yaml
regions:
- "global"

account-blocklist:
- "999999999" # production

resource-types:
  # IAMユーザは消したくない
  excludes:
  - IAMUser
```



```bash:実行コマンド
docker run --rm -it -v ./nuke-config.yml:/home/aws-nuke/config.yml -v ~\.aws\:/home/aws-nuke/.aws rebuy/aws-nuke --config /home/aws-nuke/config.yml --profile e1 --no-dry-run
```

## 結論
config.yamlにaccountsを指定する必要があった。
加えてIAM系は消したくないので適当に追加して以下とした。
```config.yaml
regions:
- "global"

account-blocklist:
- "999999999" 

resource-types:
  excludes:
  - IAMUser
  - IAMGroup
  - IAMGroupPolicy
  - IAMGroupPolicyAttachment
  - IAMInstanceProfile
  - IAMInstanceProfileRole
  - IAMLoginProfile
  - IAMOpenIDConnectProvider
  - IAMPolicy
  - IAMRole
  - IAMRolePolicy
  - IAMRolePolicyAttachment
  - IAMSAMLProvider
  - IAMServerCertificate
  - IAMServiceSpecificCredential
  - IAMSigningCertificate
  - IAMUser
  - IAMUserAccessKey
  - IAMUserGroupAttachment
  - IAMUserPolicy
  - IAMUserPolicyAttachment

accounts:
  0000000000: {}
  
```

参考にした記事に「削除対象のアカウントを記載」とあり、「アカウントは消さないからいらないか～」って書かなかった。
しかしそうではなく「指定したアカウント内のリソースを削除する」だった。
aws-nukeでは削除するリソースを指定する際にtargetでできるため、リソースを絞る場合はここに書くと思い込んでいたのも原因


### メモ追記
```bash:除外リソース表示コマンド
docker run --rm -it -v ./nuke-config.yml:/home/aws-nuke/config.yml -v ~\.aws\:/home/aws-nuke/.aws rebuy/aws-nuke --config /home/aws-nuke/config.yml --profile e1 -c aws-nuke resource-types
```
Redux ToolkitのRTK Queryを使ったシンプルなReact Nativeアプリを作ってみた

公式DocにPokemon APIの[例](https://redux-toolkit.js.org/rtk-query/overview)が載っているが、練習のために[FakeStoreApi](https://fakestoreapi.com/)を使ってできる限りシンプルなモバイルアプリをExpo Snack上に作ってみた。

RTK Queryを使ってAPIにアクセスして、エラーがなければ商品のタイトルと画像を表示する。

https://snack.expo.dev/@steve.moritani/simple-redux-toolkit-rtk-api

ほぼ公式Doc通りに使ったので複雑なことはなかったが、エクスポートされるFunctionの名前が自動生成される説明を見落とし少し混乱した。

```javascript:product.js
export const fakeApi = createApi({
  ~
    getAllProducts: builder.query({
      query: () => `products/`,
    }),
  ~
  }),
})

// Export hooks for usage in functional components, which are
// auto-generated based on the defined endpoints
export const { useGetAllProductQuery } = fakeApi;
```

export hooksはauto-generatedとあり、
形としては 「use + PropertyName + Query」になる。

builder.queryで作られたgetAllProductsはエクスポート用には
「useGetAllProductQuery」になる。
GetのGが大文字なのも注意。

次はTypeScriptバージョンも練習したい。
2022年版「AviUtl実験室」のリンク先が開けない場合の対処法、結論：URLの「https」の「s」を抜くんだ！

結論：URLの「https]の「s」を抜くんだ！

AviUtl実験室の
「DirectShow File Reader プラグイン for AviUtl」
をダウンロードしようと思ったらこの問題に遭遇した。

DirectShow File Reader プラグイン for AviUtl
https://videoinfo.tenchi.ne.jp/?DirectShow%20File%20Reader%20%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3%20for%20AviUtl

これ開いてみるか
↓
<code>
このサイトは安全に接続できませんvideoinfo.tenchi.ne.jp ではサポートされていないプロトコルが使用されています。
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
サポートされていないプロトコルです
クライアントとサーバーで、共通の SSL プロトコル バージョンまたは暗号スイートがサポートされていません。
</code>

ぬーん。
サイトのトップはどうだべ

ここから後ろの文字を全部消してっと
https://videoinfo.tenchi.ne.jp/?DirectShow%20File%20Reader%20%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3%20for%20AviUtl
↓
https://videoinfo.tenchi.ne.jp

これもダメか

このサイトって何て名前だったか

AviUtl実験室だ
「AviUtl実験室」でgoogle検索してっと

あった

AviUtl実験室
http://videoinfo.tenchi.ne.jp

一応開いてみっか。
お、開けた。

さっきのURLと同じだと思うんだが何か違いが・・・

さっきの
https://videoinfo.tenchi.ne.jp
開けたやつ
http://videoinfo.tenchi.ne.jp

「https」の「http」違いか。

ってことは
「https」の「s」抜いて開いてみたらどうだべ
DirectShow File Reader プラグイン for AviUtl
http://videoinfo.tenchi.ne.jp/?DirectShow%20File%20Reader%20%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3%20for%20AviUtl

開けた

ds_input026a.lzh

ダウンロードしよ。

<code>
このサイトは安全に接続...
</code>

またか。
右クリック＞リンク先コピー

リンク先は
ds_input026a.lzh
https://videoinfo.tenchi.ne.jp/?plugin=attach&refer=DirectShow%20File%20Reader%20%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3%20for%20AviUtl&openfile=ds_input026a.lzh

「https」の「s」抜いてっと
http://videoinfo.tenchi.ne.jp/?plugin=attach&refer=DirectShow%20File%20Reader%20%A5%D7%A5%E9%A5%B0%A5%A4%A5%F3%20for%20AviUtl&openfile=ds_input026a.lzh

ダウンロードできた。

結論：URLの「https]の「s」を抜くんだ！

とりあえず、今回はダウンロードできたけど
「http」やら「https」やら
プロトコル周りは安全性とかで未対応のサイトはアクセスも厳しくなりそう
[個人用]3つアノテーションの1行整理

@RequestParam：1つのHTTPリクエストを受け取るアノテーション

@ModelAttribute：Objectの作成から値の入力までのプロセスを自動化してくれるアノテーション

@RequestMapping：ClientのRequestを処理するControllerを見つけてくれるアノテーション。
　　　　　　　　　これはマッチングサービスみたいなものかな？
GraphAPIを使ってファイルをダウンロードする（Node.js）

`@microsoft/microsoft-graph-client`を使ってファイルをダウンロードするときにめんどくさかったのでメモ。

https://docs.microsoft.com/ja-jp/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=http


```js
const fs = require('fs').promises;
const Blob = require('cross-blob');
const zlib = require('zlib');
const { PassThrough } = require('stream');

async main () => {
  /**
   * 大きいファイル、小さいファイル、テキストファイルなど、ファイルの種類によって返ってくるクラスが変わる
   * @type {PassThrough|Blob|zlib.Gunzip}
   */
  const content = await client.api('/drives/{drive-id}/items/{item-id}/content').get();

  let data;
  if (content instanceof PassThrough) {
    let chunks = [];
    for await (const chunk of content) {
      chunks.push(chunk);
    }
    data = Buffer.concat(chunks);
  } else if (content instanceof Blob) {
    data = Buffer.from(await content.text());
  } else if (content instanceof zlib.Gunzip) {
    data = await new Promise((resolve, reject) => {
      let chunks = [];
      content
        .on('data', (chunk) => chunks.push(chunk))
        .on('error', reject)
        .on('end', () => {
          resolve(Buffer.concat(chunks));
        });
    });
  } else {
    throw new Error(`Unrecognize type of the content. '${content.constructor.name}'.`);
  }
  await fs.writeFile('filename', data);
}
```
HTTPの特徴

HTTPは、Connect - Request - Response - Disconnectの4段階でクライアントと通信する。

HTTPの特徴
(1)Connectionless：Clientの要求に対してサーバが応答を終えると、接続を切る。
　　　　　　　　　リソースが減り、サーバの負担が少なくなる利点があるが、
　　　　　　　　　これによってStatelessという短所もある。
(2) Stateless：接続が切れた後のClientの情報は保存しない。 
　　　　　　 接続するたびに新しく認証しなければならない欠点があったが、
　　　　　　 クッキーとセッションの登場で情報を記憶できるようになった。
MySQLのテーブルロック・行ロックについて勘違いしていたこと。

## テーブル例

下記のようなテーブルがあるとします。
このテーブルは`id`カラムのみインデックスが貼られています。

#### testテーブル
| id(indexあり) | code | date | status |
|:-:|:-:|:-:|:-:|
| 1 | 100 | 2022-01-01 | 0 |
| 2 | 200 | 2022-02-01 | 0 |
| 3 | 300 | 2022-03-01 | 0 |

## テーブルロックありパターン

MySQLの仕様として、インデックスを使ったクエリでないと行ロックを取得できません。
[こちらのブログ](https://developers.gnavi.co.jp/entry/mysql-tips)で詳しく書かれています。

簡単に書くと、、、

```sql
-- 接続①
mysql> BEGIN; -- トランザクション開始
mysql> UPDATE test SET status = '1' WHERE code = '100';
-- Query OK, 1 row affected (0.00 sec)
-- Rows matched: 1  Changed: 1  Warnings: 0　<-この時点でテーブルロックが掛かっている

-- 接続②
mysql> BEGIN; -- トランザクション開始
mysql> UPDATE test SET status = '1' WHERE code = '200';
-- ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction　<- 既にテーブルがロックされているのでロック待ちエラーが出る
```

このパターンだと、接続①、接続②ともに検索条件に指定しているのは`code`で、このカラムにはインデックスが貼られていません。
従って、接続①の段階でテーブルロックがかかり、接続②でロック待ちタイムアウトが出現します。
これは[ブログの記事](https://developers.gnavi.co.jp/entry/mysql-tips)を読んですぐに理解できました。

## 私が勘違いしていたパターン

```sql
-- 接続①
mysql> BEGIN; -- トランザクション開始
mysql> UPDATE test SET status = '1' WHERE id = '1';
-- Query OK, 1 row affected (0.00 sec)
-- Rows matched: 1  Changed: 1  Warnings: 0

-- 接続②
mysql> BEGIN; -- トランザクション開始
mysql> UPDATE test SET status = '1' WHERE code = '200';
-- ????
```

このパターンだと、接続②の結果はどうなると思いますか・・・？

私の考えでは、、、
接続①では、検索条件に指定している`id`にはインデックスが貼られている
つまり、この時点ではテーブルロックは掛かっておらず、行ロックのみ。
接続②では、`code`というインデックスが貼られていないカラムを検索条件として使用しています。
しかし、検索している行自体は、接続①で検索した行とは異なるので**ロック待ちタイムアウトは出ない**想定でした。

しかし、実際は最初のパターンと同じように**ロック待ちタイムアウトが出ます。**

## 最後に

恥ずかしながら勝手な思い込みで、接続①、接続②のいずれかで、インデックスが貼られているカラムを検索条件に使っていれば
ロック待ちタイムアウトは出ないものだと思っていました。。
実際は、インデックスが貼られていないカラムを検索条件に使った段階で、テーブルロックからのロック待ちタイムアウトが出るようです。

今回のパターンで`Lock wait timeout exceeded; try restarting transaction`が出た場合は下記２点を確認してみてください。

1. **適切なインデックスが貼られているか**
1. **既に貼られているインデックスで検索条件を組み変えることができないか**

まだまだSQL勉強中ですので、間違っている箇所や補足などありましたら、コメントにて教えていただけますと幸いです。
[Vue] <slot> を使うと"TypeError: Cannot read properties of null (reading 'isCE')" になる

# `<slot>` を使うとエラーになる

Vue3 で `<slot>` を使う npm を作成している時のことです。
Vite でコンパイルすると問題ないのに、プロジェクトでその npm を使用すると下記のエラーが出てしまい散々悩まされました。

```
TypeError: Cannot read properties of null (reading 'isCE')
```

https://github.com/vuejs/core/issues/4344

# `vite.config.ts` の設定

対応方法を検索すると `vite.config.ts` で `external` や `dedupe` を追加しろというものが出てきます。
下記のように追加してみましたがダメでした。

```js
export default defineConfig({
  build: {
    rollupOptions: {
      external: ['vue'],
    },
    // 〜略〜
  },
  resolve: {
    dedupe: ['vue'],
    // 〜略〜
  },
  // 〜略〜
});
```

# 結論： npm の中に不要な node_modules を残すな

本来なら npm とプロジェクトは別の場所で開発するものなのですが、今回は手間を省くためにプロジェクトの `node_modules` 内でそのまま開発していました。

```
/プロジェクトルート
+-- /src
|   +-- index.ts // ② ここで使う
+-- /node_modules
    +-- /myModule
        +-- /node_modules
        +-- /src
            +-- index.ts // ①ここで npm を開発して
```

すると Vue パッケージが複数存在することになり、それでエラーになってるようです。

**`/node_modules/myModule/node_modules` を削除したらエラーは出なくなりました。**

そもそも `vite.config.ts` で `external` や `dedupe` を指定する理由が Vue パッケージを除外するためですしね。

こんなことで２時間近く悩んでしまった……。