OmniAICreator/Qiita-1.07M huggingface dataset:
データ分析について考えてみた

データ分析には機械学習とデータマイニングという用語がありますが、本稿はどちらかというとデータマイニング寄りの話になります。

##本質を見抜く
データ分析に詳しくなりたいけど、未だ漠然としか把握できていないので、ここで一回初心に戻りたく、、、
要は中途半端なのです。

データ分析を学ぶにあたり、まずはデータ分析の本質を見抜く必要があると感じました。
データ分析に関心を持ち、今あるデータで分析してみたは良いけれど、分析結果を見てふと我に返ることがありました。

「で、何に使う？」

結局、単に経験値が上がっただけでした。
まだ個人だから良かったものの、これが企業だと無駄（ノーリターン）です。
データ分析の本質が見えていないってことになります。（反省...）

##そもそもデータ分析って？
みなさんの考えをまとめてみました。

>- 何らかの目的を持って表現された文字や符号、数値などを収集し、分類、整理、成型、取捨選択したうえで解釈して、価値のある意味を見出すこと

>- 意思決定のため

>- 統計分析を含むさまざまな分析手法やツールを用いてデータを分析し、それをビジネスに有用な情報へと置換すること

>- ある目的（今回はビジネス）において不可欠な情報や数値、文字などを収集し、その集めたデータを分類・整理・成形・取捨選択した上で解釈すること

>- 「経営戦略やマーケティングに有用なデータを得るための手段」

>- 「数あるデータから有益な情報を探し出し、改善に役立てる取り組みのこと」

>- 目的を持って収集・抽出したデータを解釈することで、課題解決に役立つ情報を見つけ出す手段

>- 通常ビジネスの意思決定に役立つ情報を発見するために、データを処理、変換、およびモデリングするプロセス


>- 統計学や機械学習、データ可視化を含む様々な分析手法やツールを用い、データ分析の結果をビジネスに有用な情報へと置換する過程

みなさんの言っていることは似ています。
共通して言えることは「目的」ありき、あくまでデータ分析は意思決定の手段でしかない、ってことだと思います。
そして、意思決定に役立てて初めて意味を成す。

とりあえずやってみる事は良い心掛けですが、ちゃんと「目的（ゴール）」を定めたうえでやってみることが大切なんですね。
そして、目的に沿う最適解を導き出す想像力がとても必要とのこと。

##■フェーズ定義
- ビジネス（目的・課題）の理解
- データの理解
- データの準備（収集、データクレンジングなど）
- モデル作成
- モデル評価、改善
- 提供と共有

何事もビジネスの理解がスタートです、課題や目的です。いったい何が目的でデータ分析するの？というところ。
目的が明確になったら現状のデータ把握（理解）です。今あるデータで目的を果たせる分析ができるのか否か。
否の場合は目的や課題の見直しか、どんなデータが必要か精査をし、データ収集＆クレンジングしてモデル作成準備をします。
データ準備を終えたら、モデル作成して評価と改善を繰り返します。
精度が良くなれば納品という流れになるのが一般的のようです。


##■目的や課題を理解する
そもそも目的って何？ってなりました。
どうやら、「こんなデータ分析結果がほしい」とかではないようです。

もっと先、例えば、

- ある化粧品のターゲット層30代の女性のリピート顧客を増やす
- 市場に見合った販売・製造計画をして、余剰在庫を減らしつつ利益率を上げる

これらの課題解決の意思決定に必要な情報をいち早く出してあげたほうが良いようです。
ビジネスにおける意思決定は早いに越したことはありません。

##■データを理解する
###現状どんなデータがある？
今あるデータで目的を果たせるのか？足りないデータはないか？

###どのような情報が必要？
足りないデータとして何が必要か精査します。
どのような情報（データ）が判断材料になるかを考えます。
収集困難だと思われる情報があれば、それは目的を果たせないことになるので、目的を変更するなどの措置が必要です。

###どのような分析が必要？
判断材料になる情報が明確になったら、どこまで、どんな分析が必要かを見極めます。
ざっくりですが、

- アソシエーション分析
関連性のない事象の関連性を見つけ出す。
よく聞く事例は「ビールと紙おむつ」
紙おむつを買う人は、併せてビールも買うという関連性を見つけ出し、並べて陳列したら売上向上みたいな。

- バスケット分析
アソシエーション分析からの派生、商品に特化。レコメンドなど。

- クロス集計分析
アンケートなど、属性などの項目を交えて集計。平均値など。

- 決定木分析
「もしも～」を繰り返して予測する。リスクマネジメント。


- クラスター分析（k-平均法）
複数の異なる性質の集団から似たもの（類似性に基づいて）でグループ化。


- ロジスティック回帰分析
多変量解析のひとつ。
Yes,Noで明確に定義して、事象の発生率などを予測する。


などなど。どうやら上記がビジネスデータ分析において主要な分析とのこと。


##■データを準備する
###データを収集
必要な情報、分析方法が定まったら、データ収集方法を決定し収集していきます。
目的を明確にしているため、その目的を果たすのにデータがないなら取得しないといけませんし、取得できないなら目的を変えるなどの措置が必要になってきます。

###データクレンジング
収集したデータにはノイズがふくまれているため、このままでは分析できません。
加工や整理などのクレンジングが必要です。

##■モデル作成
上記で説明した分析方法を用いてモデルを作成していきます。
※加工された学習用データや評価表データを用いたりします

##■モデル評価と改善
データマイニングは探索的、発見的な手法です。
不可欠なのは、数値指標を用いて性能評価です。
また、分類モデルや回帰モデルによって評価指標は異なってきます。
予測精度や生成にかかく時間、何をもって良しとするかは、取り決めや、正直さじ加減などあるかもしれません。
複数のモデルを評価、比較して選抜するといったこともこのフェーズに含まれます。

##■提供と共有
相手が理解しやすいフォーマットに加工して見せる必要があります。
PowerBIなどは可視化用のツールです。

##まとめ
最適解を得るためには「仮説→分析→検証」を繰り返していかないといけません。
しかも、泥臭く導き出した最適解はあくまでも現時点における最適解であって、時が経って技術能力が向上すれば、その技術で導き出したものが最適解になります。
要は最適解にゴールはないってことになります。
Windows 10でSDカードを完全消去する方法

# 1. 目的
SDカードの破棄が必要になったため、データを完全消去する方法を調べてみました。

# 2. 前提条件
市販のツール等は利用せず、Windows 10の標準機能のみに限定しています。
完全消去した後は、物理的に破壊してから破棄します。

# 3. 手段
### 選択肢1.  cipherコマンド
- NTFSの暗号化機能を制御するコマンド（FAT32への対応は限定的）
- Windows 10に最初から組み込まれている（Home 1909で確認）
- 「/w」オプションでワイプが可能
- 実行すると空き領域にデータを3回書き込む（0→1→ランダム）
- 上記より、手順は以下の通り。
    1. SDカードをNTFSでクイックフォーマットする
    2. コマンドプロンプトで「cipher /w:ドライブレター:」を実行する
- 参考URL：[Windowsでディスクの内容を完全に消去する（@IT）](https://www.atmarkit.co.jp/ait/articles/0303/01/news003.html)

### 選択肢2. diskpartコマンド
- ディスクのパーティションを管理するツール
- Windows 10に最初から組み込まれている（Home 1909で確認）
- 実行すると空き領域にデータを1回書き込む（ゼロクリア）
- 手順は以下の通り。 

    1.「diskpart」ツールを起動する（ファイル名を指定して実行）
    2.「disk list」コマンドで対象のSDカードを確認する
    3.「select disk ディスク番号」でSDカードを選択する（ディスク番号は数値1桁のみで指定）
    4.「list partition」でSDカードが正しく選択されていることを確認する
    5.「clean all」で完全消去を実行する
- 参考URL：[完全データ消去で廃棄ディスクからの情報漏えいを防ぐ（Windows diskpart編）（@IT）](https://www.atmarkit.co.jp/ait/articles/1004/16/news101.html)

# 4. 規格
ほとんどのドライブは 1回の上書きで十分にサニタイズできるとされています。

- [NIST Special Publication 800-88 Revision 1（英語）](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-88r1.pdf)
- [NIST Special Publication 800-88 Revision 1（日本語）](https://www.ipa.go.jp/files/000025355.pdf)

# まとめ
- Windows 10の標準機能でSDカードを完全消去する方法は、「diskpart」または「chiper」の2種類です。
- 通常は、「diskpart」で消去してから、物理破壊をしておけば充分と考えられます。
SpacemacsでSQLの自動補完などを効かせる

cf. https://github.com/syl20bnr/spacemacs/tree/develop/layers/%2Blang/sql

Ubuntu18.04LTS on WSL2 on Windows10でやった。





# 予約語を大文字に自動変換する
`SELECT`や `FROM`などのキーワードを入力して半角スペースを空けた時、自動的に大文字へ変換させる。

`name`や `user`など「カラム名として使っているから大文字にしたくない」キーワードがあれば、 `sql-capitalize-keywords-blacklist`設定で除外できる。

```emacs-lisp:.spacemacs
(defun dotspacemacs/layers ()
  (setq-default
   dotspacemacs-configuration-layers
   '(
     (sql :variables
          sql-capitalize-keywords t
          sql-capitalize-keywords-blacklist '("name" "user"))
    )
  )
)
```





# LSPを利用して自動補完などを行う
バックエンドにLSPを使う。
サポートされているLSPは [sqls](https://github.com/lighttiger2505/sqls)。

## sqls
sqlsが解説されている記事 => [すべてのエディタでSQLの自動補完をするためにSQL Language Server(sqls)を作った](https://qiita.com/lighttiger2505/items/5782debc59ae163a4d81)

### sqlsをインストール
Go (golang)をインストールして、Go経由でsqlsをインストールする。

Goのインストールとパス設定は、Terraform Layerを参照
cf. [SpacemacsでTerraformの自動補完やフォーマット機能を使う - Goをインストール](https://qiita.com/v2okimochi/items/00dfbc00bc4d6ad9aa85#go%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)

さらに、Go経由でインストールするコマンドのディレクトリやパス設定を行う。

- `GOPATH`でインストール先ディレクトリ (たとえば `~/.go_path_packages`とか)を指定
- そのディレクトリ下のbinディレクトリにパスを通す

```shell:~/.bash_profile
# Go
export GOPATH=$HOME/.go_path_packages
export PATH=$PATH:$HOME/.go_path_packages/bin
```

`source ~/.bash_profile`コマンドで設定を反映しておく。

そして満を持してsqlsインストール。

```shell
go get github.com/lighttiger2505/sqls
```

`GOPATH`で指定したディレクトリ内のbin下にsqlsコマンドが入り、使えるようになる。

### .spacemacsの設定
```emacs-lisp:.spacemacs
(defun dotspacemacs/layers ()
  (setq-default
   dotspacemacs-configuration-layers
   '(
     (sql :variables
          sql-backend 'lsp
          sql-lsp-sqls-workspace-config-path 'workspace)
    )
  )
)
```

sqlsで自動補完を行うためには、DBに接続する必要がある。

workspace configurationで設定する場合は、 `sql-lsp-sqls-workspace-config-path`を `'workspace` or `'root`に指定し、JSONで書いた設定ファイルを置いておく。
※ `sql-lsp-sqls-workspace-config-path`のデフォルト値は `'workspace`

- `'workspace`: `{ワークディレクトリ}/.sqls/config.json`
- `'root`: `{ワークスペースのルートディレクトリ}/.sqls/config.json`

JSON設定ファイルはこんな構成。 `driver`と `dataSourceName`の対で置いていく。

```json:.sqls/config.json
{
  "sqls": {
    "connections": [
      {
        "driver": "mysql",
        "dataSourceName": "user1:password1@tcp(localhost:3306)/sample_db"
      }
    ]
  }
}
```

sqlsの機能としては、自動補完以外にも `Execute SQL`や `Switch Connection`などあるが、Spacemacsではこれらを `codeActions (, a a)`から選んでもエラーが出て実行できない。
`executeCommand`は許可されていない模様。どうして。。。

```
lsp--send-request-async: The connected server(s) does not support method workspace/executeCommand
```
Jupyterlabのインストールと拡張機能の導入


ubuntu18.04にJupyterlab、およびいくつかの拡張機能を導入したときのメモです。拡張機能については順次、追記していきます。

## インストール編

### Pre-requisites
* Anaconda （私の場合はversion4.8.3を使用しています）

※Anacondaの導入がまだの場合は、インストールしてから読み進めてください。[公式ページ](https://docs.anaconda.com/anaconda/install/linux/)などが参考になります。

### Install
* Jupyter notebook

```bash
conda install -c conda-forge notebook
```
* Jupyterlab

```bash
conda install -c conda-forge jupyterlab
```

## 拡張機能の導入編
Jupyterlabには便利な拡張機能が数多く用意されています。この記事ではそのうちの概要と、導入方法を紹介します。拡張機能を導入するためには、[node.js](https://nodejs.org/en/)が必要になります。

```bash
conda install -c conda-forge nodejs
```
node.jsのインストールが無事に済んだら、早速機能を拡張していきましょう。

### 拡張機能1: visual debugger
デバックを視覚的に行うための機能です。[こんな感じ](https://github.com/jupyterlab/debugger/blob/master/screencast.gif)の動作イメージです。[jupyterlabの公式ブログ](https://blog.jupyter.org/a-visual-debugger-for-jupyter-914e61716559)を参考に導入しました。

```bash
## pre-requisites
conda install ptvsd -c conda-forge
## debugger front-end
jupyter labextension install @jupyterlab/debugger
## debugger back-end
conda install xeus-python -c conda-forge
```


※[公式のgitリポジトリ](https://github.com/jupyterlab/debugger)では新しくanacondaの仮想環境を整えることが推奨されていますが、notebookやjupyterlabのバージョンが、それぞれJupyternotebook: 6以上, Jupyterlab: 2.0位上であればそのまま進めて問題はないかと思います。もし上記を満たさない場合は、[同リポジトリのREADME](https://github.com/jupyterlab/debugger)を参考にしてください。

### 拡張機能2: variable inspector
変数の型や、格納されている値が視覚的に分かるツールです。[こんな感じ](https://github.com/lckr/jupyterlab-variableInspector/blob/master/early_demo.gif)の動作イメージです。導入するためのコマンドは下記になります。

```bash
jupyter labextension install @lckr/jupyterlab_variableinspector
```

### 拡張機能3: go to definition
変数や関数の定義までジャンプしてくれる拡張機能です。[こんな感じ](https://raw.githubusercontent.com/krassowski/jupyterlab-go-to-definition/master/examples/demo.gif)の動作イメージです。導入するためのコマンドは下記になります。


```bash
jupyter labextension install @krassowski/jupyterlab_go_to_definition
```

### 拡張機能4: flake8
コードの自動チェックツールです。導入するためのコマンドは下記になります。


```bash
conda install flake8
jupyter labextension install jupyterlab-flake8
```
導入が済んだら、[公式のgitリポジトリ](https://github.com/mlshapiro/jupyterlab-flake8)のsettingsを参考に設定をすれば使用することができます。

### 拡張機能: 余談
紹介した拡張機能は全てコマンドでインストールしましたが、Jupyterlabの画面からインストールすることも可能です。その場合は[Extension Manager](https://jupyterlab.readthedocs.io/en/stable/user/extensions.html#using-the-extension-manager)を使用します。キーワードを入れれば拡張機能の候補が出てくるので、こんな機能ないかな〜、というときに検索して拡張してみてください。


お疲れさまでした！！
Vue.Draggable の奇妙な動きを対症療法でなんとかする

初投稿です。よろしくお願いします。

#1.環境

Vue.js：2.6.11
Vue.Draggable：2.23.2
Google Chrome

#2.問題

趣味でなんとなく Vue.js で Webアプリを作っています。

ドラッグ&ドロップで要素をぴょこぴょこ移動させる機能を作りたいな～と思ってたら、Vue.Draggable というなんとも便利なものが存在しているではありませんか。

さっそくインストールして実装。

なかなかいい感じになってきたな、と思ってたらふと妙な動きをしていることに気付きました。

まずは動画を見てください。

※Google Chrome の場合


![test1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666395/34a3e4d9-f0b8-a4c9-872c-cb12484b5c82.gif)


下のエリアの要素を少し動かしただけなのに、左上のエリアがなにやら蠢いています。
よくみると、下のエリアの要素を動かしはじめた一瞬、その要素が左上のエリアにワープしています。

なんじゃぁこれは、と公式のサイトを見てみたのですが、公式のサイトのデモアプリでも同じような動きをします。
あ～じゃあダメだな、と思いつつ諦めきれず英語のサイトや中国語のサイトをあさりましたが解決せず…

#3.対症療法

ぼ～っとしながら奇妙な動きをするドラッグ&ドロップの操作を繰り返してると、ふと対症療法が浮かんできました。

色々試して気が付いたのは、この現象はcloneイベントの直後に発生しているということです。
そこで、cloneイベントのイベントハンドラに以下の記述を追加しました。



```vue

<draggable tag="ul" v-model="left" :group=state @clone="onClone">
    <li v-for="l in left" :key="l.content">
        <div>{{ l.content }}</div>
    </li>
</draggable>
<!-- あと右上エリアの分と下エリアの分-->

data() {
    return {
        state: undefined,
        left: [
            {content: "task1"},
            {content: "task2"},
            {content: "task3"},
            {content: "task4"}
        ],
        //あと右上エリアの分と下エリアの分
    }
},
methods: {
    onClone: function () {
        this.state = null
        setTimeout(this.setGroup, 100)
    },
    setGroup: function () {
        this.state = "move"
    }
}
```


cloneイベントが発生したらgroup 属性を null にして group 間の移動ができないようにします。
0.1秒くらい待って、group 属性に値をセットしてgroup 間の移動を可能にします。

すると以下の動画のようになります。

![test2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666395/9be8a4cc-f443-7a62-acd8-9197eefabf1e.gif)


奇妙な動きはなくなりました。

また、同一エリア内での要素の移動に関して、動かした要素の二行上の要素が一瞬動くという奇妙な動きをすることもあります。

それもこの対症療法で対応できる気がします。
R言語　3系の最新をソースからビルドしてみる

R言語を利用する機会があったので、インストール手順をメモ

参考：[公式サイト](https://cran.r-project.org/index.html)

## R言語のバージョン

### 3系
- 2020年7月現在3系の最新バージョンは3.6.3（2020-02-29）
- Centos7 EPELリポジトリでインストール可能なバージョンは3.6.0

### 4系
- 次期バージョンとして4系がリリースされた
- https://cran.r-project.org/src/base/R-4/
    - 4.0.0　(2020-04-24)
    - 4.0.2　(2020-06-22)

## 3系のインストール

今回はGCP　CentOS7インスタンスにてR言語インストール作業を行った


### 3.6.0のインストール
```
#yum -y install epel-release

#yum info R
Available Packages
Name        : R
Arch        : x86_64
Version     : 3.6.0
Release     : 1.el7
・・・・

#yum -y install R
```


### 3.6.3のインストール

最新バージョンはソースからビルドする必要がある

必要なミドルウェアをインストール

```
sudo yum install wget gcc gcc-gfortran libgfortran gcc-c++ zlib-devel bzip2 bzip2-devel pcre pcre-devel xz xz-devel openssl-devel libcurl-devel java-1.8.0-openjdk java-1.8.0-openjdk-devel -y
```


公式からダウンロードしてインストール

```
#wget https://cran.r-project.org/src/base/R-3/R-3.6.3.tar.gz

#tar xzvf R-3.6.3.tar.gz

#cd R-3.6.3

#sudo ./configure --with-readline=no --with-x=no

#sudo make

#sudo make install
```
n桁の有効数字に丸める

```csharp
private void button_Click(object sender, EventArgs e)
{
    Debug.WriteLine(calc_significant_figures(1040000.00M, 2, 0)); // -> 1000000
    Debug.WriteLine(calc_significant_figures(1050000.00M, 2, 0)); // -> 1100000
    Debug.WriteLine(calc_significant_figures(10.0000400M, 6, 0)); // -> 10.0000
    Debug.WriteLine(calc_significant_figures(10.0000500M, 6, 0)); // -> 10.0001

    Debug.WriteLine(calc_significant_figures(1050000.00M, 2, 1)); // -> 1000000
    Debug.WriteLine(calc_significant_figures(10.0000500M, 6, 1)); // -> 10.0000

    Debug.WriteLine(calc_significant_figures(1040000.00M, 2, 2)); // -> 1100000
    Debug.WriteLine(calc_significant_figures(10.0000400M, 6, 2)); // -> 10.0001
}

static decimal calc_significant_figures(decimal value, int digits, int type)
{
    if (value == 0M)
    {
        return 0M;
    }

    var integer_part = (int)Math.Log10(Math.Abs((int)value)) + 1;

    //var decimal_part = decimal.GetBits(value)[3] >> 16 & 0x0FF;

    switch (type)
    {
        case 0:
            {
                var scale = (decimal)Math.Pow(10, integer_part);
                var result = scale * Math.Round(value / scale, digits, MidpointRounding.AwayFromZero);

                //return Math.Round(result, decimal_part);

                var decimals = digits - integer_part;
                return Math.Round(result, (decimals < 0) ? 0 : decimals);
            }
        case 1:
            {
                var scale = (decimal)Math.Pow(10, integer_part - digits);
                return scale * Math.Floor(value / scale);
            }
        case 2:
            {
                var scale = (decimal)Math.Pow(10, integer_part - digits);
                return scale * Math.Ceiling(value / scale);
            }
    }

    throw new Exception("error: calc_significant_figures");
}
```

[有効数字 @wikipedia](https://ja.wikipedia.org/wiki/%E6%9C%89%E5%8A%B9%E6%95%B0%E5%AD%97)
高位合成言語　karuta その４

#概要

スクリプト言語　karutaやってみた。
全加算器、書いてみた。

#サンプルコード


```

func ha(a #1, b #1)(#1, #1) {
  var c #1 = 0
  var o #1 = 0
  c = a & b
  o = a ^ b
  return c, o
}
func fa(a #1, b #1, d #1)(#1, #1) {
  var c1 #1
  var c2 #1
  var t #1
  var c #1 
  var o #1
  (c1, t) = ha(a, b)
  (c2, o) = ha(t, d) 
  c = a | b
  return c, o
}

func main() {
  var a #1 = 0
  var b #1 = 0
  var d #1 = 0
  var c #1 
  var o #1
  a = 0; b = 0; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 0; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 0; b = 1; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 0; b = 0; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 1; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 0; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 0; b = 1; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 1; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
}
main()





func ha(a #1, b #1)(#1, #1) {
  var c #1 = 0
  var o #1 = 0
  c = a & b
  o = a ^ b
  return c, o
}
func fa(a #1, b #1, d #1)(#1, #1) {
  var c1 #1
  var c2 #1
  var t #1
  var c #1 
  var o #1
  (c1, t) = ha(a, b)
  (c2, o) = ha(t, d) 
  c = a | b
  return c, o
}

func main() {
  var a #1 = 0
  var b #1 = 0
  var d #1 = 0
  var c #1 
  var o #1
  a = 0; b = 0; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 0; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 0; b = 1; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 0; b = 0; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 1; d = 0;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 0; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 0; b = 1; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
  a = 1; b = 1; d = 1;
  (c, o) = fa(a, b, d)
  print(a)
  print(b)
  print(d)
  print(c)
  print(o)
  print("")
}
main()


```

#実行結果


```
print: default-isynth.karuta loaded
print: 0
print: 0
print: 0
print: 0
print: 0
print: 
print: 1
print: 0
print: 0
print: 1
print: 1
print: 
print: 0
print: 1
print: 0
print: 1
print: 1
print: 
print: 0
print: 0
print: 1
print: 0
print: 1
print: 
print: 1
print: 1
print: 0
print: 1
print: 0
print: 
print: 1
print: 0
print: 1
print: 1
print: 0
print: 
print: 0
print: 1
print: 1
print: 1
print: 0
print: 
print: 1
print: 1
print: 1
print: 1
print: 1
print: 
```

以上。
Ubuntu/LinuxノートPCのWiFi問題

# ことの発端
Ubuntu 18.04LTSのGUIの設定からWi-Fiが利用できないことに気がついた。
「No Wi-Fi Adapter Found」「Wi-Fiアダプターが見つかりません」と表示されてしまうのである。
Bluetoothの欄を見てみても同様に、Bluetoothデバイスが見つからない旨のメッセージが出る。
しばらく有線接続をしていたから、いつからそうなったのかはわからなかった。

調べてみると同じようなトラブルは多く発生しているみたいだが、原因が複数ありトラブルシューティングの方法がかなり多岐にわたることがこの問題を厄介にしているようだ。
この投稿では、原因を確認するためにコマンドをうち、症状別にどのような回復方法を行うべきなのかをまとめておく。
誰かの参考になれば幸いだし、自分の環境ではこうだったというコメントも嬉しい。

# トラブルシューティング
- AirPlaneモードではないか？
    - 判断基準
        - Ubuntu上部のメニューバーに飛行機✈マークが出ている
        - 「設定」の「Bluetooth」に明確に機内モードであることが書いてある
    - 回復手段
        - 「設定」の「Bluetooth」から機内モードを切る
- Wi-FiがOFFになっていないか？
    - 判断基準
        - 「設定」の「Wi-Fi」を開いたとき、ウィンドウ上部のトグルスイッチが「OFF」になっている
        - ターミナルで`$ rfkill list`コマンドを打つと、`SOFT`の列が`blocked`になっている
    - 回復手段
        - 「設定」の「Wi-Fi」ウィンドウの上部のトグルスイッチをクリックして「ON」にする
        - ターミナルで`$ rfkill unblock wlan`と打つ
- キーボードのWirelessキーが押されていないか？
    - 判断基準
        - ターミナルで`$ rfkill list`コマンドを打つと、`HARD`の列が`blocked`になっている
        - ターミナルで`$ rfkill list bluetooth`コマンドを打つと何も出ない
        - 「設定」を開くと、Wi-FiもBluetoothもデバイスが見つからないと出る
            - トグルスイッチを「ON」にしても戻ってしまう
    - 回復手段
        - キーボードのWirelessキーを探して打つ
            - 私の場合はこれだった。DELL XPS 13ではFnキーと一緒にPrtScrキー
            - ノートPCのメーカー・型番によって、Wirelessキーのマークも位置もかなり異なる
- BIOSレベルで無効になっていないか？
    - 判断基準
        - BIOS画面からWi-Fi、Bluetoothの設定を確認する
            - BIOSの画面構成はPCによって異なるので自分のPCに合わせて調べる
    - 回復手段
        - 「Disable」になっているなら「Enable」にする
- デバイスドライバが無いのではないか？
    - 判断基準
        - ターミナルで`$ ip link show`と打ちWi-Fiデバイスの名前(logical name)を確認する
            - wlan0、wlp1s0などの名前が自動で付けられている
            - MACアドレスで区別しても良い
        - ターミナルで`$ sudo lshw -C network`と打ち、該当するnetworkの`configuration`に`driver=hoge`となっていないか確認する
        - Wi-FiモジュールがPCIデバイスとして認識されている場合、`$ lspci -nnk`でも使用中のデバイスドライバ名が確認できる
    - 回復手段
        - `driver=hoge`となっていない場合
            - lshwコマンドで確認したときの`product`を手がかりにデバイスドライバを探す
            - RealtekのrtlXXXXシリーズはgithubなどからコンパイルしてインストールする
                - BUFFALO WI-U2-433DMSはRealtek用の[このデバドラ](https://github.com/gnab/rtl8812au)で利用できた
            - Broadcomのbcmシリーズは`$ sudo apt install bcmwl-kernel-source`でインストールする
        - `driver=hoge`となっている場合
            - ターミナルで`$ modinfo hoge`と打ちデバイスドライバの情報を確認する
            - ターミナルで`$ nmcli connection`を打つ
                - 利用したいWi-FiのSSIDが表示されない場合は設定からWi-Fiネットワークの設定を行う
            - ターミナルで`$ nmcli device`を打ちデバイスの名前を手がかりに`STATE`を確認する
                - `connected`ならばWi-Fiに繋がっているはず
            - `$ dmesg | less`や`$ nano /var/log/syslog`といったコマンドを使い、エラーメッセージが出ていないかを目視で確認する
高位合成言語　karuta その3

#概要

スクリプト言語　karutaやってみた。
半加算器、書いてみた。

#サンプルコード


```

func ha(a #1, b #1)(#1, #1) {
  var c #1 = 0
  var o #1 = 0
  c = a & b
  o = a ^ b
  return c, o
}
func main() {
  var a #1 = 0
  var b #1 = 0
  var c #1 
  var o #1
  (c, o) = ha(a, b)
  print("0 0")
  print(c)
  print(o)
  a = 1
  c, o = ha(a, b)
  print("1 0")
  print(c)
  print(o)
  a = 0
  b = 1
  c, o = ha(a, b)
  print("0 1")
  print(c)
  print(o)
  a = 1
  c, o = ha(a, b)
  print("1 1")
  print(c)
  print(o)
}
main()


```

#実行結果


```
print: default-isynth.karuta loaded
print: 0 0
print: 0
print: 0
print: 1 0
print: 0
print: 1
print: 0 1
print: 0
print: 1
print: 1 1
print: 0
print: 0
```

以上。
リモートブランチに対して、ローカルブランチがいくらか進んでいる状況の解決方法

#リモートブランチに対して、ローカルブランチがいくらか進んでいて、その変更内容をリモートにpushしていない状況
```
$git status
On branch develop
Your branch is ahead of 'origin/develop' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
```
現在の`develop`がリモートのdevelopである`origin/develop`より2コミット進んでいるという意味
###ローカルブランチの更新内容をリモートに反映させたい場合
`$ git push origin`
より詳細に指定する場合は、
`$ git push origin develop:develop`

###リモートブランチの内容に合わせたい場合
`$ git reset -hard origin/develop`

###コミットをなかったことにしたい場合
`$ git reset --hard origin/develop`
DockerでLaravelの開発環境を構築する方法

![docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665011/e2d4f214-a8d1-1f14-0557-0128924a15ed.png)

本記事ではLaradockを使わずにできるだけシンプルにLaravelの環境構築を行っていきます。

####任意の場所にディレクトリを作成

```
$ mkdir myproject
$ cd myproject
```

####docker-compose.ymlファイルの作成

```Docker:docker-compose.yml
version: '3.7'

services:
  php:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: php
    volumes:
      - ./src:/var/www/html
    ports:
      - "9000:9000"
  mysql:
    image: mysql:5.7
    container_name: mysql
    ports:
      -  "3306:3306"
    volumes:
      -  ./db:/var/lib/mysql
      -  ./my_conf:/etc/mysql/conf.d
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: laravel
  nginx:
    image: nginx:stable-alpine
    container_name: nginx
    ports:
      -  "8080:80"
    volumes:
      -  ./src:/var/www/html
      -  ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      -  php
      -  mysql
```

####Dockerfileの作成

```Docker:Dockerfile
FROM php:7.4-fpm-alpine

RUN docker-php-ext-install pdo pdo_mysql
```

####Volumesの作成

```
$ mkdir db
$ mkdir my_conf
```

my_confディレクトリにmysql5.7.cnfを作成し、日本語対応できるように文字コードの設定を行います。

```mysql5.7.cnf
[mysqld]
character-set-server=utf8mb4

[client]
default-character-set=utf8mb4
```

####Nginxの設定ファイルを作成

```
$ mkdir nginx
```

nginxディレクトリにdefault.confを作成します。

```default.conf
server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        try_files $uri = 404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
```

####コンテナの作成

```
$ docker-compose up -d
```

####コンテナのステータスを確認

```
$ docker-compose ps -a

```

####Laravelのインストール

```
$ docker run --rm -v /src:/app composer create-project --prefer-dist laravel/laravel .
```

####データベースへの接続

srcディレクトリ内にある.envファイルを下記の通り編集してください。

```Laravel:.env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=password
```

.envファイルの設定が終わったら、下記のコマンドを実行してデータベースにテーブルが作成されるか確認します。

```
$ docker-compose exec php php artisan migrate
```

####開発サーバの起動

```
$ docker exec -it php php artisan serve --host=0.0.0.0 --port=8000
```

上記のコマンドを実行後、ブラウザで127.0.0.1:8080にアクセスするとLaravelのスタートページが表示されます。

![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665011/7fd56e75-6194-f8c9-08ba-a850183c9947.png)

これでLaravelにNginx経由でアクセスし、MySQLデータベースへのデータの登録まで行えることを確認しました。
地獄のチーム開発で気付いたこと

# はじめに
興味を持っていただきありがとうございます。
某IT専門学生のひかると申します。

過去の記事はかなりデザイン寄りですが、今回はチーム制作の話です。
今も尚かなり貴重な経験をしているので書き綴っておこうと思います。

あくまで、自分の経験と進行であって他の方々とは全く違うかもしれません。
私自身の伝記のつもりで書いております。
~~読むの際は、何卒ご了承の上ご反応お叩きください。:sob:~~
とは言いつつも誰かのヒントや助けになればいいなと思っています。

# 前置
現状の説明からしましょう。
とある案件を学校で扱っているのですが、数チームに分かれて開発し、優勝を決めるという形で進行しています。
つまり、チーム分けが非常に大事なのですが、、、私はインターンに行っておりチーム決めには参加できませんでした。:sob:
そして気付いてみれば教官にリーダーに任命されていて...といった状況です。
それぞれリーダーが立候補して欲しいメンツを取り合った中、余り物といっては失礼ですが、私はそんなチームを率いることになってしまいました。チームは全員で8人。

~~最初にチームを教えられた時には絶望いたしました。裏で肥溜と揶揄されていましたw~~:joy:

# 初動
物事なんでも初動が肝心です。
一応、三年間一緒のクラスにはいたので、開発に関しては大抵のことは把握しているつもりでしたが、今一度細かく色々なことを聞きました。

 1. 一番得意な言語は？
 2. どの分野を担当したいか？
 3. コーディングは好きか？
 4. どれくらいの時間を開発に当てられるか？
などなど一部抜粋ではありますが、こんなことを聞きました。

<img width="970" alt="スクリーンショット 2020-07-02 17.57.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357131/b681f565-7f17-78af-0de3-87a1447b9ae5.png">
 
驚きの結果でした。
~~嫌いって答えたやつ、なぜこの学校にいる？~~:thinking:
全くもって把握できていなかったことを反省しながら、作戦を練りました。

まずは、メンバーの分担です。

# 役割分担
知っての通り、役割分担は非常に大事です。
開発効率やメンバーのモチベーションにもかなり影響してきます。
*（ただの課題レベルな時点でメンバーにモチベなんてのはなかったわけですが。）*

まず、最優先に考えたのは、コーディングが好きと答えた私以外の二人です。
この二人は間違いなく最大戦力です。
彼ら中心の開発になるのが予測できていたので、かなり自由に動けるようにセッティングしました。
*（幸いなことに二人とも得意な言語や分野が分かれていたので悩まずに済みました。）*
バックとフロントに分かれたので、二人にはホウレンソウ以外の縛りは付けず技術選定をさせました。

残った5人。
正直、戦力としてはあまりにも拙い者たちばかり。
彼らが今まで作ってきたものも見てひとまず得意な分野に振りました。
バック：4人　フロント：3人　デザイン：1人
というバランスの分担にし、二人の元で作業に入ってもらいました。

# モチベーションの向上、維持
端からないモチベーションをどうやって持ち上げるのか。
一番の難所ですね。
幾つか試したので、まとめてみます。

#### やったこと
 - 課題であり評価に影響すると認識させる（効果中）。
 - 一週間のノルマ制にしてみた（効果無）。
 - ノルマ達成できない叱責と原因解明（効果薄）。
 - とりあえず褒めちぎる（効果中）。
 - 可能な限りアドバイスをする（効果薄）。
 - お互いの出来高を競わせる（効果薄）。
 - ペアプログラミング形式に変えてみる（効果薄）。
 - 放し飼い状態にしてみる（効果無）。
 
などなどやってみたものの、少ししか向上できず。泣

そして最後に試したのが、**チケット駆動開発**です。

#### チケット駆動開発をやってみて気付いたこと。
 - チケットに有効期限がつけると実質ノルマ制も包含。
 - チケットを終了する時に、一定の達成感を味わえる。
 - 達成感と同時に、キリが良くなるため、休憩や集中力の時zx奥に繋がりやすい。
 - お互いの出来高がよく見える。
 - 誰がどこをやっているか把握できる。
 - 自分に合った難易度のチケットを取れる。

#### 同時並行でやったこと。
 - 管生物などは一旦褒める。
 - 出来なければ原因を問い詰める。
 - アドバイスをなるべく欠かさない。
 - 日常のサポートをする（悩みなど）。
 
以上が大体やってきたことです。
その甲斐あってかメンバーのモチベはそれなりに高く（無茶苦茶高いわけではないw）保てています。

# 過去に学び今回気付けたこと
 1. ついてきてくれるメンバーの大切さ
 2. 優先順位の大切さ
 3. チームにあった開発手法の大切さ
 4. メリとハリの使い分けの大切さ
 5. 重要な授業には何がなんでも出席する大切さ
 
以上が気付けた主な学びです。
過去に組んでいたチームのメンバーの優秀さに気付けました！

# 最後に
まるで終わったかのうように書いていますが、あくまで中間報告時点の話ですw
まだ完成もしていないし、この先どうなるかはわかりません。

リーダーの在り方なんてのは、結局のところ持論でしかなく断定できるものではないです。
いわゆる正解のない問題というものだと思います。
正解はなくとも問題は飛んできます。
そして正解はなくとも不正解は存在しているようです。
（圧倒的に不利なゲームですねw嫌いじゃないですw）

まだまだリーダーとしての実力のなさや能力として低いところも垣間見えてしまいました。
修正しつつ、能力を高めつつ、経験を積んで行きたいところです。

長々と失礼いたしました。
拙い文章で伝えたいことが伝わっているのかわかりませんが伝わっていれば幸いです。

また、完全に収束したら記事にできそうなら記事にしようかなと思っています！
では、ごきげんよう。
[R] lavaanパッケージのsem実行時に「システムは正確に特異です: U[2,2] = 0」などと出るエラーの解消法の一例

# 要点

私のケースでは、以下の様に`=~`で潜在変数間に双方向のパスを作ると``システムは正確に特異です: U[2,2] = 0``といったエラーが出ました。

```R:R
# f1 f2 は潜在変数
f1 =~ f2
f2 =~ f1
```

そして、次の様に`~`に置き換えると解決されました。

```R:R
# f1 f2 は潜在変数
f2 ~ f1
f1 ~ f2
```

[共分散構造分析[Ｒ編]　--構造方程式モデリング](http://www.tokyo-tosho.co.jp/books/978-4-489-02180-0/)という本に書かれている様に、`=~`は潜在変数から観測変数へのパスを作る時に使用するのが良いのかもしれません。

# 経緯
Rのlavaanパッケージを利用して共分散構造分析（別称：構造方程式モデリング）を行っていた時次の様なエラーメッセージが表示されました。

```R:R
library(lavaan)

X <- read.csv('data.csv')

model = '
# f : 潜在変数
# x : 観測変数

f１ =~ x１ + x2 + x3
f2 =~ x4 + x5 + x6

f1 =~ f2
f2 =~ f1
'

fit <- sem(model, data=X)
```

```console:console
solve.default(tmp) でエラー: 
  Lapack routine dgesv: システムは正確に特異です: U[2,2] = 0
```

一方、次の様に`f1`と`f2`の関係を`=~`ではなく`~`で表すとエラーが消失しました。

```R:R
model = '
# f : 潜在変数
# x : 観測変数

f１ =~ x１ + x2 + x3
f2 =~ x4 + x5 + x6

# ここを変更した
f2 ~ f1
f1 ~ f2
'

fit <- sem(model, data=X)
```
VSCode + Python で, Jupyter notebook っぽいインラクティブ表示モードを使うメモ

## 背景

* Jupyter-lab で matplotlib などでプロットのインラクティブ表示などを使っているが, VSCode でも似たようなのがほしい
* `.ipynb` で VSCode で notebook モードにする手ははあるが, vim キーバインドが使えずつらい :cry:
* 素の `.py` ファイル/プロジェクトでインタラクティブプロット表示とかしてほしい

## 方法

Working with the Python Interactive window
https://code.visualstudio.com/docs/python/jupyter-support-py

Python ファイルを作成し, `#%%` と打つだけで, notebook っぽい interactive mode いけました!
(`#` と `%%` には, スペースがあってもなくてもどちらでもかまいせん)

jupyter 関連インストールされていなければ, インストールしますかポップアップ出してくれます!


![Screenshot from 2020-07-02 18-03-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/002e99bc-514e-6790-aeff-e1c137e091d3.png)


`Cell ` とかは VSCode 側でアノテーション表示されているものです.

いろいろ設定するとインライン表示もできるかも?

macOS だと, python や jupyter addon のインストール関連で注意しないとうまくうごかないかもです!

## TODO

* [ ] remote Jupyter と接続などアドバイスな機能を調べる
scoopでnodeとnpmインストールする方法のメモ

# 今更ながらscoopでnodeとnpmをインストールする方法のまとめ

## scoopインストール
Powershellを管理者権限で起動して以下を実行（細かい説明は省略）

```powershell:スクリプト実行許可
> Set-ExecutionPolicy RemoteSigned -Scope Process
```

```powershell:scoopインストール
> iex (new-object net.webclient).downloadstring('https://get.scoop.sh')
```
```powershell:scoopインストール（管理者Powershellの場合）
 iex "& {$(irm get.scoop.sh)} -RunAsAdmin"
```

```powershell:scoopコマンドの確認（Usage出ればOK）
> scoop 
```

## scoopでnvmインストール
scoopでnvmをインストール。`main bucket`にあります

```powershell:nvmインストール
> scoop install nvm
```
```powershell:nvmコマンドの確認（バージョンが出ればOK）
> nvm version
```

nvmの本体は` C:\Users\{ログインユーザ}\scoop\apps\nvm\current\nvm.exe`
追加される環境変数は`NVM_HOME`

## nvmでnode.jsインストール
nvmでnode.jsをインストール（npmも入ります）

```powershell:インストール可能なバージョンを確認
> nvm list available

|   CURRENT    |     LTS      |  OLD STABLE  | OLD UNSTABLE |
|--------------|--------------|--------------|--------------|
|    14.5.0    |   12.18.2    |   0.12.18    |   0.11.16    |
|    14.4.0    |   12.18.1    |   0.12.17    |   0.11.15    |
|    14.3.0    |   12.18.0    |   0.12.16    |   0.11.14    |
|    14.2.0    |   12.17.0    |   0.12.15    |   0.11.13    |
|    14.1.0    |   12.16.3    |   0.12.14    |   0.11.12    |
～以下、略～
```

LTSの最新版`12.18.2`を入れます。

```powershell:nodeのインストール
> nvm install 12.18.2 
```

インストールしただけだとまだ使えないので、使用するバージョンを指定します。
※ここで環境変数やPATHが追加されます

```powershell:nodeの利用バージョン指定
> nvm use 12.18.2 
```

nodeの本体は`C:\Users\{ログインユーザ}\scoop\apps\nvm\current\nodejs\nodejs\node.exe`
追加される環境変数は`NVM_SYMLINK`

```powershell:nodeのバージョン確認
> node -v
```

```powershell:npmのバージョン確認
> npm -v
```
DocumentDBって何？

# はじめに
この記事はMongoDBをまったく知らない筆者がゼロからDocumentDBを学んでまとめたものになります。
今までのDBの経験といえば
- MySQL(2年とか)
- Redis(半年とか)
- DynamoDB(3ヶ月とか)
- Spanner（１瞬）
ぐらいでNoSQLよリRDBMSの方が歴も長く、得意といった感じです。
DB設計はいくつかのサービスで経験しましたが、設計＆運用をした経験がほとんどないので、
スケールにめっちゃ自信があるわけではないですが、スケールを考えたキーの命名とかはRedis、DynamoDBあたりでは徹底的に議論した覚えがあります。それでは徒然なるままに始めていきたいと思います。

## MongoDBとは
NoSQLといえば、シンプルな検索機能が大きなメリットといえます。
KVSのNoSQLであれば、データをキーバリューの連想配列で保持して検索のスピードが速いです。
RedisはKVSで私は主にC向けのサービスを作っていた時はランキング機能に使っていました。
データが単純だが、件数が多いとRedisを使うと良いという認識でした。
また、Redisはキャッシュとしても有名ですよね。
今回のMongoDBはドキュメント指向データベースと呼ばれる種類のデータベースです。
DynamoDBと同じ種類ですね。
ドキュメント指向データベースでは、文字通りデータをドキュメントとして扱います。
ドキュメントのデータ構造は自由で、スキーマレスでスケールがしやすいのがメリットといえます。

## そもそもNoSQLってなんで生まれたん？
最後にDynamoDBを触ったのが半年近く前なのでNoSQLについて忘れてしまいました。
簡単に復習します。
NoSQLが生まれた理由はビッグデータの登場が大きいらしいです。
ビッグデータの定義は様々ですが、ここでのビッグデータは３V（Volume,Velocity,Variety）を満たしたデータということにして起きます。
ビッグデータの登場以前は、構造化されたデータを扱うクライアント・サーバサイド型のアプリケーションが主流でした。
古典的なRDMSはACIDプロパティに従います。
Atomic、Consistent、Isolated、Durableでしたね確か。
一貫性を保証するよってことです。
複数の書き込み処理や変更の処理が走ってもどのトランザクションを通してデータが一貫していることが大切です。
ビッグデータの3Vの２つ、Volume（大量のデータ）、Velocity（高頻度で高速）に対応するにはスケールを考える必要があります。
スケールは2種類あって、スケールアップ、スケールアウトの２つです。
スケールアップは個々のDBサーバの性能をあげること（メモリ容量、CPUのスペック上げるorCPUの数を増やす）で、スケールアウトはDBサーバの数を増やして全体の処理性能を上げることです。
並列処理が行われるような設計にする必要がありますが、今のクラウドだと負荷を検知して自動でスケールしてくれるサービスもあるのであまり意識しなくても良いのかもしれません。

## DynamoDBと何が違うの？
DynamoDBもDocumentDBと同様にNoSQLです。
1番の違いと言えば、アクセスパターンが多いことです。
具体的にDynamoDBとの1番の優位性はindexに依存しないクエリが可能なことと菊池さんもおっしゃっています。

https://www.slideshare.net/skikuchi/jaws-days-2019-amazon-documentdbwith-mongodb-compatibility


また、DocumentDBではネストしたデータのフィールドにもインデックスが貼れるらしいです。

## DocumentDBのプロコン
### プロ
#### 高速＆スケーラブル
ストレージの量がすっごい　６４TB
#### 高可用性
可用性が99.99%
インスタンスに障害が発生したらインスタンスを30秒以内で再起動
マスターインスタンスが死んだらリードレプリカに自動でフェイルオーバー

### コン
#### トランザクションがない
MongoDBのバージョン４以降ではトランザクションの処理が加わるらしいですが、
現在DocumentDBが対応しているMongoDBのバージョンは3.6です。

#### データ量が多くなりがち
RDBと比べるとデータ量が多くなりがちらしいです。なんでだろう保存の仕方が問題なのか。DB設計上データ量が多くなる？知っている方がいたら教えて欲しいです。


## まとめ
DocumentDBは2019年1月に発表されて現在は東京リージョンもあるAWSの完全マネージド型のドキュメント指向データベースです。
インデックスの貼り方をミスらなければかなり良いDBな気がしました。
これから具体的なサービスに落とし込んでいきたいと思います。いい感じにTipsを共有していきっます
ディレクトリのファイルを1ファイルづつ圧縮する

サンプルとしてログファイルを1ファイルづつ圧縮するものが以下になります。

`ls ./*.log | xargs -n1 -i tar cvzf {}.tar.gz {}`

ls コマンドで引っかかるものを圧縮していくアレです。
割と使うと思うので。
Google BigQueryのデータをData Portalで可視化する

TableauやGoogleデータポータルなどのBIツールは、今やデータ分析業務で欠かせないものになりました。SQLでデータを抽出しダッシュボード化するスキルは、省力化にもつながることからデータ分析の現場で役に立つことも多いのではないでしょうか。今回は、Google BigQuery内のデータを、SQLを介してデータポータルで可視化してみたいと思います。

①まずはBigQueryにアクセスし、テーブルを作成します。今回はKaggleのオープンデータから、iOSアプリの価格や評価などをまとめたデータセットを使用しました（手順は以下URL参照）。

BigQueryを使ったデータ抽出・集計
https://qiita.com/esaeki/items/53ad9ed1b7c2f7ed5c75

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265091/df6065c3-0764-d36c-a6b7-3b7de2d74611.png)

②作成したテーブルに対して、下記のSQLクエリを実行します。今回は、アプリの価格の平均値を、ジャンルごとに集計してみました。

```
select
  prime_genre, round(avg(price))
from 
  `starry-center-282006.test01.table01`
group by
  prime_genre;
```

③クエリを実行後、ページ中段の「データを探索」→「データポータルで調べる」から、データポータルに遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265091/a1c60eee-6a4e-f74e-04ba-fd228deaa722.png)

④遷移後は以下のようになります。ページ右側から使いたいグラフの種類を選択、ディメンションや指標を設定することで、ビジュアライゼーションを作成できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265091/e9432c61-5a2f-06a7-bdc7-e1d0110bc684.png)

今回は棒グラフを作成してみました。Medicalの平均額が突出して高い一方、Food&DrinkやBookなどの数値が低いことが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265091/9457a5a8-7089-60b0-366d-fc041fa89e8b.png)

⑤このビジュアライゼーションは、データポータル内の「エクスプローラ」に保存され、「レポート」側から呼び出すことも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265091/9329c27e-f70c-362a-29fe-d7fc831e1588.png)

「レポート」タブ→「空のレポート」で新規のダッシュボードを作成し、新規で棒グラフを追加、データソースで先ほど作成したエクスプローラのデータを指定することで、同じグラフをレポート内に呼び出すことができます。他のグラフや表と合わせて、ひとつのダッシュボードにまとめることが可能です。

![Capture1111.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265091/a17f7516-7ecc-daa2-33e1-e1ba80bf4f2b.png)

Tableauと接続すれば、より多様なビジュアライゼーションを作成することができるでしょう。また機械学習ツールのBigQuery MLを使えば、BigQuery上でSQLクエリを使って機械学習モデルを作成し、さらにBIツールで可視化できます。BigQuery MLについては、また次の機会に試してみたいと思います。
PostgreSQLで特定のテーブルの一部のデータをエクスポート・インポートするコマンド例

## はじめに

ちょっとわけあって、PostgreSQLの一部のデータをあるDBから別のDBにコピーする必要がありました。
そのときに使ったコマンドをメモしておきます。

## 特定のテーブルの一部のデータをエクスポートする

### psqlを実行するマシンとDBサーバーが同一の場合

psqlのコンソールからCOPYコマンドを実行し、適当なファイルにデータを出力する。

```sql
COPY (SELECT * FROM users WHERE status = 'active') TO '/tmp/users.csv' WITH CSV HEADER;
```

### psqlを実行するマシンとDBサーバーが異なる場合

ターミナル上からpsqlコマンドでCSVデータを標準出力に出力し、その内容を適当なファイルにリダイレクト（`>`）する。

```console
# 一時的にDB接続用のパスワードを環境変数にセット（historyに残らないように先頭にスペースを入れる）
 export PGPASSWORD=password1234

psql \
  -c "COPY (SELECT * FROM users WHERE status = 'active') TO STDOUT WITH CSV HEADER;" \
  -h your-host-name \
  -U your-user-name \
  -d your-db-name > /tmp/users.csv
```

## 上記の方法でエクスポートしたデータをインポートする

インポートしたデータは既存のテーブルに追記される。（全データが置きかわるわけではない）
そのため、ユニーク制約等に違反すると取り込めない（はず）。

### 注意点

データのインポートはいきなり本番環境で実行したりせず、まずローカルやステージング環境で試して期待どおりのインポートが行われるか検証しましょう。
また、本番環境でインポートする場合は万が一のトラブルに備えて、インポート前にデータベースのバックアップを取っておきましょう。

### 免責事項

本コマンドを参考にして何らかの損害が発生したとしても、筆者はいかなる責任も負いません。

### psqlを実行するマシンとDBサーバーが同一の場合

psqlのコンソールからCOPYコマンドを実行する。

```sql
COPY users FROM '/tmp/users.csv' (FORMAT CSV, HEADER true);
```

### psqlを実行するマシンとDBサーバーが異なる場合

標準入力経由でCSVファイルの内容をpsqlのCOPYコマンドに引き渡す。

```console
# 一時的にDB接続用のパスワードを環境変数にセット（historyに残らないように先頭にスペースを入れる）
 export PGPASSWORD=password1234

cat /tmp/jit_test.csv | \
  psql -c "COPY users FROM STDIN (FORMAT CSV, HEADER true);" \
  -h your-host-name \
  -U your-user-name \
  -d your-db-name
```

## おまけ：特定のテーブル（複数）をダンプ・リストアする

上記のユースケースとは別に、特定のテーブル（複数）を全件ダンプし、リストアする場合のコマンド例。

```console
# 一時的にDB接続用のパスワードを環境変数にセット（historyに残らないように先頭にスペースを入れる）
 export PGPASSWORD=password1234

# users、companies、ordersの3テーブルをダンプする
pg_dump \
  --column-inserts \
  -t users -t companies -t orders \
  -h your-host-name \
  -U your-user-name \
  -d your-db-name
  > /tmp/dump.sql

# ダンプからリストアする（users、companies、ordersの3テーブルがリストアされる）
psql \
  -h your-host-name \
  -U your-user-name \
  -d your-db-name
  < /tmp/dump.sql
```
【Folio LSP】チュートリアル②VM概要

この記事では、Library Service PlatformのOpen Sourceプロジェクトである、Folioのチュートリアルを解説します。

前記事：[チュートリアル①ワークスペースを作ってVMを立ち上げる](https://qiita.com/ayungn/items/45c3f8bbe419308106a6)

- 参考URL：https://dev.folio.org/tutorials/folio-vm/02-system-overview/
- VagrantBoxのOkapi、Docker、Postgresについてさらに詳しく知りたい方は[FOLIO system setup on Vagrant boxes](https://github.com/folio-org/folio-ansible/blob/master/doc/index.md#folio-system-setup-on-vagrant-boxes)をご覧ください。

##前提
[チュートリアル①ワークスペースを作ってVMを立ち上げる](https://qiita.com/ayungn/items/45c3f8bbe419308106a6)を参考に、Vagrantが立ち上がった状態にする。

##ログを見る
`vagrant ssh`

####Okapiのログ
`less /var/log/folio/okapi/okapi.log`

####Stripesのログ
`docker logs stripes_stripes_1`
※StripesはDockerコンテナになっています。
※--followオプションを付けるとログを追えます。

####バックエンドのモジュールのログ
バックエンドモジュールは、OkapiがDockerコンテナとしてデプロイしています。

#####モジュール名をグレップ
`docker ps | grep inventory`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342082/450eaac9-d3cb-f3ed-2597-f8790c152523.png)

※`docker ps`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342082/53722d48-d41b-e3fd-b69f-fdd9cb819e36.png)


#####モジュールのログを見る
`docker logs <container_name>`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342082/829fd04c-5579-bf18-60ca-5756e19ccfae.png)

##補足
[FOLIO system setup on Vagrant boxes](https://github.com/folio-org/folio-ansible/blob/master/doc/index.md#folio-system-setup-on-vagrant-boxes)より抜粋
『構築済みのVagrantボックスには、本番環境を模したFOLIOスタックがセットアップされています。OkapiはDebianのインストールパッケージを使ってインストールされ、ホームディレクトリは/usr/share/folio/okapi、設定ファイルは/etc/folio/okapi、ログは/var/log/folio/okapiとなっています。バックエンドモジュールは、そのDockerデプロイ機能を使用して、Okapiを通じてデプロイされます。okapi-deploy systemdサービスユニットは、バックエンドモジュールの起動と停止を管理するために使用されます。モジュールは、/etc/folioにある設定ファイルと/usr/share/folioにある静的ファイルの慣例に従ってインストールされます。Stripesは、再起動時に再起動するように設定されたDockerコンテナとしてインストールされます。

データは、Vagrantボックス上で稼働しているPostgreSQLサーバを使用して、すべてのモジュールについて永続化されます。Dockerエンジンもインストールされており、Vagrantボックスのlocalhost:4243をリスンするように設定されているので、Okapiがモジュールのデプロイに利用できるようになっています。』

www.DeepL.com/Translator（無料版）で翻訳しました。

##参考
- とほほのDocker入門 http://www.tohoho-web.com/docker/

##変更履歴
2020年7月2日　新規作成
Numpyのeinsumを使って３次元配列の掛け算

知り合いに簡単に3次元配列の掛け算をする方法を聞かれ、調べてみたらNumpyのライブラリにアインシュタインの縮約記号を用いたeinsumというのがありこれを使えば楽にできそうなのでやってみました。

１ｘ２ｘ５の3次元行列と２ｘ３ｘ５の三次元行列をまず適当に2つ作ります。



```math
A = 
\left(
\begin{matrix}
a_0 & a_1
\end{matrix}
\right)
, a_0 = 
\left[
\begin{matrix}
0 & 1 & 1 & 0 & 0
\end{matrix}
\right]
, a_1 = 
\left[
\begin{matrix}
0 & 1 & 0 & 0 & 1
\end{matrix}
\right]
```
```math
W = 
\left(
\begin{matrix}
w_0 & w_1 & w_2 \\
w_3 & w_4 & w_5
\end{matrix}
\right)
, w_0 = 
\left[
\begin{matrix}
0 & 1 & 2 & 3 & 4
\end{matrix}
\right]
, w_1 = 
\left[
\begin{matrix}
5 & 6 & 7 & 8 & 9
\end{matrix}
\right]
...
```

これをnumpyを使って作成すると、

``` 
A = np.array([[[0,1,1,0,0],
               [0,1,0,0,1]]])

W = np.arange(30).reshape(2,3,5)
```

で出来ます。

このAの行列の形状（１，２，５）をアインシュタインの縮約記号で（i, j, k)で表します。
同じようにWの行列の形状（２，３，５）を（j, l, k)で表します。

この２つの行列を掛け算すると、（１，３，５）の行列になるはずなのでeinsumを使った式はこうなります。

``` 
R = np.einsum("ijk,jlk -> ilk",A,W)

print(R)
print(R.shape)
``` 
実行するとRはこうなります。

``` 
[[[ 0 17  2  0 19]
  [ 0 27  7  0 24]
  [ 0 37 12  0 29]]]

(1,3,5)
``` 

無事、１ｘ３ｘ５の３次元行列の結果になりました。

参考（英語）：
- https://stackoverflow.com/questions/26089893/understanding-numpys-einsum
Axios で Node.js で発行した S3 の署名付き URL へアップロードすると 403 エラーになるときに確認したいこと

Nuxt.js から Node.js に S3 の署名付き URL をリクエストするような状況でつまったところの忘備録です。

# TL;DR

ドメインが違う → CORS 設定に気をつけよう
サーバーサイドに Node.js 使ってる → SDK の署名バージョンに気をつけよう
フロントに Axios 使ってる → 余計なヘッダーを送らないように気をつけよう

# s3 の Bucket の CORS 設定をする

s3 のドメインとサイトのドメインが異なるなら設定しておきましょう。
アップロードのみできれば良いなら許可は PUT だけで良いと思います。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>
```

# リージョンを指定する
# 署名バージョンを 4 に指定する

無いと失敗するようです…？

AWS_DEFAULT_REGION などは内部で勝手に使ってくれると思っていたのですが指定したほうが良さそうです。

```ts
// on server
const sts = new STS({
  accessKeyId: process.env.ACCESS_KEY_ID,
  secretAccessKey: process.env.SECRET_ACCESS_KEY,
  region: process.env.AWS_DEFAULT_REGION, // ★
})
app.get('/get-signed-url', async (req, res) => {
  const { Credentials } = await sts
    .assumeRole({
      RoleArn: process.env.STS_ROLE_ARN,
      RoleSessionName: process.env.STS_ROLE_SESSION_NAME,
    })
    .promise()
  if (!Credentials) return Promise.reject(new Error('failed to get credencials'))
  const s3 = new S3({
    accessKeyId: Credentials.AccessKeyId,
    secretAccessKey: Credentials.SecretAccessKey,
    sessionToken: Credentials.SessionToken,
    region: process.env.AWS_DEFAULT_REGION, // ★
    signatureVersion: 'v4', // ★
  })
  const Key = randomString(128)
  const putUrl = await s3.getSignedUrlPromise('putObject', {
    Bucket,
    Key,
    ContentType: req.query.mimetype,
    Metadata: { 'user-name': 'hogehoge' },
    Expires: 60,
  })
  res.json({ putUrl, Key })
})
```

# 余計なヘッダーを送らないようにする

put するときに余計なヘッダーをつけて送ると 403 SignatureDoesNotMatch が返ってきます。
Axios のデフォルトの headers に Authorization を入れている場合などは注意が必要だと思います。

```ts
// front
export default Vue.extend({
  methods: {
    async upload(rawFile: File) {
      const prepareUrl = new URL(process.env.API_URL + '/get-signed-url')
      prepareUrl.searchParams.append('filename', rawFile.name)
      prepareUrl.searchParams.append('mimetype', rawFile.type)
      this.$axios.setToken(this.$store.getters['auth/accessToken'], 'Bearer')
      const { putUrl } = await this.$axios.$get(prepareUrl.toString())

      this.$axios.setToken(false) // ★ Authorization ヘッダーが送られないように
      await this.$axios.$put(putUrl, rawFile, {
        headers: {
          'Content-Type': rawFile.type,
          // 'X-Amz-Acl': 'private', // ★ 間違えてつけてると 403 になります
        }
      })
    }
  }
})
```

# 参考

https://qiita.com/kochizufan/items/444b7e1dfcf568945410
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/cors.html
https://qiita.com/kyasbal_1994/items/774be5624e4d90c5cf38
https://qiita.com/segur/items/7746ac352afb5152cf46
備忘録　会計freeeAPI叩いた時ハマったこと

## GETでクエリ指定する場合は、ちゃんとuri.request_uriでhttp通信しようね

これに尽きます、会計freeeのAPI仕様とかじゃなくただ単に自分の凡ミスだった。


###rubyで叩いた

OAuth(オーオース)2.0でACCESS_TOKENは取得済み。
こんな感じでパラメーターをセットして

```ruby
BASE_URL = 'https://api.freee.co.jp'
MY_COMPANY_ID = '*********'
USE_ACCESS_TOKEN_HEADER = {
  "accept" => "application/json",
  "Authorization"=> "Bearer *************************"
}
```

以下のように取引先の詳細を取得するAPIを叩いたところ
(分かりやすくかなり単純なメソッドにしてます)

```ruby
def get_torihikisaki_id(name)
   uri = URI.parse(BASE_URL + '/api/1/partners')
   uri.query = URI.encode_www_form({"company_id" => MY_COMPANY_ID ,'keyword'=> name})
   http = Net::HTTP.new(uri.host, uri.port)
   http.use_ssl = true
   headers = USE_ACCESS_TOKEN_HEADER
   response = http.get(uri.path, headers)
   res_hash = JSON.parse(response.body)
end

puts get_torihikisaki_id('hoge株式会社')
```
このようなレスポンスになった。

```
{"status_code"=>400, "errors"=>[{"type"=>"validation", "messages"=>["company_id が指定されていません。"]}]}
```

company_id指定してるのになぁ〜
なんでだろうなー
かなり考え込んでしまいました。

###原因

この一文

```ruby
response = http.get(uri.path, headers)
```

uri.pathのみでhttp通信を行なっていた。
クエリ設定してるのに使ってないじゃん、、、
正しくは

```ruby
response = http.get(uri.request_uri, headers)
```

GETでurlにパラメーター埋め込む時は、ちゃんと使わないとですね、、、




日々精進
アラート表示

#アラートを表示する

```ruby:swift
 SimpleAlert.showAlert(viewController: self, title: "タイトル", message: "内容を描いてください", buttonTitle: "OK")
```

#アラート表示

```ruby:swift
import UIKit
struct SimpleAlert {
    static func showAlert(viewController: UIViewController, title: String, message: String, buttonTitle: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let okAction = UIAlertAction(title: buttonTitle, style: .default) { (action) in
            alert.dismiss(animated: true, completion: nil)
        }
        alert.addAction(okAction)
        viewController.present(alert, animated: true, completion: nil)
    }
}
```
Cloud9のMySQLをバージョンアップする方法

![mysql.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665011/652fc1f3-5134-5827-b92a-1860d9d98518.png)

####現時点でのMySQLバージョンを確認

```
$ mysql --version
```

####旧バージョン（5.5）パッケージを削除

```
$ sudo yum -y remove mysql-config mysql55-server mysql55-libs mysql55
```

####新バージョン（5.7）パッケージをインストール

```
$ sudo yum -y install mysql57-server mysql57
```

####日本語文字化け対策

```
$ sed -e "/utf8/d" -e "/client/d" -e "/^\[mysqld_safe\]$/i character-set-server=utf8\n\n[client]\ndefault-character-set=utf8" /etc/my.cnf |sudo tee /etc/my.cnf
```

####MySQLの起動

```
$ sudo service mysqld start
```

####設定を読み込み直すために再起動

```
$ sudo service mysqld restart
```

####MySQLのバージョンを確認

```
$ mysql --version
```

バージョンが5.7になっていれば成功です。

####MySQLコンソールに接続して動作確認

```
$ mysql -u root
```

データベースに接続してみて問題がないか確認します。
Vim ノーマルモード zt/zb 押下時のスクロールにオフセットを加える

Vimのノーマルモードで `zt` をタイプすると, カーソルの位置 (行) はそのままで,
カーソルが画面最上部に表示されるようにスクロールされます.
`zb` の場合は, カーソル位置が画面最下部になるようスクロールされます (t=top, b=bottom).

カーソル位置が61行目の状態で `zt` をタイプすると, 次のようにスクロールされるということです.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549855/7fb0c00f-df34-1b64-db5b-104168566785.png)

ところで, [Vim Bootstrap](https://vim-bootstrap.com/) で作ったvimrcで同じ操作をすると, 次のようにスクロールされました.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549855/3ee84c39-3330-8096-44d7-0bfc314e9bb9.png)

カーソル位置の上に3行分が表示される形で画面スクロールされます.
これ, 1行ずつ上へカーソル移動しても同様で, 3行分オフセットされる形で画面がスクロールしていきます.
下方向のスクロール (`zb`, `j`) についても同じです.

理由は `scrolloff` というオプションが作用しているためです.
`:set scrolloff=0` を実行するか `set scrolloff=0` を `.vimrc` などに追記すると,
オフセットされない形でのデフォルトの挙動に戻すことができます.
SharePoint Framework の開発環境を Docker を使って構築する際の npm install のエラーの対処

2021/5/26追記

1.12.1で本記事の方法で実行するとエラーになるっぽいです。
参考サイト通りにやりましょう。
以下でやっても一応できます。

https://qiita.com/nanoka/items/2e9f49750e973782b6fe

ここまで

***


SharePoint Framework を使った開発は、そのバージョンアップの頻度から Docker など使った環境構築がおすすめされています。しかしながら、Docker Desktop for Windows を使った環境構築において、npm install でうまくいかない部分があり、あくまで場当たり的対応ですが解消するまで苦労しましたので備忘録として残します。

#遭遇したこと
Dockerコンテナ起動後、npm install gulp、yo @microsoft/sharepoint でいろんなエラーがでて作業が進まない。ページ下部の③のリンクのエラーがでたり、コンテナがハングアップしたかのように動作が遅くなり、先に進むことができない。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ありがとうございます。<a href="https://t.co/m1CslvAZRE">https://t.co/m1CslvAZRE</a><br>この及川さんの記事みながらやっていたのですが、以下のようなエラーで躓いてました。npmのキャッシュ消したりいじくりながらまたやってみます。<br>Error: EEXIST: file already exists, copyfile &#39;/home/spfx/.cache/yarn/v6/npm-ms-0.7.1-.... <a href="https://t.co/SpFzSsX7MD">pic.twitter.com/SpFzSsX7MD</a></p>&mdash; nan_oka (@nanoka7o8) <a href="https://twitter.com/nanoka7o8/status/1272732417220984833?ref_src=twsrc%5Etfw">June 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


#対応したこと
④のリンクを参考にして、マウントしているディレクトリでないディレクトリで npm install した後、一式をマウントしているディレクトリに移動します。

1.コンテナの起動

```ruby:powershell
docker run -it --rm --name [コンテナ名] -v [プロジェクトディレクトリ]:/usr/app/spfx -p 5432:5432 -p 4321:4321 -p 35729:35729 waldekm/spfx:1.10.0
```

2.一時作業ディレクトリへの変更と、gulp インストール

```ruby:docker
cd /tmp
npm install gulp --no-bin-links
```
yarn add でも可(ただし--no-bin-linksが有効かは不明)

3.yo の実行

```ruby:docker
yo @microsoft/sharepoint --package-manager npm --skip-install
```
package-manager yarn でも可

4.spfx に必要な npm のインストール

```ruby:docker
npm install --no-bin-links
```
yarn install でも可(ただし--no-bin-linksが有効かは不明)

5.マウントしたプロジェクトディレクトリへのファイルコピー

```ruby:docker
mv * .[^\.]* /usr/app/spfx
```

6.プロジェクトディレクトリで開発を続ける！

#まとめ
原因はわかっていませんが、何度か試してもこれならエラーにならないので、とりあえずはいけそうな気がします。
環境さえできてしまえば、JavaScriptが少し触れる方ならどんどんアプリを作っていけるSpfx。環境構築で躓いてやめてしまうのはもったいないので、(SPS2013のクラシックサイトのカスタマイズなんかやめて)是非みんなでやりましょう！！！
なお、小さめのモジュールなら、npm install してもエラーになりにくいので、この後の追加に関しては直接やっても問題ないです。

#環境構築作業の参考にさせていただいたブログ
>①SharePoint Developer SharePoint Framework 開発入門 まとめ
https://sharepoint.orivers.jp/sharepoint-framework-dev

#対応方法の参考にさせていただいたブログなど
>②Rencore Try SharePoint Framework without installing it 
https://rencore.com/blog/try-sharepoint-framework-without-installing/
>③[Windows][Docker] nodeコンテナでnpm installが動かず地獄を見た
https://qiita.com/yagrush/items/5fb64f878e4b9940a4ee
>④WindowsのDocker環境でnpm install実行時にエラーが出た場合の対処法メモ
https://qiita.com/Y-Kanoh/items/58815aafb7346930f370

#感想
Twitterでつぶやいてみたら、大変ありがたいことにいろいろな方々が確認してくださり、特に工夫しなくてもうまくいっているようでした。大感謝です！

レアな事象なのかわかりませんが、同じ事象に遭遇した場合の助けになれば幸いです。
コンテナもWindowsにしてしまえばうまくいくのでしょうか。。。
【Rails】APIモードで開発を始めたけど、やっぱりcookie使いたい

# はじめに
自分用なので手順しか書かない

# 手順

## controllerに追記
controllerでcookiesを呼び出す時の話
APIモードだと `cookies` がそもそも呼び出せない

ApplicationController か、cookiesを呼びだすcontrollerに以下を追加

```ruby
include ActionController::Cookies
```

## middleware追加
middlewareを追加しないとcookieの読み出しも書き込みも実際してくれない


application.rbに以下の2行を追加

```ruby
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
```

# おわり
ここまでやるとDeviseも自然にset-cookie返してくれるようになります
基本はDevise + jwtでやってたんですけど、API経由ではないルート追加することになり、header渡せず無事死亡しました