OmniAICreator/Qiita-1.07M huggingface dataset:
Tableau初心者の入門メモ①

はじめまして。
去年の年末くらいからTableauを触り始めて早2カ月弱。

そろそろ触り始めた時の事を忘れ始めてきたので、備忘がてらもろもろとメモを残していこうと思います。

ということで、ちょうどTableau触り始めたよーって人は少しでも参考になればいいなと思いながらつらつらと目も残していきたいと思います。

まずは機能的なところで便利だったものやつまづいたとこを。

##１．マークラベル
操作：
グラフを右クリック⇒マークラベル⇒「常に表示/表示しない」

1個だけラベルを表示したい時とかに便利。

##２．左下
画面の左下にいろんな数字が載ってます。
データ数とか行列数がぱっとわかるので便利。

##３．既定のプロパティ
操作：
データペインの各項目を右クリック⇒既定のプロパティ⇒いろいろ・・・

毎度書式設定とか集計方法の変更をする必要がなくなるので、まず既定のプロパティをいじるクセを付けていきたい。
数値の桁数とか並び替えとかはあらかじめやっとくべし。

##４．カスタム分割
操作：
分割したい項目を右クリック⇒変換⇒カスタム分割

決まった文字を基準にデータを分割。普通の文字でも使えるので、「〇〇県」の県を前方でカスタム分割すれば「〇〇」にできる。

##５．メジャーバリュー
操作：
メジャーのピルをビューの軸にドラッグ（緑の1本線が表示される）

グラフを並べて見せられる。個人的には後述の二重軸のほうが好き。

##６．二重軸
操作：
メジャーのピルをビューの軸の反対側にドラッグ（緑の2本線が表示される）

メジャーバリューと同じ。軸が異なるデータを並べて見せることができるので便利。
軸をそろえてしまえばメジャーバリューと同じような使い方もできる。個人的にはこっちのが好き。

##７．簡易表計算
操作：
メジャーのピルを右クリック⇒簡易表計算⇒お好きなものを。

結構奥が深い。まだ理解が追い付いていないかもと感じるところ。
比較対象を月とか別のディメンジョンで設定できたり、ものによってはセカンダリを追加して、表計算の上に表計算を重ねられる（累計の差とか）ので、もう少し練習したい。

##８．「次を使用して計算」
操作：
簡易表計算が設定済みのメジャーを右クリック⇒「次を使用して計算」

文字だけでは何が何だかよくわからなかったやつ。
要するに、簡易表計算をどの方向に向かって計算するかって話で、クロス集計表を類型にして、選択を変えて試してみるとなんとなくわかるかも。
実際に使う上では、100%積上げ棒グラフを並べる時に「セル」を選択するって覚えておけば大体対応できるという安易な考え。


##９．グループ化
操作：
グループにしたいレコードをすべて選択して右クリック⇒グループ化
※この際、グループの軸となるディメンジョンを選ぶことができるが、基本的には全てのディメンジョンでやったほうが直感的。

インタラクティブに分析を進めるうえでは、ちゃちゃっと作業を進められるので便利。
継続的に使うダッシュボードの際は違う手を考えたいのが個人的な感触。

##１０．セット/結合セット
操作：
任意のディメンションを右クリック⇒作成⇒セット
（結合セットの作成）任意のセットを選択⇒右クリック⇒結合セットの作成

まだあまり使い方がわかっていない機能。動的にグループを作れるので、選択したものとそれ以外を比較するダッシュボードとかで使えるのかなと思っている今日この頃。MakeoverMondayとかで試してみたい。

##１１．フィルタの種類
動的（条件で売り上げTopNをフィルタする）と静的（TopN選んでフィルタする）を使い分けるのが大事。

##１２．	除外フィルタ
操作：
フィルタの設定画面右下の「除外」チェックボックスにチェックを入れる。

見たいものを選ぶフィルタではなく、外したいものをフィルタで選択できる。ダッシュボードにフィルタのカードを表示させて使うのは使いにくい気がするが、ダッシュボードアクションでレコードを選んでフィルタする分には便利。（選んだもの以外の集計を見れる）

##１３．フィルターアクション
操作：
画面上部のメニュー「ダッシュボードorワークシート」⇒アクション⇒アクションの追加⇒フィルター⇒ベースとなるシート（ソースシート）と影響を与える先のシート（ターゲットシート）を選択して、フィルタする項目を選ぶ。
![だだ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589595/57bf5f26-360f-3dec-8a6c-068fab3ad51c.png)

使いこなすことができればできることが広がるテクニック。
メニューでアクションを作成することで、複数のアクションに分岐させることができたりする。ただクリックが増えてしまうので、個人的にはポイントでアクションを作るのが好き。

##１４．地図
操作：
地理的役割を持つデータをマークの詳細にドラッグ
都道府県は「都道府県/州」、市町村は「群」で地理的役割を与えること。

苦手。上手に使えない。使いこなせるようになりたい。

##１５．ページ
操作：
ビューのカードの「ページ」にディメンジョンをドラッグ（基本的には日付データかな。）
右側に下のようなカードが表示されるので、「履歴の表示」をクリックして任意に設定。
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589595/75cc0e44-6b8e-a06f-5333-858b8eee4966.png)

意外と便利な機能。左右でディメンジョンを変更したり、▶ボタンで自動再生されるのでアニメーション風に使える。履歴の表示を設定すれば、軌跡を残すこともできるので、グラフで変遷を見るのに使える。

##おわり
とりあえず今日はこのくらい。
ECSにおいてdocker runコマンドの-t,--ttyオプションに相当する設定をした話

# はじめに
こんにちは。
現在私は社内のデータ分析基盤の刷新に取り組んでおります。

今回は検証中の***DataSunrise***をECSに乗せるべくを試行錯誤を行っていた中で発見した、
`docker run`コマンドの`-t`,`--tty`オプションに相当するであろう設定をECSで行う方法について記載します。

DataSunriseについては[こちら][1]をご参照下さい。
[1]:https://qiita.com/t_odash/items/5792cd2aaf6adda6b4a2
## 事の起こり
**localでできることがECSでできない**

検証のためにlocal環境にてコンテナを立てていました。
``docker run -itd -p 11000:11000 [datasunrise image id]``(local環境にて)
この場合は期待通りコンテナが立ち上がり、https://[グローバルIP]:11000で繋ぐことができました。

これをECSで実現したかったのですが、ECSのタスクは即時終了し、
CloudWatchLogsに流れてくるのは``service is started.``のメッセージのみでした。

試しにlocal環境にて、
``docker run [datasunrise image id]``を実行してみると、
``service is started.``との表示のみでコンテナは即時終了していました。
(本メッセージはDataSunriseコンテナが起動、即時終了した際に残すログのようです。)

結果的にECSにおいて`docker run`コマンドの`-t`,`--tty`オプションに相当するようなことを設定しなければならないと判断しました。

# 結論
タスク定義において``pseudoTerminal``を``true``にすることで、コンテナを起動させ続けることができました。
なお、本問題を解決に導いて下さった記事はこちらの[stackoverflow][2]です。
[2]:https://stackoverflow.com/questions/47550448/how-to-enable-tty-and-run-interactive-console-with-aws-ecs
具体的な設定方法は次の通りです。

## 設定方法
GUIでの設定方法を記載します。
最終的にJSONをいじることになるのでCLIで設定する場合も対応可能ではないかと思います。

1. 対象のECSタスク定義を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570763/f20f8a56-90f3-6e37-f955-826a273992cf.png)

2. JSONによる設定を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570763/1465fc8a-9517-586a-abda-2b8980bce9aa.png)
ページ最下部に存在します。(画像赤枠部分)


3. pseudoTerminalをtrueに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570763/60afc024-4da2-223a-6a38-7a0b7dbb999e.png)
初期設定でnullとなっていましたが、trueに書き換えて保存を押せば適用できました。(EC2/Fargateともに適用可能)
*こちらは説明用画像ですので、当該箇所以外は環境に合わせてよしなに設定下さい。念の為。

# まとめ
ECSにおいて``docker run``コマンドの``-t``,``--tty``オプションに相当するであろう設定ができました。
今回は試行錯誤段階において、stackoverflowに行き着いた事によって解決したのですが、
よくよく公式ドキュメントを読んでみると

>pseudoTerminal
>Type: Boolean

>Required: no

>When this parameter is true, a TTY is allocated. This parameter maps to Tty in the Create a container section of the Docker Remote API and the --tty option to docker run.

という記載がありました。

ちゃんと公式ドキュメント読みましょうという教訓でした。。。
# 参考

 - [DataSunrise公式][2]
 - [Stack Overflow当該記事 How to enable tty and run interactive console with AWS ECS?][3]
 - [AWS ECS公式ドキュメント][4]


また、試行錯誤段階にて以下記事も参考にさせて頂きました。ありがとうございます。
[Dockerのコンテナを起動したままにする][5]
[5]:https://qiita.com/reflet/items/dd65f9ffef2a2fcfcf30



[2]:https://www.datasunrise.com/
[3]:https://stackoverflow.com/questions/47550448/how-to-enable-tty-and-run-interactive-console-with-aws-ecs
[4]:https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#other_container_definition_params
LibreOffice で TexMaths を使う（メモ）

# はじめに
LibreOffice を使ってプレゼンや作図をするときに、ちょっとした数式を LaTeX で書きたい、既に書いた LaTeX 数式を流用したい、なんて場合があろうかと思います。そんなときに使える拡張機能が [TexMaths](http://roland65.free.fr/texmaths/) です。記事も検索すればいくつかありますね。

で、その利用法をざっと書き殴って出来た資料が以下、なんですが……冗長？
![libreoffice-with-texmaths](https://speakerd.s3.amazonaws.com/presentations/a8d6d443b5364e38a93d19885b712261/preview_slide_0.jpg)
https://speakerdeck.com/taraijpn/libreoffice-with-texmaths

# 要点抜粋と追加情報

+ LaTeX 組版環境はちゃんと整えて、CLIで動くことを確認しよう。
+ **PNG画像はLaTeX環境でのみ作成可能。XeLaTeX 環境では作成出来ない。** SVG画像は両環境で作成可能。
+ 動きが怪しいときはセーフモードにして一旦環境をリセット、拡張機能は入れ直してみよう。
+ 組版命令が機能してないなと思ったら プリアンブルの記述を確認しよう。
 + `\usepackage{bm}` とか。
+ OpenGL レンダリングはOFFにしよう。(Windows?)
 + SVG 画像の数式が画面で見たときだけ妙に太く見えるのは、これが原因。
+ SVG 画像は縦横比をうっかり崩して拡大縮小しそうになるので気を付けよう。
+ 作成した数式をうっかりダブルクリックすると、埋め込まれたLaTeXコードが消えるかも？
 + 数式だけ何処かにメモしておくと復旧が楽かも。
+ `\usepackage{bm}`と`\bm{x}`じゃなくて、`\boldsymbol{}`でいいんじゃなかろうか？
+ πに歯車アイコンの機能は **一斉再組版** なので、うっかりRunすると大変なので気をつけて。

と、これに加えて、資料には入れておらず個人環境での問題なのですが…

+ 64bit 版の dvisvgm.exe (w32tex, version 2.8.2) が [Segmentation falut で落ちる](https://twitter.com/taraijpn/status/1228269586103128066)？
 + 32bit版に向けておけばとりあえず動く。

# おわりに
いきなりLibreOffice Impressの資料を作ってから要点をQiitaにまとめる、という変則的なやりかたをしたのは、実際にLibreOfficeを使いながらメモしたものが先にあったからです。とはいえ SpeakerDeck よりも Qiita のほうが検索される割合が高そうなので、こちらに書き直した次第です。

LibreOffice Math もいいよ。

# 付録(1) (texmathsで)日本語入り数式などの組版は難しい？
いろいろやってみたんですが難しそうです。問題点は以下の通り。

+ Inline,Displayタイプのドキュメントクラスが `\documentclass[10pt,dvips]{article}` にハードコーディングされている。
 + 回避することは可能なのですが、そのためには 1つの画像に対し LaTeXタイプでプリアンブルから全て書かないといけません。
+ PNG画像はlatex系からしか作れない。
 + 上記の縛りで uplatex を使って dvipng が理解する 日本語入り .dvi  を作成する方法が難しいようです。
+ SVG画像の作成工程が .tex → (xelatex) → .xdv → (dvisvgm) → .svg に固定されている。
 + ドキュメントクラスを変更出来ない状態で日本語を通す方法をうまく見つけられずに困っています。LaTeXタイプにすれば良い？ 煩雑では……？ 

<details><summary>texmaths を諦めて LaTeXを諦めないなら standalone 文章クラスと pdftocairo を使ってみるといいかも知れません。</summary>
![standalonepdftocairoresults.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158337/fd14f2d9-06b8-6bac-1022-e2e115d56f01.png)
（何故画像にした）
</details>


# 付録(2) texmaths のマクロ本体は何処にあるの？
LibreOffice のメニューから ツール → マクロ → マクロの管理 → Basic を開くと、マイマクロの下にインストールされていると思います。LibreOffice Basicで。例えば TexMathsEquations の MakeEquation 関数、TexMathsSysConfig の WriteScript 関数などをご覧下さい。内部で何をやっているかが多分分かります。
【初心者向け】form_withでundefined method `form_with' forというエラーが出た際の対応方法について

#Railsでform_withを使用した際、undefined method `form_with' for やDid you mean?  form_tagと表示されてしまって詰まった話

Railsでアプリケーションを作成中、投稿フォームの実装時、form_withを使用したところ、永遠とエラーが出てしまって解決に時間がかかってしまったため、備忘録として残す。

#結論、form_withはRailsのバージョンが5.1 以上じゃないと動かないようです。

Railsガイド様いつも参考にしています
https://railsguides.jp/5_1_release_notes.html

Webcamp様にも記載ございました
https://web-camp.io/magazine/archives/17665

#何をすればいいのか？


Gemfileの中にあるRailsのgemのバージョンをアップグレードする

#Railsバージョンアップデートの手順

1. gemファイルのrailsを5.1以上で指定する（ここでは5.2.4を指定しています）

```ruby

gem 'rails', '~> 5.2.4'
```

2. bundle updateする（※注意：bundle installではない！！！！）

```ruby

bundle update
```

#Railsをバージョンアップした際にRails sで立ち上がらない問題が発生

```
undefined method `halt_callback_chains_on_return_false=' for ActiveSupport:Module (NoMethodError)
```

これが表示されたら、configファイルの中身の以下

```
config/initializers/new_framework_defaults.rb
```

以下をコメントアウト

```
ActiveSupport.halt_callback_chains_on_return_false = false
と
Rails.application.config.action_controller.raise_on_unfiltered_parameters = true

```


上記をコメントアウトし、これで通常通りRails sで起動した。
（よかった・・・・でも勉強になった）


ちなみに、ActiveSupport.halt_callback_chains_on_return_falseの意味はよくわかりません・・・。
https://techracho.bpsinc.jp/hachi8833/2017_02_21/35843


参考記事
https://qiita.com/luglio22/items/0dd520f3748935bada81


もし
ここは違う、ここはこうした方が良い等々ございましたらご指摘いただけますと幸いです。
最後までみていただき、ありがとうございます。
Macの ダークモードを Spotlight を利用して一瞬で切り替える方法

## 前置き

書いているのは2月ですが、
この投稿は [OPENLOGI Advent Calendar 2019 - Qiita](https://qiita.com/advent-calendar/2019/openlogi) の 13日目の投稿です！
すみません :bow:

さて、これを読んでいるみなさんはダークモードが大好きだと思いますが、MacOS Catalina では、ダークモードの切り替えは 設定アプリを開いて、ゴニョゴニョする必要がありますね。たかだかダークモードを切り替えるのに手順が多くてとてもめんどくさいです。

しかし、ダークモードをもっと簡単に切り替えたい！
そんなあなたのための記事です！

## AppleScriptを書く

以下のAppleScriptを実行すると、ダークモードのオンオフができます。

```darkmode.scpt
tell application "System Events"
	
	tell appearance preferences
		
		set dark mode to not dark mode
		
	end tell
	
end tell
```

カレントディレクトリなら、 `osascript darkmode.scpt` で実行できます。
実行するたびにダークモードのオンオフができます。
このAppleScriptはコマンドで実行するのもいいですし、
スクリプトエディタからショートカットキーに登録するようにもできますが、
どれも僕的にはいまいちでした。
CLIを利用しているときはダークモードのオンオフはしたくなりませんでしたし、
新しくショートカットキーを作るのは既存のアプリのショートカットとバッティングするのが難点です。

参考URL
[Mac ―「ダークモード」をショートカットで切り替える方法 | iTea3.0](https://itea30.jp/change-appearance-mode/)

## アプリケーションにしてみる

そこで app 形式にして保存することで、spotlight から実行することができるという奇跡の解決策を考えつきました。
以下の手順で実行します。

- MacOSに標準搭載されている スクリプトエディタ.app を起動します

- 新規書類のボタンを押します
<img width="796" alt="開く 2020-02-20 19-38-58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130428/fa8d1d1a-c5f3-0871-f5ad-a14df2893cfe.png">

- 上のスクリプトを貼り付けます
<img width="714" alt="名称未設定.scpt 2020-02-20 19-39-44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130428/5b439c80-9cb3-b9e9-6cf7-204af12dcaba.png">

- ファイル -> 書き出す -> ファイルフォーマットをアプリケーションにする
- 好きな名前（私は dark.app  にしました） にして保存する
<img width="484" alt="Monosnap 2020-02-20 19-40-10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130428/b4d9e4b4-d50e-cc16-2b98-953d870ab4bd.png">

これで app形式で保存できましたので、スポットライトから実行できます。
最初実行するときはアクセスを要求されるので許可してあげます。

<img width="449" alt="Monosnap 2020-02-20 19-41-50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130428/71a15d1c-a1be-6be7-e7fe-5c805dd13001.png">


<img width="725" alt="スクリーンショット 2020-02-20 19.44.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130428/d81921bc-9633-46d6-8568-161ec5ee37a2.png">

スポットライトを起動してdark と入力してエンターを押すだけでダークモードの切り替えができます！
これはお手軽で簡単ですね！
みなさんもやってみてください！


参考URL
[すべてのアプリを一発で終了させるアプリを自作する[Mac OS X] | Basic Werk](http://basicwerk.com/blog/archives/1066)
【備忘録】macOS Catalinaでパーティションサイズを減らそうとして詰まった話

# 事の発端

私のMacBook Airで使ってたArch Linuxの環境で空き容量が足りなくなったのでほとんど起動してなかったmacOSの空き容量を削ることに。

ってことでAPFSはLinuxでは読み込めないのでmacOS立ち上げてディスクユーティリティで
ってやろうとしたあら案の定サイズ変更ができなくなってたのでその時に行った対処法

# TimeMachineをオフれ

設定からTimeMachineをオフります。
というか全ての元凶こいつです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144572/04078684-84f0-c41a-085e-fe177b229033.png)


# TimeMachineのローカルスナップショットの在処を探せ

まずファイル名を確認します

```terminal:Terminal
$ tmutil listlocalsnapshots /
```

```terminal:結果
Snapshots for volume group containing disk /:
com.apple.TimeMachine.2020-02-20-175726.local
```

数字のとこだけメモります

# TimeMachineのローカルスナップショット消せ

さっさと消します。数字のところはさっき調べて出てきたやつに書き換えます

```terminal:Terminal
$ tmutil deletelocalsnapshots 2020-02-20-175726
```

ちょっと時間かかるので待ちます

# リサイズします

これで多分りさいずできるようになってるのでリサイズします
今回は390GBに縮小しますがお好みで変更してください
ちなみにどのドライブがAPFSコンテナかは`diskutil list`で確認できます

```terminal:Terminal
$ sudo diskutil apfs resizeContainer disk0s2 390g
```

# 終わり

もしmacOSでAPFSコンテナのりサイズ、縮小とかができなくなってたらお試しあれ

#参考文献
- [disk utility - Can't resize APFS Container: Not enough free space in Container due to APFS limits or tidemarks - Ask Different](https://apple.stackexchange.com/questions/321533/cant-resize-apfs-container-not-enough-free-space-in-container-due-to-apfs-limi)

- [disk utility - 200GB unused, but can't change APFS container size due to minimum requirement - Ask Different](https://apple.stackexchange.com/questions/345256/200gb-unused-but-cant-change-apfs-container-size-due-to-minimum-requirement)
rails s 起動しない　解決方法の１つ

チーム開発においてエラーが発生！

※　初心者向けに何か助けになればと思い記述しております。
※　アウトプットの練習も兼ねております。

開発環境　rails 5.2.4.1
        ruby  2.5.1
クラウドサービスはAWSを使用
現状自動デプロイまで完了

5名でフリマアプリの作成

githubアプリより最新のタスクデータを取得のため
masterブランチにブランチを切り替えpullを実行

rails sでサーバーを立ち上げた際に起動しない
----------
    .....
    => Rails 5.2.4.1 application starting in development 
    => Run `rails server -h` for more startup options
    Exiting
    Traceback (most recent call last):
        85: from bin/rails:3:in `<main>
    .....
試した事
PC再起動
bunde linstall
rails db:migrate
rails db:rollback
rails db:drop
rails db:migration:reset
rake  db:migrate:reset   等...いずれもエラー表示

冷静にエラーの記述を見るとrails sの起動時に下記の内容が
---------
     config/initializers/carrierwave.rb:10:in `block in <top (required)>'
---------
指定のファイルconfig/initialize/carriewave.rbの記述に注目
-------
     provider: 'AWS',
     aws_access_key_id: Rails.application.credentials[:aws] 
     [:access_key_id],
     aws_secret_access_key: Rails.application.credentials[:aws] 
     [:secret_access_key],
     region: 'ap-northeast-1'
-------

結果awsのマスターkeyをpullでは取得できていないためであったと思われる。
configファイルの参加にmaster.keyのファイルを作成しマスターよりkeyを一旦取得し記述するとエラーは解決。

しかしこのままではセキュリティに問題がある為、別の方法を模索中です。
Hyperとvimの背景色を揃える

#環境と前置き
私は現在、ターミナルとして[Hyper](https://hyper.is/)を使用しており、最近Hyper上でvimを使い始めました。
この記事を書く前に@pepoipodさんのm[Vimの背景色をターミナルの背景色と揃える方法](https://qiita.com/pepoipod/items/e058b098af389ddb451f)という記事を参考にしたんですが、私の環境ではうまくいかなかったので、最終的に行き着いた解決方法を記そうと思います。

#何が起こったか
私はvimのカラースキームとして[Molokai](https://github.com/tomasr/molokai)を気に入って使い始めたんですが、[Molokai](https://github.com/tomasr/molokai)の背景は黒っぽく、ターミナルの背景は青に近い色に設定してあるため、ターミナルとvimで色の段差が発生していたわけです。(以下参照画像)<img width="1214" alt="スクリーンショット 2020-02-20 18.05.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143170/10122879-c85f-a7e7-2aa1-071a8ce11021.png">

#解決方法
`~/.vimrc`に背景をNONEにするよう記述します。

```vim
colorscheme molokai
hi Normal guibg=NONE
hi LineNr guibg=NONE
hi VertSplit guibg=NONE
hi Special guibg=NONE
hi Identifier guibg=NONE
"highlight グループ名 guibg=NONE
```

大まかな部分は冒頭で挙げた記事と似てるんですが、
__重要なのは__

- `colorscheme`の記述の下に書くこと
- `guibg=NONE`と書くこと。

です。
元記事では`guibg`ではなく`ctermbg`だったのですが、Hyperを使っているからなのか、`ctermbg`では変わりませんでした。

[__グループ名__](http://tech.alters.co.jp/vimrc/vimrc%E3%81%AEcolor%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E4%B8%80%E8%A6%A7/)と言うのはいくつかあるのですが、私は代表的なものの背景をとりあえずNONEにしました。

- __Normal__は一般的な文字の背景です。これの背景をNONEにすることで全体の80%程度は透過されます。
- __LineNr__ はvimの左にある行数を表す数字のことですね。
- __VertSplit__はvimを縦に分割した時の分割線のことです。
- __Special__は確か&などの記号のことです。
- __Identifier__はvimrcとかでよくある<C-r>のような予約語のことだと思います(多分)。


これらの背景をなしにすると、とりあえず僕の環境ではいい感じになりました。
取りこぼしがあるかもしれないので、それに関しては見つけ次第`vimrc`に書き足すとします。

####参照
[set vim background transparent](https://stackoverflow.com/questions/37712730/set-vim-background-transparent)
[python] htmlファイルを読み込んでスクレイピング練習

#はじめに
スクレイピングやってて躓いたときに`copy outerHTML`で要素解析すること多いと思うんだけど忘れていたのでメモ

# 参考

[Python2年生 スクレイピングのしくみ 体験してわかる！会話でまなべる！](https://amzn.to/36LQuJ1)

#やりかた
コピーしてきたHTMLでファイルを作って読み込む

```python
from bs4 import BeautifulSoup

with open('copy.html', encoding='utf-8') as f:
    html = f.read()

soup = BeautifulSoup(html, 'html.parser')
```
遅い部分テンプレートを改善！！処理速度が早いrender

renderは使い方を間違えると表示に読み込みが遅くなってしまう。
今回はパフォーマンスを意識して学習した。

## NG：each doで部分テンプレート読み込み
each doは繰り返し処理なので、部分テンプレートもなんども読み込みする。

```ruby:悪い例
# eachを使う処理はNG
<% @products.each do |product| %>
  // ３つの書き方を記述しているが、each doを利用しているのでだめ
  <%= render product %>
  <%= render 'products/product', product: product %>
  <%= render partial: 'products/product', locals: { product: product } %>
<% end %>
```

@productsが1000個の場合、1000回部分テンプレートを読み込む事になる。

### 処理が早い書き方

```haml:正解
= render partial: 'product', collection: @products, as: "product"

 # partial: 'product'    > _product.html.erbを読み込む


 # collection: @products > 複数あるproductを1つずつ処理する。 > each doの代わりになる。


 #  as: "product" > @products の単体の変数 、部分テンプレートで利用する変数はproductになる。

```

これだと一度しか部分テンプレートが読み込まれないから、処理速度が早まる。
std::tupleを使わないパラメータパック展開

#やりたいこと
　可変長templateパラメータのn番目の要素を取り出したいことがある。取り出したい要素が非型の時ふつうはstd::tupleを使って以下のように書く。

```tuple_nontype.cpp
template<std::size_t N, int... I> auto some_func() {
  auto nth_num = std::get<N>(std::tuple{I...});  // N番目の要素を取り出す。
  // 何かしらの処理
}
```

　また、取り出したい要素が型の時は

```tuple_type.cpp
template<std::size_t N, typename... T> auto some_func() {
  using nth_type = std::tuple_element_t<N, std::tuple<T...>>;   //N番目の要素を取り出す。
  // 何かしらの処理
}
```

こんな感じだろう。
　別にこれでやりたいことは完璧にできているし、std::tupleはconstexprなのですべてコンパイル時に評価され、何ら問題はない。そう、何ら問題はないのだ。しかし、こんな簡単にパラメータパック展開できてしまってはつまらないではないか。そこで、std::tupleを使わずにパラメータパック展開しよう。

#というわけでstd::tupleなしのコード
　N番目の非型要素を取り出す。

```nontuple_nontype.cpp
template<std::size_t N, typename T, T, T... Param> 
inline constexpr T nth_param_v = nth_param_v<N - 1, T, Param...>;
template<typename T, T Param0, T... Param> 
inline constexpr T nth_param_v<0, T, Param0, Param...> = Param0;

template<std::size_t N, int... I> auto some_func() {
  auto nth_num = nth_param_v<N, int, I...>;  // N番目の要素を取り出す。
  // 何かしらの処理
}
```

　N番目の型を取り出す

```nontuple_type.cpp

template<std::size_t N, typename, typename... T> struct nth_type {
  using type = typename nth_type<N - 1, T...>::type;
};

template<typename T0, typename... T> struct nth_type<0, T0, T...> {
  using type = T0;
};

template<std::size_t N, typename... T> using nth_type_t = typename nth_type<N, T...>::type; 

template<std::size_t N, typename... T> auto some_func() {
  using n_type = nth_type_t<N, T...>;   //N番目の要素を取り出す。
  // 何かしらの処理
}
```

#あとがき
　思いのほか簡単でしたね。何度も使う場合は、std::get<N>(---)とかstd::tuple_element_t<--->とか書かなくて済むので、こっちの方が書くコード量は少なくなります。が、素直にstd::tupleを使うことをお勧めします。

　おしまい。
reactのmemoが使いこなせない


# reactのmemoが使いこなせない...
【助けていただいたサイト一覧】
- [公式様](https://ja.reactjs.org/docs/react-api.html#reactmemo)
- [react.memoの解説がとても分かり易かったです] (https://numb86-tech.hatenablog.com/entry/2019/12/20/222412 )

## 出発の問題

前提: react.memoの仕様の把握 

react.memoを使ってパフォーマンスアップするぞーと意気込んでいました。
作業内容は、あるデータをループで回してリスト化する。あるあるです。

<img width="852" alt="スクリーンショット 2020-02-20 15.52.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/25cff243-03c2-6bf2-8f99-b628843ce403.png">

このデータはしょっちゅう変更されますが、


```js
// 前回データ
[0:{title: 'わに'},
 1:{title: 'とり'},
 2:{title: 'いるか'}
]

// 変更後データ
[0:{title: 'わに'},
 1:{title: 'かば'},
 2:{title: 'やぎ'}
]
```
であった場合、0個目のリストのpropsは変わらないので、再レンダリングするのはエコではありません。

コードで示すと以下のようになります。

```react:parent.js
Parent = () => {
  const [stateTest, setTest] = useState({
    array: [
      {title: 'わに'},
      {title: 'とり'},
      {title: 'いるか'}
    ]
  })

  const propsChanger = () => {
    setTest({
      array: [
        {title: 'わに'},
        {title: 'かば'},
        {title: 'やぎ'}
      ]
    })
  }

  let ListDom = []
  stateTest.array.forEach((item, i) => {
    ListDom.push(
      <List objData={item} key={`list${i}`}/>
    )

  return (
    <div>
      {ListDom}
      <div onClick={propsChanger}>props更新!</div>
    </div>
  )
}
```

```react:List.js
export default function List ({objData}) {
  console.log(`${objData.title}はレンダリング`)
  return(
    <p>{objData.title}</p>
  )
}

```

再レンダリングさせない...`react.memo`の出番だ！と思ったわけです。


```react
import React, { memo } from 'react'

const List = memo(({objData}) => {
  console.log(`${objData.title}はレンダリング`)
  return(
    <p>{objData.title}</p>
  )
})

export default List
```

メモをかませたので、shallowで比較されるはず、、！
と思って更新ボタンを押すと、

![スクリーンショット 2020-02-20 17.24.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/69f11abd-7133-13b1-e951-8b5a8bbe55f3.png)

わに、しっかり再レンダリングされていました...


## なぜ？
**オブジェクトの比較はインスタンスが違うと中身が同じでも同等と見なされないから。**
memoを使いこなすのは難しそうです。

## 解決方法!
### その１　オブジェクト・配列は渡さない。

```react:Parent
stateTest.array.forEach((item, i) => {
  ListDom.push(
    <List title={item.title} key={`list${i}`}/>
  )
})
```

```react:List
const List = memo(({title}) => {
  console.log(`${title}はレンダリング`)
  return(
    <p>{title}</p>
  )
})
export default List
```
propsを文字列で渡すようにしました。これであれば　わにのリストは再レンダリングされませんでした。
でも、渡す情報が多い場合は、propsをたくさん渡さなければなりません。

### その2　第二引数を使う
deepな比較はshallowよりコストが高いので注意です!
三菱形継承時の明示的クラス指定方法

タイトルは思い付きで。
[これ](https://teratail.com/questions/232258)の続き。

---

```python:test.py

class A(object):

    def primary_process(self):
        print('A')

    def say_this_func_name(self):
        pass

class B(A):

    def first_process(self):
        super().primary_process()

    def say_this_func_name(self):
        print('B')

class C(A):

    def first_process(self):
        super().primary_process()

    def say_this_func_name(self):
        print('C')

class D(A):

    def first_process(self):
        super().primary_process()

    def say_this_func_name(self):
        print('D')

class E(B, C, D):

    def __init__(self):
        super().first_process()

    def say_B(self):
        super().say_this_func_name()

    def say_C(self):
        super(B, self).say_this_func_name()
        
    def say_D(self):
        super(C, self).say_this_func_name()

print(E.mro())

b = E()
b.say_B()

c = E()
c.say_C()

d = E()
d.say_D()
```

で以下のように出力される。

```
[<class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
A
B
A
C
A
D
```

とりあえず望み通りの出力になった。

恐らくEの宣言時に継承するクラスの順序と関係があるんだろうけど
いまいち動きが良く分からない。。。

# というわけでググってみた

[https://www.lifewithpython.com/2014/01/python-super-function.html](https://www.lifewithpython.com/2014/01/python-super-function.html)

super(B, self)という書き方はどうやら2系のときは標準だったらしい。
そもそも普段(非菱形継承時)から書いているsuper()は引数を省略していたようだ。

[https://methane.hatenablog.jp/entry/20081227/1230400144](https://methane.hatenablog.jp/entry/20081227/1230400144)

mroはmethod resolution orderの略。関数解決順とでもいうのだろうか。
おそらくメソッドチェーンなる概念があって、このチェーン順に関数名を検索して
初めにヒットした関数を使用しているのだろう。
となるとsuper(B, self)という書き方は```<class '__main__.B'>```まで検索をスキップして
```<class '__main__.C'>```から検索を始めろということなのだろうか。。。。

すぐ調査できそうだけどとりあえずまた今度。
Python: htmlデータからタグを除外する

# BeautifuleSoupでタグを除外
```python
text = '<br />あか<br />あお<br />みどり<br />きいろ<br />'

import requests
from bs4 import BeautifulSoup

soup = BeautifulSoup(text,"html.parser")
soup_text = soup.get_text()
```

# EXECUTION EXAMPLE
```python
In [86]: soup_text
Out[86]: 'あかあおみどりきいろ'
```
rubocop-railsのfind_by_*系メソッドの自動修正をstaticに定義した一部のメソッドの上で無効にする

Railsで開発するにあたって、rubocop-railsをLinterとして利用しており、
自動修正機能を適用したときにエラーに繋ってしまったのでメモしておきます。

# 背景

Railsでは`find_by_id`や`find_by_name`のように、ActiveModelのカラム名を利用して検索できるメソッドが動的に定義されます。

しかし、このような個別のメソッドを利用するのではなくfind_by形式に統一するスタイルがRuboCopにおいては[推奨されており、](https://github.com/rubocop-hq/rails-style-guide#find_by)検知&自動修正するための[Copが存在します](https://github.com/rubocop-hq/rubocop/issues/3455)。

一方で、自前で`find_by_hoge`のようなメソッドを定義した場合にもこのCopの判定対象になってしまい、自動修正の対象になってしまいます。

自分の開発しているプロジェクトでは自動修正をかけた際に意図せず変更されてしまい、メソッド未定義のエラーに繋りました。

# 回避方法

一部のメソッドをこのCopの対象から除外したい場合には以下のアプローチがあります:

- 該当行にコメントで `rubocop:disable Rails/DynamicFindBy` を追加する
- `rubocop.yml`中で該当メソッド名をホワイトリストに追加する

2つの方法があるなかで、私は後者の選択をしました。

判断の理由としては、前者のインラインコメントで都度対応をするという方法は

- 実装者がコメントの追加を忘れやすい(コードレビューでも指摘忘れやすい)
- 後からコードを読むメンバーにコメントの背景が伝わりづらい
- 呼びだしの箇所で個別に記述するコストがかかる

といったいくつかのデメリットがあると考えたためです。

そのため、後者の`.rubocop.yml` 中に記述するアプローチを取りました。

```.rubocop.yml
Rails/DynamicFindBy:
  Whitelist:
    - find_by_sql
    - find_by_hoge
```

Whitelistに該当メソッドだけでなく、`find_by_sql`についても追加していますが、こちらのメソッドもRailsの標準のメソッドであり自動修正の対象とはしたくないためです。

RuboCopの設定は、デフォルトの設定を自動的に継承するようになっていますが、

継承されている設定と同じ項目についての設定を記述した時に以下のようなルールで上書きがされます。

- ハッシュマップはデフォルトの物とマージされ、衝突したキーについては最後の設定で上書きされる
- 配列については常に最後の設定によって上書きされる

(参考: [Configuration - RuboCop: The Ruby Linter that Serves and Protects](https://rubocop.readthedocs.io/en/latest/configuration/#inheritance))

今回は後者の配列の上書きに該当しますので、標準でWhitelistに追加されているfind_by_sqlについても自分で追加しておく必要がありました。
ゼロから作るDeep Learning ②  をANACONDAのspyderで利用する時の「上位ディレクトリの取得ができない」エラー対策

ANACONDAのSpyderでPythonを扱う際、特に、『ゼロから作るDeep Learning ② 』で、
以下のコードでエラーが発生する際には、この様に対策すればエラーが解決しました。

sys.path.append('..')  # 親ディレクトリのファイルをインポートするための設定

この場合、ANACONDAのSpyderの左上のpythonタブからPYTHONPATH managerをクリックします。![スクリーンショット 2020-02-20 18.29.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182169/e40a49dc-3e76-e12b-bd01-341c8e88cfb9.png)

その後、上位ディレクトリを入力することで解決できました。
![スクリーンショット 2020-02-20 18.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182169/0ea340ea-f041-0d54-26c8-88af80dba3dd.png)

こんな、簡単にできるなんて、素晴らしいです。
【Excel】同じデータを枠線で囲む【方眼紙】

# はじめに

例はこんな感じです。

![使用前使用後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/f756729d-7037-9f91-5fc2-422a55b3d5e4.png)

- 実例はOffice365版ですが、他のバージョンでも大丈夫（のはず）

# 概要

- 「条件付き書式」上のセルと異なるなら上枠線、左のセルと異なるなら左枠線
- 上記ルールの適用範囲を設定


## 実際の操作例（一例）

- 適当なセル（今回は **B2**）を選択
- ［ホーム］タブ → 条件付き書式 → ルール管理
![B2選択2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/d87e2549-a619-1ddb-df75-5f6d7fdd2c87.png)

- 「新規ルール」クリック
![新規ルール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/d032228f-c8fe-fa55-6691-e6e333e2befe.png)

- 「数式を使用して、書式設定するセルを決定」を選択
- 数式欄に`=B2<>B1`を入力：現在選択中のセルとその上のセル（`<>`は不等号）全て半角
- 「書式クリック」

![新しい書式ルール2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/586b2426-1efb-401a-010b-af2b0b4e70cd.png)

- 上罫線ボタンをクリック
- 「OK」→ 「OK」

![上罫線.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/b1827ba2-9be4-a14b-2e7e-374a75502e8b.png)

- 「条件付き書式ルールの管理」ダイアログで再度「新規ルール」クリック

![新規ルール追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/26320e6e-65f2-568c-e6f3-4ecaafba66f3.png)

- 先ほどと同様「数式を使用して、書式設定するセルを決定」を選択
- 数式欄に今度は`=B2<>A2`を入力：現在選択中のセルとその左のセル
- 「書式クリック」

![左用式.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/045b5e6f-7e58-cd7d-17d1-eb91c35f56f6.png)

- 左罫線ボタンクリック → 「OK」→「OK」

![左枠線指定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/1ff2e3c6-3621-fb1c-42dd-96c9d4563e2b.png)

- 適用先指定ボタン(?)クリック
![適用先指定クリック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/4d4ab4d5-109e-93e5-c7d4-e5baf430ca14.png)

- 適用範囲をドラッグで指定
- ダイアログを閉じる


![適用範囲ドラッグ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/4a0eeac9-ac27-f506-06c6-f09545f791f8.png)

- 適用先をもう一方にコピペ
- 「OK」
![適用先コピペ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/6925a8c7-a62d-a161-c090-4bf3e1663dc3.png)

- できた！

![結果2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/594b2f21-dd5b-c0de-f010-c1e48fbbbb5e.png)

- 適用先の指定は「B2」セルコピー → 範囲指定して「書式のみペースト」等でも可能

## おわりに

![マップ例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284455/cfc3016d-983e-cf55-bcac-cac13edf1d74.png)
Excelでは空白と0は等しい扱いでしたかね。


- 説明用にデータを見やすくしたりするのに便利（？）
- もっといい方法や応用例も？
【Unity、Windowsビルドエラー Burst】解決済み

UnityでWindows向けにビルドしたときに下記エラーが出たので下記の様なエラーが出た。

```
Burst.Backend.CompilerBackendException: Unable to write module to filePath:
C:\Users\?????\AppData\Local\Temp\burst-aot3zybxaez.424\lib_burst_generated_part_0.bc

Burst.Backend.StandardCompilerBackend.ErrorHandlerCallback(String reason)
Burst.Backend.StandardCompilerBackend.SaveModuleToDisk(Module module, String filePath)
Burst.Backend.ChainCompilerBackend.SaveModuleToDisk(Module module, String filePath)
Burst.Compiler.IL.Aot.AotCompiler.ModuleToLink.WriteModule(ExtendedCompilerBackend backend, TargetMachine targetMachine)
Burst.Compiler.IL.Aot.AotCompiler.Link(List`1 groups, AotCompilerOptions compilerOptions)
Burst.Bcl.BclApp.CompileAndLink(List`1 methodGroups)
Burst.Bcl.Program.Main(String[] args)
BuildFailedException: Burst compiler (1.1.1) failed running
```

##環境
Windows10(x86-64)
Unity 2019.2

今回キーとなったパッケージ
Barracuda 0.4
Burst

##解決法
エラーの内容で、パスの一部が???なので、
ディレクトリのパスが日本語になっているところの問題なのかなと思ったが、
先人のやり取り曰くそうなでもないらしい。

下記はその抜粋だが、特定のUnityバージョンでBurstが正常に動かないそうな。
https://issuetracker.unity3d.com/issues/linux-burst-compiler-fails-when-building-windows-player
>[LINUX] BURST COMPILER FAILS WHEN BUILDING WINDOWS PLAYER
Linux-Jul 31, 2019
To reproduce:
1) Create a new project
2) Add a Burst package to project
3) Build a windows player

>Result: You get errors that Burst Compiler failed running. Build succeeds in 2018.4 and 2019.1 and executables are made; but fails in 2019.2 and 2019.3

>Reproduced in 2018.4.0f1, 2019.1.0b2, 2019.3.0a11

感想⇒　マジで。

ただ、先人のおかげでちゃんと解決法が公式ページにありました↓
https://docs.unity3d.com/Packages/com.unity.burst@1.1/manual/index.html?_ga=2.105268739.1800891498.1582179731-112051585.1573460324#standalone-player-support

大事なのはこのあたり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504562/5e2a9916-23eb-d027-5c58-d9babd975a69.png)

Project Settings > Burst AOT Settings にて
全項目をDisableにするとイケた！！！


##感想
良かった。ほっとした。
BarracudaがBurstに依存しており、
私の開発環境ではOnnxを読むためのBarracudaはどうしても外せなかったから一安心でござる。


以上。どどん。
[openFrameworks]pingPongBufferとMRTを手取り早く連携させる

# pingPongBufferとは
n-1フレームでの計算結果をnフレームでの計算に用いたいことは多くあると思います．しかしshader内では変数を保持することができません．そこでn-1フレーム目の演算結果を入力, nフレーム目での計算結果を出力とするような形でFboを２つ用意する手法をpingPongBufferといいます．

# MRT(Multiple Render Targets)
１つのshaderで複数の出力を行うことをMRTと言います．MRTが主に使用される代表的な場面は遅延レンダリングなどでしょう．今回このMRTを使用する理由は、粒子などの座標を物理的な計算を元に計算する場合速度、力(抵抗、圧力)、密度など複数の情報が必要になるためです．

# 結果
この記事では難しい計算を置いておいてMRT, pingPongBufferにフォーカスを当てて説明するためなるべく簡易的なサンプルとして前フレームでの値を保持して状態変化(色情報)する物を上げておきます．
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184790/55941aa2-59ab-5027-b52b-b75a7b3c7bb3.gif)
完成コードは[ここ](https://github.com/KeitoTakaishi/CGLab-oF/tree/master/MRT-Sample01)にあげてます．またなかで使用されている`pingPongBuffer.hpp`は[こちら](http://yasuhirohoshino.com/archives/30)を使用させていただきました．ちなみに構造としてはoFのexampleの中にあるgpuParticleとほぼ同じかと思います．

# 流れ
1. Fboを生成
2. Fbo内にColorBufferを生成
3. ColorBufferへ値を登録
4. MRT用のShaderで値を更新
5. step4で更新されたBufferと前フレームをswap
6. step4, step5を繰り返す


# ColorBufferへ値の登録
Fboの中に必要な数分のColorBufferが用意できたらColorBufferの中身を初期化していきます．

```cpp
res = 4;
//internal format
pingPong.allocate(res, res, GL_RGBA32F, 3);
int ch = 3;
    //----ColorTexture1
    float* data1;
    data1 = new float [res * res * ch];
    for(int y=0; y < res; y++){
        for(int x = 0; x < res; x++){
            auto i = (x + y * res) * ch;
            data1[i] = 0.0;
            data1[i+1] = 0.0;
            data1[i+2] = 0.0;
         }
    }
    //pixelFormat
    pingPong.src->getTexture(0).loadData(data1, res, res, GL_RGB);
    delete[] data1;
```

自分がハマった点なのですが、oFFboでallocateする際に渡すのは`internal format`でloadDataする時に渡すのは`pixelFormat`という点です．ここで引数をミスるとなかで呼ばれる`glPixelStorei `で用意したtextureのチャンネル数と配列側のデータ境界がずれてしまいます．
## MRT
ここで重要なのは`activateAllDrawBuffers()`でこれをコールすることでレンダーターゲットとして全てのColorBufferが登録されます．あとはshaderへ値を送信するだけ．

```cpp
void ofApp::timeStep(){
    //mrt------
    float t = ofGetElapsedTimef();
    pingPong.dst->begin();
    ofClear(0);
    mrtShader.begin();
    pingPong.src->activateAllDrawBuffers();
    mrtShader.setUniform1f("time", t);
    previewShader.setUniformTexture("tex0", pingPong.dst->getTexture(0), 0);
    previewShader.setUniformTexture("tex1", pingPong.dst->getTexture(1), 1);
    previewShader.setUniformTexture("tex2", pingPong.dst->getTexture(2), 2);
    pingPong.src->draw(0.0, 0.0);
    mrtShader.end();
    pingPong.dst->end();
    pingPong.swap();
    //---------
}
```

shader側ではlayoutでロケーションを指定してあげないと出力順がおかしくなることがあります．

```glsl

#version 150
#extension GL_ARB_explicit_attrib_location : enable
precision mediump float;
uniform sampler2DRect tex0;
uniform sampler2DRect tex1;
uniform sampler2DRect tex2;
uniform float time;

in vec2 vTexCoord;

layout (location = 0) out vec4 vFragColor0;
layout (location = 1) out vec4 vFragColor1;
layout (location = 2) out vec4 vFragColor2;


void main(){
  vec4 c0 = texture(tex0, vTexCoord);
  vec4 c1 = texture(tex1, vTexCoord);
  vec4 c2 = texture(tex2, vTexCoord);


  vFragColor0 = vec4(mod(c0.r + 1.0, 2.0), 0.0, 0.0, 1.0);
  vFragColor1 = vec4(0.0, mod(c0.r + 1.0, 2.0), 0.0, 1.0);
  vFragColor2 = vec4(0.0, 0.0, mod(c0.r + 1.0, 2.0), 1.0);
}

```
XCodeのRun ScriptでFirebaseにシンボルをアップロードした件

# メモ書き

ネットで色々調べればすぐ分かる内容ですが、情報がたくさんありすぎて苦労したのでメモとしてまとめました。

> コンソールからの dSYM のアップロードは 2020 年 3 月 1 日をもってサポート終了となります。このアップロード処理はアップローダー スクリプトに置き換わります。上記のアップロード スクリプトを使用できます。

上記のようにFirebaseで案内していますが、コンソールからアップロードは廃止される予定です。

まず、Firebaseドキュメントを参考にXCodeのRunScriptに追加したらOKらしい。

```shell
"${PODS_ROOT}/Fabric/upload-symbols" -gsp "${PROJECT_DIR}/GoogleService-Info.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
```

早速、RunScriptを作ったのはこんな感じです。

## まず、RunScriptの環境変数を調べる

とりあえずこれを叩くと全てのパスが確認できる

```shell
xcodebuild -showBuildSettings
```

または、

```shell
$ xcodebuild -showBuildSettings | grep "XXX"
```

## 環境ことにGoogleService-Infoを置き換える

ビルド環境が分けてあって複数のGoogleService-Infoを使っている場合は下記のように置き換える必要があります。

```shell
#[CP]GoogleService-Info.json
# Replace GoogleService-Info.json file by environment
if [ "${CONFIGURATION}" = "Debug" ]; then
    cp "${PROJECT_DIR}/${PROJECT_NAME}/GoogleService-Info-Debug.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
    echo "Debug(Develop) GoogleService-Info copied."
elif [ "${CONFIGURATION}" = "Staging" ]; then
   cp "${PROJECT_DIR}/${PROJECT_NAME}/GoogleService-Info-Staging.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
    echo "Staging(Staging) GoogleService-Info copied."
elif [ "${CONFIGURATION}" = "Release" ]; then
    cp "${PROJECT_DIR}/${PROJECT_NAME}/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
    echo "Production(Release) GoogleService-Info copied."
fi
```

## シンボルをアップロードする

上記のように環境が分けてあるのでアップロードも分けて処理するようにしておく。

```shell
#upload symbols
if [ "${CONFIGURATION}" = "Debug" ]; then
    "${PODS_ROOT}/Fabric/upload-symbols" -gsp "${PROJECT_DIR}/GoogleService-Info-Debug.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}"
    echo "Debug(DEV) uploaded symbols."
elif [ "${CONFIGURATION}" = "Staging" ]; then
   "${PODS_ROOT}/Fabric/upload-symbols" -gsp "${PROJECT_DIR}/GoogleService-Info-Staging.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}"
    echo "Staging(Staging) uploaded symbols."
elif [ "${CONFIGURATION}" = "Release" ]; then
    "${PODS_ROOT}/Fabric/upload-symbols" -gsp "${PROJECT_DIR}/GoogleService-Info.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}"
    echo "Production(Release) uploaded symbols."
fi
```

## Fabric initialize

これなんのためなのか分からないが、Firebaseドキュメントに書いてあったので最後に追加しました。

```shell
#Fabric Initialize
"${PODS_ROOT}/Fabric/run"
```


##ダメだった。

Archiveする際にアップロードはできているが（ログ上の確認）なぜか、Firebase上ではアップロードされませんでした。
誰かご存知の方、教えてください。
結局、ArchivingしたファイルからdSYMsをコピーしてターミナルでアップロードしました。
（これで一応SymbolはアップロードできてFirebase上でもアップロード表示に変わります。）

ターミナルコマンド

```shell

{プロジェクトのパス}/Fabric/upload-symbols -gsp {プロジェクトのパス}/GoogleService-Info.plist -p ios {dSYMsの場所}

```

以上。
Hey Siriで 自宅のテレビ 操作する

#はじめに
aloha!
巷には、とても便利な赤外線学習リモコンとアプリのセットやスマートスピーカーによって、音声で家電をコントロールしてくれるものも増えてきています。
今回は、ハードウェアを購入せずに、いつものiPhoneから「Hey Siri〜」で自宅のテレビを操作する方法をご紹介します。
iPhoneやiPadには、Appleが提供している「ショートカット」というアプリがあります。これを使うことで、「Hey Siri〜」と発話すると「Siri Kit」に対応するアプリと連携し、自動処理させることができます。

#必要なもの
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/06cc84b8-0f51-aedf-0bf0-e07359dfbd9a.jpeg" width=85%">
・WiFiルーター等とホームネットワーク（有線LAN、WiFi）
・ネットワーク接続に対応したテレビ（リビングで使っているシャープ製アクオスを使用）
・iPhone（iOS13.x）
・Apple製ショートカットアプリ（<a href="https://apps.apple.com/jp/app/id915249334">https://apps.apple.com/jp/app/id915249334</a>）
・家電手帳アプリ（<a href="https://inetcore.com/kadentecho/">https://inetcore.com/kadentecho/</a>）
　※家電手帳アプリiOS版2.0以降でTVリモコン機能とSiri Kitに対応。数社のテレビに対応してます。
#手順
※iPhoneをダークモードで使っているため、全体的に画面が黒いですが、気にしないでください。
１、iPhoneとテレビが同じネットワークに接続していることを確認します。（ネットワークに詳しい方は、デフォルトゲートウェイが同じかどうかなど疎通確認してください）
２、家電手帳アプリで、WiFi登録を行い、リモートで操作したいテレビ（例えば、「リビングのテレビ」）を登録します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/2bc55b81-2e76-6b0c-e6b5-463b1c927087.jpeg" width=50%>
この「リビングのテレビ」を選択して、TVリモコン画面を表示します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/e333b753-6ca8-421c-0c74-4161743fd615.jpeg" width=50%>
３、このTVリモコンで、「電源」ボタンを押したり、「地デジ」ボタンを押したり、「チャンネル1」（東京だとNHK総合）を押してみてください。
４、次に、「ショートカット」アプリを起動してください。まだダウンロードしていない場合は、ここでダウンロードしてください。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/e7b98e9c-cde1-6d1f-ba3e-c9dbdebb7438.jpeg" width=50%>
５、マイショートカットで、「ショートカットを作成」をタップしてください。「新規ショートカット」が表示されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/04a68342-528f-6a97-f507-198a8761b877.jpeg" width=50%>
６、「アクションを追加」をタップします。ショートカットで利用可能な直前までの操作が表示されますので、候補の中から「リビングのテレビの電源を入れる」をタップします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/84134dd5-4e84-cf75-15b2-d6166d65b4a5.jpeg" width=50%>
７、「次へ」を押して、呼び出しを行う際に使用するショートカット名を記入します。例えば、「リビングのテレビをつけて」などです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/1a8063e7-7e74-ae40-c756-6ad2cf869878.jpeg" width=50%>
８、これで完了です。複数のショートカットを登録するときは、3〜7を繰り返してください。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413003/1b263473-f4a6-677b-0345-b79465d3db1d.jpeg" width=50%>

#動作確認
１、iPhoneでSiriを起動（「Hey Siri!〜」か電源ボタンを長押しなど）します。
２、「リビングのテレビをつけて」と発話します。
３、「リビングのテレビ」と名付けたテレビの電源が入ります。

#参考
・デベロッパのためのSiri(<a href="https://developer.apple.com/jp/siri/">https://developer.apple.com/jp/siri/</a>)
・「ショートカット」（<a href="https://apps.apple.com/jp/app/id915249334">https://apps.apple.com/jp/app/id915249334</a>）
・「家電手帳」（<a href="https://inetcore.com/kadentecho/">https://inetcore.com/kadentecho/</a>）

#ご注意
今回ご紹介した方法は、ホームネットワークにiPhoneが繋がっている時にリモート操作する方法です。外出中には利用できません。テレビの電源をリモートからONにするためには、テレビ側の設定変更が必要ですので、予め変更をお願いします。詳しくは、テレビの取扱説明書をご覧になってください。（家電手帳アプリからでも、読めるかも。）

#おわりに
アプリ側が、Siri Kitに対応するように作られていれば、いろいろな機能をSiriから使うことができます。また、オートメーション機能もあるため、時刻やWiFi接続、NFCにタッチしたタイミングなどで一定の自動化を行うこともできるようです。詳しくは、Appleの資料（<a href="https://support.apple.com/ja-jp/HT209055">Siri ショートカットを使う</a>）をご覧ください。

mahalo!
DataCoreのVMware vSphere Virtual Volumes (VVols) 2.0を試す

[前回のセットアップはこちら。](https://qiita.com/tsurun/items/3fbb4e8a77d5e33e4d49)

前回の手順でインストールするとVASAプロバイダーは組み込みになったこともありインストール直後からすぐに使える状態になっています。
さっそく状態と動作を確認してみます。

###前回のおさらい
VASAプロバイダーが設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/2838798a-ad5d-76a9-a44c-cbc2408148b6.png)

VVOLのエンドポイントも自動で作成されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/4740660a-3e10-d58c-efa9-053f66386de2.png)


###動作テスト
サンプルの仮想マシンを作ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/c2604d79-4678-e5f2-2248-4953aaab52b0.png)

データコアのコンソールから見てみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/cbd4ed34-a36d-35d5-9e14-50ebd787bfe4.png)

vSphere側からスナップショットを作ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/9c8e7b8b-a5bf-cafc-e3da-67970a57cffe.png)

ストレージ側にオフロードされて、ストレージスナップショットが作成されることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/b9cb4348-4ef9-f57a-6da1-c0b6acbb3b9e.png)

仮想マシンをクローンしてみました。無事に終わってますが、グラフを見るとディスクに全然負荷が発生していませんね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/69f05575-f755-287f-7935-2e700a8ca32b.png)

データストアの中をのぞいてみます。フォルダの中身がb7a5～という4GBのダミーのvDisk内に格納されていることがわかりますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115778/b1767042-0ac8-ec99-1b85-d0b442590eb0.png)
【arrayformula()対応版】Google Spreadsheet 半角から全角に変換

@ssmxgo さんの記事に、
https://qiita.com/ssmxgo/items/2bc510c6cec91badd332

ミラクル素敵な関数 「toFullWidth()」を見つけました。

arrayに非対応だったため、arrayformula()で処理できなかったので、
ちょい足ししたものを公開させていただきます：


```js
// こちらを拝借させて頂きました
function toFullWidthSingle(value) {
  if (!value) return value;
  return String(value).replace(/[!-~]/g, function(all) {
    return String.fromCharCode(all.charCodeAt(0) + 0xFEE0);
  });
}

// アレイ対応にしました
function toFullWidth(array) {
  if (!array) return array;
  var newValues = [[]];
  array.forEach(function(item, index){
    newValues.push(toFullWidthSingle(item));
  });
  return(newValues.slice(1)) // 頭に一つ余計な要素が発生するのを削除して返す
}
```

Google Spreadsheetsは本当に便利ですね！

@ssmxgo 様ありがとうございました。
COTOHA アクセストークンの取得

[COTOHA API Portal](https://api.ce-cotoha.com/contents/index.html) の使用例です。

仕様
>[アクセストークン取得](https://api.ce-cotoha.com/contents/reference/accesstoken.html)

```py:access_token.py
#! /usr/bin/python
# -*- coding:utf-8 -*-
#
#	access_token.py
#
# ----------------------------------------------------------------------
import sys
import os
import json
from dotenv import load_dotenv
import  requests
# ----------------------------------------------------------------------
dotenv_path = '.env'
load_dotenv(dotenv_path)
CLIENT_ID = os.environ.get("CLIENT_ID")
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
DEVELOPER_API_BASE_URL = os.environ.get("DEVELOPER_API_BASE_URL")
ACCESS_TOKEN_PUBLISH_URL = os.environ.get("ACCESS_TOKEN_PUBLISH_URL")
#
data = {
	"grantType": "client_credentials",
	"clientId": CLIENT_ID,
	"clientSecret": CLIENT_SECRET
	}
str_json = json.dumps(data)

url = ACCESS_TOKEN_PUBLISH_URL
headers={
	"Content-Type": "application/json"
	}

try:
	rr=requests.post(url,headers=headers,data=str_json)
	print(rr.text)
except Exception as ee:
	sys.stderr.write("*** error *** in requests.post ***\n")
	sys.stderr.write(str(ee) + "\n")
# ----------------------------------------------------------------------
```

```text:.env
LIENT_ID = AAAAAAAAAAAAAAAAAAAAAAAAAA
CLIENT_SECRET = aaaaaaaaaaaaaaaaaaaaaaaaaa
DEVELOPER_API_BASE_URL = https://api.ce-cotoha.com/api/dev/nlp/
ACCESS_TOKEN_PUBLISH_URL = https://api.ce-cotoha.com/v1/oauth/accesstokens
```

実行結果

```text
$ ./access_token.py 

          {
            "access_token": "VAIET9p2UVvb*******", 
            "token_type": "bearer",
            "expires_in": "86399" ,
            "scope": "" ,    
            "issued_at": "1582265896034"           
           }
```

使ったバージョン

```text
$ python --version
Python 3.8.1
```
誕生日から年齢、曜日、干支、誕生石、星座を求める JXA（JavaScript for Automation）

## 概要
　AppleScript のスクリプトエディタで動作する、JavaScript です。（OS X で動作します。）
誕生日を入力し、基準日（省略すると現在日付）現在の年齢を計算します。
誕生日の曜日、干支、誕生石、星座も表示します。
誕生日の入力は、和暦："元号yy年mm月dd日"、西暦："yyyy/mm/dd" どちらの形式でもOKです。

　Scriptフォルダに入れとくと、メニューバーから起動できて便利に使えると思います。

## ソース
　スクリプトエディタの画面で、JavaScript に設定してソースをコピし、保存します。

```javascript:年齢計算Javascript.scpt
// 誕生日の曜日と年齢、干支、誕生石、星座を求める。
var app = Application.currentApplication()
app.includeStandardAdditions = true

var ans = app.displayDialog("誕生日を入力 (yyyy/mm/dd か 元号nn年mm月dd日)", {defaultAnswer: ""})
var iDate = ans.textReturned
var sDate = new Date(gengoChack(iDate))
var ans = app.displayDialog("計算の基準日を入力 (yyyy/mm/dd)入力を省略すると今日を基準に計算します。", {
	defaultAnswer: ""})
if (ans.textReturned == "") var tDate = new Date()
	else var tDate = new Date(ans.textReturned)

var youbi = '日月火水木金土'[sDate.getDay()]
var age = tDate.getFullYear() - sDate.getFullYear()
var mDate = new Date(tDate.getFullYear() + "/" + (sDate.getMonth() + 1) + "/" + sDate.getDate())
if (tDate < mDate) age = age - 1
ans = tDate.getFullYear() + "/" + (tDate.getMonth() + 1) +"/" + tDate.getDate()
var eto = ('申酉戌亥子牛寅卯辰巳午未')[sDate.getFullYear()%12]

app.displayDialog(iDate + " " + youbi + "曜日、" + eto + "年生まれのあなたは\n" +
	yymmdd(tDate) + "現在の年齢は " + age + "才で、\n" +
	"誕生石は" + stone(sDate.getMonth()) +
	"、星座は" + seiza((sDate.getMonth() + 1), sDate.getDate()) + "です。")

function yymmdd(wDate) {
	return wDate.getFullYear() + "/" + (wDate.getMonth() + 1) + "/" + wDate.getDate()
}

function stone(MM) {
	var ishi = ["ガーネット","アメジスト","アクアマリン","ダイヤモンド","エメラルド","真珠","ルビー",
			"ペリドット","サファイア","オパール","トパーズ","タンザナイト"]
	return ishi[MM]
}

function seiza(MM, DD) {
	var seiza = ""
	if (MM == 3 && DD >= 21)　ans  = "牡羊"
	if (MM == 4 && DD <=19)　ans  = "牡羊"
	if (MM == 4 && DD >= 20)　ans  = "牡牛"
	if (MM == 5 && DD <=20)　ans  = "牡牛"
	if (MM == 5 && DD >= 21)　ans  = "双子"
	if (MM == 6 && DD <=21)　ans  = "双子"
	if (MM == 6 && DD >= 22)　ans  = "蟹"
	if (MM == 7 && DD <=22)　ans  = "蟹"
	if (MM == 7 && DD >= 23)　ans  = "獅子"
	if (MM == 8 && DD <=22)　ans  = "獅子"
	if (MM == 8 && DD >= 23)　ans  = "乙女"
	if (MM == 9 && DD <=22)　ans  = "乙女"
	if (MM == 9 && DD >= 23)　ans  = "天秤"
	if (MM == 10 && DD <=23)　ans  = "天秤"
	if (MM == 10 && DD >= 24)　ans  = "蠍"
	if (MM == 11 && DD <=21)　ans  = "蠍"
	if (MM == 11 && DD >= 22)　ans  = "射手"
	if (MM == 12 && DD <=21)　ans  = "射手"
	if (MM == 12 && DD >= 22)　ans  = "山羊"
	if (MM == 1 && DD <=19)　ans  = "山羊"
	if (MM == 1 && DD >= 20)　ans  = "水瓶"
	if (MM == 2 && DD <=18)　ans  = "水瓶"
	if (MM == 2 && DD >= 19)　ans  = "魚"
	if (MM == 3 && DD <=20)　ans  = "魚"
	return ans + "座"
}

function gengoChack(ymd) {
	var gengo = ymd.substr(0,2)
	var dif
	switch(gengo) {
		case '明治': dif = 1867; break; // 元号の開始年 -1 を設定
		case '大正': dif = 1911; break;
		case '昭和': dif = 1925; break;
		case '平成': dif = 1988; break;
		case '令和': dif = 2018; break;
		default: return (ymd); 	// 西暦をそのまま返す
	}
	var nen = ymd.split(gengo)[1].split('年')[0]
	var tuki = ymd.split('年')[1].split('月')[0]
	var hi = ymd.split('月')[1].split('日')[0]
	nen = Number(nen) + Number(dif)
	return nen + "/" + tuki + "/" + hi	// 和暦を西暦に変換した値を返す
}

```

## コメント歓迎
　もっとエレガントな方法がありましたら、是非コメントをお願いします。
AWS Aurora Postgres のレプリケーションについて確認してみた。

公式ドキュメントはこの辺りになります。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-replicas-adding.html

AWSのRDSでAuroraを運用していますが、これまでそれほど負荷が高くないことも有り、リードレプリカのインスタンスは利用していませんでした。
これを、ちょっと重たい分析などを行いたいという話が出てきたため、リードレプリカのインスタンスを追加すればできるんじゃないかということで、漠然とした利用イメージはあるものの細かな動作や設定をどうすればいいかわかっていなかったので、確認してみたものです。

一通り動かして確認したものですが、ツールなどを使って厳密に検証を行ったと言えるものではありませんので、もし誤って理解しているような箇所があればご指摘いただけると幸いです。


# 結論
とにかく、検証結果確認できた結論から。

* 書込み可能なプライマリーインスタンスと、読み込み専用のリードレプリカは、インスタンスタイプは揃える必要はない。プライマリーより大きいリードレプリカ、プライマリーより小さいリードレプリカのどちらも作成が可能。
* エンドポイントは、クラスターのエンドポイントを指定し、個別インスタンスのエンドポイントは使用しない。個別のインスタンスを指定したい場合は、カスタムエンドポイント機能を使う。
* RDSの停止処理は、クラスター単位。リードレプリカを追加して、レプリカのインスタンスのみを停止させるといったことは不可能。
* プライマリーインスタンスに書き込まれた情報は、ほぼリアルタイムでレプリケーションされる。（タイムラグは通常数十ミリ秒単位）よほどシビアにリアルタイム性が追求されるシステムでもない限り、誤差が発生することを意識する必要なし。
* プライマリーインスタンスのDBに読み込みロックが掛かると、リードレプリカのテーブルも読み込み不可となる。
* Fail-over状態は1分程度で復旧。

--- 

## 0.前提
環境は `AWS RDS Aurora for Postgres でエンジンバージョンは 10.7` で確認しました。


## 1.インスタンスタイプについて
検証では、プライマリーインスタンスのタイプを

| プライマリーインスタンスタイプ | リードレプリカのインスタンスタイプ |
|---|---|
| r5.large | t3.medium |
| t3.medium | r5.large |

の両方で検証。いずれも問題なく作成できた。
もちろん、両方のサイズを揃えた状態でも問題なし。


## 2.エンドポイントについて
参考URL
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.Connecting.html#Aurora.Connecting.AuroraPostgreSQL
https://dev.classmethod.jp/cloud/aws/amazon-aurora-custom-endpoints/

AruroraのDBを指定するエンドポイントとしては

* クラスターの書き込み用エンドポイント
* クラスターの読み込み用エンドポイント
* カスタムエンドポイント
* インスタンスエンドポイント

の4種類がある。

この内、インスタンスエンドポイントについては基本的に **利用してはいけない** 。
一見、インスタンスのエンドポイントを指定しても正常に動作するように見えるが、フェイルオーバーなどの処理によってロールが変更され、書き込み用インスタンスだったものが読み込み専用になるなど、障害等が発生した際に処理が継続できなくなる恐れがある。このため、必ずクラスターのエンドポイントを指定する。
クラスターのエンドポイントは書き込み用と読み込みようが用意されていて、基本は書き込み用にアクセスできるようになっていればすべての処理が実行可能。
読み込み用のエンドポイントの場合は、リードレプリカが複数ある時、どのインスタンスにアクセスするかは自動的に振り分けられる形になる。
リアルタイム分析など、読み込み専用の処理であれば、読み込み用のエンドポイントを利用することで、書き込み用のプライマリーインスタンスに負荷をかけずに処理することができる。
カスタムエンドポイントは、その組み合わせ。例えばリードレプリカを5台用意しているような場合で、分析で大きな負荷がかかるような処理がある場合、書き込み処理を行うメーンの処理はプライマリー1台と2台のリードレプリカを指定し、残りの3台を分析処理専用に使う、といった処理系の大きさに合わせた組み合わせでインスタンスを効率的に利用することが可能となる。

~~~
[未検証情報]
参考URL: https://readouble.com/laravel/6.x/ja/database.html#read-and-write-connections
Laravelを利用する場合は、databaseの設定で、readとwriteのDBを切り分けが可能。
この機能とエンドポイントの指定をうまく組み合わせれば、書き込み処理と読み込み処理の接続先を切り分けることで負荷分散が図れるはず。
~~~

## 3.停止・削除処理
RDSの停止処理は通常のRDSインスタンスと同様に1週間の停止後自動起動となる。
ただし、停止できるのはクラスター単位。インスタンス単位での停止は不可。
追加したリードレプリカの削除は随時任意のタイミングで実施可能。
リードレプリカの作成もダウンタイム無しで任意のタイミングで実施可能。
リードレプリカが存在する状態でプライマリーインスタンスを削除すると、ロールが変更され、リードレプリカのインスタンスがプライマリーインスタンスへと昇格する。
ダウンタイムはほとんどなかった（あったとしてもおそらく切り替わる数秒間程度）。

## 4.レプリケーション・ロック
レプリケーションにより発生するタイムラグは、概ね20ミリ秒以下（同一A-Z内）。異なるアベイラビリティゾーンの場合でも30ms程度。
ほぼリアルタイム処理と考えて問題なし。
Postgresの `LOCK TABLE` 機能で確認。
プライマリーインスタンスのテーブルにロックをかけると、クラスターのエンドポイントからも、リードレプリカのエンドポイントからも、該当テーブルを読み込めなくなった。

## 5.Fail-Over
フェイルオーバーをAWS consoleから実行したところ、ダウンタイムあり。
ただし、１分程度で利用可能な状態に復旧する。実際に障害が発生した際も同様と考えられる。