OmniAICreator/Qiita-1.07M huggingface dataset:
【PostgreSQL】参照整合性を維持するテーブルについて、CASCADEオプションを指定せずに被参照テーブルを削除したら、どうなる？

#1.環境
|||バージョン|
|:--|:--|:--|
|Host OS|Windows 10 Home|21H1(OSビルド:19043.1165)|
|Virtual Machine|WSL2|-|
|Remote OS|Ubuntu| 20.04.2 LTS (GNU/Linux 5.4.72-microsoft-standard-WSL2 x86_64)|
|Database|PostgreSQL|12.7 (Ubuntu 12.7-0ubuntu0.20.04.1)|
|Database GUI|DBeaver|21.3.2.202112271055|
|Docker|無し|-|

#2.疑問と答え
『[徹底攻略OSS-DB Silver問題集［Ver.2.0］対応](https://www.amazon.co.jp/dp/B086YWFFPR/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)』（＝黒本）に、こうあった。

>問19
参照制約が設定されているテーブルdummytbを削除するために、次のようなSQL文を実行した。dummytbは被参照テーブルである。
DROP TABLE dummytb CASCADE;
（黒本10章問19 解説p242）

**Q：参照整合性を維持するテーブルについて、CASCADEオプションを指定せずに被参照テーブルを削除したら、どうなる？**
↓
**A：エラーになり、テーブル削除できない**

#3.基本知識整理

・参照制約
緑本で言う「外部キー制約/参照整合性制約」(緑本p225)のことかな。
緑本には被参照テーブルの列を削除/更新する方法は解説されているけれど、被参照テーブルを削除する方法は記載されていない。

・被参照テーブルの列を削除/更新
①　エラーにさせる方法（被参照テーブルのデータは変更させない）
②　被参照テーブルの列を削除/更新すると同時に、参照テーブルのデータも削除/更新してしまう方法
の2つを選択できる。デフォルトは「①」。
（参考：緑本p227）

・被参照テーブルを削除
DROP TABLE実行時にCASCADEオプションを指定することで、参照制約が削除される。（本問の解答）

#4.試してみる
**疑問：CASCADEオプションを指定しなかった場合、エラーになるのか？**
↓
**試す：WSL2でサンプルデータを動かし、試してみる！**

サンプルのテーブルを作る。（参考：緑本p226）

```:PostgreSQL_(DBeaver_VSCode_WSL2(Ubuntu))
CREATE TABLE master ( id int PRIMARY KEY);　←被参照テーブル（id列＝主キー）
CREATE TABLE tbl ( id int REFERENCES master(id));　←参照テーブル（masterテーブルのid列を外部キーとする）
insert into master values (1); 
insert into tbl VALUES(1);
```
参照制約をもつテーブルが出来上がった。

(**疑問：DVBeaverの操作について。**上記4文は1文1文実行していった。
**4文全体を選択して全てを連続して実行する方法**は無いか探してみたが、見つけられず。
ひとつのSQLエディタ内に書かれているSQL全てを連続して実行する方法（Alt+X）は見つかったのだが・・・。）

次に、
①CASCADE オプションを付けてDROP
②CASCADEオプション付けずにDROP
の2通りの方法を試し、挙動を確認する。

**①CASCADE オプションを付けて被参照テーブルをDROP（問題文の方法）**

```:PostgreSQL_(DBeaver_VSCode_WSL2(Ubuntu))
DROP TABLE master CASCADE;　
```
実行結果↓  DROP TABLEできた！
<img width="400" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498057/a5398c02-c248-2bfd-fb96-5b7501ad8b1d.png">

②を試すためにtblテーブルも削除しておく。
`DROP TABLE tbl;　`
その後もう一度masterテーブルとtblテーブルを前回と同じ条件で作成しておく。

**②CASCADEオプション付けずに被参照テーブルをDROP**

```:PostgreSQL_(DBeaver_VSCode_WSL2(Ubuntu))
DROP TABLE master;　
```
実行結果↓  エラーになった！
<img width="700" alt="1000.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498057/6b50e9c3-4811-bee5-178d-e79d6dd90bc0.png">

【エラー文】
SQLエラー [2BP01]: ERROR: cannot drop table master because other objects depend on it
  詳細: constraint tbl_id_fkey on table tbl depends on table master
  ヒント: Use DROP ... CASCADE to drop the dependent objects too.

依存しているからDROP TABLEできませんよ、とのこと。
ヒントでもCASCADEを使うように勧めている。

エラーになり、DROP TABLEできなくなることがわかった。解決！
改めてmasterテーブルとtblテーブルを削除しておき、完了。

#未解決の疑問
##（GUIの操作）DBeaverで複数のSQLを選択して連続して実行する方法はあるのか？
DBeaverの操作について。
今回複数（4文）のSQLを実行する際、1文1文実行していった。
**4行全体を選択して全てを連続して実行する方法**が知りたい。

（ひとつのSQLエディタ内に書かれているSQL全てを連続して実行する方法（Alt+X）は見つかったのだが…。）
pythonで実行位置指定型ジョブリラン

# はじめに

pythonで書かれたバッチジョブにて、ジョブ途中停止の状況によりリランする位置を変えたいという要望がありました。
本記事ではその方法について考えていきたいと思います。

### お断り

ここに書くことは基本的にバッドノウハウだと思います。

# pythonでできないこと

## gotoがない

今どきのプログラミング言語では存在するほうが珍しいgoto構文ですが、pythonにも当然存在しないようです。
ただ、検索すると[冗談のようなgotoモジュール](http://entrian.com/goto/download.html)が存在します。実際冗談なので使用してはいけないでしょう。

## switchもない

swithがあれば以下の様に記載できるでしょう。

```c:例えばcなら
void job(int stepNo){
  switch stepNo{
    case 0:
    // step0の処理を実行
    case 1:
    // step1の処理を実行
    case 2:
    // step2の処理を実行
    case 3:
    // step3の処理を実行
    default:
    // 有効なstepNoが存在しない場合は何もしないが、defalutを空にはできないので何かしらのダミー処理を入れる
  }
```

というようにbreak文のないswitch構文であれば、比較的簡単にリランの実行位置を外部から与えることができます。

しかしpythonにはswitch構文が存在しません。if-elseで全部代替できるからということですが、breakを使わないswitch構文はその限りではないでしょう、と声を大にして言いたい（言うとは言っていない）。

# 代替手段検討

## その1 リスト形式

```python
# stepNoは外部から与えられたリラン位置番号
if stepNo in [1,2,3]:
  # step1の処理
if stepNo in [2,3]:
  # step2の処理
if stepNo in [3]:
  # step3の処理
```

上記の様にリラン番号がリストに入っているかどうかでそのブロックを実行するかどうか判断できるかと思います。
ただこの方法はプログラム上のリラン番号がコードから分かりにくいのでstepごとのコメントは必須となるでしょうか。
リテラルでin以降を書きたくない場合はこうなりますでしょうか。

```python
# stepNoは外部から与えられたリラン位置番号
rerunList = [1,2,3]
if stepNo in rerunList:
  # step1の処理
  rerunList.pop(0)
if stepNo in rerunList:
  # step2の処理
  rerunList.pop(0)
if stepNo in rerunList:
  # step3の処理
  rerunList.pop(0)
```

## stepNoの大小関係で判断

外部から与えるstepNoが実行ステップ以上であればifブロックを実行する方法も考えられます。

```python
# stepNoは外部から与えられたリラン位置番号
if stepNo >= 1:
  # step1の処理
if stepNo >= 2:
  # step2の処理
if stepNo >= 3:
  # step3の処理
```

こちらのほうが汎用的でしょうか。
コード上でどのステップかも追うことができます。
リテラルをそのまま埋め込むのはどうかとは思いますが。
また、stepを10刻みとかにして保守時に新しいstepを挿入することも比較的簡単かもしれません。
昔のBASICの行番号みたいに。

# wip

他の方法を思いついたらまた追記したいと思います。
【Python】パッケージからクラスをimportする。モジュール名は省略可能

### 概要
Pythonのパッケージとモジュールのimportの方法に関してようやく腑に落ちたのでメモ。

#### 例：scikit-learnの graph_lasso_モジュールのGraphicalLassoクラスをimportする
https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/covariance/_graph_lasso.py#L338

sklearn/covariance/graph_lasso_.py 内にGraphicalLassoクラスが定義されています。

今回の例において、各オブジェクトの名称は以下のように解釈できます。


>sklearn: パッケージ <- ディレクトリであり、\_\_init\_\_.pyが存在するため
covariance: パッケージ　<- ディレクトリであり、\_\_init\_\_.pyが存在するため
graph_lasso_: モジュール <- graph_lasso_.py という名のファイルが存在する
GraphicalLasso: クラス <- graph_lasso_.py 内で定義されている。

- (モジュールとパッケージの定義に関してはこちらの記事を参照してください。)
 - [あまり基礎から教えてもらうことがないpythonのimportについて。モジュール？パッケージ？クラス？](https://qiita.com/hiroyuki_mrp/items/4b7102709e6582b9dd15)

#### 試したこと
下記の①と②を比較してみましょう。
パッケージからモジュールをインポートせず、直接クラスなどのオブジェクトをimportすることが可能であることがわかります。
具体的には下記の②が該当します。②においてはgraph_lasso_(.py)を呼び出さずに直接GraphicalLassoクラスのオブジェクトをimportしています。

```py

# $ python3
Python 3.6.1 (default, Jul 13 2017, 17:01:43)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
# 　①パッケージからモジュール(.py)をインポートし、その後クラスをインポートする。
>>> from sklearn.covariance import graph_lasso_
>>> graph_lasso_.GraphicalLasso()
GraphicalLasso(alpha=0.01, assume_centered=False, enet_tol=0.0001,
        max_iter=100, mode='cd', tol=0.0001, verbose=False)
# ②パッケージから直接クラスをインポートする。
# (モジュールのインポートを明示的に行わなくても良い。)
>>> from sklearn.covariance import GraphicalLasso
>>> GraphicalLasso()
GraphicalLasso(alpha=0.01, assume_centered=False, enet_tol=0.0001,
        max_iter=100, mode='cd', tol=0.0001, verbose=False)
>>>
```

もちろん①のようにモジュール名を指定してimportすることも可能です。しかし、②のように予め使用するメソッドをソースの上部付近でimportするほうが、記述するコードが少なくスコープを狭めてインポートすることができるメリットがあります。その結果、ソースコードの可読性が高くなると思われます。(個人の意見です)

#### 最後に
実際のコードでは①と②が入り交じって書かれることが多く正しく理解しないままであったのでまとめてみました。
以上です。
【Github】 複数アカウントでssh接続する方法

Githubアカウントを複数使用している場合、下記のエラーが発生することがあります。

```
fatal: Could not read from remote repository. 
Please make sure you have the correct access rights and the repository exists.
```

これは、既にローカル(Git)とリモート（Github）を繋いでいる場合、そのアカウントと既存のsshキーが紐づいているため、新しくsshキーを発行して、Githubに登録する必要があります。

難しいことはさておき、解決策を解説していきます。

## 1. sshキーを発行する

```
cd ~/.ssh
```

上記コマンドを実行してsshディレクトリに移動。
次に接続したいGithubアカウント用のsshキーを発行します。

```
ssh-keygen -t rsa -C [接続したいGithubのメールアドレス] -f [ファイル名]
```
（[]部分を入れ替えてください。）
自分はプライベート用のGithubアカウントを接続したかったので、ファイル名をprivateにしました。
次に下記コマンドを実行してファイルが作成されているか確認してください。

```
ls
```
おそらく、2つファイルが作成されています。
`private` → 秘密鍵
`private.pub` → 公開鍵
## 2. 発行したsshキーをコピーする
```
pbcopy < ~/.ssh/公開鍵名
```
上記コマンドを実行すると公開鍵をコピーできます。
自分の場合は`pbcopy < ~/.ssh/private.pub`となります。
## 3. コピーした公開鍵をGithubに追加する
SSH接続したいGithubアカウントにログインし、右上アイコン→`Setting`→`SSH and GPG keys`に移動。
`New SSH key`を押して任意のタイトルと先ほどコピーした公開鍵を追加します。

![スクリーンショット 2022-02-01 23.46.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2466417/be5aa48d-85c3-1bdf-b9f4-14ba6d513757.png)

## 4. configファイルを編集する
次に先ほど作成した公開鍵と秘密鍵のファイルと同階層にある`config`ファイルを編集していきます。

```
open config
```
上記コマンドでconfigファイルを開き、下記を追加。

```
Host github-[任意の文字]
  User git
  Port 22
  HostName github.com
  IdentityFile ~/.ssh/秘密鍵
  TCPKeepAlive yes
  IdentitiesOnly yes
```
簡単に説明すると、git remoteで登録しているurlに`github-private`のホスト名がある場合は、`IdentityFile`に記載している秘密鍵を参照するよ〜っていうイメージです。

## 5. remoteのURLを変更する
すでにリモートリポジトリと接続している場合、下記のようなURLになっていると思います。

```
git@[Host name]:[Account name]/[Repository name].git
``` 

[Host name]の部分を、先ほど`config`ファイルに設定したホスト名に書き換えます。

例えば、configファイルのホスト名を`github-private`にしている場合、

```
git@github-private:test/[Repository name].git
```

上記のように書き換えます。
書き換え方については、

```
git remote set-url origin git@github-private:test/test.git
```
でURLを書き換えることができます。

以上で冒頭に載せたエラーが解決し、複数アカウントでssh接続ができるようになってるかと思います。
Ubuntu 20.04にWireGuard Serverをセットアップする

#環境
- Ubuntu 20.04がインストールされているVPS

#手順

WireGuard Serverをインストールし、セットアップスクリプトを実行する

```
wget https://git.io/wireguard -O wireguard-install.sh && bash wireguard-install.sh
```

WireGuardが待ち受けするポートを指定します。

```
Welcome to this WireGuard road warrior installer!
What port should WireGuard listen to?
Port [51820]:
```

これはサーバー構成用のプロファイル名になります。ユーザー用に複数のプロファイルを作成する場合に使用します。

```
Enter a name for the first client:
Name [client]:
```

以下のオプションで使用するDNSサーバーを指定できます。広告ブロックなどを使用したい場合は指定することで設定が可能です。ここでは`1.1.1.1`を使用するので、`3`を選択します。

```
Select a DNS server for the client:
1) Current system resolvers
2) Google
3) 1.1.1.1
4) OpenDNS
5) Quad9
6) AdGuard
DNS server [1]: 3
```

サーバーをセットアップする準備ができたので、Enterを押してインストールします。

```
WireGuard installation is ready to begin.
Press any key to continue...
```

スクリプトを実行した場所にConfigが作成されるので、それを使用してサーバーに接続します。

> 使用したスクリプト - https://github.com/Nyr/wireguard-install
【mod_security】mod_securityのログファイル（modsec_audit.log）の解析 その２

#はじめに
mod_securityの自己学習をしています。mod_securityのログファイルを解析してみます。
前回記事の続きになりますが、mod_security監査ログのHセクションについて解析をしてみます。

#解析する監査ログは以下です。
```
--eddafe7b-H--
Message: Access denied with code 403 (phase 2). Pattern match "(?i:([\\s'\"`\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)\\b([\\d\\w]++)([\\s'\"`\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)(?:(?:=|<=>|r?like|sounds\\s+like|regexp)([\\s'\"`\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)\\2\\b|(?:!=|<=|>=|<>|<|>|\\^|is\\s+not ..." at ARGS:value. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "77"] [id "950901"] [rev "2"] [msg "SQL Injection Attack: SQL Tautology Detected."] [data "Matched Data:  'a'='a found within ARGS:value: 1' or 'a'='a"] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "8"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"]
Apache-Error: [file "apache2_util.c"] [line 273] [level 3] [client 6A.1BC.1DE.2FG] ModSecurity: Access denied with code 403 (phase 2). Pattern match "(?i:([\\\\\\\\s'\\\\"`\\\\xc2\\\\xb4\\\\xe2\\\\x80\\\\x99\\\\xe2\\\\x80\\\\x98\\\\\\\\(\\\\\\\\)]*?)\\\\\\\\b([\\\\\\\\d\\\\\\\\w]++)([\\\\\\\\s'\\\\"`\\\\xc2\\\\xb4\\\\xe2\\\\x80\\\\x99\\\\xe2\\\\x80\\\\x98\\\\\\\\(\\\\\\\\)]*?)(?:(?:=|<=>|r?like|sounds\\\\\\\\s+like|regexp)([\\\\\\\\s'\\\\"`\\\\xc2\\\\xb4\\\\xe2\\\\x80\\\\x99\\\\xe2\\\\x80\\\\x98\\\\\\\\(\\\\\\\\)]*?)\\\\\\\\2\\\\\\\\b|(?:!=|<=|>=|<>|<|>|\\\\\\\\^|is\\\\\\\\s+not ..." at ARGS:value. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "77"] [id "950901"] [rev "2"] [msg "SQL Injection Attack: SQL Tautology Detected."] [data "Matched Data:  'a'='a found within ARGS:value: 1' or 'a'='a"] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "8"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] [hostname "5A.9B.2C.1DE"] [uri "/"] [unique_id "YfvCE7Yy7OCFRLMWFtNyCwAAAAM"]
Action: Intercepted (phase 2)
Stopwatch: 1643889171139933 687 (- - -)
Stopwatch2: 1643889171139933 687; combined=292, p1=202, p2=86, p3=0, p4=0, p5=3, sr=115, sw=1, l=0, gc=0
Producer: ModSecurity for Apache/2.9.3 (http://www.modsecurity.org/); OWASP_CRS/2.2.9.
Server: Apache/2.4.52 ()
Engine-Mode: "ENABLED"
```

#パラメータ（項目）の説明
|項目名  |説明  |備考  |
|---|---|---|
|Message|xxxxxx|yyyyy|
|Apache-Error|xxxxx|yyyyy|
|Action|xxxxx|yyyyy|
|Stopwatch|xxxxx|yyyyy|
|Stopwatch2|xxxxx|yyyyy|
|Producer|xxxxx|yyyyy|
|Server|xxxxx|yyyyy|
|Engine-Mode|xxxxx|yyyyy|

↑編集中です。

#おわりに
では、また。
SolidityでのStringの比較で効率がいい書き方の備忘録

## Solidityでは文字列の比較は一手間必要

SolidityではStringを比較するときに

```
function test() public view returns (bool){
    return "" == "";
}
```

このような書き方をすると、コンパイルエラーが出ます。

![Screen Shot 2022-02-03 at 23.20.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/60e60ad0-d110-bfc7-67a1-6e2905730ee0.png)

```
TypeError: Operator == not compatible with types literal_string "" and literal_string ""
```

## 解決方法

こちらの[stackoverflow](https://ethereum.stackexchange.com/questions/30912/how-to-compare-strings-in-solidity/103807)では、記事作成時点で下記のようなる回答として下記のような実装がありました。

```
// 記事作成時点で50いいね
function test() public pure returns (bool) {
    return keccak256(abi.encodePacked("string")) == keccak256(abi.encodePacked("string"));
}

// 記事作成時点で7いいね
function test() public pure returns (bool) {
    return keccak256(bytes("string")) == keccak256(bytes("string"));
}
```

## 追加調査

この回答を見てて、abi.encodePackedとbytesのどっちがコードの効率がいいのか気になったので調べてみました。

```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract CompateAbiEncodePackedAndBytes {

    function execute1() public {
        require(test1());
    }

    function execute2() public {
        require(test2());
    }

    function test1() public pure returns (bool) {
        return keccak256(abi.encodePacked("string")) == keccak256(abi.encodePacked("string"));
    }

    function test2() public pure returns (bool) {
        return keccak256(bytes("string")) == keccak256(bytes("string"));
    }

}
```

[こちらの共有用リンク](https://remix.ethereum.org/?#code=Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC4wOwoKY29udHJhY3QgQ29tcGF0ZUFiaUVuY29kZVBhY2tlZEFuZEJ5dGVzIHsKCiAgICBmdW5jdGlvbiBleGVjdXRlMSgpIHB1YmxpYyB7CiAgICAgICAgcmVxdWlyZSh0ZXN0MSgpKTsKICAgIH0KCiAgICBmdW5jdGlvbiBleGVjdXRlMigpIHB1YmxpYyB7CiAgICAgICAgcmVxdWlyZSh0ZXN0MigpKTsKICAgIH0KCiAgICBmdW5jdGlvbiB0ZXN0MSgpIHB1YmxpYyBwdXJlIHJldHVybnMgKGJvb2wpIHsKICAgICAgICByZXR1cm4ga2VjY2FrMjU2KGFiaS5lbmNvZGVQYWNrZWQoInN0cmluZyIpKSA9PSBrZWNjYWsyNTYoYWJpLmVuY29kZVBhY2tlZCgic3RyaW5nIikpOwogICAgfQoKICAgIGZ1bmN0aW9uIHRlc3QyKCkgcHVibGljIHB1cmUgcmV0dXJucyAoYm9vbCkgewogICAgICAgIHJldHVybiBrZWNjYWsyNTYoYnl0ZXMoInN0cmluZyIpKSA9PSBrZWNjYWsyNTYoYnl0ZXMoInN0cmluZyIpKTsKICAgIH0KCn0&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.7+commit.e28d00a7.js)からすぐテストができます。

### abi.encodePackedを使ったコード

```
to	CompateAbiEncodePackedAndBytes.execute1() 0xd9145CCE52D386f254917e481eB44e9943F39138
transaction cost	21923 gas 
```

### bytesを使ったコード

```
to	CompateAbiEncodePackedAndBytes.execute2() 0xd9145CCE52D386f254917e481eB44e9943F39138
transaction cost	21499 gas 
```


ほんの少しですがBytesを使った方がGas効率が良さそうです。NFTを実装する際に、小さなガスコストの節約を積み重ねることで、よりユーザーにとって便利なものが提供できるようになるので、ぜひ試してみてください！
Googleカレンダーから昼休憩の時間を取得してslackに投稿する

## 動機
- 在宅勤務の家族と昼休憩の時間を共有したい。
  - 家族のお昼休憩の時間は日によってまちまち。
  - 休憩開始時間を知りたいけど、毎日直接聞いて確認するのは面倒だし仕事の都合で変わることもある。
- 会社のカレンダーを共有することはできないので、Google Apps Script(GAS)で昼休憩の開始時間だけ取得してslackに投稿する。

## 前提
- 昼休憩の時間はタイトル「ランチ」で登録している。
- ついでにその日最後のスケジュールの終了時間も取得。
  - 晩ご飯を早くて何時から開始できるか知るため。
- 有給の日と祝日はslack投稿を行わない。
  - 休みの日はタイトル「有給」で登録している。
  - 祝日はGoogleカレンダーの「日本の祝日」(カレンダーID `ja.japanese#holiday@group.v.calendar.google.com`)から取得する。

## 前準備
- Slack Incoming Webhookを設定してWeb hook URLを取得。
- GASのスクリプトエディタのtimeZoneをAsia/Tokyoに変更。
- 予定を取得したいカレンダーのカレンダーIDを確認。
- GASのトリガーを日時ベースのタイマー午前10~11時と午後5時~6時に設定。


## コード
```javascript
function postMealtime() {
  // 日付を設定
  const today = new Date();
  const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 10, 0);
  const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 0);

  // カレンダーから祝日を取得
  const holiday = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com').getEvents(startTime,endTime); 
  // 祝日の確認
  if(holiday.length > 0) {
    //return;
  }
      
  // カレンダーから予定を取得
  const schedule = CalendarApp.getCalendarById('カレンダーIDを記載').getEvents(startTime,endTime); 

  // 有給の確認
  if(schedule.find(v => v.getTitle() === "有給" )){
    return;
  }

  // ランチの時間を取得
  const lunchSchedule = schedule.find(v => v.getTitle() === "ランチ");
  const lunchTime = lunchSchedule ? Utilities.formatDate(lunchSchedule.getStartTime(), "JST", "HH:mm") : "登録されていません";  

  // 晩ご飯の時間を取得
  // 厳密にはスケジュールがないときのハンドリングもしたほうがいい
  const dinnerTime = Utilities.formatDate(schedule[schedule.length - 1].getEndTime(), "JST", "HH:mm");
  postToSlack(`お昼🥐${lunchTime}\n晩ご飯🍴${dinnerTime}以降`);
}

function postToSlack(postMessage) {
  const postUrl = 'Web hook URLを記載';
  const payload = JSON.stringify({ text: postMessage });
  const options = { method: 'post', contentType: 'application/json', payload: payload };
  UrlFetchApp.fetch(postUrl, options);
}
```

## 結果
![slack投稿.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177373/04d3c71c-f477-9788-485c-731a582bd3d4.png)
意外と簡単でした。これで家族とより便利に過ごせそうです。
Emotet って結局どんなやつ？

## 勉強前イメージ

恥ずかしながら最近流行ってるやつ・・・ってくらいの認識しかない。。

## 調査

### Emotet とは

エモテット と呼び、拡散力が強いマルウェアの一種になります。
2014年に発見されて以降、形を変え生き残っています。
元々はバンキングトロージャンと呼ばれる、オンラインバンキングの認証情報を盗むマルウェアでしたが、
2017年以降は単体での動作でなくトロイの木馬やランサムウェアなどいろんなマルウェアに感染させる役割を持ちます。

### Emotet の攻撃方法

Emotetは攻撃者によってメールに添付されるなどし、受け取ったユーザはそのファイルを開くと感染するというものになります。
攻撃者はマクロ付きのwordやexcelファイルを添付して大量に送付するという方法をとっています。
ファイルを開き感染してしまうと、アカウントやパスワード、取引先の情報なども抜き取られてしまいます。

よくある方法では？と思う方も多いかと思いますが、
被害が広がったのにはいくつかウイルスとは見分けがつかないような工夫がありました。

- メールが巧妙

実際にあったものでは、正規にやり取りをしているメールに `RE:` をつけてあたかも実際のメールの返信を装おって
大量にメールが送付されました。
元のスレッドに割り込まれるので見破るのが難しいのが被害が広がった理由の一つです。

- Emotet本体には不正なコードを多く含まない

↑でも記載している通り、最近は単体での動作でなくマルウェアに感染させる役割を持ちます。
Emotet本体自体も悪さを行いますが、基本的には他のマルウェアに大量に感染させるようなものです。
また、感染者のPCにダウンロードさせたモジュールはファイルでなくメモリ上で動作するので調査者から発見されづらい工夫がされていあmす。

### Emotet の対策方法

- セキュリティ対策ソフトでの保護

Emotetに限らずですが、マルウェアへの感染等はセキュリティ対策ソフトでブロックできる場合があります。
セキュリティ対策ソフトを導入し、できるだけ最新化しておくことが重要です。

- セキュリティパッチの適応

Emotetを経由したマルウェアはOSやアプリケーション、様々な脆弱性を狙ったものが多いです。
できるだけ上記と同様ですがOSのセキュリティパッチやアプリケーションは最新化しておくことがた大切です。

- メールでのファイルをやり取りしない

Emotet自体の主な感染源はメールの添付ファイルです。
そのことからできるだけメールでファイルのやり取りをしないということが重要です。
普段からファイル転送サービスを使用しているとメールにファイルが添付されていると怪しむことができますが、
普段からメールでファイルの転送を行っていると、ついダウンロードしてしまう可能性があります。

### Emotet に感染してしまった際の対応

もしEmotetに感染してしまったら以下のようなことを実施する必要があります。

1. 感染端末をネットワークから隔離、被害の調査
2. 感染端末で使用していたアプリケーションやアカウントのパスワード変更
3. Emotetだけでなく、他のマルウェアへの感染調査
4. 関係者へ注意喚起
5. 感染端末の初期化

## 勉強後イメージ

Emotetもそうやけど、Emotetに感染してしまうと他のマルウェアにも感染しやすい状況になるのめっちゃ怖いな....

## 参考

- [最恐のマルウェア “Emotet（エモテット）” を徹底解剖。特徴と今必要な対策を解説します。](https://www.lanscope.jp/trend/16983/)
- [Emotet（Emotet）とは？特徴から危険性、対策方法まで徹底解説](https://cybersecurity-jp.com/column/34114)
- [「エモテット（Emotet）」の被害を招かないための対策とは？](https://eset-info.canon-its.jp/malware_info/special/detail/210422.html)
G検定合格体験記

# はじめに
　かなり前の話になってしまうのですが、G検定に合格をしたので記事に残しておこうかと思います。私がG検定を受けたのは2019年11月9日に行われた2019#3の試験になります。現在のG検定の参考になるかはわかりませんが、私の勉強法などについて書いていきたいと思います。

# G検定とは
　G検定は一般社団法人日本ディープラーニング協会が主催している人工知能に関する資格試験になります。試験範囲に関してはG検定のHPに詳細がのっているので、そちらを参考にしていただきたいのですが、内容としては人工知能に関する知識を広く浅く問われる試験となっています。なので、人工知能に関して興味を持ち始めた人が人工知能の概要を知るのに丁度いい指標となる試験だと思います。

# 受けた理由
　大学3年の春に大学の「機械学習」という授業が面白かったのがきっかけで、機械学習、人工知能についてもっと深く知りたいと思い、何か目標になるものはないかとネットで探していたところ、見つかったのがG検定でした。そこから夏休みを利用して勉強をして大学3年の11月に受験しました。

# 受けるメリット
　G検定は持っているからと言って、就活や転職活動で有利になったりすることはないと思います。私は自主的に人工知能の勉強をするための指標として選んだだけなので、特にメリットなどは考えていなかったのですが、合格から2年たった今考えると大きなメリットがあったと思います。

それは、<font color="Red">日本ディープラーニング協会のコミュニティ（CDLE）、およびそのSlackに入れること</font>です。

このCDLEでは様々なチャンネルがあり、活発な議論が行われています。私が重宝しているのが、おすすめの本を紹介するチャンネルで、人工知能に関する本の発売情報などを教えてくれます。また、CDLEメンバー限定で参加できる勉強会もあり、毎回講師の方を招いて、人工知能を使用した事業説明などが行われています。

# 勉強法
G検定のシラバスに書いてある用語をWordに書き出し、参考書にその説明が出てきたらまとめていく、という方式で勉強を進めていきました。

私は主に3冊の参考書で勉強をしました。

### 1. 人工知能は人間を超えるか
<img width="400" alt="mojikyo45_640-2.gif" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269186/1d3b4e1f-30fd-cbc6-48e5-4296f50c20aa.png>

引用元：https://www.amazon.co.jp/dp/B00UAAK07S

　G検定を主催している日本ディープラーニング協会の理事である東京大学の松尾豊教授が書かれている本です。めちゃくちゃ売れていて日本の人工知能の本で最も有名なのではないかという本で、この本を読めば人工知能に関する概観が得られると思います。公式HPのシラバスの内容もこの本でほとんどカバーされているのではないかと思います。人工知能に関して初めて勉強するという方はこの本を理解できるまで熟読することをお勧めします。

### 2.AI白書2019
<img width="400" alt="mojikyo45_640-2.gif" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269186/57e4645c-22e0-ebe1-5130-740a83e9ecf7.png>

引用元：https://www.amazon.co.jp/dp/B07QGRH7F6

　AIが具体的にどのような使われ方をしているのかの事例がたくさん載っています。ただ、G検定対策として重要なのは最後の方にのっている、人工知能に関する法律に関する部分です。（私はこの部分の勉強があまり楽しくなくてさぼってしまい、この本に関してはほとんど読みませんでした。）

　amazonなどで見ると分かりませんが、この本めちゃくちゃでかいです。持ち運びが非常に大変なので、小さいサイズにしてほしいです…

### 3. 徹底攻略 ディープラーニングG検定ジェネラリスト問題集
<img width="400" alt="mojikyo45_640-2.gif" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1269186/4b69c820-6968-3485-b367-3e0713d2557f.png>

引用元：https://www.amazon.co.jp/dp/B0976LT94B

　G検定のシラバスに沿った問題集で、これが解ければ、まず落ちることはないと思います。私がG検定を受けた当時は、G検定に関する問題集がこれと公式問題集くらいしかなく、公式問題集のamazonでの評価がすこぶる悪かったので、必然的にこの問題集を使うことになりました。解説もかなり丁寧に書かれているので、間違った問題の解説をしっかり読む、ということを3周くらいすれば十分だと思います。

# テストの感想
　G検定は120分で220問程度の選択肢問題を解いていきます。自宅での受験となるため、わからない問題はネットで調べることができますが、時間的に厳しいので、いちいち調べていたら時間が全く足りなくなります。私は上述のとおり、人工知能の法律関係の部分の勉強が少なかったので、この分野の問題でわからないものが多かったです。問題集が解けていればほとんどの問題は簡単に解けると思います。

# テスト結果
タイトルが合格体験記だったり、合格のメリットなどをすでに書いてきたのでわかっているとは思いますが、無事合格しました。得点率などは開示されないため、私がどれくらい解けたのかはわかりませんが、余裕をもって合格できていたのではないかと思います。

# 感想
　人工知能に興味を持った人がまず最初に勉強する内容としてちょうどいい資格試験だと思います。合格難易度は高くないと思うので、興味を持った人は受けてみると思います。

　私はこの試験に合格したのち、研究室で人工知能を用いた画像解析の共同研究を2つ掛け持ちをし、人工知能に関する長期インターンに参加し、G検定の上位資格にあたるE資格を受験するという人工知能三昧な日々を送っています。

またの機会に、そちらについての記事も書きたいと思います。
Vivliostyle-CLIで表にキャプションを付ける


見た目にそれほど不自然では無い形で表にキャプションを付けることができるCSSのサンプルです。

本来のtable要素内に記述するcaption要素は使用していないので注意してください。

## 汎用キャプション

表に限らず使えるキャプションです。

### 表示結果

![スクリーンショット 2022-02-23 23.39.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57548/c966c852-1d0f-bdcc-9cd9-f2f894c95f21.png)


### ソースコード

```markdown
<div data-caption="汎用のキャプション">

| 見出し1 | 見出し2 |
|--------|--------|
| 値1    | 値2     |

</div>
```

```css
/*
 * 汎用キャプション
 */

[data-caption] {
  margin-bottom: 3em;
  page-break-inside: avoid;
  position: relative;
  font-size: 0.85rem;
}

[data-caption]::after {
  content: attr(data-caption);
  text-align: center;
  bottom: -1.5em;
  width: 100%;
  position: absolute;
}
```

## キャプションを上に表示する

### 表示結果

![スクリーンショット 2022-02-23 23.43.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57548/d8b2e87f-346f-f7e2-0824-dd3a9fa0a587.png)


### ソースコード

```markdown
<div data-caption-top="汎用の上キャプション">

| 見出し1 | 見出し2 |
|--------|--------|
| 値1    | 値2     |

</div>
```

```css
[data-caption-top] {
  margin-top: 3em;
  page-break-inside: avoid;
  position: relative;
  font-size: 0.85rem;
}

[data-caption-top]::before {
  content: attr(data-caption-top);
  text-align: center;
  top: -1.5em;
  width: 100%;
  position: absolute;
}
```

## 表番号付きキャプション

表専用のスタイル定義を作れば表番号を自動的にインクリメントすることもできます。

### 表示結果

![スクリーンショット 2022-02-23 23.29.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57548/a0cdbfad-f090-de3d-ff91-7bef7a94c1c5.png)

### ソースコード

```markdown
<div data-caption-table="ひとつめのテーブル">

| 見出し1 | 見出し2 |
|--------|--------|
| 値1    | 値2     |

</div>

<div data-caption-table="ふたつめのテーブル">

| 見出し1 | 見出し2 |
|--------|--------|
| 値1    | 値2     |

</div>

```

```css

/*
 * 表番号付きキャプション
 */

body > section {
  /* Lebel 1の見出し毎に表番号カウンタをリセット */
  counter-reset: table-counter 0;
}

[data-caption-table] {
  margin-bottom: 3em;
  page-break-inside: avoid;
  position: relative;
  font-size: 0.85rem;
  counter-increment: table-counter;
  width: 100%;
}

[data-caption-table]::after {
 /* ここでキャプションの文字列を組立 */
  content: "表" counter(table-counter) " " attr(data-caption-table);
  text-align: center;
  bottom: -1.5em;
  width: 100%;
  position: absolute;
}


```
【AWS】Basic認証の設定手順

今回はAWSのEC2インスタンスを用いてApacheのBasic認証を導入していきたいと思います。
経緯としてはLPIC202の学習で座学の学習だけではApacheの設定関連のテスト範囲が記憶に定着しないため、実際に手を動かして覚えることを目的としております。

#前提条件
- Windows10を使用
- PCはDELLを使用
- 東京リージョンを使用
- Linux serverはAWSのEC2インスタンスを使用
- Apacheがインストールされていること。


##Basic認証の設定手順

１. htpasswdコマンドでユーザとパスワードを作成する

```bash
$ htpasswd -c /etc/httpd/htpasswd testuser
```

２. ユーザとパスワードが作成されたことを確認する

```bash
$ cat /etc/httpd/htpasswd
```

３. htpasswdファイルの所有者・グループ・権限を変更する

```bash
$ chown apache:apache /etc/httpd/htpasswd
$ chmod 600 /etc/httpd/htpasswd
```

４. 項番３で変更した内容が反映されていることを確認する

```bash
$ ls -l /etc/httpd/htpasswd
```

５. httpd.confを編集してDirectoryタブに以下の内容を追記

```bash
$ vim /etc/httpd/conf/httpd.conf
```
```/etc/httpd/conf/httpd.conf
<Directory "/var/www/html">
  AuthType Basic
  AuthName "auth"
  AuthUserFile /etc/httpd/htpasswd
  Require valid-user
</Directory>
```

６. Apacheの起動状態を確認する

```bash
$ systemctl status httpd.service
```

７.Apacheが起動していない場合は起動する（起動している場合は不要） 

```bash
$ systemctl start httpd.service
$ systemctl status httpd.service
```

８. 設定ファイルを反映させる

```bash
$ systemctl reload httpd.service
```
##Basic認証の動作確認

１. 任意のブラウザからhttp://{パブリック IPv4 アドレス}にアクセスして認証情報を入力するポップアップが表示されていることを確認
![basic認証画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/9db10ab3-e1aa-6a84-9e6a-58b7695cbaab.png)

２. htpasswdで作成した認証情報を入力してウェブページが表示されることを確認する

##あとがき
今回はBasic認証の設定手順について説明しました。
実際に手を動かすことでLPIC202に必要な知識が定着しやすいと感じました。
今後は積極的にLinuxを触っていき知識を積み上げていきたいと思います。
40 代おっさん GASのGmailMessageクラスについて学ぶ

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## GmailMessageクラス

GmailMessageクラスとは
メッセージを取り扱う機能を提供している。
メッセージからさまざまなデータを収得するメソッドや、メッセージの操作をするメソッドなど

＊GmailMessageクラスの主なメンバーの図は、参考資料の本を見ていただくか、ネットで調べください。

ちなみにこちらで書いてありました。
<https://for-dummies.net/gas-noobs/gas-japanese-reference-for-gmail/>

### メッセージ本文を取得する

メッセージの本文を取得するメソッドは
getBodyメソッド

構文

```javascript
GmailMessageオブジェクト.getBody()
```

HTMLタグも含めてメッセージ本文を収得

getPlainBodyメソッド

構文

```javascript
GmailMessageオブジェクト.getPlainBody()
```

HTMLタグを除いた純粋なテキスト部分のみを収得

がある

両者の違いはHTMLメールに対しての挙動（上を確認）

お試し

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0, 1);
  const message = GmailApp.getMessagesForThreads(threads)[0][0];

  console.log(message.getBody);
  console.log(message.getPlainBody);
}
```

### メッセージの返信と転送

返信：replyメソッド

構文

```javascript
GmailMessageオブジェクト.reply(本文 [, オプション])
```

全員に返信：replyAllメソッド

構文

```javascript
GmailMessageオブジェクト.replyAll(本文 [, オプション])
```

転送：forwardメソッド

構文

```javascript
GmailMessageオブジェクト.forward(宛先 [, オプション])
```

すべてのオプションは省略可能

お試し

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0, 1);
  const message = GmailApp.getMessagesForThreads(threads)[0][0];

  let repiyBody = '';
  repiyBody += '全員に返信をします';
  repiyBody += 'ご確認ください';
  message.replyAll(repiyBody);

  const recipient = 'k.toshiki1115@gmail.com';
  message.forward(recipient);
}
```

### メッセージの操作をする

メッセージにスターを付与したり、既読または未読にするなどの操作ができる。

お試し（スター）

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0, 1);
  const message = GmailApp.getMessagesForThreads(threads)[0][0];

  message.star();
}
```

お試し（配列すべてにスター）

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0, 1);
  const messages = threads[0].getMessages();

  GmailApp.starMessages(messages);
}
```

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
Elmerを使ったパラメトリック解析（FORTRANサブルーチン自作編）

前回の記事「Elmerを使ったパラメトリック解析」は[こちら](https://qiita.com/maimai310/items/702413677a834230bb28)

# 異方性材料の物性値設定
伝熱解析、構造解析、電磁界解析など、Elmerのモジュールの中には異方性材料をサポートしているものがあります。今回は伝熱解析で異方性の物性値を与える例で、パラメトリック解析を行いたいと思います。具体的にはFORTRANのプログラムで熱伝導率テンソルの主軸を回転させて、材料内で熱の通りやすい方向を色々変えてみるというものです。

今回のモデルはL字型の部品を考えます。ジオメトリは前回の記事のようにチュートリアルのものを使用できればよかったのですが、境界の設定が少々面倒だったため、Salomeを使ってUNVファイルで作成した以下のようなモデルを用いました。Elmerが対応しているメッシュ、ジオメトリファイル形式で作成できれば何でも大丈夫です。

![geo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524246/74795412-861a-c8fb-c917-42838aebf7a4.png)

ついでに境界条件を説明すると、L字の下部に一定の熱流束（100.0）を、それ以外の端部には室温（20.0）空気中での熱伝達（熱伝達率10.0）を与えました。（数値はテキトーです）


各種解析設定の方法は[前回の記事](https://qiita.com/maimai310/items/702413677a834230bb28)をご覧いただくとして、今回の記事の目玉となるFORTRANサブルーチンを使ったパラメトリック解析を行っていきます。

まず、今回の解析のパラメータである熱導電率テンソルの主軸の角度は以下のように、1°から180°へ1°ずつ変えていきます。
[Timestep Intervals] -> 180
[Timestep sizes] -> 1.0

次に、熱伝導率を以下のように記述します。
[Heat Conductivity] -> `Variable Time; size 2 2; Real Procedure "cond" "getHeatCond"`

この`size 2 2;`は以降の値が2×2の配列であることを示すElmerのキーワードで、`Real Procedure "cond" "getHeatCond"`は`cond.dll`（`cond.f90`をコンパイルしたもの）の`getHeatCond`サブルーチン（または関数）を呼び出すことを示しています。


次に、熱伝導率テンソルを計算するサブルーチンをプログラムしていきます。


```fortran:cond.f90
SUBROUTINE getHeatCond(model, n, t, cond)
    USE DefUtils
    IMPLICIT None

    TYPE(Model_t) :: model
    INTEGER :: n
    REAL(KIND=dp) :: t

    REAL(KIND=dp),pointer,contiguous :: cond(:, :)
    REAL(KIND=dp) :: ref_c(2, 2)
    REAL(KIND=dp) :: rad
    REAL(KIND=dp) :: R(2, 2)


    ref_c = reshape((/100.0, 0.0, 0.0, 1.0/), shape(ref_c))

    rad = t / 180.0 * acos(-1.0)
    R = reshape((/cos(rad), -sin(rad), sin(rad), cos(rad)/), shape(R))

    cond = matmul(matmul(TRANSPOSE(R), ref_c), R)

END SUBROUTINE getHeatCond
```

細かい説明は省きますが、パラメータ`t`（角度）を使って、主軸を回転させた熱伝導率テンソルを計算し、`cond`として返しています。`cond`の`contiguous`属性は無しで書く人もいるみたいですが、自分の場合invalid memory referenceのエラーが出てしまったので、対応としてつけたら動くようになりました。

次に、`cond.f90`のあるフォルダでコマンドラインを開き、`elmerf90 cond.f90 -o cond.dll`を実行すると、FORTRANのプログラムがコンパイルされます。（もしかしたら最初は`elmerf90`のディレクトリにPATHが通っていないかもしれないです）

`cond.dll`が作成されたら準備はOKなので解析を実行します。


# 解析結果
角度を変えると、定常状態はこんな感じに変わります。

![anim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524246/fa10bed2-8324-c525-3354-0a06061f8f37.gif)


せっかくなので、最高温度をプロットしてみましょう。
![plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524246/b70bbc46-1cb9-0b9f-ba16-c2f2dc897d2c.png)


角度を20°、150°くらいにすると最高温度を抑えられるらしい。（テキトーな設定なのでテキトーな結果）


# 最後に
今回はElmerを使ったパラメトリック解析の応用編として、FORTRANの自作サブルーチンを使った解析を行いました。正直に言えば今回の解析だとFORTRANを使わずElmerのMATCプログラムを使っても記述できましたが、より複雑な数学的計算を含む場合は今回のような方法が役に立つと思います。
WebDynpro開発に役立つWebページまとめ


# はじめに
WebDynpro開発の日本語記事が全くない！
それでは困る(私は困った)ということで、私の備忘録もかねて役立つWebページを残します。(ちなみにすべて英語の記事しかありません)

WebDynproなんか需要ない？確かにブラウザでWebDynpro使うくらいなら、Fiori使えばいい。PCで仕事するなら従来のGUI for Windows使えばいい。

しかし、WebDynproで開発しなければならないときもあるかもしれない。そういった珍しい案件に入った方の一助になればと思い書いています。

※WebDynproとは何かを説明している記事ではありません。単に備忘録としてリンクを貼っているだけなので、リンク切れ等あれば申し訳ないです。

# 実際に開発に役立ったWebページ
######・チュートリアル

https://archive.sap.com/documents/docs/DOC-8863

ひとまずこれに沿ってコーディングすると動くWebDynproが作成できます。
ちなみにレイアウトタブで選択画面に項目を配置したい場合は、右側のコンテナ(〇〇CONTAINER)を右クリックして、エレメントの挿入をしてください。左側の絵が描いているほうから、挿入はできないです。(できそうではあるのだが...単なる見本？)

######・画面のレイアウト(意図したところに画面の項目を置きたい)

https://blogs.sap.com/2012/06/03/usage-and-significance-of-various-layouts-in-webdynpro-abap/

完璧に位置は指定できないが、Matrix layoutを使用すると位置をそろえることはできます。

######・画面項目の表示、非表示

https://wiki.scn.sap.com/wiki/display/WDABAP/Set+visibility+of+button+dynamically

######・画面項目の必須設定

https://answers.sap.com/questions/10039928/webdynpro-input-field-required.html](url)

######・チェックボックスの設定

https://blogs.sap.com/2013/08/10/abap-webdynpro-steps-by-step-procedure-to-create-check-box/

######・SELECT-OPTIONSの画面表示

https://blogs.sap.com/2014/02/05/select-options-in-web-dynpro-abap-part-1/

######・メッセージ出力(指定した文言出力)

https://blogs.sap.com/2013/04/24/display-message-in-webdynpro-abap/

Using Wizardでやったほうが楽です。

######・画面項目の必須入力エラーチェック(SAP標準メッセージ)
INPUT FILEDの必須入力エラー

https://archive.sap.com/kmuuid2/207e4467-227e-2e10-6fbb-e3a562038296/Mandatory%20Field%20Check%20in%20Web%20Dynpro-%20ABAP.pdf

SELECT-OPTIONSの必須入力エラー

https://answers.sap.com/questions/11515202/check-mandatory-for-select-option.html

######・XSTRINGをSTRINGに変換

https://answers.sap.com/questions/6693477/conversion-xstring-to-string.html

Webでアップロードされたファイルは一度XSTRING型で読み込まれ、人が読める形式XSTRINGに変えなければなりません。

######・テキストシンボル

https://answers.sap.com/questions/10603038/text-symbols-in-webdynpro-abap.html?db=5

https://www.fareez.info/blog/text-symbols-in-web-dynpro-abap/

スーパークラスあたりはオブジェクト指向の継承のようなことをしているような気がします。(自信ない...)

######・トランザクションコード割当

https://www.kodyaz.com/sap-abap/create-transaction-code-for-web-dynpro-application.aspx#:~:text=WDCONFIGURATIONID%20%3A%20ID%20of%20the%20configuration%20Save%20and,within%20the%20web%20browser%20%28Internet%20Explorer%20for%20example%29

# おわりに
単にリンクを貼っただけで解説等一切していないですが、見ていただきありがとうございました。
[初心者向け]Javaデータ型について

#まず データ型の効果
　　データ型は変数を声明するために使用され、プログラムは実行中に異なるタイプに応じて異なるサイズの空間を割り当てます。例えば：

```perl:uniq.pl
int i = 10;
double d= 123;
```
i変数とb変数のタイプが異なり、空間サイズが異なる。

#Javaデータ型
Javaのデータ型主に2種
一.基本型（int double最もよく使われる）
1.第一類：整数型：byte short int long【long：1L】
第二類：浮動小数点型：float double【float：0.0F double：0.00B 】
 第三類:ブール型：Boolean【true false结果】
 第四類：文字型（char）【‘あ’】
2.八小類：byte short int long float double boolean char
二.引用型
stringとは引用型　基本型ではない “”を使う 

```perl:uniq.pl
String a = "こんにちは";
```
8つの基本タイプ以外は引用型です

#区别とは？
一.byte short int longの違い
　　１．占有バイトが違う
　　　　byte：1バイト short：2バイト int：4バイト long：8バイト
    2.値範囲
       byete：-128~127
       short：-32768~32767
       int：-2147483648~2147483647
       long：-9223372036854774808~9223372036854774807（数字L）
       （数字が2147483647を超えた場合はlongを使用しなければなりません）

二.floatとdouble区别の違い
  1.占有バイトが違う：float 4バイト  double 8バイト
  2.默认值：float：0.0f   double：0.0

三.charとshort
char&short実際には容量は同じですが、charはより大きな数字を表すことができます。charは文字を表しているので、負の区別はありません。

四.charとstringの違い
charは漢字を1つしか保存できません ‘’を使う
stringは漢字をたくさん保存できます　“”を使う

#ASCIIコードについて
　最初のコンピュータは文字をサポートしないで、科学計算だけをサポートして、それからコンピュータの発展に従ってコンピュータは文字をサポートし始めて、最初にサポートする文字の英語、そのため対応する文字の符号化が現れました---ASCIIコード
                    “ 0～9数字対応10進数48－57”
                    “ a~zアルファベット対応10進97-122”
                     “A~Zアルファベット対応10進65-90”

#Javaエスケープ文字
1.\+n=改行  2.\+t=tab 3.\+~=~  4.\+\=\   5.\+"="

#4種類の整数型の書き方（intを例とする）
10进制：

```perl:uniq.pl
int a = 10;
```
8进制：

```perl:uniq.pl
int b = 010;
```
16进制：

```perl:uniq.pl
int c = 0x10;
```
二进制：

```perl:uniq.pl
int d = 0b10;
```
#タイプ変換
1.一般的に整数のデフォルトはint，小数のデフォルトはdoubleです もちろん自分でタイプ変換を選ぶこともできます 小容量タイプは自動的に大容量タイプに変換できます

```perl:uniq.pl
long b = 200；//（200はint でもlongは8バイト intは４バイト　自動的に変換ました）  
```
2.强制变换

```perl:uniq.pl
long x = 100L;
int y = (int)x；//精度が損なわれる可能性があります
```
「マイクロサービスパターン」の復習 6章 イベントソーシング

## 概要

- Java読書会でせっかく勉強したのにつぎつぎと忘れていくので、印象に残ったところを記録していく

http://www.javareading.com/bof/

## 6章 イベントソーシングを使ったビジネスロジックの開発

モデリングした結果を反映したテーブルを作るのではなく、エンティティに対する生成・更新イベントをDBに記録していくという話
https://microservices.io/patterns/data/event-sourcing.html

### 従来のアプローチ

- やり方
    - なんらかモデリング
    - 対応するクラスを作る
    - 対応するテーブル作る
    - ORマッパーでテーブルとクラスをつなぐ
- 欠点
    - 履歴が残らない
    - 後付で履歴つくるのは大変
    - 生成・更新イベントも後付


### イベントソーシング

- やり方
    - モデリングはする
    - 対応するクラスは作る
    - でも永続化するのは、生成・更新イベントのみ（永続化用のテーブルをイベントストアと呼ぶ）
    - デシリアライズは、空オブジェクトにイベント履歴を繰り返し適用する
        - 場合によっては、スナップショットテーブルを用意して、高速化する
    - イベントの発行は、イベントテーブルのトランザクションログを見るなり、ポーリングするなりして発行する
- 利点
    - 履歴ファーストなので、当然すべての履歴が残る
    - イベント発行もネイティブに対応
- 欠点
    - イベントや対象となるオブジェクトのスキーマに追随するのが大変
    - 従来手法とあまりに違いすぎるので習得難易度が高すぎる
    - 履歴が残る分、削除が苦手
    - 履歴しかないので、検索が困難⇒これは7章のCQRSで説明されている検索専用サービスを建てることで解決する

### 実現手段

基本的に作者の作成したEventuateフレームワークシリーズを使う

- Eventuate Local
    - イベントストアの実装用ライブラリ
    - イベントの永続化はMySQL、イベントのパブリッシュはKafkaベース
    - スナップショット機能もあり
- Eventuage Client
    - Eventuate Localを基盤として、サービスを実装するためのライブラリ
- Eventuate Tram Saga
    - Sagaを実現するためのライブラリ
    - Sagaは4章で説明されている。マイクロサービスだとサービスをまたがるところはトランザクションが効かないので、変わりにSagaと呼ばれるものを作る

## 感想

- 難しくてついていけません。
- 概要レベルなら分かるのですが。
- Eventuateシリーズをよほど使いこなせないと実現できなさそう
    - ピットフォールになる部分をよくしっているか
    - トラブル時にどうデバッグするか？
- 6章、7章を合わせて読んでみると、マイクロサービスはイベントを発行するのが当たり前なのか？
- 世の中のマイクロサービス開発というのは本当にこの本に書いてあるようなことをやっているのか？それとも2、3種類程度のWebアプリがコンテナ化されて動いているだけでモノリシックアプリと大差ないのか？
Hardhatでpolygonテストネットワークへのデプロイ方法まとめ

## 概要
hardhatで作成したdappsをAlchemyを用いてPolygonテストネットワーク（Mumbai）にデプロイするまでのまとめ

- [Hardhat](https://hardhat.org/getting-started/)
- [Alchemy](https://dashboard.alchemyapi.io/)
- [polygonscan](https://polygonscan.com/)

## 1. MetamaskにPolygonテストネットワークの設定をする
以下リンク先の通りに設定

https://docs.polygon.technology/docs/develop/metamask/config-polygon-on-metamask#using-polygonscan

## 2. テストネット用のトークンを取得する
以下リンク先で取得できる

https://faucet.polygon.technology/

![スクリーンショット_2022-02-23_22_20_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272185/4217f14c-174c-e9ab-89a9-ea988a6c084a.png)

## 3. Alchemyでアプリを作成する

以下リンク先で作成

https://dashboard.alchemyapi.io

アプリ作成時にHTTPのURLをコピーしておく

![スクリーンショット_2022-02-23_22_31_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272185/876a0ff0-abae-c7a3-b6a8-fe32246ccc1a.png)

## 4. 作成したコントラクトをデプロイする

コントラクト自体の作成は省略します

#### 環境変数の設定
`.env`ファイルを作成し、環境変数を設定する

```bash
$ npm i --save-dev dotenv
```

以下を`.env`ファイルへ記述

- 「3. Alchemyでアプリを作成する」　でコピーしたURL
- メタマスクアカウントの秘密鍵

メタマスクアカウントの秘密鍵取得方法
![名称未設定.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272185/bf3a8afd-4efb-a31f-e638-655f7d5b7faa.jpeg)


```.env
API_URL=https://polygon-mumbai.g.alchemy.com/v2/xxxxxxxxx
PRIVATE_KEY=xxxxxxxxx
```

```hardhat.config.js
require("dotenv").config();  //dotenvを読み込む
require("@nomiclabs/hardhat-waffle");

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.8.4",
  //mumbaiを追加
  networks: {
    mumbai: {
      url: process.env.API_URL,
      accounts: [process.env.PRIVATE_KEY],
    },
  },
};
```

コンパイル　＆　デプロイ

```bash
$ npx hardhat compile
# デプロイスクリプトをdeploy.jsで記述している場合
$ npx hardhat run scripts/deploy.js --network mumbai
# hardhat.config.jsのタスクで記述している場合
$ npx hardhat deploy --network mumbai
```

デプロイ後にエラーなど出ていなければ成功
デプロイしたコントラクトは、alchemyのダッシュボードから確認できる

## 最後に
意外と簡単にデプロイはできますが、メタマスクの設定などが面倒でした＞＜
Keycloakでmaster realmを無効化しちゃった場合の回復方法

# この記事の概要

Keycloakの設定を誤って、管理者ログインできなくなるケースと、その回復方法の話。

# 起きたこと

[Keycloak](https://www.keycloak.org/)で管理者ログインしようとしたら、以下のような画面が表示されログインできなくなってしまった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/5ead75e7-fb34-b9f0-cf3a-2f8559a7292a.png)

# 原因に至った操作

よく分かってないまま、初期状態で作成されていた「Master」realmの「Enabled」をオフにしてしまった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/d70dec02-8a93-321b-a44e-02cbf9c3cb96.png)

（Keycloak自身の管理に必要なのかよ！！知らないよ！！）

# 回復方法

デフォルトのH2データベースを使っているので、以下の手順でrealmを再度有効に設定する。

1. Keycloakサービスを停止
1. H2データベース管理アプリを起動
1. 管理アプリ(ブラウザ)からKeycloakのデータベースを指定して開く
1. realmの設定を更新

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/6e119a38-2694-b3d1-5d55-7307f4fda561.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/f6f74049-0286-2db1-39e4-ae937d9e2d67.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50759/89eab295-aca5-5d08-d7ef-0f24969a3e05.png)


# 参考

[[keycloak-user] I disabled "master" realm...now I'm stuck
](https://lists.jboss.org/pipermail/keycloak-user/2017-September/011770.html)

[H2 DBの使い方](https://blue-red.ddo.jp/~ao/wiki/wiki.cgi?page=H2+DB%A4%CE%BB%C8%A4%A4%CA%FD)
【React-Rouer】S3上でreact-router-domを利用したSPAで404エラー

## 問題
Reactのページ遷移で404になる。

## 対応方法

S3単体でできます。
amazon s3から
→  {バケット名}
　→「プロパティ」
　　→「静的ウェブサイトホスティング」(ページの下の方)
　　　→「編集」
　　　　→「静的ウェブサイトホスティング」に"index.html"を記載

## その他
apacheなどでも同じ問題が発生しますが、以下で表示されるようになります。

```
sudo vi /etc/httpd/conf.d/httpd.conf
#ErrorDocument 404 /missing.html
ErrorDocument 404 /index.html
```
apache再起動する

以上
Windbgを使用したClash Dumpの解析

# 問題

アプリケーションが現在の環境(Windows10)で起動しませんでした。エラーメッセージも表示されず終了しており、ソースコードも持っていなかったため何が悪いか分かりませんでした。そこで、ダンプファイルを利用した解析を行いました。

# 環境

Windows10

## ダンプファイルの出力設定

Applicationがclashした際に、ダンプファイルを出力する設定を行いました。
以下のAdobeのサイトを参考にしました。丁寧に書かれているので分かりやすいです。
[WIndows MachineでClash dampを作成する方法](https://helpx.adobe.com/jp/xd/kb/how-to-generate-crash-dump-on-windows-machine.html)

# ダンプファイルの解析

出力されたファイルを`Windbg`を使用して解析します。WindbgはWindowsのデバッガーです。ダンプファイルの解析やアプリにアタッチしてリアルタイム解析することができます。また、Kernel modeとしてwindowsの深い部分も調べることができます。x64とx86がありますが、今回は32bitアプリケーションであったためx86の方を使用しました。
WindbgでDumpファイルを開き、`!Analyze -v`コマンドで解析を行うと以下の結果が表示されました。

```
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

DEBUG_FLR_EXCEPTION_CODE(80040154) and the ".exr -1" ExceptionCode(e0434352) don't match

KEY_VALUES_STRING: 1
.
.
.

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 296

    Key  : CLR.BuiltBy
    Value: NET48REL1

    Key  : CLR.Engine
    Value: CLR

    Key  : CLR.Exception.System.Runtime.InteropServices.COMException._message
    Value: CLSID {AE784C6C-0155-11D3-B24B-0000F879F93B} を含むコンポーネントの COM クラス ファクトリを取得中に、次のエラーが発生しました: 80040154 クラスが登録されていません (HRESULT からの例外:0x80040154 (REGDB_E_CLASSNOTREG))。

.
.
.
```
以上の結果から特定のCOMコンポーネントが足りず、起動できないことが分かりました。
COM(Component Object Model)はソフトの機能を外部からアクセスして使用する仕組みのことです。
ネットで調べた結果、特定のソフトが必要なことがわかりました。このソフトをインストールするとアプリケーションは正常に起動しました。
開発環境にはインストールされているが、ユーザー環境にはされていないソフトウェアに依存してしまうことはままありますね。

# まとめ

アプリケーションが起動しない場合、Dumpファイルを解析することで解決できる場合があります。

# 参考
[Analyze crash dump files by using WinDbg](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/crash-dump-files)
【JavaScript関数ドリル】Lodash関数の実装【勉強用】_.join関数  


#【JavaScript関数ドリル】初級編の_.join関数の実装のアウトプット

       
```javascript:_.join関数の挙動
_.join(['a', 'b', 'c'], '~');
// => 'a~b~c'
```
第1引数の配列の要素の間に、第2引数を追加していく
第2引数がなければ初期値の`','`が追加される
##_.join関数の課題内容
https://youtu.be/tl8HO0GVaIs

##_.join関数に取り組む前の状態
- 配列に任意の位置に順番に挿入するには`splice`を使えばよさそう
- 普段通りの`for(let i = 0; i < array.length; i++)`でよさそう

##_.join関数に取り組んだ後の状態
- かなり強引に実装している
- forループにspliceを用いてインクリメントした結果、当初ループの条件を`i < array.length`としていたため無限ループとなってしまった
- 無限ループを改善できた後も、変わりゆく配列の要素数に`i`の2個飛ばしで無理やり対応させてしまった
- 変数名を`new○○`とする癖があるので、解答のように配列のコピーであれば`copiedArray`など分かり易い変数名にしていくべきだと感じた
- 加算代入`+=`について理解していなかった


##_.join関数の実装コード

```javascript:
const join = ((array, separator = ',') => {
    const newLength = array.length;
    const newArray = array.slice();
    for (let i = 1; i < (newLength * 2) - 1; i = i + 2) {
        newArray.splice(i, 0, separator);
    }
    return newArray.toString().replace(/,/g, '');
});

const arrays = ['a', 'b', 'c', 'd']
console.log(join(arrays, '~'));
// => 'a~b~c~d'
```



##_.join関数の解答コード

```javascript:
function join(array, separator = ',') {
  const copiedArray = [...array];

  let joinedString = copiedArray.shift();
  for(let i = 0; i < copiedArray.length; i++) {
    joinedString += separator + copiedArray[i];
  }

  return joinedString;
}

console.log( join(['a', 'b', 'c'], '---') );
// => 'a~b~c'
```
pg_dumpでダンプファイル作成。ローカル→(ssh接続)踏み台サーバー→DBサーバー

# DB接続環境

![pg_dump.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278776/32128693-f773-8f60-ccd0-cb5bacad3846.png)

図のような環境でローカルにダンプファイルを作成したいケースはありませんか？

SQLクライアントツールを使うと簡単にダンプファイル作成出来ますが、開発者が各々好きなツールを使っていたので作成方法の共有が面倒でした。
スマートに作成したいなと思い調べたところ、2行のコマンドで出来ることが分かったので共有します。

# コマンド

localに`postgresql`をインストールして下記コマンドを実行。

SSHポートフォワーディング
```zsh
ssh [remote.username]@[remote.host] -p [remote.port] -i [秘密鍵のpath] -f -N -L [local.port]:[db.host]:[db.port]
```

ダンプファイル作成
```zsh
pg_dump "host=localhost port=[local.port] dbname=[db.name] user=[db.user] password=[db.password]" > ~/Downloads/backup.dmp
```

# コマンドの補足

ポートフォワーディングを利用してlocalのポートをDBサーバーのポートと見なす設定を行います。

```zsh
// 踏み台サーバーにssh接続。
ssh [remote.username]@[remote.host] -p [remote.port] -i [秘密鍵のpath]

// 「-f」でバックグラウンド実行。「-N」でリモートコマンドを無効。
-f -N

// 「-L」がポートフォワーディングのオプション。local.portは空いているポートを指定。
-L [local.port]:[db.host]:[db.port]
```

今回は、踏み台サーバーからDBサーバーへの接続はパスワード認証を想定。
```zsh
// 接続パラメータの指定方法としてconninfo文字列を使用
pg_dump "host=localhost port=[local.port] dbname=[db.name] user=[db.user] password=[db.password]"

// ダンプファイル格納先を指定。
> ~/Downloads/backup.dmp
```
conninfo文字列について

https://www.postgresql.jp/document/9.1/html/app-psql.html#:~:text=%E6%8C%87%E5%AE%9A%E6%96%B9%E6%B3%95%E3%81%A8%E3%81%97%E3%81%A6-,conninfo%E6%96%87%E5%AD%97%E5%88%97,-%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99
40 代おっさん GASのメッセージを取得する

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## スレッドからメッセージを収得する

受信したメールの情報や内容を蓄積するには、メッセージを取得する必要がある

メッセージを取得する方法

・スレッドからメッセージを取得する
・IDでメッセージを取得する
・スレッドの配列からメッセージを取得する

### スレッドからメッセージを取得する

GmailThreadクラスの
getMessagesメソッドを使用

構文

```javascript
GmailThreadオブジェクト.getMessages()
```

お試し

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0, 1);
  const messages = threads[0].getMessages();
  console.log(messages[0].getSubject());
}
```

### IDでメッセージを取得する

メッセージにも一意で決まるIDが付与されている。
メッセージIDがわかれば
getMessageByIdメソッドで直接収得できる。

構文

```javascript
GmailAPP.getMessageById(id)
```

お試し

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0, 1);
  const messages = threads[0].getMessages();
  const id = messages[0].getId();

  const message = GmailApp.getMessageById(id);
  console.log(message.getSubject());
}
```

### スレッドの配列からメッセージを取得する

スレッドの配列から直接メッセージを取得できる
getMesssagesForThreadsメソッド

構文

```javascript
GmailAPP.getMesssagesForThreads(スレッドの配列)
```

お試し

```javascript
function tosiki() {
  const threads = GmailApp.getInboxThreads(0, 2);
  const messagesForThreads = GmailApp.getMessagesForThreads(threads);

  for (const [i, thread] of messagesForThreads.entries()) {
    for (const [j, message] of thread.entries()) {
      console.log(`[${i}] [${j}]: ${message.getSubject}`);
    }
  }
}
```

## 参考資料

<https://www.amazon.co.jp/s?k=google+apps+script+%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80&adgrpid=110264232688&gclid=CjwKCAiA9aKQBhBREiwAyGP5lSl7AJJLCvOEHb4wQgMlyqW1fll5X8GDTT_Rkd1_soUAyIPMXQr26hoClHEQAvD_BwE&hvadid=553833563682&hvdev=c&hvlocphy=1009076&hvnetw=g&hvqmt=b&hvrand=4378489642044417389&hvtargid=kwd-594191211348&hydadcr=4106_13159878&jp-ad-ap=0&tag=googhydr-22&ref=pd_sl_2x1owglv0s_b_p52>
[Nuxt] @nuxt/color-modeを使おうとしたらエラーが出た

# 今回の題

NuxtとTailwindCSSで作った個人ブログでダークモードを試してみようと考え、[公式](https://color-mode.nuxtjs.org/)を参考に@nuxtjs/color-modeというモジュールをインストールしました。

```terminal
$ npm install @nuxtjs/color-mode
```
インストール後に公式の通りにnuxt.config.jsに設定を済ませコンパイルを行ったところ、
下記のエラーが出てきました。

```terminal
 FATAL  Cannot find package '@nuxt/kit' imported from プロジェクトまでのパス/node_modules/@nuxtjs/color-mode/dist/module.mjs
```

@nuxt/kitというパッケージが無いよ、怒られてます。
ところが、@nuxtjs/color-modeの公式を見ても、そんなパッケージを入れるようにとは書かれていません。
なら原因は何かと調べたところ、以下のようなすごく初歩的なミスでした😓

# 原因

原因：@nuxtjs/color-modeのバージョン

パッケージ周りのエラーでまず疑わしいのはバージョンだと思いますが、
今回はまさにそこでした。

今回、使用していたNuxtのバージョンは2.15.8。いわゆるNuxt2系です。
@nuxt/color-modeの最新版(メジャーバージョンが3のもの)はNuxt3系のみに対応しているので、インストール時にバージョンを指定してあげる必要がありました。

# 解決方法

間違えたものを削除します。

```terminal
$ npm uninstall @nuxtjs/color-mode
```

以下で提供されているバージョンを調べます。

```terminal
$ npm info @nuxtjs/color-mode versions
```

↓結果。

```terminal
[
  '0.0.1',        '0.0.2',
  '1.0.0',        '1.0.1',
  '1.0.2',        '1.0.3',
  '1.1.0',        '1.1.1',
  '2.0.0',        '2.0.1',
  '2.0.2',        '2.0.3',
  '2.0.4',        '2.0.5',
  '2.0.7',        '2.0.8',
  '2.0.9',        '2.0.10',
  '2.1.0',        '2.1.1',
  '3.0.0-beta.0', '3.0.0-beta.1',
  '3.0.0',        '3.0.1'
]
```

この中でメジャーバージョン2の最新のものである2.1.1をインストール。

```terminal
npm install @nuxtjs/color-mode@2.1.1
```

無事にコンパイルも行え使用出来るようになりました。

# 参考
[Nuxt Color Mode - Setup](https://color-mode.nuxtjs.org/#setup)
このバージョンに関する注意喚起は、Setupの項目の一番初めに大きく書かれていました😓
AWS EC2からS3にIAMロールでアクセスする

# できたこと
EC2にS3権限のあるIAMロールを付与すると、aws configureを設定しなくても、EC2からAWS CLIでS3にアクセスできるようになりました。
AWS CLIではEC2インスタンスでaws configureが行われていない場合に、EC2のIAMロールを利用してくれるそうです。

## 参考url
### AWS CLIでのEC2のIAMロールの利用
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html

# 勘違いしていたこと
EC2からS3にアクセスする際に、S3権限をもったIAMユーザーの認証と、EC2へのS3権限のIAMロールの両方が必要だと思っていた。
EC2へのS3権限のロールがあれば、AWS CLI・AWS SDK等からS3にアクセスできる。