OmniAICreator/Qiita-1.07M huggingface dataset:
【AWS】AWSにおける高可用性の定義

# AWSにおける高可用性の定義

## AWSにおける可用性向上策

- **Design for Failure**（障害発生を前提としたシステム構築）
- 障害を回避する設計を行うのではなく、**障害が発生してもシステムが継続できるように設計すること**

### ◉可用性向上のポイント
#### ◎リソースを冗長化する
- **単一障害点（SPOF：Single Point of Failure）**をなくすことが重要
- **内部的に冗長化**しているAWSサービスと**ユーザー側で冗長構成を設計**しなければいけないAWSサービスがある

:::note info
単一障害点
障害が発生するとシステム全体が使用不能になる／システムの動作結果の正しさを保証できなくなる箇所のこと
:::

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

#### ◎地理的に冗長化する
AWSの管理画面から設定を行うだけで地理的に離れた場所で即座にリソースを用意することができる

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


#### ◎システムを疎結合で構成する
- システムやコンポーネントを**独立させることが重要**
- システムの一部分が故障したり動作不良を起こした場合、その部分だけを切り離して復旧作業を行うことが可能
- システム全体への影響を軽減することができる

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

:::note info
・ELBと利用することで、エンドポイントから複数のEC2インスタンスに処理分散できるため、インスタンス同士が干渉しない
・SQS（Simple Queue Service）を利用することで、大量処理の必要がある場合でもSQS側でバッファリングしてインスタンスへ処理を並列化できる
:::

#### 参考
https://aws.amazon.com/jp/architecture/well-architected/?wa-lens-whitepapers.sort-by=item.additionalFields.sortDate&wa-lens-whitepapers.sort-order=desc

https://docs.aws.amazon.com/ja_jp/wellarchitected/latest/reliability-pillar/availability.html
API Gatewayに独自ドメインを適用

## はじめに

備忘録的なメモです。大まかな手順のみ記載します。
作成済みのAPI Gatewayに独自ドメインを適応する方法です。

## 手順

#### サブドメインの登録

Route53でサブドメインのホストゾーンを追加します。現在所有しているドメインが、example.comであればapi.example.comみたいな。
ホストゾーンを追加するとNSレコードが作成されるのでこれをコピーします。
次に親となるホストゾーンを開きNSレコードを追加し、先ほどコピーしたネームサーバーたちを追加します。
稼働中のサーバーなどがあればAレコードを追加するなどして動作確認。

#### 証明書の取得

Certificate Managerを開き証明書のリクエストを行います。
ドメイン名を入力する欄に先ほど設定したサブドメインを入力します。api.example.comみたいな。

検証保留中の表示とともにRoute53でのレコード作成ボタンが表示されるので押します。まもなくステータスが発行済みに変わります。ホストゾーンの設定がおかしいと検証保留中のまま変わらないので設定を見直します。

#### カスタムドメイン名設定

API Gatewayを開きカスタムドメイン名の画面を表示します。作成ボタンを押して表示される画面で今回作成したサブドメインを入力します。api.example.comみたいな。エンドポイント設定にはエッジ最適化を選びます。
ACM証明書に上記で取得した証明書を指定します。
作成されたら同画面内のエンドポイント設定でAPIマッピングを選択します。
新しいマッピングを追加し、目的のAPI、ステージを指定します。
API Gateway ドメイン名としてCloudFrontドメイン名が表示されるのでコピーします。xxxxxxxxxx.cloudfront.netみたいな。

#### Aレコード追加

上記のCloudFrontドメイン名のエイリアスを作成します。Route53でサブドメインのホストゾーンを開き、レコード名は空欄、エイリアスのスイッチをオンにするとエンドポイントが選択できるので、上記のCloudFrontドメイン名を指定。api.example.comのAレコードで値がxxxxxxxxxx.cloudfront.netとなれば良い。

反映されるまで多少時間がかかる模様。しばらくするとapi.example.comにアクセスできるようになる。

## 注意

カスタムドメイン名作成でCloudFrontドメイン名が表示されるがアクセスするとForbiddenとなる。

## 参考文献

以下のサイトを参考にさせていただきました。感謝です。
https://dev.classmethod.jp/articles/amazon-api-gateway-integrates-acm/
https://dev.classmethod.jp/articles/api-gateway-custom-domain-ssl/
2021年8月にRuby on Rails チュートリアルの環境構築

2021年8月にRuby on Rails チュートリアルの環境構築
=============================

[Ruby on Rails チュートリアル](https://railstutorial.jp/chapters/beginning?version=6.0)を2021年8月に始めようとした。
いろいろとつまずいたので私の解決までの思考回路をメモする。

## 要約
最新のRubyを使って`bundle update`をやろうとしたら無理だった。
いい感じに低いバージョンのRubyを使えばうまくいった。

## 注意
- 私は、情報系の大学院生なので、現場のことなど知らないです。
- 私はOracle VM VirtualBox上にインストールしたUbuntuで作業しています。つまり、うまくいかなかったらOSのインストールからやり直せばいいと思ってます。本番環境でマネをしないようにしてください

## 新しいRubyでやろうとした話
Rubyの最新版をインストールした。

```bash
$ rvm install 3.0.2
```

Railsチュートリアルの言うとおりにコマンドをポチポチした。
yarnのインストールは自分で調べろって書いてあったから、公式の言うとおりにインストールした。

```bash
$ gem install rails -v 6.0.3
$ sudo apt install npm
$ sudo npm install -g yarn
$ yarn set version latest
$ mkdir environment
$ cd environment/
$ rails _6.0.3_ new hello_app
```

Gemfileを編集して`bundle install`

```bash
$ bundle install
Fetching gem metadata from https://rubygems.org/............
You have requested:
  listen = 3.1.5

The bundle currently has listen locked at 3.6.0.
Try running `bundle update listen`

If you are updating multiple gems in your Gemfile at once,
try passing them all to `bundle update`

```

失敗！

チュートリアルによると、エラーメッセージを見て解決するよう書いてある。
エラーメッセージには`Try running bundle update listen`と書いてある。

やってみるか

```bash
$ bundle update listen
Fetching gem metadata from https://rubygems.org/............
You have requested:
  spring = 2.1.0

The bundle currently has spring locked at 2.1.1.
Try running `bundle update spring`

If you are updating multiple gems in your Gemfile at once,
try passing them all to `bundle update`

```

次のTry runningは`bundle update spring`

```bash
$ bundle update spring
Fetching gem metadata from https://rubygems.org/............
You have requested:
  listen = 3.1.5

The bundle currently has listen locked at 3.6.0.
Try running `bundle update listen`

If you are updating multiple gems in your Gemfile at once,
try passing them all to `bundle update`

```

これ、さっき見た！無限ループじゃん！！

でいろいろQiitaの記事を覗いたけど、無理だった。（バージョンの指定を`~>`に変えたら良いとか書いてあった。マイナーバージョン程度ではどうにもならないのだった。

## 考察と解決

仮説を立てた

- もしかして、Rails 6.0.3にとってRuby 3って知らない子なんじゃ？？
- つまり、Rails 6.0.3はRuby 3と相性が悪いんじゃないか？


そこで、Rails6.0.3ができたとき、Rubyの最新版っていくつだったのか調べた。

以下のURLからRails 6.0.3は2020年5月6日にリリースされたことがわかった。

https://weblog.rubyonrails.org/2020/5/6/Rails-6-0-3-has-been-released/

2020年5月ってRubyのバージョンはいくつなのか以下のURLで調べた

https://www.ruby-lang.org/ja/news/2020/

2.7.1が最新だったことがわかった。
2.7系だと今は2.7.3が最新なので、2.7.3でも行けるんじゃね？
だめだったら、やりなおせばいいや！

というわけで、Hello_appをぶっ壊し、Rubyを入れ直す（rvmでバージョンを変えるだけ）

## うまく行った話
```bash
rm -r *
$ rvm install 2.7.3
$ gem install rails -v 6.0.3
$ rails _6.0.3_ new hello_app
$ cd hello_app
$ bundle install
$ bundle update
$ bundle install
```

`bundle update`したあとなら`bundle install`うまくいきました

## まとめ
他のソフトウェアに依存するようなソフトウェアを使うときは、そのソフトウェアがリリースされた頃のバージョンにそろえてあげないといけない
ダンプ・リストア・マスキング[SQL]

### この記事の目的

実務開発において、mysqlのデータをマスクする、という実装の一部に携わりました。その際に利用したコマンドを記録しておきます

### マスキングとは

「データをマスクする」というのは、本番環境のデータにおいて、個人情報などのデータを開発環境で見えなくすることです。できる限り本番に近い、だけど個人情報などが保護されているデータ、を扱うために行います。それらのデータを扱う目的や方法などは以下を参考にしました。

具体的な方法や手順は異なりますが、参考記事などを拝見したところ、以下の流れでデータをマスキングしています。

1. データをダンプ
2. データをマスク
3. データをリストア

今回私が関与させていただいたのは、マスクする為のSQL文を作成する部分です

https://pokosho.com/b/archives/2753

https://tech.tabechoku.com/entry/2018/11/29/113244

### マスクするまでのコマンド

```sql
-- dumpする
$ mysqldump -h localhost -u root database_name > bakup/$(date "+%Y%m%d").sql

-- restoreする
$ mysql -h localhost -u root -D database_name < bakup/$(date "+%Y%m%d").sql

-- maskする
$ mysql -h localhost -u root database_name < ~/App/masking.sql
```

ちなみに`$(date "+%Y%m%d").sql`により、ファイル名が年月日（ex. 20210802.sql）と自動命名される

### マスクするSQL文（スクリプトで自動化する場合

```sql:~/App/masking.sql
use table_name;

-- users
UPDATE users SET 
	username = concat('username', id),
	email = concat('email', id),
	phone = '00000000000';
```

### 参考

https://qiita.com/PlanetMeron/items/3a41e14607a65bc9b60c

https://qiita.com/macer_fkm/items/d920ff77f0f5ae5484f9
[Rails]予約語一覧[a~g]→指摘を頂いたので修正します

# はじめに
本記事は、Railsの予約語一覧を記述しています。
過去に予約語に指定されている単語をカラム名でたくさん指定しまい、
エラーが多発しました。
インプット及びアウトプットを兼ねて記述していきます。

# 予約語とは
プログラミングにて人工言語の仕様に定められている、
開発者が識別名として`利用できない`文字列のこと。

```
予約語に指定されている単語は変数名や関数名などに使用することはできない。
```

# 予約語一覧(注意すべき単語を記述しています)
|頭文字|単語||||
|-|-|-|-|-|
|a|action|all|alter|and|any|
||are|array|as|at||
|b|before|begin|between|bit|
||both|by|||
|c|call|case|change|check|
||class|close|collect|column|
||commit|condition|config|connect|
||continue|count|create|cube|
||current|*「current_」の予約語がかなりあるため注意|cycle||
|d|date|datetime|day|*「day_」の予約語もやや多いです|
||default|delete|desc|describe|
||destroy|dir|disconnect|div|*「dlurl〜」も多いです|
||do|double|drive|drop|
||dual|dynamic|||
|e|each|else|elseif|end|
||env|errors|escape|every|
||except|exec|exists|exit|
||exp||||
|f|false|fetch|file|first|
||for|foreign|format|found|
||free|from|full||
|g|gem|get|go|goto|
||group||||

# 終わりに
少しずつでないと予約語を覚えることができないため、
分割して紹介します。
次回以降[h~n][o~u][v~z]に分けて投稿いたします。

引き続き明日も頑張ります！！

参考サイトは[こちら](https://www.trail4you.com/TechNote/Ruby/Rails_keyword_list.html)です。
Crystal で AtCoder(Log #4)

#Easy_4

https://atcoder.jp/contests/sumitrust2019/tasks/sumitb2019_b

$⌊X×1.08⌋=N$ を満たす整数$X$を求める。$N$は1から50000での整数。
$O(1)$でもいけるが多少の紛れが生じる。
$N$から$X$を求めるより$X$から$N$を求める方が遥かに容易。
$N$が大きければ二分探索法の出番だが、今回の制約なら全探索で十分。
$X$を1から50000まで見ていって、解が見つかれが途中で終了する。

##プログラムの終了 `exit`

Crystalには`return`文があるが、メインプログラムには使えないとのこと。
`exit(status)`で終了できる。正常終了なら`exit(0)`。デフォルトで`status = 0`なので`exit`でよい。[^1]
`each`は`(a..b).each {|i| ... }`で他言語のfor文のような事が出来るのだが、blockとかyieldとか調べていくと味わい深い[^2]。実質的には1から50000までの数を順々に`{}`内に投げて、`{}`内では`x`で受け取って処理している。

```crystal:sumitrust2019_b.cr
n = read_line().to_i
(1..50000).each { |x|
  if x * 108 // 100 == n
    puts x
    exit
  end
}
puts ":("
```

#Easy_5

https://atcoder.jp/contests/abc121/tasks/abc121_b

+ M個からなる数列のセット$\\{\\{A_{i1}, A_{i2}, …, A_{iM}\\}, i=1...N\\}$

+ 数列$\\{B_1, B_2, …, B_M\\}$

+ 定数$C$

が与えられる。

$A_{i1}B_1+A_{i2}B_2+…A_{iM}B_M+C>0$を満たすセットはいくつあるか。

## n回ループ `times`

`n.times do`...`end`でn回ループが実現する。
`n.times do |i|`...`end`で何回目のループかを取得することも出来る。0-indexだが。

## 複数を組み合わせる`zip`

`zip`は２つ以上の配列(正確には`Iterator`あるいは`Enumerable`)に使えるメソッド。
`a.zip(b)`とすると、`a`と`b`のそれぞれ先頭から一つずつ順にとってきてタプルの配列にする。
`Iterator`の時はlazyに、`Enumerable`の時はeagerlyな挙動なのか。

```crystal:zip.cr
a = 1..4; b = 2..5; c = 3..6
p! a.zip(b, c) # => [{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}]
```

`zip`の括弧内の要素が余るのは問題ないが、足りないとエラーなる仕様。

```crystal:zip.cr
a = 1..3; b = 2..5; c = 3..10
p! a.zip(b, c) # => [{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}]
p! b.zip(a, c) # => Unhandled exception: Index out of bounds (IndexError)
```

## タプルも波括弧`{}`

`a.zip(b)`は`[{ai0, b0}, {ai1, b1},... , {aim, bm}]`の形の配列を生成する。`{x, y}`はタプルと呼ばれる表現で、他言語では丸括弧`()`を用いるものも多いがCrystalでは波括弧`{}`を用いる。
`{x, y}`の形のタプルはクロージャ内では`|x, y|`という記法で受けることができる。


## 後置`if`

`if cond do_something`は`do_something if cond`と書くことができる。`do_something`が短ければ(文頭と`if`が一つの視界に入る程度なら)、分かりやすい。

## AC例
```crystal:abc121_b.cr
n, m, c = read_line.split.map(&.to_i)
b = read_line.split.map(&.to_i)
ans = 0
n.times do
  a = read_line.split.map(&.to_i)
  ans += 1 if a.zip(b).map{|x, y| x*y}.sum + c > 0
end
puts ans
```


[^1]: https://crystal-lang.org/api/0.33.0/toplevel.html#exit(status=0):NoReturn-class-method
[^2]: https://ja.crystal-lang.org/reference/syntax_and_semantics/blocks_and_procs.html
Z3Py　例題　ビンパッキング問題

# 問題
4人で8個の荷物を運ぶとする． 各荷物の重さは 3.3kg, 6.1kg, 5.8kg, 4.1kg, 5.0kg, 2.1kg, 6.0kg, 6.4kg である (合計は 38.8kg)． 各自の運ぶ荷物の重さの合計が 11kg 以下になるように荷物を割り当てることはできるか?([Wikipedia:ビンパッキング問題](http://ja.wikipedia.org/wiki/%E3%83%93%E3%83%B3%E3%83%91%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0%E5%95%8F%E9%A1%8C))


# 回答
```example_bin_packing.py
from z3 import *

loads = [3.3, 6.1, 5.8, 4.1, 5.0, 2.1, 6.0, 6.4]
X = [[Int("x_%s_%s" % (i, j)) for j in range(len(loads))] for i in range(4)]

s = Solver()
s.add([And(0 <= X[i][j], X[i][j] <= 1)
      for i in range(4) for j in range(len(loads))])
# 各荷物は、誰か1人が運ぶ
s.add([Sum([X[i][j] for i in range(4)]) == 1 for j in range(len(loads))])
# 各自の運ぶ荷物の重さの合計は11kg以下
s.add([Sum([loads[j]*ToReal(X[i][j])
      for j in range(len(loads))]) < 11 for i in range(4)])

print(s.check())

m = s.model()
for i in range(4):
    sum = 0
    for j in range(len(loads)):
        sum += loads[j]*m[X[i][j]].as_long()
    print("*", i, sum)
```
出力

```terminal
sat
* 0 10.8
* 1 8.1
* 2 9.7
* 3 10.2
```

## 解説


# 他の例題
[Z3Py個人的ポータル](https://qiita.com/Ganesha/items/7a606ffc8a7c2504c143) へ
AtCoderログ：0055 - ABC 067 B

# 問題

https://atcoder.jp/contests/abc067/tasks/abc067_b

## 問題文
> すぬけくんは $N$ 本の棒を持っています。$i$ 番目の棒の長さは $l_i$ です。
> すぬけくんは $K$ 本の棒を選んでつなげて、ヘビのおもちゃを作りたいです。
> ヘビのおもちゃの長さは選んだ棒たちの長さの総和で表されます。ヘビのおもちゃの長さとしてありうる長さのうち、最大値を求めなさい。

## 制約
> ・$1 \le K \le N \le 50$
> ・$1 \le l_i \le 50$
> ・$l_i$ は整数

## 収録されている問題セット
- [AtCoder に登録したら次にやること](https://qiita.com/drken/items/fd4e5e3630d0f5859067) ([第06問類題](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-6-%E5%95%8F--abc-088-b---card-game-for-two-200-%E7%82%B9))

# 回答
# 回答1 (AC)
おもちゃの長さは選んだ棒の長さの総和になるので、おもちゃの長さを最大にするには長い方から $K$ 本を選べば良いです。処理としては、それぞれの棒の長さを配列 l() に受け取った後、長い順 (降順) にソートし、最初の k 本を選んだときの長さの総和を出力すれば良いでしょう。コードは以下のようになりました。

```C++:abc067b-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n, k;
  cin >> n >> k;

  vector<int> l(n);
  for ( int i=0; i<n; i++ ) {
    cin >> l.at(i);
  }

  sort(l.rbegin(),l.rend());

  int sum = 0;
  for ( int i=0; i<k; i++ ) {
    sum += l.at(i);
  }
  cout << sum << endl;
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc067/tasks/abc067_b/editorial) → [公式解説](https://img.atcoder.jp/arc078/editorial.pdf)
回答と同じ方針でした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0054 - 「AtCoder Beginners Selection」のまとめ](https://qiita.com/RoadLynton/items/7f43c4d2ddf17c2d61ae)
AWS環境のEC-CUBE4にてgmailでメール送受信を行う方法

ECサイト必須機能のメール送受信を**gmail**で設定する方法です。
gmailの場合、**AWS側の設定が不要**なため容易に利用することができます。

###1.安全性の低いアプリの許可
①google→画面右上のgoogleアプリ→アカウント
②左ペイン→セキュリティ→**安全性の低いアプリのアクセス**→アクセスを有効にする

###2.２段階認証→Appパスワード作成
①安全性の低いアプリの許可と同様のセキュリティ画面へ
②Googleへのログイン→**２段階認証プロセス**→オン
※ここで**Appパスワードが**発行されるのでコピーしておく

###3..envファイルの編集
EC-CUBEインストールディレクトリ直下にある.envファイルを以下の内容で編集する
MAILER_URL=gmail://**メールアドレスを入力**:**Appパスワードを入力**<span>@</span>localhost?encryption=tls&auth_mode=oauth
[PHP]foreachで各要素の値を更新する時はkeyでしよう

# この記事の内容
「foreachで回した要素自体の値を更新したい」といったことが、たまにあるかと思います。
（あるよね...?）

上記の要件を満たしたいと思った時に
・参照渡しを使う
・foreachのkeyを使う
大きく分けて上記2種類の方法があると思ってるのですが、個人的にはkeyを使用した方法を使いたいなと感じたので、その辺りの方法とメリデメを残しておこうと思います。

間違ってる点あれば、ご指摘頂ければ幸いです。

# 環境
```bash:ターミナル
$ php -v
PHP 7.1.33 (cli) (built: Oct 31 2019 17:37:57) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
```

## ダメなパターン
まずおさらいですが、普通にforeachで値をそのまま代入しても値は変わりません。
foreachを使用すると、元の値のコピーが作られる為です。

```php
$tests = ["a" => 1, "b" => 2, "c" => 3];

foreach ($tests as $test) {
    $test *= 2;
}

print_r($tests);

Array
(
    [a] => 1
    [b] => 2
    [c] => 3
)
```

## 参照渡しで更新するパターン
変数の前に「&」を付ける事で、参照渡しになります。
通常の値渡しと違う点は、その名の通り「参照」が渡されるので、元の値を直接参照できること。
個人的には、ショートカットみたいなイメージを持ってます🤔

foreachの各要素を更新する場合は、asの後で指定する変数に&を付ける。

```php
$tests = ["a" => 1, "b" => 2, "c" => 3];

foreach ($tests as &$test) {
    $test *= 2;
}

print_r($tests);

# 結果
Array
(
    [a] => 2
    [b] => 4
    [c] => 6
)
```
ただし、これだと最後の参照が残りっぱなしになるので、
$testを更新したりすると、最後に参照したkeyが"c"の要素が更新されます。

```php
$tests = ["a" => 1, "b" => 2, "c" => 3];

foreach ($tests as &$test) {
    $test *= 2;
}

$test = 100;

print_r($tests);

# 結果
Array
(
    [a] => 2
    [b] => 4
    [c] => 100
)
```

この問題を回避するためには、参照を解除するために「unset」を使うと良い。
公式にも丁寧に書いてますね。

https://www.php.net/manual/ja/control-structures.foreach.php

```php
foreach ($tests as &$test) {
    $test *= 2;
}

unset($test);
$test = 100;

print_r($tests);

# 結果
Array
(
    [a] => 2
    [b] => 4
    [c] => 6
)
```
まぁ、$testという変数は作られちゃってるんですがｗ

## 参照渡しはあまり使いたくない
上記のようにすれば更新はできるんですが、個人的には参照渡しは好きじゃない。

・「&」一個付いているだけで挙動が変わるので、見逃しがち
・改修が難しくなる
・処理追うのめんどくさい
・unsetを忘れてバグを生む可能性が微レ存

バグが生まれやすいですし、「この変数は参照渡し」ってずっと自分の脳のメモリが圧迫されながら処理を追うのは結構しんどいです。

ということで、Keyで更新する方法をオススメしたい。

## keyで更新するパターン
```php
$tests = ["a" => 1, "b" => 2, "c" => 3];

foreach ($tests as $key => $value) {
    $tests[$key] *= 2;
}

print_r($tests);

# 結果
Array
(
    [a] => 2
    [b] => 4
    [c] => 6
)
```

個人的にはこっちのが読みやすい...。
上記パターンだと「$value」がいらない子になっちゃってるので、特に必要ない場合は「array_keys」を使うことで更にスッキリします。

```php
$tests = ["a" => 1, "b" => 2, "c" => 3];

foreach (array_keys($tests) as $key) {
    $tests[$key] *= 2;
}

print_r($tests);

# 結果
Array
(
    [a] => 2
    [b] => 4
    [c] => 6
)
```
うん、読みやすくなりました。
ただし、真偽の程は定かじゃないけどこのやり方は参照渡しに比べるとパフォーマンス面では劣るそう。
普通に考えたら、値のコピーを作って処理する分参照渡しの方が早いのはそうなんだろうなぁ。

とはいえ、結構変わってくるなら業界的にも「大きめの処理では出来るだけ参照渡しを使いましょう」みたいな話が出回ってそうなので、気にする程ではないのかなとw

それよりも、初学者にも玄人にも読みやすいかつバグを生みづらいコードである事の方がメリットとして大きいと思ってます🤔

# まとめ
参照渡し
・パフォーマンスは良い(はず)
・コードが読みづらい
・バグを生みやすい

key
・パフォーマンスは参照渡しより劣る(はず)
・読みやすい

ざっくりですが、こんな感じ。
この辺りの使い分けについて、明確にコーディングルールで定められている会社の方とかいらっしゃれば、ぜひ理由をお聞きしたいです！
Cloudformationを用いて、Crawler完了時にJobを実行させるAWS::Glue::Triggerを作成する際の注意点

##環境
2021/08/05時点での情報です。

##問題
[公式マニュアル](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-glue-trigger.html#cfn-glue-trigger-startoncreation)に則り以下のようにTriggerを記述したが、
スタック生成時に"state cannot be null or empty, choose from one of the following crawler state: [succeeded, failed, cancelled]"とエラーが生じる。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  GlueJobTrigger:
    Type: AWS::Glue::Trigger
    Properties:
      Type: CONDITIONAL
      Actions:
        - JobName: JobName
          Arguments:
            "--job-bookmark-option": "job-bookmark-enable"
      Predicate:
        Conditions:
          - LogicalOperator: EQUALS
            State: SUCCEEDED
            CrawlerName: CrawlerName
      StartOnCreation: true
      Name: GlueJobTrigger
```

##原因
StateではなくCrawlStateと指定する必要がある。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  GlueJobTrigger:
    Type: AWS::Glue::Trigger
    Properties:
      Type: CONDITIONAL
      Actions:
        - JobName: JobName
          Arguments:
            "--job-bookmark-option": "job-bookmark-enable"
      Predicate:
        Conditions:
          - LogicalOperator: EQUALS
            # State: SUCCEEDED
            CrawlState: SUCCEEDED
            CrawlerName: CrawlerName
      StartOnCreation: true
      Name: GlueJobTrigger
```

## 最後に
同じようなエラーで困っている方の役に立てれば幸いです。
[感想]  技術的に挑戦し続けるチームとエンジニアの成長  (qiita ✖️ UZABASE Tech Meetup#3) 

## 概要
2021/08/05(木)
技術的に挑戦し続けるチームとエンジニアの成長  (qiita ✖️ UZABASE Tech Meetup#3) のライブ配信を見たのでその感想。 (タイトル通り)

いくつか、コンテンツがあり各担当者が発表していく形式。
基調講演２つ。技術講演３つ。

## 所感(まとめ)
・全編通して成長についての話があった。
・大きすぎないチャレンジを日常的に行うというのが、製品とエンジニアの成長の両立に良いという話が印象に残った。
・1年目からでもチームの中でも自分主体でいくつかの取り組みを行なっている人もいて、爪の垢を煎じてもらいたいなと思った。 (自分が主体でやると学びが多そう。モチベも必然的に高まる。)

・今後も、何か参考になるエンジニア関連の勉強になる配信とか試聴したい。
→ どなたでもおすすめのイベント等があったら教えてください。


## 書いた理由
(qiita ✖️ UZABASE Tech Meetup)第１回、第２回も視聴したが、見ているだけだとぼーっと聞いてしまい後で覚えていないなと思ったので、
改善のため、感想を書くことで、話を聞く&後々振り返れることを目的としている。


### 基調講演① プロダクト開発こそ、事業成長の 「一丁目一番地」 (発表者：ユーザベース　Co-CEO 稲垣雄介さん)

(諸事情でほとんどを聞き逃してしまった。)

エンジニアもビジネス視点を持つ必要があるという話？

## 内容
### 技術講演①「機械学習モデルをボタン一発でデプロイ!」 (発表者：ガオさん)
機械学習周りの話。

いい制度の機械学習モデルを作るだけではだめ → 機械学習のコードだけでは価値を届けられない。

入社段階(1年半前)では知識はなかった。
(Jenkins, Kubernetes, docker, google Cloud Storage等)
↓ どうやってキャッチアップしたのか
最初に機械学習を始めた。個人的にキャッチアップが難しかったのはdocker,kubernetes周り。

やったこと：
ボタン一発で、最新のデータで学習したモデルの作成・デプロイができるようにした。

### 技術講演②「Kubernetes /Istioによるマイクロサービス化で得られたもの」 (発表者：八代さん)
##### 変更点
SPEEDA(経済情報プラットフォーム)について
以前：モノリシックなJavaアプリケーション
↓
現在：Kubernetes /Istioによるマイクロサービス化

##### この変更により、得られたこと
ソフトウェアエンジニア目線
→ 使用する技術の幅が広がった。
→ アプリケーション実行方法の設定もSWEの担当範囲に
上記によって開発チームの自立性が高まった。

SREとしての変化
→ オートヒーリング(※)により構築作業や障害対応が減った
より、全体に関わる時間が増えた

※ オートヒーリング：異常のある EC2 インスタンスを削除し、新しいインスタンスを起動して、常に一定数の EC2 インスタンスを維持する構成。

個人として得られたこと
→ サービス運用に関わるようになった。

##### 今後
変化に強いシステムを作る。


### 技術講演③「SWE歴1年の僕が挑戦してきたこと」 (発表者：原田さん)

挑戦1:新技術の導入 (KtorとKotest)
→ チームを引っ張る経験

挑戦２：テストについてチームに発表 (ATDD, E2Eテスト書いてる)
→ テストについての理解が深まった

挑戦３：社内副業制度DIVE (社内の別のプロジェクトに関われる？)

Tech Forum(LT会みたいなの？)が毎週金曜30分ある。

### 基調講演②「エンジニアの成長とプロダクトの成長を両立するために」 (発表者：林さん)
エンジニアの成長とは？
→ 各種スキルの向上(プログラミング、 機械学習、 インフラ、 コミュニケーション能力など)
→→ 出来なかったことができるようになる。
→→ アウトプットまでのスピードがあがる

プロダクトの成長
→ 機能の追加・向上
→ 売上の向上

どう両立するか？
→ 「大きすぎないチャレンジを日常的に行う」よう意識している。
（要管理者権限）組織のリソースを一部のユーザーとカレンダー上で管理

# はじめに
組織のリソース（会議室や貸し出し機器等）をカレンダー上で予約できるようにすることは、公式ページ

[カレンダー リソースとは](https://support.google.com/a/answer/1686462?hl=ja)

に従って行えばできるようになります。ただし、この方法では組織の全ユーザーが組織のリソースへアクセスできるため、教育現場を例に取ると生徒や学生からリソースの予約状況が見えてしまいます。

この記事では、組織のリソースを一部ユーザーとだけカレンダー上で管理するために必要な設定についてまとめます。

ここでの設定により、例えば「生徒がカレンダーに予定を追加する際に会議室のリソースは表示されず、教員の場合のみリソースが表示され、リソース予約状況も生徒のカレンダーには表示されない」ということが可能になります。とはいえ、頻繁に行うオペレーションではないので簡単に要点のみをまとめておきます。

# 設定のポイント

1. 管理コンソールの「アプリ>Google Workspace>カレンダーの設定>全般設定」で「リソース予約の許可」を**オフ**
2. 設定したいリソースのカレンダーの設定で「予定のアクセス権限」の**チェックを全て外す**→これで誰もリソースを予約できなくなる。
3. 設定したいリソースのカレンダーの設定で「特定のユーザーとの共有」に共有したいユーザーあるいはグループを設定し、「予定の表示（すべての予定の詳細）」→リソースに予約できるユーザーを限定する。リソースの場合は閲覧権限でも予約が可能となる。

※ 注意点
「特定のユーザーとの共有」を行うと、当該ユーザーのGmailに通知が飛びます。リソースが100個なら100通飛びます。これは避けられないので事前に周知の上で行って下さい。ただし、一般ユーザーがリソースのカレンダーを追加するために、個々のメールの「カレンダーに追加」ボタンを押す必要はありません。カレンダーアプリ左下の「他のカレンダー横の+＞リソースのブラウジング」から手動でまとめて追加できます。

# GASで一括設定
管理しなければならないリソースが多い場合には、リソース毎に上記設定を行わなければならない。しかも、リソースをカレンダーに追加した場合、タイムゾーンのデフォルトがアメリカになるためこちらも全て日本に設定し直さなければならない。

そこで、リソースに対して以下の設定を一括で行うGASを書いた。

* 設定したいリソースのカレンダーの設定で「特定のユーザーとの共有」に共有したいユーザーあるいはグループを「予定の表示（すべての予定の詳細）」権限で設定
* タイムゾーンを日本に設定

[Acl](https://developers.google.com/calendar/api/v3/reference/acl)というCalendar APIを用いているので、サービスのCalendar APIを追加する必要がある。[Class Calendar](https://developers.google.com/apps-script/reference/calendar/calendar)を調べたのだが、現在のところ

* 設定したいリソースのカレンダーの設定で「予定のアクセス権限」のチェックを全て外す

をGASで設定できそうになかった。この方法が分かる人は是非情報をお寄せください。

また、複数のカレンダーからリソースだけを抽出するという目的を達成すれば良いので、この部分の書き方は別に何でも良いです。カレンダークラスのオブジェクトを配列でまとめて扱っているだけです。

```javascript
function myFunction() {
  const calendars = CalendarApp.getAllCalendars();

  // 複数のカレンダーからリソースだけを抽出。著者の環境では'号館'のみで十分
  const resources = calendars.filter(function(value){
    if (value.getName().indexOf('ここにリソースのみ共通に含む文字列') != -1){
      return value.getName();
    }
  }) 

  function addUsers(calendarId, emails) {
    emails.forEach(function(email){
      Calendar.Acl.insert({
        "role": "reader",
        "scope": {
          "type": "user", // 追加するメールアドレスが個人ならuser、グループならgroup
          "value": email,
        },
      }, calendarId);
  });
  }

  for (const calendar of resources){
    calendar.setTimeZone('Asia/Tokyo');
    addUsers(calendar.getId(),[ 
      // ここに「特定のユーザーとの共有」で設定したいメールアドレスを１つ以上設定
      'メールアドレス1',
      'メールアドレス2'
    ]);
  }
} 
```
MQL5はclassの継承とinterfaceの実装が一緒くたなのは勘弁して欲しい (オブザーバーパターンの迂遠な一例)

欲にまかせてMT5用のEA作成をしてるのですが、良くある(だろう)インターフェースを実装する形でのオブザーバーパターンなコードを書いたら、コンパイラに怒られました。

```C++:コンパイラに怒られる例
class CAnyEvent { /*色々と*/ };

interface IAnyEventListener {
  public:
    void onAnyEvent(const CAnyEvent&);
};

class CBase1 { /*なんやかんや*/ };
class CDerivesAndImplements : public CBase1, IAnyEventListener { /* <-多重継承禁止に引っかかる*/
  public:
    void onAnyEvent(const CAnyEvent&)override;
};
```

まあ怒られますよね。'implements'てのが無いんだから。
それがinterfaceであるなら、クラスの多重継承禁止の対象にはしないというようにしてくれるコンパイラになってくれんかな、とか思いますが、現になってないんだから仕方がない。

「どうしたもんだか」と悩んだ末に、ひとまずやってみて、一応望んだ通りに動作してくれたのは以下のコード。(CAnyEvent と IAnyEventListener は省略)

```C++:結局こうした

// IAnyEventListenerを実装するクラス
// これを一段かませて、実際のリスナーの仕事をするメソッドを呼び出す
template <typename OUTER>
class CAnyEventListener : public IAnyEventListener {
  public:
    CAnyEventListener(OUTER *o) : outer(o) {}
    void onAnyEvent(const CAnyEvent &evt)override {
        outer.onAnyEvent(evt);
    };
  private:
    OUTER *outer;
};

class CAnyEventSource {
  public:
    void addListener(IAnyEventListener*);
};

class CBase1 { /*なんやかんや*/ };

class CListener1 : public CBase1 /*implements IAnyEventListener <-これが出来れば問題無かったのだけど*/ {
  public:
    // コンストラクタで、
    // IAnyEventListener を実装したリスナーオブジェクトに、
    // 自身の存在をセットしておき、イベント発生時には
    // 自身のonAnyEventを呼んでもらう
    CListener1() : anyEvtListener(GetPointer(this)) {}

    // イベントソースにリスナーオブジェクトをセットする
    // (自身をセットするのではない)
    void setAnyEventSource(CAnyEventSource &src) {
        src.addListener(GetPointer(anyEvtListener));
    }

    // 実際にリスナーとしての作業をするメソッド
    void onAnyEvent(const CAnyEvent &evt) {
        /* ........ */
    }

  private:
    // IAnyEventListenerインターフェースを実装したリスナーオブジェクト
    CAnyEventListener<CListener1> anyEvtListener;
};

```

という感じで、いちおう機能するものにはなりました。
しかし回りくどい。

なんか良い手は無いでしょうかね。
【SwiftUI】Appからのトラッキング要求

###メモ
・Appからのトラッキング要求は最初の実行時のみポップアップが表示される。
・再インストールなどすれば再びポップアップが表示
・設定のアプリへの権限許可？画面で設定変更も可能

トラッキングの許可を要求したいタイミングで"requestPermisson()"を実行
上記の通り、最初だけポップアップが表示され、以後表示されなくなる。

###コード
```ContentView.swift
struct ContentView: View {
    
    var body: some View {
        Button(action: {
            requestPermission()
                    
        }){
            Text("広告許可")
        }

//トラキング許可メソッド
func requestPermission() {
    if #available(iOS 14, *) {
        ATTrackingManager.requestTrackingAuthorization { status in
            switch status {
            case .authorized:
                // Tracking authorization dialog was shown
                // and we are authorized
                print("Authorized")
                
                // Now that we are authorized we can get the IDFA
                print(ASIdentifierManager.shared().advertisingIdentifier)
            case .denied:
                // Tracking authorization dialog was
                // shown and permission is denied
                print("Denied")
            case .notDetermined:
                // Tracking authorization dialog has not been shown
                print("Not Determined")
            case .restricted:
                print("Restricted")
            @unknown default:
                print("Unknown")
            }
        }
    }
}
```

【追記】
info.plistへ追記も必要でした。これがないとクラッシュしますね。

&lt;Key&gt;Privacy - Tracking Usage Description&lt;Key&gt;
&lt;Value&gt;広告を最適化するためにトラッキング許可してください&lt;Value&gt;
Swift　　アクセスコントロールメモ

Swiftアクセスコントロール
----

チーム開発でプロパティが参照されている可能性がある（自分の知らないところで）

だからこそ考慮した上で適切なアクセスコントロールの処理をする必要がある。

アクセスコントロールの種類
--

```swift
open
//別モジュールからも呼び出せることができる + 継承やオーバーライドも可能
public
//別モジュールからも呼び出せることができる + 継承やオーバーライドはできない
internal
//同モジュールであれば呼び出せることができる
fileprivate
//同ファイルであれば呼び出せることができる
private
//同スコープ内なら呼び出せることができる
```

上記２つはライブラリの開発等をしなければほとんど使用しないので意味さえ理解していれば良い。
下記２つはチーム開発でバシバシ使用されるのでしっかり使えることが必要。
何も付けないとデフォルトで```internal```になる
AWS認定 SAAの無料勉強Webサイト一覧

# AWS 認定 SAAとは？
AWS 認定ソリューションアーキテクト アソシエイト試験は、AWSにおける分散システムの可用性、コスト効率、高耐障害性およびスケーラビリティの設計に関する 1 年以上の実務経験を持つソリューションアーキテクト担当者を対象としています。

https://aws.amazon.com/jp/certification/certified-solutions-architect-associate/

## 試験範囲
https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Exam-Guide.pdf

## サンプル問題
https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Sample-Questions.pdf

# 勉強する前に必要な能力

• 中学高校卒業程度の現代文、読解能力
• IT•Web系•AWS用語への単語、カタカナ語への用語理解

# AWS SAA無料で勉強する方法

約2,600円で<strong>AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト アソシエイト 改訂第２版</strong>の参考書を購入するのも良いが、<strong>無料の学習サイト</strong>でAWS SAAの模擬問題を回答してから受験するかどうか検討する方が望ましい。
## AWS SAA無料勉強Webサイト集
AWS SAA無料勉強Webサイトについて紹介する
※Youtubeや一部有料のWebサービスも含む
### AWS認定資格 無料WEB問題集＆徹底解説 ソリューションアーキテクト アソシエイト
1問回答するごとに正解か不正解か表示される。170問無料で回答することができる。易しい順、難しい順で問題を回答することもできるので、初めてSAAの問題をやってみる方におススメです。

https://aws-exam.net/saa/

### AWS WEB問題集で学習しよう
1問回答するごとに正解か不正解か表示される。27問無料で回答することができる。
※ベーシックプラン4928円/月を契約すると1,068問回答可能になる

https://aws.koiwaclub.com/

### Ping-t AWS無料問題集

Ping-t IT学習サイト利用者数３０万人を突破しました。

ITパスポートをはじめ、AWS SAA、LPIC、LinuC、CCNAの問題集が提供している。

AWS SAAの練習問題は600問無料で用意されております。

https://mondai.ping-t.com/g/

### Cloud Tech
KWS(くろかわWebサービス)が運営している会員制コミュニティ付きのAWS初学者を導く体系的な動画学習サービス、AWS学習サイトである。AWSの有料ハンズオンをするにあたっては、業界最安値と言っても過言では無い！
1問回答するごとに正解か不正解か表示される。
30問無料で回答することができる。無料会員登録をすると200問無料で回答することができる。

<strong>プラン一覧</strong>

|レベル|金額|
|:--|:--|
|AWS CloudTechコース|4,980円/月|
|AWS CloudTechコース（3ヶ月ライセンス）|9,960円/3ヶ月|	
|AWS CloudTech ゴールドプラン（永久ライセンス）|一括買い切り29,800円|	
|フリーコース|無料|

https://kws-cloud-tech.com/courses/%e3%83%86%e3%82%b9%e3%83%88%e3%82%b3%e3%83%bc%e3%82%b9

### AWSチャンネル 【ソリューションアーキテクトアソシエイト試験対策】
AWS Cloud Techの代表取締役が「AWSチャンネル」でYoutubeに１問ごとに動画を投稿している。144問無料で回答することができる。

https://www.youtube.com/watch?v=c89BR3PQuI0&list=PL2nCE2iR-lplkSsCoKuixZB4dNlFoHjEW

### 【オススメ】 Maruchin techチェンネル

今回の動画は、AWSソリューションアーキテクトアソシエイト試験の対策についてまとめています。
「これだけ押さえれば試験に受かるだろう」という網羅性があります。
スライド100ページ以上あります。

https://youtu.be/fsz6G45A4H4


【AWS】AWS-SAA-C03の変更ポイント【ソリューションアーキテクトアソシエイト試験】

https://youtu.be/3B7YlmNcONo

### サーバーワークス 公式チャンネル

サーバーワークス宮沢さんが親切丁寧にAWS SAA(CO3)の試験範囲やサンプル問題10問を解説している動画です。


新バージョン試験に備えよう！AWS 認定ソリューションアーキテクト – アソシエイト試験ガイド確認【SAA-C03】

https://youtu.be/AtkywbK3JHc


【SAA-C03】AWS Certified Solutions Architect – Associateサンプル問題解説11 本の動画

https://youtube.com/playlist?list=PLCRz5JqTKzfnW-S5Lardk_Fw6hqtzwgnL





# 最後に
私は、2022年1月にAWS SAAを合格しました。AWS CLFの土台があるからこそAWS SAAの演習問題を難なく解答することができました。たとえ不正解だったとしても解説を読んでわからないことは調べる等すれば、大丈夫です。AWS未経験者がAWS SAAを取得する際は、AWS クラウドプラクティショナーを合格してから受験することをオススメします。
IT未経験者がいきなり基本情報処理技術者試験、応用情報処理技術者試験に挑むようなものです。

# お願い
AWS SAAの資格取得は、<strong>年収が上がる、職場で重宝される</strong>のでオススメです。
AWS SAAの無料Web問題サイトがあったら教えて欲しいです。
FastAPIのOpenAPIバージョンをpyproject.tomlから取得する

# 課題

FastAPIでAPIサーバーを作っている。

FastAPIは関数の引数や戻り値の型情報を読み取ってOpenAPI（旧Swagger）形式のドキュメントを作ってくれる。

OpenAPIには今のAPIのバージョンを設定するフィールドがあり、ここでAPIのバージョンを管理することができる。
もちろんハードコーディングで管理してもいいのだが、今回はパッケージマネージャーにPoetryを使っているので、 `pyproject.toml` 内の `[tools.poetry]` セクションの `version` を動的に読み取るようにすると綺麗に管理できるような気がした。

```pyproject.toml
[tool.poetry]
name = "my_api_server"  # <- ついでにこれも表示させたい
version = "12.8.9"  # <- これをOpenAPIドキュメントに表示させたい
description = "私のAPIサーバーです。"  # <- ついでにこれも表示させたい
authors = ["que9 <example@example.com>"]

...

```

# 解決方法

愚直に実装した。なお、TOMLファイルの読み込みには [toml](https://pypi.org/project/toml/) パッケージを採用した。

1. `poetry add toml` を実行し、[toml](https://pypi.org/project/toml/) パッケージをインストールする
1. `main.py` に以下を仕込む

```main.py
import os
from typing import Any, Dict

import toml
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi

app = FastAPI()

def custom_openapi():
    if app.openapi_schema:
        return app.openapi_schema

    assert os.path.exists("pyproject.toml")

    with open("pyproject.toml") as f: # ... ③-1
        pyproject_toml = toml.load(f) # ... ③-1
        poetry: Dict[str, Any] = pyproject_toml["tool"]["poetry"]
        title: str = poetry["name"]
        version: str = poetry["version"] # ... ③-2
        description: str = poetry["description"]

    app.openapi_schema = get_openapi( 
        title=title,
        version=version, # ... ②
        description=description,
        routes=app.routes,
    )
    return app.openapi_schema

app.openapi = custom_openapi # ... ①


@app.get("/test")
def test():
    return "success"

```

一応解説すると、 `app.openapi` にOpenAPIのスキーマ情報を取得する関数 `custom_openapi` を定義している（①）。
OpenAPIのスキーマ情報は `fastapi.openapi.utils.get_openapi` に適当に引数を設定すると取得できる（②）。
引数に設定する値はtomlパッケージを使って `pyproject.toml` から読み込んでいる（③-1）。
`[tool.poetry]` の `version` を参照するためには `pyproject["tool"]["poetry"]["version"]` のようにしてアクセスできる
今回はバージョンの他にも `name` や `description` もスキーマ情報として設定したかったので、
`pyproject["tool"]["poetry"]` を一時変数に代入してから取得するようにしている（③-2）。


# 結果

こんな感じ。

**/docsの表示**

![スクリーンショット 2021-08-05 20.42.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82681/8a807448-503c-dc2b-e17e-b20c30c8c1da.png)

**/redocの表示**


![スクリーンショット 2021-08-05 20.43.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82681/7a78565a-0e09-7aa8-fe01-fb6cb5d3ec80.png)

`main.py` を書き換える前はバージョンが0.1.0だったが、書き換えた後は `pyproject.toml` 記載の値になった。
ついでにAPIの名称や説明文も `pyproject.toml` 記載の値になった。よしよし。
Micro PythonでRaspberry Pi Picoを遊んでみる

# 1. はじめに
Raspberry PI Pico は、驚くべきコスパが良いラズパイです。これをMicro Pythonで使ってみます。使用したマシンは、Windows 10です。

# 2. ファームウェアのインストール
Micro Pythonを使用するには、Raspbery Pi Picoにファームウェアをインストールする必要があります。

[Firmware for Raspberry Pi Pico](https://micropython.org/download/rp2-pico/)　のサイトからファームウェアをダウンロードします。最新の安定板（[rp2-pico-20210618-v1.16.uf2](https://micropython.org/resources/firmware/rp2-pico-20210618-v1.16.uf2)）をダウンロードしました。

PicoのBootselボタンを押しながらPicoをPCに接続すると、PCからPicoがドライブとして認識されます。

ここに、先ほどダウンロードしたファームウェアをコピーします。コピーが完了すると、自動的にPicoが再起動します。ドライブとして認識されなくなり、Micro Pythonが動作します。

# 3. 開発環境IDE(Thonny)の準備
Python IDEのThonnyを使います。

## 3.1 ダウンロード・インストール
Thonnyは、[https://thonny.org](https://thonny.org/)よりダウンロードできます。

今回は、Windows 10を使うので、Windows用のインストーラをダウンロードします。このページの一番上から”for Windows”を選んでインストーラをダウンロード。今のところ”thonny-3.3.13.exe”でした。

インストールを実行します。

## 3.2 ちょっと設定

Thonnyを起動します。起動時に「Raspberry pi」を選択します。

### 3.2.1 メニューの日本語化

ツール->Optionsで、Languageを日本語にします。できないときは、画面右上で「Switch to regular mode」を押して、再起動します。

### 3.2.2 ファイルの表示

PCとRaspberry pi Pico のファイルを両方見えるようにする。

表示->ファイル　をチェックします。

### 3.2.3 インタプリタの設定

ツール->Options のインタープリタ タブ で　上のコンボボックスで「MicroPython(Raspberry Pi Pico)」を選択します。

## 3.3 Thonnyの画面

うまくセットアップが完成すると、以下のような画面になります。
![thonny.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618305/df06f8ef-75cf-e4be-d8e5-971bde7ca9bc.png)

左上がローカルPCフォルダ、左下がPicoのフォルダ、右上がファイルの内容、右下がシリアルコンソール（REPL）になります。


# 4. つかってみる

Picoのフォルダに、main.pyという名前で付けたファイルがPicoの電源投入時に起動します。

main.pyというファイルをつくり、以下のコードを書いて保存します。

```
from machine import Pin
import utime
led = Pin(25, Pin.OUT)
while True:
    led.toggle()
    utime.sleep_ms(200)

```


PicoでPin25は内臓LEDにつながっています。Thonnyの画面上部の三角ボタン（Run currentscript）ボタンを押すか、Picoを再接続すると、内臓LEDが200ms毎に点滅します。

![Pico.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618305/c63d9264-3793-fba8-0ced-ce5332de8d72.jpeg)
mysql on docker on ubuntu on hyper-v on windows10な環境でMySQLに接続できなくなったとき

# 問題と原因

```
Lost connection to MySQL server at 'reading initial communication packet', system error: 0
```

のようなエラーが出るとき、原因は様々だ。

今回の原因は、UbuntuのVMがネットに接続されていなかったというかHyper-Vのネットワークスイッチがおかしくなっていたことであった。

```bash:ubuntu_on_hyper_v
$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From 172.18.11.59 icmp_seq=1 Destination Host Unreachable
From 172.18.11.59 icmp_seq=2 Destination Host Unreachable
From 172.18.11.59 icmp_seq=3 Destination Host Unreachable
From 172.18.11.59 icmp_seq=4 Destination Host Unreachable
From 172.18.11.59 icmp_seq=5 Destination Host Unreachable
From 172.18.11.59 icmp_seq=6 Destination Host Unreachable
^C
--- 8.8.8.8 ping statistics ---
7 packets transmitted, 0 received, +6 errors, 100% packet loss, time 6137ms
pipe 4
```

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

## 発見経緯

Railsの開発をしていて、rspecを回そうとしたところ当該エラーが出た

## 前提

前夜までは何事もなく動いていた。

## 試行

1. 手元の変更を`git stash`で退避させてrspecをまわす→同じエラー
1. `docker ps`でmysqlのdocker imageが起動していることを確認→起動している
1. `docker kill <image hash>`して殺して`sudo docker-compose -f docker-compose-web.yml up -d db`してrspecを回す→同じエラー
1. `docker-compose -f docker-compose-web.yml build`してみて同様に試す→同じエラー
1. Windows10からheide sqlでいつも通り接続を試みる→同じエラー
1. rspecを回すときにmysqlの動いているシェルの実行ログを監視する(VSCodeで簡単に見れる)→なにも出力されない
1. mysqlのdocker containerにattach shellして(VSCodeで簡単にできる) `mysql -u root -p`して手動ログインを試みる→成功
1. `bundle exec rails console`を試す→同じエラー
1. 3306 portへの疎通確認→成功  

    ```bash
    $ nc -vz localhost 3306                                                                                                                                         
    Connection to localhost 3306 port [tcp/mysql] succeeded!
    ```
1. UbuntuのVM再起動→変化なし


ここまで試して、試しにaptの更新かけてみたら？今日dockerの更新降ってきてたよと言われて`sudo apt update`したところ、全部のサーバーに疎通してない。

もしかしてと思って冒頭のpingを打ったところ疎通してないことを確認したのである。

Hyper-Vの設定は特に問題なかった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94177/dd95fc25-4986-df04-bc4d-ad430a1ff736.png)

このため再度Windows10を再起動して解決に至った

# 解決を難しくした原因

少し前にWindows10を再起動していたためHost側は関係ないと思っていたがそうではなかった。

再起動直後くらいに、Wi-Fiへの接続が切れたため、トラブルシューティングツールからネットワークアダプターのリセットを行っていた。このときにHyper-VのDefault Switchがおかしくなったと考えられる。
Grove IoT スターターキット for SORACOM で磁気スイッチを使う

プログラムを動かして、磁石がついてない状態でLEDは青、
磁石をつけると LED が赤くなります。
磁気スイッチの Grove を D38 に接続します。

```text:magnetic_switch/magnetic_switch.ino
// ---------------------------------------------------------------
/*
	magnetic_switch.ino

					Aug/05/2021
*/
// ---------------------------------------------------------------
#include <WioLTEforArduino.h>

#define MAGNETIC_SWITCH_PIN (WIOLTE_D38)
#define INTERVAL            (100)

WioLTE Wio;
int icount = 0;
// ---------------------------------------------------------------
void setup()
{
	Wio.Init(); 
  
	pinMode(MAGNETIC_SWITCH_PIN, INPUT);
}

// ---------------------------------------------------------------
void loop()
{
	int switchState = digitalRead(MAGNETIC_SWITCH_PIN);
	SerialUSB.print(switchState ? '*' : '.');

	if (switchState)
		{
		Wio.LedSetRGB(1, 0, 0);
		}
	else
		{
		Wio.LedSetRGB(0, 0, 1);
		}
	
	delay(INTERVAL);

	if ((icount % 40) == 0)
		{
		SerialUSB.println("");
		}
	icount++;
}

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

磁気スイッチが OFF
>![IMG_20210806_075745.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/9827c438-e1ea-821f-844a-0c8bbe1f10c8.jpeg)

磁気スイッチが ON
>![IMG_20210806_075805.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/cf01c3a5-575a-cff1-741a-09a488bf93b9.jpeg)
[Ruby] AtCoder 過去問　B-Bishop

##はじめに
AtCoder過去問のB問題、Bishopを解いてみました。

この問題を解くときに、最初に浮かんだのはfor文やtimesメソッドを用いて繰り返し処理をすることでした。しかしながら、数字が大きくなれば処理に膨大な時間がかかってしまい、アウトになってしまったので、他のやり方を試行錯誤してようやく解けました。

問題はこちらから確認してください。↓

https://atcoder.jp/contests/panasonic2020/tasks/panasonic2020_b

よろしくお願いします。

##B-Bishop
まず、はじめに入力の受け取りをします。

```ruby
H, W = gets.split(' ').map(&:to_i)
```

考え方としては、一番左上に存在する角行が移動可能な最大のマスの数を出力せよ、ということで盤上のマスの数は入力値によって変動するようになっています。

まずはじめに、縦 × 横が盤上全体のマスの数になるので受け取った数値をかけたものを変数に入れておきましょう。後で使います。マスのことをcellと表現していいのかわかりませんが、、、

```ruby
H, W = gets.split(' ').map(&:to_i)
total_cell = H * W
```


ここからはif文を使って条件分岐していくのですが、これから分岐する条件(後述します)の中にイレギュラーがあるので最初にその条件の振る舞いを書いてあげます。

それは縦もしくは横のマスが1マスしかない場合、斜めにしか動けない角行は、動きようがないということです。
ですので角行が存在できるマスは最初に位置している1マスだけになります。
下記のように書きます。

```ruby
H, W = gets.split(' ').map(&:to_i)
total_cell = H * W

if H == 1 || W == 1
  answer = 1
```

イレギュラーの条件は最初に処理するように記述したので、あとはある共通の法則で分岐をすればOKです。

その法則とは、角行が一番左上がスタートであり、盤上のマスが偶数であれば単純に全部の数のちょうど半分のマスを角行は動くことができます。

つまりHかWのどちらかが偶数であれば、全部のマスの半分が答えの数になります。

```ruby
H, W = gets.split(' ').map(&:to_i)
total_cell = H * W

if H == 1 || W == 1
  answer = 1
elsif H % 2 == 0 || W % 2 == 0
  answer = total_cell / 2
```

そして残るはそれ以外、つまりHもWも奇数で盤上のマスが奇数の場合です。
例えば縦3マス横3マスであれば9マスです。
紙に書くと非常にわかりやすいですが、この場合角行が動けるマスは5になります。

盤上のマスが奇数の場合は、その数に1足して、2で割ると答えが出ます。

```ruby
H, W = gets.split(' ').map(&:to_i)
total_cell = H * W

if H == 1 || W == 1
  answer = 1
elsif H % 2 == 0 || W % 2 == 0
  answer = total_cell / 2
else
  answer = (total_cell + 1) / 2
end

puts answer
```

これで完了。

##終わりに
はじめは、繰り返し処理を使ってfor文でぶん回していましたが、入力例3(冒頭の問題URLで確認してください)のような大きな数字が来るとかなり処理が重くなります。その結果、時間オーバーでアウトになってしまいました。

頭を柔らかく、ある法則を見つけ出して、できるだけシンプルに書くことが重要なんですね。
なにをやってAWS認定ソリューションアーキテクト-アソシエイト-に合格したか

# まず結論
### 学習教材は、以下の3つのみ！
#### udemy
* [これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/course/aws-associate/)  
* [【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)  
  
#### くろかわこうへいさんのCloud Tech
* [AWS SAA 問題(200問無料、自分は有料会員登録した)](https://kws-cloud-tech.com/)

# はじめに
こんにちは！@yuki5664と申します！

この度、AWS 認定ソリューションアーキテクト – アソシエイトに合格することができました！
なにで学習したのか？
それをどのように勉強したのか？
どのくらい時間をかけたのか？
学習前の自分のレベルは？
等を書いた、合格体験記になっています。
これから、AWS SAA合格を目指している方に役立つ情報になれば幸いです！

結構ギリギリ(笑)
![スクリーンショット 2021-08-03 9.26.28（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634021/9532f795-98df-6dd8-0572-d9f069da3ee6.png)


# 学習過程
#### 学習前
業務でAWS EC2 RDS Lambda S3 CloudWatch等基礎的なAWSサービスを使ったことがある程度。
個人開発で、Lambda APIgateway DynamoDB等を使ってサービス →[【シェアハウス🏠ハック】洗濯機が稼働しているかわかるサーバレスなWebシステムを作ってみた【IoT AWS Lambda APIGateway DynamoDB】] (https://qiita.com/yuki5664/items/aac81d730187f8cfbc7b)を作ったことはある。  
  ぐらいスペックでした。

#### 学習初期(30時間程度)
とりあえず、すでにAWS SAAに合格している友人の進めで、  
・ [これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/course/aws-associate/)  
で、AWSの基礎的な部分を学習！非常にわかりやすいし、ハンズオン形式で学べるのでかなりオススメです！ただ結構長い(2倍速)です。
随時、わからない用語等は、AWSの公式サイトで調べていく。

#### 学習中期(30時間程度)
実践的な問題になれるため、  
・ [【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/course/aws-knan/)   
に取り組む。やや難易度高め、AWSサービスのより細かい設定やAWS EMRなど普段あまり聞き慣れないサービスについて実践問題形式で学びました。 
模擬試験形式(1つ65問)が5つあるのですが、自分は3周は繰り返しやりました。

#### 学習終盤(20時間程度)
さらに細かい部分の知見を蓄積、補完するために  
・  [くろかわこうへいさんのCloud Tech AWS SAA 問題](https://aws-cloud-tech.com/) (200問無料、自分は有料会員登録した)  
で学習をすすめる。一問やってすぐ答えを確認できる一問一答形式なので、とても学習しやすいです。模擬試験もあります！

#### 試験当日(1時間半ぐらい)
私は、自宅で受験(ピアソン VUE)しました。
試験が始まって10分後ぐらいから、途中でトイレに行きたくなり、辞退するか迷うぐらい苦しみながら受験しましたw
試験は、結構長丁場になるんで、事前にトイレは行っといたほうがいいですね(当たり前)
また、自宅で、受験される方は、ピアソン VUEの説明要項にもありますが、誰もいないや安定したネット環境など環境に配慮しないといけないのでご注意を！

# まとめ
* 自分は、あまり試験勉強を超万全にしたタイプではないとは、思いますが教材は、上記の3つをしっかりやれば合格ラインには行けると思います。
* 総学習時間は100時間ぐらい。
* 自宅受験は、環境整備除いては、楽なのでオススメです。

あと、Twitterもやってます！[(@tanayu7777)](https://twitter.com/tanayu7777)よかったらフォローしてくださいね！
VRChat の Unity 2019 移行手順など

# ３分で終わる本編
絶対にこれ！ ⇒ [公式移行ガイド（英語）](https://docs.vrchat.com/docs/migrating-from-2018-lts-to-2019-lts)
英語なんてわかるか！⇒ [移行ガイド（非公式日本語訳）](https://docs.google.com/document/d/1cAOtIpB-miSF5ImfPTpbk3HQKK90kdph7UCRQY0iVV4/edit)

# 補足
※2021/09/17 追記
　VRChat が Unity 2019.4.30f1 に移行しました。
　新規に 2018 から 2019 へ移行させる場合は何も問題ないかと思いますが、2019.4.29.f1 へ移行済みの場合、そのまま 2019.4.30f1 で開くと Unity がクラッシュするかもしれまぜん（私の環境ではしました）。
　Unity 2019.4.29f1 で最新 SDK に更新してから 2019.4.30f1 で開くと大丈夫だったので、先に SDK の更新が必要かもしれません。
　Udon# もアップデートがされているので、こちらも更新した方がよさそうです。
※2021/09/17 追記終わり

* フォルダ丸ごとコピーで良いのでバックアップは取る。

* Unity は VRChat が指定するバージョンじゃないとダメ。 ⇒ [VRChat 指定の Unity バージョン確認](https://docs.vrchat.com/docs/current-unity-version#current-unity-version)

* VRChat の Steam アプリをアップデートしたらキャッシュを削除する。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">公式Discordのアナウンスからの情報です <a href="https://t.co/5zzOxDHNSs">pic.twitter.com/5zzOxDHNSs</a></p>&mdash; bd_ (@bd_j) <a href="https://twitter.com/bd_j/status/1423134244784676864?ref_src=twsrc%5Etfw">August 5, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


* Cloth は挙動変わるので覚悟。
Notion APIとFileMakerが良い化学反応を起こしそうな予感

Notion APIが公開され、普段使っているFileMakerとの連携に可能性を感じています。
Notionはチームで書き込むこともできますが、APIを使うことでNotionにログインしなくても外部からアクセスでき、入力フォームも用意することができます。

https://developers.notion.com/

##まずは今まで作ったものを見てください！

###My日報
https://twitter.com/zemiseipen/status/1413846097919840263?s=20

###My本棚
https://twitter.com/zemiseipen/status/1423196491930161157?s=20

#FileMakerとは
FileMakerはローコードの開発プラットフォームです。

FileMakerを使うと、このような社内システムを1人でも効率的に作ることができます。
[デイサービスで自社システムを作って楽をしています](https://qiita.com/gokkozemisei/items/79dd2e9a34fa06c67b32)

FileMakerは中小企業の社内システムなどで広く活躍しています。
[Claris ブログ 事例](https://www.claris.com/ja/blog/?category=%E4%BA%8B%E4%BE%8B)

小さなものでれば、思い立ったらすぐにさくっとアプリ（システム）を作ることができます。

##FileMakerで入力フォームを作る
FileMakerを販売しているClaris社はAppleの子会社で、iOSの機能を標準で使うことができます。
![スクリーンショット 2021-08-05 17.56.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237172/199cd8df-2d9d-a0a6-8f90-445787229a07.png)
例えば、カメラを起動してバーコードを読み取ってデータを書き込むまでのステップがこんな風に記述できます。
本の情報はopenBDで取得しました！
https://openbd.jp

##FileMakerからデータを送る
https://developers.notion.com/reference/database/

▼Notionにデータベースを追加するために整えた例


```json
{
      "parent": { "type": "database_id", "database_id": "**** database　idを入れる　****" },
      "properties": {
      "タイトル": {
        "type": "title",
        "title": [{ "type": "text", "text": { "content": "世界のかわいい村と街" } }]
      },
      "著者":  {
    "rich_text": [
      {
        "type": "text",
        "text": {
          "content": "パイインターナショナル／著・編集"
        }
     } ]

    },
      "表紙":  {
        "type": "url",
        "url": "https://cover.openbd.jp/9784756248893.jpg"
    },
      "ジャンル":  {
    "rich_text": [
      {
        "type": "text",
        "text": {
          "content": ""
        }
     } ]

    },
      "自分メモ":  {
    "rich_text": [
      {
        "type": "text",
        "text": {
          "content": "とても癒される本。
デジタルデトックスにも◎"
        }
     } ]

    },
  "説明文":  {
    "rich_text": [
      {
        "type": "text",
        "text": {
          "content": "おとぎ話に出てきそうな、かわいい村めぐり\n\n昔ながらの建築が残るノスタルジックな街や、山あいにひっそりと佇む小さな村など、世界中に残る小さくてかわいい村や街を紹介します。石畳の小道や花が飾られた窓など、おとぎの国に迷い込んだような気分にさせてくれる写真集です。"
        }
     } ]

    }



  }
}

```

##FileMakerのcurlオプションでNotionへ
![スクリーンショット 2021-08-05 18.15.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237172/3c403656-616a-3c97-81a4-5fc35cbb455d.png)


##FileMakerの弱点
###ライセンス費用
FileMakerはライセンス費用がかかります。
中小企業の基幹システムとして活用できる場合は問題ない費用感だと思いますが、限定的に使いたい場合にライセンス費が高いと感じる人もいるみたいです。ただし、FileMakerのiOSアプリ　FileMaker GOは無料です!
https://apps.apple.com/jp/app/claris-filemaker-go-19/id1484857908


###openな情報共有
FileMakerでの共有は基本的には社内でのclosedな共有が前提となっていて、
一部だけopenにしたいといった場合、そのような手段はありますが(Web direct,FileMaker data apiなど　…)ちょっと敷居が高いです。

##Notionがそこを埋めてくれることもあるのでは…
FileMaker GOで入力フォームを整えたものをキオスク的に活用し、そこで得た情報はNotionで共有すれば、NotionもFileMakerも無料の範囲で十分活躍できます。
もちろんFileMaker GOのファイルを配布して各々の端末から情報を入力してもらってNotionで集約するという使い方もできます。

そのほか、社内システムはFileMaker ServerやCloudで共有していて、一部の情報だけ取引先の方と共有したいときにも有効だと思います。

##何かもっとすごいコラボができる気がする
Notion自体を私が触り出して日が浅いですが、まだまだ気づいていない活用法がある気がしてなりません。
Notion APIの活用法の中でもFileMakerとのコラボは割と相性が良い気がしていて、FileMakerのユーザーを増やす糸口にもなりうるのではないかと感じています。
Okta Developer の制約について

お金がある人は全然いいのですが、検証用とかでOkta Developerを使う場合ありますよね？
https://developer.okta.com

今までは無料版だと1ヶ月しか使えなかったのですが、それが無くなってとってもいい感じです。
ただ、無料版だけあって、やっぱり制限があります。

## SSO制限
https://www.okta.com/pricing/#customer-identity-products

## API制限
https://developer.okta.com/docs/reference/rate-limits/

やっぱりこの中ではApplicationの追加が「5 OIDC Clients and 3 SAML applications」までしかできないのが一番の制約かなーと思いますね。いろんなものをSSOしようとするとあっという間に引っかかる。
PDOでMYSQLに接続  PHP

#■はじめに
●phpMyadminでデータベースとテーブルを作成している事

●データベースに接続するユーザーを作成する。この時にパスワードも設定しておく。
ユーザーごとに操作権限を決めると誤って必要なものを消したりする可能性が低くなる。
あなたはテーブルだけの権限ね
あなたはカラムのだけの権限ね

#■PDOを使いMYSQLに接続します。
PDOとはPHPでMYSQLに接続するのに必要なもの

``` php
 $dbh = newPDO($dsn,$user,$pass);

//結果 下記のように表示されれば成功
object(PDO)#1 (0){}
```

####▼$dbh
データベースハンドルの略　データベースを操作しますよと言う変数

####▼newPDO
PDO接続を呼び出す。
PDOクラスのインスタンスを作成

####▼$dsn
データソースネームの略
接続したいデータベースの情報を書く
下記のような決まった書き方がある。

``` php
$dsn = 'mysql:host=localhost;dbname=データベースの名前;charset=utf8';
```

####▼$user,$pass
データベースで自分で決めたユーザー名とパスワードを記載する。
初期設定ではどちらもrootになっている。

#■エラーハンドリング(接続が失敗した時の処理も書く)
####try~catchを使う
書き方

``` php
try{
 通常処理
} catch() {
 例外処理(エラー)
}
```

####▼オプションの指定
$passの横にエラーを表示するために必要な文を配列で書く
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]

``` php
try{
$dbh = newPDO($dsn,$user,$pass,[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
  echo'接続成功';
  $dbh = null;
} catch(PDOException $e){
  echo '接続失敗'. $e->getMessage();
  exit();
};
```

これで接続成功したら接続成功とでてくる。
失敗したら接続失敗とでてくる。
iOS11~12台のSafariでは、landscape時かつアドレスバー展開時に下部に50pxのスクロール可能領域が発生する

##タイトル通り
about:blankのページを開き、html・body要素のheightに関わる数値を0pxに指定、`overflow: hidden;`とした状態であれど、タイトルのような現象が発生する。
ちなみに本記事はただの備忘録です。

##どうしたか

プロダクトの仕様上、

- `document.body.scrollHeight === innerHeight`でありたい
- `scroll`や`touchmove`の差し止めをすることはできなかった

という条件があったため、妥協の下

```js:sample
const scrollPrevent = () => {
    if (window.pageYOffset > 0) window.scrollTo(0, 0);
}
window.addEventListener("touchend", scrollPrevent);
```
とした。
presto, sparksqlの日付型関連の関数の対応表

# 日付型→文字列型への変換
presto, sparksqlともdate_format関数が使える。第2引数の日付のフォーマットが違うことに注意。

```sql:presto
select date_format(date('2021-01-01'), '%Y%m%d')
```

```sql:sparksql
select date_format(date('2021-01-01'), 'yyyyMMdd')
```

# 文字列型→日付型への変換
```sql:presto
-- date_parseの戻り値がtimestampなのでdateに変換する
select date(date_parse('20210101','%Y%m%d'))
```

#### 
```sql:sparksql
select to_date('20210101','yyyyMMdd')
```

# 日付の加算、減算する（date_add関数)
引数の順番が異なるので注意。sparksqlでは期間の単位が設定できない。

```sql:presto
-- date_add(期間の単位, 期間, 基準となる日付)
select date_add('day', -1 , date('2021-01-01'))
```
```sql:sparksql
-- date_add(基準となる日付, 期間) 期間の単位が設定できない（日単位しかない）
select date_add(date('2021-01-01'), -1 )
```


### 参考にしたサイト
[presto](https://prestodb.io/docs/current/functions/datetime.html)
[spark](https://spark.apache.org/docs/2.3.0/api/sql/index.html)
【MySQL】DBに接続してSQLファイルを実行してCSVを出力するシェルスクリプト（備忘録）

# はじめに
* DBのクライアントツール(a5:SQL Mk-2とか)が使える環境であれば特段困らないが、そうもいかないとCSVを出すのは至難の業…ということでshで一発でやれるshを作りました。

# 手順
* confファイルを作る
  (shの中でmysqlコマンドを実行するところでユーザとパスワードを指定することもできますが、実行時に警告が出るのでやっておいたほうが吉。)

    ``` mysql.conf
    [client]
    user = DBのユーザ
    password = DBのパスワード
    # ↓必要に応じて別ホスト経由で接続する場合に記載
    host = DBのIPアドレス
    ```

* shを作る

    ``` get_csv.sh
    #!/bin/bash
    # 使用するdatabase
    DB="$1"
    # 実行するSQLファイルパス
    FILE_PATH="$2"
    # confファイルパス
    CONF_PATH="$3"

    if [ $# != 3 ]; then
        echo "Usage  : ./get_csv.sh データベースの名前 実行するSQLのファイルパス"
        echo "Example: ./get_csv.sh sample_db /home/mome1014/test.sql /home/mome1014/mysql.conf"
    exit 1
    fi

    # SQLファイルのディレクトリパス
    DIR_PATH=${FILE_PATH%/*}

    # SQLのファイル名
    FILE_NAME=${FILE_PATH##*/}

    # 拡張子なしのファイル名
    BASE_FILE_NAME=${FILE_NAME%.*}

    echo "----- logging into db ${DB} as admin execute ${FILE_PATH} start -----"

    CMD=`mysql --defaults-extra-file=${CONF_PATH} --database=${DB} < ${FILE_PATH} > 
    ${DIR_PATH}/${BASE_FILE_NAME}.txt`

    # 各行の一番前(「^」)に「"」を付加
    `cat ${DIR_PATH}/${BASE_FILE_NAME}.txt | sed -e 's/^/"/g' > ${DIR_PATH}/${BASE_FILE_NAME}2.txt`
    # 各行の一番後(「$」)に「"」を付加
    `cat ${DIR_PATH}/${BASE_FILE_NAME}2.txt | sed -e 's/$/"/g' > ${DIR_PATH}/${BASE_FILE_NAME}3.txt`
    # タブ「/t」を「","」に変更
    `cat ${DIR_PATH}/${BASE_FILE_NAME}3.txt | sed -e 's/\t/","/g' > ${DIR_PATH}/${BASE_FILE_NAME}.csv`

    # 中間ファイルの削除
    `rm -rf ${DIR_PATH}/${BASE_FILE_NAME}.txt`
    `rm -rf ${DIR_PATH}/${BASE_FILE_NAME}2.txt`
    `rm -rf ${DIR_PATH}/${BASE_FILE_NAME}3.txt`

    echo "----- logging into db ${DB} as admin execute ${FILE_PATH} end -----"
    echo "output result ${DIR_PATH}/${BASE_FILE_NAME}.csv"
    ```

* 実行

   ```
    Usage: ./get_csv.sh ${database_name} ${sql_file_path} ${conf_file_path}
   ```

　下記の例の場合は、sample_dbにアクセス（confファイルは/home/mome1014/mysql.confを使う)、 /home/mome1014/test.sqlを実行して、結果のCSVが/home/mome1014/test.csvで出力されます。

   ```
   $ ./get_csv.sh sample_db /home/mome1014/test.sql /home/mome1014/mysql.conf
   ```