OmniAICreator/Qiita-1.07M huggingface dataset:
進捗

#プログラミングスクール

15日からプログラミングスクールに通いオンラインでPHPを学習しています。

##目的と目標

プログラミングスクールに通うことにした理由は、独学では学習に限界があったからです。

全く意味がなかったわけではなく、学習方法や目的意識の持ち方に問題がありました。

##どんな問題があったか

学習サイト（Paizaなど）でプログラミングの知識は身に付けられるが、アウトプットが出来ない。つまり、学習した内容でオリジナルのコードが書けず、サービスが作れないと言うことです。

どんなものを作りたいか、それには何が必要か（機能など）、誰に見せることを考えているかが考えていなかったからです。

#プログラミングスクールで学習していること
##言語
PHP（フレームワーク：Laravel）
##データベース
Mysql

##自分なりに気づいたこと
プログラミングはコードを書ければ良いと言うわけではなく、調べる癖をつけ、ドキュメントで調べられるようになる必要がある。

質問することや分からないことを繰り返し調べることで、身に付いていく。

#最後に

私はベイスターズが好きなので、ベイスターズに関するサービスを作れるようになりたいと思っています。（昨年の成績からの今年の予想表示など）
画像の背景を削除するための素晴らしいツール


画像の背景を削除するための素晴らしいツール

![11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535987/a9ba9611-ef8c-89a4-b925-7d3caf6d28ff.jpeg)

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535987/15ca70bf-0cd3-3152-480b-ad506ce030c6.png)




背景を削除
1秒でシングルクリック
100％自動で無料のオンラインバックグラウンドリムーバー＆エディター


https://www.cutout.pro/ja

迅速なワークフローのための簡単なAPI統合
当社のAPIは、iOS、Android、Mac、Windows、Linuxアプリ、ウェブサイト、SAASソフトウェアなどに統合できます。カスタマイズされたAPIを介して無制限の創造性を実現し、画像編集、AR / VR、広告イノベーション、Eコマースなどの業界シナリオに適合させます。 プリントオンデマンドのカスタマイズ、画像のレタッチとデザインなど。
メディアアプリをよりスマートにします。 大量の画像、ビデオ、 ワンスナップで処理。

安全、信頼性、効率性、拡張性
さまざまな目的やアプリケーション向けに最適化
98％以上の稼働時間保証
アップロードされたデータと結果はすぐに安全に破棄されます
専用のプレミアムカスタマーサポート
django-stdimageで元の画像を削除する

#はじめに
django-stdimageは画像サイズを変更して保存してくれます．
元の画像はいらないので削除しましょう。

https://qiita.com/peijipe/items/68292ded4fd3e31a8bfe



こちらにまとめさせていただきました。

https://blogdodo.com/blog/223/
Javaでreplace()メソッドを使う時にエラー: replaceに適切なメソッドが見つかりませんの対処法

Javaでコードを書いている時に、replace()メソッドを使う時に、タイトルのエラーで詰まってしまったので、備忘録としてまとめます。
以下のようにしてコードを書いていたのですが、

```main.java
class Main {
    public static void main(String args[]){
        String str = "あいうえお";
        str.charAt(0);
        String targetWord = String.valueOf(str.charAt(0));
        System.out.println(str.replace(str.charAt(0), "か"));
      }      
}
```
これで実行しようとしたらタイトルのエラーになってしまいました。

# やろうとしたこと
やろうとしたこととしては、

```
・charAt()メソッドで取得した文字を、replaceメソッドで置換する
```

というものです。
それをする時に、replaceの引数に直接charAt()メソッドで指定した文字列を

```
System.out.println(str.replace(str.charAt(0), "か"));
```

このようにして変数strに対して、頭文字を`か`に置換したかったので、第一引数に対象の文字列の頭文字を取得する処理を直接入れようとしました。
ただ、それをしてしまうと

```
main.java:6: エラー: replaceに適切なメソッドが見つかりません(char,String)
```

となってしまいます。

原因としては、charAt()メソッドで指定して取得するとそのデータ型はString型ではなくchar型になります。
しかし、replace()メソッドの引数に入れられるものはString型だけです。なのでchar型を入れるとエラーになってしまうわけです。
ではどうしたらいいのかというと、char型をStringに変換してしまえば解決します。

変換するには、StringオブジェクトのvalueOf()メソッドで指定します。

```
String targetWord = String.valueOf(str.charAt(0));
```

このように、valueOfメソッドでChar型からStringに変更します。
こうすることで、replace()メソッドに入れてもエラーにならないようになりました。
後は単純にreplaceメソッドの中に入れてあげれば大丈夫です。

```
String targetWord = String.valueOf(str.charAt(0));
System.out.println(str.replace(targetWord, "か"));
```

# 修正後のコード

```Main.java
class Main {
    public static void main(String args[]){
        String str = "あいうえお";
        String targetWord = String.valueOf(str.charAt(0));
        System.out.println(str.replace(targetWord, "か"));
      }      
}
```

以上になります。
なにかの参考になったら嬉しいです。

# 追記

```Main.java
public static void main(String[] args) {
    String str = "あいうえお";
    System.out.println(str.replace(str.charAt(0), 'か'));
}
```

で`System.out.println(str.replace(str.charAt(0), 'か'));`の部分で、第荷引数をシングルコーテーションで囲うとchar型として指定することができます。
そうすれば、第一引数と第二引数で同じchar型に指定できます。

初めて知りました。

コメントでアドバイスをもらいました。
ありがとうございます!!!
幅優先探索

[最短経路問題](https://qiita.com/sibata_yuna/items/9d3f03288422c96af632)

[問題](https://atcoder.jp/contests/abc007/tasks/abc007_3)　:　[動作確認済み](https://atcoder.jp/contests/abc007/submissions/29760115)

queue と vector を使う

```c++

int H, W; // 迷路の大きさ
char c[1009][1009]; // x座標、y座標
int dist[1009][1009]; //縦、横

void print(char c[1009][1009])
{
    rep(i, 0, H + 2)
    {
        rep(j, 0, W + 2) cout << c[j][i] << " ";
        cout << endl;
    }
}

int main() {
    // 迷路を入力する
    //cin >> H >> W; // 縦、横の長さ
    cin >> W >> H; // 横、縦の長さ

    /*周りを壁で囲う場合
    rep(i, 0, H + 2)rep(j, 0, W + 2)
        c[j][i] = '.'; // '.' 通路、'#' 障害物

    for (int i = 1; i <= H; i++) {
        for (int j = 1; j <= W; j++)
        {
            cin >> c[j][i]; 
        }
    }
    
    //print(c);
    */
    
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) cin >> c[j][i]; //壁かマスか
    }

    // 各マスの最短距離
    for (int i = 0; i < H + 2; i++) {
        for (int j = 0; j < W + 2; j++) dist[j][i] = 1000000007; // x座標、y座標
    }

    // 幅優先探索により、最短移動回数を求める
    queue<pair<int, int>> Q;
    Q.push(make_pair(0, 0));
    dist[0][0] = 0; // スタート地点

    while (!Q.empty()) {
        int cx = Q.front().first, cy = Q.front().second;
        Q.pop();

        /*
        int dx[4] = {1, 0, -1, 0};
        int dy[4] = {0, 1, 0, -1};
        */

        int dx[2][6] = {
            {-1,0,-1,1,-1,0},
            {0,1,-1,1,0,1}
        };
        int dy[6] = { -1, -1, 0, 0, 1, 1 };

        for (int i = 0; i < 6; i++) {
            int ex = cx + dx[cy % 2][i], ey = cy + dy[i];

            //周りの壁がなければ範囲指定する
            if (!(0 <= ex && ex <= W + 1 && 0 <= ey && ey <= H + 1)) continue;

            //1づつ増加するため、塗り替えない
            if (c[ex][ey] != '.' || dist[ex][ey] != 1000000007) continue;


            Q.push(make_pair(ex, ey));
            dist[ex][ey] = dist[cx][cy] + 1;
        }
    }

    return 0;
}
```
heapq.nlargest(n, iterable)でリストの上位n番目までをスッキリ抽出

# はじめに
`heapq.nlargest(n, iterable, key=None)`
はリストなどの上位n番目までの要素をリストで返します。。調べても記事がなかったので書いておきます。
# 説明
`heapq.nlargest(n, iterable, key=None)`
ではiterableで定義されるデータセットのうち、最大値から降順にn個の値のリストを返します。

つまり、
`sorted(iterable,key=None,reverse=True)[:n]`
と同義です。
# 実行
`sample=[5,7,3,12,7,3,1]`
を例に取って実行します。

### コード
```python
sample=[5,7,3,12,7,3,1]

print(heapq.nlargest(5,sample))
print(sorted(sample,reverse=True)[:5])
```

### 結果
```
[12, 7, 7, 5, 3]
[12, 7, 7, 5, 3]
```

次に、
`sample=[("c",5),("b",7),("e",3),("f",12),("a",7),("d",3),("g",1)]`
を例にとって実行します。
### コード
```python
sample=[("c",5),("b",7),("e",3),("f",12),("a",7),("d",3),("g",1)]

# 普通にソート
print(heapq.nlargest(5,sample))
print(sorted(sample,reverse=True)[:5])

# 第二引数に関してソート
print(heapq.nlargest(5,sample,key=lambda t:t[1]))
print(sorted(sample,reverse=True,key=lambda t:t[1])[:5])
```
### 結果
```
[('g', 1), ('f', 12), ('e', 3), ('d', 3), ('c', 5)]
[('g', 1), ('f', 12), ('e', 3), ('d', 3), ('c', 5)]

[('f', 12), ('b', 7), ('a', 7), ('c', 5), ('e', 3)]
[('f', 12), ('b', 7), ('a', 7), ('c', 5), ('e', 3)]
```

### まとめ
sortedを使うより多少コード量が減るし、見栄え的にもわかりやすいので、heapqをインポートしているような場面では積極的に使っていこうと思っています。
[Drupal]Viewsのテーブルでカラムのラベルをクリックするとソートできるようにする

## やりたいこと
ここクリックでソートできるようにしたい
![sort.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/8465075e-0ea4-3d58-852a-45b092f3af92.png)


## やり方
ビューの設定画面で、フォーマットの設定をクリック
![table_settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/335efb6e-7728-6417-2301-e79d133affbd.png)

ソートしたいカラムにチェックを入れる
![checkbox.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253501/f42f3ca3-ab54-06f0-1594-73261326d35d.png)

通常の並べ替え基準を設定してある場合は、カラムクリックでソート基準が上書きされます。また、外部設置してる並べ替え基準があるとこのソート方法は使えない（クリックしても何も起こらない）のでご注意ください。
ObjectMapperについて

# 概要

[jackson-databind](https://github.com/FasterXML/jackson-databind)に含まれる[ObjectMapper](https://github.com/FasterXML/jackson-databind/blob/2.14/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java)について疑問に思うところがあったため、調査した記録を残す。


## 1. [readValue] recordにreadValueすることはできるか？

できる。
recordクラスのフィールドは自ずとfinalになるため、もしかしたらデシリアライズできないのではないか？と思っていたが杞憂であった。

## 2. [readValue] jsonに想定しないpropertyが入っている場合にはどうなるか？

`UnrecognizedPropertyException`をthrowする。
もし想定外のpropertyが来たとしても無視したいならば、下記のようにObjectMapperの`FAIL_ON_UNKNOWN_PROPERTIES`をdisableしてやれば良い。

```java
        ObjectMapper disableFailOnUnknownPropertiesObjectMapper = new ObjectMapper()
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
```

## 検証コード

https://github.com/nannany/try-object-mapper
サクラエディタでよく使用するコマンド(備忘)

## サクラエディタでよく使用するコマンド(備忘)
備忘

・Grep
Ctrl+G
・ソート
Alt+A
・マージ
Alt+M
(マージはソート後に実施したほうが良い)
・CMD実行
正規表現あり

```
"C:\Program Files (x86)\sakura\sakura.exe" -GREPMODE -GKEY="bb" -GFILE=#".svn";"*" -GFOLDER="C:\Users\username\Desktop\xxx" -GCODE=99 -GOPT=SRP1
```
正規表現なし

```
"C:\Program Files (x86)\sakura\sakura.exe" -GREPMODE -GKEY="bb" -GFILE=#".svn";"*" -GFOLDER="C:\Users\username\Desktop\xxx" -GCODE=99 -GOPT=SP1
```
FlutterアプリでFirebase Authenticationを使った時のアカウント停止方法のメモ

## はじめに
Flutterのアプリ開発で`Firebase Authentication`を使いログイン機能を実装しているのだが、不正利用のアカウントに気付いた場合などの、アカウント停止がいまいち意図した様に動かなかった。
知っていれば大した話ではないのだが、自分のためにも同じ事で悩まれる開発者のためにもメモを残しておく。

## メモ内容
`Firebase Authentication`を止める方法として、Firebaseのコンソールからアカウント無効ににするだけで良いかと思っていたが、既にログインが完了しているユーザーには効かなく悩んでいた。

※無効にされたアカウントの場合、ログイン認証の際に下記の様な画面が出る
![Qiita-no062_img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654767/5675365a-d9a0-ed94-f010-9a204bf90b06.png)
既にログインが成立している状態だと、`FirebaseAuth.instance.currentUser`を使ってログイン情報を取得している場合が多いと思うが、この場合トークンの有効期限が1時間のため即時に使用不可とできないことが調べてみて分かった。

結論としては、Firebaseのコンソールからアカウント無効ににするだけで良いのだが、ログイン中のユーザーに対しては、**『無効にした約１時間後以降に、再度アプリが開かれたタイミングで無効が反映される』** っという理解でひとまずOK！
STM32L010とWS2812B(3個)でランダムに光らせる。 (Keil)


x Mbed2
x ws2812bがなぜ3個なのかと言うと2,3個で電流が超えるらしい
x 軽量高速化


目的
GPIOのテスト

STM32L010F4P6

説明
WS2812Bの接続ピンは、PA4(10ピン)です。

x 動作確認は、しましたが画像は、イメージです。

![h_con69.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5a72cc48-3337-da6b-cdd1-f97b625b3262.jpeg)




```c++



//WS2812_LED3_RAND_010_1
#include "mbed.h"

char l[90]; //max30 led

DigitalOut myled(PA_4);

//              5432109876543210
#define on1   0b0000000000010000
#define off1  0b0000000000000000

#define M_ON1   GPIOA->ODR=on1;GPIOA->ODR=on1;GPIOA->ODR=on1;GPIOA->ODR=on1;
#define M_OFF1  GPIOA->ODR=off1;GPIOA->ODR=off1;GPIOA->ODR=off1;GPIOA->ODR=off1;

// 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3
void bit_off1()
{
    //0.3us 800khz
    M_ON1;
    M_ON1;
    GPIOA->ODR = on1;

    M_OFF1;
    M_OFF1;
    M_OFF1;
    M_OFF1;
    M_OFF1;
    M_OFF1;
    M_OFF1;
    GPIOA->ODR = off1;
}//bit_off1

// 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
void bit_on1()
{
    //1us 800khz
    M_ON1;
    M_ON1;
    M_ON1;
    M_ON1;
    M_ON1;
    M_ON1;
    M_ON1;
    GPIOA->ODR = on1;
    GPIOA->ODR = on1;
    GPIOA->ODR = on1;

    M_OFF1;
    GPIOA->ODR = off1;
    GPIOA->ODR = off1;
    GPIOA->ODR = off1;
}//bit_on1

//ws2812bにデータを送る
int ws_led(int num1)
{
    char al;

    __disable_irq(); // disable interrupt

    for(int ii=0; ii<num1; ii++) {

      al=l[ii];

      if( al & 0b10000000 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}
      if( al & 0b01000000 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}
      if( al & 0b00100000 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}
      if( al & 0b00010000 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}
      if( al & 0b00001000 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}
      if( al & 0b00000100 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}
      if( al & 0b00000010 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}
      if( al & 0b00000001 ){bit_on1();/*ビットが1*/}else{bit_off1();/*ビットが0*/}

    }//for

    __enable_irq(); // enable interrupt

    return(0);//リターン
}

//メイン
int main() {


    //無限ループ
    while(1){

        for(int ii=0;ii<9;ii++){
            l[ii] = rand()%52;
        }//for

        //ws2812bへデータを送る
        ws_led(9);

        //1秒待つ
        wait_ms(100);

    } //while

} //main



```
40 代おっさん GASのGmailサービスのスレッドについて学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## システムラベルでスレッドを収得する

スレッドを収得する方法

・システムラベルからスレッドを取得する
・IDでスレッドを取得する
・検索をしてスレッドを取得する

### システムラベルでスレッドを取得する

システムラベルは、受信トレイにある、重要、迷惑メールなどのラベルです。
GASではシステムラベルについてスレッドを収得するメソッドがある。

|システムラベル|収得メソッド|
|-------------|-----------|
|受信トレイ|getInboxThreads|
|スター付き|getStarredThreads|
|下書き|getDraftMessages|
|迷惑メール|getSpamThreads|
|ゴミ箱|getTrashThreads|

下書きは送信前につき、スレッドと言う概念がありません。したがって。収得できるのはメッセージの配列となります。

受信トレイからスレッドを配列として取得するgetInboxThreadsメソッドを見て見ます。

構文

```javascript
GmailApp.getInboxThreads([開始位置, 最大取得数])
```

受信トレイは最新のものからインデックスが付与される。
引数の省略も可能だが、その場合はすべてのスレッドを収得する。

お試し

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0,3);

  for (const thread of threads) {
    console.log(thread.getFirstMessageSubject());
  }   
}
```

＊一日当たり2万件ないしは5万件までと言う制限があるので注意

### IDでスレッドを収得する

スレッドには一意に決まるIDが付与されています。スレッドIDがわかればスレッドを取得できる。
getThreadByIdメソッドで収得できる

構文

```javascript
GmailApp.getThreadById(ID)
```

お試し

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0,1);
  const id = threads[0].getId();

  const thread = GmailApp.getThreadById(id);
  console.log(thread.getFirstMessageSubject());
}
```

### スレッドを検索する

searchメソッドを使うことで検索機能を使うことが出来る。

構文

```javascript
GmailApp.search(クエリ[, 開始位置, 最大収得数])
```

クエリはGmailの検索条件を指定する文字列で、検索対象となるキーワードのみで検索することも可能
検索演算子を使用できる。

＊検索演算子の図は、参考資料の本を見ていただくか、ネットで調べください。

ちなみにこちらで書いてありました。
<https://support.google.com/mail/answer/7190?hl=ja>

お試し

```javascript
function tosiki() {
  const query = 'is:read "お問い合わせ"';
  const threads = GmailApp.search(query, 0, 10);

  for (const thread of threads) {
    console.log(thread.getFirstMessageSubject());
  }
}
```

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
unknown attributeのエラー

簡易的なフリマアプリを作成中。

一通りコードも書き終えて、いざHerokuへデプロイ！！

デプロイ後、挙動確認のため、ユーザー登録→商品登録→別ユーザーの登録→商品購入を試みるも、

`We're sorry, but something went wrong.`のエラー文が表示。


## 原因探究
何が悪いのかを調べるため、エラーログを確認。

```:ターミナル
> heroku logs --tail
```
すると下記のエラーログを発見。

```:ターミナル
 ActiveModel::UnknownAttributeError (unknown attribute 'item_id' for Order.):
```

意味を調べてみると、`Oderモデルにitem_idがありません`　といった内容。

Heroku上でカラムの確認を行うため、下記を入力。

```:ターミナル
 > heroku run rails console
　　> Order.new
```

結果、

```:ターミナル
 => #<Order:0x00007fedc8872950 id: nil, item_id: nil, created_at: nil, updated_at: nil, user_id: nil>
```

__？？？__

item_idはちゃんと反映されている,,,
なのに、なぜエラーが？

## 結果
色々調べているうちに、一つの検証が生まれる。
__「そうだ、再起動してみよう」__

```:ターミナル
heroku restart --app <アプリケーション名>
```

上記コマンドを実行。
すると、__見事成功！！__

__？？？__

なぜ上手くいったかわかりません笑
「エンジニアあるある」で`再起動するとなぜか上手くいく`という記事を読んだ事があったが、まさしくこの事か笑

もし原因がわかる方がいらっしゃいましたら、ぜひご教示頂きたいです。
JSON/YAMLの構造を保ったまま文字列値を空文字に置換する

# TL; DR

```bash:json
$ cat sample.json | jq '(.. | select(type == "string")) |= ""'
{
  "foo": "",
  "bar": {
    "baz": "",
    "bool": true
  },
  "num": 42,
  "arr": [
    "",
    "",
    {
      "three": ""
    }
  ]
}
```

```bash:yaml
$ cat sample.yaml | yq '(.. | select(tag == ("" | tag))) |= ""'
foo: ""
bar:
  baz: ""
  bool: true
num: 42
arr:
  - ""
  - ""
  - three: ""
```

# やりたいこと

JSONやYAMLで書かれた設定ファイルのバリデーションチェックをテストするとき、「全部の値が空文字になったテストケースがあれば楽なのに」と思ったので作りました。

単純に値を空文字にすると深い階層が読み込めなくなってしまうので、スキーマを保ったまま文字列の値だけを空文字に置換するようにしています。

```json:これを...
{
  "foo": "FOO",
  "bar": {
    "baz": "BAZ"
  }
}
```

```json:こうしたい
{
  "foo": "",
  "bar": {
    "baz": ""
  }
}
```

```json:階層が消えるのは困る
{
  "foo": "",
  "bar": ""
}
```

# JSONの空文字化

[jq](https://stedolan.github.io/jq/) を使ってJSONを処理します。

```bash
$ jq --version
jq-1.6
```

オブジェクト内の文字列値を再帰的に探索し、それらを空文字列に置き換えることで実現しました。

```bash:json
$ cat sample.json
{
  "foo": "FOO",
  "bar": {
    "baz": "BAZ",
    "bool": true
  },
  "num": 42,
  "arr": [
    "one",
    "two",
    {"three": "THREE"}
  ]
}

$ cat sample.json | jq '(.. | select(type == "string")) |= ""'
{
  "foo": "",
  "bar": {
    "baz": "",
    "bool": true
  },
  "num": 42,
  "arr": [
    "",
    "",
    {
      "three": ""
    }
  ]
}
```

コードの意味は以下の通りです。

```jq
(
    # オブジェクト内の全値を再帰的に取得 (Recursive Descent)
    ..
    # 文字列型のみ抽出
    | select(type == "string")
)
# 上記で抽出できた各値を "" で上書き (Update-assignment)
|= ""
```

# YAMLの空文字化

こちらでは [yq](https://github.com/mikefarah/yq) を使用しました。

```bash
$ yq --version
yq (https://github.com/mikefarah/yq/) version 4.20.2
```

書き方はJSONの場合と同じです。ただし、yqには `type` 関数が無いため、代わりに `tag` を用いて文字列型の抽出を行っています。

```bash
$ cat sample.yaml
foo: FOO
bar:
  baz: BAZ
  bool: true
num: 42
arr:
  - "one"
  - "two"
  - three: "THREE"

$ cat sample.yaml | yq '(.. | select(tag == ("" | tag))) |= ""'
foo: ""
bar:
  baz: ""
  bool: true
num: 42
arr:
  - ""
  - ""
  - three: ""
```

`tag` 関数は式のタグを取得する関数で、デフォルトでは型名が取得できます。

https://mikefarah.gitbook.io/yq/operators/tag

```bash
$ echo "a: foo" | yq '.a | tag'
!!str
```

ただし、`!!str` のリテラルをべた書きすることはできないので、タグは第一級オブジェクトではなさそうです。
仕方がないので、上記のように「 `.` のタグが `""` のタグと等しい」という回りくどい比較を行っています（解決策をご存じの方はコメントいただけるとありがたいです）。

# おわりに

jq/yqは本当に何でもできると改めて実感しました。~~早く極めてシェル芸人になりたい~~
【個人開発】嫁ブロックを突破するアプリをつくました。

### はじめに

こんにちわ！くのと申します！


エンジニアの方ってガジェット好きな方多いですよね！！

しかしながら、エンジニアにとってガジェットを購入するために突破しなければいけない壁っていくつかありますよね。。。

突然ですが、2022年に実施されたガジェット購入時における障壁ランキングの堂々の第４位は何かご存知でしょうか！！？？

。。。そうですね！！それは「嫁ブロック」問題ですね！！
（すいません、これは僕の妄想アンケートの結果です。）


というわけで、嫁ブロックを突破し、高スペックなマシンをゲットして、強強エンジニアを目指すクソアプリを開発してみました！！


### アプリ概要
スタートから、5秒以内にボタンを連打して嫁ブロックを突破するアプリです。
＊連打回数が少ないと嫁ブロックは突破できないので、注意してくださいね。


嫁ブロックを突破するゲーム

https://infallible-chandrasekhar-86218b.netlify.app/

＊スマホ向けにデザインしていますので、スマホの方が遊びやすくなっております。

使用技術
・HTML・CSS・BootStrap・JavaScript
・プログラムを設置したサーバー：netlify


### 工夫したところ

ユーザの操作としては、ボタンを連打することがメインなので、ボタンを押した際のアニメーションにはこだわりました。
また、制限時間はを秒数表示するのではなく、ピンクの丸を縮小させていくことで、制限時間を認識できるように調整しました！

<a href="https://gyazo.com/5cbbaab9ac844f6b31511ecc02fe45cc"><img src="https://i.gyazo.com/5cbbaab9ac844f6b31511ecc02fe45cc.gif" alt="Image from Gyazo" width="1000"/></a>


### おわりに

もし興味を持っていただければ、このアプリで遊んでいただけたらすごく嬉しいです！

記事を書いて思ったのですが、嫁ブロック突破してガジェット買っても、後でバレたら怒られてしまうので対話して納得してもらうのが一番ですね！！（笑）
皆様のいい夫婦生活を願ってます！！（笑）


5秒で遊べるアプリなので、興味を持っていただき遊んでいただければ幸いです！

「嫁ブロックを突破するゲーム」

https://infallible-chandrasekhar-86218b.netlify.app/


↓↓↓
こちらのアプリも5秒で遊べる内容ですので、よろしければ遊んでみていただけると嬉しいです！
「ロケットを発射するゲーム」

https://zealous-heyrovsky-308820.netlify.app/

ここまで読んでいただき、ありがとうございました！！
異常検知(Anomaly Detection)モデルの学習・評価用データセットまとめ【機械学習】

最近、いろいろな案件で異常検知用の機械学習モデルを作成することが多いので、自分がよく使うオープンデータをダウンロードできるサイトのリンクをまとめて、データセット一覧を作成してみました。
今後も新しく見つけたデータセットを追記していくつもりです。

# データセット一覧
## 画像データ系
### [MVTec](https://www.mvtec.com/company/research/datasets/mvtec-ad/)
産業検査に焦点を当てた異常検知用の画像データセット。現時点で15種類のデータセットが公開されており、種類が豊富。
よく論文でベンチマークとして使われている。

https://www.mvtec.com/company/research/datasets/mvtec-ad/

### [ADFI](https://adfi.jp/ja/download/)
最近公開された異常検知用の画像データセット。
サイトは日本語なのでわかりやすい。外観検査などに使用できる。

https://adfi.jp/ja/download/

## 時系列データ系
### [心電図・呼吸データ](http://www.cs.ucr.edu/~eamonn/discords/)
2005年に公開された時系列データセット。心電図データや呼吸データなどが公開されている。

http://www.cs.ucr.edu/~eamonn/discords/

### [E-Commerceデータ](https://github.com/aws-samples/amazon-lookout-for-metrics-samples/blob/main/getting_started/ecommerce.zip)
Amazonが公開しているデータセット。プラットフォームと利用国ごとの、閲覧数・収益を1時間おきに記録した履歴データ。

https://github.com/aws-samples/amazon-lookout-for-metrics-samples/blob/main/getting_started/ecommerce.zip

## 音声データ系
### [機械操作音データ](https://zenodo.org/record/3351307#.YhX0pYrP3Zl)
小型機械の操作音のデータセット。３つのサブデータセットが含まれている。

https://zenodo.org/record/3351307#.YhX0pYrP3Zl

### [様々な音のデータ](https://research.google.com/audioset/)
Googleが公開している音声データ。人の声、動物の鳴き声、楽器の音などが含まれている。

https://research.google.com/audioset/

# 異常検知の関連記事
https://qiita.com/umapyoi/items/aa7c829b4591653f1b50

https://qiita.com/umapyoi/items/ddd45a47aa79ccbde28b

https://qiita.com/umapyoi/items/5a0e21338c64fc7c44e2
[Golang] [標準logライブラリ] GCPの構造化ログにX-Cloud-Trace-ContextのtraceIdをセットする

## やったこと

前回の記事で下記の課題があった。それを改善したのが本記事の内容。

> サービス運用では同時に複数のアクセスが考えられるため、traceId等でログを追跡できるようにする必要があります。アクセスがたまにしかないようなフェーズではいいかもしれないけど、X-Cloud-Trace-Contextを使用してリクエストとログを一意にできるようにすることは必須だと思うので今後やる。

https://qiita.com/t_morimori777/items/7040b6ea025db4e54630


## はてなブログに掲載しています。

https://moritomo7315.hatenablog.com/entry/go-traceid-logging
カレントディレクトリで管理者権限でPowerShellを開く1行

## はじめに

管理者権限でPowerShellを開くと、意図しないフォルダがカレントディレクトリになってしまい不便でした。「カレントディレクトリで管理者権限でPowerShellを開く」という動作が、初心者でも覚えられるレベルで、1行で実現できたので、メモを残します。

## 前提

* コマンドラインで作業していて管理者権限が必要だとわかった時点で使う
* 環境を引き継いで管理者権限での作業を行いたい
* 新たなウィンドウが開いても良い
* 特別な設定が必要ない
  * このページからの1行コピペで実現できる

## コード
### PowerShellから

```PowerShell
$cd=(pwd).path; Start-Process powershell -ArgumentList "-NoExit cd $cd" -Verb RunAs
```

省略形：

```PowerShell
$cd=(pwd).path; start powershell -a "-noe cd $cd" -v runas
```

### コマンドシェル(cmd)から
```bat
@powershell -NoProfile -ExecutionPolicy Unrestricted Start-Process powershell -ArgumentList '-NoExit cd %CD%' -Verb RunAs
```

省略形：

```pssu.bat
@powershell -nop -ex un start powershell -a '-noe cd %CD%' -v runas
```

#### 補足
* 例えば`pssu.bat`という名前でバッチファイルを作ってパスの通っているところに置いておくと
  * PowerShellからは`cmd /c pssu`で呼び出して使えます。
  * エクスプローラーのアドレスバーで`pssu[Enter]`とタイプすると、そのフォルダで管理者権限のPowerShellが開けます。
* `-ExecutionPolicy Unrestricted`は環境により省略可能です。

### 追記(2022/8/11)
OneDriveなどでマウントされている、記号や空白が含まれているパスからでは、PowerShellでのパス指定が失敗することがありました。その場合は、コマンドシェルで管理者権限に昇格してから、PowerShellに切り替えると大丈夫です。
1行ではないですが...
```su.bat
@powershell -nop start cmd -a '/k cd %CD%'-v runas
```
```ps.bat
@powershell -nol
```
ウィンドウが引き継がれるので、背景色による区別はできませんが、プロンプトで判別できます。
```bat
C:\bin>ps
PS C:\bin>
```

### 動作環境

* Windows10 Home 21H2
* PowerShell 5.1

```
OS 名:                  Microsoft Windows 10 Home
OS バージョン:          10.0.19044 N/A ビルド 19044
PSVersion:              5.1.19041.1320
```

## 説明

(カレントディレクトリの値を覚えておき、)新たなプロセスで(`Start-Process`)PowerShellを管理者権限で(`-Verb RunAs`)起動する。
その際に、「(記憶しておいた)カレントディレクトリに移動して、ウィンドウを閉じない指定(`-NoExit`)をする」、というパラメータを付ける。


## 参考
以下の記事を参考に、PowerShell用にアレンジしてみました。

* `cmd /k`が`powershell -NoExit`に置き換えられる
* `cmd`の自動変数である`%CD%`をそのまま使うか、
* PowerShellでは自前で準備しておいて展開して使う

https://qiita.com/nanagami1369/items/c5b923ec5d29c0267bc6

### ドキュメント
* [PowerShell exe について - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/module/Microsoft.PowerShell.Core/About/about_PowerShell_exe?view=powershell-5.1)
* [Start-Process (Microsoft.PowerShell.Management) - PowerShell | Microsoft Docs](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.management/start-process?view=powershell-5.1)
[JavaScript][メモ]popstateイベントをサンプルコードで挙動確認

# はじめに

（注）「～が解決した」みたいな記事じゃなくて、popstateイベントについてのメモです。

業務中、とある画面でブラウザボタンを押すとbfcache（ブラウザバック時に使うキャッシュ）が悪さをして、想定外の挙動をしてしまう、という状態だった

## 状況

A画面

①↓　↑②　↓③

B画面

①ボタンを押して画面遷移（POST送信による遷移）

②ブラウザバックで画面遷移

③再度ボタンを押して画面遷移→①でキャッシュに保存された値でリクエストしてしまいエラー
（具体的には、楽観ロックエラー）

## 対応策としてのpopstateイベント

この時に②でブラウザバックで遷移後、この「ブラウザバックしたこと」を検知して、ブラウザバックしたのであれば、強制的にリロードしてしまおう、と考えました。

## サンプルコードで試してみる

いくつか記事を拝見しましたが、自分の理解力が乏しく自分のやりたいように動いてくれるかわからなかったので、サンプルコードを自作して挙動を確認

### A画面

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>A</title>
    <script>
    history.replaceState(null, null, null);
    window.addEventListener('popstate', function(e) {
        alert('popstate!!');
    });
    </script>
</head>
<body>
    <h1>indexAです</h1>
    <a href="./indexB.html">Bへ遷移</a>
</body>
</html>
```

いくつか書いてある参考記事（本記事文末）通りですが、

```javascript
history.replaceState(null, null, null);
```

これで、この画面の履歴（history）を置き換えます。

大事なのは第3引数で、ここはhistoryに保存するurlを指定します。
nullにすると現在のurlを保存するようになります。

そして、次に同じ画面に遷移した際にhistoryを上書きします。

```javascript
 window.addEventListener('popstate', function(e) {
        alert('popstate!!');
    });
```

ここではブラウザバックされた際の処理を書いています。

今回は先ほどのreplaceStatusで必ずhistoryに履歴が保存されるので、必ずブラウザバックした際にこの処理を実行することになります。

popstatusはブラウザの履歴が変更された際に発火するイベント

### B画面

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>B</title>
</head>
<body>
    <h1>indexBです</h1>
    <p>ブラウザバックしてください</p>
</body>
</html>
```

ただの遷移用のページです。

想定では、ここに遷移したらブラウザバックして、遷移先でalertが動く挙動です。

### 挙動結果

完全に想定していた挙動ではありませんでした。実際の挙動は以下の通り。

A画面・・・③

①↓　↑②

B画面

①ボタンを押して画面遷移（POST送信による遷移）

②ブラウザバックで画面遷移・・・※ここで検知してほしかったが機能せず

③再度ブラウザバックしようとするとpopstateイベントが発火し、alertが実行

③でpopstateイベントが発火するので、今回のやりたいことは実現できなさそう。。。

### 結論

今回はこのpopstateを使った解決はできないと判断し、他の方法で解決しました。

とはいえ、完全にブラウザバックを禁止して単一的な遷移フローのサイトを作る場合はいいかもですね。
（あんまりユーザーライクじゃない気も、、、）

# 参考記事

参考にさせていただき、ありがとうございました。

[https://zenn.dev/k_kudo/articles/9b3633f4beb0b2](https://zenn.dev/k_kudo/articles/9b3633f4beb0b2)

[https://yutaihara.com/archives/512](https://yutaihara.com/archives/512)

[https://qiita.com/dkdkd335/items/5749cd740d876a9b88d5](https://qiita.com/dkdkd335/items/5749cd740d876a9b88d5)

[https://rainbow-engine.com/javascript-popstate-trigger/](https://rainbow-engine.com/javascript-popstate-trigger/)

# 最後に

たかが１つのJSのAPIの理解に時間かけちゃいましたが、想定通りに動いてくれないとわかったので、まあよしとします。

こうやってゆっくりでも知見を広げて、JSと仲良くなれればと思います。
EBSのプレウォーミングについて

## はじめに
EBSボリュームは新規作成または空である場合初回からパフォーマンスが最大化されているがスナップショットから復元したボリュームはS3からデータがプルダウン
されてボリュームに対する書き込み処理が発生するため、初回アクセス時にはフルパフォーマンスで利用できないという問題がある。
ではどうすればいいのかというと、以下の2パターンの解決方法が存在する。

- Amazon EBS ボリュームの初期化
- Amazon EBS 高速スナップショット復元 (FSR)

## Amazon EBS ボリュームの初期化

ボリュームの初期化とはスナップショットから復元したボリュームの全てブロックに対して読み取りを行う事である。
ddまたはfioコマンドを利用してブロックの読み取り処理を行う。
やり方は以下のリンクを参照。

- Linux

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-initialize.html#ebs-initialize-linux

- Windows

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ebs-initialize.html

## Amazon EBS 高速スナップショット復元 (FSR)
FSRを利用するとスナップショットから復元したボリュームは完全に初期化された状態で提供される。
FSRを利用するには各スナップショットに対してFSRを明示的に有効化する必要がある。
FSRの有効化はAWSマネジメントコンソール、CLI、APIから可能。

- Linux

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-fast-snapshot-restore.html

- Windows

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ebs-fast-snapshot-restore.html

## 料金
最低1時間単位で課金される
https://aws.amazon.com/jp/ebs/pricing/

## 所感
利用料がそれなりにかかるのでコスト削減の為にも、使い道をよく検討する必要がある。
キャッシュやDBなどのデータ領域で復元直後から高いI/Oパフォーマンスが即座に求められる場合は利用する価値がそれなりにあると思う。
また、スナップショットを世代管理しているワークロードなどでは、例えば直近1世代分は有効化し、他の世代に関しては無効化しておくなどの工夫も必要。
Rails コメント投稿機能（deviseなし）

# 前提
Ruby : 2.6.5
Rails : 6.1.3
deviseは使用していません
# モデル作成
```
$ rails g model comment content:string user_id:integer post_id:integer
$ rails db:migrate
```

``` user.rb
  has_many :comments
```

```post.rb
  has_many :comments
```


```comment.rb
class Comment < ApplicationRecord
  validates :content, { presence: true, length: { maximum: 100 } }
  belongs_to :user
  belongs_to :post
end
```
# ビューの作成
```ruby:posts/show.html.erb
<%= form_with(model: [@post, @comment], local: true) do |f| %>
<textarea name="content"><%= @comment.content %></textarea>
<input type="submit" value="コメントする">
<% end %>
<p>コメント件数：<%= @comments.count %></p>
<% @comments.each do |c| <div>
<a href="/users/<%= c.user.id %>"><%= c.user.name %></a>
<%= c.content %>
<%= link_to("削除", "/comments/#{c.user.id}/destroy", {method: "post"}) %>
<% end %>
<%= paginate @comments %>

```
# コントローラの作成

```comments_controller.rb
def create
    post = Post.find(params[:post_id])
    @comment = post.comments.new(comment_params)
    @comment.user_id = current_user.id
    if @comment.save

      flash[:notice] = 'コメントを作成しました'
      redirect_to("/posts/#{params[:post_id]}")
    else
      flash[:notice] = 'コメントの作成に失敗しました'
      redirect_to("/posts/#{params[:post_id]}")
    end
  end
```
```posts_controller.rb
def show
    @post = Post.find_by(id: params[:id])
    @user = @post.user
    @likes_count = Like.where(post_id: @post.id).count
    @comment = Comment.new
    @comments = @post.comments.page(params[:page]).per(7).reverse_order
  end
```
# 参考記事
[【Rails】コメント機能の実装手順メモ](https://qiita.com/kurawo___D/items/d2fefdd329f5310113aa#4-2comments%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%A9%E3%81%AE%E4%BD%9C%E6%88%90)
[【Rails】コメント機能の実装](https://qiita.com/__kotaro_/items/8a6bda99dab61d2a72a5#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
[[Ruby on rails]コメント機能をつける](https://qiita.com/ki_87/items/58800e49461ec7c289a4)
Railsでjsonデータを返す

## モデルを作成

まずは返却したいデータを作成したいのでモデルを作成する。

```ruby
rails g model Task title:string body:string
```

## Rails consoleでデータを作成

モデルができたら実際のデータをRails consoleで作成する。

```ruby
rails c

Task.create(titile: "jsonデータを返す", body: "railsをapiとして使いたいのでデータをjson形式で返したい")
```

## controllerを作成する

jsonデータを返すためのアクションを作成する準備としてコントローラを作成する。

```ruby
rails g controller api/v1/tasks
```

## routes.rbの編集

リクエストが通るようにroutes.rbを編集する。

```ruby
namespace 'api' do
  namespace 'v1' do
    resources :tasks
  end
end
```

## controllerの設定

controller内でjsonデータを返せるように’respond_to’を使い’.json’と言うリクエストが来たときの処理を記述する。

```ruby
class Task < ApplicationRecord
  def show
    @task = Task.find(params[:id])
    respond_to do |format|
      format.json {render json: @task} # @taskの情報がjsonデータとして返る
    end
  end
end
```

## アプリにリクエストを送る

これでjsonデータが返るはずなのでcurlコマンドを使いクエストを送る。

```
% curl "localhost:3000/api/v1/tasks/1.json"
```

下記のデータが返って来ればOK

```
{"id":1,"title":"jsonデータを返す","body":"railsをapiとして使いたいのでデータをjson形式で返したい","created_at":"2022-01-01T00:00:00.000Z","updated_at":"2022-01-01T00:00:00.00Z"}
```
git statusのmodifiedが消えない

### コミットした後、git statusすると再度同じmodifiedが表示される。

```markdown
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   data/postgres/pg_stat_tmp/db_0.stat
        modified:   data/postgres/pg_stat_tmp/db_13117.stat
        modified:   data/postgres/pg_stat_tmp/global.stat

no changes added to commit (use "git add" and/or "git commit -a")
```

### 解決法

- Git管理する必要がなければ、Git管理から除外する。
- git add（ステージングに追加）はしない。

```markdown
$ git rm --cache data/postgres/pg_stat_tmp/db_0.stat
$ git rm --cache data/postgres/pg_stat_tmp/db_13117.stat
$ git rm --cache data/postgres/pg_stat_tmp/global.stat

$ git commit -m "remove data/postgres/pg_stat_tmp/"
```

- 対象のファイルがGit管理から外れているか確認する。

下記のエラー（検索対象ファイルについて、Git管理上のどのファイルとも一致していない。という旨のメッセージ）が出ると、Git管理から除外されていることがわかる。

```markdown
$ git ls-files --error-unmatch data/postgres/pg_stat_tmp/db_0.stat
$ git ls-files --error-unmatch data/postgres/pg_stat_tmp/db_13117.stat
$ git ls-files --error-unmatch data/postgres/pg_stat_tmp/global.stat

error: pathspec 'data/postgres/pg_stat_tmp/global.stat' did not match any file(s) known to git
Did you forget to 'git add'?
```

- 再度`git status`すると、Untracked files(未追跡ファイル)として出現する。

```markdown
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        data/postgres/pg_stat_tmp/

nothing added to commit but untracked files present (use "git add" to track)
```

- Untracked files(未追跡ファイル)を削除する。

```markdown
$ git clean -df
```
- 再度 git statusすると、Untracked files(未追跡ファイル)が消えていることがわかる。

```markdown
$ git status
On branch master
nothing to commit, working tree clean
```
以上

### 参考
https://teratail.com/questions/274055

https://awesome-linus.com/2019/05/13/git-clean-untracked-files-delete/
Play console上のFlutterアプリ更新手順メモ

#バージョンを更新
pubspec.yaml内のバージョンを更新する

```
version: 1.0.0+3
```

#Appbundleファイルを作成する
```
$ flutter build appbundle
```

下記フォルダにaabファイルが作成される
build\app\outputs\bundle\release\app-release.aab

#Play Consoleにファイルアップロード
製品版　→　新しいリリースを作成　→　AppBundle内にアップロード
リリースの詳細に修正箇所などを記載
保存　→　リリースのレビューを確認

確認して公開で完了
メール（.eml）を VSCode でプレビューできる機能拡張

開発環境ローカルではメールアプリを利用していなかったため導入してみました。

## インストール

https://marketplace.visualstudio.com/items?itemName=TomasHubelbauer.email-viewer


## 利用方法
​
VSCode の上でエクスプローラー内のファイルを選択するとプレビューできる。
​
1. エクスプローラーにファイルが表示されるようにワークスペースを開く。
2. エクスプローラー内のファイルを選択する。​

日本語メールも問題なし。
Rust 言語仕様03　スタックオーバーフローとVector型、Box Pointer

スタックオーバーフローとVector型、Box Pointerについてのアウトプットです。

### スタッオーバーフローとは
変数に入れられる限界を超えることを言います。

``` rust
let a1: [u8; 9000000] = [1; 9000000]; // エラーになります。
let a1: [u8; 7000000] = [1; 7000000]; // コンパイルされます。
```

### Vector型

実行時に変更していきたい時に使用します。
ポインターとレングスとキャパシティーがあり、レングスとキャパシティーに要素数を持っている.
Heapに格納されるときに要素数が格納され、Heapには1レングス４バイトの要素が入っている。

```rust
let mut v1 = vec![1, 2, 3, 4];
let v2 = vec![5, 6, 7, 8];
let mut v3 = vec![9, 10];
println!("Stack address of v1 is: {:p}", &v1);
println!("Stack address of v2 is: {:p}", &v2);
println!("Heap memory address of v1: {:?}", v1.as_ptr());
println!("Len of v1 is: {}", v1.len());
println!("Capacity of v1 is: {}", v1.capacity());
```

#### 操作方法

```rust
// 挿入
v1.insert(1, 10);
println!("{:?}", v1);
// 削除
v1.remove(0);
println!("{:?}", v1);
// 連結
v1.append(&mut v3);
println!("{:?}", v1); // [1,2,3,4,9,10]
println!("{:?}", v3); // []
```

### Box pointer
スタックに存在するデータをヒープに移動し移動させたデータをbox pointerとして所有します。
使い道はサイズが決まらないデータをヒープ入れておいて、そのデータのポインターだけスタックに所有し、コンパイが通るようになる。

```rust
let t1: (i64, String) = (10, String::from("hello")); // タプル
println!("Stack address of tuple data is: {:p}", &t1);
println!("Heap memory address of t1.1: {:?}", t1.1.as_ptr());
println!("Len of t1 is: {}", t1.1.len());
println!("Capacity of t1 is: {}", t1.1.capacity());

// Box Pointerを作る
let mut b1 = Box::new(t1);
(*b1).1 += "world";
println!("{} {}", b1.0, b1.1);
// &を使ってb1が格納されているアドレスを確認する
println!("Stack address of box pointer is: {:p}", &b1);
println!("Heap address of tuple data is: {:p}", &b1);
```

## 最後に
最近`Rust`についてなのかメモリ管理ついてなのかわからなくなります。それくらい`Rust`ってコンピュータに近い言語なんだと思いましたし、操作できる言語なんだと思いました。
以前まではなんとなくだったんだと感じました。イメージできるくらいメモリ管理について知れたような気がしてきました。
TypeScriptとは何かを直感的に掴む。（その１） 

## はじめに
この記事は各々の理由でこれからTypeScriptに関わることになるけど、
ガチガチの入門書とか読みこむのは大変だし、要点さえ掴めれば勝手に自走して身につけられるよ！
っていう忙しい人（めんどくさがり？）向けにざっくりと「TypeScriptとは何ぞや？」のきっかけになる部分を説明します。

キチンと知りたい方は今の時代ここやGoogleやYoutubeで検索すれば素晴らしい解説が多く見つかるのでそちらの方をどうぞ。
（本当にありがたき…。）

## 前提条件
・プログラミング言語（種類問わず）でのコーディング経験がそれなりにある。
・JavaScriptをある程度理解している。
・オブジェクト指向がなんとなく分かる。

## コーディングする上での理解
TypeScript未経験だけどさっさとコーディングして感覚的に覚えたいって人は多分ここが一番知りたい部分だと思いますので、まずここから説明します。
TypeScriptをざっくりと一言で表すと
**「JavaScriptに型定義とクラス定義を可能とした言語」**
となります。
TypeScriptの名前のTypeはこの型定義から来てるんですね。~~（多分）~~
基本的にJavaScriptの上位互換として頭に入れて大丈夫です。
なんならJavaScriptのソースそのままでも扱えるので、JavaScript書ける時点でTypeScriptも割と書けるということになります。

これが何でかっていうと、TypeScriptファイル(.ts)をコンパイルするとなんやかんやでJavaScriptファイル(.js)に変換されるからです。

## コーディングサンプル
今回は「TypeScriptファイルの実行」と「変数の型定義」を説明します。

まずは「TypeScriptファイルの実行」を説明します。

```typescript:increment.ts
function increment(num) {
    return num + 1;
}
console.log(increment(999));
```

ファイル拡張子は「ts」でTypeScriptのものですが、中身はJavaScriptのみの文法となります。
関数の引数をインクリメントしてコンソールに表示するだけの単純な処理です。
まず実行までをおこないますが、TypeScriptはJavaScriptとは異なり、コンパイルしてJavaScriptファイルに変換する必要があるため、コンパイルします。

↓コンパイル結果

```
```

何も表示されません。（＝コンパイルが成功したことを示します。）
コンパイルに成功した場合、tsファイルと同名のjsファイルが作成されます。

↓変換結果

```javascript:increment.js
function increment(num) {
    return num + 1;
}
console.log(increment(999));
```

tsファイルと中身も全く同じですね。（元がJavaScriptのみなので当然ですが。）
このjsファイルを実行します。

↓実行結果

```
1000
```

結果は想定通りですね。
まとめると、「TypeScriptファイルの実行」とは以下の流れを指します。

:::note info
TypeScriptファイルをコンパイルする。
↓
JavaScriptファイルに変換する。
↓
変換結果のJavaScriptを実行する。
:::

次に、「変数の型定義」を説明します。
先ほどのtsファイルを例として、

```increment.ts
function increment(num) {
    return num + 1;
}
console.log(increment(999));
```

これに型定義を加えると、以下のようになります。

```increment.ts
function increment(num: number) {
    return num + 1;
}
console.log(increment(999));
```

引数「num」の部分に「: number」が付与されました。
これは引数「num」に数値型が定義されたことを示します。

これをコンパイルして、JavaScriptファイルに変換します。

↓変換結果

```increment.js
function increment(num) {
    return num + 1;
}
console.log(increment(999));
```

型定義前と全く同じ内容になりました。
このファイルを実行すると

```
1000
```

全く面白みもないですが想定通りです。
このことから、tsファイルをコンパイルすると単純に型定義が外されたjsファイルになるということが分かります。
tsとjsでどのように互換性が保たれているかの分かりやすい例になるかと思います。
（あくまで型定義の場合の話ですが。）

ちなみに、定義した型と違う型の値を入れた場合、

```increment.ts
function increment(num: number) {
    return num + 1;
}
console.log(increment("こんにちは"));
```

数値型として定義されている引数「num」に文字列「こんにちは」を入れてみます。
これをコンパイルすると

```
increment.ts:4:23 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

4 console.log(increment("こんにちは"));
                        ~~~~~~~


Found 1 error.
```

このようにエラーとなり、jsファイルに変換されません。
これによって実装者の想定と異なる変数値のやりとりをコーディング段階で防ぐことができます。
（このTypeScriptの型定義がいわゆる「静的型付け」と呼ばれる。JavaScriptは「動的型付け」。）

## さいごに
TypeScriptの正体と書き方をさっさと知りたい（私みたいな）せっかちさん向けに記事を書きました。
そのため、TypeScriptのメリットデメリットや環境構築などの話は意図的に省略しています。
そこらへん詳しく知りたい人は各々で調べてね！素晴らしい参考サイト様も下に掲載してます。

次回はTypeScriptでのクラス定義を書きます。

## 参考サイト様
TypeScript入門『サバイバルTypeScript』〜実務で使うなら最低限ここだけはおさえておきたいこと〜
https://typescriptbook.jp/
ARM版Chromiumのパフォーマンスの確認

#概要

[WebXPRT3](https://www.principledtechnologies.com/benchmarkxprt/webxprt/)でARM版Chromium(Chrome)のパフォーマンスチェックを行った。

#テスト環境

|種類| 内容 |
|:--:|:---|
|デバイス| M1 MacBook Pro 2021 (Apple M1 Pro: 高効率8 + 2) |
|VM| UTM v3.0.4　（QEMU)　(GPU support:disable) |
|VM上のOS| Ubuntu20.04|
|割り当てたCPU| 6 core | 
|割り当てたRAM| 16GB |

#結果
自分でコンパイルしたChromiumのパフォーマンスがUbuntu向けに用意されているものより悪い

| 種類 | 結果 | 追記 |
|:--:|:--|:--
|ARM版UbuntuでセルフコンパイルしたChromium| 121 | VM上で動作|
|ARM版Ubuntu向けに用意されているChromium | 260 | VM上で動作|
|ARM版Ubuntu付属のFirefox | 247 | VM上で動作|
|M1 MacBookProで動作させたChrome | 317 | コア数:高機能8+2 | 


# スクリーンショット

### ARM版UbuntuでセルフコンパイルしたChromium on UTM
`VMのGPU support`:disable
 ![スクリーンショット 2022-02-23 16.24.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/ae6afbf2-8b4f-fa40-c694-348b42185ede.png)

### ARM版Ubuntu向けのChromium on UTM
`VMのGPU support`:disable
apt-get でインストール可能な `chromium-browser`

![スクリーンショット 2022-02-23 17.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/ed56e1c9-ec33-0c5d-eebe-29a31bed7296.png)


### ARM版Ubuntu20.04付属のFirefox on UTM
`VMのGPU support`:disable
![スクリーンショット 2022-02-23 16.10.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/38977032-7bdd-8d84-2314-17ea7da4f735.png)

### M1 MacBook Proで動作させたChrome
![スクリーンショット 2022-02-23 16.37.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/1161902f-ac67-400d-308d-78cca06cdcf2.png)
よく使うLinuxコマンドについてまとめてみた

# Linuxについて

## Linuxコマンドのあれこれ


| コマンド | 正式名称 | 意味 |
|-----------|------------|------------|
| man | manua | マニュアル         |
| cat     | catenate / concatenate      | 連結する       |
| cp      | copy        | コピー         |
| mkdir | make directory | ディレクトリ作成  |
| rmdir | remove directory | ディレクトリ削除 　※中身がからの場合のみ |
| rm  | remove  | 削除  |
| mv | move | 移動 |
| cd    | change directory     | ディレクトリ変更     |
| pwd | print working directory | 作業中ディレクトリ表示|
| ls | list | リスト |

こうやって略さずにみると何をしてるかわかりやすいですよね。

## コマンドオプション

`-`の後に指定されたアルファベット1文字または、
`--`の後に指定された値をつけて、コマンドにオプションを指定できる。

### 例
- `ls`コマンドの`-a`オプション → 隠しファイルも全て表示してくれるオプション

```
% ls -a
.	..	html
```

- `brew`コマンドの`-v`オプション（`--version`でも同じ挙動）

```
% brew -v
Homebrew 3.3.16

% brew --version
Homebrew 3.3.16
```
【初心者向け】AZ-900/AZ-104を取得した後なにもかも忘れた自分がAzure ADとサブスクリプションの関係を思い出す

こんにちは。torippy1024です。
タイトル通りとなりますが、資格取得後、Azureに関する知識をほぼ忘れてしまったため、勉強メモとして初心者向け記事を書いてみることにしました。
一度理解した内容を思い返すためのメモですので、詳細な解説はしませんが「あーそうそうこうだった！」と思い出すための手助けとなれば幸いです。
(逆に言うと、ちゃんと知っている人から見ると「なんだこの初心者丸出しの記事！！」と怒られるかもしれません。素人ですいません)

## Azure AD/管理グループ/サブスクリプション/リソースグループ(RG)の関係
Azureを構成する重要な概念に、Azure AD(Azure Active Directory)、管理グループ、サブスクリプション、リソースグループがあります。これらはそれぞれ上位のオブジェクトと1:Nの関係があります。また、同じオブジェクト同士で入れ子の構造をとれるのは管理グループのみです。(つまり、管理グループのみが、管理グループの下にもう一つの管理グループを作ることができ、それ以外はできません)

|  名前  |  説明  |
| ---- | ---- |
|  Azure AD  |  Azure上のActive Directory. 1つ以上のドメインを持つ。 |
|  管理グループ  |  サブスクリプションをまとめた管理グループ。 |
|  サブスクリプション  |  課金・請求の単位。サブスクリプションは複数のAzure ADに所属することはできない。 |
|  リソースグループ  |  リソースを管理するための管理グループ。  |
|  リソース  |  Azureサービスなどのリソース。  |

Microsoftのこちらの図に書かれている通りですね。
https://docs.microsoft.com/ja-jp/azure/role-based-access-control/rbac-and-directory-admin-roles



## Azure ADとサブスクリプションの関係
注意しなければならないのですが、Azure ADの中にサブスクリプションがある、という考え方は少し違うということです。

**Azure ADの管理者は、サブスクリプションの管理者ではないのです。**Azure ADとサブスクリプションはそれぞれ独立の関係と考えるべきです。
そして、ある特定のAzure ADをサブスクリプションが「信頼(Trust Relationship)」することで、そのAzure ADと関連付くと理解するのが良いです。

サブスクリプションの全てがそのAzure ADの配下に所属すると理解するのではなく、「信頼したので、そのAzure ADによるユーザーを使ってこのサブスクリプションにアクセスさせてあげるよ」という意味と理解するのが良いと思います。
https://docs.microsoft.com/ja-jp/azure/active-directory/fundamentals/active-directory-how-subscriptions-associated-directory


## 主なADロールとAzureロール
Azureにおけるユーザーは、Azure Active Directory上で管理されています。
RBACによって認証・認可が設定され、ユーザーにロールを割り当てることで権限設定が行われます。

先述した通りですが、Azure ADに対する権限があるからといって、サブスクリプション(およびその配下のリソースグループやリソース)に対する権限があるとは限りません。
Azure ADに対する権限を与えるロールはADロール、サブスクリプションに対する権限を与えるロールをAzureロールと呼びます。
(まあ、グローバル管理者であれば、自分自身を昇格させることで、Azure ADを信頼している全サブスクリプションに対する権限を取得できるのですが・・・・・・。　
https://docs.microsoft.com/ja-jp/azure/role-based-access-control/elevate-access-global-admin)


ロールについては非常に多くの種類があり、しかもカスタマイズすることができるのですが、
主なロール(試験によく出てくるという意味も含める)は以下です。

| ロール種別 |  名前(日本語)  |  名前(英語)  |  説明  |
| ---- | ---- | ---- |---- |
| ADロール |  グローバル管理者/全体管理者  | Global Administrator |  Azure Active Directory(AAD)に対して設定されるロール。AADの管理者であり、AADに対する全ての権限を持つ。また自分自身を昇格させることで、配下のサブスクリプションに対する全権限を取得できる |
| Azureロール |  サブスクリプション管理者 | Subscription Administrator  | サブスクリプションに対して設定されるロール。サブスクリプションに対する全ての権限を持つ。 |
| Azureロール |  所有者 |  Owner | 特定のリソースグループまたはリソースに対する操作(作成・変更・削除)権限およびユーザーアクセス設定権限の両方を持つロール。  |
| Azureロール |  共同作成者 |  Contributor | 特定のリソースグループまたはリソースに対する操作権限のみを持つロール。  |
| Azureロール |  閲覧者 |  Reader | 特定のリソースグループまたはリソースに対する読み取り(Read)権限を持つロール。   |
| Azureロール |  ユーザー管理者 |  User Access Administrator | 特定のリソースグループまたはリソースに対するユーザーアクセス権を管理することができるロール。  |


本日の勉強メモは以上です。
認識誤りなどありましたらこっそり教えていただけると助かります。
エンジニアが学ぶべき言語は？

Q：エンジニアが学ぶべき言語は？
A：日本語
まあ日本で仕事するならそうだよね。状況を説明できないエンジニアが結構いるよね。

追記：With ChatGPT, After ChatGPTの時代において、学ぶべき言語は、「英語」になりました。お詫びして訂正いたします。
Ruby returnで複数の値を返す

# はじめに
学習記録アプリの開発中、グラフの作成のために１週間分の日付の取得する処理を、「今週」「最後に学習した日の週」「最後に学習した日の前週」の3つそれぞれ記載していました。Rubyでは、メソッドの戻り値を複数返すことができるということなので、3つの処理を1つにまとめていきたいと思います。

# 環境
- rails 6.0.4.4
- ruby 2.6.5
- chart.js 2.8.0


# 複数の戻り値を返し方
returnの後にカンマで区切って返す値を記述します。

```
def calc(a, b)
  x = a + b
  y = a - b
  return x, y
end

a = 20
b = 15
x_1, y_1 = calc(a, b)
puts x_1, y_1
```
このように、x_1とy_1の変数にそれぞれ値が入っています。

```ターミナル.
35
5
```
ちなみに1つの変数に対して、複数の戻り値を代入すると、自動的に配列に変換されます。
正確には、データそのものが配列形式で入るのではなく、データの場所の情報が入り、配列と同じ記述で取り出せるようです。

# 現在の状況
今週分の日付を取得（週初めの日付、週終わりの日付、１週間分の日付、１週間分の日付のJSON形式、の4つを定義しています）

```textbook_controller.rb
@b_date = Date.today.beginning_of_week
@e_date = Date.today.end_of_week
week_date = week_date_calc(@b_date, @e_date)
@week_date = week_date.to_json.html_safe
```
最後に学習した日を含む週の日付を取得

```textbook_controller.rb
@tb_date = @max_date.beginning_of_week
@te_date = @max_date.end_of_week
week_date = week_date_calc(@tb_date, @te_date)
@week_date = week_date.to_json.html_safe
```
上記週の１週間前の日付を取得

```textbook_controller.rb
@lb_date = @max_date.prev_week
@le_date = @max_date.prev_week(:sunday)
week_date = week_date_calc(@lb_date, @le_date)
@week_date_l = week_date.to_json.html_safe
```
補足
@max_dateは学習記録テーブルで日付の最大値を代入しています。
week_date_calcメソッドは週初めと週終わりの日付を渡して、その間の日付をもつ配列を作成します。

```textbook_controller.rb
def week_date_calc(b_date, e_date)
  w_date = []
  s_date = b_date
  while s_date <= e_date
    w_date << s_date
    s_date += 1
  end
  w_date
end
```
# メソッドを作成
日付を１つ渡して、週初めの日付、週終わりの日付、１週間分の日付、１週間分の日付のJSON形式、の4つのデータを返すメソッドを作成します。

```textbook_controller.rb
def week_date_set(search_date)
  b_date = search_date.beginning_of_week
  e_date = search_date.end_of_week
  week_date = week_date_calc(b_date, e_date)
  week_date_json = week_date.to_json.html_safe
  return b_date, e_date, week_date, week_date_json
end
```
上記、メソッドを使用してコードを書き直していきます。
今週分の日付を取得


```textbook_controller.rb
@b_date, @e_date, week_date, @week_date = week_date_set(Date.today)
```
最後に学習した日を含む週の日付を取得

```textbook_controller.rb
@tb_date, @te_date, week_date, @week_date = week_date_set(@max_date)
```
上記週の１週間前の日付を取得

```textbook_controller.rb
@lb_date, @le_date, week_date, @week_date_l = week_date_set(@max_date.weeks_ago(1))
```
prev_weekメソッドでは前週の週初めを取得してしますので、weeks_agoメソッドに変更しました。

# おわりに

これでコードを直す前と同じ動作をするようになりました。
なお、終わった後に気づきましたが、週初めと週終わりの日付は、メソッドで作成した配列から取得すればよかったので、個別で作成する必要はなかったですね。なので、４つの戻り値を返していますが、実際は2つでよかったです。

# 参照
[関数で複数の返り値を返す／関数の引数は値渡し ― コーディングミスを防ぐには？（2](
https://www.buildinsider.net/language/rubytips/0003#:~:text=%E9%96%A2%E6%95%B0%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E8%A4%87%E6%95%B0%E3%81%AE%E8%BF%94%E3%82%8A%E5%80%A4%E3%82%92%E8%BF%94%E3%81%99%E3%81%AB%E3%81%AF&text=%E6%96%B9%E6%B3%95%E3%81%AF%E7%B0%A1%E5%8D%98%E3%80%82,%E5%A4%89%E6%95%B0%E3%82%92%E6%9B%B8%E3%81%8F%E3%81%A8%E3%82%88%E3%81%84%E3%80%82)
【備忘録】バイオインフォマティクス環境設定

# 【備忘録】バイオインフォマティクス環境設定(macOS Monterey 12.2.1)

「バイオインフォマティクス　〜Pythonによる実践レシピ〜」を購入して、環境構築したときのメモです。

大まかな流れは、以下の通り。
- Xcodeインストール(GUI)
- wgetインストール（コマンドライン）
- Anacondaインストール（GUI）
- condaによるインストール（コマンドライン）


## condaによるインストール

Xcode、 wget、 Anaconda のインストールは省略して、condaのところだけ詳細に記載します。

######まずは、conda自身の確認。
>$conda install conda -y

######チャネル（リポジトリ）の追加。
>$conda config --add channels bioconda
>$conda config --add channels conda-forge

######環境構築。（biopythonは最新にして、pythonは3.8に設定）
>$conda create -n bio python=3.8 biopython=1.79

######環境のアクティベーション。
>$source activate bio

######環境上で諸々をインストール。（細かく分けているのは、どこで失敗したかを確認するため）
>$conda install scipy matplotlib pip pandas cython numba -y
>$conda install scikit-learn seaborn pysam pyvcf -y
>$conda install rpy2  -y
>$conda install r-essentials r-gridextra -y
>$conda install simuPOP dendropy -y

これで設定完了です。
Anacondaを立ち上げて、bioでJupyter-Labを起動します。
brew update が実行できなかった

gitを触っているときに、brew updateやbrew upgradeをためしたところ、
下記のようなエラーメッセージがでた。

```
Error: Running Homebrew as root is extremely dangerous and no longer supported.
As Homebrew does not drop privileges on installation you would be giving all
build scripts full access to your system.
```

訳してみると、「Homebrewの操作はroot権限で行わないでほしい」ということらしい。

sudo や su -でroot権限で操作しているときに、思い立ったように操作したせいみたいだ。

次から気をつけよう。
[JS]IF文の省略

###JavaScriptのIF文の省略形
---
下記のYoutubeを参考にWebアプリケーションを作成している際に
学習の過程で見たことのなかった構文が使用されていたので紹介します。

初期段階ではこのように1~9秒の時に01~09の表記になっていません

![addZeroBefore.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339532/cb676ea9-8061-3cc4-5a4f-a83620415779.png)

完成図はこちらになります。
![addZeroAfter.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2339532/55c7a954-4e03-798f-f5e8-d986894f1113.png)

01~09の表示にするためにaddZeroという関数を作成します。


```main.js
  function addZero(n) {
    return(parseInt(n, 10) < 10 ? '0' : '') + n;
  }
```

if文を省略せずに記述すると以下のようになります。

```main.js
  function addZero(n) {
      if(parseInt(n,10) < 10) {
        return '0' + n;
      } else {
        return '' + n;
      }
  }
```

この様に、条件文に「?」を付けて、”True”の場合の処理を記載し、続いて「:」を付けて、”else”の場合の処理を記載することができます。
今回のようなreturnするだけの処理を書く場合には時短にもなりますし簡単に記述することができます。

このような書き方を学習の過程で目にすることがなかったので勉強になりました。
今回の記述法が実際に現場で使用される書き方かどうかはわかりませんが
書籍などの学習では得られないところが学べたので良かったと思います。
これからも積極的にアウトプットして新たな知識を蓄えていきたいと思います。


https://www.youtube.com/watch?v=fSTQzlprGLI&list=LL&index=2
時系列モデルの”バックワードオペレーター”の類語を調べてみた


# バックワードオペレーターとは
簡単に言うと、時刻tの成分に作用し、後退（Backward）させるもの。
Bをバックワードオペレーターとすると、

``` math
Bs_t = s_{t-1}
```

と定義でき、時系列モデルを数式で簡単に表せる利点がある。
パッと調べたところこの記事がわかりやすかった。↓
[時系列分析:後退オペレータについて](https://messefor.hatenablog.com/entry/2020/08/09/185747)

# 類語を調べてみた
このバックワードオペレーターは、同じような言葉がゴロゴロあり、記事や文献が一通りでヒットしないこともある。気になったので一覧でまとめてみた。

- バックワードオペレーター
- バックワードオペレータ
- バックワードシフトオペレーター
- バックシフトオペレーター
- シフトオペレーター
- ラグオペレーター
- 時間シフトオペレーター
- 後退オペレーター

出典は略。もっとあるかもしれない。
On Demand Resourcesを使う(Swift Concurrency対応)

個人アプリで[On Demand Resources](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/On_Demand_Resources_Guide/index.html#//apple_ref/doc/uid/TP40015083-CH2-SW1)を使いたいところがあり、以下の記事を参考に導入してみました。

https://qiita.com/kukimo/items/39a0eeb40626a4cd364f
https://www.raywenderlich.com/520-on-demand-resources-in-ios-tutorial

仕組みや手順は公式ドキュメントと上記記事を参照するのが早いと思います。
Swift Concurrencyで以下のようなユーティリティを作っておくとより簡単に導入できるよというお話。

```swift:ResourceLoader.swift
import Foundation

/// On Demand Resourceの読み込みを支援
final class ResourceLoader {
    static let `default` = ResourceLoader(bundle: .main)
    
    private let bundle: Bundle

    private init(bundle: Bundle) {
        self.bundle = bundle
    }

    /// tagで指定されたOn Demand Resourceを読み込む
    /// onSuccessで、実際のリソース読み込み処理を実装する
    func load<R>(
        tag: String,
        onSuccess: () throws -> R
    ) async throws -> R {
        let request = NSBundleResourceRequest(tags: [tag], bundle: bundle)
        if await request.conditionallyBeginAccessingResources() {
            // リソースは端末にダウンロードされている
        } else {
            // 端末にリソースをダウンロード
            try await request.beginAccessingResources()
        }
        return try onSuccess()
    }
}
```

使い方はこんな感じ。

```swift
let image = try await ResourceLoader.default.load(
    tag: "MoreImages",
    onSuccess: { UIImage(named: "more_image1") }
)

let url = try await ResourceLoader.default.load(
    tag: "MoreSounds",
    onSuccess: { Bundle.main.url(forResource: "sound", withExtension: "mp3") }
)
```