OmniAICreator/Qiita-1.07M huggingface dataset:
[Swift] iCloudと local(UserDefaults)を同期するライブラリ 


[17/7/6追記] Swift4に対応・確認しました。
[17/5/20追記] iOS 10.3.1, macOS Sierra 10.12.4で動作確認しました。
 
[MKiCloudSync](https://github.com/MugunthKumar/MKiCloudSync "MKiCloudSync")というライブラリがあります。
簡単に local (UserDefaults)と iCloud (NSUbiquitousKeyValueStore)を同期してくれる優れものです。アプリ/デバイス間で少量データを授受するのに便利です。
しかしながら、本家が Objective-Cである＋機能追加 のため、Swiftで書き直し UbiquitousSyncを作成しました。

## インストール

Github [UbiquitousSync](https://github.com/AgeProducts/UbiquitousSync "UbiquitousSync")
Share moduleフォルダー内の UbiquitousSync.swift を Dragして Xcode projectに追加してください。

## 使用方法
### 基本
**startWithPrefix()**

- アプリ初期処理 (AppDelegateなど)で、UbiquitousSync.startWithPrefix() をコール。
- Keyに “iCloud_” prefixを持つ UserDefaults項目の初期値が iCloudよりロードされます。
- 以降、当該 Keyの UserDefaults項目に書き込みがあれば、iCloud側も同期して変更します。
- iCloud側で変更があった場合は UserDefaultsを更新し、Notification (kUbiquitousSyncNotification)が発生します。userInfoで変更のあった Keyを通知します。

### オプション

**startWithPrefix(prefixToSync:String, restore:Bool)**

- prefixToSync Keyプリフィックス変更 (defaultは “iCloud_” )
- restore==true (default) 初期処理で iCloud (NSUbiquitousKeyValueStore)値を UserDefaultsにロードする、restore==false ロードしない。

**removeiCloudItems4Debug(prefix:String, cloud:Bool, local:Bool)**

- prefixToSync 同期 Keyプリフィックス変更, 指定する場合は  startWithPrefix で同じとしてください。cloud / local 各々 NSUbiquitousKeyValueStore / UserDefaultsの内容を削除します。
- removeiCloudItems4Debugは startWithPrefixより前にコールしてください。
- デバッグ用です。

## MKiCloudSyncとの仕様差異

- 初期処理で iCloud の値を localにローディングするようにしました。startWithPrefix  restore=false でオリジナル相当になります。
- Notificationで変更項目の Keyを渡します。
- オーバヘッドの削減のため、変更項目のみ書き換えるようにしました。
- iCloud (NSUbiquitousKeyValueStore)と local (UserDefaults)の項目を初期化できます。

## デモ・プロジェクト
- 数字を +/- するだけの iOS/macOSデモアプリです。
- 開発環境: Xcode9 beta2, Swift4。
- 動作環境: iOS11 beta2 (iOS simulator), 10.3.2 (iPhone5), macOS Sierra 10.12.5 (iMac), High Sierra 10.13 beta2 (mac book air) で確認しています。
- iOSシミュレータでは、simulator->iCloud 方向にしか動作しません。
- 一般的な NSUbiquitousKeyValueStore設定方法は、Appleの sample [PrefsIn](https://developer.apple.com/library/content/samplecode/PrefsInCloud/Introduction/Intro.html)を参照ください。

## その他
- iCloudの同期遅延が大きいです。1分前後かかることもあります。
- “UbiquitousSync”というクラス名は命名則違反かも？気持ちが悪ければ変更してください。
- 前述の通り、本ライブラリの基本的なアイディアは MKiCloudSyncに依ります。CopyrightとCreditに関し作者 Kumar氏に連絡し了解をいただいております。
mixin を include したプロパティ自身を取得するには

```scss
.box {
	&-title {
		...
	}
}

...
// hoge ページ
.hoge {
	.box {
		@include box-base;
	}
}

// fuga ページ
.fuga {
	.box {
		...
	}
}

```

```scss:_box.scss
@mixin box-base {
	$target: unquote("#{&}");

	@if str-index($target, ' ') == null {
	} @else {
		$target: str-slice($target, str-index($root, ' ') + 1, str-length($target));
	}
	
	&-title {
		...
	}
	
	// ここで `.box-title` を取りたい
	@each $category in $categories {
		&.#{$category} {
			#{$target}-title {
				background-image: url(#{$category}_title_bg.gif);
			}
		}
	}
}
```

とりあえずネストは1つしか考慮してない。
digdag selfupdate後にはchmod → 0.8.18で改善

0.8.17ではchmod必要
==================

Digdag 0.8.17では以下のようにselfupdate後にchmodが必要だった

```
# id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# umask
0022
# ls -l `which digdag`
-rwxr-xr-x. 1 root root 24144190 Oct  8 10:13 /usr/local/bin/digdag
# digdag --version
0.8.17
# digdag selfupdate
2016-10-25 10:25:33 +0900: Digdag v0.8.17
Checking the latest version...
Upgrading to 0.8.17...
Verifying...
Upgraded to 0.8.17
# ls -l `which digdag`
-rwx--x--x. 1 root root 24144190 Oct 25 10:25 /usr/local/bin/digdag
# su - vagrant
$ digdag --version
bash: /usr/local/bin/digdag: Permission denied
$ sudo chmod 755 `which digdag`
$ digdag --version
0.8.17
```

embulkは大丈夫
-------------

```
# ls -l `which embulk`
-rwxr-xr-x. 1 root root 42916789 Aug 13 08:41 /usr/local/bin/embulk
# embulk selfupdate
2016-10-26 13:10:34.684 +0900: Embulk v0.8.13
Checking the latest version...
Found new version 0.8.14.
Downloading https://dl.bintray.com/embulk/maven/embulk-0.8.14.jar ...
Updated to 0.8.14.
# ls -l `which embulk`
-rwxr-xr-x. 1 root root 41500238 Oct 26 13:10 /usr/local/bin/embulk
```

0.8.18で改善(2016/10/31追記)
===========================

本記事のコメントにある通り、0.8.18では改善した

```
$ sudo /usr/local/bin/digdag selfupdate
2016-10-31 15:32:18 +0900: Digdag v0.8.17
Checking the latest version...
Upgrading to 0.8.18...
Verifying...
Upgraded to 0.8.18
$ sudo /usr/local/bin/digdag selfupdate
2016-10-31 15:33:05 +0900: Digdag v0.8.18
Checking the latest version...
Upgrading to 0.8.18...
Verifying...
Upgraded to 0.8.18
$ ls -l `which digdag`
-rwxr-xr-x. 1 root root 25269257 Oct 31 15:33 /usr/local/bin/digdag
```

感謝！

おまけ：サーバとクライアントでバージョンが合わないとエラー
=================================================================

Digdagサーバだけselfupdate＆サーバプロセス再起動した状態だと、Digdagクライアントで以下のようになる

```
$ digdag version
2016-10-31 15:57:46 +0900: Digdag v0.8.17
Client version: 0.8.17
Server version: 0.8.18
$ digdag workflows
2016-10-31 16:00:27 +0900: Digdag v0.8.17
error: Client and server version mismatch: Client: 0.8.17, Server: 0.8.18.
Please run following command locally to download a compatible version with the server:

    digdag selfupdate 0.8.18
```

Digdagクライアントの方が先にバージョンアップした状態でも同じ

```
$ digdag version
2016-10-31 16:04:28 +0900: Digdag v0.8.18
Client version: 0.8.18
Server version: 0.8.17
$ digdag workflows
2016-10-31 16:04:36 +0900: Digdag v0.8.18
error: Client and server version mismatch: Client: 0.8.18, Server: 0.8.17.
Please run following command locally to download a compatible version with the server:

    digdag selfupdate 0.8.17
```

しかし、クライアントと通信しないサーバ(Workflow executorやAgentだけが動いている)なら、バージョンが一致していなくても問題なくWorkflow executorやAgentは動作する
Javaで組み込みMySQLを使用したらエラー

Java アプリケーションのテストなどに有用な、組み込み MySQL として便利に使わせてもらっている `wix-embedded-mysql` なのですが、立てたばかりの Ubuntu 14.04 でテストしたところエラーが発生しました。
README にしっかりそれらしきことは書いてあったわけですが、微妙なバージョン差異などから見逃してしまっていたため、メモ。

Wix Embedded MySql
https://github.com/wix/wix-embedded-mysql

# 環境

- Ubuntu 14.04.3 LTS
- Java 8
- Maven 3.3.9 (Maven Wrapper)
- Wix Embedded MySql 2.0.1 (MySQL 5.5.40)


```
$ ./mvnw --version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00)
Maven home: /home/ubuntu/.m2/wrapper/dists/apache-maven-3.3.9-bin/2609u9g41na2l7ogackmif6fj2/apache-maven-3.3.9
Java version: 1.8.0_111, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.13.0-74-generic", arch: "amd64", family: "unix"

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
```

# 事象

`Version.v5_5_40` を使用して、Wix MySQL を起動しようとしたところ、以下のようなエラーに出くわしました。

```
Command exited with error code: '1' and output: ''
```

# 対応

README にも、[Known issues](https://github.com/wix/wix-embedded-mysql#known-issues) としてあげられているように、`libaio1.so` をインストールすれば良いです。

># Known issues
>
>mysql, starting version 5.5.10 requires libaio1.so to be preinstalled on linux, but that is not the case for some linux distributions. Proper error is emitted if it's missing and you have to install it manually (ex. ubuntu):
sudo apt-get install libaio1

以下のようにモジュールインストール後は、無事にエラーが解消されました。

```
$ sudo apt-get install libaio1
```

# まとめ

- Wix Embedded MySQL で、`Command exited with error code: '1' and output: ''` に出くわしたら、`sudo apt-get install libaio1`
- README はちゃんと読もう。
ファイルの1行目に文字を追加/挿入する

# 背景

```:text.txt
aaa
bbb
ccc
```

の1行目に文字を追加したファイルを生成したい

```:text.txt
hoge <- 追加
aaa
bbb
ccc
```

# コマンド
```
sed -i '1i hoge\n' text.txt
```

以上。
digdagで_errorを複数書くと

トップレベルと親タスクと子タスクの3箇所に書く
↓
子タスクが失敗する
↓
子タスクの\_error → 親タスクの\_error → トップレベルの\_error の順に実行される

```
$ cat errortest.dig
_error:
  echo>: _error at top level

+parent_task:
  _error:
    echo>: _error at parent_task

  +child_task:
    _error:
      echo>: _error at child_task
    sh>: xxx # invalid command
$ digdag run errortest.dig
2016-10-25 16:48:35 +0900: Digdag v0.8.17
2016-10-25 16:48:38 +0900 [WARN] (main): Using a new session time 2016-10-25T00:00:00+00:00.
2016-10-25 16:48:38 +0900 [INFO] (main): Using session /tmp/.digdag/status/20161025T000000+0000.
2016-10-25 16:48:38 +0900 [INFO] (main): Starting a new session project id=1 workflow name=errortest session_time=2016-10-25T00:00:00+00:00
2016-10-25 16:48:41 +0900 [INFO] (0016@+errortest+parent_task+child_task): sh>: xxx
/bin/sh: line 1: xxx: command not found
2016-10-25 16:48:41 +0900 [ERROR] (0016@+errortest+parent_task+child_task): Task failed with unexpected error: Command failed with code 127
java.lang.RuntimeException: Command failed with code 127
        at io.digdag.standards.operator.ShOperatorFactory$ShOperator.runTask(ShOperatorFactory.java:193)
        at io.digdag.util.BaseOperator.run(BaseOperator.java:51)
        at io.digdag.core.agent.OperatorManager.callExecutor(OperatorManager.java:300)
        at io.digdag.cli.Run$OperatorManagerWithSkip.callExecutor(Run.java:678)
        at io.digdag.core.agent.OperatorManager.runWithWorkspace(OperatorManager.java:244)
        at io.digdag.core.agent.OperatorManager.lambda$runWithHeartbeat$2(OperatorManager.java:138)
        at io.digdag.core.agent.LocalWorkspaceManager.withExtractedArchive(LocalWorkspaceManager.java:25)
        at io.digdag.core.agent.OperatorManager.runWithHeartbeat(OperatorManager.java:136)
        at io.digdag.core.agent.OperatorManager.run(OperatorManager.java:120)
        at io.digdag.cli.Run$OperatorManagerWithSkip.run(Run.java:660)
        at io.digdag.core.agent.MultiThreadAgent.lambda$run$0(MultiThreadAgent.java:95)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
2016-10-25 16:48:42 +0900 [INFO] (0016@+errortest+parent_task+child_task^error): echo>: _error at child_task
_error at child_task
2016-10-25 16:48:43 +0900 [INFO] (0016@+errortest+parent_task^error): echo>: _error at parent_task
_error at parent_task
2016-10-25 16:48:44 +0900 [INFO] (0016@+errortest^failure-alert): type: notify
2016-10-25 16:48:44 +0900 [INFO] (0019@+errortest^error): echo>: _error at top level
_error at top level
error:
  * +errortest+parent_task+child_task:
    Command failed with code 127

Task state is saved at /tmp/.digdag/status/20161025T000000+0000 directory.
  * Use --session <daily | hourly | "yyyy-MM-dd[ HH:mm:ss]"> to not reuse the last session time.
  * Use --rerun, --start +NAME, or --goal +NAME argument to rerun skipped tasks.
```
digdagサーバ起動スクリプト

/home/vagrant/digdag-server/bin/digsv.sh
========================================

```
nohup /usr/local/bin/digdag server --config ~/.config/digdag/config --log ~/digdag-server/log/server.log --log-level info --task-log ~/digdag-server/task-log >> ~/digdag-server/log/server_stdout.log 2>&1 &
```

ヘルプ(```digdag server help```)に```-c, --config PATH.properties   Configuration file (default: /home/vagrant/.config/digdag/config)```とあるが上記のように指定しないとエラーになる
しかし同じヘルプに```-c, --config PATH.properties    server configuration property path```という行もある(「-c, --config」についての行が2行重複している)
http://docs.digdag.io/command_reference.html#server-mode-commands の「-c, --config」の説明にはデフォルトがあるとは書いていない(ちなみにこの説明には「See Digdag server for details.」とあるがリンク切れ)
デフォルトありに改善頂けると嬉しい(ヘルプの重複行やリンク切れも)

コマンドラインでしか指定できない設定とconfigファイルでしか指定できない設定がある
全てconfigファイルに指定できるよう改善頂けると嬉しい

Digdagサーバを複数号機起動する場合、タスクログは全号機が同じディレクトリに出力するのがお勧め
→ [NFSの必要性](http://qiita.com/pilot/items/69cbae56d85a443fb623#nfs%E3%81%AE%E5%BF%85%E8%A6%81%E6%80%A7)

/etc/init.d/digdag-server
=========================

```
#! /bin/bash
# chkconfig: 2345 90 60

. /etc/init.d/functions

PROG=digdag-server
CMD=/home/vagrant/digdag-server/bin/digsv.sh
USER=vagrant
PID=`pgrep -f " /usr/local/bin/digdag server "`
EXIST=$?
RETVAL=0

start() {
  echo -n "Starting $PROG: "
  if [ $EXIST -eq 0 ]; then
    echo_failure
    echo
    echo -n "$PROG is already running."
    RETVAL=1
  else
    sudo -u $USER -i $CMD
    sleep 1
    PID=`pgrep -f " /usr/local/bin/digdag server "`
    EXIST=$?
    if [ $EXIST -eq 0 ]; then
      echo_success
    else
      echo_failure
      RETVAL=1
    fi
  fi
  echo
  return $RETVAL
}

stop() {
  echo -n "Stopping $PROG: "
  if [ $EXIST -eq 0 ]; then
    kill $PID
    sleep 1
    pgrep -f " /usr/local/bin/digdag server " >& /dev/null
    EXIST=$?
    if [ $EXIST -eq 0 ]; then
      echo_failure
      RETVAL=1
    else
      echo_success
      RETVAL=0
    fi
  else
    echo_failure
    echo
    echo -n "$PROG is not running."
    RETVAL=1
  fi
  echo
  return $RETVAL
}

status() {
  if [ $EXIST -eq 0 ]; then
    echo "$PROG (pid $PID) is running..."
  else
    echo "$PROG is stopped"
    RETVAL=3
  fi
  return $RETVAL
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  status)
    status
    ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
    exit 1
esac

exit 0
```

「pgrep -f " /usr/local/bin/digdag server "」って何回も書くのやめたいけどうまくできない...

立ち上がるまで/終了するまで`sleep 1`ってのも荒っぽいが今のところあまり困っていない

2016/11/4
　sudoに-i追加
　(rb>にてrubyコマンド(/usr/local/rbenv/shims/ruby)がみつからなかったため)

TODO
====

stdout/stderrリダイレクトログのローテート
これ使えるかも → http://blog.hansode.org/archives/52520908.html
通常のログはサイズベースでローテートされる → https://docs.digdag.io/command_reference.html#common-options
zshで適度なcase-insensitive補完

zshで大文字小文字を無視して補完したい.
例えば次のような感じ.

```shell-session
~ % cd d[TAB]
Desktop/    Downloads/  deepdream/
Documents/  Dropbox/    dev/                                      
```
そのためには次のように.zshrcに書けば良いです.

1. 大文字小文字を無視して補完する

    ```zsh
    zstyle ':completion:*' matcher-list 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}'
    ```

2. わざわざ大文字を入力した時は小文字の候補を補完しない

    ```zsh
    zstyle ':completion:*' matcher-list 'm:{[:lower:]}={[:upper:]}'
    ```

3. でもやっぱり大文字の候補が見つからない場合には, 小文字の候補を補完する

    ```zsh
    zstyle ':completion:*' matcher-list 'm:{[:lower:]}={[:upper:]}' '+m:{[:upper:]}={[:lower:]}'
    ```

4. 大文字小文字に関わらず, 候補が見つからない時のみ文字種を無視した補完をする.

    ```zsh
    zstyle ':completion:*' matcher-list '' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}'
    ```
5. 通常補完 -> （小文字 -> 大文字） -> （小文字 -> 大文字 + 大文字 -> 小文字）.

    ```zsh
    zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' '+m:{[:upper:]}={[:lower:]}'
    ```

複雑なパターンにも対応してくれますね！

参考: [第5回　zshの誇る花形機能“補完”：zshで究極のオペレーションを｜gihyo.jp … 技術評論社](https://gihyo.jp/dev/serial/01/zsh-book/0005)
vmware workstation player上で動くcentos7でapacheを動かす。

ホストOSであるウィンドウズから、vm上のapacheのウェブサイトを閲覧する方法

centosにてアパッチインストール
```
$ yum install httpd
```

インストール終了後


apacheのipアドレスを確認する。

```
$ ifconfig
```
apacheの設定は終了。
（私の環境では、192.168.0.8）


この状態で上記にて調べたipアドレス(192.168.0.8）をchromeのurl欄に入力しても、
「このサイトにつながりません」と表示されサイトが閲覧できません。

なぜならば、linux内部のfirewallが接続を止めています。
ですので、firewalldを一旦ストップさせる必要があります。

firewalldのストップ
```
$ systemctl stop firewalld
```


apacheの再起動
```
$ systemctl restart httpd
```

以上。
Node-REDを使ってECHONET Lite機器を制御１

Node-REDを使ってECHONET Lite機器を制御する１
本記事ではWindows PCにNode-REDを走らせ、ECHONET Lite機器を制御する方法を説明します。
まずは、環境のセッティングまで。

# node.jsのインストール
https://nodejs.org/en/　
にてnode.jsインストールファイルをダウンロードし、実行。
＊「v4.5.0 LTS」で動作確認。

# Node-REDのインストール
Windowsメニューの「すべてのプログラム（アプリ）」から「Node.js command prompt」を起動し、インストール。
`npm install -g node-red`
＊エラーが出ることもあるが、最後にディレクトのツリー構造が表示されれば問題ないらしい。
Node-REDが動作するか確認するため、Node-REDを起動。
`node-red`
ブラウザを起動し、http://localhost:1880　
へアクセス。

下記画面となれば、Node-REDは動作している。
![pic1.png](https://qiita-image-store.s3.amazonaws.com/0/145903/836b4ba7-0f01-8f64-1b75-2a6dcfb99db0.png)
「Node.js command prompt」の右上の「☓」印をクリックし、一旦終了。

# echonet-liteモジュールをインストール
echonet-liteモジュール詳細については下記参照。
http://qiita.com/Sugimura-Laboratory/items/28bce5212c3cff30a42b

Windowsメニューの「すべてのプログラム（アプリ）」から「Node.js command prompt」を起動
Node-REDを起動。
`node-red`
起動時に出てくる情報から、「settings.js」の場所を特定。
`[info]Settings file : ディレクトリ名`
「settings.js」ファイルをテキストエディタで開き、「functionGlobalContext」というワードを検索。
2つ見つかるので、2つ目の「functionGlobalContext」内に一文追加。
`echonetlite:require('echonet-lite')`
![pic2.png](https://qiita-image-store.s3.amazonaws.com/0/145903/e1aa57d2-1fbd-3036-b58b-eacf3582a3e4.png)
「Node.js command prompt」をアクティブにし、「CTRL」＋「C」でNode-REDを止めて、「settings.js」ファイルがあるディレクトリへ移動。
`cd ディレクトリ名`
echonet-liteモジュールをインストール。
`npm install echonet-lite`
「Node.js command prompt」の右上の「☓」印をクリックし、一旦終了。

# Node-REDの起動
Windowsメニューの「すべてのプログラム（アプリ）」から「Node.js command prompt」を起動。
Node-REDを起動。
`node-red`
ブラウザを起動し、http://localhost:1880　
へアクセス。
import したモジュールの global 変数にアクセスする方法



レガシースクリプト群へ、変更を加える際はテストを義務付けた所、class の無い関数のみのスクリプトに対して、 unittest のコードを書いていたら、 global 変数を利用した関数のテストに出会い、global宣言出来ねーぞ！のエラーが出た。

※ Python2.7 

実行

```python:test_aaa.py
import aaa_module

class TestAAA(unittest.TestCase):
    def test_aaa
        aaa_module.aaa_func()
```

エラー

```python
...
NameError: global name 'logger' is not defined
```

logger がない。あるあるだよね。



```python:aaa_module.py
if __name__ == '__main__':
    logger = logging.getLogger('...')
```

global で宣言。あるあるだよね。


# global の宣言（妄想）

仕方ないから unittest 側で 以下のようにやってみた。

実行

```python:test_aaa.py
import aaa_module

class TestAAA(unittest.TestCase):
    def test_aaa
        global logger
        logger = logging.getLogger('...')
        aaa_module.aaa_func()
```


エラー

```python
...
NameError: global name 'logger' is not defined
```

変わらない。なぜや・・・。

# Python に global 変数なんて無かった
参考: [Pythonでグローバル変数とか無い、正確にはモジュール内変数。だっけ？](http://a2c.hatenablog.com/entry/20081108/1226118772)


# モジュール内変数へのアクセス方法

`module.global変数 = 値`

実行

```python:test_aaa.py
import aaa_module

class TestAAA(unittest.TestCase):
    def test_aaa
        aaa_module.logger = logging.getLogger('...')
        aaa_module.aaa_func()
```

まだまだPythonには未知なものが多い
MindMup 2.0 > 新規マップの作成

```txt:動作環境
MindMup 2.0
```

MindMup 2.0になってから新規マップ作成の方法が煩雑になった。

以下の方法が早そう。

1. https://drive.mindmup.com/# にアクセス
2. [CREATE A NEW MAP]を選択

余談。
https://drive.mindmup.com/hogehoge など試すとPicard艦長ががっかりした画像が表示される。
> There was a problem loading the file, please try again later.

<hr>
(追記 2016/11/25)

上記のリンクは覚えにくい。かつQiitaのこの記事もたどり着きにくい場合がある。

以下が早い。

1. 「google mindmup」でchromeにて検索
2. MindMup 2.0 For Google Driveのリンクをクリック
3. [CREATE A NEW MAP]を選択

こちらの方法だと作業内容として覚えておくのがgoogleとmindmupのみ。
Linux超初心者メモ３

Linuxのシェルコマンドを使う前に覚えておきたいことをメモ。

引用元の記事は以下。
[補完機能、ヒストリ、エイリアスでコマンドラインの入力を“楽”にしよう](http://www.atmarkit.co.jp/ait/articles/1603/09/news019.html)
[Linuxのディレクトリに親しもう](http://www.atmarkit.co.jp/ait/articles/1604/08/news019.html)

>使うシェル:　bash

##Tabキーでファイル名やコマンド名の補完を行う
コマンド名の入力途中にTabキー、もしくは、[Ctrl]+[I]を押すと、補完機能を使用することができます。
補完の候補が複数ある場合は、候補を全て列挙してくれます。

ファイル名についても、入力途中にTabキーを2回押すと、補完の候補を表示してくれます。

##コマンドライン入力のショートカットキー
コマンドの入力を途中で間違えてしまった場合は、左右の矢印キー（[←],[→]）で編集できます。
コマンドの編集には、以下のショートカットキーも使用できます。


| ショートカットキー       |       カーソルの移動 |
|:-----------------|:------------------|
|［Ctrl］＋［B］       |              1文字左へ |
| ［Ctrl］＋［F］	           |            1文字右へ |
| ［Ctrl］＋［A］             |              行の先頭へ |
| ［Ctrl］＋［E］               |            行の末尾へ|

| ショートカットキー       |       削除と編集 |
|:-----------------|:------------------|
|［Ctrl］＋［K］       |             カーソル位置から行末までを削除|
| ［Ctrl］＋［U］	           |           行頭からカーソル直前までを削除|
| ［Ctrl］＋［W］             |              カーソル直前の単語を削除|
| ［Ctrl］＋［Y］               |            削除文字列の貼り付け|


##コマンドのヒストリー機能
前に入力したコマンドは上下の矢印キー（[↑],[↓]）を使って表示できます。
以下のショートカットキーも使用できます。

| ショートカットキー       |       削除と編集 |
|:-----------------|:------------------|
|［Ctrl］＋［P］       |             前に入力したコマンドを表示（Previous）|
| ［Ctrl］＋［N］	           |           次に入力したコマンドを表示（Next）|

過去に入力したコマンドを表示するには以下のコマンドを入力します。行数付きで履歴を表示してくれます。

```ruby:command
$ history
```

historyで表示された特定の番号のコマンドを実行したい場合は、以下のように"!"の後にコマンドの番号を入力します。

```ruby:command
$ !495 -l
```

##Linuxのディレクトリ構成
Linuxのディレクトリ構成は以下の図のようになっています。（ディストリビューションやバージョンにより、多少異なる場合がある）
![directory.png](https://njcrandd.qiita.com/files/b32dc808-7952-f21b-d88d-b2d341ac9c25.png)
一番上の　/　がルートディレクトリ。
ルートディレクトリには、システムを起動するのに最低限必要なファイルが配置される。
/usr には、起動後に使用するファイルが配置される。
/usr/local には、用途が限られるファイルや一般ユーザーが比較的自由に使ってよいファイル等が配置される。
/bin や /lib が複数存在するのは主にHDDの容量やパーティションサイズの制限のため。
※現在は、容量の制限の問題がほとんどなくなったため、同じような役割のディレクトリは片方を“リンク（シンボリックリンク）”にして、“「/bin」と「/usr/bin」は実際には同じ場所になっている”という運用が多くなっている。
Linux超初心者メモ２

Linuxでコマンドを使えるようになりたい！と思った時に勉強したメモ。

引き続き、主な引用先は以下。
[Linuxのシェルとコマンドプロンプトを理解しよう](http://www.atmarkit.co.jp/ait/articles/1603/02/news016.html)

##そもそもGUIとCUI
コマンドラインを使う前に、超基礎のおさらい。
**GUI（Graphical User Interface）**
例えばファインダーでファイルの場所をクリックして開くというような、ウィンドウを表示してマウスで操作するスタイル。
**CUI（Character User　Interface）**
キーボードでコマンド（command：命令）を入力し、その結果を文字で受け取るスタイル
CUIを使ってPCを操作するメリットは、遠隔地から操作しやすい、操作を自動化しやすいといったことがあげられる。

##コマンドを使うためのシェル
シェルとは、「最も広い意味で捉えれば、コマンドを入力するためにユーザーが使用するプログラム」のことです（Wikipedia）。
シェルは“OSのインタフェースを受け持つソフトウェア”で、OSの中心部分（カーネル）を覆う“殻（shell）”をイメージさせるので、このように呼ばれています。ユーザーが入力するコマンドは、シェルを通して、コンピュータで実行されます。
![shell.png](https://njcrandd.qiita.com/files/7948b695-8619-48cc-3801-e772a6c286e7.png)
ユーザーはシェルを通じてOSにコマンドを送り、シェルを通じて結果を受け取ります。


##Linuxで使うシェルの種類
Linuxで使用するシェルには大きく分けて、Bシェル系とCシェル系に区別できます。

######Bシェル系
Bシェル系の**sh**は、最も古くからあるシェルで、UNIX系システムには必ず搭載されているUNIXの標準シェル。shはシェルとしての基本機能しか持っていないので、拡張された**ksh**や**zsh**が開発された。現在は、より使いやすく発展された**bash**がよく使われる。

######Cシェル系
Cシェル系の**csh**は、バークレイ版UNIXの標準シェルで、C言語と同じような文法のシェルスクリプトを書けることが特徴である。現在は、Cシェルと完全な互換性を持ち、かつ機能が強化された**tcsh**がよく使われる。

ほとんどのLinuxディストリビューションで、インストール後デフォルトでbashが起動されます。
Lunux超初心者メモ１

そもそもLinuxとは？といったことに関するメモ。
「Linuxとは」で検索した内容をまとめました。（by超初心者）

元ネタは以下。
[今さら聞けないLinuxの基礎知識](http://www.atmarkit.co.jp/ait/articles/1602/16/news016.html)


##Linuxとは
PCのハードウェアを操作するOS（Operating System）の一つです。
1991年にフィンランドのヘルシンキ大学の院生であったLinus Tovaldsにより開発されました。

Linuxは、狭義ではカーネル（kernel:核、中心部）となる部分のみを指します。カーネルは、コンピュータを操作する上で最も基本的な、CPUやメモリ、ディスクの制御を行います。Linuxは本来カーネルを指す言葉でしたが、Linuxカーネル上で動作するシステム全体を指すことが多いそうです。
Linuxのカーネルは、フリーソフトウェアとして公開され、全世界の有志の開発者により改良が進められています。

Linuxは主にサーバー用として広く利用されており、最近は、デスクトップ・ノートPCなどでも利用されます。


##ディストリビューション(Distribution)

コンピュータを利用するには、カーネルだけなく、様々なソフトウェアが必要です。そこで、Linuxカーネルに様々なソフトウェアを組み合わせて配布するディストリビューション(Distribution)スタイルが誕生しました。
![Distribution.png](https://njcrandd.qiita.com/files/9d8f65ed-f1de-3ef3-2750-4eb699d06ab1.png)
**主なLinuxディストリビューション**

| Red Hat Based　　　　　| Debian Based　　　　　|
|:---------------|:---------------|
| Red Hat Linux <br>Fedora<br>CentOS<br><br>　　　　　　　　　etc... |Debian GNU/Linux<br> Ubuntu<br>Gentoo Linux<br>SuSE Linux<br>　　　　　　　　　etc...  |

Linuxカーネルは無償ですが、ディストリビューションには無償・有償のものがあります。

##Linuxは、UNIX系OSのひとつ
もともと、Linux誕生の前に、AT&T社のUNIXというOSが開発されていました。UNIXは当初、研究用途として、設計内容が公開され自由に利用できました。さまざまな企業や団体が、独自に改造して利用した結果、同じ“UNIX”を名乗っていても、内容に隔たりが生じることになりました。
そこでAT&T社はライセンス契約によるUNIXの管理を始めました。AT&TおよびUNIXのライセンス管理団体と契約を結んだ組織だけがUNIXを名乗り、ライセンス契約を結んでいないものは「UNIX互換OS」と呼ばれるようになりました。「UNIX系OS」の誕生です。

UNIXが動作するコンピュータやライセンス料も高価であり、個人でUNIXを使用することが難しいという背景の中公開されたのが、UNIX風のOS「Linux」でした。

UNIX系OSには以下の３種類があります。
**System V系**：　AT&Tのベル研究所が開発したオリジナル版の流れをくむ。多くの商用UNIXに採用されている。
**BSD(Berkeley Software Distribution)系**：研究・教育機関に強い。現在最も有名なのが「FreeBSD」で、OS Xの基礎部分にも使われている。
**Linux系**：多くの立場の人々が開発に携わり、学生や個人が無償で使えるものから企業が利用する商用版まで幅広くカバーされている。
まだ .gitconfig に core.excludesfile を設定しているの？

グローバルな `.gitignore` を設定するとき、よくある記事の説明が、

```ini
[core]
    excludesfile = /home/${USER}/.gitignore_global
```

をして、 `${HOME}/.gitignore_global` を置くと。

ダメなんだよ・・・・・・!そういうのが実にダメ・・・・！せっかくgitconfigをスカッとしようって時に・・・・その横着は傷ましすぎる・・・・・・・・！

`man gitignore` を見ると

> Patterns which a user wants Git to ignore in all situations (e.g., backup or temporary
> files generated by the user’s editor of choice) generally go into a file specified by
> core.excludesFile in the user’s ~/.gitconfig. Its default value is
> \$XDG_CONFIG_HOME/git/ignore. If \$XDG_CONFIG_HOME is either not set or empty,
> \$HOME/.config/git/ignore is used instead.

曰く、`core.excludesFile` のデフォルト値は `$XDG_CONFIG_HOME/git/ignore`、`$XDG_CONFIG_HOME`が空の時は `$HOME/.config/git/ignore` が使われます。特別な理由が無い限り、 `$HOME/.config/git/ignore` にグローバルな設定を置くのがgitの流儀となります。

なおグローバルなgitignoreは、GitHubのリポジトリを参考にすると幸せになります。
https://github.com/github/gitignore/tree/master/Global
TensorflowをiOSで試してみた　その１

もう既に記事は出ていますが、その記事を参考にiOSでTensorflowを動かしてみました。

そもそも、Tenforflowとは、Googleが提供する、「ディープラーニング」という技術を使用したサービスです。
今更という感じもしますが、基礎的な理解のメモです。

#ディープラーニングとは？
>機械学習とは、人間が学習するのと同じように機械が学習することを目指した人工知能研究の1分野です。ディープラーニングは機械学習の中の1つです。

ディープラーニングとは、**ニューラルネットワーク(Neural network)を使用して行われる機械学習のこと**です。

ニューラルネットワークとは何なのでしょう？
>ディープラーニングの考えのもととなっているニューラルネットワークは、**人間の脳神経回路を真似することによってデータを分類しよう**というアイデアに基づくアルゴリズムです。

ニューラルネットワークのニューラル(neural)は、ニューロン(neuron・神経細胞)のことで、人間が物事を判断したりするときの神経(脳)の働きにヒントを得て、派生した学習方法です。

>ディープラーニングとは、ニューロン(神経細胞)が信号の受け渡しをすることにより情報処理をしているという脳の仕組みを、ニューラルネットワークとしてコンピュータ内に実現し、それを多層化したものです。

一つ一つのニューロン(関数)は単純な判断・計算をしていますが、組み合わせることにより、より詳細なデータを得ることができます。データから学習して発展していくものなので、たくさんのデータを学習させる必要があります（基本的には、数十万単位のデータを学習させる）。

このディープラーニングは既に色々なところで使用されています。
例えば、音声認識、画像認識、Googleが開発している人工知能による碁打ちのAlphaGoなどがあります。

Tensorflowは、Googleが提供する、ディープラーニング技術を使ったサービスの一つです。
Googleが提供する他のサービス（例えば、Google cloud vision API（画像認識）やSpeech API（音声認識））との違いは、学習済みであるかないか、という点にあります。（Tensorflowで既に学習させたものをサービスとしている）
つまり、Tensorflowは、自分のデータを自由に学習させたい！という場合に使用したいサービスです。

#Tensorflowについて

Tensorflowの読み方は、日本では、「テンソルフロー」が多く、英語圏では「テンソーフロー」が多いとのことです。
"Tensor"とは、
> 線形の量を表す概念で、多次元データ構造を表すもの
だそうです。

コア部分はC++、ユーザー向けにはPythonのインターフェースが用意されているそうです。

Tensorflowの特徴は以下です。
1. **Deep Flexibility**（深い柔軟性）：柔軟なニューラルネットワークの構築。C++で低レベル処理を書くことも可能。
2. **True Portability**（真の移植性）：どのようなハードウェア上でも動かすことができる。
3. **Connect Research and Production**（研究と製品の接続）：独自の研究の製品への転用を迅速に行える。
4. **Auto-Differentiation**（自動微分）：勾配降下法（間違えから学び、正しい方法を学んでいく）ベースの機械学習アルゴリズムは、Tensorflowの自動微分の機能から恩恵を受ける。
5. **Language Options**（言語選択）：Pythonインターフェース、C++インターフェース（現時点）
6. **Maximize Performance**（パフォーマンスの最大化）：スレッド、キュー、非同期計算のクラスのサポートを使用すると、ハードウェアを最大限に活用できる。


Tensorflowの利用例
一般の人がTensorflowをどのようにして試しているか調べてみました。

・キュウリの仕分け
キュウリの良し悪しを、画像を学習させて判断する。というもの

・株価の予想
終値が始値よりも高くなるか判定etc...

・消費者感情分析
映画のreviewデータベースを利用して評価分類を行うというもの（評価をpositive,negativeに分ける）



**参考**

[Tensorflow](https://www.tensorflow.org/)
[ディープラーニングとは何なのか？　そのイメージをつかんでみる](http://bizmakoto.jp/makoto/articles/1507/27/news067.html)
[Tensorflowとは](http://www.ossnews.jp/oss_info/TensorFlow)
ESXi 6.0 update2以降でESXiのローカルユーザーを作成する

# 概要

ESXi 6.0 update 2以降で、ローカルユーザーの作成や権限の付与をするための方法（主にPowerCLIによる手順）。

# 詳細

ESXi 6.0 update 2以降では、ESXiに直接アクセスする際のクライアントもWebベースの「vSphere Host Client」になりましたが、ここからではローカルユーザーの作成や権限の付与ができなさそうでした。

作成、設定方法は、大きくは以下の2種類になりそうです。

* 従来どおり、vSphere Clientを使用する。
* PowerCLIを使用する。

PowerCLIを使う場合について、以下にまとめています。

## PowerCLIでの作成手順

PoweCLIでの作成手順を以下で説明します（PowerCLIの使い方自体は説明しません）。

PowerCLIを起動します。PowerCLIのプロンプトで、次のコマンドを実行して、ユーザー作成対象のESXiホストに接続します。以下はホスト名が`esxi01`、rootパスワードが`R00tP@ss`の場合のコマンド例です。

    Connect-VIServer -Protocol "https" -Server "esxi01" -User "root" -Password "R00tP@ss"

次のコマンドを実行して、新ローカルユーザを追加します。以下は作成するユーザー名が`myadmin`、パスワードが`My1P@ss`の場合のコマンド例です。

    New-VMHostAccount -Id "myadmin" -Password "My1P@ss"
 
次のコマンドを実行して、役割（Role）を新ユーザへ付与します。以下はユーザー名`myadmin`に、`Admin`の役割を付与する場合のコマンド例です。 

    $vmhost = Get-VMHost 
    New-VIPermission -Entity $vmhost -Principal "myadmin" -Role "Admin" -Propagate:$true

`Entity`は役割を付与する対象で、ここでは最上位になるESXiホストを指定しています。また下位に伝達させるために`-Propagate:$true`を指定しています。

## 指定できる役割

指定可能な役割（Role）は`Get-VIRole`コマンドレットで確認できます。

    Get-VIRole

以下がESXi 6.0 update2の環境上での出力例です。

    Name                      IsSystem
    ----                      --------
    NoAccess                  True
    Anonymous                 True
    View                      True
    ReadOnly                  True
    Admin                     True

より詳細な権限指定を行いたいときには、`New-VIRole`コマンドレットで新しい役割を作成することも可能です。しかし実際にその役割に細かく権限（Privilege）を設定していくのがあまり現実的でないため、お勧めしません。

指定可能な権限を見たいときは、以下のコマンドを実行すれば確認できます。ただし内部値での表記になるので、vSphere Web Client等で表示される日本語表記とは対応付けを考える必要があります。

    (Get-VIRole -Name "Admin").PrivilegeList

# 参照

本ページの内容は、以下の情報に基づいて作成されています。

* [ESXi ホスト上でローカルユーザを作成する方法と権限を付与する方法について (2083320) | VMware KB](https://kb.vmware.com/kb/2083320)
* [Creating a local user and assigning permissions on an ESXi host (2082641) | VMware KB](https://kb.vmware.com/kb/2082641)
* [New-VIPermission - vSphere PowerCLI Cmdlets Reference](https://www.vmware.com/support/developer/PowerCLI/PowerCLI63R1/html/New-VIPermission.html)
VSCodeでPDF見たい…見たくない?

VSCodeでフォルダを開いていると、たまにPDFが紛れ込んでいたりして、うっかり開くと文字列で表示されて少し悲しい気持ちになりますよね。僕はなります。

そこでPDFをプレビューできる拡張機能を作ってみたのですが、あまりうまくいきませんね、というお話。

## とりあえず作ってみたもの
https://marketplace.visualstudio.com/items/tomoki1207.pdf
![screenshot](https://raw.githubusercontent.com/tomoki1207/vscode-pdfviewer/images/screenshot.png)
内部で[PDF.js](https://mozilla.github.io/pdf.js/)を使ってます。

## うまくいっていないところ
1. `onDidOpenTextDocument`で起動→もとのファイル閉じる→プレビュー表示 とやっているので、一瞬もとのファイルが表示される
1. ファイルオープン時点でバイナリと判定されるPDFファイルがある模様? うまく表示できるファイルと、そうでないファイルの違いは分かってません。

1つ目は `onWillOpenTextDocument` とかが用意されるまで仕方ないかなと思ってますが、2つ目は何とかしたいですね。そもそもVSCode側でテキストファイルとして認識してもらえてないから、これも仕方ないのでしょうか…?

なんかその辺に詳しい方の助言お待ちしてます。
僕に至ってはPDFの中身がテキストだということを初めて知りました。

## これから
- 表示中のページ番号表示
- ページジャンプ
- 見開き表示

とかの機能があったらいいですね(他人事)。
夢は広がります。
Charlesを使って本番ドメインを向いたアプリのリクエストをlocalhost:3000に飛ばす

別にportは3000じゃなくてもいいのですが、とにかく手元のマシンで開発しているAPIなどのテストが便利になります。

![スクリーンショット 2016-10-24 19.04.13.png](https://qiita-image-store.s3.amazonaws.com/0/4194/88e0c2da-09fb-5713-e7ba-69833ec3855a.png)

---


https://www.charlesproxy.com/

Download Versionは4.0.1です。

4系のキャプチャあり説明がこの世に全然ないので、画像つきで説明してみます。

---

## 最終イメージ

---

### 本来

![image1.png](https://qiita-image-store.s3.amazonaws.com/0/4194/99bd0b79-7bcf-0915-aef4-efb63c11d9cb.png)

アプリ→Wi-Fi→本番APIサーバー(https://example.com)

---

### 今回

![image2.png](https://qiita-image-store.s3.amazonaws.com/0/4194/a48682a6-29eb-7e3a-8796-b16809fd7a49.png)

アプリ→Wi-Fi→手元のMacのプロキシ→手元のAPI(http://localhost:3000)

---

localhostのやつが悪い顔しているように見えますが気のせいです。

---

## 手順

もし途中で詰まったらこの辺も見るといいかもです。

http://qiita.com/hiragram/items/195c7117fb6ebd50653e

---

### 1. Charlesダウンロードしてインストール

[TOP](https://www.charlesproxy.com/)よりよしなにやってください。

---

### 2. 起動

![スクリーンショット 2016-10-24 21.26.38.png](https://qiita-image-store.s3.amazonaws.com/0/4194/9d88cf28-2413-26c5-3f86-ea9ef1fb1965.png)

---

### 3. SSL Proxy に"*"設定

Mac上部の方のMenuより選択してウィンドウ表示。

![スクリーンショット 2016-10-24 21.26.56.png](https://qiita-image-store.s3.amazonaws.com/0/4194/2deca95c-55d0-13f3-2b2a-86a9a4657823.png)

---

"*"を追加してください。

![スクリーンショット 2016-10-24 21.27.04.png](https://qiita-image-store.s3.amazonaws.com/0/4194/c17d9b4b-124a-51c1-f58f-484daf76c2e9.png)

---

### 4. Map Remoteの設定

ここが最大のキモです。

MenuよりMap Remoteを選択

![スクリーンショット 2016-10-24 21.27.49.png](https://qiita-image-store.s3.amazonaws.com/0/4194/e8652fe6-f99a-2be6-6df7-17568ef504c5.png)

---

Enable Map Remoteにチェック。

![スクリーンショット 2016-10-24 21.28.14.png](https://qiita-image-store.s3.amazonaws.com/0/4194/ea73b6a8-4cd2-28ef-d3fa-b269dadf2d84.png)

---

「add」を押してEdit Mappingウィンドウを開く。例えば今回はこのようにした。https→httpが設定可能であることがわかる。

![hoge.png](https://qiita-image-store.s3.amazonaws.com/0/4194/1981549d-ceb2-6bf9-d196-41fe1c0dd0a5.png)

---

OKを押して閉じる。

![スクリーンショット 2016-10-24 21.29.05.png](https://qiita-image-store.s3.amazonaws.com/0/4194/1d2f3201-b82c-613d-45c1-963eca04da86.png)

---

### 5. iOSでプロキシ設定

設定>Wi-Fiより、すでに設定してあるSSIDの横にあるinfomationマークをタップして詳細設定画面へ。
同じWi-Fiに接続しているMacに振られているIPとポート8888(Charlesのデフォ)を入力する。

![スクリーンショット 2016-10-24 21.38.05.png](https://qiita-image-store.s3.amazonaws.com/0/4194/cefa39e1-e913-49d4-ea7d-60a9974f526e.png)

---

### 6. スマホでプロファイル設定

ここまで設定してどこかにアクセスしようとすると、Charles上に許可を促す画面が出るのでAllowする。
またここまで来たら、 http://www.charlesproxy.com/getssl にアクセスすることで、プロファイル設定へ進める。

---

### 7. 【最後】APIにアクセス！！

録画ボタンは押しても押さなくてもredirectされました。

ストアから落とした目的のアプリを起動して何らかのAPIが叩かれたときに、ローカルで用意しているlocalhost:3000にログが流れ始めたら成功！

---

APIを開発しているエンジニアが、アプリエンジニアにわざわざ自分のローカルマシンのIPを教えて再ビルドとかしなくても、自由にデバッグができて便利。

もちろん本番アプリじゃなくて、ステージングやDEVサーバーを向いているものでも同様。

---

最初Macの/etc/hostsでlocalhost設定するだけでいいんじゃね？って思ったけど、https前提のAPIではそれだけではだめだった。この方法ならhttps→httpできて便利。

---

## まとめという名の小並感

Charles超便利。プロファイルさえ入れればSSLでも気にしなくていいの楽。他にも便利機能たくさんありそうなのでもっといじり倒したい（ネットワークの帯域制限とか）。
QtのUiクラスをPimplイディオムで隠蔽する

# Qtの自動生成クラス(Visual Studio Add-in)
QtのVisual Studio Add-inで開発する場合、UIのクラスを作成すると次のようなコードが生成されます。

```cpp:foowidget.h
#ifndef FOOWIDGET_H
#define FOOWIDGET_H

#include <QWidget>
#include "ui_foowidget.h"

class FooWidget : public QWidget
{
    Q_OBJECT

public:
    explicit FooWidget(QWidget *parent = 0);
    ~FooWidget();

private:
    Ui::FooWidget ui;
};

#endif // FOOWIDGET_H
```

```cpp:foowidget.c
#include "foowidget.h"

FooWidget::FooWidget(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
}

FooWidget::~FooWidget()
{
}
```


ここではUiクラスのヘッダ(ui_foowidget.h)がWidgetクラスのヘッダ(foowidget.h)に含まれます。
すると、Uiクラスを更新した際にWidgetクラスのヘッダを読み込んでいるすべてのファイルで再コンパイルが必要になります。
コンパイル時間が長くなるため、開発のリズムが悪くなってしまいます。

# PimplクラスによるUiクラスの隠蔽
Pimplイディオムを使ってUiクラスを隠蔽します。
ヘッダからUiクラスの痕跡を消すことができるので基本的にこの方法で記載します。
他のクラスからFooWidgetのUiへ直接アクセスできなくなるので注意が必要です。

```cpp:foowidget.h
#ifndef FOOWIDGET_H
#define FOOWIDGET_H

#include <memory>
#include <QWidget>

class FooWidget : public QWidget
{
    Q_OBJECT

public:
    explicit FooWidget(QWidget *parent = 0);
    ~FooWidget();

private:
    struct Impl;
    std::unique_ptr<Impl> pImpl;

    // Ui::FooWidget ui;  Uiクラスはcppファイルで宣言する
};

#endif // FOOWIDGET_H
```

```cpp:foowidget.cpp
#include "foowidget.h"
#include "ui_foowidget.h"

struct FooWidget::Impl
{
    Ui::FooWidget ui;

    Impl(FooWidget*const obj)
    {
        ui.setupUi(obj); // FooWidgetのthisオブジェクトをImplクラスに渡す
    }
};

FooWidget::FooWidget(QWidget *parent)
    : QWidget(parent)
    , pImpl(new FooWidget::Impl(this))
{
}

FooWidget::~FooWidget()
{
}
```

# Qtの自動生成クラス(Qt Creater)
Qt Createrでは、以下のように自動生成されます。
cppファイルにUiクラスのヘッダが記載されています。

```cpp:foowidget.h
#ifndef FOOWIDGET_H
#define FOOWIDGET_H

#include <QWidget>

namespace Ui {
class FooWidget;
}

class FooWidget : public QWidget
{
    Q_OBJECT

public:
    explicit FooWidget(QWidget *parent = 0);
    ~FooWidget();

private:
    Ui::FooWidget *ui;
};

#endif // FOOWIDGET_H
```

```cpp:foowidget.cpp
#include "foowidget.h"
#include "ui_foowidget.h"

FooWidget::FooWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FooWidget)
{
    ui->setupUi(this);
}

FooWidget::~FooWidget()
{
    delete ui;
}
```

# 環境
VC2013
Qt 5.4
Qt Visual Studio Add-in 1.2.5
Qt Creater 4.0.2
クラスメソッド的なメソッドの作り方を考える

多くの言語に「クラスメソッド」がありますが、Rubyで実装する場合はいろいろ考えることが出てきます。

# 「クラスメソッド的なメソッド」とは

ここでは、「`SomeConst.some_method`」のような形式で呼び出すものを総称して「クラスメソッド的なメソッド」と呼ぶことにします。実際には、多様なものが含まれます。

* クラスインスタンスの特異メソッド（クラスメソッド）
* モジュールインスタンスの特異メソッド
* モジュール関数（厳密には1つの種類ではありませんが、便宜上入れておきます）
* クラスやモジュールのインスタンスに`extend`されたモジュールのメソッド

## 今回の論題

今回は、「特定のクラスと紐付ける必要のない（or紐付けられない）」クラスメソッド的なメソッドについて考えます。例えば、ファクトリーメソッドやActiveRecordの探索系メソッドは、同じクラスのインスタンスやコレクションを生成するためのメソッドなので、クラスメソッドとするのがいちばん自然だということで、あまり考慮の余地はありません。

また、「定数から呼ぶメソッド」でも、その定数が属するクラスのインスタンスメソッドを呼んでいるだけ（`ARRAY_CONST.each`とか`SomeModule.methods`など）の場合も考慮から除外します。

# 各種の作り方
## クラスメソッド

クラスメソッドはクラスインスタンスの特異メソッドですが、いくつかの定義方法があります。

* クラスの外側で`def SomeClass.some_method`とする
* クラス内で`def self.some_method`とする
* `class << self`で特異クラスを開いて、そこでメソッドを定義する

とはいえ、既存クラスに追加するとかそういう特殊な状況以外では、1番目というのはあまり適当ではないと思いますので、いったん置いておきます。

2番目と3番目の違いとして、「1つ1つ`self`を付ける必要があるかどうか」ということもあるのですが、大きな違いとして「`private`にしたい場合」というのがあります。`Module#private`は、（引数付きでも引数なしでも）**インスタンスメソッド**について`private`にするかどうかを制御するものなので、`def self.some_method`として定義したものには影響せず、別途で`private_class_method`を実行する必要があります。一方で、3番目のやり方では、特異クラスのインスタンスメソッドとしてクラスメソッドを定義していますので、`private`も問題なく適用可能です。

### 使い道
Javaなど他の言語では「クラスメソッドだけのクラス」が必要になる場面もありますが、Rubyの場合はインスタンス化が不要ならモジュールでかまわないので、純粋にクラスメソッドだけでクラスを構成するのが適切、という場面はそうありません。

一方で、クラスメソッドで複雑な処理をするという状況では、クラスメソッド内でインスタンスを作ってインスタンスメソッドに処理を投げて、インスタンス変数を使えるようにする、という流れが便利な場面もあるかと思います。外から見ればこのインスタンスの存在はわからず、通常のクラスメソッドとして使えます。

```rb
class Called
  def some_method
    # 略
  end

  def self.some_method(param)
    new(param).some_method
  end
end
```

## モジュールメソッド
クラスと全く同様に、モジュールにも特異メソッドを定義できます。ただ、「いちいち`self.`を付ける or 特異クラスを開いて1段インデントする」というのは煩わしいので、モジュールメソッドがメインになる場合には別な手段を考えたほうがいいかもしれません。

## モジュール関数
「モジュール関数」は1つのメソッドではなく、あるモジュールに「`public`特異メソッド+`private`インスタンスメソッド」があるという、2つセットの状態を指します。ということで、「クラスメソッド的に特異メソッドを呼び出す」のと「`include`して`private`メソッドを関数的に使う」という2つの使い方をできます。

ただ、「クラスメソッド的にしか使わない」ということであればインスタンスメソッドは不要ですが、逆に害になることもありません。とはいえ、性質上特異メソッドの方は自動で`public`になってしまうので、用途によっては向かないかもしれません。

## `extend self`
`Object#extend`はモジュールを引数にとって、特異クラスにモジュールを`include`する（結果として、モジュールのインスタンスメソッドが`extend`先の特異メソッドになる）という動作をするメソッドです。

これを使って、`extend self`とすることで、モジュールのインスタンスメソッドを特異メソッドにすることができます。モジュール関数と似ていますが、以下のような違いがあります。

* モジュール関数は**メソッド定義**に対する操作なので、`module_function`宣言以降に定義されたメソッドにしか適用されないけど、`extend self`は**特異クラス**の操作なので、モジュール内の全メソッドに適用される[^1]
* モジュール関数は「`public`特異メソッド+`private`インスタンスメソッド」という組み合わせで作られるけど、`extend self`をかけた場合はアクセス制限がそのまま特異メソッドにも引き継がれる

ということで、下請けの`private`なメソッドが必要な場合には`extend self`のほうが向いているのではないかなと思いました（どうせ、クラスメソッド的に使うためのモジュールを`include`することもないでしょうし）。

[^1]: もっとも、「一部だけモジュール関数にする」というようなモジュールの運用も通常は考えられませんが。
fluentdで苦労している点

v0.14系を使用しているがそもそも書き方で及び0.12系の書き方との差もソース見ながら四苦八苦。現在悩んでいることのメモ

# テキストとバイナリの混在

使用しているのはmulti_tailなんだが、たまにバイナリが出てくるテキストで正規表現でこけるようなのだが、その結果tagがnilになる模様。

in_forwardのskip_invalid_eventで集約サーバ側は無視できるがこれがクライアント側に残り続ける(chunk?)。

## in_tail前に事前処理

scrubで無効化すればいいんだがinputプラグイン前に割り込むってどうすればいいのだろうか。in_tail拡張するしかないのかなぁ？

10/29追記

v0.14なのでparseだけ拡張する形で対応
MultilineParserを利用して必要部分だけ変更

```
def parse(text, &block)
  unless text.valid_encoding?
    log.info "invalid byte sequence is replaced in `#{text}`"
    text = text.scrub('?')
  end
  super(text, &block)
end

def firstline?(text)
  unless text.valid_encoding?
    log.info "invalid byte sequence is replaced in `#{text}`"
    text = text.scrub('?')
  end
  super(text)
end
```

で指定側

```
<source>
  @type tail
  省略
  <parser>
    @type 作ったparser
    format_firstline 正規表現
    format1 正規表現
  </parser>
</source>
```


下記の通り、多分そのうちマージされるだろうからそれまでの暫定対応
https://github.com/fluent/fluentd/issues/1285#thread-subscription-status

## 失敗をトラップしてから再実行

これもscrubして同様になんだろうが
どうやって検知するもんだろうか。
エラー吐くプラグインとかあると思うがこのハンドリングとリカバリの仕方とかがわからない

単純にレコード捨てても良いのだがこのハンドリングの仕方がはっきりしないとどうにも対応できない


# time sliced

大量にログを吐く環境でちょいと止まっているとすぐにnofに引っかかってしまう。
chunkの数を減らすのに使えないかと試してみたがintervalかつみたいなことはできないのだろうか

イメージはqueueなんだけどこのqueueを指定した時間は一つにまとめてくれる的な、まとめてくれなくてもintervalが来たら今あるものは送信を試みて、その間にきたものは指定したtime_keyに指定したものにまとめるとか。

time_key指定してもintervalにしたらこの時点でtime slicedとしては動かないみたいだし

# forestの置き換え

どうも見る限りforest使用せず<buffer>で記載することを想定しているようだがbufferのpath(ファイル名)とかにtag埋めたいとかできるのだろうか${tag}.*.logみたいな

# out_secondary_file

time slicedのところにかぶるが、一定期間駄目だったらこちらでファイルに書き出して、nof対策とできないか？ただこれを再度投入するのにどうしたら良いかまだ調査出来てない。
fluent-binlog-readerなるものが追加されてるのでこれを使うんだろうが
TensorFlow > tf.image_summary('input', image_shaped_input, 10) > TensorBoard IMAGESへの設定なのだろう

https://www.tensorflow.org/versions/r0.11/tutorials/mnist/beginners/index.html

mnist_with_summaries.py 内のコード。

```
  with tf.name_scope('input_reshape'):
    image_shaped_input = tf.reshape(x, [-1, 28, 28, 1])
    tf.image_summary('input', image_shaped_input, 10)
```

TensorBoard上ではIMAGESのページにて以下の画像が表記されている。

- test : 0から9の画像
- train : 0から9の画像

未消化なのは、上記の20個の画像は、どのインプット画像(x)のファイルなのか、ということ。
処理を停止した時点のデータなのだろうか。

https://www.tensorflow.org/versions/master/api_docs/python/train.html#image_summary


http://robromijnders.github.io/tensorflow_basic/
の例では、IMAGESに表示されるのは1列のみ。

image_summaryのQA
http://stackoverflow.com/questions/35005691/how-to-use-image-summary-to-view-images-from-different-batches-in-tensorflow
+演算子による数値化

これも既出だが。
さっき、d3.jsの作者 Mike Bostockさんのbl.ocks.orgのコードを覗いていて小技を見つけた。

http://bl.ocks.org/mbostock/76d0c2cf689a02c35986af6e0931079d

```javascript
var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");
```

この`svg.attr()`の前の`+`演算子であるが、これは`正の符号演算子`で、後に続く値を数値化するのだそうだ。
よってここでは文字列で得られる`width`および`height`を数値化するということになる。

`+`演算子での数値化の対象となる文字列は、数値を表す文字のみ含む必要がある。

```
C:\>node
> +'123'
123
> +'+123'
123
> +'-123'
-123
> +'123px'
NaN
> +'px123'
NaN
> +'123,000'
NaN
> +'123,000.-'
NaN
> +'123+457'
NaN
> parseInt('123,000',10)
123
> parseInt('123px',10)
123
> parseFloat('123px')
123
> parseFloat('123,000')
123
> parseFloat('123+100')
123
>
```
parseInt,parseFloatのほうが応用が若干効くようである。
カンマ区切りの数値はどれも無理だね。`replace`を挟めばいけそうだけど。

参考:
http://qiita.com/zawascript/items/a25eaf7a222ac3671275
TensorFlow > link > tf.InteractiveSession() > tf.Session()との違い

`mnist_with_summaries.py`にある以下のコード

```py
  sess = tf.InteractiveSession()
```

tf.Session()と何が違うのかというのは以下を見つけた。

https://www.tensorflow.org/versions/r0.11/api_docs/python/client.html#InteractiveSession

> The only difference with a regular Session is that an InteractiveSession installs itself as the default session on construction. The methods Tensor.eval() and Operation.run() will use that session to run ops.

>This is convenient in interactive shells and IPython notebooks, as it avoids having to pass an explicit Session object to run ops.

## InteractiveSession()の場合

```
sess = tf.InteractiveSession()
a = tf.constant(5.0)
b = tf.constant(6.0)
c = a * b
# We can just use 'c.eval()' without passing 'sess'
print(c.eval())
sess.close()
```

## Session()の場合

Session()で同じようなことをする場合 with 構文が必要になりそう。

```
a = tf.constant(5.0)
b = tf.constant(6.0)
c = a * b
with tf.Session():
  # We can also use 'c.eval()' here.
  print(c.eval())
```
技術英語 > Rotate pair assignments regularly to encourage [cross-pollination]. / I am allergic to pollen.

@ Code Complete (No. 15834 / 36077)

Pair Programmingに関して

> Rotate pair assignments regularly to encourage <font color=red>cross-pollination</font>.

http://ejje.weblio.jp/content/cross-pollination
> 異花受粉

<hr>
関連して思い出したのは

http://ejje.weblio.jp/content/allergic+to+pollen
> I am allergic to pollen.

花粉症は外人に通じるのかは不明 (花粉症という概念を持っているのか)。
【BAT】複数フォルダ内を拡張子で抽出してコピーや削除する方法

# はじめに
あるフォルダを世代別バックアップしているため、フォルダ名に日時(yyyyMMddHHmmss)が付いた状態になっているが、配下のフォルダ構成は同じという状態で実績データ(CSVファイル)を取得したいという依頼があった。

親フォルダの名前が違うというのが面倒なところで、ファイルエクスプローラーの検索のように「*.csv」とすれば、親フォルダに関係なくCSVファイルが抽出できればいいのだが、バッチによるやり方がピンと来なかった。
以前、別件で同様のフォルダ構成でEXEのバージョンを取得してログ出力するVBSスクリプトを組んだこともあって、それを改変して作成した。

目的のものを作り終えたが、バッチでもやり方があるのではないかと検索して、下記サイトに辿り着いた。
[指定した名前のディレクトリを再帰的に削除するコマンドライン - IIJIMASの日記](http://d.hatena.ne.jp/IIJIMAS/20101101/1288537836)

# 対応
## FOR /Rコマンド
このサイトの[記事](http://d.hatena.ne.jp/IIJIMAS/20101101/1288537836)によれば、「FOR /R」とすることでサブフォルダーも処理対象に出来るとのこと。

```
FOR /R [[ドライブ:]パス] %変数 IN (セット) DO コマンド [コマンド パラメーター]
[ドライブ:]パスから始めて、ツリーの各ディレクトリで FOR 文を実行し
ます。/R の後にディレクトリが指定されていない場合は、現在の
ディレクトリが使用されます。セットが単一のピリオド (.) である場合は、
ディレクトリ ツリーの列挙だけを行います。
```

以下のようにすれば再帰的にフォルダを検索して処理コマンドを実行できるようです。
"%%f"には、対象のファイル名がセットされる。

```
for /R %%f in (フォルダ名) do 処理コマンド "%%f"
```
## forfilesコマンド【追記 2017/06/06】
Windows 7やWindows Server 2008以降なら、forfilesコマンドがあります。
/Sオプションを付けることで、サブフォルダーも処理対象に出来ます。
forコマンドでは特定の更新日付を持つファイルだけを抽出することはできないですが、forfilesコマンドなら一定期間経過したファイルを削除することができます。
[Windowsのforfilesコマンドで条件に合うファイルを取り出して処理する](http://www.atmarkit.co.jp/ait/articles/0902/27/news132.html)

```
forfiles [/P パス名(検索を開始するパス)] [/M 検索マスク] [/S] [/C コマンド] [/D [+ | -] {yyyy/MM/dd | dd}]
```

|変数|意味|
|:--|:--|
|@file|ファイル名（拡張子も含む）|
|@fname|拡張子無しの基本ファイル名部分|
|@ext|拡張子|
|@path|ファイルのフルパス名|
|@relpath|開始フォルダーからのファイルの相対パス名|
|@isdir|フォルダー名ならTRUE、ファイル名ならFALSE。if内部コマンドと組み合わせ、「/C "cmd /c if @isdir==FALSE notepad.exe @file"」などのように利用する|
|@fsize|ファイルサイズ（bytes単位）|
|@fdate|ファイルの更新日|
|@ftime|ファイルの更新時間|

## ファイルコピー
CSVファイルをtargetフォルダにコピーする。
同一ファイルがあった場合、XCOPYのDオプションにより送り側の日付が受け側の日付より 新しいファイルだけをコピーします。

```bat
for /R %%f in (*.csv) do xcopy /D /I /Y "%%f" target
```

## ファイル削除
gitを使用していた作業フォルダを移す場合、邪魔なgitkeepとgitignoreファイルを一掃します。

```bat
for /R %%f in (*.gitkeep, *.gitignore) do del /S /Q "%%f"
```
### 一定期間以降を削除
IISログを2ヶ月分残して削除する。2ヶ月は61日として指定。

```bat
forfiles /P "C:\inetpub\logs\LogFiles\W3SVC1" /M *.log /C "cmd /c if @isdir==FALSE del /s @path" /D -61 >> iislogdel.log
```

## フォルダ削除
gitを使用していた作業フォルダを移す場合、邪魔なgitフォルダとVisual Studioのvsフォルダを一掃します。

```bat
for /R %%f in (.git,.vs) do rmdir /S /Q "%%f"
```

# 最後に
バッチ処理でfor文コマンドはたまに使用していたが、「R」コマンドについては知らなかった。これでVBSスクリプトを組まなくともバッチでフォルダ内を再帰できるようになったので、今後活用していきたい。
LINE MESSAGE APIを使用してユーザー情報を取得する

#このAPIについて


以前のDeveloper Trialから今回正式版としてLINE MESSAGE APIがリリースされました。
無料アカウントで使用できる範囲が比較的多いので、これから多岐に渡って活躍が期待できそうですね。
[LINE BUSINESS CENTER](https://business.line.me/ja/services/bot)

さらに今回複数の言語に対応したSDKも公開されました。
リファレンスも日本語に対応しているので使いやすく実装がより簡単になりました。
[API Reference](https://devdocs.line.me/ja/)


今回の内容は以前投稿したDeveloper Trial用の[「LINE BOTを使用してユーザー情報を取得する」](http://qiita.com/yusuke-asaoka/items/0fa63d1e5cf27fe48aaa)と同様ユーザー情報を取得して返事をするBOTです。

#事前準備
- アカウントを登録
（**Channel Secret**、**Channel Access Token**が必要になります。SSLの使用できるサーバーを用意して**Webhook URL**に設定を行います。）

- composerを使用してSDKのインストール
https://github.com/line/line-bot-sdk-php

```php
require_once('./vendor/autoload.php');

new LineMessage;

class LineMessage{

  private $token = '[Channel Access Token]';
  private $secret = '[Channel Secret]';
  private $profile_array = array(); //プロフィールを格納する配列 displayName:表示名 userId:ユーザ識別子 pictureUrl:画像URL statusMessage:ステータスメッセージ
  
  private $replyToken;
  private $userId;
  private $httpClient;
  private $bot;

  function __construct(){

    $json_string = file_get_contents('php://input');
    $jsonObj = json_decode($json_string);
    $this->userId = $jsonObj->{"events"}[0]->{"source"}->{"userId"};
    $this->replyToken = $jsonObj->{"events"}[0]->{"replyToken"};
		
    $this->httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient($this->token);
    $this->bot = new \LINE\LINEBot($this->httpClient, ['channelSecret' => $this->secret]);

    $this->get_profile();

  }

  function get_profile(){

    $response = $this->bot->getProfile($this->userId);

    if ($response->isSucceeded()) {
			
      $profile = $response->getJSONDecodedBody();
      $displayName = $profile['displayName'];
      $userId = $profile['userId'];
      $pictureUrl = $profile['pictureUrl'];
      $statusMessage = $profile['statusMessage'];
      $this->profile_array = array("displayName"=>$displayName,"userId"=>$userId,"pictureUrl"=>$pictureUrl,"statusMessage"=>$statusMessage);
      $this->reply_message();
    }
  }

  function reply_message(){

    $textMessageBuilder = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder($this->profile_array["displayName"]."さんこんにちは！");
    $response = $this->bot->replyMessage($this->replyToken, $textMessageBuilder);	
  }

}
```

#注意事項（※2016/10/25時点）

~~現時点で[API Reference](https://devdocs.line.me/ja/)を参考に実装すると幾つかの不具合が生じます。~~
**修正済 (2016/10/27)**

**Get Profile**のレスポンス取得部分

```php
誤
$profile = decode_json($response->getBody);
正
$profile = json_decode($response->getRawBody());
```
関数のdecode_jsonを[**json_decode**](http://php.net/manual/ja/function.json-decode.php)に変更します。
**getBody**は使えないみたいです、[GitHub](https://github.com/line/line-bot-sdk-php#user-content-response)を参考にするとレスポンスのボディ部分を取得する際にはどうやら**getRawBody**を使用するのが正解みたいです。

#追記（※2016/10/27時点）
[API Reference](https://devdocs.line.me/ja/)に修正がありました。

```php
旧
$profile = decode_json($response->getBody);
新
$profile = $response->getJSONDecodedBody();
```
こちらの**getJSONDecodedBody**を使用する事によりレスポンスボディに対してJSONをデコードした配列で取得できるみたいです。
Excelでもmermaidしたい

[新しく作り直した。リンク](https://qiita.com/WaToI/items/259553b2d6b9eaa8da6f)

[そろそろExcelで資料作るのやめたい](http://qiita.com/tatesuke/items/794a7f97ae217daba25b)

[mermaid.jsが素晴らしいけどなかなか・・・](http://qiita.com/uzuki_aoba/items/a01f8b0b52ced69c8092)

Markdownとかでサクッと書きたい。
でも資料はExcelで提出しないといけない。
だからExcelでmermaidしてみた。

<img width="254" alt="cap1.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/145884/3d50a2ff-2610-4363-30ad-b02148b05611.png">

mermaidをエクセル関数に突っ込むと、
ブラウザが表示される。適当にサイズ調整して
閉じるとキャプチャ画像を貼ってくれる。

<img width="464" alt="cap3.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/145884/b482537b-aea3-2a0e-4dd4-1744d39a44bb.png">

### Usage
1. [xll 32bit※](https://github.com/WaToI/xlMdDna/blob/master/xlMdDna-AddIn-packed.xll)
ダウンロードしてxllを開く(Excelが開く)  
※Excelが64bitなら[xll 64bit](https://github.com/WaToI/xlMdDna/blob/master/xlMdDna-AddIn64-packed.xll)
- セルA1に graph LR   
- セルA2に  HelloWorld  
- 別のセルに=mermaid(A1:A2)
- ブラウザに表示される

[ソースはGitHub](https://github.com/WaToI/xlMdDna)
.Net4.6 C#で作って途中から.Net4.5に下げたが4.6の構文のままコンパイルできた・・・
4.5で動くのだろうか・・・？

ブラウザでmermaid表示までは簡単にできたが、画像化に苦労した。
SVGを直変換したかったが、.NetのXMLパーサがエラーを吐いて無理だった。
Imagemagickに突っ込んでみたら真っ黒Opaqueだった。  
もうスクリーンショットでいいよね。

ついでにganttが描画されない。IEのせいなのか？
phantomならできるんだろうか？
EDGEが使えれば解決するのだが
・・・（　＾ω＾）・・・

---
ライブエディット時にプレビューにコントロールが奪われるので挙動調整。 
プレビューウィンドウ（ブラウザ）は最前面固定にした。
描画サイズ調整もいろいろ試した。
そしてだめだった・・・もう無理だ。