OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】簡単なsqlを忘れないために

##SQLの基礎を理解する
PHPの勉强と共に必要な部分だけを学んでいたsqlでしたが
この度、書籍や動画で理解が深まったので記録しておきたいと思います。

##SQLの基礎
①データベースの作成・削除
②データベースの一覧表示
③テーブルを作成と削除
④データの保存＝レコード(行)の追加
⑤データの取得
⑥データの更新
⑦データの削除

##はじめに
データベースに命令をするためにデータベースに接続する

```
Mysql -h ホスト名 -u ユーザー名 -p データベース名
```
＊GUI(見ながら操作できる。例：phpMyadmin)などのツールを使ってSQLを扱うことができるのですが、CUI(真っ黒画面。例：ターミナル)でSQLを操作できるようにした方が良い！らしい。。

##①データベースの作成・削除
データベースの作成と削除は以下のコマンド。
このコマンドはテーブルを作ったわけではなく、テーブルの集合体、親を作ったというイメージ。

```
Create database データベース名;　//作成

Drop database　データベース名;　//削除
```

##②データベースの一覧表示

①で作ったデータベースを全て見ることができる。
一覧で表示されているデータベースの中から使用するデータベースを選択するのがUSEコマンド。
USEコマンドで選択したデータベースの中にテーブルを作っていく。

```
Show database; 　//一覧表示


Use データベース名;  //データベースの選択
```

##③テーブルを作成と削除

```

Create table members (id,name); //作成


Drop table members; //削除
```

Idとnameの2つのカラムを持ったmembersテーブルが作られる。
※一つのデータベースに複数のテーブルを作成することができる。

##④データの保存＝レコード(行)の追加

```
Insert into members(id,name,password) values(1,’higa’ ,’aaaa’);
```
`訳：membersテーブルのidカラム、nameカラム、passwordカラムに合わせて1、’higa’、’aaaa’という値(valuse)を保存してね〜`


注意するのが<strong>「挿入するデータはカラムのデータ型に合わせる」</strong>必要があります。


極端な例ですが、idカラムのデータ型がint型だった場合に「’1’（シングルクォーテーションで囲っているため文字列）」や「’いち’」という風に値を挿入しようとしてはいけない。


##⑤データの取得
個人的にはデータの取得が一番難しい気がします。
理由はデータベースに保存されているデータを自分の用途に合わせた形で取得するため、条件の指定方法などをしっかり考えなければいけないからです。

データの取得にはselect文を使用。
条件の指定にwhere句を使用。

| id|name| password |
|:-----------|------------:|:------------:|
|1|higa|aaaa|
|2|yara|bbbb|

```
Select * from members; //すべてのデータを取ってくる場合
```
`訳：membersテーブルのすべてのデータ取ってきて〜。`

```
Select * from members where id=2; //idが2のレコードをすべて取得する場合
```
`訳：memberesテーブルのidが2番の人のすべてのデータ取ってきて〜。`

```
Select name from members where id=1; //Idが1のnameだけを取得
```
`訳：membersテーブルからidが1番の人のnameカラム取ってきて〜。`

用語解説：from=テーブル名、where=取得するときの条件、*＝すべて

＊where句には「and」「or」などを組み合わせて使うことができる。また他にも検索条件をさらに詳しく設定できるので調べると面白い発見があると思います。


##⑥データの更新
| id|name| price|
|:-----------|------------:|:------------:|
|1|apple|200|
|2|orange|300|
|3|grape|400|
|4|melon|500|

Updateの用途は
元々保存していたデータの値が変わったときや間違えて違うデータを挿入したときにデータを更新する必要があります。

データの更新はupdateを使用します。

```
Update fluits set price='600' where name='orange;
```
`訳：membersテーブルのidが2番の人の名前をtamashiroに更新して〜。`


また、update文は複数のデータを一気に更新させることができます。

```
Update fluits set price=700 where price>=400;
```
`訳：fluitsテーブルのpriceが４００円以上の物を７００にしてください〜。`

##⑦データの削除
| id|name| password |
|:-----------|------------:|:------------:|
|1|higa|aaaa|
|2|yara|bbbb|
|3|arakaki|cccc|

```
Delete from members where id=1;
```
`訳：membersテーブルのidが1番の人のデータ(レコード)を削除して〜。`




また削除も条件指定で複数のデータを削除することができる。

```
Delete from members where age=2;
```
`訳：membersテーブルのidが2番の人のデータを削除してね〜。`


##最後に
これでSQLの基礎の基礎は大丈夫だと思っています。データの条件の詳細設定やデータの取扱いのセキュリティ対策などを学んでいきます。時間見つけてまた書きたいと思います。

また、どこかミスがあれば教えていただけると幸いです。
SwiftUI ベースのプロジェクトでの FCM 実装注意点

# はじめに
基本的な実装方法・証明書周りの設定方法は日本語の記事も多いのでそちらをご覧ください。
https://firebase.google.com/docs/cloud-messaging/ios/client?hl=ja

今回は SwiftUI でプロジェクトを作成した場合、つまり `AppDelegate` を後から追加した場合の注意点をご紹介します。

# 結論
FCM SDK は deviceToken を取得する処理の実装を Method Swizzling を利用して実現しています。ただし、これが正常に動作するのは `AppDelegate` を `@main` として利用している場合に限ります。
なので、 SDK の Method Swizzling に頼らず、以下の処理を明示的に記述する必要があります。

```swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Messaging.messaging().apnsToken = deviceToken
}
```

# 詳細
SwiftUI をベースにプロジェクトを作成した場合、以下のような形で `AppDelegate` を実装することになります。
この場合、 FCM SDK による Method Swizzling が `AppDelegate` に対して走らないため、開発者側で明示的に追記してあげる必要があります（ここの挙動は細かく調べたわけではないので、間違いがあればご指摘お願いします）

```swift
@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ...
        }
    }
}

final class AppDelegate: UIResponder, UIApplicationDelegate {
    typealias LaunchOptionsKey = UIApplication.LaunchOptionsKey
    func application(_ application: UIApplication, didFinishLaunchingWithOptions: [LaunchOptionsKey: Any]? = nil) -> Bool {
        return true
    }
}
```
詳しくはここに記述されています。
[実装入れ替えが無効な場合の APNs トークンと登録トークンとのマッピング](https://firebase.google.com/docs/cloud-messaging/ios/client?hl=ja#token-swizzle-disabled)

# さいごに
結論として、公式ドキュメントにもしっかり書かれている内容だったということになりますが、 SwiftUI メインでアプリを開発する場合は特に注意したほうがいいかと思い、記事として残してみました。
公式ドキュメント・SDK ともに後々仕様が変わる可能性がありますので、まずは最新の情報を確認した上でこの記事も参考にしていただければと思います。

最後まで読んでいただき、ありがとうございます！
フレックスボックスについて②

次にフレックスボックスの親要素について勉強していきましょう。
前回のフレックスボックスについてはこちら▶https://qiita.com/akari_0618/items/080dad83a550ea439fd2

#親要素に当てるフレックスボックス
少し複雑になるので整理しながらやっていきましょう。
まず出てくるのは
##①flex-direction
主軸の方向や向きを決めるプロバティです！

```style.css
.container {
  background-color: crimson;
  display: flex;
  flex-direction: row;
}
.case1 {
  background-color: aqua;
  width: 30%;
}

.case2 {
  background-color: burlywood;
  width: 30%;
}

.case3 {
  background-color: cornflowerblue;
  width: 30%;
}
```
１．flex-direction;row
ブラウザで表示すると変わらないように見えますのでスクショは省きますが、
これだと主軸は箇条書きリストで向きは左に向かっていきます。
2.flex-direction:column;
に変えてみましょう！
![スクリーンショット 2021-03-03 12.23.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/b0de2570-3233-6572-df62-1eae09ec0552.png)
積み重なっているのがわかりますかね！この場合は主軸が箇条書きリストから始まって下に続いて行きます！

ちなみにそれぞれにreverseという値がありますが、これはそれぞれ反対なので自分でやってみましょう！

##justify-content
中身のアイテムの間や周囲に間隔を配置する方法を定義します!
flex-directionの下にかきます。

```style.css
.container {
  background-color: crimson;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
```
1.space-between
要素の間が空きます！
![スクリーンショット 2021-03-03 12.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/f38b61df-7488-78ee-ecb9-5e12ab00deab.png)

2.center
真ん中に寄ります！
![スクリーンショット 2021-03-03 12.38.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/32c205c0-7068-8e2d-eca2-90eefd51c189.png)

3.space-around
![スクリーンショット 2021-03-03 12.40.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/c0684589-26a3-190f-c0b6-dafa667228c0.png)
space-betweenとの違いがわかりにくいですが、端も空いてる部分ですね！

4.space-evenly
![スクリーンショット 2021-03-03 12.44.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/720e1492-cae8-e1ea-d04c-c562a1dffc96.png)

##③align-items
こちらは子要素に直接当てるようです。もしこの子が当たんなかった場合はcontainerに高さをセットすればいいみたいです！
1.center
![スクリーンショット 2021-03-03 13.17.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/ab9e889f-103b-0933-6f83-f23fb606b5a8.png)

2.start
![スクリーンショット 2021-03-03 13.18.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/91c9c617-56c0-7a5f-6b05-4134fd87fd04.png)

3.end
![スクリーンショット 2021-03-03 13.20.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/608b24b1-678f-3000-4aee-fe0f44043134.png)

align-item は少し私も不安がありますが今、コードがこの状態なので、おそらく主軸が左で交差軸が上？になってるのかな？笑

```style.css
.container {
  background-color: crimson;
  display: flex;
  flex-direction:row;
  justify-content: space-around;
  align-items: flex-end;
  height: 200px;
}
```
【Heroku】メンテナンス画面をカスタマイズする

## 概要
- Herokuに載せたアプリをメンテナンスモードにした際、デフォルトではHerokuが用意しているメンテナンス画面が表示されます
- 見た目的にもセキュリティ的にも独自で作成した画面にしたほうがよいので、その方法を記載します。


## Herokuメンテナンスモード
- Herokuに載せたアプリケーションをメンテナンスモードにするには、Settings画面から切り替えます。

![Screen Shot 2021-03-03 at 12.53.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228400/6f14864b-961c-de40-21fc-457196ad1427.png)

- また、Heroku CLIを使用している場合は以下コマンドでも切り替えられます

```cmm
$ heroku maintenance:on
```
```cmm
$ heroku maintenance:off
```



- メンテナンスモード中に、対象アプリケーションにアクセスするとHeorkuが用意しているメンテナンス画面が表示されます。

![Screen Shot 2021-03-03 at 13.06.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228400/bc6afd28-d06e-80dd-5331-cea1b5bfe74c.png)

## メンテナンス画面の作成
- htmlかなんかで適当なメンテナンス画面を作成し、それをインターネット上からアクセス可能な場所に配置します
- 静的ページであれば、AWS S3やgithub pagesに置くとコストがほとんどかからずおすすめです

## Heroku設定
- Herokuアプリケーションの環境変数```MAINTENANCE_PAGE_URL```を新規に作成し、メンテナンス画面のURLを指定します。
- Heroku CLIであれば以下コマンドで指定します。

```cmm
$ heroku config:set MAINTENANCE_PAGE_URL="メンテナンス画面のURL" --app "アプリ名"
```

- ちなみにS3に配置したhtmlであれば以下のような指定になります

```
//<バケット名>.s3.amazonaws.com/maintenance.html
```

- 設定したら、反映されるまで1分程度待ちます。
- 以上で、自作のメンテナンス画面が表示されるようになります。

## 注意点
- メンテナンス画面に遷移しているのではなく、Herokuの用意したメンテナンス画面にiframeで表示されています。
    - そのため、ブラウザに表示されるURLはHerokuのURLになります
- HerokuアプリケーションはHTTPSなので、自作のメンテナンス画面もHTTPS化する必要があります。（httpのページをhttpsのメージにiframeで表示することができないため）
devise

deviseのインストール

https://qiita.com/Pirori3182/items/afd1604cb0d206b2e3cc

マイグレーションファイルに必要なカラムを追加する

[![Image from Gyazo](https://i.gyazo.com/bc7d4a087e1e6dc84c3f88b089843d99.png)](https://gyazo.com/bc7d4a087e1e6dc84c3f88b089843d99)

アプリケーションコントローラーに以下を記述
・ストロングパラメーターの設定
・deviseを使用したときだけ、configure_permitted_parametersが動くようにする。

[![Image from Gyazo](https://i.gyazo.com/80b2d8314b2885879c13f346faa855b1.png)](https://gyazo.com/80b2d8314b2885879c13f346faa855b1)

ユーザー新規登録のビューにてnicknameのフォームを追加
Discord botをAWS APIGateway+Lambdaで動かしたい

* 本記事は記載途中です *
* 現時点ではdiscord.pyがAPI GatewayのWebSocket I/Fの動きと連動させられないので、この手のラッパーを使わず、スクラッチで書く必要があるなーと考えています。 *

# Discordとは
テキスト+音声会話用コミュニケーションツールの一種。
競合としてはテキスト+音声両方ではTeamsとLINE、テキストのみであればSlack、音声会話ではZoom、WebEx、Skype辺りが競合する。

特徴としてはゲーム用途に特化させた設計になっていて、その方面に向けた機能が多い。
但し現在はゲーム用途以外でも使用するケースが増えているらしい。

# Discord BOTについて
その他のツールと同様に、特定イベントに対しテキスト応答を行う。(例えばユーザがチャンネルにJoinしたらいらっしゃいませ、とか)
そういったメジャーな処理に加えて、他ツールではAPI等が存在しない音声系の調整が可能なのが特徴。(全員ミュートなど)
(少なくともLINE、Teamsはいずれも2021/2月時点で各公式Docsには存在しない。またTeamsは不明だがLINEは2年以上APIの構成が変わってないので今後の更新は期待できそうにないと思う)

BOT作成者がBOTを公開状態にすると、原則自由に使用可能になる。

Discord自体の利用は無料であるが、BOTの処理を行うサーバは別途必要で、そのサーバ利用/維持費はBOT作成者が負担する。

# My BOTサーバインフラ方面設計
今回のポイントは「サーバ利用/維持費用」である。
費用やセキュリティ面を度外視するなら、グローバルIP+適当なドメイン付けたWebサーバを用意し、Discordからの処理を受け付ければ良いが
当然相応の維持費も要るし、セキュリティ対応も手間である。

というわけで調べても情報があまりなかったAWS API Gateway + Lambda(Python)でDiscord BOT作成を試みた。
(保険としてherokuやAWS EC2もあるが、ここは折角なのでServerlessで)

ラフのアーキテクチャは以下の通り。
![DiscordBOT_AWSArc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539237/3e371823-2ec3-3c00-8b07-8f6c7d7c0076.png)


HTTPのフロント部分のリクエスト受付はAPI Gatewayが対応し、その後の処理はLambdaのPythonが対応する。

API GatewayはAWSフルマネージドであり脆弱性対応はAWSが実施する。
多分時折中のEC2インスタンスが入れ替わったりするが、冗長化された上で実施されるため無停止である。
(たまたま運悪くリクエスト中にインスタンスシャットダウンを食らう可能性はあるが、確率はかなり低い上リトライすればOKである)

使用料は`100万リクエストあたり1.29USD`である。

LambdaはAWS上でスクリプト実行を行うプラットフォームで、所定のコードを置いておき各イベントに応じて起動が行われるマネージドサービスである。
Lamdba画面上から操作して実行したり、Lambda自体のcronで定期実行も可能であるが、今回はAPI Gatewayのリクエスト受信と連動させる。

使用料は`リクエスト10万件あたり 0.20USDと処理のCPU時間とメモリ量&利用時間に応じた費用`が発生する。

API GatewayとLambda現時点で想定月額利用料は`5.00USD/月`である。
別途通信料はあるが、テキストのみであるため一旦考慮しない。

この構成における最も大きなメリットは「処理を行わないIdle状態時には費用や手間が掛からない」点にある。
また相当量の処理を継続して実行しつづけるような状態でなければ、維持費はサーバ1台を起動しつづけるより安価になる想定である。
特に頻繁に処理を行うわけではなく、1日10回未満の処理を想定しているため、このメリットを最大に享受する構成になっている。


もし今後BOTを公開したり、Discordのチャンネル内のユーザが増えた場合は使用量に応じたAWS利用料が発生する見込みであるが
現時点でBOTを公開する予定はなく、ユーザもせいぜい2桁人数のため、1日10回未満程度の処理想定としている。

# 設計を詰めてみた結果(2021/3/2時点)
これら設計のアプリケーション部分はdiscord.pyを使用する想定だったが、
インフラ部分とdiscord.pyが噛み合わないことが判明している。

discord.pyは起動後、自身のプロセスが常駐しWebSocketを対応するが、
API Gateway+Lambdaでは以下のように、リクエストごとにLambda Functionを呼び出す形になるため噛み合わない。

以下URLより図を抜粋
https://qiita.com/G-awa/items/472bc1a9d46178f3d7a4
![AWSChatArc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539237/b4594c6c-6b86-1c78-9ff8-7fb61a032b19.png)

# 今後の進め方(2021/3/2時点)
1. API Gateway + lambdaを維持し、lambda functionにDiscordの生APIで実装する。

2. 大人しくEC2上でdiscord.pyを使う。

BOT自体は3月下旬に使用したいため、現時点では実装の早い2案を採用する予定である。
aws samでlambda layerを使う

## 背景

aws-samがどうやら使いにくいという噂がちらちら聞こえたのでどういうことか調べてみました。
一番の悩みは共通処理を書きにくいのでどうしても各ハンドラーにコピペの嵐をしてしまっているとのことです。（え！

## 調査

これはlambda-layerを使えば一瞬で解決。はい終了。
かと思ったら、そうでもなくてパス体系がローカルとlambda上でだいぶ変わってしまうことでうまくlambda-layerを使えないとのこと。

例えば、以下のようなフォルダ構成の場合。

```
├── handlers(lambda-function)
│   └── create_user
│       ├── app.py
│       └── requirements.txt
├── layers(lambda-layer)
│   ├── db_layer
│   │   ├── models
│   │   │   └── user.py
│   │   ├── setting.py
│   └── lib_layer
│       ├── lambda_common.py
│       ├── log_config.py
│       ├── requirements.txt
│       └── setup.py
```

ローカルで`handlers.create_user.app`から`db_layer.models.user`をimportする場合。

```python
from layers.db_layer.models import user
```

となると思います。ただ、これをlambdaにのっけたときとか`sam local start-api`で実行するとインポートエラーがおきます。
理由としては、lambda-layerは実行環境の`/opt/python/`以下に配置されるためです。

この場合のインポート方法は**pip installしたパッケージを使うのと似ています**

。。ということは、解決の方法としてはローカルで**layersをそれぞれパッケージとしてインストールすればいい**と仮説を立てました。

### 仮説検証

#### 1. layersのインストール

最低限の事だけ書いたsetup.pyを用意して（以下、例）

```python

from setuptools import setup

setup(
    name='db_layer',
    version='0.1.1',
)
```

`pipenv install -d -e layers/db_layer layers/lib_layer`を実行すると
Pipfileが以下のようになり、他の人が`pipenv sync -d`とかをやってくれれば環境が整うようになりました。

```
[dev-packages]
(略）
db-layer = {editable = true, path = "./layers/db_layer"}
lib-layer = {editable = true, path = "./layers/lib_layer"}

[requires]
python_version = "3.8"
```

#### 2. import方法の変更

先ほどのローカルでのインストール方法を

```python
from layers.db_layer.models import user
```

以下のように変更

```python
from models import user
```

以下の二つを確認。

1. unittestを実行してimport失敗しないこと
1. `sam local start-api`を実行して、正常に動くこと

## 結論

pythonのlambda-layerはローカルでインストールすればうまくパス周りの整合性がとれて、開発は捗ります。
デバッグもテストもしやすいし、samとはうまく付き合っていけそうだなという所感です。
それ踏まえてのレポジトリを貼っておきます。pythonで裏側作る際に参考程度に使っていただけると報われます。
※なにか不具合あっても補償はできませんが、質問やお問い合わせ、改善要望はお待ちしております。

https://github.com/omitsuhashi/lambda-sam-template
ValueError: Only one class present in y_true. ROC AUC score is not defined in that case.

#手っ取り早い解決方法
以下のようにdrop_lastをTrueで設定してあげましょう。

```python

train_loader = torch.utils.data.DataLoader(
        train_dataset,
        batch_size=batch_size,
        shuffle=True,
        num_workers=workers,
        pin_memory=True,
        drop_last=True,
        sampler=None)
```
#<参考>
このエラーの原因はラストのミニバッチの画像クラスがどちらか一方しかないことです。(下により詳しく載ってます)

https://github.com/defeatcovid19/defeatcovid19-net-pytorch/issues/4

ROC,AUCについてはここに詳しく載ってます。

https://www.randpy.tokyo/entry/roc_auc
AWS CLI メモ

# 概要
awsのcliを使う時に、profile周り毎回忘れちゃって調べるんで個人メモです。
（profile以外は、最近調査で使ったやつをメモとして記載、記事分けるべきだったかもですが）


# profile
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html

## profile作成
```
aws configure --profile test
```

## profile一覧
```
aws configure list-profiles
```

## profile削除
~/.aws/credentials
~/.aws/config

を編集して、消したいprofileの項目を消す
（configureのオプションに消す奴見つけれなかった）

# cognito
- ユーザープール、idプール構築前提
    - ユーザープール：認証 （ユーザー情報保持、ログイン許可など）
    - Idプール：認可 （AWSへの一時トークンの発行など）


## login
```
aws cognito-idp admin-initiate-auth \
--user-pool-id ${user_pool_id} \
--client-id ${cognito_client_id} \
--auth-flow ADMIN_NO_SRP_AUTH \
--auth-parameters \
USERNAME=${user_name},PASSWORD=${password}! \
--profile test
```

## identity poolからcognito_id取得（未承認ロール）
```
aws cognito-identity get-id \
--identity-pool-id ${pool_id} --profile test
```

## identity poolからcognito_id取得（承認ロール）
※調べて下記の指定っぽかったが、role設定の兼ね合いか、調査時にはできなかった。メモがわり

```
aws cognito-identity get-id \
--identity-pool-id ${cognito_identity_pool_id} \
--logins "cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxx=${id_token}" \
--profile test
```

## cognito idから一時クレデンシャル発行
```
aws cognito-identity get-credentials-for-identity \
--identity-id ${cognito_id} \
--profile test
```

## stsで発行されたcredencialの設定Role確認
※profile使わず、環境変数に設定してcli利用

```
export AWS_ACCESS_KEY_ID=xxx
export AWS_SECRET_ACCESS_KEY=xxx
export AWS_SESSION_TOKEN=xxx
aws sts get-caller-identity --profile test
```

# iot
https://docs.aws.amazon.com/cli/latest/reference/iot/

## publish
```
aws iot-data publish --topic "iot/12345/pos" --profile test
```
```
Effect: Allow
Action: "iot:Publish"
Resource: arn:xxx:topic/iot/12345/*
```

## アタッチポリシー
※policy-name: iot coreで作成したポリシー名
※target: cognito-identity-id or iot cert arn など

```
aws iot attach-policy \
    --policy-name PolicyName \
    --target "us-east-1:xxx" \
    --profile test
```

## モノに証明書を設定
※principal= cognito-identity-id or iot cert arn

```
aws iot attach-thing-principal \
    --principal "us-east-1:xxxxx" \
    --thing-name 12345 \
    --profile test
```

## アクセス元とポリシー変数について
※下記は検証・思考の流れ。こう考えてやってみたけどってメモです。
（最終的に出来るか不明。出来るようになれば更新しますが、、別方法で解決できそうだったんで一旦は捨てかなと。）

<hr>

deviceアクセス（pem利用）だと、
```${iot:Connection.Thing.ThingName}```
のポリシー変数で使えそうだが、cognito identity idで発行したクレデンシャル利用だと、何が入るんだろうという感じ。

cognito idをモノにアタッチして、そのidで発行したクレデンシャルでiot publishとかすれば、
アタッチした```${iot:Connection.Thing.ThingName}```にする権限にできるなかなと思ったら、そういう感じじゃなさそうだった。

あと、```${cognito-identity.amazonaws.com:sub}```辺り、使えばとも思ったけど、cognito_idとthingNameを一致させないとダメそうだし。。。cognito idをモノにアタッチした場合の利用方法（用途）がどうすれば良いかわからなかった。subのパラメータとか何かしら方法あるのかな？

この辺りが、うまくできるなら、、congito idと紐付けたモノにしかアクセスできないポリシーの設定とかができそう。


# 所感
- 検証ではポリシーで引っかかることが多い。
- サービスを構築している技術の事前知識ないと、説明の意味すらわからなのが辛い。。
- アプリ利用は縛る必要あるんで、わかっていない状態で手当たり次第はエラーの原因不明が多く難航しがち。

※設定側のIAMロールと、発行されたクレデンシャルでのIAMロールで、２面考える必要あるってのに後々気付いた。

この辺りのコーディングは、CLIで検証したことを、sdkで書き方換えるだけなので、設計さえしっかりしていれば、プログラム組むのは難しくないかもと思いました。

問題は設計、、、
WordPressのElementorプラグインで「プレビューを読み込めませんでした」とエラーになる

WordPressでElementorのプラグインを使おうと思ったところ、
> プレビューを読み込めませんでした

というエラーメッセージが表示されて編集ができない事象が発生しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1049264/03fa5fc5-ad07-6ce5-bc21-641e6fd08c00.png" width="300">
Elementorのログとかも出てなく、何が原因がよく分からなかったが、なんとか解決できたので、内容を記載します。

## テーマが原因

上記キャプチャの「さらに詳しく」をクリックすると以下の公式ページに飛びました。

https://elementor.com/help/how-to-fix-the-preview-could-not-be-loaded-error/?utm_source=editor-panel&utm_medium=wp-dash&utm_campaign=learn

公式のページで表示された解決方法がいくつかありました。
1つ1つ確認していくと、テーマの問題でした。

独自作成テーマを使用していて、デフォルトテーマに切り替えた時は、うまく読み込めたので、テーマが原因ということが分かります。

## functions.phpが原因

テーマが悪いってことは、感覚的にfunctions.phpかなと思って調べてみました。
テーマは違うが、以下の記事を見つけることができました。

https://forum.vektor-inc.co.jp/forums/topic/elementor%E3%81%AE%E5%AF%BE%E5%87%A6%E6%96%B9%E6%B3%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/

以下の記述で、デフォルトjqueryの読み込みをなくしていたのが原因でした。

```php:functions.php
wp_deregister_script('jquery');
```

WordPressだと、デフォルトjqueryの読み込みをなくすのは、よくありそうです。

## デフォルトjqueryの読み込みをなくすのはフロントのみとする

管理画面で編集している時は対象外にしたいので、is_admin関数を使うようにしたが、Elementorの編集時は管理画面と判断されませんでした。

どうやって判断すれば、と困っていたところ、Elementorのis_preview_modeという関数があることに、なんとか辿り着きました。

https://github.com/elementor/elementor/issues/6736

```php:functions.php
function my_delete_local_jquery() {
  if (!\Elementor\Plugin::$instance->preview->is_preview_mode()) {
    wp_deregister_script('jquery');
  }
}
add_action( 'wp_enqueue_scripts', 'my_delete_local_jquery' );
```
Juliaのインストール方法(Windows, Mac,Linux)

# はじめに
Juliaは2009年にMITに在籍していた4人の研究者が開発を始め，2012年にオープンソースソフトウェアとして公開が始まった．高速な動作，シンプルな構文，外部ライブラリとの連携が可能という特徴がある．
今回はJuliaのインストール方法についてまとめた．

# インストール方法
## Windows
[https://julialang.org/downloads/](https://julialang.org/downloads/)にアクセスし，パソコンのbit数にあわせてダウンロードする．installerまたはportableのどちらでも良い．installerをダウンロードした場合，ダブルクリックしJuliaをインストールする．
portableをダウンロードした場合，zipファイルを展開し，適当なディレクトリに移動させる．

### PATHを通す
コマンドラインから実行できるようにPATHを通す．
実行ファイルの場所を確認しPATHを追加する[^1]．
[^1]: PATHの通し方は[この記事](https://qiita.com/shuhey/items/7ee0d25f14a997c9e285)などを参照

installerを使ってインストールした場合は次のようにPATHを追加する．

```
C:\Users\(ユーザー名)\AppData\Local\Programs\Julia 1.5.3\bin
```

## macOS
[https://julialang.org/downloads/](https://julialang.org/downloads/)にアクセスし，macOS版をダウンロードする．ダウンロードしたファイルをダブルクリックする．
Applicationsフォルダに移動させる．
Julia-1.5.appをopenする．
### シンボリックリンクの設定
ターミナルから実行できるようにシンボリックリンクを設定する．
`/usr/local/bin`にPATHが通っているため，次のようにコマンドを実行し，この場所に設定する．

```
rm -f /usr/local/bin/julia
ln -s /Applications/Julia-1.5.app/Contents/Resources/julia/bin/julia /usr/local/bin/julia
```

## Linux
今回インストールした環境は次の通りである．

- WSL Ubuntu 18.04 LTS

Generic Linux on x86の64bitをwgetコマンドでダウンロードする．
[https://julialang.org/downloads/](https://julialang.org/downloads/)
にアクセスし，ダウンロードしたいファイルを右クリックし，リンクのURLをコピーすることでURLを確認できる．

```
wget https://julialang-s3.julialang.org/bin/linux/x64/1.5/julia-1.5.3-linux-x86_64.tar.gz
```

次に，tarコマンドでファイルを展開する．

```
tar zxvf julia-1.5.3-linux-x86_64.tar.gz
```

### シンボリックリンクの設定
展開したファイルを適当な場所に移動させるが，今回は/optに移動させた．

```
sudo mv julia-1.5.3 /opt
```

次に，シンボリックリンクを設定する．
`/usr/local/bin`にPATHが通っているためこの場所に設定する．

```
sudo ln -s /opt/julia-1.5.3/bin/julia /usr/local/bin/julia
```

## 実行方法
```
julia --version
```
と入力し，正しく設定されていることを確認する．
コマンドラインで`julia`と入力するとREPLが起動し，プログラムを実行できる．
REPLを終了する場合は`exit()`と入力する．
ファイルに書いたプログラムを実行する場合は

```
julia ファイル名
```

と入力する．

# 参考
- [MIT発の高度な数値処理をプログラミングできるJuliaの最新情報を紹介](https://thinkit.co.jp/article/17749)
- [【入門編】プログラミング言語Juliaの特徴、メリット・デメリットを解説](https://udemy.benesse.co.jp/data-science/data-analysis/julia.html)
- [初めてのJuliaとインストール (Windows & Linux)](https://qiita.com/ttabata/items/b05bb43d06239f968035)
- [Julia1.3をMacに導入](https://qiita.com/SatoshiTerasaki/items/41df235328badcf382eb)
- [Platform Specific Instructions for Official Binaries](https://julialang.org/downloads/platform/)
herokuでのProcfileの書き方

## 要約

herokuでProcfileに`web: python run.py`と書くと動かなかったが、
`web: gunicorn -k uvicorn.workers.UvicornWorker run:api`と書くと動いた。

## 以下詳細


`responder`で簡単なアプリを作った。

```python:run.py
import responder
import os

api = responder.API()


@api.route("/")
def index(req, resp):
    resp.text = req.method


if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5042))
    api.run(port=port)
```

ルートに来たリクエストのメソッド(GET,POST...)を表示するだけの簡単なアプリである。

これをherokuに上げるため、次のような`Procfile`を書いた。

```Procfile:Procfile
web: python run.py
```

この状態でアプリケーションをherokuにアップロードしたとき、エラーが発生した。

```:log
2021-03-03T02:25:34.944654+00:00 heroku[web.1]: Starting process with command `python run.py`
2021-03-03T02:25:40.000000+00:00 app[api]: Build succeeded
2021-03-03T02:25:43.750097+00:00 heroku[web.1]: Process exited with status 1
2021-03-03T02:25:43.829241+00:00 heroku[web.1]: State changed from starting to crashed
2021-03-03T02:25:43.836710+00:00 heroku[web.1]: State changed from crashed to starting
2021-03-03T02:25:43.533551+00:00 app[web.1]: WARNING:  You must pass the application as an import string to enable 'reload' or 'workers'.
2021-03-03T02:25:49.229908+00:00 heroku[web.1]: Starting process with command `python run.py`
2021-03-03T02:25:53.558366+00:00 heroku[web.1]: Process exited with status 1
2021-03-03T02:25:53.636099+00:00 heroku[web.1]: State changed from starting to crashed
2021-03-03T02:25:53.451857+00:00 app[web.1]: WARNING:  You must pass the appli
cation as an import string to enable 'reload' or 'workers'.
```



`Process exited with status 1`って言ってるが手元で`python run.py`をすると問題なく動く。

原理はよくわかっていないが、Procfileをgunicornを使う形式に変えたところ、動作した。

```:Procfile 
web: gunicorn -k uvicorn.workers.UvicornWorker run:api
``` 

flaskだと単に`gunicorn run:app`とかで行けると思われる。
Httpie で Synology の WebDAV にアクセスする

こちらと同じことを Httpie で行いました。
[cadaver で Synology の WebDAV にアクセスする](https://qiita.com/ekzemplaro/items/6d7deb3ff16f2cd348ca)
[curl で Synology の WebDAV にアクセスする](https://qiita.com/ekzemplaro/items/493faac63ba863892f6f)

ファイルのアップロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp01.txt
#
http --auth scott:secret PUT $URL @tmp01.txt
```

ファイルのダウンロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp02.txt
#
http  --auth scott:secret $URL > tmp02.txt
```

$HOME/.netrc を作成すれば、次でオーケーです。

より安全なファイルのアップロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp01.txt
#
http PUT $URL @tmp01.txt
```

より安全なファイルのダウンロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp02.txt
#
http $URL > tmp02.txt
```

$HOME/.netrc

```text:$HOME/.netrc
machine example.synology.me
  login scott
  password secret
```
EUC-JPでpreg_replace()を使いたいので代替になる方法を見つけた

# 結論

配列を渡す機能は代替できないが、参照は（もっと柔軟な形で）代替できる。そう、 `mb_ereg_replace_callback()` を使えばね。

# 環境

PHP5.4.1以降、mbstringが有効になっている必要があります。

# 前提

PHPのマルチバイト文字対応は、UTF-8が前提になっているものがあります。 `preg_replace()` 関数もその一つです。この関数はマルチバイト文字に対応していますが、UTF-8以外の文字コードには対応していません。
しかし例えばEUC-JPなど、どうしても古い文字コードを使わなければならない環境はあると思います。
そんな中でこれの代替になりそうなのは、 `mb_ereg_replace()` ですが、これは配列渡しや参照（`${0}`とかのやつです）が利用できないという弱点があります。
でも、UTF-8以外のマルチバイト文字で参照を利用したreplaceをやりたい！という方のための記事です。

# 説明

UTF-8以外のマルチバイト文字で参照を利用したreplaceが出来ないかというと、そんなことなかったです。 `mb_ereg_replace_callback()` がありました。
この関数は第2引数に関数をとることができます。その関数の引数に、第1引数の正規表現でマッチした部分が配列として入ります。これを利用すれば参照が使えます。しかも、関数の中で使えるのでもっと柔軟な形で利用できます。

## サンプルコード

```php
<?php

// 念のため利用するエンコーディングをEUC-JPに設定しておきます。
// php.iniの設定次第では、この行は要りません。
mb_internal_encoding("EUC-JP");
// echo mb_internal_encoding() . "\n";

$text = "あいうえお　かきくけこ　さしすせそ　たちつてと\n";
$text .= "なにぬねの　はひふへほ　まみむめも　やいゆえよ\n";
$text .= "らりるれろ　わおん\n";

// パターンは正規表現ですが、スラッシュで挟む必要はありません。
// また、少なくともEUC-JPを用いた場合、.は改行文字も含むようです。
$pattern = "([^　\n]+)([　\n])";

// 第2引数は無名関数を使うことができます。
// これにより、コールバック関数としてだけ使いたい関数があちこちに散らばるのを抑制できます。
// もちろん名前をつけた関数を利用することもできます。
// その方法はPHPの公式マニュアルを読まれるといいでしょう。
$result = mb_ereg_replace_callback(
  $pattern,
  function ($matches) {
    if ($matches[2] === "\n") {
      return $matches[1] . "," . $matches[1] . $matches[2];
    } else {
      return $matches[1] . "," . $matches[1] . ",";
    };
  },
  $text
);

echo $text;

echo "\n";

echo $result;

// $resultの中身は以下です。
// あいうえお,あいうえお,かきくけこ,かきくけこ,さしすせそ,さしすせそ,たちつてと,たちつてと
// なにぬねの,なにぬねの,はひふへほ,はひふへほ,まみむめも,まみむめも,やいゆえよ,やいゆえよ
// らりるれろ,らりるれろ,わおん,わおん

echo "\n";

```

ここで、第2引数の関数の引数にマッチした部分が入ります。その添字と中身の関係は、通常の参照の関係と同じで、0にマッチした部分全体、1以降はサブパターンにマッチしたテキストが入ります。

# まとめ

こんな感じで参照を使ったpreg_replace()の代替ができました。ちなみにpreg_replace()の方でコールバック関数を使いたいのならば、 `preg_replace_callback()` があるようです。
どうでもいいですが、Qiitaって全角文字は等幅フォントじゃないのですね。この記事書いてて気付きました。

# 参考文献
https://www.php.net/manual/ja/function.mb-ereg-replace-callback.php
https://www.php.net/manual/ja/function.mb-ereg-replace.php
https://www.php.net/manual/ja/function.preg-replace.php
https://www.php.net/manual/ja/function.preg-replace-callback.php
【UE4】Control Rig試し中…／ぷちコン15進捗 - 2021/03/03

[1]:https://historia.co.jp/ue4petitcon15
[2]:https://historia.co.jp/ue4petitcon14
[3]:https://youtu.be/loN69BeLba4
[4]:https://pt.slideshare.net/EpicGamesJapan/ue425controlrig
[5]:https://hogetatu.hatenablog.com/entry/2020/12/03/000009
[6]:https://www.unrealengine.com/marketplace/ja/product/control-rig-mannequin?sessionInvalidated=true

[株式会社ヒストリアさん主催の第15回UE4ぷちコン][1]の作業進捗。
[前回][2]は参加できなかったので、今回は頑張る。

# Control Rig をお試し中…

ドリキャスが撤退して、PS2が出るか出ないかの頃にやってた「ランタイムにリグを持ち込む試み」が、hoge 年経った今、ゲームエンジンで簡単に使えるようになって、非常に感慨深いです！ 
> ※そのゲームは残念ながら発売されず。

## 参考資料

- [猫でも分かる Control Rig UE4.25 版 - Youtube][3] と [そのスライド][4]
- [UE4.26 Control Rig における IK ノードまとめ - ほげたつブログ][5]
- [Control Rig Mannequin - UE4 Marketplace][6]

## イマココ

ひとまず、リグってこういうものだよねって知識をベースに組んでみた。
私プログラマだが、アニメーターさんと一緒に DCC ツールでリグを組んだこともあるデス。

手足のIKとか。
![20210303_1109.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/5a1f6dd3-ba6b-813d-3e08-01dbf57c26af.gif)

胸の角度を３つの背骨に配分して扱うのが好み。
![20210303_1118.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/7071f856-c2fd-add8-24d6-f5f41acc2e56.gif)

手のひらあたりを中心にして IK するようにしてみた。
![20210303_1125.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/9e4039cd-4335-669d-544d-b4349302bf0b.gif)

指リグ。これはかなりの難敵だった！
![20210303_1133.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/24998d8b-4264-ef4c-918c-5d19e469a045.gif)

まだ Forward Solver しか組んでおらず、Backward Solver どうするんだとか、ランタイムではどう動かすんだとかは調べていない。

## Control Rig エディタで気づいたこと (UE4.26.1)

超いい！　…が、まだこなれていない。バージョンアップに期待！

- ビューポートで F キーを押しても選択にフォーカスしてくれない。
    - 左上の▼メニューから「Focus Selected」を選ぶとフォーカスしてくれる。
- ビューポートでリグを動かして Ctrl+Z しても、一つ前の位置に戻ってくれない　…だけにとどまらず、Rig Graph でのノード編集内容がアンドゥーされて非常に焦る。
- コメントノードの不具合
    - エディタを立ち上げると、前回セーブした位置と違う位置に吹っ飛んでいることがある。
        - コメントに囲まれたノード群も一緒に吹っ飛んでいる。
        - 当面は、コメントでノードを囲まないようにしておいた方が安全か？
    - コメントを選択しても、詳細パネルに色やフォントサイズなどの設定項目が出ない。
        - コメント選択 → Rig Hierarchy のコントロールを選択 → グラフエリアの空いている空間をクリック　…とやると、コメントの詳細パネルが出た！
        - その他のノードも「All results have been filtered. Try changing your active filters above.」が出ていることがあるので、フィルタ文字列に(内部的に)ゴミが残っているのではないか？
        - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/db202eb8-3a69-b2a2-1a6a-19ec21a2e56f.png)
- リルートノード
    - エディタを立ち上げると、リルートノードが前回セーブした位置と違う位置にいることがある。
        - カーソルキーで動かすとこうなるっぽい。マウスで動かすと大丈夫っぽい。
    - あと、微妙に１グリッドずれていることがある。エディタ立ち上げ時に誤差か何かで別のところにスナップされたような…
- Sequence ノードが４つしか分岐できない…
- 新規ノードを作ると、最寄りのピンに自動的に繋いでくれる　…ありがた迷惑な気がします。
- 関数が作りたい。一つのグラフにゴチャっと書かなくてはならないため、スパゲティになる。
- Evaluate Curve の使いかたが分からない。[おかずさんの動画][3]のようには動いてくれない気がする。
    - ※おかずさんの動画はUE4.25版。私が今使っているのはUE4.26.1版

### おまけ：リルート(reroute)ノードでリテラルの代用をする

> バグ技かもしれないので、マネするときは気を付けてください。

![20210303_1153.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/b090c362-6faf-c2cb-9e84-ac37709ed1ca.gif)
GIFアニメには映っていないが、右クリックして「reroute」と打って、リルートノードを出してます。
…ていうか、普通に Make Literal Float とかが欲しいです。
フレックスボックスについて①

今回は前回の記事で作ったものからCSSのFlexboxを使っていきたいと思います。
今回取り上げるのはほんの一部なので、気になる場合は自分で調べてみてください👍

#フレックスボックスとは
横の主軸と縦の交差軸を使ってやるみたいなんですね。全然わからないんで、詳しくは自分で調べてみてください😂
私はなんとなくわかったので、とりあえず、進みます😂

##実装

結局なんだろうって方もとりあえず先に進んで見ましょう。
まず、index.htmlを書き換えます！　前回の記事はこちら！▶https://qiita.com/akari_0618/items/ac6eb7fae89f2329ed2c

```index.html
<link rel="stylesheet" href="css/style.css">
<div class="container">
  <section class="case1">
    <h1>箇条書きリスト</h1>
   <ul>
     <li>あいうえお</li>
     <li>かきくけこ</li>
     <li>さしすせそ</li>
   </ul>
  </section>
  <section class="case2">
    <h1>順序付きリスト</h1>
    <ol>
      <li>あいうえお</li>
      <li>かきくけこ</li>
      <li>さしすせそ</li>
    </ol>
  </section>
  <section class="case3">
    <h1>説明リスト</h1>
    <dt>あなたの名前は？</dt>
    <dd>山田花子</dd>
    <dt>あなたは女性ですか？</dt>
    <dd>はいそうです</dd>
  </section>
</div>
```
少しわかりにくいですが、新たにdivクラスにcontainerという親要素を追加します。
親要素とクラスが不安な方は▶https://qiita.com/akari_0618/items/3526fd7b751d9387667d
それではcssをいじっていきますね！

```style.css
.container {
  background-color: crimson;
  display: flex;
}
.case1 {
  background-color: aqua;
  width: 30%;
}

.case2 {
  background-color: burlywood;
  width: 30%;
}

.case3 {
  background-color: cornflowerblue;
  width: 30%;
}
```
子要素のcaseさんたちをwidth設定します！
そして、display:flex; を親要素に指定します！
『フレックスボックスはじまるよー！』の合図ですね👍

これを指定するとブラウザ上でこうなります。
![スクリーンショット 2021-03-03 11.49.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/6c37f892-517e-7541-44be-cc58d913fc6b.png)

横に整列しましたね！

次からは親要素に適応するフレックスボックスについて学んで行きましょう！
Amazon linux 2でsystemctlコマンドが見つからないとき



いつもと違うインスタンス内でsystemctlコマンドを使ってcrondの再起動をしようと思ったら
以下のエラーメッセージが出ました

## エラーメッセージ


```
$ sudo systemctl restart crond
sudo: systemctl: コマンドが見つかりません
```

## 解決方法


`systemctl`コマンドが使えなかったので`service`コマンドを使用しました

```
$ sudo service crond restart
Stopping crond:                                            [  OK  ]
Starting crond:                                            [  OK  ]
```

`service`コマンドを使用することで`crond`の再起動を行うことができました。

## よく使うコマンド

```
sudo service nginx status

sudo service nginx restart

sudo service nginx stop

```
LottieをリソースIDでデータバインディングしてコードをスッキリ

Lottieは簡単に素敵なアニメーションを追加できるAirbnbのライブラリです。
更に使いやすくresourceIdでデータバインディングできるようにカスタムBindingAdapterを用意して使ってみました。

[Lottie](https://airbnb.design/lottie/)

## カスタムBindingAdapterを作成

```java:LottieAnimationViewBindingAdapter.java

import androidx.annotation.RawRes;
import androidx.databinding.BindingAdapter;
import androidx.databinding.BindingMethod;
import androidx.databinding.BindingMethods;

import com.airbnb.lottie.LottieAnimationView;

@BindingMethods({
        @BindingMethod(type = com.airbnb.lottie.LottieAnimationView.class, attribute = "lottie_rawRes", method = "setAnimation"),
})
public class LottieAnimationViewBindingAdapter {

    @BindingAdapter("lottie_rawRes")
    public static void setAnimation(LottieAnimationView view, @RawRes final int rawRes) {
        view.setAnimation(rawRes);
        view.playAnimation();
    }
}
```

## ViewModelでResId用のLiveData<Int>を作成

```kotlin:HogeViewModel.kt

val animationResId: LiveData<Int> = Transformations.map(hoge) {
        when {
            hoge.value!! > THRESHOLD -> R.raw.rocket_in_space
            else -> R.raw.lighthouse
        }
    }
```

## レイアウトにバインド

```xml:hoge_fragment.xml

<data>
        <variable
            name="vm"
            type="com.hoge.HogeViewModel" />
    </data>

...

<com.airbnb.lottie.LottieAnimationView
            android:id="@+id/animationView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:lottie_autoPlay="true"
            app:lottie_loop="true"
            app:lottie_rawRes="@{vm.animationResId}" />
```
AWS EC2インスタンス内からRDSのMySQLにログインする

EC2インスタンスのターミナルからRDSのMySQLにログインする

# 目的

- EC2インスタンス内からRDSのMySQLにログインする方法をまとめる

# 実施条件

- EC2インスタンスとRDSインスタンスのセキュリティグループ設定やIAMの設定が正常に行われていること。
- RDSインスタンスのエンドポイント、MySQLのユーザ名、MySQLのユーザに紐づくパスワードがわかっていること。

# 詳細

1. EC2のインスタンスにsshでログインする。
1. 下記コマンドを実行してMySQLにログインする。

    ```terminal
    $ mysql -u MySQLのユーザー名 -p -h エンドポイント
    ```
1. ログインパスワードを問われたら入力する。
curl で Synology の WebDAV にアクセスする

こちらと同じことを curl で行いました。
[cadaver で Synology の WebDAV にアクセスする](https://qiita.com/ekzemplaro/items/6d7deb3ff16f2cd348ca)

ファイルのアップロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp01.txt
#
curl --user scott:secret -T tmp01.txt --url $URL -X PUT
```

ファイルのダウンロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp02.txt
#
curl --user scott:secret --url $URL -X GET > tmp02.txt
```

より安全なファイルのアップロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp01.txt
#
curl --netrc-file $HOME/.netrc -T tmp03.txt --url $URL -X PUT
```

より安全なファイルのダウンロード

```bash
URL=https://example.synology.me:5006/homes/scott/tmp/tmp02.txt
#
curl --netrc-file $HOME/.netrc --url $URL -X GET > tmp02.txt
```

$HOME/.netrc

```text:$HOME/.netrc
machine example.synology.me
  login scott
  password secret
```
numpy.ndarrayの連結

以下記事を参考にしています。
http://tanukigraph.hatenablog.com/entry/2017/08/23/195756

忘れやすいのでメモ。

```
import numpy as np

a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
c = np.array([[1,2],[3,4],[5,6]])
```
## 1. (2,2)×2 -> (4,2)

```
np.concatenate([a,b],axis=0)

# output
array([[1, 2],
       [3, 4],
       [5, 6],
       [7, 8]])
```
※concatnateで次元を上げることはできない

## 2. (2,2)×2 -> (2,2,2)
パターン１

```
np.stack([a,b],axis=0)

# output
array([[[1, 2],
        [3, 4]],

       [[5, 6],
        [7, 8]]])
```

パターン２

```
np.stack([a,b],axis=1)

array([[[1, 2],
        [5, 6]],

       [[3, 4],
        [7, 8]]])
```
M1 MacへのWebAssembly環境構築手順

# 結論

### 良い点

* WebAssembly(以下、Wasm)は実行環境を選ばない
* 他言語との連携が可能
* ５Gなど先の時代を見据えた高速な処理が可能
    * サーバーの処理をフロントで処理させることも可能
        * 動画変換など

### イマイチな点

* 資料が少ない
* 環境が整っていない
* 開発コストが高い(上記の理由により)

# 環境

* macOS Big Sur ver11.2.1
* zsh 5.8 (x86_64-apple-darwin20.0)

# 手順

## Node.jsのインストール

過去の[こちら](https://qiita.com/naoto24kawa/items/6c1be2296bb762ff283f)の記事を参照しました

https://qiita.com/naoto24kawa/items/6c1be2296bb762ff283f

## Rust のインストール

[公式サイト](https://www.rust-lang.org/tools/install)または[日本語サイト](https://doc.rust-jp.rs/book-ja/ch01-01-installation.html)から手順を参照

特段理由が無い場合は`rustup`を用いてインストールを行うことが推奨されている

```
> curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
```

インストール方法を聞かれるがデフォルトで良い

```
You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


   default host triple: x86_64-apple-darwin
     default toolchain: stable (default)
               profile: default
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
```

```
> 1
```

下記、メッセージが表示されていればインストール完了

```
Rust is installed now. Great!
```

注意点として
パスは通してくれているが、現在のシェルに反映されてないので再読み込みさせる

```
To get started you need Cargo's bin directory ($HOME/.cargo/bin) in your PATH
environment variable. Next time you log in this will be done
automatically.

To configure your current shell, run:
source $HOME/.cargo/env
```

```
> source $HOME/.cargo/env
```

## ライブラリをインストールする

Wasmへコンパイルするための標準ライブラリ

```
> rustup target add wasm32-unknown-unknown
```

```
info: downloading component 'rust-std' for 'wasm32-unknown-unknown'
info: installing component 'rust-std' for 'wasm32-unknown-unknown'
```

## wasm-packのインストール

Wasmアプリケーションのbuildのために利用します

```
> cargo install wasm-pack

Installed package `wasm-pack v0.9.1` (executable `wasm-pack`)
```

以上です

# 余談

データ通信以外がすべてフロントエンドの技術で済む時代も来るのか！といった感じ
これからますますの発展に期待するばかりです
M1 MacへのNode.jsインストール手順

# 結論

以下の順でインストールします

```
Homebrew -> anyenv -> nodenv -> Node.js
```

# 環境

* MacBook Air (M1,2020)
* macOS Big Sur バージョン 11.2.1
* zsh 5.8 (x86_64-apple-darwin20.0)
    * デフォルト状態でzshが利用されている想定

# Homebrewのインストール

過去の[こちら](https://qiita.com/naoto24kawa/items/59cdae4377f84d248a48)の記事を参照しました

https://qiita.com/naoto24kawa/items/59cdae4377f84d248a48

# anyenvのインストール

`anyenv`を利用する理由としては、今回利用する`nodenv(Node.js)`を始め、`rbenv(Ruby)`、`pyenv(Python)`など他の言語もまとめて管理できるためです

```
# Homebrewからanyenvをインストールする
> brew install anyenv

# シェルにパスを通す
> echo 'eval "$(anyenv init -)"' >> ~/.zshrc $ exec $SHELL -l

# 現在のシェルへ反映させる
> exec $SHELL -l
```

# nodenvのインストール

`nodenv` は Node.js のバージョン管理ツールです

```
# anyenvからnodenをインストールする
> anyenv install nodenv

# 現在のシェルへ反映させる
> exec $SHELL -l
```

# Node.jsのインストール

(20210303時点)現在のM1 Macのデフォルト環境では14．*以前はインストールできません
※ Rossetaなどを利用してIntelベースに置き換えることができれば可能です

```
# インストール可能なバージョンを確認する
> nodenv install -l
(中略)
15.10.0

# バージョン名を指定してインストールする
> nodenv install 15.10.0

# インストールしたバージョンを反映させる
> nodenv global 15.10.0
```

# 余談

まだまだすべてがM1 Macに対応できているわけではないので注意が必要になります
連続した処理待ちで中間をキャンセルする排他制御

表現が難しい…。

タスクが非同期で複数殺到して処理待ちになるような状況で、現在処理中のタスクと一番最後に来たタスクだけ残して、その他（中間）はキャンセルとする。というものを実装したくなった。

##実現したいこと

下記のようなイメージ。

```
・タスク1がやってくる
1 →　　　( )


・タスク1が重めの処理を開始、続けてタスク2がやってくる
2 →　　　(1)


・タスク2はタスク1が処理中なので待機、続けてタスク3がやってくる
3 →　 [2](1)


・この時点で、
　　 3[2](1)


・タスク2は無かったことになり消滅
　　 3[ ](1)


・タスク3がタスク1の次で待機
　　　[3](1)
```

例えばスライダーコントロールとかで、値が変化するたびに値に応じて何らかの処理をしないといけないけど、その処理が若干重い場合。
全部律儀にこなしてたらガクガクになっちゃうので、1発目と最後のだけ処理して、他は捨てたい、そんな時。

##アルゴリズム

セマフォを2つ使う。1つ目は初期値2、2つ目は初期値1にする。そしてセマフォとは別にカウンタXを用意して、3つ目以降のタスクが来たら増やすようにする。
wait1、wait2はそれぞれセマフォ1、セマフォ2のwaitの箇所。

```
・タスク1がやってくる

カウンタX　wait1　wait2　処理
　　0　　　　2　　　1
1 →　　　　 [ ]　　[ ]　　( )


・タスク1が2か所のwaitを通過し、重めの処理を開始。タスク2が来る

カウンタX　wait1　wait2　処理
　　0　　　　1　　　0
2 →　　　　 [ ]　　[ ]　　(1)


・タスク2はwait1を通過するが、wait2のカウンタは0なので足止め、タスク3が来る

カウンタX　wait1　wait2　処理
　　0　　　　0　　　0
3 →　　　　 [ ]　　[2]　　(1)


・wait1の直前でタスク3はwait1のカウンタを見て、0なら…

カウンタX　wait1　wait2　処理
　　0　　　　0　　　0
　　　　　 3[ ]　　[2]　　(1)


・カウンタXを1増やし、セマフォ2とセマフォ1のカウンタを1ずつ解放

カウンタX　wait1　wait2　処理
　　1　　　　1　　　1
　　　　　 3[ ]　　[2]　　(1)


・タスク2とタスク3がそれぞれwaitを通過するが…

カウンタX　wait1　wait2　処理
　　1　　　　0　　　0
　　　　　　[ ]3　 [ ]2　 (1)


・wait2の出口には罠が仕掛けてあり、もしカウンタXが0じゃなかった場合、
　タスク2はカウンタXを1減らして、自らは退散する
　タスク3はwait2で足止め。つまりタスク3が来る前の状態に戻る

カウンタX　wait1　wait2　処理
　　0　　　　0　　　0
　　　　　　[ ]　　[3]*　 (1)


・処理を終えたタスク1は、セマフォ2とセマフォ1のカウンタを1ずつ解放して退散

カウンタX　wait1　wait2　処理
　　0　　　　1　　　1
　　　　　　[ ]　　[3]　　( )*


・タスク3がwait2を通過して処理に入る。これはタスク2が来る前の状態と同じ

カウンタX　wait1　wait2　処理
　　0　　　　1　　　0
　　　　　　[ ]　　[ ]　　(3)


・タスク3も処理を終えるとセマフォのカウンタを解放して退散
　これは一番最初の状態に戻ったことになる

カウンタX　wait1　wait2　処理
　　0　　　　2　　　1
　　　　　　[ ]　　[ ]　　( )*
```

こんな感じでイケるんじゃないかと！

##実装

C#でやってみたけど、まあ他の言語でも出来そう。

```csharp
//--------------------

private System.Threading.SemaphoreSlim semaphore1 = new System.Threading.SemaphoreSlim(2, 2);
private System.Threading.SemaphoreSlim semaphore2 = new System.Threading.SemaphoreSlim(1, 1);
private int count_x = 0;

//--------------------

private void CutTask() {
	Task.Run(() => {
		if (semaphore1.CurrentCount == 0) {
			System.Threading.Interlocked.Increment(ref count_x);
			semaphore2.Release();
			semaphore1.Release();
		}
		semaphore1.Wait();
		semaphore2.Wait();
		if (count_x > 0) {
			System.Threading.Interlocked.Decrement(ref count_x);
			return;
		}

		HeavyProcess();

		semaphore2.Release();
		semaphore1.Release();
	});
}

//--------------------
```

##感想

4つ目以降のタスクが来たら処理順が変わっちゃうんじゃないかとも思ったけど、3つ目が来てから2つ目が抹殺されて詰められるまでは多分一瞬なので、基本的に一度に3つ以降のタスクが長時間溜まるような状況は無いんじゃないかと思う。あまり自信無し。
oracle sqlで1vs多テーブルの最新シーケンスを取得する

## 記事概要
oracle sqlで1vs多テーブルの最新シーケンスを取得する方法を述べます。
例では、会員毎の最新の送信メールを取得します。

## 想定テーブル
以下の2つの`メンバテーブル`と`メール送信テーブル`が、1vs多の関係となっている想定。

#### メンバテーブル
#####  説明
会員を管理するテーブル。
#####  主キー
pk: MEMBER_ID

#### メール送信テーブル
#####  説明
会員ごとのメール送信を履歴管理するテーブル
#####  主キー
pk: MEMBER_ID, MAIL_SEQ

## SQL
### サンプルSQL

```sql:sample.sql
-- 最新シーケンスのデータをとってくる
SELECT
  MEMBER_ID
  , SENT_TIMESTAMP
FROM
  (
    -- ID単位でシーケンスの降順に並び替え
    SELECT
      MEMBER_ID
      , SENT_TIMESTAMP
      , ROW_NUMBER() OVER (
        PARTITION BY
          MEMBER_ID
        ORDER BY
          MAIL_SEQ DESC
      ) AS ROW_NO
    FROM
      MAIL
    WHERE
      DELETE_FLAG = '0'
  )
WHERE
  -- 最新に絞る
  ROW_NO = 1
```
### 肝となる部分
#### ROW_NUMBER() OVER 
列の番号を付与する。

#### `PARTITION BY` と `ORDER BY` の組み合わせ
ID単位で並び替えを設定する。
VS CodeでPower Appsを作れるか試してみた

# きっかけ
ローコードでブラウザ上でポチポチするだけでアプリを作れてしまうPower Appsですが (だいぶ雑な説明ですが)、普段コードを書いてアプリを作っている方からすると「わざわざブラウザーでカチカチやらなきゃいかんのが云々」という煩わしさもあったわけです。

この度、Power Appsのソースコードをいじれるようになるというアナウンスがあったので、VS CodeでPower Appsが作れるか！ということにチャレンジしてみました。

↓こちらがアナウンスの内容

https://powerapps.microsoft.com/en-us/blog/source-code-files-for-canvas-apps/


# どこをいじるか
ファイル構成とかはアナウンスに書いてあるので割愛しますが、実際どこをいじればいいのかは空のアプリとコントロール1つ追加したアプリで差分を取った方が手っ取り早いです。

ボタンを一個おいて、変数に文字列を設定するだけのアプリを作り、ソースコードを除いてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/a8096e14-6ed4-ba33-5738-864b6ac61440.png)

下図は空のアプリとボタンを1つ置いたアプリの差分ファイルです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/a92b8a95-d80e-0660-3800-6bf86b270644.png)

...「ボタン一個でこれか」

各ファイルで何をしているのか見てみると

- ControlTemplates.json : アプリで利用しているコントロールに関する基本情報。利用しているコントロール種類のみここに含まれる
- Entropy.json : アプリ上に配置されているすべてのコントロールに対して設定されたUnique IDが書かれている
- Screen1.editorstate.json : Screen1の編集状態。ここが一番謎
- Screen1.pa.yaml : いわゆるPower Appsで画面でいじっている内容。ボタンの設定や数式はここ
- button_2.0.0.xml : ボタンというコントロールの定義xml。これもアプリにあるコントロール種類のぶんだけ必要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/d6f61e3c-e988-03c1-0bfd-6811baa5e033.png)

ということで、これらのファイルをいじればよさそうです！

# テキストラベルを追加してみる

上の例したがって、ラベルを1つ追加してみます。すでにボタンで `test`という変数に`Hello World`をセットしているので、この`test`の値を表示させてみましょう。

ラベルコントロールの定義などは一から作るものではないので、適当に手元にあったアプリから持ってきます。
この内容を踏まえて、ControlTemplates.jsonを更新します。（主にIdとバージョンに気を付けつつ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/53fe2d7b-55a0-62b9-38f1-2fe9c2fde228.png)

ユニークIDは数字なので、被らないように設定。EditorStateは謎ですが、これも他のアプリから拾ってきて、Label1 に変更します。

ここまできてやっとPower Apps感が出てきますが、最後にScreen1.pa.yamlを編集します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/36408f3b-147a-c583-839a-edd5eea06e58.png)

当初「なんでyamlなんだ？」と思っていたけど、jsonで書くよりも式が圧倒的に見やすいですね。Power Appsは " ダブルクォーテーションを多用するので、そのたびにエスケープされていたら見にくすぎるし。

ということで、ここまでの内容を保存して、再度msappにpackし直します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/b7af5e2e-22ea-8ee6-c4fc-ba8c16b2a562.png)

###成功！！

無事ボタンだけのアプリにラベルが追加され、しかも変数が設定された状態になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/263ff2a7-7acd-6c24-a1bb-136c7610277a.png)

# おわり
無事VS CodeだけでPower Appsのアプリを作成 (というか改修) できました。
ただやりたいことに対して労力が見合わない気はしますね。

あくまでもチームでPower Appsのアプリを管理・作成する上でのバージョン管理・差分チェックの方法ととらえた方がよさそうです。
【Ruby on Rails】FactoryBotとFakerについてまとめ

初学者です。
テストコードがなぜか大好きです。

Ruby on Railsでテストコードを書く際にFactoryBotとFakerを使うと効率的にできます。
使い方をまとめます。


## 前提条件

Rspecを導入済みであること

## FactoryBot

FactoryBotとは、Railsで利用できるGemです。
FactoryBot用のファイルであらかじめのインスタンスに定める値を設定しておき、各テストコードで使用します。
例えばユーザー登録のテストコードで、ユーザー名やメールアドレスやパスワードをFactoryBotにまとめておくことで効率的に記述をすることができます。

## FactoryBot導入

下記のように`Gemfile`の`group :development, :test do`に`gem 'factory_bot_rails'`と記述します。

```Ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0'
  
# 以下を追加する
  gem 'factory_bot_rails'

end
```

ターミナルで下記のコマンドを実行しGemを導入します。

```Ruby:ターミナル
bundle install
```

このあとにテストコードを記述するためのファイルを生成すると、`specディレクトリ`配下に`factoriesディレクトリ`と`FactoryBot用のファイル(例：users.rbなど)`が生成されますが、既にテストコード用のファイルを生成している場合などは生成されないので手動で作成しても問題ありません。

`specディレクトリ`配下に`factoriesディレクトリ`と`FactoryBotを記述するためのファイル`を作成します。

例：spec/factories/users.rb

そのファイル内に記述していきます。

```Ruby:spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name                  {'test'}
    email                 {'test@example.com'}
    password              {'123456'}
    password_confirmation {password}
  end
end
```

上記のように記述しておけば、テストコード内で下記のように記述してデータを使い回すことができます。

```Ruby:spec/models/user_spec.rb
user = FactoryBot.build(:user)
```

上記の例では`user`という変数にFactoryBotのデータを入れているので、例えば`user.name`のように呼び出して使うことができます。

このままでもいいのですが、実際のサービスはユーザーがどんなデータを入れてくるかわからないこともあるのでそれを想定していた方がいいと思います。
そのために使うのがFakerです。


## Faker
Fakerとは、Railsで利用できるGemです。
ランダムな値を生成してくれて、人名や住所や電話番号など様々用意されています。
[Faker公式Github](https://github.com/faker-ruby/faker)
アニメの名前とか登場人物とかもあって見てるだけでも面白いです。

ちなみに`日本語`のデータがよければ`gimei`というGemもあります。
例えばバリデーションで日本語のカナじゃないとダメとかにしてる場合はFakerよりもgimeiが使いやすいと思いました。
[gimei公式Github](https://github.com/willnet/gimei)


## Faker導入

下記のように`Gemfile`の`group :development, :test do`に`gem 'faker'`と記述します。

```Ruby:Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails', '~> 4.0.0'
  gem 'factory_bot_rails'

# 以下を追加
  gem 'faker'
end
```

ターミナルで下記のコマンドを実行しGemを導入します。

```Ruby:ターミナル
 bundle install
```

先ほどのFactoryBotの内容をFakerを利用したものに変更します。

```Ruby:spec/factories/users.rb
FactoryBot.define do
  factory :user do
    name                  {Faker::Name.initials(number: 2)}
    email                 {Faker::Internet.free_email}
    password              {Faker::Internet.password(min_length: 6)}
    password_confirmation {password}
  end
end
```

書き方は公式のGIthubにも書いてあるのですが
`Faker::`の後に指定したいものを選択します。

例えば名前だけでもたくさんあります。

```Ruby:Faker

Faker::Name.name                 #=>フルネームの名前
Faker::Name.first_name           #=>firstnameだけ
Faker::Name.initials             #=>イニシャル
Faker::Name.initials(number: 2)　#=>2文字のイニシャル
```

基本的に公式に書いてある通りに記述すればOKなので簡単にできます。
コンソールでデータを見ると面白いですよ。


以上です。
cadaver で Synology の WebDAV にアクセスする

Ubuntu 20.10 で確認しました。
Synology に、WebDAV Server がインストールされ、ルーターの設定も完了しているものとします。

クライアントを Ubuntu にインストール

```bash
sudo apt install cadaver
```

tmp01.txt というファイルがあるフォルダーで、それを、Synology にアップロードします。

```text
$ cadaver https://example.synology.me:5006
Authentication required for SYNO_WebDAV Storage on server `example.synology.me':
Username: scott
Password: 
dav:/> cd homes/scott/tmp
dav:/homes/scott/tmp/> put tmp01.txt
Uploading tmp01.txt to `/homes/uchida/tmp/tmp01.txt':
Progress: [=============================>] 100.0% of 29 bytes succeeded.
dav:/homes/scott/tmp/> quit
```

tmp02.txt というファイルを Synology からダウンロードします。

```text
$ cadaver https://example.synology.me:5006
Authentication required for SYNO_WebDAV Storage on server `example.synology.me':
Username: scott
Password: 
dav:/> cd homes/scott/tmp
dav:/homes/scott/tmp/> get tmp02.txt
Enter local filename for `/homes/uchida/tmp/tmp02.txt': ./tmp02.txt
Downloading `/homes/scott/tmp/tmp02.txt' to ./tmp02.txt:
Progress: [=============================>] 100.0% of 20 bytes succeeded.
dav:/homes/scott/tmp/> quit
```

Username と Password の省略
$HOME/.netrc に次のように書き込みます。

```text:$HOME/.netrc
machine example.synology.me
  login scott
  password secret
```
（備忘用）TypeScriptのconst assertion

主にconstantsな値を扱うときに、`as const`(const assertion)をつけて、
constの書き換えをtsで検知する。

```
const CONST1 = {
  REGULAR: 1,
  SUB: 2,
} as const

const CONST2 = {
  REGULAR: 1,
  SUB: 2,
} 
```

```
CONST1.SUB = 3; // Error
CONST2.SUB = 3; // No Error
```
ULボックスのその他

この記事ではUlボックスの中身の紹介をします。
前の記事でも紹介しましたが、ここではその他について紹介しますね😊

#①箇条書きリストについて
これは、リスト項目についてのタグでしたね。

```index.html
<section class="case1">
 <ul>
   <li>あいうえお</li>
   <li>かきくけこ</li>
   <li>さしすせそ</li>
 </ul>
</section>
```


#順序付きリストについて

```index.html
<section class="case2">
  <h1>順序付きリスト</h1>
  <ol>
    <li>あいうえお</li>
    <li>かきくけこ</li>
    <li>さしすせそ</li>
  </ol>
</section>
```
ちょっと混乱しそうですが、前回と違いolタグで囲んでいます。
これは「オーダードリスト」と読みます。
#説明リストについて

```index.html
<section class="case3">
  <h1>説明リスト</h1>
  <dt>あなたの名前は？</dt>
  <dd>山田花子</dd>
  <dt>あなたは女性ですか？</dt>
  <dd>はいそうです</dd>
</section>
```
上記では質問形式になっていますが、下記のようになっています。
dt▶定義語・用語
dd▶dtで囲った用語を説明する文章

ブラウザで表示するとこうなります。
![スクリーンショット 2021-03-03 10.50.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1033397/97243a9a-6d0c-62de-7bd8-ebb85dac939a.png)

ではこれらの要素をCSSを使って少し動かして行きたいなと思います。
次の記事で動かしていきます。