OmniAICreator/Qiita-1.07M huggingface dataset:
[WWDC18]OpenGLとOpenGL ES、OpenCLがdeprecated

<p>いつかその時が来ることは予想されていたが、macOSでOpenGLとOpenCLがdeprecatedとなった。また、iOSでもOpenGL ESがdeprecatedとなった。Metalが推奨されるようになたっということだ。</p>

<p>Khronos GroupからVulkanが発表されたことを考えると時間の問題だったともうが、このタイミングとたった。ただし、推奨されないが使えるので、直ぐに切り替えないとというわけではないが、ゲーム関連のディベロッパーなどは喧喧諤諤としていると思う。</p>

<p>macOSやiOSでMetalとVulkanの関係がどうなるのか予測できない部分もあるが注目していこうと思っている。</p>

●●●

<p>WWDCに行かなかった（行けなかった）、日本残留組の朗報だ！6月15日(金)にWWDC関連の合同勉強会『<a href="https://cocoa-kanto.connpass.com/event/85554/">THe Bash in Tokyo</a>』を開催するので、都合がつく人はぜひ！</p>

【関連情報】
<a href="https://cocoa-kanto.connpass.com/event/85554/">BUKURO.swift 合同勉強会 WWDC18特集！ : The Bash in Tokyo</a><br />
<a href="https://cocoa-kanto.connpass.com/">BUKURO.swift</a><br />
<a href="https://www.facebook.com/groups/cocoa.kanto/">Cocoa勉強会 関東</a><br />
<a href="https://note.mu/mosa_media/m/me339a1d6e3f2">App Engineer Journal "猛者"</a><br />
<a href="https://mosa.connpass.com/">MOSA</a><br />
<a href="http://www.bitz.co.jp/weblog/">Cocoa練習帳</a><br />
<a href="https://qiita.com/m_yukio">Qiita</a><br />
MonoDevelopでペーストできなくなった時の、再起動不要の対処法

MonoDevelopを使用中に文章をペーストできなくなった時の対処法です。
今までは再起動したりしていましたが、再起動は不要です。
Windowsで機能することは確認しましたが、Macでは未確認です。

１．任意のテキストをコピーする
２．MonoDevelopを開き、Ctrl + fを押し、検索ウィンドウを表示する。
３．検索ウィンドウにペーストをする
４．Ctrl + aで検索ウィンドウ内のテキストを全選択し、Ctrl + c(or Ctrl + x)でコピーし、escキーで検索ウィンドウを閉じる
５．MonoDevelopでペーストする。

以上の手順でペーストが可能になります。
一度ペースト可能になるとしばらくは正常にペーストが可能でした。

ショートカットキーのみで説明をし直すと、以下の手順です。

１．Ctrl + c
２．MonoDevelopを開く
３．Ctrl + f
４．Ctrl + v
５．Ctrl + a
６．Ctrl + c(or Ctrl + x)
７．esc
８．Ctrl + v

そもそもペーストできなくなる不具合が解消されればよいのですが。
Virsh をつかって仮想マシンを管理する

> [!NOTE]
> この記事は 2013/08/17 に [momoto.github.io](http://momoto.github.io) へ投稿した内容を Qiita へ移行してきたものです

　[libvirt](https://libvirt.org/drvqemu.html) のコマンドラインツールである `virsh` をつかって、仮想マシンを管理する手引きです。 `virt-install` などで作成した仮想マシンの起動、停止、接続などの操作を行います。

### 仮想マシンの一覧

　`virt-manager`（virt-install を含む）で作成した仮想マシンや、XML ファイルから定義した仮想マシンの一覧を表示します。 オプションを何も付けない場合、シャットオフ状態の仮想マシンは一覧に表示されないので、状態に依らずすべての一覧を得るには `--all` のオプションを付けます。 他のユーザが作成した仮想マシンも一覧には表示されません。

```shell-session:list
$ virsh list --all
 Id    名前                         状態
----------------------------------------------------
 -     ubuntu-13.04                   シャットオフ
 6     centos-6.4                     実行中
```

### 仮想マシンの起動

　定義済みの仮想マシン（libvirtに認識されていてlistに現れる仮想マシン）を起動する場合 `virsh start <仮想マシンの名前>` のコマンドを使います。

```shell-session:start
$ virsh start ubuntu-13.04
ドメイン ubuntu-13.04 が起動されました
```

　未定義の仮想マシンをXMLファイルから定義して、起動する場合 `virsh create <XMLファイル>` のコマンドを使います。

```shell-session:create
$ virsh create centos-6.4.backup.xml
ドメイン centos-6.4 が centos-6.4.backup.xml から作成されました
```

### 仮想マシンのコンソールへ接続する

　実行中の仮想マシンのシリアルポートへコンソール接続するには `virsh console <仮想マシンのIDまたは名前>` をつかいます。

```shell-session:console
$ virsh console 6
ドメイン centos-6.4 に接続しました
エスケープ文字は ^] です

CentOS release 6.4 (Final)
Kernel 2.6.32-358.el6.x86_64 on an x86_64

localhost.localdomain login: 
```

　コンソールへ接続するには、仮想マシンのXMLファイルにシリアルデバイスが定義されていること（ホスト側）と、シリアルポートによる接続が許可されていること（ゲスト側）が必要です。

### 一時停止と再開

```shell-session:suspend
$ virsh suspend 5
ドメイン 5 は一時停止されました

$ virsh resume 5
ドメイン 5 が再開されました
```

### 停止する

　ホスト側から仮想マシンを停止させるには `virsh shutdown` または `virsh destroy` をつかいます。

```shell-session:shutdown
$ virsh shutdown 6
ドメイン 6 はシャットダウン中です

$ virsh destroy 6
ドメイン 6 は強制停止されました
```

### 定義と定義の解除

　仮想マシンの定義を消すには `virsh undefine <仮想マシンの名前>` をつかいます。

```shell-session:undefine
$ virsh undefine ubuntu-13.04
ドメイン ubuntu-13.04 の定義が削除されました
```

　XMLファイルから仮想マシンを定義するには `virsh define <XMLファイル>` をつかいます。

```shell-session:define
$ virsh define ubuntu-13.04.backup.xml
ドメイン ubuntu-13.04 が ubuntu-13.04.backup.xml から定義されました
```

　定義済みの仮想マシンの情報をXML形式で出力するには `virsh dumpxml <仮想マシンのIDまたは名前>` をつかいます。

```shell-session:dumpxml
$ virsh dumpxml ubuntu-13.04 > ubuntu-13.04.backup.xml
```

### 参考

- [Virsh Command Reference](https://libvirt.org/sources/virshcmdref/html-single/)
- [virsh を使ってゲストを管理する – Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/virtualization_administration_guide/chap-virtualization_administration_guide-managing_guests_with_virsh)
- [Managing guests with virsh - Fedora Documentation](https://docs-old.fedoraproject.org/ja-JP/Fedora/13/html/Virtualization_Guide/chap-Virtualization-Managing_guests_with_virsh.html)
- [KVM/Managing – Ubuntu Documentation](https://help.ubuntu.com/community/KVM/Managing)
- [libvirt – ArchWiki](https://wiki.archlinux.org/index.php/Libvirt)
文系のHTM/CSS学習（１）

#0. 前提
これは私が学習したことの備忘録です。大した記述はしていません。

#1. HTML
##1.1 基本文法
テキストをタグ＜＞で囲むことで意味を持たせる。
開始タグ[<]と終了タグ[/>]でテキストを囲む。
コメント（表示されないテキスト）は<!-- -->でテキストを囲む。

```html:qiita.html
<!-- This is a comment-->

<h1>hello,world</h1>
<p>hello,world</p>
```

リストを作成する際に、親要素(ul)で子要素(li)を囲むことを入れ子という
入れ子構造は親子関係が分かりやすいようにインデント（字下げ）を行う

```html:qiita.html
<ul>
  <li>Manners</li>
  <li>Maketh</li>
  <li>Man</li>
</ul>
```

##1.2 よく使うタグ一覧
| タグ | 使用例 | 特徴 |
|:-:|:-:|:-:|
|  h1 |  \<h1>\</h1> | 見出し ブロック要素 |
|  p | \<p>\</p>  |  段落　ブロック要素 |
| a  | \<a href="url">url\</a> | リンク hrefはリンク先のURL |
| img  | \<img src="url" alt="#"> | 画像　srcは画像の場所　altは代替テキスト |
|  li | \<li>\</li> | リスト　\<ul>は黒点　\<ol>は数字 |
ベリサイン 個人用電子証明書 Class1 試用版を試す

> [!NOTE]
> この記事は 2012/07/25 に `seijimomoto.blogspot.com/2012/07/class1.html` へ投稿した内容を Qiita へ移行してきたものです
> 2013 年より "ベリサイン 個人用電子証明書" は "シマンテック 個人用電子証明書" へ名称が変更されました

S/MIME に必要な証明書を、無料で取得できる「ベリサイン 個人用電子証明書 Class1 試用版」を試してみる。証明書は 60 日間有効で、メールアドレスがあれば取得できる。

### 証明書を登録する

https://digitalid.verisign.com/client/enroll.htm から、ブラウザで取得手続きを行う。

#### 1. 使用しているブラウザを選択

![01.png](https://qiita-image-store.s3.amazonaws.com/0/58/ec1db9df-d841-fb46-0f51-ac1eff3ac438.png)

証明書はブラウザ毎の証明書マネージャにインストールされるため、使用しているブラウザを選択しなければならない。

#### 2. 証明書に必要な情報の入力

![02.png](https://qiita-image-store.s3.amazonaws.com/0/58/7481721f-eab9-4392-b40e-b30751e6d6ee.png)

この画面で入力した氏名が、証明書の一般名称（CN）になる。続く、「Choose a Full-service Class 1 Digital ID, or a 60-day Trial Class 1 Digital ID」の項では「I'd like to test drive a 60-day trial Digital ID for free.」を選択し、以降の「Billing Information」の項は無記入のまま進む。

#### 3. メールアドレスのチェック

![03.png](https://qiita-image-store.s3.amazonaws.com/0/58/0b392f80-5a3a-c5ce-8a5e-c6f870262c7a.png)

入力したメールアドレス宛に、VeriSign Customer Support Department からメールが送信されたはずなので、メールの受信を確認する。

#### 4. PINの照合

![04.png](https://qiita-image-store.s3.amazonaws.com/0/58/bdfad6b9-2b5b-fd87-e0c8-0ecce35fe462.png)

メールに記載されている Digital ID PIN を入力する。PIN が照合されると証明書がインストールされる。

#### 5. 証明書のインストール

![05.png](https://qiita-image-store.s3.amazonaws.com/0/58/88230fa5-33e6-661f-cde0-04461d813455.png)

インストールされた証明書は、ブラウザの機能によってPKCS12（.p12）などのファイル形式でエクスポートできる。

### 登録された証明書を照会する

https://digitalid.verisign.com/services/client/index.html から、ブラウザで参照できる。

#### 1. 証明書の検索

![06.png](https://qiita-image-store.s3.amazonaws.com/0/58/c5a2e0a9-9530-ab65-1d63-b43c0dcf733b.png)

氏名、メールアドレスなどの情報からリポジトリに登録されている証明書を検索する。

#### 2. 検索結果から証明書を特定

![07.png](https://qiita-image-store.s3.amazonaws.com/0/58/0ec47787-9a6a-2a13-4dbb-1f5fa30efed3.png)

氏名による検索の場合、同姓同名の証明書を引いてしまうことがあるのでメールアドレスによる検索が推奨されている。

#### 8. 証明書の確認

![08.png](https://qiita-image-store.s3.amazonaws.com/0/58/c6e87a8c-6038-e500-e9f1-04c2be1a2b41.png)

「Download」から他人の個人証明書としてブラウザにインストールすることも可能。

### 参考

- [X.509 - Wikipedia](https://ja.wikipedia.org/wiki/X.509)
PHP で OAuth 1.0 Request を生成する

> [!NOTE]
> この記事は 2012/07/15 に `seijimomoto.blogspot.com/2012/07/oauth-consumer-request-10php.html` へ投稿した内容を Qiita へ移行してきたものです
> この記事で言及されている [OAuth 1.0 Library](https://code.google.com/archive/p/oauth/) は 2014 年から更新されていません。

PHP の [OAuth 1.0 Library](https://code.google.com/archive/p/oauth/) を使用して OAuth Consumer Request を実装します。

処理のおおまかな流れとしては:

1. `OAuthConsumer` クラスと `OAuthSignatureMethod` クラスをインスタンス化する
2. `OAuthConsumer` と `OAuthSignatureMethod` のインスタンスと HTTP リクエスト情報 (URLやパラメータ等) を引数に`OAuthRequest` クラスをインスタンス化する
3. `OAuthRequest` クラスの `sign_request()` メソッドで署名（シグネチャ）を生成する
4. `to_header()` メソッドで `Authorization` ヘッダを生成する

OAuthConsumer のインスタンスは、サービスプロバイダから与えられた Consumer Key ごとに １つあればよいですが、OAuthRequest は API にアクセスする度にインスタンス化します。

Authorization ヘッダを生成した後は、cURL 関数を使用して HTTP リクエストを送信します。

```php5:GET
// OAuthConsumer と OAuthSignatureMethod をインスタンス化する
$consumer_key = "****";
$consumer_sec = "****";

$consumer = new OAuthConsumer($consumer_key, $consumer_sec, null);
$signature = new OAuthSignatureMethod_HMAC_SHA1();

// OAuthRequest をインスタンス化する
$http_method = "GET";
$http_url = "http://example.com/resource";

$req = OAuthRequest::from_consumer_and_token($consumer, null, $http_method, $http_url, null);
$req->sign_request($signature, $consumer, null);
$authorization = $req->to_header();

// cURL で HTTP リクエストを送信する
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $req->to_url());
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array($authorization));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = array(
  "exec" => curl_exec($ch),
  "error" => curl_error($ch)
);
curl_close($ch);
```

もし、GET パラメータがあるならば `$http_url` に `?` で繋げて続けてもよいし、`from_consumer_and_token()` メソッドの5つ目の引数に配列型として渡してもいい（どちらにしてもOAuthRequestのコンストラクタがパースしてBase Stringに含めてくれる）。


```php5:POST
$token = new OAuthToken($oauth_token="******", $oauth_token_secret="******");

$http_method = "POST";
$http_url = "http://example.com/resource";
$parameters = array("foo" => "bar");

$req = OAuthRequest::from_consumer_and_token($consumer, $token, $http_method, $http_url, null);
$req->sign_request($signature, $consumer, $token);
$authorization = $req->to_header();

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $req->to_url());
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($ch, CURLOPT_HTTPHEADER, array($authorization, "Content-Type: application/json; charset=utf-8"));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = array(
  "exec" => curl_exec($ch),
  "error" => curl_error($ch)
);
curl_close($ch);
```

### 参考

- [The OAuth 1.0 Guide « hueniverse](https://hueniverse.com/the-oauth-1-0-guide-32503205267e)
- [oauth - Google Project Hosting](https://code.google.com/archive/p/oauth/)
- [RFC5849 - ietf.org](https://tools.ietf.org/html/rfc5849)
Arch Linux pacman: Public keyring not found

> [!NOTE]
> この記事は 2012/07/05 に `seijimomoto.blogspot.com/2012/07/pacman.html` へ投稿した内容を Qiita へ移行してきたものです

Arch Linux のインストール後、パッケージマネージャの Pacman を使おうとしたら...

![03.png](https://qiita-image-store.s3.amazonaws.com/0/58/c6563c1d-10c3-3e43-a2de-4db0c0467976.png)

```shell-session
warning: Public keyring not found; have you run 'pacman-key --init'?
error: packege_name: key "****************" is unknown
error: key "****************" could not be looked up remotely
```

...というエラーが生じて、パッケージを更新できない。

　Pacman の初期設定では、信頼できる署名がされたパッケージしかインストールできない。
信頼できる署名は `pacman-key` コマンドで管理するため、ひとまずこのコマンドで鍵束を初期化し、その束に開発者たちの鍵を追加しなければ何もインストールできない。

### pacmanキーリングの初期化

　上のエラーで出ている通り、キーリングの初期化は `pacman-key --init` で行う。鍵の生成にはエントロピーが必要とされるため、マウスを動かしたりキーボードを適当に押下する。

![02-01.png](https://qiita-image-store.s3.amazonaws.com/0/58/4f0d5f88-01e5-75ca-f6f5-aedf9112bb59.png)

### 開発者の鍵を追加

　キーリングの初期化をしても信頼のできる署名のリストが空では、パッケージをインストールする度に、次のような出力がでて時間がかかる。

```
:: Import PGP key ********, "hoge hoge <******@archlinux.org>", created YYYY-MM-DD? [Y/n]
```

```
signature from "hoge hoge <******@archlinux.org>" is unknown trust
```

　初期化が終わったら `pacman-key --populate archlinux` コマンドでオフィシャルパッケージ開発者の鍵を追加できる。

### インストールに必要な信頼の度合い

　`/etc/pacman.confのSigLevel` で、インストールに必要な信頼の程度をリポジトリ毎に設定できる。この値に `TrustAll` を設定すると検証は行われなくなるが、これはデバッグのために用意されたもので常時使用することは推奨されていない。初期値の `PackageRequired` や `TrustedOnly` のままにしておいて、必要なパッケージの署名だけキーリングに追加しておくことが望ましい。

## 参考

- [pacman/Package Signing - ArchWiki](https://wiki.archlinux.org/index.php/Pacman/Package_signing)
PHP cURL 関数で POST フィールドに多次元配列とファイルを同時に指定する

> [!NOTE]
> この記事は 2012/02/01 に `seijimomoto.blogspot.com/2012/02/php-curlpost.html` へ投稿した内容を Qiita へ移行してきたものです
> この記事では PHP 5.5.0 以降で有効な `CURLOPT_SAFE_UPLOAD` や `CURLFile` について言及されていません

　PHP がサポートする cURL 関数をつかって POST フィールドに配列データとファイルを同時に指定してリクエストを送信します。

#### POST フィールドにファイルだけを指定する場合

　ファイルを指定するだけであれば、[curl_setopt](http://php.net/manual/en/function.curl-setopt.php) のドキュメントでも説明されているように、先頭に `@` プレフィクスをつけたファイルパスを配列に格納してcURLセッションハンドルのオプションに設定します。

　例えば、フィールド名は "filedata" で `/tmp/hoge.txt` をアップロードしたいときは下のようになります:

```php5:POSTフィールドにファイルだけを指定する
$postfields = array("filedata"=>"@/tmp/hoge.txt;type=text/plain");

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
curl_exec($ch);
```

#### POST フィールドに配列データだけを指定する場合

　上の例とは別に、POST フィールドに配列だけを指定する場合、例えば、フィールド名は "postdata" で配列 `[ 'A', 'B', 'C' ]` を送信するときは...

```php5:Notice-Array-to-string-conversion
$postfields = array("postfields" => array('A', 'B', 'C'));

// Notice:  Array to string conversion
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
```

...とできれば楽ですが `curl_setopt()` に渡す引数が結果的に多次元配列になると NOTICE レベルのメッセージ `Array to string conversion` となり、パラメーターには文字列 "Array" が格納されるため、適当なリクエストになりません。多次元配列を POST パラメーターとして送る場合、PHP の配列を HTTP の POSTパラメーター に割り当てる必要があり、次のような方法があります:

##### 1. 配列データを文字列に書き換えて設定する（http_build_query の要領）

```php5
$postfields = "postdata[0]=A&postdata[1]=B&postdata[2]=C";

curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
```

##### 2. 一次元配列を維持したままフィールド名に添え字を付け加えて設定する

```php5
$postfields = array("postdata[0]"=>'A', "postdata[1]"=>'B', "postdata[2]"=>'C');

curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
```

#### POSTフィールドに多次元配列とファイルを同時に指定する場合

　上の例を併せて、フィールド "filedata" にはファイル `/tmp/hoge.txt` を指定しながら同時に、フィールド "postdata" には配列 `[ "A", "B", "C" ]` を一度に設定したい場合は下のようにすることができます:

```php5
$postfields = array(
    "postdata[0]"=>'A',
    "postdata[1]"=>'B',
    "postdata[2]"=>'C',
    "filedata"=>"@/tmp/hoge.txt;type=text/plain"
);

curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
```

#### 参考

- [RFC2616 - Hypertext Transfer Protocol -- HTTP/1.1 - ietf.rog](https://tools.ietf.org/html/rfc2616)
- [curl_setopt - php.net](http://php.net/manual/ja/function.curl-setopt.php)
- [http_build_query - php.net](http://php.net/manual/ja/function.http-build-query.php)
[AutoHotKey]コンビネーションキーとかでKeyWaitしたい


## 動機
- ループのたびになんか停止して、なんかのキー/マウス入力で進行するスクリプトを書きたい

## KeyWait
- [KeyWait \- AutoHotkey Wiki](http://ahkwiki.net/KeyWait)

基本的にやりたいことはコレ。こっちからの入力を待って進めてくれってこと。

```sample.ahk
Loop, 10 ; 10回繰り返し
{
    Msgbox, , %A_scriptname%, %A_index%回目
    Keywait, RControl ; 右Ctrlを押すと進む
}
Exit
```

ただし、いくつか問題がある。

- コンビネーションキーが使えない
- 複数の選択肢を用意できない

## Input
- [Input \- AutoHotkey Wiki](http://ahkwiki.net/Input)

「複数の選択肢を用意できない」については、`Input`コマンドで対応できなくもない。
`Input, , , abc,`とかね。

どっこい、これだとコンビネーションキーは使えないし、どころかマウス入力さえ使えない。ちゃうねん

## ホットキー
そうなると、トリガーはホットキー（orホットストリング）で作るしかない。
問題は、**`Loop`ブロックの外部にある**ホットキーラベルで、どのように干渉するか。

最初は、`Sleep`とラベルを組み合わせてどうにかならんかと考えた。

```sample.ahk
Loop, 10 ; 10回繰り返し
{
    Msgbox, , %A_scriptname%, %A_index%回目
    Sleep, 300000 ; 適当にスリープ
    Trigger:
}
ExitApp
Rbutton & LButton:: ; マウス右ボタン押しながら左クリック
^j::
    Goto, Trigger
    Return
```

しかし、実行すると「Error:  A Goto/Gosub must not jump into a block that doesn't enclose it.」＝Goto/Gosubでブロック内に飛ぶ場合はそれ自体がブロック内に含まれてないとダメだよーときた。そりゃそうか。

じゃあ`Hotkey`コマンド使ってループ内で動的定義したるわと思ったが、`Sleep`中にホットキーが利かなかった。

```sample.ahk
Loop, 10 ; 10回繰り返し
{
    Msgbox, , %A_scriptname%, %A_index%回目
    hotkey, ^j, cont
    Sleep, 3000 ; 適当にスリープ
    cont:
    Continue
}
ExitApp
```

となると、停止/再開をなんか別の方法で処理する必要がある。

……`Pause`か。

```sample.ahk
Loop, 10 ; 10回繰り返し
{
    Msgbox, , %A_scriptname%, %A_index%回目
    Pause, on ; スクリプトの実行を停止
}
ExitApp
Rbutton & LButton:: ; マウス右ボタン押しながら左クリック
^j::
    Pause, off ; スクリプトの実行を再開
    Return
```

これでいけた。
デザイン自動化メモ（InDesignのテキストフレームの文字数を確認する）

#デザイン結果を確認するとき、文字数チェックは基本ですね。
よくわからないスペースとか、スペースとか、スペースとか、スペースとか。
デザイン重視でとりあえず作ったデータは変なデータが入っていたりします。
とりあえず、文字数カウントして見通しをよくしたいところです。

```js
    pageObj = app.activeDocument.pages[0];
    total = pageObj.allPageItems.length;

    for (i=0;i<total;i++) {
       pageItem = pageObj.allPageItems[i];
       alert(pageItem.contents.length);
    }
```

実行結果
![スクリーンショット 2018-06-10 22.26.09.png](https://qiita-image-store.s3.amazonaws.com/0/139650/99b3bc41-f3b2-0f7d-e981-5de102f4eba1.png)
クラスタリングにおける問題点、注意点

#はじめに
[言語処理のための機械学習入門](https://www.amazon.co.jp/%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E5%85%A5%E9%96%80-%E8%87%AA%E7%84%B6%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E9%AB%98%E6%9D%91-%E5%A4%A7%E4%B9%9F/dp/4339027510)の3.6「クラスタリングの問題点や注意点」を読んで、備忘録としてクラスタリングを扱う自身の研究メモも交えてまとめる。


>[言語処理のための機械学習入門 (自然言語処理シリーズ) ](https://www.amazon.co.jp/%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E5%85%A5%E9%96%80-%E8%87%AA%E7%84%B6%E8%A8%80%E8%AA%9E%E5%87%A6%E7%90%86%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E9%AB%98%E6%9D%91-%E5%A4%A7%E4%B9%9F/dp/4339027510)
　![](http://t2.gstatic.com/images?q=tbn:ANd9GcQAHvqkL5AXWhGIzpmMiMyqwUk3C22hARv7v_ULrT0_Wriu46JM)

#クラスタリングとは
似ているもの同士を同じグループにまとめる処理。
与えられたデータから何らかのモデルや処理手段を導き出す教師なし学習の一種。
データからどんなグループができるかはわからず、できあがったクラスタをみて初めて、クラスタについての類推をすることができる。
>はじめから目的のグループがあり、各データをどのグループに属するかを分ける「分類」とは異なる。

#クラスタリングにおける問題点、注意点

##**問題点**
###**クラスタ数**
クラスタリングは分類と違い、似ているものをグループ化する目的であるため、どの程度まで似ているものを一つのグループにするかにする基準やクラスタ数をいくつにするか、についての一般的な解が存在するわけではない。
クラスタ数を決定する方法として
[最小記述原理などに基づいた方法](https://www.jstage.jst.go.jp/article/jnlp1994/4/2/4_2_71/_article/-char/ja/)が例としてあげられていたが、応用に最適なクラスタ数を常に決定してくれるとは限らない。
実際のところ、タスクやデータに合わせ交差検定などの地道な方法で決めることが多い。

###**結果が初期値に依存する**
k-meansやEMアルゴリズムのような繰り返しに基づくクラスタリング手法では、結果が初期値に大きく依存する。
このような手法では初期値は乱数で決定されることが多く、いくつかの初期値で実験する必要がある。
>自身の研究で利用する手法もEMアルゴリズムを用いたk-meansであるが初期値によっては稀に想像もしないクラスタが出力されてしまったりすることがある。

###**計算時間**
クラスタリングはアルゴリズム中であらゆる組み合わせを検討したり、繰り返し計算をおこなったりするため計算に時間がかかることが多い。
したがって、当然のことながらアルゴリズム中でできる限り計算数を減らすべきである。
繰り返し計算する必要のない式は最初に１回だけ計算をしたり、必要以上に繰り返さないことである。

>また、上述の初期値も計算時間に大きく関わってくる。最初に与えられた初期クラスタが収束に近い状態であったら繰り返し行うことなくすぐに計算が終わるが、適度にバラバラな初期値が与えられた場合、適切なクラスタを作るのには多くの繰り返しの計算が必要になる。

##**注意点**
###**小さな値を扱うときにアンダーフローを起こしやすい**
確立値の掛け合わせをするようなときなど、非常に小さな値を扱う場合アンダーフローを起こしやすいので、それらの値を対数にとった値に変換する。
対数として利用するので掛け合わせるときは足し算でよいが、掛け合わせるときには[logsumexp](https://en.wikipedia.org/wiki/LogSumExp)などというアルゴリズムを用いるなどの工夫が必要になる。

>どうやらpythonのライブラリで直接利用できるみたい。
*logsumexp*
[scipy.misc.logsumexp](https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.logsumexp.html)

###**評価が難しい**
クラスタリングは総じて精度の評価が難しい。
評価の一つとして正解クラスタデータを用意し、実験によるクラスタリングによりどれだけ再現できているかという指標を用いることもある。これは分類の評価指標に近い。
ただし、これらの指標が自分があらかじめ正解データを用意するため、結局自分が期待するクラスタになっているかという側面的な評価になる。
>自身の研究ではNMI(Normalize Mutual Information)を用いてクラスタリング評価をした。日本語では正規化相互情報量と訳され、正解データを用意して結果データとの相互情報量を用いて情報論的に評価する手段である。
実装ではPythonの機械学習ライブラリscikit-learnの[normalized_mutual_info_score](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.normalized_mutual_info_score.html#sklearn.metrics.normalized_mutual_info_score)を利用した。

**この指標が悪くても、別の側面から見れば非常に良いクラスタを作れているかもしれない。**

>これは,クラスタリングを研究する上で非常に大事な心構えかもしれない。
実験による指標が良くなくても失敗と断定してしまわず、一度観点を変えて考えてみることが大事。

**クラスタリングを直接評価するのではなく、獲得したクラスタが別のタスクに役立つことを示すことで間接的にクラスタリングを評価するというのも有効な手段である。**

>定性的な評価としてこちらも重要。結果としてもわかりやすい。

[](先行研究との比較等とは別にクラスタリングを評価する場合は、このような方法も、定性的な評価を行うことができる。)

#**まとめ**
クラスタリングを扱うにあたり、さまざまな点に敏感に考える必要がある。
特に最も一般的なクラスタリング手法k-means においては愚直に計算を行うと計算量はO(N^2)となる。
スケールさせるためには工夫が必要である。(古典的な改善手法では初期値決定にも計算処理を行うk-means++などがある)
ROS2やってみた

# ROS2の勉強始めました
ROS2の勉強でいろいろ検索してみても、記事が少なかったのでしばらくは[ros2の公式](https://github.com/ros2/ros2/wiki)チュートリアルをやって、感想やROS1との比較など書いていこうと思います。
## まずは環境構築
自分の環境は以下の通り
・ThinkPad X260
・ubuntu MATE 16.04

以下はROS2を入れる準備のようなものです。

```
$ sudo apt update && sudo apt install curl
$ curl http://repo.ros2.org/repos.key | sudo apt-key add -
$ sudo sh -c 'echo "deb [arch=amd64,arm64] http://repo.ros2.org/ubuntu/main xenial main" > /etc/apt/sources.list.d/ros2-latest.list'
```


次に、ROS2のパッケージインストールです。

```
$ sudo apt install `apt list "ros-ardent-*" 2> /dev/null | grep "/" | awk -F/ '{print $1}' | grep -v -e ros-ardent-ros1-bridge -e ros-ardent-turtlebot2- | tr "\n" " "`
```

`$ apt install ros-ardent-*`でROS2すべてをインストールできるんですが、
`ros-ardent-ros1-bridge`と`ros-ardent-turtlebot2-*`がどうやらROS1に依存するっぽいので、上記のコマンドでそれらはインストールしないようにするそうです。
もちろん、ROS1とROS2を同じ環境に入れることもできるそうなので、やりたい方はぜひためしてみてください。（僕はROS2だけの環境を作りました。）

以上で環境構築は終了です。
あとは毎回端末を立ち上げた時に以下のコマンドで環境を読み込んでやれば動きますが、めんどくさければ`.bashrc`の一番下に追加しておきましょう。
` source /opt/ros/ardent/setup.bash`

##　最後に
今回は環境を入れただけでまだチュートリアルを試していないので、次回からはチュートリアルの説明とROS1との比較を書いていこうと思います。
gstreamer をソースからビルドする

Ubuntu 16.04 にgstreamer 1.14.1 をソースからビルドしてインストールしてみました。
目的は新しい映像伝送プロトコルのSRTを試すため。

# 準備
必要なライブラリをインストール。

```
sudo apt build-dep gstreamer1.0
sudo apt build-dep gstreamer1.0-plugins-base
sudo apt build-dep gstreamer1.0-plugins-base-apps 
sudo apt build-dep gstreamer1.0-plugins-good
sudo apt build-dep gstreamer1.0-plugins-bad
sudo apt build-dep gstreamer1.0-plugins-bad-videoparsers 
```

[libsrt](https://qiita.com/tetsu_koba/items/92c398abd96c651f4035#libsrt%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E3%81%A8%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)もインストールしておく。

# ソースコードを取得してビルドしてインストール

gstreamer, gst-plugins-base, gst-plugins-good, gst-plugins-bad の順にこれを行う。

```
git clone git://anongit.freedesktop.org/gstreamer/gstreamer
cd gstreamer/
git checkout -b work 1.14.1
./autogen.sh 
make -j4
sudo make install
sudo ldconfig

cd ..
git clone git://anongit.freedesktop.org/gstreamer/gst-plugins-base
cd gst-plugins-base/
git checkout -b work 1.14.1
./autogen.sh 
make -j4
sudo make install
sudo ldconfig

cd ..
git clone git://anongit.freedesktop.org/gstreamer/gst-plugins-good
cd gst-plugins-good/
git checkout -b work 1.14.1
./autogen.sh 
make -j4
sudo make install
sudo ldconfig

cd ..
git clone git://anongit.freedesktop.org/gstreamer/gst-plugins-bad
cd gst-plugins-bad/
git checkout -b work 1.14.1
./autogen.sh 
make -j4
sudo make install
sudo ldconfig

```

#　確認

```
$ which gst-inspect-1.0 
/usr/local/bin/gst-inspect-1.0
$ gst-inspect-1.0 --version
gst-inspect-1.0 version 1.14.1
GStreamer 1.14.1
Unknown package origin
```

srtのエレメントが利用可能になっていることを確認。

```
$ gst-inspect-1.0 |grep srt
subparse: subparse_typefind: srt, sub, mpsub, mdvd, smi, txt, dks, vtt
dtls:  dtlssrtpdec: DTLS-SRTP Decoder
dtls:  dtlssrtpenc: DTLS-SRTP Encoder
dtls:  dtlssrtpdemux: DTLS SRTP Demultiplexer
srt:  srtclientsrc: SRT client source
srt:  srtserversrc: SRT Server source
srt:  srtclientsink: SRT client sink
srt:  srtserversink: SRT server sink
srtp:  srtpenc: SRTP encoder
srtp:  srtpdec: SRTP decoder
subenc:  srtenc: Srt encoder
```
デザイン自動化メモ（InDesignのオブジェクトの上に半透明のボックスをかける）

#無理なオブジェクト配置していないかよく確認したいですよね。
デザインに凝りすぎて、テキストボックスとか適当な大きさで置いていると後からしんどいす。
透明な網をかけていくと、ボックスの重なりが視覚的にわかって、確認がしやすい。

```js
    pageObj = app.activeDocument.pages[0];
    total = pageObj.allPageItems.length;
    for (i=0;i<total;i++) {
       pageItem = pageObj.allPageItems[i];
        
       imgObj = app.activeDocument.pages[0].rectangles.add();
       imgObj.visibleBounds = pageItem.visibleBounds;
       imgObj.fillColor = colorObj;
       imgObj.transparencySettings.blendingSettings.opacity = 40;
    }
```

pageObj.allPageItemsではなく、pageObj.PageItemsにするとグループ化しているオブジェクトが判定外になるので注意。
【Unity】範囲内に収まらないテキストを省略表示する

Unityでは標準機能で"テキストの長さに応じて表示範囲を広げる"ということはできるのですが、デフォルトのUI表示を崩したくないこともしばしばあります。
そこで表示範囲はそのままに、表示範囲を超える長いテキストが入っているときには"テキストが省略されている"ということを伝えられる機能を作りました。

![screenshot.gif](https://qiita-image-store.s3.amazonaws.com/0/58846/b831fc0a-6379-4606-6355-ade7fb93c7f8.gif)


## ソースコード

[【GitHub】TextEllipsis](https://github.com/m4tcha/TextEllipsis)

```c#
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class UITextEllipsis : UIBehaviour
{
    private Text m_Text;

    protected override void Awake()
    {
        if (m_Text != null)
        {
            return;
        }

        m_Text = GetComponent<Text>();
        m_Text.RegisterDirtyLayoutCallback(DoEllipsis);
    }

    protected override void OnDestroy()
    {
        m_Text.UnregisterDirtyLayoutCallback(DoEllipsis);
    }

    private static readonly string ELLIPSIS = "...";

    private void DoEllipsis()
    {
        if (!IsActive() || m_Text == null)
        {
            return;
        }

        if (!NeedsEllipsis(m_Text))
        {
            return;
        }

        TextGenerator generator = m_Text.cachedTextGenerator;
        TextGenerationSettings settings = m_Text.GetGenerationSettings(m_Text.rectTransform.rect.size);
        generator.Populate(m_Text.text, settings);
        string result = string.Empty;
        for (int i = 0; i < generator.characterCount; ++i)
        {
            string current = m_Text.text.Substring(i, 1);
            string next = string.Empty;
            if (i + 1 <= generator.characterCount)
            {
                next = m_Text.text.Substring(i + 1, 1);
            }

            var preferredWidth = GetPreferredWidth(result + current + next);
            if (IsOverSize(m_Text.rectTransform.rect.size.x, preferredWidth))
            {
                result += ELLIPSIS;
                break;
            }

            result += current;
        }

        m_Text.text = result;
    }

    private bool NeedsEllipsis(Text text)
    {
        return IsOverSize(text.rectTransform.rect.size.x, text.preferredWidth);
    }

    private bool IsOverSize(float textBoxWidth, float preferredWidth)
    {
        return textBoxWidth < preferredWidth;
    }

    private float GetPreferredWidth(string str)
    {
        var settings = m_Text.GetGenerationSettings(Vector2.zero);
        return m_Text.cachedTextGeneratorForLayout.GetPreferredWidth(str, settings) / m_Text.pixelsPerUnit;
    }
}
```


## 使い方
Textコンポーネントと一緒にアタッチしておくだけ。

<img width="283" alt="screenshot.png" src="https://qiita-image-store.s3.amazonaws.com/0/58846/910c0c1a-bfa7-eabb-4b33-c09415dd778e.png">



## 実装の解説
アタッチするだけでリアルタイムに処理ができるのは`Graphic.UnregisterDirtyLayoutCallback`のおかげです。こいつにイベントを登録すると、Text.textのsetが呼ばれたタイミングでコールバックを受け取ることができます。便利。

範囲を超えたら〜の部分は、
1. Textの変数としても用意されている`TextGenerator`を利用して文字数を取得
2. 文字数に達するまで1文字目から順番にテキストを形成していく
3. 必要表示範囲を超えたら、1つ前の文字を省略記号(...)に変えて表示させる
となっています。
REGZAをPCから操作

Wake on Lanに対応しているREGZAならWebブラウザで操作できます。

##必要なもの
+ REGZA(58Z10Xなど)
+ LAN環境（WiFiでも可）
+ PC or スマートフォン

##1. IPアドレス固定化
説明書などを参考にREGZAをネットワークに接続します。
自動取得になっているIPアドレスを固定化します。
以下の順にアクセスしてIPアドレス自動取得を「しない」に変更してください。

```
設定 → 初期設定 → ネットワーク設定 → IPアドレス設定
```


表示されたIPアドレスは後ほど使用しますのでメモっておいてください。

##2. Basic認証
レグザAppsコネクト設定でBasic認証を設定します。

```
設定 → 接続機器設定 → 外部連携設定 → レグザAppsコネクト設定
```

##3. リモコンキー
正しく設定されていると以下のURLで操作できます。
Basic認証は先ほど設定した内容で入力してください。

```
http://[固定化したIPアドレス]/remote/remote.htm?key=[value]
```


| ボタン名 | value |
|:-:|:-:|
| 電源  |  40BF12 |
| 音量↑  |40BF1A   |
| 音量↓  | 40BF1E  |
| チャンネル↑ |  40BF1B |
| チャンネル↓ |  40BF1F |
| 1  |  40BF01 |
| ：  | ：  |
| 12  | 40BF0C  |



##謝辞
以下の情報を参考にしました。
その他のボタンのvalueも載っています。

[REGZAをネットワーク越しに操作する - 縁　茶]
(http://misomayo.info/archives/2012041001.html)
HoloLens開発始めてみた

#最初に
インターン先でHololens開発についてまとめる機会があったので自分へのメモも兼ねて投稿します。

基本的にWindows10での開発となります。
Macを使う場合はWindowsをbootするなどの必要があります。
HoloLens Emulatorを使った開発がしたいなら Windows 10 Proが必要。

# 各種ソフトウェアインストール
## VisualStudio2017
CommunityでOK
VisualC#にユニバーサルWindowsがあることを確認しておきます。
>無かったら「ユニバーサルWindowsツールのインストール」と表示されるのでインストールします。

## Unity
お好みのバージョンで構いません。ただし、MRTK（後述）のバージョンと同じものが良いです。
BuildSupportでUWPをONにしておいてください。
今回は2017.2を使用しました。

## MRTK(Mixed Reality Tool Kit)
Unityのバージョンに対応するものを使用。
各バージョンはGitHubのreleaseにまとめられています。
>UnityPackage名は HoloToolKitとなっています。

# サンプル作成
## ProjectとSceneの設定
まず、`メニュー`>`Mixed Reality Tool Kit`>`Configure`>`Apply Mixed Reality Project Settings`を選択し、HoloLens用のプロジェクト設定を行います。チェックはデフォルトのままでOKです。
Sceneについても同様に`Apply Mixed Reality Scene Settings`から行います。
<img width="376" alt="UnityHolo_ProjectSetting(MRTK).jpg" src="https://qiita-image-store.s3.amazonaws.com/0/262329/ad44e21c-80a3-44a5-f530-5129f5a54f67.jpeg">

## カメラの設置
もともとあるカメラを削除し、`Input`>`Prefabs`の中にある`HoloLensCamera`をPosition(x:0 y:0 z:0)に設置します。

## その他に何かオブジェクトを配置
今回は`GameObject`>`3D Object`>`Cube`をPosition(x:0 y:0 z:2)に配置しました。

# ビルド＆実機に転送
## Unity上での Build設定
`Mixed Reality Tool Kit`から`Build Window`を開いて、`Unity C# Projects`にチェック。
<img width="533" alt="UnityHolo_BuildSetting(MRTK)1.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/262329/8bd1780a-d860-87a9-88df-21687e055786.jpeg">


`Deploy Options`からデプロイ先を設定する。
HoloLensをUSB接続する場合は`LocalMachine`のまま、`Username`と`Password`にそれぞれHoloLensのUsernameとPasswordを入力する。
>Wi-Fiでの接続の場合、UsernameとPasswordを入力してから左上の`Pair HoloLens`を選択すると自動で接続されます。

<img width="532" alt="UnityHolo_BuildSetting(MRTK)2.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/262329/4c04b740-e383-2ff6-60da-85590ea60a5f.jpeg">


# 実行結果
無事動きました！（Cubeの位置と向きは少し編集してます）
<img width="541" alt="UnityHolo_DeployResult.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/262329/fbb26656-5668-0c6d-dccd-136de0972979.jpeg">
Google Maps Embed APIを使ってマップを表示する方法

# 概要
* Google Maps Embed APIを使って地図を表示させます
* API KEYさえ取得できればあとはコードを貼り付けるだけ
* なので、Google Maps Embed API KEY取得方法を絵付きで丁寧に説明します

# 手順
1. Google Maps Embed APIキーを取得
2. APIキーの制限を確認
3. 試す

## Google Maps Embed APIキーを取得
* まず[Google Maps Embed API](https://developers.google.com/maps/documentation/embed/guide?hl=ja)のページにアクセスします

[![https://gyazo.com/ceaedd430a3cda4bb4dbaac882ce6075](https://i.gyazo.com/ceaedd430a3cda4bb4dbaac882ce6075.png)](https://gyazo.com/ceaedd430a3cda4bb4dbaac882ce6075)

プロジェクトを作成します。

[![https://gyazo.com/bbfeaf5e0a457f6310bed340734374c4](https://i.gyazo.com/bbfeaf5e0a457f6310bed340734374c4.png)](https://gyazo.com/bbfeaf5e0a457f6310bed340734374c4)

プロジェクト名はなんでもいいです。今回は、`otameshi-map-project`という名称で作りました。

[![https://gyazo.com/d44fae38d691699f16f3874416e37526](https://i.gyazo.com/d44fae38d691699f16f3874416e37526.png)](https://gyazo.com/d44fae38d691699f16f3874416e37526)

__API key__が作成されるので、コピーします。今回は `AIzaSyCcbgwozCTpFwcXnHt1c-HRTHRWqep6Hto` でした。　（いまはプロジェクトを削除しているのでこのAPI KEYは使えません）

[![https://gyazo.com/d0871702c72d158aafde47b151f0abab](https://i.gyazo.com/d0871702c72d158aafde47b151f0abab.png)](https://gyazo.com/d0871702c72d158aafde47b151f0abab)

## APIキーの制限を確認

[console](https://console.developers.google.com/)に移動します。

矢印の箇所を選択して、右下の鉛筆（？）アイコンを押します。


[![https://gyazo.com/0b00170bc3ac4a0301486279a61bf779](https://i.gyazo.com/0b00170bc3ac4a0301486279a61bf779.png)](https://gyazo.com/0b00170bc3ac4a0301486279a61bf779)

APIキーのアプリケーションの制限を確認します。最初は__なし__になっています。これだと、だれでも利用できる状態なので、本番環境で使う場合は、アプリケーションの制限をつける必要があります。例えば、__HTTPリファラー__を選択して、本番環境のURLを指定するといいと思います。

developmentの場合であれば、とりあえず__なし__でいいと思います。（今回は__なし__のままでゆきます）

[![https://gyazo.com/a4f1c3975d2abc8ad8d905ae3fedce9e](https://i.gyazo.com/a4f1c3975d2abc8ad8d905ae3fedce9e.png)](https://gyazo.com/a4f1c3975d2abc8ad8d905ae3fedce9e)


## 試す

test.htmlファイルを作成して、下記のコードを貼り付けます。`<iframe ・・・ </iframe>`の箇所が__Google Maps Embed API__で作成される箇所です。[詳しいフォーマットはこちらのページ](https://developers.google.com/maps/documentation/embed/guide?hl=ja)を見て下さい。


```test.html
<div>
  <h2>大國魂神社の地図</h2>
  <iframe frameborder="0" style="border:0; width: 100%; height: 50vh" src="https://www.google.com/maps/embed/v1/place?key=AIzaSyCcbgwozCTpFwcXnHt1c-HRTHRWqep6Hto&q=大國魂神社"
    allowfullscreen>
  </iframe>
</div>
```

適当なブラウザで開くと下記の様にgoogle mapが表示されます。
[![https://gyazo.com/94154cfe31b5afd63a43d0712b2f2ab7](https://i.gyazo.com/94154cfe31b5afd63a43d0712b2f2ab7.png)](https://gyazo.com/94154cfe31b5afd63a43d0712b2f2ab7)

とても簡単ですね。

2018年6月10日現在、[Google Maps Embed APIは無料](https://developers.google.com/maps/pricing-and-plans/?hl=ja)なのでこれも嬉しい。

以上です。
Laravel5.6 マイグレーション、テーブルを作成する

マイグレーションファイルを作成する

```
php artisan make:migration create_articles_table
```

できたファイルを適宜修正

```php:\database\migrations\2018_06_10_183909_create_article_tables.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->string('title');
            $table->string('body');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}
```

マイグレーションを実行する

```
php artisan migrate
```
Laravel5.6 サンプルデータを作る seeder

seederファイルを作成

```
php artisan make:seeder ArticleSeeder

php artisan make:seeder UserSeeder
```

適宜編集

```php:\database\seeds\UserSeeder.php
<?php

use Illuminate\Database\Seeder;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // テーブル内のデータを一旦全削除
        \Illuminate\Support\Facades\DB::table('users')->truncate();
        
        // データのインサート
        DB::table('users')->insert([
            [
                'name' => '山田 太郎',
                'email' => 'yamada@mail.jp',
                'password' => '',
                'created_at' => '2018-06-10 21:07:31',
                'updated_at' => '2018-06-10 21:07:31'
            ],
            [
                'name' => '鈴木 一郎',
                'email' => 'suzuki@mail.jp',
                'password' => '',
                'created_at' => '2018-06-10 21:07:31',
                'updated_at' => '2018-06-10 21:07:31'
            ],
        ]);
    }
}
```

```php:\database\seeds\ArticleSeeder.php
<?php

use Illuminate\Database\Seeder;

class ArticleSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // テーブル内のデータを一旦全削除
        \Illuminate\Support\Facades\DB::table('article')->truncate();

        // データのインサート
        DB::table('article')->insert([
            [
                'user_id' => 1,
                'title' => 'こんちには',
                'body' => '今日はこんなことがありました。',
                'created_at' => '2018-06-10 21:07:31',
                'updated_at' => '2018-06-10 21:07:31'
            ],
            [
                'user_id' => 2,
                'title' => 'こんちには',
                'body' => '昨日はこんなことがありました。',
                'created_at' => '2018-06-10 21:07:31',
                'updated_at' => '2018-06-10 21:07:31'
            ],
            [
                'user_id' => 3,
                'title' => 'こんちには',
                'body' => '一昨日はこんなことがありました。',
                'created_at' => '2018-06-10 21:07:31',
                'updated_at' => '2018-06-10 21:07:31'
            ]
        ]);
    }
}
```

seederを登録する

```php:\database\seeds\DatabaseSeeder.php
<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            UserSeeder::class,
            ArticleSeeder::class,
        ]);
    }
}
```

seederを実行

```
php artisan db:seed
```

参考サイト
Laravel 5.6 データベース：シーディング
https://readouble.com/laravel/5.6/ja/seeding.html

Laravelでシーダーを使う
https://qiita.com/shosho/items/b69db263a494edfe3b21
DataloaderをDockerコンテナにしました

# はじめに
SalesfroceのDataloaderをDockerコンテナにしました。それだけでは何の役に立ちませんが、今後続けてこのコンテナを使用する記事を書いていきます。

# Dataloaderとは
Salesforceの管理者、開発者にはご存知の、Salesforceからデータのダウンロードやアップロードができるアプリケーションです。SalesforceからWindows,Mac版がダウンロードして使用できます。Linuxでは未サポートですがソースからビルドして動かすこともできます。
データローダーはバッチで動かすこともでき，バッチで動かす記事はたくさんあります．定期的に起動してバックアップするために使用するのはWindowsよりもLinuxの適していると思います．私はDataloaderで定期的にSalesforceのオブジェクトをDBに保存したりしてました．今回はそのもとになるDataloaderをLinuxのDockerコンテナで作ってみました．

# Dockerとは
コンテナというある程度閉じた環境でアプリケーションを動かすことができます。使用するリソースが少ない仮想化環境とでも思ってください。

#Dockerfile
ファイルはGitHubの[okazakiyuji/dataloader](https://github.com/u-z/dataloader.git)を見てみてください．Dockerのイメージはokazakiyuji/dataloader:cent8-DL50.0.0です．

```Dockerfile

FROM centos:8
MAINTAINER okazakiyuji <zaki@mbf.nifty.com>
# DataloaderはビルドするのにJava11が必要
RUN dnf -y update && \
    dnf -y install langpacks-ja git svn which java-11-openjdk java-11-openjdk-devel unzip mysql && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    rm -rf /var/cache/yum/* && yum clean all
ENV LANG="ja_JP.UTF-8" \
    LANGUAGE="ja_JP:ja" \
    LC_ALL="ja_JP.UTF-8"
# make directory
ENV DL_ROOT /opt/dataloader
RUN mkdir -p $DL_ROOT && cd $DL_ROOT && mkdir bin conf data status log
# Build Maven
# Mavenをdnfでインストールするとjava8がインストールされるのでバイナリを使用する
WORKDIR /opt
RUN curl -L -O https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip && \
    unzip apache-maven-3.6.3-bin.zip && \
    mv apache-maven-3.6.3 apache-maven && \
    rm apache-maven-3.6.3-bin.zip
ENV PATH $PATH:/opt/apache-maven/bin
# Build Dataloader
WORKDIR /tmp
# 51.0.1 はビルドできない
ENV DL_VER=50.0.0 \
    DL_FILE=v50.0.0 \
    DL_FOLDER=dataloader-50.0.0
RUN curl -L -O https://github.com/forcedotcom/dataloader/archive/$DL_FILE.zip && \
    unzip $DL_FILE.zip && cd $DL_FOLDER && \
    mvn clean package -DskipTests && \
    mv target/dataloader-$DL_VER-uber.jar $DL_ROOT/bin/ && \
    cp license.txt $DL_ROOT/bin/ && \
    rm -r /tmp/$DL_FOLDER /tmp/$DL_FILE.zip
ENV PATH $PATH:$DL_ROOT/bin
# Install mysql connector
WORKDIR $DL_ROOT/bin/
ENV MYSQL_CON_VER 2.7.2
RUN curl -L -O https://downloads.mariadb.com/Connectors/java/connector-java-$MYSQL_CON_VER/mariadb-java-client-$MYSQL_CON_VER.jar
ENV DATALOADER_CLASSPATH $DL_ROOT/bin/mariadb-java-client-$MYSQL_CON_VER.jar:$DL_ROOT/bin/dataloader-$DL_VER-uber.jar
#
WORKDIR /tmp
```
このDockerfileを簡単に流れを説明すると次のようになっています
1. ベースのイメージをCentOS V8に
2. ロケールの設定
3. yumでアップデートと必要なパッケージのインストール
4. Mavenのバイナリをダウンロード
5. Dataloaderをダウンロード
6. mavenでビルド
7. mariadbのコネクタをインストール(DBに接続しなければ必要ないです)

Docker使える方はご自身でDockerfileを書いて次のように指定していただければこのイメージが使用できます。
`FROM okazakiyuji/dataloader:cent8-DL50.0.0`

#今後

このコンテナイメージの使い方の例は今後の記事で書いていきます。

1. [CVSファイルのダウンロード](https://qiita.com/okazakiyuji/items/0412685dce052853b3c3)
2. ？？？
3. ？？？
Javascriptでの正規表現の後読みの代替

Chrome以外の多くのブラウザでは、正規表現の後読みがサポートされていない(2018/06/10現在)ので、その対処法。
正規表現をあまり知らない高校生が考えたものなので、もっといい方法があればご教示ください。

---
**2018/12/25追記**
以下の例では，普通にsplitを使って取得したほうがよさそうです．

```javascript
str.split("/").filter(s => s.startsWith("Saito ")).map(s => s.split(" ")[1]);
```
や

```javascript
num.split("*").map(s => s.split("^")[0]);
```
のように．
ですので，あまり例を参考にされないようにお願いします．また，正規表現を使おうとする前に，既存のメソッド(sliceなど)を使って書けないか，と考えることも大切だと思います．

---

###肯定後読みの代替

```javascript
const str = "Saito Tsukasa/Sudo Takashi/Saito Shinji/Takeyama Kozo/Ota Hirohisa";
```

の中(トレンディエンジェルとジャングルポケット)から、「Saito」という苗字の人の下の名前を配列で受け取りたい！という状況を考えてみましょう。

肯定後読みがサポートされているなら、

```javascript
const names = str.match(/(?<=Saito )[A-Z][a-z]+/g);
```

のように書けます。これを肯定後読みを使わずに書くと、

```javascript
const names = str.match(/Saito [A-Z][a-z]+/g).map(s => s.slice(6));
```

などとなります。まず、`Saito 〇〇`にマッチさせて、その後`slice`で`Saito`の部分を削る。という方法です。


###否定後読みの代替 その1

次に、先ほどの

```javascript
const str = "Saito Tsukasa/Sudo Takashi/Saito Shinji/Takeyama Kozo/Ota Hirohisa";
```

から、苗字が「Saito」以外の人の下の名前を配列で受け取りたい！という状況を考えましょう。

これも、否定後読みがサポートされているなら、

```javascript
const names = str.match(/(?<!Saito )[A-Z][a-z]+(?! |[a-z])/g);
```

と書けます。これを否定後読みを使わずに書くと、

```javascript
const names = str.match(/[A-Z][a-z]+ [A-Z][a-z]+/g)
  .filter(s => !s.match(/Saito [A-Z][a-z]+/))
  .map(s => s.slice(s.indexOf(' ')+1));
```

などとなります。長ったらしいですが、

1. 全ての名前を配列で受け取る。
2. 「Saito」という苗字の人を弾く。
3. 下の名前だけを`slice`で取り出す。

という方法です。

###否定後読みの代替 その2

今度は

```javascript
const num = "2^3^12*3*13^4";
```

($2^{3^{12}} \times 3 \times 13^4$)から底の数字($2, 3, 13$)だけを取り出したい！という状況を考えましょう。


否定後読みを用いて書くと、

```javascript
const bases = num.match(/(?<!\^|\d)\d+/g);
```

となります。否定後読みを使わずに書くと、荒技ですが、

```javascript
const reverse = s => s.split('').reverse().join('');
const bases = reverse(num).match(/\d+(?!\^|\d)/g)
  .map(s => reverse(s)).reverse();
```

などとなります。何をしたかというと、

1. 文字列を`reverse`して、**後読みを先読みに変える！**
2. 先読みを使いマッチさせる。
3. 配列の中の文字列を`reverse`
4. 配列自体を`reverse`(任意)

この`reverse`を使う方法を用いれば大体代替できますね。(言いたいだけ)
Goにはディレクトリ構成のスタンダードがあるらしい。

# Goにはディレクトリ構成のスタンダードがあるらしい。

[参考URL](https://github.com/golang-standards/project-layout)

上記リポジトリにはGOプロジェクトでのスタンダードとなるディレクトリ構成の説明が書いてある。一つずつ見ていくことにします。

# `/cmd`

一番メインとなるディレクトリ。このディレクトリの中にアプリケーションのエントリーポイントを作る。

```
.
└── cmd
    └── sampleapp
        └── main.go
```

注意点としては`main.go`に多くのことをさせないことである。各処理は基本的に後述する`/pkg`などで実装していくのでそれをインポートする形を取るべきだとある。

# `/internal`

`/cmd`で作ったエントリポイントで使いたいライブラリをおく。だが、このライブラリは各アプリケーション毎に書かれるものとなるので他のアプリケーションと共有するライブラリは置かない。そうゆうのをおくとすれば、後述の`/pkg`に置く。

```
├── cmd
│   └── sampleapp
│       └── main.go
└── internal
    └── apps
        └── sampleapp
            ├── pkg
            │   └── hello.go
            └── print.go
```

今回の例では`hello.go`とか`print.go`みたいなのが入ってあるがほんとはこんな共通化できるようなライブラリは入れてはならないので注意。

# `/pkg`

このディレクトリがおそらく一番ファイルやディレクトリを配置することになるだろう。ここに置くライブラリは必ずどのアプリケーションから利用されてもいいように作成する必要がある。

```
.
├── cmd
│   └── sampleapp
│       └── main.go
├── internal
│   └── apps
│       └── sampleapp
│           ├── pkg
│           │   └── hello.go
│           └── print.go
└── pkg
    └── compute
        ├── add.go
        └── sub.go
```

例では計算用ライブラリを作って見た。その中の`add.go`を見てみる。

```
package compute

func Add(x int, y int) (int) {
  return x + y
}
```

他に依存もしてないし、アプリケーションを選ばないように作った。

# `/vendor`

これは特に考えることはないかと、自分で作ったライブラリを直接ここに置くことはしない。

# `/api`

ここにはSwaggerとかAPIを作成する際のJSONファイルとかを入れる。

```
OpenAPI/Swagger specs, JSON schema files, protocol definition files.
```

# `/web`

webページで使うtemplateとかimageとかcssとか入れとく。

# `/configs`

コンフィグ系のテンプレートを入れとくフォルダ。自分のconfigは指定の配置に入れておこう。

# `/init`

プロセスマネージャーがどうたらこうたら書いてある。使うことはあるのか？

# `/scripts`

`Makefile`みたいなのを配置する。

# `/build`

Dockerfileとか色々配置する様子。`go build`したものはここには入れないのかな？

# `/deployments`

k8sとかのyamlファイルを配置して置くみたい。インフラ関係はここにおこう。

# `/test`

外部テストとかはここにおこう。テストの時に使うデータはここに置いとくと管理がしやしいとかなんとか。

# `/docs`

これは地味に大事、他の人に伝えたい情報などをドキュメント化して置くことは非常に大事なのでこのディレクトリは絶対に配置すべし。

# まとめ

他にも`/examples`とかあったのですが、解説するほどでもないのでまとめに入ります。

ディレクトリ構成はコーディングにも影響を及ぼすので大事です。プロジェクトごとに適切な構成にすることが必要。

```
.
├── cmd
│   └── sampleapp
│       └── main.go
├── configs
│   └── envrc.template
├── docs
│   ├── BUG.md
│   ├── ROUTING.md
│   └── TODO.md
├── internal
│   └── apps
│       └── sampleapp
│           ├── pkg
│           │   └── hello.go
│           └── print.go
├── pkg
│   └── compute
│       ├── add.go
│       └── sub.go
└── scripts
    └── Makefile
```
vital.vimのData.Listにラムダ式が渡せるようになりました！

# まとめ
　[このPR](https://github.com/vim-jp/vital.vim/pull/511)により、
Vim scriptの準標準ライブラリであるvital.vimのData.Listモジュールで、
Funcref（ラムダ式や関数参照）が使用可能になりました！
:tada: :tada: :tada:

- [Add the supports to use Funcref and Data.Closure's {callable} in Data.List by aiya000 - Pull Request #511 - vim-jp/vital.vim - GitHub](https://github.com/vim-jp/vital.vim/pull/511)

Vim scriptでFunctional Programmingを楽しもう！ :dog2:

```vim
let s:L = vital#vital#new().import('Data.List')

let xs = range(0, 50)
let xs = s:L.map(xs, { x ->
    \   (x % 5 == 0) && (x % 3 == 0) ? 'FizzBuzz'
    \ : (x % 5 == 0) ? 'Fizz'
    \ : (x % 3 == 0) ? 'Buzz'
    \                : string(x)
\ })

function! s:p(x) abort
    return a:x ==# 'Fizz'
endfunction

let xs = s:L.filter(xs, function('s:p'))
echo s:L.all(function('s:p'), xs)
" 1
```

# 背景
　Vim8.0でラムダ式がサポートされましたので、
Data.ListがFuncrefに対応する必要がありました。

このPR以前では下記のような、
式を表す文字列を渡すことしかできませんでした。
これはVim scriptの伝統的な方法です。

```vim
let s:L = vital#vital#new().import('Data.List')
echo s:L.map(range(0, 9), 'v:val + 1')
" [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

# 今回の追加で
　下記のように、
Funcref（ラムダ式、関数参照）を使用することができるようになりました！

```vim
let s:L = vital#vital#new().import('Data.List')

function! s:succ(x) abort
    return a:x + 1
endfunction

" ラムダ式
let Succ = { x -> x + 1 }

" 関数参照
let Succ_ = function('s:succ')

let xs = range(0, 9)
echo s:L.map(xs, Succ) == s:L.map(xs, Succ_)
" 1
```

Vim scriptの古き伝統ともおさらば :confetti_ball:

# おまけ
## Data.List.Closure
　vital.vimには、
Vim8.0より前のVimでも関数の部分適用を行うためのData.Closureモジュールが存在します。

今回のPRでは、
Data.ClosureのオブジェクトでData.Listの各関数を使用するためのData.List.Closureモジュールも追加されました。

```vim
let s:V  = vital#vital#new()
let s:C  = s:V.import('Data.Closure')
let s:CL = s:V.import('Data.List.Closure')

function! s:plus(x, y) abort
    return a:x + a:y
endfunction
let plus = s:C.from_funcref(function('s:plus'), [10])

let xs = range(0, 9)
echo s:CL.map(xs, plus)
" [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
```

　Data.List.Closureはパフォーマンスに難があるため、
Data.List内の直接対応は見送られました。

ですので基本的には、
Vim8.0で追加されたclosure付き関数（ラムダ式）
またはfunction関数による部分適用
との組み合わせでData.Listを使用した方がよいでしょう。


# 以上
　Vim scriptでFunctional Programmingを楽しもう！
Data.OptionalとData.Eitherもあるよ！

# @ Milly
　実は本PRは途中で「Vim 7.4のみでVim scriptのパースエラーが起きる」という問題に出くわしていて、
遥かなるだるみによって放置してしまっていました。

そこでその対応をしてくださったのがMillyさんでした。
ありがとうございました！

# 便利なページ

- [vim-jp/vital.vim: A comprehensive Vim utility functions for Vim plugins](https://github.com/vim-jp/vital.vim)
- ドキュメント
    - [Data.List](https://github.com/vim-jp/vital.vim/blob/master/doc/vital/Data/List.txt)
    - [Data.List.Closure](https://github.com/vim-jp/vital.vim/blob/master/doc/vital/Data/List/Closure.txt)
    - [Data.Closure](https://github.com/vim-jp/vital.vim/blob/master/doc/vital/Data/Closure.txt)
    - [Data.Optional](https://github.com/vim-jp/vital.vim/blob/master/doc/vital/Data/Optional.txt)
    - [Data.Either](https://github.com/vim-jp/vital.vim/blob/master/doc/vital/Data/Either.txt)
msys2でrbenvを使うために乗り越えた４つの問題

Windowsでも、Pythonのpyenvのように、Rubyでも仮想環境（実行環境の切り替え）を使えるものだと思ってましたが、Ubuntu同様簡単に使えると高をくくっていた私には意外にハードルが高く、少し手間がかかりました。

（補足）MSYS2を使っているのは個人的な好みです。

## 概要

Windows(MSYS2)でrbenvを使おうとしたら、大きく以下の問題をクリアする必要がありました。

  1. src/realpath.cがコンパイルエラーになる
  1. rbenvにパスが通らない
  1. libexe/rbenv-*を呼び出してくれない
  1. ruby-buildでrubyがビルドできない（未だ原因不明）

## Ubuntu等でのrbenvのインストール方法（ご参考）

普通？は、これでうまくいくはずです。ところが、Windowsではそう甘くありませんでした。

```bash
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ cd ~/.rbenv && src/configure && make -C src
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ ~/.rbenv/plugins/ruby-build/install.sh
```

## 問題１の解決

ダウンロード(git clone)後、`realpath()`が無い様で`make -C src`がエラーになります。

```bash
$ cd ~/.rbenv && src/configure && make -C src
make: ディレクトリ '/home/Taro/.rbenv/src'　に入ります
gcc -fPIC     -c -o realpath.o realpath.c
realpath.c: In function 'realpath_builtin':
realpath.c:18:13: warning: implicit declaration of function 'realpath'; did you mean '_makepath'? [-Wimplicit-function-declaration]
   realbuf = realpath(p, NULL);
             ^~~~~~~~
             _makepath
realpath.c:18:11: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
   realbuf = realpath(p, NULL);
           ^
gcc -shared -Wl,-soname,../libexec/rbenv-realpath.dylib  -o ../libexec/rbenv-realpath.dylib realpath.o
realpath.o:realpath.c:(.text+0x3f): undefined reference to `realpath'
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile:22: ../libexec/rbenv-realpath.dylib] エラー 1
make: ディレクトリ '/home/Taro/.rbenv/src' から出ます
```

`realpath()`を`_fullpath()`に置き換えました。正直、rbenvがどう変わったのかわかりませんが、関数の代替はできているはずです。

```c
--- realpath.c  2018-06-10 10:30:30.460637000 +0900
+++ realpath.c.NEW      2018-06-10 10:33:03.433143400 +0900
@@ -15,7 +15,7 @@ WORD_LIST *list;

        for (es = EXECUTION_SUCCESS; list; list = list->next) {
                p = list->word->word;
-               realbuf = realpath(p, NULL);
+               realbuf = _fullpath(NULL, p,_MAX_PATH);
                if (realbuf == NULL) {
                        es = EXECUTION_FAILURE;
                        // builtin_error("%s: cannot resolve: %s", p, strerror(errno));
```

## 問題２の解決

ビルド後に（パスを通して）、`rbenv`としてもエラーになりました。

```bash
$ ~/.rbenv/bin/rbenv init
.rbenv/bin/rbenv: 行 1: ../libexec/rbenv: No such file or directory
$ file ~/.rbenv/bin/rbenv
.rbenv/bin/rbenv: ASCII text, with no line terminators
$ rm ~/.rbenv/bin/rbenv
$ ln -s ../libexec/rbenv .
```

## 問題３の解決

MSYS2はインストール直後は、シンボリックリンクは使わない設定のようです。シンボリックリンクが使えないと（なぜか）`libexec/rbenv-*`が呼び出せないようです。

`msys64/msys2_shell.cmd`中の記述を変更して、シンボリックリンクを使えるように変更します。

```bash:変更前
rem set MSYS=winsymlinks:nativestrict
```
```bash:変更後
set MSYS=winsymlinks:nativestrict
```

## 問題４の解決

ruby-buildを入れて所望のバージョンをインストールしようとしましたが、エラーになりました。これは原因がわからず断念しました。

[GitHubのoneclick/rubyinstaller2](https://github.com/oneclick/rubyinstaller2/releases)から所望のバージョンの7zファイルをダウンロードして、.rbenv/versions下に解凍して使いました。

## 環境

  * Windows 10 Pro 1803 ビルド17134.48
  * MINGW64_NT-10.0 DESKTOP-NAME 2.10.0(0.325/5/3) 2018-02-09 15:25 x86_64 Msys
  * rbenv 1.1.1-37-g1c772d5
Laravel5.6 インストール

xammpをインストールしてphpをwinに入れる。

xammp
https://www.apachefriends.org/download.html

Composerをインストール。phpを指定するところがあるのでxammpのphpを指定。

Composer
https://getcomposer.org/download/


Laravelをインストール
ここでは、最新の5.6を指定

```
composer create-project "laravel/laravel=5.6.*" appName
```

バージョン確認

```
php artisan --version
```