OmniAICreator/Qiita-1.07M huggingface dataset:
PHP 暗号化、ハッシュ関数

##ワンタイムパッド
- 平文と乱数でXOR論理演算するだけの暗号。
- 情報理論的安全性を持つ暗号方式である。
- 一度使用した鍵（乱数）は、廃棄するのが原則である。
- OTPの使い回しで解読された事例で、ベノナ文書がある。
- もっとも鍵の配送問題に難があるため、実用的でない。

```php

<?php
// 暗号化したい文字列
$str = "保つのに時があり，捨てるのに時がある。";
// ワンタイムパッド
$pad = [
  12,20,148,22,87,91,239,187,206,215,103,207,192,46,75,243,
  204,61,121,210,145,167,108,78,166,129,109,239,138,134,150,196,
  217,63,158,201,204,66,181,198,54,0,0,130,163,212,57,167,
  169,115,170,50,109,116,173,177,252,242,233,3,33,28,139,73,
];

// ワンタイムパッドで暗号化
function convert($str, $pad) {
  $res = "";
  for ($i = 0; $i < strlen($str); $i++) {
    // 一文字取り出し、ASCIIコードに変換
    $c = ord(substr($str, $i, 1));
    // XORで暗号化
    $cx = $c ^ $pad[$i];
    // ASCIIコードを文字に変換
    $res .= chr($cx);
  }
  return $res;
}

// 暗号化
$enc = convert($str, $pad);
echo "暗号化した文字列:{$enc}\n";
// 復号化 (P xor K) xor K = P
$dec = convert($enc, $pad);
echo "復号化した文字列:{$dec}\n";
```

##公開暗号鍵方式
- 公開暗号鍵と秘密鍵の二つの鍵を利用して暗号化するものを「公開暗号鍵方式」と呼ぶ。
- 受信側が公開鍵と秘密鍵を持っている。
- 送信側は受信側が公開している公開鍵を取得して、`公開鍵でデータを暗号化`して送信する。
- 受信側は受け取ったデータを`秘密鍵で復号化`してデータを取得する。

```php
<?php
$passphrase = 'test';

// config
$conf = [
    //Digest method
    'digest_alg'       => 'sha512',
    //Specifies how many bits should be used to generate a private key.
    'private_key_bits' => 2048,
    //Specifies the type of private key to create. 
    'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
// Create the keypair
$pk = openssl_pkey_new($conf);

// Get private key
openssl_pkey_export($pk, $private_key, $passphrase);

// Get public key
$pub = openssl_pkey_get_details($pk);
$pub_key = $pub["key"];

// Write data to the file
file_put_contents("private.pem", $private_key);
file_put_contents("public.pem", $pub_key);

echo "秘密鍵: " . $private_key . "\n";
echo "公開鍵: " . $pub_key . "\n";

// Read data
$pub_key = file_get_contents("public.pem");
$pri_key = file_get_contents("private.pem");

$data = 'plaintext data goes here';

// Encrypt the data to $encrypted using the public key
openssl_public_encrypt($data, $encrypted, $pub_key);

// Get the private key using pass phrase
$pri = openssl_get_privatekey($pri_key, $passphrase);

// Decrypt the data using the private key and store the results in $decrypted
openssl_private_decrypt($encrypted, $decrypted, $pri);

echo $decrypted;

```

##ハッシュ関数
- 任意の長さのデータ入力すると固定長のビット列を返す関数。
- 以下の特性を持つ。
 - 原像計算困難性（一方向性） : 与えられたハッシュ値に対して、そのハッシュ値を出力するようなハッシュ関数への入力を求めることが困難。
 - 第2原像計算困難性（弱衝突耐性) : メッセージのハッシュ値が与えられたとき、そのハッシュ値から他のメッセージを探すことが困難なこと。
 - 衝突困難性（強衝突耐性） : 同じハッシュ値を与える二つの入力値を求めることが困難。
- MD5, SHA-1は強衝突耐性が破られており、同じハッシュ値を持つ2つのメッセージが作れる。
- PHPだと`password_hash`でハッシュ化できる関数がある。ハッシュ化アルゴリズムはbcrypt アルゴリズム。

#### ソルト
ハッシュ化されたパスワードであっても、「レインボーテーブル」や「総当たり」などの攻撃で元のパスワードを復元できる可能性があるので、ソルト（salt）と呼ばれる適当な文字列をパスワードに付加する。

#### ストレッチング
生成したハッシュ値を再度ハッシュ化するループを回す手法。

##参考
[ワンタイムパッド - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%AF%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%91%E3%83%83%E3%83%89)
[ハッシュ関数 - Wikipedia]
(https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E9%96%A2%E6%95%B0)
[password_hash - PHPマニュアル]
(https://www.php.net/manual/ja/function.openssl-pkey-new.php)
「N＋１問題」メモ　

書き途中

# 「N＋１問題」とは
SQLクエリを「データ量（N)＋１回」投げてしまっている。
簡単にいうと、１回のアクセスで済むのに何回もアクセスしている。
　→必要ないアクセスまでしてしまっているためパフォーマンスが低下してしまう。

#原因
アソシエーションを使用する時に発生してしまう。
具体例としてUserモデル（ユーザー）とPostモデル（ユーザーの投稿）をアソシエーションする時を考えてみる。

【アソシエーションの設定】

Userは複数のPostを持っている

```user.rb
class User <ActiveRecord::Base
 has_many :posts
end
```

Postは１つのUserを持っている

```post.rb
class Post < ActiveRecord::Base
 belongs_to :user
end
```

【投稿を表示】

```user_controller.rb
@users = User.all
```

　→全てのユーザーを取得する

```view.rb
@users.each do |user|
 puts user.post.content
end
```

　→それぞれのユーザーに対して投稿を取得する
　　（「user_id=1」の投稿を取得、「user_id=2」の投稿を取得・・・・　N回postテーブルにアクセス）


【SQLで確認】

```
SELECT 'users'.* FROM 'users'
SELECT 'posts'.* FROM 'posts' WHERE 'posts'.'user_id' = 1
SELECT 'posts'.* FROM 'posts' WHERE 'posts'.'user_id' = 2
SELECT 'posts'.* FROM 'posts' WHERE 'posts'.'user_id' = 3
　・
　・
　・
```
Userテーブルに１回、PostテーブルにN回アクセスしていることがわかる。
（１＋N問題と言った方がわかりやすいかも）

このため、アソシエーションを使用する時は「N＋１問題」に注意しなければならない！

#対策
「includes」メソッドを使用する。
「モデルA.include（:モデルB）」　→　Aに基づくBを取得

「includes」メソッドを用いてコントローラーを書き換えると

```user_controller.rb
@users = User.includes(:post).all
```

　→全てのユーザーを取得する
　→userモデルに基づくpostモデルを取得する
　（「user_id=1~N」のデータを取得する）

```view.rb
@users.each do |user|
 puts user.post.content
end
```

【SQLで確認】

```
SELECT 'users'.* FROM 'users'
SELECT 'posts'.* FROM 'posts' WHERE 'posts'.'user_id' IN (1,2,3・・・)
```
Userテーブルに１回、Postテーブルに１回のアクセスで済む。
離散フーリエ変換について理解を深める

# 背景
画像処理100本ノックに挑戦中です。Q.32からフーリエ変換の話に入ります。いい機会なので少し離散フーリエ変換について考察します。

# 周期性と離散性
[サンプリング定理と画像処理における補間](https://qiita.com/jajagacchi/items/1d1fcc852ef7d470fe7e)において示しましたが、連続信号を離散サンプリングすると、そのフーリエ変換は元のフーリエ変換を周期的に並べたものになります。同様に考えれば、連続信号を周期的に並べれば、そのフーリエ変換は離散的になります(フーリエ級数)。周期性と離散性の関係は表裏一体にあると言えます。

# フーリエ変換を計算機で取り扱うために
今、連続信号$f(x)$があるとします。これのフーリエ変換を計算機で数値的に行いたいとします。数値的に取り扱うためには、$f(x)$を離散サンプリングする必要があります。

```math
f(x) \to \tilde f(x) = f(x)\sum_{n=-\infty}^{\infty}\delta(x-nS)
```

$S$はサンプリング間隔です。フーリエ変換は

```math
\begin{eqnarray}
\tilde F(\nu) &=& \frac{1}{S}\sum_{n=-\infty}^\infty F(\nu-\frac{n}{S})
\end{eqnarray}
```

となります。つまり、元の信号のフーリエ変換を周期的に並べたものになります。数値的に得るためには

```math
\begin{eqnarray}
\tilde F(\nu) &=& \int f(x)\sum_{n=-\infty}^{\infty}\delta(x-nS)e^{-2\pi i \nu x}dx
\end{eqnarray}
```

を実行する必要があります。$-\infty \sim \infty$の範囲の和を取ることは計算機では出来ませんが、$f(x)$がある有限の範囲でのみ値を持つと仮定すればその範囲内の$n$で和を取れば問題ありません。サンプリング間隔を十分に小さく取れば$F(\nu)$を求めることが出来ます。

ここで取り扱ったように、実空間での信号を離散サンプリングしたフーリエ変換を離散時間フーリエ変換というそうです。

# 離散フーリエ変換
フーリエ空間でのフィルタ処理を考えれば、フーリエ空間上でも離散的である方が便利です。双方のサンプリング間隔が細かければそれでも情報は失わないはずです。

そこで、実空間における連続信号を離散化 & 周期化します。

```math
f(x) \to g(x) = \sum_n f(x-nX)\sum_m \delta(x-mS)
```

フーリエ変換すれば

```math
G(\nu) = \frac{1}{SX}\sum_{n,m}\delta(\nu-\frac{n}{S}-\frac{m}{X})F(\nu-\frac{n}{S})
```

となります。これから、

```math
\nu = n'/S + m'/X
```

のみ値を持つことがわかります。また、$G$は$1/S$の周期関数であることがわかります。$S=1$という単位系を採用すると、

```math
\nu = m'/X \;(0 \leq m' < X)
```

のみ考えればよいことがわかります。さて、具体的にフーリエ変換を評価する方法を考えます。

```math
G(\nu) = \int g(x)e^{-2\pi i\nu x}dx = \sum_{n,m}f(m-nX)e^{-2\pi i \nu m}= \sum_{n,m}f(m)e^{-2\pi i \nu(m+nX)}
```

より

```math
G(\nu = m'/X) = \sum_{n,m}f(m)e^{-2\pi i \frac{m'}{X}(m+nX)} = \sum_{m}f(m)e^{-2\pi i \frac{m'}{X}m}
```

となります。これが離散フーリエ変換の式に他なりません。

$F(\nu)$を推定するためには、実空間において信号を非周期化します。つまり矩形関数でフィルタをかけます。これはフーリエ空間で言えばsinc関数を畳み込むことと等価です。実空間で離散的なままなので、フーリエ空間での周期性はなくなりませんが、1周期だけ取り出せば連続関数$F(\nu)$の推定が出来ます。

# まとめ
離散フーリエ変換は、離散信号に対する厳密なフーリエ変換であり、連続信号に対する近似的なフーリエ変換と言えます。近似精度を上げるためには台形公式等を使えばよいと思われます。ただし、サンプリング間隔が十分に小さければ、sinc関数を畳み込むことにより、正確なフーリエ変換が求まります。
None と is

```py
empty = None

if empty is None:
    print('変数emptyはNoneです。')

print(1 is True)
print(1 == True)
print(1 is 1)
print(True is True)
```

```:実行結果
変数emptyはNoneです。
False
True
True
True
```

is は none の時位しか使わない感じ。。。
Illuminate \ Http \ Exceptions \ PostTooLargeException No message を改善

laravelを勉強中に画像をアップロードすると以下のエラーMSGが表示され困っていた。

```
Illuminate \ Http \ Exceptions \ PostTooLargeException
No message
```
色々調べた結果どうやらphp.iniに記載されているpost_max_sizeを超えてしまったための模様
php.iniでファイルのサイズを設定できるらしいため
まずターミナルでpost_max_sizeを確認してみることに

```
$ php -a
$  echo ini_get('post_max_size');
8M
```
8Mがまでしか許可されていなかったためphp.iniを編集しにいく
まずはphp.iniがどこにあるか確認。


```
$ php --ini
Configuration File (php.ini) Path: /etc
Loaded Configuration File:         /etc/php.ini
```

/etcの中にあるphp.iniを $sudo vim php.iniで開き編集

記述を以下に変更

```
upload_max_filesize = 20M
post_max_size = 20M
```
編集後セーブしもう一度許可されている最大ファイルサイズを確認

```
$ php -a
$  echo ini_get('post_max_size');
20M
```

既に立ち上がっているサーバーを再起動しもう一度同じ画像をアップロードしてみたところ
うまくアップロード出来ました。
Pytorchのcollate_fnを使ってみる

Pytorchのcollate_fnは[Dataloader](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader)の引数です。

```python
DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
           batch_sampler=None, num_workers=0, collate_fn=None,
           pin_memory=False, drop_last=False, timeout=0,
           worker_init_fn=None)
```
今回はその挙動と使い方を確認していきたいと思います。

#collate_fnとは
datasetで定義された\_\_getitem\_\_がバッチの形になるとき、まずはそれぞれの要素(画像、ターゲットなど)がリストで固められます。
[Pytrochの公式](https://pytorch.org/docs/stable/data.html#automatic-batching-default)に書かれている通りcollate_fnはそれを操作し、最終的にはtorch.Tensorにする関数です。

```python
dataset_iter = iter(dataset)
for indices in batch_sampler:
    yield collate_fn([next(dataset_iter) for _ in indices])
```

デフォルトでは、torch.stack()でTensorにするのみなのですが、自作のcollate_fnを使うことで高度なバッチを作ることができます。

#collate_fnを自作
デフォルトの挙動は以下とほとんど同じとなっています。(returnの数は\_\_getitem\_\_によって変わりますが)
batchを引数にとり、stackして返しています。

```python
def collate_fn(batch):
    images, targets= list(zip(*batch))
    images = torch.stack(images)
    targets = torch.stack(targets)
    return images, targets
```
自作のcollate_fnはこの中身を変えればいいわけです。

今回は物体検出のバッチを作成します。
物体検出は基本的に物体の矩形とそのラベルを入力としますが、１枚の画像に複数の矩形があることがあるので、バッチにするときどの画像がどの矩形かを結びつける必要があり、インデックスを付ける必要があります。

```
[[label, xc, yx, w, h],
 [                   ],
 [                   ],...]

# これを下に変える

[[0, label xc, yx, w, h],
 [0,                   ],
 [1,                   ],...]
```

実装自体はそれほど難しくはありません。

```python
def batch_idx_fn(batch):
    images, bboxes = list(zip(*batch))
    targets = []
    for idx, bbox in enumerate(bboxes):
        target = np.zeros((len(bbox), 6))
        target[:, 1:] = bbox
        target[:, 0] = idx
        targets.append(target)
    images = torch.stack(images)
    targets = torch.Tensor(np.concatenate(targets)) # [[batch_idx, label, xc, yx, w, h], ...]
    return images, targets
```

実際に使ってみると以下のようになります。

```python
test_data_loader = torch.utils.data.DataLoader(
                       test_dataset, 
                       batch_size=1, 
                       shuffle=False, 
                       collate_fn=batch_idx_fn
                       )
print(iter(test_data_loader).next()[0])
# [[0.0000, 0.0000, 0.6001, 0.5726, 0.1583, 0.1119],
# [0.0000, 9.0000, 0.0568, 0.5476, 0.1150, 0.1143],
# [1.0000, 5.0000, 0.8316, 0.4113, 0.1080, 0.3452],
# [1.0000, 0.0000, 0.3476, 0.6494, 0.1840, 0.1548],
# [2.0000, 2.0000, 0.8276, 0.6763, 0.1720, 0.3240],
# [2.0000, 4.0000, 0.1626, 0.0496, 0.0900, 0.0880],
# [2.0000, 5.0000, 0.2476, 0.2736, 0.1400, 0.5413],
# [2.0000, 5.0000, 0.5786, 0.4523, 0.4210, 0.5480],
# [3.0000, 0.0000, 0.4636, 0.4618, 0.0400, 0.1024],
# [3.0000, 0.0000, 0.5706, 0.5061, 0.0380, 0.0683]]
```

#おわりに

今回紹介したでインデックスつけるとき以外に、
バッチごとにtargetが変わるときや、
targetがstackできないような数値データではないとき、
同じDatasetを少しだけ変えて使いまわしたいときに使えると思います。
bashで連番のディレクトリを作成するワンライナー


`dir001`, `dir002`, ..., `dir010` のような感じにまとめて生成したい。

```bash
$ for i in `seq -f %03g 1 10`; do mkdir dir${i}; done
```

#### 結果

```bash
$ ls
dir001	dir002	dir003	dir004	dir005	dir006	dir007	dir008	dir009	dir010
```

#### 補足
`seq` コマンドで数字の列を出力できる。連番の生成に便利。

```
seq [-w] [-f format] [{最初の数}] {最後の数}
```

`-f` で形式を指定できる。

```bash
$ seq -f %03g 8 11
008
009
010
011
```

`-w` で自動で最大幅の桁数に合わせて出力してくれる。

```bash

$ seq -w 99 101
099
100
101
$ seq -w 9 11
09
10
11
```

#### 参考
- [シェルスクリプトで桁数を揃えた連番を作成 - Qiita](https://qiita.com/cakipy/items/60353b22bbe852946da0)
- [ 【 seq 】コマンド――数字の列を出力する：Linux基本コマンドTips（110） - ＠IT](https://www.atmarkit.co.jp/ait/articles/1705/18/news033.html)
マジックナンバー142857の正体

##はじめに
この記事は[三重大学計算研のアドベントカレンダー2019](https://qiita.com/advent-calendar/2019/calc-mie)です。
私がプログラミング技術に疎いのもあり、あまり関係ない雑学のようなものを取り上げています。
知っている方も多いと思いますが温かい目でお願いします。

##142857の性質の確認
性質①142857に1~6を掛けると数の並びが循環する。


```math
142857 \times 1 = 142857\\
142857 \times 2 = 285714\\
142857 \times 3 = 428571\\
142857 \times 4 = 571428\\
142857 \times 5 = 714285\\
142857 \times 6 = 857142\\
```
性質②142857に7を掛けると9だけの並びになる。

```math
142857 \times 7 = 999999
```
このように142857という数が踊りまわったり、みんなが9になったりと不思議な数として紹介されています。

##何故こんな性質があるのか
この疑問は142857がどこから生まれるのかを考えれば、よくわかると思います。

```math
\frac{1}{7} = 0.142857142857...
```

142857は$\frac{1}{7}$の循環節であることが分かります。
$\frac{1}{7}$を桁ごとに計算してみると

```math
　　　商　　余り\\
1\div7 = 0 ・・・1\\
10\div7 = 1・・・3　\\
30\div7 = 4・・・2　\\
20\div7 = 2・・・6　\\
60\div7 = 8・・・4　\\
40\div7 = 5・・・5　\\
50\div7 = 7・・・1　\\
```
上の式の商が$\frac{1}{7}$の小数展開した数字列になります。
計算すると桁がどんどん小さくなるので前の式の余りを10倍して商と余りを計算します。
最後の式で余りが1になるので2行目の式にループします。この2行目から7行目までの式が繰り返されるので循環小数が生まれます。
$\frac{1}{7}$から$\frac{6}{7}$までそれぞれの循環節は分子このループする式の余りと対応して$\frac{2}{7}$なら余りが2の次の式から循環して循環節は285714になります。
この式のループで$\frac{1}{7}$に1~6を掛けたとき循環節がぐるぐるまわるのも分かると思います。この循環節が回っただけの性質を今後は回転において合同と表現します。(一般的な表現ではありません)

そして、性質②についても同様に

```math
\frac{1}{7} \times 7 =0.999999… = 1\\
```
と考えると納得できると思います。

##142857が特別ではない？
上述の通り、142857に面白い性質があったのは小数の循環節であるという理由から分かりました。
だとすると、他の循環小数から同じようにつくれるのでしょうか。
他の循環小数でも調べてみましょう。(桁は次の循環節のうち一番長い6桁に合わせてあります)

```math
\frac{1}{3}=0.333333…\\
\frac{1}{6}=0.166666…\\
\frac{1}{9}=0.111111…\\
\frac{1}{11}=0.090909…\\
\frac{1}{13}=0.076923…\\
```
自然数nより$\frac{1}{n}$を考えたとき、nが2や5以外の素因数を持たないと循環小数にならないのでn=2,4,5,10の例は除きました。
n=3,6,9,11,13についてはいずれも$\frac{1}{n}$から$\frac{n-1}{n}$までのすべてで回転において合同ではありません。ですが条件を緩めるとn=13では、

```math
\frac{1}{13},\frac{3}{13},\frac{4}{13},\frac{9}{13},\frac{10}{13},\frac{12}{13}\\　
\\
\frac{2}{13},\frac{5}{13},\frac{6}{13},\frac{7}{13},\frac{8}{13},\frac{11}{13}\\
```
この2グループ内それぞれで回転において合同です。
実際に計算して確かめてみてください。

また、条件を緩めずともn=17のとき、

```math
\frac{1}{17} = 0.588235294117647…
```
循環節は16桁であり、$\frac{1}{7}$の時と同様に$\frac{1}{17}$から$\frac{16}{17}$まで回転において合同になります。
このように、自然数nについて$\frac{1}{n}$を調べていくと循環節がn-1桁、つまり$\frac{1}{n}$から$\frac{n-1}{n}$まで回転において合同となるnはいくつも現れます。

どんな時に$\frac{1}{n}$の循環節がn-1桁になるのか、またn=13のようにいくつかグループに分けて回転するときそのグループの数はnのどんな条件を調べればいいのか。いろいろ気になるところはありますが、今回はこれで終わります。

##最後に
この記事はあくまで142857の数字がどこから来ているのかを紹介しただけなので、もっと調べれば他にも面白い話が出てくると思います。よければ、調べてみてください。
分かりやすい記事ではないと思いますが、ここまで読んでくださりありがとうございます。

参考文献：
[不思議で面白い数字の雑学・トリビア10選 | 数学の面白いことをまとめたサイト](https://analytics-notty.tech/10-trivias-of-numbers/)
Laravel Mix + SASS/SCSS + curly braces (波括弧/中括弧) でハマった

何が悲しくて大晦日に仕事してるのか、原因不明（いやむしろミドルウェアのバグと思われる）の現象にどハマリして、このまま絶望とともに新年を迎えるのかと思いきや、思いつきが見事に的中して、年が変わる前に解決できたこの喜びを、ここで共有させてもらいたい。

## 問題：SCSSの文字列内の`}`が外に出て解釈されてしまう
問題のSCSSコードがこれ

```
background-image: url("... fill='${BencodeURIComponent($iconColor)}' ...");
```

Webpackでコンパイルしていたときは`url()`に渡してる文字列は、意図したとおりそのままCSSに吐き出されていたが、Laravel Mixにした途端、どうしても`}`が解釈されてしまって下記のような壊れたCSSになってしまう。

```
background-image: url("... fill='${BencodeURIComponent($iconColor)

}
...");
```

クオートをシングルとダブルを切り替えてみたり、バックスラッシュ`\`でエスケープしてみたり・・・どれもダメだった。
が、渡している先が`url()`と言うことは、もしや・・・

## 解決策：URLエンコードする
`}`を`%7D`に置き換える。はい、それだけ。
ついでに`{`も`%7B`に置き換えた。

これでやっと、正常なCSSが吐き出され、意図したとおりに動いてくれました。

## あとがき
Laravel MixはWebpackのラッパーなので切り替える前と同じはずなのに、なぜか起きたこの現象。切り替え前と違うことと言えば、Laravel MixはSCSSをコンパイルするために`resolve-url-loader`を必要としたことくらい。

大晦日の貴重な数時間を返して欲しいが、もやもやしたまま新年を迎えなくて良かったとしよう。
Djangoでbitflyerの収支管理アプリを作ってみる（まとめ）

Djangoでbitflyerの収支管理アプリを作ってみるシリーズが結構溜まって来たので、まとめを作成。

設計をする。
https://qiita.com/redmeteor777/items/b373d884ba1e507a6b91

00.事前準備とプロジェクトを作成する。
https://qiita.com/redmeteor777/items/54178a7229b70fce55b3

01.URLマッピングを作成する。
https://qiita.com/redmeteor777/items/0d499c7849ad0f3df441

02_01.ログイン画面を作る。
https://qiita.com/redmeteor777/items/1b974f15ac8b0e87a17d

02_02.ログイン画面を作る②。
https://qiita.com/redmeteor777/items/8fd573b2aee3dfa20515

02_03.ログイン画面を作る③。
https://qiita.com/redmeteor777/items/fd649baf43753185a5f7

03.ユーザー情報新規登録画面を作る。
https://qiita.com/redmeteor777/items/5013c04db5c7edcf8cba

04_01.ダッシュボード画面を作成する。
https://qiita.com/redmeteor777/items/64f2288457c850666221

04_02.ダッシュボード画面を作成する。
https://qiita.com/redmeteor777/items/bdd0cf0f89b21d5f7696

05.まだ
Docker(Alpine) + Laravel 環境を PHP7.4 にアップデートする際に oniguruma パッケージのビルドエラー

PHP7.4にアップデートしようとしたらDockerのビルド中にエラーが発生しました。

## 環境

- Alpine 3.11
- PHP 7.4

## ビルドエラー

```
checking for oniguruma... no
configure: error: Package requirements (oniguruma) were not met:

Package 'oniguruma', required by 'virtual:world', not found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables ONIG_CFLAGS
and ONIG_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
```

## 対処法

```shell-session
$ apk add --update --no-cache oniguruma-dev
```

差分: https://github.com/ucan-lab/docker-laravel/pull/38/files

## 鬼車(oniguruma) とは

正規表現ライブラリです。
それぞれの正規表現オブジェクトごとに異なる文字エンコーディングを指定できる特徴があります。

- https://github.com/kkos/oniguruma

## 参考

- https://github.com/docker-library/php/issues/880
- https://pkgs.alpinelinux.org/packages?name=oniguruma-dev&branch=edge
- https://stackoverflow.com/questions/59251008/docker-laravel-configure-error-package-requirements-oniguruma-were-not-m
2019締めに除夜の鐘を作る

２時間ほどでサクッと作りました。
除夜の鐘を聞きたいけど近くにない・・・
そんな人はデジタル除夜の鐘で今年の煩悩を払いましょう。
https://jyoya.herokuapp.com/

![screencapture-localhost-3000-2019-12-31-22_19_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55077/0c484f48-57eb-5831-4ee9-bc92b0028388.png)
GeoLite 2のライセンス制度変更とその対応

# GeoLite2のライセンス制度が変わったので、その対応方法など

![スクリーンショット 2019-12-31 21.46.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12014/9622edce-558d-48aa-11fe-4e6e0f925d4c.png)

# 対応方法
## サインアップはこんな感じで登録
![スクリーンショット 2019-12-31 21.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12014/e16605d3-bcd8-5a8e-9758-c7241e679a30.png)

## 即座にメールが届くのでレジストしてからログイン
![スクリーンショット 2019-12-31 21.53.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12014/99eab653-e13d-0dfa-7d5e-16080463bc09.png)

## 「請求先を書いてくれ」と出ているので入力する
![スクリーンショット 2019-12-31 21.55.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12014/05dd79e8-a2d9-ebd7-77b3-856d98f5afff.png)

## 「My License Key」をクリックし「License key description」にわかり易い名前を入れて[Will this key be used for GeoIP Update?]で[Yes]を選択(geoipupdateを持っていること)
[github maxmind/geoipupdate](https://github.com/maxmind/geoipupdate/releases)
![スクリーンショット 2019-12-31 21.59.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12014/5c44d745-d481-710e-3a8a-e27507d588f2.png)

## /etc/GeoIP.conf にライセンスを追加
```
AccountID ******
LicenseKey xxxxxxxxxxxxx
```

## 5分くらい待つと geoipupdate でデータ取得可能
React Hooksで複数のFormを扱う

```jsx
const Forms: React.FC = () => {
  const [inputTexts, setInputTexts] = useState({
    firstName: '', lastName: '', e_mail: '', password: ''
  })

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInputTexts({ ...inputTexts, [e.target.name]: e.currentTarget.value })
  }

  return (
    <div>
      {Object.entries(inputTexts).map(([key, value]) =>
        return <input type="text" key={key} name={key} value={value} onChange={handleChange} />
      )}
    </div>
  )
}
```


- `state`を一括りにまとめる
- `Object.entries`で 各`key`と`value`を取得
- `input`タグの`name`に`key`を指定 → `onChange`の`event.target.name`で`key`を取得
validationで指定した際に出るエラー文の表示の仕方

```

<% 変数名.errors.full_messages.each do |message| %>
    <div class="form-error">
       <%= message %>
     </div>
<% end %>
```

変数名.errors.full_messages.eachで配列のエラーメッセージを取得する事が出来る
「文言/wenyan-lang」最初の一歩　コマンドライン編

## 0.はじめに

漢文風プログラミング言語
「__文言__ / wenyan‑lang」 を紹介させていただきます

名前の由来については、中国語で漢文のことを「文言文」、「文言」は拼音(ピンイン)で 「*wén yán*」なのでそこから来ていると思われます。

* 公式サイト:  [文言 / wenyan‑lang](https://wy-lang.org)

[オンラインエディタ](https://wy-lang.org/ide.html)が公開されており、環境構築無しでブラウザ上でサンプルプログラムや、自作コードを実行出来ます

この記事では、後のレンダリング処理のためにコマンドラインでの実行方法を紹介します

### 動作確認
こちらの記事の確認環境は以下の通りです

> npm v6.13.4
wenyan v0.1.2

# インストール

* node.jsを[こちら](https://nodejs.org/en/download/)より、お使いのOSに合わせてダウンロードし、インストールする

[文言 / wenyan‑lang](https://wy-lang.org)公式より


* npmより文言コンパイラー[^1]をインストールする

```sh
npm install -g @wenyanlang/cli
```

## 実行

* [こちら]
(https://github.com/LingDong-/wenyan-lang/tree/master/examples)よりExamples取得

```sh
wenyan examples/helloworld.wy
# 問天地好在。 
```

他のサンプルアプリも実行してみて下さい

## おわりに

GitHub初期commitが12月8日という生まれたてのこの言語は、記事を書いているうちにも、READMEの内容も変わり実行手順も変わっています。目が離せませんね。

# 参考

* [漢文風プログラミング言語「文言」の基本文法を読み解いてみた](https://qiita.com/GandT/items/920af538c0a405199815) - @GandT 

* [漢文プログラミング言語 wenyan-lang でメリークリスマス！]
(https://qiita.com/lovee/items/2c652d93b5dbff13e3b3) - @lovee

* [@wenyanlang/core](https://www.npmjs.com/package/@wenyanlang/core) 


[^1]: 公式表現ではcompilerとなってますが、トランスパイラですよね。中国語では区別しない?
iTermでcmd+shift+;でフォントサイズが拡大できない

## About

iTermでフォントを拡大しようとすると、`Shell Integration`のインストールダイアログが出て拡大できない件への対処です。

マシン替える度に迷ってるのでメモ

## 環境
iTerm2 Build 3.4.10
macOS Big Sur 11.5.2 （20G95）

何種類かのパターンがありそうなので、随時追記します。

今回はどなたにでも対処できそうな方法を記載します。
(途中まで実施してしまった人にも対応可能という意味で)

## 方法

1. iTerm2上で、cmd+shift+;を押す
2. `About Shell Integration`のダイアログが表示される
3. `Install Now`を選択する
4. インテグレーションがインストールされるまで待つ
5. 以下のコマンドを実行

```shell

test -e "${HOME}/.iterm2_shell_integration.bash" && source "${HOME}/.iterm2_shell_integration.bash"
```
6.iTerm2を再起動する
7. cmd+shift+;でフォントが拡大できるようになっている

## トラブルシューティング

### Open Autocompleteが出る場合
私の環境では、6でiTermを再起動しない状態ではCompletionのガイドが出ました。

iTerm2を再起動しても上手くいかない場合は以下を実施

1. 設定画面を開く
`Preferences -> Keys -> Keybindings`
2. 左下の＋ボタンから以下2つのショートカットを追加
- Keyboard Shortcutに`⌘ + ;`を、Actionに`Ignore`を登録

<img width="734" alt="complete" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/c609b342-dbcc-7bf0-7952-a1e25aad9cf5.png">

- Keyboard Shortcutに`shift + ⌘ + ;`を、<br>
Actionに`Select menu item`から`Make Text Bigger`を登録

<img width="734" alt="register" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275986/94d170c5-1c78-dea1-b38b-b0b058240f73.png">

こんな感じになればOKです。
Microsoft Learn 31日目

12月より、Advent Calendar を使って Microsoft Learn で学んでいく...と試みてなんとか完遂した([記事はこちら](https://qiita.com/advent-calendar/2019/d01tsumath_learn))。
しかし、スローペースだったのもあり25日間毎日受講しているとは言え、コースの半分しか終わってない。
そこで、「Azure の基礎」コースが終わるまで続けていこうと思う。毎日できるかは不明、でもがんばる。

と、いうことで。以下、受講記録のはじまりはじまり～。

12/31は
Azure におけるセキュリティ、責任、信頼
 - ネットワークを保護する
を受講した。

# Azure におけるセキュリティ、責任、信頼
## ネットワークを保護する
### ネットワークセキュリティに対する階層型アプローチ
ネットワーク境界のセキュリティ保護、またはネットワーク内のサービス間のネットワークセキュリティに注目するだけでは、十分ではない。
階層型アプローチでは、攻撃者が 1 つの階層を突破した場合でも、それ以上の攻撃を制限するための保護がさらに存在するように、複数レベルの保護が提供されている。
### ファイアウォールとは
ファイアウォールとは、各要求の送信元 IP アドレスに基づいてサーバーへのアクセスを許可するサービスのこと。
IP アドレスの範囲を指定するファイアウォール規則を作成し、これらの許可された IP アドレスからのクライアントのみが、サーバーへのアクセスを許可される。一般に、ファイアウォール規則には特定のネットワーク プロトコルとポート情報も含まれる。
#### Azure Firewall
Azure Virtual Network リソースを保護するクラウドベースのマネージドネットワークセキュリティサービス。
組み込みの高可用性とクラウドによる無制限のスケーラビリティを備えた、完全にステートフルなサービスとしてのファイアウォールとなっている。
#### Azure Application Gateway
ロードバランサーであり、Web サイトの一般的な既知の脆弱性に対する保護を提供する Web アプリケーションファイアウォール(WAF)が含まれている。
#### ネットワーク仮想アプライアンス(NVA)
HTTP 以外のサービスまたは詳細構成に最適なオプションであり、ハードウェアファイアウォールアプライアンスと同様。

### 分散型サービス拒否(DDoS)攻撃の阻止
Azure DDoS Protection では、Microsoft のグローバルネットワークのスケールと弾力性を利用して、あらゆる Azure リージョンで DDoS の軽減能力を発揮する。
Azure DDoS Protection サービスでは、サービスの可用性に影響が及ぶ前に、Azure ネットワークエッジのトラフィックを監視することで Azure アプリケーションを保護し、攻撃の検出から数分以内に、Azure Monitor メトリックを使用して通知する。

### 仮想ネットワーク内のトラフィックの制御
#### 仮想ネットワークのセキュリティ
Azure 仮想ネットワーク内の Azure リソースが送受信するネットワークトラフィックは、ネットワークセキュリティグループ(NSG)を使ってフィルター処理できる。
各 NSG には、送信元と送信先の IP アドレス、ポート、およびプロトコルでリソースとのトラフィックをフィルター処理できるようにする受信と送信のセキュリティ規則を複数含めることができ、NSG では、ネットワークインターフェイスおよびサブネットとの間の双方向の通信について許可と拒否の一覧が提供され、完全にカスタマイズすることができる。
#### ネットワーク統合
Azure 仮想ネットワークとオンプレミスの VPN デバイスの間の接続は、ご使用のネットワークと Azure 上のご使用の VNet の間にセキュリティ保護された通信を提供するのに最適な方法である。
使用しているネットワークと Azure の間に専用のプライベート接続を設定するには、Azure ExpressRoute を使用するのがよい。
ExpressRoute を利用すると、接続プロバイダーが支援するプライベート接続を介して、オンプレミスのネットワークを Microsoft クラウドに拡張できる。


# おまけ。
2019年年末に始動した Microsoft Learn ですが、年明けても続けていくので
よかったっら温かく見守ってくださいませ。
renderメソッド

renderメソッドを用いる事で別のアクションを経由せずに表示する事が出来る。
似た様な内容でredirect_toメソッドは表示されるアクション内の@変数を利用して表示されるが、renderメソッドはそのアクション内で定義されている@変数を使用してビューを表示する。

例なのでアクション名などは適当です

```ruby

 def index
   @post = モデル.find_by(引数)
　　
 end

 def show
   @post = モデル.find_by(引数)
   @post.カラム名 = params.カラム名
   redirect_to("indexのURL")
 end 

 def update
   @post = モデル.find_by(引数)
   @post.カラム名 = params.カラム名
   render("フォルダ名/ファイル名")
 end

```

この場合showとupdateはカラム名の中身が変更されたらアクション内では変更されますが、
showの方ではredirect_toで指定してる為、表示されるのはindex内のアクション内容になってしまいます。

このような違いがあります。
.gitignoreの作り方

GitHubが用意してくれている。ありがたい。
https://github.com/github/gitignore

Railsならこんな感じ。
https://github.com/github/gitignore/blob/master/Rails.gitignore

```:Rails.gitignore
*.rbc
capybara-*.html
.rspec
/log
/tmp
/db/*.sqlite3
/db/*.sqlite3-journal
/public/system
/coverage/
/spec/tmp
*.orig
rerun.txt
pickle-email-*.html

# TODO Comment out this rule if you are OK with secrets being uploaded to the repo
config/initializers/secret_token.rb
config/master.key

# Only include if you have production secrets in this file, which is no longer a Rails default
# config/secrets.yml

# dotenv
# TODO Comment out this rule if environment variables can be committed
.env

## Environment normalization:
/.bundle
/vendor/bundle

# these should all be checked in to normalize the environment:
# Gemfile.lock, .ruby-version, .ruby-gemset

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc

# if using bower-rails ignore default bower_components path bower.json files
/vendor/assets/bower_components
*.bowerrc
bower.json

# Ignore pow environment settings
.powenv

# Ignore Byebug command history file.
.byebug_history

# Ignore node_modules
node_modules/
```

これをベースに、環境やプロジェクトに応じたものを作っていけばよさそう。

OSやエディタについても、メジャーなものは大抵用意されている。
https://github.com/github/gitignore/blob/master/Global/

例えば、Macユーザーなら毎回`.DS_Store`を追加しているはずだが、Mac用の.gitignoreもある。
https://github.com/github/gitignore/blob/master/Global/macOS.gitignore

```:macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
```
vscodeでscss開発して発生したエラーについて

#はじめに
vscodeでscssを触っていた時にLiveSassCompilerでエラーが発生しまくって腹が立ったので調べてみた
#調べてわかったこと
エラーは色々でているそうです
[Watch My sass *Extension host terminated unexpectedly #53](https://github.com/ritwickdey/vscode-live-sass-compiler/issues/53)
その結果競合がたびたび起こるらしいのですが中身を見ないとわからないですね
なので中身をみます
上の`help`から`開発者ツールの切り替え`で見れます
#結果
[encdetect jp](https://marketplace.visualstudio.com/items?itemName=inoueben.encdetectjp)が原因でした
何故かは全くわかりません
まさに一期一会🌸!!
とりあえずアンインストールしたらエラーがでなくなりました
まあ今時UTF8じゃない人も珍しいので無くても大丈夫でしょう
皆さんには皆さんの競合があるのでこれで:hand:
2019年をふりかえる

## はじめに。2019年のやったこと

　[昨年](https://qiita.com/warumonogakari/items/b465651ea9b4adc05764)と同様、[twilog](https://twilog.org/warumonogakari/month-1812/asc)をつかってこの一年間何があったか思い出してふりかえります。
　ちなみに、月別のツイート数はこんな感じ。
![twilog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242026/78aa8047-0075-e4e2-69a5-2bbfab22d720.jpeg)
　８月以降、ツイート数がおちたのは、母の入院・介護が大きかったかな。
　活動記録を紐解くと以下のような感じ。

 出かけた | 関東       | 9  
:---|:---|:---
         | 関西       | 2  
          | 名古屋     | 10 
 書いた   | ブログ     | 12 
          | スライド   | 10 
 活動した | 勉強会主催 | 4  
          | ＬＴ       | 3  
　ここ名古屋のよいところは、関東・関西どちらでも行けるところ。今年は、かなり頑張って東京方面にでかけることができました。また、自分の感覚以上に、地元名古屋での活動もできました。ちょっとびっくりですね。
　[支援者のためのダイアローグ勉強会IN名古屋](https://qiita.com/warumonogakari/items/0e548f39a9d1c028b29a)を通じて 12月には東海ダイアローグの立ち上げにも参加でき、全然畑のちがう医療関係者の皆さんにも知り合うことができました。

　その他、なんといっても、[Engineering Manager Meetup in NAGOYA](https://em-nagoya.connpass.com/) #EM_NAGOYA を立ち上げたこと。主旨に共感してくれて毎回場所も貸してくれた フェンリルさんがいなければここまでやれることはなかったです。この場を借りて御礼申し上げます。どうもありがとうございました！

## わかったこと。
　今年は、ブリーフセラピー、オープンダイアローグ、適応課題と、長年もやもやとしていた、言葉にできなかった課題を言語化し、その方向性を見出すことができました。開発組織が旧態のままだと、リファクタしても元にもどってしまう積年の課題にようやく一定の答えがだせそうな気がしています。まだまだ山あり谷ありだとはおもいますが、ライフワークはこれかもしれないなとおもえる出会いがありました。

## そして、来年やること。
　まず、#EM_NAGOYA は継続して続けていきたいですね。だいたい１か月に１度だと息切れしそうな気がするので、２か月に１度くらいかな。Podcastに出演して宣伝したり、出張して、大阪や東京方面でもやってみたい（会場貸してくれるところってあるんですかねぇ）
　次に、せっかく ブリーフセラピーはここまで勉強したので資格とれたらとってみたいです。試験勉強なんぞ久しくやっていないので、どれだけ体力もつのかわからないですが。セラピスト兼エンジニアって、かなりニッチな気がするので、それなりに世の中に役に立てる気がしています。せっかく知り合った医療関係のみなさんとの縁も大事にしていきたいですね。エンジニアと医療関係の知見をヒントに、まだまだ世の中のために何かやれそうな気がしています。
　あと、勉強会メンバとも相談してお呼びしたい方をここ名古屋にお呼びして、たとえばお話会ができたらとおもっています。そもそもどうやってやるのか、会場はどうしようか、交通費とかどうするのか 全然わかっておりませんが、きっとチャンスがあるんじゃないかなぁと。
　そして、いつか将来は、会社の枠をこえて、適応課題解消のための専門チームを結成して、求めに応じて迅速に対応・介入することで、今困りに困っている日本の開発体験の向上ができたら。。まだまだ妄想が広がるばかりです。

### 謝辞
　いつも突然どこそこに行きたいという私を気持ちよく送り出してくれる 妻と、愛する娘ニャンズに 感謝いたします。そして、フェンリルさん、ふりかえりをご指導いただいた[びばさんこと森一樹さん](https://twitter.com/viva_tweet_x)Twitterをはじめとする SNSの関係者のみなさん、どうもありがとうございます。皆さん、来年よい年であることを心より祈念しております。
　ではでは、よいお年を、そして よい開発体験を。
お天気情報の取得（DarkSky）

###背景
ラズパイに付けたLCDの表示内容とすべく、
外部のAPIとの連携を試しました。

###手法
Livedoorのお天気情報のAPIに関する情報はたくさんあったのですが、
LCDが漢字に対応していないので、海外のものも含めて、探すことに。

[DarkSKy](https://darksky.net/dev)で作ってみました。
英語ですが、そんなに難しくは感じませんでした。
1日当たり1,000コールまでは無料です。
自分の場合20分毎に1回取りに行くだけにしたので、
まず超えません。

1. 右上のSIGN UPでアカウントを作成。
2. メール認証後、自分のシークレットが表示されるのでセット
3. APIドキュメントを見ながら当日の天気をセット


```Python
url2='https://api.darksky.net/forecast/（シークレット）/（緯度経度）
    data=requests.get(url2).json()
    separated_data=data['daily']['data'][0]['summary'].split()
    len(separated_data)
    forecast_time=date.fromtimestamp(data['daily']['data'][0]['time'])
    payload5=str(forecast_time.month)+"-"+str(forecast_time.day)+" "+separated_data[0]
    separated_data_l2=separated_data.pop(0)
    payload6=' '.join(separated_data)
   print(payload5)
   print(payload6)
   lcd_string(payload5, LCD_LINE_1)
   lcd_string(payload6, LCD_LINE_2)
   time.sleep(5)  
```

###状況
数日運用してみましたが、概要レベルでは外していないので、
16桁2行のLCDで見るには十分かと。。
S3への静的サイトホスティングとAmplify Consoleによるデプロイ比較

# S3への静的サイトホスティングとAmplify Consoleによるデプロイ比較

この記事は[サーバーレスWebアプリ Mosaic](https://mosaic.w2or3w.com "Mosaic")を開発して得た知見を振り返り定着させるための[ハンズオン記事](https://qiita.com/w2or3w/items/87b57dfdbcf218de91e2)の1つです。

以下を見てからこの記事をみるといい感じです。

* [AWS Amplify Consoleでビルド＆デプロイ](https://qiita.com/w2or3w/items/da1134fa3a14660dcc54)

##イントロダクション
Amplify Consoleの楽さをより実感するために、あえてS3にもデプロイして静的サイトとしてホストします。
静的サイトといえど、Webアプリとして動作します。

## コンテンツ
### S3バケットの作成
AWSコンソール > S3 > バケットを作成するボタンを押下
![Screenshot 2019-12-31 at 07.16.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/feb4ef06-0103-fcfe-03ba-93cbca90fdd2.png)
適当なバケット名前を入力し、次へ進んでください。
オプションの設定は、デフォルトのまま進みます。
アクセス許可の設定は、「パブリックアクセスをすべてブロック」チェックをOFFにして進みます。
![Screenshot 2019-12-31 at 07.26.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/14aee008-b494-94d5-b967-d4f595b5e373.png)
最後のページ確認でバケット作成ボタン押下により、S3バケットが作成されます。

### Webアプリケーションのビルド＆デプロイ
Webアプリケーションをビルドします。

```
$ npm run build
```
ビルドエラーなく完了すると、distフォルダにデプロイするファイルが発行されています。
このdistフォルダの中身を作成したS3バケットにアップロードします。

```
$ aws s3 cp ./dist s3://**********/ --recursive --acl public-read --cache-control "max-age=604800"
```
(※xxxxxxxxxxは作成したバケット名に置き換えてください。)

S3の作成したバケットに、distフォルダの中身がアップロードされていることを確認しておいてください。
![Screenshot 2019-12-31 at 08.26.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/e1e712c9-259c-dd87-8abe-1dcb952047a8.png)

### S3バケットのバケットポリシー設定
作成したバケット > アクセス権限 > バケットポリシー と選択してゆき、
バケットポリシーエディターに以下を設定し、保存します。
(※xxxxxxxxxxは作成したバケット名に置き換えてください。)

```
 {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::xxxxxxxxxx/*"
        }
    ]
}
```

![Screenshot 2019-12-31 at 07.53.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/01d6cebd-598d-0864-4827-190a4ad949ec.png)
保存すると、このように、「このバケットにはパブリックアクセス権限があります」というメッセージが表示されます。(バケットにファイルが1つも存在しない場合、この処理は失敗します。)

### S3の Static website hostingを有効にする
作成したバケット > プロパティ > Static website hosting を選択し、以下を設定して保存します。
このバケットを使用してウェブサイトをホストする : チェックON
インデックスドキュメント : index.html
![Screenshot 2019-12-31 at 08.02.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/471f1359-84a2-6804-8e66-3da09fc3caf8.png)

### アクセスしてみる
Static website hostingの上部に記載されているエンドポイントにアクセスし、アップロードしたWebサイトが正しく表示され、Webアプリとして問題なく動作することを確認してください。

## あとがき
いかがでしょうか。
S3の静的サイト作成に対して、Amplifyのアプリ作成、最初の作成の手間こそさほど違いませんが、デプロイの手間の差は結構大きいと感じます。

S3静的サイトホスティングの場合、まずはアプリをビルドし、ビルドが完了するのを待ち、S3にアップロードする、という一連の作業が必要となります。
Amplify Consoleの場合、リポジトリにコミットするだけです。
ビルドを待つ必要もないし、別途アップロードする手間もない。エラーがあれば中止してくれる。

デプロイは何度もする作業ですので、この差は大きいのです。

独自ドメインの設定をするのも、Amplify Consoleのほうが圧倒的に楽なのですが、それについては別記事にしたいと思います。
AWS Amplify Consoleでビルド＆デプロイ

# AWS Amplify Consoleでビルド＆デプロイ

この記事は[サーバーレスWebアプリ Mosaic](https://mosaic.w2or3w.com "Mosaic")を開発して得た知見を振り返り定着させるための[ハンズオン記事](https://qiita.com/w2or3w/items/87b57dfdbcf218de91e2)の1つです。

以下を見てからこの記事をみるといい感じです。

* [Vue CLIで新規プロジェクト作成と、よくある雛形の実装](https://qiita.com/w2or3w/items/20d393560571f1531041)

## イントロダクション
VueのプロジェクトをAWS Amplify Consoleにより、プロビジョン→ビルド→デプロイ→検証します。
指定のリポジトリ&ブランチに対するコミットをトリガーにデプロイが走り、また、amplifyapp.comドメインにホストしてくれます。

## コンテンツ
### アプリの作成
AWSコンソール > Amplify > アプリの作成ボタンを押下します。

* From your existing code
ソースコードを管理しているリポジトリサービスプロバイダーを選択します。
ここではGitHubを選択します。
![Screenshot 2019-12-31 at 00.08.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/f39efc19-bccf-a0e5-11fa-1906d844fb64.png)

* リポジトリとブランチの選択
選択したリポジトリサービスプロバイダから、対象とするリポジトリとブランチを選択します。
![Screenshot 2019-12-31 at 00.08.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/104a1f6a-c698-e084-0ad6-18acf8841c96.png)

* ビルド設定の構成
入力されているものはそのまま、選択するものも既存のものを選択し、次へ。
Select a backend environment : 既存の環境でOK (work)
Select an existing service role : 既存のRoleでOK (amplifyconsole-backend-role)
![Screenshot 2019-12-31 at 00.16.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/abddb1d6-c760-3ab3-dcf2-905ccaa1eed7.png)

* 確認
内容を確認し、保存してデプロイボタン押下。
![Screenshot 2019-12-31 at 00.17.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/5047f548-6440-0251-2505-3b22cd0530fd.png)

### デプロイ
アプリの作成が完了すると自動的にデプロイが走り、プロビジョン、ビルド、デプロイ、検証、が順に実行されてゆきます。
なお、一度アプリを作成すると、次回からは指定したリポジトリの指定したブランチに対してコードコミット(プッシュ)するたびに、このデプロイのための一連の処理が開始されます。
![Screenshot 2019-12-31 at 00.18.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/953236ea-1249-69bf-2c07-6d938e73537c.png)
オールグリーンになったら完了です。
なお、ビルドエラーになったらデプロイされませんので安心ですね。

また、amplifyapp.comのサブドメインにホストまでしてくれますので、すぐにWebアプリを公開できてしまいます。

## あとがき
EC2へのホストに比べて、S3へのホストはだいぶ楽になったと思うのですが、Amplify Consoleはそれを超える楽さですよね。
比較のために、同じアプリをS3へホストする手順を[別の記事](https://qiita.com/w2or3w/items/8f4050482fee5a9307e0)にしようと、今思いつきました。

一度アプリをセットアップしてしまえば、あとはリポジトリへコミットするだけで勝手にビルドしてデプロイしてくれる楽さは病みつきになります。
今回は触れませんが、独自ドメインの割り当てもここで簡単にできてしまいます。

もう、インフラ担当、要らないですよね。(嘘です)
バリデーション

バリデーションとは不正なデータをデータベースに保存させないようにデータをチェックする事のこと。

バリデーションはモデルで設定する

```ruby
validates :カラム名, {条件}
```


条件内に
{presence: true}と記述する事で空の投稿を防ぐ事が出来る
{length: {maximum: 数値}}で最大文字数を指定出来る
{uniqueness: true} 重複したデータを保存出来なくする
インフラ更新で困った話（後編）

2019年が終わる前に記事を書けてほっとしています。アドベントカレンダーなんてお洒落なものに刺激を受けたので来年は勢力的に頑張りたいと思います。

この記事は【後編】です。お話はつながってますので気になる方はインフラ更新で困った話（前編）（[前回の記事](https://qiita.com/Easymode/items/255853ee7cc75fc3dec8
)）をご覧ください。

# 前回のおさらい 
インフラ更新の案件で「ファイアウォールをまたいだ通信が通らない」といった話でした。
前回は事象の説明で終わりましたが今回は原因と解説まで書きます。
先に言っておきますが「そのくらいわかるでしょ」とか「なんですぐ気づかないの？」といったご意見はおおいにその通りです。あくまで雑魚エンジニアが本番環境に臨んだ時のきょどり具合まで加味してご覧ください。

# 原因１：NAT設定の仕様
原因の１つは**製品のバグ**でした。
「ファイアウォールとは境界防御の製品です」とは前回述べたとおりです。
ネットワークとネットワークの境界に設置するものですから両ネットワーク間で通信する際はファイアウォールが**いい感じにやります**。

さて、NATとは。
（IP的に）異なるネットワーク間で通信をする際にIPアドレスを変換する機能のこと。
異なるネットワークに向けて通信するときIP体系が違うので通常は通信不可です。
が、NAT機能を使用するとネットワークの違いを吸収して（IPアドレスを変換して）通信することができます。
↓の例でいうとLAN1のHostAからLAN2の端末へ通信する際、IPアドレスを192.168.1.100から172.20.1.100に変換してくれるのです。この機能により異なるネットワーク間でも通信できます。

||LAN1|LAN2|
|:-----------------|:------------------:|:------------------:|
| **HostA** |192.168.1.100 |172.20.1.100|
| **HostB** |192.168.1.101 |172.20.1.200|
| **HostC** |192.168.1.150 |172.20.1.120|

↑の表みたいなものをNATテーブルといいます。
導入したファイアウォールでは**何故か一番下のルールが効いていませんでした。**（↑の例でいうHostCのとこ）
上手くいかないのでNATのテストをするべくルールを１つ追加したところさっきまで効かなかったHostCのルールが効くようになりました。
終わって聞いた話では、前回（5年前）も同じことが起こったとのこと。GUIで設定したものが反映されなかったらしい（もっと早く聞きたかった
解決法としては、CUIで設定することorダミーのルールを一番下に入れることでした。

# 原因２：ポリシー設定ミス
※NATも「ポリシー設定」に含まれますが今回はちょっと書き分けます。

こっちはしょうもない原因です。
片方のネットワークからの通信を全拒否するよう設定していました。
でも間違いなく全許可の設定はしたはずなんだけど・・・
なんかの拍子に戻ったのかな？原因１も設定が反映されないことが根本的な話だったわけだし・・・
触っていたときには再現しなかったので何とも言えませんが、「設定したはずのものができていない」は十分疑うべき対象だと思いました。

# おわりに
長くなっちゃたけど新年会が楽しみですね！
小田急バスの位置情報を取得してみた

###背景
ラズベリーパイでLCDを付けましたが（別記事にする予定）、
朝のバスが遅れたり、たまにオンタイムだったりと
いつ玄関を出るか悩んでいたので、
[小田急バス運行情報](https://odakyu.bus-navigation.jp/wgsys/wgp/search.htm)
をスクレイピングして、表示することに。

###概略
Beatiiful Soupを使って、スクレイピングしました。
到着予想時刻をとるために、単なるCSSセレクターでは
どうしてもうまくいかず、以下のような力技？の
とても汚いコードになってしまいました。

###コード
```python
from bs4 import BeautifulSoup as BS
import urllib.request as req

def busstop():
    url="https://odakyu.bus-navigation.jp/wgsys/wgs/bus.htm?tabName=searchTab&selectedLandmarkCatCd=&from=[乗るバス停］&fromType=1&to=［降りるバス停］&toType=1&locale=ja&fromlat=&fromlng=&tolat=&tolng=&fromSignpoleKey=&routeLayoutCd=&bsid=1&fromBusStopCd=&toBusStopCd=&mapFlag=false&existYn=N&routeKey=&nextDiagramFlag=&diaRevisedDate=&timeTableDirevtionCd="
    res=req.urlopen(url)
    soup=BS(res,"html.parser")
    #data=soup.select("#buslist > div > div>table:nth-of-type(2)")
    result=[]

    table=soup.select_one("table:nth-of-type(2)")

    tr_list=table.find_all("tr")

    current=0
    for tr in tr_list:
        result_row=[]
        td_list=tr.find_all(["td","th"])
        if current<4:
            for td in td_list:
                cell = td.get_text()
                result_row.append(cell)
                if current==3:
                    result_list=[]
                    result_list=result_row
                current=current+1
        else:
            pass

    final_arrange_list=[]

    if final_arrange_list==None:
       return("NA")
    else:
       final_arrange_list=result_list[1].split(' ')
       return(final_arrange_list[1])
       print(final_arrange_list[1])
```

ちなみに呼び出し部は

```Python
   bustime_dt=datetime.strptime(busstop(),'%H:%M')
   nowtime_dt=datetime.strptime(time.ctime(time.time()),'%a %b %d %H:%M:%S %Y')
   next_bus_time=bustime_dt-nowtime_dt
   payload7="Next bus in "+str(next_bus_time.seconds/60)
   payload8="Next bus@ "+str(busstop())
   print(payload7)
   print(payload8) 
   lcd_string(payload7, LCD_LINE_1)
   lcd_string(payload8, LCD_LINE_2)
```
となかなか不格好です。
バスの到着予想時刻には、時間分しかないので、
単純にUNIX時間から引くと、年数がマイナスになるのですが、
どうせ分しか使わないので、割り切り。

いずれももう少しうまく書けるのだろうけれど。。
とりあえず動けばということで、割り切り。
サーバーレスWebアプリを開発するためのCloud9環境構築

# サーバーレスWebアプリを開発するためのCloud9環境構築

この記事は[サーバーレスWebアプリ Mosaic](https://mosaic.w2or3w.com "Mosaic")を開発して得た知見を振り返り定着させるための[ハンズオン記事](https://qiita.com/w2or3w/items/87b57dfdbcf218de91e2)の1つです。

##イントロダクション
Cloud9で開発してまして、なので、その環境構築からはじめます。
VueのWebアプリ、Lambda用のPython(3.6)、などを開発・ビルドできるようにします。

## コンテンツ

### AWS Cloud9 環境の新規作成
AWSマネジメントコンソール > AWS Cloud9
![Screenshot 2019-12-22 at 21.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/37b15543-5a7c-ca57-034f-c38cf24562c8.png)

- Create environmentボタンを押下。
  - Step1 : Name environment  
    Name : 適当な名前を設定する。
  - Step2  
    Environment Type : EC2を選択。  
    Instance Type : t2.microで充分。  
    Platform : Amazon Linux  
    Cost-saving setting : After 30 minutes(default)  
  - Step3  
    ReviewをチェックしてCreate environmentボタンを押下
![Screenshot 2019-12-22 at 21.46.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394775/1f95001a-1ddb-da53-2a05-943d476baabb.png)

### Vue CLI 3のインストール

```
$ npm install -g @vue/cli@3.11.0
$ vue --version
@vue/cli 3.11.0
```
@3.11.0を指定しないと最新版が入ります。
2019年12月中旬現在、リリースされたばかりの4が入りました。
4でも問題ないと思いますが、今回はハンズオンということで、念の為バージョンを指定してインストールします。

Vue CLI 3によるプロジェクトの作成は[別記事](https://qiita.com/w2or3w/items/20d393560571f1531041)としました。

#### cloneしてきたプロジェクトをビルドするために
Vue CLIで作成したプロジェクトをクローンしてもってきてビルドしようとすると、以下のようなエラーとなりました。

```
$ npm run build

> sample_vue_project@0.1.0 build /home/ec2-user/environment/sample_vue_project
> vue-cli-service build

sh: vue-cli-service: command not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! sample_vue_project@0.1.0 build: `vue-cli-service build`
npm ERR! spawn ENOENT
npm ERR! 
npm ERR! Failed at the sample_vue_project@0.1.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/ec2-user/.npm/_logs/2020-01-01T02_04_19_354Z-debug.log
```
これを解決するためには、以下のコマンドを実行してください。

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



### Python 3.6のセットアップ
2019年10月頃、Cloud9の標準インストール済みPythonのバージョンは2.7でした。
Python2のサポート終了が2020年1月に迫っているということで、2.7から3.6に変更する手順について書こうと思っていたのですが。2019年12月中旬現在、すでにCloud9の標準インストール済みPythonのバージョンが3.6.8になっていました。
ありがとうございます。助かります。

と、思いきや、pipの参照Pythonが2.7のままですね、、。何ででしょうか、、。罠でしょうか、、。
以下のように3.7を参照するよう変更しておきましょう。

```
$ pip --version
pip 9.0.3 from /usr/lib/python2.7/dist-packages (python 2.7)
$ sudo update-alternatives --config python

There are 2 programs which provide 'python'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/bin/python2.7
   2           /usr/bin/python3.6

Enter to keep the current selection[+], or type selection number: 2
$ pip --version
pip 9.0.3 from /usr/lib/python3.6/dist-packages (python 3.6)
```

## あとがき
ワタシのプライベート開発環境ですが、メモリ4GBのChromebook(5万円)と、t2.microのCloud9となっています。
決して快適な環境ではないのですが、これはある意味で縛りというか、制約というか、不自由を楽しんでいるというか、まぁそんな感じです。

しかしCloud9はいいですね。
すぐに開発を始められるし、インターネットとWebブラウザがあればどこからでもどのPCからでもアクセスできる。

ハンズオンの環境はCloud9で決まりですね。
Terraformを用いたSageMaker Endpointの構築

## はじめに

[こちらのブログ](https://aws.amazon.com/jp/blogs/news/build-a-serverless-frontend-for-an-amazon-sagemaker-endpoint/)を参考に以下のようなSageMaker EndpointをInvokeするEndpointを構築してみました。

<img width="652" alt="sagemaker_endpoint.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295829/4f893d6b-1728-eaeb-bfea-526accc6d552.png">

API Gateway EndpointからSageMaker Endpointを呼び出すLambda関数をトリガーし、予測を行います。

コードはGitHubに上げてあります。
https://github.com/suaaa7/iris-data-endpoint

## 動作環境

- macOS Mojave (10.14.6)
- Terraform (0.12.6)

## ファイル構成

```
$ tree
.
├── LICENSE
├── Makefile
├── README.md
├── config.tf
├── main.tf
├── modules
│   ├── apigateway
│   │   └── main.tf
│   ├── iam
│   │   └── main.tf
│   ├── lambda
│   │   ├── main.tf
│   │   ├── src
│   │   │   └── lambda_function.py
│   │   └── upload
│   │       └── lambda_function.zip
│   └── sagemaker
│       └── main.tf
├── request.sh
├── test.csv
└── variables.tf
```

本当は`main.tf`を

- `main.tf`
- `variables.tf`
- `outputs.tf`

に分けるべきだと思うのですが、分けるほどのコード量ではなかったので、`main.tf`にまとめてしまっています。

## SageMaker Endpointについて

> 推論用インスタンスを立てるために設定が必要な項目はModel・EndpointConfig・Endpointの3つです。
ModelはどのS3のデータをロードするのかと、どのECRのイメージを利用するのかを保持します。

今回は、Irisデータセットのサンプルとしてすでに構築してあるモデル、Dockerイメージを利用します。

- Location of model artifacts
    - `s3://aws-machine-learning-blog/artifacts/decision-trees/model.tar.gz`
- Location of inference code image
    - `305705277353.dkr.ecr.us-east-1.amazonaws.com/decision-trees-sample:latest`

### 参考

TerraformでSageMakerのデプロイ・モデルの更新をする
https://medium.com/mixi-developers/terraformでsagemakerのデプロイ-モデルの更新をする-c1340fa0340d

## API Gateway + Lambdaついて

API GatewayとLambdaのモジュールをまとめるか悩みましたが、分けてみました。
このあたりのベストプラクティスが分かっていないので、毎回悩みます。

### 参考

Serverless Applications with AWS Lambda and API Gateway
https://learn.hashicorp.com/terraform/aws/lambda-api-gateway

## 動作確認

### 初期化

```
$ terraform init
```

### 構築

SageMaker EndpointのCreatingには10分ほどかかります。

```
$ terraform apply
```

### 予測

csvには以下のような推論データを含めます。

- Sepal Length
- Sepal Width
- Petal Length
- Petal Width

```csv:test.csv
10,10,10,10
```

`<base_url>`には、TerraformのOutputsに出力される`base_url`を指定してください。

```
$ curl -X POST -H "Content-Type: text/csv" -d "@test.csv" <base_url>
{"code": 200, "variant": "variant-a", "prediction": "virginica"}
```

### 後片付け

```
$ terraform destroy
```
アニメーション再現の考え方

アニメーションを再現する際の第一歩として、動きの分解について考えていこうと思います。
## 動きの分解
アニメーションを再現する際に、まず重要なことが「動きの分解」だと私は考えます。
例として以下のアニメーションを再現してみます。
![アップロードの動き.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559889/a94cf4cd-0018-7608-812d-cba1e8bf27ef.gif)

このアニメーションの動きを分解すると、`帽子が震える`→`帽子が昇って消える`→`帽子が降ってくる`の3つになります(分解の粒度は個人差があります)
この3つの分解の考えを元にアニメーションを再現していきます。

再現してみました。細かい部分はまだ再現できていないですが大まかな部分は再現できたと思います。所要時間は3分です。
![アップロードの動き(作成).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559889/6764e0c3-db49-f0e5-9c18-b0699178ea1c.gif)


動きの分解さえ考えてあれば、迷うことなくサクサクとアニメーションを作成できます。
アニメーションを作成する際は、動きの分解についてを頭の片隅においておくと役に立つかもしれません。
Stackdriver Kubernetes Engine Monitoring を試す【基本編】

2019年も本日で最後となりました。

年末も、趣味でKubernetesやGKEで遊んでいるわけですが、ちょっとあまり触れてなかったGCPの監視ツールであるStackdriver Monitoring をつかって、GKEのリソース管理を試してみました。

## Stackdriver Monitoring とは

Google Cloudで提供されているモニタリング（監視）ツール。AWSでいうCloudWatchに相当するツール。もともとは、Stackdriverという会社が提供していたものであったが、2014年にGoogleが買収して、Google Cloudの中に組み込んだプロダクト。

* インスタンスのCPU使用率、メモリ使用率といったメトリックス
* インシデント管理
* アラートを飛ばす
* ダッシュボード
* プロジェクト単位での管理

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/9bb094a9-62a1-3204-450a-20b0af2f4d96.png)

## Stackdriver Kubernetes Engine Monitoring を使い方

まずは、前提条件として、GKEクラスタの設定で「Stackdriver Kubernetes Engine Monitoring」が有効になっていることが必要です。クラスタを構築すると、デフォルトで有効になっているが、念の為にご確認ください。

![stackdriver02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/aff9cc55-a808-3502-aee4-93f27817c0e8.png)

Stackdriver Monitoringの「モニタリングの概要」で、「Resource dashboards」の「Kubernetes Engine(new）」をクリックすると、「Stackdriver Kubernetes Engine Monitoring」の画面が立ち上がります。

![stackdriver01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/0f421232-997d-0d32-00e3-13e2f7fd6b81.png)

Kubernetes Engineでは、Namespace単位でCPU使用率、メモリ使用率が可視化できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/fb16babc-f7c1-2109-2cf2-f9540e10a38e.png)

Namespaceをドリルダウンをすると、コンテナ単位でのCPU使用率、メモリ使用率も確認することが可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/6b41d62f-9b31-b746-d946-3cffa415bc76.png)

## 稼働時間監視とアラート設定

Stackdriverを使ってWebアプリの死活監視、稼働時間監視といったことももちろんできます。例えば、GKE上に構成したRedmineの稼働時間をチェック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/0c9693e6-c030-3079-dd84-49e69759b426.png)

下記スクリーンショットのように設定することで、↑の画面のようなダッシュボードを作成することもできます。

![stackdriver03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/4e2a7afb-2a15-d18a-75a2-50fa5049b716.png)

また、アラート設定を行うと、Redmineのサービスがダウンしたときに、以下のようなグラフやインシデント管理を行うことができるようになります。

![stackdriver04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/afabc251-68fc-d07d-99d0-af0bf8221cd9.png)

これらのアラートは、メールはもちろんのこと、SlackやWebhookで通知させることも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92726/1b3da0e6-e857-9fac-ddd0-76978fe662c0.png)

簡単にStackdriver Kubernetes Engine Monitroingを紹介させていただきました。次回は、もう少し深い部分で監視できるかどうかを試したいと思います。

それでは、みなさんよいお年を。
空判定

```py
a = 0
if a:
    print('空ではありません。')
else:
    print('空です。')
```
a = 0 や a = '' や a = () や a = [] や a= {}の様に空であれば、
if a が false となり、
elseが以下が実行される。

逆に、
a = 1002 や a = 1 や a = (1, 2) や a= [1, 3, 5] や a = {戦士:カイン, 魔法使い:レン}の様に値が入っていれば、
if a が True となり、
print('空ではありません')が実行される。
TEE 体験入門 

IoTやブロックチェーンで何かと便利に使われるセキュリティ機能、Trusted Execution Environment(TEE) ですが、Azureが2019/12/31現在でPaaSとしてサポートしているそうなので試してみましょう。現状ではAzureとIBM、AlibabaなどがTEE(Intel SGX)をサポートしており、AWSとGCPのインスタンスはSGX利用可能になっていないようです。

基本的にIntelの第６世代以後のコアには入っている機能らしいですが、マザーボードの対応等の違いもあり、実行できる環境はまだ少ないです。
自分の実機で使えるかどうかは次のように調べられます。


```
$ git clone https://github.com/ayeks/SGX-hardware.git
$ cd SGX-hardware
$ gcc test-sgx.c -o test-sgx
$ ./test-sgx
```
出力で"sgx available"と"sgx supported"がどちらも”１”だと利用可能な状況です。

本編は「クラウドでのTEEというのはこういうものである」というのを体験するためのものであり、一切の概念・システムの説明は致しません。概念理解はこちらをどうぞ
https://qiita.com/Cliffford/items/2f155f40a1c3eec288cf

ではクラウドでTEEを実行できるConfidential Computingを使ってみましょう。
https://azure.microsoft.com/ja-jp/solutions/confidential-compute/

なにやら全く新しい世界が広がってるかのようですが、身構えることは一つもありません。単にSGXがサポートされてる仮想マシンが作れるだけです。

設定画面　https://portal.azure.com/
で
「Confidential Compute VM Deployment」を検索し、MarketPlaceの欄で見つけられるはずです。

デプロイが終わったら、仮想マシンの設定でネットワークを開いてください。


![無題のプレゼンテーション (10).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230572/3841f3be-b198-60f7-255c-6ff4b84d74c1.jpeg)

最初は下３つのルールしかないと思いますが、受信ポートの規制を追加するを押してください。
これは、初期設定でAzure内からVMへののアクセスのみOK、VMからインターネットへのアクセスは全部OKになっているので、sshのみIPを指定して入れるようにしてあげます。

![無題のプレゼンテーション (11).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230572/4a173fe4-b72d-891c-7f1a-cb01bba5a31c.jpeg)

ソースIPをVPNのものか限定されたあなたのIPアドレスにし、プロトコルをTCPに、優先度を65000より小さい数字にして下さい。これによって上記のポリシーを上書きできます。

では仮想マシン設定　→　概要　→　接続へ移動しsshのコードをCLIへコピペして実行して下さい。

繋がったら次の通りに実行します。

```
$ sudo cp -r /opt/openenclave/share/openenclave/samples/ .
$ sudo chown -R 'あなたのUserネーム':'あなたのUserネーム' samples/
$ source /opt/openenclave/share/openenclave/openenclaverc
$ cd samples/helloworld
$ make build
$ make run

```