OmniAICreator/Qiita-1.07M huggingface dataset:
C#:n個の要素からk個を選ぶ組合せを列挙する


## 組み合わせとは

組み合わせの具体的な例（重複を許さない組み合わせと重複を許す組み合わせ）を以下に示します。

重複を許さない場合、{1,2,3,4,5}の5つの要素の中から 3個を選ぶ組合せは、以下の通りです。

<pre>
(1,2,3)
(1,2,4)
(1,2,5)
(1,3,4)
(1,3,5)
(1,4,5)
(2,3,4)
(2,3,5)
(2,4,5)
(3,4,5)
</pre>

重複を許す場合の組合わせは以下のようになります。

<pre>
(1,1,1)
(1,1,2)
(1,1,3)
(1,1,4)
(1,1,5)
(1,2,1)
(1,2,2)
... 途中省略 ...
(5,5,1)
(5,5,2)
(5,5,3)
(5,5,4)
(5,5,5)
</pre>

## C#のコードを書いてみる。

ここでは、n個の異なる要素の中から k個を選ぶ組合せを列挙するプログラムを書いてみます。

書いたのが以下のCombinationクラスです。

重複を許さない場合と許す場合の両方に対応しています。


```csharp
  public static class Combination {
      public static IEnumerable<T[]> Enumerate<T>(IEnumerable<T> items, int k, bool withRepetition) {
          if (k == 1) {
              foreach (var item in items)
                  yield return new T[] { item };
              yield break;
          }
          foreach (var item in items) {
              var leftside = new T[] { item };

              // item よりも前のものを除く （順列と組み合わせの違い)
              // 重複を許さないので、unusedから item そのものも取り除く
              var unused = withRepetition ? items : items.SkipWhile(e => !e.Equals(item)).Skip(1).ToList();

              foreach (var rightside in Enumerate(unused, k - 1, withRepetition)) {
                  yield return leftside.Concat(rightside).ToArray();
              }
          }
      }
  }
```

ソースコードは、[GitHub](https://github.com/gushwell/CSharpAlgorithmCollection)で公開しています。


「[n個の異なった要素の中から k個を選ぶ順列](http://qiita.com/gushwell/items/cd1facc829a895a919cc)」で掲載したコードと見比べてほしいのですが、考え方はほぼ同じです。

順列の場合と違い、（オリジナルの順番でみて）自分よりも前の要素は候補から外すようにしています。

ちょっとわかりにくい表現ですが、例をあげればわかると思います。例えば、この処理によって、{ 1, 2, 3 } は列挙されますが、 { 2, 1, 3 } や { 3, 2, 1 }などは列挙されなくなります。


## Combinationの利用サンプル

上記のCombinationクラスを利用するサンプルコードです。


```csharp
  static void Main(string[] args) {
      int n = 5;
      int k = 3;
      var nums = Enumerable.Range(1, n).ToArray();
      var combinations = Combination.Enumerate(nums, k, withRepetition:false);

      int i = 1;
      foreach (var elem in combinations) {
          string s = "(" + string.Join(",", elem.Select(x => x.ToString()).ToArray()) + ")";
          Console.WriteLine("{0} : {1}", i++, s);
      }
  }
```

以下のような結果が得られます。

<pre>
1 : (1,2,3)
2 : (1,2,4)
3 : (1,2,5)
4 : (1,3,4)
5 : (1,3,5)
6 : (1,4,5)
7 : (2,3,4)
8 : (2,3,5)
9 : (2,4,5)
10 : (3,4,5)
</pre>

-------------------------
この記事は、Gushwell's C# Programming Pageで公開したものを加筆・修正したものです。
Statusカラムを作らないでー！

# はじめに

Ruby on Rails 上でWebアプリを開発していると、`status`カラムをテーブルで作る時は非常に頻繁にある。もう、本当によくある。でも、使わないで。 `type`カラムでSTI (Single Table Inheritance) を利用したほうがいいと思います。

# statusの問題
statusカラムを使える時は、必ずクラスをわけれます一番典型的な例は、 `users` テーブルです。よく、Userモデルで、 `status` カラムを作成し、 adminや他のユーザーの種類を分けてます。これだと、 adminだけに使用するメソッドも、一般userだけに使用するメソッドもすべて、`User`モデルにいれてしまうので、わけれるメソッドがどんどんごっちゃになって増えていきます。それじゃいけない。なので、 typeカラムを作成し、STIを利用しましょう。

# 参考資料

[みんなRailsのSTIを誤解してないか!?](http://qiita.com/yebihara/items/9ecb838893ad99be0561)
Windwos Updateでエラコード：80070002が発生する問題について

Windows8.1のWindows Updateを実行するとkb3000850辺りのパッチで
`エラコード：80070002`が発生して更新完了できなくなっていたのでメモ。

# 調査

`C:\Windows\Logs\CBS\CBS.log`を調べると`TATUS_OBJECT_NAME_NOT_FOUND`のErrorが出ている。
エラーの内容としては、`必要なフォルダが無い`との事。

# 対応

1. CBS.logからTATUS_OBJECT_NAME_NOT_FOUNDが発生している箇所を調べる。
2. パスを確認して必要なフォルダを作成。
3. Windows Updateの再実行。


# 参考

[kb3000850が80070002で失敗する場合の対処方法](http://d.hatena.ne.jp/mut3/20141209)
バブルソートを使って一様な乱数から標準正規分布に基づく乱数っぽいのを生成する

#はじめに
ちょっと暇つぶしにpythonの練習がてらに様々なソートアルゴリズムを実装してる最中に思いついて実装してみた無駄な発想です

###バブルソートを使って標準正規分布に基づく乱数っぽいのを生成する
バブルソートの実装を行い、それぞれランダムで生成したデータをソートさせ、平均回数を求めてている時に、ソート回数は一様な標準正規分布に基づくのではないかと誰しもが当たり前に思いつくことを用いて、一様なランダム数から標準正規分布に基づく乱数を生成するプログラムを作った。

そのプログラムは有用なの？
~~pythonのベクトル演算numpyの
```R = np.random.rand() ```
を使わなくても標準正規分布に基づく乱数を生成できる。~~

randomでも
```random.normalvariate(mu, sigma)```
を用いることによって正規分布に基づく乱数生成できます。

~~つまりpythonにnumpyを入れなくても標準正規分布に基づく乱数を生成できる有用的でない発想です。~~
本当に有用的ではないです。

##以下プログラム
```.py
# -*- coding: utf-8 -*-
import random
import matplotlib.pyplot as plt

def bubble_sort(data,data_num):
	count = 0
	for i in range(0,data_num):
		for j in range(data_num-1,i,-1):
		 	if data[j] <= data[j-1]:
		 		count += 1
		 		data[j] , data[j-1] = data[j-1] , data[j]
	return count

if __name__ == '__main__':
	t = 10 #それぞれ各バブルソートお行う乱数の数
	n = t*(t-1)/2 #nの範囲で標準正規分布が作成される
	y = [0]*n #それぞれバブルソートを行なった時のソートにかかった回数を格納
	data = [] #毎回t個のソートするデータ

	for j in range(0,100000):
		count = 0
		for i in range(0,t):
			data.append(random.randint(1,100))

		count = bubble_sort(data,t)
		y[count] = y[count] + 1
		del data[:] #データの初期化

	plt.plot(y,marker="o")
	plt.show() 
```

![figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/154154/d69da292-2c35-e02a-b2a7-a8ebdecb472d.png)

##結果について
今回は10万回10個の乱数リストをソートし、それぞれソートにかかった回数を新たに生成された乱数として捉え、数えてグラフにしました。グラフから見て取れるように標準正規分布っぽい感じがします。n個のデータをバブルソートでソートを行なった時の最大ソート回数はn(n-1)/2であるので、今回はそれぞれ行うソートデータが10個なので10*(10-1)/2 = 45という計算になります。何故標準正規分布っぽくなるかは、ソート回数に属する乱数のパターンであると考えられます。

###まとめ
ただの自己満足のプログラムです。
S3をトリガーとするLambdaの冪等性をDynamoDBで実現してみた

Lambdaの冪等性をDynamoDBを使って実装してみました。

S3をトリガーとしてLambdaで処理する際に冪等性は考慮しておいたほうが
後々余計な手間が発生せずに済むと感じたのでブログにしてみました。
だれかの参考になれば幸いです。

詳細は下記リンクに記載しています。

http://dev.classmethod.jp/cloud/aws/lambda-dynamodb/
Android Studioでのビルド速度が約2.5倍になった話


## 環境
AndroidStudio:2.2.3
buildToolsVersion "24.0.0"

## やったこと

gradle.propertiesに下記を記述することによりビルドの速度が2倍以上速くなりました。
6分40秒→2分38秒
※初めての端末で「Run」する時の時間です。「Rebuild Project」の場合は1分以下


```
org.gradle.jvmargs = -Xmx3072m
```

ビルドの速度改善を行ったアプリではbuild.gradleにて javaMaxHeapSize "2g" を設定していたので、gradleのメモリサイズはそれよりも+1024MB多く設定する必要があったようです。

Android Studioの公式サイトに書かれています。
https://developer.android.com/studio/run/index.html#instant-run

## まとめ
ビルドがあまりにも遅いのでPCの買い替えも検討していたのですが、まずはビルドの設定から見直すべきですね！
Docker for Macを使ってRuby on Rails環境を構築する

# 概要
Ruby on Railsの開発環境をDockerを使って簡単に構築したい。

# Docker for Macのインストール

https://docs.docker.com/docker-for-mac/install/
から`Get Docker for Mac [Stable]`を選択しダウンロード、インストール。

# Ruby on Rails + PostgreSQLのアプリを動かす

https://docs.docker.com/compose/rails/
に従う。

## プロジェクトの構成を定義

適当なプロジェクトフォルダを作ってその中にファイルを4つ作る。

```:Dockerfile
FROM ruby:2.4.1
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
```

```ruby:Gemfile
source 'https://rubygems.org' 
gem 'rails', '5.1.1'
```

空の`Gemfile.lock`を作る。

```Gemfile.lock
```

```yaml:docker-compose.yml
version: '3'
services:
  db:
    image: postgres
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

## プロジェクトをビルド

ターミナルでプロジェクトフォルダに行き、以下を実行。

```
docker-compose run web rails new . --force --database=postgresql
```

Railsのファイルがずらっと生成される。次に以下を実行。

```
docker-compose build
```

## データベースの設定
`config/database.yml`の`development:`の部分を以下のように変更。

```config/database.yml
development: &default
  adapter: postgresql
  encoding: unicode
  database: myapp_development
  pool: 5
  username: postgres
  password:
  host: db
```

そしてデータベースを作成。

```
docker-compose run web rake db:create
```

## 起動

```
docker-compose up
```

http://localhost:3000
にアクセスしてみる。`Yay! You’re on Rails!`と表示されれば成功。

## 終了

`Ctrl+C`で終了してしまうと次に`docker-compose up`で起動しようとしたときにエラーで起動できなくなることがある。`tmp/pids/server.pid`が残ってしまっているのが原因なので、

```
rm tmp/pids/server.pid
```
で削除してから再び`docker-compose.up`すればいい。ただ、毎回これをやるのは面倒なので、もう一つターミナルを立ち上げ、
```
docker-compose down
```
で終了すれば余計なファイルが残ったりせず、正常に終了できる。

## DBの永続化

このままだとデータベースが終了するたび毎回消えてしまうので、`docker-compose.yml`を以下のように修正する。

```yaml:docker-compose.yml
version: '3'
services:
  db:
    restart: always
    image: postgres
    volumes:
      - sql-data:/var/lib/postgresql/data
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  sql-data:
    driver: local
```
Kinesisを使うAWSのシステム構成

AWSのKinesisに関する基本的な内容をまとめてみたものです。AWSのKinesisに関する、Web上にすでにある解説コンテンツをまとめたサイトの抜粋です。
[Kinesisを使うシステム構成] (https://www.techcrowd.jp/kinesis/configurations-2/)

# [Amazon Kinesis Firehoseを用いたシステム構成] (https://www.techcrowd.jp/kinesis/configurations-2/)

Kinesis使ったシステムのデザインパターンは複数ありますが、最も手軽にストリーミングデータをロード出来るのがAmazon Kinesis Firehoseを利用する方法です。

Amazon Kinesis Firehoseを使えば、AWS マネジメントコンソールを使って簡単に

・Amazon S3
・Amazon Redshift
・Amazon Elasticsearch Service

にストリームを配信する事が出来ます

ストリームの送信先に、

・Amazon S3 バケット
・Amazon Redshift テーブル
・Amazon Elasticsearch ドメイン

を設定する事が出来ます。


# [AWS Lambdaを用いたシステム構成] (https://www.techcrowd.jp/kinesis/configurations-2/)

AWS Lambdaを使ってシステムを構築すると、Kinesisを効果的に利用出来ます。

AWS Lambda は定期的にストリームをポーリングして、新しいレコードを検出し、Lambd関数によってAmazon Kinesisストリームからレコード読み取込み、データの処理を行います。

具体的な処理の流れは、次のようになります。
・Kinesisのストリームにレコードが書き込まれます
・ストリームをポーリングしているAWS Lambdaが、新しレコードを検出するとLambda 関数が呼び出されます
・Lambda 関数が実行されて、レコードを読み込んで処理します


# [Amazon Kinesisアプリケーションを構築する] (https://www.techcrowd.jp/kinesis/configurations-2/)

既存のAWSを利用する事でKinesisを使ったシステムを構築出来ますが、

・Amazon Kinesis API
・Amazon Kinesis Client Library (KCL)

などを使用して、Amazon Kinesisアプリケーションを構築する事も可能です。

独自のAmazon Kinesisアプリケーションを構築すれば、より複雑なストリーム処理が行えます。
【React Native】React.ATRライブラリのリンクを自動でやる方法

使いたかったパッケージが `react-native-progress` ってパッケージでプログレスバーを出したかった。

https://github.com/oblador/react-native-progress

しかし、React Nateveに取り込まれている `React.ATR` を使っているらしくヒモ付をする必要があるみたいでした。
ReadMeの手順では、CocoaPodを使う or 手動でした。Gemに依存するのが嫌だったので他の方法を探して見つけたのでメモしておきます。

バージョン情報等は下記リポジトリを参照していただけると。。。
https://github.com/togana/sample-rnpm

# React Native公式ページ参照

http://facebook.github.io/react-native/docs/linking-libraries-ios.html#content

## 自動でのやり方

他のパッケージ(react-native-vector-icons)などはうまくヒモ付がされて感動したのですが、肝心のprogressがうまくいかない。

```bash
$ npm install <library-with-native-dependencies> --save
$ react-native link
```

# rnpmを使ってみた

```bash
$ npm install -g rnpm
$ rnpm link react-native/Libraries/ART
rnpm-link info iOS module react-native/Libraries/ART is already linked
```

`react-native link` で紐付けられなかった `React.ATR` を紐付けることができた。

# 最後に

実はrnpmは、すでにreact-nativeのcoreに取り込まれているので同じようなことができると思われる。
オプションでconfigを受け取ることができるようになっているみたいなので引き続き調査して可能であれば `react-native link` でできるようにしたい。

ちなみにissue見てた感じだとstack overflowで聞けってことらしい。
https://github.com/facebook/react-native/issues/12852#issuecomment-285730218

時間かかりすぎて疲れたので後日また試したい。こうやるべきとかあればコメントなどで教えてください。

こんな感じで指定できるといいんだけどな。。。
参照 https://github.com/rnpm/rnpm/releases/tag/v1.5.4

```json:package.json
	"rnpm": {
		"ios": {
			"libraryFolder": "react-native/Libraries/ART"
		}
	},
```
KinesisとSQSの違いとは 

AWSのKinesisに関する基本的な内容をまとめてみたものです。AWSのKinesisに関する、Web上にすでにある解説コンテンツをまとめたサイトの抜粋です。
[KinesisとSQSの違いとは] (https://www.techcrowd.jp/kinesis/diff-from-sqs/)

# [Amazon SQSとは] (https://www.techcrowd.jp/kinesis/diff-from-sqs/)

Amazon SQS（Amazon Simple Queue Service）は、コンピュータ間で通信されるメッセージを保存するためのキューサービスで、
・メッセージの監視を行うので、アプリケーションの負担が軽減される
・最大15分間のメッセージの遅延をスケジュール出来る
などの機能があります。

Amazon SQSを使う事で、複数のコンピュータによって分散処理する際に、信頼性の高いメッセージの遣り取りをする事が可能となります。


# [KinesisとSQSの違い] (https://www.techcrowd.jp/kinesis/diff-from-sqs/)

AWSにおいてKinesisとSQSは共に、データの投入から取り出しまでをサポートするサービスである事は同じですが、データの処理能力や用途などが大きく違います。

KinesisとSQSを比較すると、

Kinesis
・大規模なデータのストリーミングをリアルタイム処理する
・メガバイト単位のデータも扱える
・アプリケーションを開発するのは難しい

SQS
・コンピュータ間のメッセージの遣り取りのために使われる
・コマンドなどを伝えるためのメッセージを扱う
・簡単に操作出来る

といった違いがあります。


# [KinesisとSQSの本来の役割] (https://www.techcrowd.jp/kinesis/diff-from-sqs/)

KinesisとSQSは、広い意味でのキューサービスに含まれますが、

・Kinesisは、キューの機能を持ったビックデータの処理基盤
・SQSは、キューの本来の機能を備えたシンプルなサービス

と解釈出来ます。

KinesisとSQSは機能が豊富なので、さまざまな使い方が出来ますが、本来の用途に従って使う事で、安定したシステム構築が可能となります。
Kinesisストリームに対する操作手順

AWSのKinesisに関する基本的な内容をまとめてみたものです。AWSのKinesisに関する、Web上にすでにある解説コンテンツをまとめたサイトの抜粋です。
[Kinesisストリームに対する操作手順] (https://www.techcrowd.jp/kinesis/methods/)

# [Kinesisストリームに対する操作] (https://www.techcrowd.jp/kinesis/methods/)

Kinesisストリームに対して、

・ストリームの作成
・ストリームへのデータの追加
・ストリームからのデータの読み取りと処理

などの操作を行う事が出来ます。


# [Kinesisストリームの作成手順] (https://www.techcrowd.jp/kinesis/methods/)

AWSにサインアップしてから、
・Amazon Kinesis Management Console
・Amazon Kinesis CreateStream オペレーション
などを使って、Amazon Kinesisストリームを作成出来ます。

Amazon Kinesisストリームのスループットについて、ストリーム内のシャードの数によって決定します。

シャードの数は、以下の式で計算します。

・A＝ストリームに書き込むレコードの平均的サイズ（キロバイト単位で計算して、最も近いKB値に切り上げたもの）
・B＝1秒間にストリームに書き込むレコード数
・C＝ストリームからのデータを同時に使用するKinesisのアプリケーション数
・D=A×B（入力を書き込む時の帯域幅のKB数）
・E=C×D（出力を読み取る時の帯域幅のKB 数）

ストリームで必要なシャード数＝max (D/1000, E/2000)


# [ストリームへのデータの追加] (https://www.techcrowd.jp/kinesis/methods/)

Amazon Kinesisストリームにデータを追加するには、

・PutRecordオペレーション
・PutRecordsオペレーション
・Amazon Kinesis Producer Library (KPL)
・Amazon Kinesis Agent

などを使います。

PutRecordオペレーション
１つのデータレコードの操作をします

PutRecordsオペレーション
複数のデータレコードの操作をします

Amazon Kinesis Producer Library (KPL)
Amazon Kinesisのストリームに詳細な設定が出来るライブラリ

Amazon Kinesis Agent
Kinesisストリームの操作を行うJava アプリケーション


# [Kinesisストリームのデータの読み取り] (https://www.techcrowd.jp/kinesis/methods/)

Kinesisストリームのデータは、

・Amazon Kinesis API
・Amazon Kinesis クライアントライブラリ（KCL）

を使って開発したAmazon Kinesisアプリケーションで読み取る事が出来ます。
Kinesisストリームの構成と操作

AWSのKinesisに関する基本的な内容をまとめてみたものです。AWSのKinesisに関する、Web上にすでにある解説コンテンツをまとめたサイトの抜粋です。
[Kinesisストリームの構成と操作] (https://www.techcrowd.jp/kinesis/streams/)

# [Kinesisストリームにおけるスループットの基本単位] (https://www.techcrowd.jp/kinesis/streams/)

シャードはAmazon Kinesisストリームにおけるスループットの基本単位で、シャードの数を指定してKinesisストリームを作成します。

1シャードで、
・1MB/秒のデータ入力
・2MB/秒のデータ出力
が可能で、1 秒で最大1000件までのPUTレコードの処理が出来ます。


# [Kinesisストリームに格納されるデータの単位] (https://www.techcrowd.jp/kinesis/streams/)

Amazon Kinesisストリームに格納されるデータの単位が、レコードです。

レコードは、
・シーケンス番号
・パーティションキー
・データ BLOB
から構成されます。

データ BLOBが処理対象のデータで、最大1メガバイトまでストリームに組み込む事が可能です。

パーティションキーはストリームにデータを組み込む時に設定されて、レコードを分離してストリームの異なるシャードにルーティングされる際に使われます。


# [リシャーディング: ストリーム内のシャードの数の調整](https://www.techcrowd.jp/kinesis/streams/)

Amazon Kinesisストリーム内のシャードの数を調整する事を、リシャーディングと呼びます。

リシャーディングでは、
・シャードの分割
・シャードの結合
の2種類の操作が行われます。

シャードの分割
1つのシャードを2つのシャードに分割して、ストリームのスループットを向上させます

シャードの結合
2つのシャードを1つのシャードに結合して、ストリームのスループットを低下させます
Android初心者がGoogle Play Storeにアプリを公開するまで #1

### はじめに

私はずっとVB.NETで業務アプリを作成していたエンジニアです。
スマホもiPhoneでAndroid端末を触ったことがないですが、Androidアプリを作成し公開しようと思いたちました。
いずれiPhoneのアプリも作成しようと思ってます。
なぜAndroidかというと$25払えば公開可能という手軽さからです。
iPhoneの場合、Apple Developer Programに登録し、年11,800円支払う必要があります。

### 開発環境

Windows 10 Pro
Android Studio 2.3.2

### どのようなアプリを作るか

ここが一番悩んだところです。
今回は1000から7ずつ引いていき6になったらクリアというミニゲームを作ってみました。
広告収入も欲しかったため、AdMobに登録し、広告を表示するようにしました。

[アプリ:千七](https://play.google.com/store/apps/details?id=jp.naoki.thousandgame1&hl=ja)


### 公開準備で行ったこと
- Android Developerに登録し$25を支払う。
- AdMobに登録し広告をアプリに表示するように実装
- Firebaseに登録。
- アイコンの作成（512x512のpng）Windows標準のペイントでサクッと作成。
- スクリーンショット 2枚 エミュレーターのスクリーンショット機能で取得。
- ヘッダー画像（1024x500のpngまたはjpg） アイコンの画像を流用。

### 苦労したこと
- Androidの実機がなかったため、実機でのテストができなかった
- Google Play Consoleに登録したアイコンがアプリのアイコンになると勘違いしてましたorz
- アプリのアイコンを作成しapkに含めないといけないのをリリース後に気づきました。（そのためいまだ、デフォルトのアイコンです）



以降、随時更新していきたいと思います
Amazon Kinesis:の概要

AWSのKinesisに関する基本的な内容をまとめてみたものです。AWSのKinesisに関する、Web上にすでにある解説コンテンツをまとめたサイトの抜粋です。
[Amazon Kinesisの概要] (https://www.techcrowd.jp/kinesis/summary-5/)

# [Amazon Kinesis:とは] (https://www.techcrowd.jp/kinesis/summary-5/)

Amazon Kinesis とは、AWSにおけるストリーミングデータ用プラットフォームで、
・クリックストリーム
・アプリケーションログ
・ソーシャルメディア
などのさまざまなデータを処理する事が出来ます。

Amazon Kinesisには次のような特徴があります。

迅速なデータを取得
データが生成された時点でAmazon Kinesisストリームにデータを書き込めるので、データの生成元に障害が発生した場合でも、データが失われる事はありません

リアルタイムのストリーミングデータの分析が可能
Amazon Kinesis Streamsは、リアルタイムでストリーミングデータの分析を行えます

複雑なストリーム処理が行える
Amazon KinesisアプリケーションやデータストリームのDirected Acyclic Graph (DAG) を作成する事で、Amazon Kinesisストリームにデータを追加したり、継続的にストリームの処理が出来ます

トラフィックの増加にも対応可能
一時的にトラフィックが増加しても、データのバッファリングで対応します


# [Amazon Kinesis Streams] (https://www.techcrowd.jp/kinesis/summary-5/)

Amazon Kinesis Streamsを使うと、

・ウェブサイトのクリックストリーム
・金融に関する取引情報
・ソーシャルメディアなどのフィード
・IT関連のログ

など数多く分野で、独自のストリーミングデータ処理が行えるアプリケーションを構築出来ます。

Amazon Kinesis Streamsには、

・1 時間何テラバイトに及ぶ何十万件ものデータを、連続的に取得して保存出来る
・Amazon Kinesis Producer Library (KPL) や Amazon Kinesis Client Library (KCL)を使って、容易にアプリケーションが構築可能
・複数のAmazon Kinesis Streamsアプリケーションで、同じストリームを同時に処理出来る

などのメリットもあります。


# [Amazon Kinesis Firehose] (https://www.techcrowd.jp/kinesis/summary-5/)

Amazon Kinesis Firehoseを使えば、AWSマネジメントコンソールを数回操作するだけで、ストリーミングデータのキャプチャとロードが簡単に出来ます。

Amazon Kinesis Firehoseは、

・Amazon S3
・Amazon Redshift
・Amazon Elasticsearch Service

と統合されていますので、分析用アプリケーションやツールを用いてストリーミングデータの分析をする事も可能です。


# [Kineisの料金体系] (https://www.techcrowd.jp/kinesis/price-3/)

Amazon Kinesis Streamsは、使ったリソースについての料金を支払うだけなので、前払い金や最低料金はありません。

具体的な料金は、
・シャード
・PUTペイロードユニット
・データの保持期間延長
を使って計算されます。

シャード
Amazon Kinesisのストリームのスループット単位が、シャードです。
1時間にストリーム内で使用するシャード数に応じて、料金が決まります。

PUTペイロードユニット
PUTペイロードユニットについては、100 万件ごとに料金が請求されます。

データの保持期間延長
Amazon Kinesisではデータを24時間保存していますが、最長7日間までデータの保持期間を延長する事も可能です。但し、保持期間を延長すると、シャード時間に対する料金が発生します。

料金が請求されない使い方
・Amazon Kinesisストリームから送信されたレコードの取得
・データの生成元からAmazon Kinesis Streamsへの転送
・Amazon Kinesis Streamsから他のKinesisアプリケーションへのデータ転送
については、無料となっています。

Amazon Kinesisの無料で使える部分を活用する事で、コストを抑えてストリームデータ処理を行う事が出来ます。
Visual Studio / WPF > 「my:」プレフィックス付きのXML名前空間 | 「local:」プレフィックス付きのXML名前空間

```txt:動作環境
Windows 7 Pro (32bit)
Microsoft Visual Studio 2017 Community
Sublime Text 2
```

@gushwellさんのコードを参考にWPFの学習をしている。
http://gushwell.ldblog.jp/archives/52288631.html

```
xmlns:my="clr-namespace:WpfSample.Binding01"
```
という部分が気になった。

こちらの環境(VS2017)でプロジェクトを作った場合、デフォルトで生成されるXAMLコードにおいて、以下が近いものであるように思う。

```
xmlns:local="clr-namespace:_170604_t1600_binding_singleData"
```

myというプレフィックスがどういう経緯で使われるようになり、localとどう区別しているのかは未消化。

https://sakapon.wordpress.com/2010/11/14/xmlns/
などでもmyが使われている。

https://stackoverflow.com/questions/4797690/silverlight-custom-control-default-xmlns
Silverlightでのデフォルトだろうか?
GithubにPull Requestするときのトークンのscope

GithubにAPI経由でPull Requestを作るときに、トークンに必要なscopeを調べたところ、public_repo scopeが必要でした。


<img width="746" alt="Edit_personal_access_token.png" src="https://qiita-image-store.s3.amazonaws.com/0/529/96035c56-e9c4-0425-4eb0-859b5f2c5f0a.png">

トークンを指定していない、またはトークンに必要なscopeがないと、404エラーが返されます。

```
% curl -X POST https://api.github.com/repos/:owner/:repo/pulls
{
  "message": "Not Found",
  "documentation_url": "https://developer.github.com/v3/pulls/#create-a-pull-request"
}
```

調べるのに30分かかった。


参考: [Github REST API V3 Reference](https://developer.github.com/v3/)
unownedの使いどころ

Swiftでクロージャーを利用する場合、循環参照をしないようにself(場合によってはself以外の変数も)を弱参照にしますが、その時weak or unownedどちらにするべきか迷うことがあると思います。
基本的には困ったらweakにして置くのがベターですが、unownedを使えれば記述も少し短くなるのでその例を紹介します。

## unownedを使える条件
循環参照するかつクロージャーが呼ばれる時にその対象が解放されていない場合です。
解放されている状態で万が一その対象にアクセスするとクラッシュします。

クラッシュする例

```
class SomeVC: UIViewController {
    func apiRequest() {
       Session().send() {[unowned self] in
           // ネットワークの状況によっては数秒後にクロージャーがコールされる
           // Backボタン等でこのVCが解放されていたらselfにアクセスした時点でクラッシュする
           self.handleAPIResponse()
       }
    }
}
```

クロージャーの呼び出される期間がオブジェクトの生存期間と同じであればこのようなことは起きませんが、ネットワークアクセスやアプリで使い回すシングルトンのモジュールなどはどうしても生存期間が違ってきます。

## unownedを使えるパターン
### パターン1:オブジェクトの解放されるタイミングで明示的にクロージャーの呼び出しを無効化する場合
```
class SomeVC: UIViewController {
    var task: SessionTask?
    var object = Object()
    deinit {
        task?.cancel()
        object.completion = nil
    }
    func apiRequest() {
       task = Session().send() {[unowned self] in
           // ネットワークの状況によっては数秒後にクロージャーがコールされる
           // deinitでcancelされてるのでselfが解放されるとここは呼ばれないのでクラッシュしない
           self.handleAPIResponse()
       }

       object.completion = {[unowned self] in 
           // deinitでobject.completionにnilを代入しているので解放後ここは呼ばれずクラッシュしない
           self.someAction()
       }
       object.longTimeMethod()
    }
}
```

### パターン2:オブジェクトの生存期間とクロージャーの呼び出される期間が同じ場合
通常のSwiftではあまりないですが、RxSwiftを使う時に使えます。

```
import RxSwift
class SomeVC: UIViewController {
    let vm = SomeViewModel()
    let disposeBag = DisposeBag()
    func viewDidLoad() {
        vm.observableObj.subscribe(onNext: { [unowned self] (_) in
            // disposeBagが解放されると、このクロージャーも無効化されるので解放後ここは呼ばれずクラッシュしない
            self.someMethod()
        }).addDisposableTo(disposeBag)
    }
}
```

パターン1はdeinitに毎回書くのがめんどいのであまりやりませんが、unownedを使うとselfに直接アクセスでき、ちょっとだけ記述が楽になるので問題がない時は積極的に使ってみるのもいいと思います。
SSDをSecureEraseしてみた


[SSDをSecure Erase機能で安全に消去する](http://qiita.com/nvsofts/items/f46c8a1b3541894ad382)

SSDをSecure Eraseしたのですが、メモ的にコマンドだけ残します。上記の記事を参考にさせていただきました。細かい話はそちらを参考にしてください。

Ubuntu17.04のLiveUSBを使用しました。LiveUSBを使うと、インストールしなくて良いので楽なのと、MacなどNotePCに内蔵されているSSDにもコマンドを放てる方法です。(OS復元領域なども初期化する手順です。本当に戻せないので気をつけてください。)

Windowsしか知らない人は、LinuxのCドライブとかパーティションの扱いに関して、確認しておくと良いかと。

Linuxのお勉強が面倒なら、

■ SSDの容量や製造した会社を把握しておく
or
■ SSDを一台しか繋がない

など、対策をしておくこと。

### コマンド一覧
---

```bash

# show device list
sudo fdisk -l

# show disk info
sudo hdparm -I /dev/sda

# is passowrd set?
sudo hdparm -I /dev/sda | grep enabled

# is frozen lock?
sudo hdparm -I /dev/sda | grep frozen

# is suported secure erace?
sudo hdparm -I /dev/sda | grep supported

# set passowrd 'aaaa' to ssd
sudo hdparm --user-master u --security-set-pass aaaa /dev/sda

# exec secure erase
sudo hdparm --user-master u --security-erase aaaa /dev/sda

# exec enhanced secure erase
sudo hdparm --user-master u --security-erase-enhanced aaaa /dev/sda

```

### 手順
---

- Ubuntu LiveUSBの作成
- 起動後、コマンドで状況把握（frozen状態や「enhanced secure erase」が使えるか？など）
- frozen状態の場合、「sleep&復帰」するか「SSDの電源ケーブルを抜き差し」するなどして、SSDへの電源供給を断ってfrozen状態解除する。
- SSDに対してパスワードロックをかける。（初期化確認のため？）
- 使えるeraseコマンドを放つ。
- パスワードロックが無ければ、初期化成功。
Ubuntu 16.04 LTS 備忘録

Ubuntu 16.04についてのメモ書き

# CUI起動設定
`$ sudo systemctl set-default multi-user.target`
-元に戻す場合
`$ sudo systemctl set-default graphical.target`

# 途中でGUI起動
`$ sudo systemct1 start lightdm`

#途中で切り替え
GUI -> CUI
Ctrl + Alt + F1

CUI -> GUI
Alt + F7
npmを使ってbowerをインストールする


### node.jsをインストール

https://nodejs.org/en/

### npmを確認

node.jsをインストールするとnpmが入っているはずなので以下のコマンドを実行する

```sh
# node.jsのバージョンを確認
node -v
# npmのバージョンを確認
npm -v
```

# bowerをインストール

```sh
# npm 経由でbowerをインストール
npm install bower
# bowerのバージョンを確認
bower -v
# bowerでjqueryをインストールしてみる
bower install jquery
```

ライブラリののバージョン記載されている**bower.json**が設置される
treeコマンドでnode_modulesディレクトリを表示しないようにする


node.jsのプロジェクトディレクトリで`tree`を実行すると，`node_module`ディレクトリ以下がブワーっと出てうわー！っとなってしまうので，シェルのエイリアスで無視するように設定しました．

## 環境

```zsh
$ tree --version
tree v1.7.0 (c) 1996 - 2014 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro

$ zsh --version
zsh 5.3.1 (x86_64-apple-darwin16.3.0)
```

## 設定

zshでの設定ですが，bashでも同じように動くと思います．

```zsh:.zshrc
# tree alias
alias tree="tree -I node_modules -L 3"
```

`node_modules`の無視と，最大で3つ下までのディレクトリをツリー表示するのをデフォルトオプションにしました．

## エイリアスを無視する場合

エイリアスを無視して`tree`コマンドそのものを呼び出す場合は`\`を付けて実行します．

```zsh
$ \tree
```
[IntelliJ IDEA][IdeaVim] Vim Emulationのキーバインド設定変更

未定義の設定の警告はでるもののどこから設定すればいいかだいぶ迷ったので設定箇所のメモ

# 設定場所

上部メニューバーから `File -> Settings` でSettingsダイアログを開く。
Settingダイアログの左から `Other Settings --> Vim Emulator` を選択。(上の検索バーで `vim` と検索しても良い）

すると以下の設定画面が表示されるはずなのでキーバインドを変更する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37721/c40939c0-88ec-0074-56d2-8860458730ac.png)

未定義だと毎回警告ポップアップが出てしまうので全部埋めたほうが良いかもしれない。

# 参考
[vim - how to change editor behavior in intellij idea - Stack Overflow](https://stackoverflow.com/questions/28156011/how-to-change-editor-behavior-in-intellij-idea)
Happy Hacking Keyboard(PD-KB02)をSierraで使用する

# はじめに
- 初代HHK、OSX(Sierra)で利用する為のメモ

# 環境
- HHK型番:PD-KB02
- MODE設定: 3
- PS2,USB変換: ルートアール USB-PS/2 変換ケーブル RC-U2MK
- OSバージョン: 10.12.5 (Sierra)

# 設定

## Karabiner-Elements インストール

- https://github.com/tekezo/Karabiner-Elements/blob/master/README.md

## Karabiner-Elements 設定

### Simple Modification設定
- From Key: PCキーボードの無変換キー → To key: left_command 
- From Key: PCキーボードの変換キー → To key: right_command 
 

# まとめ

公式ドライバが提供されていない初代HHK、引退考えていましたが、暫く現役でつかえるようになりました。
Karabiner Elementsの開発者、ブログ記事上げて頂いた方に感謝です。

# 参考

- [Happy Hacking Keyboard(PD-KB02)をSierraで使用する](http://koty.hatenablog.com/entry/2017/01/04/093930)
- [Happy Hacking Keyboard(PD-KB02)をEl Capitanで使用する](http://qiita.com/a_k0406/items/800841182813ef9e787f)
MSYS2でPGIコンパイラを使う

[PGIコミュニティ版](http://www.pgroup.com/products/community.htm)は誰でも無料で使えます。URLはpgi.comでもpgigroup.comでもないので注意。Fortranが含まれていて，OpenACCやCUDA Fortran（macOSはGPUサポートなし）が使えます。MPIは16プロセスまで。詳しくは [機能の比較](http://www.pgroup.com/products/feature-compare.htm) 参照。

# インストール

Mac版のインストールは，インストーラーを使って簡単にできます。

Linux版はシェルスクリプトの質問に答えていく形式。

~~Windows版は[Visual Studio 2015](https://www.microsoft.com/ja-jp/dev/products/visual-studio-2015.aspx)が必要です。~~Microsoftアカウントを作って，[このあたり](https://my.visualstudio.com/downloads)からダウンロードします。[Visual Studio 2015](https://www.microsoft.com/ja-jp/dev/products/visual-studio-2015.aspx)からだと最新版の2017に誘導されます。
[追記] 18.10からVisual Studio 2017に対応

MSYS2が使いたいので，Cygwinは断りました。それでも環境変数を設定済のコマンドプロンプトPGI Cmdから使えます。

数値計算をするならIntelの[MKL](https://software.intel.com/en-us/mkl)が[無料で使える](https://www.isus.jp/products/psxe/free_mkl/)ので入れておきましょう。オプションでPGIコンパイラのサポートにチェックを入れてください。

# MSYS2から使う

MSYS2から使うには`PATH`の設定が必要です。PGIコンパイラは無料ですがコンパイル時にはライセンスをチェックしていますので，ライセンスファイルを環境変数`LM_LICENSE_FILE`に指定しておく必要があります。`MKLPATH`に[Intel Math Kernel Library](https://software.intel.com/en-us/mkl)のライブラリのパスを指定します。ここではMKLで導入したものを指定しています。

```.bashrc:
PGI="/c/Program Files/PGI"
PGIVERSION=18.10
PATH="/c/Program Files/Java/jdk1.8.0_144/bin:/c/Program Files/PGI/flexlm:${PGICE}/win64/2018/cuda/9.1/bin:${PGI}/win64/2018/cuda/9.2/bin:${PGI}/win64/2018/cuda/10.0/bin:/c/Program Files (x86)/Windows Kits/10/bin/x64:/c/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.15.26726/bin/Hostx64/x64:${PGI}/win64/${PGIVERSION}/bin:${PATH}"
MANPATH="${PGICE}/win64/${PGIVERSION}/man:${MANPATH}"
LM_LICENSE_FILE="${PGI}/license.dat"
MKLPATH="/c/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows/mkl/lib/intel64_win"
export PATH MANPATH LM_LICENSE_FILE MKLPATH
```
[追記] 18.10に更新しました。バッチファイル`C:\Program Files\PGI\win64\18.10\pgi_dos.bat`を参考にPATH等環境変数の設定を改めました。

# 動作確認

[PGIコンパイラによるインテル MKL ライブラリのリンク方法](https://www.softek.co.jp/SPG/Pgi/TIPS/public/general/mkl_link.html)の行列積のプログラムのコンパイルやリンクを試してみましょう。`MKLPATH`は設定済ですし，WindowsのPathの設定などは必要ありません。

```
$ pgfortran -Minfo -fast -L"$MKPATH" mkl_intel_lp64.lib mkl_pgi_thread.lib mkl_core.lib -mp mutmul.f -o mutmul
```
[追記]
* `MKLPATH`は引用符で囲む。
* ライブラリを`-l`で参照すると当然先頭に`lib`がついて`libmkl_core`のようになるので，ファイル名をそのまま書く。
PDFにページ番号を振って目次をつける

原稿を集めてページ番号を振る方法を半自動化する方法。[gist](https://gist.github.com/tenomoto/bffd8896a1ec10205ec86aab01127327)に一式あり。

## 準備

* xpdfに含まれるpdffonts, pdfinfo
* pdflatex

## 1. フォント埋め込み

* 集めたPDFをpdfフォルダに格納する。
* run_pdffonts.shを実行する。
* フォントが埋め込まれていないPDFはpdf_not_embeddedに移動される。
* pdf_not_embeddedのファイルを一つずつ開いて「印刷>PDFに保存」（macOSの場合）でpdfフォルダに保存する。

## 2. ページ番号付け

run_addpage.shを実行する。

     ./run_addpage.sh > pages.txt

ページ番号付けは次の手順で実行され，ページ番号が書かれたpages.txtが出力される。

1. pdfinfoでページ数を数える。
2. addpage.shの中でtemplate.texの開始ページNと埋め込むファイル名PDFを置き換える。
3. addpage.shからpdflatexを呼び出してページ番号のついたPDFを作成する。
4. run_addpage.shでpdf_outに格納する。

## 3. 目次と結合されたPDFに関するデータの作成

prepare_tex.shを実行する。

1. pages.txtの後ろにタイトルと著者を半角の「,　」で区切って並べたtitle-author.txtを連結しagenda.txtを作成する。
2. toc.awkによりagenda.txtから目次ファイルtoc/toc.tocと
3. all.awkによりagendata.txtから要旨を結合するためのファイルを指定するall/includepdf.texを生成する。

## 4. 目次の生成

toc/toc.texを編集し，タイプセットする。

     $ platex toc && platex toc && dvipdfmx toc

## 6. 結合されたPDFの作成

all/all.texをタイプセットする。platexではないので注意。

     $ pdflatex all
Vim script 用オムニ補完関数の設定


[Vim script 用のオムニ補完関数を書きました - 書いたものなど](http://machakann.hatenablog.com/entry/2017/05/29/191116) とのことなので、[vim-Verdin](https://github.com/machakann/vim-Verdin) を使う設定を書いてみた。

[dein.vim](https://github.com/Shougo/dein.vim) で TOML を使っているのでこんな感じ。
[neocomplete.vim](https://github.com/Shougo/neocomplete.vim) と [neosnippet.vim](https://github.com/Shougo/neosnippet.vim) ので neocomplete から Verdin を呼び出すようにする。
（当初は neocomplete と置き換えようかと思ったけど、neosnippet を使いたかったのでやめた。）

Vim script で補完を実行するタイミングが、この正規表現でいいのかはわからん。
名前空間もあるか～と思って : も含めたけどいらんかな？
同じ考え方なら # も含めた方が良いか……。
``` let g:neocomplete#force_omni_input_patterns.vim = '\%(\w\|[:\.]\)\{3,}' ```


```
[[plugins]]
repo = 'machakann/vim-Verdin'
on_ft = 'vim'
hook_source = '''
  let g:Verdin_fuzzymatch = 1

  " neocomplete
  let g:neocomplete#sources = get(g:, 'neocomplete#sources', {})
  let g:neocomplete#sources.vim = ['neosnippet', 'omni']
  let g:neocomplete#force_omni_input_patterns = get(g:, 'neocomplete#force_omni_input_patterns', {})
  let g:neocomplete#force_omni_input_patterns.vim = '\%(\w\|[:\.]\)\{3,}'
'''
```
NSRunLoopを立ち上げるベストプラクティス

# NSRunLoopを立ち上げるベストプラクティス

## 問題

NSRunLoopは個人的に以下の2点の仕様によって, 罠に嵌まることが多いように思う.

- runModeが条件を満たしていないとイベントが発火しない
- timerなどを紐付けたRunLoopが終了すると, 以降のイベントは発火しない

その為, View関係の処理を登録したい場合はmainRoopに, そうでない場合は自分でrunLoopを立ち上げることになると思う.
その際に散見されるのが以下の実装である.

```objc 
while(!finish) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
```

だが, これだとReachabilityのようなイベントがごく稀 (環境によるが...) の場合は, `finish = YES`したところでRunLoopが中々終了しない.
これは, `distantFuture`で`input source`が発火するまで待つように指示している為である.

では, 以下の要件を満たす為にはどうすれば良いのか. というのがこの記事の趣旨である.

- 短期間のポーリングによる負荷は避けたい為, `distantFuture`指定は維持したい
- 終了したいタイミングで, 出来る限り早く, 確実に終了したい.

## 解決策

```objc
/******** 起動時 *********/

dispatch_semaphore_t sem = dispatch_semaphore_create(0);
__block NSRunLoop* runLoop = nil;
__block BOOL finish = NO;

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    runLoop = [NSRunLoop currentRunLoop];
    dispatch_semaphore_signal(sem);
    
    while(!finish) {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); // runLoopに値が代入されるのを待つ為

/******* 終了時 ********/

finish = YES;
NSTimer* schedulerSignal = [NSTimer timerWithTimeInterval:0 repeats:NO block:^{ /* NOP */ }];
[runLoop addTimer:schedulerSignal forMode:NSDefaultRunLoopMode];
```

`distantFuture`は`input source`が発火する待つのであれば, `input source`が発火するようにすれば良いという話である.
また, `finish`に`semaphore`を使う実装もあるが, BOOLは1stepでアクセスできるので, これについてはどちらでも変わらないと思われる. 
(`semaphore`では`input source`代わりにはならないので, フラグ以上の意味はない)

------
捕捉: [NSTiemr # timerWithTimeInterval:repeats:block:](https://developer.apple.com/reference/foundation/nstimer/2091888-timerwithtimeinterval?language=objc)はiOS10.0+なので, それ以前の場合は適当に読み替えてください. Swiftの人もよしなに読み替えてください.
Microsoft Bot Framework 公式ドキュメント”ボットの設計”について書いてみた③

前回 [Microsoft Bot Framework 公式ドキュメント”ボットの設計”について書いてみた②](http://qiita.com/kataday/items/50b505d620161d488180)

今回は、**「会話の流れ」**について。

※記事内の画像は、[利用規約 | Microsoft Docs](https://docs.microsoft.com/ja-jp/terms)に従い、表示しています。

# 会話フローの設計と制御

従来のアプリケーションでは、ユーザーインターフェイス（UI）は一連の画面です。
単一のアプリまたはウェブサイトで、必要に応じて1つまたは複数の画面を使用して、ユーザーと情報を交換できます。
ほとんどのアプリケーションは、ユーザーが最初に訪れるメイン画面から始まり、新しい注文の開始、商品の閲覧、ヘルプの検索など、さまざまな機能のための他の画面に繋がるナビゲーションを提供します。

アプリやウェブサイトと同様に、ボットにもUIがありますが、画面ではなく**ダイアログ（対話）**で構成されています。
開発者はダイアログを使用して、ボットの機能のさまざまな領域を**論理的に分離**し、会話の流れを導くことができます。
例えば、「ユーザーが製品をブラウズするのに役立つロジックを含むダイアログ」と、「ユーザーが新しい注文をするのに役立つロジックを含む別のダイアログ」を設計することができます。

ダイアログには、グラフィカルインターフェイス（GUI）がある場合と無い場合があります。
それらは、ボタンやテキストなどの他の要素を含めることもできれば、完全に音声に基づくこともできます。
ダイアログには、**他のダイアログを呼び出す**、**ユーザー入力を処理する**などのタスクを実行するアクションも含まれています。

## ダイアログを使用した会話フローの管理

以下の図は、従来のアプリケーションの画面フロー（左）を、ボットのダイアログフロー（右）と比較しています。

![alt](https://docs.microsoft.com/en-us/bot-framework/media/designing-bots/core/dialogs-screens.png)

従来のアプリケーションでは、すべてメイン画面から始まります。
メイン画面で新しい注文画面が表示されます。新しい注文画面は、他の画面を閉じるか呼び出すまで制御されます。
新しい注文画面を閉じると、ユーザーはメイン画面に戻ります。

ボットでは、すべてが**ルートダイアログ**から始まります。
ルートダイアログが**新しい注文ダイアログ**を呼び出します。その時点で、新しい注文ダイアログは会話を制御し、他のダイアログを閉じるか、呼び出すまで制御状態を維持します。
新しい注文ダイアログが閉じると、会話の制御がルートダイアログに戻ります。

## ダイアログのスタック
1つのダイアログが別のダイアログを呼び出すと、ボットビルダーは**新しいダイアログをダイアログスタックの最上部に追加します**。
スタックの上にあるダイアログは、**会話を制御します**。
ユーザーがボットに送信したすべての新しいメッセージは、そのダイアログを**閉じる**か、別のダイアログに**リダイレクト**されるまで、そのダイアログによる処理の対象となります。
ダイアログが閉じられると**スタックから削除**され、前のダイアログは**会話の制御を引き継ぎます**。

## ダイアログ、スタックと人間
ユーザーがダイアログを**横断的にナビゲート**してダイアログスタックを作成し、ある時点で元の方向に戻り、ダイアログを1つずつきちんと整然とした方法で**アンスタッキング**することを推測することが魅力的かもしれません。

例えば、ユーザーはルートダイアログから開始し、そこから新しい注文ダイアログを呼び出してから、商品検索ダイアログを呼び出します。次に、ユーザーは商品を選択して確認し、商品検索ダイアログを終了し、注文を完了し、新しい注文ダイアログを終了してルートダイアログに戻ります。

ユーザーがいつもそのような線形で論理的なパスを行き来するのは素晴らしいことですが、**それはほとんど起こりません**。
**人間は「スタック」で通信しません。**頻繁に心を変えがちです。
次の例を考えてみましょう。

![alt](https://docs.microsoft.com/en-us/bot-framework/media/designing-bots/core/stack-issue.png)

あなたのボットは論理的にダイアログのスタックを構築しているかもしれないが、ユーザーは**全く別のことをする**か、現在のトピックと**無関係かもしれない質問をする**こともできます。


この例では、ユーザは、ダイアログが期待する「はい」または、「いいえ」で答えるのではなく、質問をしています。
**あなたのダイアログはどのように応答する必要がありますか？**

- まずユーザーに、質問に答えてもらうように主張します。
- ユーザーが以前に行ったことのすべてを無視し、ダイアログスタック全体をリセットし、ユーザーからの質問に答えることによって最初から開始します。
- ユーザーの質問に回答し、その後、上記の質問に戻り、そこから再開しようとします。

最良の解決策は、シナリオの詳細と、ユーザーがボットの応答を合理的に期待する方法に依存するため、この質問に対する**正解はありません。**

ユーザが（たとえ非線形であっても）目標を達成できるように会話フローを設計することは、**ボット設計の基本的な課題**です。

# まとめ
「MicrosoftBotFramework」では、**ダイアログ**と呼ばれる、主にユーザからの応答に対する処理のかたまりを適切に管理することでボットを構築していきます。少し触ってみると分かりますが、ロジック内の各々のトピックを関数化していくようなイメージですね。

私は他のボット系フレームワークをあまり触ったことはないですが、「MicrosoftBotFramework」のこの方法は、結構気に入ってます。
会話の流れをスタックで管理するというのは、あるトピックに限った会話の流れって意味では理にかなってると思っていて、横槍的なものを入れなければ、論理的に単一方向に流れる処理で事足りる、と。

ただ、「そういえば、〜」とか「話変わるけど、〜」みたいなことは、人間の会話としては当然あり得るので、それに対応するための方法は用意しておく必要があるってことですね。

次回は、
いくつかの、設計が不十分なナビゲーションの一般的な落とし穴を検討し、これらのトラップを回避するための戦略について！（らしいです）です。
MacOS Sierra (10.12) でRPGツクールMV作品を開く

MacOS Sierra環境において、
RPGツクールMVのゲームをWebからダウンロードして起動しようとすると、

**「ゴミ箱に入れろと言われる」**

![shot04.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/ec50db6e-e43f-3604-dfff-2b287a9b03ec.jpeg)


**「開発元が未確認のため開けませんと言われる」**

![shot02.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/f27e012d-c40c-5e88-325e-93ba73a0a738.jpeg)


**「ゲームは起動できたけどオプションを開いて閉じるとすぐこんなエラーが出る」**

![b01.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/43db2071-75ef-f640-09d3-d7f0fdcdc8db.jpeg)


この3種類の症状に出くわす事が多いと思います。

その解決策を載せておきます。



#ゴミ箱に入れろと言われた場合の対策

画面左上リンゴのマークから「システム環境設定」を開き、「セキュリティとプライバシー」をクリックしてください。

![shot05.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/01a8efa6-4a80-8555-7850-5a862d6b293d.jpeg)

続いて表示された画面、タブ［一般］の下側、「ダウンロードしたアプリケーションの実行許可」を「App Storeと確認済みの開発元からのアプリケーションを許可」にチェックを入れ、画面を閉じます。

![shot06.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/d99d2c04-03a8-58dc-237e-9aaa149622b3.jpeg)

もし消えていてチェックが切り替えられない場合は、そのすぐ左下の鍵アイコン（変更するには〜）をクリックし、ログイン名とログインパスワードを入力すれば操作を行えます。

:cry: *ゲームに関しては、もしかしたら一度**ダウンロードし直さないといけないかも知れません**。この設定を切り替えてもなお「ゴミ箱に捨てろ」と言われる場合は、再度ダウンロード・圧縮ファイルを解凍し直す所から始めてください。*


#「開発元が未確認のため開けません」と言われた場合の対策

まず、Gameを起動する時、Gameにカーソルを合わせて右クリック（トラックパッドは二本指タップ）してください。要はサブメニューが開く状態です。

![02.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/a7f8988e-27b6-b2b5-4862-649c0fdd9aad.jpeg)

表示されたメニューから「開く」をクリックしますと、

![shot03.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/8120a770-af24-cc58-eff0-468bc1671fb9.jpeg)

先ほどとは違うメッセージが表示されますので、「開く」を再度クリックしてください。

:cold_sweat: *未認証のアプリケーションを開く事を防ぐためのMacOS側の仕様であり、ツクール本体の不具合では無いと思います。開けない事について作者さんに連絡が行くかも知れませんが、冷静にこのページを連絡してあげてください。*


これで問題なくゲームは起動出来ると思います。
次回以降はいつも通りダブルクリックで開いてもこのメッセージも出なくなります。


#オプションを開いたりセーブ画面などでエラー（Unknown Error - Error EROFS〜）が発生する場合の対策

フォルダから、**Gameアイコンだけを一度別の場所に移して起動してください**。

![b02.jpg](https://qiita-image-store.s3.amazonaws.com/0/180923/ba8b6b1b-982f-757c-cea0-8b549ceaeada.jpeg)

それだけでエラーは出なくなるはずです。

エラーが出なくなったのを確認したら、元のフォルダに戻してもOK。二度目は起動するはずです。もちろん別のフォルダを作って、その中で起動しても構いません。

:cold_sweat: *こちらもOS側の仕様もしくは不具合だと思います。オプションを起動したりセーブデータを保存する際、saveフォルダとconfigファイル等がGame内に作られるのですが、ダウンロード後のフォルダではその保存するパスがおかしな事になっている様です。*
音データセット全体の時間長を計算したいときのシェル芸

# はじめに
音に関する識別実験などを行っていると，音クラス毎に時間長を計算したいときがあります．わざわざスクリプトを書くほどの計算でもないため，ワンライナーでどうにか計算するというのがモチベーションです．

# 環境
- OS: Ubuntu 16.04
- 必要なソフトウェア: SoX

SoX は音データを取り扱う際に非常に便利なコマンドを提供してくれるため，入れておくと何かと便利です．以下のようにインストールできます．

```
sudo apt install -y sox
```

# 本題
背景でも申したとおり，`path_to_dataset` 以下に，たくさんの wav ファイルが格納されていて，それらを合算した時間長を取得するという問題にします．

SoX を入れたことで，`soxi` コマンドが使えるようになっているはずです．たとえば，`soxi` を使うと以下のような出力を得ることが出来ます．

```
Input File     : 'path_to_dataset/A1_0000.wav'
Channels       : 1
Sample Rate    : 16000
Precision      : 16-bit
Duration       : 00:00:01.00 = 16000 samples ~ 75 CDDA sectors
File Size      : 32.0k
Bit Rate       : 256k
Sample Encoding: 16-bit Signed Integer PCM
```

そのため，この Duration の項を用いてしまえば，割と簡単に目的を達成できます．

```
find path_to_dataset/ -type f | \
xargs soxi | \
grep Duration | \
awk '{print $3}' | \
tr ':.' ' ' | \
awk '{sum += $3; sum += $2*60; sum += $3*3600} END {s = int(sum%60); sum /= 60; m = int(sum%60); sum /= 60; h = int(sum%60) print h":"m":"s}'
```

ちょっと長いので，可読性意識して改行してみましたw とりあえず，これで `2:44:2` みたいなフォーマットで時間長を見れます．

# おわりに
なんとなく書いてみただけなのですが誰かの役に立てばと思いつつ終わります．
Cubeを接地した状態で回転させる方法について

少し前にTwitterで「箱を角が設置した状態で回すのってどうやってるのか？」と言う書き込みを見て、
自分自身も少し気になってきたので調べてみた。

実装するにあたっては回転軸の位置を指定しながら回転させる必要があるが、
こちら結論から言ってしまうと`Transform.RotateAround(Vector3 point, Vector3 axis, float angle);`を使う事で実装する事が出来た。

[Transform.RotateAround](https://docs.unity3d.com/ja/540/ScriptReference/Transform.RotateAround.html)

今回テストとして実装した物としては以下の様な挙動となる。

![Rotate.gif](https://qiita-image-store.s3.amazonaws.com/0/80207/8edfc2d7-7fa0-a472-194b-0055efdadb71.gif)

実装時のテストコードはこちら。
こちらをCubeにアタッチする事で動作可能。

```csharp
using System.Collections;
using UnityEngine;

public class Test : MonoBehaviour
{
    const float RotatingSpeed = 0.2f;
    const float RotatingAngle = 90f;
    Vector3 halfSize;
    float time = 0f;
    Vector3 axis = Vector3.zero;
    Vector3 point = Vector3.zero;

    void Awake()
    {
        this.halfSize = this.transform.localScale / 2f;
    }

    void Update()
    {
        if (this.point != Vector3.zero) { return; }
        if (Input.GetKey(KeyCode.UpArrow))
        {
            this.axis = Vector3.right;
            this.point = this.transform.position + new Vector3(0f, -this.halfSize.y, this.halfSize.z);
        }
        else if (Input.GetKey(KeyCode.DownArrow))
        {
            this.axis = Vector3.left;
            this.point = this.transform.position + new Vector3(0f, -this.halfSize.y, -this.halfSize.z);
        }
        else if (Input.GetKey(KeyCode.LeftArrow))
        {
            this.axis = Vector3.forward;
            this.point = this.transform.position + new Vector3(-this.halfSize.x, -this.halfSize.y, 0f);
        }
        else if (Input.GetKey(KeyCode.RightArrow))
        {
            this.axis = Vector3.back;
            this.point = this.transform.position + new Vector3(this.halfSize.x, -this.halfSize.y, 0f);
        }
        if (this.point != Vector3.zero)
        {
            StartCoroutine(this.StartRotate());
        }
    }

    IEnumerator StartRotate()
    {
        float nowAngle = 0f;
        float addAngle = (RotatingAngle / (RotatingSpeed * 60f));
        while (this.time <= RotatingSpeed)
        {
            nowAngle += addAngle;
            if (nowAngle <= RotatingAngle)
            {
                this.transform.RotateAround(this.point, this.axis, addAngle);
            }
            this.time += Time.deltaTime;
            yield return null;
        }
        this.time = 0f;
        this.axis = this.point = Vector3.zero;
        yield break;
    }
}
```
https://gist.github.com/mao-test-h/42d580978b5fabccbe4a6a0e12b58f32
PostgreSQL - タイムゾーンをDBに設定する

# 概要
postgresのタイムゾーンはpostgresql.confに設定するが、9.1以前は固定されていない(コメントアウト)。

```
#timezone = unknown			# actually, defaults to TZ environment
					# setting
```

バージョンアップでデフォルトが変更された時の影響を考えて固定にしておく。
DB毎に個別に設定を行う。

# PostgreSQL マニュアル
## 構文
[ALTER DATABASE](https://www.postgresql.jp/document/current/html/sql-alterdatabase.html)
> ALTER DATABASE name SET configuration_parameter { TO | = } { value | DEFAULT }

[SET](https://www.postgresql.jp/document/current/html/sql-set.html)
> SET [ SESSION | LOCAL ] TIME ZONE { timezone | LOCAL | DEFAULT }
>> TIME ZONE
SET TIME ZONE valueはSET timezone TO valueの別名です。 SET TIME ZONE構文では、時間帯の指定に特殊な構文を使用できます。 

## 設定できるタイムゾーン
[pg_timezone_names](https://www.postgresql.jp/document/current/html/view-pg-timezone-names.html)
> pg_timezone_namesは、SET TIMEZONEで認識される時間帯名称の一覧を提供します。

## 設定の反映
[システム管理関数](https://www.postgresql.jp/document/current/html/functions-admin.html)
> 表9.77 サーバシグナル送信関数
> 
> |名前|戻り型|説明|
|:--|:--|:--|
|pg_reload_conf()|boolean|サーバプロセスに構成ファイルの再読み込みをさせる|

# 実行
## タイムゾーンの確認
```postgres
SELECT * FROM pg_timezone_names;
```

## 設定
```postgres
ALTER DATABASE exsampledb SET timezone TO 'Asia/Tokyo';
```

## 反映
```postgres
SELECT pg_reload_conf();
```
Chrome/Safariでもエラーにならないオレオレ証明書でTSL/SSLクライアント認証をする

## 背景
最近のChromeアップデートで、オレオレ証明書でクライアント認証していたサイトで "Certificate Error" "Subject Alternative Name Missing" "ERR_CERT_COMMON_NAME_INVALID"などのエラーが出るようになってしまったので、その対策です。
最近はフリーのLet's EncryptやAWSのCertificate Managerもあるのでそちらも検討しましたが、クライアント認証なのでオレオレ証明書の方がむしろセキュアだろうということで、引続きオレオレです。
ほとんど[こちら](https://stackoverflow.com/a/43666288)から拝借したものですが、簡単に証明書など作成できるようにスクリプトになっています。

## 証明書作成手順
証明書や鍵の作成はサーバ上でやる必要はありません。自分はローカルマシンでやってます。

#### スクリプトを取得
```
git clone git@github.com:pikanji/ssl-client-auth.git
```

#### 設定ファイル作成
必要な情報を記述した`.env`ファイルを作成します。

```
cd ssl-client-auth
cp .env.dist .env
```

`.env`を開いて必要な情報を記述します。

| 項目 | 説明 |
|------|-----|
| DOMAIN | 対象のサーバのドメイン名です。 |
| COMMON_NAME | こちらが、実際に適用されるドメイン名です。指定しなければ上記ドメイン名のワイルドカード`*.$DOMAIN`が使用されます。上記ドメインを使用したい場合は、同じ値を設定します。 |
| NUM_OF_DAYS | 有効期限。1年なら365とか。 |
| COUNTRY | 国名を２文字で。 |
| STATE | 州や都道府県。 |
| LOCALITY | 市区町村。 |
| ORGANIZATION | 組織名。会社名など。root authorityの作成にはこちらがCOMMON_NAMEとして使用されます。 |
| ORGANIZATION_UNIT| 部課名や製品名など |

#### 認証局の証明書と鍵の作成
```
./create_root_cert_and_key.sh
```
#### サーバ証明書/鍵とクライアント用証明書の作成
```
./create_certificate_for_domain.sh
```

## サーバへの設置
ここからはサーバ上での作業になります。

#### 証明書と鍵を設置して、SSLを有効にする
この期に及んでApacheを前提で説明します。自分はAWSでAmazon Linuxを使用しているのでRedHat系の説明になります。
`mod24_ssl`が入ってなければインストール。

下記内容で`/etc/httpd/conf.d/ssl.conf`を作成。最後のLog関係の３行は何でもいいです。

```
LoadModule ssl_module modules/mod_ssl.so
Listen 443
<VirtualHost *:443>
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>
  SSLEngine on
  SSLProtocol All -SSLv2 -SSLv3
  SSLCertificateFile "/etc/pki/tls/certs/server.crt"
  SSLCertificateKeyFile "/etc/pki/tls/certs/server.key"
  SSLCACertificateFile "/etc/pki/tls/certs/root_ca.crt"
  SSLVerifyClient require

  LogFormat "%h (%{X-Forwarded-For}i) %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
  ErrorLog /var/log/httpd/elasticbeanstalk-error_log
  TransferLog /var/log/httpd/elasticbeanstalk-access_log
</VirtualHost>
```

↓ここで指定するように、上記で作成した証明書と鍵ファイルを配置します。`server.crt`はスクリプトでは`[ドメイン名].crt`として生成されます。

```
SSLCertificateFile "/etc/pki/tls/certs/server.crt"
SSLCertificateKeyFile "/etc/pki/tls/certs/server.key"
SSLCACertificateFile "/etc/pki/tls/certs/root_ca.crt"
```

#### HTTPSを強制する
ウェブサイトへのアクセスを常にHTTPSに強制するため、HTTPへのアクセスをHTTPSにリダイレクトさせます。

Webサーバのドキュメントルートの.htaccessなどに下記を記載。重要なのは`RewriteCond`と`RewriteRule`ですね。

```
<IfModule mod_rewrite.c>

  RewriteEngine on

  RewriteCond %{HTTPS} !=on
  RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]

</IfModule>
```

webサーバをリスタートします。

```
sudo apachectl restart
```

## クライアント（デバイス）での設定
確認が面倒なので、自分が使っているMacの説明だけ書きますw

上記で作成された`.p12`ファイルをMac上でダブルクリックしてインストールします。  
Keychain Accessでインストールされた認証局の証明書を"Always Trust"に設定して完了です。

対象ウェブサイトにアクセスすると、証明書を選択するように促されるので、インストールした証明書を選択してOKします。

これでChromeのアドレスバー左側に緑の"Secure"が表示されると思います。

めでたしめでたし。
Alpine Linux を 3.5 から 3.6 へアップグレード

# Alpine Linux を 3.5 から 3.6 へアップグレードした記録
Alpine Linux を使い始めて、初めてアップグレードを行いました。
アップグレード用のコマンドなどは特になく、基本的に `apk` コマンドを用いるようです。
[Wiki にある手順](https://wiki.alpinelinux.org/wiki/Upgrading_Alpine#Upgrading_to_latest_release)通りで問題ありませんでした。

```shell-session
$ sudo setup-apkrepos

"e" を選択すると vi が起動し、/etc/apk/repositories を編集することになります
3.5 -> 3.6 なので
http://dl-cdn.alpinelinux.org/alpine/v3.5/main
を
http://dl-cdn.alpinelinux.org/alpine/v3.6/main
にしました

$ sudo apk update
$ sudo apk upgrade --update-cache --available
$ sudo sync   # 本当に必要でしょうか
$ sudo reboot

$ uname -a
Linux XX 4.9.30-0-virthardened #1-Alpine SMP Wed May 31 10:53:15 GMT 2017 x86_64 Linux
$ cat /etc/alpine-release
3.6.1
```
Goでのアルゴリズムクイックリファレンス第2版(マージソート)

Goに慣れるためとアルゴリズムの復習の為に週1ぐらいで更新していきます。[アルゴリズムクイックリファレンス 第2版](https://www.amazon.co.jp/gp/product/4873117852/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4873117852&linkCode=as2&tag=amesho-22&linkId=b7688201ae37a6234596fa96dfd3ccdd)を読んで各種アルゴリズムをGoで実装して行きます。

前回: [Goでのアルゴリズムクイックリファレンス第2版(バケツソート)](http://qiita.com/amesho/items/155683a22ad5fea3b735)

今回は[マージソート](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%BD%E3%83%BC%E3%83%88)

基本的なアルゴリズムは、以下。(wikipediaより)

```
1. データ列を分割する（通常、等分する）
2. 各々をソートする
3. 二つのソートされたデータ列をマージする
```

https://play.golang.org/p/elCnJhw0OZ

```go
package main

import (
	"fmt"
	"math/rand"
)

func mergeSort(a *[]int, tmp *[]int, start int, end int) {
	m := (end + start) / 2
	if end <= start {
		return
	}
	mergeSort(a, tmp, start, m)
	mergeSort(a, tmp, m+1, end)
	merge(a, tmp, start, m, end)
}

func merge(a *[]int, tmp *[]int, start int, m int, end int) {
	var start_i, end_i int
	for start_i = m + 1; start_i > start; start_i-- {
		(*tmp)[start_i-1] = (*a)[start_i-1]
	}

	for end_i = m; end_i < end; end_i++ {
		(*tmp)[end+m-end_i] = (*a)[end_i+1]
	}

	for i := start; i <= end; i++ {
		if (*tmp)[end_i] < (*tmp)[start_i] {
			(*a)[i] = (*tmp)[end_i]
			end_i--
		} else {
			(*a)[i] = (*tmp)[start_i]
			start_i++
		}
	}
}

func main() {
	var ary, tmp []int
	size := 30
	for i := 0; i < size; i++ {
		ary = append(ary, rand.Intn(size-1))
		tmp = append(tmp, 0)
	}
	fmt.Println(ary)
	mergeSort(&ary, &tmp, 0, len(ary)-1)
	fmt.Println(ary)
}
```

今回はしょうも無いところで色々はまって、考え違いしてるのかと思って色々参考にさせていただきました。再帰じゃないバージョンのマージソートも考察されているようで、これもあとでもう一度トライしたいです。

+ http://d.hatena.ne.jp/kankinkon/20120202/1328138584
+ http://konbu13.hatenablog.com/entry/2014/02/11/195731

あと、途中で見つけた[この本](https://rcm-fe.amazon-adsystem.com/e/cm?ref=tf_til&t=amesho-22&m=amazon&o=9&p=8&l=as1&IS1=1&detail=1&asins=B00U5MVXZO&linkId=7f3f5cb3b880ffd387d89ce74ff74484&bc1=ffffff&lt1=_top&fc1=333333&lc1=0066c0&bg1=ffffff&f=ifr)結構良さそうなので後で購入したいです。

次回は逐次探索の予定です。
GAE で秘匿したい環境変数を安全に設定する

# はじめに

* Google App Engine では `app.yaml` で環境変数を設定できる

```yaml
env_variables:
  MY_VAR: 'my value'
```

# 秘匿したい環境変数を設定する

* `app.yaml` はデプロイなどに必要であるためコミットする必要がある
* そのため `app.yaml` にアクセストークンなどの秘匿したい環境変数を設定することはできない
* そこで別の yaml ファイルに定義して `include` で読み込み、そのファイルを .gitignore に登録することで秘匿したい環境変数を安全に定義することができる

```yaml:app.yaml
includes:
- secret.yaml
```

```yaml:secret.yaml
env_variables:
  SECRET_TOKEN: "my secret token"
```

```txt:.gitignore
secret.yaml
```

# 参考URL

https://cloud.google.com/appengine/docs/standard/python/config/appref
Java SE 7メモ

Java SE 7 Programmer IIに合格しました。
結果は<b>80パーセント</b>。まあ大丈夫でした。
勤めて3年目ですが、開発自体(WEBの)は10か月ほどしか経験がないので自宅や通勤時に学習する時間が多かったです。勉強時間は概ね3か月くらい。
マルチスレッドプログラミングは業務でやったことがないので、難しかったです。

* 試験概要  
 * 問題数⇒65問
 * 合格ライン⇒65%
 * 制限時間⇒150分
 
## 試験内容
* Javaクラスの設計
* 高度なクラスの設計
* オブジェクト指向の設計原理
* ジェネリックスとコレクション
* 文字列処理
* 例外とアサーション
* Java I/O
* JDBCによるデータベースアプリケーションの作成
* スレッド
* 並列処理
* ローカライゼーション

## 感想
比較的に難易度の高い試験ではないと思います。デザインパターンやAPIの使い方を覚えるための試験と考えたほうが良いかと。ロジックやアルゴリズムについては深くする必要はないです。
コレクション、ファイル処理、正規表現は特にひっかけ問題が多かったです。左記の3つは業務でも扱うことが多いので3か月の勉強期間がとても有意義なものとなりました（あんまりコレクションわからなったので…）。