OmniAICreator/Qiita-1.07M huggingface dataset:
Python3.6でAirflowをインストールする

http://qiita.com/hatappi/items/6dee3af8648f21eaaff1
過去に自分で書いた記事がPython2.7でいれた時のものだったのでPython3で動かした時のメモを投稿する

## 動作環境
今回はVagrantでboxはcentos/7を使用した
https://atlas.hashicorp.com/centos/boxes/7

## 手順
### Python3.6のインストール
前回はソースからインストールしたが今回に関しては[pyenv](https://github.com/pyenv/pyenv)を使う

```text
# 事前にPythonのインストールの際に必要なものをインストール
$ sudo yum install -y git zlib-devel bzip2-devel openssl-devel
# pyenvはinstallerが提供されているのでそれを使用する
$ curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
# pyenv用のPATHを.bash_profileなどに追記した後に
$ pyenv install 3.6.1
$ pyenv global 3.6.1
$ python --version
Python 3.6.1
```

これでとりあえずpythonのインストールは完了

### MySQL5.7のインストール
```text
$ sudo rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
$ sudo yum install -y mysql-community-server mysql-devel
$ mysqld --version
mysqld  Ver 5.7.18 for Linux on x86_64 (MySQL Community Server (GPL))
$ mysql --version
mysql  Ver 14.14 Distrib 5.7.18, for Linux (x86_64) using  EditLine wrapper
```

接続確認のために

```text
$ sudo systemctl start mysqld
$ cat /var/log/mysqld.log | grep  'A temporary password is generated for'
2017-05-06T08:15:01.618375Z 1 [Note] A temporary password is generated for root@localhost: hogehoge
$ mysql -u root -phogehoge # 先程grepされて表示されたパスワードを入力
```

これで接続確認は終わりで今後使用する`airflow`というdatabaseを作成しておきます

### Airflowのインストール
installする時のコマンドは下記のみ
シンプルで良いですね
`[mysql, celery]`はairflowと一緒にインストールサブパッケージで[ここ](https://airflow.incubator.apache.org/installation.html#extra-packages)で一覧を見ることが出来ます

```text
pip install "airflow[mysql, celery]"
```

### Airflowの設定
Airflowはデフォルトでは`~/airflow/airflow.cfg`を読み込むので[githubからテンプレート](https://github.com/apache/incubator-airflow/blob/6b1c327ee886488eedbe8a8721708b89f37d5560/airflow/config_templates/default_airflow.cfg)をもってきて下記の部分を変更します

```bash:~/airflow/airflow.cfg
executor = CeleryExecutor
sql_alchemy_conn = mysql://[usr名]:[password]@[host]:[port]/[db名]
broker_url = sqla+mysql://[usr名]:[password]@[host]:[port]/[db名]
celery_result_backend = db+mysql://[usr名]:[password]@[host]:[port]/[db名]
```

この後に下記のコマンドで動作に必要なテーブルなどを作成して準備完了

```text
$ airflow initdb
```

## webserver
```text
$ airflow webserver -p 8080
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44247/b9b0ca4a-86de-9241-f04e-17d52708bfce.png)

## worker
```text
$ airflow worker
```

これでひとまず動くようになりました

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44247/c69b3c84-196c-cae4-a513-c67a88539ceb.png)


##　おまけ
###　worker起動時のエラー

```text
[2017-05-06 04:50:43,790] {__init__.py:57} INFO - Using executor CeleryExecutor
Traceback (most recent call last):
  File "/home/vagrant/.pyenv/versions/3.6.1/lib/python3.6/site-packages/kombu/transport/__init__.py", line 53, in resolve_transport
    transport = TRANSPORT_ALIASES[transport]
KeyError: 'sqla'
```

が出た
Celeryの4.0.2ではどうやらエラーが出るようで`celery==3.1.15`にdowngradeして動くようになった
一番のボトルネックを見つけよう

開発の速度や、開発の品質に問題がある場合に、何が一番のボトルネックになっているのかを見極めよう。

###**一番のボトルネックに着目すべき理由**

#### **一番のボトルネックを解決することが一番効率がよい。**
- 例：動作ログが残らない実装の状況では、問題を生じても原因を適切に推定することができない。この場合は動作ログがきちんと取れていないことがボトルネックになっています。

#### **一番のボトルネックをそのままに他の要因を最適化しようとしても、効果は上がらない。**

- 例：計測を考えてみます。誤差要因は多数あります。そのような状況では大きな誤差要因から、減らしていくことが大事です。小さな誤差要因の精度を上げようとしても、大きな誤差が残っている段階では、小さな誤差要因について改善できたのかどうかが分かりにくくなります(あるいは、まったく改善しない)。
- 例：値のばらつきが大きすぎる。観測値の分布を見たときにばらつきが大きすぎる場合には、現象をモデル化して残差を最小化することはできない。観測値の分布のばらつきを大きくしている要因(例：電源系のノイズ、機構系のがたつき（もしくは遊び）、測定系の不安定要因、振動、ケーブル線へのシールドの不足、接点の接触不良、電気系のチャタリング、初期設定時の動作にばらつき、.....)は何かを探る必要がある。
- 測定誤差を少なくするのが本質的。測定誤差を少なくするための努力をしつくさないうちに、後処理で何とかしようと思ってはならない。誤差をモデル化して残差を減らそうとするのは、測定自体を改善した後に、それでも残る誤差を削減する場合に限る。
- 誤差を1桁減らそうとすると、考慮すべき要因の数が１０倍になるように思えます。
- 本当に完全なモデルを必要とする枠組みに定式化するのではなく、もっと単純なモデルで定式化することで十分な方法はないのかを考慮してみてください。

#### **ボトルネックになっていたことを改善すると、目に見えて改善が現れてくるので、開発チームの士気が上がりやすくなる。**

- 解決を要求する作業の順序を間違えると、「もっと大きな要因があるのに、なぜ自分の担当の部部分だけ向上を要求されてもどうしようもないのに。」といった不満をメンバーに与えることになることがあります。


#### **再現性の乏しいトラブルに苦しんでいる状況では、計測も制御もいい結果にはたどりつけない。**
    
- 多変量解析や時系列解析など、どのようなデータ処理であっても、系のノイズが大きすぎる場合や、再現性の乏しいトラブルに見舞われている状況では意味のある結論に達することができない。制御は、計測結果にノイズが多すぎたり再現性が乏しかったりする状況では、無意味になってしまう。大本のデータの品質につながる要因を改善しない限り無意味だ。
- おそらくはディープラーニングも、系のノイズの大きすぎる状況、再現性の乏しい状況のトラブルに見舞われている状況で用いる限りは、有用な結論に達することはできないのではないかと私は推測する。（ゴミが入ればゴミが出る）

#### **一番のボトルネックとしてあなたが思っていることと、リーダーが思っていることとは食い違っている。**
    
- 一番のボトルネックと考えていることを解決しようとするときには、それを解決するまでの時間を長くしない方がよい。外部にその分の開発を委託する場合でも、解決するまでの時間は短くなるように配慮してください。
- 開発は時間との戦いです。開発の進展速度の低下や、期日までの達成可能性について疑いを生じてしまうことのないように、一番のボトルネックを解決することに力を集中することです。


実験の手順をしっかりメモしておこう。
だれが操作しても同じ品質で実験ができるようにすること。

------------------------------------
以下のリンクは、速度上のボトルネックを解決する場合の参考記事のリンクです。
プログラムの実行速度が一番のボトルネックになっている状況は、「ラッキーな状況」と言えます。プログラムが動くようになっていて、正しく動くようになっているからこそ、実行速度がボトルネックと言えるのですから。


- [gprofを使いこなす](http://minus9d.hatenablog.com/entry/20140112/1389502918)

 記事の中ではサンプルのプログラムがあるので、Linux環境でそのまま手順をたどってみることができます。

- [GNUプロファイラーによるコード処理速度の向上](https://www.ibm.com/developerworks/jp/linux/library/l-gnuprof/)

- [最適化の近道 プロファイラgprofのコールグラフを画像化して、コードのどこがボトルネックかをわかりやすくする](http://kiwamaru.hatenablog.com/entry/2013/05/29/070819)

 この記事の中でも手順がしっかりしているので、何かサンプルプログラムを同じ手順でグラフ化してみるといいと思います。


[C++高速化](https://heavywatal.github.io/cxx/speed.html)


[ループの高速化について(in C/C++)](http://qiita.com/EqualL2/items/472035c3f0d3e34734a8)

### Pythonの場合
以下の記事がとても参考になります。

[100万倍速いプログラムを書く](http://qiita.com/Akai_Banana/items/48a35d2a40d1804d3b32?utm_source=Qiita%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9&utm_campaign=9f2bebce72-Qiita_newsletter_266_12_07_2017&utm_medium=email&utm_term=0_e44feaa081-9f2bebce72-33096769)
UnityのSEが鳴り終わったタイミングで処理を実行する(callback)

# 概要
- SEが鳴り終わったときに処理をさせたいと思ったけれど、AudioSourceに終わったときのcallbackはなさそう…だった。
- ベストなやり方か分からないけれどcallbackを自分で作りました。
- 使い所は、SEがなり終わった後に、シーン遷移する、あるAという音が鳴ったら、すぐさまBという音を鳴らしたい、といった場合です。

# 実装
SEがなり終わったらコンソールに「END」と表示されます。
事前に、このスクリプトがアタッチされたゲームオブジェクトにAudioSourceをアタッチしてください。

```c#:CallbackTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CallbackTest : MonoBehaviour {

	private AudioSource audio;
	void Start () {
		audio = GetComponent<AudioSource>();
		audio.Play();
		
		StartCoroutine(Checking( ()=>{
			Debug.Log("END");
		} ));
	}

	public delegate void functionType();
	private IEnumerator Checking (functionType callback) {
		while(true) {
			yield return new WaitForFixedUpdate();
			if (!audio.isPlaying) {
				callback();
				break;
			}
		}
	}
}
```

# 解説

## ラムダ式（無名関数の利用）

```
StartCoroutine(Checking( ()=>{
            Debug.Log("END");
        } ));
```

- Checkingというコルーチンをスタートさせます。
- 引数には整数などの変数を入れることができますが、関数も渡せます。
- 別途、関数を定義してもよいのですが、そこまでする必要のなさそうなときは、名前がない無名関数を利用します。
- 無名関数は、ラムダ式というものを使って下記のように書くことが出来ます。

```
() => {
  処理;
}
```

## 引数として関数を受け取る

- intやboolなどの変数は基本的な機能として何もしなくても使えますが、自前の関数を引数として取る場合は、準備が必要です。

```c#:CallbackTest.cs
public delegate void "関数名"();
```

- ここで関数の型を宣言して…

```c#:CallbackTest.cs
private IEnumerator Checking (functionType callback) {
```

- コルーチンの引数として関数を受け取ります。

## SE終了の確認方法

```c#:CallbackTest.cs
while(true) {
	yield return new WaitForFixedUpdate();
	if (!audio.isPlaying) {
		callback();
		break;
	}
}
```

- 1フレーム待ってから、
- AudioSourceが鳴っているかどうか確認します。
- もしなり終わっていれば、引数でもらった関数を実行し、終了します。

# 追記2020/11/13:  Eventsを使用する方法
コメント欄でアドバイスを頂いたので掲載します。

「わざわざdelegateメンバを作るのは面倒臭いので、Unityならdelegateを使うのではなく
UnityEngine.Events.UnityActionを引数にする方がスリムかなと思います。」

## UnityEngine.Events.UnityActionを引数にする

```c#:
using UnityEngine.Events;

private IEnumerator Checking(AudioSource audio,UnityAction callback) {
    while(true) {
        yield return new WaitForFixedUpdate();
        if (!audio.isPlaying) {
            callback();
            break;
        }
    }
}
```

## 呼び出し

```c#:
void Call(){
    StartCoroutine(Checking( audiosource,()=>{
        Debug.Log("END");
    } ));
}
```

# 追記2020/11/25:  callbackのまとめ記事

以下のnpakaさんのnoteの記事にUnityでのcallbackの方法がまとめてありました。
https://note.com/npaka/n/n988adf1ecdb4
Control_Dynamics Houdini 02


*`Control_Dynamics Houdini 02`*

前回記事はコチラです。
Control_Dynamics Houdini 01
http://qiita.com/ts_bros/items/c8c9ace7863e8b93df4c



今回作っていくのは....
Advect_Solverとでも命名しますか。
移流に関して色々アプローチしていきます。

---
**`Lesson01`**
Advect?ってなんじゃワレェ！！！

超簡単でいいんでサラッと以下のコラム見ておくといいかもです。
パラパラな感じで本当に大丈夫です。
イメージしながら作っていくと理解度が全然違うので、お勧めします。

ソフトウェアクレイドル
流体解析の基礎講座　第1回
http://www.cradle.co.jp/tec/column01/index.html


流体を動かすためには流体の動きを数字やら文字やらで
記述した式が必要です。

はぁ...なんのことやらサッパリすわ

A= B+C*tみたいなノリで
自分がわかりやすい解釈で構いません。

何かしらの答えを求める時は
簡単な式をたてますよね？
コンビニでコーラとポテチを買う時だって計算式を立てています。
お会計 = コーラの値段＋ポテチの値段となりますよね？

数学物理の世界でもたくさんの学者さんがあらゆる
日常の現象を数字で表せれないか解明し続けています。

CG/VFXの流体の動きも式で管理されています。
流体の動き＝？？？？
ってな感じです。

shelfをポチッと押してSimulationが働き流体が動くのは
**`Houdiniがこれらの式を計算しているから動くのです。`**

Advectってのはこの式の一部になります。
`移流項`ってやつですね。
`流体の速度に沿って移動するっていうData`を記述しています。

`Advect`がないと流体が動いてくれません。`
(圧力で密度変化するとか抜きで）

人間が歩くって動作も
方向とスピードがきまってるから動けるわけで
これらが定まっていないと静止したままですよね。

とりあえず流体を動かしたい場合...
以下の様に簡単な式を立ててみましょう。

**`流体の動き = 流体の速度＋進行方向`**
と記述する事ができます。

---
**`Lesson02`**
Houdiniで実装してみよう

Hip_Fileは以下の置いておきます。
https://www.dropbox.com/s/5fq23867ea1vgkw/ControlFluid.hipnc?dl=0



![startup_fluid.png](https://qiita-image-store.s3.amazonaws.com/0/179218/b1c4d11f-b035-863d-b75e-e46c33d033e7.png)

簡単に作ったモノが用意されていると思います。


移流項は
流体の速度に沿って移動するDataなので
流体がVolumeDataならば...
速度、方向もVolumeDataでなくてはなりません。

え？どうしてって思った方
イメージしてください。

場所で選択しているモノは空間定義になります。
あの場所はDensity=1です。と一緒です。
あの場所が持つ速度は？
あの場所が持つ方向は？

こういう風に考えると分かりやすいですよね。

さて方向や速度を数字で定義するのに
使うのが...
**`vector Analysisです。`**(ベクトル解析)

でできましたね笑
書籍を読んでる人はここで知識のPieceが繋がり始めます。

`簡単に式にしてみます。`

速度= v
とした場合

速度は定義する事が出来るが...進行方向が分かりません。
そこで３次元空間のデカルト座標を加えて位置情報を作ります。

方向= x+y+z
とします。

なので
方向をさだめた速度 = vel

vel = xv +xy + xz
と定める事ができます。


Houdini的に記述すると

```
vector vel = set(0,0,0);

```
となります。
`ベクトルの総和や逆ベクトルも簡単に作る事ができますよね。`

このベクトルを仮に流速と呼ぶ事にしましょう。

さてあとは動かすだけです。


![Screenshot 2017-05-06_17-43-54.png](https://qiita-image-store.s3.amazonaws.com/0/179218/5ccfc824-0999-613d-afc8-eb3c617dcd5a.png)



*`AdvectのMicroSolverを一つ使います。`*

:Gas Advectってやつです。

:AdvectさせたいVolume_Fieldは？
:流速のFieldは？(vel)
聞かれているんで
それぞれ指定してあげましょう！
**`Dopに読み込まれているFieldを参照してください`**

Simulationを実行してみましょう。
Densityに変化がありましたか？
それなら
おめでとうございます!

変化がないぞ！！
って人は
:参照しているField_Name
:Simulation_Process
を見直してみてください。

**`これがSolver実装の入門ですね。`**

ここでおさらいです。
:流体を動かすには、流速が必要。
:動きを表すDataはベクトルを用いて表現される。

:Fieldは空間定義
:Simulationは式で動く

さらに...
気づいた人もいるんじゃないかと思いますが
Field_Nameって別になんでもいいんですよ。
DensityはDensityじゃなきゃダメってゆうのはないす。
**`StartとGoalさえあっていればOK!`**
僕なんか、Advectionを更新する時は、Flow,Curl,Grad,Div,Build_Curl
てな具合でガンガン作ってベクトルをカスタマイズしています。

今は、物理モデルを無視した状態でFluid_Solverを実装しています。
これに圧力、摩擦、外力なんか考慮すると
もう立派なSmoke_Solverになっていきます。

---


これらをBaseに少し複雑なAdvection_Modelを作成していきます。
**`次号に続く`**

`重要topic`
:Advect
:vector Analysis(ベクトル解析)
:流体を動かすには、流速(ベクトル)が必要。

ここ間違っているよぉ等ございましたら、ご連絡頂けると嬉しいです。
JamWikiを動かす


# はじめに

Javaで動作するwikiを動かしてみようとして検索したところ、
2013年に最終更新したjamwikiというものを見つけました。
とりあえず自前Mac,tomcatにdeployし、動かせるようにしてみました。
ソースはオープンソースです。

# JamWikiのdeploy

## Step1
1.公式より[ソース(1.3.2)](http://jamwiki.org/wiki/en/JAMWiki_Release_Archive)をダウンロード
2.IntelliJからプロジェクトをインポート(mavenプロジェクト)
3.IntelliJの依存関係でエラー
＊info.bliki.wiki:bliki-core.3.0.16がmaven-centralにない

## Step2
1.プロジェクト直下のpom.xmlを変更する。

```xml:pom.xml
<dependency>
  <groupId>info.bliki.wiki</groupId>
  <artifactId>bliki-core</artifactId>
  <version>3.0.19</version>
</dependency>
```

2.mavenでとりあえずwarを作成する。
JAMWiki Super POMからライフサイクル/package
3.テストに全て合格し、warができていることを確認

## Step3
自前用に、mysqlのjdbcドライバーを追加。
ついでに各種ライブラリを更新化し、拡張用にlombokを追加する。
de.congrace.exp4jは更新しない。
1.プロジェクト直下のpom.xmlを変更する。
2.SQLを変更する

```sql:sql.mysql.properties
create_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, \
```

3.mavenでwarを作成する。

## Step4
1.Mysqlを立ち上げ、databaseを作成する。

```sql:mysql
create database wiki;
```

2.tomcatを起動し、JamWiki.warをデプロイする。
3.JamWikiの設定を行い、初期化作業を終了する。

# JamWikiの仕様

## Table構成
25テーブルある模様。

```sql:mysql
show tables from wiki;
```

sql.mysql.propertiesには12テーブル分のcreate文しかない。。。

## Java構成
Spring3.x系を使用している。

### トップページへの遷移

```url
http://localhost:8080/jamwiki-1.3.2/
↓
http://localhost:8080/jamwiki-1.3.2/en/StartingPoints
```

/jamwiki-war/src/main/webapp/index.jspにアクセスし、
index.jsp内の下記記述にてリダイレクトされている

```jsp:index.jsp
<c:redirect url="${defaultVirtualWiki}/${defaultTopic}" />
```

(default)トップページの要素は下記で定義されてるかも？？？
/jamwiki-core/src/main/resources/pages/ja/

### 記事の投稿

管理者権限で記事を(xml)アップロードのみ？？？
(新規投稿、新規作成が見当たらない^^;)
投稿すると「jam_topic」「jam_topic_links」「jam_topic_version」にレコードが足される

### ページ構成

/jamwiki-war/src/main/webapp/WEB-INF/jsp/wiki.jsp内の下記記述で出力する内容を出し分けている。

```jsp:wiki.jsp
<jsp:include page="${pageInfo.contentJsp}" flush="true" />
```

mapping等の制御は/jamwiki-clone/jamwiki-war/src/main/webapp/WEB-INF/jamwiki-servlet.xmlで制御している。
Group Join のスクリプト


```LSL:GroupJoin.lsl

findgroupkey()
{
    list TempList = llGetObjectDetails(llGetKey(), [OBJECT_GROUP]);
    key groupkey = llList2Key(TempList, 0);
    if (groupkey == NULL_KEY)
    {
        llSay(0, "グループキーがみあたらんぞよ。。。");
    }
    else
    {
        llSay(0, "こちらをクリックしてグループにご参加ください。\n" + "secondlife:///app/group/" + (string) groupkey + "/about");
    }
}
 
default
{
    state_entry()
    {
        llSetText("Touch to Join", <1, 1, 1>, 1.0); // white and opaque floating text, optional
        findgroupkey();
    }
 
    touch_start(integer total_number)
    {
        findgroupkey();
    }
}

```
N + 1問題の検出とその対応(対応編)

##N+1問題
N+1 問題とは、Tree 状の情報を DB から読み出す際、全レコードの取得に一つ＋各レコード分だけ SQL を発行してしまう問題のこと

余分なクエリを減らすために今回はN+1問題の検出とその対応について書いてく

[N + 1問題の検出とその対応(検出編)](http://qiita.com/hnts/items/eccfd07a5c2a1516abeb)　検出編はこちらから


##rack-mini-profiler
N+1問題が発生する場合と発生しない場合でどれだけクエリ数が違うのか見てみる

```ruby:Gemfile
gem "rack-mini-profiler"
```
bundle installしてください
見たいページにアクセスして左上に出る数字をクリックすると


<img width="432" alt="N+1.png" src="https://qiita-image-store.s3.amazonaws.com/0/146799/3e809970-a9a5-bf68-821a-723ca82b46da.png">

こんな感じで表示にかかる時間やクエリの数、詳細がみれる
上のがN+1問題に未対応の結果

##対応

実際に対応してみる

```ruby:articles_controller.rb
class ArticlesController < ApplicationController

  def index
    @articles = Article.all.includes(:user)
  end
end
```

今回のN+1問題はviewでuserを呼び出してるのが原因なのでincludesでloadする
では、結果を見てみよう

<img width="425" alt="64350f54-e317-4196-a542-fa1353e23501_png__2560×1600_.png" src="https://qiita-image-store.s3.amazonaws.com/0/146799/724c4859-c162-b676-b729-7f221b1319fc.png">


前回インストールしたbulletがN+1問題を検出しなくなった
クエリ数を見てみると5分の1ぐらいに減った

##感想
見た感じだいぶクエリ数が減ったなあと思った
これからエンジニアになっていく上でこういうパフォーマンス的なところも意識できるようになっていきたい
phpenv入れようとしたらrbenvと干渉して動かなかった話

# phpenvはrbenvを利用して動いているっぽい
現象としては、phpenvをインストールした後に、
`phpenv -v`
をすると
rbenvのバージョンが出て来るし、
`phpenv install`
しようとするとrubyをインストールしようとする。

どうやらrbenvの機能を利用しているのがphpenvなのかな。

参照：
http://qiita.com/sato_ryu/items/47db3277ad32a0d7b491
http://qiita.com/fgnhssb/items/2263c79284c612c7d6ed

# とりあえずphpをバージョン管理できればいい

anyenvなるものを導入すると、***env系のものが鑑賞せずに管理できるということですが、仕組みがよくわからないものをいれちゃうのはあんまりよくないですし、php触ったことない勢にとっては、まずは動かすことが大事なので、とりあえずrbenvと干渉しないphpbrewにしました。
こちらを参考にphpbrewをインストールします。
http://www.karakaram.com/mac-install-phpbrew

これが最適な環境構築かは分からないので、phpを一通り触ってみて、必要があれば環境構築をし直すつもりです。

# おまけ phpbrewの挙動
```
% phpbrew known                               
Read local release list (last update: 2017-05-06 08:47:08 UTC).
You can run `phpbrew update` or `phpbrew known --update` to get a newer release list.
7.1: 7.1.4, 7.1.3, 7.1.2, 7.1.1, 7.1.0 ...
7.0: 7.0.18, 7.0.17, 7.0.16, 7.0.15, 7.0.14, 7.0.13, 7.0.12, 7.0.11 ...
5.6: 5.6.30, 5.6.29, 5.6.28, 5.6.27, 5.6.26, 5.6.25, 5.6.24, 5.6.23 ...
5.5: 5.5.38, 5.5.37, 5.5.36, 5.5.35, 5.5.34, 5.5.33, 5.5.32, 5.5.31 ...
5.4: 5.4.45, 5.4.44, 5.4.43, 5.4.42, 5.4.41, 5.4.40, 5.4.39, 5.4.38 ...


```
そこで、
`% phpbrew install 5.6.30`
を実行してみると...

```
Error: Make failed:
The last 5 lines in the log file:
/Users/hoge/.phpbrew/build/php-5.6.30/ext/openssl/openssl.c:44:10: fatal error: 'openssl/evp.h' file not found

#include <openssl/evp.h>

         ^

1 error generated.

make: *** [ext/openssl/openssl.lo] Error 1

Please checkout the build log file for more details:
	 tail /Users/hoge/.phpbrew/build/php-5.6.30/build.log
```
なんてこったいインストールできないぜ＼(^o^)／

http://qiita.com/hnw/items/62380e713d318906f0cd

に詳しく解説されているのでこちらを参考に設定してあげて下さい。
ちなみに私は上記で解決できず、、、こちらで対応しました。
phpbrewの場合はこれを読み込むとよさそう。

https://github.com/phpbrew/phpbrew/issues/743

`phpbrew install 5.6.30 +default`
コレでインストールできました。

## cakePHP触るために...
cakePHP触る関係で以下のようにしてインストールし直しました。

`phpbrew install 5.6.30 +default -- --enable-intl`

ちなみにコレもエラー出ました。

```
checking for icu-config... no
checking for location of ICU headers and libraries... not found
configure: error: Unable to detect ICU prefix or no failed. Please verify ICU install prefix and make sure icu-config works.
```

こいつを通すためには、

```
brew install intltool icu4c
```

でOK。やっと無事に環境が整ってきた。
Windows10のブルースクリーンを追う

<div class='alert alert-warning'><h4>警告</h4>
この本文は個人の感想しか含まれておりません。
</div>

### 秘境Windowsにて謎のブルースクリーンの秘密を追う!!
いやーめっきり見なくなりましたよね。ブルースクリーン。
XPの頃はまだ散見していましたが、7,8,10と本当にブルースクリーン見なくなりました。

本当に良い時代になったと思うのですが、たまにパーツ買い替えたときのドライバの入れ替えなどが原因で発生したりします。
様々な不具合ありますが個人的に以下の点でブルースクリーンがいやです。

#### ブルースクリーンのここがいやだ！

* エラーの情報が少ない。
* 兆候なくない？

中でもエラーの情報がぱっと見非常に少なく原因の特定が非常に難しいといつも感じていました。

が実は調べてみるとWindows自体はそBugCheckをしているようでなんとdump fileまでデフォルトで生成されているようです。
なので覚書代わりに具体的に調査方法だけおいておきます。

### 前提条件

* windows 10 home(64bit)一応
* 一応起動はできている前提
 * もしも起動すらできない状態ならまずセーフモードで起動できるか確認してみましょう 

### イベントビューアー

ブルースクリーン発生後イベントビューアーを起動
左のパネルの「Windowsログ」-> 「システム」から発生時のイベントログのBugCheckを確認してみましょう。
右の「操作」-> 「現在のログをフィルター」からログレベルをソースを「BugCheck」でフィルタするか、ログレベルを「警告」と「エラー」でフィルタリングするとわかりやすいかと思います。

![event_viwer.png](https://qiita-image-store.s3.amazonaws.com/0/67764/b5a2ef11-3417-0e33-de8b-f2bbd4acf17c.png)

なんとーここに該当時間に発生したブルースクリーンの原因のダンプファイルが保存されているんですね。

### Windbg
細かいことは自分もよく知りません。ただこいつは上で説明したDumpファイルを解析することができる。今知っておくべき事実はそれだけだ！別に威勢のいいことだけ言ってごまかそうとしているわけではありません。

#### ダウンロード
winDbg
https://developer.microsoft.com/en-us/windows/hardware/download-windbg
windbgはWDK 10かVisual Studio 10に含まれるコンポーネントの一つのためどちらかすでにインストールしている場合すでに入ってるかと思うので確認してみてください。

WinDbgをのみをインストールしたい場合は上のサイトの指示に従ってください。セットアップウィザーとにてたぶん「Debuggin Tools for Windows」だけ選択してインストールすればいいだけ(のはず)です。

#### バイナリファイルのロード
インストールしたら**管理者権限**でWinDbgを起動してみましょう
そして「File」-> 「Open Crash dump」で先ほど見つけたバイナリをロードしてみましょう。

![windebug_result.png](https://qiita-image-store.s3.amazonaws.com/0/67764/2bb93b30-b5c4-eb6f-e2ed-c38d347a7c8a.png)

atapi.sysとか出てきた!!
これくらいまで出てくればあとはyahooでググるないしで原因を特定できそうですね。正直**atapi.sys**が原因の場合何をどうすればいいのかちょっとわかりませんでしたが。

もっと細かい結果を確認したい場合```!analyze -v```をクリックしてみてください。もう少し色々出てきます。

#### 総括
最近はwindowsでブルースクリーンでの唐突な死はあまり見なくなったものの、いざ出てみるとやっぱり困るので手順だけ残しておこうと思いました。
やっぱりグラボ周りを入れ替えるとゴリゴリ不具合出ますね…悲しい。
OpenWrt/LEDE でLuCIの設定の差分を保存する

情報源：https://forum.openwrt.org/viewtopic.php?id=56087

OpenWrt/LEDEのGUIであるところのLuCIの設定はuciコマンドを使ってコマンドラインから取り出せる。しかし、単に `uci show` としたのでは全ての設定が表示されてしまい、自分が何の設定をしたのかイマイチ読み取りにくい。

デフォルト設定との差分だけを表示するには、下記のようにすればよい。（diffコマンドはopkgでインストールできます。参照：「[OpenWrt/LEDEのbusyboxでdiffが無効になってる件 \- Qiita](https://qiita.com/hnw/items/96a1cc270846927a83cb)」）

```
$ uci -d ";" -c/rom/etc/config show | sort > /tmp/default.uci
$ uci -d ";" show | sort > /tmp/latest.uci
$ diff -U0 /tmp/default.uci /tmp/latest.uci
```

上のコマンドを打つと、下記のように差分だけを取り出せる。

```
--- /tmp/default.uci	2017-05-06 15:00:35.000000000 +0900
+++ /tmp/latest.uci	2017-05-06 15:00:35.000000000 +0900
@@ -15,0 +16 @@
+dhcp.lan.dhcpv6=server
@@ -18,0 +20,2 @@
+dhcp.lan.ra=server
+dhcp.lan.ra_management=1
@@ -20,0 +24,4 @@
+dhcp.odhcpd.leasefile=/tmp/hosts/odhcpd
+dhcp.odhcpd.leasetrigger=/usr/sbin/odhcpd-update
+dhcp.odhcpd.maindhcp=0
+dhcp.odhcpd=odhcpd
@@ -24,3 +31,4 @@
-dropbear.@dropbear[0].PasswordAuth=on
-dropbear.@dropbear[0].Port=22
-dropbear.@dropbear[0].RootPasswordAuth=on
+dropbear.@dropbear[0].Interface=lan
+dropbear.@dropbear[0].PasswordAuth=off
+dropbear.@dropbear[0].Port=10022
+dropbear.@dropbear[0].RootPasswordAuth=off
（以下略）
```

こんな設定したっけなあ？という差分も出てくるが、全設定を見せられるよりは断然マシといえる。
HTML/CSSについてのまとめ

#この記事について#
自分の備忘録として、HTML/CSS全般についての自分の考えや調べたことを記載していきます。
ほぼリンク集として使用。
経験が浅いので、間違っていることもあると思いますがご容赦ください。

#テーブル内のセルをスクロールするには・・・

[テーブル・セルにスクロールバーをつける](http://kowaza.boo.jp/03table/table-07-0scroll.html)

div付けないと有効にならない、
heightもしくはwidthを指定しないと有効にならないことに注意。

#Bootstrap#

<b>・テンプレート</b>
個人的にですけど、配色がきれいなので以下のものはおすすめです。

[Umi - 日本語も美しく表示できるBootstrapテーマ](https://nkmr6194.github.io/Umi/)
WebAssemblyの開発環境事情

FirefoxやChromeで標準対応となったWebAssembly。その開発環境の構築方法について調べてみました。
結論から言いますと、執筆時点（~~2017/05/06 incoming版をインストール後のemccのバージョンは1.37.12~~ 2017/05/18 emccのバージョンは1.37.9）では、とても簡単になっています。
※ コメントをいただき、incoming版の必要がないことを確認しました。そのため、記事を修正しました。

#環境構築は、Emscriptenの最新版をインストールするだけ

以前は、BinaryenやWABTといったツールが必要だったようですが、現在はEmscripten ~~のincoming版~~ をインストールすれば全て完了します。Emscriptenは、RustからWebAssemblyへコンパイルする場合にも必要です。（バージョン 1.37.9以降が必要なようです。）

インストール方法ですが、MacOSXでは、[公式サイトのダウンロードページ](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html)から、「Portable Emscripten SDK for Linux and OS X」をダウンロードして展開してから、展開先へカレントディレクトリを移動し、

```
./emsdk update
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
```

と実行すればインストールが完了します。

Windowsの場合は、[こちら](https://www.sumirelab.com/docs/tech/windows%e3%81%abemscripten%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%ef%bc%88incoming%e5%af%be%e5%bf%9c-webassembly%e7%92%b0%e5%a2%83%e3%81%ae%e6%95%b4%e5%82%99%ef%bc%89/)をご覧ください。

Emscriptenであれば、標準Cライブラリ等も使えるので、実用性を考えると、この方法が唯一ではないでしょうか。

#オプションは「-s WASM=1」

以前は、「-s BINARYEN=1」だったそうですが、最新版では「-s WASM=1」に変わっています。以下のような感じです。

```
emcc hello.c -o hello.html -s WASM=1
```

また、この後Binaryen等で変換が必要と書かれている記事もありますが、現在は一発でWASMファイル（バイナリ形式のファイル）が出力されます。
「-s "BINARYEN_METHOD='???'"」のようにオプションを付けると、細かいこともできるようです。

#感想
昔の記事を調べたところ環境構築がけっこう大変なようで少々ビビりましたが、それらに比べると、現在は簡単になっていると思います。
ちなみに、単純なHello Worldを-O2で最適化をかけてコンパイルしただけでも、WASMファイルが26KB、補助用のJavaScriptファイルが43KBありました。おそらく、Emscriptenが用意してくれているmallocやprintf等のサイズだと思いますが、意外と大きいです。ただ、大規模なプログラムになっても、ファイルサイズはあまり大きくなっていかないのではないかと期待しています。

ちなみに、clangを使ってコンパイルする方法も試してみました。こちらは、WASMのファイルサイズこそ小さかったものの、Cの標準ライブラリも使えない状態のため、使い所が難しそうです。mallocすら無いためロジックが複雑なものは難しいですが、単純な数値計算をさせるだけといった用途であれば、こちらの方法のほうがファイルサイズが小さく、良いかもしれません。


##参考サイト
- [WebAssembly](https://github.com/kripken/emscripten/wiki/WebAssembly)
- [Hello World WebAssembly](http://qiita.com/ukyo/items/f71265fdee79b26354b9)
- [WindowsでWebAssemblyの環境を整える](http://qiita.com/Hiroki_M/items/1d2bb08b515582d39f16)
- [楓 software:: WebAssembly](http://www.kaede-software.com/2017/02/cc_wasm_clang_j.html)
zbox nano VD01にUbuntu16.04LTSをインストールする

# zbox nano VD01にUbuntu16.04LTSをインストールする

[これ](http://www.ask-corp.jp/products/zotac/mini-pc/zbox-nano/zboxnano-vd01.html)にUbuntuをインストールした。
見た目通りにCDドライブがないのでusbメモリからインストールする。

## ファイルダウンロード

公式からisoを落としてくる。

## USBメモリへの書き込み

universal usb installer(https://universal-usb-installer.jp.uptodown.com/windows) で書き込む。

## VD01へのインストール

USBメモリをさして起動。
即deleteキーでコンフィグ画面へ。
usbから起動するようにセッティングして。
以下略。

## 画面の解像度変更

起動後の解像度が640x480だったので。

```bash
sudo vi /etc/default/grub
```

で、

```bash
#GRUB_GFXMODE=1024×768
```
の行を、

```bash
GRUB_GFXMODE=1024×768
```
に直して、

```bash
sudo update-grub
```
して再起動で1024x768になる。

# 参考

http://renidentia991.wordpress.com/2012/01/15/zotac-zbox-nano-vd01にubuntu11-1064bitをインストールした！/
kintone 画像認識アプリ Analyze Image

kintone アプリで、Azure の画像認識を試してみました。
画像リンクを指定すると、画像表示と画像認識を行います。
有名人だと、かなりの認識率だと思います。

- スペース項目に 画像表示
- [Azure Computer Vision API](https://azure.microsoft.com/ja-jp/services/cognitive-services/computer-vision/) の Analyze Image を呼び出し、結果を表示

有名人は、名前も特定できるということで、試しにマリリンモンローを指定しました。

ちゃんと認識できています。

![2017-05-06_14h57_59.png](https://qiita-image-store.s3.amazonaws.com/0/100572/91a7a831-724d-b450-0d9e-a4eff15e226e.png)


# 集合写真

## ネイマールとメッシ

このくらい有名人だと、説明文にも氏名が表示されます。
メッシは、100%の認識率

![2017-05-06_16h50_14.png](https://qiita-image-store.s3.amazonaws.com/0/100572/e5e41435-341d-aa75-0ad0-3c242385c0f3.png)


## ビートルズ

残念、ジョージハリソンが認識できていません。

![2017-05-06_15h28_28.png](https://qiita-image-store.s3.amazonaws.com/0/100572/5a753374-57a7-1677-4d60-b1cf5f572b0a.png)


## ちょっと古めの AKB48 の写真です。
集合写真だと顔の角度や大きさなどにより、認識率が変わってくるようです。

- 名前認識: 6人/12人
- 人数: 11人/12人

![2017-05-06_15h12_38.png](https://qiita-image-store.s3.amazonaws.com/0/100572/aa9dfefd-3d14-dc42-308a-5cbbe6dfa821.png)

## kintone Café 秋田 Vol.1 懇親会の写真

さすがに、氏名まで認識された人はいません。
50代が二人いるはずなんですが、画像認識結果では50代が一人で他は30代以下となっています。

![2017-05-06_15h33_39.png](https://qiita-image-store.s3.amazonaws.com/0/100572/4bc8a8b3-1ed8-ebab-fa6a-97bd7cad2ea6.png)

# 人形

日本人形だと女性となりましたが、doll (0.37) と、人形の認識もあります。

![2017-05-06_15h54_18.png](https://qiita-image-store.s3.amazonaws.com/0/100572/a40bd657-6288-326c-0507-25ae646827ff.png)


# 猫

ちゃんと、猫を認識します。

![2017-05-06_15h42_39.png](https://qiita-image-store.s3.amazonaws.com/0/100572/3477c7df-75da-cf89-d0da-feda42cc5ebb.png)

猫がいっぱいいても大丈夫

![2017-05-06_15h51_15.png](https://qiita-image-store.s3.amazonaws.com/0/100572/66f4a226-290d-b8af-c104-ef8a4135f05a.png)

# 風景

風景の認識もできるようなので、試してみました。

## リビングルーム

リビングルームを認識しました。

![2017-05-06_16h16_05.png](https://qiita-image-store.s3.amazonaws.com/0/100572/2ccd4def-c788-a16f-7dd6-ff08837885fc.png)



## ニューヨーク

さすがに、通りの写真では場所まで特定は、出来ないようです。

![2017-05-06_16h02_00.png](https://qiita-image-store.s3.amazonaws.com/0/100572/f4d5dbed-765a-3ba6-2a8f-374f75fef521.png)

## セントラルパーク

セントラルパークは、認識されました。

![2017-05-06_16h10_00.png](https://qiita-image-store.s3.amazonaws.com/0/100572/e122b644-47b6-02bb-08e7-8c8dcaaa5a59.png)


## 富士山

富士山が認識されました！

![2017-05-06_16h05_08.png](https://qiita-image-store.s3.amazonaws.com/0/100572/9a8bc1f0-9200-b45b-865d-046a3c5405ca.png)


# クリップアート


![2017-05-06_16h27_35.png](https://qiita-image-store.s3.amazonaws.com/0/100572/63c39d19-93c0-d0b9-2a65-72134b03fd73.png)

# ラインアート

![2017-05-06_16h34_21.png](https://qiita-image-store.s3.amazonaws.com/0/100572/0b04c4ee-f5ad-f0ee-c8e6-e0bd75595041.png)

# 参考関連サイト

- [Computer Vision API - v1.0](https://southeastasia.dev.cognitive.microsoft.com/docs/services/56f91f2d778daf23d8ec6739/operations/56f91f2e778daf14a499e1fa)

パラメータの説明や、サンプルコードがあります。


[Computer Vision API - v1.0 console](https://southeastasia.dev.cognitive.microsoft.com/docs/services/56f91f2d778daf23d8ec6739/operations/56f91f2e778daf14a499e1fa/console)

実際に、パラメータを指定して、実行結果を確認できます。


# あとがき

もうかなりの認識率だと思います。
有名人や観光名所だと特に認識率が高そうです。
サイトをリリースしてまずやっておきたいSEO対策(Google Search Console)的な

サイトをリリースした際にGoogleにちゃんとクロールしてもらえるようにサイトマップの送信とかクロール申請とかやっといた方が良さそうだったので一連の流れをまとめる。
（GoogleSearchConsoleのアカウント作成とかは事前にやっとく。ここでは割愛）

①サイトをリリース
②サイトマップ(xmlファイル)を作成
こちらのサイトなどを使ってサイトマップを簡単に作れる。
http://www.sitemapxml.jp/
③sitemap.xmlをルートディレクトリに設置
④GoogleSearchConsoleでサイトマップをGoogleに送信
 クロール > サイトマップ > サイトマップの追加/テスト > URL(http://・・・.com/sitemap.xml)を追加
⑤送信ボタンクリック
⑥Fetch as Googleからクロール申請(月毎の申請数に制限があるっぽいので注意)
⑦しばらくすると、「サイトマップ」の項目の「インデックスに登録済み」にインデックスされたページ数が表示される

以上。
GitHubからアサインされたissue一覧を取得する

## 概要
GoogleAppsScriptからGitHubAPIを呼び出し、アサインされたissueだけをスプレッドシートに出力する。
APIで取得できるissueは20件までしか取得できないため、取得件数が0件になるまで処理を繰り返し出力している。

## 事前準備
GitHubでアクセストークンを作成しておいてください。

## 実装

```github.gs
function fetchIssues() {
  // スプレッドシート：シート名
  var SHEET_NAME = 'issue';
  // スプレッドシート：開始位置
  var RANGE = 2;

  // GitHub：アクセストークン
  var GITHUB_ACCESS_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
  // GitHub：組織名
  var GITHUB_OWNER = 'xxx';
  // GitHub：アカウント名
  var GITHUB_ACCOUNT = 'xxx';
  // GitHub：API
  var GITHUB_API = 'https://api.github.com/orgs/' + GITHUB_OWNER + '/issues';
    
  // シート情報を初期化して取得
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME).clear();
  // ページ番号
  var page = 1;
  
  while (true) {
    // GitHubAPIにアクセス
    var url = GITHUB_API + '?page=' + page;
    var headers = {
      'Authorization': 'Bearer '+ GITHUB_ACCESS_TOKEN
    };
    var options = {
      'method': "GET",
      'headers': headers
    };

    var issues = JSON.parse(UrlFetchApp.fetch(url, options);));
    
    if (issues.length == 0) {
      break;
    }
    // 取得した件数分を出力する
    var skip_index = 0;
    for(var index = 0; index < issues.length; index++) {

      var range = RANGE + index + 20 * (page - 1) - skip_index;
      var repository = issues[index]["repository"];
      var milestone = issues[index]["milestone"];

      // issueのみ出力する
      if (issues[index]["pull_request"] == null) {
        if (repository != null) { 
          // リポジトリ名
          sheet.getRange(range, COLUMN_REPOSITORY_NAME).setValue(repository["name"]);
        }
        if (milestone != null) { 
        // ミッションノート
          sheet.getRange(range, 3).setValue(milestone["title"]);
        }
        // issue番号
        sheet.getRange(range, 4).setValue(issues[index]["number"]);
        // issue名
        sheet.getRange(range, 5).setValue(issues[index]["title"]);
        // URL
        sheet.getRange(range, 6).setValue(issues[index]["html_url"]);
      } else {
        // プルリクエストは除外するためカウントして出力行を調整する
        skip_index++;
      }
    }
    page++;
  }
}
```
Git学習メモ

#gitとは
gitは、共同開発をするために便利な環境である。

#gitの準備
ターミナルで以下を入力
```
git init
```

#共有の準備
ターミナルで以下を入力
```
git add ファイル名
```

#選択したファイルを記録する
```
git commit -m "コメント"
```
コメントを残すことを、コミットという。
そのコメント自体を、コミットメッセージという。

#ファイルを共有する
クラウド上でファイルを共有するイメージ。
リモート上にファイルをアップロードし、共同開発者がリモートからダウンロードする。
**リモートの登録**
```
git remote add リモート名（originが多い） リモートURL
```

#リモートへファイルをアップロード
リモートへのアップロードをプッシュという。
以下を入力し、リモートにファイルをプッシュする。
```
git push origin master
```

#プッシュされたファイルをダウンロード
このダウンロードをプルという。
```
git pull リモート名 master
```

ここまで、学び、gituhubに登録してリモートの実験をしましたが、リモートにうまくファイルが共有されません。
だれか助けてください。
Spring Bootでファイルアップロード

記事のタイトル通り実装します。今回実装するのは以下のような機能です。
・HTMLのフォーム、インプットタグで構成された入力画面から画像のパスを指定してアップロードする
・Java経由で指定ディレクトリにファイルを出力する

## 修正するファイル
以下の3ファイルを修正します
![1.png](https://qiita-image-store.s3.amazonaws.com/0/110457/a6a88bb1-800d-600b-1aab-4b9cba98faad.png)

**Controller**

```java:com.example.SampleController.java
@RequestMapping(path = "/sample/upload", method = RequestMethod.GET)
String uploadview(Model model) {
  return "sample/upload";
}

@RequestMapping(path = "/sample/upload", method = RequestMethod.POST)
String upload(Model model, UploadForm uploadForm) {
  if (uploadForm.getFile().isEmpty()) {
    return "sample/upload";
  }

  // check upload distination directory.If there was no directory, make
  // func.
  Path path = Paths.get("/Users/demo-kusa/image");
  if (!Files.exists(path)) {
    try {
      Files.createDirectory(path);
    } catch (NoSuchFileException ex) {
      System.err.println(ex);
    } catch (IOException ex) {
      System.err.println(ex);
    }
  }

  int dot = uploadForm.getFile().getOriginalFilename().lastIndexOf(".");
  String extention = "";
  if (dot > 0) {
    extention = uploadForm.getFile().getOriginalFilename().substring(dot).toLowerCase();
  }
  String filename = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(LocalDateTime.now());
  Path uploadfile = Paths
      .get("/Users/demo-kusa/image/" + filename + extention);

  try (OutputStream os = Files.newOutputStream(uploadfile, StandardOpenOption.CREATE)) {
    byte[] bytes = uploadForm.getFile().getBytes();
    os.write(bytes);
  } catch (IOException ex) {
    System.err.println(ex);
  }

  return "redirect:/sample";
}
```

**ActionForm**

```java:com.example.UploadForm.java
package com.example;

import org.springframework.web.multipart.MultipartFile;
public class UploadForm {
  private MultipartFile file;

  public MultipartFile getFile() {
    return file;
  }

  public void setFile(MultipartFile file) {
    this.file = file;
  }
}
```

**template**

```html:src/main/resources/templates/sample/upload.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>top page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h2>画像アップロード</h2>
    <form method="post" enctype="multipart/form-data" action="/sample/upload" >
        <input name="file" type="file" />
        <input type="submit" value="送信する"/>
    </form>
</body>
</html>
```

本記事は環境依存部分を一部差し替えていますが、ソースは以下にありますので必要な方はお願いいたします。
[github kaikusakari/spring_crud](https://github.com/kaikusakari/spring_crud)
GitHubからクローンしたAngularドキュメントサイトをローカルで動かそうとした時にエラーが出た話

先日、[AngularドキュメントサイトのソースをGitHubからクローンしてDockerで動かしてみる。](http://qiita.com/tiny-studio/items/635f14e5301b4a37b4c7)という記事を投稿しましたが、実験中に出くわしたエラーメッセージがありました。

Dockerを使わずにローカルで動作させる場合にも関係する現象です。

Angularドキュメントサイトの[README.md](https://github.com/angular/angular/blob/master/aio/README.md)に従って下記のコマンドを実行すると、下記のようなメッセージが表示されて処理が中断されました。

```
bash-4.2# yarn start
yarn start v0.23.4
$ yarn check-env && ng serve 
yarn check-env v0.23.4
$ node ../tools/check-environment.js 

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!  Your environment is not in a good shape. Following issues were found:
!!!   - Looks like you are missing some npm dependencies. Run: npm install
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Your environment doesn't provide the prerequisite dependencies.
Please fix the issues listed above and then rerun the gulp command.
Check out https://github.com/angular/angular/blob/master/DEVELOPER.md for more info.
error Command failed with exit code 1.
error Command failed with exit code 1.
bash-4.2# 
```

原因は、aioフォルダの上の階層のフォルダにも`package.json`があり、事前にこちらに対してもnpm installを実行しておく必要がある、ということでした。

ローカルでドキュメントサイトを動作させる場合には、以下のような流れとなります。

```
git clone https://github.com/angular/angular.git

cd angular
npm install

cd aio
yarn
yarn docs
yarn start
```
docker-composeで簡易デプロイ

docker-composeで動かしているWebサービスで、新しいイメージを簡単にデプロイする方法を模索していたので、メモしてみます。

※あくまで簡易的なデプロイ方法なので、ダウンタイムが発生します。

例えば以下のような `docker-compose.yml` を `/var/www/app` に配置して運用しているとします。

```docker-compose.yml
version: '2'
services:
  app:
    image: registry.gitlab.com/your-name/your-project:latest
    container_name: app
    ports:
      - 8080:80
    volumes:
      - ./data:/app/data
    depends_on:
      - mongo
  mongo:
    image: mongo:latest
    container_name: mongo
    volumes:
      - ./mongo:/db/data
```

ここで使っているregistryに最新のイメージをプッシュした後、このappサービスのコンテナを新しいイメージのものに入れ替えたい、というユースケースです。

以下のようなスクリプトを配置します。

```deploy.sh
#!/bin/bash

IMAGE=registry.gitlab.com/your-name/your-project
IMAGE_TAG=latest
CONTAINER_NAME=app
CONTAINER_ID=`docker container ls -aqf "name=$CONTAINER_NAME"`

cd /var/www/app
docker image pull $IMAGE:$IMAGE_TAG
docker-compose stop $CONTAINER_NAME
docker container rm $CONTAINER_ID
docker-compose up --no-deps -d $CONTAINER_NAME
docker image rm `docker image ls -qf "dangling=true" -f "reference=$IMAGE" | tr "\n" " "`
```

1. `docker image pull ...`：新しいイメージをプルします。このとき既存のイメージはタグが外れ、新しいイメージにタグが割り当てられます。
2. `docker-compose stop ...`：appサービスのみ停止します。
3. `docker container rm ...`：appサービスのコンテナを削除します。
4. `docker-compose up ...`：新しいappコンテナを立ち上げます。このとき先程プルした新しいイメージが使用されます。
5. `docker image rm ...`：`docker image ls` で、タグが外れた（dangling）古いイメージのIDを取得し、`docker image rm` でイメージを削除します。

container registryに新しいイメージをプッシュしたあと、（例えばCIからSSH経由で）このdeploy.shを叩くことで、docker-composeのappサービスが新しいイメージのものと入れ替わり、古いイメージが削除されます。

特に最後の古いイメージを削除するのを忘れてしまうと、デプロイの度にサーバーのストレージに古いイメージが溜まり、容量がどんどん圧迫されていくので要注意です。
concourseのTIPSメモ


[concourse](https://concourse.ci/)は設定をyamlで記述出来たり、Cloud Foundryのような大規模なOSSで利用されているように、  元々jenkinsで運用していたけれどツライ部分があったので作られたので非常にシンプルな作りになっています。

しかしまだまだJenkinsと比べると利用者が多くないので、以下のようなポイントでTIPSをまとめて行きます。

* 自分や身近でハマったポイント
* その他の人がSlack等でハマっているやり取りをしていたポイント

## concourseのJOBが動いたコンテナに入るfly intercept(fly hijack)がつながらない時

fly interceptをしても上手くコンテナに入れないときがある。
以下のようにコンテナ内部のシェルでなくこちら側のシェルに戻ってしまうケース

```bash
$ fly -t moog intercept -j test/test-pipeline
1: build #1, step: test-task, type: check
2: build #1, step: test-task, type: task
choose a container: 2
$ 
```

Concourseの[公式Slack](http://slack.concourse.ci/)のチャンネルでやり取りがされていた。

```bash
thinkt [11:35 PM] 
Hi all, has anyone had `intercept` fail to intercept a container? How do you usually find out what’s happening?

[11:36] 
 ```fly -t tutorial intercept -j docker-compose-spike/docker-compose                                                                                                                            
1: build #12, step: docker-compose, type: check
2: build #12, step: docker-compose, type: task
choose a container: 2
~/p/c/concourse ❯❯❯```

[11:36] 
This is what I’m getting - it just returns back to the shell prompt after choosing a container to intercept


----- May 2nd -----
joshzarrabi 
[12:45 AM] 
@thinkt run 'fly intercept -j <pipeline/job> /bin/sh'

[12:46] 
@thinkt you are probably intercepting into a container without bash, which is what we default to, so you have to tell it to run sh instead

thinkt [12:47 AM] 
that works, thanks @joshzarrabi
```

原因としては、非常にシンプルで`docker run`等で`/bin/bash`を指定したものの  
利用しているDocker Imageには`/bin/bash`がなく`/bin/sh`のみしか無いケースと同じ理由

`fly intercept`のデフォルトが`/bin/bash`指定と同じになるため以下のように実行すると解決する

```bash
$ fly -t moog intercept -j test/test-pipeline /bin/sh
1: build #1, step: test-task, type: check
2: build #1, step: test-task, type: task
choose a container: 2
/tmp/build/63b66672 #

```
LabVIEW Tips: エラー情報の作成

# はじめに
LabVIEWで、開発中のシステムや特定の計測器に固有なエラーコードの処理ってどうしてますか？
エラークラスタにコードとメッセージを入れる処理を丁寧に作りこむって大変ですよね。それだけでダイアグラムの場所をとりますし。。。
以下で説明した方法を使って、少しでも手間が省けるようにしているのですが、皆さんはどうしているのでしょうか。

# エラークラスタに渡すエラー情報の作成
「エラーコードからエラークラスタ」を使用すると楽です。

![image](https://qiita-image-store.s3.amazonaws.com/0/43526/e54ab62f-a46c-9fc7-ff6d-98051187cd87.png)

「呼び出しチェーンを表示」をTrueに設定すると、エラーメッセージに呼び出しチェーン情報を追加してくれるので、デバッグのときにエラー発生場所がわかって楽です。

# エラーコードの定義
定義されていないエラー番号を基準にして、追加するのが推奨されていますが、まじめにエラーコード設計するとなかなか大変でわりといい加減になっている、とういう方も多いのではないでしょうか？

私の場合は、できる限り、定義済みのエラーコードを使う、という方針にしています。ぴったり一致するものはなくても似たような意味合いのコードにして、細かい情報はメッセージの方に入れておくようにしています。
たとえば、計測器ドライバなど、計測器固有のエラーコードを他とバッティングしないよに組み込もうとすると、なんだか面倒になって手が止まってしまいます。
ですので、エラークラスタのエラーコードには、いっそ、不明なメッセージにして、固有のエラーコードは、エラーメッセージ中に入れてしまう、というやり方にしています。

# 最後に
上記のやり方は、推奨するものではありません。
もし、もっと簡潔できれいな方法があれば教えていただきたいと思います。
Apple公式のiOS開発チュートリアルをやってみた（Andoridエンジニア視点）

隙間時間に細々とやっていた以下のApple公式のiOSアプリ開発チュートリアルが終わったので、復習も兼ねて内容をまとめておきます。

[Start Developing iOS Apps (Swift)](https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/)

普段は仕事でAndroidアプリを作っているので、同じように、Android開発者だけどiOSもやってみたい、という方に興味を持っていただければ幸いです。
とてもよくできたチュートリアルなので、英語を読むのが苦でなければオススメです。

## 前提知識

Swiftが初めての人は事前に「[Swift Playgrounds](https://itunes.apple.com/us/app/swift-playgrounds/id908519492?mt=8)」というiPad向け学習アプリか
「[A Swift Tour](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html)」をやっておく必要があります。
僕はiPadを持っていなかったので、「A Swift Tour」の方をXCodeのPlaygroundに打ち込みながらざっと確認しました。

## 作るもの

「FoodTracker」という料理の名前、写真、評価を管理するアプリを開発するチュートリアルです。
写経したコードは[こちら](https://github.com/takuhiro/FoodTracker)

<img width="264" alt="スクリーンショット 2017-05-06 14.49.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/100092/1734068f-d9bd-3633-cf02-bb280771e25c.png">

具体的には、Mealというモデルを作成して、一覧/詳細表示、作成、編集、削除ができるようにします。
イメージとしては、Railsのscaffoldでできる基本的なCRUD機能とほぼ同じ感じです。

## 学べる内容

大きく「UI構築」と「モデル操作（リスト表示等）」の2パートに別れています。
イメージしやすいように、Androidでいうと○○という形でまとめておきます。
※厳密に対応するわけではないのであくまでイメージです

### Building the UI

* Build a Basic UI
  * XCodeの使い方 => AndroidでいうとAndroidStudio
  * Storyboardを使ったUI構築 => Androidでいうとres/layout以下のxmlファイル
* Connect the UI to Code
  * Outlet/ActionによるUIとコードの紐付け => AndroidでいうとfindViewByIdやButterknife
  * Protocolの実装 => Android(Java)でいうとInterface
* Work with View Controllers
  * ViewControllerのライフサイクルとコールバックの実装 => AndroidでいうとActivityの実装
  * Assets(画像ファイル)の使い方 => Androidでいうとres/drawable以下のファイル
* Implement a Custom Control
  * カスタムコントロール(独自View)の作り方 => AndroidでいうとViewを継承した独自View
* Define Your Data Model
  * モデルの定義 => Android(Java)でいうとPOJO/Bean...
  * XCTestを使用したユニットテスト => AndroidでいうとJUnit

### Working with Table Views

* Create a Table View
  * 2つ目のViewController　=> AndroidでいうとActivity
  * TableViewを使ったリスト表示 => AndroidでいうとListView/RecyclerView 
* Implement Navigation
  * NavigationController, Segueによる画面遷移 => AndroidでいうとstartActivity/startActivityForResult
* Implement Edit and Delete Behavior
  * プッシュとモーダルの違い
  * TableViewControllerの編集モード
* Persist Data
  * NSCodingによるデータの永続化 => AndroidでいうとSharedPreferences、SQLite

## 感想

基本的なCRUD操作の実装パターンを掴めたので、あとは永続化をRealmにしたりRestAPIにしたりと必要に応じて部分的にブラッシュアップしていけば、プロダクションレベルのアプリが作れそうな気がします。
Android開発と比べると、Storyboard周りでかなりGUI操作が多いと感じました。この辺は慣れるまで結構大変そう。。
今回は時間をかけ過ぎて肝心の序盤のUI構築を忘れつつあるので、モデルを少し変えてまた似たようなメモアプリでも作ってみたいと思います。
Bitnamiのロゴが邪魔！

# ■ 目的(解決する問題)
AWSの「WordPress powered by Bitnami(HVM) 」AMIにてEC2インスタンスを立ち上げWordPressページにアクセスすると、ページ右下に以下のようなリンクが表示される。それを削除する方法。

![スクリーンショット 2017-05-06 15.07.35.png](https://qiita-image-store.s3.amazonaws.com/0/153140/74bb5d3e-1859-8c75-4f74-994e40318abc.png "スクリーンショット 2017-05-06 15.07.35.png")


# ■ 解決手順

① ターミナルでEC2インスタンスにアクセス。

　※接続するためのコマンドがわからない方
　1, EC2コンソールにログイン。
　2, 左サイドバーの **Instances** をクリック


![スクリーンショット_2017-05-06_15_18_47.png](https://qiita-image-store.s3.amazonaws.com/0/153140/3e3135cb-6618-74e2-26b5-b3817d8aa540.png "スクリーンショット_2017-05-06_15_18_47.png")


　3, 上部の **Connect** ボタンをクリック。すると、コマンドが表示されるため、その通りに実行。


![スクリーンショット_2017-05-06_15_12_57.png](https://qiita-image-store.s3.amazonaws.com/0/153140/1bbead20-c694-2c5d-0760-5535fa3e04d4.png "スクリーンショット_2017-05-06_15_12_57.png")


② EC2インスタンスに接続できたら、以下コマンド実行。Bitnamiのロゴを非表示にする。

```terminal:terminal
sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1
```

③ 次に、以下コマンド実行。Apacheを再起動する。

```terminal:terminal
sudo /opt/bitnami/ctlscript.sh restart apache
```

④ 最後に、サイトにアクセスし非表示になっているか確認する。


# ■ 確認

上記コマンド実行後のターミナルが、以下のようになっていれば大丈夫。

```terminal:terminal
bitnami@ip-000-00-00-00:~$ sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1
bitnami@ip-000-00-00-00:~$ sudo /opt/bitnami/ctlscript.sh restart apache
Unmonitored apache
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : httpd stopped
Syntax OK
/opt/bitnami/apache2/scripts/ctl.sh : httpd started at port 80
Monitored apache
bitnami@ip-000-00-00-00:~$ 
```
<br>
以上

# ■ 参考
http://kussuue.com/2016/06/wordpress_bitnami/
CoreDataでNSPredicateを使ったらEXC_BAD_ACCESSが出た


ゴールデンウィークいかがおすごしでしょうか
私はだらだらしたり、コード書いたりしてました。(この二つしかしていない)

今日出たエラーを残しておきます。

## Predicateを使ったらエラー出た

![スクリーンショット 2017-05-06 14.50.18.png](https://qiita-image-store.s3.amazonaws.com/0/139360/2e9089ec-50ee-7c6d-edc7-153e29c3de3b.png "スクリーンショット 2017-05-06 14.50.18.png")



このエラーが出力されてハマりました、、、、
これってログとか出してくれないの、、、
(ここにエラーログがでてるよーってゆうのがあれば教えてください)


## 解決方法

NSNumberでラップすることです。

![スクリーンショット 2017-05-06 14.58.16.png](https://qiita-image-store.s3.amazonaws.com/0/139360/6b1acb7f-2748-1332-cc41-35e1a67ac80a.png "スクリーンショット 2017-05-06 14.58.16.png")



CoreDataのカラムの定義をInteeger16に設定したので比較する変数の型をIntにしていたのでそのまま比較できると思っていましたが、
そうやらNSNumberでラップする必要があるようです。


初心者殺しですね、、
BotをSkypeに接続する


前回作った翻訳BotをSkypeに接続してSkypeから話しかけてみます。
# BotアプリをAzure App Servicesへ公開する
まずは作成したBotアプリをAzure App Servicesへ公開します。

Visual StudioでBotのソリューションを開きます。
プロジェクトを右クリックして「公開」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/279cd486-44ef-bc5b-e138-3152e4ec9a50.png)
発行画面が開くので
- Microsoft Azure App Service
- 新規作成

を選択して「発行」をクリックすると「App Serviceの作成」画面が開きます。

初期値として、申し込んであるAzureサブスクリプションが表示されますので以下を設定します。
- API Appの名前：デフォルトでもOK。ここでは「MyParrotBot」に変更
- サブスクリプション：デフォルトでOK
- リソースグループ：デフォルトでOK
- App Serivceプラン：デフォルトでOK
「作成」をクリックするとデプロイが行われます。

発行が行われると以下の画面になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/cc632ee0-0249-bb2c-765f-415c61bc80b6.png)

また、ブラウザが起動しデプロイ先のURLが開くのでデプロイが完了したことが確認できます。
ここのURLはのちほどBotを登録する際に使用しますのでメモしておきます。

# Botを登録する
作成したBotをMicrosoft Bot Frameworkに登録する必要があります。
[Microsoft Bot Framwork](https://dev.botframework.com/)サイトの「Register a bot」を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/4387d902-9cb5-3a1a-5d7e-52d679a2a607.png)

以下の画面で必要な項目を入力します。
- Bot profile
    - icon：アイコン画像をアップロード
    - Name：表示名
    - Bot handle：一意となるBot名
    - Description：説明
- Configuration
    - Messaging Endpoint：Azureに公開したBotのURLを使用します。*http://*を*https://*に変更し、最後に*api/messages*を追加します。

入力が終わったら「Create Microsoft App ID and password」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/4e129409-270b-8dcf-150f-e14f5ba1fcdd.png)

「アプリIDとパスワードを生成」ダイアログが開くので「アプリパスワードを生成して続行」をクリックします。
そうするとパスワードが生成されるので大切に保管して閉じます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/f82779ef-2e04-aa71-0196-819037e84169.png)

そのまま一番下の「Register」をクリックします。
My Bots画面が開き、これで登録は完了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/4d169188-8cc4-428f-8c36-e2fde84f1b7a.png)

# Bot登録情報をアプリに設定する
web.configを開き、以下を設定します。
- BotID(=Bot handle)
- AppID
- AppPassword

```xml:web.config
  <appSettings>
    <!-- update these with your BotId, Microsoft App Id and your Microsoft App Password-->
    <add key="BotId" value="BotId" />
    <add key="MicrosoftAppId" value="AppId" />
    <add key="MicrosoftAppPassword" value="AppPassword" />
  </appSettings>
```

再度発行画面の「発行」をクリックしして再発行します。
これでアプリの準備は完了です。

# Skypeに登録する
My bots画面のChannelsにある「Add to Skype」をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/b4ce130d-8a25-d16a-e712-bbc8fd942e31.png)

Skypeのサイトが開き「Add to contact」をクリックするとSkypeの連絡先に追加されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/ebfffda6-6a38-0ac4-475f-7595b13d9985.png)

Skypeを起動し、話しかけてみてください。
ちゃんと動作していれば成功です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/171118/66490f32-2d9b-e7e3-e7d6-12ca45b68dc4.png)

他にもいろいろなサービスに接続できますが、今回はSkypeを選択してみました。
move_baseをWEBブラウザから操作する。

#目的
　robotwebtoolsのnav2djsを使って、move_baseをWEBブラウザから操作する。
　nav2djsは、rvizと似たようなUIをWEBブラウザで動作させるjavascriptである。
![test.png](https://qiita-image-store.s3.amazonaws.com/0/73020/cdddc925-4474-e872-584e-44a5c9b628c1.png)


###インストール
rosbridge-server、robot-pose-publisher などをインストールする。(ROS Indigoの場合)

```
sudo apt-get install ros-indigo-rosbridge-server
sudo apt-get install ros-indigo-robot-pose-publisher 
```

###apache2のインストール
Apache2(webサーバ)をインストールする。

```
sudo apt-get install apache2
```


###launchファイルからのノード起動
rosbridge-server・robot-pose-publisher を起動する。
これと別にmove_baseを起動させておく。

```
<launch>
 <node pkg="robot_pose_publisher" type="robot_pose_publisher" name="robot_pose_publisher">
 </node>
 <include file="$(find rosbridge_server)/launch/rosbridge_websocket.launch" > 
   <arg name="port" value="9090"/>
 </include>
</launch>
```


###htmlソース
nav2djsを呼び出すhtmlファイルを作成し、/var/www以下に配置する。
webブラウザから、該当のhtmlファイルにアクセスすることで、move_baseをWEBブラウザから操作する。
IPアドレス(以下の例では、192.168.1.100)はネットワーク環境によって、適切に設定する。
このIPアドレスは、rosbridge_serverが起動しているPCのIPアドレスを指定する。

navi.html

```
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />

<script type="text/javascript" src="http://cdn.robotwebtools.org/EaselJS/current/easeljs.min.js"></script>
<script type="text/javascript" src="http://cdn.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script type="text/javascript" src="http://cdn.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
<script type="text/javascript" src="http://cdn.robotwebtools.org/ros2djs/current/ros2d.js"></script>
<script type="text/javascript" src="http://cdn.robotwebtools.org/ros2djs/current/ros2d.min.js"></script>
<script type="text/javascript" src="http://cdn.robotwebtools.org/nav2djs/current/nav2d.min.js"></script>

<script src="http://cdn.robotwebtools.org/EaselJS/current/easeljs.min.js"></script>
<script src="http://cdn.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script src="http://cdn.robotwebtools.org/roslibjs/current/roslib.js"></script>
<script src="http://cdn.robotwebtools.org/ros2djs/current/ros2d.js"></script>

<script type="text/javascript">
  /**
   * Setup all GUI elements when the page is loaded.
   */
  function init() {
    // Connect to ROS.
    var ros = new ROSLIB.Ros({
      url : 'ws://192.168.1.100:9090'
    });

    // Create the main viewer.
    var viewer = new ROS2D.Viewer({
      divID : 'nav',
      width : 1000,
      height : 1000

    });
        // Setup the nav client.
    var nav = NAV2D.OccupancyGridClientNav({
      ros : ros,
      rootObject : viewer.scene,
      viewer : viewer,
      serverName : '/move_base',
      withOrientation :false,
    });

  }
</script>



</head>

<body onload="init()">
<h2>Navigation</h2>
<h4>Please Click to robot Goals</h4>

<div id="nav"></div>
		
</body>
</html>
```




参考：
http://robotwebtools.org/
https://github.com/RobotWebTools
http://wiki.ros.org/nav2djs
Linux (CentOS) の OS バージョンを確認する方法

## Linux カーネルのバージョンを確認する方法

```
$ cat /proc/version
Linux version bra bra bra ...
```

```
$ uname -a
Linux bra bra bra ...
```


## CentOS のバージョンを確認する方法

```
$ cat /etc/redhat-release
CentOS release 6.5 (Final)
```