OmniAICreator/Qiita-1.07M huggingface dataset:
Windowsのターミナル背景の変え方

# 環境
OS: Windows11

# 手順
- Terminalを開きタブ右端のメニューを開き設定を開く
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3432230/0958cf43-94f2-d053-9df6-1d4f4adb5cd8.png)
:::note info
win + R でファイル名を指定して実行を開きcmdと入力し決定で開くことができます。
:::

- プロファイル欄の規定値を選択し外観を選択
- 背景画面の項目で設定する
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3432230/f7e4c757-847a-8074-12ba-2879be73716e.png)
:::note info
Terminalの種類ごとに背景を変えたい場合は規定値を選択せず
変更したいTerminalを選択する
:::
HTMLの属性を、何となく使っていませんか？

## 学習したいと思ったきっかけ
要素の後に属性を指定したけど、どんな役割があるかを知りたかった。


## 属性を調べて分かったこと
①**要素は文章に意味を持たせる(マークアップをする)のに対し、属性は更に情報を追加したもの**

例えば、ハイパーリンクの機能を持つ&lt;a&gt;要素の場合

[before]
要素を指定しただけだと、ハイパーリンクの機能を持たない
```HTML
<a>Qiitaのホームページ</a>
```
![sample-html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568357/40de4472-76d1-f320-e4a5-e7139c3235fa.png)

[after]
そこに追加情報として、URLを指定するhref属性を付ければ、ハイパーリンクとして機能する
```HTML
<a href="https://qiita.com/">Qiitaのホームページ</a>
```
![sample-html (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568357/aa9768b9-00e5-b823-2962-1a2de12dea40.png)


## 属性は2種類あるのを知っていましたか？
①指定した要素のみ指定できる属性(名称はない)
URLを指定するhref属性は、限られた要素しか使えません。
使えるのは、&lt;a&gt;・&lt;area&gt;・&lt;base&gt;・&lt;link&gt;のみ！！

②どの要素でも指定できるグローバル属性
```HTML
<div class="container">
```
Webページの装飾としてよく使うclass属性とid属性は、どの要素にも指定することが出来ます！！
グローバル属性は他にもあるので、良かったら参考に
https://creatorquest.jp/reference/html/global-attributes/


## 属性を上手く活用するには
①要素を指定したら、追加したい情報が無いか確認してみる(大きさの変更など)
②リファレンスから使用目的に合う属性を探す(属性の種類は多いから、覚えようとすると苦労する)
偽gx.dll を作成して 当時の NP2 ARM版バイナリをそのまま動かす

# 概要
偽gx.dll を作成して、PocketPC用exeや、SigmarionIII用exeをそのままドライブする。

### Brain では HPC バイナリはそのまま動く
https://x.com/YATYATYAT1122/status/1708104643606454517

Brain では NP2 for HPC はそのまま動くとのことで:
- HPC は 純正の gx.dll を利用していない
- PPC や Sig3 では Microsoft 提供の gx.dll をリンクしている
って、動かない原因って gx.dll じゃね? 作ればよくね?

### GAPI (gx.dll) について
- PocketPC 用のゲーム特化したライブラリ
  - 具体的には フレームバッファ 1枚と キーパッドが利用可能になる

### NP2 for HPC が使っている 偽 gx.dll について
- 画面周りは GDI を利用する
- キーパッドは適当に割り振ってある

### 対応方針
- NP2 for HPC のソースを引っこ抜いて gx.dll を作成する
- それ以外は 当時のバイナリを利用する

# 偽 gx.dll で動かす版
- gx.dll ダウンロード
  - [nise-gapi-20231002.zip](https://yui.ne.jp/np2/bin/nise-gapi-20231002.zip) 10KB
- 動けばいいレベルな超テキトーな実装

## PocketPC 版(QVGA)を動かす
- Brain 1～2世代目向け
- 当時のバイナリをダウンロード
  - [np2ppc_081a.zip](https://yui.ne.jp/np2/bin/np2ppc_081a.zip) 361KB

1. Brain のルートに アプリ フォルダを作成
1. アプリ フォルダに 任意(ここでは NP2)フォルダを作成
1. nise-gapi-20231002.zip/gx.dll をコピーする
1. np2ppc_081a.zip/np2ppc/World/np2ppcw.exe をコピーする
1. np2ppcw.exe を AppMain.exe にリネームする
1. 0 バイトの index.din ファイルを作成する
1. BIOS.ROM や FONT.ROM をコピーする

![NP2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821068/2e76ba78-5558-34ce-d0a5-8ae89efafe38.png)

## SigmarionIII 版(VGA)を動かす
- Brain 3世代目向け
- 当時のバイナリをダウンロード
  - [np2sig3_081a.zip](https://yui.ne.jp/np2/bin/np2sig3_081a.zip) 402KB

1. Brain のルートに アプリ フォルダを作成
1. アプリ フォルダに 任意(ここでは NP2 VGA)フォルダを作成
1. nise-gapi-20231002.zip/gx.dll をコピーする
1. np2sig3_081a.zip/np2sig3/World/np2sig3w.exe をコピーする
1. np2sig3w.exe を AppMain.exe にリネームする
1. 0 バイトの AppMain.cfg ファイルを作成する
1. 0 バイトの index.din ファイルを作成する
1. BIOS.ROM や FONT.ROM をコピーする

![NP2VGA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821068/c6aa90a7-d6de-3857-3bae-af4afa2f1860.png)

## 実際に動かしてる動画
https://x.com/yuinejp/status/1708828006469530012


※マウスはたぶんサポートしてませぬ・・・
8th Wallで 動くBIOカードを作る(その２)

# この記事でやること
8th Wall で動くBIOカードを作成するための素材を準備します。
画像、動画作成の説明です。

# 8th Wallでの処理の流れ
BIOカードをカメラで撮影するときの動作を分解すると次のようになります。
1. 8th Wallの実行URLにスマホでアクセスする
1. カメラの動作権限が求められた場合、許可して続行する
1. ブラウザでカメラが起動した状態となる
1. カメラで特定の画像を読み取ると、「ターゲット」となる物体が「指定された画像」に差し変わる
1. 画面に映った画像をタッチすると「動画」に差し変わる

# 素材の準備
上記の処理を踏まえ、必要な素材は下記です。
### BIOカードの画像 (biocard01.jpg)
カメラでこの画像が写ったら、特定の動作を行う(今回は画像に差し替える)ためのターゲットになります。物理のカードの写真を利用する場合、きれいに動作させるためにカードに合わせて事前にトリミングしておきます。
### BIOカードをアニメーションさせた動画 (Movie01.mp4)
BIOカードに書かれた自画像・キャラクターをアニメーションさせます。ネタバラシになりますが、これは特殊なスキルは全く必要なくスマホのアプリできます。
### BIOカード認識時の画像 (thumbnail01.jpg)
カメラでターゲットのBIOを写したときに表示させる静止画です。BIOカードそのままの画像でもよいのですが、星やハートマークでも散らしたほうが、処理に動きがでます。
### 公開ページのサムネイル画像
公開時に指定するための1200px × 630px以上のサイズの画像を用意します。とりあえずペイントツールで上記サイズのキャンバスを作り、BIOカードの画像でも張り付けておくといいです。（手順説明は省略します。）

# アニメーションの作成
今回は Mug Life というアプリを利用します。これは顔の画像を自動認識して、しゃべっているかのような動画を作成するアプリです。

https://play.google.com/store/apps/details?id=com.muglife.muglife&hl=ja&gl=US

ポイントは下記です。
+ 基本は無料、自動認識した写真に決まったパターンの表情を適用することができる
+ 自動認識しないキャラクターや複雑な表情は有料機能で顔をマッピングする必要がある
+ 正面を向いた、人間の画像なら自動認識率が高い(アニメ顔は精度が落ちる)
というわけで、ブライアンローズ氏のBIOカードのように、思いっきり正面の自画像なら、かなりの精度で認識してくれます。

## 作成の流れ
１．写真をアプリにインポートします(自動認識すれば、この手順だけでOKです)
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/c7644ce1-62c4-c215-80b9-4e76e9bf201d.jpeg"></br>
２．自動認識しない場合は[作成]-[顔の追加]を選択する
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/000f49fd-3eeb-6da8-0569-2e4c21ecf930.png"></br>
３．顔のターゲットマークを近い位置にセットし決定する
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/bb2550c8-5d66-3bd6-77d2-9741627ff0d4.png"></br>
４．座標がマッピングされるので適正な位置にセットする
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/dd60932d-532b-fcb4-3477-258bf0fd229d.png">
５．表情をつけ、動画(mp4ファイル)に書きだします。

https://twitter.com/MinakuchiyaEnl/status/1708828703189544983?t=O4tHen3LmymHAt-zml7Uxw&s=19

## BIOカード認識時の画像の作成
これはとりあえず、元画像にちょっとマークをつけた画像を用意します。
元の画像をペイントで開いて適当に☆をつけて保存しました。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296487/14ab92c7-80f5-6c9d-a21b-0a6045d28adf.jpeg">

これで素材の準備ができましたので、次は8th Wallでカメラで読み込んだ時の処理を作成していきます。
(次の記事へ続く)

https://qiita.com/minakuchiya/items/33be5b48605552fbaac8
8th Wallで 動くBIOカードを作る(その１)

# この記事の目的
スマホゲーム IngressのBIOカードを 8th Wallを利用して、仮想的に動かしてみます。
BIOカードを持っている、非技術者向けの説明です。

# BIOカードとは
いきなり技術の話ではありませんが、BIOカードとは Niantic社が運営する位置情報ゲームIngressにおいて、エージェント(プレーヤー)が名刺代わりに作成するカードのことです。ゲーム自体はスマートフォンの中で展開しますが、ユーザー間のコミュニケーションが重要な要素となっており、ご挨拶がわりにカードをお渡しするというシーンをよく目にします。

BIOカードのフォーマットは次の通りです。
+ 縦89mm×幅63mm
+ 図面に決まりはないが、一応ゲーム公式の枠デザインがある（何世代かパターンがある）
+ 公式はキャラクターの絵が描かれているものが多い
というわけで、自分の好きな柄で作成すればいいのですが、

例としてNianticのゲームディレクターのブライアン・ローズ氏のカードを挙げます。

https://x.com/brianrose/status/1410055643600363521?s=20

# カードを動かすために
今回はプレーヤー(またはキャラクター)の自画像が印刷されたデザインのBIOカードを、スマホのカメラで撮影すると、動きだすように見えるアプリを作成します。
カメラと画像認識の仕組みに8th Wall を利用します。

次の手順は下記です。
1. BIOカードの画像を用意する
1. BIOカードが動く動画を作成する
1. BIOカードの画像、動画を8th Wall にアップロードする

# 8th Wall とは
8th WallはNiantic社が提供する、開発者向けのサービスです。
Webブラウザ上で動作するWebARを作成、共同作業、公開することができます。

https://www.8thwall.com/

アカウント作成から2週間の無償利用期間がありますので、その間にお試し利用が可能です。
※ただし、登録にクレジットが必要で、解約しないとそのまま継続利用になってしまう点に注意

本格的に利用する場合、個人向けプランでは月払い、年払いの２パターン選択できます。
+ 月払い $12
+ 年払い $108 `(月あたり$9)`

詳細は価格とプランのページをご参照ください。

https://www.8thwall.com/pricing

それでは、実際に作成をしてみましょう。

(次の記事へ続く)

https://qiita.com/minakuchiya/items/8d8b7a75bf70c4cba5c0
AppSheet のデータソースに Amazon DynamoDB を設定する最小手順

とりあえず、この程度まで作る手順

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/04159a02-cf63-b37e-097e-e820eae01495.png)

## Amazon DynamoDB

:::note info
リージョンは任意です
:::

### DynamoDB テーブルを作成

ここで使うリソース名例:

* テーブル名: `db_for_appsheet1`
    * パーティションキー: `pkey1`
    * カラム:
        * `c1_str` 文字列
        * `c2_num` 数値

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/d27129c7-1d7f-b175-23af-3f9884999a31.png)

### モックデータの投入

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/0517df94-509d-de1b-78f0-73b4c54e4818.png)

モックデータを入れておくと、AppSheet のデータソース生成時に自動的にカラム属性を推測して設定してくれます。1アイテムだけ作ります。投入予定のデータを入れておくと良いでしょう。

## AWS IAM

:::note warn
AppSheet は、IAM ロール認証に非対応です (2023年10月時点)
:::

ここで使うリソース名例:

* IAM ポリシー名: `access_for_appsheet1`
* IAM ユーザー名: `accessuser_for_appsheet1`

### IAM ポリシーの作成

```json:access_for_appsheet1
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "dynamodb:ListTables",
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "dynamodb:PutItem",
                "dynamodb:DeleteItem",
                "dynamodb:Scan",
                "dynamodb:Query",
                "dynamodb:UpdateItem"
            ],
            "Resource": "arn:aws:dynamodb:*:*:table/db_for_appsheet1"
        }
    ]
}
```

* Resource の `table/db_for_appsheet1` は `table/*` として広い範囲の設定も可能ですが、限定化することをオススメします。

### IAM ユーザー作成

* ユーザー名: `accessuser_for_appsheet1`
* 許可ポリシー: `access_for_appsheet1`

#### アクセスキーを作成

* ユースケース > サードパーティーサービス
* 説明タグ値: 任意ですが `for_appsheet` あたりにしておくと良いでしょう

作成されたアクセスキーとシークレットアクセスキーは、必ずメモしてください。

## AppSheet

ここで使用するリソース名例:

* App name: `Amazon DynamoDB App1`

### アプリケーション作成

* [Home](https://www.appsheet.com/home/apps) -> Create -> App -> Start with existing date
* Select data source -> New source
    * Cloud Database
        * Type: `DynamoDB`
        * AWS region: `db_for_appsheet1` が存在するリージョンを選択
        * S3 bucket: `not_exists_s3_bucket`
        * Access key id: 先ほど作成したアクセスキー
        * Secret key: 先ほど作成したシークレットアクセスキー
        * -> Test -> 成功すると "Authorized Access" ボタンが有効化される > Authorized Access -> Homeに戻る

* S3 bucket はアクセスチェックは行いません。存在しないバケット名を指定してもTestは通過します (AppSheet 上で画像を扱いたい場合は存在するバケット、かつ適切なポリシーをの設定が不可欠です)

* [Home](https://www.appsheet.com/home/apps) -> Create -> App -> Start with existing date
* Select data source -> Cloud Database
    * Tables -> `db_for_appsheet1`

これで、Amazon DynamoDB テーブルから既存データを読み込み、カラム属性を自動的に設定した踏み台的な AppSheet アプリケーションが生成されます。


## この後

* Datasource 削除: https://www.appsheet.com/Account/Account/Sources
* 一時的なアクセス断: a.IAM ユーザーの当該アクセスキーを無効化 b.IAM ポリシーの変更
* DynamoDB テーブルへのカラム追加: DynamoDB テーブルへモックデータを追加後(モックデータのみとなるようにする)、AppSheet で Regenerate すると再読み込み→再構築をしてくれる

EoT
Docker基礎学習

Dockerについて学習した事をアウトプットしていきます。


参考講座：Udemy「駆け出しエンジニアのためのDocker入門」

- コンテナとは？
隔離されパッケージ化された箱の事であり、サーバー上に隔離されたアプリ空間を作れる技術。
サーバー上にパッケージ化されたソフトウェアが何個も並ぶような構造を作れる。
Linuxサーバー上に直接ソフトウェアのコンテナが立ち上がる。
ホストOS、ゲストOSの区切りがない。
メモリ上にアプリケーションが存在している。

- 仮想化とは？
パソコンの中に仮想パソコンを起動する技術。
例）windowsPCにLinuxサーバーを立てる
ホストOS→元のパソコン、ゲストOS→ホストOSに立てられたサーバー
ゲストOSはHDDに存在する。

- Dockerとは？
Linuxサーバー上でコンテナを管理するためのツール。
Dockerfileでコード化したインフラを管理できる。
→Docker file（設計書）を読むとどういったインフラの構成が分かり、誰でも同じコンテナが作れる。
テキストファイルなので容量が軽く、受渡しが簡単に。
　
・Docker file（イメージを言語化したもの）
　　↓build
　Docker image（設計図）
　　↓run
　Dockerコンテナ（一つのプロセスを入れる箱）

※Docker hubからイメージをダウンロードする方法もある。


- Docker image
 レイヤー構造のまとまり。
（一番下はLinux OS　→　一つ一つイメージレイヤーを乗せていく。）
 ・Docker imageのタグ　→　Docker imageのバージョンを指定するもの。

- Dockerコンポーズ→複数のコンテナを管理、連携させることができる。
 リンクオプションを使うことによって連携が可能に。

- コマンド
・docker run：dockerコンテナ一つを起動するコマンド
ローカルに「docker image」がない時は「docker hub」から自動で取得してくれる。
・docker run --name 命名したいコンテナ名 コンテナ名：指定したコンテナ名を付けてコンテナを起動できる。
・docker ps：起動中のコンテナを表示するコマンド
※停止中のコンテナも見たい場合は　-a　オプションを付ける。
[学習メモ] 　Java　クラス継承の注意点（子クラスのコンストラクタ）

Javaのクラスを作る上で、継承で出来ることと出来ないことがわかってきたのでまとめ。
今日は継承とコンストラクタ。
（学習中のメモなので随時更新予定。）
# 子クラスのコンストラクタでエラー
継承で子クラスを作る際、以下のようなコードでなぜかエラーが出ました。
```
class Cat{
    String name;

    Cat(String s){
        name = s;
    }
}

class Lion extends  Cat{
}
```
一見問題無さそう(Lionクラスの存在意味がないことを除けば）に見えますが、これだとエラーが出ます。（error: constructor Cat in class Cat cannot be applied to given types...）
無論、Lionにてコンストラクタを記述していないからではありません。コンストラクタは記述されていなけい場合、暗黙的に「何もしない」コンストラクタを呼び出し、実行してくれることになっています。<br>

# 原因
では何がいけないかというと、理由は以下の２つです。
- **子クラスのコンストラクタでは、デフォルトでは（やはり暗黙のうちに）親クラスの引数なしコンストラクターをまず実行することになっている**から。<br><br>
- **コンストラクタを明記した場合、もともと用意されている「何もしない」引数なしコンストラクタは、上書きされて無くなってしまう**から。<br>
例えば、

```
class Cat{
    String name;    
}

class Tiger extends Cat{
    Tiger(){
        System.out.println("ガルルルルァ！");
    }
}
```
上記のようなコードでも、実はTigerクラスのインスタンスが作られた時には、System.out...の前に、親クラスCatの（何もしない）コンストラクタが実行されています。<br>
しかし、
```
class Cat{
    String name;

    Cat(String s){
        System.out.println(s);
    }
    
}

class Lion extends Cat{

    Lion(){
        System.out.println("ガルルルルァ！");
    }
}
```
このように Catに引数有りのコンストラクタを書いてしまうと、元々用意されていた引数"無し"の何もしない暗黙コンストラクタは上書きされて無くなってしまいます。その為 Cat には、引数なしのコンストラクタが存在しない状態となります。

ですが上記のように、子クラスのコンストラクタにおいては、デフォルトでは、親クラスの引数なしコンストラクタが実行されることになっています。よって必要なものが存在しない為、エラーが出ることとなります。

# 対策
では、冒頭のコードでエラーを出ないようにするには、どのようにしたらいいのでしょうか。それは、**子クラスにコンストラクタを記述し、その中で親クラスの**（引数なしではなく）**引数ありのコンストラクタを実行するよう明記**することです。<br>
以下のように書きます。
```
class Cat{
    String name;

    Cat(String s){
        name = s;
    }
}

class Lion extends Cat{
    Lion(String s){
        super(s);
    }
}
```
これで、意図を変えないままにエラーを回避できます。

# まとめ
**親クラスが引数有りコンストラクタ（のみ）の場合は、めんどくさがらずに子クラスにもコンストラクタを書こう！**（そして親クラスの引数有りコンストラクタを実行）
SwiftDataのsortとfilterを使ってみた

# はじめに

先日、ハッカソンに参加したときに、**SwiftData**を用いてデータを扱ってみました。

[SwiftDataとは？](https://developer.apple.com/jp/whats-new/#:~:text=SwiftData,%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%81%AF%E5%BF%85%E8%A6%81%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82)

そのとき利用した`sort`と`filter`の使い方について、備忘録として記録しておきます。

## 参考

**SwiftData**の使い方は[こちら](https://qiita.com/Ri__/items/0c46c432b2e873ceeb04)の記事を参考にさせていただきました！
基本的な使い方はこちらの記事を読んでいただけるとわかるかなと思います。

https://qiita.com/Ri__/items/0c46c432b2e873ceeb04

また、同じく参考にしたページをいくつか載せておきます。

https://developer.apple.com/documentation/swiftdata/query(filter:sort:order:transaction:)-8tk8u

https://www.swiftyplace.com/blog/fetch-and-filter-in-swiftdata

https://stackoverflow.com/questions/76453130/changing-sort-in-swiftdata


## 準備(データの型を作成)

今回は、次のようなclassを作成してみます。

```swift:DataModels.swift
import Foundation
import SwiftData

@Model
class Task {
    var name: String // タスク名
    var isDone: Bool // 終わったかどうか
    let time: Date // 時間

    init(name: String, time: Date) {
        self.name = name
        isDone = false
        self.time = time
    }
}
```
また、SwiftDataを使用してデータを出し入れするために`context`を宣言し、データベースから取得したいデータのプロパティの前に`@Query`を付与します。

```swift:ContentView.swift
import SwiftUI
import SwiftData

struct ContentView: View {
    
    @Environment(\.modelContext) private var context
    @Query private var tasks: [Task]

    // ...
}
```


# タスクをリストで表示してみる

今回は、予定名と時間を設定し、追加ボタンを押すことでタスクをリスト表示するようにしました。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285857/d864a5f4-4e6b-378e-da10-e38d2dae3e40.gif">


追加ボタンを押すとタスクが1番下に追加されていくのがわかると思います。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285857/044272a8-0a70-9729-97ee-b09aef95e9b6.png">

このようにタスクを追加してみました。

## 時間順に並び替えたい

### やり方

```swift:ContentView.swift
@Query(sort: \Task.time) private var tasks: [Task]
```
このように直すだけ。
これだけでリストが時間順に並び替えられました。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285857/8e44d4e0-6cf4-2f22-3402-b253bc9e523d.png">

## タスク名で絞り込みたい

### やり方

```swift:ContentView.swift
@Query(filter: #Predicate<Task> { $0.name == "授業" }) var tasks: [Task]
```
このように直すだけ。
今回は「授業」というタスク名のものに絞り込みました。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285857/0fbb07dc-9c90-fa30-d7d7-4fe7d34e6376.png">

## タスク名で絞り込んで、さらに時間順に並べ替えたい

### やり方

```swift:ContentView.swift
@Query(filter: #Predicate<Task> { $0.name == "授業" }, sort: \Task.time) var tasks: [Task]
```
このように直すだけ。
「授業」というタスク名のものだけに絞り込まれており、時間順に並べ替えられています。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3285857/bd1421c7-184d-8987-d18f-6e809cfdb9ca.png">

# おわりに

初めてのハッカソンだったので、SwiftDataをうまく使えるか不安でしたが、**導入が簡単**かつ**直感的で使い勝手が良く**、**データ取得用の処理を書く必要がなかった**ことも良かったです！

まだまだ触り始めたばかりなので、今後も引き続き勉強していきたいと思います！

最後に、今回記事用に作成したデモのコードを載せておきます。

https://github.com/y-ma3/try-swiftdata/tree/main/TrySwiftData

最後まで見ていただき、ありがとうございました！🎣
メーカー(HP)製のPCのマザーボードと電源を交換した

## 背景
・メーカー(HP)製PCにグラボを挿してValorantで遊んでいたところ、よくブルースクリーンが出るようになった
・ブルースクリーンが出てないときの動作はいたって普通なので、GPUやCPUの異常ではなさそう
・電源が250W(!?)しかないのでここが怪しいが、**HPのPCは電源供給周りが独自規格なので交換できない** (つらい)
　→ケースとマザボと電源を替えるしかない


同じことを企む人向けの記事です。


## 元のPC: HP EliteDesk G5 SFF
・Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz  8 Core(第9世代)
・Windows10
・独自規格マザーボード
・独自規格電源 (250W)




## 買ったもの
・マザーボード: ASRock Z390 Pro4 (第8/9世代CPUが挿せるやつを探した。中古のマザボって高いんですね)
・電源: 玄人志向 KRPW-BKシリーズ 80PLUS Bronze 650W ATX
・CPUファン: Deepcool AK620 (グリスもついてきた)
・PCケース: てきとう



## 準備


### Microsoftアカウントにする
引き続きWindows10(11)を使いたいので、認証がオンラインで行えるようにMicrosoftアカウントに切り替えます。
調べればすぐわかります。

ログインパスワードも控えておく必要があります。普段PINを使っている人は忘れていると思うので注意。
そして、**ネットワークにつながった状態でそのアカウントにログインする操作を一回行います。**
(あとで「端末で最後に利用されたログインパスワード」を入力する機会があります)


### Bitlocker回復キーをメモするorBitlockerをオフにする
普段意識することはないですが、マザーボードが変わった後は回復キーを起動時に求められるようになるので、BitlockerがONになっている場合は回復キーをメモするか切っておきます。毎回入力するのは面倒なので自分は切りました。
これも調べればやり方は出てきます。


### グラボのドライバはアンインストール
ハードウェア構成を変えるのでいったん消しておきます。そのまま移行するとうまく動かない可能性があります。

## 流れ
普通の自作PCと同じなので、CPU＋ファン、メモリ、電源、SSD、HDDを好きな順番でつければいいです。
・上記パーツを組み立てる 
・起動(回復キーやらを聞かれます)
・いったん終了後グラボを挿し、ドライバの再設定


## 結果
全然ブルースクリーンが出なくなった！うまくいきました。



### スタックしそうなポイント
・Microsoftアカウントにするのを忘れる
・グラボを挿した状態ではBIOSが起動しない/映らない
　・挿さない状態でBIOS設定→プライマリのビデオカードを使用するオンボードにする→それで起動するならグラボを再設定する
　・CMOSをリセットしてみる
　・BIOSをアップデートしてみる


## 感想
・思ったより簡単だった
・めっちゃ静かになった(ファンの性能)
・いじるなら元からBTO買っておけよという気もする

そこそこのスペックで企業レンタル落ちということで安く買ったPCですが、まだまだ遊べそうです。
システム開発プロセス/開発モデル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/659080c0-8ac2-2d46-8ab2-9ea9a164e1cb.png)
　システムの規模が大きくなるにつれて、手当たり次第にシステムを作り上げることは困難になり、システム開発の体型立てた枠組みが必要になりました。このような枠組みとして、JIS X０１６０：２０２１で定めているソフトウェアライフサイクルプロセスや共通フレームがあります。いずれも、システムの構想から開発、運用、保守、廃棄までまでの各段階で、どのような作業が必要か、作業の役割は何かを規定した「ITシステム開発の作業規定」とも言える枠組みです。
　また、これらの枠組み以外にも、システム開発工程の流れを標準化した開発モデルがあります。代表的な開発モデルとして、ウォータフォールモデル、スパイラルモデル、プロトタイプモデルがあります。

１：ソフトウェアライフサイクルプロセス　
　ソフトウェアライフサイクルプロセスとは、システムの構想段階から、システムを引退させる段階までにおいて、ソフトウェアをどのように設計し、開発して、保守するのかという過程を体系立ててまとめたものです。JIS X０１６０：２０２１という規格で定めています。

　ソフトウェアライフサイクルプロセスは、以下のようになります。
①システム要件定義　ソフトウェア要件定義：システム全体やシステムを実現するソフトウェアについて、機能要件や非機能要件を定義する。

②システム設計：システムの機能をハードウェア、ソフトウェア、サービスなどに分割し、システムの処理方式を決定する。

③ソフトウェア設計：ソフトウェアを構成する部品（モジュール）とソフトウェアの構造を設計する。

④実装・構築：ソフトウェアを構成する部品（モジュール）をプログラミング（コーディング）する。作成したプログラムが、単体として、正しく動作するかをテストする。このようなテストは、単体テスト（ユニットテスト）という。

⑤結合・テスト：ソフトウェアを構成する部品（モジュール）が、正しく連携して動作することを確認するために、結合テストを実施する。また、システムが仕様を満たしていることを確認するために、検証テストを実施する。

⑥導入・受け入れ支援：システムを運用環境に導入して、運用環境下でユーザの意図通りにシステムが動作することを確認するために妥当性確認テスト（受け入れテスト）を実施する。いわゆる、試運転である。

⑦保守・廃棄：機能追加、性能向上、バグ修正などのシステムの保守作業を行う。使わなくなったシステムを廃棄する。

機能要件とは、システムやソフトウェアが備えるべき機能をまとめた要件です。非機能要検討は、機能要件以外のすべての要件のことです。日機能要件として代表的なものに、性能（スループットやレスポンスタイムなど）、信頼性（稼働率や故障率など）、セキュリティレベルがあります。
テクノロジーレーダーを初めて知った話

教えていただいたサイトで面白かったものをメモとして残しておくシリーズです。
今回はテクノロジーレーダーについて。

- 本家(多分)(English)
https://www.thoughtworks.com/radar

- 読み方について分かりやすく説明してくださっているサイト様
https://zenn.dev/miyataka/articles/technology-radar-vol-27

新しい技術についてどこで情報を仕入れているんだろうなーと常々疑問に思っていました。
その答えの一端がこんなところに。
ざーっと見ているだけでも面白いですね。評価付きで説得力があるのも素晴らしい。
ビジネスロジックそのもの、複雑なロジック処理はどんな風に設計してますか？

# はじめに
いまどきのシステムエンジニアさんって、複雑なロジック処理はどんな風に設計してるんだろうということが気になりだしたので、とりあえずQiitaユーザーさんの何割くらいが下記に述べておりますシステムエンジニアさんに該当するのかはわからないのですが、とりあえず聞いてみよう。

## 対象読者
システムエンジニアさん。エンベデッド系やネットワーク・インフラエンジニアもシステムエンジニアさんですが、狭くは業務系システムの設計に携わる方がいいな。

# ロジック処理の設計標準化とは
私の個人的な経験をつらつらと述べて、こんな感じなんですけどどうでしょうでは、もしかしたら相手にされないかもしれませんので、わりと先進的と思われた下記のThink ITさんの記事を題材に考えてみてほしいと思っています。

https://thinkit.co.jp/article/17556

# 要約
リンク先の記事をじっくり読んでいただくことが望ましいですが、そんな時間というかこの記事のお題にそんなにつきあってられないよという方は下記の要約だけでも読んで参加してください。
>- **ロジック処理のフォーマット**：設計書作成CAD「SI Object Browser Designer (OBDZ)」を例に、ロジック処理を記述する標準フォーマットについて解説する。
>- **モジュール化の重要性**：ソフトウェアを小さな部品に分割し、独立した形で扱えるようにすることで、メンテナンス容易で共通化できるなどのメリットを説明する。
>- **オブジェクト指向との関係**：モジュール化はソフトウェア設計の基本的な大原則であり、オブジェクト指向はそれを実現する1つの手法であることを示す。
>- **ロジック定義の具体例**：CADツールで作成したロジック一覧画面やロジック定義画面を用いて、ロジックの基本情報、概要、履歴、インターフェース、アクション、処理内容、メッセージなどを定義する方法を紹介する。

という感じの内容です。SIOBDZなかなかすごそうなツールです。CADとはコンピュータが支援する設計環境のことなので、当然このようなツールをCADと呼ぶことに異論はまったくございません。ただ、昔ハードウェアエンジニアとしてメカCADやECADを使った感覚では、ソフトウエア設計のCADってだいぶイメージが違うなという印象はぬぐえないです。

# ロジックの中身の書き方

これは記事本文からの引用になります。
>また、処理内容には箇条書きフォーマットを用意しますが、複雑なものは自由記述で記載するしかないこと

ここです。ロジック定義画面というのがあるのですが、えっそうなんだ！？というのが率直な感想です。

実際のところ、Excelとかでやられている現場も恐らくけっこう少なくないと思われる中で、この記事で紹介されている設計活動は、いろいろな設計成果物や帳票、データシートを一つのシステムの中に集約統合していらっしゃるので、かなりすごい！という感じです。もちろん。

しかし、やっぱりそうなのかーという確信めいたものを感じてしまいました。

# 検討課題

それはDDDでこんな風にアーキテクチャ考えてますよとか、というよりは、賞味、システム化対象の業務の中で、非常にめんどい処理が要求されたとき、みなさんはどんな風にその処理内容を設計されているのかなあというところです。

つまり、いわゆるビジネスロジックとも呼ばれる業務的なロジックそのものをどうやって設計しているかということです。

ビジネスロジックとその他の機能要素、非機能要素をどのように構造化するかということはこの記事の主題ではありません。

# おわりに

ぜひ、みなさまのコメントでご紹介をお願いいたします。すごく気長にまっています。この記事の投稿日が１年前になってコメントがらがらであっても、たぶん私はQiitaにいます。その近い将来、こんな古い記事にコメントしても返事つかないよなとか思われるかもしれませんが、たぶんだいじょうです。気長にいろいろやっております。

# 2023/10/19 追記

@kazuo_reveさんの記事[^1]　への質問コメントで、「内部仕様」「ビジネスロジックのアルゴリズム記述」という単語の解釈が問題になったので、補足のコメントを返させていただきましたが、本記事にも関係しますのでその内容を転記しておきます。

>とりあえず「ビジネスロジック」とはビジネス（仕事・業務）上の作業のルール・手順をソフトウェアに置き換えたものまたは置き換えようとするものとさせてください。
「ビジネスロジックのアルゴリズム記述」とは、ソフトウェアに置き換えられた状態の構造化された手続きの記述のことを意味して使っておりました。
よく想定されるバックエンドのAPIコントローラを例にとりますと、コントローラ内での着信制御と戻り制御と、正味のロジックとの間に境界があるなしはとりあえず問わず、APIコントローラへのリクエストパラメータの仕様とレスポンスパラメータの仕様だけが決まっている状態を「外部仕様」または「要求仕様」（の一部）、正味のロジックの詳細が「内部仕様」という意味です。
>
>　要求：ビジネスロジックの概要（ルール・作業マニュアル）
　要求仕様：ビジネスロジックのインターフェースの取り決め
　内部仕様：ビジネスロジックの実現方法詳細
>
>というイメージが私の中では想起されておりまして、

本記事での「ビジネスロジック」もそのような意味で運用しています。

[^1]: Qiita [USDMに対するひと工夫](https://qiita.com/kazuo_reve/items/989274a57fcb9b54ab6f#comment-a77dbeaa26c369c38566) 参照
テストのアンチパターン議論スレッド

教えていただいたサイトで面白かったものをメモとして残しておくシリーズです。
今回はテストのアンチパターンについて。

- 元スレ(English)
https://stackoverflow.com/questions/333682/unit-testing-anti-patterns-catalogue

- 有志による日本語訳
https://joker1007.hatenablog.com/entry/20130709/1373365053
私は英語に弱い人間なのでこちらのサイト様は本当にありがたかったです。
日本語に訳しただけでなく、パターンの名称の訳し方も的確で面白い。
あるあるなパターンだな～と頷きながら、面白名称に笑いながら読み進めることが出来ます。楽しみながら知識を増やしたい人におすすめ。
5pin のロータリーエンコーダ

- 概要
格安(Amazonで¥200くらい)の、5ピンのプッシュスイッチ付きロータリーエンコーダについてのメモ。

    - ボード実装

        - 3ピン側
ロータリーエンコーダとして扱う。
ピン配置は真ん中をGNDに、左右をA,Bに接続する。

        - 2ピン側
プッシュスイッチとして扱う。
5vとGNDはどちらでもよい。


    - Arduino Leonardo

ロータリーエンコーダは割り込み、プッシュスイッチは周期的にチェックする。
Arduino Leonardoの割り込みは、0, 1, 2, 3, 7のピンのみが可能。


```
#define PIN_ROTARY_A 3
#define PIN_ROTARY_B 7
#define PIN_PUSH 15
static const int rotaryPtn[] = {0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0, 0};

bool prevRotaryA = false;
bool prevRotaryB = false;
int count = 0;
char prbuf[50];

void setup() {
  pinMode(PIN_PUSH, INPUT);

  pinMode(PIN_ROTARY_A, INPUT_PULLUP);
  pinMode(PIN_ROTARY_B, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_ROTARY_A), count_rotary, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_ROTARY_B), count_rotary, CHANGE);

  Serial.begin(9600);
}

void loop() {
  sprintf(prbuf, "count:%d, push:%d", count, is_push());
  Serial.println(prbuf);
  delay(10);
}

void count_rotary() {
  bool rotaryA, rotaryB;
  int ptn;
  rotaryA = digitalRead(PIN_ROTARY_A);
  rotaryB = digitalRead(PIN_ROTARY_B);
  
  ptn = 0x0f & (prevRotaryA << 3 | prevRotaryB << 2 | rotaryA << 1 | rotaryB);

  switch(rotaryPtn[ptn]){
    case -1:
      count++;
      break;
    case 1:
      count--;
      break;
    default:
      break;
  }

  prevRotaryA = rotaryA;
  prevRotaryB = rotaryB;
}

bool is_push(){
  return !digitalRead(PIN_PUSH);
}
```
Flutter　環境構築　エラー　

久しぶりにFlutterを使おうとしたらうまくいかなかったので、環境をチェックしたところ、エラーがたくさん出てきました。
今後同じようなことがあったときのためにエラーと解決策をメモしました。

## 環境
windows10
visual studio 2019 16.11.21

## エラー
flutter doctorを実行した結果、このようなエラーが出てきました。
エラーは三つありました。一つずつ見ています。
![スクリーンショット 2023-10-02 092907.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568691/10c60c35-2133-f291-8f1e-58f60640be7d.png)


### 1.「cmdline-tools component」
1つ目のエラーが「Android Studio」に「cmdline-tools component」がインストールされていないために発生するエラーでした。
まず「Android Studio」を起動します。
File→Settings→Appearance→language&Frameworks→Android SDK→SDK Toolsタブ
「Android SDK Command-line Tools (latest)」にチェックしてインストールします。
>参考記事
>https://zenn.dev/imasaka0909/articles/00ebfaf74f9cea


### 2.「Visual Studio is missing necessary components」
「Visual studio installer」で以下の必要なワークロードをインストールする必要があります。
・Desktopdevelopment with C++
・MSVC v142 - VS 2019 C++ x64/x86 build tools
・C++ CMake tools for Windows
・Windows 10 SDK

まずは「Desktopdevelopment with C++」からインストールします。
変更→ワークロード→「c++によるデスクトップ開発」をチェックし、インストールします。

残りのワークロードは
変更→個別のコンポーネントからそれぞれを検索し、
最新版にチェックし、インストールしました。
「C++ CMake tools for Windows」は「Windows 用 C++ Cmake ツール」と検索したら出てきます。


### 3.「Unable to find bundled Java version.」
調べたところMacでの解決策は多く出たのですが、Windowsの記事は少なかったのでこちらの記事がとても参考になりました。

>参考記事
>https://flying-birds.net/post-227/

他にもFlutterのバージョンが違うことによるエラーなどが原因の方もいるみたいでした。

### 4.再度flutter doctorを実行した結果
・FlutterのUpgrade
・Android のライセンスが受け入れられていない。
と警告されました。

まずはFlutterが古いバージョンだったので、アップデート。
安定版の最新をインストールしました。

Android のライセンスは
「flutter doctor --android-licenses」と実行すれば規約が出てくるので、同意することで無事に解決しました。
VueでFirebaseを始めよう！

# VueでFirebaseを始めよう！①

ちょっとしたことを毎日残す100日チャレンジ　１日目

### firebaseをVueで使うためのconfigとか、定義はどこに配置するのか

```typescript:src/main.ts

import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: "",
};

export const firebaseapp = initializeApp(firebaseConfig);
export const auth = getAuth(firebaseapp);
```

### ほかのファイルからの読み込み

```typescript
import { firebase, auth } from "../../main"; // main.tsへの相対パス
```
Renderデプロイ時の! Unable to load application: ArgumentError: Missing `secret_key_base` エラーの対処法

# 概要
個人開発の際Renderでデプロイしようとしたところ
```ruby 
! Unable to load application: ArgumentError: Missing secret_key_base for 'production' environment, set this string with bin/rails credentials:edit`
```
というエラーが発生し苦戦したので備忘録として残しておきます。
※初学者で知識に乏しいため誤った記述があればコメントいただけると幸いです。
## secret_key_baseとは
Railsのアプリケーションでは、``secret_key_base``というシークレットキーが必要です。これは、暗号化やセッションの検証など、さまざまなセキュリティ関連のタスクで使用されます。production環境で、このキーが設定されていないことが原因で今回のエラーが発生しました。
## 対処方法
対処方法は簡単です。
ローカル環境で、以下のコマンドを実行してRailsのクレデンシャルを編集します。
```ruby:bash
bin/rails credentials:edit
```
このコマンドを実行すると、エディタが開きます。

secret_key_base を設定
クレデンシャルのエディタが開いたら、secret_key_baseの値を設定します。

```ruby:yml
production:
  secret_key_base: YOUR_SECRET_KEY_BASE
```
YOUR_SECRET_KEY_BASEは、適切なシークレットキーの値に置き換えてください。

#### ``シークレットキー``の生成方法について
1.Railsのコマンドを使用してキーを生成

以下のコマンドを実行して新しいsecret_key_baseを生成します。
```ruby:
rails secret
```
このコマンドで、ランダムな文字列を出力できます。この文字列を新しいsecret_key_baseの値として使用します。

2.生成されたキーをクレデンシャルに設定
``bin/rails credentials:edit``を実行してクレデンシャルを編集し、先ほど生成したキーをsecret_key_baseの値として設定します。

```ruby:yml
production:
  secret_key_base: [生成されたキー]
```
これで、適切なsecret_key_baseの値がクレデンシャルに設定されます。
変更を保存(:wq)してエディタを終了(:wq!)します。

再度デプロイ
上記の変更を行った後、再度Renderへのデプロイを試みます。
Python で日本語コード判定

# はじめに

　今更かもしれないが、Python で日本語の文字コード（エンコーディング）を判定する方法について。

　最近必要になってググってみると `chardet` を使って判定する記事が多い。「じゃあ……」と思って使ってみたが、どうもうまくいかない。

　というわけで、自分でこしらえてみた、という話。

# コード

　前提として、自分の場合、日本語と ASCII くらいしか想定していない（つまり他の国特有のコードを想定していない）、ということがある。

```python:jp.py
# -*- coding: utf-8 -*-
JP_ENCODE = 'iso2022_jp', 'euc-jp', 'shift-jis', 'cp932', 'utf-8'


def decode(buf):
    for c in JP_ENCODE:
        try:
            r = buf.decode(c)  # まず decode してみる
            try:
                r.encode('ascii')  # ascii で encode できたら、それは ascii
                return r, 'ascii'
            except UnicodeEncodeError:
                return r, c  # ダメなら c を返す
        except UnicodeDecodeError:
            pass
    return str(buf), ''  # 最後のあがき(w


if __name__ == '__main__':
    import chardet
    text = 'これはひらがなと漢字だけ。片仮名があると違うんだろう。たぶん'
    # text = 'これはひらがなと漢字だけ。カタカナがあると違うんだろう。たぶん'
    # text = 'これはひらがなと漢字だけ。①があると違うんだろう。たぶん'
    # text = 'This is ascii only, abcABC012()[]_@#$'
    for c in JP_ENCODE:
        try:
            buf = text.encode(c)
        except UnicodeEncodeError:
            print(c, '... skip')
            continue
        print(c)
        print(decode(buf))
        print(chardet.detect(buf))
        print()
```

# テスト

```shell-session:実行
$ python -V
Python 3.10.6
$ pip list | grep char
chardet           5.2.0
$ python jp.py
iso2022_jp
('これはひらがなと漢字だけ。片仮名があると違うんだろう。たぶん', 'iso2022_jp')
{'encoding': 'ISO-2022-JP', 'confidence': 0.99, 'language': 'Japanese'}

euc-jp
('これはひらがなと漢字だけ。片仮名があると違うんだろう。たぶん', 'euc-jp')
{'encoding': 'EUC-JP', 'confidence': 1.0, 'language': 'Japanese'}

shift-jis
('これはひらがなと漢字だけ。片仮名があると違うんだろう。たぶん', 'shift-jis')
{'encoding': None, 'confidence': 0.0, 'language': None}

cp932
('これはひらがなと漢字だけ。片仮名があると違うんだろう。たぶん', 'shift-jis')
{'encoding': None, 'confidence': 0.0, 'language': None}

utf-8
('これはひらがなと漢字だけ。片仮名があると違うんだろう。たぶん', 'utf-8')
{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
```

　ひらがなと漢字しか無いような shift-jis/cp932 のテキストは、`chardet` としては難しいらしい。

　関数 `decode` も、shift-jis と cp932 の区別は、特定の文字が入っていないこのテキストでは流石に難しい（というか無理）なんで、そこはご愛嬌。

# 終わりに

　この方法がベストプラクティスだ、とか言うつもりはない。
　前述もしたが、前提として自分が必要としたのは一般的に使われているであろう日本語エンコーディングだけ。それだけに特化した手法とそれ以外も想定している手法では、前提が違うのだから公平な比較にならない。
　それだけはここに重ねて追記しておく。
今更AWS編 (1-1 リージョンとアベイラビリティゾーン)

### ①AWSグローバルインフラストラクチャとは
・AWSが提供するクラウドサービスを稼働させる為の物理的な設備
・世界中に分散されたリージョン/アベイラビティゾーン/エッジロケーション/ローカルゾーン/それらを繋ぐネットワークによる網構成要素の総称。
### ②リージョンとは
・AWSサービスを提供している国や地域等の拠点の事。
・リージョン同士はそれぞれ地理的に離れた場所に配置されている。
### ③アベイラビリティゾーン(AZ)とは
・リージョンを構成する為の、細分化されたデータセンター(DC)の集合体の総称。
・複数のDCがAZを構成し、複数のAZで構成されている物がリージョン。
### ④アベイラビリティゾーンによる信頼性の向上
・AZは地理的・電源的に独立した場所に配置及び稼働している為、落雷や洪水などの自然災害によるAZへの局所的な障害に対して別のAZが影響されないようになっている。
・AZ間では距離的に数十キロ単位で離れて配置されているが、各AZ間では高速なネットワーク回線で接続されている為、ネットワーク遅延(レイテンシー)の問題が発生する事はほぼ無い。
### ⑤マルチAZによる可溶性の向上
・システム構築の可用性を高めるには、複数のAZを利用してシステム構築するのが基本。これをマルチAZと呼ぶ。
・ユーザー側が単一AZのみでシステム構築をした場合、単体のデータセンターにオンプレミスでのシステムを構築したケースと対障害性はそれほど変わらない。
・EC2(仮想サーバー)やRDS(データベース)などのインスタンスベースのサービスは、可用性を高める際には、マルチAZ内のに配置する冗長構成が基本となる。
### ⑥エッジロケーションとは
・ユーザー側が低レイテンシーで高速なコンテンツ配信を実現する為に設計されたAWSが提供するサービスの総称。グローバルインフラストラクチャの一部であり、実態としては世界中に配置された物理的なデータセンター群。
・エッジロケーション同士がAWSネットワークに接続されており、ユーザー側のリクエストに応じて最も近いエッジロケーションで処理される為、高速なレスポンスを返す事が可能。
・エッジロケーションのサービス例　
**Amazon Cloud Front**
→コンテンツデリバリネットワーク(CDN) Webコンテンツを低レイテンシーで高速配信するサービス。
**Lambda@Edge**
→Cloud Frontに統合された機能　ユーザーに距離的に近いCloud Frontにてプログラムコードを実行するサービス。
### ⑥AWS Local ZONEとAWS Outpostsについて
・ユーザーから近い場所でEC2・EBS・RDS等のコンピューターリソースを利用する為のサービス総称。
・**AWS Local ZONE**はAWSとオンプレミス間をより低いレイテンシーで結び付け(**特定リージョンの拡張/細分化**)、高速処理を実現する。
・AWS Local ZONEの例 
AWS上のオレゴン(米国西部)リージョンの表記名は「us-west-2」
上記リージョンの拡張である、ロサンゼルスのLocal ZONEの表記名は「us-west-2-lax-1a」
・**AWS Outposts**はAWSサービスをオンプレミス環境で実行する為のサービス。
・サービスと契約すると物理サーバーやラックがAWS社から配送され、ユーザー側のオンプレ環境でEC2やRDSといったサービスをAWSインターフェースを介して管理する事が可能。
社内SE、ラズパイ4を買う。パート5（APIから明日の天気情報を取得し、Line通知する）

・前回

https://qiita.com/ra_risu/items/5dd76d428ba7a716d246

・今回やりたいこと

どっかのAPIから住んでいる地域の降水確率を取得して、ライン通知する。

・解決したい課題

家にテレビがないし、朝起きるのがギリギリなので、前日中に降水確率をチェックして傘を持っていくべきか判断したい。午前中晴れ→午後雨のパターンでいつもびしょぬれになっている。

・技術的なポイント
Line通知は前回やったので

https://qiita.com/ra_risu/items/5dd76d428ba7a716d246

今回はどっかのAPIを叩いて降水確率のデータを取得すればよい。

今回はこちらを使わせていただく。

https://weather.tsukumijima.net/

また、APIの叩き方についてはこちらを参考にさせていただいた。

https://qiita.com/ehjivh/items/121afaecad59a7e11c61

一時間ぐらい格闘して完成したものがこちらになります。
(生まれて初めてAPI叩いてJSONいじった）

    def LinePrint(msg):

    # -*- coding:utf-8 -*-
    import requests
    import json

    jma_url = "https://weather.tsukumijima.net/api/forecast/city/(地域コード)"
    jma_json = requests.get(jma_url).json()

    # 明日のデータなので、forecast[1] 0は今日のデータ
    jma_date = jma_json["forecasts"][1]["dateLabel"]
    jma_weather = jma_json["forecasts"][1]["telop"]
    jma_rainfall_1 = jma_json["forecasts"][1]["chanceOfRain"]["T00_06"]
    jma_rainfall_2 = jma_json["forecasts"][1]["chanceOfRain"]["T06_12"]
    jma_rainfall_3 = jma_json["forecasts"][1]["chanceOfRain"]["T12_18"]
    jma_rainfall_4 = jma_json["forecasts"][1]["chanceOfRain"]["T18_24"]
    jma_max = jma_json["forecasts"][1]["temperature"]["max"]["celsius"]
    jma_min = jma_json["forecasts"][1]["temperature"]["min"]["celsius"]
    # 全角スペースの削除
    jma_weather = jma_weather.replace('　', '')

    message = "\n" + jma_date + "の天気は" + jma_weather + "\n" + "最高気温" + jma_max + "度\n" + "最低気温" + jma_min +"度\n" + "降水確率\n" +"0時-6時 " + jma_rainfall_1 + "\n6時-12時 " + jma_rainfall_2 + "\n12時-18時 " + jma_rainfall_3 + "\n18時-24時 " + jma_rainfall_4 + "\nです"

    import requests
    token='(Line Notifyトークン)'
    headers = {'Authorization': 'Bearer %s'%token, }        
    files = {'message': (None, message),}
    r = requests.post('https://notify-api.line.me/api/notify', headers=headers, files=files)
    print(r,r.text)
    
    LinePrint('')

**追記**
出力はこんな感じ（書くの忘れてた）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565403/b762c96b-67cb-7a98-bd05-a71f3a38767b.png)

なあ～んだ、APIとかJSONとか怖いものかと思ってたけど、自分で頑張っていじってみれば全然怖くないじゃんか（思い上がり）

あとはこいつをいつものcronで定時実行して、終わり！
イェンセンの不等式を使って対数和不等式を導く

# わからなかったこと

https://www.nature.com/articles/s41567-018-0076-1

Newman (2018) の序盤で，
> Employing the well-known Jensen inequality
>  $$\log\sum_i x_i \ge \sum_i q_i \log\frac{x_i}{q_i}$$

とあるが，この形のイェンセンの不等式がどう導かれるのかわからず，本題に入る前から躓いていた．

# 不等式の導出
そもそも上記の不等式は，イェンセンの不等式ではなかった．[対数和不等式 (log sum inequality)](https://en.wikipedia.org/wiki/Log_sum_inequality) というらしい．対数和不等式は $f(x) = x\log x$ にイェンセンの不等式を用いて導くことができる．導出には，以下のサイトを参照した．

https://manabitimes.jp/math/1254

## イェンセンの不等式
$f(x)$ が凸関数のとき，任意の実数 $x_1,\ldots, x_n$ と $\sum_i \lambda_i = 1$ を満たす任意の非負の実数 $\lambda_1,\ldots, \lambda_n$ について，

```math
\sum_i^n \lambda_if(x_i) \ge f\left(\sum_i^n \lambda_i x_i \right)
```
が成り立つ．つまり，関数 $f$ のアウトプットの加重平均は，インプットの加重平均を与えた時のアウトプットの値以上であるという不等式である．この不等式の両辺に $-1$ をかけた

```math
-\sum_i^n \lambda_if(x_i) \le -f\left(\sum_i^n \lambda_i x_i \right)
```
という関係を以下で使用する．

## 対数和不等式
$f(x) = x\log x~~(x > 0)$ について，$f'(x) = \log x + 1, ~~ f''(x) = x^{-1}$ より，$f(x)$ は凸関数である．任意の正の実数 $x_1,\ldots, x_n$ と $\sum_i q_i = 1$ を満たす任意の非負の実数 $q_1,\ldots, q_n$ を考える．$\lambda_i = x_i/\sum_i x_i$ とすると，対数和不等式の右辺は，

```math
\begin{align}
\sum_iq_i\log\frac{x_i}{q_i} &= -\sum_iq_i\log\frac{q_i}{x_i} \\
&= -\sum_i x_i\frac{q_i}{x_i}\log\frac{q_i}{x_i} \\
&= -\sum_i x_i f\left(\frac{q_i}{x_i}\right) \\
&= -\sum_i \lambda_i\left(\sum_i x_i\right) f\left(\frac{q_i}{x_i}\right) \\
&= -\left(\sum_i x_i\right)\sum_i \lambda_i f\left(\frac{q_i}{x_i}\right) \\
& \le -\left(\sum_i x_i\right)f\left(\sum_i\lambda_i\frac{q_i}{x_i}\right) \\
&= -\left(\sum_i x_i\right)f\left(\frac{\sum_iq_i}{\sum_ix_i}\right) \\
&= -\left(\sum_i x_i\right)f\left(\frac{1}{\sum_ix_i}\right) \\
&= -\left(\sum_i x_i\right)\frac{1}{\sum_ix_i}\log\frac{1}{\sum_ix_i} \\
&= -(-1)\log\sum_ix_i \\
&= \log\sum_ix_i.
\end{align}
```
最初と最後を比べると，途中で $\le$ を挟んで対数和不等式となっていることが確認できる．
MySQLのDockerコンテナ作成時にDBのスキーマ、レコード作成を行う方法

# 結論
スキーマやレコード作成を記述したSQLファイルと、そのSQLを実行するシェルファイルを用意し、Dockerfileでコピー、もしくはdocker-compose.ymlのvolumeマウントで用意したファイルをMySQLコンテナの`/docker-entrypoint-initdb.d/`に設置することで初回コンテナ起動時にシェルファイルが実行され、スキーマ、レコード作成を行うことができる。

# docker-composeによる例
```Dockerfile:Dockerfile
FROM mysql:8.0.34

# SQLファイルをコピー(docker-compose.ymlでマウントする場合は不要)
# COPY /database/*.sql /database/

# # テストデータベース作成用のスクリプトをコピー(docker-compose.ymlでマウントする場合は不要)
# COPY /docker-entrypoint-initdb.d/init_db.sh /docker-entrypoint-initdb.d/

# # このフォルダにファイルをコピーして実行権限を付与しておけば初回コンテナ作成時に自動実行してくれる(docker-compose.ymlでマウントする場合は不要)
# RUN chmod +x /docker-entrypoint-initdb.d/init_db.sh

CMD ["mysqld", "--default-time-zone=Asia/Tokyo"]
```
```yaml:docker-compose.yml
version: '3'

services:
  rdb:
    build: ./
    platform: linux/x86_64
    environment:
      LANG: C.UTF-8
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: user
      MYSQL_PASSWORD: user
      TZ: 'Asia/Tokyo'
    ports:
      - "3306:3306"
    volumes:
      - sample-mysql-data:/var/lib/mysql
      # DockerfileでCOPYする場合は以下の二行は不要
      - ./database/:/database/
      - ./docker-entrypoint-initdb.d/:/docker-entrypoint-initdb.d/

volumes:
  sample-mysql-data:
```
```shell:init.sh
mysql -h localhost -u root -proot < /database/create_schema.sql
mysql -h localhost -u root -proot < /database/create_row.sql
```
```sql:create_schema.sql
CREATE SCHEMA IF NOT EXISTS `sample_db` DEFAULT CHARACTER SET utf8 ;

USE `sample_db`;

CREATE TABLE IF NOT EXISTS `sample_tbl` (
  `id` CHAR(36) NOT NULL,
  `text` VARCHAR(50) NOT NULL,
  `created_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

```
```sql:create_row.sql
USE `sample_db`;

INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c91', 'text1', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c92', 'text2', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c93', 'text3', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c94', 'text4', '2023-09-30 00:00:00');
INSERT INTO `sample_tbl` (`id`, `text`, `created_at`) VALUES ('t78648f5-740f-4cb0-bf40-7213c58a8c95', 'text5', '2023-09-30 00:00:00');
```

# ハマったこと
以下のケースに該当する場合はSQLファイルを更新して、コンテナを作り直してもスキーマなどが更新されません。
- Dockerfileでコピーのみを行ない、マウントしていない場合はその都度イメージ作り直さなければならない。
- ボリュームを作成し、/var/lib/mysqlをボリュームマウントしている場合はボリュームを削除しなければならない。
- docker-compose.ymlでSQLファイルやスキーマファイルをマウントにより共有している場合はホストで実行権限を付与しておかなければならない。

# 最後に
上記のことから開発環境で利用する場合は作成したデータが消えないようにボリュームを作成してマウントし、スキーマの変更があった場合は直接コンテナにアタッチしてMySQLにログインし、変更を反映することがいいように思いました。
また、自動テストで利用する場合はボリュームを作成せずにコンテナを作り直しただけでスキーマが反映されるようにすることがいいように思いました。
VirtualBoxでNATネットワーク構成、ホストからゲストにSSH接続まで

これも苦労した。備忘録。

ツールを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/d388f34f-3e25-ad9e-75a4-06a7eebd042f.png)

NAT Networksタブをクリックして新規作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/19bae0dc-fbf9-7a1b-60d3-7098776ed44f.png)
構成内容
名前　NAT-Network
IP 10.254.20.0/24
DHCP Enable


ポートフォワーディング設定もやっておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/48e79367-d3a3-0c12-f416-c24a5bcaf7aa.png)

ゲストのIPは10.254.10.4/24を割り振ることにして設定。
ホストポート22、ゲストポート2200はSSHログインの際使うので覚えておく。

仮想マシンのネットワーク設定でNATネットワークと先ほど作ったNAT-Networkを選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/eb5643a0-2819-651a-5f1c-c0f6040ed73b.png)

VMを立ち上げる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/a9d23aed-8acf-a33e-bf7d-933c49093e7a.png)


端末開いてIP設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/a416b83e-ef06-b094-aca1-340194df820d.png)

設定は以下の通り
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/3fd58f2d-3948-55c2-1e9d-332280daa87e.png)

sudo netplan applyコマンドで適用する。
エラーでなければOK

一応Pingを打って外部に出れているか確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/ceff47ae-03d9-44cf-4b68-04f692a56b59.png)

OKならいよいよSSH接続

localhost ホストポート 
TCPポートにゲストポートを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/df9d8d1d-aa17-c034-23f1-441d82809c8b.png)


ユーザ名、パス入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/8593ca31-f56b-a857-0d1d-3a289bb77689.png)


ログインできた！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284920/3c45b7d6-22a1-3292-ba81-44b594fed5e9.png)



まとめ
NATネットワークとは別に内部ネットワークのアダプタを追加してそちらでSSH接続したかったがなぜ、インターフェースを認識せずIP設定すらできなかった。なぜだろう…
NWは難しいですネ…
えっ、まだList<T>使ってるの？ [C#, コレクション]

C#のコレクションの話です．
どうも特に理由なく`List<T>`を漠然と使うようなコードをまま見るので，コレクション型の使い分けについて書いていきます．

# TL;DR

コレクション型には様々な種類があり，それそれに違った利点があるので，何でも`List<T>`を使うのではなく場面に合ったものを使おうね！

# `List<T>`が適している場合

https://learn.microsoft.com/ja-jp/dotnet/api/system.collections.generic.list-1

`List<T>`の一番の強みは，配列のようにインデックスでアクセスできることです．ご存知の通り，`list[2]`のような書き方でn番目の要素を取り出すことができます．この順番は勝手に変わったりしないので，順番に意味がある場合にも使えます．

```cs
var numList = new List<string>(){ "ぜろ", "いち", "に" };
var item = numList[2];  // "に"
```

また，要素の中からランダムに1つ選ぶような処理でもよく使われます．0-要素数の範囲で乱数を生成し，その乱数をインデックスとしてアイテムを取り出すことで，リストの中からランダムに1つの要素が得られます．

```cs
var random = new Random();
var item1 = numList[random.Next(numList.Count)];  // "に"
var item2 = numList[random.Next(numList.Count)];  // "ぜろ"
var item3 = numList[random.Next(numList.Count)];  // "に"
var item4 = numList[random.Next(numList.Count)];  // "いち"
```

逆に言えば，これらの用途ではない場合は他の型の使用を検討すべきです．

# `Stack<T>`, `Queue<T>`

要素の追加順が大事なときに使うのがこの2つです．

https://learn.microsoft.com/ja-jp/dotnet/api/system.collections.generic.stack-1

https://learn.microsoft.com/ja-jp/dotnet/api/system.collections.generic.queue-1

`Stack<T>`は，その名の通り上に積み重ねるように要素を追加します．要素を取り出すときは一番上から取り出すので，最後に追加された要素が取り出されます．

`Queue<T>`は，要素を順番待ちの行列の一番後ろに追加します．要素を取り出すときは一番前のものを取り出すので，最初に追加された要素から順に取り出されます．

# `HashSet<T>`

順番に意味がなく，要素が重複しない，もしくは重複しているかどうか調べたいときに使います．

https://learn.microsoft.com/ja-jp/dotnet/api/system.collections.generic.hashset-1

`HashSet<T>`は，順番に意味を持ちません．そのため，`[]`を使ってインデックスでアクセスすることはできません．

また，`HashSet<T>`には同じ要素を複数追加することはできません．
`Add`メソッドで要素の追加を行いますが，すでに同じ要素が含まれており，追加できなかった場合はfalseが返ります．
この特性を利用して，例えば同じオブジェクトに対しては1回だけ処理を行うような処理を書くことができます．

```cs
// ChackUser済のUser
private readonly HashSet<User> checkedUsers = new();

public void CheckUser(User user)
{
    // CheckUserしたことがある場合，要素が重複するのでfalseが返る
    if (!checkedUsers.Add(user))
    {
        return;
    }
    // 以下メソッドの処理
}
```

# まとめ

それぞれに書いたような目的は，極論`List<T>`でもLINQやループを使えば達成できますが，当然目的に合ったものを使った方が圧倒的に利点が多いです．
HashSetで例に挙げたような処理をListで行う場合，Containsで重複を確認して，重複していなかったらAddして，と非常にまどろっこしいことになります．

他の利点や計算量などの違いもありますが，状況によってコレクションを使い分けることでパフォーマンスの向上が期待できますし，コードも読みやすくなります．

コレクションに漠然と`List<T>`を使う前に，本当にそれが適切なのか，ぜひとも一度見直してみてほしいと思います．

# 参考

https://ufcpp.net/study/dotnet/bcl_collection.html
govcのjsonオプションのフィールド名に破壊的変更が加わる（govmomi 0.31）

# TL; DR

- フィールド名が **`PascalCase` -> `camelCase` に変更**

```bash:before
$ govc vm.info -json DC0_H0_VM0 | jq .VirtualMachines[].Self
{
  "Type": "VirtualMachine",
  "Value": "vm-55"
}
```

```bash:after
$ ./govc vm.info -json DC0_H0_VM0 | jq .virtualMachines[].Self
{
  "type": "VirtualMachine",
  "value": "vm-55"
}
```

# はじめに

9/25にgovmomi [0.31](https://github.com/vmware/govmomi/releases/tag/v0.31.0)が、そして間をおかず9/29に [0.32](https://github.com/vmware/govmomi/releases/tag/v0.32.0) が実装されました[^update]。このリリースは影響範囲の広い破壊的変更を含みます。

# 破壊的変更：フィールド名がPascalCaseからcamelCaseに変更

冒頭の例の通り、vCenterレスポンスモデルをJSON化する際にフィールド名の先頭が大文字から小文字になりました。
これに伴い、govcの `-json` オプションによる出力結果が変わります。

```bash:0.30まで
$ govc version
govc 0.30.0
$ govc vm.info -json DC0_H0_VM0 | jq .VirtualMachines[].Self
{
  "Type": "VirtualMachine",
  "Value": "vm-55"
}
```

```bash:0.31以降
$ ./govc version
govc 0.32.0
# キーがcamelCaseになっている(jqのフィルタも変えていることに注意！)
$ ./govc vm.info -json DC0_H0_VM0 | jq .virtualMachines[].Self
{
  "type": "VirtualMachine",
  "value": "vm-55"
}
```

スクリプト等でgovcが出力しているJSONを使っていた場合、**0.31以上に上げると動かなくなってしまいます**。

```bash
$ govc vm.info -json DC0_H0_VM0 | jq .VirtualMachines[].Self
jq: error (at <stdin>:494): Cannot iterate over null (null)
```

# 対応

上記のように、キーをcamelCaseに変えることで対応可能です。

しかし、スクリプト全体のフィールド名を逐一書き換えると手間がかかります。
別のアイデアとして、本記事ではjqで 「フィールド名をPascalCaseに戻すフィルタ」 を噛ませます。

```bash
$ ./govc vm.info -json DC0_H0_VM0 | jq 'walk(if type=="object" then with_entries(.key|=(.[0:1] | ascii_upcase) + .[1:]) else . end)' | jq '.Virtua
lMachines[].Self'
{
  "Type": "VirtualMachine",
  "Value": "vm-55"
}
```

フィルタ `jq 'walk(if type=="object" then with_entries(.key|=(.[0:1] | ascii_upcase) + .[1:]) else . end)'` で、キーの先頭を大文字にしています。

仕組みは以下の通りです。（`jq` の話なので使うだけであれば気にしなくてokです）

- `with_entries` でオブジェクトの各キー、値に対しmap処理を適用
- キーの一文字目だけ大文字化して自身に代入 ( `|=`)

https://yujiorama.github.io/unofficial-translations/jq/l10n/jp/manual/

[^update]: 0.31から1週間たたずに0.32がリリースされフィールド名変更範囲が追加されたため、改修は完了していないかもしれません。
2つのChromeブラウザを立ち上げ、 それぞれ異なるMetaMaskアカウントを操作する方法

DAppの動作確認で、2つのChromeブラウザを立ち上げ、 それぞれ異なるMetaMaskアカウンでDAppを操作したいとします。通常、Chromeのウィンドウを2つ立ち上げても、同一のMetaMaskアカウントでしか操作できません。

異なるMetaMaskアカウンでDAppを操作するには、ブラウザのプロファイルを追加して、それぞれのプロファイルでDappを操作する必要があります。この方法について記述します。

## 前提
- MetaMaskをインストール済である
- Metamaskアカウントを複数保持している

## Chromeのプロファイル追加
1. 右上のアカウントアイコンをクリック
1. 追加をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/69cab5ee-331a-8a05-b321-ee29dcc2438b.png)

1. `アカウントなしで続行`をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/b9f85e5f-18a2-4c91-61b6-785b669a8fd1.png)

1. 好きな名前を入力
1. 好きなアイコンを選択
1. `完了`をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/56255b59-3f9e-17e3-14f4-58651c664e24.png)

1. 選択したアイコンの色合いのブラウザが立ち上がる。これが新たなプロファイル。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/3c8a36e1-ac51-683e-5d31-2923e6753834.png)


1. 以上のプロセスで、右上のアイコンから新たなプロファイルを選択できるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/f8ccdf1e-4407-8e2c-921e-8ad5da166efa.png)


## 新たなプロファイルにMetaMaskをインポートする
1. [https://metamask.io/](https://metamask.io/)にアクセス
1. 左下の`Download for Chrome`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/0628ae75-337c-1d5b-7e0d-0e0055c7106b.png)

1. `Chromeに追加`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/0cb7f089-6b14-cc8b-530d-b1b5b1701351.png)

1. ポップアップの`拡張機能を追加`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/b5365bdb-5200-c1a5-9715-206e7e572807.png)

1. `I agree to MetaMask's 利用規約`をチェックし`既存のウォレットをインポート`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/bf5a16e3-dc01-8154-fa2d-13242cbc0d55.png)

1. 記載事項を読んで、`同意します`をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/10438e83-aaf7-71bd-9daf-913025c8a4a3.png)

1. MetaMaskを初回インストールしたときのリカバリーフレーズを入力し、`シークレットリカバリーフレーズの確認`をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/d56bd725-3dc6-8099-eb2e-d1b32179f496.png)

1. パスワードを再設定して、`ウォレットをインポート`をクリック。このパスワードは新たなプロファイルのパスワードであって、元からあったプロファイルでMetaMaskを利用する時のパスワードは変化しない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/cbbfb62f-6739-a2d1-7e6e-9a5ef4ab9de8.png)

1. 記載内容を読んで`了解`![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/e990e294-cd70-250b-bd3f-8fa73ddbd6e2.png)

1. 新たなプロファイルで、既存のMetaMaskを利用できる。

## プロファイルを2つ立ち上げる
右上のアイコンから2つのプロファイルを立ち上げる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/f8ccdf1e-4407-8e2c-921e-8ad5da166efa.png)

## 各プロファイルで異なるMetaMaskアカウントを選択
左はアカウント1、右はアカウント2を選択できている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163239/2c2f7803-0858-6e05-e97e-54607bb9efcb.png)

## おまけ
私が作成したUdemyコースですが、DApp開発講座です。DApp開発では、2つのChromeブラウザを立ち上げ、 それぞれ異なるMetaMaskアカウントを操作して、動作検証することも多々あります。DApp開発にご興味あれば、無料部分からご視聴ください。

https://www.udemy.com/course/dapp-vyper/?referralCode=D50B5400D6DD442667C2
NLP100本ノックのtypoglycemiaをできるだけ短く書いてみた。

# はじめに
最近言語処理100本ノックとか競プロとかやっている中で、typoglycemiaコードを短く書いてみたくなったので書いてみました。

この記事は完全に自己満足なので、ご容赦ください。

# コードはこちら

```py:q09.py
import random

s = 'I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .'

print(' '.join(map(lambda word: word[0] + ''.join(random.sample(word[1:-1], len(word[1:-1]))) + word[-1] if len(word) > 4 else word, s.split())))

```

書いてあることはシンプルですが、、、、見た目がきついですね・・・。

さらに短くしてみます。
```py:q09-2.py
import random

print(' '.join(map(lambda word: word[0] + ''.join(random.sample(word[1:-1], len(word[1:-1]))) + word[-1] if len(word) > 4 else word, 'I couldn’t believe that I could actually understand what I was reading : the phenomenal power of the human mind .'.split())))

```
文章を変数に切り出さすに直接mapの引数に入れてみました。
非常に見にくいですね。
みなさんちゃんと関数化しましょう。
Discordのコマンド実行時に「アプリケーションが応答しませんでした」が表示される場合の原因と解決方法

DiscordのチャンネルにINTERACTIONS ENDPOINT URLを登録した自作のBotを招待し、コマンドを実行すると、処理は実行できているものの、「アプリケーションが応答しませんでした」と表示されました。

2023/10/02時点、Discord APIのバージョン10の場合です。

## ✅ 解決方法

コマンド実行から3秒以内にInteractionsの初回のレスポンスを行う。

## 🔴 原因

> Interaction tokens are valid for 15 minutes and can be used to send followup messages but you must send an initial response within 3 seconds of receiving the event. If the 3 second deadline is exceeded, the token will be invalidated.
>
> &mdash; <cite>[Responding to an Interaction](https://discord.com/developers/docs/interactions/receiving-and-responding#responding-to-an-interaction)</cite>

「DiscordのInteractionsの初回のレスポンスを3秒以内に行わないと、トークンが無効になる」という仕様を見逃していました。

> Interaction tokens are valid for 15 minutes

の部分を見て、15分間は有効だと勘違いしてしまいました……

## 💻 エラー発生時にやっていたこと

やろうとしていた事はこんな感じです。

- EC2に建てたゲームサーバーの起動をDiscordのコマンドで行う
- Discordのコマンド(Interactions)のハンドリングはLambdaで行う
  - PING - PONGの対応
  - Authorizationの対応
  - サーバーコマンドのハンドリング用のLambdaを呼び出す

「アプリケーションが応答しませんでした」を表示しないようにするには、
`コマンド送信 → LambdaのInitialization -> LambdaのInvocation　-> Discordがレスポンスを受け取る`の**一連の流れを3秒以内に終わらせる必要があります。** 当然Lambdaのコールドスタートも含めて3秒以内に応答する必要があります。

自分の今回のケースだと、Lambdaの実行時間は平均3~6秒前後かかっていたので全然間に合っていませんでした。

今回は、サーバーコマンドのハンドリング用のLambdaを呼び出す際に、[非同期呼び出し](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-async.html)ではなく同期呼び出しを行なっていたため、サーバーコマンドのハンドリング用のLambdaのレスポンスを待機してしまって、Discordへのレスポンス送信に時間がかかってしまったのが原因でした。

解決方法としては、サーバーコマンドのハンドリング用のLambdaを非同期呼び出しして、サーバーの起動処理が終わる前に一旦Discordに対してInteractionsの応答を行うとうまくいきました。