OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Peacock Management Consoleを設定して、複数AWSアカウントのコンソール迷子を防止する

# 複数AWSアカウントの切り替えは面倒且つ間違いの元


業務でAWSを使用する場合、用途に合わせて複数のAWSアカウントを使い、環境を切り替えることがあります。

・**開発環境（dev）**
・**検証環境（stg）**
・**本番環境（prd）**

どの環境にログインしているかは、上記の様な命名規則で定められた各環境のリソース名をチェックすることで確認可能ですが、頻繁に異なる環境にログインする場合、面倒な上にログイン環境を間違えて意図しないリソース変更をしてしまう恐れがあります。
![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638561/3a704c2e-ca4c-16c6-2abb-bf3823257e83.jpeg)
AWSコンソールにログインすると、アカウントIDに関係なく画面のヘッダーとフッターはデフォルトで色が決まっています。このヘッダー、フッターを任意の色に変更し、どの環境にログインしているか一目で理解できる方法があります。
# 「AWS Peacock Management Console」の設定
Chrome拡張機能に **「AWS Peacock Management Console」** という拡張機能があるので、アカウントID毎にヘッダー、フッターを表示する色を変更するという方法です。
- **[AWS Peacock Management Console - Chrome ウェブストア](https://chrome.google.com/webstore/detail/aws-peacock-management-co/bknjjajglapfhbdcfgmhgkgfomkkaidj
)**
![WS000002.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638561/dead9a62-fce8-f849-66f8-a0457a926999.jpeg)

Chrome拡張機能を追加するとWindows画面右上にアイコンが追加されるので、オプション欄を押下します。
※ピン止めして表示させています
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638561/0f2b8049-d54f-7c94-3b94-7864f983c447.png)
**アイコン**をクリックして次に**オプション**を押下すると、下図のJSONのConfiguration（構成）画面が開くので、必要なAWSアカウントIDの数だけ設定を追加し、任意のカラーコードを設定します。

**[カラーコードの一覧表(色を調べる/色を作る)](https://itsakura.com/html-color-codes)**

色設定に関しては、画面下部に**Color Palette**があって、設定する色を決められるのですが、
色の度合いを決めるのが面倒だったので、上記のカラーコードの一覧表(色を調べる/色を作る
で使用する色を決めました。
![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638561/af2f83fc-ba20-8238-96b9-05a4b6933b65.jpeg)
赤枠で囲った個所を変更して画面色を変更したいAWSアカウントIDと任意の色を設定します。
dev、stg、prdの3環境がある想定で記載していますが、3つ以上の環境があっても必要な数だけコピペして設定する環境数は増やせます。

3環境で済む場合は交差点の信号機の赤黄青に見立てて色を設定する方もいらっしゃるようです。



編集を終えたら画面下部にある **「SAVE」** を押して変更を反映させます。
あとは実際にAWSコンソール画面にログインして色が反映されているか確認します。
![WS000005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638561/922f3e9c-e1ee-6aad-8724-6b61b7234ea7.jpeg)
AWSのコンソールにログインするとヘッダーとフッターの色が設定した色に変更されています。

このように自分に分かりやすい色をアカウントID毎、環境ごとに設定して何色がどの環境か一目で分かるようにすれば、逐一ログインしてのリソース確認、意図せぬリソース変更を防止できる一因になるかと思います。

# 使用したテンプレート
参考までに使用したテンプレートを置いておきます。

```
[
  /**
   * JSON with comment format
   *
   * When multiple rules match, the first matching rule will be applied.
   *
   */
  // dev
  {
    "env": {
      "account": "12桁のアカウントID"
    },
    "style": {
      "navigationBackgroundColor": "#ADFF2F",
      "accountMenuButtonBackgroundColor": "#000080"
    }
  },
  // stg
  {
    "env": {
      "account": "12桁のアカウントID"
    },
    "style": {
      "navigationBackgroundColor": "#FFFF00",
      "accountMenuButtonBackgroundColor": "#000080"
    }
  },
  // prd
  {
    "env": {
      "account": "12桁のアカウントID"
    },
    "style": {
      "navigationBackgroundColor": "#00FFFF",
      "accountMenuButtonBackgroundColor": "#945bc4"
    }
  },
]
```
githubに草が生えない！〜sourceTree編〜

# 草が生えない
sourceTreeからgithubへコミットしてもcontributionが反映されない。

## sourceTree側でメールアドレスを設定しよう
どうやら、souceTreeのコミット時に付与されるメールアドレス情報とgithubのメールアドレス情報を照合している（？）ようだ。

![スクリーンショット 2023-05-25 23.33.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3452782/11ad829a-a50b-91a0-d037-c4ea88eafce8.png)
↓
↓
↓
![スクリーンショット 2023-05-25 23.37.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3452782/88711dec-d6ae-2fd4-4e37-2eeeb6502fac.png)
ここにメールアドレスを設定すると無事反映された！


## 終
少しでも毎日生やしたい。
dockerの基本コマンド

# Dockerのインストール
Docker CLIをインストールする。

https://dev.classmethod.jp/articles/docker-cli-without-dockerdesktop-on-windows/

https://eng-blog.iij.ad.jp/archives/14205
# Dockerコマンド
一連の流れで記載する。

## 1.Dockerデーモン起動
```
sudo service docker start
```
なお、停止は以下のコマンド。
```
sudo service docker stop
```

## 2-1.Dockerfileをビルドしてimageを作成 
Dockerfileがあるディレクトリで以下を実行。
```
docker build -t <ユーザ名>/<名前>:<タグ名> .
```

## 2-2.Dockerhubからimageをpull
```
docker pull <ユーザ名>/<名前>:<タグ名>
```

## 3.imageの一覧を表示
imageIDなどを確認するときに使う。
```
docker image ls
```

## 4.imageからcontainerを起動
```
docker run -it <imageID>
```

## 5.containerから抜ける
```
ctrl + p q
```

## 6.containerの一覧を表示する
```
docker container ls
```
また稼働中のcontainerのみの表示は以下。
```
docker ps
```

## 7.commitする
```
docker commit <container名/ID> <ユーザ名>/<名前>:<タグ名>
```
またここのタグ名は、ローカル上で決めてよい。（ローカル上でのバージョンなど）
タグ付け(下の場合はlatestタグ)は以下のコマンド。
```
docker tag <imageID> <ユーザ名>/<名前>:latest
```

## 補足：image、containerを削除する
```
docker rmi -f <imageID>
```
使用していないimage/containerをまとめて削除する。
```
docker image prune
```
```
docker container prune
```
【Rails】ホスト名をホワイトリストに登録する方法

## はじめに

特に設定をしていない場合には、任意のホスト名を指定してアクセスしようとした際に次のようなエラーが発生します。

```
Blocked host: sample-host.com
To allow requests to sample-host.com, add the following to your environment configuration:
    config.hosts << "sample-host.com"

```

エラー文に記載のとおりホスト名をホワイトリストに追加する必要があります。

## ホワイトリストに追加する方法

次のように`config/environments/development.rb`に追記しホスト名をホワイトリストに追加します。

```rb:development.rb

Rails.application.configure do

  config.hosts << "sample-host.com"

end

```
PrettierのVSCode拡張機能でTypeError: Cannot read properties of undefined (reading 'uid')

## tl;dr :zap:

`settings.json` に次の一行を追加する

```json
  "prettier.prettierPath": "./node_modules/prettier"
```

## 環境 :cooking:

- `Visual Studio Code - Insiders` : 1.79.0-insider (user setup)
- `Prettier - Code formatter` : v9.13.0
- `WSL` Ubuntu 22.04
- `asdf` v0.11.3
  - `nodejs` 20.2.0

## 何が起きたのか :thinking:

上記環境で SvelteKit の開発環境構築を行っていたのだが、Prettierの拡張機能にてエラー。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2566826/fe45a90c-26e4-7eed-b95e-4883d6615314.png)

ログを確認すると

```log
["ERROR" - 9:21:35 PM] Cannot read properties of undefined (reading 'uid')
TypeError: Cannot read properties of undefined (reading 'uid')
    at Object.statSync (/home/tellmin/.vscode-server-insiders/bin/f6be5461f8bc69013a605f5baea834651c6589fb/node_modules/graceful-fs/polyfills.js:313:17)
    at p (/home/tellmin/.vscode-server-insiders/extensions/esbenp.prettier-vscode-9.13.0/dist/extension.js:1:35221)
    at L (/home/tellmin/.vscode-server-insiders/extensions/esbenp.prettier-vscode-9.13.0/dist/extension.js:1:37052)
    at /home/tellmin/.vscode-server-insiders/extensions/esbenp.prettier-vscode-9.13.0/dist/extension.js:1:36677
    at Function.e.exports [as sync] (/home/tellmin/.vscode-server-insiders/extensions/esbenp.prettier-vscode-9.13.0/dist/extension.js:1:36723)
    at t.ModuleResolver.findPkg (/home/tellmin/.vscode-server-insiders/extensions/esbenp.prettier-vscode-9.13.0/dist/extension.js:1:7297)
    at t.ModuleResolver.getPrettierInstance (/home/tellmin/.vscode-server-insiders/extensions/esbenp.prettier-vscode-9.13.0/dist/extension.js:1:3251)
    at t.default.handleActiveTextEditorChanged (/home/tellmin/.vscode-server-insiders/extensions/esbenp.prettier-vscode-9.13.0/dist/extension.js:1:9781)
```

ということで、'uid'というプロパティを読み込もうとしたときに、その親オブジェクトがundefinedであることが原因のようです。

調べてみると、prettierのリポジトリに次のようなissueが立てられていました。

- [Broken in vs code insiders - #3000](https://github.com/prettier/prettier-vscode/issues/3000)

そのなかで、次のようなコメントがありました。


> **Dnouv:**
> Well, not sure if it is the correct way to resolve but,
> 
> After changing the prettier path settings to the ones below, it does the trick.
> "prettier.prettierPath": "./node_modules/prettier"
> 
> Thank you!

https://github.com/prettier/prettier-vscode/issues/3000#issuecomment-1547290873

ということで、`settings.json`に次のような設定を追加することで、エラーが解消されました。

```json
  "prettier.prettierPath": "./node_modules/prettier"
```

（Dnouvさんに:rocket:飛ばしておきました。参考になった方は是非！）

## まとめ :memo:

悩んでいた時間に対して、あっさりと解決してしまいました。
PrettierプラグインのModuleResolverのエラーのようですが、プロジェクトによっては正しく機能することもあり、詳しい原因まではわからなかったのが心残りです。

さらに情報が分かり次第、追記していきます。
どなたかのお役に立てれば幸いです。
Qiita投稿の執筆環境を整える


# はじめに

VS CodeでQiitaへ記事を投稿する環境を整える。

# 環境

| 項目 | バージョン |
| ---- | ---- |
| OS | Windows11 |
| VS Code | 1.78.2 |

# VS Codeの拡張機能のインストール

* Prettier
* markdownlint
* Markdown Preview Enhanced
* テキスト校正くん

# Chocolatey, Go, Qiisyncのインストール

## Chocolateyのインストール

下記のコマンドをコマンドプロンプト（管理者）で実行する。

```cmd
> @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;> @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFIL%ALLUSERSPROFILE%\chocolatey\bin"
```

## Go言語のインストール

下記のコマンドをコマンドプロンプト（管理者）で実行する。

```cmd
> choco install golang
```

## Qiisyncのインストール

下記のコマンドをコマンドプロンプト（管理者）で実行する。

```cmd
> go install github.com/d-tsuji/qiisync/cmd/qiisync@latest
```

[こちら](https://qiita.com/settings/applications)からAPIのトークンを取得する。

C:\Users\【User名】\\.config\qiisync\configに下記を記載して保存する。

```txt
[qiita]
api_token = "1234567890abcdefghijklmnopqrstuvwxyz1234"

[local]
base_dir = "./testdata/output"
filename_mode = "title"
```

# Qiitaに記事を投稿する

下記のコマンドを実行して、Qiitaに記事を投稿する。

```cmd
> qiisync post XXXX.md
```

# 参考リンク

[Qiita投稿用の執筆環境を整える](https://qiita.com/fniplot/items/bbd8eec2164c5234f20d)
[Markdown Preview Enhancedを使いこなす](https://qiita.com/take_me/items/5ff5304b58d9feec21df)
[WindowsにGo言語をインストールする方法まとめ](https://qiita.com/yoskeoka/items/0dcc62a07bf5eb48dc4b)
[GitHub: Qiisync](https://github.com/d-tsuji/qiisync#%E4%BD%BF%E3%81%84%E6%96%B9)
[AWS Q&A 365][SNS]AWSのよくある問題の毎日5選 #66

# 1. メッセージデータ保護とは何ですか？
回答：メッセージデータ保護とは、Amazon SNSを通じて送信されるメッセージ内のデータの機密性、完全性、可用性を確保するための措置を指します。これには、暗号化、アクセス制御、およびデータの不正なアクセスまたは変更を防ぐための監視が含まれます。

# 2. メッセージデータ保護の重要性は何ですか？
回答：メッセージデータ保護の重要性は、メッセージに含まれる可能性のある個人データや金融データなどの機密情報を保護するのに役立つからです。また、データ保護規制と規格の遵守を確保するのにも役立ちます。

# 3. データ保護ポリシーとは何ですか？
回答：データ保護ポリシーは、組織内でデータがどのように扱われ、格納され、送信されるかを規定する一連のルールと手順です。これらは、データ処理に関与する個人やチームの役割と責任を定義し、データを保護するために必要な技術的および管理的な制御を指定します。

# 4. Amazon SNSのためのデータ保護ポリシーをどのように作成しますか？
回答：Amazon SNSのためのデータ保護ポリシーを作成するには、まず保護が必要なデータタイプ、例えば個人を特定可能な情報（PII）や金融データを特定する必要があります。次に、このデータの取り扱いと送信のルールと手順を定義し、暗号化やアクセス制御のような技術的な制御を確立することができます。

# 5. 管理データ識別子とは何ですか？
答え：管理データ識別子は、個人情報や金融データなどの機密データタイプを識別するための事前定義されたパターンや形式です。これらは、Amazon SNSを通じて送信されるメッセージ内の機密データを自動的に検出し、データ保護ポリシーまたはフィルタリングルールを適用するために使用できます。
Power BI: クリックすると、データ連携されずに、テーブルが表示されるのは、データポイントテーブルの設定だった

# 状況
Power BIでヴィジュアルをクリックすると、いつもなら選択したデータの強調表示がされるところで、何故かテーブルが表示される、という現象が発生した。

で、調べたところ、いつの間にかデータポイントテーブルの設定が効いていただけだった。

データによって勝手に設定がかわるようだが、何故なのかはさっぱり

データポイントテーブルの設定、の挙動は以下
![データポイントテーブル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e0ade8ff-3986-9e65-0d3f-ba16c0438d83.gif)

[データポイントテーブル](https://learn.microsoft.com/ja-jp/power-bi/create-reports/end-user-show-data?tabs=powerbi-desktop#use-data-point-table-in-power-bi-desktop) とは

> [視覚エフェクト テーブル] または **[データ ポイント テーブル]** を選択すると、Power BI では、そのデータの視覚化およびテキスト表現の両方が表示されます。 "横表示" では、ビジュアルがキャンバスの上部に表示され、データが下部に表示されます。
[AWS Q&A 365][SNS]Daily Five Common Questions #66

# 1. What is message data protection? 
Answer: Message data protection refers to the measures taken to ensure the confidentiality, integrity, and availability of the data contained in messages sent through Amazon SNS. It includes encryption, access control, and monitoring to prevent unauthorized access or modification of the data. 

# 2. Why is message data protection important? 
Answer: Message data protection is important because it helps to safeguard sensitive information that may be contained in messages, such as personal or financial data. It also helps to ensure compliance with data protection regulations and standards. 

# 3. What are data protection policies? 
Answer: Data protection policies are a set of rules and procedures that govern how data is handled, stored, and transmitted within an organization. They define the roles and responsibilities of individuals and teams involved in data handling, and specify the technical and administrative controls that must be in place to protect data. 

# 4. How do I create a data protection policy for Amazon SNS? 
Answer: To create a data protection policy for Amazon SNS, you must first identify the data types that need to be protected, such as personally identifiable information (PII) or financial data. You can then define the rules and procedures for handling and transmitting this data, as well as the technical controls that must be in place, such as encryption and access control. 

# 5. What are managed data identifiers? 
Answer: Managed data identifiers are predefined patterns or formats that identify sensitive data types, such as PII or financial data. They can be used to automatically detect and protect sensitive data within messages sent through Amazon SNS, by applying data protection policies or filtering rules.
geopandasでみえない交差点を調べる

# みえない交差点

https://www.asahi.com/special/jiko-kosaten/

https://github.com/yamazakikeisuke/python_for_journalism-/blob/main/Python_for_journalism.ipynb

# データ

## オープンデータ

https://www.npa.go.jp/publications/statistics/koutsuu/opendata/index_opendata.html

## 都道府県コード

https://www.npa.go.jp/publications/statistics/koutsuu/opendata/2021/codebook_2021.pdf

## 日本測地系2011（JGD2011）

https://lemulus.me/column/epsg-list-gis#i

# インストール
```
pip install pandas
pip install geopandas
pip install folium
```
# プログラム
```python

# 都道府県コード（神奈川県）
pref = 45

# 日本測地系2011（神奈川県）
epsg = 6677

# プログラム

import pandas as pd
import geopandas as gpd

from tqdm.notebook import tqdm

pd.options.plotting.backend = "plotly"
pd.set_option("display.max_columns", None)

df0 = pd.read_csv("https://www.npa.go.jp/publications/statistics/koutsuu/opendata/2021/honhyo_2021.csv", encoding="cp932")

# 緯度経度を度分秒から10進数表記に変換

def dms2deg(df_tmp, col):

    df = df_tmp.copy()
    
    df["d"], df["t"] = df[col].divmod(10000000)
    df["m"], df["s"] = df["t"].divmod(100000)

    result = df["d"] + (df["m"] / 60.0) + (df["s"] / 1000.0 / 3600.0 )

    return result

df0["lat"] = dms2deg(df0, "地点　緯度（北緯）")
df0["lon"] = dms2deg(df0, "地点　経度（東経）")

df0

df0.columns

df0["発生日時　　年"].value_counts()

# 2021年のみ
df1 = df0[df0["発生日時　　年"] == 2021].copy()

df1.shape

# 月ごとの事故数を確認
df1["発生日時　　月"].value_counts()

# 曜日別の事故数を確認
df1["曜日(発生年月日)"].value_counts()

# 昼夜別の事故数を確認
df1["昼夜"].value_counts()

# 道路の形ごとの事故数を確認
df1["道路線形"].value_counts()

# 交差点の大きさごとの事故数を確認
df1["車道幅員"].value_counts()

df2 = df1[df1["車道幅員"].isin([11, 14, 15]) & (df1["都道府県コード"] == pref)]
df2

geo_df = gpd.GeoDataFrame(df2, geometry = gpd.points_from_xy(df2.lon, df2.lat), crs=6668)
geo_df = geo_df.to_crs(epsg)

df3 = geo_df.copy()

# 半径10メートル
df3["buffer"] = df3.buffer(10)

# 10mの範囲
dft = df3["buffer"].apply(lambda x: df3.geometry.within(x))

dft.sum().value_counts().sort_index()

# さらに10mの範囲×2回
dfp = dft.apply(lambda x: dft.loc[dft.loc[x].any()].any(), axis=1)

dfp.sum().value_counts().sort_index()

# 件数
df3["len"] = dfp.sum()

# indexのタプル
df3["idx"] = dfp.apply(lambda x: tuple(dfp.loc[x].index.to_list()))

df3

df3["len"].value_counts()

# 5より多い事故の場所を危険交差点

df4 = df3[df3["len"] > 5].copy()

df4

se = df4.groupby("idx").apply(len).rank(ascending=False, method="first").astype(int).apply(lambda x: f"intersection_{x}")
se.name = "intersection_name"

df5 = pd.merge(df4, se, on="idx")

df5
```

# 地図表示
```python
import folium

m = folium.Map(
    location=[df5.lat.mean(), df5.lon.mean()],
    zoom_start=12,
    tiles="https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png",
    attr='&copy; <a href="https://maps.gsi.go.jp/development/ichiran.html">国土地理院</a>',
)

for i, r in df5.iterrows():

    folium.Marker(
        location=[r.lat, r.lon],
        icon=folium.Icon(color="red")
    ).add_to(m)

m
```
CSS グリッドレイアウト

# グリッドレイアウト(デザインとは)
グリッドレイアウトとはWebデザインにおいて使用される，画面やコンテンツ領域を均等な格子状(グリッド)に分割し，それぞれのセルに要素やコンテンツを配置する方法である．列数と行数をあらかじめ指定し，水平線と垂直線が交差してできたエリアに要素を配置していくことでレイアウトを組む．

メディアクエリと組み合わせることで，閲覧している端末に応じてコンテンツの配置を変えるようなレスポンシブデザインを実装することができる．

# グリッドコンテナとグリッドアイテム
![grid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/9c76b01e-f02d-7119-ed50-1c1786fcb6bd.png)
**・グリッドコンテナ**
複数のコンテンツをまとめる親要素

**・グリッドアイテム**
１つのコンテンツとなる小要素

グリッドコンテナとグリッドアイテムとなる要素に対してそれぞれ設定する必要がある．


# グリッドコンテナ
グリッドコンテナはコンテンツをまとめる親要素となり，コンテンツの配置方法を行数と列数で設定する．以下の記述例をもとに設定する内容を確認する．
**〜記述例〜**
```html
<div class="grid-container">
    <div>グリッドアイテム</div>
</div>
<style>
    .grid-container{
        display: grid;
        grid-template-columns: 1fr 2fr 1fr;
        grid-template-rows: 100px 100px 100px 100px;
        gap: 20px;
    }
</style>
```
**・display: grid;**
指定した要素をグリッドコンテナとして設定する．

**・grid-template-columns: ;**
グリッドコンテナの**列数**と**各グリッドのサイズ**を設定する．記述された個数が列数となる．

:::note info
``fr単位``とは
グリッドの大きさを自動的に調整してくれる単位で，"比率"で大きさを指定する．
記述例の``1fr 2fr 1fr``であれば，画面を4分割し，３つのコンテンツを1:2:1の比率で配置．
:::
**・grid-template-rows**
グリッドコンテナの**行数**や**各グリッドのサイズ**を設定する．列と同様に個数が行数となる．
**・gap**
グリッドアイテム同士の隙間を設定する．

# グリッドアイテム
グリッドアイテムはコンテンツを構成する子要素となり，グリッドコンテナのどこに配置されるかを具体的に設定する．
**〜記述例〜**
```html
<div class="grid-container">
    <div id="item1">グリッドアイテム１</div>
    <div id="item2">グリッドアイテム２</div>
    <div id="item3">グリッドアイテム２</div>
</div>
<style>
    .grid-container{...}

    #item1{
        grid-column: 1 / 2;
        grid-row: 1 / 2;
    }
    #item1{
        grid-column: 2 / 4;
        grid-row: 1 / 2;
    }
    #item1{
        grid-column: 4 / 5;
        grid-row: 1 / 2;
    }
        
</style>
```
**・領域の指定方法**
横方向も縦方向も領域の始めと終わりとなる辺を指定することで領域を指定する．グリッドコンテナを２行４列に指定した場合は，グリッドの辺は以下のようになる．
![grid2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/3eebc2cf-e106-ab2b-45ac-e54737f8601f.png)
``始めの線 / 終わりの線``のように指定することで，その２本で挟まれた領域を指定する．


**・grid-column**
グリッドアイテムの横方向の位置を指定する．

**・grid-row**
グリッドアイテムの縦方向の位置を指定する．


# グリッドコンテナの補足
**○repeat関数**
```css
.grid-container{
    display: grid;
    grid-template-columns: repeat(4, 100px);
    grid-template-rows: repeat(2, 100px);
}
```

grid-template-columnsやgrid-template-rowsを指定する際に，同じ値を繰り返す際には，repeat関数を使用して，効率的に指定することもできる．第1引数に繰り返す回数，第2引数に繰り返す値を指定する．

**○frの組み合わせ**
```css
.grid-container{
    display: grid;
    grid-template-columns: 500px 1fr 1fr;
    grid-template-rows: 100px 100px;
}
```
grid-template-columnsやgrid-template-rowsを指定する際に，具体的な値指定と``fr``を組み合わせることができる．その際は，横幅から具体的に指定した値を引き，残りの幅を比率で分割する．
上記の例では，ウィンドウサイズが1000pxとすると，１列目を500px，2，3列目を1:1の比率で分けるので，250pxずつとなる．
SSHで鍵を利用してログインできるようにしてみた

# 概要
SSHで秘密鍵と公開鍵を作って鍵で入れるようにしてみました。以下のページを参考にしました。

http://gomocool.net/gomokulog/?p=557

# ログイン元で秘密鍵と公開鍵を作って公開鍵を登録

ログイン元で秘密鍵と公開鍵を作成しました。
```
$ ssh-keygen -t rsa
```
id_rsa.pubをログイン先にコピーしました。

ログイン先でauthorized_keysに追加しました。公開鍵を登録しました。
```
$ cat id_rsa.pub >> authorized_keys
```

# ログイン実験

ログイン元から秘密鍵を指定してログインを試みました。
```
$ ssh -i .ssh/id_rsa <hostname>
```
無事ログインできることを確認しました。

# まとめ
何かの役に立てばと。
[忘備録]「TypeScript の基礎から始める AWS CDK 開発入門」が有用な件

表題のワークショップが初学者に優しすぎて泣けそうなのでまだ途中ですが感想を書きます。
https://catalog.workshops.aws/typescript-and-cdk-for-beginner/ja-JP

ワークショップ前を始める前の状態：
・CloudFormation便利そうだけど分からない...
・CDK始めたいけどどの言語が良い？
・TypeScriptってなんやねん

始めてみて：
・CloudFormationすげー
・TypeScriptってこんなものか～

#
基本的なワークショップの流れはTypeScriptの基礎→CDK実践になっていて、TypeScriptはめちゃめちゃ丁寧に変数や型、関数の定義方法まで教えてくれる。結局はJavaScriptの静的型付けバージョンなだけやった。

CDK実践ではVPCの作成→EC2の作成→WordPressのインストールまでが出来る。ユーザーデータの書き方まで分かればかなり出来る事が増えるんじゃないか。

何より良いなと思ったのが、ドキュメントの見方を説明してくれている事。機能が多すぎて全てを何も見ずに１から書くのは本当に難しいからドキュメントを見ながら自分で実装出来る能力を養ってくれるのはとてもためになる！

以上！最後まで進めたらまた書きます。
めっちゃわかりやすいDIとAOPの仕組み（リフレクションで理解しよう）

DIとAOPの仕組みを知るにはリフレクションを試すのがいいと思ってサンプルを準備してみました。

## 1. クラス名をもとにインスタンスを作れるか実験

まずはリフレクションを使うことでクラス情報をもとにインスタンスを制御できることを確認します。

```java
package test;

public class Student {
    public void print() {
        System.err.println("うごいた");
    }
}
```

```java
package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class TestRefect {
    public static void main(String[] args) throws Exception {
        // クラス名がわかるとクラス情報をつくれる
        Class clazz = Class.forName("test.Student");
        Constructor constructor = clazz.getConstructor(null);
        // クラス情報がわかるとインスタンスがつくれる
        Object taro = constructor.newInstance();
        Method method = clazz.getMethod("print", null);
        System.out.println("まえしょり");
        // インスタンスを制御できるとメソッドが呼び出せる
        method.invoke(taro, null);
        System.out.println("あとしょり");
    }
}
```

```console
まえしょり
うごいた
あとしょり
```

## 2. メソッドが呼ばれたことを検知できるか実験

次に、インスタンスを制御できると、メソッドが呼ばれたことを検知して前後処理が仕込めることを確認します。

```java
public interface SomeService {
    public void someMethod();
}
```

```java
class SomeServiceImpl implements SomeService {
    public void someMethod() {
        System.out.println("メソッドが呼ばれた: someMethod");
    }
}
```

```java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

class AOPHandler implements InvocationHandler {
    private final Object target;

    public AOPHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前処理: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("後処理: " + method.getName());
        return result;
    }
}
```

```java
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        // クラス情報やインスタンスを登録しておく
        SomeService target = new SomeServiceImpl();
        SomeService proxy = (SomeService) Proxy.newProxyInstance(
            SomeService.class.getClassLoader(),
            new Class[]{SomeService.class},
            new AOPHandler(target)
        );

        // メソッドの呼び出しを検知できる
        proxy.someMethod();
    }
}
```

```console
処理: someMethod
メソッドが呼ばれた: someMethod
後処理: someMethod
```

## 3. まとめ

1. DIにクラス情報を登録しておく
1. 登録されたクラス情報をもとにインスタンスをつくる
1. メソッドの実行をハンドリングし、呼ばれたメソッドの前後に処理を挟む

この2つのサンプルを確認によって、DIの仕組みが理解できると幸いです。
RNN(リカレントニューラルネットワーク)とは

# 概要
<!-- 発端や概要を記載 -->
RNN(リカレントニューラルネットワーク)とは、再帰的な結合を持ったニューラルネットワークで、時系列データを扱うネットワークである。
ディープラーニングの一種として位置付けられている。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [RNN](#RNN)
1. [活性化関数](#活性化関数)
1. [参考](#参考)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# RNN
以下の図がRNNの概略図である。
![RNNの図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457216/b98f60a4-7598-f3c2-9b8e-316d74358128.png)
このように再帰的な結合を持ったネットワークとなっている。
時刻tにおけるRNNの隠れ状態（出力）は以下の式で表される。
![RNNの式.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457216/22594c58-d73e-c3f2-6b6a-32116753e726.png)
x<sub>t</sub>は時刻tにおける入力、W<sub>ih</sub>は入力からRNNへの結合重み、W<sub>hh</sub>はリカレント結合重み、b<sub>ih</sub>、b<sub>hh</sub>はそれぞれに対応するバイアスである。
活性化関数には、式のようにtanh関数を用いていることもあるが、ReLU関数を用いる場合もある。

<a id="#Chapter2"></a>
# 活性化関数
活性化関数とは、生体における活性化したニューロンを表現するために考えられた関数である。この活性化関数を通すことで、小さな入力を活性化させ、大きな入力を得ることを可能にしている。RNNの章で挙げたtanh関数とReLU関数について解説する。
## tanh関数
以下のようなグラフがtanh関数である。入力が-3から3の場合で表示している。
![tanh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457216/01666e64-2d97-b13f-7828-39deaf0f4e0b.png)
このようにtanh関数は任意の点で微分可能な関数である。
## ReLU関数
ReLU関数は0以下の時に0を返し、0より大きい時、入力された値をそのまま返す関数である。出力をすべて非負値にしたいときに用いる。

<a id="#reference"></a>
# 参考
- [PyTorch RNN](https://pytorch.org/docs/stable/generated/torch.nn.RNN.html)
【ubuntu】 Python3をアンインストール▶画面クラッシュ時の対処


# Introduction

**下手に`Python`アンインストールしない！**
**`ubuntu-desktop`を再インストールしても直らない場合に！**

別バージョンの`Python`を試す予定で`Python3.10`と`Python3.11`をインストールしていました。
不要になったため後から入れた`Python3.10`をアンインストールする予定だったのですが、何を思ったのか(タブ補完で typo して)デフォルトで入れた`Python3.11`の方をアンインストールしてしまいました。

途中で気付いて`Ctrl+C`したのですが、画面が落ちて無事クラッシュ......

`ubuntu-desktop`を再インストールすれば直るとのことですが、それでは解決しませんでした。
似たような現象の方に届くことを願って共有します。

**本記事が少しでも読者様の学びに繋がれば幸いです！**
**「いいね」をしていただけると今後の励みになるので、是非お願いします！**

## 環境

Ubuntu22.04

## 前提

- `ubuntu`で`Python3`をアンインストールして画面クラッシュ。
- `ubuntu-desktop`を再インストールしても変化なし。
  ```bash:
  sudo apt-get install --reinstall ubuntu-desktop
  ```

## 結論

リカバリーモードで CUI ログイン画面に入り、`gdm3`を再インストールしてサービスを再起動したら回復しました。
手順を以下に記載します。

1. 電源ボタンからマシンを起動する。
1. `Shift`を連打で`GNU GRUB`を起動する。(普段は`Esc`でも起動できるのですが、何故か効きませんでした)
1. 上から 2 番目の「`Advanced options for Ubuntu`」を選択する。
1. カーネル選択で、語尾が`recovery mode`のものを選択する。
1. 下から 2 番目の`root`を選択し、root ユーザーでコマンド入力できるようにする。
1. `gdm3`を再インストールする。
   ```bash:
   sudo apt purge gdm3
   sudo apt install gdm3
   ```
1. `gdm3`の設定ファイルを確認する。
   ```bash:
   sudo vim /etc/gdm3/custom.conf
   ```
1. `Vim`で以下の行からコメントアウトを解除する。
   ```vim:
   WaylandEnable=false
   ```
1. サービスを再起動する。しないと画面暗転に逆戻りしました。
   ```bash:
   sudo service gdm3 restart
   ```
1. マシンを再起動し、GUI ログイン画面が起動することを確認する。
   ```bash:
   reboot
   ```

## おまけ：`grub>`が表示される方

`grub`のログイン画面に入ったり、`Ctrl+Alt+F2`でコマンドモードに入ってコマンド入力等の手段もありました。

https://kajindowsxp.com/grub2/

1. Ubuntu の/ (ルートパス)は`ls`や`ls /boot`コマンドで表示される`vmlinuz-`の更新日時が一番新しいものをルートパスとして指定してください。
   私の場合は(hd0,3)でした。
   `bash: 
    set root=(hd0,3)
    `
1. カーネルイメージのパスは、`vmlinuz-`のカーネルバージョンが一番新しいものを指定してください。ドライブ名は 1. と同じです。
   ```bash:
   linuxefi [カーネルイメージのパス] root=(hd0,3)
   ```
1. 初期 RAM ディスクのパスは`initrd.img-`で、2. と同じカーネルバージョンを指定してください。
   ```bash:
   initrdefi initrd.img-[カーネルイメージのパス]
   ```
1. 再起動する。
   ```bash:
   reboot
   ```

そもそもクラッシュしているため、すべてに当てはまる事象ではないと思います。
上記紹介記事の手順も参考にしてみてください。

## 最後に

最後まで閲覧頂きありがとうございました。

`Python`をアンインストールしなければ良いだけの話ですが、`Linux`にはトラブルがつきものなのでお守り代わりに本記事を覚えておいていただければ幸いです。

正直結論に至るまで数時間は格闘して試行錯誤したため、カーネル周りについてかなり良い勉強になりました。怪我の功名でした。

実践も良いですが心臓に悪いため、私が`Linux`の勉強に使っている書籍を紹介しておきます。
安易にクラッシュさせずに書籍で勉強しましょう......

https://www.amazon.co.jp/%EF%BC%BB%E8%A9%A6%E3%81%97%E3%81%A6%E7%90%86%E8%A7%A3%EF%BC%BDLinux%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF-%E2%80%95%E5%AE%9F%E9%A8%93%E3%81%A8%E5%9B%B3%E8%A7%A3%E3%81%A7%E5%AD%A6%E3%81%B6OS%E3%80%81%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E3%80%81%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98%E3%80%90%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88%E3%80%91-%E6%AD%A6%E5%86%85-%E8%A6%9A/dp/429713148X

備忘録の側面もありますが、本記事がお役に立てば幸いです！

### 参考 URL

https://qiita.com/R1ngNebula/items/a35af01868b590ac7e89
PythonでPDFファイルからテキストを抽出して出力する

# 前提条件
* Windows10
* Python3
* PyMuPDFライブラリ
* Tkinterライブラリ 

サンプルのPDFファイルは下記のウィキペディアトップページをPDFとしてローカルに保存したものを使用します。
https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8

PyMuPDFライブラリの公式ドキュメントは以下です。
https://pymupdf.readthedocs.io/en/latest/

Tkinterライブラリの公式ドキュメントはこちらです。
https://docs.python.org/ja/3/library/tkinter.html

# 目的
Pythonを使用してローカルにあるPDFからPyMuPDFライブラリを利用し、テキストを抽出します。
抽出したテキストを出力する前に、Windows OSでの文字化け対策のため、Shift_JISへ文字コードを変換してから、標準出力へ出力します。

# 環境構築

PyMuPDFライブラリのインストール。
```
pip install pymupdf
```
# サンプル

```pdfread.py
# -*- coding: utf-8 -*-

import fitz # pymupdfライブラリ

pdf = 'C:\\Wikipedia.pdf'
doc = fitz.open(pdf)

for page in range(len(doc)):
    tmp = doc[page].get_text()
    tmp2 = tmp.encode('shift_jis','ignore')
    text = tmp2.decode('shift_jis')
    print(text)

doc.close()
```

Tkinterライブラリを利用し、PDFをGUIで選択できるようにする。
```pdfread2.py
# -*- coding: utf-8 -*-

import fitz # pymupdfライブラリ
from tkinter import filedialog #tkinterライブラリ

typ = [('pdfファイル','*.pdf')] 
dir = './'
pdf = filedialog.askopenfilename(filetypes = typ, initialdir = dir) 

doc = fitz.open(pdf)

for page in range(len(doc)):
    tmp = doc[page].get_text()
    tmp2 = tmp.encode('shift_jis','ignore')
    text = tmp2.decode('shift_jis')
    print(text)

doc.close()
```
# 参考資料
https://www.amazon.co.jp/Python%E3%81%A7%E6%96%87%E6%9B%B8%E5%87%A6%E7%90%86%E2%80%95%E8%B3%87%E6%96%99%E3%81%AEPDF%E5%8C%96%E3%80%81%E6%96%87%E5%AD%97%E8%AA%8D%E8%AD%98%E3%80%81%E6%A4%9C%E7%B4%A2%E3%80%81%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E4%BD%9C-%E5%8C%97%E5%B1%B1-%E6%B4%8B%E5%B9%B8/dp/4877834974?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=K018UDE4Y69J&keywords=python+pdf&qid=1686010977&sprefix=%E4%BA%BA%E5%8F%A3%2Caps%2C2758&sr=8-1&linkCode=ll1&tag=qiitajinbei23-22&linkId=6fd240817b25e70d26c80bf24d192ed7&language=ja_JP&ref_=as_li_ss_tl

<!-- admax -->
<div class="admax-ads" data-admax-id="869dac7522ec2a866395c856f2775f30" style="display:inline-block;width:728px;height:90px;"></div>
<script type="text/javascript">(admaxads = window.admaxads || []).push({admax_id: "869dac7522ec2a866395c856f2775f30",type: "banner"});</script>
<script type="text/javascript" charset="utf-8" src="https://adm.shinobi.jp/st/t.js" async></script>
<!-- admax -->
【ChatGPT】「続けて」はもういらない

初めまして。カーブミラーと言います。
自己紹介は、のちほど、ということで、
よろしくお願いします。

タイトルのとおりなのですが、
（すでに知っていたら、ごめんなさい）
これまで、ChatGPTの返事の量が多く、途中で止まってしまうことがありました。

皆様も当然のごとく、「続けて」等の言葉を打ち込んで、続けてきたと思います。

ところが、先日（2023/05/24）、画面に変化がありました。とても小さい変化です。
ちなみに私はふだんは、スマホです。

プロンプト入力枠のとなりに矢印がグルグルまわるようなボタンがありましたが、そのとなりに新たなボタンがあったのです。
「▷▷」ボタンです。

タップしてみると、なんと続きが流れはじめました。そう、「続けて」ボタンだったのです。

試しに、プログラムを出させて、途中で止まるので、タップ。
見事にコードブロックの中に続きが流れていきます。

ちなみに長い返答コードの際に今までどおりに「続けて」と打ち込んでみたら、新たな発言として、コードが流れて行きました。コードブロックからはみ出して（悲）

PCでの確認してみると、
“Regenerate response”ボタンのとなりに
新たなボタンが追加されていました。
“Continue generating”ボタンです。
***
　2023/07/04確認したのですが、
　　MicrosoftBingも
　　　Googlebardも
　　　　「続けて」を入れるしか
　　　　　ありませんでした。
iTunesで評価していないのにグレーの星がついている場合の対応

# 状況

評価していないのにグレーの星がついている曲がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/24bc47e4-3d68-cbc0-0baa-607b4a93c0ee.png)

こういった曲は『星4以上』っていう条件のスマートプレイリストにピックアップされてしまう。

こういった曲の評価をできるかぎりまとめて『星無し』にしたい。

# やり方

右クリックして『アルバムをライブラリに表示』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1f199c46-0a90-093d-d6b9-f9fda2d28f38.png)

右上の…から『評価』を『なし』に。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/11713444-a23d-5fb4-2e1e-5b7486103f0f.png)

**すでに星がついている曲の星はそのまま** なので『意図せず評価が消えてしまう』という心配は無し。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/21ab6628-da36-0453-eb98-bc33f8c587b5.png)

# バージョン

Windows 10 Home 22H2 19045.2965
iTunes 12.12.8.2
ずっと手元に置いておきたい DOM操作用ロケータ チートシート

# チートシート

## そもそもDOMって何?
https://qiita.com/yurihyp/items/dd31f32f34a192ff6568

DOMを知らない方やHTMLの要素の情報の見方がわからない方はこちらをご覧ください

## documentの要素取得API

### document.querySelector
| querySelector | 説明 |
|---|---|
| document.querySelector('button[type="submit"]') |type属性がsubmitのbutton要素のうち, 最初の一つを取得する|
| document.querySelectorAll('button[type="submit"]') |type属性がsubmitのbutton要素の全てを取得する|

### document.getElement
| セレクタ | 説明 |
|---|---|
| document.getElementById('SearchBox') |id属性がSearchBoxの要素を取得する|
| document.getElementsByClassName('reservation') |クラス属性がSearchBoxの要素を全て取得する|
| document.getElementsByName('title') |name属性がtitleの要素を全て取得する|




## CSSセレクタ


### 型セレクタ
| CSSセレクタ | 説明 |
|---|---|
| button | button 要素 |

### IDセレクタ
|CSSセレクタ | 説明 |
|---|---|
| #draft | id="draft" の要素 |

### classセレクタ
| CSSセレクタ | 説明 |
|---|---|
| .SearchBoxTextEditor | class="SearchBoxTextEditor" の要素 |
| div.SearchBoxTextEditor | class="SearchBoxTextEditor" の div 要素 |
| div.SearchBoxTextEditor.textInput  |SearchBoxTextEditorクラスとtextInputクラスの両方に属するdiv属性  |

### 属性セレクタ
|CSSセレクタ | 説明 |
|---|---|
| input[value="test"] | value属性が[test]のinput属性 |
| input[value="test"]（n)  | value属性が[test]のinput属性のn番目の要素 |
| a[title="test"] | title属性が[test]のa要素 |
| [title="test"]| title属性が[test]の要素 |
| input[name='radio'][value='on']| nama属性が[radio]&vlue属性が[on]のinput要素 |

### 正規表現的なセレクタ
|CSSセレクタ | 説明 |
|---|---|
| input[value^="test"]| value属性が[test]で始まるinput要素 |
| input[value$="test"]| value属性が[test]で終わるinput要素 |
| input[value*="test"]| value属性に[test]を含むinput要素 |


### 子セレクタ
|CSSセレクタ | 説明 |
|---|---|
| #root > div | id[root]の要素の直下にあるdiv要素 |
| #root > div > a | id[root]の要素の直下にあるdiv要素の直下にあるa要素 |

### 子孫セレクタ
|CSSセレクタ | 説明 |
|---|---|
| #root div | id[root]の要素の下にあるdiv要素 |
| #root div.content |id[root]の要素の下にあるdiv要素の下にあるcontentクラスの要素 |

### nthを使った セレクタ
|CSSセレクタ | 説明 |
|---|---|
| #root > div.nth-of-type(2) | id[root]の要素の下にあるdiv要素のうち2番目のもの|

### 変数を利用してエレメントを取得する
```javascript
let serviceId
Document.querySelector('a[href$="/${serviceId}"]')
//セレクタを囲っているのがダブルコーテーションではなくバッククオートであることに注意
```

## 子孫node, elementの指定方法
|取得方法| 説明 |
|---|---|
| parentNode | 親ノードを指定する|
| parentElement | 親要素を指定する|
| childNode | 子ノードを指定する|
| firstChild | ノードの最初の子要素を取得する|
| firstElementChild | ノードの最初の要素子要素を取得する|
| lastChild | ノードの最後の子要素を取得する|
| lastElementChild | ノードの最後の要素子要素を取得する|
| nextSibling | ノードの次の要素兄弟要素を取得する|
| previousSibling | ノードの前の兄弟要素を取得する|
| previousElementSibling | ノードの前の要素兄弟要素を取得する|


## 要素のテキストを取得する
|取得方法| 説明 |
|---|---|
| textContent | 要素のテキストを取得する|
| innerText | 要素のテキストとHTMLタグを一緒に取得する|

## パフォーマンス観点でのCSSセレクタ取得
https://qiita.com/rnakayama/items/168bcbc05e6b1fc989f5
データサイエンスのための微分積分 第11回 極限の演算法則

:::note info
本記事は数学講座[2.10極限の演算法則](https://www.matongxue.com/lessons/593/parts/939)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

# 無限小の加算

**定理：**
二つの無限小の和も無限小です。

証明は以下の通りです：
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/c25609b4-7539-11f1-dc76-70159010cb09.png" width=480>

$\delta=\min\{\delta_1,\delta_2\}$で、小さいの方を選んでいれば、両方ともみたされます。


**推論：**
有限な数の無限小の和も無限小です。



# 無限小の乗法

**定理：**
有界関数と無限小の乗積が無限小です。

**推論：**
- 定数と無限小の乗積が無限小です。（定数も有界関数です）
- 有限な数の無限小の乗積が無限小です。（無限小も有界関数です）

# 極限の演算法則

**定理（関数）：**
もし $\lim f(x) = A  と　\lim g(x) = B $であるならば、以下が成り立つ：

- $\lim [f(x) ± g(x)] = \lim f(x) ± \lim g(x) = A ± B$

- $\lim [f(x) ⋅ g(x)] = \lim f(x) ⋅ \lim g(x) = A ⋅ B$

- もし $B ≠ 0$ であるならば：
```math
\displaystyle\lim\frac{f(x)}{g(x)} = \frac{\lim f(x)}{\lim g(x)} = \frac{A}{B}
```

**定理（数列）：**

数列${x_n}と{y_n}$が与えられ、$\lim_{n\to\infty} x_n = A、\lim_{n\to\infty} y_n = B$の場合、次のことが成り立つ:

- $\lim_{n\to\infty}(x_n\pm y_n)=\lim_{n\to\infty} x_n\pm \lim_{n\to\infty} y_n=A\pm B；$

- $\lim_{n\to\infty}(x_n\cdot y_n)=\lim_{n\to\infty} x_n\cdot \lim_{n\to\infty} y_n=A\cdot B；$

- $y_n\ne 0（n=1,2,\cdots）かつ B\neq 0の$場合、以下が成り立つ：
```math
\displaystyle\lim_{n\to\infty}\frac{x_n}{y_n}=\frac{\displaystyle\lim_{n\to\infty} x_n}{\displaystyle\lim_{n\to\infty} y_n}=\frac{A}{B}
```

**推論（極限演算法則の推論）：**
- もし $\lim f(x) $が存在するならば、$\lim [cf(x)] = c \lim f(x)$ となります。ただし、c は実数です。
- もし $\lim f(x) $が存在するならば、$\lim [f(x)]^n = [\lim f(x)]^n $となります。
- 対応する局所領域で$ f(x) ≥ g(x) $が成り立ち、かつ$ \lim f(x) = A、\lim g(x) = B $である場合、$A ≥ B $が成り立ちます。

# 極限の演算法則-練習
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/ed3d4c53-78d4-07f7-74e8-e39623b57568.png)

**定理：**

もし$a_0\ne 0，b_0\ne 0，n、m$も0以上であれば：

```math
\lim_{x\to \infty}\frac{a_0x^m+a_1x^{m-1}+...+a_m}{b_0x^n+b_1x^{n-1}+...+b_n}=\begin{cases}
0，&\text{}\ (n > m)\\
\\
\displaystyle\frac{a_0}{b_0}，&\text{}\ (n = m)\\
\\
\infty，&\text{}\ (n < m)
\end{cases}
  ```

# 放物線（ほうぶつせん）での面積
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/04126849-2821-5049-4118-a5a8b9dd0a14.png)

# 参照情報
CSS レスポンスデザイン

# レスポンスデザインとは
Webサイトを閲覧するユーザが使用する<ins>デバイスの画面サイズ</ins>に応じて表示を最適化するデザインのことを**レスポンスデザイン**という．PCやモバイル端末(スマホ・タブレット)では画面サイズが違うため，同じ表示方法では一方が見にくくなることがある．レスポンスデザインを利用すれば，一つのhtmlから複数の見え方を作ることが可能であるため，端末にあった配置や表示を適用できる．

![レスポンシブデザイン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/d212fa9d-bed3-2d3d-494d-55c79f67d85f.png)


# メディアクエリ
メディアクエリとは，レスポンスデザインを実現するために必要な機能で，Webページのスタイルを記述するCSSの仕様の一つ．具体的には，表示された画面環境に応じて適用スタイルを切り替える機能である．

### HTMLの追加事項
```html
<head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
</head>
```
メディアクエリを利用したレスポンシブデザインを実装する場合は，適応したいHTMLファイルのヘッダ要素に，上記のmeta要素を追加する必要がある．

### 基本構文
メディアクエリの基本構文は以下のようになる．それぞれ**メディアタイプ**と**メディアの特性**を指定することで，特定の画面環境のみに適用させることができる．
```css
@media メディアタイプ and (メディアの特性){
    /*指定したいCSS*/
    selector{}
}
```
**・メディアタイプ**
→どのメディアにCSSを適用させるかを指定するもの．メディアタイプに指定されるデバイスとして以下のものが記述する．(他にもあります．)

|記述方法|適用されるデバイス|
|:--:|:--:|
|all|全てのデバイス|
|print|プリンター|
|screen|プリンター以外のデバイス(PC，スマホ，タブレット)|

**・メディアの特性**
→メディアの特性は，CSSを適用させる条件を指定するもの．メディアの特性として以下のものが使われる．(他にもあります)

|記述方法||
|:--:|:--:|
|width|ブラウザの表示領域の幅|
|height|ブラウザの表示領域の高さ|
|device-width|デバイス画面の幅|
|device-height|デバイス画面の高さ|
|orientation|ブラウザの表示領域の向き|


# 画面サイズごとに切り替え
閲覧している端末の画面サイズに応じて表示を切り替えるには以下のように記述する．
```css
@media screen and (min-width: 768px){
    /*指定したいCSS*/
    selector{...}
}
```
メディアタイプには``screen``を指定する．メディアの特性として``min-width``を指定することで，ウィンドウ幅が768px以上の場合にCSSを適用することができる．

### ブレイクポイント
ブレイクポイントとは，レスポンスデザインの表示を切り替えるポイントを指す．ブレイクポイントにデバイスのウィンドウ幅を指定することで，デバイス毎のCSSを適用することができる．Webアプリでは，基本的にPC/スマホ/タブレットの3種類を指定すれば良い．

**端末ごとの横幅**
PC：768px以上
タブレット端末：480px〜767px
スマホ端末：479px以下
（厳密には使う端末によって少し異なる）

### 例
```css
/* PC */
@media screen and (min-width: 768px){
	/* PCに適用するCSS*/
}
/* Tablet */
@media screen and (max-width: 768px){
	/* タブレット画面に適用するCSS*/
}
/* SmartPhone */
@media screen and (max-width: 480px){
	/* スマホ画面に適用するCSS*/
}
```


# コンテンツの配置を変える方法
コンテンツの配置を変える方法は，別の記事にまとめました．本記事と組み合わせることでレスポンスデザインが完成させることができます．

https://qiita.com/thirai67/items/3c8b5a15ec9d2cbf0fbb
【Rails】ダウンタイムなしでDBのデータを移行する

## 概要

### 前置き

最近、サービスを止めずDBのデータを違うテーブルに移すのをよく行っています。
せっかくなので、その際の手順を記事にしました。

この記事では、ユーザーテーブルのメールアドレスの移行で話を進めます。   
具体的には、ユーザーテーブルからメールアドレスを切り出し、新しく作成したメールアドレステーブルに移行する話です。

### 環境

- Ruby 3.1.2
- Rails 7.0.4
- ridgepole 1.1.0

## 移行前の状態

### ユーザースキーマ

下記が、移行前のユーザーテーブルのスキーマです。
```ruby:
create_table 'users', charset: 'utf8mb4', force: :cascade do |t|
  t.string 'name', null: false
  t.string 'email', null: false
  t.datetime 'created_at', null: false
  t.datetime 'updated_at', null: false
  t.index ['email'], name: 'index_users_on_email', unique: true
end
```

## 移行

### 1. ダブルライトするように変更しデプロイ

ユーザーモデルが追加/更新された際に、そのメールアドレスをユーザーメールアドレステーブルにもUPSERTされるように変更します。

以下が、追加するユーザーメールアドレススキーマです。
```ruby:
create_table 'user_emails', charset: 'utf8mb4', force: :cascade do |t|
  t.string 'email', null: false
  t.references :user, null: false, foreign_key: true
  t.datetime 'created_at', null: false
  t.datetime 'updated_at', null: false
  t.index ['email'], name: 'index_user_emails_on_email', unique: true
end
```

ユーザーモデルに、ユーザーメールアドレスモデルをUPSERTするメソッドを追加し、`after_save`に設定します。
```ruby:
class User < ApplicationRecord
  after_save :upsert_user_email!

  has_one :user_email, dependent: :destroy

  private

  def upsert_user_email!
    if user_email.present?
      user_email.update!(email:)
    else
      create_user_email!(email:)
    end
  end
end
```

これで新しく追加されるユーザーや変更されたユーザーに対して、ユーザーメールアドレステーブルにもデータが作成/更新されるようになりました。

### 2. 古いデータを移行する

移行用のRakeTaskを実装し、古いデータに対しての移行を行ないます。
*本筋から少し外れるのでここは割愛します。*

### 3. 古いカラムを参照している箇所を切り替えるデプロイ

2でDB上のデータ移行は終わりました。
次はソースコード上でユーザーモデルのメールアドレスを参照している箇所を、ユーザーメールアドレスモデルのメールアドレスに切り替えます。

### 4. 古いカラムを削除する準備

いきなり古いカラムを削除すると、マイグレーションとソースコードのデプロイ間にエラーが発生する場合があります。
なのでユーザーモデルに下記記述を追加し、事前にデプロイしておきます。

```ruby:
class User < ApplicationRecord
  after_save :upsert_user_email!

  has_one :user_email, dependent: :destroy
  # 下記を追加
  self.ignored_columns = [:email]

  private

  def upsert_user_email!
    if user_email.present?
      user_email.update!(email:)
    else
      create_user_email!(email:)
    end
  end
end

```

### 5. 古いカラムを削除する

4のデプロイ後、数日様子を見て問題なければ古いカラムを削除します。

## まとめ

移行を段階的に行うことで、何か問題が発生した場合でも元の状態に戻すことができます。
全ての移行が完了するまでに時間はかかりますが、安全に移行できるのでおすすめです。
git worktreeが便利だった

## 複数ブランチを並行して開発したい
こんな状況ありませんか？
- アサインされた開発チケットが複数あり、並行して開発している
- 運用が挟まり、developブランチの内容を確認したい
- 仕様待ちになったので、他チケットに着手したい
- コードレビュー待ちの間は他の開発をしていたが、レビューの指摘が来たので対応したい

`git stash`は便利ですが、毎回行うのはしんどいし、stashした内容を再度反映させるときにミスするのも怖いですよね。
正直、stashした内容を覚えてないこともありませんか…？

## git worktreeを使う
上記のような状況で`git worktree`が便利だったので紹介しておきます。
以下、リポジトリとブランチは下記として手順を説明します。

```sh
# リポジトリ
$ tree -L 1
.
└── myrepo

# ブランチ
$ git branch
   main
 * develop
   feature/t1
```

## 手順
#### 1. worktreeの対象ブランチを決める
ここでは`feature/t1`ブランチとします。

#### 2. worktreeを作成するディレクトリを決める
ここでは`dir_t1`ディレクトリにします。
git worktreeでは、worktreeを作成するディレクトリを決め、そこに作業ブランチを指定してソースコードを取得します。
挙動としては`git clone`を2回行うのに近いです[^1]
#### 3. worktreeを作成
下記のコマンドを実行します。
コツは、対象のリポジトリと並列でworktreeを作成することです。
そうすることで、ソースコードの検索時に複数ヒットしてややこしくなるのを回避します。
```sh
$ git worktree add ../dir_t1 feature/t1
#                   ↑ ../ とすることで、並列に作成しています
```

この状態で`git branch`をすると、worktreeには`+`が付きます
```sh
$ git branch
   main
 * develop
 + feature/t1
```

#### 4. worktreeの移動
`cd`を実行してディレクトリを移動するだけです。
```sh
$ cd ../dir_t1
$ git branch
   main
 + develop
 * feature/t1

$ tree -L 1
├── myrepo
└── dir_t1
```
この状態で、`feature/t1`として開発できます。
やっぱりdevelopに戻りたい！となった場合は`cd`で戻りましょう。
このとき`git stash`をしなくても、変更は消えません。

#### 5. さらにworktreeを増やす
`feature/t1`での作業が途中でも、`feature/t2`に着手する必要がある、そんな場面もあるでしょう。
そのときも素直にworktreeを増やせばOKです。
```sh
$ git worktree add ./dir_t2 feature/t2
   main
 + develop
 + feature/t1
 * feature/t2

$ tree -L 1
├── myrepo
├── dir_t1
└── dir_t2
```

#### 6. 不要になったworktreeは削除
開発が完了したworktreeは不要なので削除しましょう。
```sh
$ git worktree remove feature/t1
```

## ぶっちゃけ
環境構築が必要な場合、再度構築し直す必要はあります。
そして当然ですがサーバーの起動などは、ポートが被ったらできません。

それでも、複数ブランチの並行開発においては十分に便利であり、もっと早く知りたかった…！と思ったので紹介しました。

https://git-scm.com/docs/git-worktree

[^1]:じゃあ２回cloneすればいいじゃん、という意見はもっともです。違いは[こちら](https://news.ycombinator.com/item?id=19007761)でもディスカッションされています。この記事では便利だよ！を伝えたかったので、詳細までは調べておりませんm(_ _)m
phpunit(Futureテスト)のassertメソッドの種類

# 目的
業務でFutureテストを使うことになったのでとりあえずアウトプット

# 種類
| メソッド| メソッドの説明|
|-----------|---------------|
|**assertStatus($code)**| レスポンスのHTTPステータスコードが指定した値と一致することをアサーションします。|
|**assertSee($value)**|レスポンスの内容（HTMLまたはテキスト）に指定した値が表示されていることをアサーションします。|
|assertHeader(\\$header, $value = null) | レスポンスヘッダーが指定した値と一致することをアサーションします。|
|assertCookie(\\$cookieName, $value = null) | レスポンスに指定した名前のCookieが存在し、値が指定した値と一致することをアサーションします。|
|assertJson($data = null) | レスポンスが有効なJSON形式であり、指定したデータと一致することをアサーションします。|
|assertJsonFragment($data) | レスポンスに指定したデータの一部が含まれていることをアサーションします。|
|assertSeeInOrder($values) | レスポンスの内容（HTMLまたはテキスト）に指定した値が指定した順序で表示されていることをアサーションします。|
|assertDontSee($value)  | レスポンスの内容（HTMLまたはテキスト）に指定した値が表示されていないことをアサーションします。|
|assertDontSeeInOrder($values) |レスポンスの内容（HTMLまたはテキスト）に指定した値が指定した順序で表示されていないことをアサーションします。|
|assertRedirect($uri = null) | レスポンスがリダイレクトを示しており、指定したURIにリダイレクトされることをアサーションします。|
|assertViewIs($value)|レスポンスが指定したビューを表示していることをアサーションします。|

# よく使うコード
urllを入れてステータスコードとそのページに表示されているであろう文字列を取得する。

```php
  public function testSample1() : void
  {
    $url = "/test";
    $response = $this->get($url);
    $response->assertStatus(200);
    $response->assertSee('aaa');
  }

  public function testSample2() : void
  {
    $url = "/test2";
    $response = $this->get($url);
    $response->assertStatus(200);
    $response->assertSee('bbb');
  }

```
# 参考URL
https://phpunit.de/documentation.html

# 感想
今のところ使っているのは"assertStatus"と"assertSee"ぐらいなので、それ以外は「へー、そんなのがあるんだ」ぐらいの感触。
1つのurlにつき1つの関数で分けているが、正直正しいかどうかは分からない。
特に指摘は受けていないので大丈夫と信じたい。
たまに権限のせいかあるはずなのに403が返されることはあるが、それはまた機会があれば別記事にて。

構文とか基本的な使い方はChat-GPTに聞いた方が早いかも。
一応公式は確認するが英語だらけのドキュメントだとGPTでいいやってなっちゃう。
【Flutter】Could not build the application for the simulator. Error launching application on iPhone XXX.のエラーが出る

# はじめに
Flutterをやっていたらめっちゃエラーが出ました😭

初学者にこのエラーの量はきついです😭

![スクリーンショット 2023-05-24 22.16.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2c9ee06b-7371-c1e3-a2a6-ad10f6ca597e.png)

```
Could not build the application for the simulator.
Error launching application on iPhone 14.
```

# エラーの心当たり
このプロジェクトのフォルダを移動させたんですよね
おそらくその影響でパスが変更されて何かが見つからないとかでしょう
知らんけど

# 原因をChatGPTに聞いてみる
>このエラーの原因は、Xcodeビルド時にモジュールキャッシュのパスが一致しないことです。モジュールキャッシュは、ビルドプロセスの高速化のために使用されるデータの一時的な格納場所であり、以前のビルドから生成されたモジュールの情報を保持します。

>一般的に、このエラーは以下のいくつかの原因によって引き起こされる可能性があります。
>1. プロジェクトのパスが変更された: Xcodeプロジェクトが移動されたり、名前が変更された場合、モジュールキャッシュのパスが一致しなくなります。
>2. モジュールキャッシュが破損している: モジュールキャッシュに保存されているデータが破損している場合、ビルド時にエラーが発生します。
>3. XcodeやFlutterのバージョンの不一致: XcodeやFlutterのバージョンが互換性のないものである場合、ビルド時にエラーが発生することがあります。

>これらの原因のいずれかが、エラーメッセージに示された問題の原因となっています。具体的な原因を特定するには、プロジェクトの構成や環境を詳しく調査する必要があります。提供された情報だけでは原因を特定することは難しいかもしれませんが、前述の解決策を試してみることで問題が解決する可能性があります。

だそうです

# 解決方法
プロジェクトのiosファイルまで移動する
```:ターミナル
cd プロジェクトのパス
cd ios
```

`Pods`と`Podfile.lock`と`DerivedData`と`.symlinks`を削除する
```:ターミナル
rm -rf Pods/ Podfile.lock DerivedData/ .symlinks/
```

アップデートする
```:ターミナル
flutter pub get
```

再ビルドしてみる
```:ターミナル
flutter run
```

治った！！！

# おわり
いやーChatGPTは最高ですね

ChatGPTがあるかないかでは学習の速度が段違いです
CSS マージンとパディングとボーダー

# ボックスモデルの考え方
HTMLで余白やレイアウトを設定するには，CSSのボックスモデルという概念を理解すると良い．HTMLの全ての要素は，以下の4種類の領域を持ち，この４つを合わせた領域のことをボックスという．
![mbpc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/1791434f-5431-3131-c14c-8d72062eaed9.png)

**１．内容領域：コンテンツ(Content)**
ブラウザに表示される要素内のテキストや画像を含む領域．
**２．内側余白領域：パディング(Padding)**
内容領域の外側にある「余白」の領域．
**３．境界線領域：ボーダー(Border)**
パディング領域の外側で，パティング領域とマージン領域の「境界線」となる領域．
**４．外側余白領域：マージン(Margin)**
ボーダーより外側にある「余白」の領域．隣り合った要素との間の設定に使う．

# パディングの指定方法
```css
    /*例*/
    selector{
        padding: 10px 20px 20px 40px;
    }
```
要素には，上下左右の４つの余白を持つため，**1つずつ指定する方法**と**複数指定する方法**がある．
|記述方法|指定される方向|
|:--:|:--:|
|``padding: (値);``|上下左右の４つ全てに同じ指定をする|
|``padding: (値)　(値);``|上下と左右のセットで同じ指定をする|
|``padding-top: (値);``|上のパディングを指定する|
|``padding-bottom: (値);``|下のパディングを指定する|
|``padding-left: (値);``|左のパディングを指定する|
|``padding-right: (値);``|右のパディングを指定する|
|``padding: (値) (値) (値) (値);``|上下左右にそれぞれ指定をする|


# マージンの指定方法
```css
    /*例*/
    selector{
        margin: 10px 20px 20px 40px;
    }
```
marginも同様で，上下左右の４つの余白に対して，**1つずつ指定する方法**と**複数指定する方法**がある．
|記述方法|指定される方向|
|:--:|:--:|
|``margin: (値);``|上下左右の４つ全てに同じ指定をする|
|``margin: (値)　(値);``|上下と左右のセットで同じ指定をする|
|``margin-top: (値);``|上のマージンを指定する|
|``margin-bottom: (値);``|下のマージンを指定する|
|``margin-left: (値);``|左のマージンを指定する|
|``margin-right: (値);``|右のマージンを指定する|
|``margin: (値) (値) (値) (値);``|上下左右にそれぞれ指定する|

# ボーダーの指定方法
ボーダーに関しては，線の太さ・色・スタイルの３つを指定することができる．このボーダーに関しても，**1つずつ指定する方法**と**複数指定する方法**がある．

|記述方法|指定される方向|
|:--:|:--:|
|``border-〇〇: (値);``|上下左右の４つ全てに同じ指定をする|
|``border-〇〇: (値)　(値);``|上下と左右のセットで同じを指定する|
|``border-top-〇〇: (値);``|上のボーダーを指定する|
|``border-bottom-〇〇: (値);``|下のボーダーを指定する|
|``border-left-〇〇: (値);``|左のボーダーを指定する|
|``border-right-〇〇: (値);``|右のボーダーを指定する|
|``border-〇〇: (値) (値) (値) (値);``|上下左右にそれぞれ指定する|

上記の``〇〇``に何を入れるかで，線の太さ・色・スタイルのどれかを指定することができる．

**１．width**
線の太さを指定することができる．
```css
selector{
    border-width: 5px 10px 15px 20px;
}
```
↓結果
![width.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/e44eddc3-6f2e-ef57-90c7-112df3179762.png)

**２．color**
線の色を指定することができる．
```css
selector{
    border-color: red blue green yellow;
}
```
↓結果
![color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/833bbe67-92db-47a3-161b-d9a73f22ae3e.png)

**３．style**
枠線のスタイルを指定することができる．スタイルには以下のような種類がある．
・none：枠線なし
・solid：実践
・double：二重線
・dotted：点線
指定しないとデフォルトで枠線なしが指定されるので注意．他にもさまざまな種類のstyleがある．

```css
selector{
    border-style: solid dotted dashed double;
}
```
↓結果
![style.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/86815b08-8c46-e7f4-58cc-6f39589d9f76.png)

**４．``〇〇``に何も入れない**
``〇〇``に何も入れない場合は，線の太さ・色・スタイルを同時に指定することができる．指定する順番は，線の太さ→スタイル→色という順番になる．

```css
selector{
    border: 5px double red;
}
```
↓結果
![set.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3133563/1407da96-a231-e78b-ca02-98f802348817.png)
【ショートカットキー】Xcodeで作業している時に出てくる邪魔なアイツを消す方法

Xcodeで作業している時に出てくる下の画像の赤い線で囲っている
邪魔なコイツを消す方法ですが

#### 『Command + Shift + Control + M』  で消せます

![DFCB484E-214E-4A99-B587-6B3CDF8B4440_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359201/fb090c93-b412-8ad5-c3b4-e2dfff492a90.jpeg)
Android10以下と11以上で生体認証の挙動が違う件

## Android10以下の生体認証の動き
Android10以下でDeviceCredentialsやBiometricAuth（いわゆる画面ロック解除ね）を使う場合、SDK内部の動きとしては、IntentでOSの機能に飛ばしている。
結果はonActivityResultに返ってくるので、従来は固有のRequestCodeをつけて結果の判別をしていた。

## AndroidXライブラリの登場
その後、AndroidXライブラリの登場によってOSバージョンごとの実装をしなくても良くなった。
ところが今度は「タスク復帰も生体認証から戻ってきたときも、アプリの状態として同じ判定を受ける」という別の問題が発生。
さらに、RequestCodeは起動の都度変わっていた。

## 困りどころ
ActivityのonStart,onResumeでタスク復帰時の処理をしていたので大いに困った。
今回は、onActivityResultで画面ロック解除成功（RESULT_OK）を通った時のonStartだけ、「生体認証成功時の処理」にしたい。

## 解決策
**LifecycleCoroutineScope**を使う。
この記事が参考になった。
https://qiita.com/HanaleiMoon/items/4735f977b9ef1be8bde2

## サンプルコード
Android10以下では、onActivityResult（Depricatedですが）に結果が渡ってくるので、onActivityResultで「RESULT_OK,処理成功」をキャッチしたら、このあと呼ばれるonStartでlifecycleScope.launchWhenStarted{}内に書いた処理が走る（== onResumeが呼ばれる前に走る）、という流れにしていきます。

```kotlin:MainActivity.kt
@Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    activityResultCode = resultCode

    lifecycleScope.launchWhenStarted {
        if (resultCode == -1) {//生体認証がとおったら == RESULT_OK == -1
            //次回onResumeの時に生体認証を走らせない
            mainViewModel.disableBiometric()
        }
    }
}
```


## ちなみに
AppLifecycleを噛ませる方法でも結果一緒でした。
あれは同一パッケージ内のActivity遷移でonResumeを通らないもので、今回はOSの機能に飛ばしているせいかガッツリ通っていた。
onActivityResultがDeprecatedなのは一旦見逃してください...