OmniAICreator/Qiita-1.07M huggingface dataset:
ExpoでAndroidエミュレーターを起動してもロードが終わらずアプリが起動しない

React Nativeの入門中に遭遇。

## 環境
- macOS Big Sur バージョン11.6.1
- Android Studio Arctic Fox 2020.3.1
- Node.js v14.16.0

## 事象

Android StudioでPixel 5のエミュレーターを起動し、Expoでエミュレーターを起動したところ画面のロードが終わらずアプリが起動しませんでした。

`Pixel 5 API 29` のエミュレーターを使用。
![スクリーンショット_2022-01-05_23.20.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217116/cbf47baa-83c9-4c2d-a0e3-dc2682bd52a9.png)
ブラウザから `Run on Android device/emulator` を行う。
![スクリーンショット_2022-01-05_22.52.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217116/b413aa48-fa39-94ac-02ba-0ea73f4e0fde.png)
ロードが終わらずアプリが起動されない。
![Pixel5_load.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217116/b7ed2c13-1903-6c1a-1d4c-df0cc73653a8.gif)



## 解消方法
`Pixel 3 API 29` のエミュレーターを使用したところ問題なく起動出来ました。

![スクリーンショット_2022-01-05_23.14.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217116/306702b3-8576-7fb9-bb84-70636951099d.png)
新し目の端末には対応していないということでしょうか？原因まではわかりませんが以上です！
AWS License Manager　を利用して　SQLServerライセンス変更を行った

テナント属性、BYOL、ライセンス込みなどいろいろ制限ありますが、
今回はSQLServerのBYOLからライセンス込みに実施したことを記載します。

まずは、前提条件があります。
①AWS　SSMを利用できること。（SSMロールが必要です）
②License Manager にオンボーディングする
詳細は以下リンクを参照ください。

https://docs.aws.amazon.com/ja_jp/license-manager/latest/userguide/conversion-prerequisites.html

アクセスキーを発行して、SQLのBYOLからラインセス込みに変換するコマンドを実行するだけ変換ができます。便利ですね、
aws license-manager create-license-conversion-task-for-resource \
    --resource-arn <instance_arn> \
    --source-license-context UsageOperation=RunInstances:0800 \
    --destination-license-context UsageOperation=RunInstances:0006 

※＜<instance_arn>＞はインスタンスIDではなく、region instance type 含まる識別子になります。

結果はこちらの結果UsageOperationを確認することは可能ですし、AWSコンソールにも確認できます。
aws ec2 describe-instances –instance-id <instance-id>

対象となるインスタンスタイプ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1348505/d8c9fce4-bdc5-9655-72c3-4891733d2abb.png)
リンク：
https://docs.aws.amazon.com/ja_jp/license-manager/latest/userguide/conversion-types.html

Tips:実行時サーバは停止中であることが必要です。
iOSで「iSH」を使用してasciidocを書く

# はじめに
iOSのアプリにはasciidocを書くアプリが見つからなかったため、「iPhone/iPadでx86 Linuxを動かすアプリ」である「iSH」を使用して、asciidocを書くための環境を構築しました。
本記事の内容は次の通りです。

* 「iSH」上でvimをインストールする
* 「iSH」上でasciidocのファイル形式変換環境を構築する
* 「iSH」上でasciidocファイルをpdfファイルに変換する

# 「iSH」上でvimをインストールする
ここでは「iSH」アプリのインストール方法は割愛します。
「App Store」で「iSH」で検索すれば該当アプリをすぐに見つけ出すことができると思います。
先ずは、「iSH」アイコンをタップして、「iSH」アプリを起動します。
「iSH」アプリが起動したら下記のapkコマンドを実行してvimをインストールします。

```bash:vimのインストール
apk add vim
```

インストールが完了したらvimコマンドを実行してvimが起動することを確認します。
この時点でvimで日本語入力ができていると思います、日本語が入力できることも確認します。

<img width="300" alt="IMG_0072.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354472/694152ce-a37d-585c-ac98-d038ce250772.png">


# 「iSH」上でasciidocのファイル形式変換環境を構築する
次に「iSH」上で作成したasciidocファイルをiPhoneで見れる形(pdfファイル)に変換する環境を構築します。
下記のapkコマンドを実行してrubyをインストールします。

```bash:rubyのインストール
apk add ruby ruby-dev ruby-json
```

rubyのインストールが完了したら下記のgemコマンドを実行してasciidoctorをインストールします。

```bash:asciidoctorのインストール
gem install asciidoctor asciidoctor-pdf asciidoctor-kroki
```

これでasciidocのファイル形式変換環境の構築は完了です。

# 「iSH」上でasciidocファイルをpdfファイルに変換する
asciidoctor-pdfを使用してasciidocファイルをpdfファイルに変換します。
下記のコマンドではsample_jp.adocというファイルをpdfファイルに変換しています。
asciidocファイル中にダイアグラムがあるため、asciidoctor-krokiも使用しています。

```bash:asciidocファイルをpdfファイルに変換
asciidoctor-pdf -r asciidoctor-kroki -b pdf -a allow-uri-read -a scripts=cjk -a pdf-theme=default-with-fallback-font -o sample_jp.pdf sample_jp.adoc
```

変換したpdfファイルを下記のようにiOSの「ファイル」アプリで閲覧することができるようになります。
ダイアグラムも正常に変換されています。

<img width="300" alt="IMG_0073.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354472/f35ca7ef-8d0d-25bd-bf70-41f9845ac59e.png">

# さいごに
今回は「iSH」を使用して、asciidocを書くための環境を構築しました。
ただし、「iSH」自体がx86 Linux エミュレータであるため、動作が重くpdfファイルへの変換にかなりの時間が必要でした。
Androidの「Termux」だったら、高速にpdfファイルに変換できるのか気になります。
AndroidでPermissionをリクエストするとき

## AndroidでPermissionをリクエストするとき

ネットで探すと、未だにリクエストを開発者側でハンドリングする記事ばかり出てきます。

しかし[公式ドキュメント](https://developer.android.com/training/permissions/requesting?hl=ja)では、**RequestPermission**や**RequestMultiplePermissions**のコントラクトを使用した方がいいと書いてあります。

> 従来からある方法では、権限リクエストの一部として開発者自身がリクエスト コードを管理し、このリクエスト コードを権限コールバックのロジックに含めます。別の方法として、AndroidX ライブラリに含まれる RequestPermission コントラクトを使用して、システムに権限リクエスト コードの管理を許可することもできます。RequestPermission コントラクトを使用するとロジックが簡素化されるため、可能な場合は使用することをおすすめします。

使用例は以下の通り
Kotlin + Jetpack Composeでの複数権限のリクエストの場合となります。

```
    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { granted ->
        val notPermission = granted.filter {
            !it.value
        }.size
        if (notPermission != 0) {
            // 何かしらの権限が取得できなかった場合
        } else {
            // 正常に取得できた場合
        }
    }

    @Composable
    fun PermissionRequestButton() {
        Button(onClick = {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                requestPermissionLauncher.launch(
                    arrayOf(
                        ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION,
                        WRITE_EXTERNAL_STORAGE, FOREGROUND_SERVICE
                    )
                )
            }
        }) {
            Text(text = "Permission Request")
        }
    }

```

##　参考

https://developer.android.com/training/permissions/requesting?hl=ja
https://qiita.com/irgaly/items/f98acbadb83c799cb666
Androidアプリで使用するアプリ固有データまとめ

# 目的
- Android アプリで使用するアプリ固有データの種類・保存についてまとめる。

# Androidアプリデータの保存方法による分類

- Androidでアプリが保存するデータ（以下「アプリデータ」）の種類には以下がある。
  
  (1) アプリ固有のファイル
     アプリ独自のファイルで、他のアプリから共有しないファイル。アプリ独自フォーマットのファイル等。

  (2) 共有ファイル
     メディアやドキュメントなど、他のアプリと共有可能なファイル。一般的なフォーマットで他アプリから利用可能な画像・音声・動画ファイル等。

  (3) 設定データ
     アプリ固有の設定データ。他アプリからアクセスできない領域へキーと値のペアで保存する。

  (4) データベース
     構造化したデータを非公開のデータベースへ保存する。

- アクセス手段・必要な許可・アプリのアンインストール時に削除されるかどうかはそれぞれ異なる。
- 詳細は Android developers [データ ストレージとファイル ストレージの概要][link0] 参照。

# アプリ固有ファイルの保存場所

- アプリ固有ファイルの保存場所は、内部・外部の2種類がある。
- 内部・外部の別は保存場所や他アプリからアクセスできるかできないかの違いを示し、 __デバイス内蔵で取り出せないメディアか・取り出せるメディア（SDカード）かの別を示すものではない__ 。GoogleのPixelシリーズ等、SDカードスロットが無いデバイスでも "外部ストレージ" は存在する。
- 内部・外部ともにファイルを保存する専用の場所とキャッシュファイルを保存する別の場所がある。

  (1) 内部ストレージディレクトリ

- 専用ディレクトリのパスは [`Context#getFilesDir()`](https://developer.android.com/reference/android/content/Context#getFilesDir()) で取得する。実機のPixel5a（API30）では `/data/user/0/（パッケージ名）/files` の `File` オブジェクトを返す。
- API30 の環境では Android Studio の Device File Explorer でも上記フォルダはアクセス不可。（暗号化されて見えない？）
- Android10（APIレベル29）以上では保存場所は暗号化される。

  (2) 外部ストレージディレクトリ

- デフォルトの専用ディレクトリのパスは [`Context#getExternalFilesDir(String type)`](https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)) で取得する。
- 保存するファイルが一般的なフォーマットで他アプリから利用可能な画像・音声・動画ファイル等の場合、上記 `String type` 引数でメディア種別毎のディレクトリへ保存することが推奨されている。使用可能な定数は `Environment.DIRECTORY_PICTURES` （画像）・ `Environment.DIRECTORY_MUSIC` （オーディオ）・ `Environment.DIRECTORY_MOVIES` （動画）等。他にも指定できるので [Environmentクラス](https://developer.android.com/reference/android/os/Environment?hl=ja) を参照。
- 実機のPixel5a（5G）（API30）で、引数 `String type` へ `Environment.DIRECTORY_PICTURES` を指定した場合の返値（Fileオブジェクト）は  `/storage/emulated/0/Android/data/（パッケージ名）/files/Pictures` となる。
- 保存するファイルが一般的なフォーマットでない場合、引数 `String type` には `null` を指定する。
- 実機のPixel5a(5G)（API30）で、引数 `String type` へ `null` を指定した場合の返値（Fileオブジェクト）は  `/storage/emulated/0/Android/data/（パッケージ名）/files` となる。
- 上記メソッドで取得可能な保存場所の権限は、Pixel5a（5G）では `drwxrws---` 、AVD上のPixel3（API30)では  `/storage/emulated/0/Android/data` までは見えるが、それ以下は `Permission denied` と表示され見えない。（Android Studio のDevice File Explorer で確認。）AVD上では他のアプリからアクセスできないかもしれない。

# その他
- 設定データ（Preference）については後で追記するかも。
- データベースについては調べたら追加するかも。

# 参考

- [データ ストレージとファイル ストレージの概要][link0]
- [アプリ固有のファイルにアクセスする ][link1]


# 変更履歴
- 2022/1/5 初版




[link0]:https://developer.android.com/training/data-storagehl=ja#additional-resources-videos
[link1]:https://developer.android.com/training/data-storage/app-specific?hl=ja#external
Multipass と cloud-init で Docker Desktop の代用

## はじめに
Docker Desktop の有償化がアナウンスされ、猶予期間満了日の 1月 31日も少しずつ近づいてきました。

https://www.docker.com/blog/updating-product-subscriptions/

そんな中で、Multipass と cloud-init を使用して Docker Desktop の代わりにしている記事が Canonical 社のブログにあったので試した記事となります。

## 実行環境

次の環境で実施しています。

|ツール|バージョン|
|:----|:-------|
|OS|MacOS Monterey 12.1|
|Multipass|1.8.1+mac|
|multipassd|1.8.1+mac|

## ざっくり使うものの概要

### Multipass

コマンド１つで Ubuntu の仮想マシンを構築・管理できるツール

https://multipass.run/

### cloud-init

あらかじめ定義を用意しておくことで、仮想マシンの初期設定を自動で実行できるツール

https://cloud-init.io/

## 手順

1. Multipass をあらかじめインストールしておきます
2. `multipass launch` コマンドでインスタンスを構築します。この時、`--cloud-init - ` オプションで後続の設定をします

    ```shell
    $ multipass launch --cloud-init - --disk 40G --mem 4G --cpus 4 --name docker-vm <<EOF
    groups:
    - docker
    snap:
      commands:
       - [install, docker]
    runcmd:
    - adduser ubuntu docker
    EOF
    ```
3. `multipass alias` コマンドで docker の仮想マシンへのエイリアスを作成します。自分の場合は後者を実施しました

    ```shell:cliがインストールされていない場合
    $ multipass alias docker-vm:docker
    ```

    ```shell:cliがインストールされている場合
    $ multipass alias docker-vm:docker mpdocker
    ```

    ```shell:実行後に表示されるガイド
    You'll need to add this to your shell configuration (.bashrc, .zshrc or so) for
    aliases to work without prefixing with `multipass`:
    
    PATH="$PATH:<ユーザーのホームディレクトリ>/Library/Application Support/multipass/bin"
    ```

    :::note warn
    docker cli が PC にインストールされている場合は、cli の競合が発生してしまうようなので、エイリアス名として名前を変更したものを明示的に設定します。
    :::

4. 実行後に表示されるガイドに記載のパスを `.bashrc` に設定します

    ```shell:.bashrc
    export PATH="$PATH:<ユーザーのホームディレクトリ>/Library/Application Support/multipass/bin"
    ```

5. `.bashrc` を再読み込みします

## 確認

コマンドを実行したら次の結果が表示されました。

```
$ mpdocker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete 
Digest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

```

## 感想

難しい設定も特になく、簡単に実施できたので、選択肢としてよさそうな感じです。

手順の中でインラインで記載している設定は、ファイルとして保存し、それを指定する形でもいけると思います。

## 参考
- [How-To: Docker on Windows and Mac with Multipass |  Ubuntu Blog](https://ubuntu.com/blog/replacing-docker-desktop-on-windows-and-mac-with-multipass)
lsコマンドで直下ディレクトリ内のファイルのフルパスを表示したいだけ

調べてもいい感じの記事がヒットしなかったのでメモ

```bash:bash
ls -dF $(pwd)/* | grep -v "/$"
```
<br>
以下のように直下のファイルのみフルパスが表示されている

```bash:bash
user@LAPF13C6TSA:~/main$ ls
Makefile  README.md  cloud  common  config.sh  device  doc  edge  misc

user@LAPF13C6TSA:~/main-system$ ls -dF $(pwd)/* | grep -v "/$"
/home/kmuser/main-system/Makefile
/home/kmuser/main-system/README.md
/home/kmuser/main-system/config.sh
```
「ディープラーニングの数学」９章補足　3値分類モデルの決定境界の表示

# はじめに
書籍「最短コースでわかるディープラーニングの数学」の著者です。
書籍のリンクは[こちら](https://www.amazon.co.jp/dp/4296102508)
読者から９章の多値分類モデルに関して、決定境界表示はできないのかとの質問があり、試しに実装した結果を公開します。

Notebook全体のリンクは、[こちら](https://github.com/makaishi2/math_dl_book_info/blob/master/notebooks/ch09-multi-classify-dec.ipynb)です。

# 考え方
決定境界とは、２つの確率値が等しくなる点の集まりです。つまり、　softmax関数の入力の時点で考えると、「*２つの１次関数の計算結果が等しい場所*」ということになります。
これを、NumPyの重み行列の言葉でいいかえると、重み行列を一列ずらした行列と元の行列の差をとり、その結果の行列と(1, x, y)の内積の結果がゼロになる場所です。
※　この考え方が成り立つのは正確にいうと例題で扱っている３値分類の場合に限定されます。４値以上の分類の場合は、決定境界の組み合わせがもっと複雑なので、計算もそれに対応して複雑になります。

これから紹介するコードはこの考えに基づいて実装されています。

# 実装コード紹介
これから紹介する実装コードは、書籍でいうとp.263で学習が終わり、三次元のグラフの描画までできた、その後に追加したものです。

## x, yの描画領域の計算
決定境界の直線を元の散布図と同時に表示しようとすると。決定境界の直線に引っ張られて、散布図の点と関係ない領域まで表示されてしまいます。そのことを防ぐために、x, yの描画領域をあらかじめ計算し、 axis関数で明示的に描画領域を指定するようにします。
※　この考え方は一般論としては間違っていないのですが、今回の場合は、一番最後の図を見ると、こういう問題は起きなかったみたいです。つまり、結果論としては、y_min, y_maxの計算と、描画のときのaxis関数呼び出しは不要でした。

```py
# x, yの描画領域計算
x_min = x_select[:,0].min()
x_max = x_select[:,0].max()
y_min = x_select[:,1].min()
y_max = x_select[:,1].max()
x_bound = np.array([x_min, x_max])
```


## 決定境界のyの値計算用関数

```py
# 決定境界用の１次関数定義
def d_bound(x, i, W):
    W1 = W[:,[2,0,1]]
    W2 = W - W1
    w = W2[:,i]
    v = -1/w[2]*(w[1]*x + w[0])
    return v
```

行列W2は上の説明に基づいて実装しています。
その後の計算は、

$ w_0 + w_1 x + w_2 y = 0$

をyについて解いた結果です。


## 決定境界のｙの値を計算
今、定義した関数を使って、決定境界のyの値を計算していきます。決定境界は全部で３つあります。

```py
# 決定境界のyの値を計算
y0_bound = d_bound(x_bound, 0, W)
y1_bound = d_bound(x_bound, 1, W)
y2_bound = d_bound(x_bound, 2, W)

# 結果確認
print(y0_bound)
print(y1_bound)
print(y2_bound)
```

```
[2.90696266 5.10075533]
[2.13912805 3.9149779 ]
[3.58457746 6.14720506]
```

## グラフ描画
これで準備は全部整いました。あとは、今計算で出したyの値を使ってplot関数で直線を書けばいいだけとなります。

```py3
# 散布図と決定境界の標示

#グラフサイズ指定
plt.figure(figsize=(8,8))

# 元データをグループ分け
x_t0 = x_select[y_org == 0]
x_t1 = x_select[y_org == 1]
x_t2 = x_select[y_org == 2]

# xとyの範囲を明示的に指定
plt.axis([x_min, x_max, y_min, y_max])

#  散布図の表示
plt.scatter(x_t0[:,0], x_t0[:,1], marker='x', c='k', s=50, label='0 (setosa)')
plt.scatter(x_t1[:,0], x_t1[:,1], marker='o', c='b', s=50, label='1 (versicolour)')
plt.scatter(x_t2[:,0], x_t2[:,1], marker='+', c='k', s=50, label='2 (virginica)')

# 決定境界の標示
plt.plot(x_bound, y0_bound, label='2_0')
plt.plot(x_bound, y1_bound, linestyle=':',label='0_1')
plt.plot(x_bound, y2_bound,linestyle='-.',label='1_2')

# 軸ラベル設定
plt.xlabel('sepal_length', fontsize=14)
plt.ylabel('petal_length', fontsize=14)
plt.xticks(size=14)
plt.yticks(size=14)
plt.legend(fontsize=14)
plt.show()
```

下のようなグラフが表示されれば成功です！

![スクリーンショット 2022-01-05 22.15.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206130/5dd02fc8-4a23-8b26-87be-9652f6aeab09.png)
Firebase StorageにおけるCORS

# はじめに
個人開発しているWebアプリでFirebase Storageを使用していた際に、
CORSでハマってしまったので、備忘録として残しておく。
Firebase Storageに保存した3Dモデルのファイルをfetchで取得してcanvasに描画する際にエラーが発生した。
![cors-policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1504894/58c6133a-11ab-7c8f-9048-a99d5451aed6.png)
エラーの原因はたぶん以下だと思われる。

> CORS による許可なしに他のオリジンから読み込んだ何らかのデータをキャンバスに描画すると、キャンバスは汚染されてしまいます。汚染されたキャンバスは安全とみなされなくなり、そのキャンバスから画像データを取得しようとすると、例外が発生するでしょう。

https://developer.mozilla.org/ja/docs/Web/HTML/CORS_enabled_image

## そもそもCORSとは
`CORS`は`Cross-Origin Resource Sharing`の略で、オリジン間リソース共有のこと。
同一生成元ポリシーによってブロックされる、オリジンを跨ぐリソースへのアクセスを許可するためのものだとかなんとか。
オリジンとは何なのか調べると、URLのうち、スキーム(プロトコル)、ホスト(ドメイン)、ポートの3つのことを指すらしい。
ドメインはたまに聞くがオリジンはあまり聞かないので違いが分かっていなかった...
例えば、自分がQiitaに書いた記事のURLは以下のようになっているが、
`https://qiita.com/web-novice/items/c77b30c7f7db780c745e`
**https://qiita.com** が オリジン、
**qiita.com** が ドメイン、ということ。

|  | オリジン | ドメイン(ホスト) |
|-----------|------------|:------------|
| 概要       | スキーム(プロトコル) + ホスト(ドメイン) + ポート | インターネット上の住所 |
| 具体例1 | https://qiita.com | qiita.com |
| 具体例2 | http://localhost:8080 | localhost |

# Firebase Storage に対してCORS設定を行う 

> ブラウザで直接データをダウンロードするには、Cloud Storage バケットに対してクロスオリジン アクセス（CORS）を構成する必要があります。この構成は gsutil コマンドライン ツールを使って行います。

https://firebase.google.com/docs/storage/web/download-files?hl=ja

と公式ドキュメントに書かれているため、まずは `gsutil` を
ここ ( https://cloud.google.com/storage/docs/gsutil_install?hl=ja ) からインストールする。

インストールできたら、CORS構成を記述したJSONファイルを作成する。

```json:cors.json
[
  {
    "origin": ["*"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]
```

そして、cors.jsonを作成したディレクトリで以下を実行すればCORS構成が設定される。

```terminal:ターミナル
$ gsutil cors set cors.json gs://************.appspot.com
Setting CORS on gs://************.appspot.com/...
```

Firebase StorageのURL (gs:// から始まるもの) は、Firebaseのコンソールから確認できる。
![storage-url.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1504894/352310df-184a-f8aa-f875-56551843bd90.png)

設定したCORS構成を確認するには、以下を実行する。

```terminal:ターミナル
$ gsutil cors get gs://************.appspot.com
[{"maxAgeSeconds": 3600, "method": ["GET"], "origin": ["*"]}]
```

設定したCORS構成を削除するには、空のCORS構成を含むJSONファイルを作成し、以下を実行する。

```json:cors.json
[]
```

```terminal:ターミナル
$ gsutil cors set cors.json gs://************.appspot.com
Setting CORS on gs://************.appspot.com/...
```

以上、Firebase StorageのCORSにハマった際の備忘録でした。
Fortranで、B - FizzBuzz Sum問題を解いてみる

https://qiita.com/official-events/5cb794f7cb9ac194ed70

**海道一の弓取り**

Advent Calendar 2022 9日目[^1]です。
**:santa:2022/12/25が来るのが待ち遠しいです。**
私の[Advent Calendar 2022 一覧](https://docs.google.com/spreadsheets/d/1HQvFjagQLRPjOYAjDVzWp9S4b8dKixxvvaz_TtbZWto/edit#gid=1723448955)。

[^1]: @kaizen_nagoya さんの「[「@e99h2121 アドベントカレンダーではありますまいか Advent Calendar 2020」の改訂版ではありますまいか Advent Calendar 2022 １日目　Most Breakthrough Generator](https://qiita.com/kaizen_nagoya/items/49ebebee3a0377f3b59b)」から着想を得て、模倣いたしました。 

# はじめに

[Elixir](https://elixir-lang.org/)を楽しんでいますか:bangbang::bangbang::bangbang:

[AtCoder](https://atcoder.jp/home)の[B - FizzBuzz Sum](https://atcoder.jp/contests/abc162/tasks/abc162_b)を[Fortran](https://fortran-lang.org/)で解いてみます。

[Fortran](https://fortran-lang.org/)に興味をもったきっかけは、[Nerves](https://www.nerves-project.org/)で、Fortranが使えるようになるらしいからです。

https://qiita.com/torifukukaiou/items/9494767af2816d1b607c


この記事では、[Elixir](https://elixir-lang.org/)のことは取り扱っていません。

# [B - FizzBuzz Sum](https://atcoder.jp/contests/abc162/tasks/abc162_b)

> AtCoderは、オンラインで参加できるプログラミングコンテスト(競技プログラミング)のサイトです。リアルタイムのコンテストで競い合ったり、約3000問のコンテストの過去問にいつでも挑戦することが出来ます。

[AtCoder](https://atcoder.jp/home)の[B - FizzBuzz Sum](https://atcoder.jp/contests/abc162/tasks/abc162_b)問題とは次のような問題です。

例: 入力が5の場合、FizzBuzzの列は、`1,2,Fizz,4,Buzz`となり、数字だけを足し算して、7が答え

問題文は[リンク先]((https://atcoder.jp/contests/abc162/tasks/abc162_b))をご参照ください。

プログラミングの基本である

- 順次
- 分岐
- 繰り返し

が含まれている良問だとおもっています。


```fortran:hello.f
      PROGRAM HELLO
      INTEGER(8) :: J
      READ (*, *) N
      I = 1
      J = 0
      DO WHILE (I .LE. N)
        IF ((MOD(I, 3) .NE. 0) .AND. (MOD(I, 5) .NE. 0)) THEN
          J = J + I
        ENDIF
        I = I + 1
      END DO
      PRINT '(i0)', J
      END PROGRAM HELLO
```

たったこれだけのことを書くのに、いろいろ詰まりました。
なにせ私は、[Fortran](https://fortran-lang.org/)初心者なので。

実行環境はDockerで用意しました。

```docker:Dockerfile
FROM alpine

WORKDIR /home/fortran
RUN set -x && \
    apk update && \
    apk add --no-cache gfortran musl-dev

CMD ["/bin/sh"]
```

```yml:docker-compose.yml
version: '3'
services:

  fortran:
    build: .
    container_name: fortran
    volumes:
      - .:/home/fortran
    tty: true
```

# Run

ローカルでの実行は以下の感じです。

```bash
$ docker-compose run --rm fortran gfortran hello.f -o hello 
$ docker-compose run --rm fortran ./hello
```

[AtCoder](https://atcoder.jp/home)はもちろんパスします。

https://atcoder.jp/contests/abc162/submissions/28338552

![スクリーンショット 2022-01-05 22.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/c3c89d43-f103-30e0-03b4-692b98e1bcc5.png)



# Wrapping up :lgtm::lgtm::lgtm::lgtm:

Enjoy [Fortran](https://fortran-lang.org/):bangbang::bangbang::bangbang:

2022年に流行る技術予想 ーー それは、[Fortran](https://fortran-lang.org/) on [Nerves](https://www.nerves-project.org/)です:rocket::rocket::rocket:
【失敗談】AmplifyのCI/CDにPlayWright(E2Eテストツール)は乗せられないっぽい

# はじめに結論

**おとなしくCypressを使っておけ！！！**

# 隙あらば自分語り

あけましておめでとうございます、やぐちはるおと申します。最近SIerを退職して起業しました。
起業先でしこしこアプリを作っていますが、タイトルの通り失敗したので内容を共有します。
この記事を見た出来杉君が解決策を提示してくれるのを待っています。それだけが私の望みです。

# 前置き

軽くAmplifyとPlayWrightについて触れておきます。

## AWS Amplifyとは

AWS Amplifyはアプリ開発のためのツールで、AWSの認証やAPI、ホスティングサービスを
一言管理できるサービスになっています。これを使うことで、AWSの各サービスを一つ一つ
細かく調べなくても(※1)、簡単に(※2、※3)アプリに機能を追加することができます。

※1 嘘です。結局調べる必要があります。
※2 嘘です。AWS慣れていないと難しいです。
※3 個人の感想であり、効果・効能を示すものではありません。

FirebaseやSupabaseを知っていれば、それのAWS版だと思ってください。
最近はローコード向けのツールも提供されているので、本当に簡単になっているのかもしれません。

### 参考

[AWS Amplify Studio – 最小限のプログラミングでFigmaからフルスタックのReactアプリを実現](https://aws.amazon.com/jp/blogs/news/aws-amplify-studio-figma-to-fullstack-react-app-with-minimal-programming/)
[【多分初心者向け】AWS Amplify Studio に触ってみて、とりあえず1からwebページを作ってみた](https://dev.classmethod.jp/articles/aws-amplify-studio-maybe-beginner/)

## PlayWrightとは

Microsoftが開発したE2Eテスト用のツールです。これを適切に設定することで(※4)
ページにアクセスしてログインするとか、マイページに遷移したときの画面が崩れてないかとかを
自動でテストすることができるようになります。

# 本題

AmplifyはGitHubなどのリポジトリと連携して、ソースコードが更新されたら
Webページに更新がかかるような設定が可能になっています。以下のような設定画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608452/55dd3b75-a723-1983-ccf6-2d68bdd68657.png)
ソースコードの変更を検知すると「プロビジョン → ビルド → デプロイ → 検証」というように
処理が流れていきますが、このビルドとデプロイの間に「テスト」を挟むことができます。
そしてPlayWrightを挟んだら見事処理が落ちました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608452/3bf3acb3-1223-deda-fb88-b37efdf1a7b9.png)

## 失敗 その1 PlayWright をインストールしようとしてタイムアウト

エラー文を見てみるとPlayWrightをインストールしている途中で落ちているっぽいです。
いろんな記事をググってみても時間がかかることに言及されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608452/0ed1437c-48b0-541c-cdf1-0fb2e6c07de2.png)
> [PlayWright を使ってE2Eテストを書いてみた](https://www.cresco.co.jp/blog/entry/14335/)
> Chromium, Firefox, WebKit のダウンロードが行われるため、結構時間かかります。

>[Playwrightも知らないで開発してる君たちへ](https://qiita.com/cc822jp/items/6f786a9ed104af1a382f)
>あと個人的にはnpm installがやたら長かったことも気になりました。。
>firefoxとsafariのインストールに時間がかかってました。

書いてあるとおりなんですが、つまるところいろんなブラウザでテストできるようにダウンロードが走って
そのダウンロードにやたらめったら時間がかかってAmplifyの30分という制限時間を過ぎてしまいます。

## 失敗 その2 インストールするブラウザを減らしたけどタイムアウト

ブラウザのダウンロードに時間がかかるならブラウザをダウンロードしなければいいじゃない
って古事記に書いてあるってアメリカの研究所が発表してるってNHKで放送してたって誰かが言ってたので
ブラウザをダウンロードしないでPlayWrightをインストールしてみます。

```
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 yarn add -D @playwright/test
```

こうするとPlayWrightのインストールは通りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608452/55258e5d-727d-bafb-72a9-135d990c282a.png)
しかしブラウザが無いと何もテストできないので、この上でchromiumだけインストールします。ややこしい。

```
yarn add -D playwright-chromium
```

結果は……
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608452/f2232413-5211-6fea-0a80-8d7645f67a0e.png)
ここまで言って30分が過ぎタイムアウトで落ちました。もう俺はほんと何やってもダメ。

# 結論

**おとなしくCypressを使っておけ！！！**

PlayWrightはブラウザのインストールにめっちゃ時間かかるからCI/CDに乗っけるもんじゃなさそう。
というかソースコード更新するたびデプロイまでに30分以上かかるCI/CDは存在してはいけない生き物だ。

そもそもドキュメントなどを見てると基本的にCypress使うことを想定してあるっぽいので
おとなしくCypressを使うのが良さそうです。そこんとこよろしく。

# あとがき

Amplify + Next.js 使った開発を日々つぶやいていますので良かったらtwiiterフォローしてくだちい。
https://twitter.com/haruo2177
市区町村コードの一覧をjson化するpythonスクリプトを書いた

# 日本全国の市区町村コードのjson探している方向け
[ここ](https://github.com/inchoxd/getAreaCode/blob/main/areaId.json)に市区町村コードをまとめたjsonがあります。

# 背景
日本全国の市区町村コードがjsonで配布されていないかなんてことを思ったが、存在していない。
そして、内閣府にいい感じのapiがあるけど登録がめんどくさい。(APIキーは即日発行された。)
国土交通省のAPIの中に市区町村コードが取得できるものがあったのでそれを使うことによってサクっと日本全国の市区町村コード一覧を取得することにした。

# 本題
コードはこちらの[Github](https://github.com/inchoxd/getAreaCode/blob/main/get_area_code.py)から。

## コードの仕組み
自動化の一環でこのコード書いたのに、都道府県名はコードは**手入力**しました。本末転倒です()
というのも、今回使用したAPIのレスポンスには都道府県名が含まれていないため、補完する必要がありました。なので仕方なく。。。。。。

``` python
    prefectures = ["北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", "福島県", "茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県", "新潟県", "富山県", "石川県", "福井県", "山梨県", "長野県", "岐阜県", "静岡県", "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県", "奈良県", "和歌山県", "鳥取県", "島根県", "岡山県", "広島県", "山口県", "徳島県", "香川県", "愛媛県", "高知県", "福岡県", "佐賀県", "長崎県", "熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県"]
```

このリストの中身は都道府県コード順に並んでいるのでfor文で回してjsonの中に突っ込んでいます。

データは以下のようなuriから取得します。

```
https://www.land.mlit.go.jp/webland/api/CitySearch?area={都道府県コード}
```
uriの都道府県コードの部分にindex番号+1した数字を入れるとその都道府県に属する地区町村の名前と市区町村コードを入手することができるようになります。

上記の処理をfor文で回すことによってそれっぽいjsonデータを生成します。

``` areaCode.json
{
    "data": [
        {
            "北海道": [
                {
                    "札幌市": {
                        "id": "011002"
                    }
                },
                {
                    "中央区": {
                        "id": "011011"
                    }
                },
                {
                    "北区": {
                        "id": "011029"
                    }
                },
                {
                    "東区": {
                        "id": "011037"
                    }
                },
                {
                    "白石区": {
                        "id": "011045"
                    }
                },
                {
                    "豊平区": {
                        "id": "011053"
                    }
                }...
```

### チェックディジット
@shiracamus さんご提案誠にありがとうございます！

``` Python
def add_check_digit(code):
    a, b, c, d, e = map(int, code)
    check_digit = 11-((6*a+5*b+4*c+3*d+2*e)%11)
    area_code = code+str(check_digit)[-1]

    return area_code

```

コードの頭の方にあるcheckDigit関数はその名の通り、コードが正しいかどうか判断するためのチェックディジットを計算しています。
使用しているAPIから値はチェックディジットなしの5桁が返ってきますが、チェックディジットが必要な場合もあると思い、今回生成するjsonでは末尾に付与しています。
ちなみにチェックディジットは以下の公式で簡単に求めることができます。]
5桁の都道府県コードを"abcde"とすると、
$$11-((6a+5b+4c+3d+2e) mod 11)$$
で求めることが可能です。
以上で求めたチェックディジット一桁を5桁の市区町村コードの末尾に付与することで今回生成される市区町村コードが完成します。
# おわり
意外にサクッと市区町村コードのjsonを生成するコードが書けましたね。
Android Layoutの種類

##レイアウト

- LinearLayout（線形レイアウト）
    - すべての子ビューを垂直又は水平の一方向に揃えるビューグループ
    - android:orientation属性によりレイアウトの方向を指定します。
        - 縦方向に表示：android:orientation="vartical"
        - 横方向に表示：android:orientation="horizontial"
    - 垂直方向のリストは、幅に関係なく、一つの行に1つの子ビューしかない。
    - 水平方向のリストは、1行分の高さしかない。


- RelativeLayout(相対レイアウト)
    - 子ビューを相対位置に表示するビューグループ
- ConstraintLayout
    - フラットなビュー改装を持つ大きくて複雑なレイアウトを作成可能
    - RelativeLayoutよりも柔軟性がありAndroid StudioのLayoutEditorで使用しやすくなっている。
- MotionLayout
    - アプリ内のモーションとウィジェットのアニメーションを管理できるレイアウト
    - ConstraintLayoutのサブクラス。

- TableLayout
    - 子ビューを表のように行と列で配置するレイアウト。

- GridLayout
    - 子ビューを長方形のグリッドに配置するレイアウト。

- FrameLayout
    - パーツを一つだけ配置して使用するレイアウト。配置したパーツは左上に表示される。
    - 　複数のパーツを配置した場合は、重なって表示される。

さまざまな画面のサイズに合わせて柔軟な表示にするには幅と高さにwrap_content,match_parentを使用します。
<TextView
wrap_content
 ビューのサイズをそのコンテンツに必要なサイズにする。
match_parent
　ビューのサイズを親ビューグループで許容される最大サイズにする。
Parquet とパーティショニングによる高速化

課題：TSV テーブルの処理速度が遅い

TSV ファイル形式のテーブルには実行速度が遅いという課題がある。Parquet とパーティショニングによる高速化で、カラムナーフォーマットを使うことで実行速度が向上する。更にパーティショニングを適用することで、特定のパーティションのみをスキャンし、必要なデータのみを処理することができる。

CTAS を使用した Parquet テーブルの作成

以下の CTAS クエリを使用することで、TSV テーブルを Parquet フォーマットとパーティショニングを適用したテーブルにコピーできる
```
CREATE table if not exists hoge.hoge_parquet
WITH(format='PARQUET',
    external_location='s3://path/to/external/', partitioned_by=ARRAY['product_category'])
as (select
        marketplace,
        customer_id,
        review_id,
        product_id,
        product_parent,
        product_title,
        star_rating,
        helpful_votes,
        total_votes,
        vine,
        verified_purchase,
        review_headline,
        review_body,
        cast(year(date(review_date)) as integer ) as year,
        date(review_date) as review_date,
        product_category
    from hoge.hoge_tsv)
```
備考：
キュー: 0.217 秒 実行時間: 5分4.028秒 スキャンしたデータ: 32.22 GB
1億6千万レコードのテーブルに対してathenaは遅め
VSCodeでC/C++プログラミングを始める（Windows + MSVC）

本家 Visual Studio Code サイト「[Configure VS Code for Microsoft C++](https://code.visualstudio.com/docs/cpp/config-msvc)」の補足情報です。

https://code.visualstudio.com/docs/cpp/config-msvc

Visual Studio Community Edition はインストールせず、Build Tools を使用します。

# 環境
OS : Windows11 21H2
エディター : Visual Studio Code 1.63.2
ビルドツール : Build Tools for Visual Studio 2022

# 環境構築
1. Visual Studio 拡張機能「C/C++ for Visual Studio Code」をインストール
1. Build Tools for Visual Studio 2022をダウンロードし「Microsoft Visual C ++（MSVC）コンパイラツールセット」をインストール
1. インストールを開始するとワークロードの選択画面が表示されるので「C++によるデスクトップ開発」を選択してインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/9c1fa3b6-f048-3086-50c8-d5f83fcbf9de.png)

# Hello World
1. コンパイラツールセットのインストールが完了したら Developer Command Prompt を検索して起動する  
clコマンドを実行するとコンパイラのバージョンを確認できる
1. Hello World 用のプロジェクトを作成するため `cd %HOMEPATH%` でディレクトリを移動する
1. [Configure VS Code for Microsoft C++](https://code.visualstudio.com/docs/cpp/config-msvc)の手順に従って、プロジェクトフォルダを作成しVSCodeを起動する
1. helloworld.cpp を新規作成する  
「C/C++ Extension Pack」のインストールをお勧めされるので、インストールする
1. [Terminal]-[Configure Default Build Task...]を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/bbafd24d-8c04-28db-e1f9-8af404ce6bfc.png)
1. 「C/C++:cl.exe アクティブなファイルのビルド」を選択すると tasks.json が開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/f7aca0f0-a4ff-6ec0-7d07-dab0c1f4aa68.png)
1. helloworld.cpp を選択し[Terminal]-[Run Build Task]を実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/4cdb12cc-547c-0602-cefa-48508d9314ad.png)

1. TERMINALウインドウの[+]をクリックして、新しいTERMINALウインドウを開きます
ビルドした helloworld.exeを実行します

# デバッグ
1. [Run]-[Add Configuration]から「C++ (Windows)」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240467/45175e76-80f8-cb39-60e0-e42bf4aa263c.png)

1. launch.json が作成され、アプリケーションがデバッグ実行されます。

1. launch.json の stopAtEntry を true に設定します
helloworld.cpp を選択し[F5]キーを押下すると、mainメソッドの最初で実行を中断します

# 構成
[View]-[Command Palette]から「C/C++: Edit Configurations (UI)」を実行します
c_cpp_properties.json が作成され、インクルードパスの設定などが可能になります

# まとめ
若干分りにくい表現がありましたが「[Configure VS Code for Microsoft C++](https://code.visualstudio.com/docs/cpp/config-msvc)」に従って進めれば問題ありませんでした。
Dynamics 365 Finance and Operations ~ 会計用語編 ~

D365 FO で登場する会計用語をリスト化していきたいと思います。随時更新します。間違いや補足あればご指摘ください。

|単語(英)  |単語(日)  |意味  |
|---|---|---|
|Main account  |主勘定  |資産、負債、資本、収益、費用を表す勘定科目のこと。財務のトランザクションや残高を記録する際のカテゴリ。  |
|Chart of accounts  |勘定科目表  |Main accountの一覧表。特定の法人に紐づかない。  |
|Financial dimension  |財務分析コード  |主勘定だけでは足らない、事業・部署・製品グループなどの細かいレベルでカテゴリするために使う。  |
|Ledger account  |元帳勘定  |Main account と Financial dimension を組み合わせた勘定科目（勘定構造）のこと。  |
|Ledger  |元帳  |勘定科目ごとに整理した帳簿記録（⇔時系列順の帳簿記録は「仕訳」）。勘定構造、会計カレンダー、通貨など、特定の法人で使用されるためにある  |
|General ledger  |一般会計  |Ledgerと同義だが、特定の法人の財務（借方・貸方）を記録すること。そのモジュール。  |
|Sub-ledger  |補助元帳  |特定の勘定についての明細を記録した帳簿（売掛金元帳、買掛金元帳など）  |
|Journal  |仕訳  |取引によって発生する一連のトランザクション（グループ）  |
|Voucher  |伝票  |1つのJournalの中にある各トランザクション（それぞれユニークにVoucher番号が振られる）  |
|aging  |エイジング  |"特定の期間"を表す。財務系レポートや在庫系レポートなどにおいて用いられる。  |
|Settlement  |決済  |売掛金（請求書）、買掛金（支払）の（オープンな）トランザクションを回収（消込・クローズ）すること。  |
|Ledger settlement  |元帳決済  |転記済みのトランザクションを確認するための機能  |
|全銀ネット  |全銀ネット  |金融機関相互間の内国為替取引をオンライン処理する「全銀システム」と、企業間の振込電文に様々なEDI情報（支払通知番号・請求書番号など）を添付可能とする「全銀EDIシステム（ZEDI）」を運営しているネットワーク  |
|FB  |ファームバンキング  |総合振込・給与振込など、複数の振込を一度に行う際に利用可能なデータ。電話回線経由（⇔インターネットバンキング）。各銀行共通の「全銀協」フォーマットで作られたデジタルデータ(テキストファイル)で、テキストファイルのため、システムからダウンロードしたデータをアップロードする際は、・「固定長（=textデータ）」・「CRLF有」といった文言のデータ形式を選択することになります。CSV（可変長）形式ではありません。  |ISO20022  |ISO20022  |金融機関、顧客、および金融取引の処理に関与する企業のクロスボーダー通信のための国際規格。  |
|ZEDI  |全銀EDIシステム  |支払企業から受取企業に総合振込を行うときに、支払通知番号・請求書番号など、さまざまなEDI情報（固定長形式から国際標準であるXML形式 （ISO20022 ※5 ）へ）の添付を可能とするシステム。ZEDIの導入によって、入金消込業務の効率化など、企業における資金決済事務の合理化が可能となります。ZEDIは2018年12月25日に稼動を開始。 |

・勘定科目系の用語の構造イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2375815/5e09ec84-c78b-66ce-c8ab-415cbbfbce1f.png)
[WPF] .net5でSystem.Windows.Formsを使いたい

# もくじ

https://tera1707.com/entry/2022/02/06/144447

# やりたいこと

.NET5/6で、`System.Windows.Forms`にあるライブラリを使いたい。

# やりかた

`.csproj`を直接いじって、下記のようにする。

- `<TargetFramework>net5.0</TargetFramework>`になっていたら、`<TargetFramework>net5.0-windows</TargetFramework>`にする。
- `<PropertyGroup>`の中に`<UseWindowsForms>true</UseWindowsForms>`を追加する。
- `Project Sdk`の値を`<Project Sdk="Microsoft.NET.Sdk">`にする(今回試したときは、初期値でそのようになってたのでいじってない→[参考](https://blog.yucchiy.com/2021/08/dotnet-windows-form/))

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/f70c854d-5a7a-9d48-298e-6a6fe3954b07.png)

※.net6使用時は、5.0のところを6.0にすること。

# 参考

https://blog.yucchiy.com/2021/08/dotnet-windows-form/
グラボ とは

## 勉強前イメージ

グラフィックボード...だけど、
どうついてて、何をしてるとかは正直良くわかってない
映像のやつって感じ

## 調査

### グラボ とは

グラフィックボード、通称グラボ とは
パソコンで映像をきれいに映し出す役割の部品になります。
3Dゲームや高画質の映像などの際に必要になります。

グラボはもともとPCに搭載されてる場合もあればされてない場合もあり、
搭載されてなかったら購入する必要があります。

### GPU とは

グラフィックボードを調べていると `GPU` というワードが出てきますが、
GPU(Graphics Processing Unit) とは画像処理に特化しているプロセッサになります。
PCの全般の演算処理はCPUですが、GPUは画像処理専門って感じになります。
GPUとグラボの関係性としては以下になります。

- GPU → 画像処理専用のチップ
- グラボ → GPUが入った金属板部品

### GPUの種類

GPUの種類には以下の2種類があります。

- 内蔵GPU

そのままの通り、CPUに内蔵されているGPUのことです。
以前はマザボに組み込まれることもありましたが、最近は少ないようです。
単体のGPUを使用するよりは性能は低いですが、設置するスペースが必要なかったり
内蔵されているのでGPUを買い必要はないです。

- 単体のGPU

CPUとは別にGPUが存在するものになります。
単体のGPU搭載のグラボは高価ですが、全体的に内蔵GPUより性能がよいです。
ただし、設置スペースが必要だったり消費電力が大きかったりします。
また、PC内部に搭載する `dGPU` と
外付けする `eGPU` があります。

## 勉強後イメージ

GPUっての初めて聞いたかも？？
GPUに外付けってあるのね。
しかもCPUに組み込まれることも多いのか・・・
全然何も知らなかったな

## 参考

- [GPU（グラボ）とは？【ざっくり解説】](https://pcfreebook.com/article/460217557.html)
- [グラフィックボード（グラボ）の確認方法とその見方とは](https://www.dospara.co.jp/5info/cts_str_parts_vga)
Aws Glue エラー備忘録

エラー：

S3のtsvファイルからテーブルを作成する際に、原因不明のエラーが発生し、作成したテーブルを読み込むことができなくなった解決方法は不明だが、コメントに-- MEMOを追加し、LOCATIONを小文字で表記した。これらの変更によりGlueのテーブルが正常にS3の場所を指すようになった

```
CREATE external table if not exists dsoaws.amazon_reviews_tsv(
marketplace string,
......
review_date string
) row format delimited fields terminated by '\t'
lines terminated by '\n'
-- MEMO
location 's3://buckets/tsv'
tblproperties('compressionType'='gzip','skip.header.line.count'='1');
```
LaravelでCollection型のデータを作ってバルクインサートする

それなりの量のデータをインサートする場合、バルクインサートをしたほうが早いです。

例えば下記のようなデータがある場合を考えます。

```php
$posts = new Collection();
for ( $i = 0; $i < 1000000; $i++ ) {
   /** @var Post $row */
   $post                  = new Post();
   $post->title   = 'Hello';
   $post->content = 'Good day';
}
```

下記のように都度`save()`を走らせるとかなり遅いです。

```php
foreach($posts as $post) {
  $post->save();
}
```

`DB::insert()` メソッドを使うとバルクインサート（一括インサート）となるため早いです。

```php
Post::insert($posts->toArray());
```

下記の記事を参考にするとInsert文を確認できます。

https://qiita.com/ucan-lab/items/753cb9d3e4ceeb245341


# 参考
https://www.geeksengine.com/database/data-manipulation/bulk-insert.php

https://laravel.com/docs/8.x/collections
インデントについてまとめてみた

###インデントとは
文章の頭を字下げするという事を指します。

実際の例を紹介していきます。



###コード紹介
インデント(字下げ)していないコード

```php:HTML
<div>
<h2>内服歴</h2>
<ul>
<li>ロキソニン60mg2錠(朝・夕)</li>
<li>ムコスタ100mg2錠(朝・夕)</li>
<ul>
</div>
```

インデント(字下げ)してあるコード


```php:HTML
<div>
  <h2>内服歴</h2>
  <ul>
    <li>ロキソニン60mg2錠(朝・夕)</li>
    <li>ムコスタ100mg2錠(朝・夕)</li>
  <ul>
</div>
```

このように
インデントがしてあるコードの方が一目でネスト（入れ子構造）が分かりやすい記述となります。
また閉じタグの関係も分かりやすく綺麗なコードと言えるでしょう。

ちなみに、中にはインデントをしなくても良いケースがあります。
その一例がこのリンク先を表示するコードです。

```php:HTML
<a form action=""></a>
```

インデントの方法は
①Tabキー
②Enterキー
このどちらかで行う事ができます。
Tab派かEnter派に分かれるそうで、『シリコンバレー』という海外ドラマでは
このTab派かEnter派かを口論されているシーンがユニークに表現されております。

###まとめ

インデントとは字下げの事を指す。
インデントされたコードは読みやすい。(チーム開発ではマナー)
方法は①Tabキー②Enterキーで行う。
[WPF] クラスライブラリのプロジェクトにWPFのウインドウを追加する

# もくじ

https://tera1707.com/entry/2022/02/06/144447

# やりたいこと

.net6のクラスライブラリで、WPFのウインドウを出すような機能(Model)を作ろうと思い、プロジェクトにWPFのウインドウをしようと思ったが、WPFアプリならソリューションエクスプローラーの中のプロジェクトを右クリックして [追加] > [ウインドウ(WPF)] とすると追加できるウインドウが出てこなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/03a9f81b-d57b-e71e-4521-842d009520bb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/3e6708ca-5b16-0df0-ec7e-78839b697f5e.png)
どうにかして、dllのプロジェクトにWPFのウインドウを追加したい。

# 前提

下記を使用。
`VisualStudio2022`
`.net5`

# やりかた

csprojのファイルを直接編集して、`<PropertyGroup>`の中に下記を追加した。

`<UseWPF>true</UseWPF>`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/def3b392-f6de-0e82-efa8-3d619d0b71b7.png)

これで、`ウインドウ(WPF)`が出てくるようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/f5fe65cf-8153-3f58-62b0-36eab816e8b7.png)
[docker] `docker compose` （docker コマンドのサブコマンドである compose）を全ユーザ向けにインストールする


# 概要

Linux で `docker-compose` ではなく `docker compose`（[Docker Compose overview | Docker Documentation](https://docs.docker.com/compose/)）を全ユーザ向けにインストールする記事です。

タイトル通りの内容で、方法も公式ドキュメントそのままです。
そのままやらずにつまづいた例のメモもあります。

# インストール方法

ユーザごとにインストールするなら `$HOME/.docker/cli-plugins` ディレクトリを作成し、その中に `docker-compose` を配置します。
全ユーザ向けにインストールするなら `/usr/local/lib/docker/cli-plugins` ディレクトリを作成し、その中に `docker-compose` を配置します。

```sh
mkdir -p ~/.docker/cli-plugins/
curl -SL https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
chmod +x ~/.docker/cli-plugins/docker-compose # 実行権限の付与

# 全ユーザ向け
mkdir -p /usr/local/lib/docker/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
chmod +x /usr/local/lib/docker/cli-plugins/docker-compose # 実行権限の付与
```

version で確認できます。

```sh
$ docker compose version
Docker Compose version v2.2.2

$ /usr/local/lib/docker/cli-plugins/docker-compose version
Docker Compose version v2.2.2
```

公式ドキュメントの Install the plugin manually 部分そのままです。

https://docs.docker.com/compose/install/linux/#install-the-plugin-manually

# つまづいた例

全ユーザ向けのインストールに指定したパスが
`/usr/local/lib/docker/cli-plugins/docker-compose` ではなく
`/usr/local/bin/docker-compose` でした。

```sh
$ /usr/local/bin/docker-compose version
Docker Compose version v2.2.2
$ docker-compose version
Docker Compose version v2.2.2
$ docker compose version
docker: 'compose' is not a docker command.
```

上のように PATH が通っているので `docker-compose` は成功します。
`docker compose` はプラグインディレクトリがないので失敗します。

`docker-compose` が成功するためインストール成功したと思い込んでいて、やや時間がつぶれました。
【Rails】redirect_backとは

redirect_backを使うと、``直前のページにリダイレクト``をしてくれる。


```使い方.
redirect_back fallback_location: 直前のページに戻れなかった際のパス

#使用例
redirect_back fallback_location: root_path
```

redirect_backを使う際は、直前のページに戻れなかった際のパスの記述が必要。
コンテナにgitの指定バージョンをインストールする

指定バージョンをインストールする為に make を行います。
その為、ビルドには時間がかかります。

```Dockerfile
ARG GIT_VERSION=2.34.0
ARG DIR_TMP=/tmp/

# libcurl4-gnutls-dev, libexpat1-dev, gettext, libz-dev, libssl-dev はgitのmake時に必要になります。
RUN apt-get install -y \
        curl \
        libcurl4-gnutls-dev \
        libexpat1-dev \
        gettext \
        libz-dev \
        libssl-dev

RUN cd ${DIR_TMP} \
    && curl -o ${DIR_TMP}git-v${GIT_VERSION}.tar.gz -OL https://github.com/git/git/archive/v${GIT_VERSION}.tar.gz \
    && tar -zxf git-v${GIT_VERSION}.tar.gz \
    && cd git-${GIT_VERSION} \
    && make prefix=/usr all \
    && make prefix=/usr install
```

:::note
GIT_VERSION はdocker-compose.ymlに記載することも可能です
:::
Rustの配列やらVecやら&strやらStringやらについての備忘録

* array
  - 全てのデータがスタックにある
  - 値の変更は可能だが固定長
* Vec
  - データそのものはヒープにある
  - スタックには先頭データへのポインタ、データ数、キャパシティがある
  - データを変更したり追加したりできる
  - キャパシティを超えるデータを追加しようとするとヒープの別の空いている場所に移動されることがある
* スライス
  - Vecやarrayなど、連続するデータを参照するための型
  - Vecとは違い、先頭データへのポインタとデータ数のみをスタックに持つ
  - 可変スライスと不変スライスがあり、可変スライスのみデータの変更が可能
* u8
  - 8bitのデータをもつ型
* char
  - 4バイトのUnicodeスカラー値を表現するデータを持つ型
* &str
  - u8の不変スライス
  - マルチバイト文字は複数のデータで一文字を表現する
* 文字列リテラル
  - ハードコードされた文字列
  - 型としては&strと同じ
* String
  - 中身はu8のVec
  - ただし、インデックスによるアクセスはできない
* Chars
  - char型が取り出されるイテレータ
コンテナにNode.jsの指定バージョンをインストールする

nvmを用いてインストールを行います。
nvmを使用すれば、簡単に複数のバージョンをインストールすることができます。

```Dockerfile
ARG NVM_VERSION=17.1.0

ENV NVM_DIR /root/.nvm

RUN apt-get install -y \
        curl

RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash \
    && . ${NVM_DIR}/nvm.sh \
    && nvm install ${NVM_VERSION} \
    && nvm alias default ${NVM_VERSION} \
    && nvm use default \
    && ln -s ${NVM_DIR}/versions/node/${NVM_VERSION}/bin/node /usr/bin/node \
    && ln -s ${NVM_DIR}/versions/node/${NVM_VERSION}/bin/npm /usr/bin/npm \
    && ln -s ${NVM_DIR}/versions/node/${NVM_VERSION}/bin/npx /usr/bin/npx
```

:::note
NVM_VERSION はdocker-compose.ymlに記載することも可能です
:::
Pythonのキューは3種類ある

# Pythonのキュー

Pythonにはキューを実現する方法が3種類あります。備忘のために整理します。

- list
- collections.deque
- queue.Queue

## list
listで実現する場合は、`append()`と`pop(0)`を利用します。

```python
def test_queue_list():
    q = []
    q.append(1)
    q.append(2)
    q.append(3)
    v = q.pop(0)
    assert v == 1
```

ただし、Pythonのlistは内部的にはCの配列で実装されているため、この方法はおそいです（ちょっと正確な表現ではないかも）。`append()`は $O(1)$ で実現できますが、`pop(0)`は $O(N)$ 。ドキュメンテーションの案内はこんな感じ。

https://docs.python.org/ja/3/tutorial/datastructures.html#using-lists-as-queues

> リストをキュー (queue) として使うことも可能です。
（中略）
追加（append）や取り出し（pop）をリストの末尾に対して行うと速いのですが、挿入（insert）や取り出し（pop）をリストの先頭に対して行うと遅くなってしまいます（他の要素をひとつずつずらす必要があるからです）。

## collections.deque

dequeはdouble-ended queueの略で、デックと読みます。`append()`と`popleft()`でキューを実現します。両端が終端のため、キューとしてもスタックとしても使えて便利、高速。ただし、スレッドセーフではありません。

```python
from collections import deque

def test_queue_deque():
    q = deque()
    q.append(1)
    q.append(2)
    q.append(3)
    v = q.popleft()
    assert v == 1
```

## queue.Queue

同期キュークラス。スレッドセーフな実装です。`put()`と`get()`を利用します。スレッドセーフを実現するためにややオーバーヘッドがあるため、dequeよりは遅い。

```python
import queue

def test_queue_Queue():
    q = queue.Queue()
    q.put(1)
    q.put(2)
    q.put(3)
    v = q.get()
    assert v == 1
```

# おわりに
listが汎用的で便利ですが、ちゃんとメリット・デメリットを把握して使い分けたいですね。にしても、インターフェイスは、`enqueue()`、`dequeue()`だと分かりやすいんだけどなぁ。
Streamlit Sharingでシークレット情報を扱う

StreamlitでAppを作成する際、DBのパスワードやAPI Keyなどのシークレット情報がアクセスに必要になることが多々あります。 　
今回、AzureのAPIキーをStreamlit Sharingで使いたかったので、StreamlitのSecrets管理機能を試してみました。

## Secretsの設定

Streamlit Sharingにてホストしたサイトの設定から`Settings`を選択し、`Secrets`の設定を行います。
シークレット情報はTOML形式で記述します。

![20220105133416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484840/c86206ad-138d-7873-b89b-15319e53f597.png)

![20220105133405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484840/8bdd1580-7770-992c-1e8b-3dbdfce2db6d.png)

なお、ローカル環境でシークレットを使用したい場合は、`.streamlit/secrets.toml`を作成し、同様の定義をすることで実現可能です。**この際、secrets.tomlはGitリポジトリにコミットしないよう注意してください**。  

## Appでの利用方法

アプリ側で設定したシークレット情報を読み込みたい時は以下のように記述します。

```python
import streamlit as st

KEY = st.secrets.AzureApiKey.key
ENDPOINT = st.secrets.AzureApiKey.endpoint

# 以下の書き方でも可
KEY = st.secrets["AzureApiKey"]["key"]
```

## 参考

https://docs.streamlit.io/streamlit-cloud/get-started/deploy-an-app/connect-to-data-sources/secrets-management
他ユーザーの作成したノートブックを実行する際の注意点

https://qiita.com/gudapys/items/24a04b01438ea7e01678#%E5%90%84%E5%90%8D%E7%A7%B0

![colab_screen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459843/9c938da8-2a02-4403-7638-6c74083cd518.jpeg)

# 他ユーザーのノートブックを開く。
colabで他ユーザーのノートブックを開く方法がいくつかあります。

１つ目の方法は、`IPYNBファイルを開く`ことです。
`メニューバー①`から、`ファイル`>`ノートブックをアップロード`より`.ipynbファイル`をアップロードします。

２つ目の方法は、`ノートブックの共有URLを開く`ことです。
`共有URL`とは例えば

>[https://colab.research.google.com/drive/1M7vXfYIeLed1u-awzd39u6PU-tCGNC0W](https://colab.research.google.com/drive/1M7vXfYIeLed1u-awzd39u6PU-tCGNC0W)

こういうURLのことです。

# 共有URLから開いたときの注意点

:::note warn
共有ノートブックは作者がいつでも更新することができるため、実行する際には注意が必要です。
:::

`前回`確認済みの共有ノートブックも、`今回`実行するときには（URLは同じであっても）中身は違ったものになっている可能性があります。なのでソースコードを確認して大丈夫であれば、自分のcolabにクローン（他ユーザのノートブックの複製）を作って、次回からは自分のcolabページからクローンを実行すると安心です。

# 実行する前に


:::note warn
このノートブックは Google が作成したものではありません。
:::
という警告が出たら内容をよく確認して、よければ`このまま実行`を押す。

:::note info
最初は、各セルを確認しながらコピペして、自分でノートブックを作ってみるのがいいと思います。
:::


# 他ユーザーのノートブックのコピーを保存する。
`メニューバー①`から`ファイル`>`ドライブにコピーを保存`を押します。
`ノートブックのタイトル のコピー`というタイトルでコピーが保存されます。
（3時間超・14本の動画）NestJS, Puppeteer, Docker, Supabase, YouTube Data APIが学べる開発講座を作りました

![001_yt-ads-scraping-online-seminar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/289248/71a0a315-a5f7-62b2-4383-53715c7df2cf.png)




# 解説動画で学習する技術（ツール）

YouTubeの再生リスト（14本の動画）で以下の技術を取り上げて解説しました。
（ライブコーディング含む）

- NestJS
- Puppeteer
- Docker, Docker Compose
- Prisma
- Supabase
- YouTube Data API


使用するプログラミング言語は「TypeScript」となります。

上記の中で「〇〇気になってるんだよなー」と思うのもがあれば、こちらの解説動画が参考になれば幸いです^^


詳細はブログにもまとめました^^
↓
https://tsuyopon.xyz/2022/01/05/yt-ads-scraping-online-seminar/
初めまして。

<h1>
自己紹介
</h1>
初めましてOっ茶nと申します。
「おっちゃん」若しくは「おっさん」と呼んでください。
普段は地方でSEをやらせてもらっているアラサーです。
これまで何もしてこなかったため何も身についていない
いわゆる「底辺」と呼ばれている存在と遜色がない立場です。

このまま30代を迎えるのはあまりにもやばいと思ったので、
まずは資格を取ろうと考えました。

本記事はそんな底辺無能なんちゃってSEが人並みの知識を持った
SEになるための奮闘記を綴っていきたいと思います。

どうぞよろしくお願いします。

<h1>
で、実際に何の資格取るの？
</h1>
まず初めに基本情報技術者を取りたいと思います。
次に応用情報技術者を取り、最終的には何かしらの
スペシャリストの資格を取れたらなと思います。

応援よろしく。

<h1>
学習予定
</h1>
本試験が令和4年4月17日（日）なので
そこから逆算してスケジュールを立てる必要があります。

1/5～1/31　テクノロジ系
2/1～2/28　マネジメント系・ストラテジ系
3/1～3/31　午前問題の苦手分野の克服＋午後問題
4/1～4/16　主に苦手分野で点を取れるように追い込む

目標は「最低でも毎日最低でも1時間は勉強の時間を作る」ことです。

応援よろしく。

<h1>
懸念点
</h1>
1.勉強の「やり方」がわからない
→何かいい方法があればご教示いただければと思います。
3カ月以上あると言っても時間が惜しいので、
単元ごとに本を読み終えたら過去問を実施し、
間違えた箇所はもう一度本を読みなおしもう一度解く・・・
と言うようなやり方で勉強していこうと思います。

2.苦手箇所が多すぎる（2022/01/05時点）
逆に自信をもって分かると言える箇所が少ない。
一番初めの離散数学でまず詰みだし、
システム設計？マネジメント？戦略？経営？法務？なんのこっちゃ
こういう奴でもとりあえずIT業界で飯食っていけるところが
IT業界の良いところでもあり悪いところでもある・・・と思う・・・

そんなこといつまでも机上で言ってたってしょうがないので
とりあえず不格好なりにやってみる

応援よろしく。

<h1>
最後に
</h1>
少しでも明るい30代を過ごしたいと思いこれから頑張りますので
どうか応援よろしくお願いします。
【Flutter】iOSビルドでエラー「module 'xxx' not found」の対処

# 発生するエラー

```bash:実行コマンド
$ flutter build ios --release
```

```:エラーログ
 [PROJECT_DIR]/ios/Runner/GeneratedPluginRegistrant.m:12:9: fatal error: module 'device_info_plus' not found
 @import device_info_plus;
 ~~~~~~~~^~~~~~~~~~~~~~~~~
 1 error generated.
```

# 原因

下記(1)(2)のバージョンが一致していない事が原因。

(1) [PROJECT_DIR]/ios/Podfile

```:Podfile
platform :ios, '13.0'
```

(2) Xcodeの「Runner->General->Deployment Info」

<img width="800" alt="xcode_ios_ver.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421601/0dbce179-2e42-1690-402d-1cf87f2f5fda.png">

# 対処

(2)の赤枠部分をクリックして、Podfileで指定したバージョンを設定する。
Go のジェネリクスを使って map と filter を実装してみた

C# の LINQ、JS の map, filter など、多くのプログラミング言語には一般的なコレクション操作が提供されています。
一方、Go にはそういった機能・ライブラリはありません。しかし、Go1.18 で導入されるジェネリクスを使えばこういった一般的なコレクション操作を実装できるのでは？

### やってみた
`myMap` と `myFilter` を実装してみました。

```go
package main

import "fmt"

func myMap[T1, T2 any](s []T1, f func(T1) T2) []T2 {
	var ret []T2
	for _, v := range s {
		ret = append(ret, f(v))
	}
	return ret
}

func myFilter[T any](s []T, f func(T) bool) []T {
	var ret []T
	for _, v := range s {
		if f(v) {
			ret = append(ret, v)
		}
	}
	return ret
}

type hoge struct {
	x int
	y int
}

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7}


	t := myFilter[int](s, func(x int) bool {
		return x%2 == 0
	})
	for _, v := range t {
		fmt.Println(v)
	}
	
	u := myMap[int, hoge](s, func(x int) hoge {
		return hoge{
			x: x,
			y: x * 2,
		}
	})
	for _, v := range u {
		fmt.Println(v)
	}
}

```

https://gotipplay.golang.org/p/LH34QBzMABb

Go 的にこれが美しいコードとされるのかは怪しいですが...僕が個人的に感じてた Go のコレクション操作の不足をこのようにして解決することができるかも？
【CSS】エンジニアなら知っているSassの世界

「Sass」皆さんはご存じでしょうか？
Web開発をされているエンジニアの方々はよくご存じかと思います。（私は最近知りました...）

結論から言うとこのSassですが、覚えることでcssのコーディング速度が格段に向上します！
仕事は捗り、残業は減り、余暇を楽しめ、人生が好転し始めるでしょう...
そしてなによりコーディングが楽しくなります！

これはもう導入せざるを得ませんね...早速ご紹介します。

#Sassとは
"Syntactically Awesome StyleSheet" = 「文法的に素晴らしいスタイルシート」
簡単に言うとCSSを拡張し、より見やすく、書きやすくしたものです。
Sassで記述したものをCSSにコンパイルし、使用します。

###SASS記法とSCSS記法
実はSassには上記2つの記法があり、ファイルの拡張子も"○○.sass", "○○.scss"と異なってきます。
詳細の説明は省きますが、現在では主にSCSS記法が使われており、本記事でもそちらで進めます。

#とりあえず触ってみる
ここでは環境構築の説明は省いて、下記のサイトを使用したいと思います。
（環境構築自体も非常に簡単なので、興味が湧きましたらぜひ試してみてください。）
SCSS記法で書いたコードをCSSにコンパイルすることができます。

https://www.sassmeister.com/

使用例は下記のような形です。
左側がSass、右側がコンパイルされたCSSです。
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482062/4e98516e-d76b-4584-4dc0-4a38efd446bb.jpeg)

##セレクタの階層化
まずはセレクタをネストする記述から始めます。
例えば以下のようなCSSを記述したいとします。

```css:sample.css
html { 
  background: #000;
}
html div {
  display: inline-block;
}
html div p {
  color: #fff;
}
```
SCSS記法では下記のようにネストして記述することができます。
直感的になり、記述量も減らすことができました。

```scss:sample.scss
html {
  background: #000;
  div {
    display: inline-block;
    p {
      color: #fff;
    }
  }
}
```
##変数の使用
Sassでは変数を使うこともできます。
例えば上記のコードを変数を用いて書き直すと下記のようになります。

```scss:sample.scss
$mainColor: #000;
$subColor: #fff;
html {
  background: $mainColor;
  div {
    display: inline-block;
    p {
      color: $subColor;
    }
  }
}
```
コンパイル後のCSSに変数が吐き出されることはありません。
非常にプログラミングチック（？）になり、保守性が高まります。

#まとめ
実はまだまだ紹介できていない機能（継承、条件分岐、関数、etc.）がたくさんあります。
ただ、ここまで紹介した内容でも十分効率アップを図れると思います。
触れてみて、興味が湧きましたらぜひ調べてみてください。

Sass最高！！
【実録】CISSPの試験申込から、エンドースメント等を経て、資格を取得するまでのタイムライン【過激 (嘘)】

# 勉強＋試験を正味60時間で済ませて、手続き系もかなりサクサク進めても2カ月半かかりますよってお話
CISSPの試験合格して手続きを進めている間、自分も「やきもき」したので、後進の方々のために簡単にタイムラインを残しておきます。Qiitaの別記事で「[【攻略法】情報処理安全確保支援士とCISAとCISSPに並列で挑戦して合格したので、勉強法と判断力のチューニングを中心にレポしてみる](https://qiita.com/mrpepper/items/4194402002765b8abd53)」を書いて、勉強については触れたので、ここでは本当にシンプルにタイムライン＋一行コメントだけを書いておきます。

# 2021/10/20 試験申込
・急ぐなら、勉強を始めたら申し込むくらいでちょうど良いくらい。割と候補日が限られている。
# 2021/11/30 試験受験
・試験直後の一枚紙では「暫定的に」合格、というのが強調されていてちょっとビビる。
# 2021/12/01 合格通知メール
・急ぎ、エンドーサー（証人）になっていただける方に依頼＆職務経験にサインしてくれる方にもアポイント。
# 2021/12/07 手続書類のOnline Submit
・昔は大変だったらしいエンドースメントだけど、今はオンラインで非常に楽。
# 2021/12/10 エンドーサーによるOnline Submit
・「エラー or Not」だけの判断なら、大体24時間以内にはレスポンスが返ってくる感じ。
# 2021/12/11 エンドースメント受理メール
・クリスマス～年末年始を挟んだが、24暦日で審査してくれた。ありがたい。
# 2022/1/4 審査完了メール
・実は、1/4にはメールに気づかなかった。気づいてからはサクサク。支払から受理までだけ、半日待った。
# 2022/1/5 初回AMF支払、同日受理
・めでたし！　なお、credlyにバッジが反映されるのはここからさらに24時間くらいかかると思う。

以上、こんな感じ。ご参考まで！　ちなみに、無職転生の2期は、CISSPの審査よりも、さらにやきもきしながら待つことになりそうです。なお、ちはやふる4期は諦めています。元々1～3期の原作準拠度がめちゃめちゃ高いおかげで、もはや原作読んでいても声が聞こえるし、シーンに合わせた劇伴まで聴こえるので、脳内アニメ化上等です。