OmniAICreator/Qiita-1.07M huggingface dataset:
ReactでSCSSの変数をimportする

# 概要
Reactでscss moduleを扱うとき、scss内で定義した変数をReact側に持ってきたいことがたまにあるので、メモ。

# やりかた

`:export` を使う。


``` colors.module.scss
$dark-087: rgba(0, 0, 0, 0.87);

:export {
    dark087: $dark-087;
}
```

``` Hoge.tsx
import style from '../style/colors.module.scss';

export default Hoge = () => (
  <div style={{
    border: `1px solid ${style.dark087}`, 
  }}>
    <p>Hello man!</p>
  </div>
);

```

# おわり
- 大抵は `className` でやるけど、必要なときに。

# 参考
- [https://github.com/css-modules/css-modules/issues/86#issuecomment-158273243](https://github.com/css-modules/css-modules/issues/86#issuecomment-158273243)
[HTML/CSS]SVGで円グラフを作り、くるっとCSSで動かしたい

[SVGで円グラフを描くシンプルな方法 – KSK\-soft\.com](https://ksk-soft.com/2014/08/06/svg-pie-graph/)

このサイトを参考に、SVGで円グラフを作って回しながら表示される動きをつけた。
一つずつの割合ずつアニメーションで出したかったが、とりあえず一度に表示。

<p class="codepen" data-height="406" data-theme-id="0" data-default-tab="html,result" data-user="himeka223" data-slug-hash="pozdqXN" style="height: 406px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="SVGで円グラフ">
  <span>See the Pen <a href="https://codepen.io/himeka223/pen/pozdqXN/">
  SVGで円グラフ</a> by himeka223 (<a href="https://codepen.io/himeka223">@himeka223</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

#SVGとは

今までSVGは、

* ただどの拡張子よりもきれいに表示できる画像データ
* なんかHTMLみたいなので出来上がってる？

みたいな認識しかなかった。ちゃんと調べてみた。

参考：[WEBデザイナーのはじめての「SVG」 \- ウェブ企画ラボ](https://webkikaku.co.jp/blog/webdesign/svg_for_webdesigner/)

>SVGとはScalable Vector Graphics（スケーラブル・ベクター・グラフィックス)の略で、**JPEGやPNGのような画像(ビットマップデータ)ではなくイラストレーターで扱うベクターデータ**

イラストレーター用のやつだから、書き出す時イラレでやるのが一番安心だったのか、、、！

##SVGデータをWEBで表示させるには

* imgタグで画像として読み込ませる
* インラインで直接HTMLに書き込んで表示させる

今まで私が使ってたのは、**imgタグで画像として読み込ませる**方法。
今回は**インラインで直接HTMLに書き込んで表示させる**方法を使い、CSSアニメーションで動かす。

SVGと少し和解できたので、早速かいてみちゃう。

#viewBoxとは！？

なんか聞いたことあるけど`viewBox`とはなんぞと思ったので調べた
参考：[SVGのviewBoxをわかりやすく紐解く](https://www.indetail.co.jp/blog/13002/)

> viewBoxを指定することで、**描画エリアのアスペクト比、およびその中の要素の相対的なサイズ**を決定

言葉のまんまだった。
**描画エリアの大きさと要素の場所を決めてる**ってことにしよう。
ここで気をつけるのは、
**SVG自体の要素の`width`と`height`と
描画エリアの`width`と`height`全く別ということ。**

##viewBoxは４つの値から指定できる

`viewBox="x, y, width, height"`

* `x`と`y`は左上からみたx座標とy座標の位置
* `width`と`height`は描画エリアの幅(座標値)と高さ(座標値)

なんとなくわかった気がしたので早速かいていく

#円グラフを作る

##構造

* 円は`svg`の`circle`タグでかいていく。
* 円の色は、塗りは透明で、線の色をつけ、線を太くし、中心まで線とすることで出だしている。
* 円の割合は円の線を破線として、線分の長さで決めている
* 割合の数の分、円を作り重ねている


###`circle`タグとは

`cx="31.8309886184" cy="31.8309886184" r="15.9154943092"`

* cx …円のX方向への中心座標
* cy …円のY方向への中心座標
* r  …円の半径

###ポイント

>円弧をパーセンテージで指定し易くする為に、以下の工夫をしてます。

* 円周が100pxになるように逆算し、半径（r）を`15.9154943092`にする
<円周を求める公式>
`円周{100}`=`直径{？}`×`円周率{3.14159265359}`
<直径を求めるには>
`直径{？}`=`円周{100}`÷`円周率{3.14159265359}`
直径は`31.8309886184`となり、半径を`15.9154943092`となる。


* 円の中心（cx,cy）は、半径の倍の`31.8309886184`にしておく
* svgのviewBoxは、見かけ上2倍になった円が収まる様に、半径（r）の4倍の大きさ`0 0 63.6619772368 63.6619772368`にする
* 扇型は時計で言うと3時の位置から描かれはじめる。円グラフにするなら、12時からの方が良いので、`stroke-dashoffsetを25（1/4回転分）`ずらす。
* svgの大きさをコントロールし易くする為に、svgをdiv等でラップして、ラッパーに幅を指定する。svg自体は、ラッパーの幅に応じて変わるように`padding-bottom trick`を使う。
※親要素に`padding-bottom`と`width`を同じ大きさにし、子要素を`position`で絶対位置を指定し、width,heightを100%にすることで、親要素の大きさに合わせて子要素は変わる。

* このように準備した上で、例えば30%の扇形を描きたいなら、 `stroke-dasharray=”30,70" `とする。

引用：[SVGで円グラフを描くシンプルな方法 – KSK\-soft\.com](https://ksk-soft.com/2014/08/06/svg-pie-graph/)

自分の言葉で書くのが難しすぎたので、参考サイトの言葉を引用させていただきました。m(_ _)m

`circle`タグは1つから出来てるわけではなく、割合ごとに円を用意し、線分で割合を決め、重ねている。


##割合の計算
sassでは計算ができるのでその機能を使い、`1/6`等を`(100/6)`という値にし計算させている。



#まとめ
簡易的なまとめになってしまった、、、
SVGについてもまとめも書きたい。
Qt Quick（C++＋QML）サンプルアプリケーション

Qt 5.13を勉強して、c++＋QMLでアプリケーションを作りました。
ドキュメントは読みやすくて、5.13ではサンプルがたくさんあるのでとっつきやすいですが、`QAbstractListModel`を継承したc++定義クラスのサンプルが無かったので公開します。

c++サイドで定義、操作する自前のクラス型のリスト`QList<CustomClass>`をいい感じに動的表示するアプリケーションです。

基本的なLayout、Animation、Model/View、SIGNAL/SLOTのC++：QMLバインディングの参考にもなると思います。

# 環境
* Qt 5.13
* Qt Creator 4.92

# 動き
![qtquicksample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/4a1c69e5-30e5-7e5a-e606-ced996ebfe8f.gif)

# ソースコード
https://github.com/koyayashi1231/QtQuick_QListSample

```bash
git clone https://github.com/koyayashi1231/QtQuick_QListSample.git
```
AWS Systems Manager ちょい触ってみた。

試験ででそうなので、AWS Systems Manager を纏めてみた。というか触ってみた。

セッションマネージャだけはやったことある。
[AWS Session Manager ハンズオン](https://qiita.com/leomaro7/items/2ec067a457d7062c37f8)

#1.AWS Systems Managerとは#
AWS内に構築したEC2インスタンスなどのリソースを統合的に可視化、管理し、運用オペレーションなどの自動化などの制御を実現するサービスです。
AWSのリソースだけでなく、オンプレミスに構築されたサーバも含め、ハイブリッドでリソースや運用状況の可視化および自動化を実現できます。



#2.機能##

##2-1 運用オペレーションの自動化##

|機能|説明|
|-----|------|
|メンテナンスウィンドウ　|定期的に行う運用作業やサービス停止の実施時間帯をスケジューリングして定義します。|
|ランコマンド|SSHやRDPを使用せず、安全にEC2インスタンス上のOSに接続し、コマンド実行などの一括操作を行う。|
|セッションマネージャ|SSHやRDPを使用せず、リモートアクセスを行う。|
|オートメーション|一連の運用作業のフローを定義し、自動化する。|

##2-2 リソース構成の可視化と管理##

|機能|説明|
|-----|------|
|アクティベーション|オンプレミス、AWS以外のサービス、デバイスを登録する。|
|マネージドインスタンス|EC2やオンプレミス仮想マシンの一元的な可視化と管理を行う。|
|ステートマネージャ|OS設定値をポリシーに定義し、それを維持する。|
|インベントリ|インストールソフトウェア一覧を収集、検索する|
|パッチマネージャ|OSパッチの選択と適用を自動化に実施する。|
|ドキュメント|Systems Manager自体の設定や操作を記述するためのドキュメント|
|パラメータストア|設定値やパスワードなどを集中管理する階層型ストレージで、IMAなどのアクセス制御サービスから参照できる。|



#3.準備するもの#

- Systems Manager APIへのアクセス経路
 - インターネットへのアウトバウントアクセス（SSM AgentはSystems Manager APIを呼び出すため、インバウンドは不要）
 - VPCエンドポイント
- IAMロール
 - IAM ポリシー「AmazonEC2RoleforSSM」を割り当て
- SSM Agent
 - AWSが提供するAMIの一部には、デフォルトでSSMエージェントがインストールされています。それ以外は手動でインストールします。
 - CloudWatch AgentやInspector Agentは後からSSMを使用してインストールすれば良い.



#4.やってみる#

【3.準備するもの】は整っているものとします。

##4-1 ランコマンド##
ランコマンドで、SSMAgentのインストール と シェルスクリプトを利用して yum　update を実行してみます。

「マネージドインスタンス」から対象にインスタンスを選択し、「コマンドを実行」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/a5baf849-3c25-6a9a-56e6-ab13078895cf.png)

今回は「AWS-UpdateSSMAgent」を「実行」してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/ed3c75e2-8351-93b5-f296-3b93373698d7.png)

下記のとおり実行されたことがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/1d2ee946-de2c-f9a2-9ca5-a300a5477450.png)

今度は同じように「AWS-RunShellScript」で sudo yum update -y を実行してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/22fd2a69-07c5-c4b5-2f0c-1352afaf6069.png)

「出力」から実行されたことがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/806a1ba3-92c0-1cce-375c-e0822c273ebe.png)


##4-2 ステートマネージャ##
ドライバーが利用可能になると自動的に新しい AWS PV ドライバーをダウンロードしてインストールするよう ステートマネージャー を設定する方法を示します。

どのインスタンスを、
いつ、
何を処理するのかを指定する。
ドキュメントは「AWS-ConfigureAWSPackage」、パラメータは「Install」Name「AWSPVDriver」とします。
なお、今回は実行するだけなので特にスケジュールはしていません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/190b38bd-3d09-dcba-328f-51309a65610c.png)

「出力」から実行されたことがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/990d13c2-7d62-bd41-b52b-396a61b8c5c5.png)


今後も追加していく予定。。。


#リンク#
[パッチマネージャー で hooks をかけれるように](https://qiita.com/leomaro7/items/216075ce7e4917f81d5f)
言語処理100本ノックやってみる　16

#16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り，入力のファイルを行単位でN分割せよ．同様の処理をsplitコマンドで実現せよ．

#解答
```py
import math

fname = 'hightemp.txt'
n = int(input("自然数入力よろ"))

with open(fname) as f:
    lines = f.readlines() #①ファイル全体をリストに読み込む

count = len(lines) #count=24だった
unit = math.ceil(count / n)  # ceilは小数点を切り上げる

for i, offset in enumerate(range(0, count, unit), 1):#range(0, count, unit)でリスト作成になっている
    with open('child_{}.txt'.format(i),'w') as out_file:
        for line in lines[offset:offset + unit]:#[0:8],[8:16],[16:24]
            out_file.write(line)
```
＃参考記事
#①readlines()とは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/b7d1d341-b3d0-0752-a0c6-1d71f990c5dc.png)
https://www.sejuku.net/blog/62683
#②enumerate関数とは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/1505fcd1-586d-5aa7-c8c2-24cc46818939.png)
https://note.nkmk.me/python-enumerate-start/
Cisco 設定

プログラミング知識をMarkdown記法で書いて共有しよう:P

対象読者: 自分

前提: Aeronet 1200とかいうふっるーい機体で確認した。GUIツールとかもうサポート終わってて落とせないんだよね。前にも使ったんだけど、もう二度と使うことはないだろうと思って忘れてたら、二度目があったので三度目に備えて保存する。APなんざbuffaloでえーやろ！

コンソールで設定できるはずなんだけど、Teratermになんの反応もない(ストレートの9600-8-N-1だよね!?)のでブラウザインターフェースでの設定。

# リセット

電源を切って、後ろの MODE ボタンを押しっぱなしで起動。おしっぱなしのまま、1～2秒たってオレンジ色のランプが点灯したらリセット完了？

# SSIDの作成

1. 左側のメニューから`Security` > `SSID Manager`を選択。画面が更新されて、更にデータが反映されるまで待機。
2. `SSID Properties`の`Current SSID List`のリストボックスから、`<NEW>`を選択。`SSID`のテキストボックスに新規のSSIDを入力して、`Apply`をClick。データが反映されるまで待機。
3. 画面を下までスクロールして、`Guest Mode/Infrastructure SSID Settings`のSSIDを適用したいアンテナの`Set Beacon Mode`で`Single SSID`を選択して、その右の`Set Single Guest Mode SSID`で作成したSSIDを選択する。
4. `Apply`をClick。データが反映されるまで待機。

# WPA-PSK TKIPの設定

1. 左側のメニューから`Security` > `Encryption Manager`を選択。画面が更新されて、更にデータが反映されるまで待機。
2. 画面上部のタブで、セキュリティを設定したいアンテナ(RADIO0とか1とか)を選択する。データが反映されるまで待機。
3. `Encryption Modes`の`Cipher`のラジオボタンを選択し、コンボボックスから`TKIP`を選んで、`Apply-RadioN`または`Apply-All`をClick。データが反映されるまで待機。
4. 左側のメニューから`Security` > `SSID Manager`を選択。画面が更新されて、更にデータが反映されるまで待機。
5. `SSID Properties`の`Current SSID List`のリストボックスから、セキュリティを設定したいSSIDを選択する。
6. `SSID Properties`の`Interface`で、`Encryption Manager`で暗号方式を設定したアンテナにチェックを入れる。
7. `Client Authentication Settings`の`Methods Accepted`で、`Open Authentication`にチェックを入れ、その右のコンボボックスでは`<NO ADDITION>`を選択。
8. `Client Authenticated Key Management`の`Key Management`で、`Mandatory`を選択し、`WPA`にチェックを入れ、さらに`WPA Pre-shared Key`に設定したいパスフレーズを入れる。
9. `Apply`をClick。データが反映されるまで待機。

# WPA2-PSK AESの設定

WPA-PSK TKIPの設定手順の以下の部分が違う。

<ol start="3">
<li> `Encryption Modes`の`Cipher`のラジオボタンを選択し、コンボボックスから`AES CCMP`を選んで、`Apply-RadioN`または`Apply-All`をClick。データが反映されるまで待機。
</li></ol>

# WPA-PSK AES, WPA2-TKIPの設定

調査中。わっかんね。

# WPA Key更新間隔の設定

1. 左側のメニューから`Security` > `Encryption Manager`を選択。画面が更新されて、更にデータが反映されるまで待機。
2. 画面上部のタブで、セキュリティを設定したいアンテナ(RADIO0とか1とか)を選択する。データが反映されるまで待機。
3. `Global Properties`の`Broadcast Key Rotation Interval`で、WPA Key更新を止めたいときは`Disable Rotation`のラジオボタンを選択。WPA Key更新をしたい場合は`Enable Rotation with Interval`のラジオボタンを選択して、テキストボックスに更新間隔を秒単位で入力する。
4. `Apply-RadioN`または`Apply-All`をClick。データが反映されるまで待機。

これを設定した後に暗号方式を変更すると、表示状は設定されていても実は設定が無効化されていることがある。
化学反応式の検索フォームのようなもの

化学反応式の検索フォームのようなものです。
最初に化学式データと化学反応式データをインポートしてから検索する
仕様になっています
*化学反応式の登録に備考欄を追加しました(2019.09.06)
*サンプルデータを修正しました

githubURL: https://github.com/NanjoMiyako/KagakuHannousikiDB

サンプルページURL: https://nanjomiyako.github.io/KagakuHannousikiDB/

反応式データ生成用GASシートURL:https://docs.google.com/spreadsheets/d/10BM_uj5Hf0InN-PF0Vde29ixV2b4tR3FHMYBug7e1eM/edit?usp=sharing

GASPGM: https://github.com/NanjoMiyako/SampleGasScripts1/blob/main/kagakuHannousiki.txt


反応式の参考元URL:
<a href="https://hitowomusubu.com/science/chemical-equation-list/">
化学反応式一覧 | 夢を叶える塾
</a>

画面のスクリーンショット
![screenshot1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412430/8beea62f-57e4-1aea-1b5b-f5cecc38d4f1.jpeg)
Nomad インストール (->Linux)

インストール手順
--------------------
[Installing Nomad - Nomad by HashiCorp](https://www.nomadproject.io/guides/install/index.html)

### 1. 圧縮ファイルをダウンロード

[Download Nomad - Nomad by HashiCorp](https://www.nomadproject.io/downloads.html)

### 2. 圧縮ファイルを解凍する

```sh
unzip nomad_0.9.5_linux_amd64.zip
```

### 3. nomadバイナリファイルをコマンド呼び出し可能なディレクトリへ移す

```sh
sudo install nomad /usr/local/bin
```

Linux 64bit用ダウンロード/インストールスクリプト
--------------------

引数無し、実行するだけです。
Linux 64bit以外の環境でNomadをインストールしたいなら、手動でやる方が速いです。

```sh
#!/bin/sh

###########################################################
# Linux 64bit用
# Nomadバイナリファイルダウンロード/インストールスクリプト
###########################################################

# 以下の変数は適宜変更してください
VERSION="0.9.5"            # Nomadバージョン
DEST_DIR="/usr/local/bin"  # nomadコマンドインストール先ディレクトリパス

ZIP_FILE_NAME="nomad_${VERSION}_linux_amd64.zip"

# 本スクリプト中で使う、インストールされていない可能性があるコマンド群
COMMAND_LIST=`cat <<EOF
curl
unzip
EOF
`

# ダウンロード前のコマンド存在チェック
for USING_COMMAND in $COMMAND_LIST
do
  if ! command -v $USING_COMMAND 1> /dev/null ; then
    echo "Please install [$USING_COMMAND] command."
    exit 1
  fi
done

# Nomadのバイナリ圧縮ファイルをダウンロード
curl -LO https://releases.hashicorp.com/nomad/${VERSION}/${ZIP_FILE_NAME}

# ダウンロードしたNomadの圧縮ファイルを解凍する
unzip ${ZIP_FILE_NAME}
ls -lt ./nomad*

# ホスト共通の実行可能ディレクトリへNomadバイナリを移動する
sudo install nomad ${DEST_DIR}
if [ "$?" -ne 0 ] ; then
  echo "Failed installing nomad to ${DEST_DIR}"
  exit 2
fi

# nomadコマンドが実行可能であるか確認する
if command -v nomad ; then
  echo "Success installing nomad"
else
  echo "Failed installing nomad"
  exit 3
fi
```
TypeScriptのObject型とobject型は同じ……と思うじゃん?

TypeScriptには`Object`型と`object`型があるが、それぞれ違う型である。`Object`型はプリミティブ型の`boolean`, `number`, `string`, `symbol`も含むのに対し、`object`型はプリミティブ型を含まない。`{}`型は`Object`型と同じだ。

![TypeScriptのObject型とobject型の違い](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/9ccdcafd-254b-2acb-055d-c2b792812c60.png)

「Aが`Object`のサブタイプである」というのは「Aが`Object.prototype`と同じ構造のプロパティとメソッドを持つ」ということなので、そう考えると`Boolean`や`Number`にも`.toString`などが生えており、それらが`Object`型に含まれるのは不思議なことではない。

[Object.prototype - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype)
【BeanValidation】「is~」で始まるメソッドでjava.lang.Booleanを返す場合AssertTrue / AssertFalseでバリデーションできない【Java】

記事内容はタイトル通りです。

# 起きた状況
`AssertTrue`を用いた相関チェックで、「`false`ならエラー1、`null`ならエラー2」というようなバリデーションを行おうとしたところ、バリデーション時にメソッドが呼び出されなくなりました。

```java
@AssertTrue(message = "ほげほげ")
@NotNull(message = "ふがふが")
private Boolean isValid() {
  /* 相関チェック */
}
```

# 原因
公式ドキュメントより、以下の通りです。
平たく言うと、`java.lang.Boolean`はオブジェクトなので、`is~`から始まるメソッド名を付けるのは規約違反だからです。

考えてみれば当たり前の話なんですが、ややこしいので勘弁して欲しいです……。

> What is a getter?
> The JavaBeans specification specifies that a getter is a method whose

> - name starts with get and has a return type but no parameter
> - name starts with is, has no parameter and is returning boolean
>
> 出展: [Bean Validation specification](https://beanvalidation.org/2.0/spec/2.0.0.cr2/#constraintdeclarationvalidationprocess-requirements)

# 対処
メソッド名を変更することで呼び出してもらうことができます。
ただ、この場合は`Boolean`を指定する必要も無いと思います。

また、フィールドに対するゲッターと名前が被る問題も有ります。

```java
@AssertTrue(message = "ほげほげ")
@NotNull(message = "ふがふが")
private Boolean getValid() {
  /* 相関チェック */
}
```

自分にはこれ以外の解決方法を見つけられませんでした。

# 感想
アノテーションを作らずに同じフィールドに関する複数の相関チェックを動かせると思ったんですが、うまくいきませんでした。
値の取得とバリデーションとを両立しようと思うとかなり辛くなるので、特に諸々が複雑になる場合はバリデーション用オブジェクトと値取得用オブジェクトを分けた方が賢明ですね……。
構成情報のエクスポートをしたファイルしてインストール

## PowerShellで実行
```powershell

Install-WindowsFeature -ConfigurationFilePath .\Desktop\IIS.xml
```

## xmlファイルをエクスポート
役割機能のインストールから進めて、`構成情報のエクスポート`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/9659e5ad-e856-3540-40ed-4702248a0087.png)
Terraform で書く CodeBuild -> ECR -> ECS with Vapor その3

[Terraform で書く CodeBuild -> ECR -> ECS with Vapor その1](https://qiita.com/takoikatakotako/items/0ff29e014c0812b4b369)
[Terraform で書く CodeBuild -> ECR -> ECS with Vapor その2](https://qiita.com/takoikatakotako/items/72bcbac64bbd178a5859)

最後に ECS でタスクとサービスを作り、デプロイします。



```tf
########################
## ECS
########################
# IAM
resource "aws_iam_role" "my_ecs_role" {
  assume_role_policy = "${file("iam_role/ecs_assume_role_policy.json")}"
  name               = "my_ecs_role"
}

resource "aws_iam_policy" "policy" {
  name        = "test-policy"
  description = "A test policy"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "test-attach" {
  role = "${aws_iam_role.my_ecs_role.name}"
  policy_arn = "${aws_iam_policy.policy.arn}"
}

# ECS Cluster
resource "aws_ecs_cluster" "ecs_cluster" {
  name = "my-cluster"
}

## ECS Task Definision
data "template_file" "container_definitions" {
  template = <<EOF
[
  {
    "name": "my-container-name",
    "image": "${aws_ecr_repository.repository.repository_url}:latest",
    "essential": true,
    "portMappings": [
      {
        "containerPort": 80,
        "hostPort": 80
      }
    ]
  }
]
EOF
}

resource "aws_ecs_task_definition" "service" {
  family = "service"
  task_role_arn = "${aws_iam_role.my_ecs_role.arn}"
  container_definitions = "${data.template_file.container_definitions.rendered}"
  network_mode = "awsvpc"
  cpu = 256
  memory = 512
  requires_compatibilities = ["FARGATE"]
  execution_role_arn = "${aws_iam_role.my_ecs_role.arn}"
}

## ECS Service
resource "aws_ecs_service" "ecs_service" {
  name = "vapor-service"
  cluster = "${aws_ecs_cluster.ecs_cluster.id}"
  launch_type = "FARGATE"

  task_definition = "${aws_ecs_task_definition.service.arn}"
  desired_count = 3

  load_balancer {
    target_group_arn = "${aws_alb_target_group.target_group.arn}"
    container_name = "my-container-name"
    container_port = 80
  }

  network_configuration {
    subnets = [
      "${aws_subnet.public-a.id}",
      "${aws_subnet.public-c.id}",
    ]

    security_groups = [
      "${aws_security_group.my_security_group.id}",
    ]

    assign_public_ip = true
  }
}
```
Procedural Dependency GraphでPython3を使う

# はじめに

なんだかんだと、動いてるのまとめてなかったので。まとめとく。

### 実行環境

> Windows 10
> Houdini 17.5.327
> Python 3.7.4

### サンプルファイル

http://hdbp.io/SfQr0u6b

# 使い方


とりあえず、PDGの全体図をば。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51857/972f0b6e-63c2-c842-94b9-8bb55767161c.png)


つまるところの流れは、

1. Python3用に、環境変数PYTHONHOMEとPYTHONPATHをセットする。
2. Python3用に、Python Scriptのパラメータをカスタマイズする。
3. Python3用に設定した環境変数をクリア/リセットする。



## 1. Python3用に、環境変数PYTHONHOMEとPYTHONPATHをセットする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51857/44eb1fae-3b7a-df71-2e76-c87a8b98e05b.png)

1. Python3の実行ファイルがある場所にPYTHONHOMEを通す。
2. 使いたいモジュールがある場所に、追加でPYTHONPATHを通していく。
    * 図では、ユーザー任意のパスを設定。


## 2. Python3用に、Python Scriptのパラメータをカスタマイズする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51857/def837a3-af35-24a8-0bdc-81dc4efc261f.png)

1.  *Evaluate In Process* を *OFF* に。
2.  *Python Bin* を *Custom* に。
3.  *Custom Python Bin* に、Python3の実行ファイルを指定。
4.  *Reset Python Path Variables* を *ON* に。
    * これは入れなくても動きはすることも多いが、事故を防ぐためにONにしておく。 

ついでに書き出すとこんな感じで、ちゃんと結果が出る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51857/c762ea82-8301-c487-920a-a21c32df90ab.png)

## 3. Python3用に設定した環境変数をクリア/リセットする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51857/0e9f6566-aa87-cdfd-4bb7-ea07fc7e7fd8.png)

1. PYTHONHOMEをクリアする
    * これも必須ではないが、事故を防ぐために行っておく。
    * 途中でPython2の処理を挟まなければ、この限りではない。
    * もし2で、 *Reset Python Path Varibables* をやってない場合は元のPYTHONPATHで設定していた項目を設定しておく。



# まとめ

要は、PYTHONHOMEの設定とPYTHONPATHの設定、あとは、実際にPython3の実行ファイルを叩くだけというシンプルなもので、Python環境的にはよくある考え方かと。もうそろそろ、Python3への移行の時代も一気に動き始めると思うので、早めに実装を当たり前のものにしておきましょう！
言語処理100本ノックやってみる　17

#17. １列目の文字列の異なり
1列目の文字列の種類（異なる文字列の集合）を求めよ．確認にはsort, uniqコマンドを用いよ．

```py
frame="hightemp.txt"

with open(frame) as f:
  set_ken=set()#set_kenを空の集合にする
  for i in f:
    cols=i.split("\t")#タブのタイミングで文字列を細かくする
    set_ken.add(cols[0])#1列目のみを抽出
    
for k in set_ken:
  print(k)
```
#出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/7f013c09-2230-ccba-0a5b-d457fb3df613.png)

#UNIXコマンド確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/58cca64b-52a2-7257-c9d0-184e89225040.png)
### main.pyのファイルはvim main.pyと打つことで作成画面に飛べる！
以下のようにmain.pyにプログラムを書き込む

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475270/d1c2dddc-f52a-22d7-014e-fa0e4a5e9986.png)

vimについて詳しく↓
https://qiita.com/okamos/items/c97970ab34ff55ff3167
CUIウェブブラウジング: 出先で論文をダウンロードする

# 出先で論文をダウンロードしたい...
出先で論文をダウンロードしたい、でもOpen accessじゃないからダウンロードできない...ってことありますよね。

解決策のひとつとしては、sshで自分の所属機関のサーバーにアクセスして、ダウンロードできれば良いわけです。

ただちょっと問題があって、pdfが置いてあるurlをいつも把握しているわけではないですよね。

そこでコマンドライン上でウェブブラウジングをする方法をまとめます。

sshした先のサーバー上でウェブブラウジングできれば、いつだって論文がダウンロードできます。


# CUIで論文ダウンロード

コマンドライン上のウェブブラウザはいくつかあります。ただ基本的に、所属機関のサーバーはインストール権限がないので、どれかのコマンドがなかったらできないです。他(のサーバー)を当たってください。とりあえず以下のコマンドを叩いてみて、どれがあるかチェックしてみてください。僕の場合は`w3m`が使えました。

- Lynx: `lynx`
- w3m: `w3m`
- Links: `liks` 
- Links2: `liks2` 
- Elinks: `elinks`

使えるコマンドを見つけたら、あとは`<command> <url>`で繋げて、pdfのリンクを探せばOKです。
#余談
随分昔の記事(2005年)ですが、Lynxを使ったことによって有罪判決を受けた人がいるようです。こっわー。

- [Lynxでアクセスしたら逮捕された?](https://srad.jp/story/05/01/29/0848215/)
- [「Lynxでアクセスしたら逮捕」の事件で有罪判決](https://srad.jp/story/05/10/13/1030233/)



#参考

- [【w3m】CUIで動くウェブブラウザの紹介【Lynx】](https://chishiki-motomeru.com/post/20181004/)
- [CUI テキストベースブラウザ5種を試用](https://pc.casey.jp/archives/153900584)
Java Silver 勉強法メモ

JavaSilverに合格したときの勉強方法のメモです。

## 受験概要
受験日：2019/03/31
正答率：80%
結果：合格

## 試験対策としてやったこと
1. とりあえず1回受けてみる
→再受験無料キャンペーン中だったので、1回分は本番の雰囲気を知るための模試として受験しました。ほぼノー勉だったので当然のごとく不合格でしたが「何回か模試やれば受かりそうだな」という謎の自信を手に入れることができました。
1. 黒本の模試1の解説を読む
→わからないところだけ第1章～第9章の該当部分を読む
1. 模試1を解く
→間違えたところの解説はちゃんと読む
1. 模試2を解く(時間と気力の都合で半分くらいしかできなかった)
→間違えたところの解説はちゃんと読む

## 試験対策ではないけど役に立ったと思うこと
- 普段の業務でJavaのコードを読む機会に恵まれてた
- progateのJavaコース完走したことがあった
- 『スッキリわかるJava入門』『スッキリわかるJava入門 実践編』を読んだことがあった

『スッキリ～』2冊を読んだのは受験の半年くらい前でした。
(実践編の通読はしてないです)

## 感想
- Javaの勉強をしたことがある人は黒本の1～9章を通読する必要はないかなと思いました。
- 先に解説を読んでから模試を解くことで理解と記憶の度合いを確認できたのが勉強時間の短縮に繋がったような気がします。
- 再受験無料キャンペーン中の申し込みが◎(そこそこの頻度で実施してるらしいです)
Project Euler 006を解いてみる。「二乗和の差」

# Project Euler 006
[006](http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%206)
>最初の10個の自然数について, その二乗の和は,

```math
1^2 + 2^2 + ... + 10^2 = 385
```
>最初の10個の自然数について, その和の二乗は,

```math
(1 + 2 + ... + 10)^2 = 3025
```
>これらの数の差は 3025 - 385 = 2640 となる.
同様にして, 最初の100個の自然数について二乗の和と和の二乗の差を求めよ.

->[次の問題](https://qiita.com/radiol/items/e83ec06c5075b19a3f6c)

## 考え方①
シンプルに1~100までの配列を作成し、2乗してから足すpow_sumと足してから2乗するsum_powを計算、その差を出します。

## コード
```Python:euler006.py
import numpy as np


def main():
    n = 100
    num_arr = np.arange(1, n + 1)
    pow_sum = sum(num_arr ** 2)
    sum_pow = sum(num_arr) ** 2
    print(sum_pow - pow_sum)


if __name__ == '__main__':
    main()
```

## 考え方②
1~nまでの自然数の和は、等差数列の和の公式より

```math
S_n = \frac{n(n+1)}{2}
```
で求められるのでこれを2乗すればOKです。
2乗和も公式より

```math
S_n = \frac{n(n+1)(2n+1)}{6}
```
で算出できます。
あとは差を計算して完了です。
公式を使うとnが増えても計算量が同じでお得ですね。

## コード
```Python:euler006.py
def main():
    n = 100
    pow_sum = n * (n + 1) * (2 * n + 1) // 6
    sum_pow = (n * (n + 1) // 2) ** 2
    print(sum_pow - pow_sum)


if __name__ == '__main__':
    main()
```
余談ですが、方法①のコードではn = 77936以上になると、`sum_pow=-9223077348122983360`とマイナスの値になってしまい正しい答えを返せなくなるようです。数が大きくなりすぎるためでしょうか。
foo.webarchive を html に変換する方法

# イントロ
JavaScriptなどの関係でhtmlで保存すると情報が落ちてしまうウェブページでも、Safari等の.webarchiveフォーマットで保存するとほとんど情報を失わずに保存できるので便利 -- ということはよく知られていますが、その後の操作法のメモ。

*もっとも、そもそも Mac を使っている前提なのだから、terminal を立ち上げて `textutil` コマンドで一発変換。おしまい、と言う場合も多く、以下の記事を読む必要はほとんどなくなくなったりします。*

```zsh
~ % textutil -convert html foo.webarchive
```

*とは言え、ページによっては一筋縄では行かない場合も間々あるので、その場合は以下の方法を使うことになるかと思います。*

# 方法
1. Safari等で目的のページを.webarchiveフォーマットで保存
2. テキストエディタで.webarchiveを開き、ヘッダ部分を掃除する（下図）。

3. あとは直接 BeautufulSoup で読み込む（Beautiful Soup 4 以外では動作確認していない）。
4. おわり。

**《掃除前》**
この例では削除すべき部分（<!DOCTYPE html>）の直前までが1, 2行と短いが、場合によっては***数百行に及ぶこともある***ので、`<!DOCTYPE html>`を検索（複数見つかることも）して、最後の`<!DOCTYPE html>`の直前までバッサリ削除する。

```HTML
bplist00�T_WebMainResource_WebSubframeArchives_WebSubresources�	

_WebResourceData_WebResourceMIMEType_WebResourceTextEncodingName^WebResourceURL_WebResourceFrameNameO��<!DOCTYPE html><html lang="ja" class="enhanced vanilla-layout mouse-optimized is-search-header-sticky" data-service-name="search" data-is-logged-in="true" data-user-rank="DSR3" data-sentry-dsn="https://example.com/foo" data-kite-env="production">
```

**《掃除後》**
頭から <!DOCTYPE html> の直前まで削除した。
ここからあとはほぼ普通のHTML。

```HTML
<!DOCTYPE html><html lang="ja" class="enhanced vanilla-layout mouse-optimized is-search-header-sticky" data-service-name="search" data-is-logged-in="true" data-user-rank="DSR3" data-sentry-dsn="https://example.com/foo" data-kite-env="production">
```

# 結論
🍺😋

# 蛇足
## ヘッダの削り方
頭から 最後の`<!DOCTYPE html>` の直前まで思いっきり削除した。

最初は、保存したままのfoo.webarchiveをbs4で開くと、

```Python
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd3 in position 8: invalid continuation byte
```
のようなError Messgeが出たので 0xd3 とおぼしき`�`まで削ってみたら、こんどは

```Python
IOPub data rate exceeded.
The notebook server will temporarily stop sending output
to the client in order to avoid crashing it.
To change this limit, set the config variable
`--NotebookApp.iopub_data_rate_limit`.

Current values:
NotebookApp.iopub_data_rate_limit=1000000.0 (bytes/sec)
NotebookApp.rate_limit_window=3.0 (secs)
```

のようなErrorになりもう理解の範囲を超えるので、`�`がいる付近をザックリ削ったらうまく行った。

なお、ファイル末尾近くの`</html>`の後ろにも何やらコードがあるけれども放置して問題なし。

ちなみに、ひとたび `IOPub data rate exceeded.` が出てしまうと、Jupyter Notebookの Kernel を立ち上げ直さないとダメでした

**以上**
AssetManagerを用いた非同期ロードがパッケージ後正常に動作しない現象についての解決策

#はじめに
>[Asset Managerのアセットの非同期ロード機能について その1 ( 非同期ロードの解説 & レベルの裏読み編 )](https://qiita.com/EGJ-Kaz_Okada/items/f18bca3fb5c8fc1aea9c)

こちらの記事を参考にAssetManagerを用いた非同期ロードを実装したところ、パッケージ後のみ動作しない現象に遭遇したのでその対処法について書いていきます。

#具体的な症状
**AssetManagerでの非同期ロードについてよく知らない方は「はじめに」に記載された参照先の記事で分かりやすく解説されているのでそちらを読むことをおすすめします。**

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/3825ed2d-0c7f-8ef3-8933-60901b424852.png)
このように処理を組み非同期ロードをして、完了したのちにOpenLevelでレベルを移動するようにしました。
一見問題ないように見えますし、PIEでもStandaloneでも問題なく動作しますが、パッケージ後だと正常に読み込まれません。

#原因について
GetPathNameの戻り値の文字列を確認してみたところ、
[ファイルパス]/[レベル名].[レベル名]
の形で出力されました。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/cacc549c-5f6f-451d-3b77-d1258be6ead1.png)

#解決策について
GetPathNameの戻り値の.以降の拡張子にあたる部分が問題かと思い、以下のように文字列を処理しました。
![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325493/cfbda0c8-cc85-817f-ab40-7b77a6f4256c.png)
Splitノードは戻り値を見ればわかりますが、ファイルパスをパスとファイル名と拡張子に分離するノードです。
分離した後に[パス]/[ファイル名]という形にすることで.以降の部分を無くしています。

このように.以降の部分を無くすとエディタ上でもパッケージ後も正常に動作するようになりました。

#おわりに
私の場合、非同期ロード→OpenLevelの処理をGameInstanceに実装し、外部から呼び出して使う形で実装していてそこに問題があるかと思いましたが、この記事を書くにあたりレベルブループリントに実装したものも作ってみましたが、同様の動作でした。
したがって、おそらくGetPathNameの戻り値の.以降が問題だろうと思いますが、間違いや補足などありましたら、コメントなどで教えていただけると嬉しいです。
Laravel 6.0 LTSをセットアップしてみる。



Laravel 6.0 LTSをセットアップしてみるが、以前とほぼ変わらない。

PHPのバージョンが、7.2 以上となっている。


```json:composer.json
{
    "name": "laravel/laravel",
    "type": "project",
    "description": "The Laravel Framework.",
    "keywords": [
        "framework",
        "laravel"
    ],
    "license": "MIT",
    "require": {
        "php": "^7.2",
        "fideloper/proxy": "^4.0",
        "laravel/framework": "^6.0",
        "laravel/tinker": "^1.0"
    },
    "require-dev": {
        "facade/ignition": "^1.4",
        "fzaninotto/faker": "^1.4",
        "mockery/mockery": "^1.0",
        "nunomaduro/collision": "^3.0",
        "phpunit/phpunit": "^8.0"
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "classmap": [
            "database/seeds",
            "database/factories"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ]
    }
}
```


```json:package.json
{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.19",
        "cross-env": "^5.1",
        "laravel-mix": "^4.0.7",
        "lodash": "^4.17.13",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.15.2",
        "sass-loader": "^7.1.0"
    }
}

```

追記
Laravel 6.0からはログイン機能は、laravel/uiという名前の別パッケージとして管理。


```
composer install
composer require laravel/ui
php artisan ui vue --auth
npm install

```
[ReactNative]FlexBoxメモ

# flex
画面いっぱいにコンポーネントを表示する。
同レベルで他のコンポーネントもこれを指定していた場合、指定した数値によって表示比率が変わる。

# flexDirection
コンポーネントの並びの向きを設定する。

|キーワード|内容|
|----|----|
|row             |縦並び|
|column (default)|横並び|

#flexWrap
並べた要素が画面からはみ出た時の振る舞いの設定。

|キーワード|内容|
|----|----|
|nowrap (default)|はみ出ても一行で表示する。|
|wrap            |はみ出たら折り返す。|

# justifyContent
子コンポーネントの配置方法を指定する。

|キーワード|内容|
|----|----|
|flex-start (default)|縦並びの場合は上から、横並びの場合は左から配置していく。|
|flex-end            |縦並びの場合は下から、横並びの場合は右から配置していく。|
|center              |中央に揃えて配置していく。|
|space-between       |両端を基準に、子コンポーネントを均一に配置する。|
|space-around        |子コンポーネントを均一に配置する。|

# alignItems, alignSelf
alignItemsは子コンポーネントの配置方法を指定する。
alignSelfは親の指定した配置方法を上書きできる。

|キーワード|内容|
|----|----|
|stretch (default)|コンポーネントを表示範囲に伸ばして配置する。|
|flex-start       |縦並びの場合は左から、横並びの場合は上から配置していく。|
|flex-end         |縦並びの場合は右から、横並びの場合は下から配置していく。|
|center           |中央に揃えて配置していく。|
サクセスメッセージの表示方法

`redirect_to`の第二引数に`notice`を指定することができる。
viewでは、`<%= notice %>`ってやったらでてくる

```ruby:tweet_controller.rb
def create
 @tweet = Tweet.new(tweet_params)
 if @tweet.save
  redirect_to @tweet, notice: `投稿されました` #notice: `投稿されました`がサクセスメッセージ
else
 render :new
 end
end
```


```ruby:show.html.erb
<p id="notice">
 <%= notice %> #サクセスメッセージの表示
</p>
```

こんな感じー！
投稿詳細ページ(show)と投稿一覧ページ(index)の作成まとめ

#投稿詳細ページの作成
ＳＴＥＰ１
ルーティングに`get "posts/:id => "posts#show"`　を記述。
※posts/〇〇すべてを読み込むので注意が必要。下に位置させる。

ＳＴＥＰ２
コントローラにshowアクションを作成し、
def show
`@post = Post.find_by(id:params[:id])`を記述。
end
※paramsでルーティングで指定したidを取得している。
※paramsはハッシュなので、params[:id]とすることで、id番号だけ取り出せる。
※find_byメソッドで（第一引数：指定したいカラム　第二引数：〇〇）を指定し、変数に代入。idカラム以外も指定可能。

ＳＴＥＰ３
ビューに、`<%= @post.content %>` `<%= @post.created_at %>`と記述で表示。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458009/9fa696da-24ed-abde-e244-d3fcd0e10faf.png)

#投稿一覧ページの作成
ＳＴＥＰ１
postsコントローラのindexアクション内の@postsに、Post.allで取得したデータを代入しましょう。
def index
`@posts = Post.all`
end

ビューでは@postsに代入されている配列データをeach文で1つずつ変数postに代入し、投稿内容を繰り返し表示させていきましょう。

`<% @posts each do |post| %>
 <%= post.content %>`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458009/a6b58619-c165-d1f0-a8f9-c7110befc947.png)


ＳＴＥＰ２
各投稿の内容の部分をクリックすると詳細ページに移動できるように、`link_to(post.content, "/posts/#{post.id}")`とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458009/35036c73-75eb-07c8-6640-b664579285ea.png)
EC2 EBS ボリュームサイズ拡張のやりかた

## tl;dr

EC2 でディスク使用量がパンパンになってきて
ボリュームをオンラインで拡張したくなったときのやりかたメモです。

基本的に公式ガイドに沿えば OK です:
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html

## チェック

```
df -h
```

```
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1      7.7G  6.7G  1.1G  87% /
```
(※ルート以外省略してます)

ここのルート `/` の容量を拡張したいとします。

```
lsblk
```

```
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0   8G  0 disk
└─xvda1 202:1    0   8G  0 part /
```

ボリュームの容量をチェックしておきます。

## ボリュームの容量を変更する

コンソールだとボリュームの編集でかんたんに変更できます:

<img width="658" alt="Volumes___EC2_Management_Console.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359439/32fb8557-42ab-70e0-2d15-66ee84c70914.png">

(少しだけ時間かかります。5分くらい？)

## パーティションの拡張

で `lsblk` でサイズを再度確認してみます:

```
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  12G  0 disk
└─xvda1 202:1    0   8G  0 part /
```

ボリューム全体のサイズは拡張されていますが、
ルートのパーティションのサイズは変わってません。

なので `growpart` で `xvda1` のサイズを拡張します:

```
sudo growpart /dev/xvda 1
```

> CHANGED: partition=1 start=2048 old:  size=16775135 end=16777183 new: size=25163743,end=25165791

`CHANGED` とか出たら変わってます。
容量がカツカツのときはこの操作に必要な一時ファイルを`/tmp` に作成することもできないので、いくらか空き容量を空けておきます。

ふたたび `lsblk` してパーティションが拡張されていれば OK です:

```
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  12G  0 disk
└─xvda1 202:1    0  12G  0 part /
```

## ファイルシステムの拡張

ここで `df -h` をしてみて、まだ容量が変化してないことに気づいたときは:

```
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1      7.7G  6.7G  1.1G  87% /
```

ファイルシステムもあわせて拡張する必要があるのでリサイズします (`ext4` の例):

```
sudo resize2fs /dev/xvda1
```
> resize2fs 1.42.13 (17-May-2015)
> Filesystem at /dev/xvda1 is mounted on /; on-> line resizing required
> old_desc_blocks = 1, new_desc_blocks = 1
> The filesystem on /dev/xvda1 is now 3145467 (4k) blocks long.

```
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1       12G  7.7G  6.0G  56% /
```

これで OK です。

`xfs` とか `ext4` 以外のファイルシステムの場合は別のコマンドを使用して同様に拡張すればいいです。
GoogleDriveからファイルをwgetでダウンロードするためのコマンド

# 背景

1.GoogleDriveにあるファイルをサーバーに配置したかった。
2.ファイルは大きい（2GBくらい）ので「ローカルにダウンロードしてサーバーへアップロード」という手順はやりたくなかった。
3.サーバーからGoogle Driveのファイルをwgetコマンドなどでダウンロード出来ないかを調べた。

# 解決策
こちらのコメントがベストでした。
https://gist.github.com/iamtekeste/3cdfd0366ebfd2c0d805#gistcomment-2359248

以下簡単に翻訳
# セットアップ:

下記のコードを `~/.bash_aliases` に追加

```
function gdrive_download () {
  CONFIRM=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate "https://docs.google.com/uc?export=download&id=$1" -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')
  wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$CONFIRM&id=$1" -O $2
  rm -rf /tmp/cookies.txt
}
```
新しくセッションを開始する
（もしもコマンドが見つからないと言われたら `source ~/.bash_aliases` で読み込めるはず）

# 使い方:

`gdrive_download fileのid 保存先のファイル名`

##file_idとは
<img width="337" alt="スクリーンショット 2019-09-05 13.44.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58437/c387b333-deb5-93c3-bb25-c74231e87daa.png">
**file_id**はGoogleDriveの画面からファイルを右クリックして、「共有可能なリンクを取得」を選択した際に表示されるURLの `?id=hogehoge` のhogehoge です
AWS認定アカウントに登録した名前を変更する方法

## AWS認定試験を受けるために
AWS認定試験の試験会場では、受験前に本人確認をするそうですが、
その際、認定アカウントの名前と同じ名前が記載された身分証を提示しなければなりません。

しかし、認定アカウント作成時に旧姓で登録してしまいました。
旧姓の名前が書いてある身分証を持っていないため、このままでは、模擬試験は受けられますが本試験が受けられません。

## プロフィール変更を試みるも…
認定ポータルのトップページにアクセスし、「マイプロフィール」タブをクリック
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408585/81e4ca1a-e5b0-3494-6a0d-49ede6e36e49.png)

↓

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408585/099f0b49-c37c-a2eb-22c2-6ab85ea1263f.png)

姓を変更しようとしたところ、なんと
`First name` と `Last name` は編集できないようになっていました。
ブラウザ検証で要素確認したらがっつり `disabled` と書いてあります。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408585/925c70bf-a833-ec14-f4de-44dc418140b9.png)

## 公式の変更方法

[AWS トレーニングと認定ポータルのサポート](https://www.aws.training/Support) に書いてあった内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408585/32104265-40a5-d0ef-7b04-73ccfe495a39.png)
面倒くさそうなので、メールで直接お願いすることにしました。

## メールでやりとり
[AWSトレーニングおよび認定チーム](https://aws.amazon.com/jp/contact-us/aws-training/)
こちらの問い合わせフォームから、姓を変更したい旨を送信しました。
ちなみにこのページが日本語だったので日本語で依頼を出したら、英語でしか対応していないから自動翻訳使って読んだよ、と言われました。。
レスポンスが来たのははだいたい2〜3営業日後くらいです。

>I will be happy to assist with updating your name in your AWS Certification account. In order to have your name changed in our system, we will require a copy of non-expired legal photo identification that displays your legal first and last name (such as a passport or government- issued ID).

>Please provide your name in Roman English Language:
First name:
surname:

名前が確認できる写真付きの身分証明書を用意しろとのこと。
私は運転免許証しか持っていないのでそれを送ることにしました。

これでできなかったらアカウントを作り直します、と添えて。

...

翌日、返事が来ました。

>Thanks for providing your ID.
At this time we are unable to update your name in Kanji.
Please provide both your name and surname in Romanji.
Name:
Surname:

機械が書いたような文面ですね。
今までのやりとりにはあった気さくな挨拶文もなく、一瞬スパムメールかと思いました。
どうやら弾かれたようです。

## 2019/9/25 追記
![プレゼンテーション2-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408585/13c274b5-36b0-71ce-b823-6754dcec9d35.jpeg)
このとき、私は運転免許証の画像を圧縮し、zip形式で送付しました。
_理由：顔写真が見えるのがなんか嫌だったから…_

しかし、この記事公開後に頂いたコメントで、圧縮せず生の画像データで送ったら成功したとの情報が。

さっそくjpg形式の画像を添付し、再度登録名変更リクエストを送信したところ、
その日のうちに変更完了の返事がきました。

>Thank you for providing your full legal name. I have corrected your name on your Certification account to the following:

>First Name: ***
>Last Name: ***（新姓）

また、認定ポータルの「マイプロフィール」画面に、新しい名前が反映されていることも確認できました。

※ 混乱を招かぬよう、この先は元記事を大幅に修正しています。

## 運転免許証で登録名変更が成功

![プレゼンテーション2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408585/ed310c9b-b4b6-0c2f-75e4-6f4392bdd1f0.jpeg)

ダメもとで送ったのですが、意外でした。

特に懸念していたのは以下の2点。
・名前がローマ字表記じゃない
・有効期限が西暦ではなく、元号で書いてある

## まとめ
日本の運転免許証で、AWS認定ポータルの登録名を変更できることがわかりました。
注意すべき点は、変更リクエストのメールに運転免許証の画像を添付する際は、 **画像を圧縮しないこと！**
zip形式だとNGというのも謎ですが、そういう仕様なのです。

コメントにてご協力くださった bass8827 様、本当にありがとうございました。

---

運転免許証の画像を圧縮して送り、名前が変えられないとわかったときの悲しきまとめを残しておきます。一応。
アカウント再作成するって言ってますが、してません。さぼってました。

...

名前の変更ができなかったので大人しく新アカウントを作成します。
私はまだ認定資格を持っていないのでこの対応ができますが、資格取得済みの状態で改姓するとなると厄介ですね。。

日本人で認定アカウントの名前を変更したことがある方は、どの身分証でクリアされたか
ぜひ教えてください。

ちなみにアカウント削除を依頼したところ、削除したアカウントと同じメールアドレスでアカウントを作り直すのは不可能とのことでした。
LaravelのwithCountとwithは挙動が異なるので併用する

# N+1問題を解決する際に利用する with

withでリレーション先を指定することで基本的に N+1 は解決することが多い
withCountも同様に N+1 問題を解決することができると思っていたが違うようだ。

```php
self::withCount('hoge')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/5203ad31-d4a0-8959-d88f-463af665884b.png)

* SQL発行数は54個
* 処理時間は54ms


## withCountとwithは併用する

```php
self::withCount('hoge')->with('hoge')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/1d4104ea-6bbf-3fc1-5a15-e7445206f4d9.png)

* SQL発行数は14個
* 処理時間は18ms

Nが47（都道府県分）だと約3倍高速化が可能である。
#MicrosoftFlow の Outlookコネクタを使って、仕訳ルールの新着メールを通知する

# はじめに

Office365使いとして、メール仕訳ルールって
殆どの皆さんが使っていると思います。
システムのメール
ダイレクトメール
業務メール
などなど
いろんなルールで仕分けをして、特定フォルダに入れてくれる
非常にありがたいツールなのです。

# しかし弱点がある

仕訳ルール入れるとですね
「新着メール」通知が来ないんですよ！！

なので、システムのメールで気づかないといけないメールとか
結構取りこぼしかねないのですよね。

# そこで Microsoft Flowの出番です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/53f5e60d-31f8-f06c-d29d-f7a73653299d.png)


こんな風にフローを作ることで
仕訳されたメールであっても、新着メール通知を受け取ることができます。
しかも、件名フィルタも使えますので、通知の必要なメールのみに制限することも可能です。
Flow側での通知も来ますし
Teamsでもこんな風に内容を確認できますので、ものすごく重宝しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/51f5a23b-ffcb-44e3-fa91-059641f6ff36.png)

仕訳ルールを使っていて、通知が来なくて悩んでいる方
ぜひお試しください！
project euler 24

意外とめんどくさかったが、なんとかワンライナー。

http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2024
> 順列とはモノの順番付きの並びのことである. 
> たとえば, 3124は数 1, 2, 3, 4 の一つの順列である. 
> すべての順列を数の大小でまたは辞書式に並べたものを辞書順と呼ぶ. 
> 0と1と2の順列を辞書順に並べると
>
> 012 021 102 120 201 210
> になる.
>
> 0,1,2,3,4,5,6,7,8,9からなる順列を辞書式に並べたときの100万番目はいくつか?

```js
(n=>((arr=[...Array(n).keys()])=>
  (f=(r,v=[])=>(r.length==1)?[[r[0]]]:[r.forEach(a=>f(r.filter(e=>e!=a)).forEach(e=>v.push([a, ...e]))), v][1])(arr)
[1000000-1]
.join("") // 2783915460
)())(10)
```
YAMAHA のルータ (RTX1210 / NVR510) のユーザ / パスワードの種類と用途

YAMAHA のルータの管理で、パスワードまわりがややこしかったのでまとめた。
詳細なドキュメントな見つけられず、色々試して得た結果なので間違いがあるかもしれない (あったらコメントください)。

検証環境は下記。

* RTX1210 (Rev.14.01.34)
* NVR510 (Rev.15.01.14)

# パスワードの種類

YAMAHA のルータの管理に必要なパスワードは 3 種類ある。
いずれも Web GUI の `管理 - アクセス管理 - ユーザーの設定` から設定できる。

* 管理パスワード
* ユーザのパスワード
* anonymous ユーザ (ユーザ名なし) のパスワード

# Web GUI

ユーザ名: ユーザ名 または 入力なし (anonymous)
パスワード: ユーザのパスワード または 管理パスワード

管理パスワードを入力した場合は、管理者権限での操作が可能になる。
ユーザのパスワードを入力した場合は、一般ユーザ権限での操作になる。

# SFTP
ユーザ名: ユーザ名
パスワード: ユーザのパスワード または 管理パスワード

管理パスワードを入力した場合は、管理者権限での操作が可能になる。
ユーザのパスワードを入力した場合は、一般ユーザ権限での操作になる。

# SSH
ユーザ名: ユーザ名
パスワード: ユーザのパスワード

ログイン後 `administrator` と入力し、管理パスワードを入力すると管理者権限での操作が可能になる。

## show config NUM / load config NUM
SSH で `show config 0` や `load config 0` などのコマンドを実行すると下記のように 2 つのパスワードを要求される。

```
# show config 0
Input passwords of CONFIG0
Login Password:
Administrator Password:
```

`Administrator Password` には管理パスワードを入力すればよいが、`Login Password` には **anonymous ユーザのパスワード** を入力する必要があるので注意。 

また、現在アクティブな設定以外を指定した場合は、現在のパスワードではなく、**読みだそうとする設定に保存された** パスワードが必要なので注意。
やさしいZIPダウンロード機能

# やさしいZIPダウンロード機能

## 概要

WEBアプリケーションに、複数ファイルの一括ダウンロード機能(ZIPダウンロード機能)を実装したら色々気になることが出てきた。その問題点や解決法を考えてみる。


## 読むの面倒な人向けまとめ

ZIPのストリーミングダウンロードは、(圧縮後サイズが不明なのでContentsLengthがセット出来ず)残り時間が出なくて困る。だが圧縮方式がSTORE(無圧縮)であれば圧縮後サイズを計算できる。

それには、

  1. 全ファイルのファイルサイズの合計
  2. 全ファイルのファイル名のバイトサイズの合計の2倍
  3. 全ファイルのファイル数 * 76 バイト
  4. 固定の 22 バイト

を足し合わせば良い。
※ Comment, ExtraField, DataDescriptor, 暗号化, 64bit対応 がない前提


詳細は以下に

## ZIPダウンロード機能について

　ブラウザでは1回のダウンロード(リクエスト)で1つのファイルしか送信出来ない。そこでWEBアプリケーションから複数ファイルをダウンロードさせる為、ファイルをZIP圧縮して送るケースがままある。

少量のファイルであれば一度サーバー側に一時的にZIPファイル作成し、そのZIPファイルを送信するという方法が簡単だ。しかしファイルが大量であると、ZIPファイルを作成する時間・ディスク容量・一時ファイルの管理などが問題になるだろう。

そしてこの問題は、ストリーミング機能を使えば解決する。送りたいファイルを少しずつ読み込み、圧縮されたバイナリができあがり次第チョロチョロと送ってあげればよい。ストリーミングは多くのZIPライブラリで用意されているハズ。

ただこの方式では、(当たり前ではあるが)圧縮前に圧縮後のファイルサイズがわからない。送信するデータサイズが不明だと、ブラウザでダウンロードしている間に残り時間が表示されない。特に大容量のダウンロードになるといつ終わるかわからず不安になるかもしれない。

| ZIPダウンロードの方式 | 準備時間        | 一時ファイル    | 残り時間表示    |
|-----------------------|:---------------:|:---------------:|:---------------:|
| ZIPファイル事前作成   | :cry: 長い      | :cry: 必要      | :smile: 可能    |
| ZIPストリーミング     | :smile: 短い    | :smile: 不要    | :cry: 不可能    |


## 圧縮前に圧縮後サイズを取得する方法

圧縮方式がSTORE(無圧縮)の場合、ファイルがそのままZIPファイルに入っている。あとはZIP内ファイル毎のヘッダと、最後に固定長のフッタが付くだけだ。ファイルサイズがわかっているならば計算できそうである。

というわけで冒頭のまとめで記述した内容になる。

> 圧縮方式がSTORE(無圧縮)であれば圧縮後サイズを計算できる。
> 
> それには、
> 
>   1. 全ファイルのファイルサイズの合計
>   2. 全ファイルのファイル名のバイトサイズの合計の2倍
>   3. 全ファイルのファイル数 * 76 バイト
>   4. 固定の 22 バイト
> 
> を足し合わせば良い。
> ※ Comment, ExtraField, DataDescriptor, 暗号化, 64bit対応 がない前提

ただ、※印に色々書いて有るように上記の計算が成り立つのには条件がある。

* まず圧縮方式がSTORE(無圧縮)であること。DEFLATEDだと実際に圧縮してみて圧縮後サイズを調べる必要がある。
* Comment が空であること。実はZIPはファイル毎にコメントを入力出来る。
* ExtraField が存在しないこと。ライブラリによっては拡張フィールドを利用してより正確な日付情報を付けるなどする場合がある。
* DataDescriptor が存在しないこと。DataDescriptor はファイルデータの直後に追加される 12 or 16バイトのCRC・ファイルサイズ情報。
* 暗号化されていないこと。暗号化の為のフィールドが追加される為。
* ZIP64(64bit対応のZIP)でないこと。ヘッダ・フッタのサイズが変化する為。個々のファイルサイズ・合計ファイルサイズ・ファイル数が32bit以内なら問題無いはず。


## 実装例

[maennchen/ZipStream-PHP]( https://github.com/maennchen/ZipStream-PHP ) を利用した例

```php
<?php
require 'vendor/autoload.php';

# 送信したいファイル一覧
$files = glob("*.jpg");
$size = 22;
foreach($files as $path) {
	$size += filesize($path);
	$size += strlen($path) * 2;
	$size += 76;
}
header("Content-Length:" . $size); //ZIPファイルサイズの計算値
# 以下はZipStream-PHPの処理
$options = new ZipStream\Option\Archive();
$options->setSendHttpHeaders(true);
$fileopt = new ZipStream\Option\File();
$fileopt->setMethod(ZipStream\Option\Method::STORE()); //無圧縮
$zip = new ZipStream\ZipStream('download.zip', $options);
foreach($files as $path) {
	$zip->addFileFromPath($path, $path, $fileopt);
}
$zip->finish();
```

他の言語・ライブラリでも似たような感じで実装出来るハズ。Javaなら [commons-compress]( https://commons.apache.org/proper/commons-compress/ ) が良いか。


## 参考

* [wikipedia/Zip (file format)]( https://en.wikipedia.org/wiki/Zip_(file_format) )
* [PKWARE/APPNOTE.txt]( https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT )
WebSocket コードチート

###opcode
|code|説明|
|---|---|
|0x0|継続フレームを表す |
|0x1|テキストフレームを表す|
|0x2|バイナリフレームを表す|
|0x3〜0x7|追加のデータフレーム用に予約済み|
|0x8|接続の close を表す|
|0x9|ping を表す|
|0xA|pong を表す|
|0xB〜0xF|追加の制御フレーム用に予約済み|
|0xA|pong を表す|
|0xB〜0xF|追加の制御フレーム用に予約済み|

###ステータスコード
|code &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|説明|
|--------------------------------------------------|---|
|1000|正常な closure を指示する。<br>確立された接続の目的が充足されたことを意味する。|
|1001|端点が “消え去っている” ことを指示する。<br>サーバがダウンしたり，ブラウザがページから<br>どこか他へナビゲートし|たときなど。|
|1002|端点がプロトコルエラーにより接続を終了していることを指示する。
|1003|受容できないデータを受信したため、端点は 接続を終了していることを指示する<br>（例えば，テキストデータしか解せない端点がバイナリメッセージを受信したとき、これを送信してもよい）。|
|1004|予約済み。 特定の意味は、将来に定義されることになるであろう。|
|1005|予約済みの値であり、端点は， Close 制御フレームの状態°コードに設定してはならない。<br>これは、どの状態°コードも実際には無いことを指示する状態°コードを期待するアプリ用のものとして，指定されている。|
|1006|予約済みの値であり、端点は， Close 制御フレームの状態°コードに設定してはならない。<br>これは、接続が異常に（例えば， Close 制御フレームの送信や受信抜きに）close されたことを指示する状態°コードを期待するアプリ用のものとして，指定されている。|
|1007|受信したメッセージ内のデータがメッセージの種別と整合していないため（例えば，テキストメッセージ内の非 UTF-8 [RFC3629] ），端点は 接続を終了していることを指示する。|
|1008|施策に違反しているメッセージを受信したため、端点は 接続を終了していることを指示する。<br>これは、より相応しい状態°コード（例えば， 1003 や 1009 ）が他にないとき|
|1009|処理するには大き過ぎるメッセージを受信したため、端点は 接続を終了していることを指示する。|
|1010|1 つ以上の拡張を折衝するよう期待していたのに，サーバは WebSocket ハンドシェイクの応答メッセージ内に<br>それらを返さなかったため、クライアントは 接続を終了していることを指示する。<br> Close フレームの 事由 には、必要な拡張のリストが出現するべきである。 サーバは、代わりに WebSocket ハンドシェイクを失敗させれるので，この状態°コードを利用することはないことに注意。|
|1011|要請を充足できなくするような，予期されない条件に遭遇したため、サーバは 接続を終了していることを指示する。|
|1015|予約済みの値であり、端点は， Close 制御フレームの状態°コードに設定してはならない。<br>これは、 TLS ハンドシェイクを遂行した際の失敗により（例えば，サーバが証明書を検証できないなど），<br>接続が close されたことを指示する状態°コードを期待するアプリ用のものとして，指定されている。|
laravel new project で困った時

In Application.php line 670:
                                                             
  Class 'Facade\Ignition\IgnitionServiceProvider' not found  
ー＞このコマンド
composer dump-autoload

https://nextat.co.jp/staff/archives/121


ブラウザで イカエラー
No application encryption key has been specified.

→ .env内の記述が不十分
  key generateとphp artisan config:cache 両方やる
https://qiita.com/ponsuke0531/items/197c76fcb9300d7c5f36
Rails6 のちょい足しな新機能を試す75（ActiveJob enqueued_at編）

# はじめに

（多分）Rails 6 に追加された新機能を試す第75段。 今回は、 `ActiveJob enqueued_at` 編です。
Rails 6 では、 ActionJob で Job を Enqueue したときに、 Enqueue された時刻がログ出力されるようになりました。

Ruby 2.6.3, Rails 6.0.0.rc2, Rails 5.2.3 で確認しました。

（Ruby 2.6.4, Rails 6.0.0 がリリースされましたが、動作確認当時の最新版は、Ruby 2.6.3, Rails 6.0.0.rc2 でした。）

Rails 6.0.0.rc2 は `gem install rails -v 6.0.0rc2 --prerelease` でインストールできます。

```shell
$ rails --version
Rails 6.0.0.rc2
```

# プロジェクトを作る

```shell
$ bin/rails new rails_sandbox
```

# Job を作る

Job を次のコマンドで作ります。

```shell
$ bin/rails g job my_task
```

# rails console で確認

```irb
irb(main):001:0> MyTaskJob.perform_later
```

# ログファイルを確認

ログファイルを確認すると enqueued at 2019-08-16T05:40:44Z と最後に時刻が表示されていることがわかります。

```log:log/development.log
...
[ActiveJob] [MyTaskJob] [6fdfc00f-744e-4526-873b-f2319b5fc51e] Performing MyTaskJob (Job ID: 6fdfc00f-744e-4526-873b-f2319b5fc51e) from Async(default) enqueued at 2019-08-16T05:40:44Z
...
```

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try075_activejob_enqueued_at


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Adding enque time tracking and logging](https://github.com/rails/rails/pull/35238)
Amazon CloudWatch Events で cron 式を使う場合は時差に気をつける

## Amazon CloudWatch Events の cron 式で使うタイムゾーンは UTC

[ルールのスケジュール式 \- Amazon CloudWatch Events](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)

> cron または rate 式を使用して、CloudWatch イベント で自動化されたスケジュールに基づいて自己トリガーするルールを作成できます。すべてのスケジュールされたイベントは UTC タイムゾーンを使用し、スケジュールの最小精度は 1 分です。

## 日本とロンドンとの時差

日本標準時 (JST) と協定世界時 (UTC) との時差は、9時間。

[Ruby で時差を求める \- Qiita](https://qiita.com/niwasawa/items/93275acac3b489760ce2)

> 東京が 0時のとき、ロンドンは前日の15時、ニューヨークは前日の10時、ライン諸島は同日の 5時

> 2018年 1月 1日 0時: 東京
> 2017年12月31日15時: ロンドン

## フォーマットの違いを意識しておく

### crontab のフィールド・フォーマット

```
分 時 日 月 曜 コマンド
```

### Amazon CloudWatch Events の cron 式フォーマット

crontab とちがって「年」のフィールドがある。

```
cron(分 時 日 月 曜 年)
```

また、曜日のフィールドの「*」「?」の扱いにも気をつける。

[ルールのスケジュール式 \- Amazon CloudWatch Events](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)

> ワイルドカード * (アスタリスク) にはフィールドのすべての値が含まれます。時間フィールドの、* にはすべての時間が含まれています。[*] を日および曜日フィールドの両方に使用することはできません。一方に使用する場合は、もう一方に [?] を使用する必要があります。

> ? (疑問符) ワイルドカードはいずれかを意味します。[日] フィールドに 7 と入力し、7 日が何曜日であってもかまわない場合、[曜日] フィールドに ? を入力できます。

## 具体例

例えば毎日0時0分に cron で実行している処理があった場合は、

```
0 0 * * * /bin/sh /home/foo/bar.sh
```

以下のように、9時間前 (15時0分) の cron 式に置き換える。

```
cron(0 15 * * ? *)
```

## 参考資料
- [ルールのスケジュール式 \- Amazon CloudWatch Events](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)
- [crontab \- Wikipedia](https://ja.wikipedia.org/wiki/Crontab)
- [Man page of CRONTAB](https://linuxjm.osdn.jp/html/cron/man5/crontab.5.html)