OmniAICreator/Qiita-1.07M huggingface dataset:
Misskeyで、Twitterのツイートをノートする

## はじめに
Misskey垢を持っているが、ノートすることがあまりないので、TwitterでツイートしたものをMisskeyの方にノートして、ノート数を増やす作戦です(?)
僕が持っているアカウントは「りんごぱい」というインスタンスで登録しているので、そちらでやっていきます。
りんごぱい https://misskey.04.si
## APIのアクセストークンの取得
まずは、APIを叩くためのアクセストークンを取得します。
ホームから、設定=>API
と移動します。
設定のAPIのページ https://[Host名]/settings/api
右上のアクセストークンの取得を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/6efc1c54-1f8e-20e3-014f-dd5b9754746f.png)
このような画面が出てくるので、名前と、権限を指定して右上のチェックを押します。
すると、トークンが表示されるので、必ずコピー等をして忘れないようにして、わかったを押します。

:::note warn
ここで保存を忘れると、もう一度取得することは出来ません
:::
## APIを叩く
では、APIを一度叩いてみようと思います。
[Telend API Tester](https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm?hl=ja)を使います。
POSTで送信をします。
`
https://[host]/api/notes/create
`
で、ノートの作成ができます。
参考：https://misskey-hub.net/docs/api/endpoints/notes/create.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/48d7b942-0533-fc40-390e-105e7c390b6c.png)
Headerには、
```
Content-Type : application/json
```
を指定します。これがないと、エラーが出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/a1bc03c4-49c2-f108-c068-290971354f94.png)
Bodyには、ノートの中の内容と、先程のアクセストークンを指定します。
"i"に、アクセストークンを。
"text"に、投稿するテキストを入れます。
```
{
  "i" : "{{アクセストークン}}",
  "text" : "APITEST"
}
```
他にもパラメータはあるので、先程のMisskeyのドキュメントを見てください。

これで準備はできました。これでSendを送ると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/2826ea86-6ad8-7fd1-6260-188b2a68a913.png)
このように、ノートできます！
## Twitterとつなげる
ずっと、もっと、Twitterとつなぐぞ。ということで(?)
IFTTTを使用して、Twitterの新しいツイートがあったときに、先程のAPIを送る、ということをします。
https://ifttt.com/ にアクセスして、右上のCreateを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/a4013d1f-be3b-4fb2-366c-2e17da290193.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/cebb1cec-b183-c22f-9416-a15282d2e2d5.png)
IF Thisには、Twitterを選択して、NewTweetを指定し、新しいツイートがあったことを検知します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/5e690166-679f-30ed-8aad-5968eb2ee905.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/4ccaefc6-9b88-b7ed-fb09-eb6f8a1fa05d.png)
Then Thatには、WebHookを指定します。
Url、Method、Content-Typeには、先程のAPIの内容を指定します。

Bodyも、先程と同じように指定します...が、Tweetの内容を入れたいですよね
そのようなときには、"text"の中に、Add ingredientをクリックして、Tweetの内容等を指定できます。({{text}}、{{LinkToTweet}}、など)
これで、できました！

あとは、Twitterでツイートすると、Misskeyにノートされます。
(IFTTTの仕様上、すこし反映に時間があります。)

:::note warn
Misskeyの仕様からなのか、うまくいかず400エラーが出るときがあります。
:::

このようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349977/50a37cff-52ab-acaa-5281-9fc7e1535dd5.png)

Twitter : https://twitter.com/Kota_pclive
Misskey(りんごぱい) : https://misskey.04.si/@skota
プログラムのテストをするメリット

## はじめに
個人開発ではあまりした事がないという事も多いと思うが
今回はプログラムのテストについて調べたことをまとめていきたいと思います。

<h2>前提としてプログラムテストをする理由</h2>
プログラムテストを行うことで、プログラムが正しく機能していること、またはバグがないことを確認することができます。これによって、プログラムが期待通りに動作することを保証し、将来のトラブルを防ぐことができます。

## テストをするメリット
### 【担当者が変わった場合や新規にプロジェクトを担当する事になっても役立ちます】
プログラムを開発したチームが異動した場合や新しい開発者がプロジェクトに参加する場合に、テスト結果を参考にすることで、プログラムが正しく動作していることを確認し、メンテナンス作業をすることができます。
<br />
<br />
また、プログラムテストを通して、開発者が意図した通りに動作しているかを確認することができます。
これが確認できると、今後のトラブルを少なくしてくれるはずです。

### 【プログラムのパフォーマンスを測定し、改善することができる】
プログラムが大量のデータや高負荷の状態でも正しく動作し、期待通りの速度で動作するかを測定することができます。
<br />
<br />
例えば、作ったサービスがやたらとローディングが長くて使用ユーザーが早期離脱してしまうといった場合もデータベースアクセスやネットワーク通信などの、時間のかかる処理について
どの程度の時間がかかっているかを計測し、その結果を分析することで、どこが問題になっているかを特定し、それを解消することでパフォーマンスを向上させることができます。
<br />
<br />
また、パフォーマンスのテストは、様々な環境やデバイス上での動作を確認することができ、それによって、プログラムがどの程度のリソースを必要とし、どの程度のパフォーマンスが出るかを把握することができます。

なので、事前にテストを行うことで環境毎の確認も出来るわけです。

これによって、開発者は、処理を高速化するための最適なアルゴリズムの選択や、システム構成の最適化など、様々な手法を用いて、パフォーマンスを向上させることができます。

### 【ユーザーの期待に添うような品質のプログラムを提供することができる】
個人開発で自分が使うだけだと、あまり意識しなくてもいいかもしませんが
通常の場合、作成したプログラムは最終的にユーザーが使用することになります。

そのためにユーザーの期待に添うような品質のプログラムを提供できるように開発者が思いも
しなかったバグなどを早期発見して改善することができます。

### 【テストを通じて開発者のコーディングスキルを向上させることができる】

テストを書くことで、開発者は、プログラムがどのように動作するかを考える必要があります。これにより、コードの考え方を整理することができます。
テストでプログラムがどのような入力を受け取ってどのような出力を生み出すかを明確にすることができます。これにより、プログラムの内容をもう一度見直しコードの可読性を向上させることができます。

特に新規で参画したプロジェクトなどでは全体像を把握するためにもテストを作成する際にどのような入力を受け取ってどのような出力を生み出すか確認できることでソースコード内容の理解するためにも役に立つと思います。

## 【まとめ】

今回はテストプログラムについて調べたことをまとめましたが、個人開発ではあまりプログラムテストって取り組む事が少ないという事も多いと思います。
ですが何かしらのプロジェクトに参画するとプログラムテストを作成することがあるかと思います。
プログラムテストを行うことで、バグなどを防ぐ役割もありますが開発者側にも既存のテストでプログラムの動作確認やコーディングスキルを上げることも可能みたいですね。
javascriptで、文字列中のアルファベット以外の値を削除する

### やりたいこと

javascriptで、文字列に含まれる小文字のアルファベット以外の値を削除したい。

### 結果

以下のように書くことで、実現できた

```jsx
var str = "a man, a plan, a canal: panama"
var newStr = str.replace(/[^a-z]/gi, '')
// newStr = "amanaplanacanalpanamavar"
```

### 先頭の^の意味は何？

Caret（キャレット）と読む。行の先頭を示す

### 後ろのgiの意味は何？

g はグローバルサーチのg。通常は一度マッチングすると処理を終了する。このオプションをつけることによって一度マッチングした場合でも処理を繰り返す。

i は大文字と小文字を区別しない（今回の場合はすべて小文字なのでなくても良さそう）
【ABC285_D】 UnionFindで解いてみた 【C++】

[abc285のD問題](https://atcoder.jp/contests/abc285/tasks/abc285_d)をUnionFindを使って解いてみました。
言語はC++です。

- [DFSを使って解いてみた](https://qiita.com/Sakasu/items/6765f09172cad421d171 " DFS(深さ優先探索)で解いてみた")
- [BFS(幅優先探索)を使った解き方はこちら](https://qiita.com/Sakasu/items/2fb79169367d650d64a4 "")




# Point

1. **a → b → c → aと一巡したらダメ**そう
    * グラフ理論でいうところの**サイクル(閉路)があるかどうかを検出**
2. **頂点が文字**で与えられている 
    * **unordered_mapを使って番号に変換**
3. **UnionFind**(dsu)で頂点をグループ化
    * **既に閉路がある場合にさらにつなげる -> No**
4. 解けました！

# コード例

```c++:d.cpp
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
#define rep(i, a, b) for (int i = a; i < b; i++)

int main(){
    int n;
    cin >> n;
    //mapだと遅いので基本unordered_mapを使う
    unordered_map<string, int> mp;
    vector<string> s(n), t(n);
    //頂点が文字列 -> mapで頂点数を取得する
    rep(i,0,n){
        cin >> s[i] >> t[i];
        //文字の頂点番号を取得
        //文字が重複したら、最初に記録した頂点番号を採用
        if(!mp.count(s[i])) mp[s[i]]=mp.size();
        if(!mp.count(t[i])) mp[t[i]]=mp.size();
    }
    int m = mp.size(); //頂点数の取得
    //Disjoint Set Union = Union Find (素集合データ構造)
    //素集合...二つの集合が交わりを持たないor互いに素
    //∴共通の元を持たない
    dsu d(m);
    rep(i,0,n){
        //頂点番号の取得
        int u = mp[s[i]];
        int v = mp[t[i]];
        //すでにサイクルが形成されていればアウト
        if (d.same(u, v)){
            cout << "No" << endl;
            return 0;
        }
        //基本的に頂点をつなげるスタイル
        d.merge(u, v);
    }
    cout << "Yes" << endl;
    return 0;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2404591/bb5393a2-e641-d46f-8c13-cee72b6b521d.png)
解けました！
Docker を基本からまとめてみた【入門】

## Dockerとは?
１台のPC上に複数の仮想的なサーバー環境を手軽に構築できるソフトの事。

Dockerでは、あらかじめ構築したサーバーのセッティングを『イメージ』として配布してできるので、Docker設定ファイルに簡単な設定を書くだけですぐに構築済のサーバーを起動する事ができる。Docker設定ファイルをチーム内で共有すれば、全員のPCに同じ構成の開発環境を構築する事も簡単にできる。

公式サイト：[docker](https://docs.docker.com/desktop/install/mac-install/)

## 「コンテナ型」の「仮想化」プラットフォーム

「コンテナ型」の「仮想化」プラットフォーム、Dockerの登場によって、従来の作業や管理方法が激変し、開発などで発生するさまざまな作業の自動化が可能になった。
Dockerにおける貨物輸送に用いる「コンテナ」にも同じような意味合いがあり、アプリケーションやサーバを「コンテナ」という規格が定まった容器に収納することで、扱いやすくしている。

Dockerの仕組みを理解するには、「仮想化」という概念が重要で、10年ほど前は、1台のサーバに1つのOSをインストールして利用するのが一般的でした。対して「仮想化」は、1台のサーバに仮想化ソフトをインストールすることで複数のサーバとして利用することができる。

しかし、「仮想化」といってもPCのハードウェア全体を仮想化することで、OSやアプリケーションなどを動作させる「完全仮想化」の仮想マシンと違い、「コンテナ型」はコンテナがホストOSのカーネルを利用することからメモリやディスクの使用量が少なく、軽量で高速な動作が可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/856d84d4-bffe-e5fb-b2db-6c01a4b97994.png)

## コンテナ型

コンテナ型は、OS上に「コンテナエンジン」という仮想化ツールをインストールし、コンテナイメージを作成することでコンテナを仮想化する方式。ゲストOSを必要としない分、少ないリソースで済み、コストパフォーマンスにも優れていますが、仮想技術としては後発ということもあり、構築できるベンダーや管理ツールが少ないという現状はある。

ホスト型やハイパーバイザー型といった仮想化環境とコンテナ型の仮想化環境の最大の違いはゲストOSの有無で、前者で仮想サーバを作った場合、それぞれのゲストOSを独立したサーバとして起動させるので、アプリの構築・運用における自由度が高くなりますが、毎回OSを起動しなければいけないので物理環境よりも性能が劣る可能性がある。
一方、コンテナ型でコンテナを作った場合、各コンテナが1つのOSを共有しているため、OSに関して不自由ではありますが、メモリやディスクといったリソースやユーザやプロセスなどをサーバごとに隔離できるため、高速起動・実行できる。

## Dockerを使うメリット
##### メリット①：システム導入までの手間が省ける
OSは既に共有して利用しているので、設定を省くことができ、システム構築に必要な最低限のプログラムのみのインストールですぐに使い始めることができる。

##### メリット②：起動時間の短縮と処理速度の向上
OSが既に立ち上がっている分、サーバーの起動時間を短縮できる。また、最小限のリソースの使用量で済むため、サーバーへの負荷が低く、1度に多くのプログラムを処理できる。

##### メリット③：コンテナ設定の再利用が可能
Dockerで一度作成したコンテナは、他のコンテナに適用させることで再利用が可能。
リソースを拡大したい時や検証したい時などに、すぐに同じ環境設定のコンテナを準備することがでる。

## Dockerの使い方や基本コマンド

##### バージョンの確認
```
docker version//インストールされたDockerのバージョンを確認する
```
##### 動作しているコンテナの確認
```
docker ps//動作しているコンテナを確認する
```

##### 現在取得済みのイメージの一覧表示

```
docker ps -a//取得済みのイメージを一覧表示する

docker images//ダウンロードしたDockerイメージを一覧表示する
```
## Dockerの実行
```
docker run hello-world//Dockerを実行する
```
「Hello from Docker!」と表示されれば成功




## 参考サイト
[Docker最初の1歩 Webアプリの開発環境を構築してみよう！【初心者向け】【プログラミング】](https://www.youtube.com/watch?v=s1FVLHSDIZE)
[【Docker入門】初心者向け！Dockerの基本を学んでコンテナ型の仮想環境を作ろう！](https://www.youtube.com/watch?v=B5tSZr_QqXw)
[Docker入門（第1回）｜初心者向けに概要や基本コマンドを解説](https://techmania.jp/blog/docker0001/)
ESP Web Toolsを使用してビルド済バイナリを配布する方法

# はじめに

スマートホームの新標準「Matter」のビルド環境を構築するのがそれなりに大変なので、ESP Web Toolsを使用してビルド済バイナリを配布する方法を試してみた。

https://esphome.github.io/esp-web-tools/

# 構成

ビルド環境でビルドしたバイナリファイルをGitHubへPUSHし、GitHub Pagesへ公開します。
ウェブシリアル機能を使用可能なブラウザ(Chrome、Microsoft Edgeなど)からGitHub Pagesへアクセスし、パソコンへ接続したデバイス(M5Stackなど)へウェブシリアル経由でバイナリファイルを書き込みます。

![スクリーンショット 2023-01-22 10.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/1e612f20-30da-20d7-93c3-eadca1e89663.png)

# 手順

## 1. index.htmlにESP Web ToolsのJavaScriptを埋め込む

(抜粋)

```javascript:index.html
<script
  type="module"
  src="https://unpkg.com/esp-web-tools@9.2.0/dist/web/install-button.js?module"
></script>
```

## 2. manifest.jsonファイルを作成する

複数のバイナリファイルを配布する場合、フォルダを作成し、その中にmanifest.jsonファイルを作成します。

(サンプル)

```json:manifest.json
{
  "name": "Matter Lighting App Example for ATOM Lite",
  "version": "4088a77",
  "new_install_improv_wait_time": 0,
  "builds": [
    {
      "chipFamily": "ESP32",
      "parts": [
        {
          "path": "bootloader.bin",
          "offset": 4096
        },
        {
          "path": "partition-table.bin",
          "offset": 32768
        },
        {
          "path": "ota_data_initial.bin",
          "offset": 61440
        },
        {
          "path": "chip-lighting-app.bin",
          "offset": 131072
        }
      ]
    }
  ]
}
```

# サンプルサイト

## GitHub Pages

https://kitazaki.github.io/matter-example-apps/

### 警告表示について

左下の「詳細」ボタン→「安全でないこのサイトにアクセス」を選択すると、インストール画面が表示されます。

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/709ea569-ed57-1cc2-9d16-d1435dafd39c.jpeg)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/d2555964-b2c5-f43d-c3d3-3deb812cf0b2.png)
![スクリーンショット 2023-01-22 10.46.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/ab521e96-e1c2-2ff9-5c34-a88da9458cdb.png)

## Netlify

GitHubからNetlifyへデプロイした場合、警告表示はされませんでした。

![スクリーンショット 2023-01-31 15.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/204ecbdc-494f-ef60-eff8-4cfefd6d9d23.png)

https://illustrious-donut-ee3174.netlify.app/

![スクリーンショット 2023-01-31 15.21.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72479/874de4c0-b5d4-6021-5e30-4cd77ee80448.png)
Oracle で、スキーマ毎の利用容量を一覧で取得したい



Oracleで、スキーマ毎に利用している容量を知りたい。

……んだけど、なぜか、where 文でいちいちスキーマを指定する方法のクエリしか見つからない。探し方悪いかも、なんだけど。

別に大したことしていないんだけど、owner で group by しただけなんだけど、これでスキーマ毎に表示してくれる。

```
select owner,sum(bytes)/(1024*1024) "SIZE[M]" from dba_segments group by owner;
```
JavaScript行きついた結論(3)

前回の続き。。。
以下のソースをJavaScriptのフレームワークを変えて、VERCEL上にデプロイしてみた。

https://qiita.com/EasyCording/items/3643c482b29c87841207?fbclid=IwAR2uj27eSoLL-gVjx7lLCNPN0qf5U99aLDa8V-uj3CBobtBQhTlMOycUzrg

# React / Next / Parcel

(REACT)　https://create-react-app-yamap-y6hp.vercel.app/
(NEXT)　https://nextjs-yamap.vercel.app/
(percel) Staticデータの保存先がよく分からずに、結局、PARCELは動かなかった。

# 結果
若干だがREACTよりも、NEXTの方が読み込みが速かった。

# 結論
やはりNEXT.JSで開発を進めることにした。
Playwright テストコード並列実行時のワーカー別ログ出力方法メモ


* `Playwright`+`pytest-xdist`で並列ブラウザアクセスした際のノード(ワーカー)別にログ出力する方法についてメモする。

## コード

* `test.py`

  * `Playwright`公式サイトにアクセスし、`title`要素の確認を行う。
  * `pytest-xdist`ワーカー別にログ出力を行う。

  ```python
  from playwright.sync_api import Playwright
  import logging
  
  # ワーカー別ロガーを定義する
  def _get_logger(worker_id):
      logger = logging.getLogger("logger_{}".format(worker_id))    
      handler = logging.FileHandler(filename="test_{}.log".format(worker_id))  
      handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))
      logger.setLevel(logging.INFO)  
      logger.addHandler(handler)
      return logger
  
  # `worker_id`にワーカープロセスIDが格納される
  def test_parallel(playwright: Playwright,worker_id):
      browser = playwright.chromium.launch(headless=True)
      page = browser.new_page()
      # ページアクセス＋タイトルチェック
      page.goto('https://playwright.dev/python/')
      assert page.title() == 'Fast and reliable end-to-end testing for modern web apps | Playwright Python'
  
      # ワーカー別ログファイルにログ出力を行う
      # ワーカープロセスID,URL,タイトル
      logger = _get_logger(worker_id)
      logger.info('worker:{}  url:{}  title:{}'.format(worker_id,page.url, page.title()))
      page.close()
  
  ```

  

## 動作確認

* 以下のコマンドを実行する

  ```shell
  pytest -n 3 --dist each test.py
  ===================================================== test session starts =====================================================
  platform linux -- Python 3.8.10, pytest-7.2.0, pluggy-1.0.0
  rootdir: /home/u5008506/dev/playwright-test
  plugins: html-3.2.0, playwright-0.3.0, metadata-2.0.4, cov-4.0.0, base-url-2.0.0, xdist-3.1.0, parallel-0.1.1, anyio-3.3.4
  gw0 [1] / gw1 [1] / gw2 [1]
  ...                                                                                                                     [100%] [100%] [100%]
  ====================================================== 3 passed in 9.98s ======================================================
  ```

  以下のように、`test_{worker_id}.log`ファイルにログ出力が行われる

* `test_gw0.log`

  ```
  2023-01-09 10:50:45,884 INFO worker:gw0  url:https://playwright.dev/python/  title:Fast and reliable end-to-end testing for modern web apps | Playwright Python
  ```

* `test_gw1.log`

  ```
  2023-01-09 10:50:45,898 INFO worker:gw1  url:https://playwright.dev/python/  title:Fast and reliable end-to-end testing for modern web apps | Playwright Python
  ```

* `test_gw2.log`

  ```
  2023-01-09 10:50:46,002 INFO worker:gw2  url:https://playwright.dev/python/  title:Fast and reliable end-to-end testing for modern web apps | Playwright Python
  ```

  

## 参考情報

* [Identifying the worker process during a test](https://pytest-xdist.readthedocs.io/en/latest/how-to.html#identifying-the-worker-process-during-a-test)
pytest-xdistを用いたPlaywright テストコード並列実行方法 メモ



* ブラウザテスト用ライブラリ`Playwright`で作成したコードをテストライブラリ`pytest-xdist`で並列実行する方法についてメモする。

## 事前準備

* 並列実行用ライブラリ`pytest-xdist`をインストールする

  ```shell
  pip install pytest-xdist
  ```

  

## コード

* テストコード`test.py`

  ※Playwright公式サイトにアクセスし、ページタイトルを確認するコード

  ```python
  from playwright.sync_api import Playwright
  
  def test_parallel(playwright: Playwright):
      browser = playwright.chromium.launch(headless=True)
      page = browser.new_page()
      # ページアクセス
      page.goto('https://playwright.dev/python/')
      # タイトルチェック
      assert page.title() == 'Fast and reliable end-to-end testing for modern web apps | Playwright Python'
      page.close()
  
  ```

  

## 動作確認

* 以下のコマンドを実行し、並列アクセスを行う

  ```shell
  pytest -n 3 --dist each test.py
  ================================================================================ test session starts =================================================================================
  platform linux -- Python 3.8.10, pytest-7.2.0, pluggy-1.0.0
  rootdir: /home/u5008506/dev/playwright-test
  plugins: html-3.2.0, playwright-0.3.0, metadata-2.0.4, cov-4.0.0, base-url-2.0.0, xdist-3.1.0, parallel-0.1.1, anyio-3.3.4
  gw0 [1] / gw1 [1] / gw2 [1]
  .                                                                                                                                                                              [100%]. [100%]. [100%]
  ================================================================================= 3 passed in 9.37s ==================================================================================
  ```

  ※`-n` ：並列実行するノード数を指定する。`auto`を指定した場合利用可能なCPUのコア数が自動的に設定される。

  ※同時に3ブラウザからアクセスするテストを実行する。

## 参考情報

* [Parallel Runs in Playwright Python](https://chercher.tech/python-playwright/parallel-run-playwright-python)
* [pytest-xdist](https://pytest-xdist.readthedocs.io/en/latest/index.html)
ARPテーブル管理

# はじめに

- arpテーブルはほとんどみることがなくて忘れるのでメモ

# arpテーブル管理コマンド

- ip neigh show
- ip neigh show nud reachable
    - REACHABLEでフィルタ
- ip neigh add
    - 追加
- ip neigh change
    - 変更
- ip neigh replace
    - 値が存在していれば変更し、なければ新規追加
- ip neigh del
    - 選択削除
- ip neigh flush
    - 一括削除
バージョン2.0.1でSWRの型が便利になった

# はじめに
SWRは[バージョン2.0.1](https://github.com/vercel/swr/releases/tag/v2.0.1)でSuspenseモードにおける`data`の型推論の結果が変化しました。パッチリリースですが、長年苦しんでいた問題が解決されたので紹介します。

# 2.0.0以前の世界
ReactにSuspenseが登場してからデータ取得はより宣言的に書くことができるようになりました。
元々SWRを用いてデータ取得を行うコンポーネントは以下のように書かれていました。以後`fetcher`の返り値は`Promise<string>`とします。
```tsx
export const Sample = (): JSX.Element => {
  const { data } = useSWR(key, fetcher);
  
  if (!data) {
    return <Loading />;
  }
  
  return <>{data}</>;
};
```
そして、Suspenseが登場してからは以下のように書けるようになりました。
```tsx
export const Sample = (): JSX.Element => {
  const { data } = useSWR(key, fetcher, {
    suspense: true,
  });

  return <>{data}</>;
};

export const App = (): JSX.Element => {
  return (
    <Suspense fallback={<Loading />}>
      <Sample />
    </Suspense>
  );
};
```
`data`が取得できていなかったら(`undefined`だったら)`<Loading />`を返すような命令的なコードから親コンポーネントで`<Sample />`がSuspenedされていたら`fallback`を表示させるような宣言させるコードに変わっています。
この例では`useSWR`から`data`が返される時には`fetcher`が解決済みになっているはずなので、`data`の型は`string`となって欲しいです。しかし、実際は`string | undefined`となります。この結果はこの例では問題になりませんが、取得したデータを他のコンポーネントに渡すときや、プリミティブで無いデータを扱っているときに`data`が`undefined`ではないことを確認する分岐が必要になってしまいます。
このことはswrのリポジトリでも議論に挙げられることが多く、例えば以下のissueで議論されていました。

https://github.com/vercel/swr/issues/1412

# 2.0.1で変更された型
先日のパッチバージョンアップではその問題が解決しました。
```tsx
export const Sample = (): JSX.Element => {
  const { data } = useSWR(key, fetcher, {
    suspense: true,
  });

  return <>{data}</>;
};

export const App = (): JSX.Element => {
  return (
    <Suspense fallback={<Loading />}>
      <Sample />
    </Suspense>
  );
};
```
先ほどと同じコードなわけですが、`data`の型は`string | undefined`から`string`に推論されるように変更されました。
これによって毎回`data`が`undefined`では無いことを確認しなくて済むようになったのでとても嬉しい変更です。ただし、`useSWR`の第三引数`options`に`{ suspense: true }`としなければこの推論にならないので注意してください。

# 疑問
私の環境ではSuspenseモード下で条件付きフェッチを行ったとしても`data`の型は`string`に推論されてしまいました(実行するとエラーが出ます)。
[ドキュメント]([https://swr.vercel.app/ja/docs/suspense#%E6%B3%A8%E6%9D%A1%E4%BB%B6%E4%BB%98%E3%81%8D%E3%83%95%E3%82%A7%E3%83%83%E3%83%81%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88])に従うと`data`の型は`string | undefined`になると考えていたので疑問でした。
先ほどの[issue](https://github.com/vercel/swr/issues/1412
)を読むとSuspenseが有効な時は`data`が`undefined`にならないという制限だけではなく、`key`がFalsyな値ではないこと、`fetcher`が`null`ではないような制限が必要と書かれていました。Suspenseモードでは`Promise`を`throw`するもしくは解決後の値を返すだけを想定していて、これに当てはまらない条件付きフェッチではエラーを出さざるを得ないのではいかなと考えています。
今後この周りがどのように変化していくかとても楽しみです。
Laravel9でアプリを作成してみた【ゴミ箱付きToDoリストアプリ】

## ファイル構成
```
  docker-config
   ├─ mysql
        ├── data //データの保存
        └── my.cnf
   ├─ nginx
        ├── Dockerfile
        └── default.conf
   ├── php
        ├── Dockerfile
        └── php.ini
```
```
docker-compose up -d
docker ps

```





## 参考サイト
[【シンプル解説】Laravel9でゴミ箱付きToDoリストアプリを作る](https://www.youtube.com/watch?v=HHHN76dHrv0&t=1144s)
主なTCP/UDPのチューニングポイント

# はじめに

- すぐに忘れてしまう、TCP/UDPのチューニングポイントのメモ

# 設定値の確認

- カーネルパラメータで設定

    - net.core.rmem_default
        - 受信ソケット用バッファのデフォルト値(Byte)
    - net.core.rmem_max
        - 受信ソケット用バッファの最大値(Byte)
    - net.core.wmem_default
        - 送信ソケット用バッファのデフォルト値(Byte)
    - net.core.wmem_max
        - 送信ソケット用バッファの最大値(Byte)
    - net.ipv4.tcp_rmem
        - TCP受信バッファの最小、デフォルト、最大(Byte)
    - net.ipv4.tcp_wmem
        - TCP送信バッファの最小、デフォルト、最大(Byte)
    - net.ipv4.tcp_mem
        - TCP全体で利用するメモリの最小、デフォルト、最大(Byte)
    - net.ipv4.udp_rmem
        - UDP受信バッファの最小、デフォルト、最大(Byte)
    - net.ipv4.udp_wmem
        - UDP送信バッファの最小、デフォルト、最大(Byte)
    - net.ipv4.udp_mem
        - UDP全体で利用するメモリの最小、デフォルト、最大(Byte)
    - tcp_max_syn_backlog
        - 接続待ち数
    ```terminal
    $ sudo sysctl -a | grep net\.core\..mem
    net.core.rmem_default = 212992
    net.core.rmem_max = 212992
    net.core.wmem_default = 212992
    net.core.wmem_max = 212992
    $ sudo sysctl -a | grep net\.ipv4\.tcp_.*mem
    net.ipv4.tcp_mem = 91269	121692	182538
    net.ipv4.tcp_rmem = 4096	131072	6291456
    net.ipv4.tcp_wmem = 4096	16384	4194304
    $ sudo sysctl -a | grep net\.ipv4\.udp_.*mem
    net.ipv4.udp_mem = 182538	243384	365076
    net.ipv4.udp_rmem_min = 4096
    net.ipv4.udp_wmem_min = 4096
    $ sudo sysctl -a | grep tcp.*backlog
    net.ipv4.tcp_max_syn_backlog = 512
    ```

# 設定方法

- `/etc/sysctl.conf` へ記述、 `sysctl -p` で即時反映
console.tableでobjectをテーブルで表示する

## console.tableをするとobjectをテーブルで表示することができる
```js
const user = {
    name: 'Josh', age: 22,
    name: 'Bob', age: 18
};

console.table(user);
```
結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/380959/44998394-f8d2-87a1-a1c5-a01e2bbbd7b3.png)
UbuntuでRAMディスクの利用

# はじめに

- tmpfsはRAMディスクだけど、自分で定義もして使いたい

# 自動的に作成されてマウントされている tmpfs

- 自動的に作成・マウントされているRAMディスク
- /dev/shm にマウントされているので使うことができる

- 確認
```terminal
$ df -h | grep tmpfs
tmpfs           780M  1.3M  779M   1% /run
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
tmpfs           780M     0  780M   0% /run/user/1001
```

# 自分で作成してマウントする tmpfs

- 作成

```terminal
$ sudo mkdir /data
$ sudo mount -t tmpfs -o size=100m tmpfs /data
```

- 確認

```terminal
$ df -h | grep tmpfs
tmpfs           780M  1.3M  779M   1% /run
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
tmpfs           780M     0  780M   0% /run/user/1001
tmpfs           100M     0  100M   0% /data
```

# マウント解除

```terminal
$ sudo umount /data
```

- umount が busy でエラーになる場合、利用しているプロセスをみつけて kill するなりする

```terminal
$ fuser -muv /data
```

# さいごに

かんたんでしたね
console.timeで処理時間を表示する

## console.timeを使用すると細かく処理にかかっている時間を見ることができる
```js
console.time("Loop");
for(i = 0; i >= 10000; i++){
    // 処理
}
console.timeEnd("Loop");

// 結果
// Loop: 7.615ms
```


下記のように時間をとるとms単位で時間をとることができなかった
```js
let startTime = Date.now();
for(i = 0; i >= 10000; i++){
    // 処理
}
console.log(Date.now() - startTime);

// 結果
// 0
```
GitHub APIでユーザーの情報をJSONで取得し、画面に表示する

## はじめに
GitHubについて勉強したので、メモとして残していきたいと思います。

## GitHub APIとは？
GitHubが提供しているAPIで、GitHubに登録しているユーザーの情報や、そのユーザーのリポジトリの情報など、様々なデータをJSONで取得できるAPIになります。
今回は、取得したリポジトリの一覧を、JavaScriptで画面に表示をしていこうと思います。

## リポジトリの情報を取得する
今回は自分が公開をしているGitHubを使用していきます。
以下のURLでAPIを用いて、自分のユーザーデータから、リポジトリ一覧情報を取得することができます。

```
https://api.github.com/users/GitHubの登録ユーザー名/repos
```

今回使用するURLはこちらです。hukuryoというユーザーのリポジトリ一覧を取得します。

```
https://api.github.com/users/hukuryo/repos
```

表示される画面がこちらです。↓
![スクリーンショット 2023-01-22 9.14.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/8cc009e3-1f5b-c361-0065-3625868e930b.png)

このように、リポジトリの一覧が取得できました。
色々な情報を取得できていますが、nameというカラムがリポジトリの名前になります。

## 取得したJSONをHTMLに反映する。
次は、取得したJSONをJavaScriptでHTMLに表示していきたいと思います。コードはこちらです。

``` : script.js
const button = document.getElementById('click');
const type = document.getElementById('type');
button.addEventListener('click', () => {
    let url = 'https://api.github.com/users/hukuryo/repos';
    fetch(url)
      .then(response => response.json())
      .then(data => {
        for(let i = 0; i < data.length; i++){
          newElement = document.createElement("div");
          newElement.innerHTML = data[i].name;
          type.appendChild(newElement);
          console.log(data[i].name);
        }
    });
});
```

``` : index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>sample</title>
    </head>
    <body>
    <button id='click'>sample</button>
    <div><span id='type'></div>
    <script src="script.js"></script>
</body>
</html>
```


そしてこれが実際の画面です。↓
![スクリーンショット 2023-01-22 9.18.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/75dd1482-7410-acba-6651-ebf3bde3e169.png)

ボタンを押すと...

![スクリーンショット 2023-01-22 9.19.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/1f3dd957-1715-f7a7-7575-66d30e6e3517.png)

JSONで取得したデータをHTMLに反映することができました！
GitHub APIには、他にも様々な機能があるので下記のURLから調べてみてください！
https://docs.github.com/ja/rest?apiVersion=2022-11-28

以上になります。
Reactで星評価機能を実装する

react-awesome-stars-ratingというライブラリを使用して、
下記のような星評価機能を実装しました。
https://github.com/fedoryakubovich/react-awesome-stars-rating

![8b6e208377656b92b5b0dfbbfc642489.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1559434/3f7dc993-922f-9567-ef1e-e327e0c023e2.gif)

## 使い方
npmにreact-awesome-stars-ratingをインストールする。
```
npm install react-awesome-stars-rating
```

ReactStarsRatingコンポーネントをimportして使用する。
```Star.jsx
import { useState } from "react";
import ReactStarsRating from 'react-awesome-stars-rating';

export const Star = () => {
  const onChange = (value) => {
    setValue(value)
  };

  const [value, setValue] = useState(3);

  return (
    <>
      <ReactStarsRating onChange={onChange} value={value} />
    </>
  )
}

```
星の色や数も変更することができます。
設定値についてはドキュメントに記載されています。
https://github.com/fedoryakubovich/react-awesome-stars-rating#documentation

![57d1125b4b7f554c204daea04444cb7b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1559434/1a74fab4-1505-7268-8402-e69ee348e790.gif)
CLOUD SHELL が起動できなくなるという嵌り

さあ、CLOUD SHELL を立ち上げて遊ぼうかな、と思って、いつものように立ち上げようとすると、なにやら不穏な表示が。

![Screenshot from 2023-01-22 08-35-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470368/e1331cd0-21bd-cbbf-7c2f-d662d636ce05.png)

CLOUD SHELL に Quota なんかあったのか、知らなかった。

なんでも、週、50時間とか、リクエストできるみたいだけど、時間かかるようだし、有償に入るものちょっとまだにしたいし、どうしたらいいんだろうか。今週分の Quota を使い切ったということなら、来週になったら使えるようになるのだろうか。

```
Usage quotas
The default weekly Cloud Shell quota is 50 hours.
```

（参考）
https://cloud.google.com/shell/docs/quotas-limits#usage_quotas

Quota の上限を変更要求するという、そのもののリンクがあるようだ。
ここからできるのかな？

（参考）
https://cloud.google.com/docs/quota#requesting_higher_quota

どうやら、IAM & Admin の下にあることがわかった。
そこから、検索して、目的の Quota のとりあえず、現状が確認できるのか。

うーん、filter にかけようとしても、Cloud Shell は、発見できない。
1週間 50時間というのは、直近 1週間ということだとすると、ひょっとして、明日になったら使えるようになる可能性もあるかも？

（参考）
https://youtu.be/sc5ssfin8L0?list=PLIivdWyY5sqJOQJCXW_aYEqwfyi6bu1gC

数時間待って、再度 CLOUD SHELL を起動してみたところ、起動できました。

ということは、直近 1週間の使用時間が 50 時間を越えていた、その、1日分がリセットされた、ということなのかも。使用時間が、直近 1週間で、50時間を越えないように使用する工夫が必要なのかな、と考えています
Googleプロジェクト管理：データのプライバシーとバイアス

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/dc97f9d2-8c30-5310-a190-3fb484c9c091.png" width="800">

# データ倫理

プロジェクトマネージャーとして、データの収集と分析はプロジェクトの重要な部分を占めます。インタビュー、アンケートなど、さまざまなソースからデータを収集することになります。収集するデータには通常、PII（個人を特定できる情報）、つまり個人を直接特定したり、連絡したり、場所を特定したりするために使用できる情報が含まれます。また、多くの場合、収集したデータについてステークホルダー、顧客、プロジェクトチームに対して報告する必要があります。このようなデータを倫理的な方法で収集、分析、共有することは、組織、プロジェクト、および自分の地位の完全性を維持するために非常に重要です。

***<font color="MediumVioletRed">『データ倫理とは、データの収集と分析に関連する道徳的な課題を研究し評価すること』</font>***

企業は、データ倫理の実践を行うことで、以下のことが可能になります。

- 規制を遵守する
- 信頼に足ることを示す
- 公正かつ合理的なデータ利用を確保する
- バイアスの最小化
- ポジティブな社会的認知を獲得する

データ倫理は、いくつかの原則に根ざしています。今回は、そのうちの2つの原則、

- データプライバシー
- データバイアス

に焦点を当てます

## データプライバシー

***<font color="MediumVioletRed">『データ・プライバシーは、データの適切な取り扱いを扱うもの』</font>***

これには、データの収集と処理の目的、プライバシー設定、組織による個人データの管理方法、および個人の権利が含まれます。データの収集、処理、共有、保存、削除の方法がすべて法律に従っていることを確認することに重点が置かれています。

プロジェクトマネージャーには、収集したデータを保護する責任があります。プロジェクトのためにユーザー、ステークホルダー、その他の人々から収集したデータのプライバシーを確保するために、次のことを行うことができます。

#### <font color="MediumBlue">データプライバシーに関する意識の向上</font>
プロジェクトチームのメンバー全員、およびベンダー、請負業者、社外の関係者に、組織のデータセキュリティとプライバシーに関するプロトコルを周知徹底させる。

#### <font color="MediumBlue">セキュリティツールの使用</font>
暗号化されたストレージソリューションやパスワードマネージャなどのセキュリティツールを使用すると、データ侵害に対するプロジェクトの脆弱性を低減することができます。Google WorkspaceやMicrosoft OneDriveのような多くのアプリケーションでは、プライバシー設定を調整して、特定の個人のみにアクセスを許可することができます。


#### <font color="MediumBlue">データの匿名化</font>
データの匿名化とは、データに含まれる人々の身元を保護するために、個人情報や識別情報をブランキング、ハッシュ化、マスキングするなどの1つまたは複数のテクニックを指します。これにより、匿名性を維持することで、個人の個人情報を保護することができます。匿名化された情報は、自由に利用・共有することができます。匿名化されるべきデータの種類には、名前、電話番号、社会保障番号、電子メールアドレス、写真、口座番号などがあります。

## データバイアス

もう一つの重要なデータ倫理の実践は、収集したデータが偏りを示していないことを確認することです。

***<font color="MediumVioletRed">『データバイアスとは、結果を特定の方向に偏らせる傾向のあるエラーの一種』</font>***

- アンケートの質問が回答に影響を与えるような特定の傾きをもっている。
- サンプルグループが調査したい集団を完全に代表していなかったりする。
- サンプルグループが包括性を欠いている場合にも、偏りが生じる。たとえば、サンプルに障害者が含まれていない場合など。
- データを収集する方法によっても、データセットに偏りが生じることがあります。質問に答えるための時間を短くすると、回答を急がせることになります。人々は、急ぐとミスをする傾向があり、データの品質に影響を与え、偏った結果を生み出す可能性があります。

プロジェクトマネージャーとして、あなたはデータを集め始めてから結論を発表するまでの間、バイアスと公平性について考えなければならないのです。

### バイアスの種類

- **サンプリング・バイアス**: サンプルが母集団全体を代表していない場合です。例えば、サンプルに65歳以上の人が含まれていなかったとします。あるいは、特定の社会経済集団の人々を除外したのかもしれません。
- **観測者バイアス**: 異なる人々が異なる方法で物事を観察する傾向のことです。例えば、世界の異なる地域の関係者は、同じデータでも異なる見方をし、そこから異なる結論を導き出すかもしれません。
- **解釈バイアス:** 明白な答えのない状況において、実際にはデータを理解する方法が1つではないにもかかわらず、常に厳密に肯定的または否定的に解釈する傾向のことです。結論が明らかでないデータは、人によっては不安になり、それが解釈バイアスにつながることがあります。例えば、あるチームメンバーは結論の出ない調査結果を否定的に解釈し、他のチームメンバーはより慎重に考え、異なる角度からデータを評価することができるかもしれません。
- **確証バイアス:** 既存の信念を確認するような方法で情報を探したり解釈したりする傾向です。例えば、プロジェクトの一部について、特定の関係者だけにフィードバックを求めることがあります。この関係者は、あなたと同じ視点を持つ可能性が最も高いとわかっているからです。

これらのバイアスは、データの収集や意味の理解の仕方に影響を与えるので、データ収集プロセスを設定する際に意識することが重要です。
「なぜあなたの仕事は終わらないのか」から学ぶ時間管理


# はじめに

こんにちは。
こちらの記事では、中島 聡さん著「[なぜあなたの仕事は終わらないのか](https://www.amazon.co.jp/%E3%81%AA%E3%81%9C%E3%80%81%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AF%E7%B5%82%E3%82%8F%E3%82%89%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B-%E3%82%B9%E3%83%94%E3%83%BC%E3%83%89%E3%81%AF%E6%9C%80%E5%BC%B7%E3%81%AE%E6%AD%A6%E5%99%A8%E3%81%A7%E3%81%82%E3%82%8B-%E4%B8%AD%E5%B3%B6%E8%81%A1/dp/4905073413/ref=sr_1_1?keywords=%E3%81%AA%E3%81%9C%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BB%95%E4%BA%8B%E3%81%AF%E7%B5%82%E3%82%8F%E3%82%89%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B&qid=1674277774&sprefix=%E3%81%AA%E3%81%9C%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BB%95%E4%BA%8B%2Caps%2C277&sr=8-1)」を読んで学んだことやこれから実践することについてまとめていきます。

# 本の概要

「なぜあなたの仕事は終わらないのか」では、タイトルの通りの仕事が終わらない要因となっている仕事の取り組み方や考え方について説明し、それらをどのような手段で解決していくかを説明している本です。

# この本をおすすめしたい人

- 期日までに仕事が完了できそうになく、残業することが多い状況をどうにか変えたい人
- 自分夢を実現したい人

# 学んだこと

## 1. 仕事が終わらない要因

- 計画の見積もりをしていない。
- 開始のデッドラインを決めていない。
    - 完了期日は決めていることが多いが、複数のタスクをこなしていく中で、いつまでに開始すれば間に合うのか。を決めておく。
- ラストスパート志向で仕事に取り組んでしまっている。
- 数学のテスト後半にある応用問題を甘く見ている。
    - 応用問題は、想定よりも時間がかかってしまうように、仕事が終わらない人はどれくらいの規模のタスクがあるのか把握できていない。
- 仕事に取り組む前に、明確な期日を決めていない。
    - 「なるはやで」といった曖昧さが仕事の遅延を招く。
- 自身が抱えているタスク状況を共有せず、仕事を安請け合いしてしまう。
- 締め切り前に徹夜・残業すればなんとかなると考えている。
- どうしても締め切りに間に合わなければ、スケジュールを変更して貰えばいいと安易に考えている。

## 2. 仕事を終わらせるための対策

- 仕事の見積もりは、実際に手を動かして、リスクを排除しながら設定する。
    - 慣れるまでは、憶測だけでは正確な見積もりは測れない。
- 仕事を受けたら期日までの 2割の時間で ほぼ完成（8割）までもっていく。
    - 2割の時間で仕事の進捗が間に合いそうになければ、すぐに上司に相談する。
- 70,80% の完成度でも、期日前に提出してフィードバックを受ける。
    - 仕事では必ず、大なり小なりやり直しが発生するため。
- 締め切り前の締め切りを自分の中で決めておき、その期日までに達成できるように、スタートダッシュを切る。
- スケジュールに余裕を持った上で、仕事の質を高めることを意識する。
- 「界王拳」で仕事の集中時間を確保する。
- 寝る前に明日やることを 15分単位のタスクでリストアップする。

# 実践すること

## 最初の2割に全集中する

仕事が遅延してしまう要因として、

- 正確な見積もりができていない
- 集中して仕事に取り組む時間を確保できていない
- 前半にタスク状況を上司に相談する

などが挙げられるかと思います。
プロジェクト後半になってくるにつれて、どんどん余裕がなくなってくるので、前半でいかに対策を講じれるか、が肝になると痛感しました。

なので、本書で紹介されている「ロケットスタート時間術」を実践し、集中時間と流す時間のメリハリを意識して仕事に望んでいきます。

## 前日に15分単位でタスクを分割する

タスクの見える化は当たり前のことですが、 `15分単位` というのが効果的だと感じました。
この粒度で細分化できれば、見積もりの正確性が向上したり、サクサクタスクをこなすことができるので、**「仕事を追っている感覚」** が得られて達成感につながります。
それによって、仕事を進めていくリズムが生まれて、今までのような「期限が迫る仕事に追われる感覚」から解放されるのではと思います。

私も以前は、この方法を実践して効果を実感していましたが、余裕がなくなるにつれて忘れてしまっていました。地味ながらも、リストアップの威力は計り知れないので、改めて実践していきます。

## 期日直前の交渉は絶対に避ける

仕事の前半で対策を講じるべきとお話ししていたように、期日直前になってからでは、対策のしようがなくなります。

プロジェクト後半に差し掛かると、だれもが忙しい状況となるため、ヘルプを求めるのが億劫に感じられることがあると思います。ですが、チーム全体としての成果を考えたときに、自身では解決できないボールを持ち続けているのは、遅延を招く原因となってしまいます。

なので、2割の時間で上司に状況を説明し、フィードバックを受けるタイミングを自身で設定しておくことで、できるだけ方向性をブらすことなく、仕事を前に進められるようにしていきます。

# おわりに

ここまで「なぜあなたの仕事は終わらないのか」についてまとめました。
以上、最後まで読んでいただきありがとうございました！
RailsでAjax通信を使って項目を絞り込む



# やりたいこと

　個人開発でやっているサービス「lytnote」の改善を行いたい。目標一覧画面にはユーザーが登録した目標が並んでいる。それぞれにはステータスがあって、完了や中止や進行中が選べる。振り返りの際に目標のステータスを変更するのだ。

```
目標A  状態：進行中
目標B  状態：完了
目標C  状態：中止
目標D  状態：完了
....
```

　でも使っていくと、目標がどんどん増えてしまう。進行中の目標のみを絞り込んで表示したい。

　目標の絞り込みを行うぞ。

# フロー

```
目標一覧画面表示
↓
絞り込みたいステータスをプルダウンで選ぶ 
↓
絞り込みボタンを押す
↓
絞り込まれる
```

　これでやっていこう。つくるものを考える。

1. 一覧画面にプルダウン表示
2. コントローラー修正
3. jsファイル修正
4. 一覧画面に部分テンプレート追加   


# 1. 一覧画面にプルダウン表示

```erb:app/views/plans/index.html.erb
<%# 略 %>

<%= form_with url: plans_path, method: :get, local: false do |f| %>
    <%= f.select :status, ["進行中","中止/完了","全て"] ,{class: "form-control"}%>
    <%= f.submit   "絞り込み" ,{class: "btn-primary"}%>
<% end %>

<%# 略 %>
```

`local: false` がポイントだ。これによってフォームの送信がAjaxで行われることになる。

# 2. コントローラー修正

 Ajax通信になってもコントローラーのいく先は同じである。今回はindexアクションに飛ばすようにしている。ただ飛ばすだけでなく、プルダウンの中の値を確認し、それによって引き出すデータを絞り込んでいる。

```ruby:app/controllers/plans_controller.rb
class PlansController < ApplicationController
# 色々略

  def index
# 色々略

      plans_nonorder = Plan.includes(:review_items).where(user_id: current_user.id).page(params[:page])

      if params[:status].present?
        if params[:status] == "進行中"
          filterd_plans = plans_nonorder.where(status:"進行中")
        elsif params[:status] == "中止/完了"
          filterd_plans = plans_nonorder.where(status:"中止").or(plans_nonorder.where(status:"完了"))
        else
          filterd_plans = plans_nonorder
        end
      else
        filterd_plans = plans_nonorder
      end
      @plans = filterd_plans.order(deadline: :desc)

# 略
  end

# 略
```

`params[:status]` にプルダウンの値が入ってくる。



# 3. jsファイル修正

 Ajax通信が行われると、コントローラーに飛んだ後は`index.js.erb`にゆく。

```js:app/views/plans/index.js.erb
var plans = document.querySelector("#plan_list");
plans.innerHTML = '<%= j render 'planlist' %>';
```

　これはビューファイルの`id = plan_list` で囲まれた箇所のみを書き換える処理である。 

# 4. 一覧画面に部分テンプレート追加 

　ここまでだけだとうまくいかないので、部分テンプレートをつくる。目標一覧画面を修正する。

```erb:app/views/plans/index.html.erb
<%# 略 %>

<%= form_with url: plans_path, method: :get, local: false do |f| %>
    <%= f.select :status, ["進行中","中止/完了","全て"] ,{class: "form-control"}%>
    <%= f.submit   "絞り込み" ,{class: "btn-primary"}%>
<% end %>

<div id="plan_list">
    <%= render partial: 'planlist' %>
</div>
<%# 略 %>
```

　部分テンプレートは頭に`_`をつけて作成する。

```erb:app/views/plans/_planlist.html.erb
<% @plans.each.with_index(1) do |plan, i| %>
    <%= plan.name %>
    <%= plan.status %>
<% end %>
```

　本当はデザインの関係でdivとかいっぱいあるけど、省略している。

# 5. ページネーションも追加する

　これだけだとページネーションの処理がうまくいかない。部分テンプレートのところを修正する。

```erb:app/views/plans/_planlist.html.erb
<% @plans.each.with_index(1) do |plan, i| %>
    <%= plan.name %>
    <%= plan.status %>
<% end %>
<% if @plans.empty? %>
<%# ページネーション非表示 %>
<% else %>
<nav aria-label="Page navigation example">
  <ul class="pagination">
    <%= paginate @plans, remote: true %>
  </ul>
</nav>
<% end %>
```

　この`remote: true`が重要。これによってページネーションもAjax通信で行われ、部分テンプレートの箇所のみが更新される。

# うごく

![ly.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104211/07ef5277-cdb6-5d8a-ff6d-c94aa64826a3.gif)


# おわり

　今月はずっとこれをやっていたのでうまくいってよかった。次はいよいよ振り返り機能を見直していくぞ。
脚注に Indented code block をネストするにはどうするの

# 脚注に Indented code block をネストするにはどうするの

脚注に Indented code block をネストするには、半角スペースによるインデントはいくつ必要でしょうか。

## ■ 背景

リストに Indented code block をネストするには、少しややこしい計算をすることで必要なインデント量を求めることが出来ます。

リストにネストされた Indented code block には、
- リストマーカー（`-` や `1.` など）の幅（文字数）
- リスト項目インデント量（リストマーカーとリスト項目の間の半角スペースの量）
- Indented code block のための半角スペース 4 つ

の合計のインデント量が必要です。（詳細は [ブロックのネスト化 \- CommonMark リストの仕様を理解したい - Qiita][qiita-234d67c193a71b72d035]）

[qiita-234d67c193a71b72d035]: https://qiita.com/Yarakashi_Kikohshi/items/234d67c193a71b72d035#-%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%81%AE%E3%83%8D%E3%82%B9%E3%83%88%E5%8C%96

では、脚注に Indented code block をネストするには半角スペースいくつ分でインデントすれば良いでしょうか。ややこしい計算が必要でしょうか。

## ■ 検証と結果

次のような脚注を作成し、8 つの半角スペースによるインデントを使って Indented code block を表現しました。これは、The four-space rule に従っていることを想定しました。

```markdown
ここに脚注 [^footnote] を作ります。

[^footnote]: Indented code block には
いくつのインデントが必要？

        Indented code block
```

ここに脚注 [^footnote] を作ります。

[^footnote]: Indented code block には
いくつのインデントが必要？

        Indented code block

:::note info
是非、脚注先に移動してみてください。
:::

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

やっぱりｯｯｯｯ！！！！The four-space rule は正義だ！！！！

:::note info
脚注内の Indented code block は 8 つの半角スペースでインデントする必要がある。
:::

ちなみに、脚注に他のブロック要素をネストしたい場合には、The four-space rule に従って、半角スペース 4 つでインデントする必要があります。脚注は決して 1 行であることを要請せず、lazy 性があるようです。

# まとめ

The four-space rule は正義だ！！！！

Markdown における脚注は GFM でさえ仕様を定義していないものの、The four-space rule に従っているようです。The four-space rule で書いていれば良しなに理解されるし、運気も上がりそうですね (?????)
Git push後のコミットメッセージを変更する方法

# はじめに
これまで色々なプロジェクトに参加してきましたが、コミットメッセージが指定されている案件が意外とあります。
しかし、開発しているとコミットメッセージに意識が回らずフォーマットを無視してcommitしてしまいそのままpushしてしまうということが多々ありました。
最悪ブランチを作り直したりすれば良いのですが、それは面倒なので今回はpush後のコミットメッセージを変更する方法を紹介します。

# push後のコミットメッセージを変更する方法　
### git logで現状を確認
```
$ git log --oneline
61776cf (HEAD -> master, origin/master) readme修正2
33c682d readmeを変更1
33eaec9 initialize repozitory
```
今回は1つ前の`readme修正2`と2つ前の`readmeを変更1`のコミットメッセージを修正していきます。

### 該当コミットを指定
```
# HEAD~3で遡るコミット数を指定
$ git rebase -i HEAD~3
# 上記でエラーが出る場合は
$ git rebase -i --root
```
以下のような画面になるはずです。
```
pick 33eaec9 initialize repozitory
pick 33c682d readmeを変更1
pick 61776cf readme修正2

# Rebase 61776cf onto 0fc52ae (3 commands)
# 以下省略
```

修正したいコミットの`pick`の部分を`e`or`edit`に変更します
```
pick 33eaec9 initialize repozitory
e 33c682d readmeを変更1
e 61776cf readme修正2

# Rebase 61776cf onto 0fc52ae (3 commands)
# 以下省略
```
この状態で保存`:wq`

### amendでコミットを修正
```
$ git commit --amend
```
以下のような画面になるのでメッセージを修正します
```
readmeを変更1修正

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Jan 22 04:27:17 2023 +0900
#
```
修正したら`:wq`
以下のようなメッセージが出ればOK
```
[detached HEAD fbd1503] readmeを変更1修正
 Date: Sun Jan 22 04:27:17 2023 +0900
 1 file changed, 1 insertion(+), 24 deletions(-)
```
次のコマンドで、1つ目の修正を終了
```
$ git rebase --continue
```
今回は複数のコミットを修正しているのでもう一度
```
$ git commit --amend
```
これによって2つ目のコミットの修正画面になるので同様に修正して保存`:wq`
次のコマンドで、2つ目の修正を終了
```
$ git rebase --continue
Successfully rebased and updated refs/heads/master.
```
上記のようなメッセージが出れば変更完了！

### pushする
```
$ git push --force-with-lease origin master
```
普通にpushすると通らないので`--force-with-lease`オプションをつけます。
普通の`-f`オプションは使わないようにします（*説明は省略）

### 確認
最後にコミットメッセージが変更されたか確認しましょう
```
$ git log --oneline
6b8f1c2 (HEAD -> master, origin/master) readme修正2修正
310e3cf readmeを変更1修正
33eaec9 initialize repozitory
```
これで完了です🎉

# 最後に
この方法は最終的に強制的なpushしているのでチーム開発などをしている場合には利用には十分に注意してください。
mergeされていない、自分の作業ブランチなどで行うのは大丈夫です！
何か間違いなどありましたらご指摘ください！
Elixir dbgをIExで使うときにpryを無効化する方法

## dbgとは

Elixir言語でデバッグするときに使用される関数です。

まだ`dbg`を使ったことがない方はQiitaにいくつか日本語で説明された記事がありますのでそちらをご覧ください。

https://qiita.com/search?q=elixir+dbg


もちろんElixir言語の公式ドキュメントにも載ってます。

https://hexdocs.pm/elixir/Kernel.html#dbg/2

https://elixir-lang.org/getting-started/debugging.html#dbg


## dbgをIExで使うときの問題点

こういったコメントをElixirコミュニティで見かけます。

https://twitter.com/dnautics/status/1613601060236722179

実際にIExを開き`dbg`挙動を確認してみます。

```bash:OSのシェルからIExを起動
$ iex
Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]

Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex> 
```

```elixir:初期設定のIEx
iex> "hello" |> String.upcase |> dbg()
Break reached: iex:3
pry>
```

初期設定の状態では、IEx起動中に`dbg`を使用すると`dbg`の呼び出しがある場所でコード実行が停止し、pryセッションが起動します。

落ち着いて`next`か`continue`を打てばpryセッションを終了させることができます。

```elixir:pry起動中のIExでpryセッションを終了させる
pry> next
"hello" |> String.upcase() #=> "HELLO"

[:ok]

Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex>
```

pryはデバックをする際に便利な機能ではあるのですが、ただ単に値を確認したいだけの場合には余計な機能でもあります。

## dbgをIExで使うときにpryを無効化する方法

一言で言うとこうなります。

* `:elixir`アプリケーションの設定の`:dbg_callback`キーの値を`{Macro, :dbg, []}`にする

https://hexdocs.pm/elixir/Kernel.html#dbg/2-configuring-the-debug-function

### IEx起動後に設定変更

必要に応じてIExから設定変更します。

```elixir:IExから設定変更してpryを無効化
iex> Application.put_env(:elixir, :dbg_callback, {Macro, :dbg, []})
:ok

iex> "hello" |> String.upcase |> dbg()                      [iex:2: (file)]
"hello" #=> "hello"
|> String.upcase() #=> "HELLO"

"HELLO"
```

### `~/.iex.exs`ファイルから設定変更

IExで使うときにいつもpryを無効化したい場合は、ご自身の`~/.iex.exs`ファイルでpryの設定変更ができます。

```elixir:~/.iex.exs
Application.put_env(:elixir, :dbg_callback, {Macro, :dbg, []})
```

`~/.iex.exs`ファイルを使ってことがない方はQiitaにいくつか日本語で説明された記事がありますのでそちらをご覧ください。

https://qiita.com/search?q=iex.exs

もちろんElixir言語の公式ドキュメントにも載ってます。

https://hexdocs.pm/iex/IEx.html#module-the-iex-exs-file

### IEx起動時に`--no-pry`オプションを渡す技

IExを起動するときに、`--no-pry`オプションを渡す技もあります。この手法が一番シンプルと言えるかもしれません。

@zacky1972 さんからお便りをいただき知りました。ありがとうございます。

```bash:OSのシェルから--no-pryオプションをつけてIExを起動
$ iex --no-pry
Erlang/OTP 25 [erts-13.1.3] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]

Interactive Elixir (1.14.3) - press Ctrl+C to exit (type h() ENTER for help)
iex>
```

```elixir:pryが無効化されたIEx
iex> "hello" |> String.upcase |> dbg()
[iex:1: (file)]
"hello" #=> "hello"
|> String.upcase() #=> "HELLO"

"HELLO"
```
コンストラクタインジェクションを紐解く

# コンストラクタインジェクションとは

**依存先のモジュールを自ら生成せずに、コンストラクタの引数としてもらうようにすること**です。

はい。イメージつきにくいですよね...。

# コンストラクタインジェクションしていない例

Carクラス内で、Engineクラスのインスタンスを作成しています。
```php
class Car
{
    private $engine;

    public function __construct()
    {
        $this->engine = new Engine();
    }

    public function move()
    {
        $energy = $this->engine->run();
    }
}
```

# コンストラクタインジェクションしている例

Carクラス内で、Engineクラスのインスタンスは作成していません。
引数としてEngineクラスのインスタンスを受け取っています。

```php
class Car
{
    private $engine;

    public function __construct(Engine $engine)
    {
        $this->engine = $engine;
    }

    public function move()
    {
        $energy = $this->engine->run();
    }
}
```


# メリット
1, 疎結合になる
依存モジュール同士が疎結合になることで依存先の具体的な実装の変更に依存元のコードは影響を受けなくなります。
先ほどの例で考えてみます。普通のエンジンではなく加速がすごいスーパーエンジンを使いたいとします。その場合carクラスのインスタンス作成時に引数でスーパーエンジンを渡してあげればいいだけです。Carクラスの変更は無しで済みます。

```php
    public function hoge()
    {
	superEngine = new superEngine();
        car = new Car(superEngine);
    }
```

2, テスト容易性が向上する
エンジンをモック化が必要であれば、モックしたものをCarクラスに引数として渡してあげればいいだけです。
```php
    public function testMove()
    {
	engineMock = new engineMock();
        car = new Car(engineMock);
	Car.move();
    }
```

Carクラスの引数がエンジンだけでなく複数の引数を取るとします。
ある引数はモックに、他の引数はモックではなく本物を渡すみたいなこともできます。
そして、何より見やすいし理解しやすいと思います。
```php
    public function testMove()
    {
	engineMock = new engineMock();
	wheel = new wheel();
        car = new Car(engineMock, wheel);
	Car.move();
    }
```

# コンストラクタインジェクションをしとけば完璧なのか？

完璧ではないと思います。
例えば、コンストラクタの引数が増えたら、毎回インスタンスを作成するたびに、引数の管理が大変ですよね。
```php
    public function hoge()
    {
	classA = new classA();
	classB = new classB();
	classC = new classC();
	classD = new classD();
	...
        car = new Car(classA, classB, classC, classD...);
	
	....
    }
```
そこで登場するのが、**DIコンテナ（サービスコンテナ）** です。
ここではDIコンテナの説明をすると話が拡がってしまうので、一旦ここまでにします。

# まとめ

コンストラクタインジェクションによって、疎結合とテスト容易性が向上できます。
疎結合で保守性の高いコードにしていきましょう。
2023/1/22主にITとかセキュリティの記事

大学院入試問題や個人情報が学内クラウドで閲覧可能に - 琉球大学
https://www.security-next.com/143009

学内で利用するクラウドサービスにおける個人情報等の不適切な取扱いについて（お詫び）(1/20)
https://www.u-ryukyu.ac.jp/news/40936/

琉球大学　入試問題や学生の成績などが学内誰でも閲覧できる状態だった(1/20)
https://news.yahoo.co.jp/articles/2e394217102364e72240ad23c3761e8f6ea0c95a?source=rss

非常災害時用端末を用いて他社顧客情報を閲覧 - 九州電力
https://www.security-next.com/143015

関西電力、情報漏洩で個人情報保護委に報告(1/20)
https://www.nikkei.com/article/DGXZQOUF206OK0Q3A120C2000000/

新電力顧客情報の取扱いに係る調査結果の報告について
（個人情報保護委員会からの報告徴収への報告）(1/20)
https://www.kepco.co.jp/corporate/pr/2023/pdf/20230120_1j.pdf

TP-Link製の一部ルータに深刻な脆弱性 - アップデート未提供
https://www.security-next.com/143012

ならコープが個人情報漏えいの可能性で対応　サイバー攻撃によるシステム障害で(1/19)
https://www.nara-np.co.jp/news/20230119215401.html

不正アクセス、自分だけは大丈夫と思わないで 気をつけるポイント(1/20)
https://ascii.jp/elem/000/004/120/4120586/?rss

北関東マツダから約5万件の個人情報が流出か、委託先サーバーに不正アクセス(1/20)
https://xtech.nikkei.com/atcl/nxt/news/18/14486/

コストパフォーマンス重視のサイバー犯罪が目立った2022年--セキュアワークスが報告(1/20)
https://japan.zdnet.com/article/35198866/

企業の情報漏えい、平均被害額は約3億2,850万円！【トレンドマイクロ調べ】(1/20)
https://webtan.impress.co.jp/n/2023/01/20/44129

米国の医療機関へのランサムウェア攻撃の現状(1/20)
https://medical.nikkeibp.co.jp/leaf/mem/pub/hotnews/jama/202301/578109.html

サイバー攻撃身代金が4割減、支払い拒否で　民間調査(1/20)
https://www.nikkei.com/article/DGXZQOUC19DBO0Z10C23A1000000/

Trellix、2023年の脅威予測を発表　〜2023年にハクティビズムと地政学を背景とするサイバー攻撃の増大を予測(1/20)
https://securityinsight.jp/news/13-inbrief/5295-230120-1

アダストリア、自社ECが不正アクセスを受けて休止中(1/20)
https://www.tsuhanshimbun.com/products/article_detail.php?product_id=6605&_ssd=1

個人情報漏えい・紛失事故 2年連続最多を更新 件数は165件、流出・紛失情報は592万人分 ～ 2022年「上場企業の個人情報漏えい・紛失事故」調査 ～(1/19)
https://nordot.app/988627752284667904?c=220450040231249399

新型コロナやロシア・ウクライナ戦争の影響を考慮した国内IT市場予測- IDC(1/20)
https://news.mynavi.jp/techplus/article/20230120-2568803/

ウィズセキュア、サイバー攻撃での「ChatGPT」悪用について警鐘(1/20)
https://japan.zdnet.com/article/35198849/

成長を続ける脅威インテリジェンス市場、製造・金融の大企業を中心に需要が高まる─ITR(1/20)
https://it.impress.co.jp/articles/-/24333

Wi-Fi機器をスリープさせずバッテリー残量を急速に低下させる攻撃(1/20)
https://www.zaikei.co.jp/article/20230120/706401.html

カスペルスキー、攻撃活動「ローミングマンティス」に新たにルーターのDNS設定を改ざんする機能が実装されたことを発見(1/20)
https://www.nikkei.com/article/DGXZRSP647898_Q3A120C2000000/

Kaspersky、「Roaming Mantis」が使用するAndroid向けマルウェアに、Wi-FiルーターのDNS設定改ざん機能が新たに加えられたことを発見(1/20)
https://prtimes.jp/main/html/rd/p/000000336.000011471.html

Linux管理で人気のツール「CWP」の脆弱性、積極的な悪用確認(1/20)
https://news.mynavi.jp/techplus/article/20230120-2566427/

CircleCI、認証トークン窃取によるデータ流出事故の詳細を公開(1/20)
https://news.mynavi.jp/techplus/article/20230120-2567904/

暗号資産取引所ビットマート、カストディアンと提携──機関投資家向けに資産保護を強化(1/20)
https://www.coindeskjapan.com/171840/

白馬村、冬の写真をブロックチェーンに記録し特設Webサイトで公開。投稿者にはNFTを発行(1/20)
https://news.yahoo.co.jp/articles/7b68ff32934887a062165aa47598de65a5677711?source=rss

KFCやピザハットの親会社、ランサムウェア攻撃で数百店舗を一時休業(1/20)
https://japan.cnet.com/article/35198864/

世界有数のモバイルキャリア「T-Mobile」から約3700万件の顧客データが盗まれる(1/20)
https://gigazine.net/news/20230120-t-mobile-stole/
Object.keysのreturn valueに型をつける関数

## はじめに
Object.keys()の返り値の型がstring[]になるのを避ける策として型アサーションがありますが、
ソースコードに型アサーションをあまり増やしたくない。。その解決策メモ

## 問題点
string[]が型推論される
```typescript
const user = {
  name: "abc",
  age: 10
}

const keys = Object.keys(user) // string[]
const assertKeys = Object.keys(user) as (keyof typeof user)[] // ("name" | "age")[]
```

## 解決策
Object.keysをラップした関数を作成する
内部で[Type Assertions](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions)を使用する
```typescript
const myObjectKeys = <T extends Record<string, unknown>>(obj: T)=> Object.keys(obj) as (keyof T)[]

const keys = myObjectKeys(user) // ("name" | "age")[]
```

## 参考文献
> [TypeScript Documentation](https://www.typescriptlang.org/docs/)
WSL2 でUbuntuを立ち上げたら、「0x80370102」と「0x800701bc」というエラーが出た

故あって、開発環境をMacからWindowsへシフトして、早速WSL2からUbuntuを立ち上げようとしたところ、表題にある2つのエラーが出ちゃいました。

こういうところWindowsってめんどくさい

今後、また同じエラーが出たら面倒なので、備忘録がてら対応履歴を残しておきます。

# 環境
Windows10 Pro
Ubuntu 20.04.5 LTS
「Linux用Windowsサブシステム（WSL）」と「仮想マシン プラットフォーム」は有効化済み
PowerShell上から下記コマンドで、WSL2を既定バージョンに設定済み
```
wsl --set-default-version 2
```

# 原因
なんてことはなく原因は下記の2つでした。
- CPUの仮想化機能が有効化になっていなかった
- 規定のLinux カーネル更新プログラム パッケージを更新していなかった

# まずは「0x80370102」エラー
Ubuntu 20.04.5 LTS をインストールして、立ち上げたところ下記のようなエラーが出ました。
```
Installing, this may take a few minutes...
WslRegisterDistribution failed with error: 0x80370102
Error: 0x80370102 ??????????????????????????????????????

Press any key to continue...
```
<b>「？」はひとつでいいだろ、びっくりするなあ。</b>
単にBIOS側でCPUの仮想化機能が有効化になっていなかっただけでした。
再起動後、BIOSを立ち上げて、「System Configuration」＞「Virtualization Technology」＞「Enabled」で仮想化機能を有効化。
これで無事にUbuntuを立ち上げられると思いきや……

# 今度は「0x800701bc」エラー
```
Installing, this may take a few minutes… WslRegisterDistribution failed with 
error: 0x800701bc Error: 0x800701bc WSL 2 ???????????? ??????????????????????? https://aka.ms/wsl2kernel ?????????
```
一難去ってまた一難。<b>だから「?」を並べるな、怖いだろ。</b>
わかりやすいことに、エラーメッセージの中にURLがあります。そこを見ろということですね。

https://learn.microsoft.com/ja-jp/windows/wsl/install-manual#step-4---download-the-linux-kernel-update-package

というわけでアクセスした先で、<b>「手順 4 - Linux カーネル更新プログラム パッケージをダウンロードする」</b>とありますので、それに従います。

以上の手順で解決し、無事にUbuntuを起動することができました。

# 反省
過去にWSL1の導入をやったことがありましたが、その時と同じようなノリであまり手順を再確認しなかったことでハマりました。
それに加えて何はともあれ、まずは公式ドキュメントを読むべきでしたね。