OmniAICreator/Qiita-1.07M huggingface dataset:
Primer3webをMacにインストールしてローカルでprimer3サーバをたてる



- Mac (SierraだけどEl Capitanとかでも同じ。High Sierraでも同じなはず) でたてる。いちおうXcodeとcommand line toolがはいっていることが前提。

- ダウンロードして展開する

	[primer3: https://sourceforge.net/projects/primer3](https://sourceforge.net/projects/primer3)
	[primer3web: https://sourceforge.net/projects/primer3/files/primer3-web/](https://sourceforge.net/projects/primer3/files/primer3-web/)

- 180621の時点でprimer3が2.4.0でprimer3webが4.1.0

```
tar zxvf primer3-2.4.0.tar.gz
tar zxvf primer3web-4.1.0.tar.gz
```

## primer3

- primer3のツールをコンパイルする

```
cd primer3-2.4.0/src
sudo make
```

- warningでたけど`make test`して全部OKなら大丈夫

```
make test
```

-  `primer3-2.4.0/src/` ディレクトリ内にある `primer3_core` をCGIにつかう

## apache と CGI

- apache使えるようにしておく

```
sudo apachectl start

# もし自動起動にしておくなら以下
# sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

```

- perl に `CGI.pm` があるか確認（ないならcpanなどでinstall）

```
perl -MCGI -e 'print $CGI::VERSION' 


# もしないなら、sudo perl -MCPAN -e shell または sudo cpan
# cpan> install CGI
```

- CGIが動くディレクトリ（ここでは`~/Sites`）を用意する

```
mkdir ~/Sites
```

- `/etc/apache2/httpd.conf` とかを書き換える（たとえば以下）

```
LoadModule cgi_module modules/mod_cgi.so  #コメントアウトする
<Directory "/Users/{user_name}/Sites/">   #{user_name}は自分のアカウント名にする
     AllowOverride All
     Options ExecCGI
    AddHandler cgi-script .cgi
</Directory>
```

## primer3web 

- CGIが動くディレクトリ（ここでは `~/Sites`）にprimer3webを置く（`~/Sites/primer3web-4.1.0/`）

```
mv primer3web-4.1.0 ~/Sites/primer3web-4.1.0
```

- `~/Sites/primer3web-4.1.0/html` ディレクトリのなかに、`~/Sites/primer3web-4.1.0/cgi-bin` ディレクトリをまるごと移動する （`~/Sitesにprimer3web-4.1.0/html/cgi-bin`にする）

```
mv ~/Sites/primer3web-4.1.0/cgi-bin ~/Sites/primer3web-4.1.0/html/cgi-bin
```

- `~/Sites/primer3web-4.1.0/html/cgi-bin` ディレクトリのなかの `primer3web_results.cgi` を実行可能にしておく。

```
chmod 755 primer3web_results.cgi
```

- `~/Sites/primer3web-4.1.0/cgi-bin` ディレクトリのなかに 読み書き可能なcacheディレクトリをつくっておく （`~/Sites/primer3web-4.1.0/cgi-bin/cache`）

```
mkdir ~/Sites/primer3web-4.1.0/cgi-bin/cache
chmod 777 ~/Sites/primer3web-4.1.0/cgi-bin/cache
```

- `~/Sites/primer3web-4.1.0/cgi-bin` ディレクトリのなかに `primer3_core` をコピーしておく（`~/Sites/primer3web-4.1.0/cgi-bin/primer3_core`）

- もうこれでうごくはず。以下から動作確認。
 
```
http://localhost/{user_directory}/primer3web-4.1.0/html/primer3web_input.htm
```

- 必要なら、primer3_coreをコンパイルした`primer3-2.4.0/` ディレクトリ内にある、`kmer_lists`ディレクトリを`~/Sites/primer3web-4.1.0/cgi-bin` ディレクトリのなかにコピーしておく（`~/Sites/primer3web-4.1.0/cgi-bin/kmer_lists/*.list`）


## misc.

本当はhtmを`chmod 644`とか、ほかのディレクトリやCGIスクリプトも`chmod 755`とか、cgiのshebang(`#!`)をシステムのperlのpath（`which perl`で調べる）に書き換えるとか、安全対策で`primer3_core`とCGIスクリプトはweb上から見えないディレクトリに移すとか、index.htmlを準備（`ln -s`するなり作るなり）するとか、いろいろ必要あるとおもうけど、ローカルマシンでならこのままで（なぜか）動く。

そもそもコンパイラのインストールとかネットワークの準備とか、ほんとはそこが敷居がたかいのかな。。。
リアルタイムにテキストボックスの入力値を取得する

おなじみの`change`だと、フォーカス失ったときにしか発火しないのでこれまで工夫が必要でした。
知らなかったのですが、`input`イベントてのがあり、これだとリアルタイムで入力を取得できます。

<p data-height="265" data-theme-id="0" data-slug-hash="NzYyRw" data-default-tab="js,result" data-user="pokkur" data-embed-version="2" data-pen-title="Check Input Number (onInput)" class="codepen">See the Pen <a href="https://codepen.io/pokkur/pen/NzYyRw/">Check Input Number (onInput)</a> by pokkur (<a href="https://codepen.io/pokkur">@pokkur</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

ちなみに初期値は、dispatchEventでinputさせています。

```js
origin.dispatchEvent(new Event('input'))
```
erlang: Eunitテスト時debugVal等を使って debugします

OTP:20.1.1
Eunitを使ってテストすることが多いです
python2みたいに手軽に```print "Debug Info"```を出したい時Eunitの便利なマクロ群を使うと便利です
erlangでも似たようなことができます
# 前提
テスト対象モジュールに

```erlang
-include_lib("eunit/include/eunit.hrl").
```
eunitのヘッダーを追加します
# 使用
あとは[ドキュメント](http://erlang.org/doc/apps/eunit/chapter.html)通り使えばいいと思います
自分のよく使うマクロは
## debugMsg(Message).

``` erlang
?debugMsg("Enter RoutineA").
```
```:output
/path/to/test.erl:line:PID:Enter RoutineA
```

## debugVal(Expr)

``` erlang
?debugVal(Body).
```
```:output
/path/to/test.erl:line:PID: Body = <<"Request Body">>
```

## debugVal(Expr, Depth)
debugValを使う時Exprが長すぎると、表示が```...```により省略されることがあります。

```:bad_sample
/path/to/test.erl:line:PID: Body = <<"Request Has Lonnnnnng Bo...">>
```
肝心のデバッグ情報が省略されてこれじゃデバッグできないじゃと悩む時、eunitのソースを読んでみると

```erlang:
-define(debugVal(E, D),
        begin
        ((fun (__V) ->
                  ?debugFmt(<<"~ts = ~tP">>,
                            [(??E), __V, D]),
                  __V
          end)(E))
        end).
-ifndef(EUNIT_DEBUG_VAL_DEPTH).
-define(EUNIT_DEBUG_VAL_DEPTH, 15).
-endif.
-define(debugVal(E), ?debugVal(E, ?EUNIT_DEBUG_VAL_DEPTH)).
```
つまり```?debugVal(Expr)```実は```?debugVal(Expr, 15)```を呼び出しています。そしてドキュメントによると
> debugVal(Expr, Depth)
> Like debugVal(Expr), but prints terms truncated to the given depth.
デフォルトは一つのtermを深さ15まで出力してくれます

したがって```?debugVal(Expr, 100000)```にすれば多めに出力してくれます。ただし本番環境だとメモリが食うすぎて気をつけること。OTP21だと```?debugVal(Expr, 0)```で全部出力してくれそう（未検証）
しかし```?debugVal```マクロが使用するformatは```<<"~ts = ~tP">>```なので、charが全部255以下の場合```<<50,48,53,53,51,52,51,56,34,44,10,32,34,110,97,109>>```のような意味不明なバイナリーが出力されます
この時は

``` erlang
io:fwrite("show data: ~ts", [Data]).
```
で```~ts```フォーマットを使って出力すれば元の文字列が見れます。
## debugFmt(FmtString, Args)
久しぶりにerlangをかくとよくinterpolationのフォーマットが忘れてしまうのでできるだけ避けてきたが、親切なよりexpressive(表現力の高い)デバッグメッセージを出力したい時はやっぱりdubugFmtを使います(@shino さんのサンブルコードを拝借いたします、thx)

``` erlang
?debugFmt("show data: ~ts", [Data])
```
Vagrantの導入

# Vagrantのインストールと設定
Vagrantの操作はコンソール(Macならターミナル)で行うこととなる。

## 前提
VirtualBox
https://www.virtualbox.org/wiki/Downloads
Vagrant
https://www.vagrantup.com/downloads.html

上記がインストールされていること。
※ VirtualBox→Vagrantの順番でインストールしておくとトラブルが少ない。

## Vagrantのインストール
ダウンロードしたVagrantのインストールファイルを叩けば完了する。

## 便利設定
仮想マシンGuest Addtionsの自動更新を有効化する。
1. `$ vagrant plugin install vagrant-vbguest`

## Vagrantfileの用意
Vagrant用の設定ファイル。VirtualBoxへのOS導入も自動でやってくれる。

    --Vagrantfileの内容--
    
    Vagrant.configure("2") do |config|`
      config.vm.box = "[任意のvm名称]"
      config.vm.box_url = "[仮想マシンで利用するBOXのURL]"  // 仮想イメージの作り方等は別記事で。
      config.ssh.password = "[仮想マシン上でのVagratユーザのpassword]"
      config.vm.network "forwarded_port", guest: 10080, host: 10080 // httpのポート設定
      config.vm.network "forwarded_port", guest: 10443, host: 10443 // httpsのポート設定

      ---- ホストOSとゲストOSで共有するフォルダ(例としてWebアプリで使用するフォルダを記載)
      config.vm.synced_folder "html", "/var/www/html/", create: true, mount_options:                 
      ['dmode=777','fmode=777']
      config.vm.synced_folder "ssl", "/var/www/ssl/", create: true, mount_options: 
      ['dmode=777','fmode=777']
      config.vm.synced_folder "log", "/var/log/httpd/", create: true, mount_options: 
      ['dmode=700','fmode=644'], owner: "root", group: "root"
    
      # 共有フォルダ設定でログフォルダが作り直されてログ保存ができなくなるのでApacheを再起動してフォルダを認識させる
      config.vm.provision "shell", run: "always", inline: "service httpd restart"
    end

## Vagrantの起動
 Vagrantfileが設置されているディレクトリで以下のコマンドを実行する。

    $ dir /b       // Vagrantfileがあることを確認する。
    Vagrantfile
    $ 
    $ vagrant up   // Vagrantの実行。
    Bringing machine 'default' up with 'virtualbox' provider...
    ～～
    default: Running: inline script
    default: Redirecting to /bin/systemctl restart httpd.service
    $ 
##### 
※ 上記仮想マシンは10080,10443,2222番ポートを使用しますので、既に使用している場合は他ソフトを閉じるかVagrantfileの中身を書き換えてる必要がある。

vagrantが起動すると、ブラウザから http\://localhost:10080 または https\://localhost:10443 で自身の仮想マシンにアクセスすることができる。

※ Windowsの記事だが、Macでもほぼ変わらない操作で導入できる
##
Vagrant & CentOS7.2 に Rails と PostgreSQL をインストールする手順

# 環境

|項目|バージョン|
|:--|:--|
|ホストOS|Windows10|
|ゲストOS|CentOS7.2|
|VirtuaoBox|5.2.12|
|Vagrant|2.1.2|

# rubyをインストール
参考：https://qiita.com/inouet/items/478f4228dbbcd442bfe8

```bash:bash
### gitをインストール
sudo yum -y install git

### rbenvをインストール
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

### PATH に追加
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile

### .bash_profile に追加
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

### 上記設定の再読み込み
exec $SHELL -l

### rbenvのバージョン確認
rbenv --version

### ruby-buildをクローン
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

### インストール可能なバージョン一覧を確認
rbenv install --list

# パッケージをインストール
sudo yum install -y openssl-devel readline-devel zlib-devel

# rubyをインストール
rbenv install -v 2.5.1

# 再読み込み
rbenv rehash

# インストールされているruby一覧を確認
rbenv versions

# rubyのバージョンを設定
rbenv global 2.5.1

# バージョン確認
ruby -v

```

# bundlerをインストール
```bash:bash
gem install bundler
```

# railsプロジェクト上でgemをインストール

```bash:bash
# node.jsをダウンロードしておく
sudo yum install nodejs --enablerepo=epel

# sqliteをインストール出来るようにしておく
sudo yum install libsq3-devel

# pgを個別にインストールしておく
gem install pg -v '0.21.0' -- --with-pg-config=/usr/pgsql-9.6/bin/pg_config

#gemをインストール
bundle

#------------------------------------
# ovirt-engine-sdk -でエラーが出たら, 
# gemfileで 「gem 'fog', '~> 1.41.0'」として
# fogのバージョンを下げる
#（2.0.0を入れようとするとエラーが出る）
#------------------------------------

```

# postgresqlをインストール
参考：https://zilu.sakura.ne.jp/develop/vagrant-centos7-postgresql9-6

```bash:bash
# パッケージをダウンロード
wget https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm

# インストールを確認
ls

# パッケージをインストール
sudo yum -y install pgdg-centos96-9.6-3.noarch.rpm
sudo yum -y install postgresql96-server postgresql96-devel postgresql96-contrib

# PostgreSQLのデータベースを初期化と起動
sudo /usr/pgsql-9.6/bin/postgresql96-setup initdb
sudo systemctl start postgresql-9.6

# PostgreSQL9.6の設定を変える
sudo vi /var/lib/pgsql/9.6/data/postgresql.conf
#----------------------------------------------
# 59 # listen_addresses = 'localhost'
# #↓に変更
# 59   listen_addresses = '*'

# 433 log_line_prefix = '< %m > '
# #↓に変更(ログ出力形式：「日時　ユーザ　データベース」)
# 433 log_line_prefix = '<%t %u %d>'
#----------------------------------------------

sudo vi /var/lib/pgsql/9.6/data/pg_hba.conf
#-----------------------------------------------
# 80行目付近の
# local all all peer 
# という形になっている6行のpeerやidentをtrustに変える
# (パスワード無しでもログイン出来たり, migrate出来るようになる)
#-----------------------------------------------

# 再起動
sudo systemctl restart postgresql-9.6

# ユーザーをpostgresに変える(shell-promptが表示される)
sudo su - postgres

```

```shell-session:shell-prompt

# postgresにログイン(postgres-promptが表示される)
psql

```

```shell-session:postgres-prompt
# ユーザーを作成
CREATE USER 【ユーザー名】;

# ユーザーに権限を追加
ALTER ROLE 【ユーザー名】 WITH SUPERUSER CREATEROLE CREATEDB REPLICATION BYPASSRLS;

# ユーザーを確認
\du

# テーブルを作成
CREATE DATABASE 【テーブル名】;

# テーブルを確認
\l

# 出る
\q
```
```shell-session:shell-prompt
# 出る
exit
```
Golang Walk: タイトルバーにアイコンをセットする方法

golang walkでタイトルバーにアイコンを表示する方法の質問があったので回答してみました。

https://github.com/lxn/win/issues/53

#■アイコンファイルをロードする方法

```
    icon, iconErr := walk.Resources.Icon("foo.ico")

    err := MainWindow{
        AssignTo: &mainWin,  
        Title:    "MainWindow",
        Icon:     icon,
        (snip)
    }.Create()
```
#■リソースからアイコンをロードする方法
rsrcでリソースにバインディングします。
```
rsrc -arch amd64 -manifest foo.exe.manifest -ico foo.ico -o rsrc.syso
```
ソースコードでは次のように呼び出します。
"3"はrsrcすると、アイコンのリソースIDが"3"になっていたのでこのように指定しています。

```
	icon, iconErr := walk.Resources.Icon("3")
```
Windows 10: デスクトップのコンテキスト メニューに残る"Open with GitKraken"を削除する

Windowsで利用可能なGit Clientである[GitKraken](https://www.gitkraken.com/)。

入門者向けを意識して極力オプションも省いた設計の新鋭Gitクライアントです。

私のWindows 10 Home x64環境ではデスクトップを右クリックして出てくるコンテキスト メニューに

`Open with GitKraken`

が登録されていて、これは通常の登録方法（一般的には自動起動の Directory or Folder キーに登録される）とは異なるレジストリKeyに格納されているためGitKraken本体をいくら削除しても再インストールしても消えることがありませんでした。

前述したように可能な限りオプションを省いたクライアントのため設定画面には「右クリック メニューへの登録」の有無を行う項目はありません。

日本語検索では解決方法が見つからないので現行のインストーラーでは発生しない事象かもしれず以前のインストーラーが強制的に行った設定かもしれません。

今回はregeditで検索してKeyを探し削除することで解決したので記しておきます。

Keyの場所は

`HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell`\GitKraken

です。

レジストリ エディター（regedit.exe）を管理者権限で起動して該当箇所にある `GitKraken` 以下を削除してWindowsの再起動を行えば完了です。

入門者向けということでデスクトップのコンテキスト メニューに強制登録したのかもしれませんが日本語環境だと場合によりデスクトップはDesktopに置き換えられ、かえって混乱を招くため個人的にはあまり推奨できません。
EclipseでC++でDirectX11を使って3D表示

# 初めに
そもそも論だけど、DirectxやるならVisual Studio使ったほうが楽。（MSの回し者ではないよ？）
Windowアプリ作るだけでも（以下略

諸事情により、Visual Studioがインストールできない環境でどうしてもDirectXを使ってみたかったから、Eclipse使ってどうにかならないかなーと四苦八苦してやっとこ表示まではこぎつけた。

#環境
ちなみに、自分がやった環境はこんな感じ。
- Windows7 64bit
- Eclipse pleiades all in one Oxygen Release (4.7.0) Ultimate Full Edition

#設定
プロジェクトプロパティの設定がいくつか必要

(1)コンパイル設定
GCC C++ Compilerの設定で以下を追加設定
- プリプロセッサーに \_XM_NO_XMVECTOR_OVERLOADS_ を追加 → DirectxMath使うため
- その他のその他フラグに -mwindows 追加 → Windowアプリのとき必要なので

(2)リンカ設定
MinGW C++ Linker設定
- ライブラリーにd3d11を追加
- その他のリンカーフラグに -mwindows 追加 → Windowアプリのとき必要なので

#シェーダー
環境の都合上、D3DCompiler_47.dllが入っていなかったので、DLLの入っているPCでfxc.exeを使用してバイナリコンパイルしたものを使用。

#DirectXMathの利用
D3DX系は終了なので、座標計算のライブラリはDirectXMathを利用することに。
[Github](https://github.com/Microsoft/DirectXMath)からダウンロードし、Incフォルダ内をコピー
※プリプロセッサーに \_XM_NO_XMVECTOR_OVERLOADS_ を設定してないとコンパイル時にエラーがでる

#Windowの表示
WinAPIを使用してウインドウを表示。
コードは省略。

#DirectX
[このサイト](https://araramistudio.jimdo.com/2017/09/01/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-directx-11%E3%81%A7%E7%AB%8B%E4%BD%93%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%97%E3%82%88%E3%81%86-%E3%81%9D%E3%81%AE%EF%BC%92/)をほぼそのまま使用。シェーダーがヘッダファイルを使用しているけど、そこの部分をバイナリファイルを読み込んで使用するように修正したくらい。

#結果
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/195280/ae914565-a0c2-e7a4-013e-6c9fd5ec452b.png)

まぁこれでとりあえず第一段階は終了、
MySQLでSQLの結果を変数に格納する

# やりたかったこと
開発用のローカルDBを作るのに本番DBからのダンプデータを使いたい。
ただし全件ではデータが膨大でマスク処理やリストアに時間が掛かるので、直近登録の1000件のユーザを除いて古いユーザデータを削除したい。

# どうやったか
直近1000件のユーザIDを取得して関連データを削除する。

### set構文
最初はset構文を使い手動でid降順で1000件目のidを変数へ代入していました。

```sql
> select MIN(id) from (select id from users order by id desc limit 1000) hoge;
+---------+
| MIN(id) |
+---------+
|    4001 |
+---------+

> SET @min_user_id = 4001;
```

この方法だと毎回1000件目のidを調べてから手動でSQLを書き換える必要があったので面倒くさい

### SQLの結果を格納

SELECT句の中で代入式を書くとその結果を変数に格納して利用できます。

```sql

> SELECT @min_user_id := `id` FROM users ORDER BY id DESC LIMIT 1000;
+----------------------+
| @min_user_id := `id` |
+----------------------+
|                 5000 |
|                 4999 |
.
.
.
|                 4002 |
|                 4001 |
+----------------------+
1000 rows in set (0.00 sec)

> select @min_user_id;
+--------------+
| @min_user_id |
+--------------+
|         4001 |
+--------------+
1 row in set (0.00 sec)

> DELETE from users where id < @min_user_id
Query OK, 4000 row affected (0.00 sec)
```

これで毎回同じSQLで実行できるので自動化できるようになりました。
[VisualStudio2017から] C++プロジェクトのソースコードをUTF-8で保存する方法

VisualStudio2017から（もしくは何かの拍子に？）、C++プロジェクトを新規作成すると、そのソースコードが UTF-16 で保存されるようになっていた。
UTF-16だとSourceTreeやBitBucketなどでソースコードが正しく表示されないという問題があるため、何とかしたいと色々探し回っていたら以下の方法を発見した。

この方法だと、簡単にかつ確実に UTF-8 で保存されるようになる。

## 方法
プロジェクトフォルダー（もしくはそれより上位のフォルダー）に .editorconfig というファイルを置く。
内容は以下の通り。

```:.editorconfig
root = true

[*.{c,h,cpp,cs}]
end_of_line = crlf
charset = utf-8-bom
trim_trailing_whitespace = false
insert_final_newline = false

[*.rc]

[*.{md,txt}]

[*]
```

### 注意
`[*]` にutf-8設定を記述してしまうと、リソースファイル（*.rc）もUTF-8化されてしまうため（Editorで直接編集した場合のみ？）、ビルドすら通らなくなってしまう。
そういったトラブルを避けるために、utf-8化するのは .cpp/h に限定している。

## 参考
[.editorconfig の書き方 - Qiita](https://qiita.com/inabe49/items/d81fed3cf58ad751d915)

## 補足 
VS2019ではボタン1つで .editorconfig を生成できるように ~~なるっぽい~~ なっている。（2019/08/06確認）
https://twitter.com/okazuki/status/1073568778900824064?ref_src=twsrc%5Etfw

## おまけ: プロジェクトテンプレート化
[Visual Studio 2017でプロジェクトテンプレート作成 - 何でもプログラミング](http://any-programming.hatenablog.com/entry/2017/05/24/190524)
プロジェクトの新規作成を頻繁に行うならテンプレート化しておいたほうがいいかも。
但し、VS2017のテンプレートのエクスポートでは正しく？エクスポートされないようなので、MyTemplate.vstemplate ファイルを手作業で書き換える必要がある。

```xml:MyTemplate.vstemplateのサンプル
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
  <TemplateData>
    <Name>MyConsoleApplication</Name>
    <Description>UTF8</Description>
    <ProjectType>VC</ProjectType>
    <ProjectSubType>
    </ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>MyConsoleApplication</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <Project TargetFileName="ConsoleApplication2.vcxproj" File="ConsoleApplication2.vcxproj" ReplaceParameters="true">
      <ProjectItem ReplaceParameters="false" TargetFileName="$projectname$.vcxproj.filters">ConsoleApplication2.vcxproj.filters</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="$projectname$.cpp">ConsoleApplication2.cpp</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="stdafx.cpp">stdafx.cpp</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="stdafx.h">stdafx.h</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="targetver.h">targetver.h</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName=".editorconfig">.editorconfig</ProjectItem>
    </Project>
  </TemplateContent>
</VSTemplate>
```

※.cpp/h が全く入っていなかったので追記。さらに、zipファイル内に該当ファイルを追加。
Google Docsをコピーするときにコメントや返事も一緒にコピーしたい

# 概要
Google Docs（Document, Spreadsheet, Slide）を手動やGoogle Apps Script、APIなどを使ってコピー（複製の作成）すると、Docs本体やバウンドスクリプトはコピーされるのですが、Docs内に書かれたコメントやコメントへの返事はコピーされません。コメントやコメントへの返事を全部削除したい場合はこの仕様で問題ないのですが、それらを一緒にコピーしたいと思った時、少し悩まされましたので、解決方法も含めてこの記事でGoogle Docs内に書かれたコメント、コメントへの返事をコピーする方法について紹介させていただきます。


# 試したこと
1. Google Docsをweb interfaceを使って手動でコピー、Drive apiのdrive.files.copyやDriveAppのmakecopyでコピー
    - コメント自体が失われる。
    - 使用: **✖**
1. Google DocsをMicrosoft Docs（Word, Excel, Powerpoint）へ変換して、それを再びGoogle Docsへ変換
    - コメント並びに返事は残るが、アンカーがおかしくなるため、コメントの場所情報が失われる。
    - 使用: **✖**
1. Drive APIのDrive.Commentsを使ってコピー
    - コメント、返事、場所ともにコピー可能
    - 使用: **〇**
        - Drive.Comments.listでコメントと返事を取得し、Drive.Comments.insertでコメントをコピーしてDrive.Replies.insertでコピーしたコメントに対して返事をコピー（専用のAPIがあるので素直にそれを使いましょうということですね。）

DriveAppではコメントを取得したりインサートするメソッドが今のところ見当たらないため、Drive APIの[Drive.Comments](https://developers.google.com/drive/api/v3/reference/comments)を使用しました。Drive APIを使用しますので、スクリプトを変更することで外部からの操作も可能です。


# サンプルスクリプト
## スクリプトの実行前にすること
このサンプルを使用する際は、Googleの拡張サービスとAPIコンソールでDrive APIを有効にしてください。

- [Googleの拡張サービス](https://developers.google.com/apps-script/guides/services/advanced)
    - スクリプトエディタから リソース -> Googleの拡張サービス を開き、Drive APIを有効にしてください。バージョンは今のところv2のみを選択することができます。

- APIコンソール
    - スクリプトエディタから リソース -> Cloud Platform プロジェクト を開き、右下の 「APIコンソールを表示」 をクリックします。
    - スタートガイドの中にある「APIを有効化し、鍵などの認証情報を取得」をクリックします。
    - 「有効な API またはサービスがありません」と表示されている場合は、その下にある「Google Drive API」をクリックして「有効にする」ボタンを押して有効にします。
    - 「有効な API またはサービスがありません」と表示されていない場合は、左側の「ライブラリ」を開いて「APIとサービスを検索」のテキストボックスへ「Drive API」と入力して検索し、「Google Drive API」をクリックして「有効にする」ボタンを押して有効にします。

これで準備は完了です。


## サンプルスクリプト
このサンプルスクリプトはGoogle Apps Script用です。スクリプトエディタへコピー＆ペーストしてお使いください。コピー元となるコメントやコメントへの返事が書かれているGoogle DocsのファイルIDを``src``としたサンプルスクリプトは下記の通りです。

~~~javascript
var src = "#####"; // コメントのコピー元になるGoogle DocsのファイルID. この部分は入力してください。

var dst = DriveApp.getFileById(id).makeCopy().getId(); // コメントのコピー先になるGoogle DocsのファイルID
var commentList = Drive.Comments.list(src);
commentList.items.forEach(function(item) {
    var replies = item.replies;
    delete item.replies; //  item.repliesを削除しないとエラーになる。
    var commentId = Drive.Comments.insert(item, dst).commentId;
    replies.forEach(function(reply) {
        Drive.Replies.insert(reply, documentId, dst);
    });
});
~~~

## スクリプトの流れとポイント
スクリプトの流れは次の通りです。

1. コピー元のファイルをコピー
1. コピー元のファイルからコメントと返事を取得
1. コピーしたファイルへコメントと返事をコピー

コメントと返事をコピーする際のポイントは次の通りです。

- コメントをコピーする際はDrive.Comments.insertを使って新規で作成します。コンテンツやアンカー情報はDrive.Comments.listで取得したオブジェクトに含まれていますのでそのまま使用します。このとき、コピーするオブジェクトに返事のオブジェクトを含めているとエラーになってしまいます。
- コメントへの返事をコピーする際は、insertしたコメントからコメントIDを取得してDrive.Replies.insertを使ってコピーします。

## 制限
このスクリプトの制限としては、コメントや返事が書かれた日付はインサート時のリクエストボディや後からのアップデートを使っても変更できなかったため、残念ながら日付情報についてはコピーはできません。これはDrive API v3で試してもできませんでした。コンテンツは変更できますが、日付の変更ができませんでした。何か他の方法が見つかった際はこの記事を更新したいと思います。
知らなかったけど「isset($a) && isset($b)」は「isset($a, $b)」と書けるらしい。コード量が減るのでいいかも。

PHPで`isset($a) && isset($b)`は`isset($a, $b)`とも書ける。コード量が減るのでいいかも。

```php
$a = 1;
$b = 2;

isset($a, $b); // true
isset($a) && isset($b); // true

isset($a, $hoge); // false
isset($a) && isset($hoge); // false
```

なお、普通にマニュアルに書いてある: [PHP: isset - Manual](http://php.net/manual/ja/function.isset.php)。

ベンチマーク的には

* 値が定義されている場合(つまり`true`を返す場合)は`isset(a,b)`を使ったほうが早い
* 値が定義されていない場合(つまり`false`が返る場合)は`&&`を使った方が早い
    * でも調べる個数が増えると`&&`は遅くなる

という結果が出たが、些細な違いな気がする。

```php
<?php

function bench(int $repeat, callable... $snippets)
{
    foreach ($snippets as $no => $snippet) {
        $start = microtime(true);
        for ($i = 0; $i < $repeat; $i++) {
            $snippet();
        }
        printf("snippet #%d: %0.8f秒\n", $no + 1, microtime(true) - $start);
    }
}

$data = ['x' => 1, 'y' => 2];

bench(
    10000000,
    // 0.76908994秒
    function () use ($data) {
        isset($data['x'], $data['y']);
    },
    // 0.83662701秒
    function () use ($data) {
        isset($data['x']) && isset($data['y']); 
    },

    // 0.68813109秒
    function () use ($data) {
        isset($data['none1'], $data['none2']);
    },
    // 0.54158902秒
    function () use ($data) {
        isset($data['none1']) && isset($data['none2']);
    },

    // 0.67208385秒
    function () use ($data) {
        isset($data['x'], $data['none']);
    },
    // 0.66804123秒
    function () use ($data) {
        isset($data['x']) && isset($data['none']);
    },

    // 0.76296902秒
    function () {
        isset(
            $data['a'],
            $data['b'],
            $data['c'],
            $data['d'],
            $data['e'],
            $data['f'],
            $data['g'],
            $data['h'],
            $data['i'],
            $data['j']
        );
    },
    // 0.81688905秒
    function () {
        isset($data['a']) &&
        isset($data['b']) &&
        isset($data['c']) &&
        isset($data['d']) &&
        isset($data['e']) &&
        isset($data['f']) &&
        isset($data['g']) &&
        isset($data['h']) &&
        isset($data['i']) &&
        isset($data['j']);
    }
);
```

結果

```
snippet #1: 0.76908994秒
snippet #2: 0.83662701秒
snippet #3: 0.68813109秒
snippet #4: 0.54158902秒
snippet #5: 0.67208385秒
snippet #6: 0.66804123秒
snippet #7: 0.76296902秒
snippet #8: 0.81688905秒
```
ESP32をWiFiにつなげる

ESP32をWiFiに繋げたので、スケッチを書いておく

ESP32-DevKitC 及び HiLetgo ESP-32s NodeMCU
ArduinoIDE 1.8.5

Arduino WiFi Library
https://www.arduino.cc/en/Reference/WiFi

```WiFi.ino

#include <WiFi.h>

// 接続先のSSIDとパスワード
const char ssid[] = "########";
const char passwd[] = "########";

void setup() {
    Serial.begin(115200);

    // Connect WiFi
    connectWiFi();
}
void loop() {
    // Reconnect
    if ( WiFi.status() == W_DISCONNECTED ) {
        connectWiFi();
    }
}

/**
 * Connect WiFi
 */
void connectWiFi()
{
    WiFi.begin(ssid, passwd);
    Serial.print("WiFi connecting...");
    while(WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
    }
    Serial.print(" connected. ");
    Serial.println(WiFi.localIP());
}
```
subversion のチェックアウト時のタイムスタンプをコミットした時間に変更

チェックアウトするユーザディレクトリに以下を書き足せば幸せになれる。

```text:~/.subversion/config
[miscellany]
use-commit-times = yes
```
また、インラインでは以下のスイッチを書き足せば幸せになれる。

```shell-session
--config-option config:miscellany:use-commit-times=yes
```
ReactNativeのパフォーマンス改善時におさえておきたいこと

どれも[公式ドキュメント](https://facebook.github.io/react-native/docs/performance.html)で触れられるくらい大事なことなので、取り組む前に軽く目を通して置くと助けになると思います。
主にメインスレッドに処理を切り分けよう、モニタリングできるようにしよう、起動時のロードを減らそうって内容です。

最終更新日: 2018 6/21
React Nativeに触れる機会が増えているので随時更新していきます。
## 知っておきたいことまとめ

### できる限りメインスレッドに処理を任せる

- JSスレッドとメインスレッド(Nativeのスレッド)が動いておりJSスレッドがボトルネックになることが多い
- 100ms以上フレームが落ちるとユーザーに感じ取られる
- JSスレッドで必要なすべてのコンポーネントをレンダリングするため、Navigatorの遷移中にフレーム落ちが発生しやすい
- JSスレッドが忙しいとメインスレッドから受け取ったタッチイベントに反応できないが、フィードバックは即座に描写してしまう
- NavigatorIOSはアニメーションをメインスレッド上で行うためフレーム落ちを起こさない
- 開発モードではJSスレッドのパフォーマンスが大幅に低下する
- ListViewではなくFlasListにするとパフォーマンスが上がる
  - 描写が遅ければgetItemLayouを実装して最適化する
  - rowHasChangedを実装することでレンダリングの必要を確認する処理を減らせる

### アニメーション

- LayoutAnimationはCore Animationを使うのでJSスレッドのフレーム落ちの影響を受けない
- Viewを動かす処理でフレーム落ちしやすい
  - メモリの使用量に気をつける
  - アルファ合成等はshouldRasterizeIOSやrenderToHardwareTextureAndroidに任せれるかもしれない
- 画像のサイズをアニメーションするとフレーム落ちしやすい
- onPress関数が返されるまでフィードバックを返せない場合はrequestAnimationFrameでアクションをラップする

```js
handleOnPress() {
  // Always use TimerMixin with requestAnimationFrame, setTimeout and
  // setInterval
  this.requestAnimationFrame(() => {
    this.doExpensiveAction();
  });
}
```

- アニメーションの値をリスト化してメインスレッドに送信するとJSスレッドを経由せずフレーム落ちも起きない

### プロファイリングでボトルネックを特定する

- ChromeのDedicatedWorker Threadをみてボトルネックを探す
- [systraceを使ってAndroidのUIのパフォーマンスをプロファイルする](https://facebook.github.io/react-native/docs/performance.html#profiling-android-ui-performance-with-systrace)


### 起動時のロードを減らす

- インラインでrequireすることによって起動時のロードを減らす

```jsx
import React, { Component } from 'react';
import { TouchableOpacity, View, Text } from 'react-native';

let VeryExpensive = null;

export default class Optimized extends Component {
  state = { needsExpensive: false };

  didPress = () => {
    if (VeryExpensive == null) {
      VeryExpensive = require('./VeryExpensive').default;
    }

    this.setState(() => ({
      needsExpensive: true,
    }));
  };

  render() {
    return (
      <View style={{ marginTop: 20 }}>
        <TouchableOpacity onPress={this.didPress}>
          <Text>Load</Text>
        </TouchableOpacity>
        {this.state.needsExpensive ? <VeryExpensive /> : null}
      </View>
    );
  }
}
```


## 参考

- [React Native 公式ドキュメント](https://facebook.github.io/react-native/docs/performance.html)
無限∞Todo+他人のTodoが見れるWebアプリをReactとFirebaseで作った

作ったもの
------
TodoのTodoのTodo...が作れ、他人のTodoが見れるTodoリスト
[夢叶えるツールLisTodon](https://listodoon.firebaseapp.com)

使ったもの
------
- [React](https://reactjs.org/)
- [React-Router](https://reacttraining.com/react-router/)
- [Material-UI](https://material-ui.com/)
- [Firebase](https://firebase.google.com/)
  - Authentication
  - Realtime Database
  - Hosting

データはローカルストレージに保存
他の端末からも見れるようにと、他人のTodoを見れたら面白いかと思いFirebaseのAuthとDBを使った。

学んだこと
----
### Firebaseを初めて使ってみた
- めちゃめちゃ楽だった
- これが全て無料なのはすごい
  - AWSも無料枠はあるけど、個人で使うならFirebaseの方が上限が決まっているので安心感がある 
- ReactやVueなどのSPAとの相性は抜群だと思った
  - 「ホスティング、認証、データ保存」Firebaseだけで完結する
      - ※Node.jsが使える環境で静的ファイルのみ
- Authentication
  - アプリ側でTwitter用、Facebook用などを作る必要がなくキーをFirebaseで設定するだけだった
  - 認証ユーザーだけ書き込み許可するやり方も簡単（後述の「Realtime Databaseのルール」を記述するだけ）
  - どれだけ簡単にできるのかサンプルを作った
      - [10分でできるReact+FirebaseのGoogleAuth](https://qiita.com/HorieH/items/8b4b1c4807e1eb6fcb0a)
- Realtime Database
  - 進化版のCloud Firestoreもあるが、まだβ版で子ノードの削除などができないため今回は見送った

### Material-UIがv0からv1になっていた
- v1は、基本的にstyleを細かく指定する必要がありReact Nativeの使い方に近くなった
- 個人的にそういう細かい設定はしたくないので、v0のデフォルトのまま使える仕様が好きだった

### 設定したFirebase Realtime Databaseのルール

```json
{
  "rules": {
    ".read": true,
      "todos": {
      "$user_id": {
        ".write": "$user_id === auth.uid"
      }
    },
    "latests": {
      ".write": "auth !== null",
    },
    "tags": {
      ".indexOn": "count",
      ".write": "auth !== null",
    },
    "forks": {
      ".indexOn": ".value",
      ".write": "auth !== null",
    }
  }
}
```

- 読み込みは誰でも可能、
- latests,tags,forksは認証ユーザーのみが書き込み可能
- todosは認証ユーザーで自分のみが書き込み可能
- indexOnはsortを使う時のindex

失敗したこと
-----
- 先にアプリ名を決めたため、Firebaseのアプリ登録で、すでに使われていて登録できなかった
  - 使いたかったアプリ名「listodon」
  - Firebaseのアプリ名「listodoon」
      - listodoonで作ればよかった...    
  - 次回からはアプリ名を登録できるか調べてから決めたい（ドメインとかも）
- Reduxを使わなかった
  - 数ページだから必要ないかと思ったけど、途中からページをまたがってデータを共有したくなった
     - 今回は無理やり感ある実装で乗り切った
     - 保守や拡張を考えるとReduxはやっぱり便利だと実感した
          - （MobXは流行るのか・・・？）
- Todoの階層化は画期的ではと思った
   - 探してみたら以外に昔からあった
   - それでもReact  

ホスティングサーバー
----
- [React Routerを使った場合rewriteの設定が必要になる。](https://qiita.com/Jey/items/fe98cb6773c057b1a4c8)
- 最初にGitHub Pagesを試してみたがrewriteの設定の他に、React Routerのbasenameの設定も必要になり少し大変そうだった。
- [公式でもサイトと設定方法などが紹介されていた。](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#deployment)
- 今回はFirebase Hostingを試してみた。下記２つの設定だけで簡単でした。

### Firebase Hostingの設定
下記のfirebase initの質問をYesにするとrewriteの設定が作られる

```
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
```

公式サイトの設定方法で記述されている下記を追記

```js:firebase.json
{
  "hosting": {
    ...
    "headers": [
      {"source": "/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}]}
    ]
    ...
```

つまづいた点
------
FirebaseDBの orderByChild は foreachを使う（ snapshot.val だと sort されていない）
(参考) https://stackoverflow.com/questions/38345510/firebase-orderbychild-unexpected-results

余力や反響があれば追加したいもの
------
- チェックしたものをアーカイブ
- 並び替え
- 入力補完（サジェスト）
- 検索
- デザイン最適化
CentOS7へyumをインストール

# CentOS7へyumをインストールする。


## 前提
なし

## CentOSのバージョン確認
CentOSのバージョンは、/etc/redhat-releaseファイルに記載されている。

1. `$ cat /etc/redhat-release`

## インストールコマンド
1. `$ yum install yum-utils`
RACIで権限委譲と責任分担し業務を円滑に進める

# はじめに
普段業務を進める上で、以下のような不満をもったことはないでしょうか？

- サービス運営やプロジェクト進行について指示する人が複数いて現場が混乱する
- メンバー間で支持する設計手法や開発手法がバラバラで統率が取れない
- プロダクトオーナーがタスクを抱え込み過ぎて、ボトルネックになってしまっている

こういった問題は、適切な権限委譲と責任分担である程度解決できます。そして、権限委譲と責任分担を行う際に役立つのがRACIです。


# RACIとは
RACIは、各業務内容における役割毎の責任分界点を可視化する思考フレームワークの一つです。責任範囲を、**R**esponsble、**A**ccountable、**C**onsulted、**I**nformedで定義することから、RACIと呼ばれています。

Responsble、Accountable、Consulted、Informedのそれぞれの意味は以下の通りです。

- **Responsble (実行責任者)**: 実際にタスクをこなす人
- **Accountable (説明責任者)**: 成果に対して責任を取る人
- **Consulted (協業先)**: 報・連・相の相を行う対象
- **Informed (報告先)**: 報・連・相の報・連を行う対象

RACIでは、業務内容と役割からなる表にR・A・C・Iを埋めることで、どの役割がどういった権限と責任を持っているのかを可視化します。以下は、RACIマトリクスの例です。

| 業務内容 | エンジニア | アーキテクト | スクラムマスター | プロダクトオーナー | マネージャー |
|:--------|:---------:|:------------:|:--------------:|:----------------:|:-----------:|
|プロダクトのKGI/KPI設定|I|C|I|R/A|C|
|プロダクトのアーキテクチャ設計|I|R/A||C||
|タスクチケットの管理|I||R|A|I|
|コーディング|R/A|C||I||
|...||||||

|役割|担当者|
|:---|:----|
|エンジニア|Aさん、Bさん、Cさん|
|アーキテクト|Bさん|
|スクラムマスター|Dさん|
|プロダクトオーナー|Eさん|
|マネージャー|Fさん|

# RACIの運用ノウハウ
RACIの詳細は他のブログでも丁寧に紹介されていますが、実際に運用した際によく起こる問題の解説はあまりありません。以下では、RACIを初めて運用する人が陥りやすい問題と簡単な解決アプローチをまとめています。

- [責任を持つとは？　〜RACIチャートの紹介〜](https://dev.classmethod.jp/etc/raci/)
- [
RACIマトリクスを使ってスクラムプロジェクトの責任分担を見える化する](http://www.ryuzee.com/contents/blog/7076)

## Aを複数の役割に割り当てない
1行にAが2つ以上でてきた場合、組織構成に問題があると思ってください。目標設定に関する業務でマネージャーとプロダクトオーナーの両方にAがついていたり、技術選定に関する業務でプロダクトオーナーとアーキテクトの両方にAがついていたりするのは起こりがちです。

1行にAが複数あるということは、いい成果が得られた際には成果の奪いあいに、問題が起こった際には責任のなすりつけあいになるということです。

## 特定の役割にAを集中させない
権限委譲や責任分担に頓着しない組織では、Aがプロダクトオーナーやマネージャーに集中しがちです。「メンバーにAを割り当てるなんて怖くてできない！」というのも尤もではあるのですが、Aが集中しすぎると、その人がボトルネックになって業務の停滞を招きます。

例えば、稟議の最終承認者が、全部社長になっていたりすると稟議が中々通らずヤキモキしますよね？そういった場合、組織を細かく分割し、プロダクトやプロジェクトの規模によって最終承認者をわけるわけですが、RACIでも同じことを行えばいいわけです。RACIマトリクスで定義された業務内容を怖いと思わなくなるまで細分化し、できる範囲から権限委譲していきましょう。

## 特定の役割・人にRを集中させない
特定の役割や人に、Rが集中している場合、その役割や人に過負荷がかかっている可能性があります。

Rは実際にタスクをこなす人なので、その役割や人ができる範囲でしかRをつけてはいけません。業務内容や役割を見直すか、人を増やすなどして、実働部隊の負荷が集中しないようにしましょう。

## Cが多すぎないかを確認する
相談先が多いということは悪いことではないですが、Cが多いということは、それだけコミュニケーションコストがかかるということです。MTGばかりしているなと思った場合は、Cが多すぎないか確認してみましょう。

プロダクトやプロジェクトの内容によっては仕方ない部分もありますが、必要以上にプロダクトやプロジェクトのスコープが大きい可能性があります。

## by nameで権限を割り当てない
RACIマトリクスを作る際には、名前でなく役割を使ってください。by nameで権限を割り振ると、「自分自身が偉くなった」と勘違いする可能性が高まります。アジャイルソフトウェア開発でも述べられていますが、ソフトウェア開発において誰が上・下ということはありません。お互いに割り当てられた役割（ロール）があり、それに則って、職務を遂行するというだけです。

役割に権限と責任が紐付いていて、その責任の重さなどによって給与に差が生まれます。by nameにすると、それが見えにくくなり、人事マネジメントが、難しくなるという問題があります。

役割と人が1対1であっても、役割を使い。役割に権限と責任、求められるスキルセットを定義するようにしましょう。

## RACIマトリクスに書いてある以上のことが行われていないかを監督する
I（報告を受けた人）が口を出すとか、C（相談先）が作業に加わってしまうとか、R（タスクをこなした人）が責任をなすりつけられるということは、よく起こることです。常にRACIマトリクス通りにすることを強制することは、息苦しさを感じさせるのですべきではないですが、徐々に侵食され定常化してしまうとRACIマトリクスの意味がありません。

RACIマトリクスの実効性が薄れてきたと思ったタイミングで、関係者と相談して情報をアップデートし、あらためて権限委譲と責任分担を行う必要があります。RACIマトリクスは一度作ったら終わりというものではなく、逐次アップデートする必要があります。

# おわりに
RACIは、非常に優秀な思考フレームワークですが、こういった思考フレームワークの導入になれていない組織からすると、運用する上で様々な問題が起こります。今回は、私が現時点で発見した運用ノウハウをまとめましたが、これからも運用していく中でなにか気づきがあった場合は更新していきたいと思います。

「はじめに」で書いた問題に不満を抱えた人の参考になれば幸いです。
Dart2ではdynamic型を引数に持つメソッドに注意


Flutterアプリを書いているときに、Reduxで、dispatchしてもmidlewareやreducerが動作しないことがありました。

こんなソースです。

```
　store.dispatch(LoginAction);　
```

意外とこれ気づきません。LoginActionがインスタンス化されていません。

正しくはこうです。

```
　store.dispatch(LoginAction());　
```


dispatchの引数がdynamic型になっているためにコンパイラーはエラーを吐きません。

このように()を書き忘れることで、Type型として引数に渡されて動作しない。
単純だけど、他の人も意外と同じミスするんじゃないかと思い書いときました。
【macOS】sshで接続したときにプロンプトの文字色を変える方法

普段はWindowsなんですが、諸事情あってMacも使うことになりまして、
ターミナル上だとサーバーに接続してるのかローカルなのかわかりにくいので、
sshで接続したときのプロンプトの文字色を変えることにしました。

参考にしたのはこちら。
[Bashでssh接続時、接続先によってプロンプトの文字色/背景色を変える](https://qiita.com/asigochan/items/fd98f9efc310058734c3)

まぁ、この記事に全てが書いてあるからこの通りにやれば良いんだけど、ちょっと詰まったのでメモ。

## 1．ssh_change_prompt.shを作成する

わざわざシェルスクリプト作成してエイリアスを設定するの面倒だし、
そのまま`.bash_profile`に書けば良くね？と思ってやってみたけどダメだった。

というわけで、素直に手順に従う。

```
$ cd
$ vi .ssh/ssh_change_prompt.sh
```
```ssh_change_prompt.sh
#!/bin/bash

# server_nameごとに色を分けたい場合
if [[ "$@" == server_name ]]; then
  ssh server_name -t "export PS1='\[\e[37m\][\[\e[31m\]\u\[\e[37m\]@\h \[\e[32m\]\W\[\e[37m\]]\$ '; bash --login"
else
  ssh $@
fi

# どのサーバーにsshしても適用したい場合
ssh $@ -t "export PS1='\[\e[37m\][\[\e[31m\]\u\[\e[37m\]@\h \[\e[32m\]\W\[\e[37m\]]\$ '; bash --login"
```

ちなみにこれで`[User@host CurrentDirectory]$`のように表示されて、Userが赤、CurrentDirectoryが緑、それ以外が白になります。

## 2．エイリアスを設定する

さっき作ったシェルにエイリアスを設定して、変更を反映する。

```
$ vi .bash_profile

alias ssh=~/.ssh/ssh_change_prompt.sh
```

変更した後反映するのも忘れずに。

```
$ source .bash_profile
```

## ちょっと詰まったところ

試しにsshしてみたら、権限が無いって怒られた。

```
$ ssh server_name
-bash: /Users/user_name/.ssh/ssh_change_prompt.sh: Permission denied
```

さっき作った`ssh_change_prompt.sh`を見たら実行権限がなかったので、ユーザーに実行権限を付与したらうまくいった。

```
$ ls -l .ssh/
-rw-r--r--  1 user  group   189  3 28 12:12 ssh_change_prompt.sh

$ chmod +x .ssh/ssh_change_prompt.sh
// もしくは
$ chmod u+x .ssh/ssh_change_prompt.sh
$ ls -l .ssh/
-rwxr--r--  1 user  group   189  3 28 12:12 ssh_change_prompt.sh
```
MongoDB のスーパーユーザーの作成方法

MongoDB のスーパーユーザーの作成方法です。

1) 認証がない状態で、ユーザーを作成します。

```text
$ mongosh
test> use admin
switched to db admin
admin> db.createUser({user: "scott",pwd: "tiger123",roles: ["userAdminAnyDatabase","readWriteAnyDatabase","dbAdminAnyDatabase"]})
{ ok: 1 }
admin> 
```

2) 認証を有効にするには、設定を変更して mongodb を再起動します。

```text:/etc/mongodb.conf
# 略
auth=true
```

```bash
sudo systemctl restart mongodb
```

3) ログインできることの確認

```text
$ mongosh admin -u scott -p tiger123
Current Mongosh Log ID:	622420bbd3e3dec28881718d
Connecting to:		mongodb://127.0.0.1:27017/admin?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.2.2
Using MongoDB:		5.0.6
Using Mongosh:		1.2.2

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

------
   The server generated these startup warnings when booting:
   2022-03-06T09:08:46.696+09:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
   2022-03-06T09:08:48.768+09:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
------

admin> 
```

スクリプトで作成する方法

```js:create_user.js
db.createUser({user: "scott",pwd: "tiger123",
	roles: ["userAdminAnyDatabase","readWriteAnyDatabase",
	"dbAdminAnyDatabase"]
	})
```

実行コマンド

```bash
mongosh admin < create_user.js
```

ユーザーの削除

```text
$ mongosh
test> use admin
switched to db admin
admin> db.dropUser('scott')
{ ok: 1 }
admin> 
```
proxy環境下で、Powershellからwgetする

powershell version5では以下で動作します。
version4では動かないので注意。

## Proxy認証情報を作成

```
PS C:\> $secPasswd=ConvertTo-SecureString "<ProxyPassword>" -AsPlainText -Force
PS C:\> $myCreds=New-Object System.Management.Automation.PSCredential -ArgumentList "<ProxyUserName>",$secPasswd
```

## wgetする

※ `wget` は `Invoke-WebRequest` のエイリアスです。

```
PS C:\> wget -Uri https://qiita.com -Proxy <プロキシサーバー> -proxyCredential $myCreds
```

プロキシサーバーは、`url:ポート` の形式。
CentOS7+FFMpeg

# CentOS7へFFMpeg4をインストールして、使ってみる。


## 前提
・ yum、rpm、epelは必須。


## インストールコマンド
1. `$ rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro`
2. `$ rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-1.el7.nux.noarch.rpm`
3. `$ yum -y install ffmpeg ffmpeg-devel`

## 動画を静止画にするコマンド
1. `$ ffmpeg -ss 0 -i [読み込みファイルパス] -t 180 -r 1001/1001 -f image2 -vcodec png [出力ファイルパス]`

#### option解説
|オプション|指定|なし|
|:--:|:--|:--|
|-ss|読み込み開始位置(秒)||
|-i|読み込みファイルパス||
|-t|読み込み時間(秒)||
|-r|fps(1秒あたりの読み込みフレーム数)||
|-f|"image2"以外の指定は不明||
|-vcodec|"png"以外にも指定できるはず||

※ ffmpegはオプションの読み込み順番でエンコード速度が変わるため、注意
AlibabaCloudのAuto Scaling x SLBをやってみる

# はじめに
[AlibabaCloudのROSからAuto ScalingでECSを起動してみる](https://qiita.com/wa-ta-ru/items/e38e88f96502a51211f9)
を少し拡張して、SLB(ロードバランサー)に繋がるようにします。

ROSで作成すると

- VPC
- Auto Scaling
- ECS x 2

となります。

# ロードバランサーの作成
[AlibabaCloudのロードバランサーを動かしてみる](https://qiita.com/wa-ta-ru/items/3bbcba1a2ea43f5d025f)
で同じようにコンソールから作成しておきます。

# スケーリンググループの変更から、ロードバランサーが選べない

![bb940071.png](https://qiita-image-store.s3.amazonaws.com/0/241104/248087e8-97ae-5224-7016-276c6f08ea97.png)

![1c86c603.png](https://qiita-image-store.s3.amazonaws.com/0/241104/0ccd683e-94e4-16c3-b722-ff6d04a5babd.png)

![a0dcf42c.png](https://qiita-image-store.s3.amazonaws.com/0/241104/56c18739-0ea1-fd11-6015-c439380e9d5d.png)

_グレーアウトされていて、ロードバランサーが選べません_

ここで情報(infomartionアイコン)を見てみると
**ロードバランサーにヘルスチェックがないと選べません。**
ですので、80のヘルスチェックまでやっておいてください。

![549f58b5.png](https://qiita-image-store.s3.amazonaws.com/0/241104/af459a0e-41da-a3f5-98c0-6830200cf990.png)

# Auto Scalingを新規作成

[AlibabaCloudのAuto Scalingを触ってみる](https://qiita.com/wa-ta-ru/items/df420ba29cd457db8275)

のように進めていきます。

![fa0d442c.png](https://qiita-image-store.s3.amazonaws.com/0/241104/ca7c41e9-2551-039d-888c-59e0c5b55cc0.png)

![8e35b744.png](https://qiita-image-store.s3.amazonaws.com/0/241104/a63bca91-1d6d-1522-ba8f-d912874ddce2.png)

![ee5e2ff9.png](https://qiita-image-store.s3.amazonaws.com/0/241104/cc45db8a-64e5-919d-dc61-49e1ab2e04e7.png)

![218790b4.png](https://qiita-image-store.s3.amazonaws.com/0/241104/7c4cb278-4028-70e1-13c0-fe28133c94c3.png)

![8dee913e.png](https://qiita-image-store.s3.amazonaws.com/0/241104/f3497c25-b8a5-09a5-38bd-f170ecec26a8.png)

Auto Scalingスケーリング設定は省略します。
Auto Scalingの作成まですすめていきます。

# Auto Scalingを作成しますと

![94afe270.png](https://qiita-image-store.s3.amazonaws.com/0/241104/ca905cdb-e15d-636f-2e4f-5d40dc1a6af5.png)

![84516b1e.png](https://qiita-image-store.s3.amazonaws.com/0/241104/1d6d7d22-a6dd-5699-6008-5b756b036415.png)

![a631f426.png](https://qiita-image-store.s3.amazonaws.com/0/241104/08602e5b-68db-4a64-cf31-b53d635ce458.png)

SLBにつながります。

# ヘルスチェックを正常にする

ECSにSSHログインして、nginxを動かします。

```
[root@iZ6we7d4lmtgrd11wux5i2Z ~]# yum -y install nginx
[root@iZ6we7d4lmtgrd11wux5i2Z ~]# systemctl start nginx.service
```

![e915b320.png](https://qiita-image-store.s3.amazonaws.com/0/241104/f57e1166-6073-a222-252f-cc93d1d82cdb.png)

SLBのIPアドレスをブラウザでみれば

![e1a5561a.png](https://qiita-image-store.s3.amazonaws.com/0/241104/ff12236f-a9b8-5768-756f-c905201dc589.png)

となります。

# インスタンスをリリースするとAuto Scalingにより復旧します。

![f6629724.png](https://qiita-image-store.s3.amazonaws.com/0/241104/c524f96c-3c77-8c93-ce02-3463adafb539.png)

![406ba47c.png](https://qiita-image-store.s3.amazonaws.com/0/241104/e13c9150-b066-09e7-c344-45f97986b27f.png)

ま、素のCentOSイメージが起動するので
nginxの画面は当然みれません。

ロードバランサーにはつながってますので、
ここを起動するインスタンスをクリアすれば
冗長化したWebサーバが構築できます。
Linuxコマンドで、いろいろ確認するコマンド

# はじめに

これを書くきっかけになったのは、レガシーなサーバの移設をする際に、環境を確認するワンライナーを集めておくと楽かな、とおもったのがきっかけです。それほど使う機会があるものではありませんが、覚えておくと環境を調べるのに役に立つかと。
<font color="blue"><b>覚書なので、突っ込みは勘弁してください</b></font>

# いろいろ確認ワンライナー

- Kernel/アーキテクチャ確認

```
uname -a
```

- カーネル設定確認

```
sysctl -a
```

- プロセス詳細確認

```
ps auxwwf
```

- ストレージ状態確認

```
df -aTh
cat /etc/fstab
```

- ネットワークインターフェース確認

```
ip -a
```

- リゾルバ確認

```
resolveip --info `hostname`
cat /etc/resolv.conf
```

- 言語設定確認

```
localectl status
```

- タイムゾーン確認

```
timedatectl status
```

- Cronの設定確認

```
crontab -l
```

- 環境変数確認

```
set
```

- サービス一覧

※CentOS7でもsystemctl以外で起動させてる場合もあるのでchkconfigも忘れずに
※node.jsとか自作サービスを自動起動するのにpm2とかsupervisordを使っている人もいるので忘れずに

```
chkconfig --list
systemctl list-units --type=service
systemctl list-unit-files --type=service
pm2 list
supervisorctl status
```

- FireWall確認

※firewalldとiptablesを併用している人を見かけるので一応チェックしておくといいと思う

```
firewall-cmd --get-active-zones
firewall-cmd --get-default-zone
firewall-cmd --list-all
firewall-cmd --list-all-zones
iptables -L
```

- ルーティング確認

```
route
```

- ホスト許可/拒否

※サービスの拒否をIPで設定している環境だと、ここに設定がある時があるので確認

```
cat /etc/hosts.allow
cat /etc/hosts.deny
```

- ユーザID/GID確認

※自分やユーザ名のわからないユーザのUID/GIDをとりあえず見たいとき。

```
cat /etc/passwd
```

- Linuxパッケージ確認

※CentOSの場合はまだまだ、yumを使う人がいるけど、そろそろdnfに移行がかかる感じ
※すでにDNFを導入している場合はdnfでの確認も忘れない

```
yum list installed
dnf list installed
```

- PHPモジュールの確認

※phpinfoと一緒、ただし、CLIで実行する場合はiniの場所を指定するのを忘れない

```
php -i --php-ini /etc/php.ini
```

- PHP-PECLの確認

```
pecl list
```

- PHP-PEARの確認

```
pear list
```

- Apache(httpd)のモジュール確認

```
apachectl -l
```

- MySQLのユーザ関数を確認する

```
mysql -u(USER) -p -e"SELECT ROUTINE_DEFINITION FROM information_schema.ROUTINES WHERE ROUTINE_TYPE = 'PROCEDURE'\G;"
```

- MySQLレプリケーション設定の確認

```
mysql -u(USER) -p -e"show master status\G;"
mysql -u(USER) -p -e"show slave status\G;"
```

- PostgreSQLのユーザ関数を確認する

```
psql -U (USER) -c 'SELECT * FROM pg_proc;' 
```

- PostgreSQLレプリケーション設定の確認

```
psql -U (USER) -c 'SELECT * FROM pg_stat_replication;' 
```

大体こんな感じでチェックすることが多いかな。

# 番外:依存の調査

- 実行ファイルの依存を調べる場合

バイナリだけ持ってきて動かす場合に、足りないモジュールがなんなのか調べる

```
ldd ファイル名
```

- ロックしているプロセスを調べる

ファイルやポートがロックされていて操作できない場合

```
lsof -i:(ポート)
lsof (ファイル名)
lsof -c (プロセス名)
```

- パッケージの依存関係

※ 依存ファイル調査(-qRp)と依存パッケージ名調査(-qip)がある

```
rpm -qRp (対象RPMパッケージ)
rpm -qip (対象RPMパッケージ)
```

どれも、環境を調べたり、作り直したりするときに使うと思うので、こんなのあったなと、傍らに置いておいて使うといいかもしれない。
誰かの参考になればいいな。
AWS無料枠一覧まとめ

AWSの無料利用枠の一覧がまとまっているところがなかったのでまとめ。
気が向いたら追加していきます。

##1年間限定無料枠
|サービス名|無料利用枠|備考|
|--------- |-----|----------|
|EC2|Linux、RHEL、SLES、Windowsのt2.microインスタンス<br>毎月稼働750時間まで|1か月は長くて744時間。でも稼働時間の計算は全てのインスタンスの合計なので注意<br><br>**t2.microインスタンス**<br>vCPU：1コア<br>メモリ：1GiB<br>ストレージ：EBSのみ<br>EBS最適化利用：不可<br>ネットワークパフォーマンス：低から中<br>IPv6サポート：あり|
|EBS|SSDストレージまたは磁気ストレージの任意の組み合わせで、合計30GBまで<br>磁気EBSの場合、200万I/Oまで<br>スナップショットストレージ1GB|磁気EBSの200万I/Oは毎月じゃないかも？？？|
|RDS|db.t2.microデータベース<br>毎月稼働750時間<br>汎用SSDデータベースストレージ20GB<br>DBバックアップおよびスナップショット用ストレージ20GB|多分こちらも全てのインスタンス合計の稼働時間<br>インスタンスは停止しても7日間経過すると自動で起動するので注意<br><br>**db.t2.microインスタンス**<br>vCPU：1コア<br>RAM：1GiB|
|S3|標準ストレージ5GBまで<br>毎月2万Getリクエストまで<br>毎月2000Putリクエストまで<br>データ転送毎月15GBまで||
|API Gateway|毎月100万リクエストまで|
|CloudFront|データ送信（アウトバウンド）毎月50GBまで<br>毎月200万リクエストまで|

##期限なし無料枠
|サービス名|無料利用枠|備考|
|--------- |-----|----------|
|EC2|データ受信量は無制限<br>データ送信（アウトバウンド）毎月1GBまで<br>CloudFront宛てのデータ送信は無制限|
|Lambda|毎月100万リクエストまで<br>毎月320万秒までの処理実行時間||
|DynamoDB|ストレージ25GB<br>25ユニットの書き込み容量<br>25ユニットの読み込み容量||
|Elastic IP|実行中のインスタンスに関連付けられている間無料||
Nuxt.js + Auth0 + Spring Boot で作る認証付きSPA  【 vol.1  Auth0 登録編 】

[前回で概要に触れました](https://qiita.com/mijinco0612/items/00d8a1a9dbf7eb8b9de8)ので、実際に作っていくことにします。

*記事をかきあげたところで　、ずっと丁寧でわかりやすい以下を発見...orz　
以下をご参照することをオススメします。
[クラウド認証サービス Auth0 の無料トライアルを試してみよう](https://qiita.com/furuth/items/8826b66a3ec2b2b14222)
*これは個人的な備忘録です。

## Auth0って？
[認証プラットフォーム Auth0 とは？](https://qiita.com/furuth/items/68c3caa3127cbf4f6b77)
[Auth0 Overview
](https://auth0.com/docs/getting-started/overview?wvideo=s15ysw45uy)

## Auth0を利用する準備
まずは使ってみる。
https://auth0.com/jp/
**無料トライアル**をクリック

![スクリーンショット 2018-06-21 12.08.50.png](https://qiita-image-store.s3.amazonaws.com/0/82787/f64dc241-af65-7f7c-99e8-87b4683779b9.png)

**SIGN UP WITH GOOGLE**をクリック

![スクリーンショット 2018-06-21 15.24.28.png](https://qiita-image-store.s3.amazonaws.com/0/82787/afa5aaec-befb-7316-e10d-b8a179e4dba1.png)

アカウントを選択したら....

<img width="555" alt="スクリーンショット 2018-06-20 17.43.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/9ef3a875-32da-bf2a-b64f-117eb737c335.png">

TENANTとREGIONを決める。今回は以下の通り設定しました。
**TENANT : mijinco-nuxt**
**REGION : US**

![スクリーンショット 2018-06-21 15.39.47.png](https://qiita-image-store.s3.amazonaws.com/0/82787/d31882f3-ae58-69ce-f575-597855934702.png)

Dashboardが表示されます。 
**Applications**をクリックして...

<img width="1138" alt="スクリーンショット 2018-06-20 17.27.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/fccd6047-e53f-f5a8-7336-688eafe461cf.png">

**+NEW APPLICATION**をクリック

<img width="597" alt="スクリーンショット 2018-06-20 17.30.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/e6ed82ee-285b-900c-560c-18c0f687b33d.png">

以下のように設定します
**NAME : Nuxt**
**Choose an application type : Single Page Web Applications**

<img width="840" alt="スクリーンショット 2018-06-20 17.31.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/6e2381c6-6a5d-deb7-286a-a04dc8faaad1.png">


先程作成したApplicationが表示されていますね

<img width="406" alt="スクリーンショット 2018-06-20 17.30.13 のコピー.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/75d91b5a-d196-909e-70cb-b3c8d4458868.png">

Connections > Social を選択

![スクリーンショット 2018-06-21 16.40.35.png](https://qiita-image-store.s3.amazonaws.com/0/82787/476345f4-4283-5f6f-4244-c0f22eee96c7.png)

GoogleがデフォルトでONになっている　TRYクリックしてみる。

<img width="849" alt="スクリーンショット 2018-06-20 17.32.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/4ec303ba-4a34-1a8c-391a-e493f0113c59.png">

アカウントの選択を行って

<img width="555" alt="スクリーンショット 2018-06-20 17.43.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/823e6310-0f8f-25dd-1d40-5a78c9f5f186.png">

認証できました！

<img width="758" alt="スクリーンショット 2018-06-20 17.44.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/82787/806cea34-5c01-0d55-3716-127fdcd67715.png">


[次回はNuxtとの連携おこないます](https://qiita.com/mijinco0612/items/588cb412b6a95d567e7e)
botkitを使って、平日のみslackに定時投稿するには

会社で働いていると、定時連絡みたいなものが必要になることがままあります。
ただ、その提示連絡は休日と祝祭日は不要だったりする場合が多いのではないでしょうか。
ちょっとしたことですが、こんな方法で実現ができますという話。

*20180622編集
``` change.log
// 今日の日付を取得
  var dateString = new Date();
  // Weekdayかどうかを判定
  var holidayname = Holiday.getHolidayName(new Date(dateString));
```
この部分をcron内部に持っていなかったため、foreverで永続化したタイミングの日付をずっと保持してしまう状態になっていたのを変更

##インストールまではこちらを参照
https://qiita.com/yaaah93/items/fab80ca25a39f59ae741

##botのプログラムを書く
こちらで作ったフォルダに適当なjsを作ります
今回は定時投稿ということで、必要なタイミングにだけ起動する形にします

``` yourfilename.js
const Botkit = require("botkit");
const controller = Botkit.slackbot({
  debug: false,
});

function getWeekdayFlag(){
  // 今日の日付を取得
  var dateString = new Date();
  // Weekdayかどうかを判定
  holidayname = Holiday.getHolidayName(new Date(dateString));
  return holidayname;
}

controller.spawn({ token: 'ここにbotのtokenを書く' }).startRTM((err, bot, payload) => {
  // cronに登録
  var CronJob = require('cron').CronJob;


  //slackに投げる
  var job = new CronJob({
	cronTime: "0 0 8 * * 1-5", // 1-5の部分は*でも構いません
	onTick: function() {
		var holidayname = getWeekdayFlag();
		bot.say({
  			text: "8時です！",
  			channel: "投稿先のチャンネル名を記入"
		});
  	},
	start: true,
	timeZone: "Asia/Tokyo",
  });
  
  //複数ある場合はここにjobを足していく
  // var job2 = new CronJob({ ... という感じ

  //平日のみ稼働
  if(holidayname == ""){
	job.start();
	//複数ある場合はこちらに job2.start(); とすれば良い
  }
});
```


##Holiday.getHolidayName部分について
上記コードの末尾に、こちらの判定プログラムをコピーする
https://qiita.com/horikeso/items/16da8bce3fbbee87aa45

##プログラムの永続化はforeverを使う
    npm install -g forever
    forever start yourfilename.js

とすればOK。
yarn/npmでgit指定したときの「fatal: refusing to merge unrelated histories」のエラー

# fatal: refusing to merge unrelated histories

フォークしたパッケージをgit指定で使おうとしたら遭遇した。

```
{
  "name": "PROJECT",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": { 
    ...
    "react-native-search-box": "git://github.com/wktq/react-native-search-box.git",
    ...
  },
  "devDependencies": {
    ...
  },
  "jest": {
    "preset": "react-native"
  }
}

```

yarnしたら以下のようなエラーが発生。

```
yarn install v1.5.1
info No lockfile found.
[1/4] 🔍  Resolving packages...
error An unexpected error occurred: "Command failed.
Exit code: 128
Command: git
Arguments: pull
Directory: /Users/username/Library/Caches/Yarn/v1/.tmp/4e75e9dd70d7d2e892986b32971ee582
Output:
fatal: refusing to merge unrelated histories".
info If you think this is a bug, please open a bug report with the information provided in "/Users/username/Developer/ORG/PROJECT/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
```

# 解決策

キャッシュがリモートとマージできないときに発生するみたい。キャッシュを消せばOK。

```
rm -rf /Users/username/Library/Caches/Yarn/v1/.tmp/4e75e9dd70d7d2e892986b32971ee582
```
【Rails】PDFダウンロードした時に日本語が表示されない問題

##問題点
```ruby
respond_to do |format|
  format.html
  format.pdf do
    render pdf: template: "xxxxxxxxxx.html.erb", encoding: "UTF-8"
  end
end

```

こんな感じにpdfを出力しようとするわけだが、なぜかダウンロードしてみると日本語だけ表示されずに真っ白な部分ができてしまう。

UTF-8を指定しているし文字化けも防げている。

##結論

```
$ sudo yum install -y ipa-gothic-fonts
$ sudo yum install -y ipa-mincho-fonts
```
これで日本語のフォントが使えるようになり、日本語もちゃんと表示されるはずです。