OmniAICreator/Qiita-1.07M huggingface dataset:
DockerfileのCMDとENTRYPOINTの書式について

## この記事で書いたこと
- 以下の自分なりの解釈です
  - Dockerfileの
      - CMDとENTRYPOINTの挙動について
      - 書式の違いによる挙動の違いについて

---

# DockerfileのCMDとENTRYPOINTの挙動について
- 公式ページを読むと書いてあります
  - [Dockerfile reference](https://docs.docker.com/engine/reference/builder/#usage)
  - [Best practices for writing Dockerfiles](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)

## 自分なりの解釈
### ENTRYPOINT
- `docker container run`した時に実行するバイナリやコマンドを指定するよ
- 一応`--entrypoint`上書きできるよ(けどしない方向で！)

### CMD
- 単体で使うと`docker container run`した時にバイナリやコマンド実行するよ
- ENTRYPOINTと併用するときは、ENTRYPOINTの引数指定になるよ
- `docker container run`した時に上書きできるよ(ENTRYPOINTの引数として使うときでも)

---

# 書式の違いでの挙動について
- @hihihiroro さんがまとめてくれてました！
  - [[docker] CMD とENTRYPOINT の違いを試してみた](https://qiita.com/hihihiroro/items/d7ceaadc9340a4dbeb8f)

## 自分なりの解釈
- `自分なりの解釈`と書いていますが、@hihihiroro さんの記事から得た知見や、[インフラ勉強会](https://wiki.infra-workshop.tech/)やtwitterで助言頂いた結果のまとめです。

### exec形式(推奨)とshell形式の差
- exec形式
  - 引数で渡された配列が「コマンド」「引数」に分割され`init`から実行される
- shell形式
  - 引数で渡されたコマンドがそのまま文字列として `/bin/sh -c`から実行される
  - `docker stop <container>`からSIGTERMを受信しない

## shell形式が`/bin/sh -c`で実行される理由(推測)
- **推測です**
  - `ENTRYPOINT [command] [param1] [param2]`の形式だと、`スペース区切りの引数`なのか`スペース区切りのファイル名`なのか、などの判別処理が必要となる。
    - 判別処理をdocker側でやるのではなく、``/bin/sh -c``側にやらせるために`/bin/sh -c`で実行されるのではないか
  - `ENTRYPOINT ["executable", "param1", "param2"]`の形式だと明確にコマンドと引数がわかる

---

## まとめ
- ENTRYPOINT/CMDの使い方は、単体/併用で変わる
- ENTRYPOINT/CMDは`shell形式`でなく、`exec form形式`が良い


## Special Thanks
- @hihihiroroさん
- [インフラ勉強会](https://wiki.infra-workshop.tech/)で一緒に検証したり助言をくれた cutlerさん
- twitterで助言をくれた @nntsugu さん
妻のSwift奮闘記#1

[前回の記事](https://qiita.com/masa0208/items/6c49e59aec7a4ca25e27)で妻がSwift Playgroundsを始めたことを書いたが、その続き。
どうやらforループの練習が出てきたようだ。これは難しいだろう。
まず繰り返し変数の「i」が何なのかわからなかったみたい。そりゃそうだ、だってその練習ではスコープ内で「i」を使わないんだもの。いったいなんなのこれ状態。というか、ずっとfuncの練習が続いていたからおそらくfuncとforを同レベルの何かに考えていたようだ。
なんかforを難しく考えすぎているような気がしたので、「吹き出しかっこ内の処理を繰り返してくれる便利な書き方だよ」とか「forはfuncの中に入れてもいいんだよ」とか、説明すると納得した様子。
しばらく試行錯誤の上、無事クリアしたのでさすがー！と思ってコードを見てみると大爆笑。

```swift:妻のplaygrounds.swift
func someMethod()
{

 for i in 1...1
 {
  //クソ長い処理、これでキャラクターはゴールに到達。
 }

}
 someMethod()

```
**ループしてないやん！！**


・・・妻の戦いは続く。

<img width="1366" alt="My Sketches - 2018-05-06 14.02.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/245086/fd023800-1f9f-c932-2c54-708b242497d3.png">



Swift Playgrounds
https://www.apple.com/jp/swift/playgrounds/
"debconf: delaying package configuration, since apt-utils is not installed"を表示しないようにする

Dockerイメージをビルドするときに`RUN apt-get`するステップでタイトルにある警告が表示される。
何かが遅れるだけ(?)で害はなさそうだが、目立つのでなんとか表示しないようにできないか、調べた。

メッセージを見て、先にapt-utilsをインストールしてやればよいのかと思い試したが、このパッケージ自体のインストール時に警告が表示されてしまう。しかも以下のような別の警告も表示されるようになった。

```bash
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin: 
```

[ここ](http://maku77.github.io/docker/term-error.html)を見つけ、以下のように環境変数を設定すればこの警告は表示されなくなった。

```bash
ENV DEBIAN_FRONTEND noninteractive
``` 

元々気になっていた警告を表示しなくするために、何かしらの環境変数が効くのではと思い、`debconf environment variables`で検索したら[ubuntu manuals](http://manpages.ubuntu.com/manpages/xenial/man7/debconf.7.html)がヒットした。参考にして、以下の設定をしたら当初の警告も表示されなくなった。

```bash
ENV DEBCONF_NOWARNINGS yes
``` 

apt-utilsをインストールしなくても警告が表示されなくなったので、Dockerイメージを少しでも小さくするためにインストールの対象から除いた。

今回のもの以外に、知らないうちに表示されなくなる警告があるのだろうが、、、、まあいいや。
DynamoDB StreamをトリガーにしてLambdaを実行する際にストリーム開始位置「水平トリム」を使うと書き込みキャパシティが大変なことになる件

## DynamoDB Streamとは

DynamoDB Streamは、DynamoDBに対する書込みをイベントトリガーとして利用できる機能です。つまりは特定のDynamoDBテーブルに書き込み（追加、変更、削除）があった場合にイベントが飛んでくるので、それをトリガーとしてLambdaを起動したりできます。使い方の概要このあたりが参考になると思います。

[DynamoDB StreamをトリガーにしてLambdaを実行する](https://qiita.com/Fujimon_fn/items/1f18360ee9ebf6832617)

## やりたかったこと

AWS IoT Core経由でRaspberry Piから飛んでくるセンサーデータを、DynamoDBテーブル(A)に格納しているのですが、このままでは比較的粒度が大きいので、Kibanaとかで可視化しやすいように、Lambdaで細かくバラして別テーブル(B)に格納したかったのです。

![Untitled (2).png](https://qiita-image-store.s3.amazonaws.com/0/7519/eed7c462-d3e2-492c-2e17-ccf7e59888d4.png)

定期バッチ処理なども検討しましたが、取りこぼしなく処理することを考えるのが面倒なので、DynamoDB Streamがうってつけでした。

## とんでもないキャパシティが要求された

テーブル(A)のストリームイベントをトリガーにLambdaを起動し、加工したデータをテーブル(B)に投入したところ、事件が起こりました。Auto Scalingを利用していたのですが、みるみるうちに容量がうなぎ登りとなり、**キャパシティが5,000を超えてしまいました！**見積額が月額$2,000越え！(涙)

## 原因は「水平トリム」の利用だった

どう考えても机上の計算をかるく5倍は上回りそうなので悩みましたが、原因はこれでした。

LambdaのトリガーにDynamoDB Streamを設定する際に「開始位置」というのを指定しますが、「水平トリム」と「最新」が選択できて、デフォルトは「最新」です。

![Lambda Management Console.png](https://qiita-image-store.s3.amazonaws.com/0/7519/41605c7e-6be9-036d-f9d7-873bac71b6f7.png)

本家のドキュメントが非常に分かりにくいのですが、「最新」はストリームの新しい方を優先して処理、「水平トリム」は古い方から時系列順に処理するということのようです（この辺はもっと詳しい方がいたら教えてください）。

センサーデータは24時間常時飛んでくるので、時系列順に処理した方が良いだろうと「何となく」思ってしまった自分は「水平トリム」を選択しました。

問題の原因を探るべく、書き込み側のテーブルBを確認したところ、なんと**1日前のデータが投入されているではないですか！**

自分はてっきりトリガーを購読した時点からのデータがストリームで飛んでくるのかと思ったら、なんと24時間も前のデータから飛んできているようでした。そこから最新のデータに追いつくべく、**超高速でストリームイベントが飛んでくる**ので、それを書き込む側のテーブルのキャパシティがすごいことになってしまったと言うことでしょうか。

その後、開始位置を「最新」にしたトリガーを作り直して設定したところ、キャパシティは一気に400程度まで落ちてくれました。（途中ゼロになったりしたところは、トリガーを一時的に無効にしたり試行錯誤をした形跡）

![DynamoDB · AWS Console.png](https://qiita-image-store.s3.amazonaws.com/0/7519/34516e36-3b64-2407-c15a-c283fae54243.png)

まぁ、「水平トリム」のままでも、そのまましばらく放置すれば、いずれは最新データに追いついて、その時にはキャパシティは落ち着くとは思うのですが、[こういう](https://www.hands-lab.com/tech/entry/1592.html)問題もあるみたいなので、一時的にでも不必要にキャパシティを上げるのは望ましくはないとは思います。

[DynamoDBのパーティション分割問題について](https://www.hands-lab.com/tech/entry/1592.html)

いろいろ調べると、DynamoDB Streamは内部的に24時間分のデータを保持しているようなのですね。開始位置を「最新」のままで使った場合には、恐らく過去のデータは捨てられると思いますが、今回は今現在から以降のデータが取れれば良かったので、めでたく解決です。いや、焦りました！

よほど過去の更新データ（といっても最大24時間ですが）が重要な場合以外は「水平トリム」は使わないのが無難かもしれませんね。
pip install時のエラー対処

#MacのPython3でpip install python-aimlをしようとしたら"unsupported locale setting"エラーが出たので、その対処方法のメモにゃ。

##stackoverflowに答えがあったよー
[pip install - locale.Error: unsupported locale setting](https://stackoverflow.com/questions/36394101/pip-install-locale-error-unsupported-locale-setting)

その通りに$ export LC_ALL=Cを実行したら直った・・よくわからないけどいつか分かるといいな。
anacondaの中にpython3がインストールされてるからそのせいかと思って、python3を一度アンインストールしようかと思ったけど関係なかったみたい、、
【SQL】EXISTS述語の使い方 覚書きの箇条書き

#はじめに
[達人に学ぶSQL徹底指南書](http://www.shoeisha.co.jp/book/detail/9784798115160)の 「1-8 EXISTS述語の使い方」がとても勉強になったので頭を整理するため重要だと思ったことの覚書を箇条書きにする。

#覚書の箇条書き
1.EXSITSは「量化(quanification)」という述語論理の機能を実現する。
2．述語は戻り値が真理値となる関数
3.戻り値は（true,false,unknown）のいずれか※SQLは3値論理
4．データベースは、実はデータではなく文を集めたものと言える。
５.WHERE句は、述語を組み合わせて一つの述語を作っていると見なせる。
6.WHERE句の戻り値が真になる命題のみが、テーブル(命題集合)から選択される。
7.EXISTSの特異性は入力レベルにあり。「＝」や「BETWEEN」などの単一の値、スカラ値を入力とする述語を「一階の述語」EXISTSのように行の「集合」を入力とする述語を「二階の述語」と言う。出力は、どちらも真理値。
８．EXISTSは高階関数と行って良い。
９.全称量子化と存在量子化は、片方が定義できれば、もう片方をそれによって表現できる(同値変形の規則 a.k.a ド・モルガンの法則)
１０.存在量子化→EXISTS 全称量子化→NOT EXISTS
C言語の知識に囚われたC#コードを改善する 第一弾

# きっかけ
最近読んだコードが ~~クソ~~ 伸び代だらけで、 ~~ムシャクシャていた~~ 仏の気持ちになったので書きました。

C言語の知識しかない状態で C# を書くと大勢の人が似たようなコードに行き着いてしまうと思います。

そこで、どう書くと C# らしくなるのかを自分なりにまとめていきます。


# 関連記事一覧

第一弾（本記事）
[第二弾](https://qiita.com/gaya_K/items/63cbf249887cb0d43100)

# 直したいポイント
## 命名規則
命名規則はプロジェクトで定められたものに従うのが勿論ですが、言語としての推奨があるので意識してほしいですよね。
[名前付けのガイドライン - Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/standard/design-guidelines/naming-guidelines)

Qiita にも記事がありました。
[C# CODING GUIDELINES @Ted-HM](https://qiita.com/Ted-HM/items/67eddbe36b88bf2d441d)

特に気になってしまうのは以下の2点でしょう。

```csharp
// スネークケースは推奨されていない。
public const int HOGE_HOGE = 1;

// ハンガリアン記法も過去のもの。
public int iHoge { get; set; }
public string strHoge { get; set; }
```

特に命名規則において .NET のクラスライブラリは最大のお手本ですので、自身が書いたコードと見比べてみるのがいいと思います。
（VisualStudio でクラス等にカーソルをあわせて、F12 を押しましょう！）

## 配列の呪縛  その1

```csharp
public void Fuga(string[] args)
{
  for (int i = 0; i < args.Length; i++)
  {
    // args[i] に何か処理。
  }
}
```

このコードは間違いではないですが、以下のデメリットがあります。

- インデックサ `args[i]` の部分は些細なミスで例外を引き起こす。
- 引数が配列型に固定されている。

なので、このように変更します。

```csharp
public void Hoge(IEnumerable<string> args)
{
  foreach (var item in args)
  {
    // item に何か処理。
  }
}
```
このコードでは、 for -> foreach の変更以外に、引数の型が IEnumerable\<string\> に変化しました。

単なる foreach で済むメソッドであれば、この様な引数を定義するのがベストです。
そうすると、以下の様に1つのメソッドで様々な型の引数を受け取れる汎用性が獲得できるのです！

```csharp
// どれもエラーにならない！
Hoge(new string[] { });
Hoge(new List<string>());
Hoge(new Collection<string>());
```

これにはインターフェイスが関連しているのですが、ここを理解できれば C# のレベルがグッと上がります。
（欲を言えば Linq を扱えるまでレベルアップしてほしい。）

## 配列の呪縛 その2

メソッドの戻り値やプロパティ等でも配列を使いがちです。
そして、こんなコードを書いてしまいます。

```csharp
public string[] Fuga()
{
  var list = new List<string>();
  // あれこれ list.Add() する処理
  return list.ToArray();
}
```

[前述の呪縛 その1](#配列の呪縛-その1) で引数が配列になっているため、それに合わせる為だというのが理由の一つだと思います。

しかし、それがすでに解決済みならば List\<string\> を直接 return でき、 ToArray() による無駄なオブジェクトの生成を減らすことができます。

さらに戻り値の型を IReadOnlyList\<string\> や IEnumerable\<string\> に変える事で、メソッドの外で Add() 等の変更が不可能になり、意図しないミスを防ぐ事ができます。

```csharp
public IReadOnlyList<string> Fuga()
{
  var list = new List<string>();
  // あれこれ list.Add() する処理
  return list;
}
```

```csharp
var fuga = Fuga();

// 読み出しはできる
foreach (var item in fuga) { }
var tmp = fuga[0];

// 書き込みはできない
// コンパイルエラー
fuga.Add("");
fuga[0] = "";
```

# おまけ

foreach 可能で readonly なインターフェイスを以下にまとめました。
用途に合わせて必要十分なインターフェイスを選定してください。
（もちろんすべて配列と互換があります。）

|インターフェイス名 |foreach|サイズ (int Count(){get;})|インデックサ (T this[int]{get;})|
|:--|:--:|:--:|:--:|
|IEnumerable\<T\> |○|×|×|
|IReadOnlyCollection\<T\> |○|○|×|
|IReadOnlyList\<T\> |○|○|○|
(個人的に)忘れがちなEmmetコマンド備忘録

#背景
エディタとしてEmmetをインストールしたSublime Textを使用中。
Emmetコマンド毎回調べてるので個人的なメモにまとめることにしました。

##HTML記述編

###複数のクラスを持たせる

```
.container.text-center

→ <div class="container text-center"></div>
```

###複数のidやclassを持たせる

```
#app.container

→ <div id="app" class="container"></div>
```

##CSS記述編

随時更新中...
サーバー仮想化技術の基礎

## はじめに
Kubernetes（k8s）が注目され始めていますが、それに伴いDockerのようなコンテナ型仮想化ソフトウェアにも注目が集まっています。本記事では、Kubernetes、Dockerって聞いたことあるけど、「そもそも仮想化って何？」ということについて簡単にまとめてみたいと思います。

## サーバー仮想化とは
1台の物理サーバーを複数の仮想的なサーバーに分割して利用する仕組みのことです。それぞれの仮想サーバーで個別にOSやアプリケーションを実行することが可能で、独立したサーバー環境として利用することができます。

## サーバー仮想化の手法
主に3種類の仮想化手法が存在します。
以下で1つずつ見ていきますが、サーバー仮想化の説明をするにあたり、「ホストOS」と「ゲストOS」という概念の理解が必要になってきますので、簡単に説明します。

### ホストOS
仮想環境の土台となるOSを意味します。これは言い換えると「物理サーバーにインストールされたOS」ということになります。

### ゲストOS
仮想環境上にインストールされたOSを意味します。

それでは、これらの概念を押さえたうえで1つずつ見てきましょう。

### 1. ホスト型仮想化
![a.png](https://qiita-image-store.s3.amazonaws.com/0/23101/f0bd2751-52e4-0f3e-9c0e-30cb4083ddf6.png)

ハードウェア上にホストOSをインストールした上で、その上に仮想化ソフトウェアをインストールします。この仮想化ソフトウェアによってサーバーハードウェアをエミュレーションすることで仮想サーバーを実現するのがホスト型仮想化です。
ホスト型仮想化のメリットは、仮想化ソフトウェアをインストールするだけで仮想サーバー環境が構築できるという手軽さです。そのため、開発環境の構築などによく使われます。ただし、ソフトウェア的にサーバーハードウェアをエミュレートするため、どうしても仮想化のオーバーヘッドが大きくなります（言い換えると、仮想サーバーを動かすためにホストOS自体の処理も必要になるため全体として処理速度が出にくいです）。
なお、ホスト型の仮想化ソフトウェアには、Oracle社の「Oracle VM VirtualBox」やVMware社の「VMware Workstation Player」等があります。

### 2. ハイパーバイザー型仮想化
![aaa.png](https://qiita-image-store.s3.amazonaws.com/0/23101/45f10efc-aa83-8b52-9024-6d1a80359ed9.png)

ハイパーバイザーというハードウェアが持つ仮想化支援機能と連携してサーバー仮想化を実現するのがハイパーバイザー型仮想化です。ハイパーバイザーはOSよりも上位の層からプログラムを実行するので、仮想化を実現するためのOSを必要としません。
ハイパーバイザー型仮想化のメリットは、ハイパーバイザーがハードウェアを直接制御するため、リソースを効率よく利用できるところにあります（言い換えると、仮想サーバーを動かすためにホストOSを必要としないので、ゲストOSの動作速度の低下を最小限に抑えられます）。
なお、ハイパーバイザー型仮想化ソフトウェアには、Citrix社の「XenServer」やMicrosoft社の「Hyper-V」等があります。

### 3. コンテナ型仮想化
![ss.png](https://qiita-image-store.s3.amazonaws.com/0/23101/d6a2609b-219e-ab36-4f0b-d95374435ec0.png)

冒頭でも述べましたが、近年主流となってきている仮想化技術です。ホスト型仮想化とハイパーバイザー型仮想化は、どちらも仮想的なサーバー環境を作り出してその中でゲストOSを稼働していました。そのため、仮想サーバーごとに完全に独立したゲストOSを実行することができます。ただし、これらの方式はハードウェア（CPU、メモリ、ハードディスク等）の割り当てをソフトウェアで代行するので、どうしてもその分のオーバーヘッドが大きくなります。
そこでコンテナ型仮想化です。コンテナ型仮想化では、ハードウェア上で稼働するホストOS上に論理的な区画（コンテナ）を作り、それぞれに独立したOS環境を提供します。実際に動作しているのはあくまで単一のOS(ホストOS）のみですが、アプリケーションの動作に必要なライブラリなどをコンテナ内に閉じ込めることで、あたかも個別のサーバーのように使えるようにします。コンテナ型仮想化はオーバーヘッドが少ないため、軽量で高速に動作します。一つのコンテナはホストOSから見ると一つのプロセスと見なされるので、ホストOS上で動作している他のアプリケーションとリソース（CPU、メモリ等）を共有します。つまり、コンテナをあまりに多く立ち上げすぎると、リソース的な観点から他のアプリケーションにも少なからず影響があることは認識しておく必要があります。
なお、コンテナ型の仮想化ソフトウェアには、Docker Inc.の「Docker」があります。


## 参考
[プログラマのためのGoogle Cloud Platform入門 サービスの全体像からクラウドネイティブアプリケーション構築まで](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEGoogle-Cloud-Platform%E5%85%A5%E9%96%80-%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AE%E5%85%A8%E4%BD%93%E5%83%8F%E3%81%8B%E3%82%89%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%8D%E3%82%A4%E3%83%86%E3%82%A3%E3%83%96%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E6%A7%8B%E7%AF%89%E3%81%BE%E3%81%A7-%E9%98%BF%E4%BD%90/dp/4798137146/ref=sr_1_1?s=books&ie=UTF8&qid=1525520248&sr=1-1&keywords=GCP)
名前空間について

名前空間とはクラスや関数の使える名前の集合を限定し、関数名やクラス名の衝突を防いだり、機能の参照をわかりやすくするための機能。

#名前空間を利用するときのポイント。

名前空間の区切りにはバックスラッシュ(`\`)を使う
名前空間を定義した場合、グローバルな関数やクラスには先頭にバックスラッシュを付け、グローバルな名前空間から参照しなければならない
名前空間における言葉の定義

・非修飾名...名前空間区切りを含まない識別子
・修飾名...名前空間区切りを含む識別子
・完全修飾名...名前空間区切りから始まる識別子

#名前空間の定義

```php
<?php
namespace 名前空間;
namespace 名前空間\サブ名前空間;
```

名前空間の影響受けるのは

・クラス
・関数
・定数

```php
<?php
namespace Project/Module;
class Directory{}   //Project/Moduleクラス
function file () {} //Project/Module関数
```
別の名前空間から参照される場合は、完全修飾名を指定する。

```php
<?php
namespace Other;
require_once 'Project\Module\Directory.php';
$dir1 = new \Project\Module\Directory()
```
#１つのファイルに複数の名前空間を定義する
1つ目はnamespace宣言を複数する方法。

```php
<?php
namespace Project\Module;
namespace Profect\Module1;
```
2つ目は{}で囲う方法。

```php
<?php
namespace Project\Module{

}
namespace Project\Module1{

}
```

#インポートルール

```php
<?php
use \クラス名;
use 名前空間;
use 名前空間 as 別名;
use 名前空間\クラス名;
```

#名前解決
名前空間の影響を受ける、クラス、関数、定数の定義が読み込まれそれが実際に呼び出されるまでには、コンパイル時の変換と、実行時の名前解決という２つのフェーズがある。

コンパイル時には、useキーワードによってインポートされた名前空間やクラス名でスクリプト内で使われているクラスや定数を変換する。
#動的な名前空間の利用
可変変数や可変関数や動的なクラス名など、変数に文字列を代入して動的に利用できたように、名前空間でも同じように動的な名前空間の利用ができる。

文字列の定義にダブルクォートを用いると、`\`はエスケープ文字とみなされてしまうため、`\\`とする必要がある。

シングルクォートで囲う場合で末尾に名前空間区切りが来る場合、末尾のシングルクォートのエスケープと判断されないために`\\`とする必要がある。
Node.jsのSyncは出来る限り使うな！

# はじめに

ノンブロッキングIOをちゃんと理解していないのであれば、Node.jsにあるSyncと付く関数は出来る限り使わない方が良いです。

もちろん、用意されているからには、何かしら有用性はあるため、ちゃんと理解しているのであれば、ガンガン使って良いと思います。

# なぜ使ってはいけないか

JavaScriptはシングルスレッドで動作します。なので、一つずつしか処理は出来ず、同時に複数の処理が実行されることはありません。

Node.jsのfs.readFileSyncのように、「～Sysnc」となっている関数は、同期処理であり、ブロッキングIOです。そのため、fs.readFileSyncでファイルをディスクから読み取っている間もCPUを占有し、他の処理を実行することが出来ません。

ExpressなどのWebアプリケーションは、複数のリクエストを同時に扱う必要があります。なので、fs.readFileSyncでファイルを読み込んでいる間に、他のリクエストが待たされることになります。これがブロッキングIOです。

しかし、fs.readFileという「～Sync」が付いていない関数であれば、ディスクからファイルを読み取っている間は、他のリクエストが処理を行うことが可能となります。これがノンブロッキングIOです。

Webアプリケーション以外（electronなど）であっても、複数処理を同時に実行する場合があるため、fs.readFileSyncではなくfs.readFileを使用した方がよいでしょう。

## サンプル

以下は、ブロッキングIOです。

```javascript
const express = require('express');
const router = express.Router();
const fs = require('fs');

router.get('/', function(req, res, next) {
  const content = fs.readFileSync('./test.txt', 'utf-8');
  res.json({
    result: content
  });
});

module.exports = router;
```

`fs.readFileSync`でファイルを読み込んでいる間は、他の処理が待たされます。

以下は、ノンブロッキングIOです。

```javascript
const express = require('express');
const router = express.Router();
const fs = require('fs');

router.get('/', function(req, res, next) {
  fs.readFile('./test.txt', 'utf-8', (err, content) => {
    res.json({
      result: content
    });
  });
});

module.exports = router;
```

`fs.readFile`でファイルを読み込んでいる間は、CPUを占有しないため、他の処理が実行可能となります。

# 最後に

`fs.readFileSync`の方が読み込んだ内容が戻り値で取得できるため、コールバックで取得する`fs.readFile`と比べて簡単です。そのため、よくわかっていない人は、すぐに`fs.readFileSync`を使ってしまいます。~~しかし、ブロッキングIOであるべき処理というのは、私の経験上あまり出会ったことはありません。（ブロッキングIOでも問題ない処理はあります。）~~なので、あくまでも私の考えですが、「～Sync」は使用しないで、できる限り「～Sync」が付いてない関数を使用した方がよいと思います。
KotlinをCLIから試す

IDEを使わず、kotlinのシンタックスを確認するために、最小構成でKotlinを書くためのメモ。

## Kotlinをインストール
kotlinが入っていない場合はインストール

```
❯ brew update
❯ brew install kotlin
```

## コードを書く

```
❯ cat hello.kt
fun main(args: Array<String>) {
    println("Hello, World!")
}
```

## コンパイル

```
❯ kotlinc hello.kt -include-runtime -d hello.jar
❯ ll
total 1712
-rw-r--r--  1 nakayama  staff   849K  5  5 20:58 hello.jar
-rw-r--r--  1 nakayama  staff    64B  5  5 20:57 hello.kt
```

## 実行
```
❯ java -jar hello.jar

Hello, World!
```

## 参考
https://kotlinlang.org/docs/tutorials/command-line.html
【iosアプリ開発メモ】カメラを起動させる

#すること
ボタンを押すとカメラが起動する

#環境

- macOS High Sierra バージョン 10.13.4
- Xcode version 9.3
- swift4

#やってみる

##1.ボタンを設置する
Main.storybordのViewの中にbuttonを設置する

##2.ボタンとコードを関連付ける

1. Main.storybordに設置したbuttonを選択。
2. Controlキーを押しながらドラッグして、
ViewController.swiftのViewControllerクラスの中で離す。
3. ConnectionはドロップダウンからActionを選択。<br>
Nameに任意の名前を入力。今回は「camera」にする。<br>
TypeはドロップダウンからUIButtonを選択。
4. @IBAction func camera(_ sender: UIButton)のような関数が作成されたらOK。

##3.コードを書いていく
さっき作られた関数の中にコードを書いていく。

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    //↓追記した部分
    //対応したボタンが押された時の動作を記述
    @IBAction func camera(_ sender: UIButton) {
        //インスタンス作成
        let pickerController = UIImagePickerController()
        
        //ソースタイプを指定(cameraの場合はplistでカメラ使用を許可すること)
        pickerController.sourceType = .camera
        
        //カメラを表示
        present(pickerController, animated: true, completion: nil)
        
    }

}
```

コードを書いたらplistでカメラの使用を許可しておく。

#ポイント

##UIImagePickerController

UIKitに入ってるクラス。
>ユーザーのメディアライブラリから画像を撮影し、ムービーを記録し、アイテムを選択するためのシステムインタフェースを管理するビューコントローラ。(公式より翻訳)

##UIImagePickerControllerSourceType

UIImagePickerControllerインスタンスのプロパティ
>Pickerインターフェイスを実行する前に、この値を目的のソースタイプに設定します。設定するソースタイプは使用可能でなければならず、そうでない場合は例外がスローされます。ピッカーが表示されているときにこのプロパティを変更すると、このプロパティの新しい値と一致するようにピッカーインターフェイスが変更されます。(公式より翻訳)

##present

UIViewControllerクラスのインスタンスメソッド。
第一引数に指定したViewControllerを表示してくれる。

#終わり
以上、とりあえず起動だけ。
jQuery 拡張子の無い画像ファイルを表示させる

画像ファイルを拡張子無しで格納する、簡易画像アップローダーで、
アイコン画像のアップロード後にデータベースに以下のような情報を格納できるようにしてみました。

```javascript:JSONデータ定義
[
    {
	"badge_id": 27,
	"badge_name": "おめでとう", //タイトル
	"file_name": "おめでとう.svg", //アップロードファイル名
	"img_path": "d9c5f2a7e5f24a31b3d10a785", //格納ファイル名
	"mtype": "image/svg+xml", //MIME-Type
	"file_size": 8192,
	"upd_date": "2018-04-28"
    }
]
```

拡張子無しでもブラウザのURLバーに直リンを入れると表示できるので、試しに&lt;img&gt;タグで表示させてみましたが、拡張子無しの画像は表示できませんでした。

どうやら&lt;img&gt;タグで表示させるにはMIME-Typeを関連付けしてデータの判別ができるようにしなければならないようです。

そこでひと手間かけます。
**``XMLHttpRequest()``**でファイルを動的にロードし、MIME-Typeを付与してから**``URL.createObjectURL()``**を使って一時的なURLを作り出します。

```javascript:コード
$("document").ready( function() {
	//データベースからファイル情報を読み込む
	$.ajax({ 'url': "../json/get_badge.cgi", 'type': "post"})
	.done(function(data){
		var objBadges = JSON.parse(data); //JSONをパース
		var baseUrl = "../img/badge/"; //画像ファイルのベースディレクトリ
		for(var i=0; i<objBadges.length; i++){
			//ファイルをXHRでロード
			var xhr = new XMLHttpRequest();
			xhr.open('GET', baseUrl + objBadges[i].img_path);
			xhr.responseType = "arraybuffer";
			xhr.json = objBadges[i]; //イベント内で参照できるようにオブジェクトにJSONデータを添付
			xhr.onload = function() {
				//ファイルのロード完了したらBlobURL化("blob:http://～～～")
				var blob_url = URL.createObjectURL(
					new Blob([new Uint8Array(this.response)], {
                        'type': this.json.mtype //MIME-Typeを付与
                    })
				);
				$("<img/>", {
					'src': blob_url, //BlobURLをソースにセット
					'class': "badges",
					'alt': this.json.badge_name,    //
					'badge_id': this.json.badge_id, // あとで使いやすいように要素に情報を入れておく
					'filename': this.json.file_name //
				}).on('load', function() {
					URL.revokeObjectURL(blob_url); //表示されブラウザがキャッシュしたらURLオブジェクトを破棄する
				}).appendTo(".flame")
			};
			xhr.send();
		}
	});
});
```

追記:
画像を使い回すとなるとタグにURL直打ちが不便なので&lt;div&gt;タグにしてしまい、CSSで画像IDごとにbackground-imageを定義してみました。

```javascript:divタグに変更
//<head>セクションに<style>を挿入しておく
$("<style/>", {
	'type': 'text/css',
	'id': 'badge_img_style'
}).appendTo("head");

//～～～～中略～～～～～～

	$("<div/>", {
		'class': "badges",
		'badge_id': this.json.badge_id //画像IDのみに変更
	}).on('load', function() {
		URL.revokeObjectURL(blob_url); //表示が完了したら破棄する
	}).appendTo(".flame");

	//CSSを動的に定義
	$("#badge_img_style").append(
		".badges[badge_id='" + this.json.badge_id + "']{background-image: url(" + blob_url + ")}"
	);
```

CSSで使えるようになればロード時に画像を表示させる必要はなくなるので&lt;div&gt;の挿入は、任意のイベントで追加できるのですが、**``URL.revokeObjectURL()``**を呼ばなければならないため、何かしらの``onload``イベントを呼ぶ要素が必要になるのが悩みどころ。
【React Navigation】タブとヘッダーの削除方法

## 概要

React NavigationはReact Nativeのナビゲーションライブラリで現在1番スター数が多いライブラリです。
今回、React Navigationの実装中に躓いたところを自分用にメモします。
本題はタイトルの通りなのですが、まずはReact Navigationの使い方を簡単にまとめます。

[React Navigationドキュメントはこちら](https://reactnavigation.org/)

## React Navigationのインストール

```
npm install react-navigation
yarn add react-navigation
```

## 主要コンポーネント

主要コンポーネントは以下の2つです。

- StackNavigator
- TabNavigator


## StackNavigator

StackNavigatorは名前の通り、各コンポーネントをStackします。

```
const Navigation = StackNavigator({
  Page1: { screen: Page1Component },
  Page2: { screen: Page2Component },
  Page3: { screen: Page3Component },
  Page4: { screen: Page4Component },
  });
```

図で表現するとこんな感じです。

![スクリーンショット 2018-05-05 19.11.55.png](https://qiita-image-store.s3.amazonaws.com/0/153954/42976972-5df5-030c-f8d7-7611a3a56cac.png "スクリーンショット 2018-05-05 19.11.55.png")

###### ポイント
- StackNavigatorでラップされているコンポーネントはnavigation(メソッドやstateが入ったオブジェクト)というpropsが渡される
- navigation.navigate("Page1")とすると、Page1Componentが現在のコンポーネントの上に積まれる
- navigation.goBack()とすると、1つ前のコンポーネントへと画面遷移する

###### 実際のコード例

```Page2Component
// navigate()メソッドの例
<TouchableOpacity 
	onPress={() => props.navigation.navigate('Page1')}
>
	<Text>ページ1へ移動</Text>
</TouchableOpacity>

// goback()メソッドの例
<TouchableOpacity 
	onPress={() => props.navigation.goback()}
>
	<Text>1つ前の画面へ移動</Text>
</TouchableOpacity>
```

## TabNavigator

TabNavigatorは名前の通り、Tabで各コンポーネントを表示します。

```
const Navigation = TabNavigator({
  Page5: { screen: Page5Component },
  Page6: { screen: Page6Component },
  Page7: { screen: Page7Component },
});
```

###### 参考動画
https://gyazo.com/2be7a793fc072f497da2768a13cf1877

###### ポイント
- StackNavigatorと同様、TabNavigatorでラップされているコンポーネントはnavigationというpropsが渡される
- 画面遷移はタブをタップすることでできる
- navigation.navigateメソッドを用いなくても画面遷移できる


## 本題①：タブの削除

TabNavigatorをStackNavigatorの中に入れるとタブを削除することができます。

```
// TabNavigatorを定義する。
const TabNavigatorComponent = TabNavigator({
  Page5: { screen: Page5Component },
  Page6: { screen: Page6Component },
  Page7: { screen: Page7Component },
});

// StackNavigatorの中にTabNavigatorを入れる
const Navigation = StackNavigator({
  Tab: { screen: TabNavigatorComponent }, //ここにTabNavigatorを入れる!!
  Page1: { screen: Page1Component },
});
```

###### 参考動画
https://gyazo.com/66bb49b4d7117ed5dc29158df854388a

###### ポイント
- TabNavigatorの上に他のページが積み上がるので、他のページでタブを覆い隠すことができる

## 本題②： ヘッダーの削除

Header部分を削除するには以下のように実装します。

```
Page1: { screen: Page1Component,
		 {navigationOptions: () => ({
		   header: null
    	 }), 
    	},
```

###### ポイント
- navigationOptionsに`header: null`と設定するとヘッダーを削除することができる。
- 公式ドキュメントには`headerMode: 'none'`と設定するとヘッダーを削除することができると書いていたが、現時点では削除できないので注意。
- `title: 'タイトル'`と設定すると、ヘッダー部分に文字を表示させることができる。

## まとめ

React Navigationで直感的に画面遷移ができるようになりました。navigationOptionsにはもっと他の設定があるので、もっと使いこなしていきたいです。
(GAS)スプレッドシートに記録した排泄記録をSlackにポストする

## 排泄記録スプレッドシート
[Google Homeに話しかけて娘のおむつ交換を記録する](https://qiita.com/rechiba3/items/ef163b0fc21b37e869ef)という記事に触発されて、去年の１２月くらいから３０近い無職のおじさんの排泄記録を取っていました。
<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">赤ちゃんのオムツ交換記録記事を見て29歳無職の排泄記録を取るデバイスを稼働させてるけど捗るぞ <a href="https://t.co/eYU8O2wfIP">pic.twitter.com/eYU8O2wfIP</a></p>&mdash; たねのぶ (@mtane0412) <a href="https://twitter.com/mtane0412/status/938955101246328833?ref_src=twsrc%5Etfw">December 8, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

家でGoogleに「オーケーGoogle!うんち！」と叫ぶのがすっかり学習されてしまい、出先の何もないところで突然Googleを呼び出してしまうという不具合もありましたが、ともかく記録する動作にかかるコストがほぼないので継続が容易で今日まで続けてこれています。(出先だとApple WatchのIFTTTから記録できるのですが、そもそも外に出る機会が少ないのでこちらはまだ習慣化あまりできてないです。)

最近行った改良で良かったのはGoogleHomeのレスポンスを「うんちを記録しました」から「えらいねぇ！」に変えたところです。肛門期のトイレットトレーニングのように、うんちするたびに自己肯定感を高めることができます。

排泄データを取っているのもいつか活用したいなあと思っていたので、今回は個人Slackに１日の排泄記録を報告して褒めてくれる感じにしたいと思います。

## GASでスプレッドシートのデータから本日の排泄物を集計
JavaScriptあんまり触ったことないのですが、とりあえずGASで実装してみました。

[GASでSpreadsheetを操作する自分的ベストプラクティス](https://qiita.com/ryan5500/items/e72eb205fbe006c2eb6f)によると、APIアクセスをできるだけ減らすためにシート全体のデータを取得してからJSであれこれいじるほうが良いみたいです。

```javascript

  var sheet = SpreadsheetApp.getActiveSheet(); // 現在開いているシートを取得
  var today = new Date(); // 実行時の日付を取得
  var DateColumn = 0; // シートの日付列
  var ExcretionColumn = 2; // 排泄物カラム
  var data = sheet.getDataRange().getValues(); // シート全体のデータを取得
  var unchi = 0; // うんちカウンタ初期化
  var oshikko = 0; // おしっこカウンタ初期化
  
  // dataから今日の排泄物をカウント
  for (var i = 1; i < data.length; i++) {
    if (data[i][DateColumn].getMonth() === today.getMonth() && data[i][DateColumn].getDate() === today.getDate() && data[i][DateColumn].getFullYear() === today.getFullYear()) {
      if (data[i][ExcretionColumn] == "👼") {
        oshikko++;
      } else if(data[i][ExcretionColumn] == "💩"){
        unchi++;
      } else {
        Logger.log("Error");
      }
    }
  }
  
```

JavaScriptの日付の比較の方法、もっとスマートな方法がありそうなものなのですが、とりあえずこれで…。

## SlackのWebhookからポスト
GASからSlackにポストするのはWebhookが一番簡単そうだったのでとりあえず使ってみます。[GoogleSpreadSheetの内容をSlackで自動投稿する](http://www.minemura-coffee.com/entry/2016/06/15/070611)を参考にさせていただきました。

```javascript
  // Slack Webhook
  var url = 'SlackのWebhook URL';
  var payload = {
    'text'      : "今日は" + oshikko + "回おしっこして、" + unchi + "回うんちできたね。えらいねぇ",
  };
  var options = {
    'method'      : 'post'                 ,
    'contentType' : 'application/json'     ,
    'payload'     : JSON.stringify(payload),
  };
  UrlFetchApp.fetch(url, options);
```
試しに実行してみます。

<img width="423" alt="Screenshot 2018-05-05 19.48.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/65966/ec181409-b332-73a5-3b7d-b9a0163e1196.png">

いけました。あとはイベントハンドラで定時実行するようにすればOKですね。

## todo

- より詳細な記録の方法ができないか考える(うんちの色、硬さ、おしっこの量とか。ヘルスケアデータっぽく)
- スプレッドシートをjsonで出力(今回はGAS側で実装したけど、slackbotの方でやりたい)
- 報告の褒め方を色々工夫。(前回のデータと比べるとか)
- データビジュアライズしたい(D3.jsとか、slackにイメージポストするのとか)
VS Code1.23の新機能 - マルチルートでのターミナル分割時のフォルダ指定

# Visual Studio Code 1.23の新機能
## マルチルートでのターミナル分割時のフォルダ指定

https://code.visualstudio.com/updates/v1_23#_multiroot-support-for-terminal-splitting

マルチルートワークスペースでの統合ターミナルで、**ターミナルの分割**を行った際の初期フォルダを選択できるようになった。今までは、アクティブなエディタが属しているフォルダのルートが初期フォルダになっていた。

![split_terminal.gif](https://qiita-image-store.s3.amazonaws.com/0/181011/b7242e6e-35c8-cc28-1506-5150e4d4aa28.gif)

今までと同じ挙動でターミナルの分割を行いたい場合は、コマンド「**ターミナル: (アクティブなワークスペースで)ターミナルの分割**」を呼び出すか、このコマンドのキーボードショートカットを登録して使用する。
RubyOnRailsのタグ機能を応用した少し便利なトップページ

#前説
初めまして、Rubyもう2ヶ月経っていた初心者です。
以前、タグ機能実装の話をさせていただきました。それから色々といじっていたので、ここで報告しようかと思います。完全に僕が考え抜いて実装した機能なので、親心が芽生えます。
他タグに関する内容は[こちら](https://qiita.com/networkyohan69/items/3f154be24ac87a07e65b)。

#実装した機能

マイページ編集にて登録したタグを、タイムラインで自動で表示させて、そのタグの検索結果を非同期で閲覧できる機能。

多分意味がわかんねえという方に動画でお教えします。

![gif_tag.gif](https://qiita-image-store.s3.amazonaws.com/0/253129/a141f5f6-e72a-d886-2e17-35c578db5504.gif)


#マイページでは以下のようにタグを登録できます。

![IMG_6226.JPG](https://qiita-image-store.s3.amazonaws.com/0/253129/5c13ead6-7e56-ae99-8588-0349b98d743a.jpeg)


```ruby:products_controller.rb
  def index
   #標準タグの時のツイートを探し出す
    @products = Product.order("created_at DESC").page(params[:page]).per(10)
    if user_signed_in?

    #create時にいいねを生成するインスタンス
    @likes = Like.new(user_id: current_user.id, product_id: params[:product_id])

    #destroy時にいいねをテーブルから探し出す
    @like = Like.find_by(user_id: current_user.id)

   #ここから大事
   #@tag -> ユーザーの持つタグ情報
    @tag =  User.find(current_user.id).tag_list
   #配列を用意
    @tag_products = []
   #一つずつタグ情報に関連するツイートを探し出す
      @tag.each do |a_tag|
        @tag_products << Product.tagged_with(a_tag)
      end
    end
  end
```

上記はコントローラーのコードです。
結局、@tag_productsには固有のタグ情報を持つツイート達が入ってます。


```html:index.html.erb
 <% if user_signed_in? %>
   <% split_number = 12 / (@tag.count+1) %>
     <% @tag.each do |tag| %>
     <% @tag_number = @tag.index("#{tag}").to_i %>
     <li class="tab col s<%= split_number %>"><a href="#test<%= @tag_number + 2 %>"><%= tag %></a></li>
      <% end %>
     <li class="tab col s<%= split_number %>"><a class="active"  href="#test1">標準</a></li>
<% end %>
```

上記のコードでは、上の切り替えタブが登録したタグの数に応じて、幅が合うようにコードを書きました。

```html:index.html.erb
 <% n = 2 %>
 <% @tag_products.each do |a_tag| %>
   <div class="page" id ="test<%= n %>">
   <%= render 'products/index_to_product' , products: a_tag %>
   <% n += 1 %>
   </div>
 <% end %>
```

上記のコードでは、中身の応じてタグの検索結果とそのツイート内容が表示されるように書きました。ここが、当初うまくいかず、ツイートのタグと検索内容が相違が生じていました。
nを使ったり、あまり綺麗なコードではないなと個人的に思っているので、まさかりなどあれば・・・。
test1は標準タブなので、タグ検索タブはtest2~となります。そのため、nは2が初期値となっています。

#終わりに
アルゴリズムを少し考えるのに苦戦したので、Rubyをもう少し書けるようにしないといけないなと思いました。
PhpStromでVue.jsのコンポーネント書く時に「XML tag has empty body・・」のエラーが出る件への対応

##　現象

PhpStromでVue.jsのコンポーネント書くと以下のようなエラーが出る。

<img width="374" alt="スクリーンショット 2018-05-05 19.26.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/831475d4-a6e5-2b5b-1c3e-f991230bd4a3.png">

これはうざい。非常にうざい。

## 対策

PhpStrom > Preferebces > Editor > Inspactions　と辿っていくと以下のような画面が出る。

<img width="1038" alt="スクリーンショット 2018-05-05 19.27.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/9ca5f3ec-9f68-ac5d-d193-0610726ed288.png">

上記の`XML tag has empty body`のチェックを外し「Apply」 > 「OK」をクリック。
するとどうだろう。
見事エラーが消えたでは無いか。

<img width="291" alt="スクリーンショット 2018-05-05 19.29.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/121811/540f6ce0-deae-1512-8987-a308841f918e.png">

ウェイ！

(参考)
https://youtrack.jetbrains.com/issue/WEB-31042
gem (Rubygems) のコマンドまとめ

```bash:Gemfileコマンド
gem install             インストール
gem search -r           バージョン検索
gem update              アップデート
gem list                インストールリストの表示
gem cleanup             消去（最新バージョンは残る）
gem uninstall           アンインストール

ちなみにrails4をアンインストールしたけどなぜかrails -vで4が返ってくるんですけどって時には
railsコマンドのバージョンを戻すためにgem uninstall railtiesを試してみるとよいです


railsコマンドのバージョンを戻したい
http://qiita.com/fukajun/items/0fa7699beabba6f8b720


gem env                 バージョン確認
gem help                コマンドのヘルプ
gem build               gemspecからgemをつくる
gem cert                サインの必要な証明のRubyGemsを管理する 
gem check               インストールされたgemをチェックする
gem cleanup             ローカルリポジトリの中にインストールされたgemの古いバージョンを除去する
gem contents            インストールされたgemのコンテンツを表示する
gem dependency          インストールしたgemの依存を示す
gem environment         RubyGemsの環境に関する情報を表示する
gem fetch               gemをダウンロードし、現在のディレクトリに置く
gem generate_index      gemのサーバーディレクトリ向けのインデックスファイルを生成する
gem help                'gem'コマンドにヘルプを与える
gem install             ローカルリポジトリにgemをインストールする
gem list                一続きで始まる名前のgemを表示する
gem lock                gemのロックダウンリストを生成する
gem mirror              gemの倉庫を写す
gem outdated            アップデートが必要な全てのgemを表示する
gem pristine            gemの隠し場所にあるファイルからインストールしたgemを初期状態へ戻す
gem query               特定の標準に合うgemを質問する
gem rdoc                プリインストールされたgemのRDocを生成する
gem search              一続きを含む名前の全てのgemを表示する
gem server              Documentation and gem repository HTTP server
gem sources             gemを検索するために使われているRubyGemsのソースとキャッシュファイルを管理する
gem specification       (yamlで)gemの詳細を表示する
gem uninstall           ローカルリポジトリからgemをアンインストールする
gem unpack              現在のディレクトリにインストールされたgemを解凍する
gem update              ローカルリポジトリで指定されたgem(あるいはインストール済の全てのgem)をアップデートする
gem which               ライブラリの場所を探す
```
zabbixの公式Dockerコンテナを使って、zabbixサーバーを爆速で立てる(ver.3.4)

## 公式dockerコンテナを使ってserverを構築する

現在公式の手順でzabbixを立てる方法は三つあります

* ソース(tar.gz)を落としてきて、インストール
* それぞれのOSのdistributionを落としてきて、インストール
* Dockerコンテナから作成

はじめ、ソース(tar.gz)を落としてきて、インストールしてみましたがなかなか苦戦してしまったので、
dockerコンテナで作成してみたところ驚くほど簡単でした。

https://www.zabbix.com/documentation/3.4/manual/installation/containers

## docker インストール

dockerコンテナを利用するので、当たり前ですがdockerが必要です。
以下の手順通りに作成すれば、大体上手くいきます。
https://docs.docker.com/install/linux/docker-ce/ubuntu/

## docker コンテナ作成

mysql serverの作成

```
docker run --name mysql-server -t \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix_pwd" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      -d mysql:5.7 \
      --character-set-server=utf8 --collation-server=utf8_bin
```

java gatewayの作成

```
docker run --name zabbix-java-gateway -t \
      -d zabbix/zabbix-java-gateway:alpine-3.4-latest
```

zabbix serverの作成

```
docker run --name zabbix-server-mysql -t \
      -e DB_SERVER_HOST="mysql-server" \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix_pwd" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      -e ZBX_JAVAGATEWAY="zabbix-java-gateway" \
      --link mysql-server:mysql \
      --link zabbix-java-gateway:zabbix-java-gateway \
      -p 10051:10051 \
      -d zabbix/zabbix-server-mysql:alpine-3.4-latest
```

nginxの作成

```
docker run --name zabbix-web-nginx-mysql -t \
      -e DB_SERVER_HOST="mysql-server" \
      -e MYSQL_DATABASE="zabbix" \
      -e MYSQL_USER="zabbix" \
      -e MYSQL_PASSWORD="zabbix_pwd" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      --link mysql-server:mysql \
      --link zabbix-server-mysql:zabbix-server \
      -p 80:80 \
      -d zabbix/zabbix-web-nginx-mysql:alpine-3.4-latest
```
nginxのポートフォワード設定が`-p 80:80`になっているので `http://docker-ip`でhttp接続してみました


![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/114135/a53aeacd-c0b8-4630-df0b-6790f5bbf4ea.png)

zabbixのログイン画面が表示されました。これは簡単ですね



ちなみに初期パスワードは user:`Admin` pass:`zabbix`になります。上記の引数の`MYSQL_USER`などはMysql上に作成されるユーザなので少し注意が必要
https://www.zabbix.com/documentation/3.4/manual/quickstart/login

## docker compose も用意してあるよ

複数のコンテナを作成してあるので、composeが欲しくなるところ。
もちろん用意してあります。
https://github.com/zabbix/zabbix-docker

構築まで五分もかからず完了してしまいました。さくっと試してみたい時はかなりおすすめです
【AWS】初心者がAWSでセキュアな構成を考える-Part1-【EC2・VPC・Peering】

# はじめに
社会人なりたてのエンジニアです。学生時代はデータサイエンスに取り組み、趣味でweb開発をしていたのですが、業務ではクラウド系のインフラに取り組むことになりました。

ここ最近の学びを整理するついでに覚え書きしておこうと思います。主に既出の内容ですが、今までAWSなんとなく使ってる方やAWS始めたい方の手助けになる記事になればと思います。

# ゴール
AWSを使ってインフラ構築して、簡単なブラウザアプリケーションを展開する。
※アプリケーションに関しては、詳しくは書きません。

# 設計
インフラ構築する上で設計図を用意しておきます。自分もなんですが、学生のころはとりあえず「EC2をたてる！」なんてこと多いかと思います。最初に設計図を作ると作業がスムーズになるかと思います。

## 設計図
とりあえず、こんな感じで想定します。

![test.jpg](https://qiita-image-store.s3.amazonaws.com/0/148317/3f281df3-33e5-f1b0-7c5a-540871ec6144.jpeg)

抜けてるIPらへんはElasticIPをアタッチしたときに追記します。
MySQLの接続ポートなんだっけ、、笑

## ポイント
① 固定IPをもつのは踏み台サーバー(rep_EC2)とポートフォワーディングサーバー(pf_EC2)のみ
② WEBサーバー(front_EC2)とAPサーバー(server_EC2,db_instace)の役割をもつVPCはインターネットから分離する
③ VPC同士をピアリング接続
④ 各EC2にフローログを設定

それぞれの意図を説明していきます。

### ① 固定IPをもつEC2をしぼる
固定IPをもつということは、それだけ狙われやすいサーバーだと思います。なので、できるだけ情報を持たないサーバーにすべきかと考え以下のようにしました。
運用者側からは、rep_EC2を踏み台サーバーとして各サーバーにアクセスできる形をとりました。
ユーザー側からアクセスできるEC2はpf_EC2のみにしました。このpf_EC2をポートフォワーディングさせることでwebサーバーにアクセスできる仕組みにします。

### ② 主要サーバーはインターネットから分離
上記とほぼ同様なのですが、インターネットとの接続があると攻撃の対象になると考えました。なのでインターネットとの接続を絶ちました(具体的には、ルートテーブルからインターネットゲートウェイを外す)。これで少しは安全度が増すのかなと。

### ③ VPC同士をピアリング
これは②を適用すると取らざる得ない選択肢なのかなと思うんですが、異なるVPCに属するEC2同士で疎通するためにピアリング接続をしました。ざっくり言うと、インターネットを介さずに疎通が取れるって感じですかね。

このピアリング接続は、今回の大きな学びの一つでした。学生時代は単語すら聞いたことなかったです。

### ④ 各EC2にフローログを設定
フローログは、設定したEC2への接続をログとして吐き出してくれます。これによって、見覚えないアクセスなどを把握することができます。

これも今回初めて設定してみたんですけど、特に固定IPもってるEC2(Ex.踏み台サーバー)には知らないIPからかなりアクセスがきていることがわかりました。

# まとめ
こんなところポイントとして構成を考えてみました。クラウドやセキュリティに関してはホントに初心者なんで、「こんなんでセキュアって言えるの」みたいな意見があるかと思います。コメントにて優しくご教授していただけるとありがたいです。


ただ、数ヶ月前まで学生として趣味でいじっていた自分のような方には参考、、までとは言いませんがアプローチ(インターネットからの分離,ピアリング接続,フローログなど)があるということ知ってもらえると嬉しいです。

# おわりに
とりあえず、インフラの設計とセキュアにするためアプローチをまとめてみました。

次は実際に構築していきます。
異なるVPCでPublicIP持っていないのに疎通が取れるピアリング接続(自分的には感動しましたw)やフローログの設定などもまとめたいと思っています。
ACID特性についての解説

# 概要
ACID特性とは、信頼性のあるデータベースにおけるトランザクション(データのやり取り)の持つべき性質をまとめたものです。ACIDとは、それら性質の頭文字をとったものです。
データベースを実際に作る時に最低限知っておくべき知識なので、しっかりインプットしておきたい概念です。


# 項目について
- Atomicity(原子性)
トランザクションに含まれる一連の処理は、全体として実行されるか、実行されないかのいずれかであることが保証されるという性質。
何らかの障害により処理が途中で止まってしまった場合、処理途中のデータを格納するのではなく、処理を実行していない状態を維持するということ。

- Consistency(一貫性)
あらかじめ指定したルールに沿った形で処理が行われるという性質。
例えば、あるカラムに対してuniqueという条件を指定した場合に、そのカラム内で重複しないことを保証するもの。

- Isolation(独立性)
ある処理について、外部から見ることができるのは実行前と実行後のデータだけであり、実行中のデータの状態を見ることができないという性質。

- Durability(永続性)
ある処理が完了した段階で、その出力結果は永続的に失われることのないものとしてデータベースに記録されるという性質。
rubyでクラスマクロを作った

#rubyでクラスマクロを作った

##環境
ruby 2.4.1

##概要
また、メタプログラミングです。
attr_accessorのようなクラスマクロを[メタプログラミングRuby 第２版](https://www.amazon.co.jp/%E3%83%A1%E3%82%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0Ruby-%E7%AC%AC2%E7%89%88-Paolo-Perrotta/dp/4873117437)を見ながらrubyで組んだので、それの備忘録です。

### クラスマクロとは
attr_accsessorのようなキーワードに見えるクラスメソッドの事です。
下に使用例を書きました。

```ruby
class MyClass
  attr_accessor :test1
end

obj = MyClass.new
obj.test1 = "hoge"
puts obj.test1
```

```text:出力
hoge
```

### 今回作成したクラスマクロ
attr_accessorはC言語でコーディングされていますが、今回はrubyで書いて
それに、ランダム性を持たせたattr_randomというクラスマクロを作成しました。

メタプログラミングの復習に良かったです。

### ソースコード
```ruby
module RandomAttributes
  def self.included(klass)
    klass.extend ClassMethods
  end

  module ClassMethods
   def attr_random(attribute)
       define_method "#{attribute}=" do |value|
         return false  if value.nil?
         return false  unless value.kind_of?(String)

         rand_val = value.split("").sort_by!{rand}
         instance_variable_set("@#{attribute}", rand_val.join)
       end

       define_method "#{attribute}" do
          instance_variable_get "@#{attribute}"
       end
    end
  end
end

class MyClass
  include RandomAttributes
  attr_random :test1
  attr_random :test2
  attr_random :test3
end

def check_attr_random
  obj = MyClass.new
  name = ["Tarou", "Saburou", "Kotarou"]
  obj.methods.grep(/test.*=/).each_with_index do |t, i|
    obj.send(t, name[i])
  end

  obj.methods.grep(/test[1-3]$/).each_with_index do |t, i|
    puts obj.send(t)
  end
end

check_attr_random
```

```text:出力
Troua
oaruubS
uaKroto
```
※ ランダムなので出力は実行ごとに変わるので注意してください。

### 最後に
個人的に復習できたポイントについてまとめます。

- self.includedによるフック処理
- obj.sendによる動的メソッド実行
- メソッドを定義するメソッドの書き方
- クラスマクロの作成の仕方
CAP理論についてのまとめ

# はじめに
現在はクラウドサーバーなどの分散システムを前提とした設計が主流になっており、データや処理を別々のサーバーに保持するという流れがあります。

そうした分散システムを設計する際に必ずと言っていいほど話に出てくるのがCAP理論です。

# CAP理論とは
CAP理論とは、分散システムはConsistency（一貫性） 、Availability（可用性）、Tolerance to network Paritions（分断耐性）の3つの保証のうち、同時に2つを満たすことはできるが、全てを満たすことはできないとするものです。以下それぞれの項目について書いていきます。

- Consistency: 一貫性

　最新のデータを読み込むことができるという特性です。

- Availability: 可用性

　必ずデータにアクセスできるという特性です。

- Tolerance to network Paritions: 分断耐性

　何らかの障害により通信が分断されたとしても、データにアクセスできるという特性です。

 

これだけだと少し抽象的でわかりにくいので、銀行の口座情報を例にして１つ１つの項目について考えてみましょう。



例えばAさんが自分の口座からBさんの口座へ5万円の振り込みをしたいとします。

ここではわかりやすいように、AさんとBさんの口座には10万円が入っていることとします。
 
さて、AさんはBさんへ5万円振り込みました。そしてBさんへ連絡をします。

Aさん「5万円振り込んでおいたよ」

Bさん「ありがとう！確認するね」

そして、Bさんはすぐさま口座を確認してみました。すると、本来送られた後には15万円であるはずのBさんの口座には10万円しかありません。

このように、最新の情報を受け取れない状態のことを「一貫性がない」、と言います。

一方で、最新の情報ではないものの、口座情報にはアクセスすることはできています。この状態は、「可用性がある」状態と言えます。


では、もしBさんが口座情報を確認しようとした際に、何も情報を得ることができなかったらどうでしょう。

この場合、通信に何らかの不具合があってデータベースの情報にアクセスできていない可能性があります。これは、「分断耐性がない」システムであると言えます。

 

# 本当にトレードオフ？
さて、これら3つの特性を同時に実現することはできるのでしょうか？

常に最新の情報に、通信の障害があったとしても、必ずアクセスできる状態...。

一番最初に述べましたが、CAP理論では3つはトレードオフの存在であり、分散システムにおいて全てを同時に実現することはできないとしています。

 
どういうことなのでしょうか。

大前提としてインターネットサービスを行う事業者にとって、いつでもデータにアクセスできるというのは必須でしょう。先ほどの例のように口座情報を得たいのに、その情報にアクセスできないと言うのはユーザビリティを損ないます。そのため、可用性は必須と言っていいでしょう。

 
可用性を実現させるためには、単一障害点をなくす設計が必要です。

単一障害点とは、ある１つのサーバが何らかの不具合を持った時に、目的のデータにアクセスできなくなってしまう時のサーバのこと（点）を言います。

 
この部分と関連性が強いのが分断耐性です。通信の障害があった場合にもアクセスができるように設計をする必要があります。そのため、ある通信経路が接続不可能になったとしても、別の経路で目的のデータにアクセスすることができるようにします。

 

ただ、上記のように分散システムはデータを別々に保持しているため、通信による遅延などにより必ずしも最新のデータを全てのサーバで持つことができるとは限りません。ここで一貫性が達成できないと言うことになります。

 

# 終わりに
最近ではこのようなトレードオフの関係が必ずしもゼロイチの考え方ではないとして、BASEと言う考え方も出てきています。

これは最終的には全てのデータは一貫性が担保される、と言ったものです。

詳しい内容についてはまた書きたいと思います。
これからEthereumでDApps開発する人にオススメサイト

## 概要
**「Ethereumのスマートコントラクト使ってDApps作りたい！けど、何から始めれば良いの？」**

って人向けに自分が調べて役立ったサイトを整理してみました。

## 初学者向け

##### [Ethereum入門](https://book.ethereum-jp.net/)
ブロックチェーンとEthereumの簡単な説明がまとまっているので一番最初に読んでおくのが良いのかなと思いました。また、**geth** というEthereumのクライアントツールを使ってマイニングや送金の方法を学ぶことができます。 　
  

##### [CryptoZombies | イーサリアムでのゲーム開発を学ぶ](https://cryptozombies.io/jp/)
Ethereumのスマートコントラクトを開発する場合に使用する言語は **Solidity** ですが、そのSolidityを勉強しながら実際にコーディングして学べるサイトです。2018年5月時点では6章までありますがこれから追加されていくようです。さらに、６章まで終わらすと **「10 LOOM」** 報酬が貰えます！ 
今の所初学者に一番オススメしたいサイトです。  
  
##### [Tutorials | Truffle Suite](http://truffleframework.com/tutorials/)
**Truffle** は EthereumのDAppsを爆速で開発するためのフレームワークです。 恐らくEthereum上ではTruffleを使ってDAppsを作ることが大半なのかなと思います。 
そんな Truffleの公式サイトにはチュートリアルがあって、初学者はやっといて損はないと思いました。チュートリアルの中で特にオススメなのが以下の２つです。

* [ETHEREUM PET SHOP - YOUR FIRST DAPP](http://truffleframework.com/tutorials/pet-shop)
スマートコントラクトのテストの仕方から、フロントエンド（JavaScript）からの呼び出し方など一通り経験することが出来ます。 開発者には必須レベルの **Ganache** と **MetaMask** の説明も軽くされています。

* [BUILDING ROBUST SMART CONTRACTS WITH OPENZEPPELIN]
 (http://truffleframework.com/tutorials/robust-smart-contracts-with-openzeppelin)
**openzeppelin** はスマートコントラクトを開発を楽にする便利なライブラリといった感じですが、それを使えば簡単に独自トークンが作れるよといったものです。


## ある程度開発の流れを掴めた人向け
##### [Dapp University - YouTube](https://www.youtube.com/channel/UCY0xL8V6NzzFcwzHCgB8orQ)
EthereumのDAppをライブコーディングするYouTubeチャンネルです。これをタダで観れるのはありがたいです。
私は英語は得意ではないですが、ライブコーディングの動画なので観ていると大体何しているのか分かりました。あとはYouTubeの字幕機能を使うとか。
オススメの動画は下のもので簡単な投票システムをライブコーディングしています。（２時間と結構長いです）

* [How to Build Ethereum Dapp (Decentralized Application Development Tutorial)](https://www.youtube.com/watch?v=3681ZYbDSSk)

##### [Ethereum 開発者向けコミュニティを作ったよ - Qiita](https://qiita.com/amachino/items/605ff76209d7193dc92c)
**Hi-Ether** は日本のDApp開発者が集まったコミュニティです。過去ログを漁るだけでも勉強になります。気軽に質問も出来そうな雰囲気でとっても良いです。これからDApp作るのであればコミュニティに入っておいて損はないと思います。
コミュニティに入るには「Test Network に 1.0 ETH 持っていること」が条件ですが、私は **MetaMask** を使って簡単に1.0ETH集めることができました！

##### [blockchain.tokyoの資料一覧](https://blockchain-tokyo.connpass.com/presentation/)
blockchain.tokyoは毎月東京で行われているブロックチェーンの技術セミナーです。LTで発表された資料がここで拝見することができます。内容を見ているとレベル高いなぁという印象（汗）

## さらに上を目指す人向け
##### [ALISのICOについての技術的FAQ](https://medium.com/@alismedia/alis%E3%81%AEico%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%AE%E6%8A%80%E8%A1%93%E7%9A%84faq-61028da1d8bd)
[ALIS](https://alismedia.jp/ja/index.html) は現在(2018.5)、クローズドβでDAppサービスを展開しています。日本においてはICO等を含めて先駆者的な存在でしょうか。そんなALISのCTOである石井さんが先駆者ならではの有益なノウハウを発信しています。読んで分かりますが、セキュリティ等含め、品質がとにかく大事なことが書かれています。これからICOしたり、世にDAppサービスを出したいと考えている人は目を通すことをオススメしたいです。

##### [Ethereum Contract セキュリティ・テクニック＆Tips](https://github.com/sot528/smart-contract-best-practices/blob/master/README-ja.md)
こちらのサイトは先ほど紹介したALISの記事にも「優良なドキュメント」と書かれていますが、コーディングする上でのベストプラクティスや、セキュリティ等について纏まっています。サービスを出す前に理解する必要があるなと思いました。内容は理解するのがとても難しいのでただいま勉強中です。。。


## さいごに
「ここのサイト良いよ！」ってがあったら是非教えてください。
これで DApp に興味持った人が増えると嬉しいです！
あと、このページも随時更新していきたいと思います。
CentOS7.4にGitLab CE 10.7.3の環境を構築する

﻿# CentOS7.4にGitLab CE 10.7.3の環境を構築する


## 事前準備

以下の記事手順に従って、事前にCentOS7.4の環境が構築済みであること。
[Vagrant2.0.3を使ったCentOS7.4の環境構築](https://qiita.com/You_name_is_YU/items/1bdf36270e9f594d1c7e)

また、ホスト名の設定が下記のようになっていること。
またホスト名で名前解決ができる状態であること。

```shell
hostname
gitlab-hostname
```


## GitLabの環境構築

### GitLabの環境構築をする各環境情報

|＃|ソフトウェア|バージョン|
|:--|:--|:--|
|1|GitLab CE|10.7.3|
|2|OS|CentOS 7.4|

### GitLabインストール前の準備

#### 依存関係のモジュールをインストール

```shell
sudo yum install -y curl policycoreutils-python openssh-server
```

#### sshdを自動起動にしてスタート

```shell
sudo systemctl enable sshd
sudo systemctl start sshd
```

#### ファイアウォールを自動起動にしてhttpポートを開ける

```shell
sudo systemctl enable firewalld
sudo systemctl start firewalld
sudo firewall-cmd --permanent --add-service=http
sudo systemctl reload firewalld
```

#### メース転送ソフトウェアのpostfixをセットアップ

```shell
sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix
```

### GitLab CE(Community Edition)のシェルスクリプトダウンロード及びリポジトリのセットアップ

```shell
cd /usr/local/src
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
```

### GitLab CEのインストール

`EXTERNAL_URL`の`gitlab-hostname`の部分は、任意のホスト名やドメイン名を環境に合わせて変更し、コマンドを実行する。
この`EXTERNAL_URL`は、GitLabからユーザーがcloneする際、正しいURLを生成するために必要な設定のようです。
参考：https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab

```shell
sudo EXTERNAL_URL="http://gitlab-hostname" yum install -y gitlab-ce
```

### GitLabの変更を反映

念のため設定を反映するためにreconfigureを実行します。
GitLabインストール完了時に`gitlab Reconfigured!`というメッセージが出力されているため、たぶんこの手順はいらないのかもしれませんが。。。

```shell
sudo gitlab-ctl reconfigure
```

### GitLabにアクセス確認

以下のURLにアクセスしてGitLabのログイン画面が表示されることを確認。
http://gitlab-hostname

`Change your password`と、管理アカウント``のパスワードを変更するように求められるので、任意のパスワードを入力して変更する。

その後、ログイン画面で`root`/`変更したパスワード`でログインできれば環境構築完了。

## その他

### GitLab Web IDE

GitLab10.7のバージョンから、CEでWebIDEが一般公開されています。
GitLab上でコードの編集ができる機能のようです。

![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/246556/d0123ca2-81ae-9e4f-b65d-bd3a6eabfcc4.png)
MMDモーショントレース自動化への挑戦【序章】

# MMDモーショントレースとは

> MMDモーショントレースとは、動画(映像)から、人物または物体の動作(モーション)をMikumikuDance用にMMDデータ化することである。

[MMDモーショントレースとは - ニコニコ大百科](http://dic.nicovideo.jp/a/mmdモーショントレース)

基本的には、動画から人物等の動きを目視で真似て、フレーム登録をしていきます。
Kinectによるモーショントレースも可能ですが、こちらは道具が色々と必要になります。
目視トレースは、ひたすら**地道**にやるしかありません。(色々TIPSはありますが)
特に体幹のトレースは地味に難しいです。
その辺をもう少し楽にできないかなー、というのが今回の発端です。

# プロモーション動画

[![MMDモーショントレース自動化への挑戦](http://img.youtube.com/vi/1V_IWbYUe3I/0.jpg)](https://www.youtube.com/watch?v=1V_IWbYUe3I)

# 自動化手順

1. 素材となる動画を30fpsで用意する
1. `OpenPose` で二次元の人物骨格データを取得する
1. `3d-pose-baseline-vmd` で二次元から三次元の人物関節データに変換し、関節データファイルを生成する
1. `VMD-3d-pose-baseline-multi` で関節データファイルを読み込み、vmd(MMDモーションデータ)ファイルを生成する
1. 生成したvmdファイルをMMDでモデルに読み込む

# 使用技術概要

## [OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose)

> OpenPose represents the first real-time multi-person system to jointly detect human body, hand, and facial keypoints (in total 130 keypoints) on single images.

画像から人体の骨格を検出するアルゴリズム。複数人数の検知や動画からの検知も可能。

- [OpenPoseを動かしてみた。 - Qiita](https://qiita.com/nnn112358/items/a4490d85dac5827db53b)

## [3d-pose-baseline](https://github.com/una-dinosauria/3d-pose-baseline)

> We provide a strong baseline for 3d human pose estimation that also sheds light on the challenges of current approaches. Our model is lightweight and we strive to make our code transparent, compact, and easy-to-understand.

2Dの人体モデルから3Dの人体モデルを生成するアルゴリズム

## [ArashHosseini/3d-pose-baseline](https://github.com/ArashHosseini/3d-pose-baseline)

`3d-pose-baseline` から fork されたプログラム。
`OpenPose` で検出された人体の骨格構造から、3Dの人体モデルを生成する。

## [miu200521358/3d-pose-baseline-vmd](https://github.com/miu200521358/3d-pose-baseline-vmd)

`ArashHosseini/3d-pose-baseline` から私がforkし、改造したプログラム。

### 改造点

 - 学習データのパスがWindowsだと260文字制限に引っかかるので、パス簡略化
 - 3Dの人体モデルを生成する際に、関節データを出力する
 - 複数人数のOpenPoseデータを解析できるよう改造
    - 正確には、解析対象人物Indexを指定できるように改造

## [VMD-Lifting](https://github.com/errno-mmd/VMD-Lifting)

[VMD-Lifting がやっていること - Qiita](https://qiita.com/errno_mmd/items/44a7aedfeb853307e443)

> 写真から人のポーズを推定し、VMDフォーマットのモーション(ポーズ)データを出力するプログラムです。 ポーズ推定には Lifting from the Deep (https://github.com/DenisTome/Lifting-from-the-Deep-release) のプログラムを使用しています。

このプログラムが公開されていなければ、自動化はできませんでした。多謝。

## [miu200521358/VMD-3d-pose-baseline-multi](https://github.com/miu200521358/VMD-3d-pose-baseline-multi)

`VMD-Lifting` から私がforkし、改造したプログラム。

### 改造点

 - `3d-pose-baseline-vmd` の出力パスを引数にできるよう変更
 - 複数フレームの出力に対応

# 導入手順

[【目次】MMDモーショントレース自動化への挑戦](https://qiita.com/miu200521358/items/d826e9d70853728abc51) から各ページをご参照ください。

# 今後の予定

- センターを移動させたい
    - 左足と右足の角度から求められそうな…
- 前傾姿勢になるのを直したい
    - Lifting と計算式が違うためか、全体的にX軸方向に20度ほど前傾姿勢になってしまうのを直したい
- 足首を接地させたい
    - 理論的には、地面と膝以下のベクトルの交差で求められる気がする…
- フレームの間引き
    - 一定距離範囲内の移動であれば、そのフレームを登録しないで間引きしたい
- 首の回転
    - 現在、頭のみの回転になっているが、これを首と頭に分散させたい（トレーサーとしての好みです）
- 足をIK化
    - その方が汎用的だしモーション修正もやりやすいと思うんだけど、計算式がさっぱり
- 指のモーショントレース自動化
    - 3d-pose-baseline の指版が出来ないと無理かなぁ…

# 共同開発者募集中！

Twitter\([@miu200521358](https://twitter.com/miu200521358)\)よりお気軽にご連絡ください。