OmniAICreator/Qiita-1.07M huggingface dataset:
[Three.js] ボーンアニメーションやモーフアニメーションをするメッシュの頂点座標を取得する

[Stack Overflowで質問した](https://stackoverflow.com/questions/50964972)ところ、素晴らしい回答を[gman](https://stackoverflow.com/users/128511/gman)氏から頂けたので転載する。
ちなみにStack Overflow上のコードは特段の記述が無い限り、[CC BY-SA 3.0でライセンスされる](https://stackoverflow.blog/2009/06/25/attribution-required/)。
gman氏はさらに自身のコードをCC0でライセンスすると明言しているので、この記事にライセンス上の問題は特にない。

# 問題

例えば[この動作サンプル](https://threejs.org/examples/webgl_animation_skinning_morph.html)における剣士メッシュを構成する各頂点の座標を取得するにはどうすればよいか？

# ボーンアニメーションやモーフアニメーションをしないメッシュの頂点座標

まず前提知識として。
こちらは簡単に取得できる。

```js:meshのvertexIndex番目の頂点のローカル座標を取得する
const localPosition = mesh.geometry.vertices[vertexIndex];
```

```js:meshのvertexIndex番目の頂点のグローバル座標を取得する
mesh.updateMatrixWorld();
const globalPosition = mesh.geometry.vertices[vertexIndex].clone();
globalPosition.applyMatrix4(mesh.matrixWorld);
```

先の例の剣士メッシュはボーンアニメーション、モーフアニメーションを行っているのでこの方法では頂点座標を取得できない。
ボーンアニメーションやモーフアニメーションの効果が及ぶ前の頂点座標が取得できるのみである。

# ボーンアニメーションやモーフアニメーションをするメッシュの頂点座標

そもそもの作りとして、Three.jsはJavaScriptのコード中でGLSLのプログラムを自動生成し、描画処理の大半を自動生成したGLSLに任せている。
ボーンアニメーションやモーフアニメーションをするメッシュの頂点座標を計算する処理もGLSLの中で行われており、JavaScript側で計算結果を取得することは原則できない。

そこでgman氏はGLSL中の頂点座標計算処理をJavaScriptに翻訳した。
なお、あらゆるケースで完璧に動く保証まではしないので、うまく動かないケースに当たったら頑張れということである。

```js:meshの頂点の座標を取得する
// 各種パラメータを最新の状態にしておく
mesh.updateMatrixWorld();
mesh.skeleton.update();

// バッファ
const position = new THREE.Vector3();
const transformed = new THREE.Vector3();
const temp1 = new THREE.Vector3();
const tempBoneMatrix = new THREE.Matrix4();
const tempSkinnedVertex = new THREE.Vector3();
const tempSkinned = new THREE.Vector3();

// 頂点座標計算処理
for (let vndx = 0; vndx < mesh.geometry.vertices.length; ++vndx) {
  position.copy(mesh.geometry.vertices[vndx]);
  transformed.copy(position);

  for (let i = 0; i < mesh.geometry.morphTargets.length; ++i) {
    temp1.copy(mesh.geometry.morphTargets[i].vertices[vndx]);
    transformed.add(temp1.sub(position).multiplyScalar(mesh.morphTargetInfluences[i]));
  }

  tempSkinnedVertex.copy(transformed).applyMatrix4(mesh.bindMatrix);
  tempSkinned.set(0, 0, 0);

  const skinIndices = mesh.geometry.skinIndices[vndx];
  const skinWeights = mesh.geometry.skinWeights[vndx];

  for (let i = 0; i < 4; ++i) {
    const boneNdx = skinIndices.getComponent(i);
    const weight = skinWeights.getComponent(i);
    tempBoneMatrix.fromArray(mesh.skeleton.boneMatrices, boneNdx * 16);
    temp1.copy(tempSkinnedVertex);
    tempSkinned.add(temp1.applyMatrix4(tempBoneMatrix).multiplyScalar(weight));
  }

  transformed.copy(tempSkinned).applyMatrix4(mesh.bindMatrixInverse);

  // この時点でのtransformedがmeshのvndx番目の頂点のローカル座標

  transformed.applyMatrix4(mesh.matrixWorld);

  // この時点でのtransformedがmeshのvndx番目の頂点のグローバル座標
}
```

# 動作サンプル

![サンプル](https://qiita-image-store.s3.amazonaws.com/0/106760/f596f5e3-4f0b-f5b8-3f87-2126b05da0ab.gif)

剣士メッシュを構成する各頂点の座標に赤い箱を設置している。
正しく頂点座標を取得できていることが分かる。
ただ、本来GPUでやる処理をCPUでやっているのでカクカクにはなってしまう。

# おまけ: 描画に使われているGLSLのコードの取得方法

ある`material`で描画に使われている頂点シェーダのソースは`renderer.context.getShaderSource(material.program.vertexShader)`、ピクセルシェーダのソースは`renderer.context.getShaderSource(material.program.fragmentShader)`で見れる模様。
ネットワーク知識まとめ

- DNSコンテンツサーバー
問い合わせがあった場合に，名前(Domain)からIPアドレスを発行する(正引き)する機能を持つ．コンテンツを提供する方が持つ．

- DNSキャッシュサーバー
接続するプロバイダがほとんどの場合管理する．依頼に応じて適切なコンテンツサーバーに問い合わせを行い，利用者に返す．再利用できるよう，一定時間キャッシュする．


- ルータが持つ機能
LANとWANの間を取り持つ機能．

 - 端末で指定するDNSサーバー:  DNSキャッシュサーバーへの問い合わせを行うサーバー．複数のDNSキャッシュサーバーを指定可能である．

 - DHCPサーバー: LAN内の接続端末にプライベートIPアドレスを分配するサーバー．

 - NAPT機能: "Network Address Port Translation". グローバルIPアドレスとプライベートIPアドレスを変換する機能

 - PPPoE: IPパケットにユーザー情報を付加する通信プロトコル． 

 - サブネットマスク: IPアドレスと用いることで，ホストアドレスとネットワークアドレスを算出する
AndroidでWifiテザリングが出来ない場合に行いたいこと

# はじめに

この記事は技術的者向けを対象にしています．
テザリングが出来ない理由は様々なので，原因を特定することが大切になります．

これから紹介する方法はadbを使うものもありますので，Android開発者モードを使ったことのある人向けの説明になります．

# 想定環境

インターネット　<=（携帯回線）=>テザリングモードのAndroid（ルーター）<=（Wifi）=>クライアントPC

# インターネットに接続出来ない時に一番初めにやる事
## Wifi接続が成功しているか？

この場合，そもそもテザリングモードがonになっていなかったり，通常のWifiが起動していたりします．
まずはWifiで接続できている事を確認しましょう．


１．　WiFiの電波マークが立っているか？
２．　pingがルーターと通っているか？
``` 
ping (rooter ip adress )
(例えば)
ping 192.168.0.1
```
　などで確認できます．

これが通らなければそもそものテザリング設定自体やクライアント側の設定が問題でしょう．
これくらいならば，割と見直すだけで接続できるようになるかと思います．

クライアント側がPCの場合，Wifiドライバーが問題の場合もあるかと思いますが機種ごとの問題となるので割愛します．Windowsの場合，原因が色々考えられますので・・・・．


#　ルーターには接続OKでも「インターネットがありません」状態

これが厄介なパターンです．なにせ，Android端末の設定が問題の可能性が高いので原因の特定が難しいです．

## ０．大前提：ルーターがインターネットに接続出来るか？ 
ブラウザを開いて適当なページを見てください．出来なければ，そもそもインターネットに繋がっていません．

## １．そのAndroidスマートフォンはドコモ製？
ドコモ製のスマートフォンはMVNOのSIMを使ったときにAPNが変更されテザリングができないです.

設定を書き換えることで可能になるようです．（最近の端末では未検証）
https://hanpenblog.com/67/


## ２．APN設定？
まずは現在使っているAPN以外を全部削除してみてください．
http://www.itmedia.co.jp/mobile/articles/1702/06/news130_3.html
（原因）
Androidシステムでテザリング時に有効でないAPNを読み込んでしまう場合があるようです．


## 3. 　APNのAPNタイプの設定が間違っている
 APNタイプのが次のものが現在は最低限必要のようです．

```
default,supl,dun
```
特にテザリングに重要なのがdunの設定になります．
https://king.mineo.jp/my/3489b0aea3ffa56c/reports/9054


## 4. tether_dun_requiredの設定がnull or 1
Redmi note5ではこの設定が標準ROMでされていないようです．


ADBで次のコマンドを実行して確認して下さい．
(正常時）
```
adb shell settings get global tether_dun_required
0
```
(設定が変更されている時）
```
adb shell settings get global tether_dun_required
null
```
```
adb shell settings get global tether_dun_required
1
```

と表示されます．
特にnullだった場合は０に設定しないとテザリングで通信ができないため次のコマンドを実行します．

```
adb shell settings put global tether_dun_required 0
```
こののちに再起動をするとテザリング通信が可能になる場合があります．


https://forum.xda-developers.com/redmi-note-5-pro/help/tethering-global-rom-9-5-6-0-t3793056
ApacheをupdateしたらInternal Server Errorになった

Apacheをupdateとして2.4.33にしたところ、直後から以下のエラーが画面に表示されてアプリが使えなくなりました。

```
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.
```

どうやら設定ファイルに書式エラーがあったようです。
コメントを非コメント行の後ろに書くのは書式エラーとのこと。
なぜ今まではエラーにならなかったのか。。

https://httpd.apache.org/docs/2.4/en/configuring.html
Syntax of the Configuration Files欄
> Comments may not be included on the same line as a configuration directive.

# 参考リンク
https://ex1.m-yabe.com/archives/2378
jQueryのfindメソッド

子孫要素を取得することができるメソッド

```html
<div id="content">
  <h2>中見出し</h2>
  <p>本文</p>
</div>
```

```js
  var element = $('#content').find('h2');
  console.log(element[0]);
```

以下のように出力

```
<h2>中見出し</h2>
```


## childrenメソッドとの違い

childrenメソッドは一つ下の階層の要素しか取得できない。

## 参考

[jQuery入門】find()で子要素を取得する手法まとめ！]
(https://www.sejuku.net/blog/37474)

[jQueryでfindメソッドを使って子要素を選択する方法【初心者向け】]
(https://techacademy.jp/magazine/9477)
PDFtkで個人的に使うものまとめ

##pdftkとは
pdftkは，TeXwikiによると，
>pdftk は PDF ファイルを編集するコマンドラインツールです． PDF ファイルの結合，分割，並べ替え，ページ回転，ページ抽出，透かしの挿入，メタデータの追加や抽出，セキュリティの設定などが可能です．
>[pdftk - TeX Wiki](https://texwiki.texjp.org/?pdftk)

とある。レポート作成などに（個人的に）使える機能があったため，使ってみる。

##pdftkのインストール
[pdftk](https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/)
↑ここからインストールする。細かい方法は，[pdftk - TeX Wiki](https://texwiki.texjp.org/?pdftk)に書いてある。

##2つのpdfを重ね合わせる
レポートなどで，指定の用紙にtexなどで書いた解答を印刷して提出する際，2回印刷して重ねていたが，その手間を省ける。
コマンドプロンプトで，

```
pdftk in1.pdf multistamp in2.pdf output out.pdf
```
とすれば，指定のディレクトリにin1.pdfとin2.pdfが重ね合わされたout.pdfが出力されている。
Swift4でJSONファイルを簡単に読み込む

JSONファイルを読み込む方法として、swift4から新しくJSONDecoderというクラスができたので使ってみました。

# JSONファイルを用意
サンプルとして以下のJSONファイルを使用しました。文字列、配列、連想配列を格納しました。

``` json
{
    "park":"higashiyama",
    "animals":["cat", "dog", "monkey", "rabbit"],
    "nickname":{"cat":"tama", "monkey":"jiro"}
}
```

# JSONに対応するデータモデルを作成
JSONファイルの形式に合わせてデータモデルを作成します。
ファイル名はanimal.jsonとしました。

``` swift
import Foundation

struct Animal: Codable {
    let park: String
    let animals: [String]
    let nickname: Dictionary<String, String>
}
```

# ファイルからデータを取り出す
JSONファイルはバンドル内にあるとします。
ここは単純なファイル読み込み処理です。

``` swift
    func getJSONData() throws -> Data? {
        guard let path = Bundle.main.path(forResource: "animal", ofType: "json") else { return nil }
        let url = URL(fileURLWithPath: path)
        
        return try Data(contentsOf: url)
    }
```

# JSONを読み込む
JSONファイルのデータをJSONDecoderを使用してデータモデルに当てはめます。

``` swift
        guard let data = try? getJSONData() else { return }
        guard let animals = try? JSONDecoder().decode(Animal.self, from: data!) else { return }
        
        // 以下JSONファイルのデータを出力
        print("\(animals.park) park")
        
        animals.animals.forEach({(animal) in
            print("animal:\(animal)")
        })
        
        animals.nickname.forEach({(animal, nickname) in
            print("\(nickname) は \(animals.park) 公園にいる \(animal) のニックネームです。")
        })
```

# 最後
このようにSwift4では簡単にJSONが扱えることがわかりました。
標準APIでできるようになったのが個人的にはとても嬉しいですね。

# 参考
[How to parse JSON with Swift 4 | Roadfire Software](https://roadfiresoftware.com/2018/02/how-to-parse-json-with-swift-4/)
オフラインリアルタイムどう書く E15 の実装例( Go )

オフラインリアルタイムどう書く E15 の実装例( Go )

問題 : http://nabetani.sakura.ne.jp/hena/orde15nohil/
実装リンク集 : https://qiita.com/Nabetani/items/705fa83cfbf20377b92f

順当に https://qiita.com/Nabetani/items/f516767d63dd7791672a を移植した。

```go:実装
package e15

import (
	"fmt"
	"sort"
	"strconv"
)

type pos struct {
	x, y int
}

func numToPos(num int) pos {
	r := pos{0, 0}
	for w := 1; 0 < num; {
		switch num % 3 {
		case 0:
			// nothing to do here.
		case 1:
			r.x += w
		case 2:
			r.y += w
		}
		num /= 3
		w *= 2
	}
	return r
}

func posToNum(p pos) int {
	if p.x < 0 || p.y < 0 {
		return -1
	}
	if p.x == 0 && p.y == 0 {
		return 0
	}
	if p.x == 1 && p.y == 0 {
		return 1
	}
	if p.x == 0 && p.y == 1 {
		return 2
	}
	if p.x == 1 && p.y == 1 {
		return -1
	}
	a := posToNum(pos{p.x / 2, p.y / 2})
	b := posToNum(pos{p.x & 1, p.y & 1})
	if a < 0 || b < 0 {
		return -1
	}
	return a*3 + b
}

func impl(num int) []int {
	p := numToPos(num)
	neis := []pos{
		pos{p.x, p.y + 1},
		pos{p.x, p.y - 1},
		pos{p.x + 1, p.y},
		pos{p.x - 1, p.y},
	}
	nums := []int{}
	for _, e := range neis {
		n := posToNum(e)
		if 0 <= n {
			nums = append(nums, n)
		}
	}
	return nums
}

func solve(src string) string {
	num64, _ := strconv.ParseInt(src, 10, 32)
	num := int(num64)
	ans := impl(num)
	sort.Sort(sort.IntSlice(ans))
	r := ""
	for _, e := range ans {
		if r != "" {
			r += ","
		}
		r += fmt.Sprintf("%v", e)
	}
	return r
}
```

```go:テスト
package e15

import (
	"testing"
)

func Test(t *testing.T) {
	var tests = []struct {
		name  string
		input string
		want  string
	}{
		{"0", "21", "19,22,23"},
		{"1", "0", "1,2"},
		{"2", "1", "0,3"},
		// 中略
		{"51", "1000000", "999999,1000002"},
	}
	for _, test := range tests {
		got := solve(test.input)
		if got != test.want {
			t.Errorf("%v: solve(%q)=%q, want %q\n", test.name, test.input, got, test.want)
		}
	}
}
```

ruby では「`return [0,1,1i].index(pos) if 1==[x.size, y.size].max`」と一行で書ける式に何行も費やしたのがちょっと悔しい。

今回は `pos` という struct を導入してみたけど、出来合いのそういう struct はあるのだろうか。調べずに書いたけど。

あと。やっぱり Sort がわかりにくいね。
ローカルネットワーク用CMDまとめ

Local Area Networkでの不良の時は，まずルーターとつながるか確認する．その後外部ネットワークとつながるか確認する．DHCPサーバーに機器を登録する場合，pcのmacアドレスが必要になる．

#ルータとの接続確認
1. ping [IPアドレス]
指定したIPアドレスにある機器との接続を確認する．実際に入力するときは[]は不要．
　- ping -4 [IPアドレス] :IP4での返信を強制する

    [帰ってくる返答例]
　- Destination Host unreachable　:IPアドレスが存在しないことを示す．
　- TTL expired in Transit : ルーターのルート選択ミスが示唆される．→tracerootコマンドでルート選択ミスを洗い出す．
　- Unknown  :ホスト名が間違っているため，DNS検索において名前解決に失敗している．
　- timed out: ホストが停止しているか，存在しない．

2. traceroot [IPアドレスorホスト名]
 指定したホストにたどり着くまでに通るルーター名が一覧で表示される．


#ネームサーバーから，アドレスを明らかにする
nslookup [IPアドレスorホスト名]

#PCのmacアドレスを確認する
1. ipconfig
PCのmacアドレスをすべて得るコマンド．
 - ipconfig /all :サブネットマスク，DHCPサーバー,DNSサーバー情報も得ることができる
 - ipconfig /fo csv :CSV形式でデータを吐き出してくれる 

2. getmac
PCのmacアドレスを確認できる,ipconfigに比べて非常に簡素
 - getmac /v : より詳しい情報を得られる
Amazon ElastiCacheにEC2から接続できない → 送信中の暗号化が原因だった

# やりたいこと
- 毎アクセス実行され、かつ同じ結果を返すクエリを発見
- 結果をredisでキャッシュしたろ
- [FuelPHP](http://fuelphp.jp/)のアプリケーションだから、[Redis_Db クラス](http://fuelphp.jp/docs/1.9/classes/redis.html)を使ってredisを操作しよ
- redisは[ElastiCache](https://aws.amazon.com/jp/elasticache/)で用意しよ

# 問題発生
1. ElastiCacheの設定完了
1. アプリから接続してみる→エラーになる:bomb: 
1. 原因究明のためアプリを動かしているEC２からredis-cliで接続してみる
 
```bash
$ redis-cli -h (ElastiCacheエンドポイント) -p 6379
(ElastiCacheエンドポイント)> ping
Error: Connection reset by peer
```

:question::question:接続はできるけど、コマンド実行しようとするとエラーになる:confused::question::question: 　
(当たり前だけど、VPC違いなどで接続できない場合は最初の　`redis-cli -h -p` 時点でエラーになる。)

# 原因判明
ElastiCacheクラスター作成時のオプション「送信中の暗号化」にチェックを入れている場合は、[SDK](https://aws.amazon.com/jp/tools/#sdk)からじゃないと操作できないらしい。
▼参考
https://forums.aws.amazon.com/thread.jspa?threadID=160851#jive-message-832075
> Please could you confirm if redis encryption in-transit is not enabled for your cluster. If it is enabled, then you would be unable to connect using redis-cli as it does not support SSL encryption. The only way to connect in redis with in-transit encyption enabled is using a SDK. 

「送信中の暗号化」チェックを外したクラスターを作成したら接続できました :thumbsup: 

2019/12/03 更新:
redis-cli経由で接続したい場合はstunnelを経由すれば良い。
▼参考
https://aws.amazon.com/jp/premiumsupport/knowledge-center/elasticache-connect-redis-node/
スピリチュアルエンジニアリングで処理速度高速化を狙ってみた

# はじめに  
- この記事を真に受けないでください。
- この記事は個人の感想であり、効果・効能を示すものではありません。
- 苦情は郵便でのみ受け付けます。

# 背景 
世の中にサービスを提供する者として処理速度の高速化は非常に重要な課題です。
単純に処理速度を速くしたいのであれば、マシンパワーを強くすれば解決することができますが、サービスとして採算が取れなくなってしまうためなかなかそうするわけにもいきません。
そこで、コードを上手に書くことによって処理速度の高速化を狙うことにします。
また、今回は例として用いやすいソートを題材とします。

# 解決策
スピリチュアルプログラミングの考えを導入し、プログラムの高速化を狙うこととします。

## 言語の選択
後述の施策を取るためにJavaを選択します。

## ソートアルゴリズムの選択
スピリチュアルプログラミングの考え方を持ってすれば、どんなコードでも爆速になることは自明ですので、
ソートのアルゴリズムは最良計算時間が低いボゴソートを用います。

## スピリチュアルみを感じる施策(独自の解釈を含んでいます)
コメントを記述するときは`//`ではなく`/* */`で囲みます。後者は対になる要素ですので狛犬っぽさが有って非常に縁起が良さそうなためです。
セミコロン(`;`)は「終わり」を意味し非常に縁起が悪いため取り払います。
実行する前には必ず祈ります。
仏滅は避けます。

# 結果
爆速になりました。(個人の感想です。)
また、ここで実行の時間を測ってしまうと、
プログラムに疑いの目を向けることとなりプログラムが機嫌を損ねて実行速度が落ちる原因になるので絶対に測ってはいけません。
コードは以下のとおりです。もし、もっとスピリチュアルみを増せるのであればどんどん書き換えてくださって構いません。
(その際は、プログラムへの感謝と信頼を欠かさず書き換えてください。機嫌を損ねます。)
対照実験をしていないのもこのプログラムを信用しているためです。
 
```Java
/* スピリチュアルプログラミングに相性の良さそうなボゴソートを「終わり」を表して縁起の悪そうなセミコロンを取り払って書いて見たやつ */
/* これでO(n)でソートできる確率が上がった気がする */
/* コメントを//ではなく対になる要素で挟むことでより縁起がよくなりそう！(狛犬的な) */
public class Bogo {
    public static void main(String... args) throws Exception {
        /* ラムダ式内にはthrows Exceptionが効かないため */
        for (java.util.ArrayList<Integer> data : new java.util.ArrayList[]{new java.util.ArrayList(java.util.Arrays.asList(1, 3, 2, 4, 0))}) {
            while (true) {
                /* ソート済みかどうか調べる */
                if (java.util.stream.IntStream.range(1, data.size())
                        .mapToObj(i -> data.get(i - 1) > data.get(i))
                        .noneMatch(b -> b)) {
                    /* ソート済みなら表示 */
                    if (java.util.stream.Stream.of(
                            data.stream()
                                    .map(String::valueOf)
                                    .collect(java.util.stream.Collectors.joining(", "))
                    )
                            .peek(System.out::println)
                            .count() == 0) {
                    }

                    if (System.class.getDeclaredMethod("exit", int.class).invoke(null, 0) == null) {
                    }
                } else {
                    /* ソート済みではない */
                    if (java.util.stream.Stream.of(new java.util.Random(System.currentTimeMillis()))
                            .peek(rand -> java.util.stream.Stream.of(rand.nextInt(data.size()))
                                    .forEach(n -> java.util.stream.Stream.of(rand.nextInt(data.size()))
                                            .forEach(m -> java.util.Collections.swap(data, n, m))))
                            .count() == 0) {
                    }
                }
            }
        }

    }
}
```

# よくありそうなツッコミ
## Kotlinで良いのでは？
うん

# 参考文献
http://blog.mirakui.com/entry/20100301/1267464280
Unity ML-Agentsのサンプルを動かす

ML-Agentsを使うと、Unityで簡単にTensorFlowを使った強化学習が実行できます。
まずはサンプルを動かしてみます。

see https://qiita.com/decchi/items/e2300f8a9dacf6ac4ccd
see http://nn-hokuson.hatenablog.com/entry/2017/12/26/213456

# ML-Agentsをセットアップ

## pythonのバージョンを確認
バージョンを確認しておきます。

```sh
$ python --version
Python 3.6.3
```

## minicondaをインストール
see https://qiita.com/FukuharaYohei/items/cf72049b2a97687037bb

## ml-agentsをセットアップ
ml-agentsをダウンロードします。
by https://github.com/Unity-Technologies/ml-agents

anaconda promptを開いてセットアップします。

```sh
conda create --name mlagent python=3.6
conda activate mlagent
cd ml-agents-master/python
pip install -r ./requirements.txt
```

# サンプルをセットアップ

## Unityプロジェクトを開く
ml-agents-master/unity-environmentをUnityでOpenします。

以下のようなサンプルが入っています。
https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Learning-Environment-Examples.md

## TensorFlowSharpプラグインをインストール

by https://github.com/Unity-Technologies/ml-agents/blob/master/docs/Using-TensorFlow-Sharp-in-Unity.md

## 使用するサンプル
BananaCollectorsを使います。

* 設定：エージェントがバナナを収集するために競争するマルチエージェント環境。
* 目標：青いバナナを避けながら、可能な限り多くの黄色のバナナに移動する方法を学ぶ必要があります。
* エージェント：環境には、単一の脳にリンクされた5つのエージェントが含まれています。
* エージェント報酬機能（独立）：
    * 黄色のバナナとの相互作用のための+1
    * 青いバナナとの相互作用のため-1。
* 脳：以下の観察/行動空間を有する1つの脳。
* エージェントの順方向（49; 7つのレイキャスト角度（7つのレイキャスト角度））の周囲の物体の光線に基づく知覚に加えて、エージェントの速度に対応するベクトル観測空間：（連続的）それぞれの測定値）。
* ベクトルアクションスペース：（連続）サイズ3、前方移動、y軸回転、およびレーザーを使用して他のエージェントを無効にするかどうかに対応します。
* 視覚的観察（オプション）：1人目のカメラごとのエージェント。VisualBananaシーンを使用します。
* リセットパラメータ：なし
* ベンチマーク平均報酬：10
* オプションの模倣学習シーン：BananaIL。

# 模倣学習する
自分で操作した結果をAIに学習させる方法です。

BananaILシーンを開きます。
Build SettingsでBuildし、ai1/ai1.exeに模倣学習用のプログラムをビルドします。
ビルドが終わったら、ml-agents-masterのpythonディレクトリで以下を実行し、模倣学習を開始します。

```sh
python learn.py ..\unity-environment\ai1\ai1.exe --train --slow
```

WASDキーで移動し、青いバナナに触れないようにして、黄色いバナナをとります。
プレイヤーの動きを生徒役のAIが学習します。
10000Stepまで学習が進むと、プログラムは自動的に終了します。

終了すると、学習モデルが以下に作成されます。

    ml-agents-master\python\models\ppo\ai1_ppo.bytes

学習モデルをBananaCollectors/TFModelsにコピーします。

## 学習モデルを実行します。

Bananaシーンを開きます。
BananaBrainのBrain TypeをInternalにして、ai1_ppo.bytesを選択します。
実行すると、さきほど学習したモデルを使ってAIが動作します。

# 自動的に学習する
自分で操作せずに自動で学習する方法です。

Bananaシーンを開きます。
BananaBrainのBrain TypeをExternalにして、ai1/ai1.exeにビルドします。
ビルドが終わったら、ml-agents-masterのpythonディレクトリで以下を実行し、学習を開始します。

```sh
python learn.py ..\unity-environment\ai1\ai1.exe --run-id=test1 --train
```

こんな風に学習している状況が見えます。
![learn.png](https://qiita-image-store.s3.amazonaws.com/0/44912/10e55a56-b96d-5235-871a-16d4d2d30cba.png)

終了すると、学習モデルが以下に作成されます。

    ml-agents-master\python\models\test1\ai1_test1.bytes

学習モデルをBananaCollectors/TFModelsにコピーし、模倣学習と同様に実行します。
自分で操作する模倣学習のときより動きが緩慢に見えます。

## Unity Editor上で学習を実行する
0.4からできるようになったようです。
by https://qiita.com/God_KonaBanana/items/8c7fa1b9da6d2e052ce2

Brain TypeをExternalにします。
pythonディレクトリで以下を実行します。

```sh
python learn.py --train
```

Unity Editorで実行ボタンを押します。

これでUnity Editorで実行をしながら学習が開始します。

おしまい。
Alibaba CloudでRancher＋Kubernetesの環境構築(2)～Kubernetes環境構築～

前回は、RancherOSを利用してAlibabaCloud ECS環境にRancherを構築しました。
今回は、構築したRancherを利用してKubernetesを導入します。

##Rancherホストの設定
最初はRancherホストが設定されていないため、ホストを設定する必要があります。
今回は現在のサーバーをRancherホストとして設定します。

- 「Add a host」をクリック
<img width="724" alt="RancherOS2-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/254932/a6ee39fa-cce8-d1bd-6a10-e38efa1d57f3.png">
- 「This site's address」を選択して「Save」をクリック
<img width="677" alt="RancherOS3.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/254932/993fd133-4dd9-ce99-a92f-0d143c0c2a09.png">

##Environmentの追加
Kubernetes Environmentを追加します。

- 左上の「Default」をクリックし「Manage Environments」を選択
- 「Add Environment」をクリック
<img width="1078" alt="Environments.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/254932/44527faf-4e6d-a15a-fe4f-73f4a340d4b2.png">
- 「Name」に名前を入力し、「Environment Template」から「Kubernetes」を選択し「Create」をクリック
<img width="1062" alt="Environment2.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/254932/d22342e0-827a-e8b3-4d60-5b8dfc940fa5.png">
- Kubernetesのセッティングが開始されます
<img width="560" alt="SettingUp.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/254932/aea8a3a1-cb2a-4c79-6793-ec1d38f1219d.png">

このままではセットアップが完了しません。
「Add Host」をクリックして表示される画面の、⑤のコマンドを実行してください。
<img width="920" alt="AddHost.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/254932/84e6f7f7-a454-682c-35a1-dc8f31e5bcdc.png">
完了すると、Kubernetes Dashboard画面が表示されます。
<img width="811" alt="Kubernetes_Done.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/254932/5713a0b3-822a-e816-0585-56072765499d.png">

ホストを追加する場合は、AddHost画面で、「Custom」を選択します。
④に追加するホストのパブリックなIPアドレスを入力して、⑤のコマンドをコピーします。
追加するサーバーでコピーしたコマンドを実行すると、Host一覧でこの様に表示されます。
<img width="632" alt="AddHost5.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/254932/10f3cd45-3a6e-7b3e-88b8-4d46ebd7dd1e.png">

##まとめ
Alibaba CloudでRancher+Kubernetesの環境構築を試してみました。
Rancher OSを利用して手軽に環境構築は行えましたが、実際に利用する際はこれから様々なチューニングが必要だと感じました。
【PWM制御】Nefry BTで上品なLチカをする

# 上品なLチカとは？
こんにちは，dotstudioのたくろーどんです．

LチカとはLEDをチカチカさせることです．
Arduinoといったマイコンを手に入れると，多くの人がLチカに取り組むでしょう．
ただ，LEDをチカチカさせるだけで満足ですか？
満足できないなら，ちょっと上級者っぽく上品なLチカを試してみましょう．

上品なLチカを実現するために，PWM制御を使います．
PWM制御の詳しい説明は[dotstudioの資料](https://dotstud.io/docs/pulse-width-modulation/)をご覧ください．

# プログラム
Nefry BTをつかったPWM制御ですが，[Nefry BTの説明書](http://www.kyohritsu.jp/eclib/OTHER/MANUAL/WIRELESS/nefrybt.pdf)には**analogWrite()関数を使っていますが，うまくいきませんでした**．

[![https://gyazo.com/1c3513db18b9fbd37db425f28781bb3b](https://i.gyazo.com/1c3513db18b9fbd37db425f28781bb3b.png)](https://gyazo.com/1c3513db18b9fbd37db425f28781bb3b)

調べてみるとNefry BTに使われている[**ESP32ではanalogWrite関数が実装されていない**](https://github.com/espressif/arduino-esp32/issues/4)ようです．
その代わりに，ESP32ではPWM制御のために**ledc()関数**が用意されているので，これを使います．

PWM制御を使ったLチカのプログラムは下記に示します．

```c++

//esp32はanalogWriteが使えない
//ledc関数を使う
#include<Nefry.h>
#include"esp32-hal-ledc.h"
#define PIN A3


void setup() {
  pinMode(PIN, OUTPUT);
  ledcSetup(0, 490, 8);
  ledcAttachPin(PIN, 0);

}


void loop() {

  int led_value;

  for(led_value = 0; led_value <= 255; led_value += 5){
    ledcWrite(0, led_value);
    delay(30);
  }
  for(led_value = 255; led_value >= 0; led_value -= 5){
    ledcWrite(0, led_value);
    delay(30);
  }
}

```

プログラムを詳しく見てましょう．
ledc()関数を使うため，ライブラリ「esp32-hal-ledc.h」を最初にインクルードします．


```c++

#include"esp32-hal-ledc.h"

```

ライブラリ「esp32-hal-ledc.h」を使うときの主な関数が以下に示すものです．

①ledcSetup(チャンネル,周波数,分解能)
②ledcAttachPin(ピン番号,チャンネル)：チャンネルはピン番号の識別番号です
③ledcWrite(チャンネル,パルス幅)：設定した角度になるように与えるべきパルス幅を算出する関数

分解能のイメージは**どれだけ細かく制御するのか**を表しています．これは**ビット数**で表します．
例えば，**分解能を8ビットとするれば0~255バイト(2の8乗で計算)，10ビットなら0~1023バイト(2の10乗で計算)**となります．

これを，どのようにPWM制御に使えるのか説明します．PWM制御とは 一定電圧の入力から、**パルス列のオンとオフの一定周期を作り、オンの時間幅を変化させる電力制御方式**のことです．つまり，**実効電圧を変化させる**ことができます．



なので，例えば，最大5[V]の出力を考えたとき，
- **分解能8ビットだと0→0[V]，127→2.5[V]，255→5[V]**
- **分解能10ビットだと0→0[V]，511→2.5[V]，1023→5[V]**
と表せます．分解能が大きい方が，細かい制御ができることがわかるかと思います．

```c++

void setup() {
  pinMode(PIN, OUTPUT);
  ledcSetup(0, 490, 8);
  ledcAttachPin(PIN, 0);

}

```

今回は，分解能8ビットで制御しています．
先ほどの説明を理解すれば，下記にvoid loop()の中身も理解できるかと思います．
ledcWrite()関数で値を出力しています．

```c++

void loop() {

  int led_value;

  for(led_value = 0; led_value <= 255; led_value += 5){
    ledcWrite(0, led_value);
    delay(30);
  }
  for(led_value = 255; led_value >= 0; led_value -= 5){
    ledcWrite(0, led_value);
    delay(30);
  }
}

```

# 動かしてみる
以下のように，ただLEDがチカチカするのではなく，上品な感じでLチカできます．

[![https://gyazo.com/72e1a967db1fe3051d7ae469fa122a3f](https://i.gyazo.com/72e1a967db1fe3051d7ae469fa122a3f.gif)](https://gyazo.com/72e1a967db1fe3051d7ae469fa122a3f)

PWM制御を使えば，DCモータやサーボモータを自由に制御できるようになるので理解しておくと良いでしょう！では！
jQueryのeachメソッド

## HTML要素に対する繰り返し

```html
<ul>
  <li>Ruby</li>
  <li>JavaScript</li>
  <li>PHP</li>
</ul>
```

```js
  $('li').each(function(index, element){
    console.log(index + ':' + $(element).text());
  })
```

以下のように出力される。

```
0:Ruby
1:JavaScript
2:PHP
```


## 配列・オブジェクトに対する繰り返し

```js

var array = ['Rails', 'jQuery', 'FuelPHP'];

$.each(array, function(index, value){
  console.log(index + ':' + value);
})
```

以下のように出力される。

```
0:Rails
1:jQuery
2:FuelPHP
```

# 参考
[【jQuery入門】2種類のeach()による繰り返し処理まとめ！](https://www.sejuku.net/blog/33609)

[【jQuery】複数の要素に対して繰り返し処理をする（each・for）！]
(http://www.task-notes.com/entry/20140725/1406216933)
【第五弾】Kubernetesベストプラクティス：Graceful Shutdown

# ベストプラクティス第五弾

こんにちは、jackです。

Kubernetesベストプラクティスも後半戦です。
今回はKubernetesがどのようにPodを終了するのか、1ステップずつ見ていきます。

[Kubernetes best practices: terminating with grace](https://cloudplatform.googleblog.com/2018/05/Kubernetes-best-practices-terminating-with-grace.html)

# TL;DR

* 常に**正常終了**処理するアプリケーションを作れ
* Kubernetesの**termination lifecycle**は
    * `Terminating` State
    * preStop Hook
    * SIGTERM
    * terminationGracePeriod (30秒)
    * SIGKILL

# もっと詳しく

## Kubernetesのtermination lifecycle

Kubernetesはアプリケーションのモニタリングはもちろんのこと、複数マシーンにアプリケーションをデプロイしたり、違うバージョンを同時に走らせたり、多くの面倒を見てくれます。

その中で、Kubernetesは**異常のないPodを終了する**ことがあります。
どういったことかと言うと、例えばアプリケーションのアップデートがありrolling updateを行えば、Kubernetesは次第に古いPodを落としつつ、アップデートされたバージョンのPodを作成します。また、Nodeのリソースが足りなくなればPodを終了し、不足したリソースを確保することもあります。

つまり、アプリケーションがいかなる状態でも正常終了の処理することが重要になります。実際には、SIGTERMを受け取り、データを保存し、コネクションをクローズするといった処理をしっかり考慮することです。

では、実際にPodが終了する時系列順に見ていきましょう。

#### `Terminating` State
Podが`Terminating`というステータスになります。この時点で、新しいトラフィックの受信はなくなります。

#### preStop Hook
`Terminating`と同時。
このpreStop HookはContainer hooksの一種で、Podが`Terminating`ステータスになったと同時に送られます。

#### SIGTERM
`Terminating`と同時。
SIGTERMシグナルがPod内のコンテナに送られます。
アプリケーションはこのSIGTERMを受け取り、正常終了するようにしましょう。

*preStop hookを使っている場合でも、SIGTERMを受け取ったときの処理をしっかりテストしましょう。

#### terminationGracePeriod
Podが`Terminating`ステータスになってからカウントダウンされる時間です。デフォルトで30秒です。
preStop hookとSIGTERMの挙動にかかわらず、指定時間内に正常終了されるように注意しましょう。
デフォルトの30秒以上の時間が必要な場合は、`terminationGracePeriod`をPodのYAMLに定義しましょう。以下は60秒の例です。

```yml:pod.yml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: busybox
  terminationGracePeriod: 60
```

#### SIGKILL
`terminationGracePeriod`が終わったら、SIGKILLシグナルがPodに送られます。この時点で、Kubernetesのオブジェクトがクリーンアップされます。

# まとめ

さて、Podが終了する過程を時系列順に見てきましたが、見ていくと意外とシンプルだったのではないでしょうか。
いかなる状況でも正常終了する処理をすることを忘れず、`terminationGracePeriod`を過ぎそうなら時間を伸ばせばよいですね。

それでは、また次回。
Laravel 概要

PHPのWebアプリケーションフレームワークのデファクトスタンダードになりつつある（？）Laravelを学ぶ機会があったため、概要を簡単にまとめてみました。

対象バージョン：Laravel 5.6

#### はじめに

##### 開発環境のセットアップ

[Laravel Homestead](https://readouble.com/laravel/5.6/ja/homestead.html)（Laravel開発に必要なミドルウェア等をパッケージしたVagrant Boxファイル）を使うと簡単に開発環境をセットアップできる。

`Homestead.yaml` にIPアドレスなどの設定が記載されている。

##### LaravelでのMVCモデル

Ruby on Railsを模倣したモデル構造をしている。

```text
Router --> Controller <--> Model <--> DB
                      <--> View
```

##### Laravelのディレクトリ構造

* `/routes/`
  - ルーティング設定ファイルを格納する。
* `/app/Http/Controllers/`
  * コントローラを格納する。
* `/app/`
  * モデルを格納する。
* `/database/migrations/`
  - データベースのマイグレーションファイルを格納する。
* `/resources/view/`
  * テンプレートファイルを格納する。
* `/public/`
  * Webに公開する静的ファイルを格納する。

#### リソースに対するCRUD操作画面を作成する流れ

##### artisanコマンドでモデル・コントローラの雛形を作成する

```text
php artisan make:model ｛モデル名} -m -c -r
```

* -m：DBマイグレーションファイルを作成する。
* -c：コントローラを作成する。
* -r：コントローラにリソースメソッドを作成する。

##### データベーススキーマを定義する

* 雛形 `/database/migrations/xxxx.php` のupメソッドにテーブル定義を記述する。
* `php artisan migrate ` を実行してテーブル定義を反映する。

参考：https://readouble.com/laravel/5.6/ja/migrations.html

##### コントローラーを実装する

雛形 `/app/Http/Controllers/xxx.php ` の各メソッドを書き換えてモデル操作とビュー返却を行う。

* 雛形コントローラーにはCRUD操作で必要になる画面用のメソッドが定義されている。
* コントローラーメソッドではモデルクラスを使ってデータ操作を行い、ビューにデータを渡してレンダリングして返却する。

##### ビューを実装する

* コントローラーから渡されたデータを[Bladeテンプレート](https://readouble.com/laravel/5.6/ja/blade.html)使ってHTML構造に埋め込む。
* CSRF対策には`@csrf`を記述することでCSRFトークンをhiddenフィールドに埋め込める。

##### ルーティングを設定する

`/routes/web.php`にコントローラーメソッドへのルーティング設定を記載する。

* `Route::resource` を使うことでコントローラのリソースメソッドのルーティング設定が簡単にできる。

参考：https://readouble.com/laravel/5.6/ja/controllers.html#resource-controllers

##### （おまけ）データベースにダミーデータを追加する

Seederを作成してデータベースにダミーデータを投入（シーディング）する。

- `php artisan make:seeder {Seeder}` を実行して雛形を作成する。
- 雛形 `/database/seeds/{Seeder}.php` を編集してダミーデータ作成コードを記述する。

参考：https://readouble.com/laravel/5.6/ja/seeding.html

#### その他補足

##### バリデーション

コントローラーにリクエストのバリデーション処理を以下の2通りの方法で記述できる。

1. [Requestオブジェクトのvalidateメソッドを使う方法](https://readouble.com/laravel/5.6/ja/validation.html#quick-writing-the-validation-logic)
   - バリデーション違反時のエラーレスポンスを自動生成してくれる。
2. [Validatorファサード](https://readouble.com/laravel/5.6/ja/validation.html#manually-creating-validators)を使ってバリデータを生成する方法
   - バリデーション処理のみ実施してエラーレスポンスを自分で構築する。

##### エラー処理

ハンドリングされない例外に対する処理は `app/Exceptions/Handler.php` に記述できる。

- reportメソッド：ログ出力や外部サービス（監視サービスなど）への通知を行う。
- renderメソッド：発生した例外に対するレスポンスを出力する。

##### ミドルウェア

ミドルウェアを使うことで、HTTPリクエストに対して、コントローラの処理の前後に処理を挟むことができる。認証やCSRF保護などコントローラーの共通処理をまとめるのに役立つ。

参考：https://readouble.com/laravel/5.6/ja/middleware.html

例：Laravel組み込みの `auth.basic` ミドルウェアを使ってBasic認証を設定する。

```php
Route::get('profile', function() {
	// ...
})->middleware('auth.basic');
```
じゃんけんアプリにEthereumを組み込んでみた


#はじめに
じゃんけんに勝つと1ETHをもらえるものを作りました。
イメージはこんな感じです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">少し前に作ったじゃんけんに勝つと1ETHがもらえるdapps。<br>ローカル環境のgethにしか対応していないクソゲーｗ<br>JavaScript覚えたてで、学校の課題のじゃんけんアプリにEthereumを組み合わせました。<a href="https://twitter.com/hashtag/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AEdapps?src=hash&amp;ref_src=twsrc%5Etfw">#初めてのdapps</a><a href="https://twitter.com/hashtag/dApps?src=hash&amp;ref_src=twsrc%5Etfw">#dApps</a> <a href="https://t.co/1dQ5YzbEPC">pic.twitter.com/1dQ5YzbEPC</a></p>&mdash; ko (@kolife01) <a href="https://twitter.com/kolife01/status/1013319290148143105?ref_src=twsrc%5Etfw">2018年7月1日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ローカル環境のgethで作成したアカウントをそれぞれこのように分けてます。
account[0]→master
account[1]→player
account[2]→pc　

#アプリの作り方
じゃんけん部は割愛するとしてgethと繋げる部分としてまずweb3を読み込みます。

```index.html
<script type="text/javascript" src="../web3/bignumber.js/bignumber.min.js"></script>

<script type="text/javascript" src="../web3/dist/web3.js"></script>

var web3 = new Web3();
    web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));

    if(!web3.isConnected()){
      alert("not connected! gethを立ち上げてください");
      console.log("not connected");
    }else{
      console.log("connected");
    }

```

アカウント、残高の表示

```
function watchBalance() {
      var add00 = String(web3.eth.accounts[0]);
      var add01 = String(web3.eth.accounts[1]);
      var add02 = String(web3.eth.accounts[2]);
      $("#add00").text(add00);
      $("#add01").text(add01);
      $("#add02").text(add02);

      var add00_balance = web3.eth.getBalance(add00);
      var add01_balance = web3.eth.getBalance(add01);
      var add02_balance = web3.eth.getBalance(add02);
      var add00_balance_eth = web3.fromWei(add00_balance, 'ether');
      var add01_balance_eth = web3.fromWei(add01_balance, 'ether');
      var add02_balance_eth = web3.fromWei(add02_balance, 'ether');

      $("#add00_balance").text(add00_balance_eth +" ETH");
      $("#add01_balance").text(add01_balance_eth +" ETH");
      $("#add02_balance").text(add02_balance_eth +" ETH");
    }

```



勝利時のトランザクション処理

```
function win(){
  var _sendTransaction = web3.eth.sendTransaction({
          from: web3.eth.accounts[2], 
          to: web3.eth.accounts[1], 
          value: 1000000000000000000
        },)
}
```
この処理をじゃんけん勝ったときに追加すればOKです。

#アプリの使い方
##gethの起動

'''
geth  --rpc --rpcport 8545 --rpcapi "web3,eth,net,personal" --rpccorsdomain "*" --rpcaddr "0.0.0.0" --datadir "~/eth_testnet" --nodiscover --networkid 10 --unlock 0,1,2 console 2>> ~/eth_testnet/geth.log
'''

アカウントをアンロックしないとトランザクション処理時にエラーになるので、geth立ち上げ時にアカウントロックを解除します。

アカウントロック例

```
Unlocking account 0 | Attempt 1/3
Passphrase: pass
Unlocking account 0 | Attempt 2/3
Passphrase: 
Unlocking account 0 | Attempt 3/3
Passphrase: 
```

マイニングスタートしてじゃんけんをする
`miner start()`


#終わりに
今回はローカル環境だったので次はテストネット上のdappsに挑戦じゃー！
Ubuntuで、VSCodeがpipenv環境を読み込んでくれない

## 環境

* Ubuntu16.04.3
* VSCode: 1.24.1
* pipenv: version 2018.6.25

## 症状

1. `Pipfile`が置いてあるディレクトリを`VSCode`でOpenする。
2. VSCodeで以下のメッセージが出る。

> Workspace contains pipfile but attempt to run 'pipenv --venv' failed with 'spawn pipenv ENOENT'. Make sure pipenv is on the PATH.

* 実際にコードを実行してもPipfileで定義された環境が使われていない模様。
(installしたパッケージがimportできない)

* エラーメッセージには`pipenv --venv` failedと表示されるが、ターミナル上からは正常に実行できる。

```
$ pipenv --venv
/home/sabaku/Documents/try-keras/.venv
```

## 原因

結論: はっきりわからないが、`pipenv`のインストールディレクトリが関係している模様。

まず、VSCodeのWebサイトによるとpipenvで構築した仮想環境も自動的に読み込まれるようだ。(補足: 検証していないが、この挙動をさせるには`export PIPENV_VENV_IN_PROJECT=true`をしておく必要があるかもしれない。今回の環境ではもともと`true`になっている。)

> The extension automatically looks for interpreters in the following locations:
> ...
> A pipenv environment for the workplace folder.
> ...

https://code.visualstudio.com/docs/python/environments#_manually-specifying-an-interpreter

VSCodeのgithubに今回の症状に似たISSUEが上がっている。

https://github.com/Microsoft/vscode-python/issues/1338

もしかすると、この件が原因なのかもしれない。
https://github.com/Microsoft/vscode-python/issues/1338#issuecomment-390243643

## 対処

pipenvのインストール先を確認してみるとuserディレクトリ以下にインストールされている事が分かる。

```
$ pip show pipenv
...
Location: /home/sabaku/.local/lib/python3.5/site-packages
...
```

これをまずアンインストールする。

```
$ pip uninstall pipenv
Uninstalling pipenv-2018.6.25:
  Would remove:
    /home/sabaku/.local/bin/pewtwo
    /home/sabaku/.local/bin/pipenv
    /home/sabaku/.local/bin/pipenv-resolver
    /home/sabaku/.local/lib/python3.5/site-packages/pipenv-2018.6.25.dist-info/*
    /home/sabaku/.local/lib/python3.5/site-packages/pipenv/*
    /home/sabaku/.local/lib/python3.5/site-packages/tasks/vendoring/*
    /home/sabaku/.local/lib/python3.5/site-packages/tests/integration/*
    /home/sabaku/.local/lib/python3.5/site-packages/tests/unit/*
Proceed (y/n)? y
  Successfully uninstalled pipenv-2018.6.25
```

pipenvをrootに再インストール。

```
$ sudo pip install pipenv
```

とりあえずインストール先が変わった。

```
$ which pipenv
/usr/local/bin/pipenv
```

この状態でVSCodeを立ち上げたら症状が改善した。

さらに、`VSCode`の下にあるPython環境の指定で、pipenvのvirtualenvを指定したところ、コードの実行時にもpipenvの環境を使ってくれるようになった。

正しい対処法なのか分からないが、とりあえず共有する。
ヘキサそろばん(16進数)による掛け算 (複数ケタ * 一ケタ)

#ヘキサそろばんによる掛け算
掛け算をするには、まず16進数掛け算表「FF」を用意します

###**FF表**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13318/98e13c83-d078-2adf-304c-48633b9fb6dd.png)

可能なら丸暗記してしまうのがよいでしょう。

あとはそろばんに値をおいて、表に従ってもとめた値をケタ毎に加算していくだけです。

##例. 34A * B　の計算

1.　34Aをそろばんに入力します

![image.png](https://qiita-image-store.s3.amazonaws.com/0/13318/f32ab494-d2ca-d633-618f-9b83f15bef1f.png)

2.　最上位ケタの計算 3 * B = 21 を掛け算表から求め、3ケタ目を基準に入力します

![image.png](https://qiita-image-store.s3.amazonaws.com/0/13318/c5f2acf1-78a1-94ce-538d-b7872b643d32.png)

3.　2ケタ目の計算 4 * B = 2C を求め入力します

![image.png](https://qiita-image-store.s3.amazonaws.com/0/13318/93e3ed91-b899-df5a-0344-f7ee473d722b.png)

4.　1ケタ目の計算 A * B = 6E を入力します。まず60を繰り上がりで加算します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13318/00f074a4-1c73-2973-4a85-df477fcd20f3.png)

5.　残った0Eを入力します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13318/723285fb-9780-73bf-3fa8-e8554c549a15.png)

6.　解として 242E が求まりました
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13318/4decb751-12c3-eddb-21c0-37e2afe55fef.png)

複数ケタ同士の掛け算は次回に。
基本的な考え方は十進数そろばんの掛け算法と変わりません。
Access から グラフ用のデータを Excel に出力する。

Accessでグラフは作れるものの、グラフなら Excelで作りたい。



#Accessのデータを集計してExcelに出力する項目を決める。

項目を選択する画面は、下図のようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/93227/c4611cbf-90af-7d39-4f48-17696cddd735.png)


集計したデータをExcelに出力する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/93227/87fffdd8-a1e6-d5ef-865b-8eec9ae23646.png)

Excelに出力したデータを使って、ユーザーは、自由にグラフを作成することができます。

#AccessとExcelを連携してシステムを作成する

[![image.png](https://qiita-image-store.s3.amazonaws.com/0/93227/548be484-20e3-51e6-af52-d8531ba492d2.png)](http://access-cloud.hatenablog.com/entry/database)
Azure Cloud ShellでCentOSのVMを作成する

# コマンド
* AzureポータルでCloudShell(Bash)を表示し、以下のコマンドを実行する。
* SizeはA0,パスワード認証で作成する。パスワードはコマンド実行後にプロンプトで入力する。
* VM作成が完了すると、PublicIPが表示されるのでsshで接続できる

```bash:bash
az vm create -n <VM名> -g <リソースグループ名> --image CentOS --size Standard_A0 --admin-username <管理ユーザー名> --authentication-type password
```

# 参考
* [チュートリアル \- Azure CLI を使用して Linux VM の作成と管理を行う \| Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/tutorial-manage-vm)


* その他のコマンド

```bash:bash
# 参考：よく使われるイメージの一覧を表示
az vm image list --output table

# 参考：リージョンで利用可能なサイズの一覧を表示
az vm list-sizes --location japaneast --output table

```
Pythonの勉強-ファイルのimport

Pythonに限らずですが、プログラムが複雑になると１ファイルで管理するよりも別ファイルに分けた方が開発効率がはるかに良くなります。
別ファイル化したプログラム(モジュール）を読み込むimport処理について、参考記事のリンク集のレベルでざっくり調べてみました。

#モジュールについて
Python3.6.5ドキュメント Python チュートリアル
6. モジュール (module)
https://docs.python.jp/3/tutorial/modules.html

##別ディレクトリのファイルをincludeする方法
https://code-schools.com/python-anotherfile/

##備考
パッケージ化についてはまた別の機会に。。。
個別に名前の入ったGoogleFormsをGmailで送信した

Googleフォームを使ったアンケートで、あらかじめ名前が入ったアンケートを個別に一斉に送りたい時にやった手順
##フォームを用意
<img width="826" alt="スクリーンショット 2018-06-30 23.14.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/267174/3c7a7500-b62b-102d-61da-fd234e7c736c.png">
こんな感じの、名前を入力する項目が入ったフォームを用意
##事前に入力したURLを取得
「事前に入力したURLを取得」を開く。今回はお名前のところを事前入力して作りたいので、お名前のところに「hoge」と入力する。
（hogeの部分はあとでGASで置換するので、わかりやすければなんでもいいが、日本語にするとあとでエンコードの問題が発生して置換しづらくなるのでさけた方がいい）
できたら「リンクを取得」を押し、左下に出てくる「リンクをコピー」を押してリンクを取得する
<img width="1303" alt="スクリーンショット 2018-06-30 23.42.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/267174/972a44a1-5327-dc7b-06ca-fe04bb277ba1.png">

ここで取得したリンクは今回の場合 `https://docs.google.com/forms/d/e/1FAIpQLSevwd9U9rBYKNKnq_HeN-2irodHg9k4MUUm4fg9W3-tBiFE9A/viewform?usp=pp_url&entry.1570869996=hoge"
`のようになっています。名前の部分で`hoge`と入力した部分が最後の`entry.1570869996=hoge`に対応しているわけですね。この部分を置換して好きな値を代入すればうまくフォームに名前を入力したまま送信できそうです。

###GASを利用してGmail、スプレッドシートと連携する
フォームの準備が整ったので、今度はGASを書いていきます。
<img width="990" alt="スクリーンショット 2018-07-01 0.49.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/267174/e2f6be6b-3944-97f8-50a1-6efb4114149b.png">
今回はこんな感じの、名前とメールアドレスの入ったUsersというシートを用意しました。ここから個別にGmailで送信したいと思います。

```javascript
//コピーしたURLをforms_urlに代入
var forms_url = "https://docs.google.com/forms/d/e/1FAIpQLSevwd9U9rBYKNKnq_HeN-2irodHg9k4MUUm4fg9W3-tBiFE9A/viewform?usp=pp_url&entry.1570869996=hoge"

//ユーザー一覧のシートをここで設定
var Users_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Users");
var Users_last_row = Users_sheet.getLastRow();
var Users_last_column = Users_sheet.getLastColumn();
var Users_list = Users_sheet.getRange(1,1,Users_last_row,Users_last_column).getValues();

////////////////////////
//
//メニュー追加
//
////////////////////////

function onOpen(){
  var menu =[{name:'アンケート送信', functionName:'Send_Forms'}]
  SpreadsheetApp.getActiveSpreadsheet().addMenu("アンケート送信",menu);
}

///////////////////////
//
//アンケート送信
//
///////////////////////

function Send_Forms(){
  for(var i =1; i< Users_last_row; i++){
    var users_name    = Users_list[i][0]; //ユーザー名
    var users_address = Users_list[i][1]; //メールアドレス
    var replace_url   = forms_url.replace("hoge",users_name); //ユーザー名をアンケートに埋めこむ部分
    var body          = replace_url  //メール本文
    var subject       = "アンケート　のご協力"  //件名
    GmailApp.sendEmail(users_address, subject, body)  //Gmail送信
  }
}
```

メニューにメール送信の項目を作っておくとその後使いやすいと思い`function onOpen()`を用意しました。ユーザー名やアドレスは自分が用意したシートにあわせて変えてください。
###結果
<img width="1025" alt="スクリーンショット 2018-07-01 15.28.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/267174/38e61454-ceea-971a-32b8-3fc1ac2114bd.png">
スクリプトを実行した結果こんな感じで無事に送信できました。URLを開いてみると
<img width="853" alt="スクリーンショット 2018-07-01 15.50.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/267174/f6474952-dba5-9ef6-160e-43ba819c73b8.png">
確かに事前に名前が入ったフォームができていました。
###まとめ
メールアドレスを必須にすればユーザー管理が楽になるが、ユーザーに余計な入力の負担がかかるのが嫌だったので、事前に名前くらいは入力させたかったので作りました。これで例えば誰からアンケートの結果が返ってきてないなど管理ができます。ただ、名前を回答者が書き換えちゃえるのが欠点。
wio LTEを使ってみる！[第1回]

とある機会で、wio LTEというデバイスに触れた。
せっかく知ったのだから、自分で買って使ってみた。

## wio LTEとは？
SORACOMが販売している、LTEモジュール付きのseeed社のマイコンモジュール
https://soracom.jp/products/wio_lte/

いわゆるIoTとやらでよく使われるデバイスの一つ。

<img src="https://soracom.jp/img/products_wio_lte.png" width=50%>

### 仕様
SORACOMサイトそのまんま引用

>Wio LTE JP Version は、Seeed社が開発しているマイコンモジュールです。
>Grove コネクターと STM32F4 マイコン、LTE モジュールが搭載されています。
>Arduino IDE で素早くプロトタイピングすることができます。

仕様の詳細、Arduino IDE用ライブラリはWio LTE for Arduinoをご確認ください。

プロセッサー : STM32F405RG, ARM Cortex-M4, 168MHz
フラッシュメモリ : 1Mバイト
内蔵SRAM : 192Kバイト
LTE Cat.1 : FDD-LTE B1/B3/B8/B18/B19/B26
SIMサイズ : ナノ
 ```

# 概要
以下サイト様を参考に実施(というかそのまんま書いてることやるだけ)
https://github.com/soracom/handson/wiki/Wio-LTE-%E3%83%8F%E3%83%B3%E3%82%BA%E3%82%AA%E3%83%B3

第1回目はwioLTEにプログラムを書き込むまで。
最終目標は、**とりあえずLTEでなんか通信して、データを見る**です。


## まずは購入
思ってたよりwioLTEが高い。

* スイッチサイエンスでwio LTEを購入
https://www.switch-science.com/catalog/3600/

    実は秋月電子のほうが数百円安いが、wioLTEにセンサ等をつなげるのに必要な[groveコネクタのバラ線ver](https://www.switch-science.com/catalog/1048/)を合わせて買うために上記で購入。

* amazonでSORACOMsimを購入
https://www.amazon.co.jp/gp/product/B015FFCZ02/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1


## 環境構築
環境はwindows10 64bit。
### デバイスドライバのDL
以下サイトにて、stmのVirtual COM Portsデバイスドライバをダウンロード。これでteratarmとかでシリアルを受け取れる。
https://seeedjp.github.io/Wiki/Wio_LTE_for_Arduino/InstallVCOMDriver-ja.html

### WinUSB ドライバのDL
zadig2.3というUSBドライバをダウンロード。これでwioLTEにプログラムを書き込める。
手順は参考サイト様にて。
https://github.com/soracom/handson/wiki/Wio-LTE-%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89---Windows-%E7%B7%A8#2-winusb-%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90

### Arduino IDE　環境設定
手順は参照サイト様にて。
https://github.com/soracom/handson/wiki/Wio-LTE-%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89---Windows-%E7%B7%A8#5-%E3%83%9C%E3%83%BC%E3%83%89%E5%AE%9A%E7%BE%A9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB
https://github.com/soracom/handson/wiki/Wio-LTE-%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89---Windows-%E7%B7%A8#6-wio-lte-%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB


## wioLTEにプログラムを書き込む
環境設定を終えたArduinoIDEにて、
wioLTEにサンプルスケッチを書き込んでみる。
### ボード選択
wio LTEをPCに差し込んで、Wio Tracker LTEを選択
このとき、**wioLTEをDFUモードにするのを忘れずに！(RSTボタンとBOOTボタン長押し)**

<img src="https://qiita-image-store.s3.amazonaws.com/0/256787/d26a1b04-532f-4f93-0ad7-4635fb4399a1.png" width=60%>

### サンプルスケッチ選択・書き込み
LedsetRGBというスケッチを選択。
そして書き込み！

<img src="https://qiita-image-store.s3.amazonaws.com/0/256787/76c864aa-6fad-9608-d525-d1b704e7a3f4.png" width=60%>

## 実行
wioLTEのRSTボタンを押して、プログラムの実行。
こんな感じでカラフルに光る。キレイ。

<img src="https://qiita-image-store.s3.amazonaws.com/0/256787/e00a99f9-6631-bb93-c886-d090dae25479.jpeg" width=30%>

# 次回
* wioLTEにSORACOMのSIMをぶっ刺す
* SORACOM harvestの設定
* SIMの登録

をやる予定
iPhoneX以外のシュミレータでFlutterを実行する

Flutterでシュミレータを起動するとだいたい最初にiPhoneXが起動してそのまま開発することが多いと思いますがレイアウトの確認等で別の端末で実行したい場合の手順について書きます。


## iPhoneX以外のシュミレータを開く

やり方は簡単でiPhoneX以外のシュミレータを起動すればいいだけです。
なのでまず、iPhoneXのシュミレータを起動し、[Hardware]→[Device]→[iOS 11.4]と開いて実行したいデバイスを選択する

<img width="772" alt="スクリーンショット 2018-07-01 16.03.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/d5f76a52-abbe-e122-4a19-f056d7d6d497.png">

そしたらシュミレータが開くので実行するデバイスを開いたやつにして実行したら終わりです。

<img width="306" alt="スクリーンショット 2018-07-01 16.05.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/139360/ef470f1c-c15a-cb63-9dc7-b1595b4533c3.png">
macOS に Redis を Homebrew でインストールして brew services で起動する

macOS に Redis を Homebrew でインストールして brew services で起動する方法をメモっとく。

# Redis を Homebrew でインストールする

Homebrew を最新にしてから Redis をインストールする。

```shell-session
$ brew update
$ brew install redis
```

# Redis を起動する

この記事では Homebrew のサービス管理機能である [Homebrew/homebrew-services](https://github.com/Homebrew/homebrew-services) を使用する。

Redis は `brew services start redis` で起動できる。

```shell-session
$ brew services start redis
==> Successfully started `redis` (label: homebrew.mxcl.redis)
```

`brew services` を利用することで、macOS の `launchctl` で plist を登録したり、登録解除したりする作業が不要になる。自動的に `launchctl` に登録されるので、macOS を起動するたびに Redis が自動起動する点は注意してほしい。

また、`brew services list` で起動状況が確認できる。

```shell-session
$ brew services list
Name        Status  User   Plist
redis       started takuya /Users/takuya/Library/LaunchAgents/homebrew.mxcl.redis.plist
```

# Redis を停止する

Redis は `brew services stop redis` で停止できる。

```shell-session
$ brew services stop redis
Stopping `redis`... (might take a while)
==> Successfully stopped `redis` (label: homebrew.mxcl.redis)
```

# 参考文献

[OS X に PostgreSQL を Homebrew でインストールして brew services で起動する](https://qiita.com/takuya0301/items/c0720753de98572703b8)
AIの実習に手軽な環境は？

AIの学習をしたい場合、現状どんな環境があるのかをざっと調べてみました。
「できるかぎり手軽」が良いため、”無償”を基準にピックアップしてみました。

#実習環境
Windows10

#ローカルにインストールする
##TensorFlow

TensorFlowをWindowsにインストール Python初心者でも簡単だった件
https://qiita.com/FukuharaYohei/items/d8f82c827e0bae70096a

#クラウドサービスを利用する
##AWS 無料利用枠

「AWS 無料利用枠を使用すると、AWS のプラットフォーム、製品、およびサービスを無料で体験できます。」

１２か月間無料できる機能に様々なAIがあります。
https://aws.amazon.com/jp/free/?awsf.Free%20Tier%20Types=categories%2312monthsfree

##Google Cloud Platformの無料トライアル
https://console.cloud.google.com/freetrial?_ga=2.81574930.-405996633.1530427659&pli=1&page=0

参考記事
Google、Cloud AutoML発表！誰でもオリジナルAIを生成可能に！？
https://ledge.ai/google_cloud_auto_ml_vision/

##IBM Cloud ライトアカウント
IBM Cloudライト・アカウント (Bluemix)
https://www.ibm.com/cloud-computing/jp/ja/bluemix/lite-account/

「クレジットカード不要で、期間無制限でWatson含めた多数のAPIとサービスが
無料で使える新しいアカウントです。評価利用だけでなく、本番環境でもご利用いただけます。」

制限としては、10日間 開発なしでアプリを自動停止、30日間 活動なしでサービスの自動削除、など。

##リクルートのAI
参考記事
https://ledge.ai/recruit_artapi_/
リクルートがAIをまさかの無料公開。さっそくすべてのAPIを試しまくってみた

##その他参考記事
一年以上前のものなのですが、予備知識として。
http://www.itmedia.co.jp/news/articles/1703/08/news072.html
Amazon、Google、IBM、Microsoftが公開する、AIを使うための「API」「ライブラリ」「実行環境」一覧

##追記
2018/07/01
日経ソフトウエア2018年７月号特集がちょうどAIでした。
【特集】
驚異の能力　人工知能API
〜Google、Amazon、Watson〜
http://trendy.nikkeibp.co.jp/atcl/pcmedia/174/052200020/
terminal (zsh) が起動しなくなってしまったときの対処法

Homebrewに色々なパッケージをインストールしていたところ、突然以下のようなエラーメッセージがターミナルに現れ、ターミナル(zsh)が起動しなくなってしまいました。

```
dyld: Library not loaded: /usr/local/lib/libgdbm.4.dylib
  Referenced from: /usr/local/bin/zsh
  Reason: image not found

[プロセスが完了しました]
```

ターミナルが使えなくなってしまったため何もすることができず、正直パニックになりました。しかし、ある方が同じエラーについて[ブログ](http://umegusa.hatenablog.jp/entry/2012/07/21/155637)を書いており非常に役に立ったため、Qiitaにも同様の解決方法を記載しておきます。

## 1. zshからbashに変更する

ターミナルが起動しない限り、なんの対処もできないため、まずはターミナル⇒環境設定⇒一般⇒開くシェル⇒コマンド（完全パス）と移動し、パスを/bin/bashに変更します。

そうすることで、bashを用いてターミナルを起動させることができます。

## 2. 不足しているライブラリを追加

不足しているライブラリを追加するためにはwgetが必要なので、homebrewを使ってインストールします。

```
$ brew install wget
```

次にGDBMをダウンロードし、makeする過程に移ります。
GDBMパッケージは GNU DBM ライブラリがあるので、ダウンロードし、解凍します。

```
$ wget ftp://ftp.gnu.org/pub/gnu/gdbm/gdbm-1.9.1.tar.gz
$ tar zxfv gdbm-1.9.1.tar.gz
```

最後にmakeしてインストールすることで、再びzshでターミナルを起動することができます。

```
$ cd gdbm-1.9.1
$ ./configure --prefix=/usr/local
$ make
$ make install
```

※ bashからzshに戻すのを忘れずに。

## 参考
[teminalが動かなくなってしまいました - umegusa's blog 備忘録] (http://umegusa.hatenablog.jp/entry/2012/07/21/155637)