OmniAICreator/Qiita-1.07M huggingface dataset:
面白いCAD:TINKERCADを使ってみる

# 概要
2019.04.19 [Coder Dojo @Daito（大東・四條畷）](http://coderdojodaito.strikingly.com/) 大東市のお手伝いに行って、面白いCADを見せてもらったので、紹介しておきます。
子供の知育を目指したCADのようですが、本格的にも使えそうです。また、mincraftやレゴのモードもあります。
一番驚いたのはCircutモードです。回路のCADも統合されていて、シミュレートまでできます。

# 公式サイト

- [Autodesk社：TINKERCAD](https://www.tinkercad.com/)

# 特徴

- ブラウザベースで動作する。
- アカウントを作成する必要がある（年齢制限があるようで保護者がアカウントを作成するほうが無難）。
- 日本語対応している
- CADモードには、標準キャドとmincraftとブロックモードがある

# CADモード画面

- ![スクリーンショット 2019-04-30 11.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237044/ed19e092-da1d-3f68-3cd6-fa17485f23ba.png)
- この画面が新規作成を選んだときの画面
- 平面図は方眼紙をイメージ。
- 右側の形をドラグしてきて、拡大縮小、回転で形を作っていく。
- 選択してゴミ箱をクリックするとモデルを削除できる。
- 一番上の透明の部品は、カット（穴などを作る）ためのブロック。
- 左上の文字列がCADデータのファイル名になる。その前の、テーブルアイコンをクリックすると作成データの管理ができる。
- 視点は　左上のキューブをクリックすることでも変えることができる。
- インポートは、STL,OBJ,SVGをサポート。エクスポートも同様。よって、３Dプリンタ用のデータを生成できる。
- 右上のルービックキューブの正面のような青色のアイコンが現在の標準キャド画面のモードを示す。
- ツルハシをクリックすると標準キャド画面で描いた図形がmincraftのブロックに置き換わる。
- ブロックは、画面上でレゴブロックのように遊べるよう（ちゃんと使っていません。。。すいません）。
- TINKERCADのアイコンをクリックするとMyPage(?)に戻る。Circuitモードに切り替えるには、ここに戻る必要がある。

# Circuitモード画面（以下、回路モード）

- ![スクリーンショット 2019-04-30 11.47.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237044/d83ed0a2-49e3-2d30-b1da-2ba92933e074.png)
- この画面は、初めて回路モードを開いたときにデフォルトで置かれているファイルを開き、最初のチュートリアルを終わらせたときに開く画面です。
- 回路は実体配線図で表現されます。
- 「シミュレート開始」を押すと回路の動作確認ができます。
- 「コード」をクリックするとArduinoのプログラムが開きます。対応しているのはUNOだけですが、十分だと思います。
- じっくり触っていないのですが、好きな人はハマるかも？
- 電子工作はやっぱり実物！というように私も思いますが、興味を持たせるには、このような環境を起点にするのも悪くないかと思いました。
AIを学ぶために必要な数学

# 線形代数
## 固有値・固有ベクトル
行列Aに対して、以下の公式を満たすスカラーλが存在する。
この時、スカラー$λ$を固有値、$\vec{x}$を固有ベクトルという。

```math
A \vec{x} = λ\vec{x} ・・・① \\

A : 行列　λ : 固有値　\vec{x} : 固有ベクトル \\
```
### 解き方
単位行列$I$を用いて、$|A-λI|=0$となる$λ$を見つける。

```math
(A-λI) \vec{x} = \vec{0} \\
```

```math
ここで、
A = 
\begin{pmatrix}
a&b\\
c&d
\end{pmatrix}
とすると、 \\
```

```math

\\

\begin{vmatrix}
a-λ & b \\
c & d-λ
\end{vmatrix}
= 0 \\

(a-λ)(d-λ)-bc=0 ・・・②
```
②を解くことにより、固有値λが見つかる。
λを①に代入した連立方程式から、固有ベクトル xが得られる。

## 固有値分解
正方行列$A$(行と列が同じ数の行列）を以下のような３つの行列の積に変換できる。

```math

A = VΛV^{-1} \\

```

$Λ$ : 固有値λ1, λ2, λ3,... の対角行列（対角上以外の要素は0) 

```math
Λ = 
\begin{pmatrix}
λ1& & & \\
 &λ2& & \\
 & & λ3& \\
 & & &　…


\end{pmatrix}
\\

```

$V$ : 固有ベクトル$v1$,$v2$,$v3$,...を並べた行列

```math
V = 
\begin{pmatrix}
v1&v2&v3&… \\
\end{pmatrix}
\\

```
## 特異値分解
ある行列$M$（正方行列とは限らない）に対して、次のような式で表される各行列の値を求める方法。

```math
M = USV^{-1} \\
```
ここで、行列$S$は特異値$σ_1$,$σ_2$,$σ_3$ ,...を並べた行列。(Sは正方行列とは限らない)

```math
S=
\begin{pmatrix}
σ_1 & & &  \\
 & σ_2 & &  \\
 & & σ_3 & \\
 & & & & … \\

\end{pmatrix}
```

行列$U$,$V$はそれぞれ、左特異ベクトル、右特異ベクトル（行列$U$,$V$は大きさが１の単位行列）

```math
U=
\begin{pmatrix}
u_1 & u_2 & u_3 & …  \\
\end{pmatrix}
,
V=
\begin{pmatrix}
v_1 & v_2 & v_3 & …  \\
\end{pmatrix}
```

### 解き方

```math
MM^{t}=USS^{t}U^{-1}
```
となるので、$MM^{t}$を固有値分解すると、左特異ベクトル$U$と$SS^{t}$が得られ、
$SS^{t}$は特異値の２乗の対角行列になるので、固有値$λ_i$は特異値$σ_i$の２乗になる。

同様に、右特異ベクトルは$M^{t}M=VS^{t}SV^{-1}$を解くことで得られる。


# 確率・統計

## ベイズ則（ベイズの定理）

```math
P(X)P(Y|X)=P(Y)P(X|Y)=P(X∩Y）　\\
P(X) : 事象Xが起きる確率,　P(X|Y) : 事象Xが起きたもとで、事象Yが起きる確率(条件付き確率)
```

## 分散・共分散

### 分散
データの散らばり具合を表す。
分散が大きいほど、データのばらつきが大きい。

```math
Var(f) = σ^2 = E((f_(x)-E_(f))^2)
```

*分散$σ^2$に対して、$σ$は標準偏差という。

### 共分散
２つのデータの近似性を表す。
共分散が　正の値＝関連性ありそう、負の値＝関連性なさそう。
(０だと、関係性に乏しい)

```math
Cov(f,g) = E( (f_(x)-E_(f) )( g_(y)-E(g) )
```

*共分散の傾向は例外があるので気を付ける。

## 確率分布
### ベルヌーイ分布
「コインの表か裏」、「勝ちか負け」の２つの結果しかない場合、
確率μでx=1になるとすると、確率1-μでx=0になる。
それを、次のような式を表すことができる。

```math
P(x|μ) = μ^x(1-μ)^{1-x} \\
```

*$x$は0か１しか取らない。$0≦μ≦1$である。

### マルチヌーイ（カテゴリカル）分布
サイコロのように、取りうる値が複数パターンある時の確率の表し方。

```math
P(x|μ) = μ_1^{[x=1]}μ_2^{[x=2]}μ_3^{[x=3]}...
```

* $[x=k]$ : $x=k$の時に、値が１となり、それ以外は０になる。（アイバーソンの記法という）

### 二項分布
ベルヌーイ分布のような、２つの結果しかない事を複数回繰り返した場合、
確率λでx=1になり、それをn回試行した時、x=1がk回となる確率は次のような式で表すことができる。

```math
P(x|λ,n) = _n C _k λ^x(1-λ)^{n-x} = \frac{n!}{k!(n-k)!}λ^x(1-λ)^{n-x}

```

### 正規分布(ガウス分布)
二項分布などの離散値の分布とは違い、連続型の確率分布
平均を$μ$、分散を$σ^2$とすると、次の式で表される。

```math
N(x;μ,σ^2) = \sqrt{\frac{1}{2πσ^2}}exp(\frac{1}{2σ^2}(x-μ)^2)

```

*$x$の２次関数になっているため、$μ$を中心とした、頂点がなだらかな釣り鐘型の関数となる。

# 情報理論

## 自己情報量
ある情報がもつ珍しさを表している。
確率$P(x)$で起こる、事象$x$の自己情報量$I$は次の式で表される。

```math
I(x) = -logP(x) = log(W(x))

```

*対数を取っているのは、例えば２つの事が起こった場合、情報量は感覚的に掛け算よりも足し算の方が近いため

## シャノンエトロピー (平均情報量)
自己情報量の期待値

```math
\begin{align}
H(x) &= E(I(x)) \\
&= -E(log(P(x))) \\
&= -Σ(P(x)log(P(X)))
\end{align}
```

## カルバック・ライブラー　ダイバージェンス (KLダイバージェンス)
元の情報$Q(x)$に対して、新たな情報$P(x)$を入手した時、新たな情報$P(x)$の目新しさを表す。

```math
\begin{align}
D_{KL}(P||Q) &= E_{x～P}　[log\frac{P(x)}{Q(x)}]\\ 
&= E_{x～P}　[logP(x) - logQ(x)]
\end{align}
```

## 交差エントロピー
Qについて、自己情報量をPの分布で平均化したもの

```math

\begin{align}
H(P,Q) &= H(P) + D_{KL}(P||Q)　\\
&= -E_{x～P}　logQ(x)
\end{align}

```
EC2のインスタンスに、爆速で3.7系のPython3を入れる

ひたすら打っていきましょう

## gitのインストール

```
sudo yum install git -y
```

## pyenvのインストール
```
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
```
pyenvの環境変数など設定

```
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
```

## ライブラリのインストール

```
sudo yum install gcc zlib-devel bzip2 bzip2-devel readline readline-devel sqlite sqlite-devel openssl openssl-devel libffi-devel -y
```

## python3.7.3をインストール

```
pyenv install 3.7.3
```

## pyenvでpython3を使用するように変更

```
pyenv global 3.7.3
```
laravel5.7 で バルクインサート

普通のバルクインサートはググりゃ出てくる。

しかし、今回は

- すでにそのIDのデータがあれば、アップデート
- 無けりゃ新規保存

をする。

今回は
https://github.com/yadakhov/insert-on-duplicate-key
を利用。

#composer で インスコ

```

composer require yadakhov/insert-on-duplicate-key

```

#適当なモデル

```

use Illuminate\Database\Eloquent\Model;
use Yadakhov\InsertOnDuplicateKey;

class Fortunerand extends Model
{

    use InsertOnDuplicateKey;

}


```

#適当なコントローラー

ここで新規保存したい場合は null を入れておくのが味噌。
''では動かない。
またフィールド数はわせておく。


```

//use App\Fortunerand;
$data =
[
    [
        'id' => 7,
        'text' => 'ゆめ'
    ],
    [
        'id' => 8,
        'text' => 'じろう'
    ],
    [
        'id' => null,
        'text' => 'はなこ'
    ],
];

Fortunerand::insertOnDuplicateKey($data);

```

あるものはアップデート、
無いものは新規保存になった。

# updated_at の時間も伸ばしたい

```

$now =  Carbon::now();

$data = [
[
    'id' => 7,
    'text' => 'bvv',
    'updated_at' => $now
],
[
    'id' => 8,
    'text' => 'じろう',
    'updated_at' => $now
],
[
    'id' => null,
    'text' => 'はなこ',
    'updated_at' => $now
],
];

Fortunerand::insertOnDuplicateKey($data);

```

これで updated_at にも対応。
NestJSでWebpackのHot reloadをやろうと思ったらはまった件について

アプリケーションの開発を続けていると、ビルド、実行を手動でやるのが面倒になってきました。
[NestJS公式](https://docs.nestjs.com/)を見ていると、TECHNIQUESのところに [Hot Reload (Webpack)](https://docs.nestjs.com/techniques/hot-reload) の記事を見つけました。

これを見ると、面倒だと思っていたソース修正、ビルド、実行(再起動)を自動でやってくれると言うことなので、早速、ドキュメント見ながらやってみました。

# エラー発生
ドキュメント通りにやってみましたが、起動すると以下のエラーが出ます。

```file
ERROR in multi webpack/hot/poll ./src/server/main.ts
Module not found: Error: Can't resolve 'webpack/hot/poll' in 'C:\Users\xxx\Source\xxx-api'
 @ multi webpack/hot/poll ./src/server/main.ts server[0]
```

# 原因
Webを調べて見てもこれと言って原因らしきものが見つかりません。
node_modulesには、webpack/hot/pollはあるし、うーん、うーん。

半日戦ってやっと解決。
webpack.config.jsのresolveに「.js」が抜けてました。Typescriptで開発しているので、.jsは必要無いよねと削除してました。
webpack/hot/pollが。.jsなので必要になるのね。

```javascript:webpack.config.js
    resolve: {
        extensions: [
            '.ts',
            '.js'
        ]
    },
```

たった3文字に泣かされました。
お前の目はふしあなか!というネタでした。
Leetcode #125: Valid Palindrome

 
```swift
func isPalindrome(_ s: String) -> Bool {
    var strArr = Array(s.lowercased().filter {($0 <= "z" && $0 >= "a") || ($0 <= "9" && $0 >= "0")})
    var left = 0
    var right = strArr.count - 1
    while left < right {
        if strArr[left] != strArr[right] {
            return false
        }
        left += 1
        right -= 1
    }
    return true
}
```
Record of the study(Ruby3)

Rubyでデータを取り扱うために基礎
**・オブジェクト**
**・クラス**
**・変数**
**・定数**

##オブジェクト
Rubyで使う全ての値(データ) の基本単位が**オブジェクト(物)**

オブジェクトには多くの種類が存在し、メインなのもとして
**-文字列オブジェクト**(`“hello world”、”おはよう”`などの文字)
**-数値オブジェクト**(`1,2,3、3,14` などの数値)
**-配列・ハッシュオブジェクト** 
( 複数のデータをまとめる `pref = [“鹿児島”,”熊本”,”福岡”]、` `person = {name: “fushi”, age: 33}` )

などがある。
※オブジェクトの事をインスタンスと呼ぶ場合もあるが同じ意味

##クラス
オブジェクト(物)の種類を表すもの。オブジェクトがどのような性質(メソッド)を使うかは属するクラスによって決まる。
`-文字列オブジェクト`→**Stringクラス**
`-数値オブジェクト`→**Integerクラス**
`-配列オブジェクト`→**Arrayクラス**
`-ハッシュオブジェクト`→**Hashクラス**
など

##変数
オブジェクト(物)につけるラベルのようなもので、`ラベルをつける事でコードで使用する値を格納したり,変更したりする事`ができる便利なもの。

Rubyには**ローカル変数**,**グローバル変数**、**インスタンス変数**、**クラス変数**などある。
それぞれの違いは`変数名と使える範囲(スコープ)`が異なる

**ローカル変数**
変数名  `アルファベット小文字or『_ 』で始める`
スコープ範囲→ **定義されたメソッドのみ、一番スコープ範囲が狭い変数**

**グローバル変数**
変数名 `『$』で始める`
スコープ範囲→**プロジェクト内の全てが範囲**

**インスタンス変数**
変数名 `『@』で始める`
スコープ範囲→**インスタンス内の全てが範囲**

**クラス変数**
変数名　`『@@』で始める`
スコープ範囲→**クラス内の全てが範囲**

##定数
変数同様にオブジェクトにつけるラベルとなるが、変数の様に何度も代入を繰り返す事が出来ない。変更しない値につけるラベル
変数名　`アルファベット大文字で始める`

**※Rubyにおける定数は変更（書き換えが可能）ができてしまう（警告がでるが…）**
書き換えを制限するには`Module（モジュール）`内に**定数**を定義して、**freezeメソッド**`(オブジェクトを凍結し変更不可にするメソッド)`で定数とModuleをfreezeメソッドで凍結する必要がある
[Windows]ファイル検索で*と?以外のワイルドカード

Windowsのワイルドカードでは、 `*`と`?`がよく知られているが、それ以外にも存在することを知ったのでメモ。

## tl;dr

- `>`: 名前部分のみの任意の1文字に一致する
- `<`: 名前部分のみの任意の文字列に一致する

## 詳細

[FindFirstFile](https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfilew)や[FindFirstFileEx](https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfileexw)の説明には記載されていないが、[ファイル名に使用できない文字](https://docs.microsoft.com/en-us/windows/desktop/msi/filename)を特別なパターンに割り当てているようだ。
シェル(コマンドプロンプト)で使用する文字と被っているので、APIを直接呼び出すアプリケーションからしか使用できない。

stackoverflow.comでは[こちら](https://stackoverflow.com/questions/24190389/findfirstfile-undocumented-wildcard-or-bug)が詳しい。

[FsRtlIsNameInExpression routine](https://msdn.microsoft.com/en-us/library/windows/hardware/ff546850%28v=vs.85%29.aspx)

|Wildcard character|Meaning |
| --- | --- |
|DOS_DOT(L'"')|Matches either a period or zero characters beyond the name string.<br/>名前文字列を超えたピリオドまたはゼロ文字のいずれかと一致します。|
|DOS_QM(L'>') |Matches any single character or, upon encountering a period or end of name string, advances the expression to the end of the set of contiguous DOS_QMs.<br/>任意の1文字に一致するか、ピリオドまたは名前文字列の終わりに遭遇すると、式を連続したDOS_QMのセットの終わりに進めます。|
|DOS_STAR(L'<')|Matches zero or more characters until encountering and matching the final . in the name.<br/>名前の最後の.に遭遇して一致するまで、0個以上の文字と一致します。|

`DOS_DOT` はなぜ必要なのかはわからない。

## パターン例

| ファイル名 | s*    |
| ---------- | ----- |
| s0         | Match |
| s0.txt     | Match |
| sample     | Match |
| sample.txt | Match |

| ファイル名 | s<      |
| ---------- | ------- |
| s0         | Match |
| s0.txt     | Unmatch |
| sample     | Match |
| sample.txt | Unmatch |

| ファイル名 | s*.txt  |
| ---------- | ------- |
| s0         | Unmatch |
| s0.txt     | Match |
| sample     | Unmatch |
| sample.txt | Match |

| ファイル名 | s<.txt  |
| ---------- | ------- |
| s0         | Unmatch |
| s0.txt     | Match |
| sample     | Unmatch |
| sample.txt | Match |

## コード

```c
#include <stdio.h>
#include <Windows.h>

void listup(LPCWSTR lpFileName)
{
	WIN32_FIND_DATA find_data;
	HANDLE h = FindFirstFile(lpFileName, &find_data);
	wprintf(L"searching...[%s]\n", lpFileName);

	if (h == INVALID_HANDLE_VALUE)
	{
		wprintf(L"not found.\n");
		return;
	}
	do
	{
		wprintf(L" found.[%s]\n", find_data.cFileName);
	} while (FindNextFile(h, &find_data));
	FindClose(h);
}

int main()
{
	listup(L"s*");
	listup(L"s*.txt");
	listup(L"s<");
	listup(L"s<.txt");
}
```
Leetcode #123: Best Time to Buy and Sell Stock III


```swift
func maxProfit(_ prices: [Int]) -> Int {
    if prices.count <= 1 {
        return 0
    }
    var maxProfitSoldAtIndex = Array(repeating: 0, count: prices.count)
    var maxProfitFromIndex = Array(repeating: 0, count: prices.count)
    var minPrice = prices[0]
    for i in 1..<prices.count {
        maxProfitSoldAtIndex[i] = max(prices[i]-minPrice,0)
        minPrice = min(minPrice, prices[i])
    }
    var maxPrice = prices.last!
    for i in 1..<prices.count-2 {
        let j = prices.count - i - 1
        maxProfitFromIndex[j] = max(maxPrice - prices[j], maxProfitFromIndex[j+1])
        maxPrice = max(maxPrice, prices[j])
    }
    var maxProfit = maxProfitSoldAtIndex.last!
    for i in 1..<prices.count-1 {
        maxProfit = max(maxProfit, maxProfitSoldAtIndex[i] + maxProfitFromIndex[i+1])
    }
    return maxProfit
}
```
エクセルマクロ(Excel VBA)で積分（台形則）を行う

#エクセルマクロ(Excel VBA)で積分（台形則）を行う
## はじめに
エクセルで積分を行う必要があったので、マクロを作成しました。
範囲を指定するだけで簡単に面積を求めることができます。
実験で測定した値をエクセルで分析する際に、素早く積分するために作成しました。
積分は台形則で行っていますが、シンプソン則等他のアルゴリズムに拡張することも可能なように作成しています。

## 関数の仕様
関数名：Area(範囲x, 範囲y)
引数：
範囲x: データの範囲(X)
範囲y: データの範囲(Y)

## ソース
```visualbasic:数値積分.bas
Option Explicit

Function Area(範囲x As Range, 範囲y As Range) As Variant

    ' yとxのデータは同じ個数であることが前提
    If 範囲x.Count <> 範囲y.Count Then
        ' xとyでデータ個数が異なる場合はN/Aを返す
        Area = CVErr(xlErrNA)
        Exit Function
    End If

    ' 生データの個数を代入
    Dim DataNum As Long
    DataNum = 範囲y.Count

    ' ループ関数を定義
    Dim i As Long
    Dim j As Long

    ' Rangeデータを配列に保存
    Dim Xdatas() As Double
    ReDim Xdatas(範囲x.Count)
    Dim Ydatas() As Double
    ReDim Ydatas(範囲y.Count)
    For i = 1 To 範囲x.Count
        Xdatas(i) = 範囲x(i)
        Ydatas(i) = 範囲y(i)
    Next

    ' ソートを行う
    Dim BufDouble As Double
    For i = 1 To UBound(Xdatas)
        For j = 1 To UBound(Xdatas)
            If Xdatas(i) < Xdatas(j) Then
                BufDouble = Xdatas(i)
                Xdatas(i) = Xdatas(j)
                Xdatas(j) = BufDouble

                BufDouble = Ydatas(i)
                Ydatas(i) = Ydatas(j)
                Ydatas(j) = BufDouble
            End If
        Next
    Next
    
    ' 積分を行う
    i = 1
    Area = 0#
    While i < 範囲x.Count
        Area = Area + (Xdatas(i) + Xdatas(i + 1)) * (Ydatas(i + 1) - Ydatas(i)) / 2
    i = i + 1
    Wend
   
End Function
```
クロムブックで Linux を使う

クロムブックで　Linux を使いました。

インストール

設定 -> デベロッパー
>![chrome_jun0201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/b7fa3763-4402-133a-eddb-406b38252c9f.png)

>![chrome_jun0202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/f3d38d26-bc34-6831-ab41-785bb42da76b.png)


OS　のバージョンは次の通りでした。

```text
バージョン: 93.0.4522.0（Official Build）canary （64 ビット）
```

ターミナルを起動した様子です。
![linux_aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/1de24445-691b-3ef9-5656-e4002dbfeb8d.png)

インストールされていたバージョンです。
![Screenshot 2021-06-01 11.30.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/d94c6aef-de72-e03c-dd68-9996ea1d5d86.png)


```text
$ uname -a
Linux penguin 5.4.121-14987-gc13c5558aaab #1 SMP PREEMPT Wed May 26 08:20:13 PDT 2021 x86_64 GNU/Linux

$ cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

$ python3 --version
Python 3.7.3

$ bash --version
GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
```

ssh で vps の　Arch Linux と Ubuntu 19.04 にアクセスしているところです。
![Screenshot 2019-04-30 at 11.15.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/a5f2c489-702b-a6ae-7f41-fc5b440a2f78.png)
UniDicをPythonで使おうとして詰まった話

PythonでUniDicを使おうとして、かなり詰まったので備忘録も兼ねて記録
なお、Python3環境かつ、すでにMeCabを導入している前提で話を進めます。

## mecab-python3の導入
pipを使ってmecab-python3を導入

```term
pip install mecab-python3 
```

筆者の環境ではpyenvを使ってインストールしているので`--user`オプション付けずにインストールしていますが、環境に合わせてオプションを付けてください。
導入後にpythonを起動し、次のコマンドを入力して導入できているか確認してください。

```python
import MeCab
```

何かエラーコードを吐かなければ導入成功です。

## UniDicのダウンロード
次のリンクからUniDicをダウンロードできます。
[「UniDic」国語研短単位自動解析用辞書](https://unidic.ninjal.ac.jp/)
ダウンロードする辞書はお好きなものを選択してください。  

UniDicとは国語研が公開している形態素解析用(実際は短単位)辞書です。
公開している辞書の種類はかなり豊富で、現代書き言葉と話し言葉に加えて近代文語など旧仮名表記にも対応した辞書も公開されており、MeCabでの運用が可能です。

閑話休題。

ダウンロード後は好きなフォルダに解凍しておいてください。

## UniDicをpythonで使う
UniDicをpythonで使うには、通常のMeCabにおいて外部辞書を使用する方法とあまり変わりません。

```python
import MeCab

m = MeCab.Tagger('-d path/to/UniDic') # MeCabのオプション指定と同じ
```

後は好きなように解析するだけ。

```python
s = "ほげほげ"
result = m.parse(s)
print(result)
```

結果はこんな感じ

```
ほげ	感動詞,一般,*,*,*,*,ホゲ,ほげ,ほげ,ホゲ,ホゲ,和,ほげ,ホゲ,ホゲ,ホゲ,*,*,*,*,*,*,2,*,*
ほげ	感動詞,一般,*,*,*,*,ホゲ,ほげ,ほげ,ホゲ,ホゲ,和,ほげ,ホゲ,ホゲ,ホゲ,*,*,*,*,*,*,2,*,*
EOS

```

## テキストファイルから読み込んで使う
テキストファイルから読み込むことで、大量の文書に対して解析することが可能です。

```python
import MeCab

m = MeCab.Tagger('-d path/to/UniDic')

with open('hogehoge.txt') as t:
  result = m.parse(t.read())
  
print(result)
```

結果は次の様に

```

```

? 
何も表示されない?

## トラブル発生
python上でテキストファイルを読み込んで形態素解析をすると、何故か結果が表示されません。  
筆者の環境で試した範囲ですが、今のところ分かっていることは次の通りです。

- string型変数を解析するには問題なし
- 端末から直接UniDicを指定しMeCabを起動して、入力文字を解析しても問題なし
- 同様に、txtファイルを読み込ませても問題なし
- pythonで`read()`を使って解析しようとすると結果が返ってこない
  - エラーは吐かない
- 短文なら`read()`から読み込ませてもエラーが出ない

~~原因は執筆時点でも不明で、`read()`の結果を`parse()`に受け渡し、解析するまでは問題ないようなのでMeCab側からの受け渡しに何か問題がある可能性が一番尤もっぽく感じます。~~
原因がわかりました。恐らくですが、**一行に連結した長い文章を渡すと返すのに失敗するみたいです。**
しかし、直接的な原因は不明なままで、デフォルト辞書ではこのような現象には遭遇したことがありません。 とはいえ、解決しないことには色々不都合しかないので、以下に解決策を載せます。

## 解決策
次のものを用意してください。

- 使いたいUniDic辞書
- UniDic現代書き言葉辞書

もし、現代書き言葉辞書を使う場合は、それだけで問題ないです。

まず、最初にダウンロードしてきた現代書き言葉辞書のフォルダに含まれている`dicrc`で使用したい辞書の`dicrc`を上書きします。(このとき元のdicrcのバックアップを取るようにしてください)
上書きした`dicrc`を開いて`output-format-type`と書かれている行に対し、次の様に書き換えてください。

```
;output-format-type=unidic22
```

これで`read()`を使ってもちゃんと結果が返ってくるようになります。
先程のコードを実行すると

```term
ほげ	感動詞,一般,*,*,*,*,ホゲ,ほげ,ほげ,ホゲ,ホゲ,和,ほげ,ホゲ,ホゲ,ホゲ,*,*,*,*,*,*,2,*,*
ほげ	感動詞,一般,*,*,*,*,ホゲ,ほげ,ほげ,ホゲ,ホゲ,和,ほげ,ホゲ,ホゲ,ホゲ,*,*,*,*,*,*,2,*,*
あれ	動詞,非自立可能,*,*,文語ラ行変格,已然形-一般,アル,有る,あれ,アレ,アレ,和,あり,アリ,アリ,アリ,*,*,*,*,*,*,1,C3,*
これ	代名詞,*,*,*,*,*,コレ,此れ,これ,コレ,コレ,和,これ,コレ,コレ,コレ,*,*,*,*,*,*,0,*,*
EOS

```

といった感じに結果が返ってきます。

## 終わりに
これでUniDicを使った大量の形態素解析が出来るようになりました。
とはいえ、結局表示されない原因が突き止められませんでした。
何か原因がわかる方、情報をいただけると幸いです。
【Ruby】配列の中のハッシュの中から、キーワード検索する

##　配列の中のハッシュから値を取得する方法
こんな感じの配列から値を取得したい時ありますよね

```test1.rb
team = [{number:"2", name:"小田"},
{number:"4", name:"小池"},
{number:"11", name:"佐々木"}]
```

下記のようにキーワード検索をする動きを作成します。

```test2.rb

keyword = "2"

result = team.select { |x| x[:number].include?(keyword) || x[:name].include?(keyword) }

p result
#=> [{:number=>"2", :name=>"小田"}]
```
[include?](https://ref.xaio.jp/ruby/classes/string/include)を使って部分一致（部分文字列として含まれる）を調べています。
戻り値は`[{}]`になっていますね。
ハッシュのみで値を取得したいときは、`find`を使います。

```test3.rb
result = team.find { |x| x[:number].include?(keyword) || x[:name].include?(keyword) }

p result
#=> {:number=>"2", :name=>"小田"}
```

ただ`find`では複数の値を取る事ができません。最初の値のみ戻り値として返します。
全ての値を取得したいときは`find_all`とすれば、全ての値を取得できます。
`select` と同じ機能をするが `find_all `です。

```test４.rb
team = [{number:"2", name:"小田"},
{number:"4", name:"小池"},
{number:"11", name:"佐々木"},
{number:"2", name:"小"},
{number:"4", name:"池"},
{number:"11", name:"木"}]

result = team.find_all { |x| x[:number].include?(keyword) || x[:name].include?(keyword) }

p result
#=> [{:number=>"2", :name=>"小田"}, {:number=>"2", :name=>"小"}]
```

[正規表現](https://docs.ruby-lang.org/ja/latest/doc/spec=2fregexp.html)で検索する方法もあります。
EclipseでSpringBootのGradleアプリをデバックする方法

### EclipseでGradleをデバックするときの手順
・　Mavenと違って２段階の実行が必要っぽい？

#### 手順１：
画面の上にある再生ボタンから[実行の構成] -> [Gradleプロジェクト] を開き
Gradleタスクに［bootRun --debug-jvm］と入力する

画面例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/ea5b0f3a-b13b-fdf5-9fc0-0cefdc678bb1.png)

#### 手順２：
設定した内容を実行すると、コンソール画面が途中で止まる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/86b54f96-cb24-074d-fef4-870bf6d2e0f0.png)

#### 手順3：
画面の上にある虫のデバックボタンから[実行の構成] -> [リモート Java アプリケーション] を開き
ポート番号に上のコンソール画面で割り振られた番号を入力する　画面例） 5005

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/efbf2cdd-dc8c-f3d3-90dc-8b36efb4169b.png)

#### 手順4：
設定した内容でデバックすると、SpringBootが動き出し、ブレイクポイントで止めたいとこに止まる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/41c021fd-6c96-e781-b3b9-1b510c11ea42.png)
ロリポップからさくらレンタルサーバーに移行する

# 背景
## ロリポップがひどい

- 迷惑メールがめちゃくちゃ来る
- ロリポップのSMTPサーバーが迷惑メールサーバーとしてマークされがち(送信したメールが迷惑メール判定される)

つらいのでさくらレンタルサーバーに移行することにした

## メールアドレスのエクスポート&インポート

クローラー作った
https://gist.github.com/katsusuke/22e30c14502bc497f408460712965461

なんかもうちょっといい方法がある気がするが
macOSでコンパイルエラー: unknown typeとかno memberとかが大量に出たらやること

macOSでのコンパイルにおいて、ユーザー定義の型識別子に関して大量のエラーが発生した場合の、対処方法を記載しておきます。英文サイトに事象と解決策はいくつか掲載されているのですが、どれもはっきりとした書き方はされていません。私がハマって解決した例として参考にしてください。

#1. エラーの例

明示的にmakeやcmakeでコンパイルした場合、brew installでパッケージが見つからなくてソースコンパイルが行われた場合などに、以下のエラーがでます。

```
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdint:158:8: error: no member named 'uint8_t' in the global namespace using::uint8_t;

（同様なものが大量に出ます）
（error: unknown type name 'uint8_t' とかの場合もあります）

fatal error: too many errors emitted, stopping now [-ferror-limit=]
```

#2. 原因

macOSをアップグレードした際に、古いヘッダファイルが残存してしまうためのようてす。私の場合は、High SierraからMojaveにアップグレードしていました。

#3. 対処

/usr/local/includeを強制的に切り替えます。この中はヘッダファイルだけしかありませんので、macOSの動作そのものには影響を与えませんので、ご安心ください。

```
$ sudo mv /usr/local/include /usr/local/include.org
```

削除する、という荒っぽい解決策もいくつかみられましたが、戻せるようにリネームしておきます。

たたし、これだけだと、コンパイルは通りません。コンパイル時に/usr/local/include/なんとか、が無いと怒られます。homebrewを最初からインストールしなおしして、さらにコンパイル時に無いと怒られる「なんとか」に関係するパッケージ（しかしbrewではあると言われる）について、brew uninstallして、brew installしなおすことを繰り返します。これによって、新しい /usr/local/inbclude （中身はシンボリックリンクだけですが）が作られ、コンパイル可能になります。
WordPress投稿者情報を取得するコード

WordPressでユーザー情報を取得する場合のコードです。
記事投稿者の表示などに使えます。

##投稿者名 を表示

```php:php
<?php the_author_meta('display_name'); ?>//ブログ上の表示名
<?php the_author_meta('user_nicename'); ?> //ニックネーム
```

##投稿者 プロフィール写真 を表示

```php:php
<?php echo get_avatar( get_the_author_id(), 300 ); ?>
```

##投稿者 プロフィール情報 を表示

```php:php
<?php the_author_meta('user_description'); ?>
```

##投稿者 メールアドレス を表示

```php:php
<?php the_author_meta('user_email'); ?>
```

##投稿者 サイトURL を表示

```php:php
<?php the_author_meta('user_url'); ?>
```

#表示確認コード

表示確認に使えるコードセットです。コピペでご使用ください。

````
<div class="p-author">
<figure class="p-author__figure"><?php echo get_avatar( get_the_author_id(), 300 ); ?></figure>
<div class="p-author__name"><?php the_author_meta('display_name'); ?></div>
<p class="p-author__description"><?php the_author_meta('user_description'); ?></p>
<div class="p-author__email"><?php the_author_meta('user_email'); ?></div>
<div class="p-author__email"><a href="<?php the_author_meta('user_url'); ?>" target="_blank"><?php the_author_meta('user_url'); ?></a></div>
</div>
```
swift4.0でランダムに取得した値の重複をなくす

#はじめに

randomで値を取ってきても、重複して困るってこと結構ありませんか？

#なんのために必要か？

自分はテニスが好きで、スクールに通ったり、地域のテニスイベントに参加したりしている。スクールはさておき、テニスイベントでは最後に参加者をランダムで<a href="https://ja.wikipedia.org/wiki/%E3%83%80%E3%83%96%E3%83%AB%E3%82%B9"target="_brank">ダブルス</a>の試合をするのだが、参加者が多いと、ダブルスのペアを考えるのが大変😩

そこで、手軽に持ち運びのできるiPhoneでそういったアプリを乱数を使って作れば、かなり需要があるんじゃねと思い作り始めました。

#ぶつかった壁
乱数を取ってペアを作ること自体は簡単でした。
実際、このようなソースでランダムに4人取ることができます。

```swift
func makeDouble(Num:Int) {
        var intArray: [Int]
        intArray = []
        var intset: [Int]
        intset = []
        
        if Num < 4 {
            displayAlert()
        }else{
            intArray = []
            for i in 1...Num{
                intArray.append(i)
            }
            //
            for _ in 0..<4{
                let j = Int(arc4random_uniform(UInt32(intArray.count)))
                intset.append(intArray[j])

            }
        }
    }
```

これだとどういった問題が出てくるのかと言うと、重複(同じ数が複数回出てきてしまう。)問題が発生するのだ。
実際、このソースで動かしてみると結果は以下のようになる

```
[4, 10, 9, 1]
[4, 6, 9, 8]
[6, 4, 10, 10]
[8, 9, 4, 10]
[1, 7, 3, 7]
[9, 6, 1, 1]
[9, 5, 8, 5]
[6, 4, 3, 6]
[3, 10, 2, 6]
[1, 10, 8, 1]
```

10人でシャッフルした場合は重複が少ないように見えるが、これが５人だった場合には

```
[2, 3, 5, 1]
[2, 4, 4, 3]
[2, 3, 5, 2]
[2, 5, 1, 4]
[5, 2, 5, 1]
[1, 3, 4, 3]
[3, 3, 4, 5]
[5, 2, 3, 5]
[4, 5, 1, 2]
[4, 2, 5, 2]
```

とかなりの確率で重複した値が出てきてしまう。

#じゃあどうするか？
巷では、重複をチェックするのに２重ループを回して重複の有無をチェックするやり方が
ちらほらと見受けられるが、もっとスマートにやりたい。

と色々試行錯誤してある方法を思いついた。

配列に値を入れてそこからランダムに値を入れて、それを配列から削除すれば、重複なくなるんじゃねと

実際に書いたソースがこちら

```swift
func makeDouble(Num:Int) {
        var intArray: [Int]
        intArray = []
        var intset: [Int]
        intset = []
        
        if Num < 4 {
            displayAlert()
        }else{
            intArray = []
            for i in 1...Num{
                intArray.append(i)
            }
            //
            for _ in 0..<4{
                let j = Int(arc4random_uniform(UInt32(intArray.count)))
                intset.append(intArray[j])
                intArray.remove(at: j)
            }
        }
    }
```

実際に重複した値が出てこないかチェックする。
先ほどと同じく５人、１０人でチェックする（試行回数は10回)

```
[8, 7, 2, 10]
[5, 3, 10, 9]
[10, 4, 5, 1]
[1, 8, 4, 3]
[10, 4, 2, 7]
[6, 8, 2, 3]
[10, 6, 8, 2]
[3, 10, 7, 8]
[1, 9, 3, 7]
[8, 7, 4, 2]
```

```
[5, 1, 4, 3]
[2, 1, 3, 4]
[2, 5, 3, 4]
[1, 5, 3, 2]
[1, 2, 5, 3]
[2, 1, 5, 4]
[3, 5, 4, 1]
[1, 4, 3, 2]
[5, 4, 1, 2]
[4, 3, 5, 1]
```

これで重複は無くなった。（数字に偏りはあるが😅)

今回作ったアプリはこちらで公開してます。
https://github.com/tnatsume/ShuffleDoubles
Rfc2898DeriveBytes と OpenSSL PBKDF2 で相互運用できることを確認した

# Rfc2898DeriveBytes と OpenSSL PBKDF2 で相互運用できることを確認した

RFC の規格で相互運用できなかったら詐欺じゃーんの世界だけど、念のため.

```csharp
Microsoft (R) Roslyn C# Compiler version 2.10.0.0
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> using System.Security.Cryptography;
> new Rfc2898DeriveBytes("pass", Encoding.ASCII.GetBytes("saltsalt"), 1000).GetBytes(20)
byte[20] { 100, 56, 132, 29, 150, 178, 121, 214, 208, 80, 62, 64, 40, 83, 211, 156, 131, 69, 34, 128 }
```

```ruby
$ irb
irb(main):001:0> require 'openssl'
=> true
irb(main):002:0> OpenSSL::PKCS5.pbkdf2_hmac("pass", "saltsalt", 1000, 20, "sha1").unpack("C*")
=> [100, 56, 132, 29, 150, 178, 121, 214, 208, 80, 62, 64, 40, 83, 211, 156, 131, 69, 34, 128]
```

おっけー.

一応注意事項はあって、

```csharp
> new Rfc2898DeriveBytes("pass", Encoding.ASCII.GetBytes("salt"), 1000).GetBytes(20)
Salt is not at least eight bytes.
  + System.Security.Cryptography.Rfc2898DeriveBytes.set_Salt(byte[])
  + System.Security.Cryptography.Rfc2898DeriveBytes..ctor(byte[], byte[], int, System.Security.Cryptography.HashAlgorithmName)
  + System.Security.Cryptography.Rfc2898DeriveBytes..ctor(string, byte[], int)
```

```ruby
irb(main):003:0> OpenSSL::PKCS5.pbkdf2_hmac("pass", "salt", 1000, 20, "sha1").unpack("C*")
=> [59, 207, 44, 177, 178, 30, 14, 32, 48, 209, 13, 36, 152, 42, 10, 175, 56, 141, 117, 36]
```

Rfc2898DeriveBytes は規格に則って8バイト未満の salt を弾くけど、OpenSSL は気にせず計算する.
PureScriptでAjaxするときはRemoteDataも使おう

# 前書き

[`purescript-affjax`](https://pursuit.purescript.org/packages/purescript-affjax) はajaxする際のデファクトスタンダードと言って良いと思います。
通信が成功したか失敗したかは`Either`で受け取ることができますが、実際には`Either`や`Maybe`を直に取り扱うのは辛いです。

動機付けとして、Halogenのexamplesにaffjaxを使う例( [effects-aff-ajax](https://github.com/slamdata/purescript-halogen/tree/master/examples/effects-aff-ajax) )があるので見てみます。以下のように`Maybe`でモデル化されています。

```hs
-- PureScript
type State =
  { loading :: Boolean
  , result :: Maybe String
  }
```

HalogenとAffjaxを連携させる例としては十分ですが、実際には扱いづらいです。

## RemoteData

Elmのチュートリアル( [HTTP](https://guide.elm-lang.org/effects/http.html) )では以下のようにモデルを設計しています。

```elm
-- Elm
type Model
  = Failure
  | Loading
  | Success String
```

`Maybe`と上記モデルを改めて比べてみると、前者は`Failure`と`Loading`という区別されるべき2つの状態を全て`Nothing`として忘却してしまうので扱いづらくなってしまっていることがよく分かります。

`Maybe`を利用した設計の問題点は [How Elm Slays a UI Antipattern](http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html) でも説明されています。
そして、同記事で紹介されているのが`RemoteData`と名付けられたカスタム型です。

```elm
-- Elm
type RemoteData e a
    = NotAsked
    | Loading
    | Failure e
    | Success a
```

# 使ってみる

PureScriptへの移植版である[`purescript-remotedata`](https://pursuit.purescript.org/packages/purescript-remotedata) パッケージがあるのでそれを使います。
もし独自で実装する際は、Elmとは異なり`data`を使います。

```hs
--purescript
data RemoteData e a
  = NotAsked
  | Loading
  | Failure e
  | Success a
```

以下は良く使いそうな関数の例です。

```hs
fromEither :: forall e a. Either e a     -> RemoteData e a
isLoading  :: forall e a. RemoteData e a -> Boolean
```

今回は以下のようにインポートして使います。

```hs
import Network.RemoteData (RemoteData(..))
import Network.RemoteData (fromEither, isLoading) as RemoteData
```

`RemoteData`を使うと冒頭のモデルは以下のように書けます。

```hs
-- PureScript
type State = { request :: RemoteData AX.ResponseFormatError String }
```

実際にアクションと結びつけると以下のようになるかと思います。

```hs
handleAction ActionName = do
  response <- H.liftAff $ AX.get AX.ResponseFormat.string ("URL")
  H.modify_ $ _ { request = RemoteData.fromEither response.body }
```

## Submitボタンを作る

```hs
submitButton
  :: forall e a m
   . RemoteData e a
  -> String
  -> H.ComponentHTML Action () m
submitButton remote text = HH.button
  [ HP.disabled $ RemoteData.isLoading remote
  , HP.type_ HP.ButtonSubmit
  ]
  [ HH.text text ]
```

ロード中はdisabledをtrueにするという処理が簡単に書けます。

## UIのパターンマッチング

```hs
view :: forall e m. RemoteData e String -> H.ComponentHTML Action () m
view remote = HH.div_
  case remote of
    NotAsked ->
      [ HH.p_ [HH.text "Enter username and click button"]]
    Loading ->
      [ HH.p_ [HH.text "Working..."] ]
    Failure _ ->
      [ HH.p_ [HH.text "Failed for some reasons. Please try again!"]]
    Success res ->
      [ HH.h2_
          [ HH.text "Response:" ]
      , HH.pre_
          [ HH.code_ [ HH.text res ] ]
      ]
```

パターンマッチングでコードが読みやすいです。

# 結論

AffjaxとRemoteDataはセットで使おう！
画像のアップロード先をS3にしてハマった

自分用メモです。

# 環境
* ruby 2.3.1
* Rails 5.0.7.2
* unicorn
* nginx
* fog-aws(gem)
* carrierwave(gem)
* mini_magick(gem)
* Capistrano(gem)
* EC2
* S3

# what
* ローカル環境から、本番環境(AWS)へデプロイ。
* その後、画像をs3へアップロードできるようにする。
* 画像をアップロードしてもエラーとなる。
* が、ローカル環境だとs3へアップロードできる

# Why
* ローカル環境で、s3へアップロードできているので、設定の問題ではないだろう
* s３導入前からハマってた??
* ローカル環境から、本番環境(AWS)へデプロイした後、画像投稿できるか確認していないので、そこらへんの問題？？
* 「ImageMagick」ががインストールされていない？？

# やったこと
1. 「ImageMagick」のインストール
2. 一応、EC2 インスタンス再起動

## 1. 「ImageMagick」のインストール
サーバで、「ImageMagick」がインストールされているかの確認コマンドがわからないので、
といあえず、インストールしてみる

```terminal:terminal（サーバ）
sudo yum install ImageMagick
```

おっと！？普通にイントールできた。
これは？？

## 2. 一応、EC2 インスタンス再起動
### EC2 インスタンス再起動
インスタンス（サイドバー）→アクション→インスタンスの状態→再起動

インスタンス再起動すると、```mysql``` ```unicorn``` ```nginx```が止まるので、起動させていく。

### mysqlの起動
```terminal:terminal（サーバ）
sudo service mysqld start
```

### 自動デプロイ（自動デプロイで```unicorn```再起動される）
```terminal:ローカル（自動デプロイするアプリ）
bundle exec cap production deploy
```

### nginxの起動
```terminal:terminal（サーバ）
sudo service nginx start
```

できた！
S3絡みで色々試したけど、おそらく最初デプロイした時からこうなっていたんだろう。。。

３日無駄にした。。。
ポーカー(6-plus hold'em)のハンドの強さ判定

#6-plus hold'em
6+ Hold’em is a popular 'short deck' poker format that plays much like Texas Hold’em, but with a few differences:
All cards lower than a six are removed from the deck.
A flush beats a full-house and Ace, 6, 7, 8, 9 is classified as a straight.

今回はこのルールにおける5枚のハンドの役の強さを高速で判定することを考えます。

#役判定プログラム
5枚のカードの組み合わせはn=36, k=5として以下の式より`376992`通りあります。

```math
\binom nk=\frac{n!}{k!(n-k)!}
```

すべての場合に対して役の強さを整数にして並び替えてみると、ハンドの強さとしてあり得る数値は`1404`通りでした。

ハンドの強さを最も強いものを`1403`、 最も弱いものを`0`として表すことにします。

すべてのカードの組み合わせに対して、与えられた5枚のハンドを1つのIDで表し、それぞれのIDに対応するハンドの強さ(`0-1403`)を辞書で与えます。

[ID_to_Strength.csv](https://github.com/Lily0727K/Poker/blob/master/ID_to_Strength.csv)

ハンドはソートした上で文字列として結合され、重複のないIDとして表されています。
この辞書には`376992`通りのすべてのハンドに対して、`0-1403`で表された役の強さが与えられています。
これで、任意の5枚に対してソートして文字列として辞書に入れることで、一瞬で役の強さを得ることができるようになりました。

7枚の役判定は、作れるすべての5枚の組み合わせに対して役を判定する必要がありますが、5枚の判定を高速化したことで7枚の場合の判定も比例して高速になっています。

[6plusholdem_dic.py](https://github.com/Lily0727K/Poker/blob/master/6plusholdem_dic.py)
bootrec /RebuildBcd 指定されたパスがみつかりません

![windowsトラブルシューティング画面.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316196/8defdcf6-09f8-be7d-ec85-08d1af3d2223.jpeg)

### レッツノートでセキュアブートを有効にして再起動かけたらWindowsが起動しなくなっちゃった
1時間前、犯人(自分)はこのように供述していた。しかし実際は
### Ubuntuのパーテーションを削除したらUbuntuのgrubごとWindowsのBCDまで消えてしまった
というのが原因だった。犯人の言うことを鵜呑みにしてはいけないという教訓の実例である[^1] トップ画像のようにWindows(のリカバリーディスク)は起動している。しかしスタートアップ修復が失敗するのである。

[^1]: 書いているうちに直前にWindows updateをかけていたことを思い出した。これによっても似たようなことが発生し得るらしいのでそれだったかもしれない。やはり犯人の言うことは(略

## 環境(大学生協PC)
- Let's note CF-SZ5
- Windows10 Pro

# 解決策
1.  BIOS画面に入る(Panasonic画面でF2)
1.  初期設定に戻す(F9)
1.  保存して再起動(F10)
1.  トップ画像のようなWindowsっぽい青画面が出てくるので「トラブルシューティング」->「コマンドプロンプト」と進む
2.  次のコマンドを打ち込む

```
bootrec /rebuildbcd
```

などといった情報がネットの海には漂っていた。しかしこれで直った人はこの記事にはたどり着かない。Cドライブは見つかって「インストールをブート一覧に追加しますか？」と言われたのに`Y`や`A`や`Yes`や`All`を入力しても「指定されたパスがみつかりません」と言われたからこの記事にたどり着いたのである。

というわけで，上記コマンドの代わりに以下のコマンドを実行するとよい。

```
bcdboot C:\Windows /l ja-jp
```
これにより日本語版WindowsのBCDファイルが作成される[^2]
[^2]: 英語版を使用している場合は`/l ja-jp`オプションを使わずに`bcdboot C:\Windows`のみで実行する
`exit`してコマンドプロンプトを抜けると、先程の画面に歯車の「続ける」と書かれたアイコンが加わるのでそれを押すと再起動されてWindowsが起動する

# まとめ
bootrecコマンドを使ってBCDファイルを作成すると直る

# 参考
- [知恵袋　BCDファイルの削除と作成について](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14191306289)
- [Microsoft BCDbootコマンド](https://msdn.microsoft.com/ja-jp/library/windows/hardware/dn898490(v=vs.85).aspx)
nextCloudとcloud9をdockerで導入し、NginXでリバースプロキシをかけてサブディレクトリで切り替える

拙作[nextCloudをdockerで導入し、NginXでリバースプロキシをかけてサブディレクトリで動かす
](https://qiita.com/hidao/items/4ac7114258dc6d04e157)と[cloud9をdockerで導入し、NginXでリバースプロキシをかけてサブディレクトリで動かす
](https://qiita.com/hidao/items/69f19994044bc8070d27)の合体技です。ほんとはこれがやりたかった！

## 概要
![2019-04-30 045124.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76242/a4e925b5-10b1-3136-3504-20819123ee50.jpeg)

## 前提

1. `docker`、`docker-compose`はインストールされているものとします。
2. 作業フォルダとファイル構成は以下ファイルツリーの通りです。
3. <a href="#docker-compose.yml">`docker-compose.yml`</a>、<a href="#nginx.conf">`config/nginx.conf`</a>は下記の通りあらかじめ用意しておきます。

```:ファイルツリー
workdir
│ └ docker-compose.yml
│
└─config
  └─ nginx.conf
```
<a href="#docker_compose.yml"></a>

```docker-compose.yml
version: '2'

volumes:
  nc:
  db:

services:
  nginx-proxy:
    container_name: nginx
    image: nginx
    prots:
      - 80:80
    volumes:
      - ./config/nginx.conf:/etc/nginx/conf.d/default.conf
    links:
      - c9:c9
      - nc:nc

c9:
  container_name: c9
  image: sshinya/alpine-cloud9
  environment:
    USERNAME: user # 任意のBASIC認証ユーザ名
    PASSWORD: pass # 任意のBASIC認証パスワード

nc:
  container_name: nc
  image: nextcloud

db:
  container_name: nc_db
  image: mariadb
  volumes:
    - db:/var/lib/mysql
  environment:
    - MYSQL_ROOT_PASSWORD=root   #
    - MYSQL_PASSWORD=root        # 左記のままでは防御力弱そうなので、
    - MYSQL_DATABASE=nextcloud   # ユーザ名とパスワードは変えましょう
    - MSYQL_USER=nextcloud       #
```
<a href="#nginx.conf"></a>

```nginx:config/nginx.conf
server {
  listen 80;
  server_name _;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  location /nc/ {
    rewrite /nc/(.*)$ /$1 break;
    proxy_pass http://nc;
  }

  location /core/ {
    proxy_pass http://nc$request_body;    
  }

  location /c9/ {
    rewrite /c9/(.*)$ /$1 break;
    proxy_pass http://c9:8080;
  }

  location ~ /(configs/|static/|vfs/|_ping)(.*)$ {  # _pingの後ろに'/'は無いよ！
    proxy_pass http://c9:8080$request_body;
  }
}
```

## コンテナの作成

```sh:手順1
cd workdir
sudo docker-compose up -d
```

`nginx`コンテナと`nc`(nextCloud)コンテナ、`nc9`(cloud9)コンテナ、`nc_db`(mariadb)コンテナが作成され、バックグラウンドで起動します。

## nextCloudサーバの設定

本来なら`docker-compose.yml`ファイルから設定できないとあまり意味がないのですが、今回は解決方法がわからなかったので手動で直しました。😅
きれいな解決方法でないので、うまいやり方がわかり次第、記事を更新します。

```sh:手順2
# 上記 docker-compose の続きとします
sudo docker exec -it nc /bin/bash
# 以下は nc コンテナの内部での作業です
apt update && apt install vim
cp config/config.sample.php config/config.php
vi config/config.php
```

```config.php
$CONFIG = array(
  ...
  // この中に値を追記する
  // ほかにも変数が登録されているけど、さわらない
'overwritehost' => '<物理サーバIP>',
'overwritewebroot' => '/nc',
);
```

```sh:手順3
# 手順2 の続き
exit
```

`http://<物理サーバIP>/nc/`にアクセスするとnextCloudが、`http://<物理サーバIP>/c9/ide.html`にアクセスするとcloud9が起動します。
`<物理サーバIP>`は`192.168.0.32`など、適宜インストールしたサーバのものと読み替えてください。

## おわりに

VPSのWebシェルを利用しているため、コピペが簡単にできず手打ちで記事を書きました。
おそらくtypoのひとつやふたつあると思われますので、動かない等不具合がありましたら、編集リクエストまたはコメントでお知らせください。
LINE Thingsの開発をしていて詰まったことのまとめ

最近LINEの中の人から「LINE Things Developer Board」をいただきました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">LINEさんから開発ボードがとどいた！<br>よーし、今日はこれで遊ぶぞー！ <a href="https://t.co/7tE8E6Vzhv">pic.twitter.com/7tE8E6Vzhv</a></p>&mdash; K.Miura (@k_miura_io) <a href="https://twitter.com/k_miura_io/status/1111849848016265216?ref_src=twsrc%5Etfw">2019年3月30日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

この開発ボードにはnRF52832が使われてあり、ボードには最初からいろんなセンサが実装されています。
というわけでLINE Thingsでセンサーをつなげてみたり、LIFFをアレンジしてみたりしていたときに通信で詰まったことを項目ごとに備忘録としてまとめてみようと思います。（勢いで書いたので間違いがあったら指摘お願いします）

# Arduino編
## データの送信がうまくいかない
[このプログラム](https://github.com/line/line-things-starter/blob/master/line-things-dev-board/arduino/sample/sample.ino)を参考にセンサーの値を送信しようとしましたがうまくできずかなり悩んでいたときに、```setupServices```を眺めていたときのことです。

```cpp

notifyCharacteristic.setFixedLen(1);
```
これはデバイスから送信する最大のデータ量を示しているようです（構造体を定義するような感じでしょうか）。starterプログラムでは一つのボタンの値を送信することを想定しているので送信するデータ量は1になってますけど、複数のデータを送信したいときには、この部分の数値を大きくすればいいようです。あとは、もともと開発ボードに書き込まれていた[コード](https://github.com/line/line-things-dev-board/tree/master/arduino/linethings-dev-default)を参考にしながら複数のデータを送信できるようにStarterのアプリのアレンジをしやすくなります。

# JavaScript編
## 通信エラー
送信をする部分を書けたし、今度はJavaScriptのコードをいじっていたら、ペアリングをしたときにLIFF上にこんなエラーが出ました。

```
BLUETOOTH_SERVICE_NOT_FOUND
```
接続は出来ても、デバイスの認証ができてないせいで起こるエラーっぽいですね。なので、もう一度コードを戻して行ったときに、原因の記述を見つけました。

```javascript
device.gatt.getPrimaryService(USER_SERVICE_UUID).then(service => {
    liffGetUserService(service);
}).catch(error => {
     uiStatusError(makeErrorMsg(error), false);
});
device.gatt.getPrimaryService(PSDI_SERVICE_UUID).then(service => {
    liffGetPSDIService(service);
}).catch(error => {
    uiStatusError(makeErrorMsg(error), false);
});

```
ここを消してしまっていたために、デバイスと接続出来ても認証が出来なくて、通信が確立されないからセンサーの値が取れなかったみたいです。逆を言えばここさえしっかりやれば、あとはデバイスのデータを受け取るだけになるはずです。それでもうまくいかないときは、ペアリングのときに問題が起こっているのかもしれません。次のペアリング編の解決方法を見てください。
# ペアリング編
同じボードを使って別のLIFFをつなぐためにファームウェアを書き直したときに、ペアリングをすると、接続エラーになってしまい、そもそもLIFFが出現しない問題が起こります。これは、Bluetoothのキャッシュが残っていることで起こる問題であることが多いです。そういうときは、一旦ファームウェアを書き直したデバイスの電源を落としてから、iPhoneの場合は設定アプリのBluetoothのペアリングデバイスの項目にある該当のデバイスの連携を削除して、更にLINE Thingsの連携画面からもデバイスの連携解除をしたあとに、再度デバイスの電源を入れ直せば、また新しいLIFFアプリを立ち上げてデバイスを操作できるはずです。また、micro:bitの場合は追加で[micro:bitのキャッシュをクリアにする](https://qiita.com/n0bisuke/items/09bc7868d0f6af69879e)必要があります。
RSpecのエラー Failure/Error: expect(page).to have_selector '.alert-success', 〜 が出た時の対処法


### 本文に書いた解決策は間違いでした。申し訳ございませんが、正しい解決策についてはコメント欄をご覧ください。

 [Junichi Ito さん](https://qiita.com/jnchito)、本記事へのご指摘ありがとうございました。

# はじめに
この記事の最後に本タイトルとは別にRSpecのエラー「[Capybara::ElementNotFound: Unable to find field "タイトル"](#おまけ)」が出た際の対処法もおまけとして簡単に記述しておきましたので参考にしていただければ幸いです。

# エラー画面と問題の部分
エラー画面

```terminal:Terminal
Failures:

  1) イベント管理機能 新規作成機能 新規作成画面でタイトルを入力したとき 正常に登録される
     Failure/Error: expect(page).to have_selector '.alert-success', text: '新規作成のテストを書く'
       expected to find visible css ".alert-success" with text "新規作成のテストを書く" but there were no matches. Also found "イベント「@event.title」を登録しました。", which matched the selector but not all filters.
```

問題の部分

```ruby:events_spec.rb

context '新規作成画面でタイトルを入力したとき' do
      let(:event_title) { '新規作成のテストを書く' }

      it '正常に登録される' do
        expect(page).to have_selector '.alert-success', text: '新規作成のテストを書く'
      end
    end
```

Bootstrap4のクラス".alert-success"を持つ要素が画面内に見つからなかったとのことなのでレイアウトに誤記等が無いかを確認。
HTMLをSlimで記述しています。

app/views/layouts/application.html.slim (一部抜粋)

```slim:application.html.slim

.container
      - if flash.notice.present?
        .alert.alert-success = flash.notice
```

特に問題なさそう。

# 対処

とりあえずエラーメッセージをググってみた。
すると[海外のStackOverflow](https://stackoverflow.com/questions/35989268/test-that-a-toast-fires-off-in-a-capybara-feature-spec)で有力な情報を発見。

この方は私とは違う内容で質問されてましたが質問中のコードに以下の様に書かれていました。

```ruby
expect(page).to have_content("Your email address has been updated successfully.")
expect(page).to have_css(".alert-success")
```

どうやら記述方法を間違えていたらしいのでこれを参考に問題の部分を以下の様に修正

```ruby:events_spec.rb

context '新規作成画面でタイトルを入力したとき' do
      let(:event_title) { '新規作成のテストを書く' }

      it '正常に登録される' do
        expect(page).to have_content('新規作成のテストを書く')
        expect(page).to have_css('.alert-success')
      end
    end
```


`$ bundle exec rspec spec/system/oogiri_events_spec.rb` を実行

テストが通った(GREEN)

```terminal:Terminal
.....

Finished in 4.64 seconds (files took 1.39 seconds to load)
5 examples, 0 failures
```

# まとめ

Specエラー解決方法はいくつかあります。

- Specが通らない際はエラーコードを頼りに対象のファイルと行を見つけます。

- 時にはコンソールのsandboxモード(`$ bin/rails c -s`)でモデルなどの各動きを確認して期待通りの検証か調査する。

- RSpecとCapybaraとの連携によるSystem Specではテストに失敗した時点のスクリーンショットを作成してくれるのでどのタイミングで失敗したのか視覚的に分かるので便利です。

- テスト失敗時のスクリーンショットは tmp/screenshots に保存されます。



# おまけ

### エラー「Capybara::ElementNotFound: Unable to find field "タイトル"」 が出た際の対処法


エラー画面

```terminal:Terminal
Failure/Error: fill_in 'タイトル', with: event_title

   Capybara::ElementNotFound: Unable to find field "タイトル"
```

fill_inで指定した'タイトル'が見つからないとのこと。
i18nによる国際化対応でja.ymlに日本語対応を施したため、問題の部分とja.ymlに相違が無いか確認する。

問題の部分

```ruby:event_spec.rb
before do
  visit new_event_path
  fill_in 'タイトル', with: event_title
  click_button '登録する'
end
```


config/locales/ja.yml

```yaml:ja.yml

attributes:
      event:
        id: ID
        title: イベント名
...省略...
```

ja.ymlのtitle:に「イベント名」と設定されているのにevent_spec.rbのfill_inが「タイトル」になっているためエラーが発生したと考えられる。

### 対処

event_spec.rbのfill_inの部分を「イベント名」に修正したらテストが通った(GREEN)

```ruby:event_spec.rb
before do
  visit new_event_path
  fill_in 'イベント名', with: event_title
  click_button '登録する'
end
```
テスト的にサイトを作る

#なにこれ
備忘録として私が残しているもの。
なにかとでもサイトを作ったりするときのやり方を残しておく。

#テスト的にサイトを作るやり方

##その1 「CSSをHTMLに直接書く」
[デモを確認する](https://css-to-html.netlify.com)

```index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>cssをhtmlに直接書く</title>
    <style>
        @charset "UTF-8";

        * {
            margin: 0;
            padding: 0;
        }

        body {
            background-image: url(pattern.png);
        }

        img {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 70vw;
            border-width: 8px;
            border-style: ridge;
            border-color: #ded000;
            padding: 50px 80px;
            background-color: #00005c;
        }
    </style>
</head>

<body>
    <img src="title.svg" alt="">
</body>

</html>
```

##その2 「JavaScriptをHTMLに直接書く」
[デモを確認する](https://js-to-html.netlify.com)

```index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>jsを直接htmlに書く</title>
    <link rel="stylesheet" href="style.css">
    <link href="https://fonts.googleapis.com/css?family=Amatic+SC:700" rel="stylesheet">
</head>

<body>

    <h1>Sample</h1>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script>
        $(function() {
            $('h1').text('Hello, World!');
        });
    </script>
</body>

</html>
```

#終わり
参考にさせていただきました
[HTML5&CSS3 デザインレシピ集](http://gihyo.jp/book/2017/978-4-7741-8780-8)
[Windows10] ローカルアカウントからMicrosoftアカウントに切り替えられないとき

# ことの発端
1. Win10の設定同期機能を有効にするため、ローカルアカウントにMicrosoftアカウントを関連付けたかった。
2. 調べると一度Microsoftアカウントでのログインに切り替えた後、ローカルアカウントに戻すことで関連付けができるとのこと。(以下、参照ページの一つ)  
[`ローカルアカウントにmicrosoftアカウントを関連付け`](https://paso.123net.jp/windowstips/ローカルアカウントにmicrosoftアカウントを関連付け/)
3. アカウント設定の変更ー＞ユーザーの情報の「Microsoftアカウントでのサインインに切り替える」からログインして切り替えようとする。
4. するとWin10さん曰く、「既にこのPCに使用されているのでこのアカウントは使えません。」とのこと。
5. 以前に他のサービスでログインしたことはあるが紐づけした記憶はないし、そもそも他のアカウントの欄にMicrosoftアカウントは存在しない。それどころか、他のアカウント自体が存在しない。  

6. はて、どうしたものか？？？
以上経緯。

検索しても解決策は出てこなかった。（クリーンインストールとういう文字はあったが、そんな面倒なことはしたくない。）
が、いくつか試すと解決したので記録として残しておきます。

困っているそこのあなた！
もしかしたら解決するかも。

# 原因
Microsoftアカウントがないのに既にあるということは、アカウント情報のキャッシュが問題である可能性が高い。
ということは、そのあたりを編集するか、変更を重ねてOSに気づかせ修正させるかどちらかで解決されると考えた。

結果それは合っていたが、結構面倒だった。でも、、、

**クリーンインストールするよりマシ**

# 有効ではなかった対応
### 1. アカウント情報を直接変更する
そんな方法見つからなかった。。。  


### 2. 別ローカルアカウントを作る
一旦別のローカルアカウントを作ってそのアカウントで切り替えー＞削除ー＞元のアカウントで切り替えー＞成功！
ってなら、、、  

なかった。
新しいローカルアカウントでMicrosoftアカウントに切り替えしようとすると、「既にこのPCに使用されている... と同じエラーを返された。

### 3. 新しいWinアカウントをMicrosoftアカウントとして作る
ならば、最初からMicrosoftアカウントでユーザーを作ればいいのでは？？

無理でした。。。「既にこのPCに使用されている... とまた同じエラーを返された。

# 最終的に成功した方法
### 一旦別のMicrosoftアカウントを作り、後に本命のMicrosoftアカウントに切り替える。
1. 切り替えるユーザーで「Microsoftアカウントに切り替える」を実行する。
2. 「Microsoftアカウントを **作成** する」で新しいMicrosoftアカウントを作って、Microsoftアカウントに切り替える。
3. 指示通りの設定すると、新しいMicrosoftアカウントに切り替えられる。
4 ローカルアカウントに戻す。
5. メールとアカウントから新しく作ったMicrosoftアカウントを削除。
6. ユーザー情報から「Microsoftアカウントに切り替える」から、今度は本当に切り替えたいMicrosoftアカウントで切り替える。
7. 通常通り設定でき、問題なく同期も始まる。

　　　**MISSION COMPLETE！**
WSL(Debian GNU/Linux)にdockerを入れた

# WSL(Debian GNU/Linux)にdockerを入れた

## 1. はじめに
Docker Desktopをインストールして立ち上げてみたのだが、私の自宅の貧弱スペックPCは『カクカクフリーズ状態』に陥り、とてもそれを立ち上げながら作業する気持ちになれなかったので、WSLにインストールする事にした。

## 2. 環境 
**Windows10の環境**

```
Windows 10 Pro Insider Preview
評価コピー。Build 18875.rs_prerelease.190405-1518
```

**WSL(Debian GNU/Linux)の環境**

```bash

xxxxxx@xxxxxxxxxxxxxx:~$ cat /etc/debian_version
9.7
xxxxxx@xxxxxxxxxxxxxx:~$ cat /etc/issue
Debian GNU/Linux 9 \n \l
```



## 3. インストール作業
### 3.1. つまづき
こちらのページのとおりに作業を進めて行けば、インストールそのものは簡単に終わる。ページからコマンドをコピー＆ペーストでサクサクと進めれば良いだろう。
[https://docs.docker.com/install/linux/docker-ce/debian/#install-docker-ce](https://docs.docker.com/install/linux/docker-ce/debian/#install-docker-ce)


しかし、その方法でインストールされる、最新バージョンのDockerでは、
Dockerのサービス起動には成功するのだが、次の段階のコンテナ起動で、
以下のようなエラーを吐いて、どうしても動かない。

```bash

xxxxxx@xxxxxxxxxxxxxx:~$ docker start 209ebb8f7e26
Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "process_linux.go:297: getting the final child's pid from pipe caused \"EOF\"": unknown
Error: failed to start containers: 209ebb8f7e26
```

調査を進めて行くと、WSLがdockerの新機能に対応していない事が原因で、通信が不調なのだから、dockerをダウングレードせよとの事だった。ネット上の情報はubuntuが多くdebianが少ない。また、WSLの記事となるとさらに少なくて、英語で書かれたubuntuやmacosの記事をWSL(debian GNU/Linux)用に読み替える事に、一番時間がかかった。

### 3.2. 再インストール（ダウングレード）

あまり関係ないかもしれないが、Windowsの管理者モードで起動した方がよさそう。
ターミナルを閉じて、再度立ち上げる。
![20190430_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/332d7969-241c-25d0-8d51-550934bbc2ce.png)


マニュアルに記載のあるとおり、以下のコマンドで、docker-ceを削除する。

```bash

sudo apt-get purge docker-ce
```

```bash

sudo rm -rf /var/lib/docker
```

以下のコマンドでdocker-ceのバージョンを指定してインストールする。
(17.03.3~ce-0~debian-stretchをインストールしたら上手く行きました)

```bash
sudo apt-get install docker-ce=17.03.3~ce-0~debian-stretch
```

ここからが重要なのだが、公式のマニュアルには書かれておらず、暫くハマったのだが、以下のとおりコマンドを順次投入してやると、起動する。

```bash
sudo cgroupfs-mount
sudo usermod -aG docker $USER
sudo service docker start
```

cgroupfs-mountは特殊なセキュリティの仕掛けとの事。このコマンドを投入しないとdockerのサービスは起動しない。

以下のとおりDockerの起動が確認された。

```
xxxxxx@xxxxxxxxxxxxxx:~$ sudo service docker status
[sudo] password for kazuki:
[ ok ] Docker is running.
```

コンテナを実行する。

```
sudo docker run hello-world
```

コンテナの実行結果が表示された。
![20190430.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374511/e9aea6c6-fd2e-3c9e-9434-81b10043f6e2.png)


## 4. まとめ
最初からdocker-ceをダウングレードしてインストールすれば良いとする情報があれば良かったと思うので、今回は投稿させていただきました。WSLが更新されれば最新のdockerにも対応するようになるかもしれませんし、先の事はわかりませんが、備忘録的に纏めさせていただきます。

・ debianの情報は少ないのでubuntuの方が調査はやりやすい。
・ Windowsの管理者モードでターミナルを立ち上げること。
・ Dockerの起動コマンドはマニュアルに記載が無い。cgroupfs-mountを実行する必要がある。
・ docker-ceは17.03.3~ce-0~debian-stretchにダウングレードする。
・ https://qiita.com/forest1/items/ab6d8b345653c614229b こちらも参考になります。