OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerで、Rails 6系とMySQL8の開発環境の構築（OS : mac)

# Rails 6系とMySQL8 で開発環境を作る

docker-compose upでrails serverを起動できるようにすること  
ホストのファイルシステムとコンテナのファイルシステムを同期させること
勉強中の初学者です。誤りなどのご指摘いただければ嬉しいです！

## 流れ
1. 各種ファイルの作成
2. イメージのBuild
3. `rails new` でアプリ作成 -> `Gemfile`が上書きされる
4. 新しい`Gemfile`でイメージの再ビルド
5. `database.yml` の設定,DB生成
6. コンテナ起動＆サーバ起動
7. 確認


### 各種ファイル作成
下記を作成します。
`dockerfile`
`docker-compose.yml`
`Gemfile`
`Gemfile.lock`

```
$ mkdir docker_rail_mysql
$ cd docker_rail_mysql 
```

#### dockerfile作成

```dockerfile
FROM ruby:2.6

RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs

RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs  

RUN npm install --global yarn

WORKDIR /docker_rail_mysql

COPY Gemfile Gemfile.lock /docker_rail_mysql/
RUN bundle install
RUN rm -f tmp/pids/server.pid

CMD ["rails","s","-b","0.0.0.0"]
```

#### docker-compose.yml作成

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

volumes:
  db-data:

services:
  web:
    build: .
    ports:
      - '3000:3000'
    container_name: 'web'
    volumes:
      - '.:/docker_rail_mysql'
    tty: true
    stdin_open: true
    depends_on:
      - db

  db:
    image: mysql:8
    container_name: 'db_mysql'

    volumes:
      - 'db-data:/var/lib/mysql'
    environment:
      - 'MYSQL_ROOT_PASSWORD=password'
      - 'TZ=Asia/Tokyo'
    ports:
      - 3306:3306

```

#### Gemfile作成

```rb
source 'https://rubygems.org'
gem 'rails', '~>6'
```
#### Gemfile.lockを作成
Gemfile.lockの内容はありません。

#### コマンド　　

まずは、docker-composeで、imageとcontainerを作ります。
```
$ docker-compose run web bash
```

#### コンテナー上でのコマンド

`rails　new`コマンドで、Gemfileは上書きされます。

```
$ rails new . -force --database=mysql --webpacker  
$ exit
```
#### config/database.yml　変更

```yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("MYSQL_USERNAME", "root") %>
  password: <%= ENV.fetch("MYSQL_PASSWORD", "password") %>
  host: <%= ENV.fetch("MYSQL_HOST", "db") %>

development:
  <<: *default
  database: docker_development

test:
  <<: *default
  database: docker_test

production:
  <<: *default
  database: docker_homework_production
  username: root
  password: <%= ENV['DOCKER_DATABASE_PASSWORD'] %>
```
#### コマンド
貧弱なGemfileで作られた最初のimageは削除して、
新しいGemfileでもう1回buildしましょう。

```
$ docker-compose down
$ docker-compose up --build -d
$ docker-compose run web rails db:create
$ docker-compose up 
```


- host側のWEBブラウザで確認　http://localhost:3000/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2350392/a028561c-0f52-8f07-25b8-1846692a5e31.png)

host側の`docker-homework`フォルダの内容をgithubにpushしておくと、
下記のコマンドで、どこでも同じ環境構築ができるようになります。

```
$ git clone -b [ブランチ名] https://github.com/〜
$ cd docker 
$ docker-compose run web rails db:create 
$ docker-compose up
```
## 最後に
これで構築完了です。
かなり時間がかかりましたが、無数のエラーを出しながら、dockerにもっと慣れてきたと思います。
参考になったら嬉しいです。


### 参考にしたサイト
- https://qiita.com/nsy_13/items/9fbc929f173984c30b5d
- https://qiita.com/A-Kira/items/f401aea261693c395966
- https://qiita.com/ape/items/885e97ed1978f972d266
- https://zenn.dev/yuma_ito_bd/scraps/1adb89dfe0661c
MTCNNで顔検出したときに得られる情報

# はじめに
MTCNNを使って顔検出するときにどんな情報が得られるのか知りたくて、ラズパイでサンプルコードを実行してみました。
全ての情報は以下にあります。

https://github.com/ipazc/mtcnn

# 実行環境
|ライブラリ|バージョン  |
|---|---|
|python  |3.7.3|
|mtcnn  |0.1.1 |
|opencv-python |4.5.3.56 |
|tensorflow | 1.14.0 |


# やったこと
example.pyの内容を少しいじって、以下のコードを実行しました。

``` python3
import cv2
from mtcnn import MTCNN

filename = "ivan.jpg"
output = "drow_" + filename

detector = MTCNN()

image = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB)
result = detector.detect_faces(image)

# Result is an array with all the bounding boxes detected. We know that for 'ivan.jpg' there is only one.
bounding_box = result[0]['box']
keypoints = result[0]['keypoints']

cv2.rectangle(image,
              (bounding_box[0], bounding_box[1]),
              (bounding_box[0]+bounding_box[2], bounding_box[1] + bounding_box[3]),
              (0,155,255),
              2)

cv2.circle(image,(keypoints['left_eye']), 2, (0,155,255), 2)
cv2.circle(image,(keypoints['right_eye']), 2, (0,155,255), 2)
cv2.circle(image,(keypoints['nose']), 2, (0,155,255), 2)
cv2.circle(image,(keypoints['mouth_left']), 2, (0,155,255), 2)
cv2.circle(image,(keypoints['mouth_right']), 2, (0,155,255), 2)

cv2.imwrite(output, cv2.cvtColor(image, cv2.COLOR_RGB2BGR))

print(result)
```

# 実行結果
顔を検出した箇所にマーキングされました。画像のサイズは561×561のファイルです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1359985/365da2fa-421d-9b1d-4779-df028ccbf404.png" width=50%>


resultは以下のように出力されました。※見やすいように改行入れてます。
```
[{'box': [277, 93, 49, 62], 'confidence': 0.9999709725379944, 
'keypoints': {'left_eye': (291, 117), 'right_eye': (314, 115), 
'nose': (304, 130), 'mouth_left': (296, 143), 'mouth_right': (313, 142)}}, 
{'box': [307, 173, 37, 55], 'confidence': 0.8657229542732239, 
'keypoints': {'left_eye': (327, 194), 'right_eye': (339, 191), 
'nose': (341, 199), 'mouth_left': (334, 215), 'mouth_right': (342, 213)}}]
```

なんだか2か所の顔を検出しているように見えるので、result[1]の方を書き込むようにして実行してみました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1359985/6dbed07d-01c0-3c09-f5c0-6aa17fc20329.png" width=50%>

どうやらマイクを持った右手で顔検出しているようです。
あんまり精度が良くないのかもしれません。サンプルの画像なのできちんと検出するものを置いておけばいいのに。


# 気になった点
コード実行時、以下のエラーとワーニングが出てました。このままでも動いたのでスルーしましたが、いつか気が向いたら調べようと思います。

```
E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] 
HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory
WARNING:tensorflow:From /home/pi/.local/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: 
calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
```
【Unity】Editor拡張でメニューからHLSLを作成できるようにした

# ソースコード
https://github.com/ayaha401/CreatHLSLScript

<img src = "https://user-images.githubusercontent.com/75297336/159118761-33d56f63-aaf3-440e-93a5-017e58806753.png">

<img src = "https://user-images.githubusercontent.com/75297336/159118836-b3817761-e212-4443-ad9b-33b1f5a54a61.png"><br>
こんな感じで作れるようになります。

# 作ったわけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/41ceb0d6-ce9a-d498-3204-0d365fc5d369.png)
HLSLをUnityで作るには右クリックして**Show in Explorer**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/b5cfe3a7-f443-8299-82f4-64cda001ed2f.png)
テキストを作成して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/0f06d10b-965b-00c2-b021-aa6ac0332ffb.png)
名前を変更して拡張子をhlslに書き換えれば完成！
しかしこの一連の動作が面倒くさいのでEditor拡張して簡単に作れるようにしようというわけです。

# 解説

```C#
[MenuItem("Assets/Create/Shader/HLSLScript")]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/ccd53db9-e334-f4bb-9bc1-df4ddce0efcf.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/7edd9e9b-3fa8-47af-db4b-2927bbeeca8a.png)
これでUnityの上のメニューバーのAssetsボタンやProjectウィンドウで右クリックしたときにメニューを追加します。

```C#
path = AssetDatabase.GetAssetPath(Selection.activeInstanceID);
```
これで右クリックした場所のパスを取得します。

```C#
path = EditorUtility.SaveFilePanelInProject("CreatHLSLScript", "NewShader", "hlsl", "", path);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/17c585ae-67a9-be25-e3e2-07cbc5a28f2d.png)
`EditorUtility.SaveFilePanelInProject()`を使うことでファイルを生成するウィンドウを出すことができます。
参考 : https://docs.unity3d.com/ja/current/ScriptReference/EditorUtility.SaveFilePanelInProject.html

```C#
File.WriteAllText(path,"");
```
`File.WriteAllText()`で新しいファイルを作成します。
参考 : https://docs.microsoft.com/ja-jp/dotnet/api/system.io.file.writealltext?view=net-6.0

```C#
AssetDatabase.Refresh();
```
最後に`AssetDatabase.Refresh()`で更新を行います。
ArduinoIDEでランダムな小数値を生成

0~1までのランダム小数を生成します。

```
float random(0,100) / 100.00
```

>0.59

**.00　と欲しい桁数を指定して割るのがポイントです。**
🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
flutter build iosの際に'Flutter/Flutter.h' file not foundやfailed to emit precompiled headerが出まくって、解決しない

# flutter build iosの際に'Flutter/Flutter.h' file not foundが出まくって、解決しない

https://www.yuukinishiyama.com/2021/01/16/flutter-fatal-error-flutter-flutter-h-file-not-found%E3%81%8C%E9%80%A3%E7%99%BA%E3%81%99%E3%82%8B/

https://seikousyahenomichi.com/flutter-h-file-not-found/

https://qiita.com/masashi_goto/items/aec610ece2a5a04075d4

https://qiita.com/TaisoItsukage/items/7b43d4156f2d546bcd6f

とか、色々試したけど、全部ダメでした...
# 結論

https://zenn.dev/nrikiji/articles/f54c428f881997
で、Google-Servise.plistを開発用と本番用に分けた時のスクリプトが原因でした

Runner.xcworkspaceをXcodeで開いて、
Targets -> Build phases
### ダメな方のスクリプト  
```Runscript.js
if [ "${CONFIGURATION}" == "Debug" ]; then
cp -r "${PROJECT_DIR}/Runner/GoogleService-Info-dev.plist" "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/GoogleService-Info.plist"
elif [ "${CONFIGURATION}" == "Release" ]; then
cp -r "${PROJECT_DIR}/Runner/GoogleService-Info-prod.plist" "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/GoogleService-Info.plist"
fi

```
### いい方のスクリプト
```Runscript.js
if [ "${CONFIGURATION}" == "Debug" ]; then
cp -r "${PROJECT_DIR}/Runner/GoogleService-Info-dev.plist" "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/GoogleService-Info.plist"
elif [ "${CONFIGURATION}" == "Release" ]; then
cp -r "${PROJECT_DIR}/Runner/GoogleService-Info-prod.plist" "$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app/GoogleService-Info.plist"
fi
/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build

```  
解決！！！！！！！！！！！！！！！！！！！！！
VisualStudio 2022 community で CMake プロジェクトをビルドする


m1 mac でつくった CMakeLists.txt を VisualStudio2022でビルドする方法のメモ

## 手順
1. VisualStudio2022 を起動する
2. ファイル -> 開く -> CMake
##

これだけ。

buildフォルダに、*.sln などができているのでこっちを開くといつものVisualStudioのソリューションファイルとプロジェクトファイルが使える。
外部ファイル関連（出力、読込、追記）

●外部ファイルへの書き込み
`file_put_contents('パス/出力ファイル名', '出力内容')`を用いる。
例)
```
<?php
$success = file_put_contents('data/output.txt', 'ファイルを出力しました');
if ($success !== false) {
    echo 'ファイルの出力が完了しました';
} else {
    echo 'ファイルの出力に失敗しました';
}
```
※dataディレクトリにoutput.txtを作成
※output.txtには、ファイルを出力しました、と記入
※if文で完了or失敗をチェック

●外部ファイルの読込、追記
・外部ファイルの読込
`file_get_contents('外部ファイルへのパス')`を用いる。
・既に存在している外部ファイルへの追記
`file_put_contents('パス/追記ファイル名', '出力内容')`を用いる。
例)
```
<?php
// ファイルの読込
$output = file_get_contents('data/output.txt');
// ファイルへの追記
$output = $output . "<br>追記です";
file_put_contents('data/output.txt', $output);
```
PHP 配列の要素をランダムに並び替える関数 shuffle

# 概要

- 既存の配列を渡すと配列内部の要素をランダムに並び替えてくれる関数`shuffle()`についてまとめる。

# 紹介

- 下記の様に実行する。

    ```php
    $array = ['りんご', 'いちご', 'バナナ'];
    shuffle($array);
    ```

- 下記の様に配列の内部要素をランダムに並び替える。

    ```php
    var_dump($array);
    // 筆者が実行したときは['バナナ', 'いちご', 'りんご']に並び替えされた
    ```

- 当該関数に引数として渡す配列そのものの要素を入れ替える（難しい言い方をすると「参照渡し」でもともとの配列に影響を与える）ので注意する。
- 成功したらtrue、失敗したらfalseを返す。

# 参考文献

- [https://www.php.net/manual/ja/function.shuffle.php](https://www.php.net/manual/ja/function.shuffle.php)
UiPath ブラウザIE11からEdge変更のノウハウ_1

こんにちは、HANAKOです！東京でRPAのお仕事しています。
今回UiPath案件でブラウザ変更を行いました。
IE11のサポート終了まで残り3ヶ月を切りました〜！
ブラウザIE11からEdgeheへの手作業で変更したノウハウを共有したいと思います。
参考になれば幸いです～

UiPath公式のアナウンスはこちら↓
https://www.uipath.com/ja/resources/knowledge-base/internet-explorer-workflow-migration
今回の案件はマイグレーションツールを使っていません。手作業で行った場合に気を付けたことです。

(20220427 追記)
この記事は3部構成です。
ノウハウ_2
https://qiita.com/rpa_hanako/items/fd31f2195bc599fc7409
ノウハウ_3
https://qiita.com/rpa_hanako/items/0df4ab88b9cbd7ca335e


■目次
1.事前設定
2.ダウンロード
3.セレクター

※注意事項
今回シナリオ作成に当たって、UiPathなどのデモサイトで構成を考えたのですが、
HTML構成がシンプルだったので企業サイトで解説しております。


# 事前設定
Edge対応のために事前設定がありますので、簡単に解説していきます。
主にやるべきことは下記2つ！
・拡張機能をブラウザにインストール
・ブラウザを「Edge」に設定
・UiAutomation21.10.4以降が必要

## 拡張機能をブラウザにインストール
EdgeブラウザにUiPath拡張ツールをインストールします。
UiPath Studio から[ホーム]→[ツール]→[Edge]を選択してください。
![20220227_1025_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35333/3bc661f8-9bbb-ec87-afa5-647b63ceb3aa.png)

下記のようにUiPathアイコンが青く表示されていればOK
![20220227_1023 - コピー (6).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35333/29462299-2daf-6b86-401f-7ecfd3140e98.png)

## ブラウザを「Edge」に設定
ブラウザーを開くアクティビティで[ブラウザーの種類]を[Edge]を選択
![Edge1 (2).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35333/f836e82b-e7ee-201f-4cd5-7fd63254ec0a.png)

## UiAutomation21.10.4以降が必要

記載する

では早速、解説していきます！！

# ダウンロード処理
ブラウザ変更に伴って挙動の大きな変更点であるダウンロード処理についてです。
そもそもですが、ブラウザ側のダウンロードの挙動がIE11とEdgeで下記のように変わります。（ファイルはPDFになります。）

### 【IE11】表示されているタブと【同一タブ】上で表示される
ダウンロードポップアップは画面下記に通知バーとして表示されます。
![ブラウザIE11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35333/997fc645-6940-1f8a-5a4d-4312e94d5209.png)


### 【Edge】表示されているタブと【別タブ】上でPDFファイルが表示される
ダウンロードポップアップは画面右上に出すこともできます。（ブラウザ設定で変更できます。）
![Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35333/b6d17c9c-0eb8-acdf-b209-fe37dace70bf.png)

### UiAutomation21.10.4以降が必要
画面左側にプロジェクトパネルの「UiAutomation」のバージョンを確認しておきましょう。
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35333/41e0dcf8-a177-0733-73e3-0ce0a996dbcc.png)

「UiAutomation21.10.4」以前のバージョンであれば下記手順でバージョンアップができます。
「パッケージを管理」→検索で「UiAutomation」と検索し、「UiAutomation.Activities」を選択。
バージョンを選択しインストールボタン押下、保存でバージョンアップできます。
![tempsnip1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35333/48ad79ce-6fa6-0282-7395-5396c9ea06a6.png)
へ

ここは基本動作ですので開発する前に理解しておいたほうがいいです～

長くなったので今回はここまで。
ImageSharpのバージョンアップでマークシートシステム Mark2のマーク認識が高速化

# マークシートシステム Mark2の近況

Blazor WebAssemblyを利用して開発している[マークシートシステム Mark2](https://mark2.defrag.works/)はまわりの人に使ってもらう機会も増えてきて、先日は[地方自治体向けにマークシートとWebアンケートに対応したハイブリッドアンケートシステム](https://prtimes.jp/main/html/rd/p/000000001.000095976.html)のプレスリリースを配信しました。利用してもらうといろいろなフィードバックをいただき、やはり一番多いリクエストは処理速度を速くできないかというもので、引き続き改善を進めています。

処理速度のボトルネックになっているのは主に画像処理で、Blazor WebAssemblyのAOTコンパイルによって高速化されているのですが、やはりデスクトップアプリと比較すると動作が遅く感じる部分もあるのかもしれません。

# ImageSharpのバージョンアップ

2022年2月7日にImageSharp 2.0.0がリリースされ、パフォーマンスの向上に関する記載がありました。

https://sixlabors.com/posts/announcing-imagesharp-200/

いくつかの破壊的な変更があったためにMark2のプログラムを修正しているうちに、ImageSharp 2.1.0がリリースされていました。せっかくなのでこれまで利用していたImageSharp 1.0.4と2.1.0で処理速度にどのくらいの変化があったのか計測してみることにしました。

# マークシートのマーク認識の処理速度を比較

800枚のマークシートをマーク認識した処理時間は以下のようになりました。

| ImageSharp | 処理時間（秒）  |
|-----------:|------------:|
| 1.0.4      | 276.448     |
| 2.1.0      | 210.254     |

ImageSharp 1.0.4から2.1.0にバージョンアップすることで約1.3倍の高速化ができました。ここまで速くなると思っていなかったので、期待以上でした。
自宅のNASにDocker環境を用意してスマートホーム化 #1

スマートホーム化したいけどラズパイ導入とかちょっと面倒。。
ということで自宅にあったNASにDocker環境を構築して、NodeREDコンテナを作成しました。

# 必要なもの
* QNAPのNAS (自宅のはエントリモデルのTS-230)
* QTS環境 (管理者権限, バージョンはちょいちょい変わるので出来なかったらスミマセン)

# 手順
1. [QTS環境にログイン](#qts環境にログイン)
1. [ContainerStationアプリをインストール](#containerstationアプリをインストール)
1. [NodeREDイメージをインストール](#noderedイメージをインストール)
1. [NodeREDを開く](#noderedを開く)

## QTS環境にログイン
私の画面はこんな感じです。
![qts_main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478155/c0c346e3-82ee-1c51-e5b2-91817bd48b87.png)

## ContainerStationアプリをインストール
なければAppCenterからインストールします
![containerstation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478155/e94b4919-c865-3fe6-3fc4-27088e7b9be0.png)

インストールするとNASのルートに"Container"フォルダが作成されます ↓
![filestation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478155/97f1bfaa-c1cf-48a9-ce8e-f18a633743e5.png)

## NodeREDイメージをインストール
"Create"タブから"nodered"を検索してイメージのインストールを行います。
バージョンはlatestでよいでしょう。(再現性薄くてスミマセン)
その他設定も一旦デフォルトで問題ないです。
![containerstation_create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478155/0aab7d05-e8bb-2cb2-2bf7-b675068c0ee7.png)

インストールすると、Overviewに追加したイメージのコンテナが起動します。(図にはmysqlがいますが気にせず。。)
![containerstation_overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478155/372859c5-00f6-e607-de08-fc8224b17696.png)

## NodeREDを開く
ブラウザで[NASのIP]:[ポート番号1880]でアクセスすると開けます。
![nodered.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478155/5ce9e20f-3fc9-b5ad-8291-8994f1a213e0.png)

これでお手軽ノンコードプログラミング！！

→ NEXT: [SwitchBotを実行](https://qiita.com/tosix13/items/b8a2f73617a0d380fc84)
フォームのラジオボタンをカスタマイズ

ラジオボタンのカスタマイズの仕方をいつも忘れてしまうので、自分用にメモ。

```html:HTML
<label>
	<input type="radio" name="性別" value="男性" class="bl_gender">
	<span>男性</span>
</label>
```
男性、女性で選択できるラジをボタンを想定。

```css:CSS
.bl_gender {
  display: none; /* 初期のラジオボタンを非表示 */
}
.bl_gender + span { /* .bl_genderの次のspan */
  position: relative;
  padding-left: 40px;
}
.bl_gender + span::before { /* ラジオボタンを作成（外側） */
  content: "";
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid #969696;
  background: #fff;
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
}
.bl_gender + span::after { /* ラジオボタンを作成（内側） */
  content: "";
  width: 12px;
  height: 12px;
  background: #006688;
  border-radius: 50%;
  position: absolute;
  top: 50%;
  left: 6px;
  transform: translateY(-50%);
  opacity: 0; /* 基本は非表示 */
}
.bl_gender:checked + span::after { /* 選択されたボタンだけ表示 */
  opacity: 1;
}
```
↓ こんな感じになります。
![ラジオボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552308/8f0ba05d-93c7-87ce-9f5b-524da317af3c.png)

bl_genderというクラス名をつけてますが、``input[type="radio"]``でもいけるとおもいます、たぶん！
AtCoder ABC244 D - Swap Hats を3通りの方法で解く : 転置数, 乱択

https://atcoder.jp/contests/abc244/tasks/abc244_d
以下の３つの方法で解きます
- 全列挙で考察
- 転置数
- 乱択

# 1:全列挙で考察
`R,G,B`の並び替えは6つしかないです。以下の解説のように図を書いて考えます。
https://atcoder.jp/contests/abc244/editorial/3594
コードは割愛します。(解説に書いてある通りです。

長さがNだとするとハッシュをO(N)でとれるとして
- 時間計算量はO(N)
- 空間計算量はO(N!)と極めて大きな数になります


# 2:転置数
これも上記の解説に書いてある通りです。ある`1,2,3,4,...,n`という数列が昇順で並んでいた時、異なるi, jを選んでswapするとその転置数は奇数になります。もう一度、適当なswapをすると転置数は偶数になります。
今回の場合、操作の回数が十分なので、偶数回の移動で両者の転置数の偶奇が一致するものに絶対遷移できます。なので、偶奇を判定します。

転置数の実装は典型通りにBITで頑張ります。
- 時間計算量: O(NlogN)
- 空間計算量: O(N)

https://atcoder.jp/contests/abc244/submissions/30366609

<details><summary>実装(Python)</summary><div>


```python
# https://ikatakos.com/pot/programming_algorithm/data_structure/binary_indexed_tree
class Bit:
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)

    def sum(self, i):
        s = 0
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s

    def add(self, i, x):
        while i <= self.size:
            self.tree[i] += x
            i += i & -i
############################################
# 転置数を求める
# 1,2,3...のリスト。0はダメ版
def transposes(s):
    n = len(s)
    bit = Bit(n)
    ans = 0
    for i in range(n):
        assert s[i] != 0
        ans += i - bit.sum(s[i])
        bit.add(s[i], 1)
    return ans

a = input().replace("R", "1").replace("G", "2").replace("B", "3").split()
b = input().replace("R", "1").replace("G", "2").replace("B", "3").split()
a = list(map(int, a))
b = list(map(int, b))
if transposes(a)%2 == transposes(b)%2: print("Yes")
else: print("No")
```

</div></details>

# 3: 乱択
実はsample-1を読むと、`場面: 偶数回のSWAPの回数が残っていても、今、正解と同じ順番になっていればYesになる`ことが分かります。
Nが3と小さいので以下のように考えます。
- ある瞬間、あと偶数回swapできるなら2回適当にswapする
- もし、`場面`であればYes。Noならもう一度swapを繰り返す
- 十分な数これを繰り返してもダメならNo

ここで、あり得る並び方は1の通り高々6通りのため、十分な数(例えば1000回など)swapすれば、まず、十分に判定できそうです。

このように、適当な試行回数で、全パターンを（ほぼ間違いなく=100%ではない）列挙しきれる場合、乱択は条件の考慮漏れなどの心配がなく、有効な手段です。

今回は愚直に比較をしているので時間計算量は試行回数をkとしてO(kN)ですが、工夫すれば(例えば、異なる数字の数を持っておけば)、O(k)になります。

https://atcoder.jp/contests/abc244/submissions/30307084

<details><summary>実装(Python)</summary><div>

```python
from random import sample
import sys
s = input().split()
t = input().split()
for i in range(100000):
    if s == t and i%2==0:
        print("Yes")
        sys.exit(0)
    i, j = sample([0,1,2], 2)
    s[i], s[j] = s[j], s[i] # 適当な2つをswap
print("No")
```

</div></details>
CloudFormation「1 validation error detected: Value '[AWS::EC2::VPC...]' at 'typeNameList' failed to satisfy constraint」

# はじめに
他人が書いたCloudFormationのyamlコードの動作確認をしたところ、以下のエラーが出力しました。
>1 validation error detected: Value '[AWS::EC2::VPC, AWS::EC2::RouteTable,AWS::EC2:Route, ...＜略＞]' at 'typeNameList' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 204, Member must have length greater than or equal to 10, Member must satisfy regular expression pattern: [A-Za-z0-9]{2,64}::[A-Za-z0-9]{2,64}::[A-Za-z0-9]{2,64}(::MODULE){0,1}]

これまた些細なことなのですが、10分以上解決に時間がかかりました。。。

# 原因
`AWS::EC2:Route`になっていた。  
正しくは`AWS::EC2::Route`。

# コメント
最近こんなのばかり。。。  
CloudFormationは便利だけれど、エラーメッセージが雑？で辛いときがあります。  
`Value '[AWS::EC2::VPC, AWS::EC2::RouteTable,AWS::EC2:Route, ...<略>]'`のエラーメッセージ、`Value '[AWS::EC2:Route]`のように問題の箇所だけ抜き出して表示できないのかなあ。サービスを大量に定義しているコードだったため、問題の箇所が埋もれてしまってどれも正しいように見えてました。
zsh: command not found: npmが出た時の対処法

ある日、npmコマンドを打つと`zsh: command not found: npm`とエラーが出ました。

```
$ npm -v
zsh: command not found: npm
```

npmコマンドが一切使えなくなってしまいました。

この記事では解決までに行った方法を共有します。
結論を先に話すと、nodeをインストールし直すことで解決しました。

環境はmacOS Montereyです。

## nodebrewがインストール済みか確認する
`nodebrew`と打って確認します。
色々と表示されれば問題ないです。一番上の行にバージョンの記載が出ます。
```
$ nodebrew
nodebrew 1.2.0

Usage:
~~~
```

### nodebrewをインストールする
もしnodebrewが入っていなけばHomebrewを使用してインストールします。
```
$ brew install nodebrew
```
Homebrewが入っていなれば下記コマンドでHomebrewのインストールができます。
```
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```
上記のコマンドは公式からのコピーですが、不安な方は直接公式からコマンドをコピーしてきてください。
https://brew.sh/index_ja

## nodeをインストールして使用するバージョンを指定する
nodeをインストールします。

```
$ nodebrew install-binary stable

// 補足
stable 最新の安定版
latest 最新版
vXX.XX.X バージョン直接指定
```

`nodebrew install`でもインストールは可能ですが、`install-binary`のほうがインストール時間が短いです。

nodeがインストールがされたかを`nodebrew ls`で確認します。

```
$ nodebrew ls
v16.14.2

current: none
```

currentに表示されるのが現在使用中のバージョンになります。
この場合はcurrentがnoneになっていて、v16.14.2がインストールされていますが使用するように設定されていない状態です。

`nodebrew use`で使用するバージョンを指定します。
こちらもinstall時同様、`stable`や`latest`で指定することも可能です。

```
$ nodebrew use v16.14.2

or
$ nodebrew use stable
$ nodebrew use latest
```

これで完了です。
確認してみます。

```
$ nodebrew ls
v16.14.2

current: v16.14.2
```

```
$ node -v
v16.14.2
```

指定したバージョンが使用されているのが確認できました。
npmコマンドも打てるようになっていました。

```
$ npm -v                        
8.5.0
```

## 原因は何？
インストールされていたはずのnodeがインストールされていない状態になっていたことが原因でした。
数日前まで問題なくnpmコマンドが打てていたのに、ある日突然といった形です。
なぜ突然このような現象が発生したのかは判明しませんでした。
同じエラーがmacのアップデートによって発生したとの報告が何件かあるようなので、そちらの可能性が高いと思っています。

## pathを通せば解決する？
エラー文で検索するとpath関係が原因だと書いてあるサイトもいくつか出てきました。
私の場合はpathは関係なくnodeをインストールし直す形で解決しましたが、もしこの記事の方法で解決できなければpathを疑ってみるのもありかなと思います。

## 参考にしたサイト
https://qiita.com/sinmetal/items/154e81823f386279b33c
https://github.com/hokaccha/nodebrew
Microsoftのデータサイエンス初心者向けコースDay3：割合を可視化

# はじめに

本記事では、Microsoftのデータサイエンス初心者向けコースDay3の"Visualizing Proportion"のPython関連について
Google Colaboratoryを利用して実際に動かしていく。エラーを特定して修正して動かすという体感を通してのみ学びがあると信じている。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409610/266682aa-ccc8-888a-2cfd-9cfd885b49c7.png)


# 対象読者

　Pythonとデータサイエンスに興味があって、英語が苦手な人（英語が得意な人は、[参考文献](#参考文献)を直接解いてね。

## きのこについて知る。

```Python

import pandas as pd
import matplotlib.pyplot as plt
mushrooms = pd.read_csv('https://raw.githubusercontent.com/microsoft/Data-Science-For-Beginners/main/data/mushrooms.csv')
mushrooms.head()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409610/a3e4b7d9-8e0c-5d81-5895-419cf0ad899d.png)

きのこに関するデータセットの先頭５行を表示。
毒キノコかどうかの列があるので、極性判定とかできそうな感じ。


## ラベルをカテゴリのdtypeとして扱い、食べれるキノコと毒キノコの属性を集計。


```Python

cols = mushrooms.select_dtypes(["object"]).columns
mushrooms[cols] = mushrooms[cols].astype('category')
edibleclass=mushrooms.groupby(['class']).count()
edibleclass

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409610/25f183ee-4154-5c11-e8c6-4a4364e086a1.png)




## 食べれるキノコと毒キノコの割合をパイチャートで。

```Python

labels=['Edible','Poisonous']
plt.pie(edibleclass['population'],labels=labels,autopct='%.1f %%')
plt.title('Edible?')
plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409610/77f7e3e6-8ea3-aae8-626e-f51cd50e6d34.png)




## キノコはどこで育つのかをドーナッツチャートで。

```Python

habitat=mushrooms.groupby(['habitat']).count()
habitat
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409610/14f7f503-5339-a230-4004-32de92531ef6.png)



```Python

labels=['Grasses','Leaves','Meadows','Paths','Urban','Waste','Wood']

plt.pie(habitat['class'], labels=labels,
        autopct='%1.1f%%', pctdistance=0.85)
  
center_circle = plt.Circle((0, 0), 0.40, fc='white')
fig = plt.gcf()

fig.gca().add_artist(center_circle)
  
plt.title('Mushroom Habitats')
  
plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409610/f42be828-b44b-6d2b-2ff2-b35735e125d2.png)




## ワッフルチャート

「ワッフル」タイプのチャートは、数量を正方形の2次元配列として可視化する別の方法である。このデータセットで、キノコの傘の色の異なる数量を視覚化してみる。これを行うには、PyWaffleというライブラリをインストールし、Matplotlibを使う必要がある。

```Shell
pip install pywaffle
```


```Python

import pandas as pd
import matplotlib.pyplot as plt
from pywaffle import Waffle

capcolor=mushrooms.groupby(['cap-color']).count()
capcolor
  
data ={'color': ['brown', 'buff', 'cinnamon', 'green', 'pink', 'purple', 'red', 'white', 'yellow'],
    'amount': capcolor['class']
     }
  
df = pd.DataFrame(data)
  
fig = plt.figure(
    FigureClass = Waffle,
    rows = 100,
    values = df.amount,
    labels = list(df.color),
    figsize = (30,30),
    colors=["brown", "tan", "maroon", "green", "pink", "purple", "red", "whitesmoke", "yellow"],
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409610/6772e9a8-7ff0-4212-fddc-5e2511777e4a.png)



　おしゃれなWaffleグラフの出来上がり。ボナペティ！


# 著者のTWITTERアカウント

@keiji_dl

# ホームページ（pytorch/python/nlp）

https://deeplearning.sakura.ne.jp/hp


# 参考文献

https://github.com/microsoft/Data-Science-For-Beginners
シェルのクォーティングについてのメモ

# クォーティングとは
<p>メタ文字を展開させずに、文字そのものとして扱う記法です。</p>
<p>*や{ }などの記号がメタ文字と呼ばれ、シェルスクリプトではメタ文字があると別の文字列に置き換わってしまいます。これを展開と呼びます。</p>
<p>クォーティングには大きく２種類あり、\をメタ文字の前に付ける方法と、' 'または" "の中にメタ文字を入れる方法があります。</p>

<h2>展開の例</h2>

sample.sh
<pre><code>#!/bin/bash
ls *.sh
echo $HOME
echo $(date +%Y-%m-%d)
echo $((1+1))
</code></pre>

出力結果

<pre><code>$ bash sample.sh
sample.sh
/Users/taro
2022-03-23
2
</code></pre>

### 解説
上から順にパス名展開、パラメータ展開、コマンド置換、算術式展開となります。説明は割愛します。

<h2>\（バックスラッシュ）</h2>
<p>メタ文字の前に\をつけると、直後の1文字だけメタ文字の効果が無効化されます。</p>

<p>sample2.sh</p>
<pre><code>#!/bin/bash
ls \*.sh
echo \$HOME
echo \$(date +%Y-%m-%d)
echo \$((1+1))
</code></pre>

<p>出力結果</p>
<pre><code>ls: *.sh: No such file or directory
$HOME
test.sh: 行 4: 予期しないトークン `(' 周辺に構文エラーがあります
test.sh: 行 4: `echo \$(date +%Y-%m-%d)'
</code></pre>

<h2>解説</h2>

<h3>ls \*.sh</h3>
<p>*が無効化され、*.shというファイル名に対してlsを行います。</p>

<h3>echo \$HOME</h3>
<p>\$が無効化され、$HOMEという文字列を表示します。</p>

<h3>echo \$(date +%Y-%m-%d)　echo \$((1+1))</h3>
<p>文法エラーとなります。$は無効化されるが、それ以外の( )などのメタ文字はクォーティングされないためです。</p>

<h2>クォーテーション</h2>
<p>クォーテーションの中に入っているメタ文字は文字そのものとして扱われます。</p>
<p>' 'は中に書かれた全てのメタ文字がクォーティングされます。</p>
<p>" "は中に書かれたメタ文字の中で\と$だけは展開され、それ以外はクォーティングされます。</p>
<p>意図しない展開を防げるため、はじめのうちはシングルクォーテーションを使うのが無難です。</p>
<h2>' '（シングルクォーテーション）</h2>
<p>sample3.sh</p>
<pre><code>#!/bin/bash
ls '*.sh'
echo '$HOME'
echo '$(date +%Y-%m-%d)'
echo '$((1+1))'
</code></pre>
<p>出力結果（全てクォーティングされる）</p>
<pre><code>ls: *.sh: No such file or directory
$HOME
$(date +%Y-%m-%d)
$((1+1))
</code></pre>
<h2>" "（ダブルクォーテーション）</h2>
<p>sample4.sh</p>
<pre><code>#!/bin/bash
ls "*.sh"
echo "$HOME"
echo "$(date +%Y-%m-%d)"
echo "$((1+1))"
</code></pre>

<p>出力結果（$は展開される）</p>
<pre><code>ls: *.sh: No such file or directory
/Users/taro
2022-03-23
2
</code></pre>

<h1>クォーティングが複数現れる場合</h1>
クォーティングが複数現れるケースを見ていきます。
<pre><code>#!/bin/bash
echo "$HOME '$HOME' "
test='hoge $HOME'
echo "$HOME $test"
</code></pre>

<p>出力結果（" "の中であれば' 'も展開される）</p>
<pre><code>/Users/taro '/Users/taro' 
/Users/taro hoge $HOME
</code></pre>

<h2>解説</h2>
<p>コードの2行目では、" "の中にある変数であれば、たとえその中にシングルクォーテーションがあったとしても無効化され、文字列の' 'として認識します。</p>
<p>一方で3行目のように変数の代入値としてシングルクォーテーションとした場合、既にクォーティングされた結果が変数に格納されます。そのため変数の中の\$HOMEは展開されず、出力結果2行目のようになります。</p>

<h1>あとがき</h1>
<p>この記事書いている時もメタ文字が展開されてしまったので、\でクォーティングをやってました。</p>
Types of property 'delimiters' are incompatible.  Type 'string[]' is not assignable to type '[string, string]'. の対処法

### 概要
Django + vue.js などの場合、どちらも変数展開に mustache記法({{ }}) を用いるため、
vue.js 側の delimiters オプションを使用して、以下のように回避することがあると思います。
``` vue.js 
delimiters: ['[[', ']]']
```
Javascript と Typescript が混在しているプロジェクトの場合、
これが原因でビルド時にタイトルのエラーを吐くことがあります。

具体的には、ts 形式のファイルから上記のオプションが設定されている js 形式のモジュールを import して使用する場合などです。

### 原因
vue.js のランタイムにて、delimiters は以下のように型付けされています。
```ts
delimiters?: [string, string];
```
これは、文字列型が二つ含まれる**タプル型**です。
ところが、Javascript にはタプル型は存在しないため、文字列が含まれる**配列型**と誤認してしまうためにエラーとなります。

### 解決策
解決策はいくつかありますが、
たったこれだけのために副作用のありそうな諸々の無効化オプションを設定したくはないので、最も影響の小さい解決方法を考えました。

1. ts ファイルで、正しい型定義を行った変数を定義する
    ```ts
    export const typedDelimiters: [string, string] = ["[[", "]]"];
    ```
2. 上記変数を、js形式のファイルで import し、delimiters オプションの値として使用する
    ```js
    import { typedDelimiters } from '../utils';
    
    ...中略...
    
    delimiters: typedDelimiters
    ```

トランスパイル時には、js も ts も全て Typescript として認識されます。
そこで、JS による動的型付けに任せず、明示的に型付けしてしまうというわけです。

以上です。
【AWS環境構築メモ①】お名前.comで独自ドメイン取得する

## 0.はじめに

AWSで本番環境構築するに当たり、お名前.comで独自ドメインを取得してみたことを書いてみました。
とても簡単なので、誰でも簡単に取得できます。多分。

あくまでもメモなので、詳しい説明等は参考にした記事などをご紹介する形で記載します。

## 1.ドメイン取得手順(サマリー)
|順番|手順|
|---|---|
|1|取得したいドメイン名を決める|
|2|お申込み内容確認、メールアドレス、パスワード入力|
|3|会員情報登録|
|4|支払い方法選択|
|5|申し込み完了|
|6|メール確認|

## 2.ドメイン取得手順

### 1.取得したいドメイン名を決める

![スクリーンショット 2022-03-23 17.35.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/8a53ac4c-6ac3-4fe0-a00a-56d35af55301.png)

- [お名前.com](https://www.onamae.com/) にアクセス
- ページ中央の「取得希望の文字列を入力」部分に、取得したいドメイン名を入力
- 入力し終わったら検索ボタンを押す

**ドメイン入力の際は、.com .jpなどの選択は不要です。**

![スクリーンショット 2022-03-23 17.35.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/64a9f5b4-a10b-1146-282e-289916191fe2.png)

- ドメイン一覧から取得したいドメインにチェックをする(.comとか.jpとか色々あります)
- 選択した商品の欄で、取得したいドメインを確認して、お申込みへ進む

### 2.お申込み内容確認、メールアドレス、パスワード入力

![スクリーンショット 2022-03-23 17.54.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/3ea9c093-cf45-7ca9-6404-7f41388b9949.png)

- お申し込み内容
  - Whois情報公開代行
    - 1年登録でOK
  - Whois情報公開代行メール配信オプション
  - ドメインプロテクション
    - チェックなしのままでOK

- メールアドレス、パスワードを入力して次へ(画面右上)

Whois情報公開代行については以下の記事をご参考↓
[Whois情報公開代行をやさしく説明！意味・費用・設定方法を徹底解説！](https://tk-create.com/domain/whois/)

### 3.会員情報登録

**訳あって画像は無いです**

- 必須項目はすべて入力してください
- 記入し終えたら「次へ」を押す

### 4.支払い方法選択

**訳あって画像は無いです**

- 支払い方法を以下の３つから選び、必要事項を入力
  - クレジットカード
  - 銀行振込み
  - コンビニ決済

- 申し込むを押します

クレジットカード払いだと、ドメイン取得後すぐに取得したドメインが使えるみたいです。

### 5.申し込み完了

申し込むを押した後、**「お名前.comのレンタルサーバー」** の申し込み画面がでてきますが、
私は必要無かったので申し込みませんでした。有料だし。

以上でドメイン取得の申し込みは完了です。

### 6.メール確認

![スクリーンショット 2022-03-23 19.02.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891391/47debaaa-3576-0fb9-eec2-914e391dbeeb.png)

上の画像のように、

- ドメイン登録　料金ご請求/領収明細
- ドメイン自動更新　設定完了
- Whois情報公開代行　完了通知
- ドメイン登録　完了通知
- 会員情報変更　完了通知

のメールが通知されていることを確認してください。
通知が来たら、内容を確認してください。

## ドメイン取得完了

以上で独自ドメイン取得完了です。
そんなに難しい作業では無かったので、おそらく5~10分で終わると思います。

**次回は、取得したドメインをRoute53に登録します。**

**次回 ： [【AWS環境構築メモ②】お名前.comで取得したドメインをRoute53に登録する](https://qiita.com/yuuichimizuta/items/bd335c9af518560ca3d4**)**

## 参考

https://tk-create.com/seo/original-domain-acquiring-method/

https://blog-bootcamp.jp/start/onamae-registration/
styled-component

## component selector

- styledでラップされてるコンポーネントしか使えない

https://styled-components.com/docs/advanced#caveat

- 要素にclassNameを渡さないと、styledでラップしてもスタイル効かない
  - 特にmoleculesとかでハマりそう

https://stackoverflow.com/questions/52542817/styled-components-not-applying-style-to-custom-functional-react-component

## tips
- 命名は頭に$をつける
Atomで選択したテキストをHTMLタグで囲むコマンドを作りました

Atomで選択したテキストをHTMLタグで囲むコマンドを追加しました。
こんな感じで動作します。

![mov1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79979/511a9038-436e-9137-e6dd-1fb16f0c0dbe.gif)

1. タグで囲みたいテキストを選択し、cmd+ctrl+Tを押すとコマンドが実行され、テキストが\<xxx\>〜\</xxx\>で囲まれる（ショートカット設定方法は後述）

2. コマンド実行後、「xxx」が選択された状態になっているので、タグ名を入力する

* 複数選択も可能です
* 複数行を選択した場合は、選択されたブロックがタグで囲まれます

## コマンドの追加方法

Atomのメニューから「Init Script…」を選択してスクリプトファイルを開き、以下のスクリプトを追加します。

```javascript:encloseTag
function encloseTag(){

	var editor = atom.workspace.getActiveTextEditor();
	var selections = editor.getSelections();

	selections.forEach(
		function(selection){

			var text = selection.getText();
			var tagged_text;

			//複数行選択されている場合は改行を追加
			if(text.match('\n')){
				tagged_text = '<xxx>\n' + text + '</xxx>\n';
			}
			else{
				tagged_text = text.replace(/^(\s+)?/, '$1<xxx>') + '</xxx>';
			}

			var options = {
				'select': true
			};

			//タグで囲む
			selection.insertText(tagged_text, options);

			//インデントを整える
			selection.autoIndentSelectedRows();

		}
	);

	//xxxを選択する
	var tagname_ranges = [];

	selections.forEach(
		function(selection){
			editor.scanInBufferRange(
				/xxx/g,
				selection.getBufferRange(),
				function(obj){
					tagname_ranges.push(obj.range);
				}
			);

			selection.clear();
		}
	);

	editor.setSelectedBufferRanges(tagname_ranges);

}
```

init.jsの最後で、追加したスクリプトをコマンドとして登録します。

```javascript
atom.commands.add("atom-text-editor", {
	"EncloseTag": encloseTag
});
```

コマンド追加を反映するため、一度Atomを再起動します。

### ショートカットの登録

次に、ショートカットを登録します。（この段階でもコマンドパレット cmd+Shift+P から「EncloseTag」と入力すれば、実行できます。）

![mov2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79979/ff6087b9-b556-cf86-f846-54c3c6e203a5.gif)


Atomのメニューから「Keymap...」を選択、「keymap.cson」を開き、以下のコードを追加します。

```coffeescript
"atom-text-editor":
    "cmd-ctrl-t": "EncloseTag"
```

わたしはショートカットの競合がしにくく、比較的押しやすい「cmd+ctrl」のコンビネーションをAtomでは好んで使っています。（「T」はタグの頭文字です）

これでコマンドの登録とショートカットキーの登録は完了です。

AtomでHTMLコーディングをされている方のお役に立てれば幸いです！
[neos(NeosVR)]5分で分かるAssetFrameの実装の仕方

写真などを放り込むだけで簡単に使える便利なコンポーネントという事はわかっていたけど、
開発する際、具体的にどう組み込んで使うのか全くわかってなかったので
同じ悩みを抱えているかもしれない人向けに簡単に使い方をメモしておきます。

![20220323184325_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/bcae9a7e-0b91-ebcd-e96f-d1df3a653752.jpeg)

まず、どこでもいいので空のSlotを作成。
そのSlotに「Transform/Interaction/AssetFrameSlot<A>」を選択。
その後は用途次第ですが、今回はITexture2Dを選択して追加しました。

コンポーネントを追加したら、Targets(list)の下のAddボタンを押します。(図で言えば0.2の真下あたり)
次に、適用したいテクスチャがあるSlotをインスペクタで開きます。(図の右側)
最期にTextureの文字の部分をLogixTipでドラッグして、先ほどボタンを押して追加されたリストの空白にドロップします。

設定は、以上です。

後は適当な写真をフレーム内にドラッグしてあげると、写真がその中に納まって適用したいテクスチャの部分が変化しているはずです。
（図の左下）
swift5 Sqlite3 FMDBにてデータベース構築

swift5にてSqlite3とFMDBライブラリ利用で、iPhoneアプリ内にデータベース構築し、アプリ個別情報管理に利用する。
https://www.sqlite.org/download.html
より(2022/03)現在最新sqlite-tools-osx-x86-3380100をダウンロード。
![スクリーンショット 2022-03-23 18.32.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/299803fc-7656-ef11-7c62-00a31fb7f0ea.png)
sqlite3をXcode内へコピー
![スクリーンショット 2022-03-23 18.33.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/86c8543a-de20-2657-2511-e79d5881feeb.png)
FMDBの導入は下記サイトよりダウンロード。
https://github.com/ccgus/fmdb
フォルダsrc→fmdbフォルダ内の下記ファイル群を
![スクリーンショット 2022-03-23 18.39.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/a10d4444-15d6-8ee0-3023-50f3eba94e08.png)
Xcode内にgroupフォルダfmdbを作成その内にコピーと同時にheaderファイル作成要求に従い作成そのファイルXXXXXXXXXXX-Bridging-Header.h内に下記のように記述。
#import "FMDatabase.h"
#import "FMResultSet.h"
#import "FMDatabaseAdditions.h"
#import "FMDatabaseQueue.h"
#import "FMDatabasePool.h"
#import "sqlite3.h"
これにてプロジェクト内で任意のデータベースを作成利用可能となる。
YOLOv5で検出結果の出力を保存する方法（Google Colaboratory）

はじめての投稿です。:bow:

該当の方法についてはGoogle Colabratoryでの話なので他の環境について把握していませんのであしからず。

先に結論。


```
! python detect.pyへのパス --source 動画ファイルへのパス 2> XXXXX.txt
```
例えば自分の場合、
```
! python /content/yolov5/detect.py --source /content/drive/MyDrive/otaku.mp4 2> list.txt
```
といった感じ。
ちなみに出力結果のファイル名の前に保存したいディレクトリのパスを記載すれば任意の場所にほぞんできます。

参考記事として、
- <https://eng-memo.info/blog/yolo-original-dataset/>
- <https://qiita.com/electronics_diy721/items/c1347939bb3e763094d0>

があります。

もともと、上記の二番目のリンク先と同じことがやりたくてdetect.pyで出力されるフレームごとの検出結果を.txtでも.csvでもなんでもいいから保存できないかと考えていました。

参考記事の通り```>```を入れてもなぜか上手くいかず、かなりの時間を要しました:cold_sweat:

どうやら該当の処理のことをlinuxでの**リダイレクト**というものに該当するとのことで、またリダイレクトにも種類があるということがわかりました。(詳細は調べてください）

参考になれば幸いです。
Zoomの新3Dアバター機能で動物の姿でMTGに参加できるらしい

Zoomが2022年3月22日、ウサギ（または犬、キツネ、パンダ、馬など）の姿でミーティングに参加できる機能を発表したようです。

実際にカメラに映ることなくボディランゲージや顔の表情を伝える方法を提供することを目的としているようです。

![avatars-in-meeting-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/896811ec-b824-340e-ed53-9e1b18df04db.png)
出典元)https://support.zoom.us/hc/en-us/articles/4642184011917-Using-Avatars-in-meetings-and-webinars

> 会議中にこの機能をオンにすると、Zoomの技術により、デバイスのカメラを使用して画面上の顔の位置を検出し、選択したアバター効果を適用します。この機能を使用する場合、顔の画像はデバイスから離れることはなく、保存もZoomへの送信もされません。この機能は顔認識を使用しないので、あなたが誰であるかを特定することはありません。したがって、アバター機能は、何が顔であるか、または顔でないかを識別することはできますが、個々の顔を認識したり、区別したりすることはできません。

出典元)https://support.zoom.us/hc/en-us/articles/4642184011917-Using-Avatars-in-meetings-and-webinars

とのこと。

# 動作環境
- Zoomバージョン5.10.0以降
- WindowsとmacOSのデスクトップデバイス、およびiOSモバイルデバイスの両方で利用可能
    - 現状Androidは未対応

## Zoomのバージョンアップ方法
Zoomのバージョンが古い場合は以下をご参考下さい。

https://support.zoom.us/hc/ja/articles/201362233-Zoom-%E3%81%AE%E6%9C%80%E6%96%B0%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%B8%E3%81%AE%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89


# 利用方法
- 「ビデオの開始 / 停止」ボタンの横にあるキャレット（^）マークをクリック

![Screen Shot 2022-03-23 at 18.15.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/dcff6df0-bc8d-75a2-0605-66ef0153f7b9.png)

- 「バーチャル背景を選択」または「ビデオフィルターを選択」のどちらかを選択すると「アバター」というタブが表示される
- 好きなアバターを選択

![Screen Shot 2022-03-23 at 18.18.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/83c82d60-d3ed-0f34-1ded-00a32f3360f7.png)

# やってみた
<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/kNOyMdnJ0Y">pic.twitter.com/kNOyMdnJ0Y</a></p>&mdash; tak001 (@5HdM6WlLVaazBV7) <a href="https://twitter.com/5HdM6WlLVaazBV7/status/1506562236634234888?ref_src=twsrc%5Etfw">March 23, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

思っていた以上に体の傾きとか、目、口、頭の向きとか再現されてました。

万歳してみたり、腕を動かしてみたのですが流石に手振りまでは再現されませんでした。

バーチャル背景と一緒に使うこともできました。

# まとめ
- 髪の毛ボサボサの時とか良さそう
- カメラを写すのが抵抗あるけど顔の表情をある程度伝えたい時とか良さそう
- リモートだとこういった機能は有難い
- MTG(怒られないようなシーン)の機会があれば使ってみたい

# 文献
https://support.zoom.us/hc/en-us/articles/4642184011917-Using-Avatars-in-meetings-and-webinars

https://techcrunch.com/2022/03/22/zoom-animal-avatars/
サプライチェーン とは

## 勉強前イメージ

つながる的なやつ？チェーンだし

## 調査

### サプライチェーン とは

日本語では 供給連鎖 といい、製品の部品や原材料の調達から販売されるまでの一連の流れを指したものになります。
サプライチェーンの特徴は、その一連の流れを自社だけでなく協力会社などの他社をまたいでものの流れを捉えます。
他社もまたいでの原材料の仕入れから販売されるまでのフローになります。

ITの業界でも存在し、ITサプライチェーンと呼ばれます。
上記と考え方は同じですが、ITシステムやサービスを提供する業務を一部外部委託してその委託が連鎖する形態と定められています。
システム開発など行ってる会社では、一部業務を外部委託しているとこともありさらに孫受けなども呼ばれることがあります。

サプライチェーンを管理・最適化する手法を `サプライチェーンマネジメント` と言います。
略して `SCM(Supply Chain Management)` になります。

### ITサプライチェーンのリスク

業務委託社からはサプライチェーンの先は見えづらい可能性があります。
社内セキュリティレベルや、セキュリティガイドラインなど基本的に見えているものだと思いますが、
委託(他社)では情報ベースでは上記の資料があったりするかもしれませんが感覚値としては難しいかもしれません。

マルウェアなどの攻撃で情報漏えいやデータの入った端末の紛失等の過失が発生したりする可能性があり、
それは二次受けと呼ばれるものでも同様のリスクはあります。

## 勉強後イメージ

サプライチェーンって物理的にものを作って売るというものが多い気がする。
IT系ってのはむずかしいのかな？あまり資料なかった
ただ、こういう形態ってサプライチェーンっていうんだっていうのは理解できたし、
自分主導で情報は引き出さないといけないのだなと・・・。

## 参考

- [ITサプライチェーンとは？外部委託に潜むセキュリティリスクとその対応](https://businessonline.trendmicro.co.jp/sb/smb/problem_044.asp#:~:text=IT%E3%82%B5%E3%83%97%E3%83%A9%E3%82%A4%E3%83%81%E3%82%A7%E3%83%BC%E3%83%B3%E3%81%A8%E3%81%AF%E3%80%81IPA%EF%BC%88%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8E%A8%E9%80%B2%E6%A9%9F%E6%A7%8B,%E3%81%A8%E5%AE%9A%E7%BE%A9%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)
- [意外と知らない？ITトレンド用語](https://www.ntt.com/bizon/glossary/j-s/supply-chain.html)
Keycloak 自前の署名鍵を設定する方法 メモ

* KeycloakでOpenSSLで生成した自前の署名鍵を利用する方法についてメモする。



## 署名鍵(公開鍵・秘密鍵)の生成

[OpenSSL](https://www.openssl.org/source/)を利用して、署名用(RSA)の秘密鍵と公開鍵を生成する。

1. 秘密鍵の生成

   ```shell
   # PEM形式の秘密鍵を生成する。
   openssl genrsa -out jwt-private-key.pem 2048
   ```

2. 公開鍵の生成

   ```shell
   # DER形式の公開鍵を生成する。
   openssl rsa -in jwt-private-key.pem -pubout -outform DER -out jwt-public-key.der
   ```



## 署名鍵の設定

1. Keycloakコンソールからレルム設定画面を開く。
2. 「`Keys`」->「`Providers`」を選択し、「`Add keystore...`」から`rsa`を選択する。
3. 以下の項目を入力し、「`Save`」する。
   * `Priority`(鍵設定の優先度) : `100`
   * `Private RSA Key` （秘密鍵）:前述の手順で作成した「`jwt-private-key.pem`」ファイルを選択する。

## 確認方法

1. IDトークンを発行する。
1. 1で発行したIDトークンをデコードし、ヘッダー部を確認する。
   * 前述の手順で設定した署名鍵に対応する`kid`が設定されている。
第11回　レイヤ1　ネットワーク・トロポジ

ネットワークの構成図
---
実際の機器とメディアの配置のことを物理ト
ロポジという。

ノードとリンクという2つの図形を用いて、
ネットワークの物理的配置を表現する。

ノードとは、コンピューターやネットワーキ
ングデバイス、リンクとはメディアを指す。
これらの配置は大きく5種類に分かれる。


バス型トロポジ
---
バス型トロポジは下記の通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/1d3180db-3159-4df1-41bd-7fe752bc8723.png)


共有メディア環境といえば、このバス型を指
す。少し古いタイプの物理トロポジで、同軸
ケーブルを用いる。T型コネクタを使い、母船
と支線をつなげる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/dc0eeeb6-5b7a-3767-12c6-ed31b7dbbb78.png)

リング型トロポジ
---
それぞれのノードが隣の2つと接続している。
かつ、円形になるのがリング型である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/dd0d14c3-ff9f-f307-3c51-8063f5540e06.png)

特徴としては、信号が一方通行であること。
右回りなら右回り、逆方向には流れない。

リング型の特徴としては二重リング型であ
ること。通常は片方しか使わず、臨時のた
めの二重性。


スター型トロポジ
---
現在のLANの一般的なトロポジはスター型。
中央のノードはハブのようなネットワーク
デバイスが使われる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/6c125cb6-f131-dd52-cd8f-857881778815.png)


ハブ、もしくはスイッチを中央において相
互に接続される、接続される台数がハブの
ポート数を超えることが多く、いくつもの
ハブを繋いだ形の拡張スター型となる。



ツリー型トロポジ
---
段階的に分かれている形をしている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/9b343d79-94ce-d0b4-a158-8854a8b0c212.png)


メッシュ型トロポジ
---
このトロポジの特徴は、全てのノードが相互
に直接接続されていること。上記のトロポジ
は、どこか一か所切断されてしまうと他と繋
がらなくなってしまう構造であった。

メッシュ型であれば、遠回りにはなるが、必
ず接続することが可能。

これは、通信が遮断されると致命的なエラ
ーとなるシステムで適応されている。具体例
を上げると原発の管理システムなど。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/864556fc-0e69-b69f-cda2-5624ed33c212.png)


上記のようなトロポジは完全メッシュ型とい
い、逆に一部がメッシュ型となるものを部分
メッシュ型という。(下図)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/680bc8f4-eadc-77b9-d372-96ce32be6b01.png)


論理トロポジ
---
物理トロポジはあくまで、ノードとリンクの
物理的な配置を指す。一方、データの流れと
いう観点から見た論理トロポジも存在する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602995/a46a79df-bc7b-22ea-0c71-85cfb2dc6e7d.png)


物理トロポジのリング型は論理トロポジで
もリング型だが、物理トロポジがバス型やス
ター型となると物理トロポジと論理トロポジ
が一致しないこともある。

配置とデータの動きが一致しているかどうか
はアクセス制御方式で判断する。

参照URL：
<a href="http://www5e.biglobe.ne.jp/~aji/3min/">3分間ネットワーキング</a>
IPとVPC EndpointでIAM Userが使えるプリンシパルを制限

# 概要
IAMユーザを使用できる[プリンシパル](https://docs.aws.amazon.com/IAM/latest/UserGuide/intro-structure.html#intro-structure-principal)をIPやソースのVPCエンドポイントで絞りたいです。

※プリンシパル：AWSのリソースに対してアクションやオペレーションを実行できる人、もしくはアプリケーションのこと

図にすると以下となります。
![スクリーンショット 2022-03-15 16.35.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109911/ce14d9ac-0ae9-c16a-716e-02412802f68e.png)



# 要件を満たすIAM ポリシーを作成する
**やりたいこと：プログラム経由(CLI、SDK等)のIAMを使うプリンシパルが以下の場合はアクセスを許可したい**

1.  アカウントAのVPCエンドポイントを経由している
2.  特定のパブリックIP
3.  AWSのサービス

つまり**1 or 2 or 3**であればIAMが使えます。
ソースIPを絞りたい場合、[こちらの公式ドキュメント](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws_deny-ip.html)を参考にIAMポリシーを作成しました。
また、経由するVPCエンドポイントを絞るのは「StringNotEquals」と「aws:SourceVpce」の組み合わせを使いました。
以下が完成したIAMポリシーです。
```
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Deny",
        "Action": "*",
        "Resource": "*",
        "Condition": {
            "StringNotEquals": {
                "aws:SourceVpce": [
                    "<アカウントAのVPCエンドポイント>"
                ]
            },
            "NotIpAddress": {
                "aws:SourceIp": [
                    "<アカウントAのEC2のパブリックIP>"
                ]
            },
            "Bool": {
                "aws:ViaAWSService": "false"
            }
        }
    }
}
```
これは以下の3つのAND条件となります。

1. アカウントAのVPCエンドポイントを経由していない
2.  特定のパブリックIPではない
3.  AWSのサービスではない

なぜこんなややこしい書き方をするかというと、
[IAMポリシーのConditionに対する評価ロジックはAND条件となる](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_multi-value-conditions.html)ためです。

つまり、この章の初めに記載したOR条件ではポリシーを記述することができず、中学生・高校生の時にやった集合でいうところの対偶(正反対)の条件に書き換える必要がありました。

文字だと分かりにくいため、図にすると以下となります。
![スクリーンショット 2022-03-15 17.41.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109911/04c2912d-6118-2e97-86f0-4aec41a4aa58.png)

# 検証
念のため、以下の条件で動作検証をしてみました。

1. Account Aのプライベートサブネット上に存在するEC2へuser Aのクレデンシャルを登録してAccount BのS3へアクセスできる(図の<span style="color: #d86e00">オレンジ</span>の経路)
2. Account Aのパブリックサブネット上に存在するEC2へuser Aのクレデンシャルを登録してAccount BのS3へアクセスできる(図の<span style="color: #2357b5">水色</span>の経路)

![スクリーンショット 2022-03-15 16.35.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109911/ce14d9ac-0ae9-c16a-716e-02412802f68e.png)
※水色の経路はローカルからCLIを実行しているのと同じです

以下コマンドでアカウントBのバケットへアクセスすることができました。
```
aws s3 ls s3://バケット名
```

また、逆にIAMポリシーのConditionに記述しているIPやVPCエンドポイントのIDを存在しないものに書き換えた場合、アクセスができなくなりました。

# おわりに
IAMポリシーのCondition句「StringNotEquals」や「NotIpAddress」といったNotのDenyは分かりづらいですが、整理して考えることができれば大変柔軟が効くポリシーを書くことができます。
機会があれば使ってみてください！
crontabの基本的なコマンドとファイル差替え（Windows）

### 事前事項
1. 差替え用のcronファイル（cron_batch.cron.new）は既に用意済み。
2. ファイル名、ディレクトリ構造は適当に記載している。

### 差替え手順
- FTPソフト（WinSCP等）を使用して、バッチサーバーの「/tmp」にcronファイルを格納する。
- SSHクライアント（Putty等）を使用して、「踏み台サーバー」→「バッチサーバー」の順に接続する。
- root（スーパーユーザー）に切り替える。

```markdown
sudo su -
```

- tmpディレクトリへ移動する。

```markdown
cd /tmp
```

- 変更前のcrontabを「tmpディレクトリ」へバックアップをとる。

```markdown
crontab -l > crontab_backup1
```

- 差替え用のファイルを反映させる。

```markdown
crontab /tmp/cron_batch.cron.new
```

- 変更後のcronファイルのバックアップをとる。

```markdown
crontab -l > crontab_backup2
```

- 変更前後の差分を確認する。

```markdown
diff crontab_backup1 crontab_backup2
```

- バックアップディレクトリの作成

```markdown
mkdir -p /home/backup/`date +%Y%m%d`
```

- crontab出力ファイルをローカルのバックアップディレクトリに退避する。

```markdown
mv /tmp/crontab_backup? /home/backup/`date +%Y%m%d`
```

- 退避ファイルを確認する。

```markdown
ls -l /home/backup/`date +%Y%m%d`
```

- ログアウト

```markdown
exit
```

### 基本的なcrontabコマンド

|コマンド      |  内 容          |
|----         |----             |
|  crontab ファイル名    |  cronファイルの更新<br>（ファイル名を指定しないと、空ファイルを指定したことになり、cronファイルが消えるので注意が必要。 ）               |
|  crontab -l |  cron設定の表示 <br>（「crontab -l > ファイル名」で表示した内容を別ファイルに保存。 ）|
|  crontab -e |  cronファイルの編集 <br>（「e」の隣に「r」があるので、使用する際は注意が必要。） |
|  crontab -r |  cronファイルの削除<br>（警告なしで削除される。）  |
SATySFi のrefコマンドでうまく引用できないとき

## 対象者
- \theorem, \lemma などにラベルをつけたけど、\ref にラベルを渡してもうまく表示されない人
- 久しぶりにSATySFiを使って書く自分

## SATySFi の version
```bash
$ satysfi -v
  SATySFi version 0.0.6
```

## SATySFi のソースを見てみよう
stdjareport.satyh での実装は次のようになっている。
``` code
let-inline ctx \ref key =
    let opt = get-cross-reference (key ^ `:num`) in
    let it =
      match opt with
      | None    -> {?}
      | Some(s) -> embed-string s
    in
      inline-frame-breakable no-pads (Annot.link-to-location-frame key None) (read-inline ctx it)
```
\ref(key); で渡した文字列 key の末尾に ":num" という文字列を追加して検索をするようだ。

## (ファイル名).satysfi-aux ファイルを見る
``` code
{"generated:4:num":"0.1.3","generated:6:num":"0.2","generated:1:page":"1",
 ...,
 "theorem:hey:num":"0.2.7","generated:9:num":"0.2.8",...
}
```
色々あるけど、\theorem でラベルを登録すると、"theorem:(ラベル名):num" という形になるようだ。

## 解決策
例えば、hey というラベルで登録した定理 0.2.7 の定理番号を、+proof の冒頭で書きたいとする。

```
+proof?:({\ref(`hey`);}){

}
```
と書き、コンパイルすると
![Screen Shot 2022-03-23 at 17.53.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2578661/fd98dfd6-a460-04d4-205d-e2ceea516d86.png)
となる。

aux ファイルの構造を参考にして、次のように書いてみる。
```code
+proof?:({\ref(`theorem:hey`);}){

}
```
コンパイルすると、
![Screen Shot 2022-03-23 at 18.03.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2578661/339295f1-bc6e-32cc-f877-1b9d4f0049d1.png)
と表示される。うまくいった。

## まとめ
- theorem にラベルを登録すると、定理番号は、.satysfi-aux ファイルに "theorem:(ラベル名):num" で .satysfi-aux ファイルに登録されている。
- "(コマンド名):(ラベル名)" を \ref に渡すとうまく表示される。(lemma や definition でも同じ。)
- 困ったら aux ファイルやソースコードを見よう。