OmniAICreator/Qiita-1.07M huggingface dataset:
GASを使ってSurfingKeysのInlineQuery機能からGoogle翻訳機能を呼び出す

何ごともキーボードを使う私が愛用する拡張機能のSurfingKeys。こいつさえあればVimライクにブラウザを操作できるわけですがこれにはInlineQueryという機能があります。詳しくは[公式のWiki](https://github.com/brookhong/Surfingkeys/wiki/Register-inline-query)から。

公式Wikiでは、shanbayのAPIを指定してクエリーを投げてレスポンスをポップアップに表示するのですが個人的に使い慣れてるGoogle翻訳をAPIとして使いたい気持ちがありました。
しかしGoogleTranslateAPIは有料でなるべくならクレカの情報も入力したくないので、今回はGAS(GoogleAppsScript)に備わっているLanguageServiceから翻訳機能を呼び出すことで無料でInlineQueryを行います。

今回のゴールはこの機能をつくるだけのでササッと説明します。詳しい話は参考にした記事が分かりやすかったのでそちらを参照(記事の最後に貼っておきます)。

## いじるもの

- GASのエディター

- SurfingKeysの設定

たったこれだけ。

## Google Apps Scriptをいじる

[公式のダッシュボード](https://script.google.com/)から事前にGASのプロジェクトを作成してエディター画面に移動してください。


プロジェクトが作成されたら以下のように記述して保存。

```javascript
function doGet(e) {
    // GETパラメータ
    var p = e.parameter;
    // LanguageServiceをつかって翻訳(text=翻訳したい文、source=翻訳元言語、target=翻訳先言語)
    var translatedText = LanguageApp.translate(p.text, p.source, p.target);
  
    // JSON文字列にする
    var responseText = JSON.stringify(translatedText);
    // ウェブアプリケーションとしてデプロイするときはこれを返り値にしないとだめ
    var out = ContentService.createTextOutput();
    // レスポンスタイプをapplication/jsonにする
    out.setMimeType(ContentService.MimeType.JSON);
    out.setContent(responseText);
  
    return out;
}
```

デプロイまでできたら一応翻訳できてるかブラウザでURL叩いて確認。

## SurfingKeysの設定をいじる
`se`を打つことでSurfingKeysの設定にとびます。
あとはWikiにならって`Front.registerInlineQuery`を以下のように書く。

```
Front.registerInlineQuery({
        // auto -> englishに翻訳
        url: "https://script.google.com/macros/s/XXXXXXXXXXX.../exec?source=ja&target=en&text=",
        parseResult: function(res) {
            try {
                // ダブルクォート削除(こいつも値に含まれるのか…)
                const result = res.text.replace(/[\"]/g,"");
                return `<div>${result}</div>`;
            } catch (e) {
                return "";
            }
        }
    }
);
```

## 結果

`v`でビジュアルモードに入り翻訳したいテキストを選択して`q`を押せばInlineQueryがはしります。

![スクリーンショット 2019-06-11 10.44.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189954/b55590ef-0a38-6199-7528-c046942ee0c8.png)

できた！

より翻訳がはかどりますね（英語の勉強も忘れずにやります）

日本語→英語の翻訳しかできないので、なにかをトリガーにして同時に英語→日本語とかもできるようにしたいですね。

## 参考

- [今から10分ではじめる Google Apps Script(GAS) で Web API公開](https://qiita.com/riversun/items/c924cfe70e16ee3fe3ba)
.swfファイルをローカルで開く

最近(といってもだいぶ前)、Chromeをはじめとした主要ブラウザで、Flashの実行がブロックされてしまうようになってしまいましたね...
今回は、ローカルにある.swfファイルを「Flash Player projector」を使って再生する方法を書きます！

##手順
1. https://www.adobe.com/support/flashplayer/debug_downloads.html へ飛ぶ
2. 出てきたページを下にスクロール、OSにあった「Download the Flash Player projector」をクリック![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331782/3c5dacdb-da7e-ea30-ee4b-48292a7298eb.png)

3. 適当なところへ保存します。
4. あとは再生したい.swfファイルをダウンロードした「flashplayer_xx_sa.exe」へD&Dする
5. これでswfがよみがえる！
複数のpythonがインストールされて'import cv2'が通らない時の対処法

後輩のpcにpython3とopencvを入れたらエラー
内容はこんな感じ

>Traceback (most recent call last):
>File "<stdin>", line 1, in <module>
>ImportError: No module named 'cv'

去年も見た
とか思いながら原因を探ってました

サイトを見るとシンボリックリンクを作成しろらしい...
作ってもエラーは解決されないし...と思ってよく見てみたら

cv2という名前のファイルがない

そりゃエラー起きるわ

#原因と解決法
どうやら先に公式サイトからpython3をインストールしていたことが原因だったらしい


公式サイトでpython3をインストール(パスとかが設定される)
↓
opencvのインストール
↓ 動かない...
homebrewでpython3をインストール(公式サイトのpython3のパスを**上書きしない**)
↓
動かない...(**homebrewのpython3を参照していない**)


ちなみにhomebrewでpython3をインストールしたらcv2が入りました
homebrewでpython3をインストールする方法は説明してくれてます
https://qiita.com/7110/items/1aa5968022373e99ae28

そしてもう１つの問題はパスの設定とかとか
先に公式サイトからpython3をインストールしたから先にパスが作られていて
後からbrewでpython3をインストールしてもパスが通ってないから使えない

ということで
公式サイトのpython3を削除 ⇨ パスとかの削除 ⇨ brewでインストールしてたpython3とかがあれば削除
 ⇨ brewで再インストール
でエラーがとれました

公式サイトからインストールしたpython3と、そのパスの削除とかは説明してくれています
https://peachcle.com/uninstall-python-for-mac/

以上
可変長引数

```go
func hoge(param1, param2 int) {
	sum := param1 + param2
	fmt.Println(sum)
}

func main() {
	hoge(23, 30)
}
```

関数hogeは引数を2つしか受け付けないので、プログラムの途中で引数を増やしたい場合などに対応できない。
そういう時に備えて可変長引数を使う。

中身を展開して確認しながら見ていく。

```go
func hoge(params ...int) {
	fmt.Println(len(params), params)
	for _, param := range params {
		fmt.Println(param)
	}
}
func main() {
	hoge(10, 20)
	// 2 [10 20]
	// 10
	// 20

	hoge(20, 30, 60)
	// 3 [20 30 60]
	// 20
	// 30
	// 60

	hoge()
	// 0 []

	s := []int{1, 2, 3}
	fmt.Println(s) //[1 2 3]

	hoge(s...)
	// 3 [1 2 3]
	// 1
	// 2
	// 3
}
```
`func hoge(params ...int)`のように`...`をつけることで可変長引数を使うことができる。

>【参考】
現役シリコンバレーエンジニアが教えるGo入門(https://www.udemy.com/share/100BhMB0obeFpbTX4=/)
2019-06-11 時点では fzaninotto/Faker で image() を使ってて $faker->image() が false になるよ

see https://github.com/fzaninotto/Faker/issues/1710

SSL Certs の有効期限エラー が起きるよ。 2019-06-11 09:20 JST 現在。

この原因は fzaninotto/Faker が https でリクエストを出してるから。

https://lorempixel.com/g/400/200/ とかで証明書のエラーが確認できるね。

原因は https://github.com/fzaninotto/Faker/blob/master/src/Faker/Provider/Image.php#L33 で `$baseUrl = "https://lorempixel.com/";` として、 `https://lorempixel.com/` と言った具体に https がハードコートされてるから。(リンク先はそのうち更新されるかもね。)

かつ、 https://github.com/fzaninotto/Faker/blob/master/src/Faker/Provider/Image.php#L84 (リンク先は同上) にて、 Options を設定できない実装だから。

こうなると、 SSL Certs の更新を待つのが良いかな。って。

evil な方法としては、 https://github.com/fzaninotto/Faker/blob/master/src/Faker/Provider/Image.php#L33  を各自の vendor 配下で直接修正する方法で一時的バイパスできるよ。

その場合は、 Deploy とかにも気を回してあげねて。たぶん、特殊な対応を入れないといけないので、そこは頑張ろうね。

というメモです。
udemyを利用してみた感想

#udemyを使い始めました
こんにちは2年の日向野邦春です。
まだ正式にはゼミに参加していないのですが投稿させていただきます。


#udemyとは
udemyはオンラインでプログラミング学習ができるコミュニティ学習ツールです。
選んだコースは
[はじめてのPython 少しづつ丁寧に学ぶプログラミング言語Python3のエッセンス](https://www.udemy.com/python-python3/)です。
バックエンドとフロントエンドどちらにしようか悩みましたが、python3の需要が高いと言うことでバックエンドにしました。
セミナーの価格はセールで1400円でした。これでプログラミングが学べるなら安いと思います。
#受講準備
まずANACONDAとJupyter-notebookをインストールして基本的な受講準備はこれで終了です。
#学んでみて
・メリット
　オンラインなのでいつでも勉強できる。
　映像なのでわからない箇所を何度でも見返す事ができる。

・デメリット
　オンラインなのでダラけやすい
　作成者に質問もできるが返答が遅い

通いのプログラミングスクールとは違うのでお尻を叩いてくれる人がいません。なので根気強く勉強していく事が大切だと思います。あとインプットはいくらでもできるのですが、アウトプットをしていかないと覚えられないと実感しました。これについては「プログラミングはコードを書いて覚えろ」とよくブログとかでも書いてありますが、その通りだと思います。

とりあえず、このセミナーを何回か繰り返して他のセミナーも購入してマスターしていきたいと思います。

次回の投稿では実際に自分が書いたコードも載せられればと思います。

できればレクチャーの様子のスクショも掲載したいのですが著作権の観点からご容赦ください。
Windows10 で Hyper-V を有効にする方法(PowerShell)

## はじめに
WSL2とかWindowsTerminalが来るともう少し
使いやすくなりそうなのですがもう少し先なので
備忘録がてら投稿(重要な点のみ記載してます)

## 環境

本記事は以下の環境等を使用しております。

| 環境 | Version |
|:-----|:--------|
| Windows | 10(64bit) |

## 前準備 
管理者としてPowerShellを開く

|スタートメニューを右クリックすると楽です|
|:---|
|![65C57A94-09A7-433E-8692-8945570ABF61.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269640/def9df27-42d6-9b3d-48b8-cf46dfe7e902.png)
|

## Hyper-Vを有効化する
```shell:terminal
$ Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
```
インストール完了後に再起動が必要です

## 最後に
VirtualBoxやVMと共存できないので注意が必要
ifortからgfortranへの移行〜Can't Open included file編~

# 手短に
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251535/80b22c9a-746d-6cfc-3894-d45999e8f407.png" width=40%>

上記のようなフォルダ構成のプロジェクトのコンパイル
``root> ifort -o hoge test00/*.f90 test01/src/*.f90``
だとコンパイルが通るが、
``root> gfortran -o hoge test00/*.f90 test01/src/*.f90``
これだと通らない。

きったない``Makefile``を書いて解決

# 環境
OS:ubuntu 18.04LTS
コンパイラ:gcc 7.4.0

# 解決方法
件の``Makefile``はこちら。(Makeはずぶの素人なのでﾕﾙｼﾃ…)

```Makefile:Makefile

hoge: test00.o test01.o
	gfortran -o hoge test00.o test01.o -g
test00.o: test00/test00.f90 head00
	gfortran -c test00/test00.f90 -o test00.o -g
test01.o: test01/src/test01.f90 head00 test01/head01
	gfortran -c test01/src/test01.f90 -I./test01/ -I./ -o test01.o -g

```
# 原因
``ifort``だと依存関係は明らかにしなくても羅列するだけでよしなにやってくれているらしい
一方で、``gfortran``だと依存関係を1つ１つ書かないといけないらしい

# ちなみに

twitterでわからんって言ってたら、つよつよFortranエンジニアの方から反応をいただきました。
近々Fotran＋CMakeで幸せになる記事を書かれるそうです。（ありがてぇ（五体投地））

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Fortran90+Makefileは、各ソースの依存関係までは自分で定義しないといけないので、結局自力でやる部分が多いうえにgnuでないと使えない(Windowsに持ち出しにくい)けれど<br><br>cmakeであれば、ソースファイルをリストで書くだけで依存関係の解決までやってくれるしコンパイラ/OSに依存しないし最高。</p>&mdash; ねこぜせんぱい (@ijknabla) <a href="https://twitter.com/ijknabla/status/1137682957978628096?ref_src=twsrc%5Etfw">2019年6月9日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
plunkerで真理値表 その5

#概要

plunkerで真理値表やってみた。
nand,nor,notを実装してみた。

#写真

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/6e0ff99b-1741-d798-0958-0b1520e70091.png)

#成果物

https://embed.plnkr.co/ruqtjXnvT7O95qnvGCF9/

以上。
voiceflowのブロックの概要

[2019/06/11]
Voiceflowで使うBlockの用途が分からなかったので、実際に使ってみて概要を整理。
Blockのヘルプにオフィシャルの解説動画があるので、時間がある人はそっちを見たほうが理解が深まると思います。
途中だけど投稿。
[2019/06/21]
userinfo,permission,paymentを更新

## Basic
### Speak
Alexaのターン。Alexaが話すことばを定義します。
声色も選択可能で、ドロップダウンからAmazon Polyで選べる声色を選べます。
また、音声ファイルも流すことができます。
音声ファイルは、URLで指定するか、アップロードします。

### Choice
ユーザーのターン。ユーザーの発話と分岐を定義します。
定義された発話と実際の発話が合致した場合に、関連づいたブロックに処理が移ります。
定義する発話のシノニムも指定できるため、同じ意味の内容をグルーピングすることで発話ゆれを吸収することができます。

## Logic
### Set
変数に値をセットします。
数値でも文字列でも設定可能です。また、計算式の結果を設定することもできます。
しかし、このSetブロックの定義内で計算結果を設定するのは結構しんどかったです。
ポリシーにもよると思いますが、計算結果を設定するのであれば、あとで出てくるCodeブロックを使うことをお勧めします。

### If
変数を使った条件分岐です。
定義方法はSetブロックに近いです。
複数の条件を定義でき、合致する条件に関連づいたブロックに処理が移ります。
条件分岐の数がビジュアルに反映されるので、どれだけ分岐しているのか一目瞭然でわかりやすいです。

### Capture
ユーザーのターン。ユーザーの発話を変数で受け取ります。
質問に対する回答を受け取る器のような使い方が良いと思います。
変数の型を指定する必要があるので、期待する型でユーザーが回答しやすいような設問をしておく工夫が必要です。

### Random
ランダムな分岐を定義します。
ゲームなどでランダムな結果がほしい場合に使えると思います。
また、それとは別に、スキルが呼び出された場合の挨拶などをランダムにすることで、スキルに厚みが出るんじゃあないかなと考えています。

## Advanced
### Intent
ユーザーのターン。定義された発話と実際の発話が合致した場合に、関連づいたブロックに処理が移ります。
事前にスロットを定義しておくことで、スロットを使ったシノニムの定義ができます。
また、Choiceが、前のSpeakブロックのリプライを処理するタイプで複数の分岐を定義できるのに対し、Intentは、前のブロックは不要で会話のスタートにも使えます。ただし、こちらは分岐は定義できず、発話が合致しなければそもそも呼ばれません。（多分）

### Intaraction
ユーザーのターン。定義された発話と実際の発話が合致した場合に、関連づいたブロックに処理が移ります。
ChoiceとIntentとcaptureを合体した感じに近く、スロットを使った発話内容での条件分岐が定義できます。Choiceでは発話の内容を変数に取ることはできませんが、Intaractionでは、発話内のスロット部分を変数に取ることができます。

### Stream
音声ファイルを流すことができます。
わかりにくかったのは「next」「previos」の遷移条件です。
音声ファイルを最後まで聞いた後に「next」には遷移しません。音声ファイルの再生中に「次！」「前！」と発話することで、それぞれ「next」「previos」に関連づいたブロックへ遷移します。

### Integrations
外部サービスとの連携が可能です。
voiceflowが準備しているAPIを使うか、自分でRESTで連携するか選べます。
現時点では、voiceflowが準備しているAPIは少ないですが、これから色々なサービスが続々と実装されそうです。

### Flow
関数定義です。入力パラメータと出力パラメータを定義でき、プロジェクト変数とFlowの変数の関連づけができます。
Flow内の操作は、通常の操作を変わりありません。

### Code
JavaScriptのロジックを書けます。
Setブロックでは、Math等の組み込み関数が使えませんでしたが、こちらでは使えます。
プロジェクト変数も参照することができますが、ちょっとハマったのでメモしておきます。
CanvasのVariablesで宣言した`{name}`という変数を参照する場合、Codeブロックでは`name`と書きます。
`{}`で括ったり、`${}`のようにしてみても参照できませんので気をつけてください。

### Exit
スキルを終了します。

## Visuals
### Card
調査中
### Display
調査中
## User
### User Info
ユーザー情報にアクセスします。
スキルに権限がああるかを確認します。権限があれば、「ユーザー名」「メールアドレス」「電話番号」等にを取得でき、リマインダーや通知の機能を使う事ができます。権限が無い場合は次のPermissionを使う事で、スマホ等のアレクサアプリに各機能の利用許可を促す画面を表示します。
### Permission
ユーザー情報にアクセスするための許可をユーザに促すため、スマホ等のアレクサアプリに各機能の利用許可を促す画面を表示します。
その画面で権限のON/OFFができます。
### Payment
課金機能を設定します。「Alexa Developer Console」のビルドタブの「スキル内商品」に相当します。
日本の課金と同じく「買い切り型」「サブスクリプション型」「消費型」が選択可能です。
しかし、せっかく日本でスキル内課金が可能になりましたが、voiceflowでは、ドル建てでまだアメリカONLYです。
### Cancel Payment
調査中
### Reminder
リマインダーを使えます。使うには上記のPermissionでリマインダー機能に許可を与える必要があります。
リマインダーには、お知らせする経過時間を指定する「タイマー」と、お知らせする日時を指定する「スケジュール」の２種類があります。
リマインダーでお知らせを設定すると、メッセージと共に音楽が流れます。
VScodeでコメントの色だけ変える方法

テーマを変えずにコメントの色を変える方法です。
拡張機能を使う方法と設定を変える方法の2つをご紹介します。


## 拡張機能を使う
下記のルールに従うことで簡易に色を変えることができます。

拡張機能の`Better Comments`をVScodeにインストールする。
>//*<font color="Green"> 緑文字</font> 
>//!<font color="RED"> 赤文字</font> 
>//?<font color="Aqua"> 水色文字</font> 
>//TODO<font color="Orange"> 黄文字</font>
>////~~打消し線~~

[Better Comments](https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments)

[Better Comments使い方 応用](http://baba-s.hatenablog.com/entry/2017/12/21/210800)



## コメント自体の文字色を変える
JSONの設定を書き換えることでコメントの色を一律で任意の色に設定することができます。

設定を開き（Ctrl + ,）、右上の三角の横にある`設定(JSON)を開く`を押すと`settings.json`が開く。
{ }の中の最後に`,`をつけてから下記を追加する。

    "editor.tokenColorCustomizations": {
    "comments": "#FF0000"}

を書き足すとコメントの文字が赤色になる。
`#FF0000`を変えることで任意の色に変更することが可能。
自分好みの色に変えると気分が上がったり、作業効率も上がるかもしれませんね。
下記色見本を参考にお好きな色に変えてみてください。
[色見本](https://www.colordic.org/)



---
テーマを変えてみても、コメントが見づらかったため
色を変えて見やすくた方法をご紹介させて頂きました。
ご覧頂きありがとうございました。
[参考](https://infoteck-life.com/a0306-vscode-comment-color/)
ChromeDriverとChromeバージョン違いで起こるエラー

## 概要
ChromeDriverと、Chromeバージョンが違うとエラー出されます。
## 環境
- Windows10 64bit
- Python 3.7.3
- selenium 3.141.0
- ChromeDriver **76.0.3809.12**
- Chrome バージョン: **75.0.3770.80**（Official Build） （64 ビット）


## 起きたこと
http://chromedriver.chromium.org/getting-started
の"SimpleTest"のコードを実行したら、下記のようなエラーが出る。

"selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 76"
→　このChromeDriverバージョンでは、Chromeバージョン 76しか対応してない。とのこと。

## 原因
エラーメッセージにもあるように、ChromeとChromeDriverのバージョンをあわせる必要があるそうです。

## 対策結果
ChromeDriverのバージョンを変更し直して、再実行すると正常に動きました。
- ChromeDriver **76.0.3809.12** → **75.0.3770.8**


## 備考
ChromeDriverのサイト
http://chromedriver.chromium.org/downloads
に
「Supports Chrome version **　」
のように、Driverが対応しているChromeバージョンが書いてある。

## 参考にさせていただいた記事
https://qiita.com/memakura/items/20a02161fa7e18d8a693
[PHP]関数呼出し引数末尾にカンマを付ける際は気をつけるべし

デバッグメモです。
レアケースかもですが、同じようなエラーに悩む方に届きますように…！

Laravelにて新規フォームを作成中

「よし！ローカル環境実装できた！開発環境に上げて確認するぞ～」

「・・・あれ？？？」

# 1. 開発環境でエラー発生・・・

フォームテストでエラーになってしまいました。
ログも出ない！なんてこともたまにあるのですが今回は幸いにもエラーログを吐いていたので、
出力されたログを確認すると下記のようなエラーが・・・

```laravel-2019-06-03.log
[2019-06-03 19:02:49] development.ERROR: Class App\Http\Requests\HogeHogePost does not exist {"exception":"[object] (ReflectionException(code: 0): Class App\\Http\\Requests\\HogeHogePost does not exist at /xxx/hogehoge.jp/vendor/laravel/framework/src/Illuminate/Routing/RouteSignatureParameters.php:25, ParseError(code: 0): syntax error, unexpected ')' at /xxx/hogehoge.jp/app/Http/Requests/HogeHogePost.php:37)
```

「どうやらHogeHogePostクラスが見つからないよ～」と言われているようです。
クラスが見つからないということなので真っ先にvendor/composer/autoload_classmap.phpファイルの不備を疑い、下記コマンドを叩いてみましたが、結果は変わりませんでした。

```
composer dump-autoload
```

Laravelで新たに名前空間を追加した際は、ここにクラスあるよ！という情報をクラスマップに定義してあげる必要があります。
ですがvendor/composer/フォルダやcomposer.jsonファイルの差分を見て差異がないところを見ると、composerは今回関係ないかもしれない。。。

# 2. クラスマップの問題ではないとすると、問題はソースの方？？？

一旦頭を切り替え、ログに「syntax error, unexpected ')' ～app/Http/Requests/HogeHogePost.php:37 (37行目に構文エラーあるぞ～)」とあったので改めてapp\Http\Requests\HogeHogePost.phpを見てみることにしました。
すると

```php:app\Http\Requests\HogeHogePost.php
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return array_merge(
            $this->nameKanaRules(),
            $this->devidedPhoneNumRules(),
            $this->phoneNumRules(),
            $this->appointTimeRules(),   //カンマ！！！！
        );                               //37行目
    }
```
これかあああああああ

はい、関数呼出し引数の末尾にカンマをつけてしまっていたのが原因ですね

なぜローカル環境ではエラーが出なかったかというとローカル環境と開発環境のPHPバージョンに差異があり、その間に引数末尾のカンマを許容する新機能が追加されたことが原因でした。
(ローカル環境:PHP 7.3.2, 開発環境:PHP 7.2.13)

下記PHP公式のリリースノートです。
https://wiki.php.net/rfc/trailing-comma-function-calls

配列を扱うときの癖で末尾にカンマをつけてしまっていましたが、引数末尾にもカンマを付けられるようになったのは最近だったようです。
PHP歴が浅いこともあり全く気がつきませんでした。

末尾のカンマを取り、無事エラーは発生しなくなりました。(いや〜、本番環境じゃなくてよかった。。。)

```php:app\Http\Requests\HogeHogePost.php
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return array_merge(
            $this->nameKanaRules(),
            $this->devidedPhoneNumRules(),
            $this->phoneNumRules(),
            $this->appointTimeRules()   //エラー解消
        );
    }
```

# 3. まとめ
これまで環境の違いによるエラーに出会うときはほとんどgit管理されていないファイルが原因で起きていたのですが、今回のようにファイルは同一であっても言語のバージョンが異なることでエラーが発生してしまうこともあります。

念のためPHPのリリースノートを一通りチェックしておこうと思います。
nodenvでいつも使うパッケージを自動でインストールする

nodenvを使ってnodeバージョン管理していて、それぞれのバージョンで`npm install -g`しているとこっちのバージョンではパッケージが入っているがこっちのバージョンでは入っていない！というケースが発生したりすることがあると思います。

nodenvでは[nodenv-default-packages](https://github.com/nodenv/nodenv-default-packages)というプラグインを利用することでnodeインストール時に自動的に指定したパッケージをインストールすることができます。

## インストール

プラグインインストール用のディレクトリがなければ作成します。

```bash
mkdir -p "$(nodenv root)/plugins"
```

プラグインをリポジトリからクローンします。

```bash
git clone https://github.com/nodenv/nodenv-default-packages.git "$(nodenv root)/plugins/nodenv-default-packages"
```

## default-packagesファイルの設定

インストールするパッケージ名を記載する`default-packages`を作成します。

```bash
touch $(nodenv root)/default-packages
```

あとはこの`default-packages`ファイルにインストールしたいパッケージ名を記載しておけば`nodenv install`時にそのバージョンのnodeに対してパッケージをグローバルインストールしてくれるようになります。

以下記入例です。パッケージ名は改行で区切って記載します。
バージョン指定もなどもできます。

```default-packages
typescript
parcel-bundler <=1.12.0
# #の行はコメント行
```

ちなみに特定のバージョンにしかインストールされていないコマンドを叩いた場合は以下のようになります。

```bash
bash-3.2$ node -v
v8.10.0

bash-3.2$ parcel
nodenv: parcel: command not found

The `parcel' command exists in these Node versions:
  10.15.3

```

## インストール済みのnodeへのインストール

すでにインストールされているnode対してパッケージインストールを行いたい場合は、以下のようにバージョンを指定して実行します。

```bash
nodenv default-packages install 8.10
```

インストールされているすべてのnodeに対して適用する場合は--allオプションを使用します。

```bash
nodenv default-packages install --all
```
【SAPUI5】コントローラーでよく使うメソッド

##目的
SAPUI5のコントローラーでよく使うメソッドについてまとめます。

##BaseControllerで実装されている処理
※バージョン1.60のテンプレートの場合

テンプレートからアプリを作った場合、共通処理をまとめたBaseControllerというコントローラーが自動的に作られます。BaseControllerはよく使う処理をラッピングしてくれているので、ラッピングされたメソッドを使うことができます。

###Routerを取得
BaseControllerでの定義

```javascript
getRouter : function () {
	return UIComponent.getRouterFor(this);
}
```

コントローラーから呼び出すとき

```javascript
//create画面に遷移
this.getRouter().navTo("create");
//notFound画面を表示
this.getRouter().getTargets().display("notFound");
```

###モデルを取得
BaseControllerでの定義

```javascript
getModel : function (sName) {
	return this.getView().getModel(sName);
}
```

コントローラーから呼び出すとき

```javascript
//ビューモデルを取得
this.getModel("createView");

//デフォルトモデル（主にOData）を取得
this.getModel();
```

###ビューモデルを登録
BaseControllerでの定義

```javascript
setModel : function (oModel, sName) {
	return this.getView().setModel(oModel, sName);
}
```

コントローラーから呼び出すとき

```javascript
var oViewModel = new JSONModel({
		busy : true,
		delay : 0
	});
	
this.setModel(oViewModel, "createView");
```

###i18nのテキストを取得
BaseControllerでの定義

```javascript
getResourceBundle : function () {
	return this.getOwnerComponent().getModel("i18n").getResourceBundle();
}
```

コントローラーから呼び出すとき

```javascript
var sMeesage = this.getResourceBundle().getText("successMessage");
```

##画面項目の操作
###IDを指定して項目（オブジェクト）を取得
```javascript
var oTable = this.byId("table");
```

###項目の値を取得
```javascript
var sName = this.byId("name").getValue();
```

###項目の属性を変更
```javascript
this.byId("edit").setEnabled(true);
```
setXXXで属性を設定、getXXXで属性を取得できる。
詳細は各コントローラーのメソッドを確認
例：[sap.m.Button](https://sapui5.hana.ondemand.com/#/api/sap.m.Button)

##バインドされた値の操作
###バインドされたオブジェクトをJSON形式で取得
```javascript
var oObject = this.getView().getBindingContext().getObject()
```
###バインドされた値をキーを指定して取得
```javascript
var sName = this.getView().getBindingContext().getProperty("Name")

//または
var sName = this.getView().getBindingContext().getObject().Name
```

###バインドされたオブジェクトへのパスを取得
```javascript
var sPath = this.getView().getBindingContext().getPath()

//リターンの例：/SalesOrderSet(5000000001)
```

##イベントパラメータの操作
イベントハンドラメソッドで受け取る、イベントパラメータの操作について。

###イベントを発生させる起因となったコントロールのオブジェクトを取得
例：リストの行が選択されたとき、行にバインドされたコンテキストを取得する

```javascript
onPress : function (oEvent) {
	var studentId = oEvent.getSource().getBindingContext().getProperty("StudentId");
}
```

###イベントに渡されたパラメータを取得する
フィルタに検索条件を入力したときに呼ばれるイベントの例

```javascript
onSearch : function (oEvent) {
	var sQuery = oEvent.getParameter("query");
}
```

[EventはSourceとParameterでできている](https://sapui5.hana.ondemand.com/#/api/sap.ui.base.Event)
ので、基本的にそのどちらかを使うことになると思われます。
【ターミナル改造⑤】便利なcatコマンドを、更に装飾して高機能にしてくれる「bat」コマンドを導入

- 白黒ターミナルを利用する生活が多くなってきた無機質生活に、少々彩りを加えるために奔走する記事第五弾。
- 外観重視による、心身からの効率性の道を、とことん追求し続けた、ここ最近の日常。
- 今回は、内容の表示や連結の際に用いる**catコマンド**を「装飾・更なる視覚化」をしてくれる**batコマンド**を試用していくことにしよう。

## 概要
- Rust製の、ファイルの内容表示や連結が可能なコマンドツール。
- 同様のcatコマンドに比べて、「表示内容の色付け表示・ページング表示」等の、高機能さや便利さを備えている。
- [公式GitHub](https://github.com/Peltoche/lsd)
- [公式日本語ドキュメント](https://github.com/sharkdp/bat/blob/master/doc/README-ja.md)

## 特徴
### ハイライト表示
- ファイル内容の言語に対応したシンタックスハイライトでの表示をしてくれる。

### ページング表示
- catコマンドの全表示とは違い、標準で内容をlessコマンドに出力するため、読みやすいページング表示が可能。

### ファイル連結
- catコマンド同様、出力や複数ファイルの内容を、連結することが可能。

## 作業環境
- Mac OS X 10.13.4
- Homebrew 2.1.4

## インストール

### Mac

- 下記のコマンドをうち、**bat**の利用環境を構築する。
    - **※Homebrew未導入の場合、[こちら](https://brew.sh/index_ja)を参考にインストールする。**

```bash
# brewでbatをインストール
$ brew install bat
```

### Windows
- 下記のコマンドをうち、**bat**の利用環境をchocolateyで構築する。
    - **※Chocolatey未導入の場合、[こちら](https://qiita.com/konta220/items/95b40b4647a737cb51aa)を参考にインストールする。**

```
$ choco install bat
```

### Linux(Debian)
- 下記のコマンドをうち、**bat**の利用環境をdpkgで導入する。
    - **最新のバージョンのインストールの際には、[こちらの一覧](https://github.com/sharkdp/bat/releases)を確認**

```
$ sudo dpkg -i bat_0.11.0_amd64.deb
```

### その他環境
- 上記以外の環境でのインストール方法は、[こちらの公式Github](https://github.com/sharkdp/bat#installation)のインストール欄を参考にする。

## 結果
- 下記、実際の画面。

<img width="563" alt="screen.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/efa9472e-8bb2-5ce0-3ee7-76647fa062d7.png">

- 複数ファイルの表示も可能。

<img width="661" alt="screen2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/3b3a5757-2d8b-bae3-6075-7293362d71a6.png">

- ファイル連結も可能。

<img width="640" alt="screen3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/3f52e738-a36d-495b-5216-fba6c9b07fcd.png">

- テーマ指定での表示も可能

<img width="594" alt="screen4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336499/a02a0129-426f-3e9f-365b-399ab70339d6.png">

## 基本操作
- batの基本操作コマンドとしては、下記。

|内容|コマンド|
|:---:|:---:|
|通常表示|`bat ファイル名`|
|行数のみ表示|`bat -n ファイル名`|
|不可視文字(空白文字等)の可視化|`bat -A ファイル名`|
|内容のみの表示|`bat -p ファイル名`|
|内容のみの表示、ページング無効化|`bat -pp ファイル名`|
|指定範囲行での表示|`bat -r3:7 ファイル名`<br>※1行目からの指定の際は、`bat -r:5`のように省略可能|
|対応言語リストの表示|`bat --list-languages`|
|言語の指定|`bat -l 言語 ファイル名`|
|対応テーマの表示|`bat --list-themes`|
|指定テーマでの表示|`bat --theme テーマ名 ファイル名`|
|ファイル連結|`bat ファイル名 ファイル名 > 結合ファイル名`|
|バージョン確認|`bat -V`|
|ヘルプページ表示|`bat -h`|

## カスタマイズ設定
- batの各種設定をしていく場合は、下記で環境変数として設定する。
    - デフォルトでのテーマ設定は、`~/.bash_profile`等のファイルに、下記を記述する。
        - `export BAT_THEME="テーマ名"`

    - デフォルトでのページャー設定は、`~/.bash_profile`等のファイルに、下記を記述する。
        - `export BAT_PAGER="less -RF"`

## まとめ
- 今回はファイルのハイライト表示ということで、装飾多用による色覚中毒に陥りながら、記事を書く。
- とうとうCLIにも、多彩性を当然のように求めてしまう現代エンジニア。
- 改造欲求は果てしなく続いてしまうと悟ったため、外観設定以外のも探してみることにしよう。

## 参考
- https://github.com/sharkdp/bat  
→公式GitHubです。大変お世話になりました。
- https://github.com/sharkdp/bat/blob/master/doc/README-ja.md  
→batの日本語ドキュメントです。大変お世話になりました。
- https://co.bsnws.net/article/332   
→こちらの記事を参考にしました。大変お世話になりました。
sed 4.7(GNU sed 4.7)適当に和訳

# sed 4.7(GNU sed.4.7)適当に和訳

GNU sed 4.7を適当訳しました。

##訳
https://kuma35.github.io/sed47doc-jp/

##プロジェクト
OmegaTをオフラインで使って訳出しました。
そのOmegaTプロジェクト含めて欲しい人は

https://github.com/kuma35/sed47doc-jp

# 翻訳環境
- Ubuntu 18.04
- OmegaT with JRE
- Web上の翻訳サービス(Google翻訳など)

# 翻訳環境のセットアップ
- githubからプロジェクトをcloneしてくる
- OmegaTをインストールを適当なフォルダに展開
- OmegaTのフォルダに入る
- ./jre/bin/java -jar ./OmegaT.jar --no-team
- OmegaTでcloneしたフォルダ指定

--no-team　オプションを付けないと、何処かのSVNリポジトリに
勝手にプロジェクトを登録して管理しはじめます。
手元のフォルダ構成とかいじったのにナゼか元に戻ってるという
謎な現象は毎回起動時にこの勝手に作ったSVNプロジェクトを
チェックアウトしてくるからなのでした。

#使い方

上記から辿っても、docs/sed.htmlファイルを直接持っていっても構いません。

#著者
文書中を参照下さい。

#ライセンス
文書をご覧ください。

#参照先
[GNU sed online manual  page](https://www.gnu.org/software/sed/manual/)

[HTML compressed (72K gzipped characters)](https://www.gnu.org/software/sed/manual/sed.html.gz) - entirely on one web page.



-
deviseを使ったログイン・サインアップ機能の実装手順について

#1.deviseについて
diviseとは、アプリ作成において、ログイン・サインアップ機能を実装する際に用いられるgemのことをいう。これを使うことによって、比較的簡単にそれらの機能を実装することができる。


#2.deviseの導入
Gemfileの最後の行に以下のような記述をする。

```
gem 'devise'
```
そして、ターミナル上でbundle installを実行する。
※deviseに限らず、gemをインストールする際は、必ずbundle installを実行する。

次に、ターミナル上で以下のコマンドを実行し、deviseの設定用のファイルを作成する

```
$ rails g devise:install
```
これにより、以下のファイルが生成される。
・config/initializers/devise.rb
・config/locales/devise.en.yml


#3.Usersモデルの作成
サインアップする際、アカウントを作成するためのUserモデルを新しく作成する。
ターミナル上で以下のコマンドを実行する。

```
$ rails g devise user
```
※通常のモデル作成であれば、deviseという記述は不要となる。

これにより、以下のファイルが生成される。
・app/models/user.rb
・db/migrate/2014XXXXXXXXXX_devise_create_users.rb
・test/fixtures/users.yml
・test/models/user_test.rb

次に、生成されたマイグレーションファイルを実行する。
ターミナル上で以下のコマンドを実行する。


```
$ rake db:migrate
```
これにより、DB上に新たにusersテーブルが作成される。


#4.未ログイン時とログイン時の画面設定
以下では、未ログイン時では、画面にログインボタンと新規登録ボタンを表示させる。また、ログイン時では、画面にログアウトボタンを表示させる実装を行う。

app/views/layouts/application.html.erb

```html


<header class="header">
    <div class="header__bar row">
      <h1 class="grid-6"><a href="/">ミニブログ</a></h1>
      <% if user_signed_in? %>
        <div class="user_nav grid-6">
          <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
          <a class="post" href="/tweets/new">投稿する</a>
        </div>
      <% else %>
        <div class="grid-6">
          <%= link_to "ログイン", new_user_session_path, class: 'post' %>
          <%= link_to "新規登録", new_user_registration_path, class: 'post' %>
        </div>
      <% end %>
    </div>
  </header>
```
if文を使って、未ログイン時とログイン時の画面表示を変更する処理を記述する。
また、user_signed_in?は、ユーザーがサインインしているかどうか検証するメソッドで、サインインしている場合にはtrueを返し、サインインしていない場合にはfalseを返す処理を行うメソッドである。

#5.リダイレクトの設定

未ログインユーザーが、直接/tweets/newというパスにアクセスした場合、それに対して、ルートパスに遷移するようにリダイレクトの設定を行う。

app/controllers/tweets_controller.rb

```ruby
class TweetsController < ApplicationController

    before_action :move_to_index, except: :index

    def index
      @tweets = Tweet.page(params[:page]).per(5).order("created_at DESC")
    end

    def new
    end

    def create
      Tweet.create(tweet_params)
    end

    private
    def tweet_params
      params.permit(:name, :image, :text)
    end

    def move_to_index
      redirect_to action: :index unless user_signed_in?
    end
```

以上のように、before_actionを最初に記述する理由は、newアクションを動かす前に強制的にindexアクションにリダイレクトをさせるためである。そのため、newアクションよりも前に記述する必要がある。また、except: :indexとすることで、move_to_indexをnewアクションとcreateアクションが作動する前にのみリダイレクトがされるように設定する。

そして、最終行では、before_actionの内容をredirect_toメソッドを使って定義する。今回は、最初に強制的にindexアクションにリダイレクトをさせる内容を定義して、次にunless文を用いて、作動する条件を付与している。unless文は、条件の返り値がfalseだった場合、手前の式を実行する設定になっている。
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　以上
BC用語集１

今まで学んだ中で、よく意味を理解せずに済ました単語や概念をまとめました。
BCに関わらず、セキュリティの話だったりします。

###チェックサム
一般的に、チェックサムとは簡易的な誤り検出に用いられる符号（もしくは検出そのもの）を指す。**これはデータの送信者と受信者の間で何者かがデータを改竄していないかチェックする役目を持つ。**ビットコインコア においては（BC全般？）入力されたアドレスに間違いがある場合にそれを検出するための付加情報と定義され、５１２ビットの公開鍵に1バイトのプレフィックスをつけたものを入力として、**SHA256によるハッシュ値を二回繰り返した値の先頭４バイト**をチェックサムとして利用する。よって、以下の式から求められる。

*SHA256(SHA256(プレフィックス　＋　512ビットの公開鍵))*

###ロギングポリシー

調べたけどわかんないw

どなたかご教授ください。

###テストガバレッジ
全ての実行可能な命令のうちテストで実行された命令の割合。
つまり、**どれだけテストが終わったかを表す。**

###エクスプレッションビルダ
調べたけど、これもよくわからん。

###アノテーション
あるデータに対してメタデータを注釈として記述すること。BCにおいてはトランザクションに対しUNIX時間やサイズを記述し渡すことになる。

###メソッドチェーン
BCに関係ないプログラミング一般の話。javascriptやpythonなんかでメソッドを連鎖的に繋げて処理をしていくこと。

###チェーンコード
送金の度に複数の公開鍵を用いるのが一般的なBTCの取引において、実はこれらの関連を調べ上げることは可能である。これを防ぐために、**チェーンコード**を用いる。仕組みを簡単に説明すると**公開鍵間の関連を推定不能にするために、推定の候補を現実に実行不能なまでの数にする。**そのためにインデックスに256ビットの巨大な乱数を加え、これをハッシュに加えることで、子公開鍵から親公開鍵を推定することを不可能にしている。(これが新しいインデックスとなる。)

*chain_code = h(i,c)*
コードの共通化を意識する ③ コントローラ編

自分がエンジニアバイトをしているところでは週1回Rails勉強会をしています。今回はそのやったところのまとめを残しておきます。
参考書：[現場で使える Ruby on Rails 5速習実践ガイド]
(https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Ruby-Rails-5%E9%80%9F%E7%BF%92%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E5%A0%B4%E5%AF%A7%E5%AD%90/dp/4839962227)

## コントローラの役割
コントローラにはいろいろなコードが書きやすいため、たくさんのコードが集中しやすいです。モデルに書くべきビジネスロジックがコントローラに書かれているなんてことはよくあります。コントローラは受け取ったリクエストに対してレスポンスを返すために、何が必要かをモデルとビューに呼びかけて、レスポンスを作成し返すのが役割です。
然るべき場所にコードを移した後、コントローラには以下のものが残ります。

- アクション群の提供(index、show、new、edit等)
- before_actionやafter_actionのようなアクションの事前、事後のフィルタ群
- paramsに関する処理(ストロングパラメータによる送られた値を安全に受け取れるよう加工等)
- URLの生成に関する処理
- モデルに記述したビジネスロジックの呼び出し
- メールなど、モデル以外のロジックの扱い
- ビューテンプレートのハンドリングやレスポンスそのものの動的作成、リダイレクト先の管理

上記のようなもので似ている部分は共通化をするといいでしょう。**ただし共通化する前にMVCの役割にそった所にコードを書いておくのが前提となります。**

## 共通機能をモジュールで複数のコントローラと共有する
共通化したい機能をモジュールにしてそれぞれのコントローラでincludeして使用する。ただポイントとして**本当に似ているアクションだけを共通化するようにする。**実際の処理の流れが違うものをアクション名が同じなだけで共通化しようとすると、アクション内で条件分岐が行われるなどして、余計に複雑性が上がってしまう。

アクションの中身がほぼ同じといってもコントローラ毎で若干の違いは出てきます。（同じならコントローラを分ける必要がないですから）モジュール内の実装は同じでいいですが、若干の差異を吸収する場所としてコントローラにメソッドとして実装させるのが手としてあります。

## 共通機能を基底クラス(親クラスにもたせる)を作り、持たせる
アクションの追加をするために継承をするのは基本避けるべきでしょう。以下のようなことがあるからです。

- 基底クラスは簡単に外したり、分割できない。結果、一部のコントローラに不要なアクションが存在したり、アクションメソッドのオーバーライド(子クラスが親クラスのメソッドを上書きすること)が起きたりするから。 
- モジュールが必要な時にだけ使用する「追加的存在」であるのに対して、継承における基底クラスとは子クラスがそもそも備えているべき「基本的性質」を表す存在です。継承している全てのクラスが、追加するアクションの性質を持ち合わせているかを網羅するのは難しいからです。

結果としてコントローラの継承では、privateメソッドの実装や、フィルタ定義などのアクション以外の処理を共通化することを行うのがいいでしょう。
１. アクションを実装している通常のコントローラクラス
２. アクションは実装していない、共通処理をかいた基底コントローラクラス

## ApplicationControllerに共通処理を持たせる
ApplicationControllerに共通処理を持たせることですべてのコントローラで使用することができます。

- ログインしているかどうかの判定
- 権限チェックをし、エラーをだす

汎用的に使えそうな処理をprivateメソッドに書いておき呼ばれない限り誤作動に注意しておくといいでしょう。
WordPressをPug + Stylus + TypeScriptで構築

WordPressをPugでかけるという情報を聞いて、ちょうどGulpかけるようになったきたのでついでに構築してみました。

割と良さそうだったので、誰でも使えるようにサンプル置いておきます。

[Githubはこちら](https://github.com/usu-blog/wp-pug)

Githubのソースコードでは使いやすいように`wp-content/themes/my-theme -> src/my-theme`にシンボリックリンク張っていますがいらなければ削除して使用してください。

## How to use
以下の手順でいけるはず...。

```bash
git clone git@github.com:usu-blog/wp-pug.git
cd wp-pug
docker-compose up -d
yarn
yarn start
```

## WordPress
WordPressはDockerComposeで構築しました。
Volumesは、カレントディレクトリにmysqlのデータとwp-content以下を保存してます。

```yml:docker-compose.yml
version: "3"
services:
  wordpress:
    container_name: wordpress
    image: wordpress
    environment:
      VIRTUAL_HOST: test.local
      WORDPRESS_DB_PASSWORD: root
      WORDPRESS_DB_NAME: test-wp
    restart: always
    volumes:
      - ./wp-content:/var/www/html/wp-content/
    ports:
      - "80:80"
    links:
      - mysql
  mysql:
    container_name: mysql
    image: mysql:5.7
    volumes:
      - ./mysql:/var/lib/mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
    restart: always
```

一応バーチャルホスト登録しておきました。

> `VIRTUAL_HOST: test.local`

なので`/etc/hosts`に以下のように保存すれば

```
127.0.0.1       localhost test.local
```
ブラウザで`test.local`でアクセスできます。

## Gulp
Gulp4の書き方は、Gulpっぽく書くのかJSっぽく書くのかという2つの選択肢があるようですが
私は、JSっぽく書くほうがわかりやすくて好きなのでこういう書き方しています。(Gulp超初心者ですが)

```js:gulpfile.js
const gulp = require('gulp')
const rename = require('gulp-rename')
const stylus = require('gulp-stylus')
const pug = require('gulp-pug')
const ts = require('gulp-typescript')
const plumber = require('gulp-plumber') // エラー時の強制終了を防止
const notify = require('gulp-notify') // エラー発生時にデスクトップ通知する

const dist = "./wp-content/themes/my-theme"

// Styles
function styles() {
  return gulp.src('./src/stylus/**/*.styl')
    .pipe(stylus({
      outputStyle: 'compressed',
      'include css': true
      // outputStyle: 'expanded'
    }))
    .pipe(gulp.dest(`${dist}`))
}

// Views
function views() {
  return gulp.src('./src/views/**/*.pug')
    .pipe(plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }))
    .pipe(pug({
      pretty: true
    }))
    .pipe(rename({
      extname: '.php'
    }))
    .pipe(gulp.dest(`${dist}/`))
}

// TypeScript
function typescript(){
  return gulp.src('./src/ts/**/*.ts')
    .pipe(plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }))
    .pipe(ts({
      target: 'ES5',
      noImplicitAny: true,
      outFile: 'dist.js'
    }))
    .pipe(gulp.dest(`${dist}/js/`))
}

// Watch
function watch() {
  gulp.watch('./src/stylus/**/*.styl', styles)
  gulp.watch('./src/views/**/*.pug', views)
  gulp.watch('./src/ts/**/*.ts', typescript)
}

exports.styles = styles;
exports.views = views;
exports.typescript = typescript;
exports.watch = watch;

gulp.task('default', gulp.series(gulp.parallel(styles, views, typescript, watch)));
```

## 最後に
何かうまく動かずエラーが出てたら報告お願いいたします。

それでは、Happy Hacking~😁♪
spf13/cobraで作ったCLIツールのbash/zsh補完スクリプトを自動生成する

# はじめに

GoでCLIツール作るのにフレームワークとして [spf13/cobra](https://github.com/spf13/cobra) が便利なのでよく使ってます。
そんなcobraですが、よく見るとbash/zsh補完スクリプトの自動生成が意外と簡単にできることに気づいたので、やり方を共有しておきます。

# 環境

手元の環境は以下のとおりです。

- macOS 10.14
- zsh 5.3
- bash 3.2
- Go 1.12
- cobra 0.05

# 補完スクリプトを生成するコマンドを生やす

completionというサブコマンドを生やして、その下にさらにbashとzshコマンドを生やします。
イメージとしてはこんなかんじ。ここではコマンド名を `hoge` とします。

```console
hoge completion bash
hoge completion zsh
```

コードはこんなかんじ。

```go
package cmd

import (
	"os"

	"github.com/spf13/cobra"
)

func init() {
	RootCmd.AddCommand(newCompletionCmd())
}

func newCompletionCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "completion",
		Short: "Generates shell completion scripts",
		Run: func(cmd *cobra.Command, args []string) {
			cmd.Help()
		},
	}

	cmd.AddCommand(
		newCompletionBashCmd(),
		newCompletionZshCmd(),
	)

	return cmd
}

func newCompletionBashCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "bash",
		Short: "Generates bash completion scripts",
		Run: func(cmd *cobra.Command, args []string) {
			RootCmd.GenBashCompletion(os.Stdout)
		},
	}

	return cmd
}

func newCompletionZshCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "zsh",
		Short: "Generates zsh completion scripts",
		Run: func(cmd *cobra.Command, args []string) {
			RootCmd.GenZshCompletion(os.Stdout)
		},
	}

	return cmd
}
```

# 補完スクリプトを読み込む

生成されるスクリプト自体は、とりあえず標準出力に垂れ流してあるので、zshならfpathが通ってる適当なところに保存します。
Homebrewでzsh-completionsを使ってる場合、 `/usr/local/share/zsh/site-functions/_hoge` に保存しておけば自動で読み込まれます。

```console
$ hoge completion zsh > /usr/local/share/zsh/site-functions/_hoge
```

普段zsh使ってるのでbashはあんまり良くわかってませんが、Homebrewのbash-completionを使ってる場合は、 `/usr/local/etc/bash_completion.d/hoge` に置いておけば良さそうです。

# HomebrewのFormulaで自動インストールする

CLIツール自体を既にHomebrewで配布している場合は、バイナリのインストール時に自動で補完スクリプトも仕込んであるとうれしいですね。

あらかじめリポジトリにコミットしてあるファイルを配布するだけなら、 単純に `zsh_completion.install` とかでいけるっぽいのです。が、動的に生成したファイルを登録する方法がわからず、ちょっと悩みました。
そういえば `kubectl` もcobraだったなと思い出し、 [kubectlのformula](https://github.com/Homebrew/homebrew-core/blob/5c8b7ec2c39f5801b5c5f1d5c610e599b62c56f2/Formula/kubernetes-cli.rb) を参考に、こんなかんじにしておけば良さそうです。

```ruby
class Hoge < Formula
  desc "Hoge"
  homepage "https://github.com/minamijoyo/hoge"
  url "https://github.com/minamijoyo/hoge/releases/download/v0.0.1/hoge_v0.0.1_darwin_amd64.tar.gz"
  version "0.0.1"
  sha256 "xxxxxx"

  def install
    bin.install "hoge"
    output = Utils.popen_read("#{bin}/hoge completion bash")
    (bash_completion/"hoge").write output
    output = Utils.popen_read("#{bin}/hoge completion zsh")
    (zsh_completion/"_hoge").write output
  end
end
```

# おわりに

cobraのドキュメントを見ると、もうちょっとカスタマイズできるっぽいのですが、まだいろいろ発展途上のようです。

[Generating Zsh Completion for your cobra.Command](https://github.com/spf13/cobra/blob/f2b07da1e2c38d5f12845a4f607e2e1018cbb1f5/zsh_completions.md)

ただTabでサブコマンドや引数の補完が出るだけでも十分快適です。
わりと簡単に実装できてコスパがよいので、cobraで自作のCLIツール作ってる人は補完できるようにしてみるとよいんではなかろうか。
mavenでコマンドラインアプリ作成

# 最小限のMavenプロジェクトを作成
Eclipse(正確にはSTS)でデフォルトのままMavenプロジェクトを作成するとPOMはこんな感じになります。

```xml:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</project>
```

# 適当にクラス作成して...

```java:Main.java
package jp.demo;

public class Main {
	public static void main(String[] args){
		System.out.println("### START ###");
		System.out.println("### END ###");
	}
}
```

# 実行すると...
maven install後、Jarを実行するとマニフェストがないと怒られます。

```:コマンドライン
C:\sts\workspace\simple_maven\target>java -jar test-0.0.1-SNAPSHOT.jar
test-0.0.1-SNAPSHOT.jarにメイン・マニフェスト属性がありません
manifestファイルを生成する
```

# mainClassを指定
そこで以下のようにbuildタグから順にmainClassタグを指定します。
mainClassタグにはパッケージからメインクラスを指定します。

```xml:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>test</groupId>
	<artifactId>test</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<mainClass>jp.demo.Main</mainClass>
						</manifest>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
```

# 再度実行すると...
maven install後、再度実行するとちゃんと正常終了しました。

```:コマンドライン
C:\sts\workspace\simple_maven\target>java -jar test-0.0.1-SNAPSHOT.jar
### START ###
### END ###
```

# こんなエラーが出たら...
- 「ダイヤモンド演算子を使用可能にするには、-source 7以降を使用してください」
- 「ラムダ式を使用可能にするには、-source 8以上を使用してください」

コンパイラのバージョンが低いということですので以下を追加しましょう。

```xml:pom.xml
	<properties>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>
```

# こんなエラーが出たら２...
- POM.xmlの先頭で「Unknown Error」

以下を上記同様にpropertiesに追加しましょう。(maven-jar-plugin 3.1.2のバグのようです。別プロジェクトで出ました。)

```xml:pom.xml
	<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
```

参考：
https://bugs.eclipse.org/bugs/show_bug.cgi?id=547409

# 最終的に
こうなりました。

```xml:pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>test</groupId>
	<artifactId>test</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<mainClass>jp.demo.Main</mainClass>
						</manifest>
					</archive>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
```
キャッシュミス率から考えるペアプログラミング/モブプログラミングの効率性

# ペアプログラミング/モブプログラミングについて

エクストリーム・プログラミング(XP)で提唱されたソフトウェア開発プラクティスであるペアプログラミング(以下ペアプロ)は、2人で1つのPCを用いてプログラミングを行うというものである。近年では3人以上で行うモブプログラミング(以下モブプロ)の話もウェブ上でよく目にするようになった。
ペアプロ/モブプロといえば、よく単純な分業と比較しての開発効率の低下が懸念として挙げられる。その一方で、暗黙知の共有や不具合埋め込み率の低下、実証実験の結果から開発効率はむしろ向上するというメリットが主張されている。

- 参照: [ペアプログラミング - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9A%E3%82%A2%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

# キャッシュミス率からペアプロ/モブプロの効率性を考える

ここでは、キャッシュミス率からペアプロ/モブプロの効率性を考えてみよう。
例えば1行平均30文字で100行のコードを書く事を考えてみる。そして、コードの内容はすべて頭に入っていて、あとは手を動かすだけという状態を考える。文字数にしてみればせいぜい3000文字であり、ゆっくり目のタイピング速度 3文字/秒 だとすれば、最短 1000秒 ≒ 17分 でコードを書き上げられることになる。しかし、現実的にはこのような最短時間でコーディングできることはまず無い。何故か？
その理由は、自分の脳内に無い情報を調査したり検討したりする必要があるからだ。具体的には:

- プログラミング言語の文法を調べる
- 既存のライブラリがないか調べる
- ライブラリの仕様を調べる
- 既存コードの設計方針を調べる
- 自分の書こうとしている関数仕様の細かい部分を調べ直す
- より良い設計はないかと調査したり検討する

などが挙げられる。このような、自分の脳内にない情報が必要になることを、ここではCPUのキャッシュミスに例えることにしよう。

## 問題設定

キャッシュミス率からペアプロ/モブプロの効率性を単純分業時と比較するために、以下の設定を考える。

$T$件のタスクを$N$人で処理するリードタイムを計算する。キャッシュミスが起こらなければ、タスクは $X$ 分/件で実行できるが、キャッシュミスが起こると $L$ 分のロスが発生するとし、一人の開発者は、1件のタスクに付き $p \in [0, 1]$ の確率で独立にキャッシュミスを起こすとする。 

この時、完全分業した場合のタスク完了までのリードタイム $Time_{分業}$は、キャッシュミスを考慮するとタスク一件あたり $(X + Lp)$ 分 かかり、T件をN人で分担するので、

$Time_{分業} = (X + L p) T / N$

と計算できる。

一方、モブプロでのリードタイム $Time_{モブプロ}$ は、N人全員がキャッシュミスを起こした時のみロスが発生するという事にすると、キャッシュミスが起こる確率は $p^N$ に低下するため、タスク一件あたり 平均 $(X + Lp^N)$ 分かかり、T件をN人全員で直列に作業するので、

$Time_{モブプロ} = (X + Lp^N) T$

となる。

## 具体例1: ペアプロ

ペアプロの場合について、実際に計算してみよう。
タスク件数はとりあえず $T = 10$、ペアプロなので $N=2$、タスク粒度は $X = 1$ として、キャッシュミス率は $p = 0.1$ とし、ロスも $L = 10$ 程度とする。
この時、

$Time_{分業} = (1 + 10 * 0.1) * 10 / 2 = 10$
$Time_{モブプロ} = (1 + 10 * 0.1^2) * 10 = 11$

となり、モブプロは若干非効率という結果になってしまった。しかし、その差は10%程度であり、キャッシュミス率の低下により、2人で作業してもそこまで時間はかからないことが分かる。

## 具体例2: モブプロ

ペアプロの条件で人数を $N = 3$に増やしてみると、

$Time_{分業} = (1 + 10 * 0.1) * 10 / 3 ≒ 6.67$
$Time_{モブプロ} = (1 + 10 * 0.1^3) * 10 = 10.1$

となり、若干差が開いてしまった。

## 具体例3: 不慣れなタスクでのモブプロ

今度は、不慣れなタスクでのモブプロを想定してみよう。
上記モブプロの条件から、不慣れなタスクであるためにキャッシュミス率が$p= 0.5$まで上昇し、また、調査工数であるロスも$L = 100$ まで増加すると考えると、

$Time_{分業} = (1 + 100 * 0.5) * 10 / 3 ≒ 170$
$Time_{モブプロ} = (1 + 100 * 0.5^3) * 10 = 135$

となり、モブプロでの大幅な効率改善が得られた。

# まとめ

ペアプロ/モブプロがキャッシュミス率の低減に寄与するとして、リードタイムの短縮につながるかを非常に単純化したモデルで検討してみた。

* 十分にキャッシュミス率が低いか、キャッシュミスが起こってもロスが少ない場合は分業の方が効率的
* 逆に、不慣れなタスクや、新人が既存コードの構造を知らないなど、キャッシュミスが多発したり、ロスが大きいような状況では、ペアプロ/モブプロによりキャッシュミス率を低下させることが有効である。

上記の結果は、不確実な要求や環境の変化に対応するためのアジャイル開発手法においてペアプロ/モブプロがフィットする理由として考えられるのではないだろうか。
また、上のモデルでは表せていないが、ペアプロ/モブプロによって暗黙知が共有され、個々人のキャッシュミス率の低下も期待できると考えられる。
結局ソフトウェア開発でどこに時間がかかるかといえば、キャッシュミス時の調査工数であり、これらを効率的に削減する手法の一つとしてペアプロ/モブプロは積極的に実施していくのが良いのではないだろうか。
TypeScriptの組み込み型関数【Partial, Required,ReadOnly,Pick,Record】

enumに関しても記事も以下のブログで書いています。
ぜひ一読下さい！

- https://in-thepink.com/enum/

# Partial

プロパティを任意化させることができます。

## 一部のプロパティをPartial化する場合

```ts
type Person = {
// ageが任意項目
    age?: number,
    name: string
}

// Partial化している為、必須項目が無くてもコンパイルエラーにならない
const user: Partial<Person> = {age:22}

// Partial化していない為、コンパイルエラーになる
const user2: Person ={age:22}
```

## 全てのプロパティをPartial化する場合

```ts
type Person = {
 age: number,
 name: string
}

// Partial化している為、コンパイルエラーにならない
const user2: Partial<Person> ={}
```

# Required

プロパティを必須化させることができます。
Partialの真逆です。

```ts

type Person {
    name: string,
    age: number
}

const user2: Required<Person> ={age:22,name:"Yamada"}

```

# ReadOnly

プロパティを読み取り専用にし、再代入不可にします。

```ts

type Person = {
    name: string,
    age: number
}


const user: Readonly<Person> = {
    name: "Yamada",
    age: 22
}

// Cannot assign to 'name' because it is a read-only property.
user.name = "Tanaka" 
```

# Pick

定義した型から任意のプロパティを抜き出し、新しい型を作成します。

```ts
type Person = {
    name: string,
    age: number
}

// Person型から"name"プロパティのみを取り出す。
const user: Pick<Person, "name"> = {
    name: "tanaka"
}

// "name"プロパティのみ取り出している為、コンパイルエラーになる。
// Type '{ name: string; age: number; }' is not assignable to type 'Pick<Person, "name">'. 
const user: Pick<Person,"name"> = {
 name: "Yamda",
 age: 22,
}
```

# Record

プロパティを一気にまとめて型定義をすることができる。

```ts
// key名を"Tanaka"と"Yamada"のみ許容する。
type Users = "Tanaka" | "Yamada"

//valueの型付けを行う
type Info = { [key: string]: string }

// keyにUsers,valueにInfoを使用する。
// Infoは配列の為オブジェクトにするとコンパイルエラーになる
const userGroup: Record<Users, Info[]> = {
    Tanaka: [{ city: "Osaka" }, { firstName: "Ichiro" }],
    Yamada:[{city:"Tokyo"}]


// Usersが"Tanaka"|"Yamada"なのでエラーになる。
// "Tanaka"|"Yamada"|"Kato"にすれば使用できる
    Kato:[{city:"Kyoto"}]
}
```

# さいごに

まだまだたくさんの型があるのでどんどん紹介していきます！
型付けって楽しいかも！

### 参考

- https://speakerdeck.com/masashi/number-kansaits-1/?slide=31
- https://nju33.com/note?note=typescript#number_%E5%9E%8B
bridge-utilsをソースからインストールする

特に難しいところは無かったのだが、一般ユーザで `autoconf` しようとすると下記エラーが出力された。


```zsh
 % apt-get source bridge-utils
kure@ubuntu /usr/local/src/bridge-utils-1.5
 % autoconf                                                                                           
autom4te: cannot create autom4te.cache: No such file or directory
```

rootで実施したら普通にいけた

```
ubuntu# autoconf
ubuntu# ./configure
ubuntu# make
ubuntu# make install
ubuntu# brctl -h
Usage: brctl [commands]
commands:
	addbr     	<bridge>		add bridge
	delbr     	<bridge>		delete bridge
	addif     	<bridge> <device>	add interface to bridge
	delif     	<bridge> <device>	delete interface from bridge
	hairpin   	<bridge> <port> {on|off}	turn hairpin on/off
	setageing 	<bridge> <time>		set ageing time
	setbridgeprio	<bridge> <prio>		set bridge priority
	setfd     	<bridge> <time>		set bridge forward delay
	sethello  	<bridge> <time>		set hello time
	setmaxage 	<bridge> <time>		set max message age
	setpathcost	<bridge> <port> <cost>	set path cost
	setportprio	<bridge> <port> <prio>	set port priority
	show      	[ <bridge> ]		show a list of bridges
	showmacs  	<bridge>		show a list of mac addrs
	showstp   	<bridge>		show bridge stp info
	stp       	<bridge> {on|off}	turn stp on/off
```
設問テスト

<変換>
【読み込み】
□データが以下の形式で格納されることを確認する
　□各行は一次元配列に格納される
　□カンマ区きりで、行の個々の要素は２次配列元に格納されること

【データ処理】
グルーピング
□正規表現の定義に従ってラベルの先頭部を抽出されることを確認する
　例）no●_▲_◆　の「no●」の部分
□「no●」の部分一致するラベルは同じ設問集合に格納されること

【変換】

【出力】
□個々の要素に対して接合処理を行うこと
□接合された行の行末に改行符号が付加されることを確認する
□各行がStringで接合されることを確認する
□出力されたファイルは以下の形式であることを確認する
　□UTF-8（BOM付き）
　□ファイル形式：CSV
□ラベルファイル及びローデータファイルと同じディレクトリに以下のファイルが作成されること
　□datamap.csv
　□rawdata.csv
□成功に変換されたデータマップ及びローデータファイルのパスはプロパティにセットされSPSSデータ作成ツールにて取得可能であることを確認する
□変換失敗時、データマップ及びローデータファイルのパス格納用プロパティを""にセットされることを確認する
□SPSSデータ作成ツールで取得したデータマップ及びローデータファイルのパスが””である時、何も処理せずメイン画面を表示させることを確認する

<障害テスト>
①化けた文字列をラベル対応表（ローデータ）ファイルに設定して保存する
②SPSSデータ作成ツールで、以下の設定を行い作成ボタンを押下する
　・回収方法　：CM
　・データマップ／ローデータのファイルパス設定
③ステップ実行で読みこみ処理を確認する

□化けた文字の読み込みでエラーがキャッチされた後、以下の処理が実行される事を確認する
　□ストリームリーダーはクローズされる事を確認する
　□ストリームリーダーに使用されたリソースは解放される事を確認する
　
□発生したエラーはSPSSデータ作成ツールにてハンドリングされることを確認する

<負荷テスト>
通常タイプ
①以下設問タイプを含むCM設問を７９問作成する
　・SA
　・MA
　・FA
　・NU
　・SAMX　
　・MAMX
②全設問を回答したローデータは3500件作成する
　※１行目のみ回答し、以降の行は１行目のコピーとなる
③3500行分の回答データの「モニターID」ダミー6桁数値で埋める
④SPSSデータ作成ツールで、以下の設定を行い作成ボタンを押下する
　・回収方法　：CM
　・データマップ／ローデータのファイルパス設定

負荷
①現状CMから受領した設問データを元に作成可能なCM設問データを作成する
　※現時点作成可能なCM設問タイプは「」シートを参照　
②全設問を回答したローデータは10万件作成する
　※１行目のみ回答し、以降の行は１行目のコピーとなる
③10万行分の回答データの「モニターID」ダミー6桁数値で埋める
④SPSSデータ作成ツールで、以下の設定を行い作成ボタンを押下する
　・回収方法　：CM
　・データマップ／ローデータのファイルパス設定
--------------------- 
作者：weixin_36770774 
来源：CSDN 
原文：https://blog.csdn.net/weixin_36770774/article/details/91402575 
版权声明：本文为博主原创文章，转载请附上博文链接！
[Laravel-admin]ログインしているユーザ情報を取得する

## 概要
Laravelの管理画面用のライブラリである[Laravel-admin](https://laravel-admin.org/docs/)のログインユーザの情報を取得する方法です。
探し方が悪かったのか、ドキュメントを見つけるのに少し手間取ったので忘備録です。
[公式ドキュメント](https://laravel-admin.org/docs/#/en/permission?id=access-control)に記載があります。

## 名前空間の宣言
ファイル上部でLaravel-adminのAdminクラスの名前空間を宣言します。

```php
use Encore\Admin\Facades\Admin;
```

## 関数一覧
その後、Adminクラスから得たいユーザの情報を取得します。

| オブジェクト　|  | 
|:-----------|------------:|:------------:|
| Admin::user() | 現在のユーザーオブジェクトを取得する |
| Admin::user()->id | 現在のユーザーIDを取得する |
| Admin::user()->roles | ユーザーのRoleを取得する |
| Admin::user()->permissions | ユーザーの権限を取得する |
| Admin::user()->isRole('developer') | ユーザーがそのRoleであるかどうか |
| Admin::user()->can('create-post') | ユーザーにその権限があるかどうか |
| Admin::user()->cannot('delete-post') | ユーザーに権限がないかどうか |
| Admin::user()->isAdministrator() | 管理者であるかどうか |
| Admin::user()->inRoles(['editor', 'developer']) | ユーザがRolesのどれかに属するかどうか |

## 確認例

```xxxController.php
use Encore\Admin\Facades\Admin;

class xxxController extends Controller
{
   public function index(Content $content)
   {
      $user = Admin::user()->username;
      dd($user);
   }
}
```

## 最後に
記事に間違いや不明な点があれば遠慮なくご指摘ください。
AsteriskのVoicemailメッセージをODBC経由でMySQLに保存する

# AsteriskのVoicemailメッセージをODBC経由でMySQLに保存する

とりあえず、memo書きなので時期に補足します。

## 環境

- FreeBSD 12.0R
- Asterisk16 16.4.0
- MySQL 5.6

## Asteriskの導入時に注意すること

FreeBSDのPackagesやportsではVoicemailメッセージの保存先にODBCを利用するになっていないため、
portsを利用し、コンパイルオプションを変更して対応する

```/usr/ports/net/asterisk16/Makefile.
# post-configureセクションの最後に追記
post-configure:
        #.........
        @cd ${WRKSRC} && ./menuselect/menuselect --enable ODBC_STORAGE menuselect.makeopts
```

## テーブルの作成

データベースに下記のテーブルを作成する

```
CREATE TABLE `voicemessages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `msgnum` int(11) NOT NULL DEFAULT '0',
  `dir` varchar(80) DEFAULT '',
  `context` varchar(80) DEFAULT '',
  `macrocontext` varchar(80) DEFAULT '',
  `callerid` varchar(40) DEFAULT '',
  `origtime` varchar(40) DEFAULT '',
  `duration` varchar(20) DEFAULT '',
  `mailboxuser` varchar(80) DEFAULT '',
  `mailboxcontext` varchar(80) DEFAULT '',
  `recording` longblob,
  `flag` varchar(128) DEFAULT '',
  `msg_id` varchar(40) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `dir` (`dir`)
) ENGINE=InnoDB;
```

## ODBC向けのMySQL Connectorを導入

```
# pkg install mysql-connector-odbc-unixodbc-mysql56
```

## 各種設定

```/usr/local/etc/odbcinst.ini
[MySQL]
Description=ODBC for MySQL
Driver=/usr/local/lib/libmyodbc5w.so
UsageCount=20004
#Trace=yes
#TraceFile=/tmp/mysql.log
```

```/usr/local/etc/odbc.ini
[asterisk]
; odbcinst.iniの[MySQL]と合わせる
Driver=MySQL
SERVER=127.0.0.1
PORT=3306
DATABASE=asterisk
USER=UserID
PASSWORD=Password
```

```/usr/local/etc/asterisk/res_odbc.conf
[asterisk]
enabled => yes
; odbc.iniの[asterisk]と合わせる
dsn => asterisk
pre-connect => yes
```

```/usr/local/etc/asterisk/voicemail.conf
; res_odbc.confの[asterisk]と合わせる
odbcstorage=asterisk
odbctable=voicemessages
```

## 動作確認

* odbc.iniの設定が出来ていることを確認   
セクション名が表示されればOK

```
# odbcinst -s -q
```

* ODBC経由でMySQLに接続出来ることを確認   
1が返ってくればOKです。上手く接続出来なければ何かしらのエラーが表示されると思います。

```
# echo "select 1" | isql -v asterisk
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> +---------------------+
| 1                   |
+---------------------+
| 1                   |
+---------------------+
SQLRowCount returns 1
1 rows fetched
```