OmniAICreator/Qiita-1.07M huggingface dataset:
MMDモデルを使用したデスクトップユーティリティの開発 その4 頂点インデックス・カメラ

前: [その3](http://qiita.com/JI1LDG/items/f7d759612c7296def79a)
次: [その5](http://qiita.com/JI1LDG/items/457e76ae15da214c8004)

##今回やること
頂点インデックスを元にモデルの描画
カリング
カメラの設定

今回のソース: [頂点インデックス・カリング](https://github.com/JI1LDG/ModelViewer/tree/2acb5c092c97f258dbcb837f36a917682e11371d),  [カメラ](https://github.com/JI1LDG/ModelViewer/tree/80cabecf1c8ab8791995fb82458a4436a281cdf2)

##頂点インデックス
詳しいことは[こちら](http://marupeke296.com/DXG_No30_VertexIndexBuffer.html)に。

頂点インデックスとは、三角形を構成する頂点に対応する頂点の番号のリストのことです。
MmdFileLoaderを使用した場合は、MmdFileLoader.Pmd.PmdLoader.Indexに格納されています。
このリストに対応する頂点をバッファに送ることで、正しく描画できるはずです。

バッファに送る頂点のリストは`pmdLoader.Index.SelectMany(x => x.Indicies).Select(x => pmdLoader.Vertex[x].Position).ToArray()`で、
頂点の数は`pmdLoader.Index.Length * 3`で取得できます。

##カリング(Culling)
DirectX11の初期設定では、MMDモデルを表示しようとすると、モデルの裏もしくは表が描画されません。
描画を設定するラスタライザステートで設定するため、下のコードを追加します。

```csharp:DrawPmdModel.cs
private void InitializeRasterizerState() {
	device.ImmediateContext.Rasterizer.State = Dx11.RasterizerState.FromDescription(device,
		new Dx11.RasterizerStateDescription() {
			CullMode = Dx11.CullMode.None, FillMode = Dx11.FillMode.Solid,
		}
	);
}
```

CullModeには「表面の描画を省略する」「裏面の描画を省略する」「描画の省略をしない」の3つから選択可能。
FillModeにWireframeを指定すると、ワイヤフレーム表示になります。

結果は下図のようになります。
![cirno_raster.png](https://qiita-image-store.s3.amazonaws.com/0/135830/c807d982-0554-32f0-f748-7d49017b1407.png)

##カメラ
詳しいことは[こちら](http://memeplex.blog.shinobi.jp/directx11/c-%E3%81%A7directx11%20slimdx%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB%E3%81%9D%E3%81%AE07%20%E3%82%AB%E3%83%A1%E3%83%A9%EF%BC%88%E9%81%A0%E8%BF%91%E6%84%9F%EF%BC%8B%E5%9B%9E%E8%BB%A2%EF%BC%89)に

モデルの表示ができましたが、いちいち1/20に縮小したものを用意するのは面倒です。
そこでカメラを用意します。
Direct3D11においては、「カメラ機能」なるものは用意されていない(はず)です。
エフェクトファイルで座標変換を行うことで「カメラ」を実現しています。

下のコードで、(0, 10, -10)から(0, 10, 0)に視線を向けさせ、全体をy軸を中心に回転させています。
flameCountは描画するごとにインクリメントさせています。
また、エフェクトファイルの頂点シェーダも変更しました。

```csharp:DrawPmdModel.cs
private void UpdateCamera() {
	var world = Matrix.RotationY((flameCount / 20 % 360) * (float)Math.PI / 180);

	var view = Matrix.LookAtRH(
		new Vector3(0, 10, -10), new Vector3(0, 10, 0), new Vector3(0, 1, 0)
	);

	var projection = Matrix.PerspectiveFovRH(
		(float)Math.PI / 2, ClientSize.Width / ClientSize.Height, 0.1f, 1000
	);

	effect.GetVariableByName("World").AsMatrix().SetMatrix(world);
	effect.GetVariableByName("View").AsMatrix().SetMatrix(view);
	effect.GetVariableByName("Projection").AsMatrix().SetMatrix(projection);
}
```

```effect.fx
matrix World;
matrix View;
matrix Projection;

float4 myVertexShader(float4 position: SV_Position) : SV_Position {
	float4 pos = mul(position, World);
	pos = mul(pos, View);
	pos = mul(pos, Projection);
	return pos;
}

float4 myPixelShader() : SV_Target {
	return float4(1, 1, 1, 1);
}

technique10 myTechnique {
	pass myPass {
		SetVertexShader(CompileShader(vs_5_0, myVertexShader()));
		SetPixelShader(CompileShader(ps_5_0, myPixelShader()));
	}
}
```

くるくるまわってます。
![cirno_round.png](https://qiita-image-store.s3.amazonaws.com/0/135830/c6267753-b77d-6ad0-2c56-fce1460fe4c8.png)

##さいごに
次回は、拡散色(Diffuse)とテクスチャでモデルに色をつける予定です。
Grapeとrablを捨て去って原点回帰した話

---

## 自己紹介

- @qsona (Twitter/GitHub)
- Node.js 2年半
- 2016/2 - now FiNC株式会社
- Ruby, Rails 半年
- マイクロサービス
- [Microservices Meetup](http://microservices-meetup.connpass.com/) 運営してます

---

## 概要

- 最近、Rails上の技術スタックを変更してみている
  - `Grape` => `ActionController`
  - `rabl` => `active_model_serializers`
  - `(grape-)swagger` => `JSON Hyper-Schema`
- その背景と理由を話します

--- 

## 背景

- 2014- FiNCアプリ開発開始
- 早いうちから Microservices を選択
- grape, rablでAPI開発
- grape-swagger でAPIドキュメント生成

---

## 起こっていた問題点

---

## 起こっていた問題点

1. ドキュメントが片手落ち
2. レスポンスの型が安定しない
3. Smart UIなAPI
4. rabl辛い

---

## ドキュメントが片手落ち

- Grape: 受け付けるリクエストパラメータを宣言的に記述できる

```rb
params do
  requires foo, type: String
  optional bars, type: Array[String]
end
get '/path/to/api' do
  # ...
end

```

- そこからドキュメントを自動生成できる
  (grape-swagger)

---

## ドキュメントが片手落ち

- レスポンスのドキュメントはない
  - swaggerの画面から、実際にAPIを叩いて確認はできる
  - 結構めんどい、クライアントに不評
  - Microservicesにとっては、APIのリクエスト/レスポンス型のドキュメントがフルで存在しないのは致命的

---

## レスポンスの型が安定しない

- 同じようで違うキー名
  - ex) 同じユーザ情報でも、APIによりキーが多い/少ない
  - ex) ページングで次のページ番号のキーが has_next, has_next_page, next_page, ...
- rablをちゃんと使いこなせてない
  - rablに強制力がない

---

## Smart UIなAPI

前項に関連.

- 画面に密接に紐づくAPI
- 画面仕様が変わる度に、APIも変更に
- 万能なAPIがあちこちで使われる
  - ex) 「マイページ」向けAPI
  - パフォーマンス問題が起こる

参考: [http://qiita.com/qsona/items/9c062de2bb83491aec38](Webアプリケーションで、APIが画面と結びつきすぎる問題を解決するには)

---

## rabl辛い

demo

---

## rabl辛い

- ドキュメントが薄いDSLは辛い
  - 社内で知見がめっちゃあるとかでもない
- 挙動が不思議ちゃん
- デフォルトの挙動も不思議ちゃん
- rablかわいいよrabl😄
- 使いにくい、イライラする💢

---

## やったこと😀

---

## ドキュメントの問題を解決する

- JSON Hyper-Schemaでリクエスト・レスポンスの型を記述 
- interagent/prmd を利用してドキュメント自動生成
- interagent/committeeを 利用して、バリデーションする

---

## ActionController

- JSON Schemaにより
  リクエストのValidationできる
- Grapeいらなくね? という話になった
  - ちょうどGrape重い問題あった
- Controllerに回帰

---

## active_model_serializers

- レスポンスが安定する
- リソース志向, RESTfulへの回帰
  - Backendとしてビジネスロジックを守る
  - Front-end Serverでオーケストレーションする

---

## お気持ち

opinionated は Railsで十分かなー

---

## 新たな問題

- request paramsのType Coercionがない
  - Grapeのtypeのやつ結構優秀だった。。。
  - 代替策募集中
- 別ライブラリにしてくれ💢

---

## Questions.

---

## 1. active_model_serializers vs rabl

- 単なる書き方の違いではない、思想が違う
- 単純に「どちらが良い」ではなく、目指すモノ、フェーズ、チームのレベルによっても変わりそう

---

## 2. ドキュメント自動生成?

pros/cons

- Grape + swagger
- JSON Schema + prmd
Rails5 belongs_toを設定において、nilで保存できなくなる？belongs_toのrequiredがデフォルトでtrueに。


モデル間に置いてのバリデーションを書いていたら、気づいたことがあるので共有したい思います。


has_many:とbelongs_toの紐付けをする時、
rails5ではデフォルトでrequireになり、通常ではnilでの保存ができなくなる。


class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable

has_many :pictures

end


class Picture < ApplicationRecord
  validates :title, presence: true
  belongs_to :user

end



これだけでは、userも一緒に付いてくる。
rails5では新しくoptionalオプションが追加されたので、
 belongs_toを設定においてnilの場合は、
optional: trueを追加すれば、
値がnilでも保存できるようになる。


class Picture < ApplicationRecord
  validates :title, presence: true
  belongs_to :user,optional: true

end



参考にしたサイト
https://www.wantedly.com/companies/wantedly/post_articles/31132
http://zeny.io/blog/2016/07/03/rails-5/
fragmentのタブのアイコン画像のサイズをカスタマイズする


### タブに画像を設定する場合

デフォルトで24dpのサイズしか適用されない。

```java:FragmentActivity.java

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);

// タブに画像をセット
tabLayout.getTabAt(0).setIcon(R.drawable.ic_photo_camera_black_24dp);
tabLayout.getTabAt(1).setIcon(R.drawable.ic_line_weight_black_24dp);


```

### タブの画像サイズを変更する場合

setIconではなく、→　**setCustomView**  ←でlayoutファイルを指定。

```java:FragmentActivity.java

TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);

tabLayout.getTabAt(0).setCustomView(R.layout.design_fragment_icon_camera);
tabLayout.getTabAt(1).setCustomView(R.layout.design_fragment_line_weight);

```

#### 1番めのタブ画像用xml
```xml:design_fragment_icon_camera.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:scaleType="centerInside"
    android:src="@drawable/image_icon_camera"
    />
```

#### ２番めのタブ画像用xml
```xml:design_fragment_icon_line_weight.xml

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:scaleType="centerInside"
    android:src="@drawable/image_icon_line"
    />

```


## おまけ

setCustomViewでセットするxmlファイルのImageViewですが、

```xml:design_fragment_icon_camera.xml
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:scaleType="centerInside"
    android:src="@drawable/image_icon_camera"
    />
```

srcCompatで、svg画像もできるかなと思ったのですが、
何故か**svg画像**だと、画像が表示されませんでした。。
(ic_attachment_black_24dp.xmlがsvg画像)

```xml:design_fragment_icon_camera.xml

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:scaleType="centerInside"
    app:srcCompat="@drawable/ic_attachment_black_24dp"
    android:tint="@color/colorBlack"
    />

```

### 参考にさせて頂いたサイト様 m( _ _ )m

https://blog.4star.link/?p=1784
http://qiita.com/ryohey/items/df96d3f7e56756962380
Enzymeでテキスト変更をsimulateする

Reactでユニットテストを書くときには、ユーティリティとしてairbnbのenzymeを使うと便利。

https://github.com/airbnb/enzyme

enzymeはshallowやmountといったI/Fでレンダリングを模擬してくれる。
またsimulateメソッドを利用してDOMのイベントを模擬できる。

## ボタンクリック
クリックはドキュメントにもあるが、以下のように記述できる。

```js
const wrapper = mount(<a onClick={() => alert('click!!')}/>);
wrapper.find('a').simulate('click');
// click!!
```

## テキストフィールド変更
テキストフィールド(input type=text)の場合は、対象nodeのvalueを変更してからchangeを模擬する。

```js
const wrapper = mount(<Foo />);
wrapper.find('input').get(0).value = 'My new value';
wrapper.find('input').first().simulate('change');
```

よりシンプルにやる方法も紹介されている。
simulateの第2引数のモックイベントオブジェクトを利用する。

```js
const wrapper = mount(<Foo />);
wrapper.find('input').simulate('change', {target: {value: 'My new value'}});
```


## 参考
https://github.com/airbnb/enzyme/issues/76
[JavaScript]Live2Dみたいにキャラを動かしたかった男の話

# Live2D作りたい
Live2Dすごいですよね。
![maxresdefault.jpg](https://qiita-image-store.s3.amazonaws.com/0/77608/c1a0ec0f-63ae-2b0c-d174-0a2a13f2b9c6.jpeg)

さらに「Live2D Euclid」で360度動けるなんてもう意味がわかりません（褒め言葉）
あんなものを自分で作って見たいですよね。
そこで技術力皆無の僕がjavascriptでLive2Dっぽいものを作りたかった話をします。

## 脳筋プログラミング その１
思考力がないので脳筋で実装。
DOMでキャラのパーツごとの要素をそれぞれ誤差を与えながら動かす。
![マイムービー.gif](https://qiita-image-store.s3.amazonaws.com/0/77608/0f123db3-5b83-e499-a718-ec0716f5ea1e.gif)
※比がおかしくてすみません。

ああ、なんか怖い。
あとDOMで```top```や```left```を動かしているのでガタガタと揺れちゃってる。

さて、どうしよう...

canvasで同じようなとこをやってみよう！

## 脳筋プログラミング その２
パーツごとの画像を

```javascript:sample.js
var img = new Image();
img.src = 'img/parts1.png';
img.onload = function() {
    // 画像読み込み終了
}
```
上記のような感じで一旦読み込んだ後、
canvasコンテキストの``` ctx.drawImage() ```で各パーツごとに誤差を与えながら描画する。
使う画像は事前に読み込まないと描画できないので注意。

![H-MIGiAtjizrDrCg.gif](https://qiita-image-store.s3.amazonaws.com/0/77608/4a78a72e-27cf-07c9-863a-72433cdb077f.gif)
※比がおかしくてすみません。

あ、なんかそれっぽい!（満足）
可愛い。もうこれで完成では？

ですが、問題が...

## 問題点 その１
みなさんご存知の通り、本家Live2Dは各パーツをポリゴン分けしてキャラを動かしています。
![live2d_007.png](https://qiita-image-store.s3.amazonaws.com/0/77608/252dbf90-8113-b0c2-67d8-a682c9addef0.png)

それに対し、自分が作ったものは各パーツに誤差を与えてキャラが動いているように見せています。
これではLive2Dのように手を動かしたりといった、柔軟な動きを表現することができません。

## 問題点　その２
現状、動きの情報はコードで全て書いています。
これでは違うキャラを動かしたい場合、もう一回コードを書かなくてはいけないので、Web上でGUIアプリのようなツールを作らなくてはいけない。

## 脳筋プログラミング その3
この時点でモチベーションは、ほぼゼロなのですが一応試して見ます。

まず、canvasでテクスチャマッピングできるのか調べて見たところ、
「[canvasを使って知識ゼロから独学してみた「エセ」テクスチャマッピング入門以前編](http://akibahideki.com/blog/html5-canvas-1/canvas.html)」という記事があったのでこれを参考にさせていただきました。

あと、Web上でGUIアプリのようなツールを作るのですが、jsのフレームワークとかどれがいいかわからないし、そもそも使い方もわからないので全部js直書きしました。jQueryすら使ってません。（脳筋）

<img width="1280" alt="スクリーンショット 2016-09-13 21.17.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/77608/6fab1391-f535-8a0c-d40d-10b1325ec668.png">

<img width="1280" alt="スクリーンショット 2016-09-13 21.21.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/77608/90254182-be0f-0fa9-26fb-7ae9ba072c94.png">

こんな感じのUIになりました。
まあ、普通な感じです。

問題の動作なんですが...
![名称未設定2.gif](https://qiita-image-store.s3.amazonaws.com/0/77608/7286aca5-8fb0-8f7d-79e7-5dc647eec21a.gif)
※別のキャラ画像ですみません。

ああ！なんか変！
まあ、もっと作り込めば多少はマシにはなるかな...

これで基本機能は完成のはずだったんですが...

## いままでとこれから
とりあえずしたいことはできたんですが、問題点が多すぎてスッキリしません。
canvasでテクスチャマッピングするのはどうも動作が遅いのでスマホとかタブレットではまともに動きませんでした。

なので、今は空いた時間でWebGLを使って作っています。
あと、マウスの動きを追って動くのではなく、gif画像みたいにアニメーションを作れるサービスにして、2月ごろにウチの学校の作品発表会で出そうと思っています。

中途半端な内容ですが、同じようなものを作ろうとしている人のヒントにでもなればと思います。

canvas版の未完成品ですが一応、[GitHub](https://github.com/yuki540net/char-motion)に上げておきます.
Rubyでdateのvalidationをする

　Rubyで、渡ってきた文字列が正当なdateである場合だけ`true`を返し、その他の場合は`false`を返すvalidatorを作りました。
　Ruby on Railsなどで活用できると思われます。というかRailsで使うために作りました。
　gemとかがオーバーキルっぽい時に。

```ruby
require 'date'

# 日付のvalidationを行う関数
# strに不正な文字列や文字列以外が渡ってきた場合rescueが動き、
# 不正な日付(2016-2-31など)が渡ってきた場合
# Date.valid_date?でfalseが返る
private def date_valid?(str)
  begin
    y, m, d = str.split("-").map(&:to_i)
    return Date.valid_date?(y, m, d)
  rescue
    return false
  end
end
```

# 追記
　コメント欄でのご指摘を受け、次のようなコードにしてみました。

```ruby
require 'date'

private def date_valid?(str)
  !! Date.parse(str) rescue false
end
```

　こうすることで、様々な日付フォーマットを受け入れられるようになりました。
　また、trueオブジェクトに`!!`をかけることで、`true`が返ってくるのも勉強になりました。
　ありがとうございます。

## !! object #=> true_objectの場合true、false_objectの場合falseになる仕組み
　まず、`! object`が評価され、objectを`true`か`false`に変換してしまいます。
　今回返ってくることが期待されているDateオブジェクトはtrueオブジェクトなので、ここで`false`が返り、そして更に`!`をかけることで`true`が返るようになります。
　もし、期待されていないNilオブジェクトが返ってきた場合、Nilオブジェクトはfalseオブジェクトなので`true`が返り、更に`!`をかけると`false`になります。
WRF > Open MPI / MPICH > Default January 2000 caseの処理時間の比較 > ほぼ同じ

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
openmpi-1.8.x86_64 とその-devel
mpich.x86_64 3.1-5.el6とその-devel
gcc version 4.4.7 (とgfortran)
```

WRF(Weather Research and Forecasting Model)関連。

WRFの処理をOpen MPIとMPICHで比べてみた。

対象としたケースは
http://www2.mmm.ucar.edu/wrf/OnLineTutorial/CASES/index.html
の
Default January 2000 case

### Open MPI

wrf.exe実行時に`time mpirun -np 6 ./wrf.exe`のようにして処理時間を見てみた。
秒未満の時間は「切り捨て」た。

| np | real | user |
|:-:|:-:|:-:|
| 1  | 2m7s | 2m3s  |
| 3  | 0m46s| 2m15s |
| 6  | 0m28s| 2m50s |
| 16 | 0m17s| 4m26s |

なぜかnp=16のuserがやたら大きい。

### MPICH

| np | real | user |
|:-:|:-:|:-:|
| 1  | 2m6s | 2m3s  |
| 3  | 0m45s| 2m16s |
| 6  | 0m28s| 2m51s |
| 16 | 0m23s| 6m11s |

np=16のuser以外はOpen MPIと同様の結果となった。
お気に入りのディレクトリを登録するZshプラグインを作った


![Screenshot_2016-09-29_11-32-51.png](https://qiita-image-store.s3.amazonaws.com/0/103885/95f2db11-c7d3-efad-79cd-96bad2a57707.png)
巷に溢れている気もしますが、個人的にあまり使いやすいものが無かったので、作りました。

interactive filtering toolとしてpecoが必要です。

https://github.com/acro5piano/fd

下記でインストールできます。

```
antigen bundle acro5piano/fd
```

# 使い方

インストール後、`fd add`で現在いるディレクトリをお気に入りに追加します。

`fd`とすると、pecoが立ち上がり、ディレクトリを選択できます。

サブコマンドとして`add`, `edit`, `list`の3つがあり、まあその名前通りの働きをします。
AWS SNSを使ったプッシュ通知のサンプルプログラム（トピック版）

AWS SNSを使ってプッシュ通知を送る方法のうちの一つ、トピックを作成してエンドポイントを追加し送信するサンプルです。
一度に複数の端末へ送信する場合、この方法を使うかと思います。

```php:topic_push_test.php
<?php
require(dirname(__FILE__).'/vendor/autoload.php');
use Aws\Sns\SnsClient;
use Aws\Sns\Exception\SnsException;

date_default_timezone_set('Asia/Tokyo');

// 送信するメッセージ作成
$message = array(
    'default' => "メッセージ",
    'APNS' => json_encode(array(
        'aps' => array(
            'alert' => "メッセージ"
        ),
        'scheme' => ""
    )),
    'GCM' => json_encode(array(
        'data' => array(
            'message' => "メッセージ",
            'scheme' => ""
        )
    ))
);

$sns = SnsClient::factory(array(
    'credentials' => [
        'key'    => 'キー',
        'secret' => 'シークレット',
    ],
    'region' => 'リージョン名',
    'version' => 'バージョン',
));

try {
    // トピック生成
    $result = $sns->createTopic(array(
        'Name' => 'トピック名',
    ));
    $topicArn = $result['TopicArn'];

    // トピックにエンドポイントを追加
    // 複数エンドポイントがある場合はこの処理を繰り返す
    $params = [
        'Endpoint' => 'エンドポイント',
        'Protocol' => 'Application',
        'TopicArn' => $topicArn,
    ];
    $result = $sns->subscribe($params);

    // プッシュ通知
    $sns->publish(array(
        'TargetArn' => $topicArn,
        'Message' => (string) json_encode($message),
        'MessageStructure' => 'json'
    ));

    // 作ったトピックを削除する場合は以下を実行
//            $result = $sns->deleteTopic(array(
//                'TopicArn' => $topicArn,
//            ));

} catch(SnsException $e) {
    // エラー出力
}
```

送信するメッセージはandroid、ios両方に対応して、JSON形式で送ることを想定しています。この部分が送りたい内容によって書き換えが必要です。
トピック名は任意でつけられます。
RPGツクールMVで特定アクターの所持スキル数を取得するコード

全スキル数の取得

```js
$gameActors.actor(アクター番号).skills().length
```

スキルタイプが２つ以上あるとき（魔法、スキル、・・・）に、片方のだけ取得したい場合

```js
$gameActors.actor(アクター番号).skills().filter(function(item) {return item.stypeId==スキルタイプ番号;}).length
```

例：アクター番号１番のキャラの2番目のスキルタイプのスキル数を取得

```js
$gameActors.actor(1).skills().filter(function(item) {return item.stypeId==2;}).length
```

イベントのスクリプトとかで使ってください。
sshのconfig を使って rsync でファイル転送

## 参考

* [ssh の設定ファイルを使って rsync で簡単にファイル転送 - Qiita](http://qiita.com/ironsand/items/90cced5bd318344ef514)

## 方法

```bash:
rsync -e "ssh -F $HOME/sshprivate/config" -a srv1:work/ .
```

```bash:
rsync -a -e srv1:work/ .
```
Open MPI / MPICH > Fortran90サンプル実行 > Open MPIで-f90=gfortranエラーが出た

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
openmpi-1.8.x86_64 とその-devel
mpich.x86_64 3.1-5.el6とその-devel
```

関連 http://qiita.com/7of9/items/cf99212b42ea64e8dbf0

MPICH使用時にmpif90の`-f90=gfortran`オプションでエラーが出ている件に関して。

http://people.sc.fsu.edu/~jburkardt/f_src/mpi/mpi.html
にあるFortran90用サンプルを試した。

http://people.sc.fsu.edu/~jburkardt/f_src/hello_mpi/hello_mpi.f90

### OpenMPIで実行

とりあえず正常動作するOpenMPIの方で試した。

```
$ module purge
$ module load openmpi-x86_64
$ source ~/use_openmpi
$ mpif90 -f90=gfortran hello_mpi.f90 
f951: error: unrecognized command line option "-f90=gfortran"
```

Open MPIの方でも上記エラーが出た。

以下だと動いた。

```
$ mpif90 hello_mpi.f90 
$ mpirun -np 3 ./a.out 
 
HELLO_MPI - Master process:
  FORTRAN90/MPI version
 
  An MPI test program.
 
  The number of processes is        3
 
 
  Process        0 says "Hello, world!"
 
HELLO_MPI - Master process:
  Normal end of execution: "Goodbye, world!".
 
  Elapsed wall clock time =   0.610352E-04 seconds.
 
  Process        1 says "Hello, world!"
 
  Process        2 says "Hello, world!"
```

### MPICHでコンパイル

```
$ module purge 
$ module load mpich-x86_64
$ source ~/use_mpich 
$ mpif90 -f90=gfortran hello_mpi.f90 
$ mpif90 hello_mpi.f90 
```

反対にMPICHでは`-f90=gfortran`が有っても無くても正常にコンパイルできた。

diffの見方を間違っていた。
ぼくのかんがえた最強のタイムマネジメント

月末なので忙しいです。
それでもなんとか定時に上がれるように、ぼくのかんがえた最強のタイムマネジメントを紹介します
仕事の仕方は人それぞれあると思うので、こういう考えの人もいるのかー、程度に思っていただけたら嬉しいです。

# メリット
 - 保守しやすいコードを書く意識ができる
 - 自分のコントロールできる範囲で、工数見積もりが正確になる
 - リリースに間に合う

# 実践編

##「定時で帰る」意識をもつ

### 暗黙の言い訳の余地を外す
「定時に帰る」ということは、少なからずプレッシャーあります
帰った後にバグがみつかる可能性がありますし、適当なコードを書いたら、翌日から周囲から蜂の巣にされるでしょう。

そのため、以下のことを心がけるようになるはずです。
1. 時間内に機能実装を完了させ
2. 無難にテストを書き、
3. ある程度リファクタ済みの状態でおくこと

定時上がりの罪悪感を利用します
プレッシャーがあると副作用として焦りが生まれますが、**焦らず急げ**と心に念じておきます

### タスクを高速に、そして並列処理する
どんなに忙しくても、「定時後すぐの電車にのらないと間に合わない勉強会がある」などの理由があれば、なんとか定時までに全てを終わらせられるように集中していられます。

ポイントは、２つあります。

 - 高速化と「はまる時間」は反比例します
   - 標準APIは使いこなせるように訓練しておきましょう。
   - gemのドキュメントやPJTのソースコードは空き時間を使って読んでます。
   - 読むことに生産性はありまん。しかしレバレッジが効かせられます。
   - コードの速読ができれば強いです。ぼくはできないので練習してます
 - 並列処理
  - rspecやrubocopの実行。ブラウザリロードは自動化
  - Webサービスはルーチンで型が決まっていて、無意識でも可能です
  - 無意識でいいなら、意識的に別の機能の設計を考えながらでOKです
  
## スケジューリング（見積もりは冷静に）
ぼくの経験では、私自身が楽観的見積もった工数で、その通りにリリースできることはほとんどありませんでした。

たとえば、「この機能はいつまでに実装完了するか？」と質問された場合です。

楽観的に自分のスキルなら**３日でできる**と思って、そのまま**「３日あればできます」**といってしまったなら、
**なんとか３日で実装しなければ**という気持ちになります。

なぜなら、３日以内にできなければ**無能だと思われる**からです。
エンジニアとして、「無能」と思われるというのは、非常に居心地が悪く、避けたいものです。

しかし、上で述べたように楽観的に見積もった工数どおりにリリースできることは、ほとんどありません。ぼくの経験則的にもそうですし、[人月の神話
](https://ja.wikipedia.org/wiki/%E4%BA%BA%E6%9C%88%E3%81%AE%E7%A5%9E%E8%A9%B1#.E6.9C.AC.E6.9B.B8.E3.81.A7.E8.BF.B0.E3.81.B9.E3.82.89.E3.82.8C.E3.81.A6.E3.81.84.E3.82.8B.E8.A6.8B.E8.A7.A3)もそう言ってます。

**工数(リリース)間に合わない**と感じたときから、プロジェクトの崩壊が始まります
(テストとリファクタの手抜き)

### 方法
1. 伝える工数は、楽観的見積もりの３倍の日数
2. 楽観的見積もり工数内の完了を意識して実装する
3. 楽観的見積もり内に終わらなかったら、どこかでハマってるということなので、そこを重点的に勉強する

工数の何倍がちょうどいいかは個人差あるとおもいます。
楽観的見積もりは、着手からレビュー対応完了まで悩まず進んだ場合の作業時間です。

# それでも定時で終わらない時
スキル不足かオーバータスク、または適材適所に問題があるので、その場はできる人にデリゲートor撤退or残業になります。

次は時間を守れるようにスキルアップに取り組みます
自己啓発本や技術書をよんだり、できる人のやり方を真似（エンジニアならgitのコード）して勉強することになります
SwiftLintのカスタムルールを使って、スクリーン計測用コードの実装漏れを防ぐ

この記事では、SwiftLintのカスタムルールを使い、Google Analyticsのスクリーン計測用コードの実装漏れを防ぐ方法をご紹介します。

SwiftLintのカスタムルールを使うと、気合や根性で何とかしていた問題を、ルールに落とし込むことができ、ミスが減ります。

# 背景
アプリを開発する際に、ユーザーの行動計測を目的として、Google Analyticsの[スクリーン計測](https://developers.google.com/analytics/devguides/collection/ios/v3/screens?hl=jp)を使うことは多いと思います。このスクリーン計測を利用する際には、各ViewControllerに手動でイベント計測コードを埋め込むことになりがちです。[^1]

手動でのイベント計測は正直苦行であり、実装漏れも起きやすくなります。

Method swizzlingを使って、`viewDidAppear()` を置き換え、自動計測を行うような方法も提案されていますが[^2]、黒魔術的なコードを本番アプリに組み込むのは気が引けました。

そのため、以下のような方針を立てました

* 各ViewControllerに1行だけトラッキング用コードを書く
* 実装漏れがあった場合はSwiftLintでwarningを出す

# 実装
## 1行だけでトラッキングコードを書けるようにする
extensionを使えば、UIViewControllerのサブクラスからは1行のトラッキングコードを書くだけで済みます。

```swift
extension UIViewController {
    func trackScreenView() {
        let className = NSStringFromClass(self.dynamicType)
        // トラッキング処理を書く
    }
}
```

トラッキングコード自体は以下のように1行で[^3]済みます。

```swift
    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        
        trackScreenView()
    }
```

## SwiftLintのカスタムルールで実装漏れにwarningを出す
SwiftLintのカスタムルールを使うと、正規表現をベースにwarningを出すことができます。

今回は以下のような条件でwarningを出すルールを作りました

* ファイル内にUIViewController, UITableViewController, UICollectionViewControllerのいずれかのサブクラスが実装されている
* ファイル内に`trackScreenView`という文字列が書かれていない

### .swiftlint.yml

```
custom_rules:
    unimplemented_screenview_tracking:
        name: "Unimplemented trackScreenView()"
        regex: "class\s+\w+\s*:\s*UI(Table|Collection)?ViewController(?![\s\S]*trackScreenView)"
        message: "Please implement trackScreenView() method in viewDidAppear()"
        severity: warning
```

# 結果

このような形でwarningが出るため、実装忘れに気づけます。

![ViewController_swift.png](https://qiita-image-store.s3.amazonaws.com/0/8803/8a95b6cd-8554-f410-37aa-5fb84ffc2ec2.png)

```
ViewController.swift:11:7: warning: Unimplemented trackScreenView() Violation: Please implement trackScreenView() method in viewDidAppear() (unimplemented_screenview_tracking)
```

SwiftLintのカスタムルールを使うと、スクリーン計測を忘れてしまうといった問題を、ビルド時のwarningで解決することができます。

その他のケースでも、このような気合や根性でなんとかするしかない問題をルールに落とし込むことができますので、皆様もご活用ください。


[^1]: `GAITrackedViewController` というクラスを継承して自動計測も行えますが、UITableViewControllerやUICollectionViewControllerでは使えず、使い勝手が悪いです。
[^2]: http://qiita.com/horimislime/items/71702594363b17483567
[^3]: `super.viewDidAppear(animated)` とかは見逃してください
モーダルなViewがある間はメニューの状態をDisableにしたい

ModalだったりSheetなビューを表示している時にMenubarにあるメニューを実行されると困る時があります。

<img width="628" alt="スクリーンショット_2016-09-28_18_50_53.png" src="https://qiita-image-store.s3.amazonaws.com/0/61792/e9ac800c-1ba5-ee72-34d1-006c5ebc4ce2.png">


そんな時にメニューバーをDisableにするためのメモです。

# Menubarのバリデーション
`NSMenuValidation.validateMenuItem`をOverrideしてバリデーション処理を書きます。
各NSMenuItemに対して実行できるかどうかを返します。

# 現在モーダル状態かを見る
`NSWindow`のプロパティで`worksWhenModal`ってのがあるのでこれを見ます。

ですが、このプロパティはSheetを表示している時は変わらないため、この他に`attachedSheet`プロパティを見る必要があります。
このプロパティはウインドウにシートがついてなければnilを返します。

# 例文
現在のWindowにModal（またはSheet）が表示されていない時のみMenuを有効にする例です。

```swift:SampleWindowController.swift
    override func validateMenuItem(menuItem: NSMenuItem) -> Bool {
        switch menuItem.action {
        case #selector(SampleWindowController.hoge(_:)):
            let sheet = self.window!.attachedSheet != nil
            let modal = self.window!.worksWhenModal
            return !modal && !sheet
        default:
            break
        }
        return false
    }
    
    // MenuBarに紐づくActionMethod
    @IBAction func hoge(sender: AnyObject) {
        ...
    }
```

# 参考
[attachedSheet - Cocoa API解説(macOS/iOS)](http://cocoaapi.hatenablog.com/entry/00021202/NSWindow_attachedSheet)
WRF > Open MPI / MPICH > MPICHでWRFコンパイル失敗 > 解決

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
CentOS 6.8 (64bit)
openmpi-1.8.x86_64 とその-devel
mpich.x86_64 3.1-5.el6とその-devel
```

[WRFのビルド](http://qiita.com/7of9/items/8ff328ed1c144d659335#wrf371%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89--%E6%88%90%E5%8A%9F)
を参考に以下の2つの動作を比較しようとしていた。

- Open MPI
- MPICH

module loadでそれぞれ対応するモジュールを読込み、コンパイルをしていたのだが、Open MPIではwrf.exeなどのビルドに成功する一方、MPICHではビルドが失敗した。

```
==========================================================================
build started:   Thu Sep 29 03:07:55 JST 2016
build completed: Thu Sep 29 03:07:58 JST 2016
 
---> Problems building executables, look for errors in the build log  <---
```

何が問題だろうか。

以下を試した。

```
(Open MPIの設定で)
$ ./compile em_real >& log.comp_openmpi
(MPICHの設定で)
$ ./compile em_real >& log.comp_mpich
```

そしてその差分を取ると

```
$ diff log.comp_openmpi log.comp_mpich
40c40
< /usr/lib64/openmpi/bin/mpif90
---
> /usr/lib64/mpich/bin/mpif90
45c45
< /usr/lib64/openmpi/bin/mpicc
---
> /usr/lib64/mpich/bin/mpicc
176,179c176,177
< f951: error: unrecognized command line option "-f90=gfortran"
< 0.00user 0.00system 0:00.00elapsed 50%CPU (0avgtext+0avgdata 1852maxresident)k
< 0inputs+0outputs (0major+1270minor)pagefaults 0swaps
< make[2]: [diffwrf] Error 1 (ignored)
---
> 0.30user 0.03system 0:00.33elapsed 102%CPU (0avgtext+0avgdata 24420maxresident)k
> 0inputs+160outputs (0major+13257minor)pagefaults 0swaps
378,380c376,378
< real  0m0.089s
< user  0m0.061s
< sys   0m0.027s
---
> real  0m0.118s
...
```

MPICHの場合176行目に`f951: error: unrecognized command line option "-f90=gfortran"`というエラーが出ている。
176行目は

```
time mpif90 -f90=gfortran -w -ffree-form -ffree-line-length-none -fconvert=big-endian -frecord-marker=4  -c  -I/usr/include -I../ioapi_share diffwrf.f
```

mpif90のオプションとして"-f90="がないとなっている。

### MPICHのドキュメント

http://www.mpich.org/static/docs/v3.1/www1/mpif90.html

> `-f90=name`
Use compiler name instead of the default choice. Use this only if the compiler is compatible with the MPICH library (see below)

> <h3>Compatible Compilers</h3>
The MPI library may be used with any compiler that uses the same lengths for basic data objects (such as long double) and that uses compatible run-time libraries. On many systems, the various compilers are compatible and may be used interchangably. There are exceptions; if you use the MPICH_F90 environment variable or <font color=red>the \-f90=name</font> command-line argument to override the choice of compiler and encounter problems, try reconfiguring MPICH with the new compiler and installing MPICH in a separate location. See the installation manual for more details.

yumでmpichをインストールするだけではだめなのだろうか。

### diffの見直し

http://qiita.com/7of9/items/d932df7957957125dea7
で確認したところ、`f951: error: unrecognized command line option "-f90=gfortran"`はOpenMPIの方で出ていた。

### やり直し

WRFV3のtar.gzから再度作り直したところ、コンパイルできた。

> CFLAGS_LOCAL = -w -O3 -c
を
CFLAGS_LOCAL = -w -O2 -c
で再度ビルド.

を忘れていた可能性もある。
さくらのクラウドで最小構成のサーバを作成する(2)

[さくらのクラウドで最小構成のサーバを作成する(1)](http://qiita.com/sato-w-m/items/eae773e2e4155063f95b)の続きです。

##NICの設定
NICはサーバ作成時は1つしか設定出来ませんが、後から1つ追加することができるので合計2つのNICを持てます。
![サーバ追加3.png](https://qiita-image-store.s3.amazonaws.com/0/140995/06f2d347-f471-e203-71f0-086aea265eb4.png)

まず接続先を選択します。
「インターネットに接続」は１番目のNICにグローバルIPアドレスが一つ割り当てられます。
CentOS6.xだと/etc/sysconfig/network-scripts/ifcfg-eth0にIPアドレスが直書きされています。
共有の100Mbps回線ですがWEBサービスであれば全く問題ないと思います。
「スイッチに接続」はあらかじめ作成しておいたアプライアンスのスイッチに接続させます。
これを選択すると次の「4.ディスクの修正」でIPアドレスに関する項目(IPアドレス、ネットマスク、ゲートウェイ)が出現します。
尚、あらかじめルーター付スイッチやVPCルーターを作成しておかないとインターネット接続が無い状態でサーバが作成されます。
「切断」はどこにも接続されていない状態でサーバが作成されます。
今回は「インターネットに接続」を選択した状態で作成します。
「準仮想化モードを使う」はディスクの際にも説明したもので
完全仮想化と異なりパフォーマンスが最適化されますがゲストOSにドライバが必要となる場合があります。

「パケットフィルタを選択」は別途パケットフィルタを作成していた場合にそれを適用することができます。
サーバ作成時点からしっかりしたセキュリティーを確保しておきたい場合や、
インターネットに接続を選択する場合は適用したほうがよいと思います。

##ディスクの修正
アーカイブやディスクコピーを行った場合にディスクの修正を行うことが出来ます。
![サーバ追加4.png](https://qiita-image-store.s3.amazonaws.com/0/140995/237c4df3-2db7-946b-25bc-4098d62e7523.png)

「ディスクの修正をする」チェックでそもそもディスクの修正を行うか否かを選択出来ます。
例えば既存ディスクをそのまま利用したい場合はチェックを外せばOKです。

もしNICの設定で「スイッチに接続」を選択していたらIPアドレス、ネットマスク、ゲートウェイが追加されます。
今回は「インターネットに接続」を選択しているので表示されていません。
また、選択したアーカイブによっても表示内容が異なります。
(Windowsだとディスクの修正機能が使えないなど)
さくらのクラウドで提供されているアーカイブを選択した場合は各OSごとにメッセージが表示されるので確認してください。

今回はCentOS6.8を選択してみました。
この場合、管理ユーザーのパスワードはrootユーザーのパスワードとなります。
ホスト名はhostnameコマンドで確認出来る内容になります。

「公開鍵」はサーバに公開鍵を配置出来ます。
「入力」を選択すると公開鍵を貼り付けるテキストボックスが現れます。
「選択」はあらかじめさくらのクラウドアカウントに設定しておいた公開鍵を配置出来ます。
これはさくらのクラウドの左メニューからではなく、上部の「設定」から行っておく必要があります。
また、公開鍵を設定しておくことでSSHのパスワード認証を無効にしておくことも可能です。

「配置するスタートアップスクリプト」は作成後に実行させるスクリプトを選択出来ます。
あらかじめ用意されているものでは「yum update」などがあります。
自分で作成したスクリプトを選択することも可能ですが、事前に「設定」から登録しておくことが必要です。

##シンプル監視
最近追加された機能で、pingやtcpでのポート監視などを無料で追加出来ます。

![サーバ追加5.png](https://qiita-image-store.s3.amazonaws.com/0/140995/c66b05fc-351e-ccea-5978-25d2ed250c87.png)

監視結果はメールかslackで受け取れます。メールアドレスは「設定」から登録することができます。

##サーバの情報
これはこのコントロールパネル上で表示される項目になります。
![サーバ追加6.png](https://qiita-image-store.s3.amazonaws.com/0/140995/ecce9537-7b02-b335-3fa5-d2c6b1b532c7.png)

名前はホスト名と合わせておいたほうが無難です。
その他、説明などに任意に入力しておきます。
アイコンは種類が少ないです。

##その他オプション
キーボードをUS配列として登録出来ます。
「作成後すぐに起動」にチェックが入っているとディスクコピーや修正が終了したらすぐに起動されます。
もしNICの追加設定やディスク追加などを考えている場合はチェックを外しておきます。

##作成数
これは最近追加された機能です。
ただしNICを「スイッチに接続」にしておくと項目が消えます。
IPが重複したりしたら大変なので仕方ないかと思います。

##作成
最後に「+作成」ボタンを押せばサーバが作成されます。
さくらのクラウドは起動中か否かにかかわらず課金されるので注意してください。
(サンドボックスでは課金されません)

##作成中
このようなダイアログが出ますが、最小化しておくと他の作業ができます。
![サーバ追加7.png](https://qiita-image-store.s3.amazonaws.com/0/140995/71dadaae-1132-53fe-654f-f56c63e2e4f4.png)

ディスクのコピーはSSDの20GBが最速です。
作成完了まで5分程度はみた方がよさそうです。
ディスクサイズが大きくなるとより時間がかかる様になります。

##作成完了
完了するとすべてのステータスが成功になります。
![サーバ追加8.png](https://qiita-image-store.s3.amazonaws.com/0/140995/7f47c84c-7ce2-6b11-29fd-177c16d970de.png)

NICを「インターネット接続」にしていた場合はこの時点でグローバルIPアドレスが判明します。
サンドボックスの場合はIPは割り当てられますが通信はできません。

万が一作成に失敗した場合(たとえばディスクコピーの失敗)でもサーバの作成が完了していると料金が発生します。
サーバ一覧は必ず確認して必要に応じて再実行や修正を行いましょう。
One Liner Web Server

ダウンロード速度の計測目的などで、webサーバを簡易的、一時的に起動させたい。
でも、apacheなどをインストールしてlibやbinにproductionとは関係ないファイルが残るのは嫌だなぁ。
そんな時、pythonでwebサーバを起動させる（httpをLISTENさせる）ことができます。しかも one liner で！

# サーバ側

1\. rootになります
2\. カレントディレクトリにファイルを作成します。これがhttpで配信するファイルになります

```
# echo hoge > index.html
```
3\. 次を実行して80ポートをLISTEN状態にする（webサーバを起動する）

```
# python -m SimpleHTTPServer 80
※80を指定しなければデフォルトのLISTEN PORTは8000です
```

<2024-03-25追記>
python3ではSimpleHTTPServerモジュールがhttp.serverモジュールにリプレイスされています。
```
# python -m http.server 80
※80を指定しなければデフォルトのLISTEN PORTは8000です
```

\</2024-03-25追記>

# クライアント側
1\. curlなりwgetなりでindex.htmlを取得する

```
$ wget http://サーバのホスト名/index.html
```

2\. ファイルを確認
```
$ cat index.html
$ hoge
```

# 参考URL
[http://d.hatena.ne.jp/rx7/20090812/p1](http://d.hatena.ne.jp/rx7/20090812/p1)
Jenkins で Git リポジトリを取得するとき signal 15 が発生する

> Killed by signal 15.

と言われてビルドに失敗する場合、取得するサイズが多すぎてタイムアウトが発生しているので、タイムアウトが発生しないように設定を変える。

1. Jenkins のプロジェクトの設定画面を開く
2. **ソースコード管理** の **Additional Behaviours** で **Advanced clone behaviors** を追加する
3. **Timeout (in minutes) for clone and fetch operations** を分単位で十分に大きい数を指定する。
本番運用中のウェブサービスをRails4からRails5に移行する



私が所属する会社で開発・運営しているウェブサービスはRails4.2系で動いていましたが、その中1つのサービスをRails4.2.6からRails5.0.0へとバージョンアップしましたので、その際に発生した問題とそこで得られた知見を今回の記事でお話ししようと思います。

移行の際にはこちらの記事を参考にさせていただきました。

http://tech.grooves.com/entry/2016/07/01/184458

# gemのupdate

railsを5に上げる際に依存関係を解消するためにgemのバージョンを一気に最新にしましたが、rubygemsにrails5対応のバージョンが上がってなかったり、上がっていたとしても実行時にDEPRECATION WARNINGが出たりしていました。多くのgemは既にmasterではrails5やDEPRECATION WARNINGに対応した物が出ているので

```
gem ‘hogehoge’, github: ‘hogehoge’
```

といった形でgithubから直でmasterブランチの内容を引っ張ると解消できることが多かったです。以下が実際に今引っ張っているものです。

- rails-perftest
- activemodel-serializers-xml
- sinatra
- ransack
- gretel
- enumerize
- heroku-deflater

# Rails5の書き方に合わせる

DEPRECATION WARNINGやエラーが幾つか出るので、古い書き方から新しい書き方へ直します。

- paramsをpermitしてからurlに変換する
 - 最悪、unsafe_hでパラメータクラスからHashに変換できるが余りよろしくない
- ActiveRecord::Baseから継承せずにApplicationRecordというabstractクラスを作ってそれを継承する
- merge! -> mergeに変更
- error[‘hogehoge’] = ‘hoge’ -> error.add(‘hogehoge’, ‘hoge’)に変更
- ActiveRecordのuniqをdistrunctに変更
- destroy_all(condition) -> where(condition).destroy_allに変更

# 終わりに
この記事は自ブログからの転載となっています
もし良かったらブログもどうぞ
https://hackalive.net
php-mime-mail-parserで処理した結果をまとめてみる

[php-mime-mail-parser](https://github.com/php-mime-mail-parser/php-mime-mail-parser)で手持ちのメーラーから送信したメールを処理した結果をまとめます。

# 環境・前提条件
## 受信側
* PHP 7.0.11
* php-mime-mail-parser 2.4.4
* Postfix 2.10.1
* aliases設定でメールが来ると処理してtxtに書き出す

## 送信側
文字色や文字サイズ等のhtml装飾は使用せずデフォルトの設定でメールを作成

0. SoftbankのiPhoneSE：SMS
0. SoftbankのiPhoneSE：@i.～からのメール
0. SoftbankのiPhoneSE(OS:9.3.5)：DecoMailer ver.3.6.9(アプリ)
0. docomoキャリアメール(Android) 
0. gmail(PCから)
0. yahooメール(PCから)  

# 結果
文中の変数
```php
$text = $Parser->getMessageBody('text');
$html = $Parser->getMessageBody('html');
$htmlEmbedded = $Parser->getMessageBody('htmlEmbedded');
$attachments = $Parser->getAttachments();
```

## 共通
* 絵文字を使うと文字化けを起こす

## SoftBank SMS
* `$html`,`$htmlEmbedded`は空。
* 本文はすべてプレーンテキストとして処理される
* 画像はすべて添付として処理される
* 文中に画像を挿入した場合どこに挿入されたかはわからない
* 添付画像の名前は元画像のまま
* cidなし

## @iからのメール　※要検証
* `$html`,`$htmlEmbedded`は空。
* 画像を入れると`$text`内の文章がそこで切れる現象が発生
* その後ろにも貼り付けや添付で画像を配置していたが、画像そのものはinlineとして全て`$attachment`に渡されており、画像そのものも保存されている

## デコメーラー
* inline画像はcidを与えられて`$html`には`<img src="cid:~~">`として入る
* 画像は
    * 添付なら`attachment00`～で連番
    * インラインなら`image00`～で連番が振られる
* 元画像の名前は残らない
* `$html`は`<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></HEAD><body>`内容`</body></HTML>`の形
* 改行は`div`で処理
* 続けて改行した場合は`<div>&nbsp;</div>`が入る

## docomoキャリアメール(Android)
* inline画像はcidを与えられて`$html`には`<IMG src="cid:~~">`として入る
* 画像名は元画像のまま
* `$html`は`<HTML><HEAD><META http-equiv="Content-Type" content="text/html; charset=UTF-8"></HEAD><BODY>`内容`</BODY></HTML>`の形
* 改行は`div`で処理
* タグは大文字
 

## gmail
* テキスト内に貼り付けた画像は[image: 埋め込み画像 1]の形で`$text`内にも反映
* inline画像はcidを与えられて`$html`には`<img src="cid:~~">`として入る
* `$html`ではimgタグ内に画像のサイズや位置等のstyleも入ってくる
* `$html`に`html,body`のタグはなく`div`の集まりで構成される
* 改行は`div`で処理
* 続けて改行した場合は`<div><br></div>`が入る

## yahoo
* inline画像は`$attachmennt`としては渡ってこないので画像フォルダには保存されない
* `$html`の時点で`<img src="data:image/jpeg;base64>` というように文字列で入ってくる
* `$html`は`<html><body>`内容`</body></html>`の形
* 改行は`div`で処理
* 続けて改行した場合は`<div><br></div>`が入る
* 添付画像のみが`$attachmennt`として渡される
* 添付画像の名前は元画像のまま

# 雑感
ブログ投稿的な使い方をするために検証したのですが、iPhoneの素のメールが他と違う仕様なのを痛感しました。
何より@iのメールで画像以降の本文が拾えなかったのにびっくりです。
文字コードの絡みだろうな、というのは分かりましたが今回はそれを解消することが目的でないので深くは見ていません。
@iよりはSMSのほうがまだマシ。apple仕様に少しキャリアの補正がかかっているのでしょうか。

絵文字は`php-mime-mail-parser`ではどのメーラーから送っても文字化けしました。
機種依存文字に関しては私が試した文字では一通り問題なし。

yahoo仕様だと`$html`と`$htmlEmbedded`は同じになります。画像が少ない場合はいいですが、多くなってくると`$html`がすごい文字数になるのでDB格納するのもどうなの？？って感じですね。。。

gmailとデコメーラーは基本仕様はほぼ同じで、htmlタグの使い方と画像の名前のつけ方が違うぐらいですね。
基本的にhtmlの中に読み込んで使うのでgmailの仕様のほうが便利。

今回試してませんが、html装飾機能を使った場合はdivタグの中に直接styleが書き込まれていく模様です。
Golangにてプロジェクト自作ファイルのみをテストをかける方法


ふつうにはパッケージ（導入単位）でテストを行います：

```
$ go test foo
$ go test foo/pkg1
```

たくさんのパッケージがある場合、一気に全部自作パッケージをテストしたい場合、下記のように：

```
$ go test $(go list ./... | grep -v /vendor/)
```

全部パッケージをテストできます。

`-v /vendor/` は第三者のパッケージを除外するためです。

Golang自身はパッケージ管理、テスト等色々面にまたまたそんなに便利だと言えないでしょうかね。
wordpressのカスタム投稿で投稿者にカスタム投稿を見せないようにする

探したらいろんなやり方があったんですが、一番簡単な方法で
少しカスタマイズを加えてます

``` function.php
function remove_menus () {
  global $menu;
  if (!current_user_can('level_10')) { // 管理者以下
    unset($menu[2]); // ダッシュボード
    unset($menu[4]); // メニューの線1
    // unset($menu[5]); // 投稿
    unset($menu[25]); // コメント
    unset($menu[59]); // メニューの線2
    unset($menu[60]); // テーマ
    unset($menu[65]); // プラグイン
    unset($menu[70]); // プロフィール
    unset($menu[75]); // ツール
    unset($menu[80]); // 設定
    unset($menu[90]); // メニューの線3

    if (!current_user_can('level_7')) { // 投稿者以下
      unset($menu[6]); // カスタム投稿
      unset($menu[7]); // カスタム投稿
      unset($menu[8]); // カスタム投稿
      unset($menu[9]); // カスタム投稿
      // unset($menu[10]); // メディア
      unset($menu[15]); // リンク
      unset($menu[20]); // ページ
    }
  }
}
add_action('admin_menu', 'remove_menus');

```
引用元：(http://qiita.com/konweb/items/5483efbe87087eff5cc8)

カスタム投稿を設定する際の`'menu_position' => 4`だった場合の設定です。
消えない場合、余計なものが消えた場合は`unset($menu[6])`の数字を変えてみてください
ajaxのpostでbase64ではなく画像をsubmitする


```main.js
$.ajax({
    url: "/api/hoge",
    method: 'post',
    data: imageFile
}).done(hogehoge);
```

でやっちゃうとファイルが文字列になってしまいformをsubmitしたときと違ってしまいます。

formDataを作って、appendしてそれを下記データ・フォーマットで送れば
form.submitでファイルを送った場合と同じ挙動になって送れます。

```main.js
var formData = new FormData();
formData.append('imageFile', imageFile);

$.ajax({
    url: "/api/hoge",
    method: 'post',
    dataType: 'json',
    processData: false,
    contentType: false,
    data: formData
}).done(hogehoge);
```

やったぜ乾杯🍷
AWS Lambda+API Gatewayでのタイムアウト対応

何も気にせずAWS Lambda + API GatewayでAPIを作成していたところ、

「タイムアウト発生時でもstatus code 200返ってきちゃうんすけど」

ということで慌てて対応。

# その前にタイムアウトについて

API Gatewayが発生させるタイムアウトと、Lambdaが発生させるタイムアウトの2種類が存在します。

前者は自動的に504（Gateway Timeout）を返してくれるので問題ありません（Swaggerの定義ファイル上に記載すべきか迷いますが、、、ちなみに2016/9/27時点では、管理コンソールからのこのタイムアウトを発生させると504が発生したかどうか、結果が見えないのでデプロイしたURLからお試しください）。

さて、では後者は？

# AWS Lambdaのタイムアウト対応

これは、API Gatewayの統合レスポンスに定義しておく必要があります。
エラーメッセージに対する正規表現で記載できるので、

`.*Task timed out after.*`

みたいな記載でメソッドレスポンスに定義したステータスコードと紐付ければうまく動きます。

ただ、ソースコード上からも「これは500で返したい」的な要望はあるので、その場合、私は例外メッセージの接頭辞に「INTERNAL SERVER ERROR」と付与する例外クラスを作って、統合リクエストの正規表現には

`INT.*|.*Task timed out after.*`

と記載したりしています。

正しいやり方なのかよくわかりませんが（オイ）、取りあえず上手く動いています！
さくらのクラウドで最小構成のサーバを作成する(1)

さくらのクラウドで最小構成のサーバを作成してみます。
今回はサンドボックスを利用します。
##作成後のマップ
できあがりはこちらの通り。
![サーバ追加9.png](https://qiita-image-store.s3.amazonaws.com/0/140995/60a94ba1-6a82-34a3-977a-096d68743d7a.png)

さみしい感じですがサーバを作成すると標準でグローバルIPが一つ付与されるのでこれだけでも立派にサービスを提供出来ます。

##まずはログイン
![さくらのクラウド ホーム.png](https://qiita-image-store.s3.amazonaws.com/0/140995/0ad87351-c073-965d-af6f-1dfe938ad6a7.png)
さくらのクラウドを始めるにはさくらの会員である必要があります。
すでに会員になっている場合は電話での認証ですぐに利用を始めることが出来ます。
会員は会員IDに紐付いたクラウド用のアカウントを作成出来るので
会員IDとは別にクラウドのIDを管理出来ます。

##サービス選択
![サービス選択 - さくらのクラウド ホーム.png](https://qiita-image-store.s3.amazonaws.com/0/140995/8345b17c-09bf-ae24-bfd6-78fbf26273d6.png)
ログインするとサービス選択画面になります。
普通にサーバを作成したい場合は左上の『さくらのクラウド(IaaS)』を選択すればOKです。

##サーバ一覧
![サーバ一覧.png](https://qiita-image-store.s3.amazonaws.com/0/140995/ac012b5c-c902-7cb2-be6d-ec0b48201b28.png)
今はなにも作成されていないので「リソースが作成されていません」と表示されています。
サンドボックスは石狩ゾーンを基準として参考価格が提示されますが、
実際に課金されるわけではないのでサーバを作成してみます。

##サーバ作成
サーバ一覧の上部にある「＋追加」をクリックするとこの画面になります。
![サーバ追加.png](https://qiita-image-store.s3.amazonaws.com/0/140995/114dc828-1fc6-a801-349f-a60122a82464.png)
サーバ追加のモードは2種類で、「シンプルモード」と「通常モード？」があります。
当初はシンプルモードがなかったので今回は慣れている通常モードで進めていきます。
2つのモードの切換は左上の「シンプルモード」をチェックするだけです。
(入力内容は切換時にリセットされるようなので注意した方がよいです)

##サーバプランの選択
プランはコア数とメモリ量の組み合わせで決定されます。
「サーバプラン一覧から選択」をクリックすると組み合わせ可能なコア数とメモリ量の一覧が表示されます。
コア数が増えるに従って選択出来るメモリが増えていきます。
ここでは最小となる1コア/1GBメモリを選択してあります。

##ディスクの選択

次にディスクを選択します。
![サーバ追加2.png](https://qiita-image-store.s3.amazonaws.com/0/140995/74eb3e7b-559b-9bf9-0139-08f28886b2c5.png)
最初の選択肢は新規にディスクを作成してサーバにアタッチするか、既存のディスクをアタッチするか、ディスクをアタッチしないかです。
始めて利用するなら問答無用で新規ディスクだと思います。
既存ディスクを選択した場合はサーバにアタッチされていないディスクの一覧から選択出来ます。

- ディスクプラン
SSDかそれ以外かを選択出来ます。
速度はSSDの方が早いので私は主にSSDを利用しています。

- ディスクソース
ディスクのコピー元です。
「アーカイブ」はさくらのクラウドがオフィシャルに用意しているもので最初はこの選択肢から選ぶのがよいと思います。
Windows Serverも用意されていますが、月額のライセンス費用が加算されます。
「マイアーカイブ」は自分で作成したそのゾーンのアーカイブを選択出来ます。
「マイディスクをコピー」は既存のディスクをなんでもコピー出来ます。
すでにサーバにアタッチされている稼働中のディスクでもコピー出来ます。
(一般論として稼働中のサーバのディスクをコピーするのは慎重に検討した方がよいと思います)
「ブランク」は特にディスクにデータがコピーされません。
たとえばISOイメージを利用したい場合などにつかうと良さそうです。

- ディスクサイズ
20GB以上から特定の制限の元に自由に選べます。
まずソースサイズ以下のディスクは選択出来ません。
最小サイズと最大サイズはSSDと標準プランで異なります。
最小サイズはSSDプランの方が選択肢が広く、最大サイズは標準プランの方が選択肢が広くなります。
また、さくらのクラウドから提供されるアーカイブは自動的にサイズが最大化されるものと固定サイズのものがあります。
アーカイブを選択した時点で警告表示がありますので確認してください。
メジャーなディストリビューションのメジャーバージョンであれば基本的に全サイズ対応です。
尚、固定サイズのアーカイブやマイアーカイブなどを選択してディスクサイズを既存より大きくした場合は未使用領域となります。
サーバ作成後にOS上から拡張したり割り当てたりすることが可能です。

- 準仮想化モード(Virtio)
サーバが実行される環境で準仮想化モードを利用するか否かを選択出来ます。
一般的にハイパーバイザによって完全仮想化されるより準仮想化を利用した方が効率がよいと思われるので
選択したままでよいと思います。
ただ、ブランクディスクで後からOSを入れたりする場合はVirtio対応のドライバをインストールする必要があるかもしれません。

長くなってきたので次の記事に続きます。
BrowserifyでjQueryを読み込む場合のTips

npmで追加したjQueryをBrowserifyで一つのファイルにしようと思って、

```
import jQuery from 'jquery';
```

と書くと

```
ReferenceError: Can't find variable: jQuery
```

というエラー。

```
global.$ = global.jQuery = require('jquery');
```

と書くと問題なし。
フレームワークFuelPHPの動的クラス読み込みを理解する


モデルなど決められたディレクトリ内のクラスを使用する際、
フレームワークであれば毎回includeしなくても中の人が勝手にやってくれます。
そんな中の人の仕組みを追って行ったメモ。

マジックメソッド`__autoload`を使うことでクラスが存在しない時に処理を実行できる。
この処理でクラスを含むファイルをロードできなければおなじみのエラー画面へ招待される。
http://php.net/manual/ja/function.autoload.php

FuelPHP1.8ではクラス名のアンダースコアがディレクトリの区切りになるという命名則なのでアンスコで区切ってパスにすればよい。
http://fuelphp.jp/docs/1.9/general/coding_standards.html

```php
function __autoload($name)
{
    // change file name Model_Sample -> .../model/sample.php
    $file = APPPATH.'classes'.DS.str_replace('_', DIRECTORY_SEPARATOR, mb_strtolower($name)).'.php';

    if (file_exists($file)) {
        require_once $file;
    }
}
```

`spl_autoload_register`を使えば任意の名前の関数をオートロード処理に追加できる。
http://php.net/manual/ja/function.spl-autoload-register.php

```php
function filecheck($class)
{
    if (file_exists($class)) {
        require_once $file;
    }
    else {
      echo "{$class}なんてなかった。\n";
    }
}
spl_autoload_register('filecheck');
```

実際には`Model_Hoge_Fuga`の場合、`model\hoge\fuga.php`だけでなく`model\hoge_fuga.php`にもマッチさせたりと色々やっているようです。
https://github.com/fuel/core/blob/1.9/develop/classes/autoloader.php

「なんかこうやればできる」の裏方を少し理できた気がする。処理が気になったらコアファイルも積極的に覗いて行こう。
Tomcat APPの再起動コマンドで



Tomcatの再起動があまりに遅いので、単体で再起動できるようにする。
ターミナルからアプリを指定して再起動

設定ファイルに以下の行追加
```xml:tomcat-users.xml
<user username="ユーザ名" password="パスワード" roles="manager-script"/>
```

以下のコマンドで再読み込み
```shell-session
curl --user ユーザ名:パスワード http://localhost:8080/manager/text/reload?path=/アプリケーション名
```
[Linux][cmake] 最新のcmakeをインストールする方法

Ubuntuのaptで持ってこれるcmakeのバージョンがビルドの要求最小バージョンより古い場合があったため、
最新のcmakeを取得する方法を調べた。

# バイナリを取得

公式のDownloadの `Binary distributions:` 以下から環境に合わせたものを選択。

[Download | CMake](https://cmake.org/download/)

![cmake_bin.jpg](https://qiita-image-store.s3.amazonaws.com/0/37721/b9c75151-ec2c-ff6b-bd69-300a3b73ec66.jpeg)

# ソースからビルド

同じく公式のDownloadの `Source distributions:` 以下から環境に合わせたものを選択。

[Download | CMake](https://cmake.org/download/)

![cmake_src.jpg](https://qiita-image-store.s3.amazonaws.com/0/37721/bf20beee-c4f3-f65c-6105-1708b37cd410.jpeg)

```console:ダウンロードと展開（cmake-3.6.2の場合）
$ wget https://cmake.org/files/v3.6/cmake-3.6.2.tar.gz
$ tar xvf cmake-3.6.2.tar.gz
```

添付の `README.rst` によると以下のようにするらしい

```console:ビルド
$ ./bootstrap && make && make install
or
$ ./bootstrap && make && sudo make install
```

`configure` というスクリプトもあったが、確認したところ内部で `bootstrap` を実行しているだけなので、どちらでも変わらないっぽい
(`bootstrap` がすごい長大な shell script だったので驚いた。cmakeのビルド自体は力技感がすごい)
フロントエンドの情報収集・共有・質問・勉強会告知用のSlackチームを作りました

フロントエンド情報収集の方法が多岐に渡るため、Slack Teamを作ってみました。
どなたでも参加、発言、質問、宣伝をしていただけるプラットフォームにして、
日本のフロントエンドシーンを盛り上げていくのが目的です。

## 現状できること

- 質問
- 情報共有
- コミュニケーション
- 勉強会告知

今後どんどんチャネルを増やしていきますので、
チャネル作成要望のチャネルも用意してあります。

## 参加ルール

可能な限り、参加しはじめた方は
welcome-boardというチャネルにて自己紹介をしてください。
自己紹介のフォーマットなどは決めておりませんので、自由記述でお願いします。

また、もちろん誹謗中傷などは厳禁になります。
それ以外はほぼご自由に利用していただければと考えております！

## 参加フォーム

https://jpfrontend.herokuapp.com/
こちらで参加登録が可能です。是非奮ってコミュニティにご参加ください！

※ Twitterにて一部ユーザー様よりGoogleフォームを使うことでメールアドレスの収集をしないかと、不安のお声をいただきました。
slackinを利用する手法を知らず、不安にさせてしまったことをお詫びいたします。不勉強につき、大変失礼いたしました。
[備忘録] open-vm-toolsでwindowsディレクトリのマウント


VMWareでホストWindows上でゲストLinuxを動作させているときに、Windows側の共有ディレクトリをLinuxでマウントする方法。
以前は`$ mount -t vmhgfs`でマウントできていたがopen-vm-tools推奨となって少し変わっている。

## インストール

```bash
$ sudo aptitude install open-vm-tools open-vm-tools-dkms open-vm-tools-desktop
```

## マウント

```bash
$ sudo mount -t fuse.vmhgfs-fuse -o allow_other .host:/<share dir> <mount point>
```

allow_otherをつけないとroot以外はアクセス禁止となる。（詳細やその他のオプションはfuse(8)参照）

## /etc/fstab への記述

```:/etc/fstab
.host:/<share dir> <mount point> fuse.vmhgfs-fuse allow_other 0 0
Firefox 開発者ツール ネットワークタブ 詳細ペイン はレスポンシブでなく、一定の横幅が必要

# <i class="fa fa-cogs"></i> 動作確認環境

* `Windows7`
* `Firefox Developer Edition 51`

# :warning: 問題

通信の詳細が閉じれない

あといろいろ見切れている

## Inspectorでは

![qiitahtml.png](https://qiita-image-store.s3.amazonaws.com/0/62354/af34da8a-bcd8-3136-d448-c791ddf58c7f.png)

## Debuggerでは

![qitadebugger.png](https://qiita-image-store.s3.amazonaws.com/0/62354/53977e32-2cd1-aa89-56d3-e5ff39942d00.png)

## Networkでは

![qiitanetwork1.png](https://qiita-image-store.s3.amazonaws.com/0/62354/66aa14d4-bf9d-96f1-bfbe-1ad078bac1af.png)

![qiitanetwork2.png](https://qiita-image-store.s3.amazonaws.com/0/62354/ce19c467-0b62-81ee-6533-f65dc2f2f25a.png)

# ウィンドウ自体の横幅を確保する

画像は最大化。そこまではしなくていい。

![qiitanetwork3.png](https://qiita-image-store.s3.amazonaws.com/0/62354/94e44222-1ef5-a601-96ac-69d43b8fcf52.png)

縦置きディスプレイの横幅いっぱいのサイブでギリギリ幅が足りなかったり、
自分は別ウィンドウにしてますけど同ウィンドウの右側に設置オプションの使い勝手が悪かったりでbad。
Apache2.4のhtaccessで複数条件を組み合わせる時の注意点

Apache2.4の`.htaccess`設定メモ

IP制限を掛けつつ、ダイジェスト認証を設定する
`<RequireAll>`を使わずに並列に「IP制限」と「認証」を書くと`<RequireAny>`として扱われるため、
**「IP制限」または「認証」**となってしまうので注意。

|ディレクティブ|意味|
|---|---|
|`<RequireAll>` |ディレクティブ内の条件すべてに一致することを要求する|
|`<RequireAny>` |ディレクティブ内の1つ以上の条件に一致することを要求する|
|未指定 |`<RequireAny>` と同義|

```
# IP制限かつ認証要求
<LocationMatch "/hoge/admin.*">
    <RequireAll>
        <RequireAny>
            Require ip xxx.xxx.xxx.xxx
        </RequireAny>

        AuthType Digest
        AuthName "test"
        AuthUserFile xxxxxx
        Require valid-user
    </RequireAll>
</LocationMatch>
```
これで指定されたIPのどれかに一致、かつ認証通過を要求となります。
ナウいバックアップBaculaをAnsibleを使って約５分で構築してみた。

Bacula環境をAnsibleで5分で構築してみました。

Baculaについては以下をご参照ください。
<a href="http://qiita.com/ksawada1979/items/bf771d2dbc71bba3754f">rsyncさん今までありがとう。ナウいBaculaでバックアップしてみた。</a>

## インストール環境
||バージョン|
|:--|:--|
|OS|CentOS 7.3|
|バックアップ|Bacula 7.4.7|
|データベース|MariaDB 5.5|

## 準備いただく環境
<b>CentOS7.3だけ！</b>

SELinuxとfirewalldの設定はお好みで！
Baculaはポート9101～9103を使用します。

## 自動構築する環境
お試し環境のため、１台のサーバに全てのデーモンをインストールし、さらに自サーバをバックアップ、リストアできるように設定します。
権限も全てrootで実行します。

![qiia.png](https://qiita-image-store.s3.amazonaws.com/0/101744/aa6afc8a-2bbf-b0bc-a634-3a53d25faca2.png)


## パッケージ準備
自動構築するまえに準備としてパッケージを追加します。

```shell-session
# yum install -y epel-release
# yum install -y ansible git wget
```

## 鍵交換
自サーバと鍵交換します。
ssh-keygenコマンド実行後はそのまま「Enter」連打で問題ありません
192.168.0.1は例ですので、読み替えて実施してください。

```shell-session
# ssh-keygen -t rsa
# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.0.1
```

## AnsibleのPlaybook取得
Playbookをダウンロードしディレクトリの中に移動します。

```shell-session
# git clone https://github.com/ksawada1979/Bacula7-CentOS7-ansible.git
# cd Bacula7-CentOS7-ansible
```

## Playbook修正
ダウンロードしたPlaybookのIPアドレスが記載されている箇所をお使いのサーバアドレスに修正します。
ansible_hostsはそのままIPアドレスを修正し、mail.ymlはipaddressの項目を修正してください。

```shell-session
# vi ansible_hosts
# vi roles/bacula/vars/main.yml
```

## Bacula環境自動構築
Ansibleを実行し自動的にBacula環境を構築します。

```shell-session
# ansible-playbook -i ansible_hosts bacula.yml
```

最後に再起動の処理がありサーバが再起動します。

## Bacula環境確認
Bacula環境が構築できたことを確認します。
再起動後に「bconsole」コマンドを実行して以下の画面が表示されることを確認します。

```shell-session
# bconsole
Connecting to Director localhost:9101
1000 OK: 102 bacula-dir Version: 7.4.4 (20 September 2016)
Enter a period to cancel a command.
*
```

コマンドプロンプトが「*」になっていれば成功です。

## バックアップの取得
Baculaのバックアップ取得手順については以下を参照ください。
https://www.bacula.jp/backup

runコマンド実行後に「BackupClient1」と表示されるサーバが自サーバになります。
正常にバックアップが取得できることを確認してください。

また「BackupCatalog」は自サーバのデータベースになります。

## リストア実行
Baculaのリストア手順については以下を参照ください。
https://www.bacula.jp/restore

またその他の設定変更手順については以下を参照ください。
<a href="http://qiita.com/ksawada1979/items/bf771d2dbc71bba3754f">rsyncさん今までありがとう。ナウいBaculaでバックアップしてみた。</a>


## 訂正
<font color=red>しばらくの間実行できないAnsibleファイルがアップロードされていました。試していただいた方申し訳ありません。2017年5月31日に修正しましたので、問題なく上記手順を試せると思いますので、宜しくお願いします。2016年9月29日16時ごろ〜10月2日3時ごろまで誤ったgitファイルがアップロードされており正しく動作できない状態となっておりました。現在は正しいファイルになっておりますので5分で構築可能です。
</font>