OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptで配列を指定時間で回す

###JavaScriptを使って配列を、指定時間で回す


**2019/06/18 コードを書き換えたものを下に載せています**


**用途**
ゲーム作成時に使えそう(?)
擬似的な非同期処理として使えそう(?)


JSでゲームを作る際、ループ処理で配列を回す場合が多いです
でも、ループ処理で配列から値を取得する際は一瞬で終ってしまいますし、
実行環境の処理速度によって取得時間はバラバラになります。

配列自身から値を取得する時、その取得する時間を指定して
直接関数内で動作出来たらなと思って作ってみました。

動作する物は「一次元配列」に限ります

時間の指定は 1000/1秒 で可能です。

これを使えばRPGやシューティングゲーム開発に使えるかも...?

クソソースですが誰かの役立てばいいなと書いてます。

##関数
```javascript:javascript
function ArrayRoops(array, time, fun){
	this.length = array.length;
	this.counts = 0;
	this.Timer = setInterval(() => {
		this.key = this.counts;
		this.value = array[this.key];
		fun(this.key, this.value);
		this.counts ++;
		if(this.length <= this.counts){
			this.counts = 0;
			clearInterval(this.Timer);
		}
	}, time);
}

```


##使用例
```javascript:javascript

// 1次元配列
const array = ["dog", "cat", "horse"];

// 配列を 1秒間 に 1回 づつ回す
ArrayRoops(array, 1000, function(key, value){
	// 引数は key と value
	console.log(key + " : " + value);
});

// 配列を 3秒間 に 1回 づつ回す
ArrayRoops(array, 3000, function(key, value){
	// 引数は key と value
	console.log(key + " : " + value);
});

function ArrayRoops(array, time, fun){
	this.length = array.length;
	this.counts = 0;
	this.Timer = setInterval(() => {
		this.key = this.counts;
		this.value = array[this.key];
		fun(this.key, this.value);
		this.counts ++;
		if(this.length <= this.counts){
			this.counts = 0;
			clearInterval(this.Timer);
		}
	}, time);
}

```

##出力結果
```console:console
#配列 1
2018/06/27 00:00:00 | 0 : dog
2018/06/27 00:00:01 | 1 : cat
2018/06/27 00:00:02 | 2 : horse

#配列 2
2018/06/27 00:00:00 | 0 : dog
2018/06/27 00:00:03 | 1 : cat
2018/06/27 00:00:06 | 2 : horse
```


#2019/06/18 変更

```javascript
const roop = function(fun, time) {
	const self = new Object();
	const keys = Object.keys(this);
	self.count = 0;
	self.Timer = setInterval(() => {
		self.key = keys[self.count];
		self.value = this[self.key];
		if (fun.length >= 2) {
			fun(self.key, self.value);
		} else if (fun.length == 1) {
			fun(self.value);
		} else {
			fun.call({
				key: self.key,
				value: self.value
			});
		}
		self.count++;
		if (keys.length <= self.count) {
			self.count = 0;
			clearInterval(self.Timer);
		}
	}, time);
};
Object.prototype.roop = roop;
Array.prototype.roop = roop;
```

##使用例

```javascript
const array = ["array0", "array1"];
const object = {"key0":"object0", "key1":"object1"};

array.roop(function(key, value) {
  console.log(key, value);
}, 1000);
array.roop(function(value) {
  console.log(value);
}, 1000);
array.roop(function() {
  console.log(this.key, this.value);
}, 1000);


object.roop((key, value) => {
  console.log(key, value);
}, 1000);
object.roop(value => {
  console.log(value);
}, 1000);
object.roop(function() {
  console.log(this.key, this.value);
}, 1000);
```

一番うまく書けた気がする
K-Means法の入力に距離行列を使用する

# はじめに

scikit-learnライブラリのK-Means法をしばしば使っていますが
意外と理解できていない部分が多い。

忘れないためのメモ代わりに残しておきます。
Python3.6をJupyter notebook 上で動かしていて、コードは以下の通り。

```python:
test1 = np.random.multivariate_normal([10,4],[[1,1.2],[1.2,5]],100)
test2 = np.random.multivariate_normal([5,-3],[[0.5,-0.5],[-0.5,2]],100)
test3 = np.random.multivariate_normal([3,6],[[3,0],[0,1.2]],100)
test = np.vstack([test1,test2,test3])
fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(1,2,1)
ax.scatter(test1[:,0],test1[:,1])
ax.scatter(test2[:,0],test2[:,1])
ax.scatter(test3[:,0],test3[:,1])

distance_mat = cdist(test,test,metric="euclidean")
distance_mat.shape

km = KMeans(precompute_distances=True,n_clusters=3)
result = km.fit(distance_mat)
y_pred , centroid = result.labels_ , result.cluster_centers_
ax = fig.add_subplot(1,2,2)
ax.scatter(test[:,0],test[:,1],c=y_pred)
ax.scatter(centroid[:,0],centroid[:,1],c="red",marker="x",s=20)
plt.show()
```

![kmeans.png](https://qiita-image-store.s3.amazonaws.com/0/266903/76b0f86a-4942-7a2a-bfeb-bba41fee3c50.png)

サンプル点は二次元ガウス分布でサンプリングし、クラスターが3つにわかれるように平均値を調整している。それぞれのガウス分布ごとに100サンプル出力しています。
左図が初期サンプリング、右図がKmeans法による予測。そして赤い点が各クラスタのセントロイドになります。
これが大きくずれている。それもそのはず、実はこのセントロイドはそれぞれが300次元のベクトルで、プロットしているのは最初の2次元のみ。
プロットした時には気付きませんでしたが
centroid.shape
で確認するとしっかりと(3,300)となってました。
この300はサンプル数に対応すると同時に入力の距離行列の次元も300*300
ひょっとして距離行列をKmeans法でクラスタリングしてる？

Kmeans法が距離行列から計算できることを確認した時点で、
仮説として、セントロイドはサンプル点から選ばれるのではないだろうかと考えていましたが
結果として違っていました。
検証できるかは不明。


ちなみに上記の仮説はK-medoids法と呼ばれる手法を事前に仕入れていたので、
そうなのでは？と考えた次第。
K-medoids法についての説明は[こちらの記事](http://www.dskomei.com/entry/2018/04/03/004543)で書いて下さっている方がいます。


ちなみに初投稿ですのでいろいろと不備がありそうですがご容赦を。
内部プラットフォームへの製品管理の適用(Applying product management to internal platforms)

[TECHNOLOGY RADER](https://www.thoughtworks.com/radar) vol.18 が先ごろ発表されました。

TECHNOLOGY RADER は ThoughtWorks 社が年に 1～2 回程度発表している技術のトレンド分析です。

その中から一つ「[Applying product management to internal platforms](https://www.thoughtworks.com/radar/techniques)（内製品への製品管理の適用）」というテクニックが気に入ったので簡単に紹介します。

これは vol.17 から引き続き「TRIAL（試してみるべき）」のステータスになっています。


## 概要（の引用）

外部（お客様や取引先）に向けて販売している製品について厳格な製品管理を行うことは企業にとって当然の責務ですが、このテクニックでは内部で使用しているだけの製品についても同様の管理を適用します。

このことにより、以下のような効果をもたらします。

- ユーザーと設計・開発者との連帯感
- 内部製品の開発者が、ビジネスとして価値を生み出しているという感覚
- 継続的な改善による企業全体のエコシステムの発展
- 使いづらいために未利用になってしまう内部製品開発を避ける

## 感想と、想像を広げてみる

ソフトウェアエンジニアリングの世界に当てはめると以下のような人たちが該当するでしょうか。

- 社内で使用するシステムの開発・保守を行っている部署
- 一般社員が使用する PC の準備やアプリケーションのセットアップをする部署
- 開発チーム内で使うツールやサーバ環境を構築するチーフエンジニア

これらの人々がこのテクニックに基づく製品管理サイクルを用いると、以下のようなものが「芽生える」と考えられます。

- 詳細で有用なドキュメント
- 要件に対する丁寧なヒアリング
- 顧客の視点に立脚した適切な提案
- 製品がもたらす価値についての宣伝・営業活動・勉強会の開催

面倒な仕事が増える？そうかもしれません。しかしどうでしょう。大きなメリットが潜在していると感じられないでしょうか？

様々のニュースから、社内システム部門は他部門と衝突しやすい傾向にあることがわかります。曰く「仕様追加・変更までの期限が短く品質を担保できない。システム障害に対する影響調査にもっと時間がほしい」。曰く「新しいビジネスのために運用を変えたいが、システム部門の抵抗が強い」など。

システム部門が社員を「自分達のビジネスに欠かせないエンドユーザー」と捉え、社員がシステム部門を「自分達にとって魅力的で有用なツール・環境を整えてくれるベンダー」と捉えることで組織のメンタリティに正の流れが見えてくる気がします。
Macで漢字変換を間違えるたび消去していた人へ。

## TL;DR
何を言っているかわからないかもしれないので、とりあえず、次のGIFをみてください。
![GIF](https://gyazo.com/7765532500e8954f3d6eb920d97336b1.gif)
日本語入力で一度確定させてから `Ctrl + Delete` で再編集できる！！！
もう削除して、もう一度同じ文字を打つ必要はないです！！！

たまたま気が付いてびっくりしました。
[Angular] router-outletのコンポーネントの状態により親コンポーネントの状態を変えたい（しかも子供からいちいち指示したくない）ときのやり方

親コンポーネントの状態を子コンポーネントの状態によって変更したいという時ってよくあると思います。

直接HTMLに子のセレクタを記載している場合なら、 `@ViewChild` とか `@ViewChildren` で取得してその中身を見れば良いですよね（その行為が良いかはともかく）。

でも、 `router-outlet` の場合ってどうしていますか？

実は、 `activate` `Output()` で簡単に取得できるので、便利です。

例えば、子コンポーネントの状態によってタイトルを変えたいとしましょう（タイトルを変える場合にこの方法を使うのは微妙だと思いますが、わかりやすいので）

```parent.component.ts
@Component({
  selector: 'app-parent',
  template: `<div><h1>{{ title }}</h1><router-outlet></router-outlet></div>`,
})
export class ParentComponent {
  title: string;
  nameToTitle = {
    ONE: '１つ目',
    TWO: '2つ目',
  };
}
```

```child1.component.ts
@Component({
  selector: 'app-child1',
  template: `<div>Child ONE!!</div>`
})
export ChildComponent {
  name = 'ONE';
}
```

```child2.component.ts
@Component({
  selector: 'app-child2',
  template: `<div>Child TWO!!</div>`
})
export ChildComponent {
  name = 'TWO';
}
```


上記のコンポーネントが、routerにより、 `child1` , `child2` と変更されると想定します。
この場合、親コンポーネントを少し変更して下記のようにできます。

```parent.component.ts
@Component({
  selector: 'app-parent',
  template: `<div><h1>{{ title }}</h1><router-outlet (activate)="onActivate($event)"></router-outlet></div>`, // <= activate を追加
})
export class ParentComponent {
  title: string;
  nameToTitle = {
    ONE: '１つ目',
    TWO: '2つ目',
  };

  onActivate(componentRef: any): void { // <= 追加
    this.title = this.nameToTitle[componentRef.name];
  }
}
```

これで簡単に `router-outlet` の状態を参照して親コンポーネントの値を変更できます。

他のやり方としては、子コンポーネントから親コンポーネントをサービス経由で変更する、などの方法があります（こっちが一般的）。
でも全部のComponentでやるのは面倒なのでこういうやり方でも良いときはあるかなと（継承すればDRYにもできますが、時と場合によります）
pythonでlinebot作るときに詰まったこと（未完成）

#詰まったこと一覧
・herokuってなに？？？？？？？
・gunicornが見つからない
・Procfileの書き方がわからない
・linebotのimprotがうまくいかない
・LineのWebhookに記述するURLってどうするの

#解決のためにやったこと

##herokuってなに？？？？？？？
Java向けだけど書いてくれてた
[Heroku使い方メモ（Java）](https://qiita.com/opengl-8080/items/9dc9243c4e68cd0674f8)

##gunicornが見つからない
gunicornをインストールした

```
pip3 install gunicorn
```

そもそもrequirementsに書いてない

```requirements.tex
line-bot-sdk==1.5.0
future==0.16.0
requests==2.14.2
Flask== 0.12.2
click==6.7
itsdangerous==0.24
Jinja2==2.9.6
MarkupSafe==0.23
Werkzeug==0.12.2
```

gunicorn==19.8.1
と追加したら何とかこのエラーはでなくなった。

##Procfileの書き方がわからない
heroku特有のもので参考にしたのは以下のサイト
[Standalone WSGI Containers]('http://flask.pocoo.org/docs/0.12/deploying/wsgi-standalone/#gunicorn')
[Heroku Dev center](https://devcenter.heroku.com/articles/procfile)

むちゃくちゃわかりやすかったサイトがあったけど忘れた。後で追記する。


##linebotのimprotがうまくいかない
**今、詰まってる。解決中。**
fromのところに下線が出て

```
[pylint] E0401:Unable to import 'linebot'
```

って言われる。

```app.py
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    LineBotApiError, InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
    SourceUser, SourceGroup, SourceRoom,
    TemplateSendMessage, ConfirmTemplate, MessageAction,
    ButtonsTemplate, ImageCarouselTemplate, ImageCarouselColumn, URIAction,
    PostbackAction, DatetimePickerAction,
    CarouselTemplate, CarouselColumn, PostbackEvent,
    StickerMessage, StickerSendMessage, LocationMessage, LocationSendMessage,
    ImageMessage, VideoMessage, AudioMessage, FileMessage,
    UnfollowEvent, FollowEvent, JoinEvent, LeaveEvent, BeaconEvent,
    FlexSendMessage, BubbleContainer, ImageComponent, BoxComponent,
    TextComponent, SpacerComponent, IconComponent, ButtonComponent,
    SeparatorComponent,
)
```

##LineのWebhookに記述するURLってどうするの
**上が解決したらここを調べる**
Pixi.jsメモ

<div id="test">内にあるcanvasに紐づける +リサイズしてもウィンドウサイズいっぱいのcanvas領域にする設定

```ruby:html
<div id="test">
 <canvas id="myCanvas"></canvas>
/<div>
```


```ruby:js

let bw = 1200;
		let bh = 800;
		let app = new PIXI.Application({
			view: document.getElementById("myCanvas"),
			width: bw,
			height: bh,
			backgroundColor: 0x999999,
			antialias: true,
			transparent: true
		});
		app.renderer.autoResize = true;
		app.stage.interactive = true;
		$(window).on("load resize", function () {
			app.renderer.resize(window.innerWidth, window.innerHeight);
		});
		document.getElementById("test").appendChild(app.view);
```
たぶん一番簡単なmicro:bitのはじめかた Part3 ボタン/端子編

#ボタンの使い方

---
##2個のボタンを使って操作してみよう。
micro:bitには2個のボタンがあります。
どちらも[入力]から[ボタンが押された時]ブロックで使えます。
![microbit-画面コピー-9.png](https://qiita-image-store.s3.amazonaws.com/0/65643/a71e4277-8d6f-2eba-a0e6-3390a0bcdef5.png)


---
###ボタンで表示変更
![microbit-画面コピー-11.png](https://qiita-image-store.s3.amazonaws.com/0/65643/7c6a266c-ca0b-bbe2-2ee2-75a36e9d9a95.png)
これだけ。簡単。

---
###A+Bも含めれば３通り
![microbit-画面コピー-13.png](https://qiita-image-store.s3.amazonaws.com/0/65643/4c655540-73b0-7341-2ba5-62c2c2cec9ea.png)
じゃんけんもできちゃう。

---
#端子の使い方

---
##端子とは
micro:bitの下についている金色の部分。
0,1,2は入力端子。
3Vは電源。GNDはグランドです。
micro:bitは端子に触れた時の動作があらかじめMakecodeに用意されてます。

---
###じゃんけん端子版
![microbit-画面コピー-14.png](https://qiita-image-store.s3.amazonaws.com/0/65643/cf625b99-b78a-2030-5741-63ff365bdab9.png)
端子を触るときは、必ず逆の手でGNDをつまみましょう。

---
#カウンターを作ってみよう
##ボタンを押したり、端子を触った回数を表示するカウンターを作ります。

---
##数字の入れ物「変数」を使います。
いろんな動作に共通した数字を使いたいので、変数を使います。
変数は数字の入れ物です。例えば変数を「TEST」とした場合、TESTを呼び出せばどこでも同じ数字が使えます。

---
##サンプルコード
![microbit-画面コピー-15.png](https://qiita-image-store.s3.amazonaws.com/0/65643/fc4c3d30-92bb-ae71-1b9a-89c1f8ff3a9e.png)

---
###サンプルコードの解説
[ずっと]では変数TESTを表示するだけの内容です。
それぞれのタッチやボタンで変数TESTを１だけ増やしてます。
この形であれば、それぞれのボタンやタッチで表示処理をする必要がありません。

---
ご意見お待ちしています。
行シェルフに設定できる項目数について

【自分用のメモ】

Tableauでエクセルのような表を出力する場合、7つ以上を入れると最初の方のセルが ... とかになってしまう

これを変更するには

メニューから分析→表のレイアウト→詳細

![image.png](https://qiita-image-store.s3.amazonaws.com/0/140981/b7f85118-c31b-0527-657f-10816ca67635.png)

行ラベルの最大レベル
列ラベルの最大レベル

このあたりを変更すると綺麗に



参考：https://community.tableau.com/thread/153917
redis-store(redis-rails) で Redis に SSL 接続する方法

[redis-rails](https://github.com/redis-store/redis-rails) に `rediss://hogehoge` 形式でSSL接続をしようとすると、SSL であることを無視して、`redis://hogehoge` で繋ごうとする問題。

実際の問題は redis-rails で使われている [redis-store](https://github.com/redis-store/redis-store) 側にあって、この問題は対応中で近々マージされる様子
[Honor rediss:// schemes in URI by fancyremarker · Pull Request \#306 · redis\-store/redis\-store](https://github.com/redis-store/redis-store/pull/306)

## 対処方法

取り急ぎの対処方法として、`Hash` で接続情報を渡してあげれば OK

```ruby
Rails.application.config.session_store :redis_store,
  servers: URI.parse(ENV['REDIS_SESSION_STORE']).tap { |uri|
    break {
      host: uri.host,
      port: uri.port,
      password: uri.password ? CGI.unescape(uri.password) : nil,
      db: uri.path.split('/')[1] || 0,
      namespace: uri.path.split('/')[2] || nil,
      scheme: uri.scheme,
    }.compact
  }
```
【Xcode 10 Beta】While deserializing SIL global "UIEdgeInsetsZero" error: Abort trap: 6 がでてビルドに失敗する

## はじめに
Xcode 10 Beta を使って個人アプリの Swift のバージョンを
`4.1` から `4.2` にバージョンアップして，出たエラーの対応を
している際に下記エラーが発生してビルドが通らない。

` 1.	While deserializing SIL global "UIEdgeInsetsZero" error: Abort trap: 6`

Stackoverflow の記事[^1]を参考にして解決できました。

## 環境

* Swift 4.2
* Xcode 10 Beta 2
* macOS High Sierra (10.13.4)

## 解決策

どこかに下記のコードを書くと，ビルドが通るようになった。

```Swift
#if swift(>=4.2)
import UIKit.UIGeometry
extension UIEdgeInsets {
    public static let zero = UIEdgeInsets()
}
#endif
```

記事にあるように Xcode 10 Beta のリリースノート[^2](要ログイン)に
`UIEdgeInsetsZero` について記載がある。

> Use of the zero property on UIEdgeInsets causes a compiler crash in the “Merge swiftmodule” build step. The crash log will mention “UIEdgeInsetsZero” at the very end. (40735990)
Workaround: Use the initializer instead: UIEdgeInsets().

`UIEdgeInsets` で `zero` を使うとビルドの際にコンパイラクラッシュが起きる。
最後にクラッシュログとして `UIEdgeInsetsZero` について言及される。
解決策としては， `UIEdgeInsets()` をイニシャライザとして使いなさい。

## おわりに

今回は，Xcode 10 Beta で起きる `UIEdgeInsetsZero` 周りのエラーについて書きました。
リリースノートはしっかりみるべきだなと反省しました。

これまでの書き方が悪いのか `4.1` から `4.2` は結構赤くなる。
`bringSubviewToFront` とか `sendSubviewToBack` とかはわかりやすいからいいかな。
業務のプロジェクトたちの方はまだやっていないけどすんなり移行できるといいなぁ・・・(棒)

## 参考にした記事など
[^1]: [fatal error encountered while deserializing SIL global “UIEdgeInsetsZero”](https://stackoverflow.com/questions/50704200/fatal-error-encountered-while-deserializing-sil-global-uiedgeinsetszero/50706413#50706413)

[^2]: [Xcode 10 Beta Release Notes](https://download.developer.apple.com/Developer_Tools/Xcode_10_Beta_2/Xcode_10_Beta_2_Release_Notes.pdf)
MeCabでの形態素解析 on Mac

### 目的

形態素解析ツール MeCabをインストールして、pythonから使用できるようにする

## 環境

MacOX 10.12.6（16G1314） sierra

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

## インストール

Homebrewを使用してインストール

### MeCabのインストール
```
$ brew install mecab mecab-ipadic
```

### mecab-python3をインストール

```
$ pip install mecab-python3
```

## 実行

```python:mecab_sample.py
import MeCab

m = MeCab.Tagger()
print(m.parse("コーヒー牛乳とラーメン"))
```

実行

```
$ python mecab_sample.py
コーヒー	名詞,一般,*,*,*,*,コーヒー,コーヒー,コーヒー
牛乳	名詞,一般,*,*,*,*,牛乳,ギュウニュウ,ギューニュー
と	助詞,並立助詞,*,*,*,*,と,ト,ト
ラーメン	名詞,一般,*,*,*,*,ラーメン,ラーメン,ラーメン
```
「コーヒー」と「牛乳」がわかれてしまい、想定通りの結果にならないですね。
そこで、辞書の追加です！

## 辞書の追加

こちらを追加します。
https://github.com/neologd/mecab-ipadic-neologd

```
$ git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ ./bin/install-mecab-ipadic-neologd -n
```

## 辞書を使用した実行

```python:mecab_dic_sample.py
import MeCab

m = MeCab.Tagger('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
print(m.parse("コーヒー牛乳とラーメン"))
```
実行

```
$ python mecab_dic_sample.py
コーヒー牛乳	名詞,固有名詞,一般,*,*,*,コーヒー牛乳,コーヒーギュウニュウ,コーヒーギュウニュー
と	助詞,並立助詞,*,*,*,*,と,ト,ト
ラーメン	名詞,一般,*,*,*,*,ラーメン,ラーメン,ラーメン
```

想定通りになりました！

### 参考

MeCab
http://www.mwsoft.jp/programming/munou/mecab_command.html

mecab-ipadic-neologd(辞書)
https://github.com/neologd/mecab-ipadic-neologd
WSLにneovimを入れる

## はじめに

WSLに入っているVimはVersionが古い7.4です。
makeしていれてるのはちょっとめんどうなのでaptで入れられるneovimを
入れてみました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146663/a453e5d3-346b-8714-6a24-c45c12357ab0.png)


## インストール

https://github.com/neovim/neovim/wiki/Installing-Neovim

上記に書いてあることをなぞっていきます。

```
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:neovim-ppa/unstable
$ sudo apt-get update
$ sudo apt-get install neovim
```

入りましたー
![image.png](https://qiita-image-store.s3.amazonaws.com/0/146663/16cfc416-1ef8-10e5-81d2-6c3d58d2fbf2.png)

## dein.vimインストール
プラグインを管理するdein.vimを入れます

https://github.com/Shougo/dein.vim

```
$ curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
$ sh ./installer.sh ~/.cache/dein
```

.config/neovimディレクトリを作成してinstaller.shの出力結果をinit.vimに貼り付けます。

```
$ mkdir -p .config/nvim
$ nvim .config/nvim/init.vim
```

nvimを開くとプラグインを入れてくれれば設定OKです。

```
$ nvim
[dein] Not installed plugins: ['neosnippet-snippets', 'neosnippet.vim', 'deol.nvim']
[dein] Update started: (2018/06/26 17:24:11)[dein] Updated plugins:
[dein]   deol.nvim(1 change)
[dein]   neosnippet-snippets(1 change)
[dein]   neosnippet.vim(1 change)
[dein] Done: (2018/06/26 17:24:15)Press ENTER or type command to continue
```

call dein#add()行をコピペして入れたいのを書いて再度neovimを開けば必要なプラグインを入れてくれます。

```
 call dein#add('crusoexia/vim-monokai')
```

```
$ nvim
[dein] Not installed plugins: ['vim-monokai']
[dein] Update started: (2018/06/26 17:52:19)[dein] Updated plugins:
[dein]   vim-monokai(1 change)
[dein] Done: (2018/06/26 17:52:24)Press ENTER or type command to continue
```

```init.vim
"dein Scripts-----------------------------
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=/home/xxxx/.cache/dein/repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('/home/xxxx/.cache/dein')
  call dein#begin('/home/xxxx/.cache/dein')

  " Let dein manage dein
  " Required:
  call dein#add('/home/xxxx/.cache/dein/repos/github.com/Shougo/dein.vim')

  " Add or remove your plugins here:
  call dein#add('Shougo/neosnippet.vim')
  call dein#add('Shougo/neosnippet-snippets')
  call dein#add('crusoexia/vim-monokai')

  " You can specify revision/branch/tag.
  call dein#add('Shougo/deol.nvim', { 'rev': '01203d4c9' })

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
if dein#check_install()
  call dein#install()
endif

set background=dark
colorscheme monokai

inoremap jj <ESC>
```

それでは楽しいVimライフを！
THETAプラグインパートナープログラムはじめました

## 1.はじめに

こんにちは、リコーの@mrtakadaです。


本日、RICOH THETAプラグインパートナープログラムを開始しました。

開発者の方々には是非このプログラムに登録し、THETAを活用していただきたいと思っていますが、

- そもそもTHETAのプラグインって何？
- どんなことができるの？

という方も多いかと思います。

そこで、まずはTHETAのプラグインが生まれた背景も含め、私たちがどんなことを目指しているのかを簡単にお話ししたいと思います。

 
## 2.THETAのプラグインはなぜ生まれたのか？
THETAは360度を一回の撮影で簡単に記録できるカメラデバイスです。

単機能に特化しているが故にシンプルであり、また360度すべて映っている画像の有用性から、様々な応用可能性を秘めています。

![THETA_V.png](https://qiita-image-store.s3.amazonaws.com/0/265434/46928312-ba44-8ef0-707d-00b81496914a.png)

初代のRICOH THETAを2013年に発売して以来多くの企業・大学から、

- THETAを〇〇に応用したい。どうすれば良いか？
- 自社のシステムに連携するため、××の機能を追加してほしい

等々、多種多様な要望をいただいてきました。

しかし、リコーだけでその要望に応えていくことは到底不可能なため、2014年に無線LAN経由でTHETAをコントロールするための[API/SDK](https://developers.theta360.com/)を公開し、世の中の優秀な開発者の方々にTHETAと繋がる数多くのスマホアプリを開発いただいてきました。

その中には、私たち自身がやりたかったけれど様々な事情で実現できなかったものもあれば、想定すらしていなかった機能・使い方もあり、外部の叡智を巻き込んで世界を拡げていく「オープンイノベーション」の凄さ、素晴らしさを体感することができました。

そして、、、

 

**世界中の開発者と共に、もっともっとTHETAの可能性を拡げていきたい！**

 

そう考えて生まれたのが「プラグイン」です。


## 3.THETAのプラグインでどんなことができるの？

THETA VおよびTHETA Z1はAndroidベースのOSのため、Android向けに開発したアプリが動作します。AndroidベースのTHETA向けのアプリをリコーではプラグインと呼んでいます。

通常のAndroidスマホと比べていくつか異なる点があるため若干の工夫が必要ですが、これまではできなかった「**THETA(カメラ)内部をカスタマイズする**」ことができるようになりました。

例えば、

- THETAではできない単眼での180度撮影
- USB I/Fを持つデバイスを接続してTHETAからコントロールする
- 画像データをカメラから直接Webにアップロードしてリアルタイムで活用する

などなど。

業種業態に応じたビジネス応用機能から、ちょっと面白い個人向けの機能まで、これまで以上の自由度でアイデアを実現できるようになります。

また、開発したプラグインは7月にオープン予定のプラグインストアを通じて世界に発信できるようにしていきます。

![gainenzu.png](https://qiita-image-store.s3.amazonaws.com/0/265434/0d68a672-0ac1-17fc-ab39-ec1425c8ad8e.png)


## 4.プラグインの開発準備

プラグイン開発するための準備ですが、Androidアプリの開発環境さえあれば至って簡単です。

まずTHETA Vを用意いただき、下記リンクからプラグインパートナープログラムの内容をご確認のうえ開発者登録申請をお願いします。

[RICOH THETA Plug-in Partner Program](https://api.ricoh/products/theta-plugin/)


そこで開発用としてシリアルナンバー申請したTHETAは、簡単な登録審査完了後、THETA用PCアプリから開発者モードにすることができます。

（ただし、開発登録したTHETAはメーカーサポート対象外になるのでお気を付けください！）
 
あとは通常のAndroidアプリとほぼ同じ要領で開発いただけます。

上述したようにAndroidスマホと比べていくつか異なる点がありますが、開発者登録いただいた方にはテクニカルな面でのオンラインサポートも用意していますので、公開済みの[API/SDK](https://api.ricoh/docs/theta-plugin/)と共にご利用いただくことで、スムーズにプラグイン開発を進めることができると考えています。

また、このQiita上でも開発に役立つ情報をどんどん発信していきますので、是非ご覧いただければと思います。


## 5.おわりに
THETAは無限の可能性を秘めたデバイスです。

その可能性を開発者の方々と共に切り拓いていくため、**「できる限り多くの情報を公開し、開発をサポートしていく」**という方針で今回のパートナープログラムを準備してきました。

プラグインを通じて皆様のアイデアを実現し、是非一緒に360度の素晴らしい世界を拡げていきましょう！


興味を持たれた方は [twitter](https://twitter.com/thetaplugin)のフォローと
[THETAプラグイン開発コミュニティ(slack)](https://join.slack.com/t/thetadeveloper/shared_invite/enQtNzcxODI2MTk2ODg0LWY5YmU2ZTIxNGYwNzlmNWZjMWMyMWFlMzY3ZmQ3NGU3ZjZiZjI0Njk4MGIxMDU5NDJiMzQ4Y2FkNDEzYmFlNGU)への参加もよろしくおねがいします｡
【GoogleCloudPlatform】pythonでGCSバケットのデータを読み出す/書き出す

なんだかんだと時間がかかったので、自分用のメモも兼ねて。

**GCP上のインスタンスで、GCS (Google Cloud Storage)のバケット内データを読み書きするpythonコード**です。

pythonコードは Anacondaの jupyter notebookで実行しています。

#前準備：インストール
まず google cloud をインストール
```$ pip install google-cloud```
```$ pip install google-cloud-storage　(2019/01/30修正)```


#データの読み出し

```python

from google.cloud import storage as gcs

bucket_name = バケット名
fname = ファイル名
project_name = プロジェクト名

#プロジェクト名を指定してclientを作成
client = gcs.Client(project_name)
#バケット名を指定してbucketを取得
bucket = client.get_bucket(bucket_name)
#Blobを作成
blob = gcs.Blob(fname, bucket)
content = blob.download_as_string()
```

#データの書き出し

```python

from google.cloud import storage as gcs

bucket_name = バケット名
fname = ファイル名
project_name = プロジェクト名

#プロジェクト名を指定してclientを作成
client = gcs.Client(project_name)
#バケット名を指定してbucketを取得
bucket = client.get_bucket(bucket_name)
#Blobを作成
#2019/01/30修正
blob = gcs.Blob(fname, bucket)
blob.upload_from_string('test')
```
#403エラーが出る場合
VMインスタンスを動かしているPJとは別のPJのGCSにアクセスしようとすると、以下のようなエラーが出た。

* **エラーメッセージ**

```
Forbidden: 403 GET https://www.googleapis.com/download/storage/hogehoge: google_service_account_name@developer.gserviceaccount.com does not have storage.objects.get access to bucket_name/file_name.
```
* **原因**
どうやらVMインスタンスに紐づく**Googleサービスアカウントの権限の問題**のよう。(Googleサービスアカウントについては、[このページ](https://qiita.com/t-yotsu/items/5d3d36847fbc71b72b76)を参考にさせていただきました。)

* **解決策**
GCSのあるPJのIAMの権限設定で、エラーメッセージに表示されているサービスアカウントの権限設定を追加する。
（ひとまずアカウントをPJの編集者に設定してアクセス可能であることを確認しました。）
上記に加えて、バケットについても管理者権限が必要なようです。 （2019/07/03 追記）
たぶん一番簡単なmicro:bitのはじめかた Part2 LED編

#micro:bitのLEDを操作しよう

---
##micro:bitのLEDについて

---
###LEDの個数
micro:bitのLEDは5×5の25個あります。
文字については標準ではアルファベットと数字のみ表示可能。
![スクリーンショット 2018-06-27 15.54.07.png](https://qiita-image-store.s3.amazonaws.com/0/65643/ffd010ad-9764-4218-02ba-aabd5ff5d80a.png)


---
###あらかじめ用意されているアイコンが40個
![スクリーンショット 2018-06-27 15.52.10.png](https://qiita-image-store.s3.amazonaws.com/0/65643/3a8170e7-2efb-c5f9-b22c-f19a1939dae4.png)

---
###2桁以上の文字や数字は自動的にスライド
↓やってみよう！
![microbit-画面コピー-3.png](https://qiita-image-store.s3.amazonaws.com/0/65643/56ba0c3a-15b6-a900-3725-dc16e862f420.png)


---
###show ledsをつなげて点滅
点滅も0.5秒で切り替わるくらいのちょうどいい速さです。
![microbit-画面コピー-4.png](https://qiita-image-store.s3.amazonaws.com/0/65643/ad5f1f4b-2e4d-fd27-769d-912fb13aee8c.png)


---
###LEDの番号
LED＞点灯ブロックでは任意の場所のLEDを点灯できます。
横にx、縦にyでそれぞれ表示が制御されます。
こちらは瞬間表示です。
![スクリーンショット 2018-06-27 16.17.25.png](https://qiita-image-store.s3.amazonaws.com/0/65643/011a11db-7c34-e4d8-d412-bc1d837b2963.png)

---
####やってみよう！　心拍みたいな表示
![microbit-画面コピー-8.png](https://qiita-image-store.s3.amazonaws.com/0/65643/331ceaa1-a680-936d-f6e2-4a1650d5a629.png)
どっくんどっくん

---
####やってみよう！　順次点灯
![microbit-画面コピー-7.png](https://qiita-image-store.s3.amazonaws.com/0/65643/f769af4a-1bad-c42c-2467-720e1b38a9c6.png)
左上から順番に点灯します。


---
LEDで色々表示したり、切り替えたりしましょう。
Google Maps APIでzoom levelに応じてmarkerの画像やサイズなどを変える

##やりたいこと
zoom levelに応じてmarkerの画像やサイズを変えたい

##コード

```gmapsample.js
google.maps.event.addListener(map, 'zoom_changed', function(e){
	const currentzoom = map.getZoom();
	if(currentzoom < 12){
		for(let i in marker) {
			let image = {
 				url: '/img/smallerIcon.png',
    				anchorPoint: new google.maps.Point(0,0),
    				scaledSize: new google.maps.Size(50,50),
  			};
        		marker[i].setIcon(image);
    		}
	}
});
```
`zoom_changed`のイベントリスナにzoom levelに応じた処理を書いて、最後にmarkerそれぞれに`setIcon()`メソッドを呼べばmarkerの設定が変わります。
上記の例ですと、`image = `でmarkerの設定を書いて、`marker[i].setIcon(image)`でセットしています。

以下はsetIconに関する参考です。
[setIcon](https://developers.google.com/maps/documentation/javascript/reference/3/marker#Marker.setIcon)
[google.maps.Icon interface](https://developers.google.com/maps/documentation/javascript/reference/3/marker#Icon)
DialogflowAPIでIntent作成時に、intentのIDを取得する方法

# 概要

Dialogflow V2 API使用時に、Intentを作成したのですが、戻り値にはIDは含まれていません。
そうすると、更新や削除のときに困ってしまい、APIとして機能しないので、IDの取得法の備忘録として書きました。

# 本題

以下、TypeScriptで書いてます。
accessTokenはすでに取得している前提で始めます。

```index.ts
import axios from 'axios'

async function main() {

    const URL = 'https://dialogflow.googleapis.com/v2'
    const projectId = 'test'
    const accessToken = 'hogehoge'

    let http = axios.create({
        baseURL: `${URL}/projects/${projectId}/agent/intents`,
        // timeout: 1000,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${accessToken}`,
        },
    })

    const { data } = await http.post('', {
        displayName: 'Greeting',
        webhookState: 'WEBHOOK_STATE_UNSPECIFIED',
        priority: 5000000,
        isFallback: false,
        mlDisabled: false,
        trainingPhrases: [
            {
                'type': 'EXAMPLE',
                'parts': [
                    {
                        'text': 'Hello!',
                    },
                ],
            },
        ],
        'action': 'greeting',
        'messages': [
            {
                'text': {
                    'text': [
                        'Hello!',
                    ],
                },
            },
        ],
    },
    )

    const intentId = data.name.split('/').pop()
}

main()
```

`main`関数の最終行に注目してください。

```
const intentId = data.name.split('/').pop()
```

Dialogflow V2 APIの戻り値は以下のようになっています。

```
{
  "name": "projects/test/agent/intents/15933e2c-63f4-45c9-87c2-f69a4a19f71a",
  "displayName": "Greeting-again",
  "priority": 500000,
  "action": "greeting",
  "messages": [
    {
      "text": {
        "text": [
          "Hello!"
        ]
      }
    }
  ]
}
```
上記の`name`の中の`intents`以降がintentのIDです。

そのため、`/`で`split`して、最後のものを`pop`しています。

APIのリファレンスを読まないと、IDが返ってくるものと勘違いしてしまいがちですが、返ってこないんですね。
思い込みでやったら危険ということを改めて認識しました。
ヤフオクとBuyeeをNodejsでスクレイピング


それぞれの場合で「canon カメラ -ジャンク」のキーワードで調べみました。

##1 ヤフオク
ポイント
・検索キーワードをエンコードしてはいけない（エンコードするとヤフオク側でデコードしてくれない）
・検索キーワードに「+」が入っている場合、半角スペースに置き換えなければならない
・開催中のオークションを調べたいなら　"/search/search"
・過去１２０日間のオークションを調べたいなら　"/closedsearch/closedsearch" （日付は120日しか指定不可）

```scriping_yahuoku.js
  const cheerio = require("cheerio-httpcli");
  const keyword = "canon カメラ -ジャンク";
  const res = cheerio.fetch("https://auctions.yahoo.co.jp/closedsearch/closedsearch",{
    p : keyword,  
    select : "02",//並び順 落札価格の高い順 絶対に 02 のように0をつける
    istatus : 2,//新品だけで絞るなら1 中古だけなら2
    ngram : 1, //あいまい検索するなら1を指定
    ei:'UTF-8',fixed:0,auccat:0,tab_ex:'commerce',slider:0
  });
  
  const price = Number(res.$(".ePrice").first().text().replace(/\D/g,"")); //検索結果の一番上の落札価格
  
  //上記の条件でfetchした場合、直近30日の最高落札価格を取得する場合は下記のようにする
  const moment = require('moment');
  const today = moment();
  res.$(".d").each(function(i,el){
    end_day = moment(res.$(this),'MM-DD');
    if(today.diff(end_day, 'days') <= 30){
      pr3 = res.$('.ePrice').eq(i).text().replace(/\D/g,'');
      return false;
    }
  });
```

##2 Buyee
ポイント
・検索キーワードは空白を「+」に置き換えしてからエンコードする（encodeURIでOK）
・問題無くfetchできたのにエラー吐く時がある。その際はエラーオブジェクトにcheerioオブジェクトが入っている

```scriping_buyee.js
  const cheerio = require("cheerio-httpcli");
  const keyword = "canon カメラ -ジャンク";
  const res = cheerio.fetch('https://buyee.jp/item/search/query/' + encodeURI(keyword.replace(/\s/g, '+')), {
    item_status: 2, //中古
    translationType: 1,
    order: 'd',
    sort: 'end'
  }).then((result) => {
    return Promise.resolve(result);
  }, (err) => {
    if (err.$) {
      console.log('$があるからこれがcheerioオブジェクト');
      return Promise.resolve(err);
    } else return Promise.reject(err);
  });

  const date_text = res.$('.generalicon-clock').first().text();
  var p = 0;
  var p1 = 0;
  var p2 = 0;

  if (date_text) {
    const date = time.replace(/日/, ""); //検索結果の一番上のオークション残り開催日数
    try {
      data.auction_url = "https://page.auctions.yahoo.co.jp/jp/auction" + (res.$('.product_whole').first().find('a').first().attr('href').match(/\/[a-z]*\d{9,}$/)[0]); //オークションIDを抜き出してヤフオクのオークションページURLを取得する
    } catch (e) {
      data.auction_url = 'Error';
    }

    //現在価格の最高額を求める
    res.$('.product_price').each((i, el) => {
      p = Number(res.$(el).text().replace(/\(.+\)/g, '').replace(/\D/g, ''));
      if (p > pr1) pr1 = p;
    });

    //即決価格の最高額を求める
    res.$('.product_bidorbuy').each((i, el) => {
      p = Number(res.$(el).text().replace(/\(.+\)/g, '').replace(/\D/g, ''));
      if (typeof (p) == Number && p > pr2) pr2 = p;
    });
  }
```
オブジェクト指向について

##オブジェクト指向とは
C#を勉強する中でよく目にするオブジェクト指向について、つまりどういう意味なのかを少し調べてみた自分の見解を少し書いてみたいと思います。

ネットや教科書でオブジェクト指向について調べてみました。結果自分の読解力の無さのせいでそれぞれ違うとらえ方をしているように見えてしまってボンヤリとした印象でしか捉えることができませんでした。
その中で自分なりに考えたオブジェクト指向とは、一つの大きな目的を達成するために必要な要素を細分化して制作して、出来上がったものを一つにまとめて完成させるようなそんなイメージでした。

他にもオブジェクト指向で進行する中でカプセル化といって細分化したオブジェクトの中の他人に操作されたくないようなメンバをアクセス修飾子を使うことで隠蔽していくといった事も行うようです。

##まとめ
オブジェクト指向は実際に仕事を始めてプロジェクトに携わって経験を積まないとはっきりとしたビジョンは見えてこないのかなと思いました
[Python3.6]画像を任意の枚数に分割する


一枚の画像を任意の枚数に分割するコードです。
縦、横の分割枚数、どんなサイズで分割させるかを指定します。

```python:sample.py
from PIL import Image
import os
import sys

from datetime import datetime

def ImgSplit(im):
    # 読み込んだ画像を200*200のサイズで54枚に分割する
    height = 200
    width = 200

    buff = []
    # 縦の分割枚数
    for h1 in range(6):
        # 横の分割枚数
        for w1 in range(9):
            w2 = w1 * height
            h2 = h1 * width
            print(w2, h2, width + w2, height + h2)
            c = im.crop((w2, h2, width + w2, height + h2))
            buff.append(c)
    return buff



if __name__ == '__main__':
    # 画像の読み込み
    im = Image.open('./test/IMG_0025.JPG')
    for ig in ImgSplit(im):
        # 保存先フォルダの指定
        ig.save("./test2/test" + datetime.now().strftime("%Y%m%d_%H%M%S%f_") +".jpg", "JPEG")
```

#追記

コメントでジェネレータを利用して、使用メモリ節約するコードを教えていただきました。

今回ジェネレータというのを初めて聞いたのですが、「return文をyieldに置き換えたもの」のようです。
（参考：[Pythonのジェネレーターってなんのためにあるのかをなるべく分かりやすく説明しようと試みた](https://qiita.com/keitakurita/items/5a31b902db6adfa45a70)）

```python
from PIL import Image
import os
import sys

from datetime import datetime

def ImgSplit(im):
    # 読み込んだ画像を200*200のサイズで54枚に分割する
    height = 200
    width = 200

    # 縦の分割枚数
    for h1 in range(6):
        # 横の分割枚数
        for w1 in range(9):
            w2 = w1 * height
            h2 = h1 * width
            print(w2, h2, width + w2, height + h2)
            yield im.crop((w2, h2, width + w2, height + h2))

if __name__ == '__main__':
    # 画像の読み込み
    im = Image.open('./test/IMG_0025.JPG')
    for ig in ImgSplit(im):
        # 保存先フォルダの指定
        ig.save("./test2/test" + datetime.now().strftime("%Y%m%d_%H%M%S%f_") +".jpg", "JPEG")
```
AIグルメBOT

#AIグルメBOTとは
<img src="https://qiita-image-store.s3.amazonaws.com/0/242602/31ceadf6-f447-b542-117e-9a138f23defe.png" width="200">
飲食レビューをAIが自動生成し、twitterにてつぶやき続けます。

[@selteclab](https://twitter.com/selteclab)

#学習モデル
リカレントニューラルネットワーク(RNN)の一種であるGRUをアルゴリズムとして採用し、文字レベルの日本語文章生成を実装しました。また、深層学習ライブラリはPyTorchを利用しています。教師データは、東京都内の飲食店のクチコミ文章10万件、文字数にして6698万文字の日本語データです。

文章生成の実装については、以下URLに投稿してあります。
[10万件の飲食店クチコミからRNNで文章を生成](https://qiita.com/sudamasahiko/items/cf7e4b0f372aa41d5402)

#今後の課題
生成された日本語に対して、人間の判断で内容を修正するなどはほとんど行っていないため、おかしな文章が少なからず含まれる点はあらかじめご了承ください。文章の意味に取り組むのは現時点ではかなり難しく、文章生成と辞書の関係、文法との関係など、課題とさせていただきます。

AIグルメBOTをどうぞ、よろしくお願いいたします。
DocBaseのメモに特定のタグが付いていたらSlackへ本文の投稿を抑止する

せっかくなのでこちらにも投稿しておきます。

https://github.com/snaka/docbase-post-filter

## これは何？

DocBase の WebHook を Slack の Incoming WebHook に中継するWebHookアプリケーションです。
ただし、タグに `secret`, `confidential`, `秘密` が含まれている場合、メモの内容自体はSlackに投稿されません。

メモの登録と更新のみに対応しています。

例えば以下のような感じです。

`secret`タグを含まないメモ（投稿にメモの内容が含まれる）

![](https://gyazo.com/5e42b281a325986594967813143465a4.png)

`secret`タグを含むメモ（投稿にメモの内容が含まれない）

![](https://gyazo.com/723cae0783c91671212c5ac9b0fc812e.png)



## 使い方

以下、heroku にデプロイする例です

### デプロイ

あらかじめ Slack で Incoming WebHook の設定を行い URL を取得しておく。

その後、以下のボタンを押して heroku にWebアプリケーションをデプロイする。（デプロイ時に WebHook のURLを聞かれるので先に取得しておいた Slack の WebHook の URL を設定する）

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

あるいは、以下のように手動でデプロイ（`SLACK_WEBHOOK_URL` にはあらかじめ取得しておいたSlackの WebHook URL を設定する）

```
$ heroku create
$ heroku config:set SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxxxxxxxxxxxxxxxx
$ git push heroku master
```

### DocBase の設定

DocBase の設定画面「サービス連携」を開き、サービスの中から Webhook を選択して Webhook URL に heroku にデプロイしたアプリケーションの URL を設定します。

アクティビティは「メモを公開」と「メモを更新」を選択します（他のアクティビティには対応していません）

![](https://gyazo.com/4e2823955f7d7fcfa91836fe552dcf5c.png)

上記のように設定後、「連携を開始する」ボタンを押すと設定完了。
Laravel migrateでdropUnique行う時に「needed in a foreign key constraint」が発生する場合の対応

# 前提（というか私の環境）
Laravel 5.5
PHP 7.0

# 起きたこと

開発環境のDBをクリアしようと以下コマンドを実行したところ、、、
```
php artisan migrate:refresh --seed
```

マイグレーションのロールバックに失敗する！！！

```
In Connection.php line 664:

  SQLSTATE[HY000]: General error: 1553 Cannot drop index 'xxxxxxxxxx_unique_index': needed in a foreign key constraint (SQL: alter table `xxxxxxxxxx` drop index `xxxxxxxxxx_unique_index`)


In Connection.php line 458:

  SQLSTATE[HY000]: General error: 1553 Cannot drop index 'xxxxxxxxxx_unique_index': needed in a foreign key constraint
```


# 対応
外部キー制約でエラーが発生してしまっているので、外部キー制約を一時的にとっぱらうよう記述する
https://readouble.com/laravel/5.5/ja/migrations.html#foreign-key-constraints

```php
public function down()
{
    Schema::disableForeignKeyConstraints();
    Schema::table('xxxxxxxxxx', function (Blueprint $table) {
        $table->dropUnique('xxxxxxxxxx_unique_index');
    });
    Schema::enableForeignKeyConstraints();
}
```



もしかして、テーブル設計がそもそも間違ってたかな……。
[AWS Lambda] invokeAsync ではなく invoke を使おう

# 概要
掲題の通り、invokeAsync ではなく invoke を使う方が推奨されているよ、という話。

#  内容

[invokeAsync のリファレンス](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invokeAsync-property)を見ると、↓のように書かれている。

```
This API is deprecated. We recommend you use Invoke API (see Invoke).
```

なので、[invoke](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property) を使うべし。

# サンプルコード

invokeAsync を使った例

```js
'use strict';
var aws = require('aws-sdk');

module.exports.invoke_hello = (event, context, callback) => {

  var lambda = new aws.Lambda();
  var params = {
    FunctionName: "myServiceTokinaga-dev-hello",
    InvokeArgs: JSON.stringify(event),
  };

  lambda.invokeAsync(params, function(err, data){
    if(err) {
      console.log("invoke error")
      context.done(err, err);
    } else {
      console.log("invoke done")
      context.done(null, '');
    }
  });
};

```

invoke を使った例


```js
'use strict';
var aws = require('aws-sdk');

module.exports.invoke_hello = (event, context, callback) => {
  var lambda = new aws.Lambda();
  var params = {
    FunctionName: "myServiceTokinaga-dev-hello",
    InvocationType: "Event",
    Payload: JSON.stringify(event),
  };

  lambda.invoke(params, function(err, data){
    if(err) {
      console.log("invoke error")
      context.done(err, err);
    } else {
      console.log("invoke done")
      context.done(null, '');
    }
  });
};
```
vuforia for UnityでスマホARしようとしたけど実機で画面が出ない時

#はじめに
##概要
vuforia for UnityでiPhoneARコンテンツを作ろうと思い、いつも通りUnity&Xcodeでビルドし実機で実行しようとしたところ、PCではちゃんと動くのに実機ではカメラの絵が出ず真っ黒（フリーズではない）になったり、その他色々つまって動かない症状にはまったので、目次録。基礎的なvuforiaの使い方については書かないので、他記事と並行して参考にしてください。

##ARライブラリについて
iPhoneでARを行うためのライブラリとしてまず思いつくのは[ARkit](https://developer.apple.com/jp/arkit/)です。これは導入も簡単で高精度なポジショントラッキングを提供しますが、画像（マーカ）を認識して3Dオブジェクトを追従させるという処理を実装するのは個人的に少し面倒くさいです。そこで、マーカベースでポジショントラッキングを行う[vuforia](https://developer.vuforia.com/)というAR用ライブラリがUnity2017.2から標準でサポートされているため、今回はvuforiaを使ってこんなのを作ろうと思いました。
（「こんなの」の資料は準備中）

#結論

##2018.05.23現在、最終的に落ち着いた環境
結論から言うと、2018年5月23日現在、iPhone向けにUnityとvuforiaを使って何かを作ろうと思った時、安定して動くのは以下の環境です。
- Unity 2018.1.1
- vuforia 7.1.35 （上記Unityバージョンに付いてくるやつ）
- iOS 11.3
- Xcode 9.2 （**要設定** - 「Xcode9.2の設定」を参照）


#ハマった点

##Unityの設定
以下では、Unityでvuforia appをビルドするための、Unity側ですべき設定を列挙します。

###vuforiaを有効にする
「Edit > Project Settings > Player」でPlayer Settingsを開き、XR SettingsのVuforia Augmented Realityにチェックを入れる

###カメラの使用目的を書く
アプリがOSからカメラの使用権を得るために、カメラのUsage Descriptionを書かないといけないみたいです。「Edit > Project Settings > Player」でPlayer Settingsを開き、Other Settingsの真ん中あたりにあるCamera Usage Descriptionにカメラの使用目的を記述します。厳密には ``` "" ```(何も書かない)以外ならなんでもいいっぽいですが、私は一応「Camera access required for target detection and tracking」と書いておきました。

###ARcameraのclear flagsについて
「GameObject > Vuforia > ARcamera」で追加できるARカメラですが、同ゲームオブジェクトにアタッチされているCameraスクリプトのClearFlagsがSkyboxになっていると実機で実行してもカメラの映像が映らずデフォの青々しい空が見えるだけになります。Clear FlagsはSolid Colorがおすすめです。

##Xcode9.2の設定
以下では、Unityで生成したXcodeのプロジェクトファイルをビルドするための設定を列挙します。
###iOS11.3対応のための荒技（重要）
[このポータル](https://developer.vuforia.com/forum/ios/resolution-vuforia-7-ios-113-black-screen-problem)によると、Unity 2018.1.1についてくるvuforia 7.1.35はXcode9.3と9.4に対応していないようです。そこで、Xcode9.2（iOS11.3には通常非対応、[ここからDL](https://developer.apple.com/download/more/#)）を使い、[この動画](https://www.youtube.com/watch?v=3roMSonIG5c)を参考にiOS11.3のsignatureファイル的なものをXcode9.3等から持ってくるという荒技を行います。すると、通常ではiOS11.3がサポートされていないXcode9.2で、同iOSバージョン向けにアプリをビルドできるようになります。
（この情報、日本語で記述されたものが多分ないので、貴重な情報だと思ってます）

###Signing for "Unity-iPhone" requires a development team.が消えない
[この記事](https://qiita.com/r-ngtm/items/c058c89f4acd7199f76a)を参照。

#まとめ
iOSやxcode、Unityのバージョンなどで、一発で開発環境が整う場合と全くそうでない場合があるので、怖い。しかも、iOSとかダウングレードできないし、超タイミング依存ですよね。また、時が経ちバージョンアップすると、すべてのバグ修正されてしまい本記事が全く役に立たなくなる日も来るでしょう。誰かの役に立てば幸いです。

<!--
Unity2017かUnity2018のvuforiaのバージョンの違い
player settingsのxr settingsでenable vuforiaにする
camera usage descriptionを書く
ARcameraのclear flagsをSkyboxにするとあかん
xcodeのSigning for "Unity-iPhone" requires a development team.が消えない（https://qiita.com/r-ngtm/items/c058c89f4acd7199f76a）
xcode実行時にtoo busy...と出る（http://www.crossroad-tech.com/entry/Xcode_deploypending）
Xcode9.3からXcode9.2にする（ここが一番コア） this guy https://developer.vuforia.com/forum/ios/resolution-vuforia-7-ios-113-black-screen-problem did really good stuff for me.
https://www.youtube.com/watch?v=3roMSonIG5c
-->
Excelで列の値が条件に一致する行を別の場所に抜き出して表示する

# やりたいこと
- 1行目を見出しとして2～50行目までの表から、F列が"条件"である行を別の場所に抜き出して表示したい。
- VBAは使わず、関数のみで実現する。

# 関数
```vb
=IF(ROW(A1)>COUNTIF($F$2:$F$50,"条件"),"",INDEX(A$1:A$50,SMALL(INDEX(NOT($F$2:$F$50="条件")*1000+ROW($A$2:$A$50),),ROW(A1))))
```

# 解説
## IF(ROW(A1)>COUNTIF($F$2:$F$50,"条件"),"",
エラー判定部分です。
条件に一致する行数よりも現在抽出しようとしている行数が大きい場合、空白文字を返します。
現在の行数を後述のSMALL関数内部で順位として使用しているため、条件に一致する行数より大きい値を指定すると1000を加算した行が選択されてしまい、#REFエラーになってしまいます。
これを回避するため、現在抽出しようとしている行数が条件に一致する行数よりも大きい場合は空白文字を返すようにしています。
なお、`ROW(A1)`の部分が現在抽出しようとしている行数を表すため、どんな場合でも`A1`固定にします。

## SMALL(INDEX(NOT($F$35:$F$53="条件")*1000+ROW($A$35:$A$53),),ROW(A1))
`INDEX(NOT($F$35:$F$53="条件")*1000+ROW($A$35:$A$53),)`は、条件に一致しない行は1000+行番号、一致する列は行番号となる配列を返します。
例) 2,5,6行目が一致する場合→[2,1003,1004,5,6,1007,1008,...]
ここから、SMALL関数で[現在抽出しようとしている行数]番目に小さい値を取得しています。
ここも`ROW(A1)`が現在の抽出行数を表すため、`A1`固定です。

これにより抽出した行番号を用いて、外側のINDEX関数で対象行を抽出する仕組みです。

# こんな時は
## 抽出結果が連続しない(間に空行がある)場合
1行目に1番目、4行目に2番目...という感じで抽出結果が連続しない場合、`ROW(A1)`で抽出行数を指定してしまうと1行目は1番目、4行目は4番目...になってしまい、間の結果が抜けてしまいます。
この場合、最初と最後の`ROW(A1)`の部分をCOUNTA関数に置き換えることで解決できます。
### 例) A101,A104,A105に1,2,3番目の抽出結果を表示する場合
```vb
A101=IF(COUNTA($A$100:$A100)>COUNTIF($F$2:$F$50,"条件"),"",INDEX(A$1:A$50,SMALL(INDEX(NOT($F$2:$F$50="条件")*1000+ROW($A$2:$A$50),),COUNTA($A$100:$A100))))
```
※A100が空白セルの場合は`COUNTA($A$100:$A100)+1`とする。

A101をコピーし、A104,A105にペーストします。

## 検索対象の表がシートの一番上にない場合
検索対象の表が一番上にない場合は、取得した行番号から表開始位置の前行までの行数を引いてやる必要があります。
### 例)検索対象の表が、34行目を見出しとして35～50行目の場合
```vb
=IF(ROW(A1)>COUNTIF($F$35:$F$50,"条件"),"",INDEX(A$34:A$50,SMALL(INDEX(NOT($F$35:$F$50="条件")*1000+ROW($A$35:$A$50),),ROW(A1))-ROW($A$33)))
```
引いてやる必要があるのは、SMALL関数で行数を取得した結果に対してです。
また、引いてやる数は常に固定なので、セル番地は絶対指定で指定します。

# 検索条件のバリエーション
検索条件を変更する場合、修正対象は以下の2か所です。
1. IF関数条件式のCOUNTIF関数部分
2. SMALL関数内のINDEX関数部分

## AND/OR条件
COUNTIF関数部分は、Excel2007以降ならAND条件にCOUNTIFS関数、それ以前のバージョンはSUMPRODUCT関数を利用します。OR条件の場合はCOUNTIFの和を利用します。
INDEX関数内で条件指定する方法は、SUMPRODUCT関数の条件指定と同様です。

### AND条件
```vb
COUNTIFS($F$2:$F$50,"条件1",$G$2:$G$50,"条件2")
SUMPRODUCT(($F$2:$F$50="条件1")*($G$2:$G$50="条件2"))

SMALL(INDEX(NOT(($F$2:$F$50="条件1")*($G$2:$G$50="条件2"))*1000+ROW($A$2:$A$50),),ROW(A1))
```

### OR条件
```vb
COUNTIF($F$2:$F$50,"条件1")+COUNTIF($G$2:$G$50,"条件2")

SMALL(INDEX(NOT(($F$2:$F$50="条件1")+($G$2:$G$50="条件2"))*1000+ROW($A$2:$A$50),),ROW(A1))
```

## あいまい検索
COUNTIF関数部分はワイルドカード(\*)が利用できるため特に問題はありません。
INDEX関数の条件指定ではワイルドカードが使えないため、あいまい検索を利用したい場合は文字列操作関数を利用する必要があります。

### 前方一致
```vb
COUNTIF($F$2:$F$50,"条件*")

SMALL(INDEX(NOT(LEFT($F$2:$F$50,2)="条件")*1000+ROW($A$2:$A$50),),ROW(A1))
```

### 後方一致
```vb
COUNTIF($F$2:$F$50,"*条件")

SMALL(INDEX(NOT(RIGHT($F$2:$F$50,2)<>"条件")*1000+ROW($A$2:$A$50),),ROW(A1))
```

### 部分一致
```vb
COUNTIF($F$2:$F$50,"*条件*")

SMALL(INDEX(NOT(ISNUMBER((FIND("条件",$F$2:$F$50))))*1000+ROW($A$2:$A$50),ROW(A1))
```
C# Log4netでログ出力時に設定したメッセージ内容を置き換える

## Log4netでログ内容を置き換える

Log4netはよく使っていますが、普通にログ出力くらいの機能しか使っていなかったのと
あまり日本語のサイトも引っかからなかったので一応書いて残しておきます。
※当たり前すぎて書いてないだけかもしれませんが…



## ログ出力する内容を一律なんか置き換えたりしたい！
そんなことたまにありますよね。
そういう時はこうすればOKのようです。


まずlog4netのPatternLayoutConverterを継承したクラスを作ります。
名前はなんでもいいです。
Convertメソッドをオーバーライドします。

```C#:MessageConverter.cs
namespace MyApp.Log
{
    public class MessageConverter : PatternLayoutConverter
    {
        protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
        {
            // なんか色々文字置換とかの処理をここでしましょう
            
            // ↓このままだと、設定されたメッセージがそのまま出力されるので、いい感じに変えてください
            writer.Write(loggingEvent.RenderedMessage);
        }
    }
}
```

xmlのlayoutタグ内のクラスの指定やら云々

```xml:log4net.xml
    <layout type="log4net.Layout.PatternLayout">
      <!-- ↓このconverterタグを追加 --> 
      <converter>
        <!-- ↓conversionPatternのmessageを指定してます --> 
        <name value="message" />
        <!-- ↓クラスはここで指定 --> 
        <type value="MyApp.Log.MessageConverter" />
      </converter>
      <!-- ↓これはいい感じにログを出すのに形式書いてるだけなので元からあるんじゃないかと --> 
      <conversionPattern value="%date{yyyy-MM-dd HH:mm:ss,fff} (%class.%method:%line) - %message%newline" />
    </layout>
```


---
エラーログだけとかデバッグログだけとかの設定も可能です。
DELL のサーバーの ディスク交換をしてみた @PowerEdge

# トラブル発生
先日、DELLサーバーの４つあるディスクスロットのランプが
正常時は緑であるのに対して
１つだけオレンジ色になっていた
<img width="792" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265300/8b4e44b6-6f71-0a9c-f51a-cf197a28ebb0.png">

# サポートに聞いてみた
DELLのサポートに問い合わせた所、「ディスクの故障と判断致します」との事
なので
ディスクを注文しようとした所、サポートから意外な回答が
既にディスクの在庫はなく、
残りの在庫は保守に入っていただいているお客様用に取り分けたものであるとの事

なので部品番号をお伝えいたしますので
お客様で個別に手配願います。と

# どっかで売ってないかな？
DELLのサポートからいただいた部品番号を元に調べた所
amazonにて約16,000円で売っている物を発見:rolling_eyes:

早速購入し、到着
スロット用のカートリッジ付＆未開封で
<img width="215" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265300/aa450e84-2b1a-2c92-281d-4e47d38ec533.png">

# どーやって交換するの？
DELLのサポートへ交換方法を問合せた所、
下記のような回答が
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
今回はHDD#0:1:0が失敗の状態のため、
HDDのオフライン操作は不要でございます。
不具合HDDをそのまま取り外しをお願いいたします。
 
なお、交換方法およびリビルド方法につきましては、以下のURLをご参照ください。
 
■HDD交換方法
HDDの取り外し方法および取り付け方法につきましては、以下のURLをご参照ください。
 
Dell PowerVault NX400 システム オーナーズマニュアル
http://downloads.dell.com/manuals/all-products/esuprt_ser_stor_net/esuprt_powervault/powervault-nx400_owner%27s%20manual_ja-jp.pdf
※48～49ページ「ホットスワップ対応ハードディスクドライブの取り外し」「ホットスワップ対応ハードディスクドライブの取り付け」をご参照ください。
 
■リビルド方法
HDD交換後、通常は自動でリビルドが開始されます。
HDDLEDが青色点滅、Server  Administratorにて再構築中のステータスになった場合は特に下記操作は不要でございます。
自動でリビルドが開始されない場合は、以下の手順をご確認の上リビルドのご実施をお願いいたします。
 
[OMSA] OpenManage Server Administratorを利用したリビルド手順
https://www.dell.com/support/article/SLN287354/ja
＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

どうやら今回はHDD#0:1:0が失敗の状態の場合のディスク交換方法の為、
ディスクをオフライン化させる必要はない模様

# 交換開始
サーバ筐体左横の赤丸ボタンを押すと
<img width="472" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265300/52a1b9a1-948e-ff18-c97b-d3c59f3d93cd.png">
このように開くので
<img width="516" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265300/f19ee26b-71ea-712a-7fe2-1b6ae08a012b.png">
そのまま引き抜く
<img width="253" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265300/eb79a58d-cb39-bbce-8b0e-54293ff22f2f.png">
空いたスロットに新しいディスクを挿入するとランプが緑に
<img width="291" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265300/f8b3b1da-43e2-9b95-b007-7aa3e4437a0a.png">
念の為、管理コンソールからディスクを認識しているか確認
<img width="305" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265300/6b79266b-3e95-8c1f-9798-f9c44da8fa52.png">
再構成中と表示されているので問題ない

RAIDの構成中である
進捗は１Hで10％程（全１TB）
Docker + Node.js のデバッグ Visual Studio Code編

前に[「chrome devtools」でのデバッグ手順](https://qiita.com/tailix/items/987df0f85dcc79662cb4)を題材にしましたが、今回は「Visual Studio Code」のデバッグ設定です。環境は前と同じなので「Visual Studio Code」の設定だけ記載します。

## 「Visual Studio Code」の設定

### 1. launch.jsonを作成
デバッグ(上部メニュー) → 構成の追加 → 「Docker: Attach to Node」を選択
![2018-06-25_11h17_59.png](https://qiita-image-store.s3.amazonaws.com/0/262751/7f2f3172-5bfc-b978-55fe-3981a24250fc.png)

デバッグビュー(VS Codeの横にあるアクティビティーバーのデバッグ(虫)アイコンをクリック) のトップバーにある歯車アイコンや、隣のドロップダウンでも作成出来ます。
![2018-06-22_18h48_12.png](https://qiita-image-store.s3.amazonaws.com/0/262751/224fc9b5-cdf1-4d8e-a10f-b75faf62efa8.png)

### 2. launch.json を編集
```json:launch.json
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Docker: Attach to Node",
            "port": 9229,
            "address": "localhost",
            "localRoot": "${workspaceFolder}\\app",
            "remoteRoot": "/home/node/app",
            "protocol": "inspector",
        }
    ]
```

- "type" 使用するデバッガの種類です。nodejsであれば"node"、phpであれば"php"を指定といった感じです。
- "request": "attach" は既に実行中のプログラムをデバッグする際に指定します。今回はDockerで起動したプログラムにアタッチする形でデバッグを行います。
- "name" はデバッグを起動する際に、どのデバッグ設定を使用するかの選択に使われます
- "port": 9229、"address": "localhost" にアタッチ
- localRootとremoteRootは前回作成した環境に合せています。 ※あと私はwindows環境なのでパスに\が含まれています
- "protocol": "inspector" Node.js、VSCodeが古くなければ"inspector"で問題ないかと思います。バージョンが気になる方は"auto"、古い方は"legacy"が指定できます。

### 3. デバッグ開始
`docker-compose up -d`でコンテナを起動し、VS Codeのデバッグビューのトップバーで「Docker: Attach to Node」(launch.jsonのnameに指定した値)を選択し、デバッグ開始。

ブレークポイントを設定すると止まります。
![2018-06-27_15h38_54.png](https://qiita-image-store.s3.amazonaws.com/0/262751/8909e61e-3b7f-0674-c446-5e73e0e206ca.png)

## まとめ
以上が、Visual Studio Codeのデバッグ設定です。VS Code側は launch.json ファイルを作成・設定するだけなので簡単です。やはりどちらかと言えば、nodejsの起動オプション(--inspect=0.0.0.0:9229) の方がハマる可能性高そうですね。