OmniAICreator/Qiita-1.07M huggingface dataset:
二重ルータでも自宅サーバがしたい！(M1 mac 対応)

自宅サーバを構築したいけれど、マンションのネット回線だとできない...そんな悩みを抱えている人も少なくないはずです。今回はそんな環境でも自宅サーバを構築することができたのでまとめてみます。

# 問題
- サーバーを公開したいのに、二重ルータのため公開できませんでした。
- Hamachiは M1 macには対応していませんでした。(2021年5月現在)
- クライアント側のポートが固定できませんでした。[^1]

# 解決策
VPSを使ってVPNサーバを構築しました。
![network (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163480/e6b39ea5-0d91-48b8-f644-6b3ea6e04bef.png)

# 事前準備
## 自宅サーバのIPアドレス固定
初期設定では機器のIPアドレスが動的に変更されてしまうのでIPアドレスを固定します。
システム環境設定>ネットワーク>Wi-Fi>詳細...>TCP/IP と進み、以下のように設定します。
![スクリーンショット 2021-05-20 22.53.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163480/32bf3a8d-d111-1357-a3df-29447d636ec4.png)
# VPN構築
## VPS上でVPNサーバを構築する
コスパがとても良かったので、ConoHaのVPSを借りました。[こちらの記事](https://dawaan.com/setting-up-openvpn-in-5-mins/)を参考にOpenVPNをVPSにインストールしました。CentOS8だと動かなかったためCentOS7にしました。[^2]

## ポートフォワードの設定
外部からWebサーバへのトラフィックを自宅サーバに流すように設定します。
[こちらの記事](https://zokibayashi.hatenablog.com/entry/2017/11/07/001411)のClientPCをVPSのグローバルIP、WebServerを自宅サーバに読み替えてください。

今回は4230/udpを使用したので、以下のように設定しました。

```bash
external (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: ssh
  ports: 1194/udp 4230/udp
  protocols: 
  masquerade: no
  forward-ports: port=4230:proto=udp:toport=4230:toaddr=10.8.0.2
  source-ports: 
  icmp-blocks: 
  rich rules: 
	

internal (active)
  target: default
  icmp-block-inversion: no
  interfaces: tun0
  sources: 
  services: dhcpv6-client mdns samba-client ssh
  ports: 
  protocols: 
  masquerade: yes
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
```

# 自宅サーバ編
そのままの設定だとサーバとしては動作するものの、ブラウザやzoomなど、他のソフトウェアが一切使えなくなってしまいました。完全にサーバ専用にするつもりはなかったため、サーバーとしての通信以外はVPNを経由しないようにしました。


## OpenVPNのコンフィグ設定
OpenVPNのクライアント（自宅サーバに該当)のルーティングテーブル設定は、VPN接続中のみトラフィックがVPN経由になるよう変更されます。どのような設定になっているかは、VPN接続中にnetstatコマンドで確認します。

```bash
$ netstat -rn

Routing tables

Internet:
Destination        Gateway            Flags        Netif Expire
0/1                10.8.0.1           UGSc         utun6       
default            192.168.0.1        UGSc           en1  
128.0/1            10.8.0.1           UGSc         utun6       
```
VPNの初期設定の場合、`0/1 10.8.0.1`　`128.0/1 10.8.0.1`とあるため、ルーティングテーブルの他の項目に当てはまらない通信はVPN(10.8.0.1)に転送されていることがわかります。

そこで、VPNサーバの設定を変更します。
`/etc/openvpn/server.conf` のredirect-gatewayの設定をコメントアウトしました。

```bash
# push "redirect-gateway def1 bypass-dhcp"
```

VPNサーバを再起動して適用します。自分が試した時はfirewallが再始動せず、VPNに接続できませんでした。その場合はfirewallも再始動させてください。

# まとめ
ここまでの設定で通常のPCとしての使用をしつつ、サーバとして公開したいポートのみ公開することが出来るようになりました。

# 助けてくれた人たち
@YYBatt さん : 色々なアドバイス、デバッグ等、全体的に助けてもらいました。
[きょー。 / Yukiho](https://twitter.com/kyosan34_yukiho) さん : ConoHaへのOpenVPN構築/Firewall設定で助けてもらいました。 

[^1]: UDPホールパンチングができなかった
[^2]: https://qiita.com/jre233kei/items/51c22d17ba07ab4205df
キューイングやバックグラウンドジョブへの考え方

rubyのsidekiqというqueueに詰めて非同期でjobを実行できるライブラリがあるのですが、いつタスクをqueueに詰めてtaskを実行すればいいかを悩んだためまとめてみようと思います。

# なぜbackground jobが必要なのか？
端的に言えば、めちゃくちゃ重い処理は別processなどで動かさないとメインの処理が止まってしまうからです。一番わかりやすいのはnodeだと思います。
nodeはシングルスレッドシングルプロセスで駆動するため、数十秒かかるようなDBへのqueryや画像処理などの重い処理を入れると全ての処理が止まります。これがAPIなどの場合スループットに大きな影響が出ることが懸念されます。

# background jobの種類
ではbackground jobの種類、とりわけ起動の起動の仕方はどういったものがあるのかと考えた場合に大きく二つがあると思います。

### イベント駆動型
なんらかの別の処理から起動して処理が走るタイプ。
わかりやすい例としてはwebhookやfluxもイベント駆動になると思います。

### スケジュール駆動型
特定の日時に処理を起動させるやり方。
代表例はcron。

## back ground jobの扱い方(イベント)

例としてAPIを考えた場合、APIのプロセスからqueueに詰めるタスクは戻り値を考慮しないもののみにすべきだと思います。
例えば、何かユーザーが予約処理したとして結果を即座に受け取らないとユーザーに対して適切にメッセージを表示できません。ユーザーからしてみれば、予約をして即座に成功の可否を表示しないと誤解を招くことになると思います。

もし、仮にタスクの実行結果を受け取りたい場合は別個にそれ相応のアーキテクチャー、それこそイベント駆動のようなものが必要だと考えないといけません。それを無視してqueueに詰めまくるのはアーキテクチャーの複雑性を増大させ自分の首を絞めます。

## back ground jobの扱い方(スケジュール)
次にスケジュール駆動型の場合でこれもAPIを考えましょう。なんらかの処理を特定の時間に実行させることを考えた場合、問題は問題はその時間を設定するタイミングいつか？ということです。もし相対的なスケジュール(処理を受け取って10分後にタスク実行)とかでなく絶対的なスケジュール(夜の1時に実行/毎分ごとに実行)の場合はAPIの中でqueueに詰めるべきではないと思います。なぜなら、APIはrequestを受け取ったタイミングで処理が実行されるため、根本的に絶対的なスケジュールと実行するタイミングが違います。この実行タイミングが違うものを一つのコードで表現すると密依存になってしまいます。

それでも必要な場合、taskをqueueに詰める代わりにDBに実行対象の情報やフラグなどをもたせて、cronかなんかでtaskを実行させて、taskの中で実行対象の情報を取得して処理させるべきだと思います。

# 最後に
これは個人的な考え方なので、こんなやり方があるよ！があればぜひ教えてください。
それでは良い background job ライフを!



# 参考資料
https://docs.microsoft.com/en-us/azure/architecture/best-practices/background-jobs
SQL文チートシート ~複数テーブル結合~

自分用のSQLチートシートです。

* Inner Joins
* Left Joins

### 使用するテーブル

paper_magazinテーブルスキーマ

| name | type |
| :---: | :---: |
| id | INTEGER |
| name | TEXT |
| email | TEXT |

paper_magazinテーブルデータ

| id | name | email |
| :---: | :---: | :---: |
| 1 | James |james@email.com |
| 2 | Matt | matt@email.com |
| 3 | Erin | erin@email.com |
| 4 | Chris | chris@email.com |
| 5 | Zan | zan@email.com |

online_magazinテーブルスキーマ

| name | type |
| :---: | :---: |
| id | INTEGER |
| name | TEXT |
| email | TEXT |


online_magazinテーブルデータ

| id | name | email |
| :---: | :---: | :---: | :---: | :---: |
| 1 | James |james@email.com |
| 2 | Matt | matt@email.com |
| 3 | Erin | erin@email.com |
| 6 | Jason | jason@email.com |
| 7 | Curry | curry@email.com |

## Inner Joins
`JOIN`（inner joinと呼ばれている）を使って２つのテーブルを結合する場合は`ON`の条件に合う結果だけが得られます。

```magazine.sql
SELECT *
FROM paper_magazine
JOIN online_magazine
  ON paper_magazine.id = online_magazine.id;
```

SQL結果

| id | name | email | id | name | email |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| 1 | James |james@email.com | 1 | James |james@email.com |
| 2 | Matt | matt@email.com | 2 | Matt | matt@email.com |
| 3 | Erin | erin@email.com | 3 | Erin | erin@email.com |

## Left Joins
`LEFT JOIN`は`ON`の条件に合わないものも含めて結合されるテーブルの全ての行を残します。

```magazine.sql
SELECT *
FROM paper_magazine
LEFT JOIN online_magazine
  ON paper_magazine.id = online_magazine.id;
```

SQL結果

| id | name | email | id | name | email |
| :---: | :---: | :---: | :---: | :---: | :---: |
| 1 | James |james@email.com | 1 | James |james@email.com |
| 2 | Matt | matt@email.com | 2 | Matt | matt@email.com |
| 3 | Erin | erin@email.com | 3 | Erin | erin@email.com |
| 4 | Chris | chris@email.com | NULL | NULL | NULL |
| 5 | Zan | zan@email.com | NULL | NULL | NULL |

## その他のチートシート
[SQL文チートシート①](https://qiita.com/takayuki-nakamura/items/dbb22b896bc344211089)
[SQL文チートシート②](https://qiita.com/takayuki-nakamura/items/00b32558febff89fc55a)
[Laravel6.x]ルーティング 備忘録

##はじめに
この記事はプログラミング初学者による備忘録用の記事であり、また、少しでも他の初学者のお役に立てればと思い書いています。

今回は、``Laravel6.x ルーティング``に関して再度インプットを行いましたので、初見及び忘れそうな知識について記録しておきたいと思います。

※知識が増え次第、随時更新

間違いなどがございましたら、ご指摘のほどよろしくお願い致します。

##目次
・グローバル制約
・フォールバックルート
・名前付きルートへのURLを生成
・擬似フォームメソッド

##グローバル制約
``グローバル制約とは``
正規表現でルートパラメータを制約したい場合は、RouteServiceProviderのbootメソッドの中で、patternメソッドを使いパターンを定義する。

``使い方``
正規表現をルート定義したルートパラメータに適応させたい場合に``app/Providers/RouteServiceProvider.phpのbootメソッド``内で設定を行うようにする。

``例``

```app/Providers/RouteServiceProvider.php
/**
 * ルートモデル結合、パターンフィルタなどの定義
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+'); //追記する
    //このように指定することでパラメータ名を使用している全ルートで自動的に提供される

    parent::boot();
}

```

```web.php
//略
Route::get('user/{id}', function ($id) {
    // {id}が数値の場合のみ実行されるようになる
});
```
``補足``
ルーティングに直接バリデーションをつけることも可能

```web.php
Route::get('foo/{id?}', 'FooController@index')->where('id', '[0-9]+');
```

##フォールバックルート
``フォールバックルートとは``
受け取ったリクエストが設定したRouteと一致しない場合に適用されるルーティングのこと

``使い方``
基本的に処理できないリクエストに対しては自動的に"404"ページが表示されるが、routes/web.phpファイルにフォールバックルートが定義されていれば、webミドルウェアグループの中のすべてのミドルウェアで、フォールバックルートが適用されカスタマイズした特定のページ表示をすることができる。

``例``

```web.php
//この記述を入れたい場合はルート登録で一番最後に記述する
Route::fallback(function () {
    //
});
```

##名前付きルートへのURLを生成する(パラメータ定義)
``名前付きルートの生成とは``
名前付きルートは特定のルートへのURLを生成したり、リダイレクトしたりする場合にメリットが生まれる。ルート定義にnameメソッドをチェーンすることで、そのルートに対して名前をつけることができる。

ルートに一度名前を付ければ、その名前をグローバルなroute関数で使用すれば、URLを生成したり、リダイレクトすることが可能になる。

``使い方``
ルートでパラメータを定義している場合は、route関数の第２引数としてパラメータを渡すことで、指定されたパラメーターが自動的にURLの正しい場所へ埋め込まれる。

``例``

```php
//名前付きルートにする
Route::get('sample/test', function () {
    //
})->name('test');

// URLの生成
$url = route('test');

// リダイレクトの生成
return redirect()->route('test');

//view表示ルートの指定
return view(route('test'));


//パラメータ有り名前付きルートにする
Route::get('sample/{id}/test', function ($id) {
    //
})->name('test');

//URLの生成(route関数の第２引数としてパラメーターを指定する)
$url = route('test', ['id' => 1]);

//配列に新たなパラメータを追記した場合、その[キー => バリュー]は自動的にクエリ文字列として生成されるURLへ追加される。
$url = route('test', ['id' => 1, 'name' => 'hal']);
```

##擬似フォームメソッド

``擬似フォームメソッドとは``
HTMLフォームはPUT、PATCH、DELETEアクションをサポートしていない。
従って、、HTMLフォーム上でPUT、PATCH、DELETEルートを定義する時、擬似フォームメソッドと呼ばれるものを使う必要がある。

``使い方``
フォームに_method隠しフィールドを追加する必要がある。
_methodフィールドとして送られた値は、HTTPリクエストメソッドとして使用される。
_methodフィールドを生成するために、``@method``Bladeディレクティブを使用することもある。

``例``

```php
//@method Bladeディレクティブの使用例
<form action="{{ route('sample.destroy', compact('sample')) }}" method="POST">
    @method('DELETE')
    @csrf
</form>
//formタグではmethod=POSTを指定、タグ内では@method()でアクションを指定する
```

##参考文献
[Laravel6.x ルーティング](https://readouble.com/laravel/6.x/ja/routing.html)
教師あり学習　それぞれの特徴  

最近傍法
・小さいデータに関してはいい感じになる。説明が容易。

線形モデル
・最初に試してみるアルゴリズム。非常に大きいデータセットに適する。非常に高次元のデータに適する。

ナイーブベイズ
・クラス分類にしか使えない。線形モデルよりも高速。非常に大きいデータセット、高次元のデータに適する。線形モデルよりも精度が劣る。

決定木
・非常に高速。データのスケールを考慮する必要がない。可視化が可能で説明しやすい。

ランダムフォレスト
・殆どの場合で単一の決定木よりも高速。データのスケールを考慮する必要がない。高次元の疎のデータは適さない。
・n_estimators、max_depth、max_featuresなどの事前枝刈りパラメータ。n_estimatorsは大きいければ大きいほどいい。過学習を低減できるから。増やすことによって訓練に時間がかかる様になる。max_featuresはデフォルトでいい

勾配ブースティング決定木
・多くの場合でランダムフォレストより少し精度が高い。
・ランダムフォレストに比べは訓練に時間がかかることが予測は高速。パラメータは敏感。
・主要なパラメータは決定木の数を決めるn_estimators、個々の決定木の誤りを補正する度合いを制御するlearning_rate、個々の決定木の複雑さをへらすmax_depth。max_depthは一般に5以下にすることが多い。

迷ったときはランダムフォレストを試してみる。ただ、時間が短いことを重視する場合は勾配ブースティングを試す。ランダムフォレストではn_estimatorsが大きければ大きいほど良かったが勾配ブースティングでn_estimatorsを大きくすると複雑なモデルを許容する事になり過学習を招くことになる。

SVM
・データに僅かな特徴量しかなくても複雑な決定境界を作ることができる。低次元のデータでも高次元のデータであっても（特徴量が多くても少なくても）うまく機能する。
・サンプル数が多くなると機能しない。１万サンプルぐらいまではうまくいく。
・問題点はデータの前処理とパラメータ調整を行う必要がある。また検証が難しい。ある予測がされた理由を理解するのが難しい。

ニューラルネットワーク
・大きなデータセットに有効。データのスケールを調整する必要がある。
・データの前処理に時間がかかる。
・SVMと同様にデータのすべての特徴量が同じ意味を保つ場合に最もよく機能する。様々な種類の特徴量の場合は決定木のほうがいい
・隠れ層は1つか2つで始めて増やしていくといい。

fitはモデルをリセットする。
Nest.js x TypeORMでinitializeが遅い時

# Nest.js x TypeORMでinitializeが遅い時

## 何があったのか？
Nest.jsとTypeORMの構成でバックエンドを作成していた時に、異様にinitializeが遅い時があった。
`TypeOrmModule dependencies initialized +0ms`

詳しい構成としては、Nest.jsとTypeORMのwebサービスとmysqlのDBをDockerizeした構成。
普段の時は問題なかったが、データを更新するためのスクリプトを作成している時にローカルに大量のデータ(gzファイルで2GBくらい)入れたところ、TypeORMのモジュールの初期化がめっちゃ遅くなった。

現状、ファイルを保存するごとに再ビルドしてくれるようになっていたのだが、如何せんアプリの起動が遅すぎるので開発が全然進められずに困っていました。

## 何をやったか
最初はTypeORMモジュールで渡すEntityの指定の仕方を変えてみたり(ファイルのパスから定義配列に変える)、マイグレーションがおかしくなっていないかどうか確認してみたのですが、効果なく。。。

色々試したりしているところで、本番環境では問題なく動いているため、おそらくローカル環境の問題だろうということに気づき始め、ormconfig周りを調べ変更してみたところ。。。解決しました！

その設定というのがormconfigの`synchronize`でした。
結論、これが`true`になっていたことが原因だったようで、これを`false`にし、サービスを再起動してみたところ問題なくアプリが起動されました！

## なぜこのようなことが起こったのか？
結局、`synchronize`が`true`のだとなぜこのようなことが起こるのかについてですが、そも`synchronize`とは
>Setting synchronize makes sure your entities will be synced with the database, every time you run the application.

[TypeORM公式](https://typeorm.io/#/undefined/creating-a-connection-to-the-database)

でも書かれているように、Entityファイルとデータベースとを同期してくれる設定です。これをONにすることで、Entityに何か変更があった際に自動でデータベースの方にも反映してくれるのですが、データ量が多いとどうやら初期の同期に時間がかかるっぽくこのような現象が起こったようです。

開発時はEntityを変更したら自動でDBの構成も変更してくれるので便利ですが、ローカルで大量のデータを使う際はオフにしておくのがよさそうですね！
Swiftのレビュー指摘内容一覧

# はじめに
どうも@kaneko77です。
今回は私が複数人開発でレビューする際の指摘内容などを共有していきたいと思います。

## こんな方対象
ある程度コード書くようになって**レビュー**をお願いされた....
でもどういう観点で見れば良いかわからない。。
そんな方にこの記事を見て少しでも観点を理解してもらうことができればなと思います。
基本コード規約に沿って書けば沿ってないものの指摘すればいいだけですが、
そもそも規約がある所や無い所など現場それぞれですので、規約が無い場合は
[こちらの](https://github.com/jarinosuke/swift-style-guide/blob/master/README_JP.md)GitHub社が公式に出してるSwiftのガイドラインみてくだしい

#私がいつもコードで見る観点の一覧
 - スペルチェック
 - テストコードが通っているか
 - `UITextFieldDelegate `などで使うメソッドの定義位置の確認
    - `override`で定義したメソッドが変なところで定義されていないか(`override`の記載位置はまとまったところに書いた方がよい)
 - MARKコメントを起用しているか
 - クロージャなどでselfを使う際は`[weak self]`をちゃんと書いているか
   - 強参照していないか**delegate**もね　 
 - 同じようなコードを書いていないか
   - 同じ処理ならジェネリクと使うとか同じようなViewならカスタムView作るとかしたらということです。
 - コメントアウトしっぱないしの物がないか(TODOがないなども)
 - 変数の定義について
  - `hoge1`や`hoge2`など同じような名前で定義する際、数字で適当に定義されていないか
  - `ローカル変数` . `メンバ変数` , `グローバル変数`　がそれぞれ正しいところで定義されているか(ローカルでしか呼ばれていないのにメンバ変数で定義しているとかはだめ )
  - `var`と`let`の使い分けができているか
  - クラス内でしか使ってないメソッド等に`private`付けてるか、
 - Network処理などで例外処理をちゃんと書いているか
   - エラーになったら端末落ちちゃうとか論外
 - 何でもかんでもオプショナルで定義していないか
   - この変数`nil`になることないのにオプショナルで定義しているのは無意味
 - if文関連(条件式)
  - if文などネストが深くなりすぎてないか (個人的には２~3個くらいでもう分けなよって言います(ここら辺はコード規約にちゃんと書いてるからそれ通りに))
  - 早期リターンなどちゃんとしているか
 - 色の指定の際、透明色(`.clear`)使ってないか(これはパフォーマスを低下させる原因の一つになります)
 - 強制アンラップしていないか(基本guardなど使った方がk良いです。圧倒的自信がない限り強制アンラップはあぶねぇ)
 - オートレイアウトで可変になるUilabelなど固定値で定義されていないか (`widthAnchor`や`heightAnchor`などで固定にしていないか)
 
# 終わりに
割とこう見ると見るところ少ないですね。
いうまでもなく論理的におかしいコードは指摘しないとです。
まだまだ多分絞り出せば出てくるかもですが、大体コードレビューする際は最低ここら辺は気をつけて見ています。
またアーキテクチャによってここのクラスで定義されているのおかしいよねとか出てくるのもあるので
そこら辺はそれぞれのアーキテクチャを理解してコードレビューすると良いです。
ここまで読んでいただきありがとうございます。
それではいいレビューライフを!!!
【GAS→html　値渡す】①スプレッドシート→htmlへ値受け渡し（ロード、テンプレ読み込み時）


[前回からの続きです。](https://qiita.com/forever---beginner/items/2afe3b48202041297e78)

前提・対象レベルとか、その他記事をまとめております。

次のページ
[②スプレッドシート→htmlに渡した値をテーブル形式に（jquery）](https://qiita.com/forever---beginner/items/307f7609028fa7852755)


###やること

GASで作成したWebページを開く際、

   1. スプレッドシート→GAS（サーバー側、`コード.gs`）で値取得
   1. GAS→javascript（クライアント側、`index.html`）に値受け渡し
   1. javascript→htmlの要素へ値を渡して表示



###スプレッドシート

|  | A | B | C |
|:-:|:-:|:-:|:-:|
| 1 |  地域 | 都道府県  | 県庁所在地 |
| 2 |  首都圏 | 東京  |  東京 |
| 3 | 東海  | 愛知  | 名古屋  |
| 4 |  東北 | 宮城  | 仙台  |
| 5 | 関西 | 兵庫県  | 神戸 |
| 6 |  甲信越 |  山梨 | 甲府  | （）

|![スクリーンショット 2021-05-29 14.41.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/8cdcce88-6569-50ea-56b5-69ceba051413.png)|
|:--|


###結果

Webページ↓

|![スクリーンショット 2021-05-29 14.40.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/681ba435-b855-a086-85af-69410402235b.png)|
|:--|


---
##実際のコード

###GASコード（スプシ→GASで値取得、保持）
```javascript:コード.gs

function valsget() {
  //GASに紐づくスプシ呼び出し→シート名からシート取得　　※シート名相違注意
  let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("テスト");
  
　//範囲を取得→getvaluesで値取得、二次元配列に格納
　let vals = ss.getDataRange().getValues();
  
  Logger.log(vals); 
  //[['地域','都道府県','県庁所在地'],['首都圏','東京','東京'],['東海','愛知','名古屋'],〜〜]をログで出力  
 
  return vals;
}

```


###GASコード（htmlテンプレートの作成、出力）
```javascript:コード.gs
//doGet関数を使う

function doGet(){
  let htmloutput = HtmlService.createTemplateFromFile('index').evaluate();
　//htmlテンプレートを作って再評価。再評価でjsの関数などを読み込み実行

  htmloutput.setTitle('CRUDテスト');
  return htmloutput;
  //htmlテンプレート返す

}


```

###【解説】GAS関数（サーバー）をjavascript（クライアント）で呼び出すメソッド

```javascript
  google.script.run.withSuccessHandler(コールバック関数＝クライアント側js).GAS関数();
  
/*
  1.GAS関数をまず実行
  2.GASで取得した戻り値 → コールバック関数に戻り値を渡す 
  3.コールバック関数=クライアント側jsを実行する
*/

```


###index.htmlを作成→html、クライアント側javascriptをかく

```html:index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>  
    <p id="test"></p>

        
  </body>
</html>



<script>
　
　//webページの読み込み時に実行
  window.onload = function(){

    google.script.run.withSuccessHandler(function(dt){ //valsgetの取得値をdtに渡す
      let testEl = document.getElementById('test');  //要素p取得
      testEl.innerHTML = dt;  //要素pのテキストにdtを入れる
      }).valsget();
  }  
</script>  


```
「Webがは～じまるよー ホラ また僕の番だー 」♪    【WebMTG心得その１：Win+→→↑編】

　さて今回私がご紹介するのは、在宅勤務が１年以上続き、「[もう出社なんてしたいなんて言わないよ絶対～♪][1]」な生活を続けている中で得たWebMTGにおけるTipsです。
　リモートワークが続く中で、社内外問わず会議もオンライン化が浸透してきています。
　そんな中、私もWebMTG（ミーティング）の場数を１年以上こなしてきましたので、それなりにノウハウも溜まってきました。
　今回はその中の１つ、こりゃ便利！な**【Win】+【→→↑】** をご紹介させていただきます。　

[1]:https://qiita.com/takeC74/items/8459ab4718b114707050

#▼ズバリ、【Win】+【→→↑】とは。

　Windows10に搭載されている機能、[スナップ機能][2]です。
　アクティブなブラウザとかアプリケーションのウィンドウのサイズを簡単にリサイズすることが出来る機能となります。
　キーボードの【Windows】キーを押しながら、矢印キーを押すだけです。
　【→→↑】で、画面の右半分、４分の１にリサイズされます。
　【←←↑】だと左半分、４分の１。その他いろいろ矢印を変えてみてください。
　操作を覚えたら、後は気分次第で。
　引用の記事のとおりマウスでドラッグする方法でもできますが、私はマウスを使わない方が「シゴトが出来る」感がするので好きです。

[2]:https://ascii.jp/elem/000/001/053/1053407/

#▼何が「こりゃ便利！」か？

　別にWebMTGの時じゃあなくても「こりゃ便利！」だと思うのですが、今回の話はWebMTG。
　この記事を読んでいる読者の方々はエンジニアの方が多いかと思うのですが、エンジニアの皆さんは日々自分の腕で勝負してますよね。
　だからエンジニアは自分の「心・技・体」が命。
　自身の生産性を最大化するために大型モニターやデュアル・トリプルモニターを装備していらっしゃる方が多いかと思います。
　私もエンジニアの端くれとして、在宅勤務が続くようになって[27インチの4Kモニター][3]を買いました。　
　いやー、めちゃくちゃ快適です。4K綺麗！スプレッドシートも広範囲で表示できる！

　でも、皆さん、誰もが大型モニターとか、4Kの解像度を利用している訳ではないですよね。
　WebMTGの参加者の中には、最大1Kくらいの画面が小さいノートパソコンで参加される方も多いのではないでしょうか？

#▼自分の大画面のウィンドウをWebMTGに投影するとき、このコマンドの出番だ！

　皆さんもご自身の発表資料とかを画面に表示してWebMTGすることもあるかと思います。
　「もう少し画面拡大して！」、「文字小さくて読めない。。」とか言われたことはありませんか？
　特にスプレッドシートとか表示するとき。

　課題管理表とか案件管理表とか、進捗工程とか、その他もろもろ、スプレッドシートを表示して皆でMTGすることは多いと思います。
　私は4Kモニターを購入した当初、上記のように指摘され、Google Spreadsheet（以下、GSSといいます）を使用しているのですが、いつもGSSの「ズーム」機能で拡大率を200％に表示して発表していました。
　（ちなみに現在、GSSは最大200％までしか拡大できません。）

　そこで、この【Win】+【→→↑】の登場です。
　4Kのモニター上でこのコマンドを実行すると、ちょうど画面右半分4分の1にリサイズされます。
　これが、GSSのブラウザを最大表示にして、かつ「ズーム」200％でWebMTG上に表示する画面とちょうど同じくらいの大きさの投影になるんです。

![こりゃ便利.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/d39be5f6-6b39-bbf4-e4da-30dbd925f3ef.png)


　MTG参加者にきちんと画面を見せられる上、自分の4Kモニタも画面4分の１しか占有しない。なので、もう片方にWebMTGの画面を表示することも可能！

　Windows10には、[ウィンドウを左右に並べて表示][4]するという機能もありますが、複数のウィンドウを開いている場合<br>すべてのウィンドウを分割して並べて表示してしまうため、　たくさんウィンドウをひらいている場合は面倒です。
（おや、ここにもスナップ機能が載っているな。）
　このコマンドなら特定のウィンドウを4分の1、2分の1、全画面と切り替えられるのでとっても便利。
　気まぐれでズボラな私にはとっても便利な機能です。

　是非皆さまもお試しください。　

[3]:https://qiita.com/takeC74/items/c05ec5b39e0d17be1971#%E3%81%A7%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%87%E3%82%B9%E3%82%AF%E3%82%B3%E3%82%AF%E3%83%94%E3%83%83%E3%83%88%E5%A4%96%E8%A6%B3

[4]:https://www.pc-koubou.jp/magazine/39024

#▼おまけ
　検証のため、4Kの画面をいろいろ1Kの画面に表示てみましたので参考にしてみてください。
　　●4Kフル表示GSS100％⇒1K meet画面（ちっちゃくて見えない・・・）![4k100_1k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/d20100d9-3448-1113-4d86-eabc2f1de01e.png)
　　●4Kフル表示GSS200％⇒1k meet画面（見える。）![4k200_1k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/dbc157d7-7c9c-9d94-06af-c9d1141849d1.png)

　　●4K4分の1表示GSS100％⇒1k meet画面（見える。私のモニタも広く使える）![4k100q_1k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656547/385ad2fa-7ba1-1abf-a5c2-d88ac141f8b3.png)




　
#Webがは～じまるよー ホラ また僕の番だー♪ 【WebMTG心得その１：Win+→→↑編】は以上です
皆さん、いかがでしたでしょうか？　少しでも皆さんのご参考になれば幸いです。WebMTGの心得小ネタはまだまだあるので、時間みつけてまた書いてみたいと思います。<br>
以上、最後までお読みいただきありがとうございました。
VimでSchemeの色分けとインデントを設定する

ホームディレクトリの.vimrcファイルに以下の4行を追加するとできるようだ。

	filetype plugin indent on
	syntax enable
	autocmd Filetype scheme setlocal autoindent lisp
	autocmd Filetype scheme setlocal expandtab shiftwidth=2

あと、インデントを浅くしたいキーワードは以下のように追加するらしい。

	set lispwords+=call-with-input-file,call-with-output-file

ようだとからしいとか言っているのはあんまりよくわかっていないからだが、ググると出てくる解説ページがあまりにも重厚長大なので投稿してみたw
ロール切替をしてaws-sdk-phpを使う


# ロール切替をしてaws-sdk-phpを使う

環境別にアクセスキー・シークレットアクセスキーを変更せずスイッチロールを使ってアクセス環境を変更してみた

スイッチロールはこちらの記事を参考

https://qiita.com/morita-toyscreation/items/eeba120471cfad628c49

## aws-sdk-phpの導入

PHP側でAWSを使うためaws-sdk-phpを使う
composerを使って導入

*composer.json*

```json
{
  "name": "sample/sample",
  "authors": [
    {
      "name": "morita-toyscreation",
      "email": "morita@toyscreation.jp"
    }
  ],
  "require": {
    "aws/aws-sdk-php": "3.*"
  }
}
```

*インストール*

```
$ composer install
```

## ユーザー追加

ロール切替のポリシー `sts:AssumeRole` ポリシーを持ったアカウントを作成しアクセスキー・シークレットアクセスキーを取得

1. "TargetAccountID" にはスイッチ先のアカウントIDを入力
2. "TargetAccountRoleName" はスイッチ先のロールとして作成したロール名を指定

例：

```json
{
    "Version": "2012-10-17",
    "Statement": 
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::<TargetAccountId>:role/<TargetAccountRoleName>"
        }
    ]
}
```

## PHP側

toyscreation-sandboxにアクセス可能なロールに切替

このコンソール操作をPHP側で行う
![screencapture-signin-aws-amazon-switchrole-2021-05-29-13_39_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59264/89cac6cf-795e-e2db-b2d2-63be4cdecf69.png)


```php
<?php

require '../vendor/autoload.php';


use Aws\Credentials\CredentialProvider;
use Aws\Credentials\AssumeRoleCredentialProvider;
use Aws\S3\S3Client;
use Aws\Sts\StsClient;

// 1. スイッチロールはSTS権限が必要
$stsclient = new StsClient(
    [
        'version' => 'latest',
        'region' => 'ap-northeast-1',
        "credentials" => [
            'key' => "xxx",
            'secret' => "xxx"
        ],
    ]
);

// 2. toyscreation-sandboxにロール切替
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
    'client' => $stsclient,
    'assume_role_params' => [
        'RoleArn' => "arn:aws:iam::097754223854:role/toyscreation-sandbox",
        'RoleSessionName' => 'toyscreation-sandbox',
    ],
]);

$provider = CredentialProvider::memoize($assumeRoleCredentials);

// 3. toyscreation-sandboxはS3アクセス可能
$client = new S3Client([
    'version' => 'latest',
    'region' => 'ap-northeast-1',
    'credentials' => $provider
]);


$objectContent = $client->listObjects([
    'Bucket' => "toyscreation-sandbox",
])['Contents'];

```

`toyscreation-sandbox` `toyscreation-prod` など複数ロールの権限があれば `RoleArn` `RoleSessionName` を書き換えることで一つのアカウントで環境切替が可能

```php
$assumeRoleCredentials = new AssumeRoleCredentialProvider([
    'client' => $stsclient,
    'assume_role_params' => [
        'RoleArn' => "arn:aws:iam::689371460795:role/toyscreation-prod",
        'RoleSessionName' => 'toyscreation-prod',
    ],
]);
```

## まとめ
コンソールアクセスはスイッチロールを使う人は多いが、プログラムのアクセスはあまり見かけなかったのでまとめみた。
アクセスキー、シークレットアクセスキーは最低限にして必要に応じてロール権限を与えることでセキュリティ、管理が楽になった

---

いいね！と思ったら LGTM お願いします :clap::clap::clap:

【PR】週末ハッカソンというイベントやってます！ → https://weekend-hackathon.toyscreation.jp/about/
3分クッキング trelloの情報とる、emacsのorg-modeとかに突っ込む

https://qiita.com/siba4848/items/5778e02ce320507dbde4

をpythonでやってみた。今日に割当たってるタスクをさっとターミナルで取りたいとき使う

# trelloから情報取得
諸兄におかれましてはオレオレスクリプトを保持してクラウドストレージで共有して運用しておられると思われますので
そのあたりに適当に書けば良いかと

```python
#! /usr/bin/env python3
import requests
import json

key = "キー"
token = "トークン"
list = "リストID"
url = "https://trello.com/1/lists/" + list + "/cards?key=" + key + "&token=" + token

response = requests.get(url)
jsonData = response.json()

for j in jsonData:
    print("%s" % (j["name"]))

```

# emacsで呼び出し
皆様はorg-modeを使っていると思いますのでorg-modeにリストを出せるように簡単な関数作りますね。

```lisp
(defun insert-trello-today()
  (interactive)
  (setq todo
        (shell-command-to-string "/Users/seijiro/.pyenv/shims/python ~/g/scripts/trelloc"))
  (print todo (current-buffer))
  )
```

以上です。
MacBookM1チップでもOpenSiv3Dを使いたい！



備忘録。かなり前の記事でいろいろやりました。 
https://note.com/kunidai/n/nc3fccfb7be06 
前使ってたMacの寿命がきたので新しいMacを買いOpenSiv3Dを使おうとしたらバグったので直し方をメモします。

# 環境
MacBookAir(M1,2020) Big Sur Ver.11.4 (古いパソコンからデータ全部持ってきた)
Xcode : Ver.12.5

# 前提
今のMacはApple独自のM1チップ(CPUやGPUなどを一纏めにしたもの)を使っていてこれまでの製品と比較して処理速度が少し上がったにもかかわらず消費電力が半分（充電の持ちが倍）という謎ハイスペックになっております。
そのせいで一つ前のMacBookProより今のMacBookAirの方が性能が良い逆転現象が起こっているとか。
そのへんはどうでもいいんですが、問題は「パソコンのCPUやGPUがこれまでと全く異なる」ということです。
M1チップでIntel製のチップの動作を再現するアプリは配られているのでIntel製でしか動かないソフトも問題なく動かせるのですがめちゃくちゃ問題が起きそう。
というか実際問題起きてるからこれ書いてる。つらい。
でも本当にこれが原因なのかもわからない。


# エラー： The linked library 'libogg.a' is missing one or more architectures required by this target: arm64.
(これと同様のエラーが20個ほど出る。)

###### 解決法： Bulid Setting -> Excluded Architectures に arm64 を追加
![スクリーンショット 2021-05-29 11.57.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636677/27ff3938-56d8-0c25-c3ef-eb5b49bcf2b5.png)

これでこのエラーは消失しました。しかし新たな警告が出現。

#警告： Object file (../../lib/macOS/boost/libboost_filesystem.a(path_traits.o)) was built for newer macOS version (10.15) than being linked (10.14)
（これと同様の警告が7つほど出る）

よかった。警告になったし取りあえず動く。一安心。
なにやらMacOSのバージョンが問題のようだ（英弱）。
以前のMacでは容量が足りずにMacのバージョンを上げるのを渋っていたのでそこに警告が出るのは自然に思える。
とりあえずバージョンに関係ありそうな設定を変えてみよう。

######解決策： Bulid Setting -> macOS Development Target を macOS11.3 (Max)に変更してみる

これで警告は消えました…が。

#エラー： Command CodeSign failed with a nonzero exit code
（詳細に resource fork, Finder information, or similar detritus not allowed とも書いてある。既存の警告は全て消えている。）

なんかエラー出た。分かりそうな英文です。「コマンド『CodeSign』が0でない返り値を返し失敗しました」とのこと。
警告ではなくエラーなのでプログラムは動かなくなりましたが先へ進んでいるものとみなして解決策を探ります。
CodeSignはSignなので暗号か証明書に関わっていそうです。
が、そんなことは無視してエラーメッセージで検索します。

https://qiita.com/shoukitsuda0310/items/784146486905d5551d69

https://qiita.com/ichishun87/items/da5a96a11885f58eef6b

これらを参考に Terminal で次のように打ち込みます。 

```terminal:terminal
cd ~/Downloads/siv3d_v0.4-2.3_macOS/examples/empty
xattr -rc .
```

（Siv3Dのファイル名にはバージョン名[v0.4-2.3]が含まれているためこのまま実行してもたぶん動きません。また、ファイルの位置をDownloadsから動かしていても失敗します。適宜変更しましょう。）

エラーも警告も全て消えました！




…と思いきやプログラムを少しでも書き換えると先程のエラーが再び出てきます。プログラムを書き換えるごとに先のターミナルのコマンドを実行すれば問題はありませんが、人はそれを問題があると呼びます。手間です。


これを解決するために、キーチェーンアクセスから証明書を消してみたり鍵を全てロックした後解除してみたり新しいパソコンの方でXcodeの新しい証明書を作ってみたりしましたが、以下の手順で解決できました。

1.プログラムをデスクトップから他のディレクトリに移す

以上。
何があったのかさっぱりわかりませんが、動けばヨシ！！
おそらくは「デスクトップ」がiCloud対応のディレクトリだったために勝手にデータの一部が欠損するなどしていたと思われる。（というか他に候補がない）
TortoiseGit ランキング

TortoiseGit使い始めるのに参考させてもらった記事

#第1位
https://qiita.com/Shi-nakaya/items/43c858ea707770c03b17
#第2位
https://qiita.com/silversink8888/items/605cb3d0e9647ae510e4
#第3位
https://qiita.com/piepie1231/items/1745587f128f0936f336
#第4位
https://qiita.com/MakotoIshikawa/items/db67029bd65291e75d89

#その他
https://qiita.com/washio12/items/06098cb3cf1e2a6a39a9
https://qiita.com/kyophp/items/680dae4e67e6300f7dd4

わかりやすい記事をいつもありがとうございます
Spring BootでREST API(ハローワールド級)を急いで作った

# 背景
必要に迫られている。REST APIを作るのを。
やらなければならないがやったことはない。やるしかないのだ。

## とりあえずはハローワールドでいいんだ(テキストは見つけた)
https://spring.pleiades.io/guides/gs/rest-service/

### 環境構築だ
* 「Eclipse Spring Tool Suite (STS)」のセットアップ
* とその日本語化

まぁこれはさすがにできた。

### プロジェクトを用意する
いろいろ書いてあるが３通りあると見た。
* Eclipseの入門コンテンツから作る
* gitから持ってくる
* Spring Initializrで作る

ここでは「Spring Initializr」をチョイスした
デフォルトで「GENERATE」ボタンを押すとzipができてダウンロードした
zip解凍 → STSの「ファイル」→「ファイル・システムからプロジェクトを開く」で取り込む

どれもピンとこなかったのでここが一番苦労したといっていいだろう

### リソース表現クラスを作成する/リソースコントローラーを作成する
この辺は、クラスを作ってソースをコピペでいい

この時点で、STSのBootダッシュボードから起動していい動作確認ができた
ここで終わりでもよかったが手順に続きがあるので、進むしかない。
ゲームのダンジョンでボスを倒してもダンジョン内はすべて徘徊したいタイプ

### 実行可能 JAR を構築する
GradleかMavenで手順が分かれるところだが、Mavenを選択している

これは余談だが、Mavenの読み方がわからないので声に出すのが怖い
ネット上の情報で、カタカナもいろいろあったり、そもそもイントネーションがわからない
ユーチューブで日本語読みを聞いても安心感を得られないので、できる限り声に出さないようにしている


コマンドはこちら。windows環境用です。
インポートしたプロジェクトに一緒に入っていました

```
mvnw.cmd
```

起動する場合は

```
.\mvnw.cmd spring-boot:run
```

実行可能Jarを作るには以下だそうだ

```
.\mvnw clean package
```

何も考えず実行するとエラーがでた

```
Error: JAVA_HOME not found in your environment.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.
```

JAVA_HOMEがない。環境変数を作ってない。
javaはあるはずなんで探すけど見つからない。
unixのwhichコマンドみたいのがwindowsであるかと調べたら
あるらしい。これは一番の収穫だ

```
where java.exe
```

そんなこんなでとりあえずJAVA_HOMEを作って実行したら
うまくいった

```
SET JAVA_HOME="C:\..." (binは含んではいけないらしい)
.\mvnw.cmd spring-boot:run
```

これで完了した
テキストの最後の要約。大げさ感はあるが次につながる良いメッセージだと今は思う

>要約
>おめでとう！ Spring を使用して RESTful Web サービスを開発しました。

# 最後に
急いでやったからすぐ忘れると思う。
見直したいときのために自分用のメモとして残しておく
駆け出しエンジニアのAWSクラウドプラクティショナー学習記録2日目

## AWSにおけるセキュリティ

### AWSとユーザーはそれぞれクラウドのどこに責任をおうか？

- AWS…クラウドの本体(リージョンやアベイラビリティゾーン)
- ユーザー…クラウド内部(アップデート、セキュリティグループなど)

### AWSのセキュリティ面でのメリット

- データ安全性が保護されている
- コンプライアンスが担保されている
- ユーザーが独自に施設を管理しなくていい
- ビジネス規模に応じてスケーリング可能

### セキュリティに対するAWSの責任

物理面で以下の責任を負う

- 自然災害対策…リージョン間を物理的に離すことで特定のリージョンが自然災害にやられても大丈夫なようにする
- 冷暖房や消火設備の管理
- データレイヤーに対するアクセス制限

### セキュリティに対するユーザーの責任

- ID/PW…MFA多段階認証を導入するなどして保護すべし
- ルートアカウントを用いずにIAMで最小限の権限を使うべし
- キーペアを厳重に管理…使用できるユーザーを制限しましょう。
- API keyの管理…ソースコード直じゃなくて環境変数にしましょう。

### セキュリティのベストプラクティス

- 通信データの暗号化…HTTPSなど安全な通信を使いましょう。
- 蓄積データの暗号化…ストレージやDBを暗号化しましょう。
- AWS資格情報の保護…ルートアカウントは使わずにIAMを使いましょう。
- アプリケーションの安全性の確保…XSSやSQLインジェクションなど対策しましょう。

### AWSのセキュリティ監査

第三者の監査が定期的に入っている→AWS Artifact
Androidアプリのパフォーマンス 改善①（Map、Set）

この記事では、Androidアプリのパフォーマンス改善のための、方法について記載しています。

### 改善対象
MapやSetを特定の条件で絞りたい場合、filter関数を使うことがあると思います。
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter.html

filterはとても便利な関数ですが、パフォーマンスとしては注意が必要です。

### 計測
1から１００までのキーを持つMapから、キーが９１以上のマップをfilterする場合、JUnitで処理時間を計測したところ、１００００回の平均値で、**26,731ns**でした。

```kotlin
    companion object {
        private const val MAP_SIZE = 100L
        private const val NUMBER_OF_MEASUREMENT = 10000
    }

    @Test
    fun mapTest() {
        val map = mutableMapOf<Long, String>()
        for (i in 1..MAP_SIZE) {
            map[i] = i.toString()
        }
        measurementTime {map.filter { it.key > map.size - 10 }}
    }

    private fun measurementTime(task: () -> Unit) {
        var sum = 0L
        for (i in 1..NUMBER_OF_MEASUREMENT) {
            val startTime = System.nanoTime()
            task()
            sum += System.nanoTime() - startTime
        }
        println("average=${sum / NUMBER_OF_MEASUREMENT}")
    }
```

filter関数は、指定された条件をMapの先頭から検索していくため、要素数が増えると検索する時間も増えます。
上記のMapのサイズを1000にして、条件も９９１以上とすると、**39,850ns**となります。
（ワーストケースを考えて、あえて時間がかかるような検索条件にしています）

### 改善方法
これを改善する方法の一つとして、TreeMapがあります。
上記のテストを下記のように変更することで、処理時間はMapサイズが100の場合は**840ns**、Mapサイズが1000の場合は**829ns**となりました。

```kotlin
    fun mapTest() {
        val treeMap = TreeMap<Long, String>()
        for (i in 1..MAP_SIZE) {
            treeMap[i] = i.toString()
        }
        measurementTime {treeMap.tailMap(treeMap.size - 10L, false)}
    }
```

これは、TreeMapは内部で、２分探索を行っており、Mapのサイズが大きくなっても、検索時間に影響が出にくいためです。

TreeMapにはsubmapがあり、filterと同様に範囲指定も行えます。
https://developer.android.com/reference/kotlin/java/util/TreeMap#submap

Setの場合は、TreeSetがあり、同様の処理（tailSet、subSet）が行えます。
https://developer.android.com/reference/java/util/TreeSet
elm327の研究 その4

# 概要

elm327を調べてみた。
接続実験やってみた。

# 環境

クルマ：スバルの軽トラ、サンバーTT2
ドングル：usbのelm327
パソコン：windows vista

# usbのドライバー

cp210xで、自動インストール
com12と、認識

# obdコネクタ

ハンドルの下、左側でプラプラしてた。

# シリアルコンソール

tera termを使用。

# ボーレイト

３８４００

# 接続プロトコル

ISO-14230-4(kwp FAST)

# 結果

取得できず。

```
>010c
7f 01 11
```

以上。
Prettier が Markdown の和欧文字間にスペースを入れる事で文字化けに遭遇し，回避した方法

# 導入

GITHUBのREADMEを日本語で作成したら，なぜか�という文字化けに遭遇...
文字化けの所のパターンを考えてみれば，なぜか日本語でリンクをつけた場合が多い...英語では大丈夫なのに！
[�日本語]()


# 犯人 ~~原因~~

犯人はPrettierでした．
なんだか和欧文字間にスペースを勝手に入れるけど(今まで特に気にしてなかった😂)，これがリンクの構文にも下のように勝手にスペースを入れてました！

```
[ 日本語](リンク)
```

# 解決策
空白を勝手に入れないようにするPluginを作ってくださった方がいらっしゃいました😍
根本的な解決策を求める方は下の記事を読んだほうが絶対いいと思います！
[和欧文字間（漢字仮名と英数字の間）に半角スペースが挿入されないようにするPrettier Markdownプラグインを作った](https://qiita.com/tats-u/items/bcbfe2bb4e71bf0a2b87)

# 回避策
すごい plugin を見つけましたが，スペースそこまで気にならないし（ない方が好みだけど）...
もっと手軽に文字化けをなくす方法ないかと思いました．．．
そこで，私が見つけた回避策は span tagを利用することでPrettierが空白を入れないようにする事です！

```
[<span>日本語</span>](リンク)
```
スプレッドシート⇆html 双方向の値受け渡し　CRUD（追加更新・削除）処理　（GAS、javascript、jqueryのみ）　


###◆やりたいこと
- スプレッドシート⇆html の値受け渡し
- 双方向バインドっぽいCRUD処理

###◆完成形


#####スプシ

|![スクリーンショット 2021-05-29 22.10.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/f8c0ce1e-7b25-cac5-f902-75bd379ea808.png)|
|:--|


#####webページ

|![スクリーンショット 2021-05-29 22.09.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1563301/0abc7b27-de5c-baf5-3518-b7e07606086e.png)|
|:--|


**※date型は、gas→htmlに渡そうとするとエラーになり、文字列に直す必要があるようです。**

###◆記事にする理由
　まとまっている記事が見当たらなかったり、良さげなのもvueとか入れて難しかったり


###◆対象

- webエンジニア目指してる方、駆け出しの方
- htmlとcssとjavascriptをちっとは勉強した方 
- jqueryはどう書くか、メソッドチェーンが何かがわかっている程度（ネットで少し検索した程度でも大丈夫と思います
 

###◆目次

[①【GAS→html　値渡す】スプレッドシート（サーバー）→html（クライアント）へ値受け渡し（ロード、テンプレ読み込み時）](https://qiita.com/forever---beginner/items/8e6f1e9c019070d43954)
[②スプレッドシート→htmlに渡した値をテーブル形式に（jquery）](https://qiita.com/forever---beginner/items/307f7609028fa7852755)
[③【html→GAS 値渡す】webページでテーブルの行削除→同時にスプレッドシートも同じ行削除](https://qiita.com/forever---beginner/items/88878e4ccd474a73dfed)
[④【html→GAS 値渡す】webページでテーブルの行追加→同時にスプレッドシートも同じ行追加、データ挿入](https://qiita.com/forever---beginner/items/da006c9821de98663322)


###◆GASのメリット

- 環境構築不要
- スプレッドシート＝サーバーとするので、データがどのような形で入っているかわかりやすい
- サーバー不要なので、業務で使える（会社がGoogle Workspaceを導入している場合特に）
- javascriptとほとんど同じなので、学習コストが低い
- vue.jsとかjsのライブラリが使える
- フロントエンドまわりはGASだけで結構学べる

まとめると、**初学者向き（フロントエンド）**・**実務でも使える**・****


###◆GASのデメリット
- 利用者が少ない = ソースが少ない
- サーバー周りの学習は別途必要（sql、サーバーで動作する他のプログラミング言語）
- 楽すぎる（環境構築周辺、MVCのフルスタックなライブラリ学習には足りない）
namespaceを使ってdeviseで管理者設定

# 管理者って？
普段使ってるサービスは、大半がユーザーとして使っていると思いますが、管理者の画面も必要ですよね？

たとえば、ECサイトなら商品を選んで注文確定までの流れが、普段行っているユーザー側の機能です。
管理者側の流れは、売りたい商品の登録や顧客管理、注文の管理などが挙げられます。

ユーザーと管理者の動きって全然違いますよね。
ユーザーと管理者を分ける必要があるので、今回はその方法を解説していきます。

# 対象となる方
deviseで管理者(admin)を設定したい方向け

そもそもdeviseってなに？って方はこちら
[deviseのかんたん導入手順](https://qiita.com/nakachan1994/items/302bde68cfa453533be7)
[さくっとdeviseをつかってみる](https://qiita.com/nakachan1994/items/91af6ecaf7066697fb5f)

# 開発環境

> ruby 2.6.3
> Rails 5.2.6

# 管理者追加
前提として、deviseでユーザー側の機能は追加済みと考えて進めていきます。

ターミナルで管理者を追加します。
管理者はnameカラム等いらないためそのままmigrateします。

```
$ rails g devise Admin
$ rails db:migrate
```

これで、adminのルーティングとモデルが作成されました。

管理者はあらかじめデータを登録しておき、新規登録せずにログインのみしたいため、`seed`ファイルに初期データを格納します。

```db.seeds.rb
Admin.create!(
   email: 'test@hoge.com',
   password: 'testhoge',
)
```

初期データ追加したら、ターミナルでseedファイルを反映させます。

```
$ rails db:seed
```

ログイン画面使いますので、ビューも作成しておきましょう！

```
$ rails g devise:views admins
```

# コントローラー、ビューの作成
ここまでで、管理者の追加が完了しました。

ECサイトを想定していますので、商品関連のコントローラーとして`products`コントローラーとビューを作成します。
ユーザー側と管理者側はpublicとadminで、呼び出されるコントローラー、ビューをわけていきます。

ユーザー側は商品のindex,showページを作成します。

```
$ rails g controller public/products index show
```

これで、ユーザー側のindex,showページのコントローラーとビューが作成されました。

次に管理者側のコントローラー、ビューの作成をしていきます。

管理者側は商品のindex,show,new,editページを作成します。

```
$ rails g controller admin/products index show new edit
```

これで、ユーザー側と管理者側のコントローラー、ビューを分けることができました。

`app/controllers/admin`の中に管理者側のコントローラー
`app/controllers/public`の中にユーザー側のコントローラー

`app/views/admin`の中に管理者側のビュー
`app/views/public`の中にユーザー側のビュー

があることが確認できたと思います。

`admin/products_controller.rb`の1行目が`class Admin::ProductsController`になってますので、これでadminのproductsコントローラーが呼ばれたら、`admin/products_controller.rb`のファイルが実行されることがわかります。

```admin/products_controller.rb
class Admin::ProductsController < ApplicationController
  def index
  end

  def show
  end

  def new
  end

  def edit
  end
end

```

# ルーティング変更
コントローラーの作成時に`admin/コントローラー名`をつけると`namespace`が使えます。

このnamespaceがあることで、adminとpublicの処理をわけられています。
ルーティングをresourcesに変更しましょう。

```config/routes.rb
Rails.application.routes.draw do

  devise_for :admins
  devise_for :users
  root to: 'homes#index'

  namespace :admin do
    resources :products, only: [:new, :create, :index, :show, :edit, :update]
  end
  namespace :public do
    resources :products, only: [:index, :show]
  end

end
```

`rails routes`で確認してみましょう。

![スクリーンショット 2021-05-29 11.48.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1554142/0c83e423-6b17-b636-fff3-280eb16be471.png)
しっかりadminとpublicでわかれていますね。

# まとめ
これで、namespaceを使った管理者設定ができました。
あとは、必要なコントローラーやビューを管理者側とユーザー側で追加して行って、ECサイト作成していってください。

はじめてやったときは、なかなか理解ができなかったので、まだ理解できていなかった初心者の方の役に立ててれば幸いです。

あと、ECサイトの作成途中で`devise_for`と`namespace`の順番を逆にしていてエラーが起きたので、`devise_for`を上に書くのをおすすめします。
【Docker】run コマンドをさらに詳しく。runとstart の違い。no.4

![パンプキン カフェ (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/7e7fdfc2-6821-0c1b-badd-8d0f6313a2ca.png)


こんにちは。まゆみです。

Docker に関する記事をシリーズで書いています

Dockerを使っている方なら、コマンド『run』を使わない日はないですよね。

ただ、Docker には<font color="Red">run の他に『start』コマンド</font>もあり、両者は似て非なるものです。

今回の記事では

>run と start　コマンドの違い

を詳しく解説していきたいと思います。

ではさっそく始めていきますね。

#run　コマンド

run コマンドは実は、二つのコマンドの機能が組み合わさってできています。

>run = create + start

![見出しを追加 - 2021-05-29T100042.926.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/ef5bf871-4cca-4bb1-8c55-4231b6b18585.png)

Docker Container を最初から作ってデフォルトのコマンドまで実行したい時は　<font color="Red">run</font>

既にDocker Container が作られている時、そのContainer を実行するには　<font color="Red">start</font>


ということになります

runがcreate と start が組み合わさってできているものだと分かったところで、ではcreate とstart は何をしているのか見てみましょう

#create とstartがしていること

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/06399915-7ba0-b112-8b28-cb16d755ece0.png)

create というのはDocker Image からContainer を作りますが、その時Docker Imageにあるファイルシステムのスナップショットを引っ張ってきてContainerを作ってくれます。

create の仕事はここまでです。

Image のなかにはそれぞれ、デフォルトのコマンドがプログラムされていて、それが 『start』のコマンドをうつことによって実行されます


では実際にhello-world のContainer を

>run 

>create + start 

でそれぞれ実行してみましょう


#run で実行

![2021-05-29_10-49-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/df82e9d4-f09e-a99d-3237-46517e2c2402.png)

```
docker run hello-world
```

でデフォルトコマンドの実行までしてくれます


# create とstart で実行

![2021-05-29_10-52-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/7aab223c-dd36-65bd-c6ae-37ec1c5224a4.png)


>①docker create hello-world　を実行すると、Container ID のみ返されます。

>②docker start <container ID>を実行すると、Container ID のみ返されます

>③docker start -a <container ID> で実行すると、デフォルトのコマンドを表示して実行してくれます

ということで、

run = create + start 

であるわけですが、

<font color="Red">run は-a を付けなくても、デフォルトのコマンドを表示してくれるのに対して、start は　-a を付けないとデフォルトのコマンドを表示してくれない</font>

という違いもありますので、頭の片隅に置いておいてくださいね。


#デフォルトのコマンドを上書きした場合はどうなるか？

```
docker run <container ID> (別のコマンド)
```

でデフォルトのコマンドを(別のコマンド)に上書きする事ができます

ただ、そのコマンドがContainer の元になっている<font color="Red">Imageのファイルシステムにない場合は上書きする事はできません。</font>

例えば、hello-world はechoのコマンドが入っていないので、

```
docker run hello-world echo hi
```

としても、

hi を返してくれません。


ただ、『busybox』Imageには、ファイルシステムにecho のコマンドが入っているのでデフォルトのコマンドをechoのコマンドに上書きする事ができます。
(下記参考)


![2021-05-29_11-50-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/a09bbb3a-7e8b-05b5-aa6e-523471c34c30.png)



busyboxを使ってcreate とstartによってContainer を作ったあと、デフォルトのコマンドと上書きしたコマンドがどうなるか見てみましょう


![2021-05-29_11-39-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/d8ab5cbc-9a4e-6dc9-2790-0e6c12ac318b.png)

上の実行結果のスクショから

>①createでデフォルトのコマンドが『echo hi』に上書きされたContainer を作る

>②start -a でContainer を実行すると、上書きされたコマンドの実行結果を返される

>③ただ、さらに上書きする事はできない

ただ、run コマンドでは毎回上書きされたコマンドが表示されます。


![2021-05-29_11-44-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/00436f4f-bb82-abe3-6927-e44cde75ce58.png)

なぜなら、run では、Image から引っ張ってきてContainerを新たに作るからです。


#まとめ

今回の記事はここで締めくくらせていただきます

runとstart　の違いを理解するのにお役に立てたなら幸いです。
Codeforces Round #723 (Div. 2) C. Potions トラックと燃料問題、プライオリティキュー

https://codeforces.com/contest/1526/problem/C2

蟻本の亜種までわかっていて解けませんでした。

類題は蟻本P.73です。その問題は以下の問題を「マイナスを絶対にとらないといけない。一瞬でもマイナスになってはいけない。最小で飲まないといけないプラスのポーションの数は？」です。

# 題意
- 左から順に$n$個のポーションを飲むか、飲まなくて良いです。それぞれ$a_i (0\ leq i < n)$の値を持ちます。
- 最初のHPは0で、各ポーションを読むと$a_i$分HPが変動します。
- HPがマイナスにならないように(0はok) 最大いくつのポーションを飲めますか？最大値を求めてください。

# 最初に考えたこと。
マイナスでないポーションをすべて飲んでよいことは分かります。総和を考えて、小さい順に飲んでいくことを考えますが、$[3, -4 -98, 100, -10, -10, -10]$といったケースを考えると、プラスの合計が大きい$(101)$でも、小さいポーションを飲めるとは限りません。

# こう考えた
最大化したいのは数です。
考え方自身は変わらないのですが、"最初に考えたこと"と同じく、マイナスのポーションは小さい順に飲んでいきたいですが、これは逆にいうと、大きい順に飲まなければ良いです。

これを$O(N)で計算します。次の例を使います。$[4, -3, -2, -2]$。次の動作を左から順に行います。

- プラスか0の場合、hpに足します。(例では4です)。飲んだカウントを++します。
- マイナスの場合、まずは飲んだと仮定しhpに足します。飲んだ数を++します。もし、今のhpがマイナスになったら、これまでのポーションの中で、一番小さい(マイナスが大きい)ものを飲まなかったことにします。つまり、一番小さい値を引き、飲んだ数を--します。
    - 例では最初の4は飲め、hp1になります
    - 次に-3を飲むとhp-2になりますが、過去に飲んだ[-2, -3]のうち、(おなじ1個を捨てるなら) -4を飲まなかったことにします。-4を戻し(引き)ます。 
 
マイナスになった場合、戻すポーションは1つです。自分自身を一度飲んだことにするため、(このポーションに到達瞬間はhpは負ではなかったのですから)、自分のポーション1つを飲まなかったことにすればよいです。

- 例えば、$[4, -2, -3, -2]$ だったとします。1つめはhp=4, 2つめはhp=2になりここで2飲めます。3つ目を飲むとhp=-1になるので、[-2, -3]のうち、今飲んだ、-3をなかったことにします。

# 実装
優先度付きキューを使います。

```C++
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, begin, end) for(int i=(begin),i##_end_=(end);i<i##_end_;i++)
#define REP(i, n) FOR(i,0,n)
using ll = long long;
int main() {
    int res = 0;
    int N; cin >> N;
    ll x;
    ll total = 0;
    priority_queue<ll> q;
    REP(i, N){
        cin >> x;
        total += x; res++;
        q.push(-x);
        if(total < 0) {
            --res;
            total += q.top(); q.pop();
        }
    }
    cout << res << "\n";
}
```

https://codeforces.com/contest/1526/submission/117718259
よく使うVSCode拡張機能

# 拡張機能共通事項

Visual Studio Code の設定優先度
デフォルト設定 < ユーザー設定 < ワークスペース設定

## Prettier - Code formatter
コード整形ツールで、ファイルの保存時に自動整形できる。
整形忘れでリポジトリが汚れるのを防止できるため、チームでバージョン管理する場合は必須かも。


### 自動整形設定手順
初期設定状態では自動整形が無効になっているので、下記の手順で機能を有効にする。

- Settingsメニューを開く。(Windows ：CTRL + ,)
- `editor.defaultFormatter`で`Prettier - Code formatter`を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/a753598d-357d-0884-f597-f090676081c6.png)
- `Format On Save`にチェックを入れる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/6d1369e7-0681-9388-f7d6-312445f591c7.png)
- `Prettier`で検索し、必要に応じてヒットした整形ルールを設定する。

※設定ルールはプロジェクトのルート直下に「.prettierrc」ファイルを配置することでも反映可能


## デバッグ関係
### Debugger for Chrome

## エディター関係
### indent-rainbow
### Brackets Pair Colorizer
### Marp for VS Code
マークダウンビュワー

- pdfやパワポで出力できる。
- gitのREADMEを書く時にも使える。
- Qiitaで書いた投稿をパワポに変換する時にも使える。

## 装飾
### vscode-icons

~~Trailing Spaces
末尾のスペースにハイライトを入れることができるが、全角スペースには未対応…
ファイル保存時に末尾のスペースを自動削除も可能~~
`Prettier - Code formatter`で機能を包含しているので不要になりました。

## リモート開発
### Remote - WSL
### Remote - SSH

## バージョン管理関係
### Git History
### Git Graph
### GitLens — Git supercharged
エディタのコード上にいつ・誰がコミットしたかの概要が表示されるようになる

## スニペット関係
HTML Snippets

## Japanese Language Pack for Visual Studio Code
VSCODEの日本語化

## Unity用の設定
こちらの記事が参考になります。

https://qiita.com/kuronekoieko0305/items/bb2624a77c0e19d50b47
ソケットについて

金曜日の夜だし色々読んでみたのでめもる。



## Unixドメインソケットとソケット

- Unixドメインソケット = 単一マシン上の高効率なプロセス間通信に用いられる機能・インタフェースの一種
- ソケットは、マシンをまたぐ。


### ソケット

TCP/IP郡のトランスポート層は、protocol familyとsocket typeの組み合わせ。全てのprotocol familyは`sys/socket.h`で定義されている。

### Unixドメインソケット

IP の場合は IP アドレス＋ポート番号で接続先を指定するのに対して、UNIXドメインソケットの場合はファイルパスで指定する。



## Ref

- https://ja.wikipedia.org/wiki/UNIX%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%BD%E3%82%B1%E3%83%83%E3%83%88
- https://ja.wikipedia.org/wiki/%E3%82%BD%E3%82%B1%E3%83%83%E3%83%88_(BSD)
【メモ】jupyter notebookのformmater（nb_black）を試してみた

* 製造業出身のデータサイエンティストがお送りする記事
* 今回はメモとして、jupyter notebookのformmater（nb_black）を試してみた。

##はじめに
普段分析する時、jupyter notebookを使うことが多いのですが、自動でコード整形する方法がないかなと調べていたら、`nb_black`を導入することで簡単にできたので、メモとして残しておきます。

##nb_blackの使い方
ライブラリーをpipでインストールします。

```php
pip install nb_black
```

その後、jupyter notebookのセル[1]に下記マジックコマンドを入力することでセルを実行時に毎回自動整形を行なってくれます。

```php
%load_ext lab_black
```
Vue.js テキストファイルを読み込み表示させる

Vue-CLIで、テキストファイルをファイル入力ボックスから読み込んで、中身（テキスト）を単に表示させるだけだったが、thisの使い方にハマった。function内のthisは、インスタンス内でそのインスタンスを指すので注意。


###Vueファイルコード

```*.vue
<template>
  <div>
    <form>
      <input type="file" @change="readfile" />
    </form>
    <div>{{ data }}</div>
  </div>
</template>

<script>
export default {
  data(){
    return {
      data: []
    }
  },
  methods: {
    readfile: function(e) {
      const vm = this
      const file = e.target.files[0]
      const reader = new FileReader()

      reader.onload = function() {
        vm.data = reader.result
      }
      reader.readAsText( file )
    }
  }
}
</script>
```
 
###参考
onloadイベントのfunction内で、thisを使うと上手く行かない。この場合、アロー関数を使えば上手く動く。

```
// A.動作しない
reader.onload = function() { this.data = reader.result }

// B.動作する
reader.onload = () => this.data = reader.result
```

console.logでthisの正体を調べたところ、function内のthisはFileReaderインスタンスを参照していた。

```
// thisの正体
A FileReaderインスタンスを参照 -> FileReader {readyState: 2, result:  …}
B Vueインスタンスを参照 -> Proxy {readfile: ƒ, …} 
```
Jenkinsでaws-cliをつかう

# ターゲット

- Jenkinsでaws-cliを使いたい人
- Jenkinsののったインスタンス上にprofileの設定を、aws-cliで残したくない人

# 設定手順

## IAM

- aws-cliで利用するアクセスキーとシークレットアクセスキーを発行するため、[IAM](https://console.aws.amazon.com/iam/home?/users#/users)でユーザを作成します。
- Jenkinsの認証時報の設定でアクセスキーIDおよびシークレットアクセスキーは利用しますので、「プログラムによるアクセス」はチェック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/b007a30d-60d3-2bb6-ece5-b864744ac9be.png)

refs: https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html

## Install aws-cli

- Jenkinsが動作しているインスタンスに aws-cli をインストールする。
- Jenkinsのインスタンスは、[JenkinsにG-Suiteアカウントでログインする](https://qiita.com/ot-nemoto/items/1d9d2b38c6eba70ee708)で作成したインスタンスの為、Ubuntuを前提に記載してます。
- その他OSの場合は、[AWS CLI バージョン 2 のインストール、更新、およびアンインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html)を参照

```sh
sudo apt install -y awscli
aws --version
  # aws-cli/1.18.69 Python/3.8.5 Linux/5.4.0-1045-aws botocore/1.16.19
```

## Plugin Install

- プラグインの管理画面（Jenkinsの管理 > プラグインの管理）で「CloudBees AWS Credentials」を検索・チェックし、Install without restart
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/c312ef4a-b2d1-284c-abd7-445e35f525a1.png)

refs: https://plugins.jenkins.io/aws-credentials/

## Create Credentials

- Credentials画面（Jenkinsの管理 > Manage Credentiaals）で、aws-cliの認証情報を設定する。
    - 種類: AWS Credentials
    - スコープ: （任意）
    - ID: （任意:ビルド時に設定するID）
    - 説明: （任意）
    - Access Key ID: IAMで発行したユーザのアクセスキーID
    - Secret Access Key: IAMで発行したユーザのシークレットアクセスキー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/9cd81f5a-cb47-a434-8685-b9ad675e3b6d.png)

# ビルド実行

- Credentialの設定が済んだら以下のようにパイプラインを設定し、ビルド実行し動作の確認を行います。

```
pipeline {
  agent any
  stages {
    stage("s3 ls") {
      steps {
        withCredentials(
          [[
            $class: 'AmazonWebServicesCredentialsBinding',
            credentialsId: 'sandbox',
            accessKeyVariable: 'AWS_ACCESS_KEY_ID',
            secretKeyVariable: 'AWS_SECRET_ACCESS_KEY'
          ]]
        ) {
          sh '''
          aws s3 ls
          '''
        }
      }
    }
  }
}
```

- 設定したCredentialのAWSアカウントのS3バケット一覧が出力されれば成功です。

# 関連記事

- [JenkinsにG-Suiteアカウントでログインする](https://qiita.com/ot-nemoto/items/1d9d2b38c6eba70ee708)
Redashの認証をKeycloak(SAML)で行う

## やりたいこと

Redashを日常で使っているアカウントで認証したい。

## 条件や経緯

- いにしえのローカルユーザー管理のRedash v3を担当者退職のため引き継いだ
- IT部門がActive Directoryでユーザー管理をしているが、部門管理の他の野良システムと認証連携のためbindできるユーザーは発行してもらっていた

これらを連携させたいが、Redashの外部認証はGoogle OAuthとSAMLであり~~直接LDAP/Active Directoryとは連携できないのでSAML経由でとなる。~~

https://redash.io/help/user-guide/users/authentication-options


追記: LDAP/AD Authenticationありますね。こっちの方でも良かった。なんでauthenticationとしてまとめてないのだろうか？SaaS版とSelf Hosted/OSS版の違いですかね。

https://redash.io/help/open-source/admin-guide/ldap-authentication

## 対応方法

- Keycloakを立ち上げActive DirectoryとUser FederationしSAMLに対応させる
- Redash, Keycloak共に2021/05現在最新の Redash v8, Keycloak v13にアップグレードして連携させる。

## ここで触れないこと

- KeycloakをActive Directoryと連携させること
- Redash v3からv8までのアップグレード

これらは下記の記事などを参照した

https://qiita.com/megasys1968/items/dc01f9a30fe87f9975bd

https://www.atmarkit.co.jp/ait/articles/1806/18/news007.html

https://dev.classmethod.jp/articles/redash-v4-to-v8-with-docker/

## 設定

### Redash側SAML設定

公式サイトドキュメントの[How to Configure self-hosted SAML](https://redash.io/help/user-guide/users/authentication-options#How-to-Configure-self-hosted-SAML)に書いてあるとおり

### Keycloak側SAML設定

ずばりこれ。上記のドキュメントにはOktaやAuth0の例はあるがKeycloakの例がなくSAML自体わからず悩んだが、Issueを探したらKeycloak設定を画面キャプチャー載せている事例あり。これで解決できた。

https://github.com/getredash/redash/issues/2977#issuecomment-432476154
AWSソリューションアーキテクト―アソシエイト用語集まとめ

## それぞれの用語集サイト
- [AWSソリューションアーキテクト―アソシエイト用語集①データベース編 - Qiita](https://qiita.com/tatsumicro/items/7f7154b661c7e1983066)
- [AWSソリューションアーキテクト―アソシエイト用語集②ストレージ編 - Qiita](https://qiita.com/tatsumicro/items/34894aef100d148a8163)
- [AWSソリューションアーキテクト―アソシエイト用語集③コンピューティング編 - Qiita](https://qiita.com/tatsumicro/items/27f7d47dd3d558922018)
- [AWSソリューションアーキテクト―アソシエイト用語集④ネットワーキング編 - Qiita](https://qiita.com/tatsumicro/items/42ef2262ca5c8d80fa74)
- [AWSソリューションアーキテクト―アソシエイト用語集⑤アプリケーション統合編 - Qiita](https://qiita.com/tatsumicro/items/8e28662967c267697102)
- [AWSソリューションアーキテクト―アソシエイト用語集⑥管理とガバナンス編 - Qiita](https://qiita.com/tatsumicro/items/aa1891f1b4e71d52aa10)
GitHub ActionsでHerokuにデプロイする

以下のリファレンスに書いてあるとおりに対応するだけです
https://github.com/marketplace/actions/deploy-to-heroku

# ワークフローファイルを作成

```.github/workflows/main.yml
name: Deploy

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: akhileshns/heroku-deploy@v3.12.12 # This is the action
        with:
          heroku_api_key: ${{secrets.HEROKU_API_KEY}}
          heroku_app_name: ${{secrets.HEROKU_APP}}
          heroku_email: ${{secrets.HEROKU_EMAIL}}
```

# GitHubにSecretを登録

ワークフローでsecretsを指定した項目を登録します

- HEROKU_API_KEY
  - APIキーの取得方法は下記参照
- HEROKU_APP
  - デプロイ先のHEROKUアプリ名を指定します
- HEROKU_EMAIL
  - Herokuアカウントのメールアドレス  

`Settings -> Secrets`から登録します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/63a0dd4c-1fe9-05f8-ce09-2e25eb5a23dd.png)


### HerokuのAPI　Key取得方法


- HerokuのAccountSettingsのメニューから「API　Key」でAPI　Keyを生成します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/b024dce5-42fe-4cdb-2703-322f291f2450.png)


# GitHubへプッシュする

ここまでできたらあとはリモートのmasterブランチにプッシュするだけです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/83a8f369-d1d3-6d68-99b7-46d5c583ff1e.png)

無事にワークフローが完了しました！
めちゃめちゃ簡単にHerokuデプロイできるので、対応しておいて損はないかと思います。