OmniAICreator/Qiita-1.07M huggingface dataset:
SpringアプリケーションからFirebase Cloud MessagingへのPush配信

# Firebase

Googleが提供しているメッセージを無料で確実に配信するためのクロスプラットフォーム メッセージング ソリューションの事です。

先日行われた[Google I/O 2017](https://events.google.com/io/)でも基本機能に加えて、解析系の機能で大幅改善されたようです。

今回はそんなFirebase Cloud Messaging(以下、FCM)をサーバーサイドから呼び出す際にいくつかハマるポイントがあったので、備忘録としてまとめます。

## FCMとFirebase Notificationsの違い

### FCM

モバイル端末やWebブラウザ等、幅広いターゲットに対して柔軟性のあるプッシュ配信を行う事が出来る仕組み。
基本的には各言語で送信処理を実装する必要がある。

### Firebase Notifications

プッシュ通知をFirebaseダッシュボード上から送信することが出来る仕組み。
実装の手間がないので楽だが、シンプルなプッシュ通知しか出来ない。

今回は前者について簡単にまとめます。


## リクエスト情報

- FCMエンドポイント：https://fcm.googleapis.com/fcm/send
- メソッド：POST
- リクエストヘッダー：
  - Authorization: key={サーバーキー}
  - Content-Type: application/json;application/x-www-form-urlencoded;charset=UTF-8

## レスポンス情報

上記の形式でHTTP通信をすると以下のようなレスポンス情報が返ってきます。
[公式：FCMレスポンス](https://firebase.google.com/docs/cloud-messaging/http-server-ref?hl=ja#table5
)

```json:FCMレスポンス例
{
 "multicast_id":6782339717028231855,
 "success":0,
 "failure":1,
 "canonical_ids":0,
 "results":[
  {
   "error":"InvalidRegistration"
  }
 ]
}
```

なので、上記を受け取るためのモデルを作ります。

```java:FirebaseResponse.java
public class FirebaseResponse 
{
	public Long multicast_id;
	public Integer success;
	public Integer failure;
	public Integer canonical_ids;
	public List<Result> results;

	class Result 
	{
		private String message_id;
		private String registration_id;
		private String error;
	}
	//lombokを使うのでアクセサは省略
}
```


## 実装



```java:FirebaseClient.java

public class 
{
	private final String SAMPLE_MESSAGE= "{\"to\": \"xxx\",\"notification\": {\"title\": \"見出しだよ\",\"body\": \"本文だよ\"},\"data\": {\"greet\": \"Hello. World!!\"}}";
	private final String FCM_END_POINT = "https://fcm.googleapis.com/fcm/send";
	private final String SERVER_KEY = "サーバーキー";

	RestTemplate template = new RestTemplate();

	HttpHeaders headers = new HttpHeaders();
	Charset utf8 = Charset.forName("UTF-8");
	MediaType mediaType = new MediaType(MediaType.APPLICATION_JSON, utf8);
	headers.setContentType(mediaType);
	headers.set( "Authorization", String.format("key=%s", SERVER_KEY) );

	HttpEntity< String > entity = new HttpEntity< String >( SAMPLE_MESSAGE, httpHeaders );

	FirebaseResponse response = template.postForObject(FCM_END_POINT , entity, FirebaseResponse.class );
	LOGGER.info(String.format("Firebase Push Result. header:[%s], message:[%s], response:[%s]", httpHeaders, SAMPLE_MESSAGE, response ));

}

```

こんな感じでリクエスト処理とレスポンス取得が可能になります。

## 端末に届いた通知の文字化け

端末に届いたプッシュ通知の日本語部分が「?????????」のように文字化けしてしまう部分でハマりました。

これは

```java

Charset utf8 = Charset.forName("UTF-8");
MediaType mediaType = new MediaType(MediaType.APPLICATION_JSON, utf8);
headers.setContentType(mediaType);

```

上記を行っていなかった事が原因でした。
([公式](https://firebase.google.com/docs/cloud-messaging/server?hl=ja#auth)にもしっかり書いてあります。orz)

## 課題

Firebase Notificationsの場合はダッシュボードから送信した通知がログとして残るので、データ解析は送信状況を簡単に把握することが出来るが、FCMの場合は送信結果しか戻ってこないので送信通知履歴管理等は独自で開発するなり考慮に入れる必要がある。

とはいってもそんなに多くの情報を持つものでもないので、負担は少ないと思う。

# 終わりに

Googleとしてもかなり力を入れているサービスなので、身に着けることで今後のIT社会で生きるための武器になりうる可能性を秘めた技術だと思いました。

ただ、端末で受け取るにはスマホアプリ開発の知識が必須になるので、ひとまずはブラウザプッシュ通知から身に着けようかな。。。

その時にはまた記事としてまとめます。

じゃあの。
Route53+S3+CloudFrontでhttpsのurlをリダイレクトさせる

# 概要
サイトのお引越しの時などに、Route53+S3でS3の静的Webサイトホスティング機能を使うと便利なのですが、
Httpsをリダイレクトしたい場合、S3単体ではSSL証明書を扱うことができないため、CloudFront経由で行います。
その方法とはまったところを紹介します。

# 手順
- S3のバケットを作り、全てのリクエストをリダイレクトするように設定する
- Certificate Managerで証明書を作る
- CloudFrontのDistributionを新しく作りOriginをS3にし証明書を設定する
- Route53にS3に向くようにRecordを追加する

# S3のバケットを作り、全てのリクエストをリダイレクトするように設定する

S3のコンソールを開いてバケットを作り、「Static Website Hosting」を選んで

<img width="1404" alt="スクリーンショット 2017-06-05 8.07.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/47882/714cee79-691d-9354-3b8e-a6f616fc2f58.png">

リダイレクト先を設定します。
<img width="1403" alt="スクリーンショット 2017-06-05 8.08.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/47882/dc632643-5657-65cb-12fb-01f7a784ef66.png">

エンドポイントのところをクリックして意図通りにリダイレクトされたらOKです。

# Certificate Managerで証明書を作る
CloudFrontで使うようの証明書を作るのですが、__必ずリージョンをバージニア北部(us-east-1)で作ってください__。そうしないとCloudFrontの設定画面に出てきません。ここにはまって少し時間を使いました。

<img width="1404" alt="スクリーンショット 2017-06-05 8.15.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/47882/9169db6e-c22d-8b01-a0a5-dd49f2948ab9.png">

# CloudFrontのDistributionを新しく作りOriginをS3にし証明書を設定する
<img width="1404" alt="スクリーンショット 2017-06-05 8.19.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/47882/00833e67-3c85-0075-21c3-17e0e087db28.png">

CloudFrontの設定をするのですが、ここでOrigin Domain Nameにサジェストで出てくるバケットを__指定してはいけません！！！__

S3はストレージとして使う時とWebサイトとして使うときで__エンドポイントが違います！__

ではここで何を指定するかというと、先ほどのS3の設定の時に出てきた__{バケット名}.s3-website-{リージョン名}.amazonaws.com__を指定します。ここにめちゃくちゃはまって時間を無駄にしました。ツライ。

あとは証明書を設定してCNAMEに自分のリダイレクト元にしたいドメイン名を指定します。

<img width="1405" alt="スクリーンショット 2017-06-05 8.32.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/47882/5a6fd000-98f8-4976-f691-65957fb7c860.png">


# Route53にS3に向くようにRecordを追加する
<img width="1404" alt="スクリーンショット 2017-06-05 8.29.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/47882/06b18277-03c0-bb4e-7116-dbb821930c99.png">

AレコードでCloudFrontに向けてALIAS貼ります

# まとめ
最初はS3とRoute53だけでできるんだろうと呑気にやってたら色々やらなきゃいけず、結構はまってしまいました。
設定し終わると便利だなあという感じ。
[Python]dictionary内にKeyが存在するか確認する方法


# single key
Dictionary内にKeyが存在するか確認するときはinを使う。

下記のように key in dict.keys() 又は key in dictどちらでもよい。

```python
In [2]: D = {'abc': 1, 'def': 2, 'ghi': 3, 'jkl' : 4}

In [3]: 'abc' in D.keys()
Out[3]: True

In [4]: 'xyz' in D.keys()
Out[4]: False

In [5]: 'abc' in D
Out[5]: True
```

ちなみに値が存在するかも同様にinを使うとよい

```python
In [6]: 1 in D.values()
Out[6]: True

In [7]: 5 in D.values()
Out[7]: False
```
# multiple keys

## すべてのkeyが存在するか確認する方法
複数のkeyが存在するか確認するときはDictionary view objectを使う。python2.7とpython3系でDictonary view objectの取得方法が変わっている。python2.7の時はviewkeys()をpython3の時はkeys()を使う。

### python2.7

```py:python2.7
In [8]: D.viewkeys() >= {'abc', 'def'}
Out[8]: True

In [9]: D.viewkeys() >= {'abc', 'xyz'}
Out[9]: False
```

### python3
python3 ではviewkeysがkeysになる。

```python
In [3]: D.keys() >= {'abc', 'def'}
Out[3]: True

In [4]: D.keys() >= {'abc', 'xyz'}
Out[4]: False
```
両方で動くようにするにはsixを使って下記のように書く。

```python
In [6]: import six

In [7]: six.viewkeys(D) >= {'abc', 'def'}
Out[7]: True

In [8]: six.viewkeys(D) >= {'abc', 'xyz'}
Out[8]: False
```

### setを使う方法
@shiracamus さんからコメントで教えてもらった方法。こちらだとsixをimportする必要が無くすっきりしてます。

```python
In [21]: set(D) >= {'abc', 'def'}
Out[21]: True

In [22]: set(D) >= {'abc', 'xyz'}
Out[22]: False
```

### for loop & all を使う方法
@shiracamus さんからコメントで教えてもらった方法。

```python
In [2]: all(key in D for key in ('abc', 'def'))
Out[2]: True

In [3]: all(key in D for key in ('abc', 'xyz'))
Out[3]: False
```

## 少なくとも一つkeyが存在するか確認する方法
dictionary view objectでは&を使ってintersectionが取れる。
https://docs.python.org/2/library/stdtypes.html#dictionary-view-objects

python2.7

```python
In [14]: len(D.viewkeys() & {'abc', 'xyz'}) > 0
Out[14]: True

In [15]: len(D.viewkeys() & {'x', 'xyz'}) > 0
Out[15]: False
```

python3

```python
In [10]: len(D.keys() & {'abc','xyz'}) > 0
Out[10]: True

In [11]: len(D.keys() & {'x','xyz'}) > 0
Out[11]: False
```

### for loop & anyを使う方法
@shiracamus さんからコメントで教えてもらった方法。

```python
In [25]: any(key in D for key in ('abc', 'xyz'))
Out[25]: True

In [26]: any(key in D for key in ('abc', 'def'))
Out[26]: True

In [27]: any(key in D for key in ('x', 'xyz'))
Out[27]: False
```

参考：
https://stackoverflow.com/questions/16004593/python-what-is-best-way-to-check-multiple-keys-exists-in-a-dictionary
https://docs.python.org/2/library/stdtypes.html#dictionary-view-objects
ssm put-parameterでvalueにURLを指定するとGETされる件


##事象
CLIを使ってAWSのEC2 Systems Manager Parameter StoreにURLの文字列を格納しようとした場合に以下のようなエラーとなりました。どうやらパラメータURLに対してGETした結果を格納しようとしている様子です。コンソールから手で登録できれば良いのですが、なぜかKMSにある自前のキーを使いたい場合CLI経由で登録する必要があります。

```:実行したコマンド
aws ssm put-parameter --name test.url --value "https://*****.co.jp" --type SecureString --key-id "****" --region ap-northeast-1

```


```:結果
An error occurred (ValidationException) when calling the PutParameter operation: 1 validation error detected: Value '

<!DOCTYPE HTML>
<html lang="ja">
以下略
</html>

' at 'value' failed to satisfy constraint: Member must have length less than or equal to 4096
```

##原因
[CLIの仕様](http://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-using-param.html#cli-using-param-file)で"file://", "fileb://", "http://" 及び "https://" のプレフィックスが付いた場合は自動的にデータをロードしてしまうためです。今回の場合はリモートファイルのURLと判断されて中身を取得しにいってしまったというわけです。

##解決法
上記の仕様を使ってURLの文字列をデータとしてロードさせてやればOKです。

`url.txt`にURLを書いて保存します。

```:url.txt
https://*****.co.jp
```

下記のコマンドを実行

```
aws ssm put-parameter --name test.url --value "file://url.txt" --type SecureString --key-id "****" --region ap-northeast-1
```

##注意点
この方法で登録はできるのですが、パラメータを読み出した時に改行コードが末尾に付いてくるので注意しましょう。
現在私の環境ではRubyのSDKから読み出した時にいちいちchompしています。もっとエレガントな方法があるのだと思いますが、併せて機能改善も待たれるところです。
コールバック関数をPromise化して使う


jsにおいてコールバック関数は頻出するパターンの一つである。
しかしながら、コールバックヘルという言葉があるとおりネストをすると非常に見づらくなっていく。

本記事では、Node環境においてindex.jsを読み込んで表示するスクリプトを例にいくつかのパターンを見ることにする。

```js:index.js
'use strict';
const fs = require('fs');

fs.readFile('index.js', 'utf8', (err, out) => {
	if (err) {
		console.log(err);
	}
	console.log(out);
});
```

## Promise化
node v8から導入された`util.promisify`を使うとコールバックをpromise変換できる。

```index.js
'use strict';
const {promisify} = require('util');
const fs = require('fs');

promisify(fs.readFile)('./index.js', 'utf-8').then(out => {
	console.log(out);
});
```

## async/await
また、v8(ところでv8というとV8(実行エンジン)と区別がつかないことに気づいた)からはasync/awaitが使えるので以下のように書ける。

```index.js
'use strict';
const { promisify } = require('util');
const fs = require('fs');

async function main()  {
	const out = await promisify(fs.readFile)('./index.js', 'utf-8');
	console.log(out);
}

main();
```

トップレベルawaitがほしいところではあるが、非同期処理が続くとコールバックより圧倒的に見やすいので積極的に使っていきたい。


## pify

しかしながら、これらはv8からでないと使えないので多くの場合、ライブラリで代替することになるだろう。

promise化するライブラリの一つは`pify`だ。

```
$ npm install --save pify
```

ほぼ、前述したpromisifyと同じように使える。
基本的に自分はこれを使っている。

[sindresorhus/pify: Promisify a callback-style function](https://github.com/sindresorhus/pify)

```index.js
'use strict';
const fs = require('fs');
const pify = require('pify');

pify(fs.readFile)('./index.js', 'utf-8').then(out => {
	console.log(out);
});
```

## 非同期？

しかしながら、いつでも非同期が高速ではないことに注意すべきだ。

非同期処理にはオーバヘッドがあり、このようなイベントループをブロックことが問題ではない場合、同期的に書いたほうがはるかに高速に動作する。

```index.js
'use strict';
const fs = require('fs');

const out = fs.readFileSync('./index.js', 'utf-8');
console.log(out);
```
ランサムウェアとは何か？

## はじめに
「ランサムウェアとは何か？」……と、友人から突然聞かれたため、ここに書いてみようと思います。
※ここで取り扱うランサムウェアは暗号化を伴うものについてです。

## ランサムウェアとは？
ランサムウェアはテレビでよく身代金型ウイルスと呼ばれています。
感染するとPC内のデータを勝手に暗号化[^1]し、暗号化されたデータを復号[^2]してほしければ金を払えと要求してきます。
なお、お金を支払っても暗号化されたデータを復号してくれる保証はありません。

## ランサムウェアに感染したデータは復号できるのか？
結論から述べますと、ランサムウェアに暗号化されてしまうと、そのデータを復号することは基本無理です。

ランサムウェアはAES暗号（秘密鍵暗号[^3]の一種）、やRSA暗号（公開鍵暗号[^4]の一種）でデータを暗号化します。
AES暗号とRSA暗号は非常に強固な暗号であり、その鍵長（ビット数）[^5]が大きければ大きいほど秘密鍵が無い状態で復号することは現実的な時間では不可能です。

AES暗号は現実的な時間で復号できる攻撃方法（秘密鍵を知らない状態で復号を試みるため、攻撃方法と呼びます）は、現時点において存在しません。
RSA暗号は素因数分解[^6]の求解困難性（RSA暗号を復号するためには巨大な素数[^7]と巨大な素数の組み合わせを見つけるために巨大な数の素因数分解をしなければならないが、それを効率よく行う方法が現時点において存在しない）により、同様に現実的な時間で復号することができません。

長々と書きましたが、ランサムウェアに感染するとデータの復旧は不可能、どうしようもないと認識を持っていただければ問題ありません。

## ランサムウェアの感染対象
ランサムウェアを感染する可能性があるのはパソコンだけではなく、スマートフォンも感染します。

Windows：10より前のOSは感染する可能性高
Android：Google Play以外のストアからアプリをダウンロードすると感染する可能性有
iOS：ほぼ感染しない。（厳格な審査があるiTunesストア以外からアプリをダウンロードできないため）

どれにも言えることは

+ 不用意にアプリをインストールしないこと
+ アップデートは適宜行うこと

でしょうか。

## おわりに
最近各々の職場でもランサムウェアに対する警告が流れていると思います。
今回、この記事を読んで少しでもランサムウェアについて知っていただければと思います。
以上です。

## 脚注
[^1]: 一定の規則に基づいて文書や画像などのデジタルデータを、当事者以外にわからないよう変換すること。
[^2]: 暗号化されたデジタルデータを暗号化される前のデジタルデータに戻すこと。なお、復号「化」とは呼ばないことに注意。
[^3]: 暗号化と復号に同一の鍵を用いる暗号方式のことである。この同一の鍵のことを秘密鍵といい、秘密鍵は当事者以外に知られることなく用いなければならない。
[^4]: 一対になる二つの鍵を使って暗号化、復号を行う暗号方式のことである。公開鍵暗号における一対になる二つの鍵は、一般に公開する鍵の方を公開鍵、一般に公開せず当事者以外には秘密にする鍵の方を秘密鍵という。
[^5]: 暗号鍵のデータ量のことを表し、鍵長が長ければ長いほど暗号の強度は強くなり、暗号化や復号の計算に多大な時間を要する。
[^6]: 式を素数の積で表すこと。例：6を素因数分解すると2(素数)×3(素数)
[^7]: 自然数のうち、1とその数以外でしか割り切れない数のこと。例：11は1と11（その数）でしか割り切れない
ESP8266 RTCMemory

## ESP8266 Arduino のExampleにあるRTCUserMemoryとは何か？
### RTCUserMemory
RTCMemory を理解できるページがなかなか無く、探していたらYoutube で解説しているページ見つかった。<br>
[How to use the RTC Memory in ESP8266](https://www.youtube.com/watch?v=r-hEOL007nw)<br>
ESP8266 は省電力モード、Deep Sleep Mode を持っている。Deep Sleep Mode ではRTC（Real-Time Clock) だけが動作している。Deep Sleep Modeではメモリーが保存されない。唯一、RTCのブロックが持て散るRTC Memory が使える。このメモリーは768 byteである。内、256 bytはシステムが使っている。RTC Memoryは４バイトアライメント。でるあるから 128(=512/4) のアドレスで使うことができる。 

RTCは、Deep Sleep からESP8266 を起こす機能。
![RTCMemory.jpg](https://qiita-image-store.s3.amazonaws.com/0/58417/fb2c3a7f-4cee-c99e-d076-b84e2f4a7bec.jpeg)


- [ESP8266 SDK API Guide]
(https://www.sistemasorp.es/wp-content/uploads/2015/05/2C-ESP8266__SDK__Programming-Guide__EN_v1.0.1.pdf)
- [ESP8266 Non-OS SDK API Reference](https://www.espressif.com/sites/default/files/documentation/2c-esp8266_non_os_sdk_api_reference_en.pdf)
PASONATECH CONFERENCE 2017 に参加した話。～ エコシステムの活用とコミュニティの重要性。必要な技術・サービスを選択する力。 ～


##はじめに
エンジニア生活 2 ヶ月目のわたしが書くブログ。
( あたたかい目で見てくれると嬉しいです。 )

先日 ( 2017年5月27日 ) 開催された「PASONATECH CONFERENCE 2017 インフラエンジニアday」に参加してきました。
そのときの感想などをメモしていきます。
[( HP ) パソナテックカンファレンス2017](https://www.pasonatech.co.jp/lp/conference2017/)

#スケジュール
|時間|会場A|会場B|
|:---:|:---:|:--:|
|13:00〜13:45|エンジニアが知るべきテクノロジーの「不可避」な流れと、<br> コミュニティが持つキャリア形成への影響力<br>( 小島 英揮さん )|バックエンドエンジニアから見たIoTの世界<br>( 瀬高 拓也さん )|
|14:00〜14:45|AI時代にインフラエンジニアが出来ること。やらなきゃいけないこと。<br>( 得上 竜一さん )|IoTシステムを支えるインフラとエンジニア<br>( 片山 暁雄さん )|
|15:00〜16:30|パネルディスカッション<br>AI/IoT時代におけるエンジニアの資質||
場所は、新宿アイランドタワー。
わたしは「会場A」のセッションに参加しました。

# 1 . 小島さんのセッション( 会場A )
<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.amazonaws.com/0/171147/0b3a37ec-7da8-cfda-b174-41366308b564.jpeg">
[小島さんのスライドはこちら](https://www.slideshare.net/hide69oz/20170527-pasona-techv2)

まずは小島さんのセッション。

小島さんのお話で印象的だったのが
「クラウドのエコシステムを活用すること」と「勉強会やコミュニティに参加する重要性」です。


###**クラウドのエコシステムを活用すること**
まず、「エコシステムってなんだ？？」と思いました。

お話を聞いてみると、エコシステムとは食物連鎖のイメージらしい。
クラウドのエコシステムを活用するという意味は、
クラウドやデータベースなど様々な技術をどんどん活用していこうという、世の中の動きのことなんだろうなと解釈！なるほど。

初めからサービスや技術を自社で開発するよりも
既存のものを取り入れ活用していく食物連鎖に加わっていくことで、より新しいものを作れるのかも。
エコシステムを活用することで「より力を注ぎたいことに時間をそそげる」メリットがあるのかと感じた。

###**勉強会やコミュニティに参加する重要性**
また、エコシステムを活用し、ものづくりをするにしても
「いま自分がどこにいるのか」を常に意識することが重要だと教えてくれた。

そもそも「身の回りにどんなサービスや技術があるのか」、「どういったトレンドがあるのか」にアンテナを張ることで自分に必要なサービス・技術を選択することができる、という考え方。（ とても共感 ）

また、最新のトレンドについて知る・学ぶためには各地で開催される「勉強会」や「コミュニティ」に参加することをオススメしていた。

新しい技術やサービスが発表されたら「すぐにでも使ってみたい！」ですね。
そう思ったら、経験・未験問わず参加してみるのが吉。（ いや、大吉！ ）


# 2 . 得上さんのセッション( 会場A )

<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.amazonaws.com/0/171147/9c9ae061-14eb-0153-e34e-e9ae5b6b66a7.jpeg">

つづいては得上さんのセッション。

得上さんのセッションで印象的だったのが
「AIプロジェクトでやらなきゃいけないこと」と「サービスそれぞれの個性を知っておくこと」です。


###**AIプロジェクトでやらなきゃいけないこと**
AIプロジェクトについて、聞いたことある程度ですが
個人的にはとても面白そうな分野だ感じている。

AIプロジェクトでやらなきゃいけないこととして、下記の3つを得上さんが挙げていた。

**1. データサイエンティストに必要な情報をストレスなく送ること**
**2. データを扱っていく上で使用するシステムについて学ぶこと**
**3. データを素早く可視化できる**

実はさきほどの小島さんのセッションの中で、すこしAI（機械学習）についてもお話ししていました。「機械学習の精度はデータ数できまる」という話を聞きました。

たくさんのデータを扱うということは、データ送信時間も重くなってくるだろうし
使いたいデータが一目で見つけられないと、探す過程ですっごく一苦労するんだろうな。。と。
そのため「AIプロジェクトでやらなきゃいけないこと」として得上さんが上で挙げた3つが重要になってくるんですね！なるほど。

＃どのシステムが適しているのか、プロジェクトごとに判断が必要！
＃データの可視化大事！

###**サービスそれぞれの個性を知っておくこと**
ひとことで「クラウド」や「データベース」と言っても、複数もの種類がり
それぞれ個性があるということでした。
それぞれの個性（特徴）を知っておくことで、よりスムーズな開発ができていくみたい。

＃試しに「 使ってみておく 」のも、適したサービスを選択するのに重要


# 3 . パネルディスカッション( 会場A )
<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.amazonaws.com/0/171147/9528ae2b-db8d-1fe4-bdf7-aaf325083455.jpeg">

そしてパネルディスカッション！
本日の登壇者が勢ぞろい。一度にたくさんの意見を聞けるのは面白かったです～

いちばん面白かったのは
**人工知能（AI）は仕事を奪うのか？作るのか？**というお話。

登壇者の皆さん、AIの発展にワクワク感を示している方がいっぱいいました。
わたしもワクワク派です。

「 仕事がなくなる 」と考えると悲しいけれど、
「 めんどくさい作業を代わりにやってもらえる 」って考えるとかなり魅力的ですよね。
「 もっと力を注ぎたい作業や開発に集中できる 」って幸せだ。

そのうえ、いずれ働かなくてもいい時代が来るかもしれないと思っています。（ 個人的な妄想 ）
そしたら、**もっと打ち込みたいことに打ち込める生活ができてるかと**。**趣味**とか**興味**とか。

**素敵すぎる。**

<img width="500" alt="ファイル名" src="https://qiita-image-store.s3.amazonaws.com/0/171147/1d97bbdf-145f-1680-9575-90b78ad76187.jpeg">

そしたら私は、大好きな植物とアリの研究をして過ごしたいと思う。

最近はプログラミングも好きです。楽しい！


楽しいこともやりたいことはいっぱい。
nginxで同一ホスト内にリバースプロキシしようとするとエラーが出る

# nginxで同一ホスト内にリバースプロキシしようとするとエラーが出る
## 環境
- Amazon EC2
- AMI: Centos7
- nginx/1.12.0      (80port)
- puma       (3000port)

## 状況
例えば、`/etc/nginx/conf.d/default.conf`に以下のような設定をした時、

```:/etc/nginx/conf.d/default.conf
server {
    listen       80;
    server_name  localhost;

   location / {
    proxy_pass http://localhost:3000/;
    }
}
```

ブラウザで接続してもつながらない。3000ポート直打ちだとアクセスできる。また、なぜか別ホストに変えてみるとプロキシできる。　　
`curl`でレスポンスを確認してみる。

```
$ curl -L -I xxx.com
HTTP/1.1 502 Bad Gateway
Server: nginx/1.12.0
Date: Thu, 01 Jun 2017 08:34:06 GMT
Content-Type: text/html
Content-Length: 537
Connection: keep-alive
ETag: "xxxxxxxxxx-xxx"
```
`502`が出ている。
また、nginxのログを確認すると、

```:/var/log/nginx/error.log
2017/06/01 08:38:16 [crit] 27144#27144: *1 connect() to 127.0.0.1:3000 failed (13: Permission denied) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: localhost, request: "HEAD / HTTP/1.1", upstream: "http://127.0.0.1:3000/", host: xxx.com"
2017/06/01 08:38:16 [warn] 27144#27144: *1 upstream server temporarily disabled while connecting to upstream, client: xxx.xxx.xxx.xxx, server: localhost, request: "HEAD / HTTP/1.1", upstream: "http://127.0.0.1:3000/", host: "xxx.com"
2017/06/01 08:38:16 [crit] 27144#27144: *1 connect() to [::1]:3000 failed (13: Permission denied) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: localhost, request: "HEAD / HTTP/1.1", upstream: "http://[::1]:3000/", host: "xxx.com"
2017/06/01 08:38:16 [warn] 27144#27144: *1 upstream server temporarily disabled while connecting to upstream, client: xxx.xxx.xxx.xxx, server: localhost, request: "HEAD / HTTP/1.1", upstream: "http://[::1]:3000/", host: "xxx.com"
```

どうやら権限の関係でうまくプロキシ出来ていないよう。しかしnginxの実行ユーザをrootにしてみても解消されない。

## 解決策

どうやらSELinuxが効いているせいらしい。 Centos7のAMIでは初期は無効だった気がするが有効になっていたみたい。

`httpd_can_network_connect`を許可してやることで接続できるようになるはず。

```
$ sudo setsebool httpd_can_network_connect on -P
```

確認してみます。

```
$ curl -L -I xxx.com
HTTP/1.1 200 OK
Server: nginx/1.12.0
Date: Thu, 01 Jun 2017 08:40:36 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
～～～～～～～～～～～～～～～～～～～～
```

接続できました。

## 結論
私はSELinuxを切って解決しました。
ulタグなど、一部分だけUAスタイルシートを使いたいとき

基本的にはいらないけど、一部だけブラウザ特有のCSS「UAスタイルシート」を使いたいときありますよね。
わざわざ上書きして消したCSSを当てるのは面倒です。別の方法を考えてみました。

```html:index.html
<ul data-reset="false">
  <li>リスト01</li>
  <li>リスト02</li>
  <li>リスト03</li>
</ul>
```

```css:index.css
ul:not([data-reset="false"]) {
  list-style: none;
  padding-left: 0;
  margin: 0;
}
```

data-reset="false"を記述すれば、UAスタイルシートを使うことができます。
スタイルをリセットした状態で使いたいときは、ulタグだけを書けばOKです。

#追記
詳細度の関係でこの方法は使わない方が良いことが分かりました。
CSSだけで希望の行数だけ表示して、それを越える文字は非表示にする

何文字入るかわからないけど、2行だけ表示したい！漏れた文字は表示できなくてもいいや！
というときのテクニックです。

```html:index.html
<p class="line-2">この文章を2行だけ表示したいです。それ以降の文字は消えてしまっても問題ないです。</p>
```

```css:index.css
.line-2 {
  overflow: hidden;
  height: 3.6em /* 2em（行）x line-heightの1.8 */
  font-size: 16px;
  line-height: 1.8;
}
```

以上です。
表示したい行数 * line-height
をheight（単位em）にしてoverflow:hiddenするだけです。
Linuxで結婚式動画を作る

２段階作戦。
環境　： ubuntu14.04LTS

①写真からスライドショーを作成。
ffDiaporam
※写真から動画を作成できるものの、詳細な設定は不可。

②詳細な設定を動画編集ソフトで行う。


追記：
ffDiaporamは使いにくので、やめた。
Shotcutだったら、Adobeのプレミアに操作が似ていてわかりやすい！
GPUを使うと、気持ち早くなったような気がする！
それ以外も以下に色々情報あり。
https://filmora.wondershare.com/adobe-premiere/adobe-premiere-linux-alternative.html
ls コマンドを使わずにファイル一覧を取得

`ls` コマンドは `echo` で代用できます。

```bash
# ls
$ echo *

# ls -a
$ echo .* *
```

ただし、ファイル名に区切り文字 (space:`\x20`) が含まれる場合を考慮する必要があります。

```bash
$ echo "foo" > "bar baz.txt"

# NG
$ echo *.txt | xargs cat
cat: bar: No such file or directory
cat: baz.txt: No such file or directory

# OK
$ printf "%s\n" *.txt | while read x; do cat "$x"; done
foo
```

`stat` コマンドを使うと出力フォーマットを細かく調整できますが、`ls` コマンド同様、GNU/BSD で実装が異なる点に注意が必要です。

```bash
# GNU stat
$ stat -c "%A %n" .* *

# BSD stat
$ stat -f "%Sp %N" .* *
```

単にOS判定で切り替えると、macOS (BSD) ユーザが、Homebrew で GNU coreutils を入れて alias を定義しているケース等でうまく動きません。

```bash
alias ls="gls --color"
alias stat="gstat"
```

### See Also

* https://stackoverflow.com/questions/394230/detect-the-os-from-a-bash-script
* https://stackoverflow.com/questions/1676426/how-to-check-the-ls-version
* https://github.com/postmodern/ruby-install/issues/63
CentOS 7.3でDockerを使う

CentOS7にDockerをインストールして、hello worldまでやってみました。
その際、少し引っかかったところがありましたので、メモとして残しておきます。

# 環境
- OS: CentOS7

# Dockerインストール
CentOS7ではリポジトリを追加せずに、そのままyumでインストールできます。
`$ sudo yum -y install docker`

# Docker起動
`$ sudo systemctl start docker`
自動起動設定をする場合は、以下のコマンドも。
`$ sudo systemctl enable docker`

# Docker実行
起動できたら動作確認をします。以下のコマンドを打つと、
`$ docker ps`


*Cannot connect to the Docker daemon. Is the docker daemon running on this host?*

というエラーが出ます。

`$ sudo docker ps`
のように、sudoをつけてスーパーユーザ権限で毎回実行すれば問題ないのですが、面倒なので一般ユーザーでもdockerコマンドを実行できるようにしていきます。

# 一般ユーザ用の設定

1. Dockerのグループ(dockerroot)にユーザを追加
`$ sudo gpasswd -a $(whoami) dockerroot`


2. /var/run/docker.sock のグループをdockerrootに変更
`$ sudo chgrp dockerroot /var/run/docker.sock`
<dl>
  <dt>【変更前】</dt>
  <dd>srw-rw----. 1 root **root** 0  6月  4 14:35 /var/run/docker.sock</dd>
  <dt>【変更後】</dt>
  <dd>srw-rw----. 1 root **dockerroot** 0  6月  4 14:35 /var/run/docker.sock</dd>
</dl>
これでsudoなしでdockerコマンドを使えるようになったのですが、dockerを再起動したりすると、グループの変更を再度行わなければなりません。
それはちょっと面倒なので、dockerの設定ファイルを修正します。

3. /etc/sysconfig/docker 修正
3行目あたりの記述を修正します。
`$ sudo vi /etc/sysconfig/docker`
<dl>
  <dt>【修正前】</dt>
  <dd>OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false</dd>
  <dt>【修正後】</dt>
  <dd>OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false<strong> -G dockerroot</strong>'</dd>
これでdockerを再起動しても、グループの変更をせずに一般ユーザでdockerコマンドを使えるようになります。  
準備が整ったので、あとは Hello world するのみです。

# Docker で Hello World
以下コマンドで、hello worldしてみます。
`$ docker run hello-world`
> Unable to find image 'hello-world:latest' locally
Trying to pull repository docker.io/library/hello-world ... 
latest: Pulling from docker.io/library/hello-world
...
...
**Hello from Docker!**
This message shows that your installation appears to be working correctly.
...
...
For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/


問題なく動きました！

# 参考
以下のサイトを参考にさせていただきました。
http://exlair.hatenablog.com/entry/install-docker-on-centos7
検索用Gem"SearchCop"の紹介

Railsで検索用のGemといえば[Ransack](https://github.com/activerecord-hackery/ransack)が有名かと思います。Ransackって多機能ですが独自のルールとかが多くて、しばらく使ってないと使い方忘れちゃう。

そこで、今回は別のシンプルな検索用Gemである[SearchCop](https://github.com/mrkamel/search_cop)を使ってみたので紹介しようと思います。

https://github.com/mrkamel/search_cop

# 特徴

Ransackでは独自の記法を用いて検索条件を組み立てますが、複数のフィールドに対して複数の検索ワードでAND検索やOR検索を実現するのは以外と大変です(以下は昔自分が書いた記事です)。

[ransackを使った複数ワードによるAND検索の実装](http://qiita.com/EastResident/items/54047e6e85dda0418dad)

SearchCopでは直感的かつ自然な書き方で、複雑な検索条件を組み立てることができます。

記述例

```rb
# 性・名・電話番号でのAND検索
User.search('田中 太郎 08012345678')

# メールアドレスに"gmail"が含まれており、登録が2015年あるいは2016年
User.search('email: gmail AND (created_at:2015 OR created_at:2016)')
```

# サンプルコードで使うモデルの解説

例として、以下に示す二つのモデルが存在していると仮定します。

### Userモデル
Userモデルは会員の情報を持つモデルで、以下のフィールドを含みます。

|フィールド名|型|
|---|---|
|id|integer|
|email|string|
|first_name|string|
|last_name|string|
|age|integer|
|created_at|date|

```rb
class User < ApplicationRecord
  has_many :posts
end
```

### Postモデル
Postモデルは投稿内容を持つモデルで、以下のフィールドを含みます。

|フィールド名|型|
|---|---|
|id|integer|
|user_id|integer|
|title|string|
|message|text|
|created_at|date|

```rb
class Post < ApplicationRecord
  belongs_to :user
end
```

`User`と`Post`は一対多の関係です。

# 使用方法

## 概要

仮に、`User`に検索機能をつけたい場合、`User`のモデルファイルに以下の記述を追加します。

```rb
class User < ApplicationRecord
  include SearchCop
  has_many :posts

  search_scope :search do
    attributes :email, :first_name, :last_name, :age, :created_at
    attributes post: ['posts.title', 'posts.message']
  end
end
```

上記のコードを追加することで、`User`モデルで`search`というスコープが使えるようになります。

```rb
User.search('Ruby')
```

これだけの記述で、Userモデルの全フィールド及び関連テーブルであるPostモデルのフィールドに対して、"Ruby"という文字列でLIKE検索が走ります。

## 検索フィールドの指定

前述した例では全てのフィールドを指定しましたが、検索条件として特定のフィールドのみを指定することも可能です。また、検索スコープに名前を付けて、複数定義することもできます。

```rb
search_scope :name_search do
  attributes :first_name, :last_name, created_at
end

search_scope :post_search do
  attributes post: ['posts.title', 'posts.message']
end
```

検索時に検索対象のフィールドを指定することも可能です。ここで指定しない場合は、全フィールドが検索されます。

```rb
# last_nameのみを検索
User.search('last_name:松本')
```

日付や整数に対して、範囲指定することもできます。

```rb
# 2017年に登録されたもののみ
User.search('created_at:2017')

# ageが20より上
User.search('age > 20')
```

そして、これらの条件をANDやORで容易に組み合わせることもできます。

```rb
User.search('(last_name:松本 OR age > 20) AND created_at:2017')
```

## FullText Indexへの対応

SearchCopはデフォルトでLIKE検索が実行されるため、レコード数やフィールドのサイズによっては、検索に時間がかかることが予想されます。

SearchCopでは、FullText Indexに標準で対応しています。

```rb
search_scope :search do
  attributes message: 'posts.message'
  options :message, type: :fulltext
end
```

ここでは、FullText Indexに関する詳細な説明は省きます(すみません、ここは試してないです・・・)。

# 終わりに

Ransackが、controllerやviewを含めた、**サービスに組み込むための検索機能全般**を提供しているのに対して、SearchCopは**モデルを検索するためのインターフェースのみ**に特化ている感じでしょうか。controllerやview側の処理を自前で実装したい場合は、ベターな選択肢になるのではないでしょうか。
Atom hydrogen で、ruby-xmpfilter 的な workflow を実現する

追記: 結局パッケージにしてしまった。。。 https://atom.io/packages/hydrogen-helpers


![hydrogen-helpers.gif](https://qiita-image-store.s3.amazonaws.com/0/30758/35d1cad2-b365-9c72-5e94-0d3054c32bb4.gif)


Atom のパッケージ [Hydrogen](https://atom.io/packages/hydrogen) を使い始めた。
目的は JavaScript のお勉強を加速するために、サンプルコードスニペットを手早く理解するためだ。
これまで、理解の難しいコードは自作の `transformer` パッケージで Atom から直接実行していたが、 hydrogen を試してみようと思い立った。いちいち debug プリント( `console.log` ) 入れるのが辛くなってきた。

もともと、Vim を使っていた頃、[vim-ruby-xmpfilter](https://github.com/t9md/vim-ruby-xmpfilter) というのを作って使っていた( 単なる rcodetools/xmpfilter 自体の wrapper)
これとワークフローを実現したかった。

## 実現したい Workflow

1. コードをセレクトする(from wiki, online book or blog post like pony poo)
2. sandbox 的なエディタに貼り付ける
3. 興味のある行にマークをつける( Jupyter の `cell` を行末に挿入する )
4. Jupyter kernel を restart(`restart-kernel`) してから再評価 `run-all`

## Point

#### 3.について

これ相当のコマンドは無い。気楽に cell マークをつけたり消したりしたった。

#### 4.について

kernel を restart しないといけないのは、node-process を実行毎に共有しているので、let とか var とかしてると、全体を再評価 `run-all` した時に、 **再宣言** になってしまって、怒られる(`Identifier x has already been declared`).
もちろん restart によるオーバーヘッドもあるけど、僕は全体をクリーンに毎回再評価出来る方が良い。お勉強目的の小さいコードでは特に。

### Commands

init.coffee と keymap の例は以下の gist にある

https://gist.github.com/t9md/e57172a18e6b75d0f9f1247a98a14922

### 要注意

hydrogen も Jupyter も数時間前に使い始めたばかりでよく分かっていない。
何か間違っていたら教えて欲しい。
kernel 再起動、再評価のコマンド `hydrogenRestartKernelAndRunAll` は単に２つのコマンドを
連続実行しているだけ、`run-all` 前に kernel の restart を待たないとダメなのですが、わからない(方法がない？)ので、単に `setTimeout` で delay させているだけ.
PCのスペックや評価するコード量等の要因により、適切な timeout 値は変わってきます。コピペする時は適宜変えてください。

### GIFのキーストロークとコマンドがやってること


Gist の Keymap を前提として

- `cmd-m` で line cell の toggle(なければつける、あれば消す)
- `cmd-h` で kernel の restart と 少し待ってから(1000ms の決め打ち) run-all.

最後に、基本的にこれが hydrogen のただしい使い方ではないので、まずは RADME を読もう。

### セットアップ hydrogen for JavaScript

`ijsinstall` が分かり難かった。

```shell
pip install jupyter
npm -g install ijavascript
ijsinstall
jupyter kernelspec list # <- javascript が リストアップされてればOK
```
Dockerでイメージ作成してsamba立ち上げる

Dockerがよくわからず就職難民になりかけたおじさんが復習に燃えてsambaを無駄にコンテナで立ち上げる話。
大人しくdperson/samba使えって？そりゃ楽だけど、万人に便利ってことは、それだけ無駄があるって事ですよ！！

※以下、セキュリティ的な厳しさとかは気にせず、取り敢えず見えればいいやというスタンスでの設定です

## 環境

```
# cat /etc/redhat-release 
CentOS Linux release 7.3.1611 (Core) 
# uname -r
4.11.3-1.el7.elrepo.x86_64
# docker version -f "{{.Server.Version}} : {{.Client.Version}}"
17.03.1-ce : 17.03.1-ce
```

## Dockerfile作る
完成した料理はこちらです。

```:Dockerfile
     1  FROM centos:7
     2  MAINTAINER hasegit
     3  RUN yum -y install samba
     4  RUN yum -y install ed
     5  RUN useradd -m -d /chamba chamba
     6  RUN echo -e 'chamba\nchamba' | pdbedit -a -u chamba
     7  RUN echo -e '\
     8  /workgroup\n\
     9  s/SAMBA/WORKGROUP\n\
    10  $\n\
    11  a\n\
    12  [share]\n\
    13      path = /share\n\
    14      read only = no\n\
    15      guest ok = no\n\
    16      valid users = chamba\n\
    17  .\n\
    18  w\n\
    19  q\n' | ed /etc/samba/smb.conf
    20  CMD [ "bash", "-c", "nmbd -D && smbd -F </dev/null" ]
```

## Dockerfileの解説
1) debianあまり触らないのでcent君にしました。(dperson/sambaはそれが嫌だったというのも...)
4) edは使わずにCOPYなりADDなりでもいいんですが、極力Dockerfileだけで閉じたかったので。
5) sambaにアクセスするためのユーザーはchambaにしてます。他のユーザーがよければここ変える。
6) echo -eでpdbeditのpassword確認を自動入力します。
7-19) edのコマンドをecho -eで噛ませて、無理矢理smb.conf編集してます。やっぱりedは最強。
13) 共有ディレクトリは/shareとしています。他のディレクトリを共有するならここ変える。
20) コンテナ起動後にnmbdとsmbdを起動してます。ここではまった。

## コンテナ起動まで
**1. イメージを作成**

```
# docker build -t samba <Dockerfileのあるディレクトリ>
```

-tでイメージ名(リポジトリ)をsambaにしてます。わかりゃなんでもいいです。

**2. イメージ確認**

```
# docker images samba
```

**3. ポートの穴開け**

```
# firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="samba" accept'
```

CentOS7からはiptablesではなくfirewalldがデフォルトなので、一応そちらで設定してみます。

**4. 起動**

```
docker run -d -p 139:139 -p 445:445 -v /share:/share samba
```

-dでDetached Modeで起動(バックグラウンドで動きます)。
-pでポートフォワーディング。
-vでホスト側ディレクトリ(左)をコンテナ側のディレクトリ(右)でマウント。
最後はイメージ名。

以上を実施後、Windows機から共有にchambaで走れればOKです。

## 余談：ハマったところ
- smbd即死

当初、nmbdとsmbdをどうやってコンテナ起動後に生かしっぱなしにしておくのかが分からなかった。
-Dでデーモン小暮化してもすぐコンテナ死ぬし。
ていうかコマンドがForegroundで動いてないと死ぬというDockerルールを知らなかった。
じゃあsmbd -Fにすればいいんかい、と思ったら、これがまた死ぬ。
ログを見てみたら、Terminatedされていた...。

```
# docker logs 2c4a5b2b5755f53276d088acc4b65d7f32369588026aef320c2d5d3f0bcbb131
bash: line 1:     9 Terminated              smbd -F
```

で、もうよくわからないんで、dperson/sambaを(結局)参考にして"smbd -F </dev/null"にしたら、なんと動いた。
dockerは起動後に標準入力が無くなっちゃう？ので、/dev/nullで標準入力をキープしないとsmbdが落ちてしまうんだろうか。
ここは結局謎のまま...。(nginxはdaemon offでいけるっぽいですね...sambaも見習って...)

- Windowsからアクセス出来無い

正直に言います。最初余りにもワケわからないので、dperson/samba使いました。結果、うまくいきました。
で、その後がちゃがちゃいじって、いざ自前のコンテナ起動してみたら、案の定Windowsからアクセス不可。
まぁそんなもんだよねと、dperson/sambaに戻してみたら...繋がらない。
どっか変なファイルいじってしまったか!?SELinuxとかいじらないとダメなのか!?と小一時間。

...何のことはない、ダメな時の接続が残っちゃってただけでした。
なんかおかしいと思ったら、`net use`実行!!
サイコロできるかな


- 図形は🙅 (n回目)
- 幸い埋め込みが楽なので良かったですが…
- 反転は[魔方陣で最大値？](https://codeiq.jp/q/3106)の[答案](https://github.com/cielavenir/codeiq_solutions/blob/master/thisweek_masuipeo2/tyama_codeiq3106.rb)を流用

----

- 追伸：[FASTAフォーマット](https://ja.wikipedia.org/wiki/FASTA)のパーサ、持っておくと塩基配列目的以外にもいろいろ便利ですよー

```rb:tyama_hena14.rb
#!/usr/bin/env ruby
#http://mtsmfm.github.io/2017/06/03/doukaku-e14.html
#http://qiita.com/mtsmfm/items/89b6634f363bbf5b47f5

def parsefasta(f)
	arc={}
	seq=[]
	line=f.gets
	line.chomp!
	name=line[1..-1]
	while line=f.gets
		line.chomp!
		if line[0,1]=='>'
			arc[name]=seq
			seq=[]
			name=line[1..-1]
		else
			seq<<line.chars.to_a
		end
	end
	arc[name]=seq
	arc
end

#cf: https://github.com/cielavenir/codeiq_solutions/blob/master/thisweek_masuipeo2/tyama_codeiq3106.rb
class Array
	def rotate180
		self.reverse.map(&:reverse)
	end
	def rotate90
		self.reverse.transpose
	end
	def rotate270
		self.transpose.reverse
	end
end

A=[
	[ # 反転
		lambda{|a|a},
		lambda{|a|a.map(&:reverse)},
	],[ # 回転
		lambda{|a|a},
		lambda{|a|a.rotate90},
		lambda{|a|a.rotate180},
		lambda{|a|a.rotate270},
	]
]
T=parsefasta(DATA).values.to_a

def solve(a)
	A[0].product(*A[1..-1]).each{|e|
		# 重複あるけど気にしないことにします…
		T.each{|b|
			c=e.reduce(b){|s,f|f.call(s)}
			(0..a.size-c.size).each{|sy|
				(0..a[0].size-c[0].size).each{|sx|
					h=Hash.new{|h,k|h[k]=[]}
					c.size.times{|y|
						c[0].size.times{|x|
							if c[y][x]!='*'
								h[c[y][x]]<< a[sy+y][sx+x]
							end
						}
					}
					if h.values.flatten.uniq.size==6 && h.all?{|k,v|v.reduce(:+)==7}
						return true
					end
				}
			}
		}
	}
	false
end

while gets
	p solve($_.chomp.split(',').map{|e|e.chars.map(&:to_i)})
	STDOUT.flush
end

__END__
>1
1***
2323
1***
>2
1***
2323
*1**
>3
1***
2323
**1*
>4
1***
2323
***1
>5
*1**
2323
*1**
>6
*1**
2323
**1*
>7
21**
*323
*1**
>8
21**
*323
**1*
>9
21**
*32*
**13
>10
21**
*323
***1
>11
121**
**323
```
enumを利用したSingleton実装のサンプルコード


Javaプログラミングの古典のひとつ『Effective Java』ではSingleton実現にあたって`enum`を利用することが推奨されています(「項目4: privateのコンストラクタかenum型でシングルトン特性を強制する」)。先日業務において`enum`を利用したSingletonの実装を行う機会があったので、そのサンプルコードを残しておきたいと思います。

```java:Singleton.java
public enum Singleton {
    
    /** クラス外部から呼び出してはならない. */
    INSTANCE;
    
    private String field;
    
    /**
     * 事実上のコンストラクタ。
     * インスタンスの取得にはこのメソッド以外を利用してはならない。
     * @return インスタンス
     */
    public static Singleton getInstance() {
        if (INSTANCE.field == null) {
            INSTANCE.field =  "field";
        }
        return INSTANCE;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }
}
```

```java:Main.java
public class Main {
    public static void main(String[] args) {
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance1.getField()); //=> field
        
        instance1.setField("changed field");
        
        // 別のインスタンスを生成しているように見えるが、
        // 実は同じインスタンスを使いまわしている。
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance2.getField()); //=> changed field
    }
}
```

`class`を用いた方法だと、とりわけ並列プログラミングにおいて考慮すべき点が増え、それに比例して実装も複雑化するのですが、`enum`を使うと、ごくごくシンプルにSingletonを実現することができます。とはいえこの利用方法は`enum`本来の使い方からは逸脱している――ありていにいえば「裏技」のようにも思えるので、「実装するだけでシングルトンになるinterface」が標準ライブラリにあればいいのになあと節に思う次第です(´・ω・｀)
複数人で使用しているPCでのhomebrewの正しい使い方

# はじめに

複数人でPCを使用しているときに自分専用のPCでやるようにhomebrewを使ってしまうと、PCの管理者エリアを汚してしまいます。
ユーザ固有のディレクトリにパッケージをインストールすることで、ログインしているユーザのみに影響を及ぼすようにする必要があります。
以下の手順でhomebrewを正しく使いましょう。
こんなことせずとも[linuxbrew](http://linuxbrew.sh/)なるものを使えば事足りるみたいですが。。。

# やり方

## homebrewのインストール
 `/usr/local`ではなく`~/homebrew/`に`homebrew`をインストールする。

```bash:terminal
cd
mkdir homebrew
curl -L https://github.com/Homebrew/homebrew/tarball/master | tar xz --strip 1 -C homebrew
```

## `brew`コマンドのPATHを通す
`~/homebrew/bin/`のPATHを優先する。

```bash:~/.bash_profile
PATH="$HOME/homebrew/bin:$PATH"
```

としてターミナルを再起動。
もしくは`PATH`を`export`する。

## `brew`コマンドのPATHの確認
`brew`コマンドのPATHが適切に設定できているか確認する。

```bash:terminal
which brew    # -> /Users/<user name>/homebrew/bin/brew
```

## パッケージのインストール先を確認

`brew`コマンドを用いてパッケージをインストールしたときに、そのパッケージのインストール先が適切に設定されているか確認します。

```bash:terminal
brew --prefix    # -> /Users/<user name>/homebrew
```

## パッケージをインストールしてみる

`rbenv`である必要はありません。

```bash:terminal
brew install rbenv
```

## うまくインストールできたか確認

先ほどの`rbenv`がちゃんとユーザ固有のディレクトリにインストールされたか確認する。

```bash:terminal
which rbenv    # -> /Users/<user name>/homebrew/bin/rbenv
```
Asset Localizationで多言語対応の補足

#はじめに

Neetpiaです。
現在、幻想郷ディフェンダーズというアクションタワーディフェンスをWindows/PlayStation4向けに開発しています。

[幻想郷ディフェンダーズ](http://neetpia.sakura.ne.jp/works/GensoukyouDefendersReitaisai14/index.html)

今回、台湾展示のために中国語に対応しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/182661/b8a9e768-6315-cef2-e5cc-fc5386d792b8.png)

UE4にはAsset Localizationという機能があり、楽に多言語化対応できるのですが、資料が少なく落とし穴がいっぱいありました。

今回、この資料に補足する感じで追加で対応したことを説明します。

[http://historia.co.jp/archives/6158](http://historia.co.jp/archives/6158)

#言語の切り替え

```Execute Console Command「culture=(言語別フォルダ名)」``` で言語を切り替えれるとありますが、UE4.14では何故かできませんでした。代わりにC++で言語切り替えを実装しました。

中国語に切り替えています。

```
FInternationalization::Get().SetCurrentCulture(TEXT("zh-TW"));
```

#フォルダの作成

```L10Nフォルダに作成した各言語のフォルダにアセットファイルが作られるので``` とありますが、UE4.14では自動生成されません。コンテンツブラウザからも作成できません。

例えば中国語を追加する場合、エクスプローラーから ```L10N/zh-TW``` を作成し、かつこのフォルダを認識させるために適当なアセットを入れておきます。そうすると、```Create Localized Asset``` が表示されるようになります。

#パッケージ化

パッケージ化を適切に設定しないと、パッケージにファイルが含まれずローカライズできません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/182661/1943eb1f-588f-9f53-225e-933b5844ed07.png)

----

便利な機能なのですが、資料は少なく挙動がわかりにくいところも多いです。今回もかなり回りくどいことを行ってるので、実は他に適切な方法があったら教えていただけると助かります。
[Tips]1階差分の計算と逆変換 [python/numpy]


調べてみてnumpyの関数で簡単に実現できることがわかったので、そのメモ。

```python
 import numpy as np

"""
1階差分
"""
x = np.array(range(10, 100)) # 適当なベクトル

x0 = x[0] # 初期値を保存
x_diff1 = np.diff(x)

"""
逆変換
"""
tmp = np.concatenate(([x0], x_diff1))
# または以下
# tmp = np.r_[x[0],x_diff1]
x_ = np.cumsum(tmp)

"""
チェック
"""
np.all(x == x_)
```

だいたいのことはnumpyの関数がなんとかしてくれますね。未だに馴染めないけど徐々に覚えていきたい。

# 雑記
この前処理も含めてstatsmodelsをsckit-learnのpipelineに流して綺麗に実装しようと思っているけど、微妙にインタフェースが合わないのが歯がゆい。
pipelineに乗せることで、ロジックの変更（パラメータ変更や実行順序の入れ替え、手法そのものの変更とか）に柔軟性が出ることを期待してるのですが、すんなりとは行かないものか。

楽なやり方があれば知りたい。。

# 参考
http://qiita.com/sotetsuk/items/d0e73afdcffdc8ac3e6b
Raspberry pi3構築メモ

#RASBIAN
apple pi beakerでイメージをSDに書き込んだ

参考にしたURL
(https://www.tweaking4all.com/software/macosx-software/macosx-apple-pi-baker/)
(http://qiita.com/key/items/699611bb199f63a230d1)
(http://www.myu.ac.jp/~xkozima/lab/raspTutorial1.html)

```
sudo rpi-update
sudo raspi-config
```
```
1 Expand Filesystem
2 Change Your Password
7 Advanced Options
A4 SSH No→Yes
A5 VNC No→Yes
```
```
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get install avahi-daemon
```
#解像度の設定(1080p)
/boot/config.txt

```
hdmi_group=2
hdmi_mode=82
```

#VNC
 1. メニューバーの左の方にVNCと書かれたアイコンを右クリック
 2. 「Options...」をクリック
 3. 左側メニューの「Security」を選択
 4. 「Authentic action」で、「VNC password」を選ぶ
 5. 左側メニューの「Troubleshooting」を選択
 6. 「Enable experimental direct caputure mode」にチェックを入れる
 7. 「OK」もしくは「Apply」で設定を保存

参考にしたURL
(http://a244.hateblo.jp/entry/2016/10/10/003248)
(http://www.8yazaki.jp/raspi/14_realvncserver_install/)

#リモートディスクトップ
```
sudo apt-get install xrdp
```
vncと共存できず

#node js 環境構築
```
sudo apt-get install -y node.js npm
sudo npm cache clean
sudo npm install n -g
sudo n stable
node -v
```
参考にしたURL
(http://qiita.com/setouchi/items/437e4b62e4210871496f)

Lチカ
参考にしたURL
(http://qiita.com/koki_cheese/items/a4555d6ec3a32273cf36)
(https://www.npmjs.com/package/node-pi-gpio)

node.jsのメールボックス

```
sudo npm install inbox --save
```

サービス化

```
sudo npm install forever -g
```

#シャットダウンボタン
参考にしたURL
(http://blog.livedoor.jp/victory7com/archives/42423877.html)

#カメラ

```
sudo apt-get install nc
sudo apt-get install mplayer
nc -l 5001 | mplayer -fps 31 -cache 1024 -
```

参考にしたURL
(http://www.yam-web.net/raspberry-pi/camera.html)

```
sudo apt-get install motion
sudo apt-get remove motion
cd /tmp
sudo wget https://www.dropbox.com/s/xdfcxm5hu71s97d/motion-mmal.tar.gz
sudo tar -zxvf motion-mmal.tar.gz
sudo mkdir /opt/motion-mmal/
sudo mv  motion /opt/motion-mmal/
sudo mv motion-mmalcam.conf /opt/motion-mmal/
cd /opt/motion-mmal/
sudo chmod +x motion
sudo ./motion -n -c motion-mmalcam.conf
```

/etc/motion/motion.conf

```
daemon on
```

/etc/default/motion

```
start_motion_daemon=yes
```

#音
amixer

参考にしたURL
(http://d.hatena.ne.jp/Nos/20150218/1424217597)

#サーボ制御

```
sudo raspi-config
```

```
8 Advanced Options
A7 I2C
```

```
sudo apt-get install i2c-tools python-smbus
```

#スクリーンショット

```
sudo apt-get install -y ksnapshot
```
クロージャー




・variableは定義されたときにメモリに保存される
・functionは実行されたときに中をみる
・const とかletとかにfunctionが代入されている場合、そのfunctionにはいっている変数を別のメモリに保存し、その参照をそこに保存する
・functionが実行されたときにreturnをみる。

・参照型：object, array
・プリミティブ型：string, integer, float, boolean

```sample.js
let countNumber = 0; // #0 = 0

// obejct array referece
// string integer float boolean primitive

const createCounter = () => {
  countNumber = countNumber + 1;
  const myNumber = countNumber; // #0(countNumber) = 2, #4(myNumber2) = 2
  let counter = 0 // #5(counter2) = 0

  const f = () => { // Capture: counter = #5, myNumber = #4
    counter++
    console.log(`Counter ${myNumber}: ${counter}`)
  }
  return f
}

let c1 = createCounter(); // myNumber: #1 counter: #2
let c2 = createCounter(); // myNumber: #4 counter: #5
let c3 = createCounter(); // myNumber: #7 counter: #8

c2()
c2()
c2()
c2()

c3();

c1();
c1();

```
![closure.jpg](https://qiita-image-store.s3.amazonaws.com/0/157309/21c57257-db03-7da2-ba58-982b5c21fe58.jpeg)


参考文献

関数を理解すればクロージャは難しくない！
http://analogic.jp/closure/

JavaScriptのクロージャは内部でどう機能するのか
http://postd.cc/how-do-javascript-closures-work-under-the-hood/
自由変数の名前やデータを、関数オブジェクトの中で調べる

以前、[こちらのネストした関数定義のユースケースの記事](http://qiita.com/fumitoh/items/efb44fbf3f88e8194a8d)で、クロージャについて書きましたが、フリー変数の名前や値が、関数オブジェクトの中でどのように保存されているかを調べてみました。(以下、Python3を前提にしています。)

Pythonのフリー変数は、(グローバル変数でなく、かつ)コードブロックの中で使われているけれども、そのブロック内で定義されていない変数と[説明](https://docs.python.org/3.6/reference/executionmodel.html)されています。

例えば下記のコードでは、変数`y`はネストした`bar`関数内で使用されていますが、定義されているのはその外側の`foo`関数の定義ブロック内です。なので、`y`は関数`foo`のローカル変数で、`bar`関数のフリー変数です。

```py3:
def foo():
    
    y = "I'm free in bar."

    def bar():
        print(y)
        
    y = "I'm still free in bar."

    return bar
```
`foo`は`bar`を返すので、`bar`を呼ぶには、次のように括弧が二つ必要です。

```pycon:
>>> foo()()
I'm still free in bar.
```
ちなみに、`y`の値は、`bar`が定義された時点ではなく、呼ばれた時点の値になります。上の例では`y`は`foo`の中で二回定義されていますが、後に定義された文字列になっているのがわかります。

さて、本題ですが、外側の関数`foo`オブジェクト側では、ネストした関数から使用されている変数名`y`は、自身のコードオブジェクト(`__code__`)の`co_cellvars`メンバ(tuple)に入っています。

```pycon:
>>> foo.__code__.co_cellvars
('y',)
```

一方で、`bar`オブジェクト側では、`y`はフリー変数としてコードオブジェクトの`co_freevars`メンバの中に名前が入っています。(下記のfoo()はbarです。)

```pycon:
>>> foo().__code__.co_freevars
('y',)
```
フリー変数の中身は、`cell`オブジェクトとして`__closure__`属性のtupleに入っており、次のように`cell_contents`として取得できます。

```pycon:
>>> foo().__closure__[0].cell_contents
"I'm still free in bar."
```
[macOS] ホームディクレトリやテンポラリディレクトリを URLで取得

Appleが
> ファイルを指し示す時は(NS)Stringじゃなくて(NS)URLを使おうぜ！

と言い始めてからかなりの年月が過ぎたが、頑なに(NS)Stringでしかもらえなかったホームディレクトリとテンポラリディレクトリが10.12からURLでもらえるようになってた。

```swift
extension FileManager {

    
    @available(OSX 10.12, *)
    open var homeDirectoryForCurrentUser: URL { get }

    @available(OSX 10.12, *)
    open var temporaryDirectory: URL { get }

    
    @available(OSX 10.12, *)
    open func homeDirectory(forUser userName: String) -> URL?
}
```
16進数の値が書かれたテキストファイルをバイナリファイルに変換する

#概要
- 16進数のテキストファイル --> バイナリファイルに変換する

```test.txt
1234567890abcdef
```
↓バイナリファイル化
test.bin
![test.bin.png](https://qiita-image-store.s3.amazonaws.com/0/34777/8709f126-7d11-7879-b469-7c0f0c775aea.png)

この例でpython3.2以降なら、[int.to_bytes](https://docs.python.org/ja/3/library/stdtypes.html#int.to_bytes)を使って、

```py:
with open("test.txt") as fin,  open("test.bin", "wb") as fout:
    s = fin.read()
    fout.write(int(s,16).to_bytes(len(s)//2,"big"))
```

とやってしまうのが簡単ですね。

以下は、空白や改行などが入っても対応する場合のコードです。

#コード

```py:
import re
with open('test.txt', 'r') as fin:
  s = fin.read()
  s = re.sub(r'[\r\n\t ]|0x', '', s)
  bins = [int(a+b,16) for a, b in zip(s[::2], s[1::2])]
  with open('test.bin', 'wb') as fout:
     fout.write(bytearray(bins))
```

`s = re.sub(r'[\r\n\t ]|0x', '', s)`
改行/タブ/半角スペースと`0x`を削除(置換)しています。

`bins = [int(a+b,16) for a, b in zip(s[::2], s[1::2])]`
aとbのペアで16進数を構成するように取り出して、リストに入れています。

`for a, b in zip(s[::2], s[1::2])`をもう少し詳しく示すと以下の動きをしています。

```py
In [59]: s = "1234567890abcdef"
    ...: for a, b in zip(s[::2], s[1::2]):
    ...:     print(f"a={a}, b={b}")
a=1, b=2
a=3, b=4
a=5, b=6
a=7, b=8
a=9, b=0
a=a, b=b
a=c, b=d
a=e, b=f
```


##変換例1

概要記載の通り

##変換例2
* スペースや'0x'が入ったケース

```test2.txt
0x12 0x34 0x56 0x78 0x90
```

![test2.png](https://qiita-image-store.s3.amazonaws.com/0/34777/b20f8311-12e7-4ca7-4aac-f6bbe62b51a7.png)


##変換例3
* 2の倍数の文字数でないケース

```test3.txt
1234
56789
abc
def
```

![test3.png](https://qiita-image-store.s3.amazonaws.com/0/34777/3b34b6a3-5b4f-5313-e248-6f1e469d5a8b.png)
* 最後の文字がドロップする('f'が変換されない)

# 別の手法
@shiracamuさんのpython2での方法を参考にStack Overflowを検索。回答を総合すると、python3ではcodecsを用いて以下のように書けるようだ。

```py:with_codecs.py
import codecs
with open('test.txt', 'r') as fin, open('test.bin', 'wb') as fout:
  s = re.sub(r'[\r\n\t ]|0x', '', fin.read())
  fout.write(bytearray(codecs.getdecoder("hex_codec")(s)[0])
```

#参考
- [Pythonで16進数を扱う - Python入門][1]
- [【Python】 文字列を2文字ずつ分割してリストに格納 - ばぐばぐわーるど][2]
- [Pythonでバイナリファイルを作成する - Qiita][3]
- [Python 2 str.decode(&#39;hex&#39;) in Python 3? - Stack Overflow][4]
- [Decode Hex String in Python 3 - Stack Overflow][5]


[1]:http://kaworu.jpn.org/python/Python%E3%81%A716%E9%80%B2%E6%95%B0%E3%82%92%E6%89%B1%E3%81%86
[2]:http://jum12.hatenablog.com/entry/2013/09/19/141808
[3]:http://qiita.com/norioc/items/6c6fbecc2ece6d1dc8e3
[4]:https://stackoverflow.com/questions/39784843/python-2-str-decodehex-in-python-3
[5]:https://stackoverflow.com/questions/3283984/decode-hex-string-in-python-3
Windowsのコマンドライン開発環境


# リンク集

[**Bash**  (MSYS2)](http://www.msys2.org/)
**GCC** (pacman(MSYS2/MinGW-w64))
[**Git**  (Git for Windows)](https://git-for-windows.github.io/)
[**CMake**  (本家)](https://cmake.org/)
**Make**  (pacman)
[**Python**  (Miniconda)](https://conda.io/miniconda.html)
[**Node.js**  (本家)](https://nodejs.org/ja/)
[**Ruby**  (RubyInstaller for Windows)](https://rubyinstaller.org/)
[**Perl**  (Strawberry Perl for Windows)](http://strawberryperl.com/)
**各種コマンド** (pacman)

2018/09/29 Makeについて追記
2018/12/26 chcp.comについて追記
2019/01/12 GCCのオススメを変更、pacmanについての補足の記述を変更
2020/04/03 各種コマンドのオススメを変更

# 背景
上記リンクを選択した背景です。
誤っている点などあればご指摘ください。

## Bash  (Git for Windows vs MSYS2)
**MSYS2**ではpacmanというパッケージ管理ツールが使えます。**Git for Windows**にもBash環境もついてくるのですが、pacmanの利点の差でMSYS2を選びました。[^1]

[^1]: 例えばexpectというコマンドは、非CygwinのWindows版はMSYS2のpacmanで入手するしかなさそうです。

## GCC  (Cygwin vs MinGW vs MinGW-w64)
**Cygwin**はUNIX環境を再現することに注力しているため、Linuxと同じシステムコールが使えるなど、有利な面もあります。しかしその分、Cygwin上で作ったプログラムはcygwin1.dllに依存してしまいます。今回それはなるべく避けたかったためCygwinは除外しました。
**MinGW**(Minimalist GNU for Windows)はGNUツールチェーンのWindows移植版で、**MinGW-w64**はさらにその64bit向けフォーク版です。64bit向けがあるならそちらを使いたい、ということでMinGW-w64を選びました。

## MinGW-w64  (本家 vs TDM vs MSYS2)

 **本家**のMinGW-w64は32bitコンパイルができないので**TDM**のものを使うことにしました。 

[**TDM**](https://jmeubank.github.io/tdm-gcc/) は更新が止まっています。
[**本家**](http://mingw-w64.org/doku.php) はオンラインインストーラーがありますが、私の環境では使えませんでした。
**MSYS2** のMinGW-w64をpacmanで入手することにしました。ライブラリもpacmanで取得できて便利そうです。

```
$ pacman -S mingw-w64-x86_64-gcc
```

## Git  (msys vs Git for Windows)
pacmanで**msys**のGitも入手できます。しかし**Git for Windows**にはhtmlのヘルプが付いてきました。これが読みやすかったので、シェル環境はMSYS2ですが、GitはGit for Windowsのものを使うことにしました。

## CMake  (msys vs 本家)
pacmanで**msys**のCMakeも入手できます。しかし**本家**のWindows向けCMakeではジェネレータにVisualStudioを選択できます。これは明確な利点ですので、本家版を使うことにしました。

※ 基本的に「本家で配布されている」またはそれに準じる「Windows版の定番」が存在するのであれば、pacmanで入手するよりも良い選択だと思います。

## Make  (msys vs GnuWin32)
**GnuWin32**のmakeはバージョン3.8、pacmanで入手した**msys**のmake（msysインストールときに配置されるもの）はバージョン4.1。
GoogleTestをコンパイルしようとした際、GnuWin32のものではエラーしました。

## Python  (本家 vs Miniconda)
**本家**でもWindows版が用意されているのですが、pipで取得したパッケージを使おうとした際に使えない場合が結構ありました。**Miniconda**ではpipとは別にcondaというパッケージ管理ツールが付属し、(提供されていれば)Windows用のバイナリが取得できます。OpenCV3も自分でビルドすることなく使用できたため、Minicondaを使うことにしました。

## chcp.com 65001 vs chcp.com 932

```
chcp.com 932   # -> Shift-JIS出力を期待するようになる
chcp.com 65001 # -> UTF8出力を期待するようになる
```

使いたいツールによるため、どちらがオススメとは言えません。
例を挙げておきます。

|コマンド  |932     |65001 |
|:--------|:-------|:-----|
|`cmd /?` |日本語   |英語  |
|`atom -h`|文字化け|日本語  |

## 各種コマンド（pacman vs GnuWin32）
[GnuWin32](http://gnuwin32.sourceforge.net/)でも入手できますが、pacman管理に統一した方がわかりやすくなりそうです。

# 参考
[MSYS2で快適なターミナル生活 - Qiita](http://qiita.com/Ted-HM/items/4f2feb9fdacb6c72083c)
[Windowsで使えるターミナルとシェルのまとめ - Qiita](http://qiita.com/Ted-HM/items/9a60f6fcf74bbd79a904)
[やっぱり私がUbuntuになってしまった理由 (Windows 10 Anniversary Update) - Qiita](http://qiita.com/ma2shita/items/0fac9e480d3c801b76d4#_reference-83c810a3d1996e7ad1b6)
[Windows で快適なシェル生活を送りたい - Qiita](http://qiita.com/sira/items/f90bdd70b3243af159cc#_reference-7e3ad77a5fed432afeca)