OmniAICreator/Qiita-1.07M huggingface dataset:
[railstutorial]5.3.4 リンクのテストが通らない

# TL;DR
__`sample_app/app/views/layouts/_footer.html.erb`__を確認して
余計なシングルクォーテーションがついていないかチェックする。
>得られた教訓
　「コードは間違っていないはずなのになぜかうまくいかない」ときは、
　たいてい文字ではなくて__記号の過不足__が原因。

---

# 問題点
5.3.4「リンクのテスト」のリスト5-32「レイアウトのリンクに対するテスト」においてテストが通らない。

# 状況
```:console
rails test:integration
　　　　　　↓
1) Failure:
SiteLayoutTest#test_layout_links [/foobar/sample_app/test/integration/site_layout_test.rb:10]:
Expected at least 1 element matching "a[href="/about"]", found 0..
Expected 0 to be >= 1.

1 runs, 4 assertions, 1 failures, 0 errors, 0 skips
```

# 解決までにしたこと
1.  consoleに__`rails s`__を打ち込む
2.  http://localhost:3000/ にアクセスする
3.  ページ上のAboutをクリックする
4.  Routing Errorが発生
![Routing-Error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547164/a484ea0e-4094-ce4e-fb60-4c0f7bf96c52.png)
5.  __`sample_app/app/views/layouts/_footer.html.erb`__を確認

```:sample_app/app/views/layouts/_footer.html.erb
<footer class="footer">
  (省略)
  <nav>
    <ul>
      <li><%= link_to "About",   'about_path' %></li>
      <li><%= link_to "Contact", 'contact_path' %></li>
      (省略)
   </ul>
  </nav>
</footer>
```
# 原因
  __link_toメソッドの第2引数に名前付きルートを与えたときに
誤ってシングルクォーテーション(')をつけたままにしていたから。__

# 対策
```:sample_app/app/views/layouts/_footer.html.erb
<footer class="footer">
  (省略)
  <nav>
    <ul>
     <li><%= link_to "About",    about_path %></li>
     <li><%= link_to "Contact",  contact_path %></li>
      (省略)
   </ul>
  </nav>
</footer>
```
```:sample_app/app/views/layouts/_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= link_to "sample app", root_path, id: "logo" %>
    <nav>
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Home",    root_path %></li>
        <li><%= link_to "Help",    help_path %></li>
        (省略)
      </ul>
    </nav>
  </div>
</header>
```
ubuntu 18.04 LTSで有線(wired connection)が繋がらない

## 概要
`windows 10`がinstallされていたPCに`Ubuntu18.04`をusbからboot installした時に発生した問題。画面上部にネットワークのアイコンがない上に、`settings`の中身にも、なぜか`wired settings`という項目がありませんでした。

## 原因
ネットワークアダプタに適合するドライバーがないこと。

## 前提
**まずは、インターネット環境を手に入れます。**(後述のmake等のinstallのため)
USBネットワークアダプタ(有線でも無線でも)を使って一時的にネットワークを使えるようにし、"apt install" で make, gcc などのコンパイル環境を整えてから、Intel ドライバーをコンパイル、インストールする必要があります。

USB型の無線ルーターがあるので、それを入手します。
例 [TP-Link WIFI 無線LAN 子機 11n/11g/b デュアルモード対応モデル TL-WN725N](https://www.amazon.co.jp/TP-Link-WIFI-%E7%84%A1%E7%B7%9ALAN-%E3%83%87%E3%83%A5%E3%82%A2%E3%83%AB%E3%83%A2%E3%83%BC%E3%83%89%E5%AF%BE%E5%BF%9C%E3%83%A2%E3%83%87%E3%83%AB-TL-WN725N/dp/B008IFXQFU/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=usb+wifi&qid=1583994921&s=computers&sr=1-3)

こちらを通すことで、WiFi環境を得ることができました。
本題の有線環境の設定は次の通りです。

## 確認
```sh
$ lspci |grep Ethernet
00:1f.6 Ethernet controller: Intel Corporation Ethernet Connection (2) I219-V
```

```sh
$ dmesg |grep -i NVM
[    1.380867] e1000e 0000:00:1f.6: The NVM Checksum Is Not Valid
[  322.633661] e1000e 0000:00:1f.6: The NVM Checksum Is Not Valid
```
今回は、このエラーのせいで有線ネットワークがうまく機能していませんでした。
## 対処法

```sh
sudo apt update 
sudo apt install make build-essential
```

ドライバーを以下のIntel公式HPよりダウンロードし解凍する。

[Linux * での PCIe * Intel®ギガビット・イーサネット・ネットワーク接続向けインテル®ネットワーク・アダプター・ドライバー](https://downloadcenter.intel.com/ja/download/15817/-PCI-E-Linux-)

```sh
tar -zxvf e1000e-3.6.0.tar.gz
cd e1000e-3.6.0/src
```

nvm.cの関数`s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw)`の中身でreturn以外の部分をコメントアウトします。

```c:e1000e-3.6.0/src
sudo vi nvm.c
// ・・・
s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw)
{
//	s32 ret_val;
//	u16 checksum = 0;
//	u16 i, nvm_data;
//
//	for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
//		ret_val = e1000_read_nvm(hw, i, 1, &nvm_data);
//		if (ret_val) {
//			e_dbg("NVM Read Error\n");
//			return ret_val;
//		}
//		checksum += nvm_data;
//	}
//
//	if (checksum != (u16)NVM_SUM) {
//		e_dbg("NVM Checksum Invalid\n");
//		return -E1000_ERR_NVM;
//	}
	return 0;
}
// ・・・
```

ドライバーをインストールして、ネットワーク設定を再起動します。

```sh:e1000e-3.6.0/src
sudo make install
sudo modprobe -r e1000e
sudo modprobe e1000e
sudo service network-manager restart
```


## 参考
[【Linux】対処法: 有線LANのドライバe1000eが動作しない。](http://datyotosanpo.blog.fc2.com/blog-entry-190.html?id=NM#NM)

[オンボードのEthernetコントローラ(I219-V)がUbuntuで動かない時の対処](https://blog.spiralray.net/archives/474)
postgresにログインできないときの対処方法（peer認証エラー、パスワード忘れ）

Postgreでパスワードがわからんぞ！
なんかpeer認証エラーなるものがでてるぞ！

ってときに対応した内容をまとめたメモです。

### 環境
 - Vagrant 2.1.2
 - CentOS 7.5
 - PostgreSQL 11.7


### Postgresにログインできない！？
Postgresをインストールしてログインしてみようとしたらできない。peer認証ってなんやねん。

```bash
$ psql -U postgres
psql: FATAL:  ユーザ "postgres" で対向(peer)認証に失敗しました
```

### 権限ファイルの書き換え
調べてみたら、権限ファイルがおかしいとのこと。
`pg_hba.conf`というファイルを探しましょう。

私の環境では、下記の場所にありました。
`/var/lib/pgsql/11/data/pg_hba.conf`

このファイルを編集します。
編集する際はsu（スーパーユーザー）でログインするか、sudoコマンドで編集してください。

するとファイルの下部にこんな記述があるはずです。

```bash
# TYPE  DATABASE        USER            ADDRESS                 METHOD
# "local" is for Unix domain socket connections only
local   all             all                                     peer
```

この`peer`という表記を`password`に変更します。こんな感じ。

```bash
# TYPE  DATABASE        USER            ADDRESS                 METHOD
# "local" is for Unix domain socket connections only
local   all             all                                     password
```
そしたらポスグレを再起動します。

```shell
$ sudo /etc/rc.d/init.d/postgresql-9.3 reload
```
や

```bash
$ /usr/local/bin/pg_ctl reload
```
でPostgresが再起動されるはずなんですが、私の場合はうまくいかず、Vagrantから再起動しました。。

### パスワードを忘れた！
ほいなら、あとはログインするだけです。

```bash
$ psql -U postgres
ユーザ postgres のパスワード: 
psql: FATAL:  ユーザ"postgres"のパスワード認証に失敗しました
```

………うん。パスワードがわからん。。。くそう。

### パスワードリセット
パスワードがわからないとなんともできないので、パスワードをリセットします。

さっきの権限ファイル（`pg_hba.conf`）を今度は`trust`に変更します。で、また再起動。

```bash
# TYPE  DATABASE        USER            ADDRESS                 METHOD
# "local" is for Unix domain socket connections only
local   all             all                                     trust
```

そうすると、こんな感じでパスワードなしでpostgreログインできます。

```bash
$ psql -U postgres
psql (11.7)
"help" でヘルプを表示します。
```

`\password`コマンドで、パスワードを変更します。

```bash
postgres=# \password
新しいパスワードを入力してください: 
もう一度入力してください: 
```

そうしたら、Postgreを抜けて、また`pg_hba.conf`ファイルをパスワードありの設定に戻して、再起動です。

```bash
# TYPE  DATABASE        USER            ADDRESS                 METHOD
# "local" is for Unix domain socket connections only
local   all             all                                     password
```

そしたら、ちゃんとパスワード聞かれて、ポスグレにログインできました。

```bash
$ psql -U postgres
ユーザ postgres のパスワード: 
psql (11.7)
"help" でヘルプを表示します。

postgres=# 
```

意外と面倒だった。
コンピューターの回路

現在勉強している基本情報技術者試験についてまとめたものです。
自分のアウトプット用なので見やすさなどは期待しないでください。

# コンピューターの回路
**論理演算**
1を真(True)、2を偽(False)として「AND」「OR」「NOT」などを用いて行う演算。
ベン図を使うとわかりやすく表すことができるが今回は割愛。

**論理回路**
論理演算を行う電子回路。

**基本回路**
以下の3つの回路。

- 論理積回路（AND回路）
- 論理和回路（OR回路）
- 否定回路（NOT回路）

**論理積(AND)**
2つの条件のどちらも合致した場合真となる。

**論理積回路（AND回路）**
入力がどちらも1だった場合、1を出力する論理回路。
論理式は[A（入力）・B（入力） = Y（出力）]
真理値表は下記。

|A|B|Y|
|:-:|:-:|:-:|
|0|0|0|
|0|1|0|
|1|0|0|
|1|1|1|

**論理和(OR)**
2つの条件のうち、どちらかが合致した場合真となる。

**論理和回路（OR回路）**
入力のどちらかが1だった場合、1を出力する論理回路。
論理式は[A（入力）+ B（入力） = Y（出力）]
真理値表は下記。

|A|B|Y|
|:-:|:-:|:-:|
|0|0|0|
|0|1|1|
|1|0|1|
|1|1|1|

**否定(NOT)**
ある条件の合致しないものが真となる。

**否定回路（NOT回路）**
入力を反転させて出力する論理回路。
真理値表は下記。

|A|Y|
|:-:|:-:|
|0|1|
|1|0|

**否定論理積回路（NAND回路）**
論理積と否定を組み合わせた論理回路で、論理積の結果を反転させて出力する。
真理値表は下記。

|A|B|Y|
|:-:|:-:|:-:|
|0|0|1|
|0|1|1|
|1|0|1|
|1|1|0|

**否定論理和回路（NOR回路）**
論理和と否定を組み合わせた論理回路で、論理和の結果を反転させて出力する。
真理値表は下記。

|A|B|Y|
|:-:|:-:|:-:|
|0|0|1|
|0|1|0|
|1|0|0|
|1|1|0|

**排他的論理和回路（EOR回路またはXOR回路）**
2つの入力の内、片方だけが1の場合1を出力する。
真理値表は下記。

|A|B|Y|
|:-:|:-:|:-:|
|0|0|0|
|0|1|1|
|1|0|1|
|1|1|0|

# 加算器
**半加算器**
2進数の足し算を行う回路で、桁上がりを考慮しないもの。
計算を行う際、一番下の桁は桁上がりしてくることを考慮しなくていいので、この回路を使う。

2進数の1桁同士の計算は下記の4パターンがある。

- $0 + 0 = 00$
- $0 + 1 = 01$
- $1 + 0 = 01$
- $1 + 1 = 10$

この答えの2桁目の出力をC、1桁目の出力をSとして真理値表にしたら下記のようになる。

|A|B|C|
|:-:|:-:|:-:|
|0|0|0|
|0|1|0|
|1|0|0|
|1|1|1|

|A|B|S|
|:-:|:-:|:-:|
|0|0|0|
|0|1|1|
|1|0|1|
|1|1|0|

この表はそれぞれ、出力C=論理積、出力S=排他的論理和となっているため、この2つの回路を用いることで作ることができる。

**全加算器**
2進数の足し算を行う回路で、桁上がりを考慮するもの。
計算を行う際、2桁目より上の桁は桁上がりしてくることを考慮しなければいけないので、この回路を使う。
半加算器の仕組みに加え、桁上がりしてきた数（出力C'）も考慮しなければならない。

まず、2つの入力から出力(C,S)を求めるのは半加算器と同じ。
次に、出力Sに入力C'を足せばいいので、この2つを再び入力として出力(C,S)を求める。
つまり、1つ目の半加算器の出力Sにもう1つ半加算器を繋げ、2つの出力Cを論理和回路（両方とも桁上がりすることはあり得ない為）で繋げば全加算器の完成。

# 論理回路を用いたビット操作
2の補数を求めるといったビット操作も、論理回路を使うと簡単に求めることができる。

**マスクパターン**
ビット操作をするときに使う、操作したい位置に1を入れたビット列。

例えば、[00000011]の全てのビットを反転させたいときは、[11111111]というマスクパターンを用意する。
この2つを排他的論理和で計算すると、2つの入力の内、片方だけが1の場合1を出力するので結果は下記のようになる。

||||||||||
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|2進数|0|0|0|0|0|0|1|1|
|マスクパターン|1|1|1|1|1|1|1|1|
|排他的論理和|1|1|1|1|1|1|0|0|

また、ビットの取り出しを行いたいときは論理積を使う。
例えば、[01101011]の下4桁を取り出すときは[00001111]というマスクパターンを用意する。
論理積は2つの入力が両方とも1の時、1を出力するので結果は下記のようになる。

||||||||||
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|2進数|0|1|1|0|1|0|1|1|
|マスクパターン|0|0|0|0|1|1|1|1|
|論理積|0|0|0|0|1|0|1|1|
パラメータ付きURLって、SNSでシェアできないの？（Twitter・Facebook）

#できます
ただし一手間が必要。
それは**エンコード**。

#実装方法

```js
// URLとパラメータを分ける
var href = location.href;
var param = location.search;
var url = href.replace(param, '');

// パラメータをエンコード
param = encodeURIComponent(param);

// 各SNSのシェアURLと、シェアしたいURL、パラメータ、ハッシュタグを結合
// Twitter
var twLink = 'http://twitter.com/share?url=' + url + param + '&hashtags=ハッシュタグ'; 
// Facebook
var fbLink = 'https://www.facebook.com/sharer/sharer.php?u=' + url + param;

// シェアボタンのリンクを置き換える
// Twitter
$('#js-tw-link').attr('href', twLink);
// Facebook
$('#js-fb-link').attr('href', fbLink);
```

encodeURIComponent()にパラメータを入れる一手間が必要。
最初、http://〜からURL全体をエンコードしてたのでうまくいきませんでした。
ABC - 134- A&B&C&D&E

#AtCoder ABC 134 A&B&C&D&E
[AtCoder - 134](https://atcoder.jp/contests/abc134)

E/Fは時間切れ・・・

#A - Dodecagon

```java
	private void solveA() {
		int n = nextInt();
 
		out.println(3 * n * n);
	}
```

#B - Golden Apple

```java

	/**
	 * 6 2
	 * 1 2 3 4 5 6
	 * - - ^ - -
	 *   - - ^ - -
	 *
	 * 20 4
	 * 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20
	 *  -  -  -  -  ^  -  -  -  -
	 *                             -  -  -  -  ^  -  -  -  -
	 *                                   -  -  -  -  ^  -  -  -  -
	 */
	private void solveB() {
		int n = nextInt();
		int d = nextInt();
		int d2 = 2 * d + 1;
		int res = (n / d2) + ((n % d2) != 0 ? 1 : 0);
		out.println(res);
	}
```

#C - Exception Handling

最大値または、2番目に大きい値を出力すればよい
配列コピーして対応したけど。。。

```java

	private void solveC() {
		int n = nextInt();
		int[] wk = IntStream.range(0, n).map(i -> nextInt()).toArray();
		int[] copy = Arrays.copyOf(wk, n);
		Arrays.sort(copy);
		int max = copy[n - 1];
		for (int i : wk) {
			if (i < max)
				out.println(max);
			else
				out.println(copy[n - 2]);
		}
	}
```

#D - Preparing Boxes

最初はすべての箱にボールが入っていない。
番号ごとに偶奇が合えばよい。
前から決定していくのは難しそうなので後ろから決定していけばいいのでは？と考えて実装。
後ろからなら倍数が存在しない数値があるので決定しやすい。
例えば、例1なら3番目の値を先に決定してしまう。
3番目の倍数の6は存在しないので決定可能。
1番目から決定していくと、1,2,3...と決定できない？感じ。

```java

	private void solveD() {
		int n = nextInt();
		int[] wk = IntStream.range(0, n).map(i -> nextInt()).toArray();
 
		int cnt = 0;
		int[] res = new int[n];
		//後ろから決定
		for (int i = n; i > 0; i--) {
 
			final int target = wk[i - 1];
			int wkSum = 0;
			//倍数のボールの個数を数える
			for (int j = 2; (j * i - 1) < n; j++) {
				wkSum += res[j * i - 1];
			}
			//個数の偶奇
			if (target != (wkSum % 2)) {
				res[i - 1]++;
				cnt++;
			}
		}
 
		out.println(cnt);
		if (cnt != 0) {
			StringBuilder builder = new StringBuilder();
			for (int i = 0; i < res.length; i++) {
				if (res[i] != 0) {
					builder.append(i + 1).append(" ");
				}
			}
			out.println(builder.toString());
		}
	}	
```
Python3のlistにおける重複した要素を削除する方法

### リストの中から重複をしている要素の削除
このリストを書こうと思った理由としては、要素が重複していないリストを作成する際に自身はremove()を用いた要素の削除を行っていました。自分はremove()を用いれば指定した値はすべて削除してくれるものだと勘違いしていました。

```
l = [1, 2, 3, 4, 1]
l.remove(1)
print(l)
#[2, 3, 4, 1]
```
このように一番最初に出てきた指定をした値の削除を行うことが出来ます。しかしこのコードだと、削除を行うことができるのは一つだけのため以下のような挙動が起きてしまいます。

```
l = [1, 2, 3, 4, 1, 1]
l.remove(1)
print(l)
#[2, 3, 4, 1, 1]
```

そのため、重複をしていないリストを作成するためには以下のようなコードにするべきです。

```
l = [3, 4, 3, 2, 5, 4, 3]
l_u = []
for i in l:
    if i not in l_u:
        l_u.append(i)
#[3, 4, 2, 5]
```
これによって要素の重複していなリストの作成を行うことが出来ます。

参考にしたサイト
https://www.lifewithpython.com/2013/11/python-remove-duplicates-from-lists.html
https://note.nkmk.me/python-list-clear-pop-remove-del/

###追記
コメントをいただいたため追記します。
以下のコードの方が上記に記載したコードよりも高速に実行することが出来るそうです。
また、順序も保存を行うことが出来ます。

```
l = [3, 4, 3, 2, 5, 4, 3]
print(sorted(set(l), key=l.index))
#[3, 4, 2, 5]
```
GAS　Rangeを制するものはスプシを

GASの鉄板が、「セル１つ１つ処理をしない」こと。
以下のコードは相当な遅さになるそうな。（やったことないから伝聞）

```javascript
for(let i = 0;i < 100 ; i++){
  let data = SpreadsheetApp.getActiveSheet().getRange(1,i).getValue();
  data = data + "-";
  SpreadsheetApp.getActiveSheet().getRange(1,i).setValue(data);
}

```
セル操作がそこそこ時間がかかるので、なるべくまとめてgetsetしたほうがよい、と。
結果、以下のようにするのがはやいそうな（こっちでしかしたことがない。）

```javascript
let range = SpreadsheetApp.getActiveSheet().getRange(1,0,1,100);
let values = range.getValues();
for(let i = 0;i < 100 ; i++){
  values[0][i] = values[0][i] + "-";
}
range.setValues(values);

```

#1.Range
[クラスリファレンス](https://developers.google.com/apps-script/reference/spreadsheet/range)
いわゆるセルのかたまり。
セル１つでも、グループでもレンジとしてデータの取得、設定ができる。
大体、ループで処理をすると思うので、レンジで処理すると楽。
レンジの取得はいくつかのメソッドがある

```javascript
let sheet = SpreadsheetApp.getActiveSheet();
let rangeA = sheet.getRange(row,column);
let rangeB = sheet.getRange(row,column,numOfRow);
let rangeC = sheet.getRange(row,column,numOfCol);
let rangeD = sheet.getRange(row,column,numOfRow,numOfCol);
let rangeE = sheet.getRange("Invoices!A1:D4");
```
rangeAは(row,col)の位置の１つのセル
rangeBは(row,col)の位置からnumOfRow個のセル（行）
rangeCは(row,col)の位置からnumOfCol個のセル（列）
rangeDは(row,col)の位置からnumOfCol,numOfRowのセル（行、列）
rangeEはInvoicesシートのA1からD4の範囲のセル
大抵はrangeDを使うことが多い。E使うくらいなら、下のnamedRangeを使う。

このRangeに対して、

```javascript

let values = range.getValues() // returns string[][];
for(let i = 0;i < values.length;i++){
  for(let j = 0; j < values[i].length;j++){
   console.log(values[i][j]);
  }
}
...
...

range.setValues(values);
```
などとデータ操作が可能となる。
注意点としては、setValuesの引数の配列の次元とrangeの次元が合わないと実行エラーとなる。

#2.Backgrounds Notes など
スプシなので、キレイに背景色やフォント、メモを設定したい。
Rangeでちまちま１つ一つやらず、配列にいれて一気に設定したい。

```javascript
let colors = range.getBackgrounds(); // returns string[][]
let notes = rage.getNotes(); // returns string[][]
...
...
range.setBackgrounds(colors);
range.setNotes(notes);
```
多分、設定できるものはすべて、単体と複数のget,setメソッドあると思うので、rangeをつかって一気にやりたいもの。


#3.NamedRange
他のシートの範囲を取りたい、複数人で触ってて行、列が変わってしまったりする(勝手に行を足しちゃう)、等を考えると、[namedRange](https://developers.google.com/apps-script/reference/spreadsheet/named-range)を使うと楽に。
シートからは、「データ」→「名前付き範囲」で確認できる。
名前をつけた範囲は簡単に取得できる。

###名前付き範囲を名前から取得
```javascript
let spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
let range = spreadsheet.getRangeByName('myRange'); // returns Range
...

```
NamedRange自身を取得するにはgetNamedRangesで取得できる配列を回してとる必要がある。
（NamedRangeに対する操作はほぼ不要なので使うことはないと思われる。）

###名前付き範囲の設定
名前付き範囲の設定も簡単

```javascript
let range = sheet.getRange(row,col,numOfRow,NumOfCol);
spreadsheet.setNamedRange("My range",range);
```
NamedRange自身は使うけど、NamedRangeオブジェクトはほぼ使わないと思われる。
メソッドの戻りがRangeオブジェクトだし、NamedRangeオブジェクトのメソッドにはあまり使うものがない。

###備考
注意点としては、NamedRangeの操作はSpreadsheetオブジェクトに対して行う、という点。
名前を一意につけてない場合は、シート名＋範囲名とする（リファレンスソースより）
>getRangeByName('TaxRates') or getRangeByName('Sheet Name!TaxRates')

####備考の備考
(名前付き範囲をいじるのはメニューをひらかないといけないから、そうそう変な操作の影響は受けないと思う)
NunjucksでVue.jsのマスタッシュ記法を使用する際の解決法


Nunjucksを使用時、Vue.jsのマスタッシュ記法が干渉してしまうので、`{% raw %}{% endraw %}`で囲うことで、その中の全てはplan textとして出されます。


```html
 {% raw %}
 <input v-model="ReferenceCode" placeholder="v-model" />
 <p>メッセージ ：{{ ReferenceCode }}</p>
 {% endraw %}
```

[Nunjucks offical site] (https://mozilla.github.io/nunjucks/templating.html#raw)
上記に記載ありますので、参照ください。
Ubuntuのカーネル操作

Ubuntuのカーネル操作関連について

#現在のカーネルのバージョンの確認

```shell

uname -a
```

#インストールされているカーネルの確認

```shell
dpkg -l | grep linux-image
```

#カーネルのインストール
インストール可能なカーネルの確認

```shell
apt-cache search linux-image
```
目的のバージョンのカーネルがない場合は下記を行ってから再度確認

```shell
sudo apt-get update
sudo apt-get upgrade
```
目的のカーネルのインストール

```shell
sudo apt-get install linux-image-{目的のバージョン}
```
インストール後に再起動


#カーネルを変更して固定
アップデート等で意図せずカーネルが変更されないように固定する
方法は下記の2通り（どちらかのみで有効）
##その1 
`/etc/cat/preferences.d/linux-kernel`を作成し、書き込むやり方

何らかのエディタから`/etc/cat/preferences.d/linux-kernel`を開いて編集する
rootファイルのため編集には`sudo`が必須

```shell
sudo gedit /etc/cat/preferences.d/linux-kernel
```
内容を編集
下記はカーネルを4.15.0-76-genericにした時の例
`-`（ハイフン）が`.`（ドット）になっていることに注意

```/etc/apt/preferences.d/linux-kernel
Package: linux-generic
Pin: version 4.15.0.76
Pin-Priority: 1001

Package: linux-headers-generic
Pin: version 4.15.0.76
Pin-Priority: 1001

Package: linux-image-generic
Pin: version 4.15.0.76
Pin-Priority: 1001
```

##その2
grubを編集する
こっちの方法は少しややこしい

`/etc/default/grub`をroot権限で開く

```shell
sudo gedit /etc/default/grub
```
ファイル内にある`GRUB_DEFAULT`を書き換える
下記はカーネルを4.15.0-76-genericにした時の例

```/etc/default/grub
# GRUB_DEFAULT=0
GRUB_DEFAULT="gnulinux-advanced-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX>gnulinux-4.15.0-76-generic-advanced-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
```

`XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX`の部分は前後とも共通
その内容は`/boot/grub/grub.cfg`内にある`dvanced options for Ubuntuのmenuentry_id_option`を調べる
CapsキーをCtrlキーに置き換えつつ、左Ctrlキーと左Altキーを入れ替える (Linux, Ubuntu)

## 私の欲しているCTRLキー設定

* Capsキーは要らない  
(必要性について国民投票したら負ける気がしない)
* CtrlキーはAの横派  
(私が時を巻き戻すことができるのなら、初めにCtrlキーをキーボードの左下に置いた人間に考え直すよう直談判する)
* 左の親指でCtrlキー(通常Alt/Metaキーが鎮座)を押すと、信じられないぐらいに楽なことを知ってしまった  
(普段使用しているエディタはVimでEmacs使いではないので、Alt(Meta)は多少離れていても問題ない)

## ポイント

* キーの置き換え・入れ替えの設定は「setxkbmap」コマンドで行う
* X起動時に設定するコマンドを実行する方法は、環境によって異なる

## 試した環境

* Ubuntu 19.04

## 手順

### 1. setxkbmapによるCtrlキーの置き換え・入れ替え

「CapsキーのCtrlキーへの置き換え」と「左Altキーと左Ctrlキーの入れ替え」は下記のオプションが予め定義されているのでそれを使えば良い

* 「ctrl:nocaps」 CapsキーをCtrlキーに置き換える
* 「ctrl:swap_lalt_lctl」 左AltキーとCtrlキーを入れ替える

上記オプションを「setxkbmap」実行時に指定する

```
$ setxkbmap -option "ctrl:nocaps" -option "ctrl:swap_lalt_lctl"
```

設定ができたかどうかは`setxkbmap -print`で確認する (xkb_symbols)

```
$ setxkbmap -print
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	★xkb_symbolsに指定したctrl(nocaps)とctrl(swap_lalt_lctl)が追加されていることが確認できる
	xkb_symbols   { include "pc+us+us:2+inet(evdev)+ctrl(nocaps)+ctrl(swap_lalt_lctl)"	};
	xkb_geometry  { include "pc(pc105)"	};
};
```

### 2. X起動毎にこの設定を有効にする

#### Ubuntuの場合

「gnome-session-properties」を起動、「追加(Add)」を押して「setxkbmap -option "ctrl:nocaps" -option "ctrl:swap_lalt_lctl"」を追加する

#### その他の場合

最近のRaspbianでは、LXDEベースだった頃の`~/.config/lxsession/LXDE-pi/autostart`が使えないので、シェルスクリプトに書いて、systemdにサービスとして登録して実行する

## メモ

* CapsキーへのCtrlキーの置き換えは `/etc/default/keyboard`のXKBOPTIONSに「ctrl:nocaps」を指定して実現していましたが、複数のオプションを指定した場合、最初のものしか有効とならなかった
* `/usr/share/X11/xkb/symbols/にsetxkbmap`の設定項目がファイルとして置かれている
* ctrlのオプション項目の定義とその内容は`/usr/share/X11/xkb/symbols/にsetxkbmap/ctrl`にかかれている
* 既存のオプション以外の設定がしたければ、ここを書き換えるなりすれば良さそう

* あくまでも個人の感想です。
webpack(4)でBrowserSyncをもっと簡単に使う

# 概要

- [browser-sync-webpack-plugin](https://www.npmjs.com/package/browser-sync-webpack-plugin)を使う(更新がちょっと古い気がする)
- dev-serverはPHPビルトインサーバーを使う(~~webpack-dev-serverの設定も面倒で~~)

## コマンド＆コード

```console
$ npm install --save-dev browser-sync-webpack-plugin browser-sync
```

```package.json
~~省略

  "scripts": {
    "watch": "php -S 0.0.0.0:8000 & webpack --watch --config webpack.config.js",

~~省略
```

```webpack.config.js
~~省略
  plugins: [
    new BrowserSyncPlugin({
      host: "localhost",
      port: 3000,
      proxy: "http://localhost:8000"
    })
  ]
~~省略
```

あとは

```console
$ npm run watch
```

を叩けばBrowserSyncで自動ブラウザリロード環境ができる。

## 参考

[browser-sync-webpack-plugin](https://www.npmjs.com/package/browser-sync-webpack-plugin)
複数のJupyter notebookをまとめてhtmlファイルに変換する

Jupyter notebookのipynbファイルが複数あって、それらをまとめてhtmlファイルに変換してから、一箇所にまとめたい場合に使えるスクリプトです。

ファイルが複数のフォルダにまたがって存在しても、再帰的にipynbファイルを検索して変換します。

## まず結論から
以下のスクリプトを使って変換できます。

```python
import shutil
from pathlib import Path
import subprocess

output_folder = "htmlファイルの保存先のフォルダパス"
notebook_folder = "ipynbファイルが保存されているフォルダのパス"

path_to_notebook_folder = Path(notebook_folder)
path_to_output_folder = Path(output_folder)

for path_to_ipynb in path_to_notebook_folder.rglob("*.ipynb"):
    print(str(path_to_ipynb))
    proc = subprocess.run(["jupyter", "nbconvert", "--to", "html", str(path_to_ipynb)], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    print(proc.stdout.decode("utf8"))
    print(proc.stderr.decode("utf8"))
    path_to_src_html = path_to_ipynb.with_suffix(".html")
    path_to_dest_html = path_to_output_folder.joinpath(path_to_src_html.name)
    shutil.move(str(path_to_src_html), str(path_to_dest_html))
```

## コードについての説明
### ファイルの再帰的検索

`pathlib.Path`の`rglob("*.ipynb")`によって、指定フォルダ以下のipynbファイルを再帰的に検索します。再帰的に検索したくない場合には`glob("*.ipynb")`を使います。

```python
for path_to_ipynb in path_to_notebook_folder.rglob("*.ipynb"):
    print(str(path_to_ipynb))
```
### jupyter notebookのファイルをhtmlに変換
jupyter notebookのファイルをhtmlに変換するには、linuxコマンドとして

```bash
jupyter nbconvert --to html "ipynbファイルパス"
```

とします。

### linuxコマンドをpythonで実行

linuxコマンドをpythonで実行するために、`subprocess.run`を使います。

```python
subprocess.run(["jupyter", "nbconvert", "--to", "html", "ipynbファイルパス"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
```

### pythonでファイルを移動

最後に、`shutil.move`で生成したhtmlファイルを指定フォルダに移動します。

```python
shutil.move(str(path_to_src_html), str(path_to_dest_html))
```
Deep Security Manager インストール手順

Windows Server 2016 + SQL Server 2016 にて構成

参考 URL 
https://help.deepsecurity.trendmicro.com/11_0/on-premise/ja-jp/install-deep-security.html?redirected=true

下記URL より モジュールをダウンロードする。
https://help.deepsecurity.trendmicro.com/software-earlier-versions.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/d435c27b-869a-411e-553a-f3cb90e92d49.png)

SSMS にてリモートタイムアウトの設定を実施。
※0 タイムアウト無しを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/b63db6ef-dec9-7b80-2402-49b618ce03de.png)


Deep Security Manager のインストーラを実行する。

そのまま次へを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/fa32afbf-01cb-bf80-6d57-9648f7cc037d.png)

データベースの情報を入力する。
※今回はSQLServer の名前付きインスタンスを使用する為、詳細からインスタンス名を入力した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/f876931b-ca14-d243-a828-2ce6793fc88f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/6df9c3d1-57cc-f7dd-a7e3-febd54f65a76.png)

システム要件の確認
(メモリ足りないがそのまま進める)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/7962467d-5930-b8b6-472d-5ccf3595d451.png)

アクティベーションコード入力(今回は体験版)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/207e018b-5711-5a97-02f7-860187641112.png)

今回はActiveDirectry　を使わないので、IPアドレスを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/c7e7c896-7364-eae7-68e2-61c4ddaeb220.png)

ユーザー名パスワード入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/93ca5ee9-df7a-4b04-f475-64a49711710c.png)

セキュリティアップデート特に選択しない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/17e5c4b3-232c-506c-4ce5-488f9ad9234c.png)

Relay有効化済みのAgent もインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/1bbc5d1e-8788-4836-32e1-3b4f2b428382.png)

通知もチェック外す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/9a152581-fbe4-9018-c0eb-679e8916cc57.png)

内容確認しインストールを進める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/90f7c2a9-cc04-1d63-573b-86e85bc0c269.png)

かれこれ4時間程度でインストールは完了する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/c95b4e6c-a267-2704-661d-535cb4b46e89.png)


インストール後コンソール画面を起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/b46ec4ad-c0c6-515d-4f41-0d094f7e6c60.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422457/782988ad-275d-497e-cfd0-70989c60ad50.png)


次に監視対象コンピュータへ Deep Security Agent をインストールする。
パッケージを展開し、yum でインストール

```
# yum -y install /home/piso/dsa/Agent-Core-RedHat_EL7-11.0.0-615.x86_64.rpm
```

Agentの有効化

```
# /opt/ds_agent/dsa_control -a dsm://192.168.100.214:4119/
```

DeepSecurityManager のコンピュータ一覧に表示されていればインストール完了となる。
JavaScriptでの機能

##DOM
HTMLを解析し、データを作成します。
HTMLを解析、DOMに変換=>CSS、JSを読み込んで見た目の描画=>ページを閲覧できます。
HTMLは階層構造になっていることが特徴です。例えば親要素、子要素みたいな感じです。
DOMによって解析されたHTMLは、階層構造のあるデータ(DOMツリー)となります。
DOMツリーはデータとして階層構造を扱うためのアルゴリズム(計算方法)を使い操作できます。
JSを使うと、DOMツリーを使うことができます。
HTMLの要素名や、「id、class」といった属性の情報を元にDOMツリーの一部を取得し、CSSを変更したり、要素を増やしたり、消したりできます。
変更したりするとブラウザに反映され、描画も変わります。
##ノード
HTML1つ1つのタグが、DOMツリーの中ではノードと呼びます。
例えばタグでbodyがあり階層構造にあるheaderまたその中にあるheader_lightもノードと呼びます。
##ノードの取得
JSでHTML要素のid名やクラス名を指定することで、マッチするノードを取得できます。
##document.getElementById("id名");
documentは、開いているWebページのDOMツリーが入っているオブジェクトです。.getElementById("id名")はDOMツリーから特定の要素を取得するためのメソッドの1つです。
id名で取得したい時は

```XXXX.js
document.getElementById("id名");
```
##document.getElementsByClassName("class名");
classを指定して取得する際は使用します。getElementsと複数形になっています。
class名で取得したい時は

```XXXX.js
document.getElementsByClassName("クラス名");
```
##document.querySelector("セレクタ名");
セレクタ名を指定してDOMを取得する場合、querySelectorメソッドを使用します。HTML上から、引数で指定したセレクタに合致するもののうち一番最初に見つかった要素1つを取得します。
セレクタ名を取得したい時は

```XXXX.js
document.querySelector("セレクタ名");
```
##イベント
HTMLの要素に対して行われた処理要求のことをいいます。例えば「ユーザーがブラウザ上のボタンをクリックした」「テキストフィールドでキー入力をした」「要素の上にマウスカーソルを乗せた」などがイベントです。
また、イベントを起こすのはユーザーだけでなく、「ドキュメントの読み込みが終わった」などブラウザが発生させるものもあります。
例えばWebサイト上のある箇所にマウスを乗せると、プルダウン(選択肢が下に出てくること)が展開するような挙動があります。
##イベント駆動
イベントが発生したら、コードが実行される仕組みです。
イベントを取得するためには、先に取得したノードに対して処理を記述します。
##addEventListener
ノードオブジェクトのメソッドです。

```XXXX.js
(ノードオブジェクト).addEventListener("イベント名", 関数);
```
上記の読み込み以降で「ノードオブジェクト」に「イベント」が起きた時、「関数」を実行するようになります。
一つのイベントと一つの関数を紐付ける仕組みのことをイベントリスナと呼びます。
一つのイベントに複数の関数を紐付ける場合は、関数の数だけイベントリスナが存在します。
addEventListenerは、あるノードオブジェクトに対して、イベントリスナを追加するメソッドです。
##window.onload
ページの読み込みをします。2つの記述方法があります。

```XXXX.js
window.onload = function() { 処理 };
```
```XXXX.js
window.addEventListener('load', function() { 処理 });
```
「ページの読み込みが終わる」イベントは、windowオブジェクトのloadイベントに対応します。
##イベント発火の流れ
DOMツリーからノードを取得する => JavaScriptで処理を書く => イベント発火でHTML側で動かす
簡単に書くと
HTML => DOM要素の取得 => JavaScriptで取得した要素に対して実行したい処理を記述する => HTMLでイベント発火
##innerHTML
HTML要素の中身を変更することができる関数です。
【例】

```XXXX.js
window.addEventListener("load", function() {
  let btn = document.querySelector("button");
  btn.addEventListener("click", function() {
    console.log("Hello");
  });
　// テキストの要素を取得し、変数で定義
　let btn2 = document.querySelector("#Button2");
　let changeText = document.querySelector("p");
　// ボタン2をクリックしたらテキストが置換される
　btn2.addEventListener("click", function() {
 　 changeText.innerHTML = '変更されました';
　});
});
```
##classList.add
「クラス追加」ボタンが押されたら、cssの背景色が赤のredクラスが追加されるようにclassList.addを利用します。
【例】

```XXXX.js
// クラス追加を押したらredクラスが追加される
btn.addEventListener("click", function() {
  changeText.classList.add("red");
  console.log(changeText.classList);  //デバッグ
});
```
##classList.remove
「クラス削除」ボタンが押されたら、cssの背景色が青のblueクラスを削除するのにclassList.removeを利用します。
【例】

```XXXX.js
// クラス削除を押したらblueクラスが削除される
btn4.addEventListener("click", function() {
  obj.classList.remove("blue");
});
```
##Array.prototype.slice.call()
引数にとったオブジェクトを配列に変換してくれます。
##forEach()
配列に対して使われる繰り返し処理です。

```XXXX.js
配列.forEach( コールバック関数 )
```
##indexOf()
配列に対してだけ使い、DOMを引数にとって一致した要素番号を戻します。
Laravel 6系でセッションをファイルからデータベースの保存に変更する方法

# はじめに
Laravelではユーザーのセッションはファイルに保持しています
ファイルが出力される場所は「storage/sessions」となります

ここでは、セッションの保存方法にデータベースを使用する方法についてまとめました

# 環境
PHP 7.3
Laravel Framework 6.13.1

# セッションをデータベースに保存する流れ
## 1. セッションを保持するテーブルを作成します

以下のコマンドを実行して、マイグレーションファイルを作成します

```bash
$ php artisan session:table
```

コマンドを実行すると、以下のマイグレーションファイルが作成されます

```database/migrations/YYYY_MM_DD_hhmmss_create_sessions_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateSessionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('sessions', function (Blueprint $table) {
            $table->string('id')->unique();
            $table->unsignedBigInteger('user_id')->nullable();
            $table->string('ip_address', 45)->nullable();
            $table->text('user_agent')->nullable();
            $table->text('payload');
            $table->integer('last_activity');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('sessions');
    }
}
```

マイグレーションコマンドを実行して、セッションテーブルを作成します

```bash
$ php artisan migrate
```

## 2. セッションの保持方法をファイルからデータベースに変更します

.envファイルのセッションドライバーをfileからdatabaseに変更します

```.env
SESSION_DRIVER=database
```

session.phpの設定もfileからdatabaseに変更します

```config/session.php
'driver' => env('SESSION_DRIVER', 'database'),

```

## 3. キャッシュをクリアします

以下のコマンドを実行してキャッシュをクリアします

```bash
$ php artisan config:clear
```

# まとめ
セッションの保存方法をデータベースにしてみようと思う人は参考にしてみてください


# 参考
[HTTPセッション 6.x Laravel](https://readouble.com/laravel/6.x/ja/session.html)
nodenvのinstall -l で表示されるnodeバージョンリストを最新にする。

東京都 新型コロナウイルス感染症対策サイト / Tokyo COVID-19 Task Force website
[tokyo-metropolitan-gov/covid19](https://github.com/tokyo-metropolitan-gov/covid19)

東京都 新型コロナウイルス感染症対策サイトのソースをforkし、ローカルで環境を構築中にnodeバージョンを入れるように警告がでましたがnodenvのinstall -lを実施したところ該当のバージョンがなく、nodeバージョンリストを最新にするためにやったことを記載しております。

```sh
$ yarn install
nodenv: version `10.19.0' is not installed (set by /{**}/covid19/.node-version)
```
```
$ cat covid19/.node-version
10.19.0
```

そこで`$ nodenv install -l`を実行したところ該当のnodeバージョンがありません。。 [^1]

```
[node バージョンリスト表示]
$ nodenv install -l
...
10.15.3
10.16.0
10.16.1
10.16.2
10.16.3
10.17.0
...
```

私のnodenvはanyenv経由で構築しているのではじめはanyenvでなんとかしないといけないかなと思いましたが
どうやらnodenvのリストを自分で更新する必要があるようです。

[github.com/nodenv/node-build#upgrading](https://github.com/nodenv/node-build#upgrading)

```
[公式のドキュメントによると以下を実行するように記載されています。]
$ git -C "$(nodenv root)"/plugins/node-build pull
```

これを自分の環境に置き換えて対応します。

```
[① nodenvがどこにあるのか確認]
$ which nodenv
YOUR/INSTALL/PATH/.anyenv/envs/nodenv/bin/nodenv
[② anyenv配下のnodenvへ移動]
$ cd YOUR/INSTALL/PATH/.anyenv/envs/nodenv
[③ git pullを実行 公式にある指示]
$ git pull
remote: Enumerating objects: 839, done.
remote: Counting objects: 100% (839/839), done.
remote: Compressing objects: 100% (168/168), done.
remote: Total 934 (delta 646), reused 792 (delta 622), pack-reused 95
Receiving objects: 100% (934/934), 182.67 KiB | 422.00 KiB/s, done.
Resolving deltas: 100% (658/658), completed with 301 local objects.
From https://github.com/nodenv/node-build
   3df19246..cdb2593c  master               -> origin/master
 * [new branch]        scrape-workflow      -> origin/scrape-workflow
 * [new tag]           ruby-build/v20191024 -> ruby-build/v20191024
 * [new tag]           ruby-build/v20191030 -> ruby-build/v20191030
...
 rename test/helpers/warning_messages => script/lint/lts (84%)
 create mode 100644 share/node-build/10.18.0
 create mode 100644 share/node-build/10.18.1
 create mode 100644 share/node-build/10.19.0 [→ 今回ほしい該当のバージョン]
 create mode 100644 share/node-build/12.14.0
```
git pullを実行するとログからnodeで追加されたバージョンを確認することができます。
改めて `$ nodenv install -l`を実行します。

```
[node バージョンリスト表示]
$ nodenv install -l
...
10.16.1
10.16.2
10.16.3
10.17.0
10.18.0
10.18.1
10.19.0 [→ 今回ほしい該当のバージョン]
11.10.0
...
```

ほしいバージョンが表示されています。

### 蛇足

一応ローカルでサイトが立ち上がることを確認します。

```
$ nodenv install 10.19.0
Downloading node-v10.19.0-darwin-x64.tar.gz...
-> https://nodejs.org/dist/v10.19.0/node-v10.19.0-darwin-x64.tar.gz
Installing node-v10.19.0-darwin-x64...
Installed node-v10.19.0-darwin-x64 to YOUR/INSTALL/PATH/.anyenv/envs/nodenv/versions/10.19.0
```

```
$ yarn install
yarn install v1.22.4
[1/5] 🔍  Validating package.json...
[2/5] 🔍  Resolving packages...
[3/5] 🚚  Fetching packages...
[4/5] 🔗  Linking dependencies...
warning "babel-jest > babel-preset-jest > @babel/plugin-syntax-object-rest-spread@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
warning "vue-jest > @babel/plugin-transform-modules-commonjs@7.8.3" has unmet peer dependency "@babel/core@^7.0.0-0".
・・・
✨  Done in 12.70s.
```

無事に`$yarn install`に成功しました。
そして、都内の最新感染動向 | 東京都 新型コロナウイルス感染症対策サイトを起動することができました。

[^1]: それぞれの環境で表示されるバージョンは異なると思います。
mongosをdockerで。

# mongosをdockerで動作させる設定

探しても中々書いてくれている所を発見できなかったのでdockerファイル等を読んでみた結果、
なんてことは無かった。

```docker-compose.yml
version: '2'
services:
  mongo:
    image: mongo:4.2.2
    restart: always
    volumes:
      - /var/lib/mongodb:/data/db
      - /var/log/mongos:/var/log/mongodb
      - /usr/lib/mongodb:/etc/mongo
    ports:
      - 27017:27017
    command: mongos -config /etc/mongo/mongod.conf
    environment:
     - "TZ=Japan"
```
* dockerと言いながらcomposeなのは面倒くさいからです、ごめんなさい。
* コンテナイメージは自分の使用したいバージョンを指定してください。
* volumesは自分の環境に合わせて変更してください。
* configで渡すファイルパスも自分の環境に合わせてください。
* ポートも自分の環境に合わせて…

# 要はcommandで mongosを渡したら出来る。
終了。
複数の画像が読み込まれた"後"に処理を実行させる

# やりたかったこと

1. 画像を含んだ要素をappendする
2. appendされた画像がすべてロードされたあとに関数を実行する
2. その関数で、imgを含めた要素の高さを取得する

## つまづいたところ
通常ならappendしたらそのまま次の処理でheight()すれば、要素の高さを取得することができるが、**画像をappendしたときは画像がロードされたのを見届けなければ、高さがうまくとれない。**

**それは、画像を子孫に含んだ要素も同じです。**

リロードするとキャッシュされたものを拾ってくれるので、一見するとうまく処理されているように見えるトラップつきだった。

### 失敗コード
appendしてすぐに`match_height_byChildElems('.js-add-faceImgs');`しているコードです。

```javascript
$(function () {

    var thumbnails = ['taro', 'jiro', 'saburo', 'shiro', 'goro', 'tanjiro']

    for (var i = 0; i < thumbnails.length; i++) {
        var iconURL = '/img/icon_face_' + thumbnails[i] + '.png';
        html = '<li>';
        html += '<img src="' + iconURL + '" alt="">';
        html += '</li>';
        var $elm = $(html);
        $('.js-add-faceImgs').append($elm);
    }

    match_height_byChildElems('.js-add-faceImgs'); // ココ！
});


/**
 * 子要素の最大の高さを計算して、親要素の高さを指定する
 * @param {String} className 親クラス名*/
function match_height_byChildElems(className) {
    var maxHeight = 0;

    $(className).children().each(function(){
        var thisHeight = $(this).height();
        console.log($(this), thisHeight)

        maxHeight = maxHeight <= thisHeight ? thisHeight : maxHeight;
    });
    $(className).height(maxHeight);
}
```

## 解決方法
追加した要素の長さと`loadCounter`の値が同じ = 処理完了！

として、そのときに`match_height_byChildElems('.js-add-faceImgs')`を呼び出しています。
これで、setTimeout()など当てずっぽう数字ではなく、指定のimgすべてがロード完了したときに関数を呼び出すことができます。

### 成功コード
`$('.js-add-faceImgs img').each(function(){~~`を追加して、imgのロード完了をカウントしています。

```javascript
$(function () {

    var thumbnails = ['taro', 'jiro', 'saburo', 'shiro', 'goro', 'tanjiro']

    for (var i = 0; i < thumbnails.length; i++) {
        var iconURL = '/img/icon_face_' + thumbnails[i] + '.png';
        html = '<li>';
        html += '<img src="' + iconURL + '" alt="">';
        html += '</li>';
        var $elm = $(html);
        $('.js-add-faceImgs').append($elm);
    }

    // imgのロードが完了したらマッチハイトさせる
    // ココ！
    var loadCounter = 0;
    $('.js-add-faceImgs img').each(function(){
        $(this).load(function(){
            loadCounter++;
            if (loadCounter === $('.js-add-faceImgs img').length) {
                match_height_byChildElems('.js-add-faceImgs');
            }
        });
    });
});


/**
 * 子要素の最大の高さを計算して、親要素の高さを指定する
 * @param {String} className 親クラス名*/
function match_height_byChildElems(className) {
    var maxHeight = 0;

    $(className).children().each(function(){
        var thisHeight = $(this).height();

        maxHeight = maxHeight <= thisHeight ? thisHeight : maxHeight;
    });
    $(className).height(maxHeight);
}
```

#### 余談
こう書いたほうがスッキリするかもです。

```javascript

// imgのロードが完了したらマッチハイトさせる
var loadCounter = 0;
$('.js-add-faceImgs img').each(function(){
    $(this).load(function(){
        loadCounter++;
        var loadComplete = (loadCounter === $('.js-add-faceImgs img').length);
        if (loadComplete) match_height_byChildElems('.js-add-faceImgs');
    });
});
```
rosserial tips


#rosserial tips


    [ERROR] [WallTime: 1399983538.726124] Unable to sync with device; possible link problem or link software version mismatch such as hydro rosserial_python with groovy Arduino

ボーレートを下げてみる。


    [INFO] [1551878102.653449]: Requesting topics...

ビルド、書込みはＯＫだがArduino側のプログラムに問題がある。
配列のout of range等がないかスケッチを確認する。
S3に関するIAMユーザー作成


AWSが提供する画像ストレージサービスのS3を利用するためだけのIAMユーザーを作成します

ログイン画面→サービス→IAMと検索するとこの画面になるので、
個々のユーザー作成→グループの管理をクリック

<img width="1440" alt="スクリーンショット 2020-03-12 15.02.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/7e39a14e-c0aa-669a-02b4-90a3fb796130.png">

そのあとユーザーを追加をクリックするとこの画面にいきます

<img width="1440" alt="スクリーンショット 2020-03-12 15.06.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/82dadc15-8154-3694-7b38-5a86c6ed459d.png">

名前入力、項目チェックして次のステップ
検索バーで「S3」と打つと「AmazonS3FullAccess」がでてきますのでチェックして次のステップ
<img width="1440" alt="スクリーンショット 2020-03-12 15.08.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/b4315edb-de2a-478b-dfd5-2a9d27c38e7f.png">

この次の画面は何もせず次のステップをして、
確認画面にいきます

最後にcsvファイルのある画面にきますが、
必ずcsvファイルはダウンロードしてください


<img width="1440" alt="スクリーンショット 2020-03-12 15.13.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594198/20239a12-f3ed-bb65-c1a5-cb90ddd3c045.png">

以上です

このIAMユーザーを使ってのS3ストレージ利用については別の記事であげますので参考にしてください

ありがとうございました
(Mac)SourceTree 4.0.1で「端末」からターミナルが起動しない

# 現象


<img width="278" alt="sourcetree_terminal.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/0a92f0cd-f4ae-f16f-77c0-cfc9218af874.png">

SourceTreeには、上記のように「Finderで表示」とか「端末」とか、便利なアイコンがありますが、
なぜか、2020年3月12日現在最新の4.0.1だと、以下のような現象が起きていました。

- ターミナルが起動していなければ起動する
  - ただし、ホームディレクトリで起動してしまう
  - 過去バージョンでは、プロジェクトのディレクトリで起動してくれていた
- ターミナルが起動していると、ウィンドウが一つも開いていなくても、起動してくれない
  - 過去バージョンでは新規ウィンドウが必ず開いてくれた

これはとても不便なので、調べました。

# 解決方法

こちらのやりとりが参考になりました。
(私のMacはMojaveなので、Catalinaの問題ではなく、SourceTreeの問題かと思います)

https://community.atlassian.com/t5/Sourcetree-questions/macOS-Catalina-Terminal-Button-Always-Opens-in-Home-Folder/qaq-p/1238466

## 手順

- 古いバージョン(3.2.1)を以下のリンクからダウンロードしてアプリケーションフォルダに上書きする
  - https://www.sourcetreeapp.com/download-archives
- SourceTreeを起動し、アクセスを許可する
- SourceTreeを完全に終了させる
- 新しいバージョンに再び上書き
- SourceTreeを起動

これで解決しました。

※アップデートが上がってないか調べましたが、まだのようです。
【ARFoundation】画像名は日本語OK、フォルダ名はエラー（ReferenceImageLibraryの生成エラーについて)

内容はほぼ見出しの通りです。


#対象
```
Failed to generated ARCore reference image library ~~
```
```
BuildFailedException: Failed to generate image database. Output from arcoreimg:
```
のエラーが出て、
ある程度調べて
「png→jpgにしろ！」
「300*300以上の解像度のマーカーを設定しろ!」
といわれて、指示道理にしたがUnityが治らない方


#結論
ARFoundationのReferenceImageLibraryに入れる画像のフォルダ名に日本語が入っているとビルドが通らないです。（iosでは試していない）
しかし、画像名が日本語でも構わない。これが盲点になって気が付くの遅れます。。

エンコード系のバグはエラーがそれっぽい名前にならないのが怖いですね。

以上です。
【日本語で説明】PostgreSQLのWITH RECURSIVEの動き

公式ドキュメントを読んでもググってみてもいい感じの説明がなくて動きがわかりにくかったので、ここにメモ。

# 参考
公式ドキュメント
https://www.postgresql.jp/document/9.6/html/queries-with.html

# 使う例
今回は公式ドキュメントで使われている以下の例を使っていきます。
やっていることは1から100までの和を出しているだけですね。

```sql
-- https://www.postgresql.jp/document/9.6/html/queries-with.html より
WITH RECURSIVE t(n) AS (
    VALUES (1)
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;
```

では、ここからが説明です。

# どうに動くのか
公式ドキュメントにも書いてありますが、大きく2つに分かれます。
**非再帰的表現（non-recursiveterm）** と **再帰的表現（recursive term）** です。

これらの説明をする前に、

どういうデータ構造を扱うのか理解しておくとわかりやすいので、先に少しだけ説明します。

## 事前知識：データ構造
3つのデータが出てきます。それは、
- 本テーブル
- 作業テーブル
- 中間テーブル

### 本テーブル
本テーブルはわかりやすいですね。WITH RECURSIVEを使って作ろうとしているテーブルです。例で言えば1から100までの和が入ったテーブルです。

### 作業テーブル
作業テーブルは一時的にデータを置いておく場所です。前回のSELECTの結果が作業テーブルには入っています。(例では「SELECT n+1 FROM t WHERE n < 100」の部分)。作業テーブルのデータをもとにして再帰的表現（recursive term）を評価し、その結果が本テーブルに溜まっていくイメージです。

### 中間テーブル
中間テーブルは一瞬だけデータを置いておきます。(一時的より短い期間)

めちゃくちゃ乱暴な説明ですが、これだけ覚えておけば後の説明がわかりやすくなるはずです。とりあえず信じてください。



では説明どうぞ。

## まずは非再帰的表現（non-recursiveterm）の部分
これは簡単ですね。例で言うと★の部分です。

```sql
-- https://www.postgresql.jp/document/9.6/html/queries-with.html より
WITH RECURSIVE t(n) AS (
    VALUES (1) ★
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;
```

これを評価したらどうなるのかというと、この式の結果がまず本テーブルと作業テーブルに入ります。[^1]


これで、本テーブルと作業テーブルに`1`のレコードが入った状態になります。これだけです。1つのSQL文を評価するだけなので簡単ですね。

そして、

## 次が再帰的表現（recursive term）の部分
再帰的表現（recursive term）の部分になります。ここがややこしい部分で、自分がうまく理解できなかった部分です。

例でいうと、★の行ですね。

```sql
-- https://www.postgresql.jp/document/9.6/html/queries-with.html より
WITH RECURSIVE t(n) AS (
    VALUES (1)
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100 ★
)
SELECT sum(n) FROM t;
```

で、これがどう動くのかと言うと、おおよそ以下の3行で表せます。

1. FROM句を本テーブルではなく作業テーブルに読み替える。なので、`FROM t` を `FROM 作業テーブル` と読み替える。
2. もし作業テーブルにレコードがあれば、再帰的表現（recursive term）を評価し、結果を本テーブルと中間テーブルに追加する。もしない場合、ここで終了。
3. 中間テーブルの内容で作業テーブルを上書きし、中間テーブルの内容を削除する。そして2に戻る。

擬似コードにするとこんな感じです

```
- `FROM t` を `FROM 作業テーブル` と読み替える。
while (作業テーブルにレコードあり) {
    - 再帰的表現（recursive term）を評価し、結果を本テーブルと中間テーブルに追加する
    - 中間テーブルの内容で作業テーブルを上書き
    - 中間テーブルの内容を削除する
}
- 本テーブルの内容を返す
```

図も書いてつけようかとがんばったのですが、逆にぐちゃぐちゃでわかりにくくなってしまったので、言葉だけですみません。

上の言葉を追って、脳内で(または紙上で)データがどういう風に動くのかがイメージできれば、もうWITH RECURSIVEは攻略できたも同然です。

# まとめ
WITH RECURSIVEの動きを日本語で説明しました。

例をあげるとこれ。

```sql
-- https://www.postgresql.jp/document/9.6/html/queries-with.html より
WITH RECURSIVE t(n) AS (
    VALUES (1)                      -- ★ 非再帰的表現（non-recursiveterm）
  UNION ALL
    SELECT n+1 FROM t WHERE n < 100 -- ★ 再帰的表現（recursive term）
)
SELECT sum(n) FROM t;
```


要するに、
再帰的表現のSELECT文を何回も実行していって、
一回一回の再帰的表現の結果が入っているのが作業テーブル、
その結果の積み重ねたのが本テーブル、
作業テーブルに入れる次ループのための結果を一瞬だけ保持するのが中間テーブル、
ってな感じです。

あまり使う機会がないWITH RECURSIVEですが、いざ使うときになると困るものです。この記事がWITH RECURSIVEを苦労なく使えるようになる手助けができたら幸いです。

[^1]: (本当はその下に続く行がUNION ALLなのかUNIONなのかでちょっと動きが違いますが、今回は動きを理解するのに重要じゃないので無視します。公式ドキュメントをみればすぐわかりますし)
SSHを使用したDB接続

# 接続方法

https://monotone.jp/archives/19191
https://hostingstock.net/blog/20150522/

# 接続エラー
https://yourmystar-engineer.hatenablog.jp/entry/2017/05/08/044203

## パーミッションエラー
https://qiita.com/turmericN/items/9a1756e98c062bc81ef1
http://yachibit.hatenablog.jp/entry/2013/04/25/001912 

<img width="294" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411120/336d3bc0-e141-72fc-df22-75dcc6cb695b.jpeg">
秘密鍵の権限は「600」である必要がある
きつすぎても、ゆるすぎてもエラーが発生する
USB出力９軸IMUセンサモジュール

#環境
ubuntu18.04 
ROS melodic

#USB出力9軸IMUセンサモジュールのインストール

下記のgithubから
https://github.com/rt-net/rt_usb_9axisimu_driver/wiki
https://github.com/rt-net/rt_usb_9axisimu_driver/

```
cd ~/workspace/usb_9axisimu/src
git clone https://github.com/rt-net/rt_usb_9axisimu_driver.git
cd ~/workspace/usb_9axisimu
catkin build
```

#USB出力9軸IMUセンサモジュールの実行

ターミナルごとに実行

```
source ~/workspace/usb_9axisimu/devel/setup.bash
```

launchファイルの実行

```
sudo chmod 666 /dev/ttyACM0 ※これしないとエラーが出る
roslaunch rt_usb_9axisimu_driver rt_usb_9axisimu_driver.launch  [or]
(rosrun rt_usb_9axisimu_driver rt_usb_9axisimu_driver) 
```

※ちゃんとしたUSBケーブルじゃないと認識しないので注意

```
rostopic list
```
ここで3つのデータが確認できればOK




#配信データ形式をASCII形式からBinary形式への変更

githubの[マニュアル](https://github.com/rt-net/RT-USB-9AXIS-00/blob/master/manual/USB%E5%87%BA%E5%8A%9B9%E8%BB%B8IMU%E3%82%BB%E3%83%B3%E3%82%B5ver2.0%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB.pdf)


まずはttyACM0の中身を再生

```
sudo cat /dev/ttyACM0  
```

- IMUのデータが流れてる画面でIMUのタクトスイッチを長押し3秒以上して設定画面を出す
- タクトスイッチを短く押して　modeset 8　を選び3秒長押し
- 2 BINARY を選び3秒長押し


#データを可視化
 
下記実行

```
rosrun rqt_plot rqt_plot
```
- 以下の項目をプラスボタンから追加する

並進加速度
/imu/data_raw/linear_acceleration/x
/imu/data_raw/linear_acceleration/y　
/imu/data_raw/linear_acceleration/z

角速度
/imu/data_raw/angular_velocity/x
/imu/data_raw/angular_velocity/y
/imu/data_raw/angular_velocity/z

magnetic_field
/imu/mag/magnetic_field/x
/imu/mag/magnetic_field/y
/imu/mag/magnetic_field/z



>4.1.1 パブリッシュされるトピック
/imu/data_raw(sensor_msgs/Imu)
並進加速度と角速度の生データ
/imu/mag(sensor_msgs/MagneticField)
磁束密度の生データ
/imu/temperature(std_msgs/Float64)
センサの温度データ


>4.1.2 パラメータ
~port (string, default: /dev/ttyACM0)
モジュールが接続されているポート名
~linear_acceleration_stddev (double, default: 0.023145)
並進加速度の共分散行列の対角成分の平方根(m/s^2)
~angular_velocity_stddev (double, default: 0.0010621)
角速度の共分散行列の対角成分の平方根(rad/s)
~magnetic_field_stddev (double, default: 0.00000080786)
磁束密度の共分散行列の対角成分の平方根(T)



#サンプルプログラムの実行
Linux, Mac環境でBinary出力を確認するサンプルプログラム
https://www.rt-net.jp/products/9axisimu2
https://github.com/rt-net/RT-USB-9AXIS-00
https://github.com/rt-net/RT-USB-9AXIS-00/tree/master/LinuxSampleProgram

```
mkdir workspace/9AXIS_sample
cd 9AXIS_sample
git clone https://github.com/rt-net/RT-USB-9AXIS-00.git
```

###ポートの権限を設定する
サンプルプログラムを動かす前に、デバイスファイルの権限を設定してください。
9軸センサモジュールをPCに接続したあと、下記のコマンドを実行してください。
※/dev/ttyACM0 は環境によって名前が変わります。

```
sudo chmod 666 /dev/ttyACM0
```

###サンプルプログラムのデバイスファイル名を変更する
usb9axis_test.cの70行目にてデバイスファイル名を指定してください。

```
cd workspace/9AXIS_sample/RT-USB-9AXIS-00/LinuxSampleProgram 
nano usb9axis_test.c
```

```
int main(int argc, char **argv){
    char serial_port[128]="/dev/ttyACM0"; // ここにデバイスファイル名を入力する
```

usb9axis_test.cをgccでコンパイルしてください。

```
gcc usb9axis_test.c　
```

###サンプルプログラムを実行する

```
./a.out
```


#別の方法
https://github.com/tork-a/adi_driver
コーダーの地味に便利なリンク集

転職するので、ブックマークしているURLをまとめる。

# チェック関連
## OGP
### twitter
https://cards-dev.twitter.com/validator

### Facebook
https://developers.facebook.com/tools/debug/

## HTMLバリデーション
http://validator.w3.org/

# 計算系

## 文字カウント
http://www1.odn.ne.jp/megukuma/count.htm

## 比率計算機
https://ratiocalculator.toshimaru.net/

# Facebook広告 画像チェック
https://www.facebook.com/ads/tools/text_overlay

# CSS

## animate CSS
https://daneden.github.io/animate.css/
https://raw.githubusercontent.com/daneden/animate.css/master/animate.css

## Flexboxのjustify-contentで最後の行を左寄せにする方法
https://blog.webcreativepark.net/2016/08/15-125202.html

## imgタグでSVGを使ってもfillを使えるようにするプラグイン
https://bitwave.showcase-tv.com/svg%E3%81%AE%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%82%92%E7%B0%A1%E5%8D%98%E3%81%AB%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E4%BE%BF%E5%88%A9%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88/

# HTML

## googleMap パラメーター指定でiframeに地図を埋め込む。
https://www.bricoleur.co.jp/blog/archives/4452

## Bootstrap4 Cheat Sheat
https://hackerthemes.com/bootstrap-cheatsheet/
Linuxの増分バックアップをする(リストア)

**[この記事](https://qiita.com/ykgeek/items/988db214b7ccaedca27c)と[この記事](https://qiita.com/ykgeek/items/3317031198867369547e)の続きです。詳細はこの記事で紹介しているのでそちらをご覧ください。**

大変お待たせしました。この記事ではバックアップしたファイルをリストアする方法を紹介します。
（「リストア方法は現在記事を用意しているのでお待ちください。」と書いておきながらすっかり忘れていました…ｽﾐﾏｾﾝ）


# TL;DR
個々のファイルの復元についてはバックアップ先のディレクトリを探して直接コピーして取り出してください。
ここで紹介する方法は以前の記事で紹介した方法でバックアップしたデータからシステム全体を復元する方法です。
今回は実行する回数や環境がバラバラだと思いますのでコマンドのみを残しておきます。
環境に合わせて適宜変更してください。

```
# "/var/backup/Host1/20200101/"はバックアップのパス(最後の/を忘れないこと)
# "/mnt/host1system/"はリストア先のパス

# ローカルで復元する場合
rsync -aHAX --info=progress2 --numeric-ids /var/backup/Host1/20200101/ /mnt/host1system/

# バックアップサーバから復元する場合
# backupsvはサーバのホスト名
rsync -aHAXz --info=progress2 --numeric-ids --rsync-path='sudo rsync' backupsv:/var/backup/Host1/20200101/ /mnt/host1system/
```

# リストア
以前の記事ではシステム全体をコピーする方法を紹介しましたが、リストアはそのうち復元したいシステムのデータを`rsync`を使って全てコピーします。
実はやっていることはバックアップの反対です。

外付けHDDなどローカルのシステムだけで復元できる場合はまず始めに復元するシステムをLiveUSBなどを使って起動します。
その後システムパーティションを作成し、マウントした上で下記のコマンドを実行します。

```
# "/var/backup/Host1/20200101/"はバックアップのパス(最後の/を忘れないこと)
# "/mnt/host1system/"はリストア先のパス
rsync -aHAX --info=progress2 --numeric-ids /var/backup/Host1/20200101/ /mnt/host1system/
```
パス等は適宜置き換えてください。

バックアップサーバでバックアップを行い復元もリモートのサーバという場合はバックアップと同じくssh経由で行います。

```
# "/var/backup/Host1/20200101/"はバックアップのパス(最後の/を忘れないこと)
# "/mnt/host1system/"はリストア先のパス
# backupsvはサーバのホスト名
rsync -aHAXz --info=progress2 --numeric-ids --rsync-path='sudo rsync' backupsv:/var/backup/Host1/20200101/ /mnt/host1system/
```
上記のコマンドの場合は
backupsv--->host1(コマンドを実行する端末)
と言ったデータの流れになります。データを引っ張ってくるイメージです。

# あとがき
今回は頻繁におこわない（であろう）復元だったため少しシンプルにして紹介させていただきました。
これでいざというときのシステムの復旧が楽になることを願っています。
もし間違いなどがあればそちらもご指摘いただければ幸いです。