OmniAICreator/Qiita-1.07M huggingface dataset:
MEAN環境を勉強してみる備忘録

# 基本的に自分向け記事である(という宣言)
Webは好きだが、Webのソースは嫌い。
なんだかコンパイルがないとか不安になるし、
どうにも型らしい型が無いような感じがいけ好かない。
何よりWebの事業会社のCTOさんたちに鼻持ちならない人が多く
あまりお近づきになりたくない感じだったのですが、
背を向けるのもイヤだったので、勉強する。

## デスクトップアプリ作成者にはきついお灸
自分の紹介的なもの。
- Windowsでの業務系アプリばかりを作っていた
- 老害レベルのVB.netとかDelphiとかやってた
- C#はそこそこ長い。
- Web？そんなの知らぬ！！っていう状態だったけど、さすがにWebをさわりはじめる。
- DBはOracle,SQLServer,PostgreSQL,MySQL,Sybase,DB2あたりは触ってるけど、NoSQLとかふぇぇぇ…状態。
- 転職を期にPHP触り始めたけど、なんだか慣れない…。

要するにクソ味噌レガシーエンジニアなわけです。
穴や粗があるかとは思いますがきつい突っ込みしないでね＞＜
Qiita内のモダンな方々、こんな私が生きててすみません！！！

※人に見せるというところより、自分の記録に主軸を置いている記事です。
私のような、老害YEAH!!!Web！！BOOOO!!!な人には
[「プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか](https://www.amazon.co.jp/%E3%80%8C%E3%83%97%E3%83%AD%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AEWeb%E6%8A%80%E8%A1%93%E5%85%A5%E9%96%80%E3%80%8D-%E2%80%95%E2%80%95%E3%81%AA%E3%81%9C%E3%80%81%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AFWeb%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%92%E9%96%8B%E7%99%BA%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B-%E5%B0%8F%E6%A3%AE-%E8%A3%95%E4%BB%8B/dp/4774142352)

こちらを読んでみていただきたい。
少しWebに足を踏み入れてみようかなって気持ちになるとおもう。

## Windows+Docker
どうにもVisualStudioを入れる関係で、Windowsを手放せない状況なので、
とりあえず開発環境を作ってみようとする。
Dockerのことをさらっとみてみたけど、ゲストOSが要らないという時点で素敵なにおい。
ただ、最近のWeb開発者はMacが多い関係上、ぴったりと来る記事が中々見つからず、
Windows版も出たばかりっぽかったので、とりあえず敗走となる。

## Windows + Virtual Box + Vagrant + CentOS
ほぼWebに対する知識ゼロに近い状態の私。
恥をしのんでN予備校に入校。[N予備校](https://www.nnn.ed.nico/)
（フォローアップと生放送での配信が結構自分の中ではしっくり来たので結構良かったです。）

Web関係の勉強の足がかりを得たため、そちらを踏まえ、
下記の記事をまねしてVagrantを利用して環境づくり。
[Vagrant(1.7.2)でCentOSをインストールする](http://qiita.com/ringo0321/items/f07ea1dfc9b7eb9326f8)
[Windows上にVirtualBox+VagrantでCentOS環境構築](http://qiita.com/TakashiOshikawa/items/d2fb48d59e9e316af9a2)

## はじめの1歩
### コンソールでVagrantに接続。
接続には、Poderosaを利用。

ホスト は、localhost
プロトコルは、SSH2
ポートは、2222
アカウントには、vagrant
認証方法は、パスワード
Password は、vagrant

これらを入力し、OKを押下。
無事に接続できますように！とちょっと祈りつつ接続。

### Nodeをインストール
接続が出来たらまずはNode.jsを入れるためにNodebrewを入れる。
[Nodebrewを使ってNode.jsを超高速にインストールする方法](http://qiita.com/yn-misaki/items/e92a47c662ea6d1236c1)
こちらを参考にし、
`node --version`
とコンソールに入力し、
`v6.11.0`
のようにバージョン番号が帰ってくる迄をやってみる。

### ここで降って沸いた疑問。Apacheとかいらないの？
N予備校 「Node.js」から引用
> Node.js とは、JavaScript でプログラミングすることのできる、サーバーサイド向けのプラットフォームです。 サーバーサイドとは、 サーバークライアント型のサービスのサーバー側のソフトウェアのことを指します。

要するにWebサーバだよってことと理解。
ExpressはNode.js向けのフレームワーク(裏っかわのやり取り系)。
AngularJSはフロント画面向けのフレームワークっと…。

### 初心者がNodeで躓いた点。
基本的に、Nodeで躓いた点はないのだが、
「なんだ、Javascriptじゃないか」という点。
自分が最初に触れたころから比べると大分様変わりしていたため、
1から触る言語のようで結構おろろ？となった。
ただ、基本関数型言語のような書き方はC#のラムダ式に似たものだったので、
なんじゃこりゃ！？とはならなかったのが幸い。
普通になにもしらない状態でvar hoge = function(a,b)=>{ console.log(a+b);}とか見たら
なんじゃこりゃ！！aとb殺す！！ぐらいになっていたかと思います。

## RDB⇒NoSQL 意外といいやん？！
### 言葉が変わる。
- テーブル⇒コレクション
- select * from テーブル名 ⇒ db.コレクション.find()
- where ⇒　db.コレクション.find({a:1}})
- where a > 1  ⇒　db.コレクション.find({a:{$gt: 1}})
- where a > 1 and a < 5 ⇒ db.コレクション.find({a: {\$gt:1 , \$lt: 5}})

言葉的だったものが合理的な書き方に変わっているが、
比較演算子に関しては、まるでCOBOLとかの時代に戻ったかのような感覚。

### 世の中ネコも杓子も関数型なんだなぁ…。
基本的に関数のような使い方ができる＝Javascript側の書き方と似通った感じなので、
親和性が高いように思えた。
書いているうちにおもったのが、LINQに似ているということだ。
なんとなくC#との共通部分を見出しつつ、頭のなかの点と点を結んでいる状況。

## Expressでアプリ作り。
続きはあとで
イラストレーターにフォントを追加する方法

##フォントの追加方法

1.フォントファイルをダウンロード
2.追加したフォントファイル（sample.ttfなど）を、ライブラリ/Application Support/Adobe/Fontsに追加する。

<br>
ライブラリはFinderの〇〇のMacbookのところのMacintoshHD内にあります。
AndroidでTensorFlowデモ(YOLO版)


TensorFlowのAndroidデモはYOLOに対応しているがデフォルトでは無効になっている。
YOLOを有効にしてビルドを行うための手順を記載。
バージョンはv1.2.1を使用。

# TensorFlowビルド

TensorFlowに必要なBazelのインストールは以下参照
http://knowledge.sakura.ad.jp/knowledge/6174/

TensorFlowのビルドについては以下参照
http://qiita.com/tchkwkzk/items/aa481db14126b6abdaa1
http://qiita.com/tomoima525/items/99a2df5cb0559c41647a

ポイントはNDK r12bを使うこと
TensorFlowのWORKSPACEには

> Android NDK r12b is recommended (higher may cause issues with Bazel)

とある。

古いNDKは以下からダウンロードできる。
https://developer.android.com/ndk/downloads/revision_history.html

## ビルドエラー `missing input file '@androidsdk//:build-tools/26.0.0/lib/apksigner.jar'`

WORKSPACEの`android_sdk_repository`の`build_tools_version="25.0.2"`にしたところビルドできた。
(25.0.2はAndroidStudioであらかじめインストールしておいた)

# darkflowインストールとモデルの変換

この時点ではTensorFlowのデモはYOLO未使用版である。

YOLOのモデルをTensorFlowで使うために[DarkFlow](https://github.com/thtrieu/darkflow)で変換を行う必要がある。

```bash
$ git clone https://github.com/thtrieu/darkflow.git
$ cd darkflow
$ pip3 install . --user
```

インストールされていなければ以下もインストールしておく

```bash
$ pip3 install --user tensorflow opencv-python
```

## モデルの変換

YOLOのページから[cfg](https://github.com/pjreddie/darknet/blob/master/cfg/tiny-yolo.cfg)と[weights](https://pjreddie.com/media/files/tiny-yolo.weights)を持ってきてflowコマンドでpbファイルに変換する

```bash
$ flow --model tiny-yolo-voc.cfg --load tiny-yolo-voc.weights --savepb
```

tiny-yolo-voc.pbが出来上がるのでそれをtensorflow/example/android/assetsに格納する

# デモの再ビルド

以下の変更を行い再ビルドするとYOLOが有効になったDetectionデモが実行できる

```diff
diff --git a/tensorflow/examples/android/src/org/tensorflow/demo/DetectorActivity.java b/tensorflow/examples/android/src/org/tensorflow/demo/DetectorActivity.java
index 5800f8065..c3b24846d 100644
--- a/tensorflow/examples/android/src/org/tensorflow/demo/DetectorActivity.java
+++ b/tensorflow/examples/android/src/org/tensorflow/demo/DetectorActivity.java
@@ -67,14 +67,14 @@ public class DetectorActivity extends CameraActivity implements OnImageAvailable
   // Graphs and models downloaded from http://pjreddie.com/darknet/yolo/ may be converted e.g. via
   // DarkFlow (https://github.com/thtrieu/darkflow). Sample command:
   // ./flow --model cfg/tiny-yolo-voc.cfg --load bin/tiny-yolo-voc.weights --savepb --verbalise=True
-  private static final String YOLO_MODEL_FILE = "file:///android_asset/graph-tiny-yolo-voc.pb";
+  private static final String YOLO_MODEL_FILE = "file:///android_asset/tiny-yolo-voc.pb";
   private static final int YOLO_INPUT_SIZE = 416;
   private static final String YOLO_INPUT_NAME = "input";
   private static final String YOLO_OUTPUT_NAMES = "output";
   private static final int YOLO_BLOCK_SIZE = 32;
 
   // Default to the included multibox model.
-  private static final boolean USE_YOLO = false;
+  private static final boolean USE_YOLO = true;
 
   private static final int CROP_SIZE = USE_YOLO ? YOLO_INPUT_SIZE : MB_INPUT_SIZE;
```
AWS LambdaでImageMagickによる画像への文字埋め込みで好きなフォントを使う方法

# LambdaでImageMagickを用いて好きなフォントを使う方法
方法は単純。
TrueTypeFontファイルへのパスをfontに渡してあげるだけ。
なのでデプロイパッケージに好きなフォントのttfファイルを含めてあげればできる。
下にサンプルソース。
(imagemagickのコマンドを使用する、こっちのほうが個人的には楽だった)

```js
const exec = require('child_process').exec;
const aws = require('aws-sdk');
const s3 = new aws.S3({region: "ap-northeast-1"});
const fs = require ('fs');
const uuid = require('uuid');

exports.handler = (event, context, callback) => {
  const dir = `/tmp/${uuid.v4()}`; // 書き込み可能なのは/tmp以下だけ、かつ名前重複でエラー起きるので重複できないようにする。
  const options = [
    "-size 300x300", // 画像のサイズ。変更元をxc:whiteにしているため必要
    "-font ipam.ttf", // TrueTypeFontファイルへのパス。好きなフォントのTTFを使えばよろし。
    "-pointsize 24", // 文字サイズ
    '-fill "#000000"', // 文字色
    "-gravity center", // 文字の基準位置
    '-annotate +0+0 "テスト"' // 文字。基準位置(もしくは左上)からの位置を調整できる。
  ];
  exec(`mkdir ${dir} && convert ${options.join(" ")} xc:white ${dir}/image.png`, (err, stdout, stderr) => {
    if (err) {
      callback(stderr.split("\n"));
      return;
    }
    s3.putObject({
      Bucket: "",
      Key: "",
      Body: fs.createReadStream(`${dir}/image.png`),
      ContentEncoded: 'base64',
      ContentType: 'image/png'
    }, (ex) => {
      if (ex) {
        callback(ex);
        return;
      }
      callback(null, "success");
    });
  });
};
```
VirtualBoxにインストールしたdebianにGuest Additionをインストールすると失敗する場合

VirtualBox Guest Additionをインストールしようとすると

```
vboxadd.sh: Building Guest Additions kernel modules.
Failed to set up service vboxadd, please check the log file
/var/log/VBoxGuestAdditions.log for details.
```

で止まる場合。

以下のようにインストール。(gccとかはインストールしてあること前提)

```
apt-get install build-essential module-assistant linux-headers-$(uname -r)
```

あとは普通に

```
su
sh VBoxLinuxAdditions.run
```

でOK。
NJM2035の調整

30年くらい前に秋月電子で買った組み立ててあったFMトランスミッターキットを調整してみました。（組み立て説明書は1985-3-1となっていました）

![IMG のコピー.jpg](https://qiita-image-store.s3.amazonaws.com/0/104066/619fc8ad-209e-8a72-b89c-d93edc316b3c.jpeg)


このキットは[後継機](http://akizukidenshi.com/catalog/g/gK-00086/)が今でも取り扱いがあります。私の持っている物は一番古いタイプで発振回路がトリマーのタイプです。

昔の秋月のキットは下の写真のように、ユニバーサル基板のような基板にパターンが切ってありました。

NJM2035のデーターシートを見ると11,12ピンのSUB-CARRIER BARANCEは50Kの半固定が使われているのですが、このキットでは100Kの抵抗直づけになっているので、部品箱をあさって50Kの半固定に交換してみました。現行のキットも100Kのままのようです。

![スクリーンショット（2017-07-19 16.12.52）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/27c572ea-7f98-2cd5-8105-68dc1bae65fb.png)

![IMGP0697.JPG](https://qiita-image-store.s3.amazonaws.com/0/104066/31ce9534-2401-f9a8-f8a7-56d7af19b7a5.jpeg)


この半固定の調整なのですが、データシートには「VR3を調整し副搬送波の漏れを細小にします。」とあるのですが、いろいろ試した所オシロスコーブで9ピンを確認して、波が最小になるようにすると良いようです。

半固定が一番端にあると以下のような状態です。

![Untitled4.jpg](https://qiita-image-store.s3.amazonaws.com/0/104066/a50f14bd-e0ef-4679-8a68-3b2d66937741.jpeg)

少しまわすとこうなります。

![Untitled3.jpg](https://qiita-image-store.s3.amazonaws.com/0/104066/d10ca2bb-762d-6472-8c29-81b3d7e03c9a.jpeg)

もう少しまわすとこうなります。

![Untitled6.jpg](https://qiita-image-store.s3.amazonaws.com/0/104066/d0812867-4901-450c-68d7-94191131beac.jpeg)

行き過ぎると、また波が出てきますので、波がないように調整します。オシロが無い場合はFMラジオで受信して一番クリアに聞こえる辺にすると良いようです。

8番ピンの出力はこんな感じです。

![Untitled1.jpg](https://qiita-image-store.s3.amazonaws.com/0/104066/6cde32b0-8143-1411-9bb7-64d829bf9ac4.jpeg)

今のキットは水晶になっていますが、私の持っている物はトリマーなので19Kに近くなるように調整してみました。

このキットを買った当時は、オシロスコープなんてもっていなかったんですが、将来こんな風に調整しているとは夢にも思わなかったと思います。

この記事のどこらへんが、プログラミングの話になるかというと、この信号のキャプチャは[さるのこしかけ](http://hp.vector.co.jp/authors/VA009278/monkey/)というオープンソースにしているMac OS Xのアプリでおこなっています。ObjectiveCとCで作られています。FT2232なモジュールを使ってGPIBのデータキャプチャもできます。興味ある人は、おそらく新しいXcodeではビルドできないと思うので、古いMacを用意してビルドして試してみてください。

調整終わったので、ケースに穴を空けて仕上げようと思ったら、穴をあけるときにケースを割ってしまいました。とりあえず接着剤で補修して作りました。ケース加工が苦手なのは30年進歩がありません。

せっかくなので[RTLSDR Scanner](http://qiita.com/yamori813/items/defa95a8783ca99864d7)で確認してみました。ロッドアンテナにアンテナ線を巻き付けて確認したのですが、パソコンから離さないとダメでした。

![Scan 76.0-79.0MHz.png](https://qiita-image-store.s3.amazonaws.com/0/104066/954c603a-a5f0-d4c8-6fd5-2e90a1923924.png)
Macの環境構築の同期・復元をかんたんにする

2020/01/19 Update: 整理しました

# はじめに

Macの環境を以前のものに復元するためにはconfigファイルを新環境になんらかの形で構築し直す必要があります。
本記事では低コストに環境構築を復元/同期/バックアップができるmackupというツールを紹介します。

mackupは指定したファイルを特定のディレクトリに移動させ、そこからもとのファイルの位置にシンボリックリンクを簡単に作ることができるツールです。
そして特定のディレクトリにクラウドストレージを指定することでMac間の環境の同期を実現することができます。

# インストール編

はじめに[mackup](https://github.com/lra/mackup)をインストールします

```sh
$ brew install mackup
```

# 設定編

mackupを使うには、バックアップ先やバックアップするアプリケーションを指定するための設定ファイルを作成する必要があります。
デフォルトの設定ファイルは、`~/.mackup.cfg`に保存します。

例えば、バックアップ先をGoogleDriveの設定し、特定のアプリケーションのファイルをバックアップする場合以下の様になります。。
アプリケーションごとにどのファイルがバックアップされるかは[mackup/applications](https://github.com/lra/mackup/tree/master/mackup/applications)を参考にしてください

```conf
[storage]
engine = google_drive
directory = Dotfiles

[applications_to_sync]
fish
fisherman
git
neovim
mackup
ssh
tmux
```

またバックアップ先にはクラウドストレージのみではなく、特定のディレクトリも指定できます。
これにより、クラウドストレージをのみではなく、Gitのレポジトリに対してバックアップをすることが可能です。私の場合、はじめはクラウドストレージを使って同期をしたいたのですが、不安定で同期されなかったりいつのまにか競合しているといった事象に出くわしたのでGitのレポジトリを通して同期させることにしています。。

```conf
[storage]
engine = file_system
path = <some/folder/in/your/home>
```


# バックアップ編

configファイルを作成したら以下のコマンドでバックアップします

```
$ mackup backup
```

実行すると指定したディレクトリにもとのファイルがシンボリックリンクとなり、特定のディレクトリにファイル本体が移動されます。

# リストア編

リストアは以下のコマンドで実現できます。
新規の環境に移った場合、mackup.cfgがないため最初にlnコマンドで.mackup.cfgのシンボリックリンクを作ると楽です。

```shell
$ mackup restore
```

# オリジナルバックアップ編

mackupが用意していないコンフィグファイルをバックアップする方法を紹介します。

ここでは、brewfileをバックアップしてみます。

```sh
# 出力先に.brewfileを指定する
# brewでインストールしているパッケージを書き出す
$ brew bundle dump --file=.brewfile
```

mackupで管理するために`.mackup`ディレクトリを作成し設定ファイルを書きます

```shell
$ mkdir ~/.mackup
$ vim .mackup/my-brewfile.cfg
```
```conf
[application]
name = My Brewfile

[configuration_files]
.brewfile
```

次に、`.mackup.cfg`にファイル名を追記します

```
[storage]
engine = file_system
path = src/github.com/mkazutaka/dotfiles

[applications_to_sync]
...
my-brewfile
```

以上で完了です。`mackup backup`コマンドでバックアップできます。


# まとめ

低コストに復元・同期をすることができました。
UserDefaultにログを貯めるクラス

TestFlight経由でしか再現できないとか、デバッグ実行中に再現できないとか、そういうときにサクッとログを貯めて調べたいときに使うLogger

```Lg.swift
class Lg {
    class func w(_ m: String) {
        func getNowClockString() -> String {
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss"
            let now = Date()
            return formatter.string(from: now)
        }
        let log = "[SIMPLE-LOG] \(getNowClockString()) \(m)"
        let key = "LOGGER_USERDEFAULT"
        var logs = UserDefaults.standard.array(forKey: key)
        if logs == nil {
            logs = [log]
        } else {
            logs?.append(log)
        }
        UserDefaults.standard.set(logs, forKey: key)
    }
    class func w(_ m: Any) {
        func getNowClockString() -> String {
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss"
            let now = Date()
            return formatter.string(from: now)
        }
        let log = "[SIMPLE-LOG] \(getNowClockString()) \(String.init(describing: m))"
        let key = "LOGGER_USERDEFAULT"
        var logs = UserDefaults.standard.array(forKey: key)
        if logs == nil {
            logs = [log]
        } else {
            logs?.append(log)
        }
        UserDefaults.standard.set(logs, forKey: key)
    }
    class func r() {
        let key = "LOGGER_USERDEFAULT"
        guard let logs = UserDefaults.standard.array(forKey: key) else {
            return
        }
        for log in logs {
            print(log)
        }
    }
    class func c() {
        let key = "LOGGER_USERDEFAULT"
        UserDefaults.standard.removeObject(forKey: key)
    }
}

```
# 書き出し
```kakidasi.swift
Lg.w("ログメッセージ")
```

# コンソール出力
```put.swift
Lg.r()
```

# 消去
```del.swift
Lg.c()
```

小さいプロジェクト向けに。
Dockerfile命令一覧

|命令|説明|
|:--|:--|
|FROM|ベースイメージの指定|
|MAINTAINER|Dockerfileの作成者情報|
|RUN|コマンド実行|
|CMD|デーモン実行|
|LABEL|ラベルの設定|
|EXPOSE|ポートのエクスポート|
|ENV|環境変数の設定|
|ADD|ファイル/ディレクトリの追加|
|COPY|ファイルのコピー|
|VOLUME|ボリュームのマウント|
|ENTRYPOINT|デーモン実行|
|USER|ユーザの指定|
|WORKDIR|作業ディレクトリの指定|
|ONBUILD|ビルド完了後に実行される命令|
SmartGit > git commit --amendに相当する操作

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit Version 17.0.4 #10132
```

SmartGitで`git commit --amend`に相当する操作を行うには。

- Journalペインにて直前のコミット上で右クリック
    - Edit Commit Message...を選択
    - 開いたウィンドウでメッセージの変更、保存
    
直前だけでなく、Pushしていないコミットのメッセージは変更できるのかもしれない (未確認)。
RubyでCSVのヘッダーとデータが別々の2ファイルからCSV::Tableをつくる


下記のようにデータレコードとそのヘッダが別々のファイルに保存されているような場合に、2ファイルから1つのCSV::Tableをつくりたい。

```csv:header.csv
id, name, score
```

```csv:data.csv
1, john, 10
2, paul, 12
```

結論としては1.のheadersにヘッダーの配列を渡す方法がすっきり確実そうです。


## 1. オプションのheadersにヘッダーの配列を渡す

@hanachin_ さんから教えていただいた方法。すっきりしていい感じ…！

```rb
require 'csv'

headers = CSV.parse_line(File.read("header.csv"))
p CSV.table('data.csv', headers: headers)

CSV.table('data.csv', headers: headers).each do |r|
  p r.to_h
end

# #<CSV::Table mode:col_or_row row_count:3>
# {:id=>1, :name=>" john", :score=>10}
# {:id=>2, :name=>" paul", :score=>12}
```

## 2. ヒアドキュメントでがっちゃんこする

@yancya さんに教えていただいた方法。そんな技が…。知らなかったです。

```rb
require "csv"

header = File.read("header.txt").chomp
rows = File.read("data.csv").chomp

table = CSV.parse(<<CSV, headers: true)
#{header}
#{rows}
CSV

p table
# => #<CSV::Table mode:col_or_row row_count:3>
```

## 3. シェルコマンドとCSV.newの合せ技

さすがにTempfileを使う方法から頭悪すぎる感が滲んでいたので、周りのエンジニアの方にもお知恵をいただいた結果かなりスッキリしてきました。

```rb
str = %x(cat header.csv; echo ""; cat data.csv)
p CSV.new(str, headers: true, header_converters: :symbol).read
# => #<CSV::Table mode:col_or_row row_count:3>
```

ただしこの方法だと、末尾の改行だったり、文字列が`"`で囲われているかどうかだったりと、色々なことが整った状態でないとうまくいきません。


## 4. Tempfileを使う

最初に試した方法。

```ruby
CSV.table('path/to/csv')
```

本来であれば上記のように1ファイルでサクッとできるのだが、2ファイルに分かれてしまっているので、`Tempfile`を使ってヘッダをくっつけた仮のCSVファイルを生成し、そこからCSV::Tableをつくってやる。

```rb
header = File.read('header.csv')
data = File.read('data.csv')

csv = nil
Tempfile.open do |t|
  t.write header
  t.write "\n"
  t.write data
  csv = CSV.table(t.path)
end

p csv

# => #<CSV::Table mode:col_or_row row_count:3>
```



## Ref

- [class CSV::Table](https://docs.ruby-lang.org/en/2.4.0/CSV/Table.html)
はじめてのシェル

初学者向けにシェルについて書いてみた。

# シェルとカーネル

LinuxOSは、内部の仕組みとして、大きく、カーネルとシェルと２つの部分に分ける事ができる。先ず、プロンプトから、dateコマンドをうってみると、当然、システム日付が返ってくる。

```shell-session
$ date
2017年 7月 19日 水曜日 14:47:41 JST
```

内部的にどのような仕組みになっているのだろうか。dateコマンドが直接カーネルにアクセスして結果を表示してくれるのではなく、シェルに対して命令を出している事になる。そして、シェルがカーネルにdateの処理を渡して、カーネルが処理した結果を、シェルに返して、シェルが画面に結果を表示してくれるという流れだ。つまるところ、シェルとは画面とカーネルのインタフェース的な役割をしているということになる。

# シェルの種類

シェルにもいろいろと種類があるらしく、初心者は一般的にこれさえ知ってたらいいよといわれているのが「bash」。なぜ、これがいいかといえば、世間で一番利用者が多く、書籍も多く、情報も溢れている。そしてなにより、一番使いやすいということだ。歴史の話になるが「bash」のひと世代前に「sh」というシェルがあり、それが拡張されて生まれたのが「bash」。「sh」は「Bシェル」ともいう。

「sh」は古いといいながらも、今でも全然現役でバンバン動いているようだ。他にも「csh（Cシェル）」、「tcsh」などの種類があるようだが、どうも、これらはシェルスクリプトを書くには使えないらしい。なので、大抵の人には不要だろう。


# シェルの変更

Linuxにログインした時、`$`のプロンプトが表示されるが、実はプロンプトが表示するまでの間に、バックでログインシェルなるシェルが流れている。ログイン時に流れるシェルなのでログインシェル。ログインシェルのデフォルトで使用されているのが「bash」。本当に「bash」かどうかコマンドで確認できる。このようになれば「bash」。

```shell-session
$ echo $SHELL
/bin/bash
```
「sh」に変更してみよう。プロンプトが「`~$`」から、単に「`$`」に変更したら「sh」シェルに変更したということになる。

```shell-session
$ sh
$
```

プロンプトから「bash」のコマンドをうつと「bash」に戻る。プロンプトも「`~$`」になる。

```shell-session
$ bash
:~$
```
ホームアプリアイコンの削除時にプルプル震えるアニメーション

#下記のアニメーションの処理は現在では古い方法となっております。一応残してはおきますが、もし参考にする時はお気をつけください。

ちょっと適当になんでも良いからプログラムを作りたくなり、
iphoneのホームボタンの様にプルプル震えるアニメーションを簡単に使用できる
UIButtonクラスを継承したクラスを作成してみた

        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(TimeInterval(self.animSpeed))
        UIView.setAnimationDelay(0.0)
        UIView.setAnimationRepeatCount(1e100)
        
        if (self.type == .right) {
            let rote : CGAffineTransform = CGAffineTransform(rotationAngle: CGFloat(self.slopeRigt * (.pi / 180.0)));
            self.transform = rote
            self.type = .left;
        } else {
            let rote : CGAffineTransform = CGAffineTransform(rotationAngle: CGFloat(self.slopeLeft * (.pi / 180.0)));
            self.transform = rote
            self.type = .right
        }
        
        UIView.commitAnimations()

こんな感じで,CGAffineTransformを使用して
右と左にプルプル震える様にアニメーションをさせてあげる

終了するときは
`self.layer.removeAllAnimations();`
これで終了

一つ気になったのが、
無限にアニメーションさせるために
setAnimationRepeatCountを使用しているが、その時の値が1e100であること、、、
ちょっと調べたらこれで無限アニメーションになるよって記事みつけたけど、本当にいいのだろうか、、、

ってか、このアニメーションのさせ方自体が古い？
アニメーションのクロージャを設定するやり方が今時のやり方かな？

時間がある時にまた違う方法で実装してみようかな
クラウドサーバでTensorFlow　その14

#概要
クラウドサーバでTensorFlowやってみた。
kaggleのdogs vs catsやってみた。

#環境
クラウド idcf
linux debian-8.11
tensorflow 1.2
gpu 無し

#写真

30バッチで1000エピソードやってみた。
netは、softmax_linerで10層。
画像は、208*208*3で入力。
ckptを保存した。

![dogs1.png](https://qiita-image-store.s3.amazonaws.com/0/18104/0028c5d3-141d-3860-84ce-cf02cd343224.png)
Windows10HomeエディションにLaradockをインストールし開発環境の構築

■環境
Windows10 Home

■docker toolboxのインストール
Windows10HomeではHyper-Vを使用できないため、docker toolboxをインストールする。
https://www.docker.com/products/docker-toolbox
※インストールにはPC管理者ユーザーのパスワードが必要

ウィザードに従ってインストール
・Git for Windowsもインストール
・Install VirtualBox with NDIS5 driverにチェック

■Docker Quickstart Terminalの起動
デスクトップの「Docker Quickstart Terminal」を起動するとVirtualBoxにdefaultが院トールされ実行状態になる。

■作業用ディレクトリの設定、作成
VirtualBoxを起動し「default」を選択
「設定」をクリックし、表示されたウインドウの「共有フォルダー」を選択。
共有フォルダーをダブルクリックで開き、以下の通り設定する。
フォルダーのパス：C:\dockerWorkspace
フォルダー名：c/dockerWorkspace

※次の画像参照
SmartGit > ショートカットキー > Open Git-Shell > Alt, t, g

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit Version 17.0.4 #10132
```

git stashなどで使うGit-Shell。

キーボードで開くには`Alt, t, g`でいいようだ。

他のメニュー項目を実行するにもAlt使用でマウスが不要になる。
SmartGit > ショートカットキー一覧表示 > Edit -> Customize...

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit Version 17.0.4 #10132
```

ショートカットキーを表示するには

参考: http://smartgit.3668570.n2.nabble.com/keyboard-shortcuts-td6088574.html

Edit -> Customize...

以下のような一覧が表示される。

![2017-07-19_15h02_54.png](https://qiita-image-store.s3.amazonaws.com/0/32870/101ee889-bc95-844f-e35c-37a070b74741.png)

Acceleratorという項目がショートカットキーのようだ。

「Open Git-Shell」などを含むToolsはこの一覧にはない。
Altとのコマンド組み合わせで使うことになりそう。
Arduino Ethernet シールド互換品

HiLetgo というところから Arduino Ethernet シールドを[購入](https://www.amazon.co.jp/gp/product/B007YJA4WE/)した。Arduino 製の Ethernet シールドはバージョン更新が何度かかかっているけれども、入手したものは R2 と同等品の実装の様子。

このボードは ISCP 端子も使って Arduino と接続するようになっている。ややこしいことに Arduino Uno は ISCP 端子とデジタル端子に一部同じ信号が出ていて、内部で繋がっている。

調べてみたところ、シールド側は ISCP 端子の MOSI, MISO, SCK を使っていて、SS の 10 番ピンを使っている。https://www.arduino.cc/en/Reference/SPI にも記述がある。

シールドをジャンパで接続させると、こんな感じで動作した。シールド側の 11, 12, 13 は W5100 に向かって配線されていない。

![IMG_20170719_133246.jpg](https://qiita-image-store.s3.amazonaws.com/0/41883/e606989e-5b5e-f99f-d6fd-7fab46b2b7aa.jpeg)
遅ればせながらGalaxy S7 edgeを手にして行ったこと

Qiita初投稿にして、ほぼ技術ブログではない内容ですがなんとなくUp。
Markdown記法に慣れない+Kobito に慣れないで時間がかかってます
# 自身のAndroid歴
* 実は意外と長いのに、正直初心者
* 卒論時AndroidアプリをJavaで構築しようとして失敗→別テーマに切り替えた
* 以前はGalaxy S4を使用。今年こそはAndroidも使いこなしたい

# 具体的な設定項目
### 開通作業(機種変更作業)
    Do○omo回線を使用。これは省略
### ソフトウェア更新
    必要に応じて。なんとなく先にやったほうがいい気がしたので。
### 羊を消す
    ホーム画面にフワフワ浮いているアレ…コンシェルジュっていうやつらしい。真っ先に消す
### スクリーンショットを通る
    羊を消す設定を撮りたかったので
### dアプリを消す
	一旦は一覧から消す
### ホーム画面を整える
### Google accountを作る
	諸事情により、新しいアカウントをつくる
### Google Playにログインする
    先ほど作成したアカウントでログインする
### Doc○moIDを設定する
    これが必要。
    機種変更だったのでクラウドサービスに連絡先をあげていたので必須。
### 日時設定を24時間表示にする
	設定→日時と時刻→24時間形式を使用
### キーボード設定をする
    特殊かもしれないが、どうしても日本語以外はQWERTYキーボードにしたかったので。(両手を使う前提)
### 必要なアプリをインストールする
    Google Playよりダウンロード
    
# 感想
* 全体的に画面やアイコンがぷっくりしている
    　かわいい
* ソフトウェア更新から携帯が発熱している！
    　大丈夫かコレ…
* 小さい手には非常に不向き(当たり前)
    　iphone6も持ってますが、それよりデカい…画面の1/8しか親指で触れない
   
***
※画像がないのでそのうち更新します。
SmartGit > master (Local branches) への他branchからのmerge | merge解除

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit Version 17.0.4 #10132
```

SmartGitでの、別branchでコミットした変更をmasterにmergeする方法とmerge解除方法。

### masterへmergeする

Branchesペインで以下の作業をする。

1. Local Branchesにおいてmasterをcheckoutする
2. Local Branchesで取り込みたいbranchの上で右クリック
    - Mergeを選択
    - [Fast-Forward],[Create Merge-Commit]などの選択をする
    
以上でLocal Branchesのmasterにマージされる。

### mergeの解除

1. Local Branchesにおいてmasterをcheckoutする
2. Merge前のcommitを探して、その上で右クリック
    - Resetを選択
    - 'hard'を選択してReset
IntelliJ IDEA にてSpring Boot Devtools の Restart が機能しない

# Spring Boot Devtools を IntelliJ IDEA で動かす
IntelliJ IDEA にて Spring Boot Devtools の設定をした際、一向に変更が反映されず、はまってしまったので備忘録。
結論としては、[こちらの記事](http://qiita.com/sekainohsan/items/cc998596def1cc250a5c "IntelliJ の Spring Boot を使ったプロジェクトでコード変更時に自動で再コンパイルする設定")のとおりでした。
素晴らしい記事です。

##シクりポイント
1. 魔法の力を信じてしまった

https://stackoverflow.com/questions/33869606/intellij-15-springboot-devtools-livereload-not-working
>I am guessing you are coding and expect DevTools to auto-magically figure out you have changed something in your project? Devtools does that by watching your classpath folder(s). When a .class file (or a resource) has changed, devtools take the appopriate action.

2.レジストリの設定を知らなかった

これは何か? 公式でも出てこない気がする。。

**compiler.automake.allow.when.app.running**

**2017/08 追記**
3. main メソッドから起動しなかった

タスクランナーとして Gradle を使用していますが、アプリケーションの起動タスクとして、bootRun　があります。
bootRun から起動すると、Gradle のビルド先である $projectRoot/build がリソースの変更対象として監視されるようになります。

> 14:42:38.506 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Included patterns for restart : []
> 14:42:38.509 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Excluded patterns for restart : [/spring-boot-starter/target/classes/, /spring-boot-autoconfigure/target/classes/, /spring-boot-starter-[\w-]+/, /spring-boot/target/classes/, /spring-boot-actuator/target/classes/, /spring-boot-devtools/target/classes/]
> 14:42:38.509 [main] DEBUG org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs for reloading : **[file:/Users/userName/Documents/workspace/projectName/build/classes/main/, file:/Users/userName/Documents/workspace/projectName/build/resources/main/]**

しかしながら、IntelliJ IDEA にてコンパイルすると成果物は、$projectRoot/out 配下に配置されます。
$projectRoot/build 配下にリソースを配置する役目は Gradle となりますが、Gradle が動作するきっかけがありません。
このため、main メソッドからアプリケーションを起動させて、$projectRoot/out フォルダ配下を変更の監視対象にします。

> 14:32:12.395 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Included patterns for restart : []
> 14:32:12.398 [main] DEBUG org.springframework.boot.devtools.settings.DevToolsSettings - Excluded patterns for restart : [/spring-boot-starter/target/classes/, /spring-boot-autoconfigure/target/classes/, /spring-boot-starter-[\w-]+/, /spring-boot/target/classes/, /spring-boot-actuator/target/classes/, /spring-boot-devtools/target/classes/]
> 14:32:12.398 [main] DEBUG org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs for reloading : **[file:/Users/userName/Documents/workspace/projectName/out/production/classes/, file:/Users/userName/Documents/workspace/projectName/out/production/resources/]**
Laravel5.4のメール送信でContent-Transfer-Encodingを変更する

Laravelでメール送信を行うとデフォルトでは、**quoted-printable**　になります。
それを変えようと色々悪戦苦闘しながらたどり着いた方法です。

環境
Laravel5.4
php7.0.19

```
\Mail::send ( array('text' => $view), $data, function ($message) use ($subject, $address) {
	$message->to ( $address )->subject ( $subject );
	
	// ここを追加
	$message->getSwiftMessage()->setEncoder(\Swift_Encoding::get8BitEncoding());
	
	// ヘッダーを追加する場合
	$message->getSwiftMessage()->getHeaders()->addTextHeader('X-Mailer', 'PHP/' . phpversion());
	
} );
```

また、**get8BitEncoding()** を **get7BitEncoding()** にすれば7bitでも送信できます。

参考：[http://luke.nehemedia.de/2014/03/25/laravel-emails-mit-8bit-content-transfer-encoding-senden/](http://luke.nehemedia.de/2014/03/25/laravel-emails-mit-8bit-content-transfer-encoding-senden/)
InterfaceBuilderで色を設定するときはcolorSpaceに気をつけよう


IB上で `colorSpace="calibratedRGB"` (IB上では `Generic RGB` ) で色が定義されていると、定義よりも少し白味が増す形で表示されてしまいます。
以下の例ではどちらもカラーインスペクタのRGB Sliderペインで `#CCCCCC` を指定していますが、左側では "Generic RGB" になっており、シミュレータ上の色を計測すると `#D6D6D6` になってしまっています。
![ib-rgb-configuration.png](https://qiita-image-store.s3.amazonaws.com/0/35008/9d451ded-a6b4-fab5-7ba4-2e2291603662.png "ib-rgb-configuration.png")

初期状態だとこの `colorSpace` は設定されないようなのですが、
例えばRGB Sliderペインの "Hex Color" を直接変更すると "calibratedRGB" に自動的にチェックが入ってしまいました。

iOSとtvOSどちらでも同じでした。
xibやstoryboardで設定した色がどうも想定と違うという場合には確認してみると良さそうです。
Google APIコンソールを使わずにDrive APIを有効にする

# 概要
これまでGoogle Apps Scriptを使ってDrive APIを使用する場合、手動で[Google APIコンソール](https://console.developers.google.com/)を使ってDrive APIを有効にする必要がありました。最近のアップデート？（具体的な日付は不明です）で個人的には便利と思われる変化が認められましたのでこちらでも情報を共有できればと、記載させていただきます。

その変化は、APIコンソールを使用せずともDrive APIを有効にすることができるようになったことです。

# Drive API有効化の手順
有効化させるには若干の手順が必要です。

スクリプトエディタを起動すると、デフォルトで下記のような関数が表示されています。

~~~javascript
function myFunction() {

}
~~~

この状態でAPIコンソールで有効になっているAPIを見ると、下記のように何もありません。

![fig1.png](https://qiita-image-store.s3.amazonaws.com/0/133383/2ca0c38f-a192-2044-7d3b-ac7566ccef63.png)


そこで、次のようなスクリプトを追加します。コメントアウトしたままで問題ありません。この入力後にスクリプトを**保存**します。

~~~javascript
function myFunction() {
  // DriveApp.getRootFolder()
}
~~~

すると、下記のように**Drive APIが有効状態**になります。（スクリプトを保存しただけで認証プロセスは行っていません。）

![fig2.png](https://qiita-image-store.s3.amazonaws.com/0/133383/370dae65-10ee-61cb-881a-b9d6e74ca46f.png)


プロジェクトのプロパティからスコープを見ると``https://www.googleapis.com/auth/drive``がありました。実際にDriveAPIを使用する場合はスコープの実行を許可するプロセスが必要ですが、これまでのようにAPIコンソールを開いてDrive APIを有効にする必要はなくなりました。

スクリプトを保存しない状態ではAPIは有効になりません。また、``DriveApp``の単語だけでもAPIは有効になりません。**DriveAppを使おうとする内容のスクリプトと、そのスクリプトの保存が有効化のトリガー**になっているようでした。他のAPI（全てではありません）も調べてみたところ、今のところ、DriveAPIだけが自動で有効になるようです。

# お得なこと？
Drive APIの自動有効化について個人的にお得になりそうと思ったことは次の通りです。

1. ``ScriptApp.getOAuthToken()``で取得したアクセストークンにはスコープとして``https://www.googleapis.com/auth/drive``が含まれているため、拡張サービスの"Drive"を使用せずとも``UrlFetchApp``を使ってDriveAPI v2, v3を使用することができる。
1. スクリプトの配布やスクリプトの説明時に、これまで行っていたAPIコンソールを使ったDriveAPIの有効化手順の記載を省くことができる。
1. Drive APIの有効化を失念することでエラーが発生することはなくなる。

上記ような状況は一時的なものかどうかは不明です。

# 更新: 2019年6月29日
1. 2019年4月8日以降にGoogle Apps Scriptのプロジェクトを新規作成すると、スクリプトエディタ上でAdvanced Google services（Googleの拡張サービス）で使用したいAPIを有効にするだけで実際のAPIも有効化されるようになりました。これも利用できるかと思います。

2. 以前は``DriveApp.getRootFolder()``などのメソッドをスクリプトエディタ上に書くと``https://www.googleapis.com/auth/drive``のスコープが自動的に追加されましたが、最近ではこの場合、``https://www.googleapis.com/auth/drive.readonly``となり、メソッドにより必要最小限のスコープの追加が可能になっています。``https://www.googleapis.com/auth/drive``を追加したい場合は、例えば``DriveApp.createFile(blob)``などを記入すると自動的に追加されます。

- [参考](https://developers.google.com/apps-script/guides/services/advanced)
勉強会レポート - モールに依存しない！SEOで集客力強化！本店の利益増倍セミナー


## 資料と紹介
[セミナーレジュメ](http://www.ecjissenkai.com/img/blogs/seminarresume.pdf)

講師：水上浩一　氏
独自ドメインのサイトをどのように盛り上げるか。利益をあげるのが目的。
10年間ECの経験あり。チーズバーを年間24万本販売。月8,000本販売。
客単価3,000円で月1,000万の売上。
・送料クール便800円を無料にしたら赤字。売れば売るほど赤字。
・売れ筋をやめたら減収増益になった。

！！実践しないと売上が増えないのが実践会！！

#### 幸せな売上をつくる
・値引きしない
・広告費を適正に使う
　平均10〜15％　酷いと30％使っている。売上市場主義はいけない。売上より利益。

▼以下は6月に参加した『[勉強会レポート - 脱・モール依存！自社EC成功事例セミナー](http://qiita.com/Tanazawa/private/4135f13138bdc8f0af3b)』を膨らませた内容▼

## モールと自社ECの違い
モール依存のリスク
・効果測定がしにくい、お金がかかる
　→広告費が『投機的』になっている
・ランキングやビュー数・CPC広告ばかり気にしてしまう
　→接客やサポートがおろそかになる。離脱懸念がある。

売上　＝　アクセス数　×　転換率　×　客単価
　　　　　　　　　　　アクセス数　＝　新規＋リピーター
→各変数の数値をあげることが大切

★自社の顧客リストが大切
★売上より利益が大切
　　売上中毒に要注意

★モールではできない本店での効果的な施策
リスト活用・接客　リピート集客　
スマフォマーケティング　転換率・客単価
コンテンツマーケティング　新規集客・転換率
SEO集客　新規集客
広告の効果測定　新規集客・リピート集客・客単価up

## リスト活用・接客　リピート集客　
【例】e-花屋さん
3月にギネス級の売上をあげる
＝閑散期の売上＝底上げが大切
接客を重視してメルマガや接客を重点的に行う

モールは季節イベント集客なので売上差が激しい。
→繁忙期の利益を閑散期に吐き出す経営になりがち。
→繁忙期基準の販管費にしているため。（季節採用はノウハウが蓄積しない）

★閑散期の売上の作り方
繁忙期に売る上げ、ユーザー数をアップ
→そのユーザに対して通年売れるものを閑散期に紹介
接客が大切！！
繁忙期と閑散期の商品をしっかりつくる

メールよりLINE＠が良い→反応率が30％
メールは良くて6％

【津田コスメ】
お試しメール→ステップメールの活用で年間５回ギネス更新。
年間4,000万の売上貢献
3日（津田コスメとは）・7日（隠れ炎症肌）・10日（隠れ炎症肌チェック）後に送信

ステップメールはシステム化しよう！
売上が上がっても固定費を上げない方法を考える

## スマフォマーケティング　転換率・客単価
世の中のデバイス比率　7：3＝SP：PC
スマフォの転換率は上げられる＋決済方法の工夫
→タップ数を減らす＝トップページに商品をたくさん掲載する

回遊しないので顧客単価が下がる
→セット販売を提唱する

シーン提案を行う
【例】長寿のお祝い、転職のお祝い　など

【例】ジョッパーズ
購入者は買う前に買わない理由を探す
買わない要因である不安要素を解消する（サイズがあうか？）
→ブーツお試しキャンペーン
→返品は『経費』でなく『販促費用』として計上
→乗馬クラブ内での口コミを狙う（購買のイメージができるかどうか）

スマフォではできるだけ文字を読ませないようにする
→イラストや写真を使う

【例】キューリングKカップ
選べる8箱セットはプルダウンが大変
→3択から選べるようにした
→売上200％アップ
★選びやすくした（選びにくいから）

★売れない三大理由
1.商品が選べない
2.リソース分散
3.ターゲット間違え

商品の一点集中を実践する！
★一番売れている商品を調べる
どの商品もまんべくなく売れていたら『選べない』状態になっている
売れている店舗は1位の商品がダントツで売れている。2位と10％以上の差がある。

マーケットシェア率の応用
26.12 20〜25％
41.7 35〜40％
73.88 75％

【例】ワークストリート
型番商品の中のオリジナル商品に注力する
オリジナル商品の開発ストーリーを書いて共感してもらう→安全靴『チャーリー』とは？
→お得感、第三者評価、お客様の不安要素解消（値引き・サイズ交換キャンペーン）
転換率アップ　3.73　→　5.18

★スマフォはトップページが大切
★階層が深いほど転換率が下がる

AmazonPayを導入
Amazonに渡る情報は購入金額のみ
3クリックで購入できる

## コンテンツマーケティング　新規集客・転換率

★コンテンツマーケティングの基本は【共感の創出】
１、人
　共感創出プロフィール
２、商品
　選び方コンテンツ『商品の選び方』　いきなり商品を選べと言われても困る。。。
　【例】京都東山堂　合気道着でSEO 1位　※言葉のゆらぎに注意
３、店舗・会社
　【例】エッセンシアライズ
　サポート力でファンを獲得。スタッフが資格を取得。電話対応。
　転換率　PC　0.9→3.2　スマフォ　0.8→3.4
　　
オリジナル商品は検索されないから売れない
オリジナル商品は集客力が大切

・第三者評価
・お得感
・お客様の不安要素を解消
女性向きは女性目線、男性向けも女性目線が大切

★コンテンツの質（価値あるコンテンツ）
★コンテンツの量を増やす
　→googleのインデックスを増やす▲の底辺を増やす＝商品を増やす　
　商品がない場合はグログなどでカバーする
Q＆Aをブログでかいてコンテンツを増やす

## SEO集客　新規集客
モールと本店の動線の違い
・モール
　サーチ起点なので店舗内回遊がない
　楽天サーチは価格コムと同じ　インプレッションが上がっても売上が下がる
　価格が高いままインプレッションを上げても売れない
・本店
　トップページのセッション数が多い→回遊が起こる

検索エンジンは価格比較されにくい
楽天GOLD7〜8割で集客している店舗がある
→楽天でもSEOで商品が売れる

本店のトップページで必須要素がある　※別表参照

SEOで集客力が高まったあとにクーポンやポイント施策で転換率をあげる
５％割引程度のクーポンを作成する

## 広告の効果測定　新規集客・リピート集客・客単価up

【例】O.C.Farm
効果測定でリスティング広告はチューニングしましょう。
ノウハウ化！
お試しセットから大袋のバンドル販売
→ 商品設計をしっかり行う
初回購入から2回目のリピート率47％

★『選びやすさ』は転換率UP
★不安要素解消コンテンツはSEOにも効く

## まとめ
1.コンテンツ・ブログ活用など自社でコントロールできる集客方法
2.集客商品　→　本命商品。閑散期の底上げ。
3.スマフォの転換率をアップさせる共感要素・シーン提案
4.接客・ホスピタリティ
5.実践できるシステムを使う

※その他
出荷可能時間の時間戦略
1ページ目に10のうち7以上販売サイトがあれば良いキーワード
ターゲットキーワードの探しが大切（購買確率の高い）
売上目標の5〜7％が広告費が理想
仕事の8割は集客と商品開発

売上らない理由は必ずある。
例：LPのファーストビューの精度（おじさんではなく子供にする）
phpPgAdmin 5.1でレポート機能を有効にする

# phpPgAdminのレポート機能とは？

SQLに名前をつけておいて、一発で呼び出せるようにする機能。
PostgreSQL自体に備わっているビューと似ているが、SQLを別のデータベースに保存しておく点が違う。
非常に小さなプラグインなので、ローカルファイルに保存するように変更なども簡単にできると思う。

phpPgAdmin 5.1以前では標準で入っていたようだが、5.1からプラグインになったらしい。とはいっても標準パッケージに同梱されているので、ちょっと設定をするだけで使えるようになる。


# 設定方法

## conf/config.inc.phpを編集

```conf/config.inc.php
$conf['plugins'] = array('Report');
```

## PostgreSQLサーバにレポート保存用のデータベースを作成

`phpPgAdmin-5.1/plugins/Report/sql/reports-pgsql.sql`に作成用のSQLが入っているので、これを実行する。

## 確認

画面左のツリーからサーバを選択した画面で、下記のように「レポート」が表示されるようになる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/79394/8ee78e33-f025-8b2c-7079-bdbcd4ebba48.png)


# ドキュメント

phpPgAdmin-5.1/plugins/Report/README
phpPgAdmin-5.1/plugins/Report/INSTALL
がドキュメントらしい。
mockitoでstaticなメソッドをMock化する

## PowerMockを使用する
mockitoでstaticメソッドはMock化できないので[PowerMock](https://github.com/powermock/powermock/wiki)を使用する。

## ソース
### テスト対象クラス
```java:MoriUtilA.java 
public class MoriUtilA {
	public static String getMoriString(String inStr){
		return "あなたは" + MoriUtilB.isMoriorHayashi(inStr) + "です";
	}
}
```

### モック化するクラス
```java:MoriUtilB.java 
public class MoriUtilB {
	public static String isMoriorHayashi(String inStr){
		// 入力値が「もり」なら「森」を、それ以外なら「林」を返す
		return "";// 未作成
	}
}
```

### インポート文
```java
import static org.powermock.api.mockito.PowerMockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
```

### テストクラス
```java:MoriUtilATest.java
@RunWith(PowerMockRunner.class)
@PrepareForTest({MoriUtilB.class})
public class MoriUtilATest {
	@Before
	public void setUp() throws Exception {
		// MoriUtilBをモック
		PowerMockito.mockStatic(MoriUtilB.class);
	}
	@Test
	public void mockTestMori() {
		// モックの返却値を設定
		when(MoriUtilB.isMoriorHayashi("もり")).thenReturn("森");
		// 実施
		String actual = MoriUtilA.getMoriString("もり");
		assertEquals("あなたは森です", actual);
	}
	@Test
	public void mockTestHayashi() {
		// モックの返却値を設定
		when(MoriUtilB.isMoriorHayashi(anyString())).thenReturn("林");
		// 実施
		String actual = MoriUtilA.getMoriString("林");
		assertEquals("あなたは林です", actual);
	}
}

```

### pom.xml
```xml:pom.xml
<dependency>
	<groupId>org.mockito</groupId>
	<artifactId>mockito-all</artifactId>
	<version>1.9.5</version>
	<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
	<dependency>
		<groupId>org.mockito</groupId>
		<artifactId>mockito-core</artifactId>
		<scope>test</scope>
	</dependency>
<dependency>
	<groupId>org.powermock</groupId>
	<artifactId>powermock-api-mockito</artifactId>
	<version>1.5.4</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>org.powermock</groupId>
	<artifactId>powermock-module-junit4</artifactId>
	<version>1.5.4</version>
	<scope>test</scope>
</dependency>
```
CircleCIでgit-lfsをインストールしてからテストする


## dependenciesでインストール

かなり大きめのCSVファイルを処理させる必要があり、CSVをGitLFSで管理させるようにしたら急にspecがfailedしまくった。
テスト実行前に自分でLFSをインストールして解決。


```yaml:circle.yml
dependencies:
  override:
    # installing git-lfs
    - curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
    - sudo apt-get install git-lfs=2.2.0
    - ssh git@github.com git-lfs-authenticate <user>/<project>.git download
    - git lfs pull
```

参考リンクだと最後の`git lfs pull`が抜けていたりするので（コメントには書いてありますが）、結論を自分用のメモとして残しておきます。
インストールするバージョンは変数として出すなり良きに変えるなりしてください。

GitLFSなんかすごい早くなった気がする。
CircleCIも全部2.0に移行するぞー。


## Ref

[Installing git-lfs - CircleCI Community Discussion](https://discuss.circleci.com/t/installing-git-lfs/867)
UnityのMonoDevelopを再起動せずに再接続する方法

###UnityのMonoDevelopを**再起動せず**に再接続する方法

本記事はUnityのMonoDevelop使用時に接続が切れてしまった時，Unityを再起動せずにMonoDevelopを再接続する方法を示しています。

試した環境は以下です。↓
OS:windows10 home,macOS Sierra
Unity:Ver5.5.2,Vre5.6.0

---
####・手順

1.適当なスクリプトを選択（スクリプトでなくても良い）
2.UnityのメニューバーのAssets＞Openをクリック
3.適当なスクリプトをダブルクリック

---
接続が切れてしまう原因は調査不足でわかっていませんが，再接続が再起動なしで行えるのは大きいと感じました。接続が切れてしまう原因ないし，接続の切り方を知っている方がいれば教えていただきたい！
LINE Messaging APIのImagemap Messageの分かりやすいデモ【PHP】【Ruby】【Python】

<img width="320" alt="Messaging API Imagemap Message" src="https://qiita-image-store.s3.amazonaws.com/0/164153/3ef6bcb3-8c99-3d6c-0259-7abe14497895.png">

楽しいですね。LINE Bot。LINE Messaging APIのImagemap Message関連の質問をよく受けるので、ブラウザで概念とソースコードが理解できるサービスを作りました。

## よくある質問

+ 画像5つも違うサイズで用意しないといけないの？
+ 画像リサイズするのってどうやるの？
+ BaseSizeって何？
+ 座標はどこが(0, 0)？
+ タップしても反応しないんだけど？
+ 画像変えてもキャッシュされてて変わらないんだけど？

## 作ったもの

<img alt="Messaging API Imagemap Generator" src="https://qiita-image-store.s3.amazonaws.com/0/164153/bd164dc8-884b-74cb-0a17-3d32f1025f26.png" width=50%>
[LINE Messaging API Imagemap Message Generator(Unofficial)](https://imagemap-generator.herokuapp.com/)

ドラッグでImagemapの送信、表示が出来るためのコードを生成します。言語はPHP、Ruby、Python。

ショッピングサイトのような画像がデフォで入ってます。好きな画像に入れ替えられます。

画像をドラッグするとエリアが作成されアクションの設定ができるように、各設定を弄ると下のコード(PHP、Ruby、Pythonのみ)も座標やアクションを定義したものに変わります。

コードに一枚の画像をリサイズして返す仕組みや、画像をキャッシュさせない仕組みも入ってます。Herokuにアカウントがある人はGithubからデプロイして環境変数に自分のBotのものを入れれば動くはず。

## 使ってるもの

### PHP
+ Silex
+ GD

### Ruby
+ Sinatra
+ mini_magick

### Python
+ Flask
+ Pillow

ほとんど[LINE Bot SDK](https://github.com/line)のサンプルコードからのパクリです。ありがとうございます。

## Github

各言語プロジェクトのGithubは[こちら](https://github.com/stachibana/)。

## 注意

リサイズで出来ますが、静的な画像を用意するのが一番いいのは言うまでもありませんね。
Deep Security Manager ユーザーアカウントロックアウト解除

Deep Security Managerの管理者アカウントがロックアウトしてコンソールにログインできず焦ったので、対処法を記載します。

#ユーザーのロックアウト
Deep Security Managerコンソールはログイン時のパスワード入力が規定回数（デフォルトでは5回）以上間違えるとアカウントがロックアウトしてしまいます。一定時間経過後に自動で回復するものではないので、通常は管理者に連絡して解除してもらう必要があります。

ところが、ユーザーアカウントを1つしか作成していない場合、別アカウントでログインして解除・・という方法が使えません。
→今回はこの状態でした。。
正しい運用としては管理者権限ユーザーと一般権限ユーザーそれぞれを作成して運用というのがあるべき姿かと思いますので、注意が必要です。

#対処法
GUIがだめならCLIで！

Deep Security ManagerサーバーのDSM導入ディレクトリ（/opt/dsm/）に`dsm_c`というコマンドが準備されているので、こちらを使います。

```
[root@DSM dsm]# ./dsm_c -action unlockout -username <username>
Stopping dsm_s...
Administrator: <username> is now able to sign in.
Starting dsm_s...
Complete
[root@DSM dsm]#
```
これで完了。
コンソール上にロックアウトの表示が消え、ログイン可能な状態となります。
Unity4で作ったプロジェクトをUnity5でアップグレードするに躓いた箇所覚え書き

Unity4系（4.7だったと思う）をUnity5で開く際にアップグレードを求められます。
その際にスクリプトをいくつか修正する必要があるのでそのメモ。

■error: CS1061
参考にしたサイトはこちら
・[Unity5でvelocityがエラーになっちゃう。／そこにUnityがあるから](http://qiita.com/asiram/items/9191eca1569924718419)

□解決策
GetComponentでの取得方法に切り替え。
私の場合は以下の2点必要でした。

・カメラオブジェクトの取得
`camera.ScreenPointToRay(Input.mousePosition);`
↓
`GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);`

・レンダーオブジェクトの取得
`renderer.material = materials[0];`
↓
`GetComponent<Renderer>().material = materials[0];`


■error: CS1704
参考にしたサイトはこちら
・[【Unity】Unity 5.5.1f1 に移行した際のエラー／すずしろ備忘Log](http://suzusirolog.blog.jp/archives/349000.html)
中でも言及されている公式のスレッドはこちら
・[Help needed after upgrading to 5.5.. CS1704 UnityEngine.UI already imported error](https://forum.unity3d.com/threads/help-needed-after-upgrading-to-5-5-cs1704-unityengine-ui-already-imported-error.444084/)

□解決策
Unity再起動(｀･ω･´)ゞ

公式スレではそれだけではエラーが消えない方がいて、Libraryフォルダ全消しで解決した方もいるようです。遭遇したらこちらを試してみよう。
Emacs の Window 分割を使いやすく

Emacs のウィンドウ分割といえば `C-x 2` `C-x 3` のことである。
そして残念ながらこれらはデフォルトでは右側や下側にウィンドウを分割してくれるものの、カーソルは元のウィンドウに残ったままになってしまう。
慣れたらどうでもいいことかもしれないが、 tmux なんかはデフォルトでは違う挙動をしていて、個人的にはそっちの方が好き + 統一したいので、いじって見た。

```el
(global-set-key (kbd "C-x 2")
  (lambda()
    (interactive)
    (split-window-below)
    (select-window (next-window))))
(global-set-key (kbd "C-x 3")
  (lambda()
    (interactive)
    (split-window-right)
    (select-window (next-window))))
```

これでおk。
Diskの初期化方法


## 読み込み

```bash
reboot
```

## Diskの確認

```bash
fdisk -l
```

## パーティションを分割 (sdb → sdb0, sdb1, ...)

```shell-session
# fdisk /dev/sdb
Command (m for help): n
Command action
e extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-13054, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-13054, default 13054):
Using default value 13054
Command (m for help): p
Disk /dev/sdb: 107.4 GB, 107374182400 bytes
255 heads, 63 sectors/track, 13054 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x88ac1a04
   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1
1       13054   104856223+  83  Linux
Command (m for help): w
The partition table has been altered!
```

もし、こんなエラーが出たら？

```
Calling ioctl() to re-read partition table.
Syncing disks.
```

rebootかこのコマンド

```
partprobe
```

できていることを確認

```shell-session
# fdisk -l
Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       13054   104856223+  83  Linux
```

## ext4で初期化

```bash
mkfs -t ext4 /dev/sdb1
```

## マウント

```bash
cp -p /etc/fstab{,.org}
```

```bash
vi /etc/fstab
```

このラインを追加

```
/dev/sdb1               /var/lib/mysql          ext4    defaults,noatime        1 2
```

```bash
mkdir -p /var/lib/mysql
```

読み込み

```bash
mount -a
```

確認

```shell-session
# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3        27G  1.2G   25G   5% /
tmpfs           244M     0  244M   0% /dev/shm
/dev/sda1       488M   26M  437M   6% /boot
/dev/sdb1        99G   60M   94G   1% /var/lib/mysql
```
リモートリポジトリの特定のファイルを暗号化しておく

[git-crypt](https://github.com/AGWA/git-crypt)を使えば、ファイルを暗号化してコミットしてチェックアウト時に復号化するという処理を透過的に（自動で）行えます。暗号化するにはGPG鍵が必要です。クローン時の復号化には基本的にGPG鍵ではなく<ruby><rb>対称鍵</rb><rt>symmetric key</rt></ruby>というのを使います。

# 暗号化

## セットアップ

```bash
git-crypt init
```

これを実行すると~~`.git-crypt`~~ `.git/git-crypt`ディレクトリが作成され、そこに暗号化・復号化のためのメタデータが入ります。このディレクトリは`.gitignore`してはいけません。

## 暗号化するファイルを指定する

```bash
echo '.secret filter=git-crypt diff=git-crypt' >> .gitattributes
```

以下のようになっていると思います。

```:.gitattributes
.secret filter=git-crypt diff=git-crypt
```

1つめのフィールド`.secret`の部分は、暗号化されるファイルの名前です。`.gitignore`に書くときと同じように書けます。誤って`.gitattributes`や`.gitignore`などのファイルを指定して暗号化してしまわないようにしてください。また、**暗号化したいファイルと同時かそれよりも前に、そのファイルのエントリを追加した`.gitattributes`を`git add`してください。そうでないとそのファイルは暗号化されません。**

```bash
git add .gitattributes
```

## 暗号化に使う鍵を指定する

```bash
git-crypt add-gpg-user USER_ID
```

`USER_ID`の部分に、GPG鍵を特定できる文字列を入れます。フィンガープリントやメールアドレスなど、GPGのmanpageの "HOW TO SPECIFY A USER ID" にあるやり方で指定できます。

## 暗号化するファイルを追加する

```bash
echo 'hello, secret world!' > .secret
git add .secret
```

あとは普通にコミットしてプッシュすればOKです。おめでとうございます！ 当該ファイルは暗号化されたのち送信されますし、ローカルでは生のまま扱えます。

# 復号化

基本的に自動で復号化されるので、ほとんど気にする必要はありません。特別な手順が必要になるのは、新たにクローンした時だけです。

## 秘密鍵を使う

```
git-crypt unlock
```

クローンしたリポジトリでこれを実行します。そのあとは、プルした時にいちいちアンロックする必要はありません。

## 対称鍵を使う

秘密鍵を持っていないマシンでも開発する場合や、共同開発者がいる場合などには、以下の手順が必要になります。

### 対称鍵を生成する

```
git-crypt export-key /path/to/key
```

GPGユーザ追加もしくはアンロックを行ったリポジトリでこのコマンドを実行し、生成されたファイルを別のマシンや共同開発者に送ってあげましょう。

### 対称鍵でアンロックする

```
git-crypt unlock /path/to/key
```

# その他

- アンロックされたリポジトリでは、秘密鍵がなくても:
  - 必要なときに自分で対称鍵を生成できるので、貰った対称鍵は削除しても問題ありません
  - 新たなファイルを暗号化して追加できます
- TravisCIなどでテストする場合はどうするんでしょうか……
c言語　 分散、共分散関数

```sample.c
#include <stdio.h>
#include <math.h>

//共分散
double coefficient(double *x,double *y,int len){
    double avgx,avgy;
    double sumxy,sumxx,sumyy;
    int i;
    avgx=avgy=sumxx=sumyy=sumxy=0.0;
    for(i=0;i<len;++i){
        avgx+=x[i];
        avgy+=y[i];
    }
    
    avgx/=len;
    avgy/=len;
    for(i=0;i<len;++i){
        sumxy+=(x[i]-avgx)*(y[i]-avgy);
    }
    
    return sumxy/len;
}

//分散
double dispersion(double *x ,double len){
    double avgx=0,diff=0;
    double sumx=0,sumxx=0,powdiff[255];
    
    //平均
    for(int i=0;i<len;++i){
        sumx+=x[i];
    }
    
    avgx=sumx/len;
    
    //偏差ベクトル
    for(int i=0;i<len-1;++i){
        diff=avgx-x[i];
        powdiff[i]=pow(diff,2.0);
        sumxx+=powdiff[i];
    }
    
    return sumxx/len;
}

//試しにbook1.csvファイル(とある３地点の気圧）を読み込んで見る
int main(void){
    FILE *fp;
    char *fn = "book1.csv";//要書き換え
    int ret,count=0;
    double fpa[40],tpa[40],hpa[40],result[3][3];//なんでもいいです
    
    fp = fopen( fn, "r" );
    if( fp == NULL ){
        printf( "%sファイルが開けません¥n", fn );
        return -1;
    }
    
    while( ( ret = fscanf( fp,"%lf,%lf,%lf",&fpa[count],&tpa[count],&hpa[count]) ) != EOF ){
        count++;

    }
    fclose( fp );
    
 //共分散行列として２次元配列に格納   
    result[0][1]=result[1][0]=coefficient(fpa,tpa,count);
    result[0][2]=result[2][0]=coefficient(fpa,hpa,count);
    result[1][2]=result[2][1]=coefficient(tpa,hpa,count);

    result[0][0]=dispersion(fpa, count);
    result[1][1]=dispersion(tpa, count);
    result[2][2]=dispersion(hpa, count);
//共分散行列を出力
    for (int i=0; i<3; i++) {
        for (int f=0; f<3; f++) {
            printf("%lf  ",result[i][f]);
        }
        printf("\n");
    }
    
    return 0;
}
```
再帰的にエレメントを辿って適応されているスタイルの値を取得する。

地図ライブラリを使った時に、すべての要素に当たっているz-indexの値を知りたい時があったので、指定したエレメント以下を再帰的に辿りスタイルの値を取得するスニペットを書いた。

```js

function getProperty(element, key) {
    
    var traverse = function(obj){
        var tree = [];
        tree.push(obj);
        visit(obj);
        function visit(node) {
            if (node && node.hasChildNodes()) {
                var child = node.firstChild;
                while (child) {
                    if (child.nodeType === 1 && child.nodeName != 'SCRIPT'){
                        tree.push(child);
                        visit(child);
                    }
                    child = child.nextSibling;
                }
            }
        }
        return tree;
    };

    
    var tree = traverse(element);
    
    var propertys = tree.map(function(d){
        return {element:d, value:getComputedStyle(d).getPropertyValue("z-index")};
    });
    
    
    return propertys;
    
    
}

```

上記ファンクションをコンソールに流し込んで使う。
（chromeならsnippetsに登録しておくと便利)

![c0fed43b3e35e4613116e699fb6c8bb4-sni.png](https://qiita-image-store.s3.amazonaws.com/0/2832/4b9abb23-f3b5-bc4c-98c2-14aa494538a1.png)


任意のエレメントを指定すると、それ以下のエレメントに設定されてるスタイルを取得して配列として返す。

```js
> getProperty(document.querySelector("body"), "z-index")
````

出力結果を多少整理してあげると読みやすいかも

```js
getProperty(document.querySelector("body"), "z-index") //body以下のz-indexを取得
	.filter(function(d){ return !isNaN(+d.value )}) //z-indexの値が数値以外は対象外に
	.map(function(d){ return [d.element, d.value] }) //エレメント名とz-indexの値を抽出
	.sort(function(a, b){ return b[1] - a[1]  }) //z-indexの値が大きい順にソート

```


例）

![c0fed43b3e35e4613116e699fb6c8bb4.png](https://qiita-image-store.s3.amazonaws.com/0/2832/4d9b7a45-e705-a48b-8b52-d9f0c053c11c.png)
ActiveAdminでログイン後に遷移するページをモデルごとに分けたい

ActiveAdminでAdminUserとUserのようにユーザ管理を複数用意している場合、
ログイン後に遷移するトップページを分けたい時があると思います。

AdminUserでログインしたら => AdminUser向けのDashboard
Userでログインしたら => User向けのDashboard

ActiveAdminのドキュメントを読むと、

```
  # == Root
  #
  # Set the action to call for the root path. You can set different
  # roots for each namespace.
  #
  # Default:
  # config.root_to = 'dashboard#index'
```
なんて記述があるので、namespaceごとにroot_toを設定すればOKなのかな？と想像して

```
  config.namespace :users do |user|
    user.site_title = "ほげほげ"
    user.authentication_method = :authenticate_user!
    user.current_user_method = :current_user
    user.logout_link_path = :destroy_user_session_path
    user.root_to = '/users/dashboard#index'
  end

  config.namespace :admin do |admin|
    admin.site_title = "ほげほげ管理者画面"
    admin.authentication_method = :authenticate_admin_user!
    admin.current_user_method = :current_admin_user
    admin.logout_link_path = :destroy_admin_user_session_path
    admin.root_to = '/admin/dashboard#index'
  end
```

なんてやってみたのですが、全く変わらず。userでログインしてもadminに飛ばされる。。

で、調べていたら、以下の記事を見つけまして、

https://stackoverflow.com/questions/23731590/redirect-active-admin-login-to-devise-login

```config/initializer/active_admin_force_redirection.rb
ActiveAdmin::Devise::SessionsController.class_eval do
  def after_sign_in_path_for(resource)
    if resource.is_a?(AdminUser)
      admin_root_path
    else
      users_root_path
    end
  end
end
```

こんな具合に設定したら、ちゃんと動きました。万歳！