OmniAICreator/Qiita-1.07M huggingface dataset:
GitでpushしようとしたらPlease make sure you have the correct access rights and the repository exists.というエラーが出た

## はじめに
Gitの学習をしていてエラーが出て躓いたことがあったので備忘録と他にも困った方がいた時の手助けになればと思い記事を書くとにしました。

私はパソコンをもともとデスクトップのWindowsのパソコンを使っていたのですが、持ち運び用として
MacBookを購入しました。　　
そこでMacに慣れるために普段の学習もMacを使ってやってみようと思ってGitの学習をしていた時に出たエラーになります。

今までは普通にGitHubにターミナルからpush出来ていました。
なので普通にできるものとして学習を進めていました。


## Gitでリポジトリにpush出来ない
`git push -u origin master`とターミナルに打ったところ
![スクリーンショット 2023-06-20 9.42.57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/0e800308-ef16-83a8-2cbc-951e1c4c6259.jpeg)
上記画像のようなエラーが発生しました。

ずらずらと長いエラーメッセージが出てきてなんぞや！と思って部分的に翻訳をかけて調べてみたら
「正しいアクセス権があること、およびリポジトリが存在することを確認してください。」と言う意味でした。

## エラーの解決策！！
結論から先に言ってしまうとこのケースだと**sshKeyを再発行すればOK**です。

SShKeyとは...
公開鍵認証のことです。

それでは早速sshKeyを発行していきましょう！


## sshKeyを発行しよう
① sshKeyの作成
```
$ ssh-keygen -t rsa -C hoge@example.com
# 作成するディレクトリとファイル名を聞かれる
# ~/.ssh/id_rsaとなっていれば、なにも入力しないでenterを押す


Enter file in which to save the key(~/.ssh/id_rsa):
# 何も入力せずenterを押す

Enter passphrase (empty for no passphrase):
# 何も入力せずenterを押す

Enter same passphrase again:
# 何も入力せずenterでを押す
```

② ~/.sshのファイルを確認する
```
$ ls ~/.ssh
# id_rsaとid_rsa.pubがあるかどうか確認する
```

## GitHub上で公開鍵を登録する
① GitHubにログインします
② 右上の自分のアイコンをクリック
③ Settings > SSH and GPGkeys > New SSH keysをクリック
![スクリーンショット 2023-06-20 23.40.52（2）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/777e6d5c-8956-eb5b-b239-2f157a647220.jpeg)
![スクリーンショット 2023-06-20 23.41.02（2）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/b40b19d8-5e50-0d09-178d-7cd77e10fdb8.jpeg)
![スクリーンショット 2023-06-20 23.41.17（2）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335067/f0ca99f4-5d56-b9f5-74cc-3605325693ac.jpeg)


Titleを設定するときはわかりやすい名前をつけるといいと思います。
私の場合１つ目は「AWS」と設定してありました。
今回は「Mac」と設定しました。

④ Keyに公開鍵を登録する。　　
　ここで一旦ターミナルに戻って

```
$ less ~/.ssh/id_rsa.pub
# 公開鍵が表示されるので[ssh-rsa]という部分から一番最後のメールアドレスまでコピーします
```

コピーできたらGitHubに戻って、Keyの部分にコピーしたところを貼り付けます。
`Add SSH Key`をクリックしてGitHubに公開鍵を登録します。


## 使用したい秘密鍵を設定する
再度ターミナルに戻ってconfigファイルに使用したい秘密鍵の設定をします。

```
$ vim ~/.ssh/config
```

とターミナルを打ってvim上で編集します。

```
Host github
  HostName github.com
  IdentityFile ~/.ssh/id_rsa
  User git
```

上記内容を登録します。

vimの保存は
`esc`を押して`:wq`で出来ます！

## pushをもう一度やってみる
最初にエラーになったpushをもう一度実行してみます。

```
$ git push -u origin --all
```

**成功しました!!!**
(できた時の画像撮り忘れてしまいました。。。)

GitHubでも確認してみると無事リポジトリの保存ができていました。（安心）


## 最後に
今回のケースはPCなどを変えた時によく発生するエラーのようです。　　
実際に私自身もパソコンを変えた後初めてpushするときに発生したエラーでした。　　
今回のエラーと似たような境遇の方の解決に少しでもお役に立てたら嬉しいです。

では、このへんで。
最後までありがとうございました。
Leetcode 2090. K Radius Subarray Averages

https://leetcode.com/problems/k-radius-subarray-averages/description/

# 難易度
- Medium

```java
class Solution {
    public int[] getAverages(int[] nums, int k) {
        // 初期化
        int[] result = new int[nums.length];
        Arrays.fill(result, -1);

        // Window size の計算
        // 2倍と、Indexのため、+1するみたい
        int windowSize = 2 * k + 1;

        // 元々のデータの長さがWindow Sizeより小さいと、初期化した結果を返す
        if (nums.length < windowSize) {
            return result;
        }

        // prefixSumを保存するための、配列を初期化
        long[] prefixSum = new long[nums.length + 1];

        // prefix sum を保存する
        for (int i = 0; i < nums.length; i++) {
            prefixSum[i + 1] = prefixSum[i] + nums[i];
        }

        // 平均（中間）値に、計算した結果を入れる
        for (int i = k; i + k < nums.length; i++) {
            result[i] = (int) ((prefixSum[i + k + 1] - prefixSum[i - k]) / windowSize);
        }
        return result;

    }
}
```

https://leetcode.com/problems/k-radius-subarray-averages/solutions/3659283/2-method-s-c-java-python-beginner-friendly/


上記の解説を参考しました
Amazon InspectorのSBOM出力を試してみた


Amazon InspectorでSBOMが出力できるようになったので、EC2のSBOMを出力してみました。
SBOMをCycloneDXまたはSPDXでS3に出力することができます。
EC2以外のSBOM出力もInspector管理下になっていれば、Export SBOMsのフィルター変更で出力ができるかもしれません。

#### 事前準備
- SBOM出力を試すEC2やECRの用意
  - EC2のSBOMを出力する場合、EC2がSSM管理下のマネージドノードになっている必要があります。
- Amazon Inspectorの有効化

#### SBOMの出力
1. バケットポリシーに以下の記述を追記したS3を作成します。
    ``` JSON
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "allow-inspector",
                "Effect": "Allow",
                "Principal": {
                    "Service": "inspector2.amazonaws.com"
                },
                "Action": [
                    "s3:PutObject",
                    "s3:PutObjectAcl",
                    "s3:AbortMultipartUpload"
                ],
                "Resource": "arn:aws:s3:::バケット名/*",
                "Condition": {
                    "StringEquals": {
                        "aws:SourceAccount": "AWSアカウントID"
                    },
                    "ArnLike": {
                        "aws:SourceArn": "arn:aws:inspector2:ap-northeast-1:AWSアカウントID:report/*"
                    }
                }
            }
        ]
    }
    ```
1. KMSキーを作成します。
  キータイプ: 対象
  キーの使用: 暗号化および複合化
  キーマテリアルオリジン: 推奨
  のキーを作成し、キーポリシーに以下の記述を追記します。
    ``` JSON
    {
    	"Sid": "allow-inspector",
    	"Effect": "Allow",
    	"Principal": {
    		"Service": "inspector2.amazonaws.com"
    	},
    	"Action": [
    		"s3:PutObject",
    		"s3:PutObjectAcl",
    		"s3:AbortMultipartUpload"
    	],
    	"Resource": "arn:aws:s3:::バケット名/*",
    	"Condition": {
    		"StringEquals": {
    			"aws:SourceAccount": "AWSアカウントID"
    		},
    		"ArnLike": {
    			"aws:SourceArn": "arn:aws:inspector2:ap-northeast-1:AWSアカウントID:report/*"
    		}
    	}
    }
    ```
1. InspectorのExport SBOMsをクリック
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352559/9c0bff85-1c76-9e3f-d26a-2037c912e139.png)
1. フィルターで対象のEC2を指定、今回は対象のEC2のタグを指定します。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352559/21692940-ff96-1ef6-77e8-af35754e4d4d.png)
  EC2のタグ以外には、Lambdaのタグ、アカウントIDイメージタグ、リソースID、リソースタイプ、リポジトリ名、関数名が指定できます。

1. 任意のファイルタイプを選択
1. 作成したS3,KMSキーを指定
1. Exportをクリック
  ![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352559/b177f07e-b8b5-1a6f-fe29-a016e307e2d9.png)
1. S3にSBOMが出力される(数分かかります)
  ![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352559/84c1d0b8-c65e-7168-d716-578b15addfb2.png)
プレモーテムを導入して、ちょっとした文化になったお話。

この記事は[Qiita Engineer Festa 2023](https://qiita.com/official-campaigns/engineer-festa/2023) 参加記事です。
　
### この記事で書くこと
2022年頃からPMとして担当していた開発プロジェクトにおいて、PLやチームメンバーと一緒にプレモーテムを実施した背景、実施内容、その効果を主観をもとに書いてみます。
　
### この記事で書かないこと
「正しいプレモーテムはこれだ！」といった内容は書きません。
あるべき論やベストプラクティスを学びたい方々は、世の中の秀逸な記事やChatGPTさんを参考にされてください。
　
# プレモーテムを導入して、ちょっとした文化になったお話。

## プレモーテムを知るまで

### 取り組み当時の状況
2021年頃から、次世代のリーダーやマネージャーの育成を目指して、自分自身が直接的にプロジェクトを運営する機会を減らし、明確的にPLを立てたプロジェクト運営にシフトし始めました。
最初こそヒヤヒヤする場面もありつつも、それもすぐに無くなり、大きな問題も無くプロジェクトが走りきれるようになりました。
　
一方で、今までと違ってプロジェクトを客観的に見る機会が増えた私にとって、「〇〇はもっと早く気付けそうだな〜」「△△に関しては、プロジェクトスタート時点でも気づくことができたのでは？」と思える部分も出てきました。
ただ、それは決して私が優れているわけでは全く無く、客観的に見やすい役割に移ったからこそ気付けるだけでした。
　
「プロジェクトに取り組むメンバーと一緒に考え、一緒に気づきを得て、事前に対策を打てるようになれたらいいな〜。」
「自分一人で考えるよりも、この仲間たちの知見があれば、もっとすごい気付きが得られるだろうな〜」
「でも、どうすればいいんだろう。。。」
と一人でモヤモヤしていました。

### プレモーテムとの出会い
自社が挑戦を推奨し挑戦による失敗があっても失敗から学びを得ることを大事にしている文化であることや、スクラム開発のレトロスペクティブなど振り返りの文化はあったのですが、「起きてから振り返って改善する」だけではなく、早期に気づく方法はないかな〜と。考えながら様々な勉強会に参加したり、書籍を読み漁ったりしてました。
そんな中、どこで情報を得たのかは思い出せないのですが、 [Google re:Work](https://rework.withgoogle.com/jp/ "Google re:Work") について知る機会がありました。
その中に[プレモーテムの事例](https://rework.withgoogle.com/jp/guides/foster-an-innovative-workplace/#learn-from-failures)が書かれていました。

### プレモーテムって簡単に言うと何？
プレモーテムはプロジェクトの開始前に行うアクティビティで、プロジェクトのリスクを分析する目的で実施するものです。
似た用語として、ポストモーテムというものがあり、ポストモーテムはプロジェクト終了時や障害発生時に振り返って分析を行うものとなります。
（スクラム開発を取り入れていると「レトロスペクティブ」を実施しますが、これも振り返りの一種です。）
　
## プレモーテムの導入

### 導入前夜
まずは、2人のリーダーに、私が半年くらい抱えていたモヤモヤを伝えて、その対策としてプレモーテムというアクティビティを実施したいことを相談してみました。
リーダーたちからは概ね賛同は得られたものの、「あまりにオープンクエッションだと意見が出にくそう」とFBをもらいました。
そのため、ちょっとした縛り（テーマ設定）を入れて、ケーススタディ的な形で、思考・ディスカッション・対策の検討を行うことで進めることにしました。

### プレモーテム導入の効果
明確な効果測定はしていないのですが、プロジェクトを進めている最中、メンバー間の会話でリスクに対する議題が増えました。
また、初回にプレモーテムを実施したプロジェクト以外にも、複数のプロジェクトでアクティビティを実施していますが、それぞれのプロジェクトで大きな問題が起こりにくくなったり、ある種やむを得ない問題も早めに気づけるようになったと感じています。
　
私自身は現在開発チームを離れています。
先日、私が離れた後もプレモーテムという取り組みをしているチームがあると知り、ちょっとした文化醸成に貢献できたな〜と感じて嬉しく思っています。

# Appendix

## 実際に今までやったプレモーテムのテーマ設定

- プロジェクトのリリース後、あなたの実装箇所で本番障害が発生しました。
  - それはどんな障害ですか？
  - その本番障害が起こった要因はなんですか？
  - 現時点から、リリースまでの間にその障害の発生要因を防ぐために何ができますか？

- プロジェクトのリリースリハーサルが失敗に終わりました。
  - 失敗と判断した理由は何でしたか？
  - その失敗を、今からどのように回避しますか？
　
- プロジェクトリーダーが、体調を崩して明日から3週間休むことになりました。
  - どのような影響がでますか？
  - その影響を、今からどのように回避しますか？

- リリース後、このプロジェクトが原因で重大インシデントが発生しました。
  - どのようなインシデントで、どんな影響がでましたか？
  - そのインシデントを、今からどのように回避しますか？

- リリース後、あなたが関わった部分で本番障害がおこりました。
  - それはどのような障害で、どのくらいの影響がでましたか？
  - それは何故発生したと思いますか？
  - 未然に防ぐために、今から何ができますか？

- リリース後、システム起因でCVRがありえないくらい落ちました。
  - それは何故減少したのですか？
  - それを防ぐために、今から何ができますか？

- （新規立ち上げ組織において）1年終了時点で、我々の実績が原因で部署の解散が決まりました
  - それはどのような実績によって解散となりましたか？
  - なぜ、そのような結果になったと思いますか？
  - 未然に防ぐために、これから何をしていきますか？

厳密にはプレモーテムとは違う気もしますが、成功のイメージを持つために似たようなアクティビティもやりました。

- （新規立ち上げ組織において）1年終了時点で、我々の成果が評価され臨時ボーナス100万円/人がでました
  - それはどのような成果だったため評価されたと思いますか？
  - なぜ、そのような成果を出せたと思いますか？
  - その成果につなげるために、これから何をしていきますか？
プログラミング初心者が学ぶ「抽象化」


# はじめに
最近、Pythonの学習をはじめました。学習を進めると「**抽象化**」という概念が登場しました。この抽象化という概念は、ソフトウェア開発において、非常に重要とされているようです。「抽象化」を理解するために自分なりにまとめてみようと思います。私自身まだ学習途中なので、何か間違いがあるかもしれません。もしご指摘やアドバイスがありましたら、ぜひコメント欄からお知らせください。
# 抽象化とは？
抽象化とは、「**複雑なコードを簡潔化し、大切な情報だけに焦点を当てて、その以外の詳細な部分を隠す手法**」です。たとえば、プログラミングでよく用いられる「**関数**」も抽象化の一種です。

関数は、一連の命令をまとめて名前を付け、特定の入力（引数）から出力（戻り値）を計算する一連の手順を表現します。関数はプログラマーにとってブラックボックスのようなものでもあります。その内部で行われる処理の詳細は、関数の使い手は理解していなくても入力と出力の仕組みを知っていれば使うことができます。

たとえば、Pythonの関数で考えてみましょう。
```Python
def add_numbers(a, b):
    return a + b

result = add_numbers(2, 1)  # result  3
```

このadd_numbers関数は、2つの数値を引数として受け取り、それらを足し合わせた結果を返します。この関数を使用する際、私たちは内部の詳細（どのように加算が行われるか等）を知ることなく、必要な結果を得ることができます。

# 抽象化のメリット
抽象化はソフトウェア開発において多くのメリットをもたらします。


- **コードの再利用性**: 抽象化は共通の機能を関数やクラスとしてまとめることにより、それらのコードの再利用性を向上させます。同じコードを何度も書く必要がなくなり、コードの短縮と効率性が向上します。

- **読みやすさと保守性**: 抽象化はコードの詳細を隠蔽し、大まかな概念に焦点を当てることで、コードの読みやすさと保守性を向上させます。抽象化によりコードの理解が容易になり、バグの特定や修正もしやすくなります。

- **モジュール性**: 抽象化は問題を小さな部分に分割し、それぞれを独立したモジュールとして扱うことを可能にします。これにより、大規模なプロジェクトでも、各部分を独立して開発やテストを行うことが可能になり、全体の開発プロセスを効率化します。

- **拡張性**: 抽象化されたコードは、新たな機能を追加する際の柔軟性があります。具体的な実装から疎外されたコードは、新たな要求に対して変更や拡張を行いやすくなります。

# 関数の合成
さらに関数の応用的な使い方として、「関数の合成」と「関数の分解」があります。関数の合成とは、一つの関数の出力を別の関数の入力として使うことです。これにより、より複雑な処理を行う新たな関数を作成することができます。

例えば、次のような関数があるとします。
```Python
def multiply_by_two(x):
    return x * 2

def add_three(y):
    return y + 3
```

これらの関数を合成すると、「数値に2をかけてから3を加える」という新たな関数を作成することができます。
```Python
def multiply_by_two_and_add_three(z):
    return add_three(multiply_by_two(z))

result = multiply_by_two_and_add_three(4)  # result  11
```
これが「関数の合成」の一例です。また、気を付ける点として原則として1つの関数は1つのタスクだけを担当するべきです。関数が複数のタスクを担当してしまうと、その関数が複雑になり、予期せぬバグを生み出す可能性が高まります。また、その関数の再利用性も低下します。したがって、各関数は1つタスクを持つべきです。

一方、「関数の分解」とは、大きな処理を複数の小さな関数に分けることを指します。大きなタスクを一つの関数に押し込めてしまうと、その関数は複雑になり、理解や修正が難しくなる可能性があります。関数を分解することで、各関数は特定のタスクに集中し、それぞれが独立して理解や修正を行うことが可能になります。

たとえば、以下の関数を考えてみましょう。
```Python
def calculate_and_print(a, b):
    result = a * 2 + b * 3
    print(result)
```
この関数は、「計算を行う」タスクと「計算結果を表示する」タスクを一緒に行っています。これを「関数の分解」を行うと、以下のようになります。
```Python
def calculate(a, b):
    return a * 2 + b * 3

def print_result(result):
    print(result)

result = calculate(2, 1)
print_result(result)
```
以上が、「関数の合成」と「関数の分解」についての説明です。これらの概念を理解することで、これらは抽象化の一環として、大きな問題をより扱いやすい形に変換するための有用なツールとなると思います。
# まとめ
ソフトウェア開発における「抽象化」について説明しました。「抽象化」は、複雑さを隠し、大切な情報だけに焦点を当てる手法であり、関数やクラスを使って表現することが一般的です。抽象化により、コードの再利用性が高まり、可読性が向上し、複雑な問題をより扱いやすくなるという利点があります。

また、関数の合成や分解は抽象化の一部と考えることができ、これらを使うことで、より複雑な問題を簡単に解決することが可能になります。一つの大きな問題を小さな問題に分割し、それぞれを個別に解決することで、全体としての解決策を見つけることができます。
netplan

ubuntuでは結構厄介なものがあります。
それはnetplan
自分これまでvpsでnet-toolsに頼りっぱなしだったので、
職場で恥をかいちゃいました。

```
#実際はnic（インターフェース）に空白がないので、誤解しないようお願いします
ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 02:02:a0:fb:0c:47 brd ff:ff:ff:ff:ff:ff
    inet 160.251.12.71/23 brd 160.251.13.255 scope global dynamic eth0
       valid_lft 5183552sec preferred_lft 5183552sec
    inet6 fe80::2:a0ff:fefb:c47/64 scope link
       valid_lft forever preferred_lft forever
```

まず下記はインタフェイスです。
合計二つあります。loはlocalの意味です。
lo:
eth0：


続いては以下。

```
00-installer-config.yaml

network:
  version: 2
  renderer: networkd
  ethernets:
    ens160:
      dhcp4: false
      addresses:
        - 172.16.0.100/24
      gateway4: 172.16.0.1
      nameservers:
        addresses: [172.16.0.1,8.8.8.8]
```


IPv4アドレス 172.16.0.100
サブネットマスク 255.255.255.0 ( /24 )
デフォルトゲートウェイ 172.16.0.1
DNS 172.16.0.1 , 8.8.8.8

```
ちなみになれないで練習すると、間違ったらssh接続できなくなります。
マジで気をつけてください。

```
コードで理解。jest.mock()、jest.spyOn()、jest.fn()の違い。

jestについて勉強を進めていると、
とても多くの「これは何？」に出会います。

今回は私が理解しづらかった

`jest.spyOn`、`jest.fn`、`jest.mock` について見ていきます

## jest.spyOn()って何？
jest.spyOnは、`特定のオブジェクトのメソッドをモックに置き換える` ために使用されます。
元のメソッドの呼び出しを監視（spy）しつつ、必要に応じてモックの実装を提供することができます。

```js
const obj = {
  method: () => 'こんにちわ',
};

const spy = jest.spyOn(obj, 'method'); // obj.method()を監視下として設定

obj.method(); // 使われるとそれが記録されます

expect(spy.mock.calls).toHaveLength(1); // 1度呼び出した

obj.method();

expect(spy.mock.calls).toHaveLength(2); // 2度呼び出した
```

`mockRestore` メソッドを使うと、オリジナル関数に戻すことができます。
「ここではモック化したい」「こっちは戻して使いたい」といったことが可能となります。

```js
describe('radome', () => {
  let spy: any;

  afterEach(() => {
    spy.mockRestore(); // testが終わる毎に元へ戻す
    // jest.resotreAllMopcks() // mockした全ての関数を元に戻すことも可能
  });
  it('randomを100固定', () => {
    // Math.random()は100を返す
    // モック関数の戻り値を変更するには、mockImplementationを利用します
    spy = jest.spyOn(Math, 'random').mockImplementation(() => 100);
    expect(Math.random()).toBe(100);
  });

  // ↓このままだとこけます。spyが見当たらず、初期化できないため。
  // afterEac内を spy && spy.mockRestore() で囲めば動く
  it('not random', () => {
    expect(Math.random()).toBeLessThan(1); // 1未満である
  });
});

```


## jest.fn()って何？
jest.fnは`新しいモック関数を作成する`ために使用されます。モック関数はテスト中に呼び出された回数や引数を記録するほか、任意の実装を提供することもできます。

```js
const mockFn = jest.fn(); // とりあえずmockFnというのは関数だよと設定する。 

mockFn('Hello', 'World'); // モック関数を呼び出す、適当に引数を持たせてみる

// モック関数が一度呼ばれたことを確認
expect(mockFn).toHaveBeenCalledTimes(1);
// expect(mockFn.mock.calls).toHaveLength(1); これも一緒

// モック関数が指定した引数で呼ばれたことを確認
expect(mockFn).toHaveBeenCalledWith('Hello', 'World');
```

## jest.mockって何？
jest.mockは、`モジュール全体をまるごとモックに置き換える` ために使用されます。
モジュール全体をモックに置き換えるので、そのモジュールが提供するすべての関数やオブジェクトを制御下に置くことができます。

```js

// good.ts
export const good = (): number => {
  return Math.floor(Math.random() * 10);
};
export const bad = (): string => {
  return "bad";
};

// goodjob.ts
import { good } from './seed';
export const goodjob = () => {
  return `${good()}点です`;
};

// goodjob.test.ts
import { goodjob } from './goodjob';
jest.mock('./good', () => { // good.tsを丸っとmock化
  return {
    good: jest // その中のgood.tsのgood関数をモック化
      .fn()
      .mockImplementationOnce(() => 100) // 1度目は100を返す
      .mockImplementationOnce(() => 10), // 2度目は10を返す
    bad: jest // bad関数もモック化
      .fn(()=> "ハズレです") // モックで強制的にreturnするテキストを変更している
  };
});

test('テスト名', () => {
  // goodjob関数の中で呼ばれているgoodは100を返す
  expect(godjob()).toBe('100点です'); 
  // goodjob関数の中で呼ばれているgoodは10を返す
  expect(godjob()).toBe('10点です');
});

```


## jest.spyOn() 、 jest.fn（） 、 jest.mock()の違い

- jest.spyOn
   - 特定のオブジェクトのメソッドをモックに置き換えて監視する(実際に存在するメソッドを指定すればOK) 
   - アプリケーションに実在する関数の動きをチェックしたい時に使えます。
- jest.fn
  - 新しいモック関数を作成する
  - `callback用として適当な関数を用意する時`に使えますね。 
- jest.mock
   - モジュール全体をモックに置き換える。
   - 外部のAPIとかを使ってテストしたい時に使えますね（axiosとか)
【AWS】『Exception while trying to read the task definition artifact file from: SourceArtifact』エラーの解決方法

# 概要
- AWSでCodeDeployを走らせたら以下のエラーになりました。
- 本記事では以下のエラー対応について記載します。

```
Invalid action configuration: Exception while trying to read the task definition artifact file
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/5d3e67de-2c65-9922-7e78-c2ed0b0bfe88.png)

# 原因の追求
- AWSの公式ドキュメントでは以下の通り
    - [Troubleshooting CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/troubleshooting.html#troubleshooting-ecstocodedeploy-size)

> The maximum artifact ZIP size in the CodeDeployToECS deploy action is 3 MB. 

- 上記ドキュメントには「CodeDeployToECSのデプロイアクションでの最大アーティファクトZIPサイズは3MB」とあり、圧縮ファイルが3MB未満ではない場合は上述のエラーメッセージが表示されるらしいです。
- あれ、そんな重いファイルあったかな...と思いソースを確認してみる。すると先日自動テスト用に40MBのSQLファイルを追加していたことを思い出す。お、こやつが原因か？
- ビルド・デプロイを設定しているCodePipelineを確認しておく。ビルド・デプロイはGithubウェブフックによってGitリポジトリから該当ブランチにマージがあったら自動で走るようにしてあります。ただし、パイプラインの中で、Codebuildによって入力アーティファクトにSourceArtifactを選択しており、これはCloudFormationによってS3にZip形式で保存されるようにしてあります。
    - SourceArtifactの保存先はどこで確認できるのか...というのは以下の記事に整理したのでご参考ください
    - [【AWS】アーティファクトストアはどこで確認・変更するのか（CodeBuildプロジェクトがCodePipelineと統合されている場合）](https://qiita.com/Ryo-0131/items/e7eaa92e2f5b0aaa2425)
- デプロイ方法としては、ブルーグリーンデプロイメントのフローを採用しています。SourceArtifactをCodeBuildでビルドしてS3に保存し、CodeDeployがそのS3のSourceArtifactを使用してデプロイを実行するという手法です。CodeDeployはSourceArtifactをS3から取得し、デプロイメントグループに指定されたリソース（EC2インスタンス、Amazon ECSタスクなど）にデプロイします。

# 解決手順
- ということで、今回引っかかった「最大アーティファクトZIPサイズは3MB」は、上記手順の

> CodeDeployがそのS3のSourceArtifactを使用してデプロイを実行

- で該当してしまったと考えられます。SourceArtifactは、S3に保存されているので、確認してみると、3.9MBになっていました。ちなみに今までのS3オブジェクトに保存されているSourceArtifactのZIPはどれも160KBとかで軽いものだったのに対し、今回だけ3MBを超えていることがわかりました。
- 該当ファイルを削除してpushし直すと、無事にデプロイまで成功しました。
- エラーメッセージをあらためて確認すると「CodeDeployToECSのデプロイアクション」「SourceArtifact」とあるので、間違いなさそうですね。このアクションで指定されているアーティファクトのZIPファイルが、3MBを超えていたため、上述のエラーで失敗してしまったのでしょう。

# 3MB以上を出力したい場合...
- 今回は削除という手法で解決しましたが、3MBを超えるソースコードをデプロイしたい場合は、以下の記事が参考になりそうです。BuildArtifactで`appspec.yml`と`taskdef.json`を出力するようにして、デプロイ時にこのBuildArtifactを指定してあげる、という方法です。
    - [CodePipeline『Exception while trying to read the task definition artifact file from: SourceArtifact』エラーの原因と対処法](https://qiita.com/tarian/items/aa6a5f0f960fc7c24a82)
２つのリストをマージするツールを作った

いやほんと、全然大したことなく、新人研修とかで練習で作らせたらいいんじゃないかレベルです。
でもQiitaの記事にしてみたくなったのは、SEのみなさまは、この作業をやらないといけない場面に割と遭遇するのでは？みんなどうやって解決してるの？と思ったためです。ご意見いただけましたら。

# 解決したい課題
２つのリストがあり、どっちかにあってどっちかにないとか、両方にあるものを整理したい。
DBの言葉でいうと、full outer joinしたい。
こんなことに頭を使わず、新しいソフトは入れず、ほんとはExcelでできたら幸せ。

# 作ったもの

## デモ
https://yo16.github.io/lists_outer_join/

## スクリーンショット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/722610/b3092e62-1a0d-af74-14f2-5d7d21f974c4.png)

## ソース
https://github.com/yo16/lists_outer_join

1. ソートして
1. 空行削除
1. 重複削除
1. それらをループで回して比較

地味で単純な方法です。もしかしたらかっこいい別解があるかも。
結果は、１列にマージする形式と、２列でOuter Joinっぽい形式の２つを同時に出すことにしました。

# 本題？
この作業をExcelの方法をググって調べると、Power Queryが出てくるので、簡単ないい方法はないんじゃないかと思っています。

私がこの課題に遭遇した時は、２つのリストをExcelで並べて左右で見比べて違っていたら一方のセルに空行を挿入・・・とやっていってました。ある程度なら手でやるけども、100行とかなるとミスもあるかもだしめんどくさすぎる。（こういう地味な作業は意外とやってしまう方だけど）

さてみなさまはどうやって解決されているんでしょうか。いい方法が見つかるまで私は、このツールを使ってみます。
[AWS Q&A 365][ECS]AWSのよくある問題の毎日5選 #83

# 1. コンテナエージェントのエンドポイントは何ですか？
回答：コンテナエージェントのエンドポイントは、ECSコンテナエージェントがコンテナインスタンスのメタデータとタスクのメタデータを送信するURLです。

# 2. コンテナエージェントのエンドポイントはどのように使用されますか？
回答：コンテナエージェントのエンドポイントは、ECSコンテナエージェントがコンテナインスタンスとタスクに関するメタデータをECSサービスに送信するために使用されます。

# 3. コンテナエージェントのエンドポイントはどこで見つけることができますか？
回答：コンテナエージェントのエンドポイントは、ECSコンソールで見つけることができます。また、AWS CLIやSDKを通じて取得することも可能です。

# 4. コンテナエージェントのエンドポイントは変更できますか？
回答：いいえ、コンテナエージェントのエンドポイントはECSサービスによって自動的に生成されるため、変更することはできません。

# 5. コンテナエージェントのエンドポイントが到達不能になった場合、どうなりますか？
回答：コンテナエージェントのエンドポイントが到達不能になった場合、ECSコンテナエージェントはECSサービスにメタデータを送信することができず、タスクのスケジューリングや管理に問題が生じる可能性があります。
[AWS Q&A 365][ECS]Daily Five Common Questions #83

# 1. What is the Container agent endpoint? 
Answer: The Container agent endpoint is a URL to which the ECS container agent sends container instance metadata and task metadata. 

# 2. How is the Container agent endpoint used? 
Answer: The Container agent endpoint is used by the ECS container agent to send metadata about the container instance and tasks to the ECS service. 

# 3. Where can I find the Container agent endpoint? 
Answer: The Container agent endpoint can be found in the ECS console or obtained through the AWS CLI or SDK. 

# 4. Can the Container agent endpoint be modified? 
Answer: No, the Container agent endpoint cannot be modified as it is automatically generated by the ECS service. 

# 5. What happens if the Container agent endpoint is unreachable? 
Answer: If the Container agent endpoint is unreachable, the ECS container agent will not be able to send metadata to the ECS service, which may result in issues with task scheduling and management.
TortoiseSVNでチェックアウトエラー："期待されるファイルシステム形式は 1 から '6' の間ですが、実際の形式は '7' です"

<h2>【背景】</h2>
<p>業務でSVNサーバーの構築をしそうなので、コミットするくらいでしか使ってなかったTortoiseSVNと、「ブラウザ上でSVNのやつを見れるようにするアプリ」くらいの理解なVisualSVNserverについてお勉強を開始<br><br>
もちろんエラーを吐きまくりで躓きました。<br><br>
備忘＋同じ箇所に躓く人がいたときの助けになれば<strike>徳が積まれて巡り巡って宝くじとかいろいろ当たる</strike>と思うので投稿</p><br>
<h2>【環境】</h2>
仮想化ツール：VMware workstation17<br>
ホストOS：Windows11<br>
ゲストOS：Windows7<br>
TortoiseSVN　　：ver1.8<br>
VisualSVNServer：ver5.1.5<br>

<h2>【操作内容】</h2>
<p>1.visualSVNserverでリポジトリを作成（dumpからのインポートなどではなく、新規作成）</p>

![SVNサーバーの画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/201edd2d-0cb9-f45e-8736-a75fef777b90.png)

<p>2.TortoiseSVNでそのリポジトリを元にチェックアウト</p>

![チェックアウト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/36a358ea-7bc3-2a63-e2c0-a5e875eb71a8.png)

<p>3.タイトルのエラーが発生しチェックアウト失敗</p>

<h2>【エラー内容】</h2>
"期待されるファイルシステム形式は 1 から '6' の間ですが、実際の形式は '7' です"

![svnerror.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/5a4e5e06-3e65-556d-4121-f27723705b65.png)

<h2>【原因】</h2>
チェックアウト元リポジトリのファイルシステム形式がTortoiseSVN（Subversion）側で対応していないため<br>
<br>
（例）<br>
　TortoiseSVN　　：ver1.8<br>
　VisualSVNServer：ver5.1.5<br>
<br>
TortoiseSVNでリポジトリを作成するとファイルシステム形式は「6」になる<br>
一方、VisualSVNServerでリポジトリを作成するとファイルシステム形式は「7」となる<br>
<br>
<br>
ちなみにVisualSVNServerだとこんな感じで見れる<br>
※再現しようとした自宅の環境ではバージョンが新しいのでファイルシステム形式が8になっていたがどのみち互換性無し

![gazou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/e005262d-5860-5f69-a754-51085f858b64.png)


この状態で、TortoiseSVNのチェックアウトを実行し、対象のリポジトリを後者(visualSVNserverで作ったほう)にすると上述のエラーが発生してチェックアウトが失敗する<br>
<h2>【補足】</h2>
ファイルシステム形式の記載されたファイルは「リポジトリ/db」配下の「format」というファイル<br>

![formatFile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/3dd19236-581d-55b1-d9df-c3c02851a674.png)

基本的に上書きできない（sakuraエディタだと編集できなかった）<br>
![formatData.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/3faa0061-8932-9dbe-d290-3089e7631425.png)


しかし、別のリポジトリからコピペで上書きしたり、メモ帳で開いて編集はできちゃうので注意（やったらもっと面倒なことになりそうなので、実験するときはバックアップして自己責任でやってね）<br><br>
※ちなみにファイルシステム形式が6の「format」を別のリポジトリから持ってきて上書きしたらチェックアウトできた（やったんかい!!）<br><br>
<br>
<h2>【チェックアウト時の指定方法を変更でエラー回避】</h2>
<b>2023/6/21：追記</b>
<p>ふと別のチェックアウト物を見ていたらURL形式でチェックアウトしているものがあり、ものは試しとやってみたらチェックアウト成功!!

チェックアウト時のリポジトリ指定を<'file:///～'>の形式ではなく<'http://～'>の形式でやると
ファイルシステム形式が7でもチェックアウトできてしまう謎の仕様を発見しました。
いいけどなんでや～</p>
<br>
<h3>チェックアウトOK：「http://～」形式でチェックアウト</h3>

![svnerror.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/ba7109e1-9e2f-8e50-ed50-c9c4ceceadad.png)


<h3>チェックアウトNG：「file:///～」形式でチェックアウト</h3>

![svnerror1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292179/02017d29-b0eb-90b5-860a-1fd6b6e8433a.png)


<br>
<b><a href=https://www.visualsvn.com/support/topic/00135/>参考：Understanding the Subversion repository types and formats</a></b>
（https://www.visualsvn.com/support/topic/00135/）
※英語サイトだけどグーグル翻訳でサイトをまるごと翻訳してくれるので助かる～
【libGDX】FreeTypeFontの使い方

# カスタムフォント
libGDXではボタン等のUI要素にテキストを表示することが出来ますが、デフォルトのフォントだと日本語には対応していません。日本語を表示する際には、FreeTypeFontGeneratorを使う必要があります。
# Gradle設定
新しいプロジェクトを作る場合は、gdx-setup.jarを開いてOfficial ExtensionsからFreeTypeにチェックを入れればOKです。
既存のプロジェクトに追加する場合は、build.gradleに以下のように追記します。

```gradle:Core Dependency
implementation "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
```
```gradle:Desktop Dependency
implementation "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
```
```gradle:Android Dependency
implementation "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-armeabi-v7a"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-arm64-v8a"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86"
natives "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-x86_64"
```
```gradle:IOS Dependency
implementation "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-ios"
```
これで下準備は完了です。注意点として、FreeTypeFontはHTMLアプリケーションには対応していません。
# FreeTypeFontの使い方
基本的な使い方です。
```kotlin
val fontGenerator = FreeTypeFontGenerator(Gdx.files.internal("font/japanese.ttf"))
val parameter = FreeTypeFontParameter().apply {
    size = 24
    incremental = true
}
val font = fontGenerator.generateFont(parameter)
```
- 使えるフォントファイルは.ttf形式のものです。
- parameterで細かい要素を指定出来ます。フォントの枠線や影の設定なども出来ます。
- 日本語など、デフォルトで非対応の文字を表示する場合はincrementalを必ずtrueに設定してください。
- 最後に、fontを生成して、ButtonStyleに適用するなり、Skinに追加するなりしてください。
使う文字が数個程度の場合、FreeTypeFontParameterのcharacterフィールドにそれらの文字を結合した文字列を指定することで描画することが出来ます。
一方、日本語を描画する際のような、大量の文字を描画する必要がある場合、characterにすべての文字を繋いで…というのは現実的では有りません。このような場合はincrementalをtrueに設定することで文字を適宜追加してくれます。
:::note warn
フォントファイルのパス指定には大文字、数字は使えないようです。ただ、調べてみると大文字は使えるが数字が使えない。といった症状もあり、現状詳しいことはわかりません。すべて小文字で指定するのが無難そうです。
:::
MathJax v3でTeXのautoload extensionをloadしたときに自動でloadされるextensionを確認した

:::note
MathJax v3.2.2
:::

## 結論

https://github.com/mathjax/MathJax-src/blob/3.2.2/ts/input/tex/autoload/AutoloadConfiguration.ts#L147-L161

- [action](https://docs.mathjax.org/en/latest/input/tex/extensions/action.html)
- [amscd](https://docs.mathjax.org/en/latest/input/tex/extensions/amscd.html)
- [bbox](https://docs.mathjax.org/en/latest/input/tex/extensions/bbox.html)
- [boldsymbol](https://docs.mathjax.org/en/latest/input/tex/extensions/boldsymbol.html)
- [braket](https://docs.mathjax.org/en/latest/input/tex/extensions/braket.html)
- [bussproofs](https://docs.mathjax.org/en/latest/input/tex/extensions/bussproofs.html)
- [cancel](https://docs.mathjax.org/en/latest/input/tex/extensions/cancel.html)
- [color](https://docs.mathjax.org/en/latest/input/tex/extensions/color.html)
- [enclose](https://docs.mathjax.org/en/latest/input/tex/extensions/enclose.html)
- [extpfeil](https://docs.mathjax.org/en/latest/input/tex/extensions/extpfeil.html)
- [html](https://docs.mathjax.org/en/latest/input/tex/extensions/html.html)
- [mhchem](https://docs.mathjax.org/en/latest/input/tex/extensions/mhchem.html)
- [newcommand](https://docs.mathjax.org/en/latest/input/tex/extensions/newcommand.html)
- [unicode](https://docs.mathjax.org/en/latest/input/tex/extensions/unicode.html)
- [verb](https://docs.mathjax.org/en/latest/input/tex/extensions/verb.html)

## 少し解説

MathJaxの TeX/LaTeX Extensionのリストはこちら

https://docs.mathjax.org/en/latest/input/tex/extensions/index.html

そのなかに [autoload](https://docs.mathjax.org/en/latest/input/tex/extensions/autoload.html) というextensionがある。
これをloadすると、上記のextensionが自動でロードされる。

一応、各extensionのページにはその旨が記載されているが一覧が分かりづらかったのでまとめた。

ちなみに、MathJax v2とv3では大きく機能が変わっており、新たにComponentsというものが追加されている。
そのうち、Inputに関連する、[Input Components](https://docs.mathjax.org/en/latest/web/components/input.html) で、`input/tex`を選択すると、autoload extensionがloadされるため、上記のextensionもloadされることになる。
ソースアクションが S3 である CodePipeline でCloudFormation スタックを別のアカウントにデプロイする際にハマったこと

# 実現したいこと/前提条件
- アカウント1が所有するS3 バケットに配置したCFnテンプレートをクロスアカウント(アカウント2)に構築したい。
- アカウント1がパイプラインを所有

基本的には、以下の記事を参照すればできる。
https://repost.aws/ja/knowledge-center/codepipeline-deploy-cloudformation

しかし、クロスアカウントから403 の s3 Access Denied エラーが発生して、そのエラー解消に時間がかかったので、備忘録として残す。

# TL;DR
クロスアカウントがアクセスするアーティファクトバケットは、ソースファイルの置き場所である、S3バケットとは異なる。
ソースファイルの置き場所であるs3バケットの権限周りをずっと調査していたが、そもそも調査すべき箇所が異なっていた。

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/welcome-introducing-artifacts.html
> アーティファクトバケットは、選択したソースアクションが S3 であるパイプラインのソースファイルの場所として使用されているバケットとは異なります。

# 感想
クロスアカウントな構築を行うと、権限周りの良い勉強になる。
アカウント 1 の CodePipeline サービスロールに AssumeRole 許可を追加して、クロスアカウントロールを引き受けるのかと勉強になった。
RubyでAtCoder ABC306(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC306のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - Echo
https://atcoder.jp/contests/abc306/tasks/abc306_a
```ruby:a-293.rb
gets
gets.chomp.chars{ print _1 * 2}
```

# B - Base 2
https://atcoder.jp/contests/abc306/tasks/abc306_b
```ruby:b-293.rb
a = gets.split.map(&:to_i)
puts a.map.each_with_index{ _1 * (2 ** _2) }.sum
```
## 解説
Aの各要素を`a[i] * 2 ^ i`でマッピングした後の要素の総和を出力すればOKです。

# C - Centers
https://atcoder.jp/contests/abc306/tasks/abc306_c
```ruby:c-293.rb
n = gets.to_i
a = gets.split.map(&:to_i)

hash = Hash.new(0)
ans = []
a.each do
  hash[_1] += 1
  if hash[_1] == 2
    ans << _1
  end
  break if ans.size == n
end
puts ans.join(" ")
```
## 解説
連想配列hashを用意しておき、順に要素に対応する値を更新しておきます。そして、値が2となった要素（数字）をans配列に格納していきans配列の大きさがnとなったらループから抜けます。最後に、ans配列を空白区切りで出力することで答えが求まります。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
Raiils ERDについて【注意喚起】

<p> Rails ERDというER図を自動生成してくれるGemがあると知り,</p>
導入を試していましたが、バージョン 3.0 ～ 5.0までしか対応しておらず
Rails6.0~以降は残念ながら導入出来ないことがわかったので忘備録として残しておきます泣

バージョン問題に気付かず試行錯誤して数時間無駄にしてしまったので
同じような方が出ないようRails ERDを検索タグにしておきます！

下記がERDのGithubページです！
[https://github.com/voormedia/rails-erd](https://github.com/voormedia/rails-erd)
IntelliJでkotlinのmainメソッドが実行できない

### 結論
以下をして出てくるようになった。
1. ソースルートを設定
2. ファイルタイプが「kotlinファイル/クラス」＞「ファイル」のファイルに、クラスを作らずmainメソッドを記述

### 事象
intelliJでkotlinのプロジェクトを作成して、[アプリケーションを実行する](https://pleiades.io/help/idea/running-applications.html#quick-way)などを見ながらmainメソッドを実行しようとするも、「実行」メニュー ＞ 「実行」がアクティブにならない。
mainメソッドのあるファイルの行数ゾーンに緑の▶も出てこない。

### 対応
#### 1. ソースルートを設定
ソースルート：コンパイルする必要のあるコードを置く最上位のディレクトリ
　・参考：[コンテンツルート](https://pleiades.io/help/idea/content-roots.html#configure-folders:~:text=%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82-,%E3%82%BD%E3%83%BC%E3%82%B9,-%E3%81%93%E3%81%AE%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%83%BC%E3%81%AB)

mainというディレクトリの配下にパッケージを構成していたが、このmainディレクトリをソースルートに設定した。
　・mainディレクトリで右クリック
　⇒「ディレクトリをマーク」
　⇒「ソースディレクトリ」

#### 2. ファイルタイプが「kotlinファイル/クラス」＞「ファイル」のファイルに、クラスを作らずmainメソッドを記述

Main.kt「クラス」にmainメソッドを作成していたが、
Main.kt「ファイル」にmainメソッドを直接記述した（intelliJ語をそのまま使っているため語の定義は悪しからず...）。
　・ファイル作成時に「kotlinファイル/クラス」＞「ファイル」を選んで、Main.ktファイルを作成
　⇒ファイルにmainメソッドを定義


### 参考
[チュートリアル: 最初の Kotlin アプリケーションを作成する](https://pleiades.io/help/idea/create-your-first-kotlin-app.html)

### 最後に
とりあえず動いた方法のメモ

### 追記
[Kotlinのエントリポイントの話](https://qiita.com/hisuie08/items/5e6409b23aa15ec51cf7) を拝読していて、当初「クラス」のファイルタイプで動かなかった理由が判明したため追記。

**記述していたmainメソッドがエントリポイントになっていなかった**
→インスタンスメソッドになっていた（companion object内で定義できていないなかった。Javaでいうとstatic化できていなかった（に近い））

では、どうしたら「クラス」のファイルタイプで動かせるか。
- companion objectを定義し、その中でmainメソッドを定義する必要があった。
（対象クラスをインスタンス化せずとも呼び出せるようにする必要があった（考えてみれば当然ですね...））
- @JvmStaticをmainメソッドに付与する必要があった。
（companion objectの定義は、デフォルトだとコンパイル時に専用の別クラスに切り出される（言語仕様）ため、mainメソッドを対象クラスの定義としてコンパイルしてもらう必要がある）




↑により実行用の緑の▶ も表示されるようになりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629824/a48cddfc-4437-fd2b-38d8-dc5b95d90c84.png)


参考
[kotlinlang Companion objects﻿](https://kotlinlang.org/docs/object-declarations.html#companion-objects)
EACCES: permission denied が出るので、nvmを使うようにした

## はじめに
npmを使ってグローバルにインストールしようとした時、以下のようなエラーが出力されました。
初めて出会いましたが、もう２度と会うことはなさそうなので記事に残します。
```
  % npm install -g typescript
  npm ERR! code EACCES
  npm ERR! syscall rename
  npm ERR! path /usr/local/lib/node_modules/npm
  npm ERR! dest /usr/local/lib/node_modules/.npm-i9nnxROI
  npm ERR! errno -13
  npm ERR! Error: EACCES: permission denied, rename '/usr/local/lib/node_modules/npm' -> 
  '/usr/local/lib/node_modules/.npm-i9nnxROI'
  npm ERR!  [Error: EACCES: permission denied, rename '/usr/local/lib/node_modules/npm' -> 
  '/usr/local/lib/node_modules/.npm-i9nnxROI'] {
  npm ERR!   errno: -13,
  npm ERR!   code: 'EACCES',
  npm ERR!   syscall: 'rename',
  npm ERR!   path: '/usr/local/lib/node_modules/npm',
  npm ERR!   dest: '/usr/local/lib/node_modules/.npm-i9nnxROI'
  npm ERR! }
  npm ERR! 
  npm ERR! The operation was rejected by your operating system.
  npm ERR! It is likely you do not have the permissions to access this file as the current user
```

## EACCES

### 原因
https://docs.npmjs.com/downloading-and-installing-node-js-and-npm

> To publish and install packages to and from the public npm registry or a private npm registry, you must install Node.js and the npm command line interface using either a Node version manager or a Node installer. We strongly recommend using a Node version manager like nvm to install Node.js and npm. **We do not recommend using a Node installer, since the Node installation process installs npm in a directory with local permissions and can cause permissions errors when you run npm packages globally.**

[nodeのinstaller](https://nodejs.org/en/download)を使ってnodeをインストールする場合、local permissionのディレクトリにインストールしてしまうため、npmのパッケージをグローバルにインストールしようとするとこのエラーが発生してしまうようです。

### 解決方法

https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally


これの解決方法はnpm公式にがっつり書かれていて、以下の2択です。
- nodeのバージョンマネージャーを使ってnpmを再インストールする
    - (原文) Reinstall npm with a node version manager (recommended)
- npmのデフォルトのディレクトリを変更する
    - (原文) Manually change npm's default directory

今回は前者の「nodeのバージョンマネージャーを使ってnpmを再インストールする」にします。


## nvmをいれる
Nodeのバージョンマネージャーは、[nvm](https://github.com/nvm-sh/nvm), [n](https://github.com/tj/n), [nodenv](https://github.com/nodenv/nodenv) などいくつかありますが、僕は長いものに巻かれるタイプなので```nvm```を使うことにします。
使い方に関しては、https://github.com/nvm-sh/nvm#installing-and-updating に書かれているままです。


```
  % curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
```

↓

```
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
```
上記を```~/.zshrc```に追加(※使っているシェルによりけり)

↓

```
  % source ~/.zshrc
```

↓
- 最新バージョンのnodeをいれる場合
```
  % nvm install node
```
- バージョン指定していれる場合
```
  % nvm install 14.7.0 # or 16.3.0, 12.22.1, etc
```
cscの作法 その370

# 概要
cscの作法、調べてみた。
opentkのgamewindow使ってみた。
GL.DrawElements使ってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9bd8d7ca-bde8-39cc-ac13-9209b2954f26.png)


# サンプルコード

```
using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace App
{
	class Gwin: GameWindow {
		double counter = 0;
		public Gwin(int width, int height, GraphicsMode mode, string title): base(width, height, mode, title) {
			this.VSync = VSyncMode.On;
		}
		protected override void OnUpdateFrame (FrameEventArgs e) {
			counter += e.Time;
		}
		protected override void OnRenderFrame(FrameEventArgs e) {
			base.OnRenderFrame(e);
			GL.Rotate(counter / 10, 0, 0, 1);
			GL.Clear(ClearBufferMask.ColorBufferBit);
			GL.ClearColor(Color.CornflowerBlue);
			float[] vertices = new float[] {
				-1f, 1f, 0f,
				-1f, -1f, 0f,
				1f, 1f, 0f,
				1f, -1f, 0f
			};

			short[] indices = new short[] {
				0, 1, 2, 3
			};
			GL.EnableVertexAttribArray(0);

			GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, vertices);

			GL.Color3(1.0f, 0.0f, 0.0f);
			GL.DrawElements(PrimitiveType.TriangleStrip, 4, DrawElementsType.UnsignedShort, indices);

			this.SwapBuffers();
		}
	}
	class Program {
		static void Main(string[] args) {
			Gwin window = new Gwin(500, 500, OpenTK.Graphics.GraphicsMode.Default, "Test");
			window.Run();
		}
	}
}





```


以上。
SnowSQLの試行

# 概要
SnowSQLを使って外部からSQL実行結果を取得できないかを確認してみる。

# 手順
1.　SnowSQLのダウンロードとインストール
SnowSQLのダウンロードサイトにアクセスし「SNOWSQL FOR WINDOWS」をクリックしてインストーラーをダウンロードし、インストーラーを実行。
https://developers.snowflake.com/snowsql/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171904/31de9d75-f274-64d7-bd28-f8dda8423855.png)

2.　組織名、アカウント名、ユーザー名の確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171904/58fa7548-9d2a-0a13-6bbc-54bf948c9717.png)

3.　接続確認
PowerShellを開いて2.で確認した組織名、アカウント名、ユーザー名を元にSnowSQLに接続してみる。
① 「snowsql -a 組織名-アカウント名 -u ユーザー名」（組織名とアカウント名はハイフンでつなぐ）
②　PasswordはSnowflakeへログインする際のパスワード
```powershell:powershell
PS C:\Users\uname> snowsql -a 組織名-アカウント名 -u ユーザー名
Password:
* SnowSQL * v1.2.27
Type SQL statements or !help
uname#COMPUTE_WH@(no database).(no schema)>
```
4.　SQL試し実行
テストデータに対してSQLを試しに実行してみる。
```sql: sql
* SnowSQL * v1.2.27
Type SQL statements or !help
uname#COMPUTE_WH@(no database).(no schema)> select "C_CUSTKEY", "C_NATIONKEY", "C_ACCTBAL"
                                            from SNOWFLAKE_SAMPLE_DATA.TPCH_SF10.CUSTOMER
                                            limit 10;
+-----------+-------------+-----------+
| C_CUSTKEY | C_NATIONKEY | C_ACCTBAL |
|-----------+-------------+-----------|
|     15001 |          15 |   3008.96 |
|     15002 |          21 |   2536.62 |
|     15003 |           9 |   5979.09 |
|     15004 |          20 |   3549.58 |
|     15005 |          14 |   2767.14 |
|     15006 |          23 |   8271.46 |
|     15007 |           6 |   9446.75 |
|     15008 |           8 |   6599.40 |
|     15009 |           4 |   1230.06 |
|     15010 |           5 |   2569.22 |
+-----------+-------------+-----------+
10 Row(s) produced. Time Elapsed: 0.212s
```

5.　ファイルによるSQL実行とCSV出力
① SQLを記載したファイルを作ってローカルに置く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171904/efae2142-e60d-179f-6f0a-c7016f7ef7e1.png)
② PowerShellで下記のように実行。
```powershell:powershell
PS C:\Users\uname> snowsql -a 組織名-アカウント名 -u ユーザー名 -f .\Desktop\test.sql 
                            -o output_file=.\Desktop\output.csv -o output_format=csv
Password:
* SnowSQL * v1.2.27
Type SQL statements or !help
"C_CUSTKEY","C_NATIONKEY","C_ACCTBAL"
"15001","15","3008.96"
"15002","21","2536.62"
"15003","9","5979.09"
"15004","20","3549.58"
"15005","14","2767.14"
"15006","23","8271.46"
"15007","6","9446.75"
"15008","8","6599.40"
"15009","4","1230.06"
"15010","5","2569.22"
10 Row(s) produced. Time Elapsed: 0.240s
Goodbye!
```
③ 指定の場所にcsvファイルが作成されたことを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171904/0a9e66c9-e485-06a2-3ee0-6e13618edaed.png)
どうやら開発と構築は違う意味を持つらしい

「開発と構築の違い分かってる？」

むむ、どうやら開発と構築は異なる意味を持つらしい。
開発はソフトウェアやアプリの開発、構築はインフラ周りのあれこれとのこと。

正直今までかなりあやふやなまま雰囲気で誤魔化してきた。
ということで、今回は初心者向けに「開発」と「構築」の違いを書いてみる。

＜開発とは＞
主にソフトウェアやアプリケーションの作成や改良を指す。
プログラミング言語やフレームワークは、その開発のプロセスにおいて要件に基づいたソフトウェアやアプリを設計して実装するためのツール。そしてその後にテストやデバッグが入ってくる。

＜構築とは＞
一方構築は、先に説明したアプリやらソフトウェアを動かす土台の部分を形成する作業になる。
ネットワークやサーバ、DBやストレージを設計、構築するのである。

構築のプロセスにおいては
・要件定義や設計
・インストール
・設定
・テスト
・トラブルシューティング

などがあり、いわばシステムの基盤を整え、システムが適切に動作するための環境を整備（構築）する事である。

正直インフラ構築における各作業フェーズでどういう事をするのかイメージが湧かない。
という事で、これも追加で調べてみる。

＜インフラ構築における「要件定義」＞
インフラストラクチャに必要な要件や目標を明確に定義する。
これには、ユーザーの要求や予想されるトラフィック量、可用性の要件などが含まれます。

※可用性
　システムやサービスがユーザーに対して正常に利用可能である状態であることを指す。
・動作時間
・障害耐性
・レスポンス時間
・スケーラビリティ
etc...

＜インフラ構築における「設計」＞
インフラストラクチャのアーキテクチャやネットワーク構成を設計する。
これには、サーバーの配置、ネットワークのトポロジー、冗長性の構築などが含まれます。

※トポロジー
複数の装置や機器を結ぶ配線や、接続形態の類型のこと

＜インフラ構築における「インストール」＞
インフラストラクチャに必要なハードウェアやソフトウェアを配置・設置する。
これには、サーバーの設置、ネットワーク機器の設定、ストレージの接続などが含まれる。

＜インフラ構築における「設定」＞
インフラストラクチャの機能やパラメータを設定する。
これには、ネットワークのアドレス設定、セキュリティ設定、ストレージのパーティショニングなどが含まれる。

※パラメータ
システムやネットワークの動作や構成を制御するための設定値や変数のこと

＜インフラ構築における「テスト」＞
インフラストラクチャの機能や性能を検証する。
これには、ネットワークの可用性テスト、負荷テスト、冗長性のテストなどが含まれる。

＜インフラ構築における「トラブルシューティング」＞
テストや運用中に発生する問題を特定し、解決策を見つける。
これには、ネットワークの障害調査、システムのログ解析、障害発生時の対応などが含まれる。

うーむ、当たり前だけど色々あんだね。
深掘りしようとすればキリがないので、今回はここまで。

気が向いたら「完全版　インフラ構築の全て」
みたいな調子乗った記事でも出してみます。
Akka-HTTPでCSSファイルを返す

Akka-HTTPで嵌った点をメモ的に残しておきます。

# 環境
OS: Windows11
Java: OpenJDK 17.0.7
Scala: 3.3.0
Akka: 2.7.0
Akka-HTTP: 10.5.2

※ Akkaは2.7.0からBSLに変更になりましたが、僕は年間売り上げ$25million以下なので、無料で使えると考えています。

# 内容
まず、Akka-HTTPには、レスポンスに対して、ContentTypeを設定することができる。text/htmlとか。(厳密には、text/html(UTF-8)で指定する)
ところが、CSSを表すContentTypeはhtmlと同様には用意されていない。

どうするかというと`MediaTypes`を使う。

``` Main.scala
complete(HttpEntity(MediaTypes.`text/css` withCharset HttpCharsets.`UTF-8`, MyStyles.myRender()))
```

これでいける。

# 何がうれしいか
Content typeのヘッダをつけないと、ブラウザからCSSを読みこんだときに、htmlに適用されない。
これで、Content typeにtext/cssがついて、読みこんだファイルは無事、htmlに適用される。
DuckDB と Go

2023年6月3回目です。

今回は、[DuckDB](https://duckdb.org/) についてです。

ぼくが DuckDB に興味を持ったのは、Thoughtworks 社の Technology Radar を読んでからです。

https://www.thoughtworks.com/radar/platforms/duckdb

記事の作成時点では、公式の言語に Go の紹介はありません。

そのため、Go で Query を実行する方法について書きます。

今回使用した Code は、[こちら](https://github.com/danny-yamamoto/go-duckdb-example)です。

## TL;DR
- OLAP の RDBMS です。
- 軽量な DB で、CSV や Parquet を直接 Query できます。

## Installation
- Dev Container 環境と VS Code の Extension を使用します。

https://github.com/danny-yamamoto/go-duckdb-example/blob/21714afbb3b9b7900ffc452cd89e8c9bc00382a7/.devcontainer/devcontainer.json#L9

- Dev Container を起動後、DuckDB の binary が存在することを確認してください。
```bash
vscode ➜ /workspaces/go-duckdb-example (main) $ sudo find / -name duckdb
/usr/bin/duckdb
vscode ➜ /workspaces/go-duckdb-example (main) $
```

- PATH を設定します。
```bash
vscode ➜ /workspaces/go-duckdb-example (main) $ export PATH="/usr/bin:$PATH"
vscode ➜ /workspaces/go-duckdb-example (main) $ source ~/.bashrc
```

- DuckDB の動作を CLI で確認します。   
CSV を参照できていることが確認できます。
```bash
vscode ➜ /workspaces/go-duckdb-example (main) $ cat hoge.csv 
a,1,c
aa,2,cc
vscode ➜ /workspaces/go-duckdb-example (main) $ duckdb
v0.8.1 6536a77232
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
D SELECT * FROM read_csv_auto('hoge.csv');
┌─────────┬─────────┬─────────┐
│ column0 │ column1 │ column2 │
│ varchar │  int64  │ varchar │
├─────────┼─────────┼─────────┤
│ a       │       1 │ c       │
│ aa      │       2 │ cc      │
└─────────┴─────────┴─────────┘
D .exit
vscode ➜ /workspaces/go-duckdb-example (main) $ 
```

## Usage
- Query 用の CSV を用意します。

- `github.com/marcboeker/go-duckdb` を blank import します。

- 認証は、必要ありません。DuckDB の binary を指定します。

https://github.com/danny-yamamoto/go-duckdb-example/blob/21714afbb3b9b7900ffc452cd89e8c9bc00382a7/main.go#L11

- 実行結果   
`sql.Open` 以外、通常の database の扱いと変わりません。当然ながら。
```bash
vscode ➜ /workspaces/go-duckdb-example (main) $ go run main.go 
column0: a
column0: aa
vscode ➜ /workspaces/go-duckdb-example (main) $
```

## Summary
Go で Query を実行する方法について書きました。
DuckDB の Usecase として考えられるのは、Backend Engineer が分析系の API を実装する場合でしょうか。例えば、Python よりも Go で実装したい場合。
【IBM Security Verify】Microsoft Intune と連携して、クライアント証明書認証を行う③

# はじめに
IBM Security VerifyとMicrosoft Intuneを連携させて、クライアント証明書を使った認証を試してみました。

設定が多いため、3回にわけてご紹介予定です。
①：Intuneのトライアル環境準備
②：IBM Security VerifyとIntuneの連携設定
**③：アクセスポリシーを使ったデバイスの条件付きアクセスを試す（今回）**

3回目は、IBM Security VerifyのアクセスポリシーでIntuneのデバイスコンプライアンスの遵守ステータスを利用したアクセス制御を行います。

# 17.デバイス遵守ステータスの取得確認
レポートで、デバイス遵守ステータスを確認します。
管理対象デバイスや、準拠デバイスのステータスがTrueとなっているため、IBM Security Verifyがデバイスのステータスを認識できていることがわかります。
![qiita (97).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/dba97a61-438f-3fb0-dbe7-36a7acf14dc7.png)

# 18.コンプライアンスポリシーを変更して、デバイス非準拠に変更

今回は最小OSバージョンを変更して非準拠のステータスに変更しました。
![qiita (98).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/8031c586-28e2-91df-aa8d-b4559214f198.png)
![qiita (99).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/22d5ecdd-2c78-dff5-49f8-0c53f3f88b5f.png)


# 19.アクセスポリシーの作成/アプリケーションへの割り当て
デバイスステータスを非準拠に準拠していないデバイスを拒否するアクセスポリシー作成します。

Intune-Blockというアクセスポリシーを作成し、デバイス・コンプライアンスが非準拠の場合はBlockするというIntune-Block-ruleを追加します。
![qiita (100).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/96179199-7ae1-5818-e7bc-fbfd427e6100.png)

Intune-Blockアクセスポリシーをアプリケーションに割り当てます。
![qiita (101).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/03bee83d-836d-9d8a-156d-1228ab9a5ed8.png)

# 20.アクセスポリシーの動作確認
SAMLサンプルアプリケーションにアクセスすると、アクセスがブロックされました。
![qiita (103).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/56d0c030-03ac-9c2b-52d3-969b835474bb.png)
![qiita (104).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/d1f79c0b-5eb1-94b5-d5fa-f88374282ce3.png)

アプリケーションの使用レポートを確認すると、準拠デバイスステータスがFalseとなり、デバイスの準拠ステータスが正しく連携されていました。
![qiita (105).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/a3bfa91e-8df6-4cfa-6e43-1ab4f44ddbe0.png)


# 21.参考：クライアント証明書のダイアログ表示を抑止する方法について
IBM Security Verifyの設定ではありませんが、Windows端末でレジストリ設定することでクライアント証明書のダイアログ表示を抑止できます。

以下はEdgeの場合の例です。
任意の名前.regファイルを用意して、実行することでレジストリ変更できます。
```sample.reg
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Edge\AutoSelectCertificateForUrls]
"1"="{\"pattern\":\"https://<vanityhostURL>\",\"filter\":{\"ISSUER\":{\"CN\":\"xxx\", \"O\":\"xxx\", \"S\":\"xxx\", \"C\":\"xxx\"}}}"
```
![qiita (107).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/32429cfe-40ed-5259-2a32-948b9dfc6c7b.png)

ISSUERの部分については、クライアント証明書の発行者をご確認ください。
![qiita (106).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/8280cfb1-01cb-e29c-f64f-6bb2c9857108.png)

# まとめ
デバイスの遵守ステータスを元にアクセス制御ができることを確認しました。
Intuneの連携について3回にわたってご紹介させて頂きました。

- [【IBM Security Verify】Microsoft Intune と連携して、クライアント証明書認証を行う①](https://qiita.com/fitz/items/ebe5d54fdc0f1705dee9)
- [【IBM Security Verify】Microsoft Intune と連携して、クライアント証明書認証を行う②](https://qiita.com/fitz/items/2e6abe388a0226603366)
- [【IBM Security Verify】Microsoft Intune と連携して、クライアント証明書認証を行う③](https://qiita.com/fitz/items/452f46343f14b9b13164)
ScalaCSSのちょっとした使い方について

ScalaCSSについて嵌ったところをメモ的に投稿しておきます。

# 環境
Java : OpenJDK 17.0.7
Scala : 3.3.0
sbt: 1.9.0
ScalaCSS: 0.8.0-RC1

# 内容
https://japgolly.github.io/scalacss/book/features/typed-values.html
この記事を見れば明らかなのですが、

ScalaCSSは"%%"や"px", "width"や"height"などのCSSの属性や表記について、定義されていて、
```
"div" - (
  width(200 px),
  height(100 px)
)
```

などと書けたりして、最初のチュートリアル的なコードでは、
この書き方を習います。

ところが、
"rotate"とか"deg"とかいったものは定義がなく、
"transform"とか"box-shadow"とかは、使い方がいまいち不明です。

そういう時に `:=` を使って、書き込んでやります。
例を挙げると
```
  "div" - (
    transform := "rotate 1s steps(8) 0s infinite"
    boxShadow := "0 -30px 0 #fee"
  )
```

といったような具合です。

ドキュメントにもtypedなデータがまだ用意されていない場合は`:=`を使って設定します、というようなことが書いてありますね。

以上、ちょっとしたScalaCSSの使い方でした。
iOSでショートカットを使ってYouTubeから動画をダウンロードする(超シンプル

はじめまして、しがない切り抜き師を行っている者です。
通勤中や外出先でも切り抜きを行いたいと思い考えた方法です。
※自己責任でお願いします。
※初学者なので間違えが多いかと思いますが、ご指導ご鞭撻のほどよろしくお願いします。

# 動作環境について
1.使用機器
iPad Pro iPadOS 16.5
a-shell ver1.11.1

2.対象サイト
Youtubeのみ
# 環境設定
1. a-shellのインストール

https://apps.apple.com/jp/app/a-shell/id1473805438

2.　設定
a-shellを開き、以下のコマンドを実行

~~~
~/Documents　
pip install ffmpeg-python
pip install yt_dlp
~~~

※pip install ffmpeg-pythonは不要かもしれません。


3.　ショートカットの追加

https://www.icloud.com/shortcuts/c922c090309743f994ed35414b58c56b

# 使用
Youtubeアプリやブラウザ上で動画を共有を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/301121/e7bcd596-7d5b-8ba1-987f-e2cf507cb43c.png)
Movie DLを選択すると最高画質でのダウンロードが開始されます。
a-shellフォルダに保存されています。

# おわりに
1.　なぜYoutube専用？
私自身が使えればいいと思いシンプルな作りになっています。
Youtubeの共有の仕様によりURLの末尾に&feature=shareや?feature=shareがついており、これらを削除するための処理を行っています。このためYoutube専用となっています。他サイトで利用すると目的の動画以外がダウンロードされる可能性があります。

2.　最高画質以外のDLについて
yt-dlpを利用しているのでショートカットから中身を編集していただければ様々な用途に活用できると思います。

3.　注意事項
あくまでも自分用に書いたものなので、使用時に発生したトラブルについては自己責任でお願いします。
また、著作権等に関しましても同様に当方においては責任を負いかねます。

# 参考資料
@soun1218様

https://qiita.com/soun1218/items/3f07fbaa7029208dd789#1a-shell%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E8%A8%AD%E5%AE%9A%E7%AD%89