OmniAICreator/Qiita-1.07M huggingface dataset:
食事と血糖値上昇の関係を、血糖値センサーで見える化してみた

# はじめに
メタボが気になり、糖質ダイエットをしたが、調べてみると
食べ物によっては血糖値の上がり方が異なるようだ。
じゃ、何を食べると太るのかをFreeStyleリブレという血糖値センサーを付け、
食べたものと血糖値の上昇を分析してみた。
※ちなみに、糖尿病ではなく、あくまで好奇心でセンサーを付けてみた

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [FreeStyleリブレとは](#Chapter1)
1. [早速見てみよう](#Chapter2)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# FreeStyleリブレとは
　2週間で使い捨てのセンサーとそこからデータを読み取り装置があり、
　センサーは一つ7500円、読み取り装置も7500円ほど。

二の腕についているのがセンサー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/9f565ab5-14a1-93b2-c920-34547ba485ee.png)
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/3c1b973d-dce5-2abb-3d6a-0ef84c6d5ffc.png)
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/4ab327a3-07b0-2cba-7dc6-9e85ccc7a150.png)



センサーはどうやって測っているかというと、
つけるときに、取付け機でバチっとやると、チューブのようなものが
腕の中に残り、血液から血糖値をとるというもの

最新版は読み取り機ではなく、スマホでできるようだ。

読み取り機をPCにつなげば、データをダウンロードでき、食事内容はスマホにメモっておき
後でエクセルに書き込み、ピボットで分析した


<a id="#Chapter2"></a>
# 早速見てみよう（データからの分析）
縦軸がセンサーで測った血糖値、横軸が食後の経過時間だ。
色の違いは食事内容である。線の上下の特徴から分析すると以下がある
(i)  食後1時間で急激に上がって、その後あまり下がらない (赤茶色）
(ii) 最初から低いまま（緑色）
(iii)  ゆっくりと上昇

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/0e473368-7e9e-4261-bad2-083c470fd255.png)

答えは、、

(i)  食後1時間で急激に上がって、その後あまり下がらない 
　**『白米と肉』**　を食べた時のもの。細かく言うと近くの焼き肉屋の焼肉丼である。
　炭火で焼いているので、とてもごはんが進む
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/259e56a4-16d7-fb91-4bd4-a5afbeb734d2.png)

ちなみに、**『同じ食事を同じ時間に食べたあと30分のウォーキング』**した時のグラフがこれ（青線）
食後一時間の血糖値の上昇が抑えられている！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/ef089a16-9ebd-dbca-12e2-213f95493cad.png)

(ii) 最初から低いまま（緑色）
**『肉』！**　牛肉のステーキ1枚200gくらい。牛肉は糖質がほとんど含まれていないので、血糖値の上昇がなかった。
肉ダイエットというのは、血糖値が上がらないという点では効果的のようだ。　

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/6678e499-9a38-5192-bb55-b5ea5e9a96a8.png)

(iii)　ゆっくりと上昇  
**『そば！』** 具体的にはざるそば。そばは低GI食品食品ということで
血糖値の上昇が緩やかというのは本当だ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608742/987e9335-a5c4-b9f4-e941-915fb05eb594.png)

今回はここまで。
次回は食品から、血糖値の動きを見ていく

<a id="#reference"></a>
# 参考文献
- [リンクテキスト](URL)
【初心者でもわかる】supやsubがあるテキストでも下線を引く方法

#どうも7noteです。supやsubだと下線がずれるので、対策方法を考える

**上付き文字を指定できる`<sup>`**や、
**下付き文字を指定する`<sub>`**などがありますが、
これらに下線を指定すると表示がちょっとおかしくなってしまいます。


【崩れてしまう例の画像↓】
![スクリーンショット 2021-06-02 13.45.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/06a51642-5fc3-d1f7-9900-cf75960eb171.png)

```index.html
<p>水の化学式はH<sub>2</sub>O<sup>※</sup>である</p>
```
```style.css
p {
  text-decoration: underline;
}
```

このようにsupやsubでは表示位置が上下にずれてしまうため下線がまっすぐ続きません。

これをまっすぐ線を引くための方法を考えていきます。

## 解決方法①： テキストをすべて画像にする

画像にすれば万事解決ですね。何の問題もありません。
しかしテキストの修正やSEOの事を考えるとあまり最適な方法とはいえなさそうです。

## 解決方法②： 下線をborderや疑似要素で再現する

下線がずれるのは、`text-decoration: underline;`を使っているからなので、この指定を使わずに下線を引けば問題ないはずです。

```style.css
p {
  line-height: 1.2;  /* borderの位置はline-heightを使って微調整が必要 */
  display: inline-block;
  border-bottom: solid 1px #000;
}
```

![OK02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/707aa43f-0860-6812-c7bd-729948898d0a.png)


## 解決方法③： vertical-alignを使って表示位置を微調整する（※subのみ）

subにしか使えない方法ですが、vertical-alignの指定を変えることで下揃えにすることが可能です。

```style.css
sub {
  vertical-align: baseline;
}
```
![OK3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/8a419dc8-5c0b-d0e8-d7f7-06bef552186d.png)


## 妥協案①: 対象部分の下線を消す

inline-block要素にすることで、下線をつけないようにすることができます。

```style.css
sup,sub {
  display: inline-block;
}
```
![SOSO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/31ca722a-6f00-b3c3-1de1-ed5ad824a680.png)

下線がずれたままよりはまだ見栄えがいいですね。指定が簡単なので妥協案の1つとしてはOKかなと思えます。


## まとめ

解決方法3つ+妥協案1つを考えました。もしかしたら他にももっと良い方法があるかもしれませんので、もし「こうすればもっと簡単に下線がきれいになるよ！」という案があればぜひコメントください。

まとめとしては、

- `<sup>`、`<sub>`では下線がずれる
- borderを下線の変わりに使用できる
- inline-block要素には下線が出ない

このようなところでしょうか？
ぜひ他にもアイデアあればコメントください。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
Firefoxの履歴をcsvでエクスポートする

## 経緯
* 2021-06-04にiOS版Firefoxをアップデート(v34.0)したら使いにくくなったのでChromeに乗り換えようかなと。
* ブクマはエクスポートできたし、ついでに検索履歴もエクスポートしようとしたら、できない...!?!?
* ってことで直接.sqliteから引っ張ってくることにしましたのでその過程をメモします。

## 1. Firefoxの履歴ファイルを見つける
* Macの場合、place.sqliteにこれまでの検索履歴がぜーーんぶ入ってる。<br>
    * /Users/{ユーザー名}/Library/Application Support/Firefox/Profiles/xxxxxxx.default/places.sqlite
* <b>念の為、place.sqliteをデスクトップなどにコピーしておく。</b>

## 2. コマンド実行してcsvエクスポートする
```q
$ brew install sqlite3 
// sqlite3をインストール

$ cd {places.sqliteをコピペしたディレクトリ}
// places.sqliteを置いているディレクトリに移動する
$ ls
// place.sqliteがあるか確認しとく

$ sqlite3 places.sqlite
// データベースにアクセス

$ sqlite> .tables
//テーブル情報をチェック

$ sqlite> .mode csv
// csv形式でエクスポートする設定
$ sqlite> .output hoge.csv
// csvのファイル名前を設定する（上の例ではhoge.csv）
$ sqlite> SELECT * FROM moz_places;
// moz_placeに検索履歴の情報が格納されているのでまとめて引っこ抜いてくる
// title,url,last_visit_dateなどが列名として設定されてる。
```
* こんな感じのテーブル情報になってるっぽい。↓
![moz_places.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527664/be494d0d-fdca-2558-8ebd-f61c45bef19b.png)

```q
$ sqlite> .exit
// DBを終了
// 出来上がったcsvファイルを開くと確認できます！！
```

## おわりに
* 案外簡単にエクスポートできるんですね...。
* ちなみに、Firefoxのアドオン「SQLite Manager」からも確認することできます。

ではでは〜👏
[iOS] LicensePlistを使用してライセンスを設定アプリに表示してみた

#はじめに
アプリに使用しているライブラリ等のライセンスを明示する方法が分からなかったので、調べてみると`LicensePlist`という「設定アプリにライセンスを自動で一覧表示してくれる」ツールが便利そうなので使用してみました。備忘録です。
[LicensePlist というiOSアプリ利用ライブラリのライセンス一覧を生成するツールを作りました](https://medium.com/swift-column/license-plist-c0363a008c67)
[mono0926/LicensePlist](https://github.com/mono0926/LicensePlist)

# 環境
[Xcode] 12.4
[iOS] 14.4
[MacOS] 10.15.7

#導入手順
CococaPods, Homebrew, Mintを使用してインストールすることが推奨されていました。
本記事ではCocoaPodsを利用しました。

```:Podfile
pod 'LicensePlist'
# Installation path: `${PODS_ROOT}/LicensePlist/license-plist`
```
まずプロジェクトファイルの下に`Settings.bundle`ファイルを作成します。
<img alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667697/759d907c-9eff-5b8d-b8ce-c1bdb6d44fc9.png">

次に、XcodeのTARGETSの`[Build Phases]`タブで`Run Script`を追加して以下を記載します。
自動で中身を更新してくれるためこの方法が推奨されていますが、もちろん手動でも実行出来ました。

```:
if [ $CONFIGURATION = "Debug" ]; then
 ${PODS_ROOT}/LicensePlist/license-plist --output-path $PRODUCT_NAME/Settings.bundle
fi
```

<img alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667697/7a628b45-b77d-1cb1-c7df-2455d646b96a.png">
あとはSetting.bundleの中身(画像ではRoot.plist)を画像のように編集してtitleやFilenameを指定し、アプリを実行します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667697/f542aa05-e851-50eb-6c76-42c6979370c3.png)
アプリを実行すると、設定アプリの中の自分のアプリにLicenseセルが表示されて中身を確認できます。
今回初めて`Settings.bundle`を触ったのですが、Preference Items内の項目を編集することで、設定アプリに表示する項目も変更することができるようです (例えば上の画像のitem1~item4)。
![4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667697/901bee98-2324-ca90-fb1f-da3d0d58e71d.gif)

#最後に
私を含め、アプリを作るときにライセンス表示について分からない初学者は少なくないのではないでしょうか。
ライブラリをいくつも使用する際は、手動だと時間もかかると思うので簡単に取り込むことができる`LicensePlist`を今後も活用させていただきます。

#参考文献
この記事は以下の情報を参考にしました。
- [LicensePlist というiOSアプリ利用ライブラリのライセンス一覧を生成するツールを作りました](https://medium.com/swift-column/license-plist-c0363a008c67)
- [mono0926/LicensePlist](https://github.com/mono0926/LicensePlist)
[Minecraft Forge 1.12.2] shadowJarをreobf（再難読化）するbuild.gradleの設定メモ

# 環境

- Minecraft Forge 1.12.2-14.23.5.2855

# 背景と原理と調べたこと

## デフォルトの挙動

素のForge Mdkに付属しているデフォルトの`build.gradle`では、`gradle build`でjarファイルを生成できるようになっているが、このjarファイルは既に再難読化が施されている。

`build.gradle`の中で再難読化に関連する行は次のたった1行のみである。

```groovy
jar.finalizedBy('reobfJar')
```

この行を除去すると再難読化のされていないjarファイルが得られる。

## shadowJar

ここでいうshadowJarとは、`plugins { id 'com.github.johnrengelman.shadow' version '2.0.4' }`をすることで利用可能になる、依存先jarを同封した一体化jarファイル（fat jar）を作れるGradleプラグインである。

これを使うと一体化jarをファイルを生成する`shadowJar`タスクが追加され、`shadowJar`タスクがおそらく`jar`タスクに依存する（もしかしたらソースセットだけ参照しているのかもしれない（未調査））形で動作する。

そして、**このとき生成される一体化jarファイルは再難読化が行われていない**ため、そのままMinecraftで読み込もうとすると多くの場合起動中に落ちる（具体的にはMinecraft固有の難読化対象のメソッドやフィールドやクラスを参照した瞬間にErrorになる）。

## reobfの原理

Gradleのforgeプラグインを入れると、デフォルトで`reobfJar`という`tasks`から参照できない隠れたタスクが生成される模様。

`reobfJar`は`tasks`から取得することはできないが、次のように書くと`delegate`として`reobfJar`タスクが得られる。

```groovy
reobf {
    jar {
        println delegate
    }
}
```

`reobfJar`タスクのクラスは`net.minecraftforge.gradle.userdev.tasks.RenameJarInPlace`であった。
このタスクは、「`input`プロパティが示す入力ファイルを再難読化して一時ファイルに置いた後、それを入力ファイルに上書きコピーする」という、「既存ファイルの書き換え」な動作をする。

この書き換え動作をいつ行うかを定義するのが次のコードである。
これをすると`jar`タスクの実行直後にその出力物を書き換えたりする動作ができる。

```groovy
jar.finalizedBy('reobfJar')
```

# 解決策

`shadowJar`タスクの出力ファイルを書き換えるreobf系タスクを作り、それを`shadowJar`タスクの`finalizedBy`に指定する。

新しくreobf系タスクを作るには、次のように`reobf`ブロックの中でjarファイルを生成するタスクで空のブロックを作ればよい（空だから何もしないかと思いきやこれが無いと`reobfShadowJar`が勝手には作られないっぽいので必要）。

```groovy
reobf {
    shadowJar {

    }
}
```

そしてそのタスクを`finalizedBy`で指定してやる。

```groovy
tasks.shadowJar.finalizedBy('reobfShadowJar')
```

あとは`shadowJar`タスクが実行されると、その出力物は自動的に再難読化が行われる。

# 参考資料

↓実例

https://github.com/MirrgieRiana/MirageFairy2019/blob/72642cd137c7caef7512129e5ecac0ba4567ddbe/build.gradle

↓誰かによるサンプルコード

https://gist.github.com/Commoble/ddc75e819a690198c15d26564d139333

↓forge版dynmapにおける実例

https://github.com/webbukkit/dynmap/blob/c258c5efa48ef8c3a32f0711055410ee36ab6dc2/forge-1.12.2/build.gradle
Laravel6 Migration まとめ

#はじめに
Migrationは新規テーブルの作成、カラム追加など、DBの更新を行うための機能。
今回は使い方をもう一度整理するためにまとめた。
※マイグレーションは①作成②実行の２段階に分けられる
作成は設計図を作る作業でそれを実行(migrate）しないとDBに反映されないので要注意！

#ファイルの作成・カラムの追加

```
$ php artisan make:migration create_{テーブル名}_table　//マイグレーションファイル作成

$ php artisan make:migration add_{カラム名}_to_{追加先のテーブル名}_table　//カラムの追加
```

(database/migrations)配下に作成される。
###オプション
```
$　php artisan make:migration create_users_table --create=users

$　php artisan make:migration create_users_table --table=users
```

--create、--tableのうしろに=でマイグレーションファイルで扱うテーブルの名前を引数として渡
すと、
出来上がるマイグレーションファイルはそのテーブル名を含んで雛形が作られる。
特別な理由がない限り付けておくのが無難か。（雛形と全く違うとか）

#Migration 実行

```
$ php artisan migrate
```
このコマンドで実際にテーブルが作成される。
これしないと反映されませんからね！
###ロールバック
Migrationした時に定義ミスを起こしてしまった時巻き戻しが可能。

```
# 最後に適用されたマイグレーションをロールバック
$ php artisan migrate:rollback
```
Migrationは確認することもできる。
ロールバックはやらかしがちなので落ち着いて行おう。

```
# migrationsテーブルの中身

mysql> SELECT * FROM migrations;
+----+---------------------------------------------------+-------+
| id | migration                                         | batch |
+----+---------------------------------------------------+-------+
|  1 | 2016_12_19_000000_create_tables                   |     1 |
|  2 | 2018_07_18_102240_add_column_mogumogu             |     1 |
|  3 | 2021_02_05_194658_create_hogehoge_table           |     2 |
+----+---------------------------------------------------+-------+

$ php artisan migrate:status //こちらのコマンドでも確認できるよ
```

#新たにMigrationしたい時
再度Migtationしたいときは` php artisan migrate`ではだめです

```
$ php artisan migrate:refresh
$ php artisan migrate:fresh
```


refreshはマイグレーションファイルの down メソッドを呼び出してテーブルの削除などを行ってからmigrateされます。rollback（巻き戻し)してから再実行する感じ。

freshはdownメソッド呼び出さずに、全テーブルをdropしてからmigrateがされます。
dropてのはまあ削除するってことですね。

しかしrefresh と　fresh 
これをどう使い分けるのかが調べたが出てこない。。。
基本はfreshを使っているが、わかったら追記する。
分かる方いらっしゃいましたらコメントくださいませ。
いつもぶつかって何となく調べて解決してきたAndroid周りの対応 その2

# 前置き
- いつも同じようなエラーが発生する（気がする）……
- 多分Unityのversion upしたタイミングな気がしている……
- でもその度調べて解決してるが、結局いつも原因忘れてしまっている……
- 以前書いた、「[いつもぶつかって何となく調べて解決してきたAndroid周りの対応](https://qiita.com/nir_takemi/items/b30152064ad9a7cbefbf)」とはまた別の事象
    - 以前の件はAdMobに関係するところ
- 今回はUnityでのAndroidビルド時に発生

# 環境
- Unity2020.3.9f1



# 事象
- UnityでのAndroidビルド時に下記のエラーが発生。

```sh
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/xxx/git/InfiniteStrawberry/Temp/gradleOut/launcher/build.gradle' line: 3

* What went wrong:
A problem occurred evaluating project ':launcher'.
> Failed to apply plugin [id 'com.android.internal.version-check']
   > Minimum supported Gradle version is 5.6.4. Current version is 5.1.1. If using the gradle wrapper, try editing the distributionUrl in /Users/nir/git/InfiniteStrawberry/Temp/gradleOut/launcher/gradle/wrapper/gradle-wrapper.properties to gradle-5.6.4-all.zip

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s

UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) (at /Users/bokken/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:189)
```

# 結論
- gradleのpath（Preference > External Tools）の指定が誤っていた

# 解決方法
- Preference > External Toolsのgradle部分をチェックする形にした  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/65dc842f-c231-36a4-a362-e88c8d1e539f.png)
- 前のUnityのversionの時には逆に指定しないと通らなくて、直接指定してた
    - ただ、その設定を今回引き継いだら今回のversionだとNGだった……
    - 前versionだと直接UnityをDL&installしていたが、今versionはUnityHub経由でinstallして、Android関連のモジュールもUnityHubで追加できている状態なので、ずっとUnityHubで管理している人は多分同事象は発生しない？

## その他
- 調べていく上で、同じようなエラーが発生した場合、プロジェクトのパスにASCII文字以外（日本語とか）が含まれると発生するケースもあるらしい
    - [UnityのAndroidビルドでGradleエラー](https://qiita.com/n2gate2000/items/c0fc1b671168f1959ee0)

# 参考資料
- [Can't compile Unity Project with ARCore SDK - Problem with Gradle](https://stackoverflow.com/questions/64381387/cant-compile-unity-project-with-arcore-sdk-problem-with-gradle)
【JQuery】【備忘録】ボタンの活性化・非活性化は意外と簡単にできる

今回は、備忘録としてJQueryを使った、ボタンの活性化・非活性化について書きます。
また、最後にある一定時間だけ非活性にする方法なども載せます。

#基本の形

JQueryでの記載は以下になります。

###ボタンを非活性にする
```javascript
$(要素).prop('disabled',true);
```
###ボタンを活性化する
```javascript
$(要素).prop('disables',false);
```

#例　ボタンをクリックしたら非活性化する

例として、ボタンをクリックした後、非活性化することをやってみます。

```html:html
<button id="hoge">ボタン</button>
```

```javascript:JQuery
$(function(){
 $('#hoge').on('click',function(){
  $(this).prop('disables',true);
 });
});
```
このような流れになります。

#おまけ
ボタンをクリック→一定時間(１分間）非活性化→活性化の流れをやってみます。

```html:html
<button id="hoge">ボタン</button>
```

```javascript:JQuery
$(function(){
 $('#hoge').on('click',function(){
  $(this).prop('disables',true);
 setTimeout(function () {
      $('#hoge').prop('disabled', false);
    }, 60000);
 });
});
```
一定時間非活性化から活性化をするには、setTimeoutを使い、一定時間経過したら
ボタンを活性化する処理にしてみました。

#参考
https://qiita.com/ponsuke0531/items/ed8dc7991311a9a2a5a7
https://qiita.com/pugiemonn/items/5db6fb8fd8a303406b17
https://mugenweb-note.com/web/jquery/timer-reload
dockerでwordpressのローカル開発環境を作る

# 概要



# やること

Dockerを使ってローカル環境に、1分でWordPressを構築する
https://zenn.dev/mochiblock/articles/0fc6bd37320080

上記の記事を参考にした。


```dockerfile
version: '3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     # ドキュメントに書いてある内容に、vlumesの部分だけ追記（任意）
     volumes:
       - .:/var/www/html
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
volumes:
    db_data:
```

https://docs.docker.jp/compose/wordpress.html

公式ドキュメントの上記でなかったのは公式ドキュメントだと

```
volumes:
  - .:/var/www/html
```

がなく、これがないと.phpの反映などをローカルでできない。今回はローカルで開発したいので編集できるようにする。

# コマンド

```
docker-compose up
```

上記コマンド後

ブラウザで`http://localhost:8000`
【論文紹介】下顎部電気刺激を用いた咽頭での後味の増強・持続時間延長

#論文紹介
論文：下顎部電気刺激を用いた咽頭での後味の増強・持続時間延長
著者：上野 新葉（明治大），青山 一真（東大），中村 裕美，宮下 芳明（明治大）
https://research.miyashita.com/papers/D208/paper.pdf

#どんなもの
　咽頭で感じられる後味の増強と持続時間を延長するシステム。あごの下に陽極、首の後ろに陰極を配置して、電気刺激を送ることで咽頭への味覚提示を行った。実験の結果、下顎部電気刺激によって後味の強度を強く感じ、持続時間を長く感じることができた。

#先行研究と比較してすごいところ
　これまでの研究は口腔(唇の内側)内を対象としたものが多いが、この論文で咽頭(食道につながるところ)においての味覚提示を電気刺激を用いて実現した。

#技術や手法のキモ
　あごの下に陽極、首の後ろに陰極を配置して、電気刺激を送ることで咽頭への味覚提示を行う。


#検証方法
　<font color="gray">電気刺激は約3MA、飲料は冷蔵庫約8度で保存したスポーツドリンク(DREAMeiji)を用いて行った。電気刺激の有無を提示した状態でスポーツドリンクを飲ました後にもう一方のを飲ませた。</font>

　先に飲んだものと比べて咽頭で感じる後味の強度と持続時間がどのように変化したのかを紙に記入してもらう。(後味の強度/持続時間を-3(弱い・短い)から+3(強い・長い)までの７段階で評価し、等しい場合は０をつけてもらう)
　<font color="gray">評価の一貫性と正確性を確認するための実験も行った。</font>

#議論
　飲み物以外では同じような実験の効果を得ることはできるのか。(食べ物で噛んだ後でも同じように後味の増強は起こるのか)
　後味以外の味を変化させることはできないのか。

#気になった論文
　無限電気味覚ガム
AWS Client VPN 管理者ガイドで証明書の部分をやってみた

# 初めに

ついに1次情報を見つけました。嬉しい！やってみよう！

https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/client-vpn-admin-guide.pdf

# やってみた

Linux/macOS編です。7ページから8ページにかけてやってみます。

**`yum` パッケージをアップデートする**

```
sudo yum update -y
```

**`git` コマンドをインストールする**

```
sudo yum install git -y
```

**OpenVPN Inc の easy-rsa リポジトリをクローンする**

```
git clone https://github.com/OpenVPN/easy-rsa.git
```

**easy-rsa ディレクトリに移動する**

```
cd easy-rsa/easyrsa3
```

**PKI環境を構築する**

> PKI は、Public Key Infrastructure の略であり、「公開鍵基盤」と訳されます。これは、「公開鍵」による「基盤（インフラ）」を表しています。「公開鍵」とは「公開鍵暗号方式」という特殊な暗号技術を指します。この技術を用いることで、暗号化、デジタル署名、認証といった様々なセキュリティ対策が実現できます

以下リンクより抜粋。

https://www.ipa.go.jp/security/pki/013.html

```
./easyrsa init-pki
```

**認証局を立てる**

>信頼できる第三者機関 (TTP： Trusted Third Party)に公開鍵の所有者を保証してもらう方法です。TTP は、公開鍵の所有者の本人性をなんらかの方法で確認し、公開鍵とその所有者を保証する証明書(Certificate)を発行します。証明書には、公開鍵とその所有者を証明する情報が記載され、改ざんを防ぐために TTP の署名が付与されます。証明書を発行する TTP のことを、認証局 (CA： Certification Authority)といいます。

以下リンクより抜粋。

https://www.ipa.go.jp/security/pki/031.html

```
./easyrsa build-ca nopass
```

Common Name は適当に入力します。

```
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:testname
```

**サーバ証明書と秘密鍵を生成する**

```
./easyrsa build-server-full server nopass
```

**クライアント証明書と秘密鍵を生成する**
これらは Clinet VPN エンドポイントの設定ファイルに必要です。

```
./easyrsa build-client-full client1.domain.tld nopass
```

**ACMにキー・証明書をアップロードするためのディレクトリを作成する**

```
mkdir ~/custom_folder
```

**作成したキー・証明書を作成したディレクトリに移動する**

```
cp pki/issued/server.crt ~/custom_folder
cp pki/private/server.key ~/custom_folder
cp pki/issued/client1.domain.tld.crt ~/custom_folder
cp pki/private/client1.domain.tld.key ~/custom_folder
cp pki/ca.crt ~/custom_folder
```

**作成したディレクトリに移動する**

```
cd ~/custom_folder/
```

**ACMにサーバ証明書・サーバの秘密鍵・中間証明書をアップロードする**

```
aws acm import-certificate --region ap-northeast-1 --certificate \
 fileb://server.crt --private-key fileb://server.key --certificate-chain fileb://ca.crt
```

アップロードできました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/b6c056cc-592f-b8b2-9c63-a2f9ff1fdbe8.png)

# 参考記事

https://docs.aws.amazon.com/ja_jp/vpn/latest/clientvpn-admin/client-vpn-admin-guide.pdf

- 1.3  PKI で実現できること

https://www.ipa.go.jp/security/pki/013.html

- 3  認証局と電子証明書

https://www.ipa.go.jp/security/pki/031.html

https://blog.serverworks.co.jp/tech/2019/06/10/awsclientvpn/
lsp-modeでRubyのファイルを表示した際にエラーが発生する

Spacemacsのlsp-layerを有効にし、`.rb` ファイルを開いた際に発生したエラーの対応方法

## エラーメッセージ
```
Server ruby-ls:94381/starting exited with status exit(check corresponding stderr buffer for details). Do you want to restart it? (y or n) 
```

## 対応
LSPのバックエンド(Rubyの場合はsolargraph)への接続ができない状態なので、下記のコマンドでライブラリをインストールする

```
$ gem install solargraph
```
残プロ　第-4回　~生存確認をLINENotifyで~

# 番外編ってことで

今回は初回につくったもの(mementomori.py)を利用して生存確認システムを作ります．このご時世，いつどこで死ぬかわかりませんからね．

システムといっても使うものはpythonとタスクスケジューラのみです．

![生存確認チャート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578927/fc4dbddd-d3bb-ad73-e662-aa93e2a585fd.png)

こんな感じで超シンプルに作成していきます．

# LINENotify部分

こちらの素晴らしい記事を参考にしてトークンの発行まで行ってください．超簡単！
**あらかじめ「生存確認用」のライングループを作成しておき，トークンはそのグループ宛てで発行してください.**

[超簡単]LINE notify を使ってみる
 https://qiita.com/iitenkida7/items/576a8226ba6584864d95


# pythonプログラム

~~~notify.py
import requests

if __name__ == '__main__':
	send = "\nPCが起動しました"
	send_dict = {'message': send}

	TOKEN = 'ここにトークンをペースト'
	url = 'https://notify-api.line.me/api/notify'
	TOKEN_dict = {'Authorization': 'Bearer ' + TOKEN}

	requests.post(url, headers=TOKEN_dict, data=send_dict)
~~~


※pythonの環境が古い場合，実行時にSSLErrorがでる可能性があります．新しく環境を構築する等して対応してください


# タスクスケジューラへ登録

1.タスクスケジューラを起動．
2.基本タスクの作成．
3.タスク名を記入．"生存確認"等，任意で．
4.トリガーを「コンピューターの起動時」に設定
5.操作を「プログラムの開始」に設定
6.プログラムにはpython.exeを．
　引数の追加に実行する.pyファイル名.
　開始に.pyファイルまでのpathを記入．
7.下記画像のようになっていれば完了

![タスク登録.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578927/729eb662-43ba-0c7d-2048-4a1ce49fc66f.png)


# LINEグループに招待

あとは家族なり，親しい友人なりを生存確認グループに追加し趣旨を伝えて完成です．
これで孤独死も怖くない！


# 追記　*6/6

トリガーが「コンピューターの起動時」だとうまく実行できないことがありました．「ログオン時」に変更することで解決します．
ElixirでiOSのPUSH通知

# はじめに
こんにちは。僕は普段Elixirで開発をしています。
Elixirでバックエンド開発をしている中で、iOSへのPUSH通知を実装したのでどうやって実装したかをメモとして残しておきます。

## Pigeonの導入
https://github.com/codedge-llc/pigeon

僕はiOSに通知を送信するためにPigeonというライブラリを使用しました。
デバイスのトークンと設定ファイルさえ用意すればPUSH通知を簡単に送信することができます。

## デバイストークン取得
```swift:AppDelegate.swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    // Convert device token to string
    let tokenParts = deviceToken.map { data -> String in
        return String(format: "%02.2hhx", data)
    }
    let token = tokenParts.joined()
    print(token)
    UserDefaults.standard.setValue(token, forKey: "APNKey")
}
```

僕は最初は`AppDelegate.swift`にトークンをprintさせて入手しました。なお、このトークンはXcode内のエミュレータではなく実機でアプリをrunしないといけなかったので注意してください！

## 設定ファイルの用意
開発環境内でPUSH通知の確認をするので、`dev.exs`にpigeonの設定を記述しました。

```dev.exs
...
config :pigeon, :apns,
  apns_default: %{
    key: "priv/cert/AuthKey_XXXXXX.p8",
    key_identifier: "XXXXXX",
    team_id: "IDIDIDIDID",
    mode: :dev
  }
...
```

## 通知の送信
```elixir
message
|> Pigeon.APNS.Notification.new(device_id, Notifications.topic())
|> Pigeon.APNS.push()
```

あとはこんな感じで通知が送信できます。
これだと通知のタイトルが表示されなかったりするので、

```elixir
message
|> Pigeon.APNS.Notification.new(device_id, Notifications.topic())
|> Pigeon.APNS.Notification.put_alert(%{"body" => message, "title" => "お知らせ"})
|> Pigeon.APNS.push()
```

こんな感じにしたりすると通知にタイトルを付けたりとかできます。

短い記事でしたが以上です。
scikit-learn導入時にOSErrorが出たときのメモ

ちょっとした回帰の実装をしてみようと思い、scikit-learnをpipでローカル環境(Windows10)に導入することにしました。

```
C:\Users\[ユーザー名]>pip install scikit-learn
```

しかしエラー。

```:scikit-learnインストール時のエラーメッセージ
ERROR: Could not install packages due to an OSError: [Errno 2] No such file or directory:
```

エラーの原因はインストール先のパスが長すぎることらしいです。
Windows10ではデフォルトでパス名の文字数が260文字までに制限されているので、以下の投稿を参考に文字数制限を解除しました。

https://qiita.com/y-shoji/items/19def45edf582646f584

やったことは以下の通りです。

1. スタートメニューから [グループポリシーの編集] へ
2. [コンピューターの構成] > [管理用テンプレート] > [システム] > [ファイルシステム]
3. [Win32 の長いパスを有効にする] をダブルクリック
3. [有効] のラジオボタンをonにして、画面下部の [OK] をクリック

以上でパス名の文字数制限を撤廃できます。もう一度インストールすると…

```:scikit-learnのインストール成功
C:\Users\[ユーザー名]>pip install scikit-learn
Collecting scikit-learn
  Downloading scikit_learn-0.24.2-cp37-cp37m-win_amd64.whl (6.8 MB)
     |████████████████████████████████| 6.8 MB 3.3 MB/s
・・・（中略）・・・
Installing collected packages: scikit-learn
Successfully installed scikit-learn-0.24.2
```

無事に導入できました。めでたしめでたし。
Linux: ディスク容量不足の調査に活用できるコマンド

ディスク容量不足の調査について、活用できるコマンドをメモしておきます。
なお、権限不足でディレクトリ内を確認できないことがあるため、rootで実行することを推奨します。

###### 実施環境：

```Linux:Linux
[root@testhost ~]# uname -a
Linux testhost 4.18.0-147.8.1.el8_1.x86_64 #1 SMP Thu Apr 9 13:49:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[root@testhost ~]# echo $SHELL
/bin/bash
```

# 1. 現在のディスク使用率を確認する

次のコマンドを実行することで、指定したディレクトリの所属するディスクの使用率が確認できます。

```Linux:Linux
df -h ディレクトリパス
```

以下、実行例です。

```Linux:Linux
[root@testhost ~]# df -h /var/log
Filesystem                   Size  Used Avail Use% Mounted on
/dev/mapper/c1_testhost-var  4.0G  1.3G  2.8G  32% /var
```

ディレクトリ/var/logは/varでディスクが切られているため、/varにマウントされているディスクについての情報が表示されます。
Sizeが総容量、Usedが使用容量、Availが空き容量、Use%が使用率です。

# 2. サイズの大きいファイルを抽出する

次のコマンドを実行することで、指定したディレクトリ配下のファイル及びディレクトリをサイズの降順で表示できます。

```Linux:Linux
du -ah ディレクトリパス | sort -hr | head -表示個数
```

以下、実行例です。
上位3個を表示しています。

```Linux:Linux
[root@testhost ~]# du -ah /var/log | sort -hr | head -3
14M     /var/log
6.0M    /var/log/anaconda
3.1M    /var/log/anaconda/journal.log
```

duコマンドのオプション"-a"を外すと、ディレクトリのみが表示されます。

```Linux:Linux
[root@testhost ~]# du -h /var/log | sort -hr | head -3
14M     /var/log
6.0M    /var/log/anaconda
700K    /var/log/sa
```

特定のファイルやディレクトリを除外する場合は、grepを挟むとよいです。

```Linux:Linux
[root@testhost ~]# du -ah /var/log | grep -v /var/log/anaconda | sort -hr | head -3
14M     /var/log
812K    /var/log/dnf.log
700K    /var/log/sa
```

# 3. 長期間更新されていないファイルを抽出する

次のコマンドを使用することで、長期間更新されていないファイルを検索できます。

```Linux:Linux
find ディレクトリパス -mtime +日数 -size +サイズ -type f | xargs ls -hl
```

以下、実行例です。
「更新日時が7日前より古く、サイズが1MBより大きいファイル」を検索しています。

```Linux:Linux
[root@testhost ~]# date
Sat Jun 5 16:40:19 JST 2021
[root@testhost ~]# find /var/log -mtime +7 -size +1M -type f | xargs ls -hl
-rw-------. 1 root root 3.1M Jun 13  2020 /var/log/anaconda/journal.log
-rw-------. 1 root root 1.7M Jun 13  2020 /var/log/anaconda/lvm.log
```

こちらも項番2と同様に、grepコマンドでファイルやディレクトリの除外ができます。

```Linux:Linux
[root@testhost ~]# date
Sat Jun 5 19:01:04 JST 2021
[root@testhost ~]# find /var/log -mtime +7 -size +100k -type f | grep -v /var/log/anaconda | xargs ls -hl
-rw------- 1 root root 248K May 25  17:23 /var/log/messages.20210525.gz
```
ロードバランシングの種類

## 勉強前イメージ

ラウンドロビンが結構普通かなって思ってるけど、
他のあんまり知らない・・・

## 調査

### そもそもロードバランシングとは？

同様の機能を持つ2台以上の機器に外部からのアクセスを振り分けることで
総アクセス数や耐障害性の向上を図ることが出来ます。

### 種類

#### 分類

まず分類と種類があります。
分類としては以下になります。
スタティックとダイナミックがあります。

- スタティック
	- 決められた比率・設定でロードバランシングを行う
- ダイナミック
	- その時のサーバの負荷やアクセス数に応じてどのサーバに多く振り分けるのかを変更

#### 種類

種類は以下の分類ごとにあります。
詳細な内容は以下で記載します。

- スタティック
	- ラウンドロビン
	- 比率
- ダイナミック
	- 最小接続
	- 最速
	- 監視


- スタティック_ラウンドロビン

リクエストをサーバに均等に転送

![1# ロードバランシングの種類 - diagrams.net - Google Chrome 2021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/dd516057-35e8-9ce2-d1bb-00e037bd6d9d.png)


- スタティック_比率

リクエストを設定していた重みの割合に応じて転送

![2# ロードバランシングの種類 - diagrams.net - Google Chrome 2021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/ec7e07c8-2d4f-bcb9-6d8e-074be264a3d2.png)


- ダイナミック_最小接続

接続の際のコネクション数が一番小さいサーバに転送
コネクション数が同様であれば、ラウンとロビン(均等)で転送します。

![3# ロードバランシングの種類 - diagrams.net - Google Chrome 2021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/25f9ee26-2644-80af-659c-6aa60de60809.png)


- ダイナミック_最速

リクエストの未処理数が一番小さいサーバに転送

![4# ロードバランシングの種類 - diagrams.net - Google Chrome 2021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f8f96578-a2e9-4e94-689b-b73ded4038ed.png)


- ダイナミック_監視

一定時間コネクション数を監視し、コネクション数が一番少ないサーバに転送

![5# ロードバランシングの種類 - diagrams.net - Google Chrome 2021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/f6be1b22-c242-5f23-9681-7c421076c8d2.png)

## 勉強後イメージ

ダイナミックとかスタティックとかあるのすら知らなかった・・・
ラウンドロビンとか比率とかはよく聞くけど、他にもいろいろあるのね・・
機器によって対応してるだのしてないだのはあるかもやけど

## 参考

- [Load Balancer - Round Robin / Ratio / Least Connection / Fastest](https://www.infraexpert.com/study/loadbalancer4.html)
NotionでQiitaの記事を書くとマークダウンが便利に。

Notionというアプリを知っているでしょうか？
Notionではショートカットを使うだけで簡単にマークダウンでの記述をすることができ、とても便利です。
そのため、Notionで記事を書いてQiitaにコピペするだけで簡単に記事を作成できます。



## Notionでは以下のように記入できます。
![NotionMarkdown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1606414/c76c6c30-eea6-170a-9516-9ae5e4708765.png)

---


## Notionで記入したものをQiitaの記事作成画面にコピペすると、以下のようになります。
# Header 1
## Header 2
### Header 3
**Bold**

*Italic*

[Link](https://qiita.com/)

~~Strike-through~~

`Mark as code`

- List

> Quote

```swift
//code
func introduceNotionMarkdown() {
		print("Notion is convenient when you post on Qiita.")
}
```
---
↑Divider


Notionを使うととても便利です。興味が湧いたら、Notionを利用して、以下のサイトでショートカットを学んでみてくださいね。
https://www.notion.so/0d2e6e88fc804dbf8f307191de8ca005
機械学習のプロダクト開発におけるデプロイ後のモニタリングの重要性について

# はじめに

この記事はCourseraのコース「[Introduction to Machine Learning in Production](https://www.coursera.org/learn/introduction-to-machine-learning-in-production/)」を受講し、要点をまとめたものです。そのため、人に読んでもらうということよりは、自分で後で見返したときに思い出すことを目的とした記事なので、誤りや見づらい点がございましたらどうぞ遠慮なくご指摘頂ければ幸いです。

本記事では、機械学習システムをデプロイ後のモニタリングの重要性について解説します。

# デプロイ後に起きる問題

机上検証やPocにおけるKPIも良好な結果が得られ、モデルのチューニングや仕上げが終わり、いざ本番環境へデプロイ！やったーこれでプロジェクトも無事成功だ！とは言えないのが機械学習プロジェクトの難しいところです。
デプロイはやっとスタートラインに立った地点。実はデプロイ後からが本番とも言えるでしょう。
次のような問題が起こり得るからです。

* 予測に使われるデータに破損・欠損・遅延が発生してエラーになる、または、予測精度が落ちる
* 時間の経過とともに、予測に使われる説明変数のデータ分布に変化が生じ、予測精度が低下する（データドリフト）
  * コロナの発生により、顧客のオンラインショッピングの割合が増え、流入チャネルの分布に変化が起きた
  * 画像認識システムにおいて、製品の材質の変化により学習時データとの外見との変化が起きた
* 時間の経過とともに、説明変数と目的変数の関係性に変化が生じ、予測精度が低下する（コンセプトドリフト）
    * インフレにより住宅面積と住宅価格の関係バランスに変化が生じた

上記のような問題により、当初のモデルが未来永劫ワークするかというと、そんなことはなく、定期的にモデル更新・再構築の必要があります。その頻度は扱うデータやシステムの種類によって異なりますが機械学習システムの共通の問題ともいえるでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658983/b484c9ab-8012-cbc7-a0a0-f5daf1e1d4d4.png)

（転載元）https://towardsdatascience.com/machine-learning-in-production-why-you-should-care-about-data-and-concept-drift-d96d0bc907fb

# モニタリングの重要性

上記のようなデプロイ後の問題に対処するために、まずはモデルのエラーや精度低下の原因を掴むことが大切です。
一般的にはダッシュボードを作成して時間の経過とともにシステムの状態を追跡するのが有効な方法です。
チェックするメトリクスの種類は、想定される問題をチーム間でブレインストーミングなどで洗い出し、設計します。

例えば
* 説明変数のデータ分布・統計量（平均、分散、標準偏差など）
* 欠損の有り無し、割合
* サーバーメモリ負荷状況
* モデルのアウトプットの予測精度

他にも考えられるメトリクスは様々ですが、まずは色んな指標でモニタリングをはじめ、不要なものは削っていくという手法も有効かと思います。データや予測精度だけのモニタリングではなく、メモリやCPU、応答時間なども監視の対象に入れることを忘れないでおきましょう。

重要なのは、それがモデルのパフォーマンスにどのような影響を与えるか、新たにデータの収集や再学習が必要か、そしれそれをどうやって間に合わせるかを検討し対策を打つことです。
AWS CDKのテストで「None of 0 resources matches resource」のエラー

# この記事について
AWS CDKのワークショップ（TypeScript）を試した際にテストにおいて、DynamoDBのリソースが存在するかテストコードを書いていた際にエラーが発生しましたので同じようにハマる人がいたら参考になればと思います。

https://cdkworkshop.com/20-typescript/70-advanced-topics/100-construct-testing/1000-assertion-test.html

# エラー発生箇所
ワークショップの以下のDynamoDBのリソースが存在しているか検証する箇所でエラー

``` hitcounter.test.ts
  // THEN
  expectCDK(stack).to(haveResource("AWS::DynamoDB::Table"));
```

# エラー内容
DynamoDBのリソースが無いといって怒られました。。。
実際に `cdk deploy` では問題なくデプロイできて、マネジメントコンソールでも存在を確認できているのに何故だ・・・

```
None of 0 resources matches resource 'AWS::DynamoDB::Table' with {
      "$anything": true
}.
```

# 調べたこと

* CloudFormationに存在しているか？
    * haveResourceは、テンプレートの検証をしているはずなので存在しているか確認したが、問題なく存在していました。

```
$ cdk synth | grep 'Type: AWS::DynamoDB::Table'

    Type: AWS::DynamoDB::Table
```

* 競合するCDKのバージョンが存在しないか？
    * package.jsonを確認しても全て同じバージョンなので問題なさそうです。

``` package.json抜粋
  "devDependencies": {
    "@aws-cdk/assert": "^1.105.0",
    "@types/jest": "^26.0.23",
    "@types/node": "10.17.27",
    "jest": "^26.6.3",
    "ts-jest": "^26.2.0",
    "ts-node": "^9.0.0",
    "typescript": "~3.9.7"
  },
  "dependencies": {
    "@aws-cdk/aws-apigateway": "^1.105.0",
    "@aws-cdk/aws-dynamodb": "^1.105.0",
    "@aws-cdk/aws-lambda": "^1.105.0",
    "@aws-cdk/core": "^1.105.0",
    "cdk-dynamo-table-viewer": "^3.1.2"
  }
```

* すでにインストールされているパッケージ内がどこかおかしいか？
    * 以下のコマンドで入れ替えてみてもエラーは解消できないので問題はなさそうでした。

```
rm -rf node_modules && rm -rf package-lock.json && npm install
```

* グローバルインストールしたCDKのバージョンと違い出ていないか？
    * CDKのバージョンを確認したところ、見事にずれてました！！！！
   
```
$ cdk --version
1.107.0 (build 52c4434)
```

# 対策
package.jsonのcdk周りのバージョンを　`1.105.0` から `1.107.0` にすることでバージョンを合わせてからモジュールを入れ直したところ解消！

# 最後に
今回、バージョンがずれた原因はなんとなく心当たりがあり、npmやcdkのコマンドが認識しなくなっていたので、再度nvmで設定しなおしてからcdkを入れ直していたんです。

今回はワークショップに従ってCDKをグローバルインストールしましたが、そもそもバージョンの違いでこのような挙動が発生してしまうなら、グローバルインストールせずにローカルインストールした方が良いんじゃ無いかなと感じました。

# 参考サイト
* [Assert failed after update assert module #4757](https://github.com/aws/aws-cdk/issues/4757)
* [macOSアップデート後の『xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools)...』の対処法
](https://qiita.com/nishina555/items/e23d73067a5cac182a63)
* [gitコマンドを実行したら「xcrun: error: invalid active developer path」というエラーが出た時の対処法](https://qiita.com/kooohei/items/6aada548eeb785dd2c91)
ubuntu インストール


今まで仮想マシンだと、重すぎてサクサク進まなかったので、
思い切ってubuntuをインストールしてみることにしました。


当方は、いままでLinuxの構築をしたことがなく、
LPIC１程度の知識を有しているのみなので、
多くは手探りの状態でインストールを進めた。


所感としては、デュアルブートにこだわらず、
単純にインストールするだけなら、そこまで
難しくないと感じた。


手順としては、LiveUSBを作成し、
BIOSで起動順序をUSBを最初にし、
あとは、立ち上がったubuntuの画面に従うのみである。


しかし、当方は、もともとWindowsとubuntuのデュアルブートでやるつもりだったが、これが想像以上にうまくいかなかった。


もともと2つのOSを併存させるのは、推奨されていないため、
トラブルはつきものかもしれないが。
System.Text.Jsonのシリアライズで躓いた点について...。[C#]

```csharp

    class JSON
    {
        internal List<string> Word { get; set; }

        internal string Test { get; set; }

        internal string Test2 { get; set; }

        internal int[] Test3 { get; set; }
    }
```

```csharp

    class Program
    {
        static void Main()
        {
            JSON testString = new JSON()
            {
                Word = new List<string>
                {
                    "Apple",
                    "Banana",
                    "Pine",
                },
                Test = "Hello",
                Test2 = "HEllo222",
                Test3 = new int[]
                {
                    1,
                    2,
                    3,
                },
            };

            //シリアライズ
            string jsonString = JsonSerializer.Serialize(testString, new JsonSerializerOptions { WriteIndented = true});

            //JSON文字列をテキストファイルに保存
            File.WriteAllText(@"C:\Users\user\test.txt", jsonString);            
        }
```
上の図のようにデータクラス(JSON.cs)を用意して、Program.csでJSON文字列にしていこう思ったのですが、上手くいきませんでした。
原因はデータクラス(JSON.cs)のプロパティのアクセス修飾子がinternalだったからです。
下の図のようにデータクラス(JSON.cs)のアクセス修飾子をpublicにすれば上手くいきます。

```csharp

    class JSON
    {
        public List<string> Word { get; set; }

        public string Test { get; set; }

        public string Test2 { get; set; }

        public int[] Test3 { get; set; }
    }
```
しかし何故internalではいけないのか分かりませんでした。
分かり次第、追記します。(2020/6/5更新)
ubuntu server 20.04 LTS IPアドレス固定

Ubuntu 20.04 LTS
Ubuntu 22.04 LTS

インターフェイス eth0
ルーター 192.168.0.1
ネームサーバー 192.168.0.1
固定ipアドレス 192.168.0.6

```yaml:/etc/netplan/50-cloud-init.yaml
network:
    ethernets:
        eth0:
            addresses: [192.168.0.6/24]
            dhcp4: false
            gateway4: 192.168.0.1
            nameservers:
                addresses: 
                - 192.168.0.1
    version: 2
```
cssで縦方向の相対値指定

# cssで縦方向の相対値指定
cssで縦方向のサイズ(`margin-top`や`height`など)を相対値で指定したい時、
つまり画面幅に合わせて縦方向のサイズを変えたい時は、
親要素のwidthに対して%指定することで、レスポンシブにできる。

**縦方向なのに親要素のwidth基準であることに注意**
Docker PostgreSQL を起動するコマンド

最近は docker-compose.yaml　で起動することもあって、ターミナルから起動することがあまりなく、ロケール設定とかタイムゾーンを忘れてしまうのでメモっておく

## 起動する

```zsh
docker run --name postgres \
           -e POSTGRES_PASSWORD=password \
           -e POSTGRES_INITDB_ARGS="--encoding=UTF8 --no-locale" \
           -e TZ=Asia/Tokyo \
           -v postgresdb:/var/lib/postgresql/data \
           -p 5432:5432 \
           -d postgres
```

## 確認する

```zsh
# コンテナにアクセスする
docker exec -it postgres /bin/bash

# PostgreSQL にログインする
psql -h localhost -U postgres

# locale確認
postgres-# \l
                             List of databases
   Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   
-----------+----------+----------+---------+-------+-----------------------
 postgres  | postgres | UTF8     | C       | C     | 
 template0 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
 template1 | postgres | UTF8     | C       | C     | =c/postgres          +
           |          |          |         |       | postgres=CTc/postgres
(3 rows)

# TimeStamp確認
postgres=# select NOW();
              now              
-------------------------------
 2021-06-05 22:08:55.231972+09
(1 row)

# 抜ける
\q
exit
```

終わり
pixi.jsで表示オブジェクトをソートするにはv5以上が必要なことが分かったというだけの話

タイトル通り。
公式のDocumentationとか他の人の記事を見ながら「できないな～～～」と悪戦苦闘していたけど、pixi.jsのバージョンが問題だったというだけの話。

``` js:script.js
let app = new PIXI.Application();
console.log(app.stage.sortableChildren);//v4だとundefined, v5以降だとデフォルトでfalse
app.stage.sortableChildren = true;//ここをtrueにセットすることで子要素の表示順をソートできる

//ID="game"の要素に貼り付け
document.getElementById("game").appendChild(app.renderer.view);

PIXI.Loader.shared
  .add("image.png")
  .load(setup);

function setup(){
   let sprite1 = new PIXI.Sprite(PIXI.Loader.shared.resources["image.png"].texture);
   let sprite2 = new PIXI.Sprite(PIXI.Loader.shared.resources["image.png"].texture);

   app.stage.addChild(sprite1);
   sprite1.position.set(0,0);
   app.stage.addChild(sprite2);
   sprite2.position.set(10,0);
   //この時点ではsprite2の方が前に表示されている

   sprite2.zIndex = -1;
   //この時点ではsprite1の方が前に表示されている
}
```

公式のチュートリアル[lerningPixi](URL:https://github.com/kittykatattack/learningPixi)に則ってv4.5.5でやっていたら、`console.log(app.stage.sortableChildren)`の出力が`undefined`だった。
v5.1.3にしてみたら問題なくできた。
バージョンの確認って大事だね～～っていう話。
ハンズオンはじめの一歩: AWS アカウントの作り方 & IAM 基本のキ[動画1~4]

## 本シリーズのゴール：AWSアカウントの作り方 & IAMの基本のキ

### 動画1：本シリーズの説明　5min

https://youtu.be/IW8F1I9Lwgs

1. ハンヅオン用のAWSアカウントを作ってもらう
2. IAMの基本

    IAMポリシー・IAMユーザー・IAMグループ・IAMロールについて学ぶ

3. IAMリソースを作成できるようになる

### 動画2：AWSアカウントの作り方　7min

https://youtu.be/zC_gDHHZm1E

既に存在しているので省略

### 動画3：ルートユーザーと IAM ユーザーについて学ぶ　5min

https://youtu.be/ZGRedwgoTrM

ルートユーザー

- Eメールアドレス+パスワードでログイン
- 全AWSサービスリソースに対して**完全なアクセス権限**　←権限が強すぎる
- 日常タスクでは**使わない**

IAMユーザー

- アカウントID + IAMパスワードでログイン
- 紐づいている**IAMポリシー権限で認められた操作のみ**可能
- 利用者ごとにIAMユーザーを作成し、利用者はIAMユーザーでログインして作業する

今後のウェビナーにおいて、IAMユーザーが指定した権限を行使できるか、または権限を限定できているかを確認する

例えば...AWS EC2を取り扱う場合

インフラ担当　Administratorポリシー

- インスタンス表示　○
- インスタンス作成　○

アプリ担当　EC2ReadOnlyポリシー

- インスタンス表示　◯
- インスタンス作成　×

AWSのサービスそれぞれにおいて、権限を許可・限定を行うことができる

ちなみ今後のハンヅオンで登場するサービスは...

1. Amazon EC2

    数分で起動し、従量課金型の**仮想サーバサービス**
    インスタンスタイプを需要に合わせて選択可能
    必要な時に必要な分だけリソースを起動できる

2. Amazon S3

    99.999999999%の耐久性を持つストレージサービス
    容量無制限な安価なストレージ
    静的Webホスティングサービス
    様々なAWSサービスと連携

### 動画4：IAM ユーザーを作成する　12min

実際にIAMユーザーを複数作成し、ログインし、権限を確認する作業を行う。
この辺りから、自分がこれまで指示通り手を動かしていただけの**作業の意味**が理解できるようになってきた。強い。

具体的には、IAMユーザーを3つ作成する

1. 全ての権限を与えられている(多分)
2. S3のReadOnly
3. 何も権限を持たない

これらを作成し、S3の画面へ遷移し、IAMの実力を確認する。

## 前半まとめ

自分がこれまで指示通り行ってきた作業の意味が少しずつ理解できてきた。
学ぶ順番が正しいかどうか少し不安ではあるが、とても分かりやすく、理解に繋がっていることから、もう少し続けてみようと思う。

この記事に目を通してくださった皆様、おすすめのAWS学習手順・学習教材などございましたらコメント頂けますと幸いです。最後まで読んでいただきありがとうございました！
Amazon Lightsailでワードプレス使うときはサーバー破損に気をつけた方がいい

![Amazon_Lightsail-722x400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135794/69c9c20e-fa78-6662-bda1-277bb8a75dcf.png)

Amazon Lightsaiは、月額３５０円くらいからワードプレスを一瞬で立ち上げることが出来る機能があります。




面倒臭い契約とか管理画面とか一切なしで、インスタンスも不必要になったら速攻消せるので契約とかもありません。




非常に便利で安いので複数のワードプレスメディアを立ち上げるのに結構使っていました。




でも、長らく使っているとAmazon Lightsailでワードプレスを運営するのはサーバーが壊れるリスクを気をつけないとヤヴァイなって思っています。




特に、プラグインをやたらめったら入れ替えまくると結構簡単にバグると思います。




それで、サイトにアクセス出来なくなります、それで、数回はインスタンスを再起動してれば治るんだけども、




何回も何回もインスタンスを再起動しまくってると、いよいよインスタンスが壊れて起動しなくなります。




そうすると、SSH接続すら出来なくなってオワコンです。




私は、これまでロリポップとXサーバーしか使ってこなかったんで、他のサーバーのことをよく知らないが、




ロリポップは安いが重い、Xサーバーは高性能だが高いという利点欠点がありました。




でも、両者サーバーは死んで壊れてデータが消える欠点はなかったので、こういうサーバー破損のリスクを軽んじていました。




それで、過去に一個Lightsailでサイトをダメにしています、私。




結局、Amazon Lightsailは安いし軽いし、立ち上げが楽ちんだし、もう慣れてしまって他のサービス行くいのも億劫なので、




普通に使っててそんなに壊れまくらなければ、今後も使い続けるような気がする（分からないけど）のだが、




プラグインの入れ替えの時はマジで気をつけるし、定期的にバックアップは必ず取った方がいいです、Lightsailでワードプレス運営してる人。




サーバー壊れてインスタンス立ち上がらなくなったらおわりなので。
JSON表記

#【JSON表記】

実務では、XMLしか見たことがありません。
JSONの方が使われているということで学習しました。

##JSON（JavaScript Object Notation）

データを記述するための表記法のひとつ。

JavaScriptのオブジェクトで構成されているため、JavaScriptとの親和性が高い。
XMLよりもデータの記述量が少ないので、読み込みが速いとされている。

##JSON表記

**JSONで扱える全6種類のデータ**
・オブジェクト
・配列
・数値
・文字列
・真偽値
・null

```json:JSON
{
  "human": {
    "name": "@haruki_uejima",
    "age": 24,
    "birthplace": "Nara",
  }
}
```

JSONやYAML、XMLはデータの記述の仕方が違うだけ。
JSONは、[docker-compose](https://qiita.com/uejima_haruki/items/7cf161f1cc39d8a0c67d)のYAML表記に似ている。
YAMLの方がシンプル。

##おわりに。

今後も引き続きJSONを学習して、ここに追記していく。
JSONについての理解が深まる書籍や記事などありましたらコメントにて教えていただけると嬉しいです。
はじめてC++で画面を作ろう! (6) QFileInfo編

#18.「ファイル情報をチェックする」を作ろう!!
「ファイルを開く」と「名前を付けて保存」のファイル名がバラバラなのは、ファイル名を関数間で、共有できていないからだ!

各関数から使える「共有変数」を定義する。

Qtには、QFileInfoクラスが用意されており、これを使ってファイル名などを共有する。

この変数は、mainwindow.hファイルのmainwindowクラスに変数を定義する。
[1] __QFileInfo__をインクルードする。
[2] 共有変数: __fileInfo__を定義する。

```mainwindow.h
...省略...
#include <QMainWindow>
#include <QFileInfo> /* これを追加 */

...省略...

class MainWindow : public QMainWindow
{
...省略...

private:
    Ui::MainWindow *ui;
    QFileInfo fileInfo; /* これを追加 */
};
#endif // MAINWINDOW_H
```

[3] 共有変数にファイル名を設定する。 __fileInfo.setFile()__
[4] fileInfoから、絶対パスを取得する。__fileInfo.absoluteFilePath()__
[5] __getSaveFileName()__の__3番目__の引数に絶対パスを指定する。

```mainwindow.cpp
...省略...

MainWindow::MainWindow(QWidget *parent)
...省略...

void MainWindow::on_actionOpen_triggered()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open"), "", tr("Text File(*.txt);;All Files(*.*)"));
    fileInfo.setFile(fileName); /* これを追加 */
    ui->statusbar->showMessage(fileInfo.absoluteFilePath()); /* fileName変数から、fileInfoに変更する */
}

void MainWindow::on_actionSaveAs_triggered()
{
    QString filePath = fileInfo.absoluteFilePath(); /* これを追加 */
 
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), filePath, tr("Text File(*.txt)")); /* 3番目の引数を""から取得したパスを設定 */
    fileInfo.setFile(fileName); /* これを追加 */
    ui->statusbar->showMessage(fileInfo.absoluteFilePath()); /* fileName変数から、fileInfoに変更する */
}
```

#19.動作確認!!  
画面の左下にある、右三角マークの「実行」ボタンをクリックすると、何やら右下側にビルドしている状況が表示され、「MainWindow」が出てくる!

作ったアプリのメニューで、__[File | Open]__で、開き(つもり 実際には、まだ何もしていない)、__[File | SaveAs]__で、開いた場所(=パス)で、開いたファイル名が出てくるはずだ!!

※SaveAsで、上書きOKでも、まだ何もしていないので、影響はありません。

ただ、SaveAsで、__[キャンセル]__した場合、ファイル名なしの状態で、fileInfoに設定されるので、続けて[File | SaveAs]を行うと、ファイル名が消えてしまう。

#20.C++のif文が登場!!
QString型には、文字列の長さが取得できるので、「もし。長さが 0以上ならば、fileInfoに設定する」ように追加していく。

```mainwindow.cpp
void MainWindow::on_actionSaveAs_triggered()
{
    QString filePath = fileInfo.absoluteFilePath();
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), filePath, tr("Text File(*.txt)"));

    if (fileName.length() > 0){　/* これを追加 */
        fileInfo.setFile(fileName);
    }
    ui->statusbar->showMessage(fileInfo.absoluteFilePath());
}

```

#21.再度、動作確認!! 
画面の左下にある、右三角マークの「実行」ボタンをクリックして、「MainWindow」が出てくる!

[1] [File | Open]で、他のフォルダーのファイルを開いてみる。
[2] [File | SaveAs]で、__[キャンセル]__してみる。
[3] 再度、[File | SaveAs]で、開いたファイル名がでる事を確認する。

#22.QFileInfoクラスは、便利!!
QFileInfoクラスは、絶対パス(absoluteFilePath)以外にも、いろいろ使える。

[1] fileInfo.__baseName()__で、ファイル名(拡張子なし)を取得
[2] fileInfo.__fileName()__で、ファイル名(拡張子あり)を取得
[3] fileInfo.__suffix()__で、拡張子のみを取得
[4] fileInfo.__size()__で、ファイル サイズを取得
[5] fileInfo.__lastModified()__で、ファイルの最終更新日時を取得
など、大変 便利に使える。

今回は、ここまで次回は、アプリ情報を記録しよう!!です。
Rubyの標準モジュール「NKF」を使ってみましょうかね。

# NKFとは？
NKFモジュールとは文字コードを変換することが出来るRubyの標準ライブラリです。
例えば、ひらがなをカタカナに変換したり、全角を半角へ変換するのを簡単に行えます。


# 使い方
`NKF.nkf(オプション、文字列)`とする。

## 使用例
**バリデーションでDBに保存する前に、空白を削除したりなどデータを整形するのに利用出来ます。**
※`text`には、それぞれに対応する文字列(メールアドレスや名前など)が渡ってくる想定です。

```ruby
require 'nkf'

module StringNormalizer
  extend ActiveSupport::Concern

  def normalizer_as_email(text)
    NKF.nkf("-W -w -Z1", text).strip if text
  end

  def normalizer_as_name(text)
    NKF.nkf('-W -w -Z1', text).strip if text
  end

  def normalizer_as_furigana(text)
    NKF.nkf('-W -w -Z1 --katakana', text).strip if text
  end

  def normalizer_as_postal_code(text)
    NKF.nkf("-W -w -Z1", text).strip.gsub(/-/, "") if text
  end

  def normalizer_as_phone_number(text)
    NKF.nkf('-W -w -Z1', text).strip if text
  end
end
```

### よく使うオプション一覧

| オプション | 意味 |
|:-:|:-:|
| -h1 | カタカナに変換する  |
| -h2 | 　ひらがなに変換する  |
| -s  | Shift_JISでの出力する  |
| -w  | UTF-8で入力する |
| -W  | UTF-8での出力する  |
| -Z1 | 全角空白を半角空白へ変換する  |
| -Z2 | 全角空白を空白2つに変換する  |


# 参考
[RubyのNKFモジュールの使い方を現役エンジニアが解説【初心者向け】]
(https://techacademy.jp/magazine/19939)

[module NKF]
(https://docs.ruby-lang.org/ja/latest/class/NKF.html)
スマホ＆ブラウザでカメラが使えるか デバイス取得お試し

スマホでカメラが使えるか確認
カメラの指定は、コンソールでログ出力して「検証」からデバイス一覧して、配列番号を取得

```javascript:JS
        const devices = await navigator.mediaDevices.enumerateDevices();
        console.log(devices);

        // カメラからの映像取得   //私のスマホの背面カメラは1番
        const stream = await navigator.mediaDevices.getUserMedia({
        audio: true,
        video: { deviceId: devices[1].deviceId },

```

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Camera Test</title>
  </head>

  <body>
    <h1>Webカメラテスト</h1>

    <video id="myvideo" width="640" height="480" muted autoplay playsinline></video>

    <script>

      // 関数の定義
      async function main() {
        // デバイス（カメラ・マイク）からのデータ取得を試みる
        // 映像や音声が使えるデバイスが確定するまで時間がかかるためawaitを使う
        const devices = await navigator.mediaDevices.enumerateDevices();
        console.log(devices);

        // カメラからの映像取得   //私のスマホの背面カメラは1番
        const stream = await navigator.mediaDevices.getUserMedia({
        audio: true,
        video: { deviceId: devices[1].deviceId },
        });
        // IDが"myvideo"であるDOMを取得
        const video = document.getElementById('myvideo');
        // myvideoなvideo要素のsrcObject（映像オブジェクトを入れるところ）にデータ（メディアストリーム）をセットする
        video.srcObject = stream;
      }

      // 実行する
      main();

    </script>
  </body>
</html>
```
WEBブラウザで動画再生お試し

https://qiita.com/takahasinaoki/items/0b435eca3a55fac572e1

https://yuzu441.hateblo.jp/entry/2015/12/20/173610

```html:src.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>sample</title>
<script>
//A再生
function PlayA(){
    vp = document.getElementById("videoplay");
    vp.src = "./a.mp4";
    vp.play();
}
//D一時停止
function PlayD(){
    vp = document.getElementById("videoplay");
    vp.src = "./d.mp4";
    vp.play();

}

</script>
</head>
<body>
	<video id="videoplay" width="500" height="300" >
		<source src="./d.mp4" type="video/mp4">
	</video>
<br />
<button onclick="PlayA()">a.mp4を再生</button>
<button onclick="PlayD()">d.mp4を再生</button>
</body>
</html>
```
WebAPI

#【WebAPI】

サーバーサイドエンジニアは、WebAPIの実装をする機会が多いと耳にした。
技術理解の学習が楽しい。基礎的なところを今日は抑えよう。
基礎知識に加えて、実装にも力を入れないといけないけど！

##WebAPIとは。

Web上でAPIのやり取りを可能にしたもの。
Webサービスの機能を他のWebサービスやアプリケーションから使えるようにするための仕組み。

WebAPIを使用することで、いろんなWebサービスの機能やデータなどを自分のWebサービスから使うことができる。
　→ 作れるWebサービスの幅が広がる。

超有名サービスのほとんどがWebAPIに対応している。

**プログラマーがしっかり理解しておくべき技術！**

###API（Application Programming Interface）

異なるWebサービス同士の情報を操作する仕組み。

##プログラマーがWebAPIを扱う

自分が開発しているWebサービスの機能にWebAPIを利用することで、Webサービスを構築することができる。
　→ より良いサービスを提供するために必要になることが多い。

###WebAPIは、関数のようなものである。

1、必要な機能を呼び出す処理を実装する。
2、結果を受け取り、自分のWeｂサービスに表示する。

例）TwitterAPIなど。

##APIエコノミーという考えが浸透

>そもそもAPI（Application Programming Interface）とは、プログラムを連携させる仕組みであり、開発者が使う用語である。では、ビジネス用語として使われる「APIエコノミー」とはなにか。APIエコノミーは、ネットワークを介して、様々な事業者が提供する機能をつなぎ合わせ、サービスを構築することが可能になったことで生まれた概念である。

引用：[いまさら聞けないAPIエコノミー
APIの公開でビジネスの拡大を狙うアプローチ](https://it.impress.co.jp/articles/-/15887)

WebAPIの浸透によって、従来よりも新たなビジネスが多く誕生している気がしている。
今後、WebAPIの実装が求められた時にしっかり仕組みを理解して実装をしよう。

##過去記事

[Ajaxとは。APIとは。](https://qiita.com/uejima_haruki/items/13adab01b6fa7a74af95)
【SQL】CASE式について

> SQLのCASE式について学んだことをまとめます。

# CASE式の概要
CASE式は簡単に言えば「ラベルの読み替え」をやっているに過ぎないのです。
しかし、集約関数などの技術と一緒に使えば以下のことなどが可能です。

- ラベルをまとめて読み替え
- 「行持ち」から「列持ち」への変換
- CHECK制約での条件分岐
- UPDATE文で条件分岐させて更新
- EXISTS述語を利用したクロス表の作成

# CASE式の構文
単純CASE式のほうが簡潔に記載できますが、単純CASE式で書けるものは検索CASE式でも書けるため
検索CASE式を使うほうが無難でしょう。
また、ELSE句は必ず書くようにする。

## 単純CASE式

```sql:単純CASE式
CASE sex
    WHEN 1 THEN '男性'
    WHEN 2 THEN '女性'
ELSE 'その他' END
```

##  検索CASE式

```sql:検索CASE式
CASE
    WHEN sex = 1 THEN '男性'
    WHEN sex = 2 THEN '女性'
ELSE 'その他' END
```

# CASE式の使用箇所
CASE式は評価すると一つの値になる式のため、以下の箇所のようなどこにでも記載することができます。

- SELECT句
- WHERE句
- GROUP BY句
- HAVING句
- ORDER BY句
- PARTITION BY句
- CHECK制約の中
- 関数の引数
- 述語の引数
- 他の式の中（CASE式自身も含む）