OmniAICreator/Qiita-1.07M huggingface dataset:
Gemとrbenvとbundlerって何？


プログラミング言語を勉強したいな〜、と思って環境を構築しようとするとよく出てくるのが、そのプログラミング言語の周辺に存在するツール達。これって何してるんだっけ？と何度も検索するハメになるので、ひとまずRubyについてまとめてみました。

#Gemとは
Rubyのパッケージ管理ツールの事。
では、パッケージ管理とは？
インストール、アンインストール、バージョン管理などを行うもの。（Linuxのyum、apt-getみたいなもの？）


Gemを使ったインストール方法

```
$ gem install --no-document rails 
```

#bundlerとは
Gem扱うパッケージの個別の依存関係を解決してくれて、インストールしてくるもの。


#rbenvとは
複数のRubyのバージョンを管理するもの。
例えば、2.4.0と2.5.0を使い分けたいな。って時に使う。

rbenvでRubyバージョンを指定してインストールする方法

```
$ rbenv install 2.5.0
```
ElasticBeanstalkのcontainer_commandで複数行のコマンドを使う

YAMLブロックで普通にできた。

```yaml
container_commands:
  # Remove all nginx site configuration
  10-greetings:
    command: |
      if [[ -f greetings.txt ]]; then
        cat greetings.txt
      else
        echo "no greetings file found"
      fi
```

できないと思ってたので以前は下記のようにしていたが、明らかに可読性は上記のほうが良い。

```yaml
    command: "[[ -f greetings.txt ]] && cat greetings.txt || echo 'no greetings file found'"
```
Laravel5でHTTPレスポンスのヘッダー追記をAfterミドルウエアを作成してWebサイト全体に適応する。

# HTTPレスポンスヘッダーを追加するAfterミドルウエアを作成してWebページ全体に適応する。

- セキュリティ対策などサイト全体に反映したいのでミドルウエアにする。

## ミドルウエア作成

``` php
% php artisan make:middleware AddResponseHeaders
Middleware created successfully.
```

- app/Http/Middleware/AddResponseHeaders.php　を編集

```php5

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        $response->header('TEST-HEADER',            'hoge');
        $response->header('Cache-control',          'no-store');
        $response->header('Pragma',                 'no-cache');
        $response->header('X-Frame-Options',        'Deny');
        $response->header('X-Content-Type-Options', 'nosniff');
        $response->header('X-XSS-Protection',       '1; mode=block');

        return $response;
    }
```

## ミドルウエアをWebページに適用

- ミドルウエアグループの「web」の配列に追記する。
- routes/web.php に記述してあるルートのHTTPレスポンス全部に反映。
- app/Http/Kernel.php を編集

```php5

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\AddResponseHeaders::class,// <- 追記する
        ],
```

- ミドルウエアがwebになっているルート全てに反映される。

```php
% php artisan route:list
+--------+----------+----------+------+---------+--------------+
| Domain | Method   | URI      | Name | Action  | Middleware   |
+--------+----------+----------+------+---------+--------------+
|        | GET|HEAD | /        |      | Closure | web          |
|        | GET|HEAD | api/user |      | Closure | api,auth:api |
|        | GET|HEAD | test     |      | Closure | web          |
+--------+----------+----------+------+---------+--------------+

```

### HTTPヘッダーを確認

```
% php artisan serve
Laravel development server started: <http://127.0.0.1:8000>
```

- ブラウザでhttp://127.0.0.1:8000/　にアクセス。
- デベロッパーツールのNetworkで127.0.0.1を選択してHeadersタブのResponse Headersに項目が追加されていることを確認。

<img width="810" alt="スクリーンショット 2018-05-06 11.34.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/9907/5b0804ed-4384-a790-769d-31a60bf52701.png">
PowerShellでMattermostにログインしてポストする

# 環境
PowerShell 5.1.14409.1012
Mattermost 4.8.0

# PowerShellのスクリプト

```shell

$loginResponse = Invoke-WebRequest -Uri "http://localhost:8065/api/v4/users/login" -Method POST -Body '{"login_id":"yourID","password":"yourPassword"}'
$token = $loginResponse.Headers.Token
$utf8PostBody = [System.Text.Encoding]::UTF8.GetBytes('{"channel_id":"xxxxxxxxxxxxxxxxxxxxxxxxxx","message":"出社！"}')
Invoke-WebRequest -Uri "http://localhost:8065/api/v4/posts" -Method POST -Body $utf8PostBody -Headers @{"Authorization" = "Bearer $token"}
```

* **http://localhost:8065** :仮のMattermostサーバのパス。
* **channel_id** :WebGUIのチャンネル名をクリックし、情報を表示するを選択し確認する。
* **[System.Text.Encoding]::UTF8.GetBytes()** messageに全角文字を指定したさいに文字化けさせないため記述。
PlantUMLコピペ用サンプル

# 導入方法
https://qiita.com/couzie/items/9dedb834c5aff09ea7b2

# シーケンス図
![SequenceA.png](https://qiita-image-store.s3.amazonaws.com/0/214268/3141fb25-d89c-8ad9-10be-27ef6cdfe457.png)

```txt:sequence.pu
/'
PlantUML sample
'/
@startuml
title SequenceA

'Replace name
participant "モジュールA" as ModuleA
participant "モジュールB" as ModuleB

== Sync Call ==
[-> ModuleA : start sync
activate ModuleA
ModuleA -> ModuleB : sendMsgSync(10, "a")
activate ModuleB
ModuleB -> ModuleB : do something()
ModuleA <-- ModuleB : response(OK)
deactivate ModuleB
ModuleA -> ModuleA : do something()
deactivate ModuleA

'space
|||	

== Async Call ==
[-> ModuleA : start async
activate ModuleA
ModuleA ->> ModuleB : sendMsgAsync(10, "a")
activate ModuleB
ModuleB -> ModuleB : do something()
ModuleA -> ModuleA : do something()
ModuleA <-- ModuleB : response(OK)
deactivate ModuleB
deactivate ModuleA

== Other sample ==
[-> ModuleA : Note, color
activate ModuleA
ModuleA -> ModuleB : sendMsgSync(<s:#FF0000>10
<color:red> 20</color>, "a")
note left #FF0000 : 引数変更 (ver 1.3)
activate ModuleB #00FF00
ModuleB -> ModuleB: do something()
ModuleA <-- ModuleB : response(OK)
note right
常にOKを返す
end note
note over ModuleB: 無限待ち
deactivate ModuleB
deactivate ModuleA

[-> ModuleA : loop
activate ModuleA
loop for each item
	ModuleA -> ModuleA : do something()
	break item = error
		ModuleA -> ModuleA : treatError()
	end
end
deactivate ModuleA

[-> ModuleA : ifelse
activate ModuleA
alt data < 50
	ModuleA -> ModuleA : do something()
else data < 100
	ModuleA -> ModuleA : do something()
else other
	ModuleA -> ModuleA : do something()
end
deactivate ModuleA

[-> ModuleA : opt
activate ModuleA
opt data == 100
	ModuleA -> ModuleA : do something()
end
deactivate ModuleA

[-> ModuleA : create
activate ModuleA
create ModuleC
ModuleA -> ModuleC : <create>>
ModuleC -> ModuleC : do something()
destroy ModuleC
deactivate ModuleA

[-> ModuleA : reference
ref over ModuleA, ModuleB
	Refer to
	SequenceY
end ref
deactivate ModuleA

@enduml
```

# 状態遷移図
![StateMachine_CancelChattering.png](https://qiita-image-store.s3.amazonaws.com/0/214268/ba6bc9de-ca8a-ba54-bad0-3f7613f9896f.png)

```txt:stateMachin.pu
/'
PlantUML sample
'/
@startuml
title StateMachine_CancelChattering

[*] -down-> StateOff
StateOff -down-> StateOff2On : button pushed / cnt_on = 0

StateOff2On: entry / 
StateOff2On: do / Check button status every 10msec
StateOff2On: exit / 
StateOff2On -> StateOff2On : button pushed [cnt_on < 5] / cnt_on++
StateOff2On -up-> StateOff : button released / cnt_on = 0
StateOff2On -down-> StateOn:  button pushed [cnt_on == 5] / 

StateOn -up-> StateOn2Off : button released / cnt_off = 0
StateOn2Off: entry / 
StateOn2Off: do / Check button status every 10msec
StateOn2Off: exit / 
StateOn2Off -> StateOn2Off : button released [cnt_off < 5] / cnt_off++
StateOn2Off -down-> StateOn : button pushed / cnt_off = 0
StateOn2Off -up-> StateOff:  button released [cnt_on == 5] /

@enduml
```
CLispで東大数学解いてみた(東ロボ君的文脈ではありません)

Common Lispに入門したので技術メモを投稿します．Qiita入門も兼ねています．どうぞよしなに(´・ω・`)

#いきさつと概要

吉田武教授が東海大学出版から[素数夜曲―女王陛下のLISP](https://www.amazon.co.jp/%E7%B4%A0%E6%95%B0%E5%A4%9C%E6%9B%B2%E2%80%95%E5%A5%B3%E7%8E%8B%E9%99%9B%E4%B8%8B%E3%81%AELISP-%E5%90%89%E7%94%B0-%E6%AD%A6/dp/4486019245"素数夜曲―女王陛下のLISP")なる書籍を出されており，タイトルが気になってLispに入門した次第であります．

吉田武氏はSchemeを扱っておられるようだが，僕は"[Land of Lisp](https://www.oreilly.co.jp/books/9784873115870/"Land of Lisp")"で入門したので，開発環境はCLISP2.49となっております．

ネタは2018年の東京大学入試数学の第2問です．問題文は次の通り．

```math

数列a_1,a_2,\cdotsを

a_n = \dfrac{ {}_{2n+1} C {}_n }{n!} (n = 1,2,\cdots)
で定める．

(1)n \geqq 2とする．\dfrac{a_n}{a_{n-1}}を既約分数\dfrac{q_n}{p_n}で表すとき，分母p_n \geqq 1,分子q_nを求めよ．

(2)a_nが整数となるn \geqq 1を全て求めよ．

```

(1)は計算するだけ(こんな出題で大丈夫かUT)．さて問題は(2)をどう料理するか．出題者の意図的文脈では(1)の誘導に乗ってパリティ(偶奇)で論じろという香りがプンプンしますが，そこは反骨精神を存分に発揮し(Lisper仕草?)，狭義単調減少性を示した後に,$a_n$を1より小さくなるまで手計算しました．それでも15分程度で処理できたのでまぁ良しという感じですね．

Common Lispで$a_n$を計算するコードは以下のように実にシンプルなものとなります．

# コード

```common_lisp:abc.lisp

(defun factorial (n)
  (if (<= n 1)
      1
      (* n (factorial (1- n)))))

(defun combination (a b)
  (/ (factorial a) (* (factorial b) (factorial (- a b)))))

(defun abc (n)
  (/ (combination (+ (* n 2) 1) n) (factorial n)))

```

たった8行．3ブロックあるので順に説明していきます．

まずは第一ブロックから．

```
(defun factorial (n)
  (if (<= n 1)
      1
      (* n (factorial (1- n)))))
```

階乗$n!$(英語ではfactorial)を計算する関数 factorial を定義しました．

このfactorial(n)は引数nに任意の自然数を与えるとn!を瞬時に返してくれます．

Tips

* if-else処理の構文は(if [条件部] [then節] [else節])

* (1- は与えられた数値から1を引く演算子のようなもの．

* (* n (factorial (- n 1)))のように記述しても同様に実行できます．

* recursive functionの実装美しすぎィ 

python3ならmathライブラリにmath.factorial()関数が実装されてるって？やかましいわ！

次いで，第二ブロック．

```

(defun combination (a b)
  (/ (factorial a) (* (factorial b) (factorial (- a b)))))
```

組み合わせを計算する関数 combination を定義しました．

最後にメインディッシュ，第三ブロック．

```

(defun abc (n)
  (/ (combination (+ (* n 2) 1) n) (factorial n)))
```

入力nに対して出力$a_n$を返す関数 abc を定義しました．こいつを実行すれば $a_8$の時点で2031/4032となるのが解ります．絶妙な収束速度．

#まとめと言いたいこと

* Lispを使えばint,double,floatなどの型指定なしでサクッと数値計算できるよ
* シンプルな文法で初学者にもとっつきやすいよ(というかむしろ『全ての言語はLispに始まりLispに終わる』ですね.失礼いたしました．)
* gnuplotに投げるとすぐgraph描いてくれるよ(maximaはlispで書かれてるようですね)

# 参考文献

| ISBN | Title | Date of publishing |
|:-----------|------------:|:------------:|
|978-4-87311-587-0|Land of Lisp|2013/02/23|
|978-4486019244|素数夜曲―女王陛下のLISP|2012/06/01|
wemos d1で壁打ち

#概要
wemos d1で壁打ち、やってみた。

#写真

![MVC-007F.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/3c5d6640-d72c-1cf9-f193-e732c680fce8.jpeg)


#回路図

![we.JPG](https://qiita-image-store.s3.amazonaws.com/0/18104/9feb65e7-909e-f6ce-c3d6-ab40f40e8708.jpeg)


#サンプルコード


```
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 oled(16);
int x = 64;
int y = 0;
int z = (128 - 20) / 2;
int dx = 3;
int dy = -2;
int p = 0;

void setup()
{
	Serial.begin(115200);
	while (!Serial) delay(250);
	Serial.println("\nok");
	oled.begin(SSD1306_SWITCHCAPVCC, 0x3c);
	oled.clearDisplay();
	oled.setTextColor(WHITE);
	oled.setTextSize(2);
	oled.setCursor(0, 0);
	oled.print("oled 1");
	oled.display();
}
void loop()
{
	int p = 0;
	int val = analogRead(A0);
	int range = map(val, 0, 1024, 0, 6);
	switch (range)
	{
	case 1:
		Serial.println("1");
		p = -1;
	break;
	case 2:
		Serial.println("2");
		p = 1;
	break;
	case 3:
		Serial.println("3");
	break;
	case 4:
		Serial.println("4");
	break;
	case 5:
		Serial.println("5");
	break;
	case 6:
		Serial.println("6");
	break;
	}
	if (x + dx > 125 || x + dx < 2)
	{
		dx = -dx;
	}
	if (y + dy < 2)
	{
		dy = -dy;
	}
	else if (y + dy > 48)
	{
		if (x > z && x < z + 20)
		{
			dy = -dy;
		}
		else
		{
			x = 64;
			y = 2;
			z = 54;
			p = 0;
		}
	}
	if (p == 1)
	{
		z += 5;
	}
	else if (p == -1)
	{
		z -= 5;
	}
	x += dx;
	y += dy;
	oled.clearDisplay();
	oled.drawRect(0, 0, 127, 63, WHITE);
	oled.fillRect(z, 50, 20, 10, WHITE);
	oled.fillCircle(x, y, 4, WHITE);
	oled.display();
	p = 0;
	delay(100);
}



```

以上。
AWSでメモリやディスクの使用率とか監視する


CloudWatchは便利なのですが、なぜか標準メトリクスにメモリとかディスクの使用量がありません。。

それを知りたい場合はカスタムメトリクスを定義する必要があります。いちおうAWSがサンプルで用意してくれてたりはするようです。。。
もちろん自分で書いても構いません。メトリクスは[簡単に送れるよう](http://komaken.me/blog/2018/01/15/cloudwatch%E4%BE%BF%E5%88%A9%E3%81%A0%E3%81%A3%E3%81%9F%E3%81%AE%E3%81%A7%E3%83%A1%E3%83%A2/)です。

## やりかた

ここでは以下の2つを試してみます。

* AWS提供のスクリプトを利用する。[ここ](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/mon-scripts.html)のを利用。
* 誰かが作ったスクリプトを利用する。[ここ](https://github.com/moomindani/aws-mon-linux)のを利用。

## AWS提供のスクリプトを利用する

まずは、AWS提供スクリプトを試してみます。

### 依存ライブラリ等のインストール

指示に従い、スクリプト実行に必要なファイルをインストールします。

```bash
sudo yum install perl-Switch perl-DateTime perl-Sys-Syslog perl-LWP-Protocol-https -y
```

### ツールの取得

ツールを取得、設定します。

#### ダウンロード

ま、ダウンロードしてzipを回答するだけ。

```bash
cd
# ダウンロード
curl https://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.2.zip -O
# 展開
unzip CloudWatchMonitoringScripts-1.2.2.zip
# 元ファイル削除
rm CloudWatchMonitoringScripts-1.2.2.zip
# 移動
cd aws-scripts-mon
```

#### credential情報記述

設定はcredentialを設定するだけ。事前に作成しておきましょう。

```bash
# credential設定ファイルコピー
cp awscreds.template awscreds.conf
```

vi awscreds.confで編集。

```bash
AWSAccessKeyId=XXXXXXXXXX
AWSSecretKey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

### 実行テスト

準備ができたら、--verifyオプションを付けてテストをしてみます（ま、いきなり送付してもなんあら問題ないと思いますが）。

```bash
./mon-put-instance-data.pl --mem-util --swap-util --disk-space-util --disk-path=/ --verify
```

### cronに登録

問題が無いようならcronに登録します。

```bash
*/5 * * * * /home/hoge/aws-scripts-mon/mon-put-instance-data.pl --mem-util --swap-util --disk-space-util --disk-path=/ --from-cron
```

>hogeは変えてね。

送信が完了すると、CloudWatch側に[Linuxシステム]というメトリクス群が見えるようになります。

### 注意

メトリクス送信時にディメンジョンとしてinstand idが送られるのですが、それがキャッシュされるようです。
AMIのイメージ取得して、インスタンス起動させた際、ログがかぶるの注意が必要なようです。

以下のようにキャッシュをクリアするとよいようです。

```bash
rm /var/tmp/aws-mon/instance-id
```

## 誰かが作ったスクリプトを利用する

いろいろまとめられた[aws-mon.sh](https://github.com/moomindani/aws-mon-linux)というのがあるらしいのでそれを利用してみます。

### ダウンロード

gitで取得するだけ。

```bash
cd
git clone https://github.com/moomindani/aws-mon-linux.git
cd aws-mon-linux
```

### credentialの設定

credentialは特に設定せず、awsコマンドを利用するようなので、awscliをダウンロードし、configureで設定しておきます。


### 実行テスト

何もでませんが。。。たぶん下記でいけるでしょう。

```bash
./aws-mon.sh --all-items --disk-path=/ --verify
```

### cronに登録

問題がなければcronに登録します。

```bash
*/5 * * * * /home/hoge/aws-mon-linux/aws-mon.sh --all-items --disk-path=/ --from-cron
```

>hogeは変えてね。

## 参考

参考にさせていただきました。ありがとうございます。

* https://blog.adachin.me/archives/4832


以上です。
Windowsユーザに捧げる時短テク

開発を進めるうえで、知っているとちょっぴり楽ができるTipsを紹介していきます。

## 対象

Windowsユーザ

## OS編

* 日本語入力時でも半角スペースを入力

    `Shift+スペース` を押下します。

* アプリケーション切り替え

    `Alt+Tab` で、現在開いているアプリケーションが表示されます。Altを押下したままTabを連打すると現在開いているアプリケーションを切り替えられます。

* エクスプローラ起動

    `Win+E` でエクスプローラが起動します。

* スクリーンショットを取得

    `PrtSc` でクリップボードにスクリーンショットが格納されます。「スクリーンショット」「画面キャプチャ」など、人や現場によって呼び方は様々です。

* ペイントを起動

    `Win+R` で「ファイル名を指定して実行」画面が表示されます。`mspaint` と入力して `Enter` でペイントが起動します。

* メモ帳を起動

    `Win+R` で「ファイル名を指定して実行」画面が表示されます。`notepad` と入力して `Enter` でペイントが起動します。

* リモートデスクトップを起動

    `Win+R` で「ファイル名を指定して実行」画面が表示されます。`mstsc` と入力して `Enter` でリモートデスクトップの入力画面が起動します。

## EXCEL編

* セルの内容を縦方向に複製

    複製したい範囲を選択し、`Ctrl+D` と入力します。
    ![](https://qiita-image-store.s3.amazonaws.com/0/244351/80d61892-0e96-7a89-d9ed-eb42e0b09510.jpeg)

* セルの内容を横方向に複製

    複製したい範囲を選択し、`Ctrl+R` と入力します。
    ![](https://qiita-image-store.s3.amazonaws.com/0/244351/4e8b2b02-45eb-7c56-ef3c-33a43e3092e0.jpeg)



* セルの結合

    結合したいセルを選択し、`Alt+H+M+M` と入力します。

* セルの中央揃え

    中央揃えにしたいセルを選択し、`Alt+H+A+C` と入力します。

* 罫線を引く

    * 格子 : `Alt+H+B+A`
    * 外枠 : `Alt+H+B+S`
    * 外枠太線 : `Alt+H+B+T`
    * 上罫線 : `Alt+H+B+P`
    * 下罫線 : `Alt+H+B+O`
    * 上下罫線 : `Alt+H+B+D`
    * 左罫線 : `Alt+H+B+L`
    * 右罫線 : `Alt+H+B+R`
    * スタイル変更 : `Alt+H+B+Y`

* 背景の塗りつぶし

    塗りつぶしたいセルを選択し、`Alt+H+H` と入力し、色を選びます。

* セルの書式変更

    書式変更したいセルを選択し、`Ctrl+1` と入力します。
   

## 開発お役立ち編

* エクスプローラからコマンドプロンプトを開く

    エクスプローラのアドレスバーに `cmd` と入力します。エクスプローラ上のディレクトリに移動した状態のコマンドプロンプトが開きます。gulpを実行したい際などに便利です。

* ドットで始まる隠しファイルを作成

    エクスプローラ上で右クリックし、「新規作成」－「テキスト ドキュメント」を選択し、ファイル名を `.htaccess.` などと入力します。.htaccess や .gitignore ファイルを作成する際に便利です。

* リモートデスクトップのショートカットを作成

    エクスプローラ上で右クリックし、「新規作成」－「テキスト ドキュメント」を選択し、拡張子を `.rdp` とします。作成したrdpファイルを編集し、接続先IPアドレスを指定します。

* Windows Server セットアップ時の画面キャプチャを取得

    1. Windows クライアント機にUSBメモリをセットします。
    2. USBメモリに `C:\Windows\System32\mspaint.exe` をコピーします。
    3. セットアップする Windows Server にUSBメモリをセットします。
    4. `Shift+F10` と入力します。
    5. コマンドプロンプトが開くので、`cd`コマンドを使用してUSBメモリ内に移動します。
    6. `mspaint.exe` を起動します。
    7. 通常通り画面キャプチャを取得します。
MLMultiArrayを使うと謎の位置でBAD_ACCESS

# MLMultiArrayとは

iOSアプリ上でTensorflowやTheano（Keras）、Caffeなどで出力したモデルを利用して予測等の計算が可能になるcoreMLという枠組みの中でモデルへの入力や出力に利用する型が`MLMultiArray`になります。
ちょっと特殊な配列、くらいの認識でそこまで乖離は無いと思います。

※ 以下の話は Xcode9.3 / Swift4 で経験した話なので今後改善される可能性もあります。

# 普通の配列の場合

```
let arr = [Double](repeating: 0.0, count: 5)
arr[10] = 1.0
```

もちろんですが、このコードはコンパイルは通っても実行時に2行目で`Index out of range`で落ちます。
文字通り長さが5の配列で10番目を参照しているからです。普通はここまで愚直なミスは犯しませんが、2行目の配列のインデックスを外部から持ってきた変数等を利用している場合、想定した範囲を超えることはあり得ると思います。ただ、デバッグ時にこのようなエラーが起きれば原因もすぐ分かりますね。

# MLMultiArrayの場合

```
let mlarr = try! MLMultiArray(shape: [5], dataType: .double)
mlarr[10] = 1.0
```

こちらも配列とほぼ同様に長さ5の`MLMultiArray`を定義して存在しないIndexに値を代入しようとしています。
がしかし、なんと実行時に2行目でエラーになりません。では、よしなに動いてくれているのかというとそうでもなく全然関係ない行で`BAD_ACCESS`と言われて落ちます。しかも毎回微妙に違う箇所で落ちます。なので初見だと一切原因がつかめないと思います。

※ 私の場合 `} else {` とだけ書いた行でBAD ACCESSと言われ本当に意味がわからず悩みました…

結局原因が分かればIndexの取り方にミスがあっただけなんですが、この事実を知らないと見つけるのに相当苦労しました。

# 結論
`MLMultiArray`を利用する時によくわからないエラーに遭遇したらMLMultiArrayをそっくりそのまま普通の配列に置き換えてみると原因の追求がしやすいです。

# ぼやき
`MLMultiArray`に限らずなんですが、coreML系の資料って日本語英語に限らず全然見つからないですね…
公式のドキュメントもリファレンス程度には見れますが、チュートリアル以上の事をしようと思うととたんに手探り感が出てきます。
coreMLの良い情報ソースをご存知の方いたら共有してほしいです。
chainerの作法　その10

#概要
chainerの作法を調べてみた。
kaggleのcat&dogやってみた。

#結果

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18104/47e519c1-ecaa-42a1-05f3-9ce1c6663139.png)


#サンプルコード


```
import glob
import chainer
import chainer.functions as F
import chainer.links as L
from chainer import training, datasets, iterators, Chain, optimizers, serializers
from chainer.training import extensions
from PIL import Image
import numpy as np


class MLP(Chain):
	def __init__(self, n_units, n_out):
		super(MLP, self).__init__(l1 = L.Linear(None, n_units), l2 = L.Linear(None, n_units), l3 = L.Linear(None, n_out))
	def __call__(self, x):
		h1 = F.relu(self.l1(x))
		h2 = F.relu(self.l2(h1))
		return self.l3(h2)

def main():
	cats = glob.glob('../cats/dogs/cat*')
	dogs = glob.glob('../cats/dogs/dog*')
	data = []
	for i in cats:
		data.append((i, 0))
	for i in dogs:
		data.append((i, 1))
	dataset = datasets.LabeledImageDataset(data)
	def transform(inputs):
		img, label = inputs
		img = img[ : 3, ...]
		img = img.astype(np.uint8)
		img = Image.fromarray(img.transpose(1, 2, 0))
		img = img.resize((28, 28), Image.BICUBIC)
		img = img.convert('L')
		img = np.array(img, dtype = np.float32).reshape(1, -1) / 255
		return img, label
	dataset = datasets.TransformDataset(dataset, transform)
	train_iter = iterators.SerialIterator(dataset, 100)
	test_iter = iterators.SerialIterator(dataset, 100, repeat = False, shuffle = False)
	model = L.Classifier(MLP(1000, 10))
	optimizer = optimizers.Adam()
	optimizer.setup(model)
	updater = training.StandardUpdater(train_iter, optimizer, device = -1)
	trainer = training.Trainer(updater, (5, 'epoch'), out = 'result')
	trainer.extend(extensions.Evaluator(test_iter, model, device = -1))
	trainer.extend(extensions.LogReport())
	trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'main/accuracy', 'elapsed_time']))
	trainer.run()
	serializers.save_npz('cats.model', model)

if __name__ == '__main__':
	main()



```

以上。
DApps・ブロックチェーンの通信セキュリティ

##そもそもDAppsとは


**DAppsと今までのアプリの違うとこは、利用者の情報(アカウント)をどこに保存するかの違い。**
例えば、仮にポケモンのスマホゲームがあったとすれば……
・*従来アプリ*：どの利用者がどこでどのポケモンを捕まえ、保持しているか…の情報を**メインサーバーに保存**。

・*DApps*： 上記をブロックに分けて、**マイナーのパソコンに保存**。仮想通貨と一緒でこれは**公開情報**。
なので、例えば、本当にそのポケモンがある一定の確率で出現するかとか、その技が一定の確率で当たるかを確認することが可能。(やろうと思えば笑)

これは今までのアプリでは、**会社の信用によって成り立っていた部分**。
例えば¥1,000課金すれば、レアなポケモンの確率が50%アップするとされていても、利用者は本当にそうなるか確認する手段はなかった。

アルゴリズムだけがサーバーにあって、その後の情報は全てマイナーのパソコンに保存される。


##通信上のセキュリティに関して

**従来通り**。
通信の脆弱性を利用すれば盗聴が可能で、変更は不可能。しかし全体のシステムには何も影響のないこと。
そもそも、行った通信は**そもそも公開される情報**だから、盗聴する意味がない。
プライバシー情報に関しては、その特定をするための**認証アルゴリズム**がメインサーバーにあるため、現実的に**不可能**。

DAppsではkeyを自分のデバイスにあるため、個人のハードを攻撃されたら、アカウントを奪われたり、影響は受ける。
しかし、これは**今まで通り**。


よって**通信のセキュリティはDAppsには全く関係ない**。
強いていうなら、**従来通り**。
iOSのビルドエラーで困ったこと(linker command failed with exit code 1 (use -v to see invocation))


## 環境

Xcode Version 9.3
Mac OS High Sierra ver 10.13.4
CocoaPods : 1.5.0


## 背景

firebaseのリアルタイムDBにある既存のデータをSwiftクライアントで表示させることにトライしている。

firebaseのドキュメントに記載のある、
cocoa podsのインストール
pod install,firebaseのプロジェクト設定、
import Firebase
FirebaseApp.configure()

までは完了してうまくいく。

###現象

ビルドした際に

linker command failed with exit code 1 (use -v to see invocation)
が表示される。

<img width="1115" alt="ビルドエラー.png" src="https://qiita-image-store.s3.amazonaws.com/0/135287/f050b5ae-6d55-e470-3d35-57fd3443f41f.png">



### 検索してみたキーワードとやったこと

.xcodeprojファイルのBuild Setting　-> Levelsの
Build Active Archtecture OnlyをすべてNoにチェック


framework not found GoogleToolboxForMac　原因で検索


### 見た記事
[【SOF】framework not found GoogleToolboxForMac](https://stackoverflow.com/questions/40358719/framework-not-found-googletoolboxformac)

[[XCode][Cocoapods]ビルドエラー時の対処法](https://qiita.com/nakamurau1@github/items/e4a810e21e626cf6f09a)

その他もろもろ。

### やったこと

xcodeのビルドログを見る
ひたすら検索
新しい簡単なアプリを作ってビルドしてみる→素のアプリだとビルドできる

### なぜ分からないか

・たくさんファイルが出てきて問題の切り分けができない
・podファイルの位置の問題なのか
・コードの記述が足りないのか、
・プロジェクトフォルダに然るべきファイルがないからなのか分からない

・エラーメッセージの中にあるパスの指定が自分のPCに見当たらない。
'-F/Users/*******/Library/Developer/Xcode/DerivedData/aaa-bjvtyekftolsrceuignowaszjioe/Build/Products/Debug-iphonesimulator/leveldb-library'


・そもそもXCodeProjectのファイルが何なのかの理解ができていない

・XCodeProject上でライブラリの参照が足りてないことが原因なのか？
・ライブラリの自動参照設定が必要なのか?


podファイルの中身

```rb
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'aaa' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for aaa
pod 'Firebase/Core'
pod 'Firebase/Database'


end
```

## 追記

podsディレクトリ、xcworkspaceファイル、Podfile.lockを削除し、pod installし直したら解決しました。
もしかするとpod init した後に.xcworkspaceを開いていなかった可能性がありました。
Python で独立したプロセス間の通信をやってみる

# はじめに
　Python でプロセス間通信を行う方法を色々と探してみたが、これはという方法が見当たりませんでした。
Queueを使った方法では、作成したQueue オブジェクトを渡す必要があり、独立したプロセス間ではできません。
そこで、ソケットを使った通信にて実現することにしました。

# 具体的に
　ここでは、同一ホスト上で稼働するプログラム間の通信をするので、ホストは、'localhost'を指定します。
## 受信側
　受信側では、ソケットをオープンして、送信側からのデータ受信を待ちます。通常は、テキストを受け取りますが、制御文字として「キャンセル」、「処理終了」を受け取るようにしました。

```comrcv.py
from socket import socket, AF_INET, SOCK_STREAM

HOST        = 'localhost'
PORT        = 51000
MAX_MESSAGE = 2048
NUM_THREAD  = 4

CHR_CAN     = '\18'
CHR_EOT     = '\04'

def com_receive():

    # 通信の確立
    sock = socket(AF_INET, SOCK_STREAM)
    sock.bind    ((HOST, PORT))
    sock.listen  (NUM_THREAD)
    print ('receiver ready, NUM_THREAD  = ' + str(NUM_THREAD))

    # メッセージ受信ループ
    while True:
        try:
            conn, addr = sock.accept()
            mess       = conn.recv(MAX_MESSAGE).decode('utf-8')
            conn.close()
            
            # 終了要求？
            if (mess == CHR_EOT):
                break
                
            # キャンセル？
            if (mess == CHR_CAN):
                print('cancel')
                continue

            # テキスト
            print ('message:' + mess)

        except:
            print ('Error:' + mess)

    # 通信の終了
    sock.close()
    print ('end of receiver')

def proc():
    com_receive()
```

実行は、comrcv.proc() です。'receiver ready'を表示した後、メッセージの受信待ちになり、受信した内容を表示します。
そして、終了要求を受け取るとループを抜けて、ソケットをクローズし、処理を終了します。

## 送信側
　送信側では、テキストを送信するたびにソケットをオープンし、テキストを送信します。

```comsnd.py
from socket import socket, AF_INET, SOCK_STREAM

HOST        = 'localhost'
PORT        = 51000

CHR_CAN     = '\18'
CHR_EOT     = '\04'

def com_send(mess):

    while True:
        try:
            # 通信の確立
            sock = socket(AF_INET, SOCK_STREAM)
            sock.connect((HOST, PORT))
            
            # メッセージ送信
            sock.send(mess.encode('utf-8'))

            # 通信の終了
            sock.close()
            break
            
        except:
            print ('retry: ' + mess)


def proc():
    com_send('message test')
    
def exit():
    com_send(CHR_EOT)
    
def cancel():
    com_send(CHR_CAN)
```

実行は、comsnd.proc()で、'message text'を送信します。また、comsnd.cancel()でキャンセル文字、comsnd.exit()で処理終了のコードを送信します。
C言語：ifを全部switchで書いてみる

## 動機

学校のプログラミング演習の授業で出された課題で、「ifのところをすべてswitchで書け」というのが、意外と考え方として応用ができそうだなと思ったのでメモ。

## やりたいこと

次のようなCのコードをswitchだけで書いてみたい：



```c:only_if.c
#include <stdio.h>

int main(void)
{
    int score;

    //演習の点数が80点以上なら優、６０点以上なら可、６０点未満なら不可を出力する。
    printf("あなたの演習の点数を入力してください--->");
    scanf("%d", &score);

    if(score >= 80){
        printf("優");
    }else if(score >= 60){
        printf("可");
    }else{
        printf("不可");
    }

    return 0;
}
```

## アイデア

例えば、score >= 60 のような条件式は、成立なら1、不成立なら0を返すのだった。このことを思い出せば、範囲を扱う不等式でも、ピンポイントの値で処理を振り分けるswitchがうまく使える。

## 実装

こんな感じ：

```c:only_switch.c
#include <stdio.h>

int main(void)
{
    int score;

    //演習の点数が80点以上なら優、６０点以上なら可、６０点未満なら不可を出力する。
    printf("あなたの演習の点数を入力してください--->");
    scanf("%d", &score);

    switch(score >= 80){
        case 1:
            printf("優");
            break;
        default:
            switch(score >= 60){
                case 1:
                    printf("可");
                    break;
                default:
                    printf("不可");
                    break;
            }
            break;
    }
    /*
    if(score >= 80){
        printf("優");
    }else if(score >= 60){
        printf("可");
    }else{
        printf("不可");
    }
    */
    return 0;
}

```

## まとめ

**同じ範囲に属する値たちをすべてある値にマッピングする**というのがここでの考え方のポイントでした。C言語以外でもこの考え方は活かせそうですね。


## 追記

**caseの中でbreakを実行しなければ、後ろのcase文も実行される**という性質も使うと、次のように書くこともできます：

```c
#include <stdio.h>

int main(void)
{
    int score;

    switch(score / 10 * 10)
    {
        case 100:
        case 90:
        case 80:
            printf("優\n");
            break;
        case 70:
        case 60:
            printf("可\n");
            break;
        default:
            printf("不可\n");
            break;
    }

    return 0;
}

```
Embedded Frameworkを使ってiOSアプリを適当なレイヤーごとに分割する

開発しているiOSアプリのソースが割と増えてきたので、リファクタリングついでにEmbedded Frameworkd(Cocoa Touch Framework)に分割しました。

分割した目的としては、

- レイヤー分割の明確化
- ビルド時間の短縮
- 依存関係の整理

の3点がメインです。

Embedded Framework(Cocoa Touch Framework)の導入方法や説明はこちらの記事が参考になります。

[Embedded Framework使いこなし術](https://qiita.com/mono0926/items/e29cd17789fd1d1548aa)

## ビフォーアフター

### ビフォー

分割前は、アプリ用のターゲットが1つあり、そのフォルダ以下にグループを作ってソースファイルを分割していました。

<img width="267" alt="Screen Shot 2018-05-06 at 8.12.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/9563/38127f8b-8cc9-d07a-fca6-b9a659794553.png">

<img width="162" alt="Screen Shot 2018-05-06 at 8.14.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/9563/2fa695e9-45d3-d2ec-1ac7-715774801887.png">


### アフター

分割後は、以下の4つのフレームワークを追加して、それぞれのフレームワークにソースを振り分けて行きました。

- アプリ
    - iOSアプリ
- API
    - APIとのやりとりを担当する。Modelに依存。
- Common
    - Foundation系のExtensionやロガーのように全体で使うような汎用機能。
- Model
    - CoreDataのエンティティや、データモデルのクラス・構造体。
- Storage
    - CoreDataやKeychain, iCloudへデータを保存する。Model, APIに依存。


<img width="269" alt="Screen Shot 2018-05-06 at 8.16.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/9563/94ad81d8-b284-5a00-0ebc-cbcde944908d.png">

<img width="168" alt="Screen Shot 2018-05-06 at 8.16.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/9563/9b2af97c-e32b-4d5e-4eb8-ac01a06f0533.png">


## 分割時のポイント

### フレームワークごとの依存関係を考える

当たり前ですが、フレームワークに分割することで、フレームワーク同士の依存関係が明確になるので、相互依存などならないように、どこにどのソース・クラスを入れて行くかというのを考えました。

色々と試行錯誤した結果、上記4つのフレームワークに分割して、依存関係を整理しました。

### アクセス修飾子をつける

全てのソースを1つのターゲット対象にしていた時は、アクセス修飾子を特につけずに全てデフォルトの`internal`にしていたのですが、フレームワークに分割すると`public`にしないと参照先のターゲットからは参照できないので、アクセス修飾子も整理しました。

フレームワークを参照しているのに、クラスがないというようなエラーが出たりして、一瞬理由がわからなくなったことがあったのですが、アクセス修飾子が原因でした。


### フレームワークごとにフラグを追加する

デバッグフラグや独自の開発環境用フラグを利用して、実行時の挙動やテスト環境用ビルドなどを行っていますが、こちらもフレームワークごとに追加する必要があります。

フレームワークのターゲットを選択し、`Build Settings`の`Other Swift Flags`から追加します。

<img width="730" alt="Screen Shot 2018-05-06 at 8.41.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/9563/5cd4dbe8-95e7-0996-80d6-cb936c7499ea.png">


### CoreDataの初期化処理を変更する

CoreData周りの初期化処理には、`NSPersistentContainer`を使用していますが、モデル定義ファイル `.xcdatamodeld`は、上記フレームワークのうち`Model`の中に入れました。

そのため、`NSPersistentContainer`を初期化する際には、`Model`の中の定義ファイルを明示的に指定する必要があります。

```
let modelURL = Bundle(for: Modelの中のクラス.self).url(forResource: "定義ファイル名", withExtension: "momd")!
let mom = NSManagedObjectModel(contentsOf: modelURL)!
let container = NSPersistentContainer(name: "コンテナ名", managedObjectModel: mom)
        
```

この辺は、`Bundle.main`を使ってリソースを読み込んでいた部分でも注意する必要があると思います。


## 分割した感想

ビルド時間が早くなったかというと、早くなった気もします。まだそこまで大きくもないので、もっと大規模になるともっと実感できそうです。

レイヤー分割が明確になり、テストしやすくなったり、役割が明確になったり、依存関係がはっきりしたりという点がよかったと感じています。
（初学者向け）フレームワークとライブラリの違い

なんだかよく分からないのでまとめました！

## 一言で言うと
**■フレームワーク： 汎用的に必要なものをまとめている枠組み
（例：Ruby on Rails /AngularJS /Bootsrap）**

**■ライブラリ： 汎用性の高い便利なプログラムのまとまり
（例：Railsのkaminari /PythonのNumpy）**

要は、フレームワーク>ライブラリ　の包含関係にあるという　ことになります。
**家で例えると、建物自体がフレームワークで、テレビや洗濯機などの家電がライブラリ**みたいな感じです！

## 具体的には
**フレームワーク：**
アプリケーションフレームワーク (Application Framework) とは、プログラミングにおいて、特定のオペレーティングシステムのためのアプリケーションの標準構造を実装するのに使われるクラスやライブラリの集まり。
フレームワークの目的は、Web開発で用いられる共通した作業に伴う労力を軽減すること。たとえば、多数のフレームワークがデータベースへのアクセスのためのライブラリや、テンプレートエンジン（→Webテンプレート）、セッション管理を提供し、コードの再利用を促進させるものもある。（Wikipedita）



**ライブラリ：**
汎用性の高い複数のプログラムを再利用可能な形でひとまとまりにしたもの。ライブラリと呼ぶ時は、それ単体ではプログラムとして作動させることはできない実行ファイルではない場合がある。
ライブラリは他のプログラムに何らかの機能を提供するコードの集まりと言うことができる。ソースコードの場合と、オブジェクトコード、あるいは専用の形式を用いる場合とがある。（Wikipedita）

## 注意点
**フレームワーク：**
・意味理解をしないとそのフレームワーク以外でシステムを作れなくなる。
・枠組みから外れたものを実装しようとすると大変。
・オリジナルで作った場合よりもパフォーマンスが劣る場合がある。


**ライブラリ：**
・メンテナンスが行き届いてないと思わぬセキュリティホールができる。
・物によっては関連情報が少ない。

共通して言えることは、**「便利だけど、根底に根付く技術を理解しないと、汎用性やセキュリティで失敗してしまうかも」**と言うことですね。





## 参考：
wiki (フレームワーク)：
https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF

wiki (ライブラリ)：
https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA

blog（今すぐ辞めてほしい「Ruby on Rails勉強してます」「CakePHP勉強してます）
http://blog.sumyapp.com/2013/07/no-recommend-rails/
Next.js(React)のみで開発できるElectronライブラリを作ってみた

## 作ったもの

[Nextron - ⚡ Electron + Next.js ⚡](https://github.com/saltyshiomix/nextron)

Electron + Next.jsのアプリケーションを**Next.jsの知識のみで**なるべく作成できるようにするライブラリです。

## インストール

```bash
$ npm install --global nextron
```

これで`nextron`コマンドとTypeScript用の`nextron-ts`コマンドが利用できるようになります。

## 使い方

試しに`hoge`という名前のアプリケーションを作るには、以下のようにします。

```bash
# hogeディレクトリ作成
$ nextron init hoge

# 開発モードでElectron + Next.jsアプリケーションを起動
$ cd hoge
$ yarn dev
```

これでElectron + Next.jsのアプリケーションがデバッグモードで立ち上がります。

実際のバイナリに配布するには、`yarn build`コマンドを打って10分くらい待つとできあがります。

## なぜNextronが必要なのか

このコマンドライブラリは、Next.jsで作成されたSSRの静的サイト(index.html群)をrendererプロセスとして扱い、Electronのmainプロセスに食べさせているだけのライブラリです。

なぜこのライブラリを作ったかといいますと、Electron + Next.jsがお手軽に実現できるライブラリがまだこの世に現れていない(2018/5/6現在)か、私が知らなかったからです。

[Next.jsの作者がサンプルを試していますが](https://github.com/zeit/next.js/tree/canary/examples/with-electron)、これが普通にエラーになっていて使い物にならないんですね。

Next.jsはSSR(Server Side Rendering)をキャッチコピーにやってきたので、Electronと相性が悪いのはわかるのですが、それでもここまで相性が悪いのかと思うくらい自分でも作成してみてわかりました。

## 1コマンドで実現できる世界を増やす

NextronはまだWIPプロジェクトですが、デバッグモード起動とリリースビルドがそれぞれ1コマンドで完結します。

我々開発者はなるべくコアな開発部分に集中できる状態でいたいはずなので、1コマンドに集約することは（バランスさえ保てれば）有用だと思います。

Nextronを皮切りにでもして、本家のzeitさんたちが公式のElectron + Next.jsライブラリを作成するまで、Nextronで自分は勉強していこうと思います。

## 関連記事

["Nextron": Electron + Next.js dream](https://dev.to/saltyshiomix/nextron-electron--nextjs-dream-3hg)

[Building Electron Apps with Next.js](https://leo.im/2017/electron-next)

## P.S.

誰かTypeScript + Reactが大好きな人いませんか〜？
シンキングツールの紹介

#はじめに
ビジネスにおいて
・意見を持ち寄る
・情報を整理する
・振り返る 
・目標をたてる
・意思決定する
という機会はたくさん訪れます。

そういったときに
・固定観念を取り除く
・パターン化する
・情報を共有する
・自分と周りの関係性を見直す
為の思考法を共有していれば、より成功は近づきスムーズな意思決定が可能になります。

今回は思考を図解するための方法（シンキングツール）を紹介します。
一覧として記載していますので、各手法の詳細は興味があれば調べてください。

#ブレインストーミング
創造的なアイデア創出法。

- 自由にアイデアを述べてもらう。
- 他人のアイデアに便乗する。
- 時間を決める。
- 整理、判断、批判は後回し。

あとで整理するため付箋などを利用し、発表者は付箋に書いて発表しましょう。

#KJ法
情報をカードに記して分類、情報を俯瞰的にとらえ思考を整理する。

1. カードを作成
1つのカードには1つの情報だけ書き込む

2. カードのグループ化
カードをグループ毎に分けてまとめておく

3. 整理
順番をきめたりグループの関係性を探る

#シックスハット法
会議のメンバーの思考を集中させる議論の仕方。
全員が同じ帽子をかぶる、(あるいは別の帽子をかぶる）ことによって
・視点を変える
・議論を深める　
・いろんな意見を引き出す　
・発言の指向性を与えて促す　
・意識の統一を図る

|帽子の色|意見や意識すること| 
|---|---|
|白|	客観的な情報、データ
|赤|	感情的な意見
|黄色|	楽観的な意見
|黒|	悲観的な意見
|緑|	可能性、将来的な事
|青|	会議のプロセスの検証

#なぜなぜ分析
問題に対して問いを繰り返すことで問題の真因を探り、問題対処の妥当性を検証する。

例）
なぜコンビニでおでんを買うのか　→　レジ横にあって目を引くから　→　なぜレジ横にあって目を引くと売れるのか　→　店員が勧めやすい　→　なぜ

#What-If分析
もし～ならという問いを立てることで仮設したサービスが魅力的なものかを検証する。
サービスの将来像を検証や世の中の変化への対応策を探る。

例）
もしシステムの自動運転が確立したらシステム開発サービスはどのようなものになるとおもいますか

#KPT法
プロジェクトを振り返り、以下の3つについて分析する。

**Keep**
　うまくいったこと、続けたいこと
**Problem**
　うまくいかなかったこと、問題点
**Try**
　次にすること

#SWOT分析
目標達成における内部の要因（個人や組織の強み、弱み）と、外部の要因を洗い出し、それぞれに対してどのように対処するかを決定する。

| 内的要因 | 外的要因 | 
|---|---|
| 強み (Strengths)  | 機会 (Opportunities)  |
| 弱み (Weaknesses) | 脅威 (Threats)        |


#3C分析
- Customer（顧客）
- Competitor（競合）
- Company（自社）

顧客のニーズに対して競合他社と自社がどのように応えているか（又は応えていないか）を比較し、自身の事業の問題点や今後の方針について決定する。

例）
XXXを取り巻く環境は・・主要顧客は・・・

#STP分析
自社が誰に対してどのような価値を提供するのかを明確にするための要素や組織の強みを明確にし、顧客の特定や戦略に役立てる。

**セグメンテーション（segmentation）**
　セグメント化、取り巻く環境や市場における顧客のニーズごとにグループ化する。
**ターゲティング（targeting）**
　セグメント化した結果、競争優位を得られる可能性が高い、自社の参入すべきセグメントを選定する。
**ポジショニング（positioning）**
　セグメントにターゲットに向けてどのようたちいちで臨むか。

#5forces分析
業界の構造を5つの要因から分析し事業の参入や意思決定に役立てる。

**内的要因**
「供給企業の交渉力」供給側の多さや力の強さ
「買い手の交渉力」買い手の多さ、品質に対する厳しさ
「競争企業間の敵対関係」競争の激しさ
**外的要因**
「新規参入業者の脅威」　参入障壁が高いか低いか
「代替品の脅威」代替可能なものが多いか少ないか

例）
この言語(技術)は、はやるのかすたるか...(学習する価値があるか)
スマホアプリに参入可能か...
日本のIT市場は...

#ステークホルダーマップ
ステークホルダー(利害関係者)をリストアップし、それぞれの関係を分析する。
ステークホルダーをより深く理解する。
問題点のある可能性を探す。

ステークホルダーとその利害関係をリストアップ
関係者同士の関係をまとめる
ステークホルダーやその関係性について問題点や改善点を探る


#カスタマージャーニーマップ
顧客の行動を分析して競合するサービスとの比較や分析、サービスの品質やユーザエクスペリエンス向上を狙う。
製品やサービスについて、想定されるタイプの顧客別に、認知、検討時、購入前、購入後などに
・どのようにして情報に触れたか
・情報に触れてどう行動したか
などを分析する。


#おわりに
思考を分解する事や何かの枠に当てはめるということで
・アイデア創造
・洞察を生む
・新たな発見
・思考の共有
という効果が得られます。

目標設定やプロジェクトの意思決定にお役立てください。
Node.js + Express4 + Passport + pug でログイン認証画面を作る(エラー表示あり)

# はじめに
Webアプリケーションを作ろうとすると何かと必要になってくるログイン認証画面。
今回はExpress4、Passport、pugを使ってエラーメッセージ(フラッシュメッセージ)が表示されるものが書けたのでメモ。
わざわざデータベースを使うのが面倒だったので一時的な配列にユーザを保持しています。

ScreenNameに「user1」、Passwordに「pass1」でログインできます。

動作確認にはNode.js v8.10.0を使用しました。
このコードはMITライセンスの基で改変・再配布できるものとします。

# 必要パッケージ
- express
- express-session
- connect-flash
- passport
- body-parser
- passport-local
- pug

# コード
```server.js
const path = require('path');
const express = require('express');
const session = require('express-session');
const flash = require('connect-flash');
const passport = require('passport');
const bodyParser = require('body-parser');
const { Strategy : LocalStrategy } = require('passport-local');

const app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(session({ name: 'test-sid', secret: 'hoge', resave: false, saveUninitialized: true }));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

// db
class Users {
	constructor() {
		this.store = [];
	}
	create(id, screenName, password) {
		this.store.push({ id, screenName, password });
	}
	find(key, value) {
		return this.store.find(user => user[key] == value);
	}
}
const users = new Users();
users.create('u1', 'user1', 'pass1');

// strategy
passport.use(new LocalStrategy({ usernameField: 'screenName' }, (screenName, password, done) => {
	const user = users.find('screenName', screenName);
	if (user == null) {
		return done(null, false, { message: 'invalid screenName' });
	}
	if (user.password != password) {
		return done(null, false, { message: 'invalid password' });
	}

	return done(null, user);
}));

// passport
passport.serializeUser((user, done) => {
	done(null, user.id);
});
passport.deserializeUser((id, done) => {
	done(null, users.find('id', id));
});

// routings
app.get('/', (req, res) => {
	if (!req.user) {
		res.render('login', { error: req.flash('error') });
	}
	else {
		res.render('home', { user: req.user });
	}
});
app.post('/', passport.authenticate('local', {
	successRedirect: '/', failureRedirect: '/', failureFlash: true, badRequestMessage: 'empty credentials' }));

app.listen(8080, () => {
	console.log('listening on port: 8080');
});

```

```views/login.pug
if error != ''
	p Error: #{error}

h1 Login

form(method='post' action='/')
	div
		label(for='screen-name-input') ScreenName:
		input(type='text' name='screenName' id='screen-name-input')
	div
		label(for='password-input') Password:
		input(type='text' name='password' id='password-input')
	button Login
```

```views/home.pug
h1 home
p hello, #{user.screenName}
```

# 表示

![image.png](https://qiita-image-store.s3.amazonaws.com/0/85618/297b9af1-ab40-d941-6a1a-8ad7b79061f3.png)
----

# おわりに
新しいES、皆さんもどんどん書きましょう！
カウントボタンのhtml、CSS、Javascriptのメモ

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>Count</title>
	<link rel="stylesheet" href="css/styles.css">
</head>
<body>
	<div id="btn">0</div>
	<script src="js/main.js"></script>
</body>
```

```main.js
(function() {
  var btn = document.getElementById('btn');
  var n = 0;
  btn.addEventListener('click', function() {
    n++;
    this.textContent = n;
  });
  btn.addEventListener('mousedown', function() {
    this.className = 'pushed';
  });
  btn.addEventListener('click', function() {
    this.className = '';
  });
})();
```
```styles.css
@charset "UTF-8";

#btn {
  /* 中央ぞろえ　上からマージン30px */
  margin: 30px auto 0;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: #ef454a;
  text-align: center;
  line-height: 100px;
  color: #fff;
  font-size: 42px;
  font-weight: bold;
  cursor: pointer;
  opacity: 0.9;
  box-shadow: 0 10px 0 #d1483e;
  border: 3px solid #d1483e;
  /* 連打した時にテキストが選択されるのを防ぐ*/
  user-select: none;
}

#btn:hover {
  opacity: 1;
}

/* クリックした時の動き。6px下へ。30px＋6px。*/
#btn.pushed {
  margin-top: 36px;
  box-shadow: 0 4px 0 #d1483e;
}
```
結果
<img src="https://qiita-image-store.s3.amazonaws.com/0/244207/8dea2132-da4f-c5f4-73ba-96dedcd4ac8e.gif">
Runway Machine Learning for Everyone

#Runway
クラスメートのThesisプロジェクトです。
https://runwayml.com/

コンセプトはとてもシンプルで、結構時間がかかるMachine Learningの環境づくりから簡単なサンプルの実行をクリックひとつで出来るようにして、アプリケーションの開発に注力しましょうというもの。

ITPはアートスクールなので、一応メインのターゲットはArtistとなっていますが、この間聞いたところ、
Artist等問わず、色々なところから関心を持たれているとのことです。スタートアップからNASAの職員まで。


アプリケーションスクリーンショット
![banner2.png](https://qiita-image-store.s3.amazonaws.com/0/24723/2923208f-bed6-2cb1-a9e9-cf2f88a39c1c.png)

### 何が出来るのか
現在、RunwayがサポートしているのはOpenPose, im2txt, YOLOの３種類です。
RunwayがやってくれることはPre-trainedモデルを読み込んで、その出力をJSON形式で出力するということ。
プロトコルはOSC、HTTPをサポートしているので、基本的にRunwayをMac/Windowsで動かして、データを送れば、
あとは何でもできます。
OpenPose + openFrameworks + fragment shaderで簡単なアプリを試してみましたが、
oFでskeltonデータ取るのにxcodeやらaddonで時間費やしていたのが、悲しくなるほど簡単です。
OpenPoseはrepo自体はstarしてるんですが、ザーッと確認した感じ環境構築がちと面倒そうなので、試してなかったんですが、
テストするまで10分かからないので、おおと感心しました。

![Screen Shot 2018-05-05 at 2.34.42 PM.png](https://qiita-image-store.s3.amazonaws.com/0/24723/e8e2c052-d41c-ed27-d00c-c9cdf8ec7b43.png)

im2txtに関しては以前自分でセットアップした時に結構時間掛かったので（Python、TensorFlowのバージョンやら何やら）、クリックひとつであと待ってポチポチ押せば、
動くってのは本当に便利だなぁと。

ちなみに、クリエイターとDan Shiffmanは仲がいいので、ShiffmanもProcessingで簡単なテストアプリとか作っています。


PaperspaceでのリモートGPUもサポートしているので、高速インターネット回線があれば、本当にスムーズに動くと言ってました。
AWSやGoogle Cloudのサポートは次のリリースでサポートするそうです。


ちょっとMachine Learning(Deep Learning)試してみたいけど、環境構築するのはなぁというエンジニアの方にはおすすめです。
現在βバージョンなので、invitationのリクエストが必要です。

＊ Dockerのインストールが必要です。

Github
https://github.com/runwayml

ビデオ
https://www.youtube.com/watch?v=7mCAKceSPIM
homebrew環境構築におけるgnu系コマンドのインストールについて

# はじめに
gnu系コマンドもhomebrewでただ単にインストールするには`brew install hoge`でよいのですが、
このままではコマンドの先頭に**g**が付きます（例: `ggrep`）
元の名前で使えるようにする方法についてまとめました。

また、homebrewでのコマンド等のインストールには、

- ビルド済みバイナリが提供される場合（bottledと呼ばれます）
- ユーザーがソースコードからビルドする必要がある場合

の二つがあることを念頭におく必要があります。
当たり前ですがビルドオプション付きでインストールする際には後者となります。（例: HTTP/2対応の`curl`）

# 3つの方法
現状で私が確認した解決法です。

## aliasを記述
`.bash_profile`や`.zshrc`に次のように記述しておきます。

```bash:.bash_profile
alias grep='ggrep'
```
この方法は簡単ですが***コマンドの数が多いと正直めんどくさいです***。

## --with-default-namesをつけてインストールする
だいたいググるとこの方法が出てきます。
`brew install hoge --with-default-names`
この方法が使えないものもあるので`brew info hoge`でチェックしておきましょう（`coreutils`など）
一見するとこの方法がベストなようですが、このオプションは"元の名前でインストールする"（元の名前のバイナリを用意する）という意味です。
つまり***ビルド済みバイナリが提供されている場合でもソースコードからビルドする***のでちょっと時間がかかるという欠点があります。
ビルドオプションをつけたいときや、時間がかかってもいいから後述のパスを通すのがめんどくさい人はこの方法が良さそうです。

## PATHを通す
私のお勧めです。
しかし、注意すべき点としてPATHを通すという性質上、よく使うであろう**`which`コマンドの結果も変わってしまいます**。
前述の**aliasの場合は`which`の結果は元のままです。**

この方法はhomebrewが元の名前で各コマンドへのシンボリックリンクを`/usr/local/opt/hoge/libexec/gnubin`以下に置いてくれる場合に使えます。
`brew info hoge`でそのような記述が有れば可能です。

例えば`gnu-tar`であればこのような感じに書いてあります。

```
~$ brew info gnu-tar
gnu-tar: stable 1.30 (bottled)
GNU version of the tar archiving utility
https://www.gnu.org/software/tar/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/gnu-tar.rb
==> Options
--with-default-names
	Do not prepend 'g' to the binary
==> Caveats
gnu-tar has been installed as "gtar".

If you really need to use it as "tar", you can add a "gnubin" directory
to your PATH from your bashrc like:

    PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"

Additionally, you can access their man pages with normal names if you add
the "gnuman" directory to your MANPATH from your bashrc as well:

    MANPATH="/usr/local/opt/gnu-tar/libexec/gnuman:$MANPATH"
```

この`gnu-tar`の例であれば`.bash_profile`や`.zshrc`に次のように記述しておきます。(ついでにマニュアルのパスも)

```bash:.bash_profile
export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
export MANPATH="/usr/local/opt/gnu-tar/libexec/gnuman:$MANPATH"
```

ちょっとめんどくさいですがたくさんのコマンドにエイリアスを張るよりはマシですね。
**手元でビルドする必要もありません。**

余談ですがパスを通す時は優先順位に注意しましょう。
`/usr/bin`よりも高い優先順位が必要です。
alpine linux で wheel group に所属しているユーザのみ su で root になれるようにする

lxc コンテナで動かしている alpine で必要になったのでメモ。
alpine linux 3.7 で確認しています。

1. パッケージの導入  
`apk add linux-pam shadow`
1. pam の設定  
`/etc/pam.d/su` を次の通りに設定(既存の設定は削除)  

```text:/etc/pam.d/su
auth            sufficient      pam_rootok.so  
auth            required        pam_wheel.so root_only use_uid  
auth            substack        base-auth  
```

でよいかと。あとは適当なユーザを wheel group に所属させてください。
shadow パッケージを導入しないと、 `/bin/su` は `/bin/bbsuid` へのシンボリックリンクトなっているが
bbsuid は pam を利用してくれないようで、期待通り動かなかった(wheel group に所属していないユーザでも su で root になれた)です。

---

参考 : https://unix.stackexchange.com/questions/433565/alpine-linux-restrict-su-l-to-wheel-group
TypeScriptの変数の末尾の"!"(エクスクラメーション/感嘆符)の意味

具体的に言うと、TypeScriptで"foo"という変数に対して"foo!"と記述した時の意味。

この"!"の呼び方は、Non-null assertion operator。
プログラマがコンパイラに対して、この変数はundefinedやnullになることはありません、と教える記述。
不正確だが、型&lt;T&gt;があるとして、型&lt;T | undefined | null&gt;を型&lt;T&gt;に静的にcastしていると考えると分かりやすい。
変換前の型は、型&lt;T | undefined&gt;でも型&lt;T | null&gt;でもOK。

以下、コードによる説明。

```typescript
    private func(): string {
        let foo = external_func(); // 戻り値の型はstring | undefinedとする
        
        // return foo; NG。戻り値の型がstringに対してstring | undefinedを返しているため
        return foo!; // OK。"!"によりstring | undefinedをstringにcastしているのと同等
     }
```

なお、この記述はTypeScriptがJavascriptに変換された後のコードからは削除されるとのこと。
なので、コード実行時に違反していても例外などのエラーは発生しない。
上のコードでいえば、コード実行時にfooの値がundefinedやnullでもエラーは発生しない。
(コンパイラから見てfooにundefinedが入ることが明らかだと、コンパイル時にはエラーになる)

より詳細な情報は、以下のページに記述あり。
[公式ドキュメント](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#non-null-assertion-operator)
[stack overflow](https://stackoverflow.com/questions/42273853/in-typescript-what-is-the-exclamation-mark-bang-operator-when-dereferenci)
M5Stackの傾斜計と３Ｄ表示するスマホアプリの作成

# はじめに
- M5Stackについて
    - ESP-32（WiFiとBluetoothが搭載された低価格マイコン）が搭載されたユニットで、QVGAのLCDやMicroSDカードスロットもあり、３０ピンコネクタのスタックなど、拡張性までよく考えられた製品です。
    - ESP-WROOM-32の価格（700円くらい）を知って、これベースのモノを作ってみようと色々と実験してたんですが、M5Stackに同じマイコンが載っていることは後で知りました。

---
# 完成状態
- youtubeにアップロードしてます。

[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/5XTeL1LdSCI/0.jpg)](https://www.youtube.com/watch?v=5XTeL1LdSCI)

- ソースは、GitHub（[Angle3DMonitor](https://github.com/katsumin/Angle3DMonitor)）で公開しています。

---
# M5Stackの傾斜計
- いわゆる水準器をイメージして作りました。
- M5Stack GrayにはMPU9250（９軸センサー）が搭載されているので、コレ単体でできました。
- [M5Stackのサンプル](https://github.com/m5stack/M5Stack/tree/master/examples/Modules/MPU9250/MPU9250BasicAHRS)はかなり参考になりました。（結構、コピペしてます）
    - バグかな？と思うところが１箇所あったので、そこは修正しました。

    ```cpp:オリジナル
  MahonyQuaternionUpdate(IMU.ax, IMU.ay, IMU.az, IMU.gx*DEG_TO_RAD,
                         IMU.gy*DEG_TO_RAD, IMU.gz*DEG_TO_RAD, IMU.my,
                         IMU.mx, IMU.mz, IMU.deltat);
    ```
    ```cpp:修正版
  MahonyQuaternionUpdate(IMU.ax, IMU.ay, IMU.az, IMU.gx*DEG_TO_RAD,
                         IMU.gy*DEG_TO_RAD, IMU.gz*DEG_TO_RAD, IMU.mx,
                         IMU.my, IMU.mz, IMU.deltat);
    ```
- BLE通信部分は、[こちらのサンプル](https://github.com/nkolban/ESP32_BLE_Arduino/blob/af865a916795289c8e7e09b091ff2140c33fc3fe/examples/BLE_uart/BLE_uart.ino)を参考に（というか、コレも結構コピペ）しました。

---
# スマートフォンでの3D表示
- BLE接続されたM5Stackから送られてくる加速度センサー値をもとに、X方向とY方向の傾斜を算出しています。
- 円筒型のオブジェクトを3D表示していますが、OSSライブラリの[UrhoSharp.Forms](https://www.nuget.org/packages/UrhoSharp.Forms/)を使っています。
    - [FormsSample](https://github.com/xamarin/urho-samples/tree/master/FormsSample)を参考にしています。
    - これの座標系は、まだよくわかってないです。座標値をプログラムに設定して表示させてみて・・・とカットアンドトライしました。
- BLE通信部分は、OSSライブラリの[Plugin.BLE](https://www.nuget.org/packages/Plugin.BLE/)を使っています。
- Xamarin.Formsについて
    - AndroidとiOSでコードを共通化できますが、ポータブルクラスライブラリ（PCL）と共有ライブラリの2種類があります。
    - Visual Studio Community 2017 for Macを使用していますが、新しいプロジェクト作成で「フォームアプリ」で進めると、共有プロジェクトの方でできてしまいます。
    - ポータブルクラスライブラリの方で作成したい場合、「空白フォームのアプリ」で進める必要があるところは、ちょっとハマりました。
Git + VSCode で SHIFT_JIS を扱うには Encoding 固定の方が便利

VSCode + Git で色々調べた結果、VSCode で SHIFT_JIS を扱うには、自動的に SHIFT_JIS 判別して、他にも VSCode の git.js の buffer() に textconv を設定したりとかありました。それはそれで間違いではないと思いますし、欧米語に比べて日本語の扱いづらさ (UTF-8 に至るまでに SHIFT_JIS やら JIS やら EUC やら過去の経緯で色々な文字コードが存在して、未だに後方互換を優先する Windows みたいな処理系があるとか) で、文字コードを設定するにしても色々な思想があるのだなと思う今日この頃。

色々試してみて、日本語の文字列が短すぎると VSCode の文字コード自動判定が失敗するので、やっぱり文字コード固定指定が良いのだなと思いました。

VSCode は基本 UTF-8 で運用しておいて、SHIFT_JIS 指定が必要な VBScript とか VBA のプロジェクトのフォルダの .vscode/settings.json に以下の指定を追加します。
settings.json は、「ファイル」→「基本設定」→「設定」→「ワークスペースの設定」で編集可能です。

```json:~/.config/Code/User/settings.json
{
    "files.encoding": "shiftjis",
    "files.eol": "\r\n"
}
```

ここでは、ファイルエンコーディングは SHIFT_JIS 決め打ちで、改行コードは CRLF にしています。
このときの ~/.gitconfig とプロジェクトの .git/config、.gitattributes は以下のような感じです。
改行コードの変換ができていないので git diff に -w を付けても ^M とか表示されてしまうのはご愛嬌で。恐らく iconv から nkf にして改行コードも変換するようにすれば何とかなるかと思いますが、Git for Windows には nkf は入っていないし、実害がないので我慢することにしました。

```config:~/.gitconfig
# git diff, git show 時に文字コード変換
[diff "cp932"]
    textconv = iconv -f cp932 -t utf-8
```

プロジェクト以下の Git の設定。
git config core.autocrlf ture で追加。

```config:.git/config
[core]
    # 他にも色々な自動で入った設定
    autocrlf = true
```

```config:.gitattributes
# Text
*       text=auto

# Diff
*       diff=cp932
```

diff の実行結果で、cp932 が一番しっくり来たのでこれかな。

## 2022年10月4日追記

特定の言語のみSHIFT_JISで扱う場合にはこんな設定ができる。
ただ、書いては見たが ```files.eol``` の設定は効いていないようだ。

```json:~/.config/Code/User/settings.json
// バッチファイル
"[bat]": {
    "files.encoding": "shiftjis",
    "files.eol": "\r\n"
},
// Visual Basic
"[vb]": {
    "files.encoding": "shiftjis"
    "files.eol": "\r\n"
},
```
sshfsを使ってみた

手元のマシンでSFTP環境を仮想的にマウントできるsshfsを便利に使ってみましょう！
※sftpとftpsは別物です。ftpsはftp over ssl、こちらはfile over sshです。

# sshfsとは

sshfsとは、fuseの一種で、あたかもsftp先のサーバーを自分のマシンのディレクトリとしてマウントできるものです。手元のマシンでそこに新しくファイルを作成すると、sftp先にも同じファイルが転送されます。まあ自動ミラーリングみたいなものです。

# インストール

Archなので以下でした

```
$ sudo pacman -S sshfs
```

# マウント

どうやらsftp先はホームディレクトリのchroot監獄になっているようなので、素直に`/`を指定しましょう。

```
$ mkdir ~/kosenspace
$ sshfs hoge@kosen.space:/ ~/kosenspace -o IdentityFile=~/.ssh/fuga
```

はい、これだけで完了です。
ただ、パーミッションが何故かrootのみになっていたり色々と怪しいので、後述の自動マウントを使います。

# 自動マウント

`/etc/fstab`に追記するだけでいいようです。

```
hoge@kosen.space:/  /home/hoge/kosenspace  fuse.sshfs noauto,x-systemd.automount,_netdev,user,idmap=user,follow_symlinks,identityfile=/home/hoge/.ssh/huga,allow_other,default_permissions,uid=1000,gid=998 0 0
```

最後のUIDとGIDは`id`コマンドで確認できます。
これで、起動時に自動でマウントがされるようになりました。
gemのローカルインストール

前にさんざんプロキシに泣かされた時にやったgemのローカルインストールの手順。
(-p でプロキシ経由もいけるけど、なんでだったかこの方法をとった気がする)
別環境でRailsのインストールしてて思い出したのでキロク。

でもそれこそRailsとか、でかめやつインストールするのにはやらないほうがいい。
地獄のgemたらいまわしがまってるから。

## 環境
OS：windows
サーバー：windowsServer

## ローカルインストール手順

#### 1.ネットの繋がる環境で、gemのDL
[本家サイト/gem一覧](https://rubygems.org/gems)

#### 2.サーバーにgemファイルを移動
PATHの通ったところにgemファイルを格納

#### 3.インストール

```cmd:コマンド
# インストール
$ gem install -l [gemファイルの名前]

# 確認
$ gem list
```

おしまい

## 依存gemを一括でいれるなら

ネットが繋がる環境にrubyとbundlerいれてあるなら、
gemを一括DLする方法があるらしいのでそっちの手順を踏むべし。
(やったことないから手順は不明)