OmniAICreator/Qiita-1.07M huggingface dataset:
MCP 70-534 を受験しました

MCP 70-534 Architecting Microsoft Azure Solutions に合格したので、勉強方法等を書き溜めます。

MCP 70-532 の体験記は以下リンク
[MCP 70-532 を取得しました](https://qiita.com/skwhr/items/8b97be93eadb8ea51ed5)

MCP 70-533 の体験記は以下リンク
[MCP 70-533 受験体験記](http://qiita.com/skwhr/items/2038b63a537b925bab8f)

# 試験の傾向は？

問題：50問
試験時間：150分

試験の流れは以下の3部作でした。それぞれ次に進むと見直しはできなくなるので要注意です。

* 2択問題
    * ある問題に対する答えが正しいか正しくないかの2択です。
    * 出題数は全体の1割くらいでした。
* 1問1答
    * よくある4択、5択くらいの出題です。
    * PowerShell/CLIのコマンドレットやC#のコードを埋める問題も出てきました。
    * 出題数は全体の6割くらいでした。
* ケーススタディ
    * 架空の企業システムの概要や問題点が提示され、それに対する解決法を答える形式です。
    * 出題数は全体の3割くらいでした。

試験名の通りですが、全体的に、ある要件や課題に対してAzureソリューションを活用してどう解決するかが求められます。


# 公式サイトの試験範囲を把握する

なにはともあれ、まずは範囲を把握しましょう。

[公式サイト]
[Architecting Microsoft Azure Solutions](https://www.microsoft.com/ja-jp/learning/exam-70-534.aspx)

* Azure Resource Manager (ARM) ネットワークの設計 (5 ～ 10%)
* リソースのセキュリティ保護 (20 ～ 25%)
* アプリケーション ストレージとデータ アクセス戦略の設計 (5 ～ 10%)
* 高度なアプリケーションの設計 (20 ～ 25%)
* Azure Web Apps と Azure Mobile Apps の設計 (5 ～ 10%)
* 管理、監視、ビジネス継続性の戦略の設計 (20 ～ 25%)
* Azure コンピューティング インフラストラクチャの設計 (10 ～ 15%)

始めに見たときに思ったのは、試験範囲広いな！でした。
でも、これに関連したサービスは全て実際に触ってみて理解すべきだと受けてみて思いました。


# ドキュメントを読み漁り、実際に動かしてみる

70-534は、70-533と違ってmstepオンラインセミナーがなかったので、公式サイトの試験範囲に頼るしかありませんでした。試験対策本なんてものももちろんありません。

私がやったのは、試験範囲のサービスのドキュメントを読み漁って、実際に触れてみて理解する。がほとんどです。
普段からAzureには触れていますが、試験範囲のサービスの多くは業務では中々触れる機会のないものでした。

# Microsoft公式演習テスト

一応やってみましたが、正直あまり意味なかったかなと思います。
ちょっと内容が古いものもありました。

# 問題の日本語訳が怪しい？

例えば、「Azure Functionsを使って・・・」といった問題があったとすると、「Azure関数を使って・・・」といった和訳がされているケースがあります。
Azureのサービス名を和訳しちゃってるパターンですね。
問題によってはAzure Functionsとなっているケースもありました。
英文に切り替えることもできるので、ん？と思ったら英文を見てみることもオススメです。

# まとめ

公式の試験範囲を把握して、関連したサービスを触ってみるしかありません。

クラシックの問題は出なかったですね。
Azureの特徴でもあると思いますが、ハイブリッドやセキュリティといったキーワードは頻出します。

70-533より難易度は高かったです。
時間は30分余りくらいでしたが、70-533よりは余裕なかったです。
osqueryが便利

`osquery`はFacebookが開発しているSQLベースの攻撃/侵入検出ツールです。
SQLベースのクエリで情報が取得できるのでかなり使い勝手が良いです。

## 環境
* macOS Sierra

## インストール
Homebrewで`osquery`をインストールできます。

```
$ brew install osquery
```

## 起動
`osqueryi`を起動します。

```
$ osqueryi
Using a virtual database. Need help, type '.help'
osquery>
```

## SQLを書く
リッスンしているポートの一覧を取得してみます。

```
osquery> select * from listening_ports;
+------+-------+----------+--------+-----------+
| pid  | port  | protocol | family | address   |
+------+-------+----------+--------+-----------+
| 95   | 0     | 17       | 2      | 0.0.0.0   |
| 95   | 0     | 0        | 0      |           |
| 271  | 51047 | 17       | 2      | 0.0.0.0   |
| 565  | 27017 | 6        | 2      | 0.0.0.0   |
| 1855 | 3000  | 6        | 10     | ::1       |
| 1855 | 3000  | 6        | 2      | 127.0.0.1 |
| 7205 | 38069 | 6        | 2      | 127.0.0.1 |
+------+-------+----------+--------+-----------+
```

取得できる情報（テーブル）は[こちら](https://osquery.io/docs/tables/)の公式に載っています。
HTTPメソッドに関する記述

[Webを支える技術](http://gihyo.jp/book/2010/978-4-7741-4204-3)を読んで、HTTPメソッドに関しての記述があったので、忘れないうちにまとめる

#HTTPメソッドとは
クライアントが行いたい処理をサーバに伝える。

･GET
･POST
･PUT
･DELETE
･HEAD
･OPTION
･TRACE
･CONNECT

の8つのメソッドが存在しており、用途によって使い分けられる。

##実際の通信の確認
ブラウザはFirefox54.0.1使用
開発ツールを開くと、ステータスコードやメソッドの確認を行うことができる。

##メソッド確認(GET)
GETメソッドは指定したURIの情報を取得する。
[Google](https://www.google.co.jp/)へのアクセスを確認する。

```ruby:ヘッダー

要求URL: https://www.google.co.jp/
要求メソッド: GET
リモートアドレス: ...
ステータスコード: 200 OK
バージョン: HTTP/2.0

```
応答にはHTMLやJSが返ってくる。
自分が見ているサイトでどのような通信が行われているのか確認してみるのもおもしろい。
RubyGemsに登録しなくても、gemとして認識させる方法



##概要
RubyGemsに登録しなくても、
Gemとして認識させる方法が、便利だと思ったので例を記載しています。

まずは、Gemをローカル環境で試したいときに有用かと思います。

##方法

###ディレクトリの構造
├── Gemfile
├── Gemfile.lock
├── greet
│   ├── greet.gemspec
│   └── lib
│       　　　└── greet.rb
└── sample.rb
<br>


```ruby:Gemfile
gem 'greet',path: 'greet'
```

```ruby:greet/greet.gemspec
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)

Gem::Specification.new do |spec|
  spec.name          = 'greet'
  spec.version       = '1.0.0'
  spec.summary       = 'test'
  spec.authors       = ['test']
end
```

```ruby:greet/lib/greet.rb
class Greet
  class << self
    def hello
      puts "Hello"
    end
  end
end
```

```ruby:sample.rb
require 'greet'

Greet.hello
#=> "Hello"
```
githubのリポジトリ取得

## 対象
- githubのリポジトリを取得してローカルで開発したい  
  



# ①Githubでクローンしたいリポジトリページに行く

 

# ②「Clone or download」をクリック
<img width="503" alt="スクリーンショット 2017-08-14 0.00.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/189889/a73543b1-4c50-3a98-9e59-c5300b605c0d.png">


# ③「ssh」 をコピー
<img width="127" alt="スクリーンショット 2017-08-14 0.04.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/189889/dc503065-4f7c-6a25-c3ad-dcbbd1769a04.png">

コピペして。。。

# ④ローカルのターミナルでgit cloneを実行


```
git clone git@github.com:〇〇
```
ディレクトリ内のファイルの更新日時を変更する

デジカメ本体の日時設定が初期化された状態で、うっかり撮影してしまうことがあります。
(バッテリーが放電して設定情報が飛んでしまうことは多々あります・・・。)

更新日時を変更するにも撮影した画像が大量にある場合、一つ一つ変更するのは大変なので、linuxコマンドで一括変更しましょう！

ディレクトリ内のファイルの更新日付を2017年8月13日 14時00分にする場合

```
cd /path/to/picture_dir/
touch -t 201708131400 DSCN0*.JPG
```

ただ、一枚一枚別々の時間に変更したい時は何かしら別の方法はあるかと思いますが、撮影時間を正確に覚えていることはまず無いので、とりあえず応急処置的に変更したいという場合には良いかと思います！
C++ではファイルスコープ指定にstaticは非推奨

変数とか関数をファイルスコープにしたい場合、

# C言語

```
static int g_value;

static void myfunc(int val)
{
 ...
}
```

のようにグローバル定義の変数名や関数名にstaticを付与します。

# C++言語

無名名前空間(namespace {})で囲みます。

```
namespace {
int g_value;

void myfunc(int val)
{
 ...
}
}
```

ファイルスコープを目的とした static は、C++では非推奨です。
Office「プロダクトキーは有効、別のアカウントと引き換えられました」というエラーの解消方法

## はじめに
Macを買って、Officeをインストールするために、Office Academic 2016 for Mac を買ったけど、インストールができなかったので、解消方法を書いてみました。

## どういう問題が起きたか
下記の画像のように[office.com/setup](https://www.office.com/setup)でサインイン、プロダクトキー入力後に以下の表示でofficeが取得できなかった。
<img width="1165" alt="アカウント.png" src="https://qiita-image-store.s3.amazonaws.com/0/179180/fe9c4d0f-4b8d-7170-b1c9-59b50ca47add.png">

## 原因：サインイン時のメールアドレスがoutlook.jpではなく、outlook.comで行なっていたため
→***outlook.jpでサインインを行う。
　outlook.comでもサインインまではできるため、注意が必要！

もし、その他の問題or解決できなかった場合はMicrosoftのサポートセンターへ
問い合わせてみてください。
<img width="875" alt="問い合わせ.png" src="https://qiita-image-store.s3.amazonaws.com/0/179180/2956f333-029c-613d-2ec3-881f1791a377.png">
Linux コマンドや関数のマニュアル参照

ググればいいのですが、ネット接続が出来ない環境では必要ですね。

## Linuxコマンド
引数に --help オプションを付ければ大体説明が表示されます。

```
$ grep --help
```

manコマンドでもoKです。

```
$ man grep
```

## C言語関数

- 入出力系

```
man 3 stdio
```

- 文字列系

```
man 3 string
```

- 関数個別指定

```
man 3 printf
```

## システムコール
C言語関数とはセクション番号が異なります。

```
man 2 open
```
raspberrypiにOpenFlowコントローラーをデーモン化する

# openflow.serviceの準備
下記のような「openflow.service」ファイルを/etc/systemd/system配下に作成する。

```
[Unit]
Description = openflow controler

[Service]
ExecStart=/usr/local/bin/ryu-manager /usr/local/lib/python2.7/dist-packages/ryu/app/simple_switch_13.py
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target
```
正しく設定できているか確認する

```
root@raspberrypi:/home/pi# systemctl list-unit-files --type=service | grep openflow
openflow.service                       disabled
```

サービスを起動する。

```
root@raspberrypi:/home/pi# systemctl start openflow
```

プロセスが起動していることを確認する

```
root@raspberrypi:/home/pi# ps -alxg | grep ryu-manager
4     0  1576     1  20   0  37932 33412 SyS_ep Ss   ?          0:03 /usr/bin/python /usr/local/bin/ryu-manager /usr/local/lib/python2.7/dist-packages/ryu/app/simple_switch_13.py
0     0  1599  1571  20   0   3772  1844 pipe_w S+   pts/0      0:00 grep ryu-manager
```
さらにjournalctlで起動ログを確認する

```
root@raspberrypi:/home/pi# journalctl
```
ログの後半に下記の出力が行われていれば正しく起動されている。

```
 8月 13 23:02:36 raspberrypi systemd[1]: Starting openflow controler...
 8月 13 23:02:36 raspberrypi systemd[1]: Started openflow controler.
 8月 13 23:02:37 raspberrypi ryu-manager[1776]: Registered VCS backend: git
 8月 13 23:02:37 raspberrypi ryu-manager[1776]: Registered VCS backend: hg
 8月 13 23:02:38 raspberrypi ryu-manager[1776]: Registered VCS backend: svn
 8月 13 23:02:38 raspberrypi ryu-manager[1776]: Registered VCS backend: bzr
 8月 13 23:02:39 raspberrypi ryu-manager[1776]: loading app /usr/local/lib/python2.7/dist-packages/ryu/app/simple_switch_13.py
 8月 13 23:02:39 raspberrypi ryu-manager[1776]: loading app ryu.controller.ofp_handler
 8月 13 23:02:39 raspberrypi ryu-manager[1776]: instantiating app /usr/local/lib/python2.7/dist-packages/ryu/app/simple_switch_13.py of SimpleSwitch13
 8月 13 23:02:39 raspberrypi ryu-manager[1776]: instantiating app ryu.controller.ofp_handler of OFPHandler
```

OpenFlowコントローラーをデーモン化する。

```
root@raspberrypi:/home/pi# systemctl enable openflow
Created symlink from /etc/systemd/system/multi-user.target.wants/openflow.service to /etc/systemd/system/openflow.service.
```
railsにおける状態管理とは

# 状態管理とは

HTTPはクライアントから要求があってそれをサーバが応答して終わりという非常に単純なプロトコルです。そのため一回一回別のクライアントからの要求だと認識してしまします。もしそのままwebサービスを使うとSNSなどでページを更新するたびにログインし直すなどをしなければいけません。そういったことを避けるために下記の３つの方法で状態を維持します。

* cookie
    * ブラウザに保存される小さなテキスト情報
* セッション
    * クッキー、キャッシュ、データベースなどに状態情報を保存する仕組み。
* フラッシュ
    * 現在と次のリクエストでのみ維持できるセッション情報。

# cookieとは

ユーザーのブラウザに情報を残し、それを参照することでユーザーを特定する。

```ruby:rei
def cookie
 @email = cookies[:email]
end
def cookie_rec
 cookies[:email] = {value:params[:email],expires:3.months.from.now,http_only:true}
render("")
end
<%= form_tag(action:cookie_rec) do %>
<% end %>
```
cookieは

* value・・・どんな値をいれるか
* expires・・・クッキーの期限

はかならず入れる必要がある。expiresを設定しない場合、ブラウザを閉じたらすぐに消される。

## cookieの永続化、暗号化

```ruby:rei
cookies.permanent[:email] = @email
cookies.encrypted[:email] = @email
```
pemanentメソッドやencryptedメソッドで永続化、暗号化ができる。

# セッションとは

セッションはデータの保存先を選ぶことができる。ただ基本はクッキーで保存する。保存先の設定が豊富なためcookiesを使うよりもsessionを使ったほうが色々便利。


```ruby:rei
def session_show
 @email = session[:email]
end
# これで@emailを表示するとセッションに保存されていた値が表示できる
def session_rec
 session[:email] = params[:email]
end
<%= form_tag(action:session_rec) do %>
<% end %>
# これでセッションに保存できる。
```

# フラッシュとは

フラッシュはセッションに入れるほどじゃないんだけど次のページで関連した情報を出したい時に使います。次のページまでのセッションだと考えていいです。〜が登録できましたなどに使います。
CentOS7にDokuWikiを構築するためのAnsible-playbook


# はじめに
PukiWikiよりももっと便利で使い勝手の良い情報共有ツール無いかなと、いろいろ調べていたところ[DokuWiki](https://www.dokuwiki.org/ja:dokuwiki)というのが良さそうって結論に至りました。

選んだ理由をざっくり上げると

- ページ毎のアクセス権限を細かく設定できる
- GUIの設定がしっかりしていて使いやすそう
- Markdownが使える
- プラグインの導入が楽
- テーマも豊富で設定画面からカスタマイズも容易

とりあえず適当な仮想環境上にインストールしてみたんですが、途中いくつか躓いたところがあったので今後DokuWikiを導入してみたいという人のために簡単なAnsible-Playbookを作ってみました。
※自分の備忘録も兼ねて。

# Dokuwiki導入用Ansible-Playbook

[Github上に公開しています。](https://github.com/nyk0401/ansible_deploy_dokuwiki_for_centos7)  
利用方法についてざっくりREADME.mdに記載しているので、そちらを参照してください。 
※CentOS7を前提にして書いてあります。他のOSを利用される方は書き換えてご利用ください。


# さいごに

DokuWikiのカスタマイズ等々は今後使い込んでネタができたら載せようと思います。
不明な点やコメントがあれば気軽にお願いします。
Raspberry Pi　Wifi接続設定方法まとめ（WPA/WEP）

Raspberry PiのWi-Fi設定をしていて、別のWi-Fiにつなごうとしたら何故かつながらない！とハマってしまいました。
原因は暗号化の形式がWPAとWEPで設定が違ったためでした。
それぞれの設定方法を備忘録としてここにまとめておきます。

## 使用モデル
- Raspberry Pi3 Model B

## 設定方法
どちらも `/etc/wpa_supplicant/wpa_supplicant.conf` を編集します。

`sudo vi /etc/wpa_supplicant/wpa_supplicant.conf`

WEPの設定もここに書いてうまく動きました。:thinking:
### WPA

```
country=JP
ctrl_interface=DIR/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="SSID"
    psk="PASSWORD"
}
```

### WEP

```
country=JP
ctrl_interface=DIR/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="SSID"
    key_mgmt=NONE
    wep_key0="PASSWORD"
}
```

## Rebootする
Raspberry PiをRebootします
`sudo reboot`

## インターネットに接続されたか確認する
### ping
ping で適当なWebサイトに繋いでインターネットに接続されたか確認できます
`ping www.google.co.jp`

### ifconfig
ifcongig でRaspberry PiのIPアドレスを見ることが出来ます。
インターネットにつながると、Raspberry PiのIPアドレスが表示されるので、表示されたらインターネット接続に成功しています。
`ifconfig`
しかしifconfigは現在非推薦になっているようです:scream:

### ip addr
ip addr で ifconfig と同様にRaspberry PiのIPアドレスを確認する事ができます。
ifconfigが非推薦になっているようなので、これを使うのが良いのかと思います。
`ip addr`
Gopherフィギュアを作る

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/d688e4c1-26e8-6f83-b30e-1034278af7ce.png)

## 事の発端

Gopherという[Go言語のマスコットキャラクター](https://blog.golang.org/gopher)がいます。
過去にGoogle I/O 2013に行ったときにGopherのヌイグルミを手に入れたのですが、
この子の色違いがあるとのことで今更ながら欲しくなって探しましたが、残念ながらもう生産されていないようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/9a37ebba-e058-eb66-c815-1b47a3f0e7c8.png)

## D.I.Y.

無いなら仕方がないので作りましょう。
残念ながら僕は裁縫スキルはないので3Dプリンターでフィギュアを作ることにします。
幸い可愛いフィギュアを [teamstickman](https://twitter.com/teamstickman) さんが [go-gopher-model](https://github.com/StickmanVentures/go-gopher-model) としてモデルを公開されていましたのでそこに乗っかりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/23d2d398-7434-7a7a-304c-4ac9cd600a35.png)

そのまま印刷するとこんな感じです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/183463d1-9d8d-8164-12e6-a77a95c286f6.png)


塗り分けが入ると塗装が面倒なのと色ごとに部品を分けたくなったので、Blenderで部品を分割しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/64d18eae-d02a-7974-0479-a4e030236f55.png)


そして分割したデータを印刷用に整列します。
胴体は丸っこい形をしている都合上、サポート材を使うと表面を整えるのが面倒なので２ピースにして後から張り合わせます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/6b10ebf5-6221-951f-fe35-901861e7eddd.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/a4709ed3-b913-493a-c4b9-ce94dfab57b1.png)

データができたら3Dプリンターで印刷します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/0f2c07a7-e7da-9f1d-1889-11a326c0ac1c.png)


印刷したものをポリパテやサーフェイサーで表面を整えます。
時間を掛ければ綺麗にできるのですが、今回は時間が無かったのでかなり雑です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/294c7123-a96e-689f-ba10-9aea0fe9f334.png)

そして部品別に塗装します。ドライブースとして[YAMAZENの食器乾燥機（YDA-500)](https://www.amazon.co.jp/dp/B01294UYNM/ref=cm_sw_r_tw_dp_x_JKeKzb5JQRKNA)を使っています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/e5991d42-61c1-e740-5d91-2ed93c89e449.png)


組み立てて完成です。
使用している3Dプリンターは0.5mmくらいはバラつくので、嵌め込みの部分が合わないときはリューターで削ったり、諦めて接着します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/d688e4c1-26e8-6f83-b30e-1034278af7ce.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/865533d2-a7f2-c8f9-ff70-b9fa3f63061f.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/55138/0dbc8386-6750-627c-9d23-60dbaa34670c.png)

## 終わりに

[以前、フォクすけフィギュアを作ったとき](http://wscat.blogspot.jp/2013/12/blog-post.html)は、最終的にDMMの3Dプリントサービスで印刷された精度が高いものをシリコンゴムで型どりして量産したのですが、今回は量産を考えていないのでそのまま塗装しています。

僕はGo言語自体はあまり書かないのですが、Gopherは可愛いと思います。

## データはこちら
- [go-gopher-model(Catteke version)](https://github.com/cattaka/go-gopher-model)
  - [ボディのSTL](https://github.com/cattaka/go-gopher-model/blob/master/3d-printable_separated/go_gopher_body.stl)
  - [その他のSTL](https://github.com/cattaka/go-gopher-model/blob/master/3d-printable_separated/go_gopher_misc.stl)
iOS11ベータ版アプリ起動時にスローダウンやプチフリーズが起きる時の対処

【重要】2017/12/24 現在、iOS 11.2 + Xcode 9.2 でこの問題は解消されているのが確認されました。
***

2017/8/13 現在
iOS11対応のアプリ開発中、実機で実行する際、起動はじめの時点でなぜかスローダウンやプチフリーズ（動作が停止してひっかかるがプログラム実行は生きている）症状が出た場合は、以下の方法で回避できましたのでご報告します。

ログには
[MC] Reading from public effective user settings.
または
XPC connection interrupted
が表示されている。

回避方法：

```swift:ViewController.swift　内へ追加する
override func viewDidAppear(_ animated: Bool) {

 textField.becomeFirstResponder()
 textField.resignFirstResponder()

 //textFieldは何でも良い。無ければ仮のtextFieldオブジェクトをstoryboardへ追加しておく
}
```
OK: **viewDidAppear**
NG: viewWillAppear, viewDidLoad

この問題は、今後iOS11GM版へ向けての修正で解決される可能性が高いと思われますが、現時点（2017/8/13）ではこの問題が発生すると実機でのテストが非常に不便なので、誰かのお役に立てばと思い投稿しました。
[Junji Suzuki JBOYSOFT](http://www.jboysoft.jp/)
***
環境：
Xcode 9 beta 5 9M202q
iOS 11 beta 5 15A5341f for iPad (9.7-inch)
これ以前のiOS11betaでも同じ問題が出ていました。
***
追記：2017/8/15
iOS 11 beta 6 15A5354b for iPad (9.7-inch) でも同じ症状が出ます。
***
追記：2017/12/24
iOS 11.2 + Xcode 9.2 でこの問題は解消されているのが確認されました。
C#でUndo/Redoを実装した

# Undo/Redoを実装(C#)
![UndoRedoIcon.png](https://qiita-image-store.s3.amazonaws.com/0/139940/279daa52-9ea6-409c-94da-ba6e5da64c48.png)

C#で汎用的に使える(と思われる)Undo/Redoを実装したので紹介します.
アルゴリズムも後ろの方で紹介します.

# 環境
C# 6.0～が必要です.

# ソース (GitHub)
<a href="https://github.com/nossey/UndoRedo">こちら</a>
理論はいいからともかく利用したいという方は上記リンクからダウンロードして, History.csを自分のプロジェクトに追加してください.

# 使い方
GitHubで公開しているサンプルコードを参考にして下さい.

# (ぼくのかんがえたさいきょうの)アルゴリズム
内部でどんなことしてるのか知りたい人向けです.
<a href="https://github.com/nossey/UndoRedo">ここ</a>のリビジョン:bd758f6e01c73fd7ea3ba6444d7441a59691275a<br>のソースコードをもとに説明します.

## Commandパターンの利用
デザインパターンの一つであるCommandパターンを利用します.
メソッドの実行時にこれをインスタンスとして保存しておくことで,
「取り消す操作を実行する」「再び実行する」事が可能になります.

## 概念図
![Overview.png](https://qiita-image-store.s3.amazonaws.com/0/139940/0759048b-1a43-eaed-7294-12374a48a2e4.png)

State(状態)とCommand(Undo/Redo操作)によるリンクリストになっています.<br>
<br>
![InitialState.png](https://qiita-image-store.s3.amazonaws.com/0/139940/0eabf0f8-c113-8611-e2ef-1b99ea28dbd3.png)


初期段階では, 一つのStateだけが存在しています.


## Record
実際に処理を実行し, Undo/Redo可能な操作として記録します.

![Record.png](https://qiita-image-store.s3.amazonaws.com/0/139940/ef5fe174-c72c-8dfe-9bb5-9914bf38874c.png)



- 処理を実行し, Commandを作成する
- 新しいStateを作成し, 図のようなリンクリストを構築する
- 追加されたStateに遷移する

## Undo 
Commandに記録しておいた「打ち消す処理」を実行します

![Undo.png](https://qiita-image-store.s3.amazonaws.com/0/139940/d78eb952-3ac8-f339-97bb-5d9675cb4f0d.png)

- 図のように「前のStateから遷移する時に実行されたCommand」のUndoを実行する
- 前のStateに遷移する

## Redo
次のStateへ遷移し, 登録しておいたCommandの処理を実行します

![Redo.png](https://qiita-image-store.s3.amazonaws.com/0/139940/02eaa77b-bb02-5906-72f7-0788cb170d32.png)


- 「次のStateへ遷移する時に実行されるCommand」のDoを実行する
- 次のStateへ遷移する

## Record前にUndoしていたら
下の図のように, Undoしてから新たな処理を実行する場合は, 「次に遷移するStateがある状態」で新たなStateの作成をしなければなりません.

![Overview.png](https://qiita-image-store.s3.amazonaws.com/0/139940/0759048b-1a43-eaed-7294-12374a48a2e4.png)


その場合, 現在より後ろのStateは全て破棄します.

![RedoWhenUndone.png](https://qiita-image-store.s3.amazonaws.com/0/139940/7308e87d-89f5-5e75-3ec8-5348555cdcc4.png)


## Transaction
複数の操作を一つの操作としてまとめることもできます.
Commandの配列をもつCommandクラスを用意してあげれば良いですね.
詳細はTransactionCommandクラスを見てください.

![TransactionCommand.png](https://qiita-image-store.s3.amazonaws.com/0/139940/35861fdf-f1aa-e428-a716-9f81b9727586.png)



## 余談
そもそもStateの存在可否から考えた方が良いかも知れない...
Commandの格納にQueueを使って, よりメモリ効率・実行速度の良い実装ができそうな気がしています.<br>


お付き合い頂きありがとうございました.
Cognito User Poolsのフェデレーションを試してみた

Cognito User PoolsがSAML、Google、Facebook、Amazonとの間でフェデレーションできるようになりました。
早速iOSからLogin with Amazonとのフェデレーションを試してみました。

# 準備
[Cognito User Poolsのサインアップ・サインイン画面をiOSで試してみた](http://qiita.com/sirotosiko/items/b94f21fc6ef9967be2fe)
の続きとなります。他下記アカウントが必要です。

* Login with Amazonのアカウント
* Amazon(ECサイトの方)のアカウント

# 作業概要
1. Login with Amazonにアプリを登録
2. User Poolの設定
3. Login with Amazonに登録したアプリの設定
4. iOSアプリ実行

# 1. Login with Amazonにアプリを登録
1. 下記サイトにログインする
  * http://login.amazon.com/manageApps

2. アプリを登録する
<img width="783" alt="registerapp.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/ad5f8be7-9605-0f82-cdd5-227826f82f9a.png">

3. アプリのClient IDとClient Secretを確認する
<img width="781" alt="websetting.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/592f9fd3-9885-6cfa-f101-c0c1a91f936d.png">

**補足**
アプリの登録は簡単でしたが、アプリの削除方法はわかりませんでした。

# 2. User Poolの設定
1. AWSマネジメントコンソールにログインし、[Cognito]-[User Pools]-[該当のUser Pool]-[Federation]-[Identity providers]を選択し、下記のように設定
<img width="1210" alt="identityprovider.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/0235ed6c-2e61-46e8-995d-122e1ffe1892.png">

2. [App Integration]-[App client settings]を選択し、Enabled Identity providersのLoginWithAmazonをチェック
<img width="1201" alt="selectall.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/83ca8dba-3d7e-9dd8-2375-aa31034c8556.png">


# 3. Login with Amazonに登録したアプリの設定
1. Login with Amazonに戻り、Allowed Return URLsを設定
<img width="781" alt="websetting2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/3fac9265-d16d-e68f-4809-59d42783573e.png">

ドメイン部分は、User PoolのApp IntegrationのDomainと一緒になります。

# 4. iOSアプリ実行
1. ログイン画面
Continue with Login with Amazonをクリック
  <img width="371" alt="login_first.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/ac414e39-34fb-a0c5-4d03-3adb5d335131.png">

2. Login with Amazonのログイン画面へ遷移
Email/passwordを入力して、Sign inをクリック
  <img width="374" alt="login_amazon.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/2ff09c1a-910a-66f5-0fbc-2b4f2d21ab65.png">
3. 確認画面へ遷移
  <img width="376" alt="login_amazon2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/99954366-05db-f222-4148-8656f95364bb.png">

**補足**
下記のようにEnabled Identity providersのCognito User Poolをチェックを外すと、直接Login with Amazonのログイン画面へ遷移します。
<img width="695" alt="selectamazononly.png" src="https://qiita-image-store.s3.amazonaws.com/0/192584/6c64e169-5986-b1e1-3f80-5bc7dd6ab7c0.png">

# 雑感
Azureも捨てがたいけど、なんか全部Amazon(AWS)でいい気がしてきた。。。。
Support Library 25.1 から Fragment#onCreateAnimation のタイミングが変わっている話

# TL;DR
最近、手元のプログラムの Support Library のバージョンを 25.0.1 から最新版に上げたところ、画面遷移のアニメーションが発生しなくなりました。調べてみると、 Support Library のバージョン 25.1.0 から、Fragment 表示時に onCreateAnimation が呼び出されるタイミングが変わっていました。

|Support Library|onCreateAnimation が呼ばれるタイミング|
|---|---|
|25.0.1|onCreateView の後、onViewCreated の前|
|25.1.0以降|onResume の後|

# どんな問題が起こるか
Fragment#onResume より前に onCreateAnimation が呼び出されることを仮定したようなコードを書いていると[^1]、アニメーションが正常に動作しない可能性があります。

[^1]: 本来 onCreateAnimation に Fragment の状態に依存するコードは書かないべきですが。

この挙動の変化は、Support Library の 25.1.0 で FragmentTransaction の最適化機能が追加された影響ではないかと思います。最適化は`FragmentTransaction.setAllowOptimization(false)` を設定するとオフにすることができ、また （25.1.0 でユーザーから悲鳴が上がったためか） 25.1.1 からはデフォルトでオフです。しかし、 onCreateAnimation の呼び出しタイミングについては、最適化がオンでもオフでも変化しません。

# 調査
テスト用フラグメントを作って確認してみました。ソースコード全体は [GitHub においてあります](https://github.com/okaxaki/android-fragment-lifecycle)。
## コード抜粋
```java:TestFragment.java
public class TestFragment extends Fragment {

    public TestFragment() {
    }

    private void trace(String method) {
        Log.i("LifeCycle", Integer.toHexString(this.hashCode()) + "#" + method);
    }

    @Override
    public void onAttach(Context context) {
        trace("onAttach");
        super.onAttach(context);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        trace("onCreate");
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        trace("onCreateView");
        return inflater.inflate(R.layout.fr_test, container, false);
    }
(以下略)
```
フラグメントの表示は次のように行います。

```java
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.setAllowOptimization(false); // 25.0.1 以前でビルドする時はコメントアウト
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
Fragment fragment = new TestFragment();
ft.replace(R.id.content_main, fragment);
ft.addToBackStack(null);
ft.commit();
```
## 実行結果
SDK 25.0.1 でビルドして実行すると、次のようになります。

```text:25.0.1
I/LifeCycle: 869229f#onAttach
I/LifeCycle: 869229f#onCreate
I/LifeCycle: 869229f#onCreateView
I/LifeCycle: 869229f#onCreateAnimation
I/LifeCycle: 869229f#onViewCreated
I/LifeCycle: 869229f#onStart
I/LifeCycle: 869229f#onResume
```
SDK 25.1.0 以降でビルドして実行すると、次のようになります。

```text:25.1.0以降
I/LifeCycle: c6cefb5#onAttach
I/LifeCycle: c6cefb5#onCreate
I/LifeCycle: c6cefb5#onCreateView
I/LifeCycle: c6cefb5#onViewCreated
I/LifeCycle: c6cefb5#onStart
I/LifeCycle: c6cefb5#onResume
I/LifeCycle: c6cefb5#onCreateAnimation
```

上記の実行結果は、 次の組み合わせで確認しています。

|Compile SDK|Build Tool|Support Library|
|---|---|---|
|25|25.0.3|25.1.0|
|25|25.0.3|25.1.1|
|25|25.0.3|25.4.0|
|26|26.0.0|26.0.0|

# おわりに
onCreateAnimation の実行タイミングはドキュメントに明確な記載がなかったとはいえ、アニメーションのようにオブジェクトの生存タイミングに敏感な処理について、突然このような仕様変更を入れるのは~~ひどい~~なかなかの大変更と思います。なお setAllowOptimization メソッドは API レベル 26 から setReorderingAllowed というメソッド名にすぐ変更になるなど、落ち着きがありません。この周辺の仕様はまた変化する可能性を踏まえて、ウォッチしておいた方が良さそうです。
OpenAI GymのCopy-v0をSarsaで解く

## 主旨

OpenAI Gym[^1]の課題Copy-v0の解法です．

https://gym.openai.com/envs/Copy-v0

下記記事の続きでSarsaで解いています．

http://qiita.com/namakemono/items/16f31c207a4f19c5a4df

Q学習で解くバージョンはこちらです

http://qiita.com/namakemono/items/1d03160690678380fde1

## 解法

- Sarsa[^2]

```math
Q(s,a) \leftarrow Q(s,a) + \alpha \left\{ r(s,a) + \gamma Q(s',a') - Q(s,a) \right\}
```

- $\epsilon$-greedy法

### コード[^3]

```python
import numpy as np
import gym
from gym import wrappers

def run(alpha=0.3, gamma=0.9):
    Q = {}
    env = gym.make("Copy-v0")
    env = wrappers.Monitor(env, '/tmp/copy-v0-sarsa', force=True)
    Gs = []
    for episode in range(10**6):
        x = env.reset()
        done = False
        X, A, R = [], [], [] # States, Actions, Rewards
        while not done:
            if (np.random.random() < 0.01) or (not x in Q):
                a = env.action_space.sample()
            else:
                a = sorted(Q[x].items(), key=lambda _: -_[1])[0][0]
            X.append(x)
            A.append(a)
            if not x in Q:
                Q[x] = {}
            if not a in Q[x]:
                Q[x][a] = 0
            x, r, done, _ = env.step(a)
            R.append(r)
        T = len(X)
        for t in range(T-1, -1, -1):
            if t == T-1:
                x, a, r = X[t], A[t], R[t]
                Q[x][a] += alpha * (r - Q[x][a])
            else:
                x, nx, a, na, r = X[t], X[t+1], A[t], A[t+1], R[t]
                Q[x][a] += alpha * (r + gamma * Q[nx][na] - Q[x][a])
        G = sum(R) # Revenue
        print "Episode: %d, Reward: %d" % (episode, G)
        Gs.append(G)
        if np.mean(Gs[-100:]) > 25.0:
            break

if __name__ == "__main__":
    run()
```


### スコア

```
[Sarsa] Episode: 5942, Reward: 30
[Q学習] Episode: 30229, Reward: 29
```

## References

[^1]: Brockman, [OpenAI Gym](https://gym.openai.com/), 2016.
[^2]: J.Scholz, [Markov Decision Processes and Reinforcement Learning](https://s3.amazonaws.com/ml-class/notes/MDPIntro.pdf), 2013.
[^3]: namakemono, [OpenAI Gym Benchmark](https://github.com/namakemono/openai-gym-benchmark/blob/master/envs/copy_v0_sarsa.py), 2017.
Holoviewsのdash docsetを作ってみた

# Holoviews？
[Pythonの可視化ツールはHoloViewsが標準になるかもしれない](http://qiita.com/driller/items/53be86cea3c3201e7e0f)

# Dash?
https://kapeli.com/dash
最近エンジニア転職したので、ドキュメントを調べることが多いです。
dash便利ですよ。

# holoviews-docset
https://github.com/tonyjiangh/holoviews-dashdoc

# What's in there?
1. API only
2. No top page
3. No source code

# Some problem

1. githubでdocを見つけられなかったので、holoviewsのhpをwgetでダウンロードしてみました。ただ、丸ごとやろうとすると何故かlayoutが崩れ(style情報がない疑惑)ます。(フロントエンド音痴)
2. 最終的にAPIの部分だけダウンロードしましたが、_moduleの部分がないので、[source]の部分はlocal参照ではなく、ネット接続となります。
3. 使ったwgetのコマンドは以下

```
wget --execute="robots = off" --mirror --convert-links --no-parent --wait=5 http://holoviews.org/Reference_Manual/index.html
```

**Anyway, have fun!**
【DirectX】cmoファイルを使ってスキンアニメーションさせるまで

cmoファイルを使ってスキンアニメーションをするために問題となったことの覚書。

DirectX11でサクっとモデルを出す手としてDirectXTKのcmoファイルのローダーを使用するという手があります。
http://masafumi.cocolog-nifty.com/masafumis_diary/2013/02/windows-storefb.html

これでスタティックモデルの表示はサクッとできるのですが、スキンウェイトが設定されているモデルを表示しようとするとクラッシュしてしまいます。

というのも、どうもDirectXTKのcmoファイルのローダーはスキンアニメーションが未実装のようで、コードを調べるとこんなコードが。

```C++
#if 0
        // Animation data
        if ( *bSkeleton )
        {
　　　　　　省略
           ・
　　　　　　・
　　　　　　・
        }
#else
        UNREFERENCED_PARAMETER(bSkeleton);
#endif
```

\#if 0で無効になっているコードがスケルトン、スキンウェイト、アニメーションクリップといわれるアニメーション用のデータをロードしている箇所なので、まずこのコードを有効にする必要があります。そうするとスキンが設定されているモデルをロードしてもクラッシュせずに表示できるようになります。しかしアニメーションはできません。
もう少しコードを調べていくと、有効にしたコードにこんなTODOコメントがあります。

```C++
for( UINT j = 0; j < *nBones; ++j )
{
    // Bone name
    nName = reinterpret_cast<const UINT*>( meshData + usedSize );
    usedSize += sizeof(UINT);
    if ( dataSize < usedSize )
        throw std::exception("End of file");

    auto boneName = reinterpret_cast<const wchar_t*>( meshData + usedSize );

    usedSize += sizeof(wchar_t)*(*nName);
    if ( dataSize < usedSize )
        throw std::exception("End of file");
    
    // TODO - What to do with bone name?
    boneName;

    // Bone settings
    auto bones = reinterpret_cast<const VSD3DStarter::Bone*>( meshData + usedSize );
    usedSize += sizeof(VSD3DStarter::Bone);
    if ( dataSize < usedSize )  
        throw std::exception("End of file");

    // TODO - What to do with bone data?
    bones;
}
```

ボーンの名前見つけたけどどうする？ボーンのデータ見つけたけどどうする？的な意味でしょうか。他にもアニメーションクリップ見つけたけどどうする？キーフレーム見つけたけどどうする？的なコメントもあります。
独自で実装してねってことなのかな？ってことで実装してみましたが、こんな感じでうまくアニメーションしない。

![anim0.gif](https://qiita-image-store.s3.amazonaws.com/0/167635/dbf691a4-c551-3691-cb6d-33ce11391511.gif)

グラフィック診断を使って調べてみたところ頂点に設定されているボーンインデックスやスキンウェイトがおかしくなっている模様。そこで、ローダーのスキンウェイトを頂点バッファに設定しているコードを調べてみると、下記のようなコードになってました。

```C++
skinv->SetBlendIndices( *reinterpret_cast<const XMUINT4*>( skinptr->boneIndex ) );
skinv->SetBlendWeights( *reinterpret_cast<const XMFLOAT4*>( skinptr->boneWeight ) );
```

全部の頂点に0番目の頂点のウェイトを設定してしまうコードになってます。これを次のように修正するとスキンの設定は修正できます。

```C++
skinv->SetBlendIndices( *reinterpret_cast<const XMUINT4*>( skinptr[v].boneIndex ) );
skinv->SetBlendWeights( *reinterpret_cast<const XMFLOAT4*>( skinptr[v].boneWeight ) );
```

ここまでの実装ができるとこんな感じ。

![ezgif.com-resize (1).gif](https://qiita-image-store.s3.amazonaws.com/0/167635/1ebc1eeb-3fc9-9fa8-4900-1391366df939.gif)

これでもまだおかしいのですが、これはfbxからcmoファイルへの変換のコンバーターの問題で、スケルトンの情報をちゃんと出力してくれていないためです。コンバーターのソースは公開されていないのでカスタマイズすることはできないので、スケルトンの情報だけ別途出力するスクリプトなりプラグインなりを自作する必要がありそうです。

というわけで、cmoファイルを使ってスキンアニメーションさせるまでに発生した問題の覚書でした。今時独自に3Dモデルフォーマットを考えて3Dモデルを表示したいなんて、酔狂な人はそんなにいないかと思いますが、cmoファイル自体は非常にシンプルなフォーマットで分かりやすかったので、3Dモデルフォーマットについて勉強してみたいって人は遊んでみるといいんじゃないでしょうか。
RailsとVue.jsをHerokuにデプロイするまで

# はじめに

Railsでjs書くのが楽しいらしいのでちょっといじってみます^_^

前提として

- Rubyインストール済み
- Railsインストール済み
- Herokuアカウント登録済み


参考までに↓↓↓

[MacのRubyをrbenvでバージョンアップする](http://qiita.com/Arashi/items/689e91389235c25088a5)
[Heroku初心者がHello, Herokuをしてみる](http://qiita.com/Arashi/items/b2f2e01259238235e187)

# Vue.jsとwebpackをインストール
新しいプロジェクトを作成するときにオプションを付けると一緒についてきます。

```bash
$ rails new myapp --webpack=vue
```

早…

参考：https://github.com/rails/webpacker#vue

# yarnをインストール

```bash
$ brew install yarn
# バージョン確認
$ yarn --version
  0.27.5
```

参考：https://yarnpkg.com/lang/en/docs/install/#mac-tab


# サーバー起動

```bash
$ rails s
```

それで、たぶん http://localhost:3000/
こやつにアクセスすれば

![スクリーンショット 2017-08-13 20.54.41.png](https://qiita-image-store.s3.amazonaws.com/0/50208/97fe9730-a647-be1e-014e-072acd083693.png)

こんな画面にアクセスできるはず！

出なかったらごめんなさいm(_ _)m


# Hello Vue!を表示させる

コントローラー作成。

```bash
$ rails g controller Home index
```

ファイルを編集していきます。

```app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
〜略〜
  <body>
    <%= yield %>
    <%= javascript_pack_tag 'hello_vue' %>　 ←この行を追加
  </body>
</html>
```

ルーティングを変更します。

```config/routes.rb
Rails.application.routes.draw do
  root 'home#index'
end
```

コンパイルします。

```bash
$ bin/webpack
```


再度、サーバーを起動します。

```bash
$ rails s
```

プロジェクトルートにProcfileファイルを追加します。

```Procfile
web: bundle exec puma -p $PORT
```

http://localhost:3000/
にアクセス！

たぶん、出るはず！！！

# Herokuにデプロイ

DB設定の変更が必要なので、Gemfileを編集していきます。

本番用とdev, test環境用に分けます。（一応）

```Gemfile:
〜略〜

# gem 'sqlite3' ←　削除

gem 'pg', group: :production　←　これを追加

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '~> 2.13'
  gem 'selenium-webdriver'
  gem 'sqlite3' ←　追加
end
```

pg入ってないとエラーが出るのでインストールしておく。

```bash
$ brew install postgresql
```

bundle実行します。

```bash
$ bundle install
```

Herokuコマンドを入力していきます。

```
$ heroku create
$ heroku addons:create heroku-postgresql:hobby-dev

$ heroku buildpacks:add --index 1 heroku/nodejs
$ heroku buildpacks:add --index 2 heroku/ruby

$ git add .
$ git commit -m "first commit"
$ git push heroku master

$ heroku run rake db:migrate

$ heroku open
```

参考：https://devcenter.heroku.com/articles/getting-started-with-rails5
参考：https://elements.heroku.com/addons/heroku-postgresql


終わり！

# 終わりに
結構ググりながらやってるので途中なにか抜けてる気がしてます…

ご勘弁をm(_ _)m
raspberry piでCAN(OBD2)通信ボードを認識させる

MCP2515のボードです。
とりあえずsudo raspi-configでspiを有効にします。

軽く調べると以下のような設定が出てくる。チョロい！私はすぐにそれを実行した。(google翻訳の読み過ぎで語調がおかしい)

```/boot/config.txt
dtparam=spi=on
dtoverlay=mcp2515-can0-overlay,oscillator=8000000,interrupt=25
dtoverlay=spi-bcm2835-overlay
```
しかし、/dev/spidev0.0と/dev/spidev0.1は現れるが、/sys/class/netにcan0が表示されません。

ちょっと古いリリースの2016-03-18-raspbian-jessieでは認識されるので、ハードウェアの問題ではないはず。
サラッと書いていますが、ここまで辿り着くのにわざわざカーネルビルド環境を作ったりして2日かかっています。

更に調べること数時間、掲示板にボソッと「最近のだと"-overlay"いらんよ」と書いてあるじゃないですか。
私はそれが助けになるよう強く望んだ。(goog以下ry)

```/boot/config.txt
dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25
dtoverlay=spi-bcm2835
```
2行目と3行目の2箇所あるので注意。

なんてこった！あっさり出ちまいやがった。(しつこい)

しかし、"can"と言うどの文章にでも現れる文字列を名前として付けられると、検索し辛い事この上ないですね。

また、MCP2515のVCCをバイパスして3.3Vを入力している記事を見かけましたが、普通にボードに3.3Vか5Vを入力するだけでもどちらも動いているように見えます。5Vを入れるとMCP2515には4.4Vくらいかかるようですね。
なお、入出力電圧の方は調べていません。

あ、それが原因で車に変な信号が流れても私はシリマセンよ。
go での非同期処理　その２

Go での非同期処理。まちあわせ。

前回 [Go での非同期処理 その１](http://qiita.com/TsuyoshiUshio@github/items/6c04b7617db0062d3dee)でも、channel を使った待ち合わせの方法を実装したが、もっとちゃんとしたやり方がある様子。

# WaitGroup を使う

WaitGroup というのを使うみたいだが、使うときと使わないときの比較をしてみよう。

```go
package main

import(
	"fmt"
	"time"
)

func wait(i int) {
	time.Sleep(time.Second)
	fmt.Println(fmt.Sprintf("Wait %d done!", i))
}

func main() {
	for  i := 0; i < 3; i++ {
		go wait(i)
	}

	fmt.Println("Everything Done!")
}
```

こんなコードを書いてみる。当たり前だが、go routine が動くが、終わる前にメインの処理が終わってしまうので、次のような実行結果になる。

```
$ go run cmd/wait/*.go
Everything Done!
```

じゃあ、これをちゃんと、WaitGroup というやつに対応させてみよう。

```go 
package main

import (
	"fmt"
	"sync"
	"time"
)

func wait(wg sync.WaitGroup, i int) {
	defer wg.Done()
	time.Sleep(time.Second)
	fmt.Println(fmt.Sprintf("Wait %d done!", i))
}

func main() {
	var wg sync.WaitGroup
	for i := 0; i < 3; i++ {
		wg.Add(1)
		go wait(wg, i)
	}
	wg.Wait()
	fmt.Println("Everything Done!")
}

```

基本は、WaitGroupを共有して、呼び元で、WaitGroup の Add メソッドを Go Routine の数だけ
呼んであげて、go routine の方で、`Done()` を呼び出せば、WaitGroup が終了を検知できるしくみになっている。さあ実行

```
W
io/WaitGo
$ go run cmd/wait/*.go
Wait 1 done!
Wait 0 done!
Wait 2 done!
fatal error: all goroutines are asleep - deadlock!
```

あかんがな、実行できているけど、Deadlock やがな。調べてみると、WaitGroup を渡すのに、実体を渡していると、関数にわたるときに、コピーされる。つまり、いくら Go Routine のほうで Done() を呼び出したところで、コピーのほうのDone() が呼ばれているだけで、元の、WaitGroup で足した Add の数が減ることがないという現象。じゃあ、ポインタ渡しにかえよう。


```go
package main

import (
	"fmt"
	"sync"
	"time"
)

func wait(wg *sync.WaitGroup, i int) {
	defer wg.Done()
	time.Sleep(time.Second)
	fmt.Println(fmt.Sprintf("Wait %d done!", i))
}

func main() {
	wg := &sync.WaitGroup{}
	for i := 0; i < 3; i++ {
		wg.Add(1)
		go wait(wg, i)
	}
	wg.Wait()
	fmt.Println("Everything Done!")
}

```

実行結果

```
$ go run cmd/wait/*.go
Wait 0 done!
Wait 2 done!
Wait 1 done!
Everything Done!
```
無事待ち合わせ Done!
mac OS のvagrant box を作成する

Sierraでboxを作りたかったが、

```
IOConsoleUsers:gIOScreenLockState <以後略>
```
で止まってしまうのでとりあえず "EL Capitan" でやりました。
issue は見つかるのでそのうち対策できるかなあ？

# 必要なもの
- Virtual Box
- OSX EL Capitan のインストーラー
- boxcutter

## EL Capitan のインストーラーのダウンロード
1. App Store を開く
2. 購入済みタブを開く
3. 下にスクロールして"OS X EL Capitan"を見つける
4. 右のダウンロードを押す
5. /Applicationディレクトリの中にappファイルが入ります

# 手順

1. Virtual Box のインストール
    2. 略
3. git cloneする

    ```bash
    mkdir boxcutter
    cd boxcutter
    git clone https://github.com/boxcutter/macos.git
    cd macos
    ```

4. 実行する
    `prepare_iso` を実行したあと `pucker` しても良いんだけど、`bin/box` を使うとまとめてやってくれる。
というわけで、

    ```bash
    bin/box build osx1011 /Applications/Install\ OS\ X\ El\ 
    Capitan.app/ 10.11 virtualbox
    ```
これだけでdmgの抽出、VirtualBoxへのインストール、box の作成、VirtualBoxからの削除までやってくれます。
結構時間がかかります。

5. box を追加する

    ```
    vagrant box add <好きな名前> box/virtualbox/macos1011-1.0.1.box
    ```

    ```
    vagrant box list
    ```
    でそのboxが追加されているのを確認できたら完了！

# 参考
- [boxcutter](https://github.com/boxcutter)
- [osx-vm-templates](https://github.com/timsutton/osx-vm-templates)
- [(macos-virtualbox-vm) Sierra 10.12.4 hangs during boot, stuck at gIOScreenLockState](https://github.com/geerlingguy/macos-virtualbox-vm/issues/24)
docker コマンドを docker-compose 風に綺麗に書く（書き比べてみる）

# 概要

`docker` コマンドをメンテしやすく綺麗に書ければ
`docker-compose` 使わなくてもいいのではないかと思い、書き比べてみました。
（いやまあ、`docker-compose` のメリットはメンテしやすさだけでは無いでしょうけども。）

```yaml:docker-compose.yml版
version: '2'
services:

  mysql:
    image: mysql:5.7
    container_name: mysql
    hostname: mysql
    environment:
      - "MYSQL_ROOT_PASSWORD=xxx"
      - "MYSQL_DATABASE=xxx"
      - "MYSQL_USER=xxx"
      - "MYSQL_PASSWORD=xxx"
      - "TZ=Asia/Tokyo"
    command: >
      mysqld
        --character-set-server=utf8
        --collation-server=utf8_unicode_ci
        --skip-character-set-client-handshake
    volumes:
      - "./sql:/docker-entrypoint-initdb.d"
      - "/opt/datastore:/var/lib/mysql"
    ports:
      - "3306:3306"

  node:
    image: node:boron-alpine
    container_name: node
    hostname: node
    volumes:
      - "./app:/app"
    working_dir: /app
    command: [sh, -c, npm install --no-bin-links && node app]
    ports:
      - "1337:1337"
    depends_on:
      - mysql
```


```bash:docker+sh版
#!/bin/sh

docker run                              \
    --name     mysql                    \
    --hostname mysql                    \
    -e MYSQL_ROOT_PASSWORD=xxx          \
    -e MYSQL_DATABASE=xxx               \
    -e MYSQL_USER=xxx                   \
    -e MYSQL_PASSWORD=xxx               \
    -e TZ=Asia/Tokyo                    \
    -v /vagrant/app/sql:/docker-entrypoint-initdb.d  \
    -v /opt/datastore:/var/lib/mysql    \
    -p 3306:3306                        \
    -d                                  \
    mysql:5.7                           \
    mysqld                                      \
        --character-set-server=utf8             \
        --collation-server=utf8_unicode_ci      \
        --skip-character-set-client-handshake

docker run                  \
    --name     node         \
    --hostname node         \
    -v /vagrant/app:/app    \
    -w /app                 \
    --link mysql            \
    -p 1337:1337            \
    -d                      \
    node:boron-alpine       \
    sh -c "npm install --no-bin-links && node app"
```


どちらも同様に動きましたが下記の点に注意が必要:

- docker版は `volume` で相対パスが使えない。


# 個人的結論

`bash:docker+sh版` もアリかなと思いました。
`docker-compose` という層が無ければ、その分、インストール/学習/動かない場合の調査も減りますし。

この方法、もう少し使ってみて困ったことがあれば追記します。

もし、`docker-compose` の大きなメリット、お気づきの方がいらっしゃいましたら、コメント欄等でご指摘頂けると嬉しいです。
SafariでDate（JavaScript）を扱う場合の注意

JavasScriptで日付処理をすることってよくあると思うんですが、この前Safari対応で少しハマったので備忘録。

# やりたいこと
- 日付の処理を行う画面の作成
- Chrome / Safariからのアクセスを想定
- YYYY MMM DDという日付を処理したい

# サンプルで試す

例えばこんなことをやってみます。

https://plnkr.co/edit/NsOC5d

```html
<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>

  <body>
    <script type="text/javascript">
      function date_test() {
        var date = new Date("2017 Aug 11");
        document.getElementById("result").innerHTML = date;
      }
      
    </script>
    <p>Convert "2017-08-11" to Date object.</p>
    <div><input type="button" value="Date Test" onclick="date_test();"/></div>
    <div>Result: <span id="result"></span></div>
  </body>

</html>
```

Chromeの結果

![スクリーンショット 2017-08-13 17.40.24.png](https://qiita-image-store.s3.amazonaws.com/0/102769/5ea4ab79-1a16-9abb-1057-bbd9dbbee316.png)


Safariの結果

![スクリーンショット 2017-08-13 17.40.42.png](https://qiita-image-store.s3.amazonaws.com/0/102769/f3936ce5-46d7-ad8e-d524-1a84599cb6c5.png)


SafariでのDateの動きが他のブラウザと異なるのは有名な話らしいですが、これは困った。

# Moment.jsで解消する
今回はMoment.jsを利用しました。

https://momentjs.com/

こういう書き方をすれば今回のパターンには対応できます。

https://plnkr.co/edit/1HTcyhCh


```html
<!DOCTYPE html>
<html>

  <head>
    <script data-require="moment.js@*" data-semver="2.14.1" src="https://npmcdn.com/moment@2.14.1"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <script type="text/javascript">
      function date_test() {
        var dateStr = moment("2017 Aug 11", "YYYY MMM DD").format("YYYY/MM/DD");
        
        var date = new Date(dateStr);
        document.getElementById("result").innerHTML = date;
      }
      
    </script>
    <p>Convert "2017 Aug 11" to Date object.</p>
    <div>
      <input type="button" value="Date Test" onclick="date_test();" />
    </div>
    <div>Result:       <span id="result"></span>
    </div>
  </body>

</html>

```

Chromeで試した場合

![スクリーンショット 2017-08-13 17.54.29.png](https://qiita-image-store.s3.amazonaws.com/0/102769/796e749a-f9d0-ca9a-e341-bf7c8f29bb38.png)


Safariで試した場合

![スクリーンショット 2017-08-13 17.54.35.png](https://qiita-image-store.s3.amazonaws.com/0/102769/4f881641-f87f-d8f0-2604-077e0c056cb0.png)


無事、変換されました。

# まとめ

JavaScriotでDateを扱う際には気をつけろ、ってことですね（色々なところですでに言われていることではありますが）。現状Moment.jsを使っておけば自前でConverter書かなくても大丈夫な気がします。
Atom 行番号の背景をカスタマイズ

行番号の背景と編集エリアの色が同じで見難かったので、編集する方法を調べました。
スタイルを編集するにはatomメニューのStylesheet...を選択します。スタイルシート（lessで書かれている）が開きますので、そこの最後尾に自分の設定を書き加えます。
<img width="207" alt="SS 2017-08-13 20.24.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/137440/5ac7021b-6be1-e906-699d-c060c385865b.png">

行番号の背景は`.gutter`で設定するようです。

```styles.less
atom-text-editor .gutter {
    color: #cccccc;
    background-color: #353739;
}
```
これで背景と文字色を編集することができました。

（::shadowが必要だという記述もありますが、Stylesheet...で開いて編集する限り、自動で判別してくれるらしいです。）

---
参照
[Change Gutter Background Color](https://discuss.atom.io/t/change-gutter-background-color/15023/3)
今更、phpでweb scraping

#やりたいこと
LINEグループ内で、金曜ロードショーの予定を表示したい

#こんな感じ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/86c51af6-7b2c-25cc-70d2-e27ff5dd1014.png)

#やったこと

最初に「テレビ番組検索」用APIを探したが見つけることが出来なかったので、
金曜ロードショーのサイトを直接、Web scrapingするプログラムを作成した。

#プログラム
金曜ロードショーのWEBサイトが綺麗に作成されているため、以下の10行程度で簡単に作成できました。

```ruby:確認用
<?php
$html = file_get_contents('https://kinro.jointv.jp/lineup');
$data = phpQuery::newDocument($html);
foreach( $data['.cap'] as $line) {
    $date  = pq($line)->find('.date')->text();
    $title = pq($line)->find('.title')->text();
    $en    = pq($line)->find('.en')->text();
    printf( "%s:%s(%s)\n", $date, $title, $en);
}
```

* LINE側のコーディングはもう少し効率よく書けるようになったら公開したいと思います。
15万円で買える13インチラップトップのメーカー別スペック比較2017年8月版

最近友人がコンピュータを買う機会が何度かあったのでおおよそのメーカー別スペックをまとめてみます。何かあった際の参考にしてください。基準値は一番安いmac book proのスペックです。調査日は8月13日ですべて公式オンラインストアの情報です。
共通事項としては13インチ前後、15万円前後、Windows10 Homeです。（Macを除く）。オフィスはキングソフトは除く。

## スペック表

|メーカー|ブランド|税込価格|CPU|メモリ|SSD|重量|備考|
|:--|:--|:--|:--|:--|:--|:--|:--|:--|
|Apple|MacbookPro|154,224|7世代i5|8GB|128GBSSD|1.37kg|備考|
|ASUS|ZenBook Flip|150,984|i7-6500U|8GB|512GBSSD|1.3kg||
|lenovo|ThinkPad Yoga370|154,710|i5-7200U|8GB|256GBSSD|1.38kg||
|HP|Spector x360|145,584|i5-7200U|8GB|256GBSSD|？||
|NEC|LAVIE Direct NS|155,384|i5-7200U|4GB|500GBHDD|？|15.6型||
|富士通|LIFEBOOK|141,972|i5-7200U|4GB|128GBSSD|8-900g||
|vaio|VAIO Z|169,344|i5-6267U|4GB|128GBSSD|1.17kg|第六世代|
|Panasonic|Let's note sz|254,664|i5-7300U|8GB|256GBSSD|1.03kg|12.1型|
|__以下参考__||||||||
|lenovo|ideapad 510|6,2424|i5-7200U|8GB|500GBHDD|2.2kg|15.6型|
|EPSON||123,660|i5-6200U|2.0GB|250GBHHD|？|最小構成ゆえカスタマイズ必須|
|FRONTIER|GN|140,184|i7-7700HQ|8GB|256GBSSD 1TBHDD|？|15.6型、1050Ti、BTO|

国内で売られているものですとだいたいこんな感じです。パソコン自体は適当にピックアップしたものなのでスペックだけで測れない部分も多いとは思います。参考程度にお願いします。

ちなみにPanasonicが25万円超えてるのは、Let's noteで一番安かったがこの端末。というだけです。

## 注意

一つのブランドでも大きくスペックが変わることがあります。lenovoのやつみたいに。値段が違うということは他の部分でそれ相応に違いがあるので、あまり短絡的に判断しないでください。

## 感想

Let's note高すぎない？　という疑問から出発して調べ始めたのが今回の発端なんですが……やっぱ高すぎですね。
Panasonicだけ25万超えているのは、これが一番Let's noteで安かったからです。

日本メーカーだと、SONYのVAIOも値段が高い割にスペックが低めです。富士通は、なぜメモリ4GBで良いと思ったか聞いてみたい。ちなみに日本の方が軽量化需要が強いのか、海外勢に比べて日本勢の方が軽くなっています。（でもスペックだけ見れば高いけど）

驚いたのがFRONTIERのBTOノートで、グラボ積んでます。これ、ほとんどデスクトップみたいなものなのでは、と踏んでいます。少なくとも持ち運ぶものではなさそう。

ASUSなんかはラインナップがたくさんあってどれにするか迷ったのですが、とりあえず、i7って書いてあったので、それを書きました。

## まとめ

ラップトップ選びの参考にしてください。
PreludeのfailはMonadFailのfailではない（ケアレスミス）

# 困ったこと
　僕はよく失敗表現の型を`MonadFail`インスタンスにして、`fail`を使って失敗を抽象化するなどをするんだけど、
それに対するテストで`fail`を使うと、何故かそのインスタンスの`fail`が呼ばれず、`IO`例外が送出されることがある。

Test.hs （テスト用のコード） vv

```haskell
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Test
  ( ExceptionCause
  , Result (..)
  ) where

import Control.Monad.Fail (MonadFail(..))

type ExceptionCause = String

newtype Result a = Result
  { unResult :: Either ExceptionCause a
  } deriving (Show, Eq, Functor, Applicative, Monad)

instance MonadFail Result where
  fail = Result . Left
```

Main.hs （テスト） vv

```haskell
import Test (Result(..))


-- tasty-discover用の命名
test_it_is_pure :: Bool
test_it_is_pure = pureFail "x(" == negativeContext "x("
  where
    -- Expected behavior
    pureFail :: String -> Result ()
    pureFail = Result . Left

    -- An alias of `Result`'s fail
    negativeContext :: String -> Result ()
    negativeContext = fail -- （！！）


main :: IO ()
main = print test_it_is_pure
```

　このテストは通らない。
（以下の出力になる）

```console
$ stack runghc Main.hs Test.hs
Main.hs: x(
```


# Control.Monad.Failのfailを明示的にimportする
　これは`negativeContext`で`Prelude`の`fail`を呼んでしまっていることに起因する。

```haskell
Prelude.fail            :: Monad     m => String -> m a
Control.Monad.Fail.fail :: MonadFail m => String -> m a
```

　テストを修正する。

Main.hs

```haskell
import Control.Monad.Fail (fail)
import Prelude hiding (fail)
import Test (Result(..))


-- tasty-discover用の命名
test_it_is_pure :: Bool
test_it_is_pure = pureFail "x(" == negativeContext "x("
  where
    -- Expected behavior
    pureFail :: String -> Result ()
    pureFail = Result . Left

    -- An alias of `Result`'s fail
    negativeContext :: String -> Result ()
    negativeContext = fail -- （！！）


main :: IO ()
main = print test_it_is_pure
```

出力

```console
$ stack runghc Main.hs Test.hs
True
```

要するにMonadFailProposalより前の歴史のせい！
シンプルなカーネルモジュールメモ

# 前提
- Ubuntu 16.04
- Windows/VMWare
- ロードしてログの出力をするだけ

# メモ

```c:simple_kernelmodule.c
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("Dual BSD/GPL");

static int kure_init(void){
        printk("kure_init\n");
        return 0;
}

static void kure_exit(void){
        printk("kure_exit\n");
}

module_init(kure_init);
module_exit(kure_exit);
```

```file:Makefile
KERNEL_DIR = /lib/modules/$(shell uname -r)/build
BUILD_DIR := $(shell pwd)
VERBOSE   := 0
obj-m := simple_kernelmodule.o
all:
        make -C $(KERNEL_DIR) SUBDIRS=$(BUILD_DIR) KBUILD_VERBOSE=$(VERBOSE) modules
clean:
        rm -rf  *.o *.ko *.mod.c *.symvers *.order .tmp_versions .helloworld.*
```

## 実行

```
# make
# insmod simple_kernelmodule.ko
```

## 実行結果（/var/log/syslog）
```
Aug 13 02:30:43 ubuntu kernel: [  109.905030] kure_init
Aug 13 02:30:48 ubuntu kernel: [  114.971318] kure_exit
```
補助線170813

# 方向性
新技術を Cartography に取り込むために引き続き進む。ただし、その仕事は一人の手には余る。このため、自分の行うべきことをより精密に位置づける必要がある。

---

# 取り組みの階層性
1. デジタル地図に対する FUD を排除する
2. ウェブ地図に対する FUD を排除する
3. タイル地図に対する FUD を排除する
4. ベクトルタイル地図に対する FUD を排除する
5. バイナリベクトルタイルに対する FUD を排除する

FUD を排除するには、おそらく「実際にできることを示す」しかない。また、排除には予防を含む。

---

# バイナリベクトルタイルと小縮尺の問題
バイナリベクトルタイルと小縮尺の問題について、どのように取り組むか。その前に、主攻と助攻を明確に分離しておく必要がある。

バイナリベクトルタイルの重点は常に大縮尺にある。大縮尺において属性が取得でき、属性からウェブの他の情報にリンクできること、これがバイナリベクトルタイルの本質的重要性。

小縮尺は経済性を無視すれば他技術で代替可能。

---

# バイナリベクトルタイル小縮尺問題
バイナリベクトルの小縮尺対応はあくまで助攻。

1. 小縮尺でデータが混み合いすぎる問題
  1. そもそもデータを見せないことで対処
  2. 画像タイルをハイブリッドして対処
  3. ベクトルレベルで総描して対応
2. 投影法問題
  - ベクトルは問題ではなくて解法

---

# 小縮尺でデータが混み合いすぎる問題

本稿の主題ではないが、整理すると次のとおり。

1. そもそも小さすぎる縮尺でデータを見せない工夫をすることが早道である。
2. 塗り系データで詳細さを表現する狙いがあるならば、[画像タイルをハイブリッド](https://github.com/NYCPlanning/labs-land-use-tiles)する。
3. ベクトルレベルで総描して対応するのが正攻法であるが、これは大きな仕事を生む。

---

# 小縮尺投影法問題

こちらが本稿の本題。まずは大勢を整理。

1. そもそもバイナリベクトルタイルに限らず、タイル地図全般の問題。
2. しかしウェブメルカトルに対抗しようと考えることすらすべきではない。
  - ウェブメルカトルは単位平面を四分木で分割する手法を含む。
  - データの相互運用を阻害すべきではない。
  - 小縮尺において、最も避けるべきである不連続を発生させず、最も事業意義が高い大縮尺において投影上の問題がない。

---

# 小縮尺投影法問題の解法

1. 大縮尺との連結性を保つ
  - ウェブ地図ライブラリの拡張を意味する。
  - 大掛かりになる。
  - 決め手となるものがないのでは。
2. 大縮尺との連結性を断つ
  - 投影した画像（好例：Polar Stereographic の例）を無理にウェブメルカトルに乗せる方法は、プラクティカルではあるが、行き詰まりを意味する。その先の展開がない。
  - d3.js でやられているような投影法の導入が有望。ベクトルが前提となる。

---

# この先の展開

1. [d3.js での投影](https://www.jasondavies.com/maps/transition/)技術を使う。
2. できればこの技術のデータソースに[バイナリベクトルを使う](https://github.com/mapzen/d3-vector-tiles)ことができるようにしたい。
  - 上記の実証済み技術を使うか、あるいは単純にベクトルデータのソースとして最初に読み込むだけに留めるか。

---
# （蛇足）毘
上杉謙信の旗印の「毘」は、毘沙門天の毘であるという理解に留まるべきではなく、「毘」の一字自体が「たすける」、「増す」、「厚い」、「へそ」、「連なる」という意味があるということを理解すると良いのではないかと思った。上記本文で「助攻」と書く時に気がついたもの。
Amazonプライムビデオが見たいのでUbuntuにGoogle Chromeをインストールする（GUIからだと失敗する）


## 概要

普段はChromiumを使っているが、Amazonプライムビデオを見ようと思ったら「Google Chrome」を使えと言われた。

GUIからChromeを入れようとしたが、途中で止まって進まない。そこで、CUIから依存関係を解決した上でインストールする。

## 環境
Ubuntu 16.04.3 LTS

## 手順
### パッケージを取得
下記からパッケージを取得する。（"*.deb"のパッケージを取ってくる）

https://www.google.co.jp/chrome/browser/desktop/index.html

### 依存するパッケージの取得

そのままでは依存関係の問題でインストールできないので、下記を先に入れておく。

```
$ sudo apt-get install libappindicator1 libindicator7
```

### Chromeのインストール

ダウンロードしておいたChromeのパッケージをインストールする。ブラウザから取得した場合は、~/ダウンロード以下にあるはず。

```
$ sudo dpkg -i google-chrome-stable_current_amd64.deb
```