OmniAICreator/Qiita-1.07M huggingface dataset:
HACHIDORIを使ってみる

だいぶ遅刻してしまいました…
前職で投資を教えていたこともあり、
初めは投資のことや今年身に起きたことを書こうと思っていたのですが、
まぁQiitaだし、何かそれっぽいことを書かなきゃだよなぁと。
というわけで、LINE botに手を出すことにしました(急に）

とはいえスキルがあるわけではないし…と考えていたところHACHIDORIを思い出したわけです。HACHIDORIは、誰でも簡単にLINE or FACEBOOKのBotを作れるサービスになってます。

じゃぁ、やってみます〜
#登録する
HACHIDORI
https://hachidori.io/users?logout=true

<img width="1171" alt="スクリーンショット 2018-12-13 16.14.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/317455/73561f47-7e67-b712-b06a-53e197962dfe.png">
まずはささっと登録ですね〜、と同時にLINEdeveloperへの登録も必要です。
デベロッパー登録後にBotの設定も済ませて置く必要があります。

LINEdeveloper
https://developers.line.biz/ja/

<img width="1174" alt="スクリーンショット 2018-12-13 15.21.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/317455/406f994f-26d4-99f7-d7bd-7c6437ceb1a1.png">
HACHIDORIの方でも、動画でどうやればいいか教えてくれます（親切）
登録の流れもスクショに撮りつつ書こうと思ったのですが、
その必要なかったです(親切)

<img width="738" alt="スクリーンショット 2018-12-13 15.25.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/317455/9f386165-d4ec-e667-dc92-7fcb4e94e326.png">
手順通りにBOT設定まで済ませて、ここからBOTをあれこれ作れます

#シナリオはこんな感じ
<img width="976" alt="スクリーンショット 2018-12-13 16.25.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/317455/adfd8539-8baf-bc88-793e-57c5e3edcecd.png">
シナリオから、ユーザーのアクションに対してのBOTのアクション、それから条件分岐、クエリを使ってユーザーの発言に応じたBOTのアクションとまぁ色々できそうです。

<img width="710" alt="スクリーンショット 2018-12-13 16.29.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/317455/08df475b-4031-df85-ea7c-2b89ce512264.png">
BOTの反応も簡単に設定できるようになってて便利。
<img width="337" alt="スクリーンショット 2018-12-13 18.17.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/317455/386aeb99-e0bd-f850-8a68-2c033b06b9df.png">

;userinfo_longitude;;userinfo_latitude;　やら色々あるのでいろんなユーザー情報得ることができそうです。

<img width="1433" alt="スクリーンショット 2018-12-13 17.12.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/317455/cff190e6-7671-4cc9-f882-b347f8f6dffa.png">
選択による分岐。
本当はシナリオを一通り作ったんですが、保存するのを忘れていて全部消えてしまいました笑 (勝手に自動保存されると思い込んでました)
というわけでこんな感じで作れるよ〜という記事に路線変更してお届けしました。悲しい。
<img width="414" alt="IMG_2962.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/317455/9ef5abb6-f4e3-35fe-bbbd-b9e818a00050.png">
LINEで見てみると、こんな感じで出来上がりですね〜
<img width="414" alt="IMG_2963.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/317455/1cff29aa-43c3-9791-fbec-7aab671a824d.png">
クエリを使ってのアクションです。結構強引ですね。

#感想
思っていたよりもかなり簡単に作れました。短時間でこれだけ簡単にできるので、時間かければもっと色んな機能つけたBotが作れそうですね〜！
というわけで、サクッと作ってみたい人はぜひ試して見てはどうでしょうか。
Gitから.DS_Storeを外そう（Gitデフォルトのignoreファイルの場所はこちら）

# はじめに

MacでGitを利用すると必ず邪魔をしてくる `.DS_Store` さん。
Finderでの表示設定をディレクトリごとに保持してくれてるそうだが、正直いらぬ。

# Gitの設定

この問題はMacのみで起きることなので、プロジェクト全体の `.gitignore` に含めるのは不適切（という声もある）らしい。

そこでよく使われるものがいわゆる `.gitignore_global` 。
よく見る設定方法が、

1. home直下に `.gitignore_global` なるファイルを作る
2. そこに `.DS_Store` と書く
3. Gitコマンドでこのファイルをglobal設定をする

という方法。
これでもじゅうぶんだが、実は3番目の「コマンド打ってglobal設定」はしなくても済む。

このコマンドは、自分でglobalなignoreファイルを指定するという方法。

```:~/.gitconfig
[core]
  excludesfile = /Users/your_user_name/.gitignore_global
```

gitの設定ファイルにはこう書かれる。

# デフォルトのignoreの場所

だがGitには、デフォルトでignoreファイルを見てくれる場所が存在する。

それがこの場所

```
~/.config/git/ignore
```

（なければ作ってね）

このファイルにglobalで除外したいファイルを書いておくと、自動で除外してくれる。
`.DS_Store` を除外したいのならば、

```:~/.config/git/ignore
.DS_Store
```

このように書けばいい。

Gitデフォルトの場所なので、コマンドを打ってこのファイルを指定する必要はない。

# 終わり
設定項目を無駄に増やしたくない人へ捧ぐ（そんな人いるかはわからないが）。


# おまけ
なぜデフォルトの設定場所ではなく `.gitignore_global` が広まったかというと、SourceTreeがこのファイルを使っているからじゃないかなと思う。
正直どちらでも振る舞いに差はないので、好きな方を選んで快適なGitライフを送ろう。

そもそも `.DS_Store` が作られないようにするなら[こちらのサイト](https://uxmilk.jp/48160)が参考になります。
3プラットフォームに「ほげほげ」と話しかけた場合の謝るメッセージ一覧

ごきげんよう

この記事は
**「するめごはんのVUI・スマートスピーカー Advent Calendar 2018」**
の15日目の記事です。


先日、某イベントでこんなような会話がありました。

Aさん「～～～で、大丈夫ですか？」
僕「おっけーぐーぐる！」
Aさん「わかりませんでした。すみませんｗ」
僕「それはAlexaだろうが！ｗ」


というわけで、VUIのスキルやアプリ作成時のエラーメッセージはバリエーションを持たせると機械っぽさが低減されて良いです。

なので、3プラットフォームに**「ほげほげ」(hogehoge)**と呼びかけた時、どういう返答をするかまとめました。
謝る系で、発見できたワードのみ掲載です。

これをどうでもいいと思うか、ユーザビリティと思うかは、その人次第です。


#Alexa、ほげほげ

1. うまく答えられません、ごめんなさい。
2. わかりません、ごめんなさい。
3. わかりませんでした、すみません。
4. ごめんなさい、ちょっとわかりませんでした。
5. すみません、ちょっと難しいです。
6. すみません、よくわかりません。
7. ちょっとよくわからなかったです。ごめんなさい。
8. ちょっと難しいです。ごめんなさい。
9. ごめんなさい、今はわかりません。
10. すみません、わかりませんでした。


#Clova、ほげほげ

1. すみません、わかりませんでした。
2. すみません、よくわかりませんでした。

※
たまに
「あら、そうですか」
などの相槌がでます。

#OK,Google、ほげほげ

1. 聞き取れませんでした。もう一度お願いします。
2. すみません、お役に立てそうもありません。もっと頑張ります。
3. すみません、よくわかりません。

※
たまに
「ぽけぽけを探しましたが現在利用できないようです」
になります。


#まとめ

各社、様々な対応をしていますね。

Alexaが10種類も見つかったのは意外でした。
Clovaは相槌を話すことがあり、コミュニケーションを大事にしている様子が伺えます。
Google Home（Actions on Google）は「ぽけぽけ」で必死に検索しようとするので、いかにも検索の会社らしいです。

エラーメッセージにも各社の社風がでてきて面白いと思います。
何かしらの参考になれば幸いです。

以上
JavaScript: range関数。逆順も小数もいけるやつ

#追記

+ ジェネレーター版を作った。
+ getDigit: 元記事のやりかただと望み通りに丸めてくれない小数があるので、回避策として文字列にして有効桁を推定することにした。

```js
const toFixedToN = digit => n => Number.parseFloat( n.toFixed( digit ) ) 
const getDigit = n =>{ 
  const a = n.toString() 
  return (!a.includes('.'))? 0
    : a.length - a.indexOf('.') - 1  
}
const maxDigit = (...params) => Math.max( ...params.map( getDigit ) )
const fixedToMaxDigit = (...params) => toFixedToN(maxDigit(...params))

const rangeG = begin => end => step => function*(){
  if( step === 0 ) return 
  if( Math.sign( end - begin ) !== Math.sign( step ) ) return 
  for(let i=begin; (end-i) * Math.sign(step) > 0; i+=step)yield fixedToMaxDigit(begin, step)(i)
}()

const range = begin => end => step =>
  ( step === 0 )? []
  : ( Math.sign( end - begin ) !== Math.sign( step ) )? []
  : [...Array( Math.ceil( ( end - begin ) / step ) ).keys()]
      .map( e => fixedToMaxDigit(begin, step)( begin + e * step ) )

//使用例：
> [...rangeG(0.111)(-10)(-1.7777)]
=> [ 0.111, -1.6667, -3.4444, -5.2221, -6.9998, -8.7775 ]
> range(0.111)(-10)(-1.7777)
=> [ 0.111, -1.6667, -3.4444, -5.2221, -6.9998, -8.7775 ]
```

#以下、元記事。   

[ES6で指定範囲の整数配列を作る](https://qiita.com/takehilo/items/59cb8dc93d28ca252570)にコメントした内容が自分でもいまいちだなあと思ったんで、後でよく考えてみた、という内容です。

時々あったらいいなと思うrange関数を考えてみました。逆順も小数もいけるやつです。

+ begin、end、step必須。
+ beginは含み、endは含まれない。
+ stepが良くない数(0または逆向き)だと空の配列を返します。


```js:
const range = begin => end => step  =>
  (step === 0) ? []
  : ( Math.sign( end - begin ) !== Math.sign( step ) ) ? []
  : [ ...Array( Math.ceil( ( end - begin ) / step ) ).keys() ]
      .map( e => begin + e * step )

//使用例:
//整数
> range(0)(10)(1)
=> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
> range(0)(10)(3)
=> [ 0, 3, 6, 9 ]
//小数 & 逆順
> range(0.1)(-3)(-0.7)
=> [ 0.1,
  -0.6,
  -1.2999999999999998,
  -1.9999999999999996,
  -2.6999999999999997 ]
//stepが0だと空の配列を返す
> range(0)(10)(0)
=> []
//stepが逆向きだと空の配列を返す
> range(0)(10)(-1)
=> []
```
だいたいこれでいいんだけど、小数を使うと仕様上端数というか誤差というかがでてくるので、もうちょっと工夫してみます。


```js:
const range = begin => end => step =>{
  if( step === 0 ) return []
  if( Math.sign( end - begin ) !== Math.sign( step ) ) return []
  
  const getDigit = digit => n =>
    Number.isInteger( n ) ? digit 
    :getDigit( digit + 1 )( n * 10 )
  const maxDigit = Math.max( ...[ begin, end, step ].map( getDigit( 0 ) ) )
  const toFixedToN = digit => n => Number.parseFloat( n.toFixed( digit ) )
  
  return [...Array( Math.ceil( ( end - begin ) / step ) ).keys()]
      .map( e => toFixedToN( maxDigit )( begin + e * step ) )
}
//使用例:
//整数
> range(0)(10)(1)
=> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
> range(0)(10)(3)
=> [ 0, 3, 6, 9 ]
//小数 & 逆順
> range(0.1)(-3)(-0.7)
=> [ 0.1, -0.6, -1.3, -2, -2.7 ]
//stepが0だと空の配列を返す
> range(0)(10)(0)
=> []
//stepが逆向きだと空の配列を返す
> range(0)(10)(-1)
=> []
```
返り値を引数の小数桁の一番大きいものに合わせる、という作戦です。
クラス、インスタンスとは？


##前提
　こちらは、swiftをudemyで学んで数週間の人間が、キータで初めて書いた記事になります。
「です、ます」調で書いています。判断留保の部分を断定してしまっているリスクがあります。なので、何かしらの間違いがあることを前提に読んで頂けると、幸いです。また、もし自分の表現に間違いや、認識の甘さがありましたら、ご教示頂けると嬉しいです。どうぞよろしくお願いいたします。


##class、instanceとは？
classとは、「設計や仕様」で、instanceとは、「製品」に例えられます。
例えば、自動車には、classとinstanceがあります。
自動車でいうclassとは、車の色、車の座席の数、など記述されている設計を指します。
一方、instanceとは、設計図から作られた自動車という製品🚗のことです。

##class,instanceを使う目的・メリットとは？
　「設計」にかかるコスト（時間、労力など)を省けるからです。
そもそも、何かを作るのに、「設計」と、「生産」という2つ過程が必要です。この前者の「設計」にかかるコストを削減できるのが、class,instanceを使うメリットです。

　車の例で説明してみます。全ての自動車🚗には、基本的に、必要な部品と機能があります。例えば、ハンドル、アクセル、ブレーキなどの部品は全ての車にあります。また、ハンドルを回せば、方向を変えられる、アクセルを踏むと車は前進する、ブレーキを踏まえば、停車するなどの全ての車に共通する機能があります。これらは、まとめて、設計図(class)に書きます。
　
　設計図(class)があれば、あとは、工場で生産をして、具体的な製品(instance)にするだけです。ゼロから、「自動車とは何か」、「自動車を作るには、どんな部品が必要か」など、18紀の産業革命の時に考えられてきたことを、21世紀の現代において、考える必要はありません。そのため、自動車の設計書(class)のおかげで、自動車を生産する際、自動車を設計するコストを払うことなく、沢山の自動車を生産(instance)することができます。

　これと似たようなことを、コード上で、class、instaceを使ってできるそうです。
そうすると、コードをシンプルに短く書けて、エラーも起こりにくく、他の人がみても理解しやすくなるという効果が得られます。以上が、swiftのclass,instanceの説明になります。初学者が説明していることなので、何かしらの間違いや、飛躍している部分があると思います。
もし、ご指摘がありましたら、ご教示頂けると幸いです。
R.swiftがXcode10の新ビルドシステムにどう対応したか

~~つい先日**R.swift**が`5.0.0.rc.1`になりました~~
~~https://github.com/mac-cain13/R.swift/releases/tag/v5.0.0.rc.1~~

~~まだプレリリース版ではありますが、これでXcode10対応がほぼできたと見れそうです。~~

12/18付で`5.0.0`が正式版としてリリースされたようです。やったね！
https://github.com/mac-cain13/R.swift/releases/tag/v5.0.0

# どんな問題が起きていたか
詳しいやり取りは[このIssue](https://github.com/mac-cain13/R.swift/issues/456)でされていますが、Xcode10から標準になった新しいビルドシステムを使うとR.swiftが上手く動かないという問題がありました。

新しいビルドシステムではビルド時間短縮のために各Build Phaseを並列処理しているようなのですが、それによってR.swiftの実行を待たずにコンパイルに入ろうとするため、リソースの更新が上手くされなかったり、CIサービス上でビルドエラーになったりしていました。

# 解決策1
R.swift実行用Build Phaseの**Output Files**に*R.generated.swift*へのパスを追加すると、
このBuild Phaseを待って次のBuild Phaseを実行するようになりました。

ところが、Output Filesにファイルが指定されると、どういうわけか２回目以降R.swiftが実行されなくなりました。
恐らくInput Filesが空なので変更が無いとみなされてスキップされるようです。

[robinkunde氏によって提案されていた](https://github.com/mac-cain13/R.swift/issues/456#issuecomment-426344064)のはBuild Phaseに`date > 適当なファイル`を追加し、
そのファイルをInput Filesに指定してやるという方法でした。

Input Filesが指定されている場合、そのファイルに変更があればそのBuild Phaseを実行するようなので、
Build Phaseが実行される度に変更されるファイルを用意して、そのファイルをInput Filesに指定すると良いみたいです。

# 解決策2
[tomlokhorst氏によると](https://github.com/mac-cain13/R.swift/issues/456#issuecomment-438734079)、Appleのテクニカルサポートから提案された方法として`Edit Scheme -> Build Pre-action`で予めファイルを作成するようにする方法を提示しました。

ビルドの前に実行されることが保証されるので、少なくともCI等でR.generated.swiftが無い状態からビルドを走らせるとコケるといったことは防げます。(けどこれBuild Phaseがスキップされる問題は解消できるんだろうか🤔)

# 結論
最終的にR.swiftでは解決策1を採用し、日付を`$(TEMP_DIR)`に書き出す処理を`rswift generate`の処理に入れ込むことで決着したようです。
これに伴い、Input Files及びOutput Filesに対してバリデーションをかけるようになりました。

これからR.swiftを導入しようとしている方や、R.swiftを4.x系から更新しようとしている方はご注意ください。
Redashがバージョンアップ(v5)して便利になったこと＆不便になったこと

エニグモ データ活用推進室 @kmt47 です。
この記事は[Enigmo Advent Calendar 2018の14日目](https://qiita.com/advent-calendar/2018/enigmo)です。

# 概要

redashがv5にバージョンアップしました。（少し時間経ちますが）
この記事では、ユーザ目線でredash v5の新機能を紹介します。
v3→v4へのバージョンアップと比べると、機能的な追加は少なめ＆追加された機能の便利度も低めといった印象です。
また、v4で追加になった超便利機能「表示形式(format)」設定において、v5からパーセント表示の仕様が変更になっています。
それでは、上手に新機能を使って、redash作成を効率化していきましょう！

# クエリ編（表、グラフ）

## クエリを「お気に入り登録」できるようになった（便利度：★★）

クエリを「お気に入り登録」できるようになりました。

「お気に入り登録」したクエリは、redashのトップページに「Favorite Queries」として表示されます。
※ redashのトップページとは、画面の最上段のリダッシュのマーク（💭）をクリックしたときの画面
また、クエリ一覧画面(Queries)では、右側の「☆Favorites」で絞り込むことができます。
小技として、最上段の「Queries」の右の下のボタンをクリックすると、「お気に入り登録」したクエリが選択できるようになっています。

「お気に入り登録」の方法は簡単で、クエリの画面でクエリ名の左の☆をクリックするだけです。
登録されたクエリは、:star: が黄色になります。
もう一度 :star: をクリックすると、登録が解除されます。

良く利用するクエリは「お気に入り登録」しておくことで、トップページから簡単にアクセスできるようになります。

## クエリに「タグ」を付けることができるようになった（便利度：★★）

クエリに任意の「タグ」を付けることができるようになりました。

「タグ」を付けることで、クエリ一覧画面(Queries)の右側のリストから選択したタグで絞り込むことができます。

「タグ」を付ける方法は、クエリの画面の最上段にマウスをナビゲーションすると「+Add tag」のボタンが表示されます。
そのボタンを押すとポップアップ画面が表示されるので、既に登録済みのタグを選択、または新たなタグを入力して付与することができます。
１つのクエリにタグは複数付けることができます。
付けたタグを削除したい場合は、タグの右に表示される鉛筆マークをクリックして、削除したいタグの「×」を押してください。

## パラメータの作成ボタンが追加になった（便利度：★★）

これまでは、パラメータを作成するときは、クエリ入力画面に波括弧を二つ {{ }} 入力して、その間にパラメータ名を入れていたかと思います。
こんな感じです。→　{{ hoge }}

v5では、パラメータ追加ボタンが追加されました。
クエリ入力画面の下の {{ }} ボタンがそれです。

ボタンをクリックすると「Add Parameter」というポップアップが表示されます。
「Keyword」は、クエリに埋め込むパラメータの名前、「Title」はパラメータの入力エリアの名前です。
「Type」でパラメータのデータ型を選ぶことができます。

なお、これまで通りクエリ入力画面で直接追加することもできます。

## パーセント表示の仕様が変更になった（便利度：マイナス☆☆☆☆）

この記事[「Redashがバージョンアップ(v4)して便利になったこと」](https://qiita.com/kmt47/items/d9997a3cf85e802175fd)にも記載しましたが、v4で追加された最大の便利機能「数値の表示形式（フォーマット）をredashで設定できるようになった」のパーセント表示に関する仕様が変更になりました。

例えば、前年比を表示する場合、
「売上（今年） 120万円」÷「売上（去年） 100万円」の結果に対して、表示形式で「0.0%」を指定すれば、
120 ÷ 100 = 1.2 で 「120.0%」と表示されていました。

しかし、v5では、このままでは「1.2%」となってしまいます。
つまり、v4では自動的に100倍されましたが、v5でクエリで100倍する必要があります。
個人的な意見としては、v4の仕様の方が良い（正しい）と思います。
Excelでも1.2の値をパーセント表示にしたら120.0%になりますよね。それを敢えて100倍するなんて。

パーセント表示を使っていたクエリは、v5へのバージョンアップによって、全て修正が必要になりました。:cold_sweat:

# ダッシュボード

## ダッシュボードを「お気に入り登録」できるようになった（便利度：★★）

使い方はクエリと同じなので、詳細は省略します。

## ダッシュボードに「タグ」を付けることができるようになった（便利度：★★）

使い方はクエリと同じなので、詳細は省略します。

## ダッシュボードの変更時にグチャってならなくなった。（便利度：★★★★）

v5でもっとも良くなった点は、ここだと思います。
v4のユーザであれば「グチャって」いう意味が分かると思いますが、
v4では、ダッシュボードのクエリのサイズ、特に高さを変更していると、クエリのサイズが崩れて（「グチャって」）、取り返しのつかないことになった経験がある方も多いと思います。
その為、一度変更したら、保存して、また変更したら保存して、といったように崩れても元に戻れる対策を講じながら作業を行う必要がありました。クエリのサイズを自由に変更できる機能はv4で追加された便利な機能なのですが、ちょっと不具合があったようです。
それがv5では修正されています。ちょっと変更するごとに保存して、「グチャって」なったら修正をキャンセルして、といった作業から解放されたのは非常に助かりました。

# まとめ

v5へのバージョンアップでは、便利機能の追加は少なめでした。
v4では、かなり便利な機能が多く追加されていたので、偶数バージョンのv6に期待します。
IchigoJamにマイクをつないで歌ってみました

#1. 歌ってみた動画がこちら
[![https://youtu.be/fMHYM7MfU58](http://img.youtube.com/vi/fMHYM7MfU58/0.jpg)](http://www.youtube.com/watch?v=fMHYM7MfU58)
歌声に合わせて、画面の文字が左右に動きます。
（歌わない時も2〜3くらいは動きます）

#2. 材料
・IchigoJam　１個
・超小型シリコンマイクモジュール　ＳＰＵ０４１４ＨＲ５Ｈ－ＳＢ使用（秋月電子 [M-08940]　） １個
・セラミックコンデンサー　０．１μＦ５０Ｖ（秋月電子 [P-11154]　）　１個
・ブレッドボート　１個
・ジャンパー線　数本

#3. 作り方
## 3.1. マイクモジュールの基板裏面の半田ジャンパーを、半田づけしてショートする。
## 3.2. ジャンパー線でつなぐ。

|マイク   |IchigoJamの左側ソケット|
|:-------|------:|
|VCC ->    |V+|
|OUT -> コンデンサ-> |IN2|
|GAIN|(つながない）|
|GND ->   |GND|
マイクのOUTはコンデンサーにつないで、そこからINにつなぎます。

#4. コード

```
10 CLS:CLT:X=12
20 A=ANA(2)-880 + 8
30 A=A%32
40 LC A,22:?"0"
50 LC A,23:?""
60 WAIT 5:GOTO 20
```
20行目でマイクの数値を読み込んでいます。
・880：何も歌わないときのだいたいの平均値
・8：画面表示するときの横位置
この2つはいろいろ変えてお試しください。

#5. 実行結果
マイクに向けて歌うと、マイクが検出した数値に合わせて、画面上の「0」が左右に動きます。

#6. 次にやりたいこと
LEDと連動させて、話しかけると光るぬいぐるみ。
胸に装着して、歌声に合わせてLEDの光り方が変わる、キラキラ合唱隊をやってみたい。
またはウルトラマンごっこや、だるまさんが転んだ的な遊びなど。
AWS環境でClovaスキルを開発してみる

[ヴァル研究所 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/val) 15日目の記事です。

スマートスピーカーと言えばGoogle HomeやAmazon Alexa、LINE Clovaなど様々なプラットフォームがありますが、「スキルを作りたい」と思ってもなかなか難しいですよね。
今回はLINE Clovaに焦点を当てて紹介していきます。

# まず何やって良いかわからない

そんな方はこちら
[Clovaスキル×駅すぱあとWebサービス開発体験！初心者向けハンズオン](https://www.slideshare.net/RyusukeTakeda/clovaweb-108731707)
https://www.slideshare.net/RyusukeTakeda/clovaweb-108731707

スライドに沿って実装していくと簡単にスキルが出来上がります。

ソースコードもこちらにすべてアップしてありますので、後は駅すぱあとWebサービスのアクセスキーさえ用意してしまえば十分です。
https://github.com/val00250/ClovaSkills_Hands-on

駅すぱあとWebサービスのアクセスキーは、[こちら](https://ekiworld.net/service/sier/webservice/free_provision.html)から申請いただくと無料で入手できます。
https://ekiworld.net/service/sier/webservice/free_provision.html

# Heroku?AWS使いたいんだけど・・・

はい。
業務などでAWSをガッツリ使っていたり、Alexa向けスキルをAWS環境で作っていて流用できないかとか、よく聞きます。

# ClovaスキルをAWS上で実装する方法

基本はAPI Gateway + Lambdaで問題ありません。
あとはDynamoDBなどと連携すればいろいろ出来ます。

## まずは何したら良い？

スライドの11ページ以降がHerokuからAWSに変わります。

## Lambda関数の作成

1. Lambda関数を作成する
ランタイムは **node.js 8.10** を指定しておきます。 
ロールは CloudWatch への書き込み権限など、最低限のものでかまいません。

2. ソースコードを書き換える
このindex.jsをそのままコピペしちゃえばOKです。
https://github.com/val00250/ClovaSkills_Hands-on/blob/master/AWS/index.js

この後、ソースコードの編集を行うので、今はこのまま保存してしまって大丈夫です。

## API Gatewayを設定する

1. APIの作成

2. POSTでメソッドを追加
※リソースの階層は問いません

3. 呼び出すLambda関数に作成したスキルを指定

4. メソッドリクエストのHTTPリクエストヘッダーに**SignatureCEK**を追加

5. 統合リクエストのマッピングテンプレートに下記を追加
 * リクエスト本文のパススルー  
 **テンプレートが定義されていない場合 (推奨)**
 * Content-Type  
 **application/json**
 * テンプレート

```json
{
    "body":$input.body,
    "headers":{
        "SignatureCEK":"$input.params('SignatureCEK')"
    }
}
```

## CEK側でAPI Gatewayのエンドポイントを指定

APIのデプロイを行うと通常は下記のエンドポイントが割り当てられるので、CEKに設定します。
https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/{$ステージ名}/{$リソース名}

設定の仕方はスライドの15ページ以降を見ながらやってみてください。

で、23ページまで進んだら下記を行います。

## Lambdaのソースコードを修正

1. Webサービスのアクセスキーを書き換え
下記のkeycodeにWebサービスのアクセスキーを設定します
var key = "**keycode**";

2. extensionIdを書き換え
スキル登録時のExtension IDを設定します
var extensionId = "**extensionId**";

これが終わったら26ページ以降を実施すればAWSでClovaスキルが出来上がります。

# 補足

API Gatewayにテンプレートを設定している理由はいくつかあります。

* CEKからPOSTされる内容はbodyに全て入っている
* bodyとSignatureCEKを利用して検証しなければならない
* bodyはJSONなので、body以下に入れてしまって問題ない
* SignatureCEK以外のヘッダは不用なので、テンプレートにもSignatureCEKだけで良い

あと、**$util.escapeJavaScript**とか**.replaceAll("\\'","'")**は入れないとエラーにならない？と思いでしょうが、CEKからは登録した対話モデルしか飛ばないことと、元々JSONの構文として正しいものしか来ないので、大丈夫です。

# まとめ

うまくやればAlexaとClovaで同じスキルが開発できますし、データも共有できますので、マルチプラットフォーム、クロスプラットフォームのスキルが出来上がります。

また、Clovaスキルを作る際にAlexaへの展開も考えている場合はAWSで構築するのもオススメですよ。
Vue.js Canvasで円グラフ

D3.jsを使えという声がありそうですが、
Canvasで円グラフをつくってみました。

<p data-height="400" data-theme-id="0" data-slug-hash="roaPBw" data-default-tab="js,result" data-user="AsaToBan" data-pen-title="Vue.js Pie canvas" class="codepen">See the Pen <a href="https://codepen.io/AsaToBan/pen/roaPBw/">Vue.js Pie canvas</a> by AsaToBan (<a href="https://codepen.io/AsaToBan">@AsaToBan</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

今回はgraphicの描画にpixi.jsを使っています。


**ポイント : watchを利用する**
canvasタグの描画にv-forをつかって
算出プロパティを定義できないためwatchをつかって算出プロパティを監視します。

```js
  computed : {
    items(){
      return this.$store.state.piedata;
    }
  },
  watch:{
    items:{
      handler(){
         this.draw();
      },
      deep:true
    }
  },
```
この様にwatchを利用しstoreに変更があった場合に
描画を走らせるようにしています。
watchはデフォルトでは深いオブジェクトの中までは監視しないので

```
deep:true
```
こちらの記述が必要になるようです。

**ポイント : マスクをかける**
canvasだとそれぞれを円弧を重ねるとガビガビなってしまった
力技ですが全体をちょっと小さめの円でマスクしてます。

```js
let mask = new PIXI.Graphics();
      mask.beginFill(0x000000);
      mask.drawCircle(x1,y1,r*0.95,false);
      mask.endFill();
      stage.addChild(mask);
      sp.mask = mask;
      wp.mask = mask;
```

感想:
SVGのpathと違って直感的に作成することができました。
Rails でドメイン駆動開発 (DDD) をするときの集約の作り方

Rails で DDD をしている時の集約の実装方法を考えます。

## ActiveRecord と集約を別として考える
### メリット
- 集約が `PORO (Plain Old Ruby Object、素の Ruby)` で実装できる
- 集約にDB へのアクセスロジックが混在せず、ビジネスロジックの実装に集中できる

### デメリット
- `ActiveRecord` のインスタンスが別に作成されるのでメモリの使用効率が悪い
- 集約へ再構成を行う実装コストがかかる (ライブラリがあるかも)

### 方法
`ActiveRecord` のインスタンスは DAO として捉えます。
DAO はテーブルに対して操作をおこなうインタフェースとして考えればよく、リポジトリから使用することが想定されます。

例えば、作成や更新を行う `リポジトリ#save` を実装する場合には以下のようになります。

```ruby
class UserRepository
  def save(user)
    user_dao = User.find_or_initialize_by(identity: user.identity)

    user_dao.assign_attributes(
      name: user.name,
      email: user.email
    )
    
    user_dao.save!
  end
end
```

次に、`リポジトリ#user_of_identity` というメソッドを実装して、識別子から集約のオブジェクトを検索/再構成するパターンです。


```ruby
class UserRepository
  def user_of_identity(identity)
    user_dao = User.find_by(identity: identity)

    return nil unless user_dao

    user = Users::User.allocate # 集約を再構成する

    user.instance_variable_set(:@name, user_dao.name)
    user.instance_variable_set(:@email, user_dao.email)

    user
  end
end
```

ポイントは再構成を行う時に、`Class#allocate` を使用していることです。

このメソッドはクラスのインスタンスを作成しますが、`#initialize` を呼び出しません。
再構成時に `#initialize` の呼び出しを回避することで、オブジェクトの作成時にのみドメインイベント発行させたりすることが出来ます。
また、前述の理由のため、集約の各属性への値の代入も、集約を振る舞いを使用せずに `#instance_variable_set` を使用して行います。

実際には、再構成の処理をリポジトリのプライベートメソッドや、Rails のモデルにロジックをまとめる方法が有効的です。

## 番外編: ActiveRecord と集約を同じにする

### メリット
- リポジトリにて、集約への再構成を行うコストが少なくなる
- メモリの使用効率が良い
- [composed_of](https://api.rubyonrails.org/classes/ActiveRecord/Aggregations/ClassMethods.html) で値オブジェクトをマッピング出来る

### デメリット
- ビジネスロジックと DB へのアクセスロジックが混在する
  - DB アクセスのロジックを別モジュールにしてファイルを分けることは出来そう
- ドメインモデル層に `ActiveRecord` のインタフェースが公開されている状態になる

## まとめ
基本的には、DB へのアクセスロジックは集約には漏らさないようにしたいので `ActiveRecord` と集約を別にするパターンで良いのかなと思いました。高い非機能要件が求められて効率的にメモリを使用しなければならない場合には、`ActiveRecord` と集約を同じにするパターンを検討してみてはいかがでしょうか。
ただし、高速化を求める方法はキャッシュの活用や、クエリのチューニングなどでも大きな効果があるはずなので、本当の最終手段のような気がしました。
macで pip 更新エラーについて

この記事は[Wanoアドベントカレンダー](https://qiita.com/advent-calendar/2018/wano-group)の21日目の記事です。

ある日、install pythonのlib時
あるmessage出てました

```
You are using pip version 8.1.2, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```

OK、普通の更新と思いますから
指示通り、以下の命令入れた：

```
~ pip install --upgrade pip

Exception:
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/pip/basecommand.py", line 215, in main
  File "/usr/local/lib/python2.7/site-packages/pip/commands/install.py", line 342, in run
  File "/usr/local/lib/python2.7/site-packages/pip/req/req_set.py", line 784, in install
  File "/usr/local/lib/python2.7/site-packages/pip/req/req_install.py", line 851, in install
  File "/usr/local/lib/python2.7/site-packages/pip/req/req_install.py", line 1064, in move_wheel_files
  File "/usr/local/lib/python2.7/site-packages/pip/wheel.py", line 462, in move_wheel_files
  File "/usr/local/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py", line 372, in make

  File "/usr/local/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py", line 276, in _make_script
    if self._is_nt and not outname.endswith('.' + ext):  # pragma: no cover
  File "/usr/local/lib/python2.7/site-packages/pip/_vendor/distlib/scripts.py", line 250, in _write_script
    script_bytes = launcher + shebang + linesep + zip_data
  File "/usr/local/lib/python2.7/site-packages/pip/_vendor/distlib/util.py", line 407, in write_binary_file

IOError: [Errno 13] Permission denied: '/usr/local/bin/pip'
```

権限足りない？ならば

```
~ sudo pip install --upgrade pip

Traceback (most recent call last):
  File "/usr/local/bin/pip", line 11, in <module>
    load_entry_point('pip==9.0.1', 'console_scripts', 'pip')()
  File "/Users/johnny/Library/Python/2.7/lib/python/site-packages/pkg_resources/__init__.py", line 567, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/Users/johnny/Library/Python/2.7/lib/python/site-packages/pkg_resources/__init__.py", line 2604, in load_entry_point
    return ep.load()
  File "/Users/johnny/Library/Python/2.7/lib/python/site-packages/pkg_resources/__init__.py", line 2264, in load
    return self.resolve()
  File "/Users/johnny/Library/Python/2.7/lib/python/site-packages/pkg_resources/__init__.py", line 2274, in resolve
    raise ImportError(str(exc))
ImportError: 'module' object has no attribute 'main'
```

調べると、何がversionの問題っぽい
[pip install --upgrade pip (10.0.0) 後の奇妙な挙動について] (http://icchy.hatenablog.jp/entry/2018/04/17/064443#solution)

この時点既にpip動くできないので、取りあえず一旦10.0.0のversion前戻す
sudo python -m pip install pip==9.0.1

もしpip10に乗り換えたいなら、既存のパッケージに影響の可能性があるので、注意してください
Dockerコマンドチートシート

記憶力がないからDockerコマンドの個人的なメモを書いておきました。何分初心者なので間違ってても許してください。自分が使う分だけ書いてあります。

順次追記していきます。
#docker image [コマンド]
|コマンド|説明|
|:----|:----|
|build|ビルド|
|pull|pull|
|ls|ビルドまたはプルしたイメージの一覧表示|
|history|履歴表示|
|rm|イメージを削除|

#docker container [コマンド]

|コマンド|説明|
|:----|:----|
|run|コンテナを実行|
|attach|コンテナにアタッチ|
|ls|コンテナの一覧表示|
|kill|コンテナの停止|
|port|コンテナが使用中のポートを表示|

#各コマンドの詳細
各コマンドの詳細なオプションを書いていきます。
##docker image build
docker image build [オプション] [Path]
PathはDockerfile内で使用するファイル等が置かれているディレクトリを指定する。

|オプション|説明|
|:----|:----|
|-f [hoge]|Dockerfile名を指定|
|-t [hoge]|タグの指定|

##docker container run
docker container run [オプション] <イメージ名> [コマンド] [引数...]

|オプション|説明|
|:----|:----|
|-d|コンテナをバックグラウンドで起動|
|--name|Dockerコンテナに名前を付ける|
|-it|実行結果をコンソールに出力|
|-p [host]:[container]|ポートフォワーディング|
|-e [HOGE]=[hoge]|環境変数を指定|
|(--read-only) -v [host] [container]|ディレクトリをマウント <br> --read-onlyを付けると読み取り専用でマウント|
|-w=[dir]|作業ディレクトリを指定|
Markdownツールなどをまとめてみた

おはようございます｡Markdown過激派のgakkiです｡

# Markdown #とは
Markdownとは簡単な記法でHTML化してくれるやつです｡(Markupの逆)
Qiita記事もMarkdownです｡詳しくは調べてください｡

ティラノサウルスなどを暴れさせるのはWordに任せて､
文書等はMarkdownにしていきましょう｡

# Markdownを書く
## [Atom](https://atom.io/)
言わずもがなGitHub社製のテキストエディタ
デフォルトでもMarkdownを書きやすいがプラグインをお好みで入れると最強になれる｡

## [Typora](https://typora.io/)
Markdown専用のシンプルなエディタ
書いたその場でプレビューと記述一体型でスタイルが適応されていく｡


# Markdownでメモをとる
## [Boostnote](https://boostnote.io/)
日本製のOSSでMarkdownファイルを書くのではなくメモを取るのに特化
ファイルが煩雑にならず書いたメモのリストがいっぺんに出る｡フォルダ分けもできるのでメモアプリとして完成度が高い｡
スマホアプリもあり､Dropboxなどと連携すれば自動で複数デバイスで共有できる｡
もちろん書いた文書をファイルにエクスポートもできる｡


# Markdownでスライドを作る
## [Marp](https://yhatt.github.io/marp/)
日本製のOSS｡
非常に手軽にMarkdown書くだけでそれなりのスライドを作れる｡
作ったスライドをPDFにエクスポートできる｡

## その他
詳しくまとめてる記事がありましたので参考までに
[[ Markdownでスライド作成 ] 5種類くらいツールを試してみた結果](https://qiita.com/ykhirao/items/74a23f812dd5d22b3b88)


# Markdownで仕様書
## [GitBook](https://www.gitbook.com/?t=1)
Markdownで書いた文書をHTMLやPDFにできる｡GitHub社とは関係ない｡
目次も作れて結構使いやすい｡
GitHubPagesで簡単に公開もできる｡
HTML1ファイルになるのでその他の場合でも簡単にデプロイ可能｡
ただ現在Windowsだとちょっと手直しが必要

## [API Blueprint](https://apiblueprint.org/)
MarkdownでAPIの仕様書を書ける｡しかもそのままAPIのモックになる｡強い｡
REST APIを作る時なんかに重宝する｡
仕様書がそのままモックにもなるので`モックを作る時間`が無くなる｡


# MarkdownでWiki
## [Growi](https://growi.org/)
日本製のOSSで[Crowi](http://site.crowi.wiki/)というMarkdownWikiの機能拡張版
なんとMarkdownでUMLなんかも書けるので社内用仕様書なんかは全部これでいいかもしれない｡
Dockerで簡単にセットアップからSSL対応までできて至れり尽くせり｡


# Markdownで技術情報共有
## [Qiita](https://qiita.com)
今ご覧頂いているこれ

## [Qrunch](https://qrunch.io/)
`もっと気軽に技術ブログを書こう！`をモットーに作られたプログラマのための技術ブログサービス
`「WordPress・はてなブログ」と「Qiita・dev.to」の中間的な存在`を目指しているらしい｡
機能としても使いやすく､記事の他にメモ書き等を`ログ`という形式で投稿できたりと今まで届かなかったところまで届いている気がする｡最近のお気に入り｡

# まとめ
Markdown関連ツールを簡単にまとめてみました｡
こう見るとMarkdownツールは日本製が結構優れている気がする｡
他に良いツールやサービス等があればコメントで教えてください｡
ログを読むアプリ

#数百MB以上のログを調査する
機会がとても多いんです。

RHEL6.5上で動作するWebアプリケーションが吐くログが毎日このサイズなんです。

そんな時に活躍しているのが、もう十数年愛用しているテキストエディタ、**PeggyPad**。
今使っている最新バージョンのビルド日が2009-12-24なので、もう9年前のアプリです。

このテキストエディタは、もう開発が終了している(開発していた会社はあるみたいだけど開発部門が消滅した)ためダウンロードすらままならないので、インストーラが超大事です。
~~と言いながら先日紛失…爆~~

この子がですね。
**数百MBのファイルがサクッと開いて編集も超軽い**んです。
なので、ログチェックには手放せません。
※使った感覚的にはEmEditorよりも軽いです

代替アプリとして今はMeryを使っていますが、作者の方も言われている通り巨大ファイルが苦手で重いんですよね…

**Vim**が結構サクサク動いてくれるので代替アプリの候補に挙げましたが、Windows上で使うには不便すぎて…コマンドが覚えられない…

皆さん、こういったログのような巨大なテキストファイルを開いて内容を調査するには、どんなアプリを使われているんでしょう。

真っ先にEmEditor(Free含)や秀丸が挙がってくるのは目に見えるのですが、職場の事情で使えません。
AtomやBrancketなどのChromiumベース？のエディタはことごとく使い物にならず。
VS Codeもダメでした。
TeraPadやサクラエディタなどの定番系フリーテキストエディタも実用に耐えません。

もうこの問題に悩み続けて早数年。
何かいいアプリはないものか…
【Phalcon】Phalconで生のSQLを実行する【PHP】

「phalcon 生SQL 実行」で検索しても、「実行したクエリを取得する」みたいなのしか出てこなかったので

```◯◯.php
#model
use Phalcon\Db\Column;
use Phalcon\Db\Adapter\Pdo\Mysql;


class ◯◯ extends \Daisy\Util\Model
{
  public function initialize()
    {
      $this->adapter = $this->di->get('db');
    }
  public function test(){
    $ret = $this->adapter->fetchAll("SELECT * FROM user WHERE id = 1");
  }
}
```


・[Phalcon勉強会資料](https://www.slideshare.net/yujiotani16/phalcon-37768016)
ここ見てレコード数多いときはPDOを使うのがめっちゃ早いっぽい。


・[抽象クラスPhalcon \ Db \ Adapter \ Pdoのメソッド一覧](https://code.i-harness.com/ja/docs/phalcon~3/api/phalcon_db_adapter_pdo)
fetchAllは全部持ってくるやつだけど他にも便利なのがたくさんあります。
Echo Show、Echo Spotの電源の切り方

ごきげんよう

この記事は
**「するめごはんのVUI・スマートスピーカー Advent Calendar 2018」**
の14日目の記事です。

今回は明らかに小ネタです。

Echo Spotの時もハマったのですが、Echo Showで再度それをやることになりました。

けど、僕は完全に忘れていてハマったので記事にすることにしました。

#電源の切り方がわからない

Echo Showのスタンドも買ってあって、それが昨日届きました。
これ、角度が結構調整できて大変嬉しいのですが、設置するときに（哲学的に？）壁に当たりました。

**説明書が「電源ひっこぬけ」の絵しかない。**

![DSC_1576.JPG](https://qiita-image-store.s3.amazonaws.com/0/67398/6060998d-6650-82f0-0e00-68609d8b07f0.jpeg)

世界中に配るであろうスタンドの説明書・解説書なので、わざわざ日本語はありません。
そこにいきなり「1」で電源を抜く画像です。
初手から電源を引っこ抜く指示です。

もう動いちゃってます。

ところが、Echo Showの画面上部から下に向かって設定メニューを表示して、さ迷いましたが電源の切り方がない。
もちろん電源ボタンもないです。

で、もしかしたらと・・・

**ミュートボタンを長押ししたら電源が切れることがわかりました。**


![DuRhMR4UUAAQpWs.jpg](https://qiita-image-store.s3.amazonaws.com/0/67398/0058bcbc-b16a-ca79-9944-dbab2c9a2dd5.jpeg)


#Echo Spotでも同じです

ミュートボタンを長押しです。
※　ミクさんが写りこんでいるのは僕の家の仕様です

![DSC_1577.JPG](https://qiita-image-store.s3.amazonaws.com/0/67398/28b8cb2f-0c9b-f825-4402-9982313ccb35.jpeg)


#さすがにEcho Spot、Echo Showで電源で何かあるのが怖い

それなりのお値段がするので、こんなことで何かあったら嫌なので、改めて記事にしました。

Dotはぶっこぬいてます。。。


以上、小ネタでした。
heroku にloginが出来ない場合

##エラー発生 (heroku loginできない)
 `$heroku login`を入力すると、ターミナル上に<b>herokuのアドレスが表示</b>され、それをクリックしてブラウザを開き<b>loginボタン</b>を押すと、今まではログインできていた。

しかし、、、

今回は、1分ほど待った後に、ターミナルに`Error: timed out　at Object.error`が表示されログイン失敗。


##解決策

`$ heroku login --interactive`を入力後、<b>herokuに登録しているメールアドレス・パスワードを入力</b>して、無事ログインできました！
【MySQL】ソートをした際のNULLの位置について

# MySQLでソートをした際のNULLの位置について


## table

|id  |name  |
|---|---|
|1  |aaa  |
|2  |NULL|
|3  |bbb  |



### 昇順（NULLが上）
```sql
SELECT * FROM table ORDER BY name ASC;
```

実行結果：

|id  |name  |
|---|---|
|2  |NULL|
|1  |aaa  |
|3  |bbb  |
---
### 降順（NULLが下）
```sql
SELECT * FROM table ORDER BY name DESC;
```
実行結果：

|id  |name  |
|---|---|
|3  |bbb  |
|1  |aaa  |
|2  |NULL|
---
### 昇順（NULLが下）
```sql
SELECT * FROM table ORDER BY name IS NULL ASC;
```
実行結果：

|id  |name  |
|---|---|
|1  |aaa  |
|3  |bbb  |
|2  |NULL|
---
### 降順（NULLが上）
```sql
SELECT * FROM table ORDER BY name IS NULL DESC;
```
実行結果：

|id  |name  |
|---|---|
|2  |NULL|
|3  |bbb  |
|1  |aaa  |
シルエット解析のための前処理

```python
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
import cv2
from PIL import Image
from sympy import *
from sympy.abc import a,b,c
from sympy import var
from rdlib2 import *
```
##  処理対象画像例

![17daruma6o06_l.jpg](https://qiita-image-store.s3.amazonaws.com/0/175067/9d11f293-31ae-c9f3-9ea0-f812e97c116c.jpeg)

## 平滑化

```python
daruma='daruma.jpg'
img = getstandardShape(cv2.imread(daruma,cv2.IMREAD_GRAYSCALE), unitSize=UNIT, thres=0.25)  
plt.imshow(img)
```

![ダウンロード.png](https://qiita-image-store.s3.amazonaws.com/0/175067/1d04781d-6d19-38b6-c355-bc35c30fa78a.png)

#輪郭線抽出

```python
# 輪郭情報
_image, contours, _hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 輪郭線追跡
cnt00 = contours[np.argmax([len(c) for c in contours])] # 最も長い輪郭
canvas = np.zeros_like(img)
canvas = cv2.drawContours(canvas,[cnt00],-1,255,2) # 輪郭線の描画
plt.scatter([cnt00[-10][0][0]],[cnt00[-10][0][1]],color="red") # 輪郭点列の先頭位置
plt.imshow(canvas)
```

## OpenCV の輪郭線データのデータ構造

```print(cnt00[:3],cnt00[-3:],type(cnt00))```

```python
[[[193 65]] [[192 66]] [[191 66]]] 
[[[196 65]] [[195 65]] [[194 65]]] 
 <class 'numpy.ndarray'>
```

- OpenCV の findContours関数で、RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE を指定した場合、最外殻輪郭を構成する点列の座標が**左回り**で並ぶ
- １つの座標データは **[[x座標, y座標]]** というリスト。カッコが２重であることに注意
- 開始点と終了点は重複していない
- ８連結のチェインである



## ヒゲの除去

上の例で用いた画像では発生しないが、対象図形に幅１の部分がある場合、輪郭チェインに同一の座標が重複して現れることになる。もし、輪郭チェイン内の座標に唯一性が要求される場合には、次のプログラムを通してヒゲ要素を取り除くとよい。

```python
# 輪郭データからのひげ除去
def shaver(cnt):  # 輪郭点列のうち、ヒゲ要素を取り除く
    # まず輪郭列のスタート部分がヒゲ要素を取り除く
    while True:
        if len(cnt) > 2 and list(cnt[1][0])==list(cnt[-1][0]): # 最初の点がヒゲの先端
            cnt = cnt[1:-1]
        else:
            break
    # 途中のヒゲ要素を取り除く
    while True:
            l = len(cnt)
            for  i in range(1,len(cnt)-1):
                    if list(cnt[i-1][0]) == list(cnt[i+1][0]):
                            cnt = np.r_[cnt[:i],cnt[i+2:]]
            if l == len(cnt):
                break
    return cnt
```
【Django】クエリ数を減らすための工夫たち（随時追加予定）

## この記事で書いていること
- ORMを使っていると、知らぬ間に大量のSQLが発行されてる恐れがある
- クエリ数を発行しないための工夫がいくつかあるので、それを紹介する
- 新しい使えるテクニックを見つけたら、随時加筆予定

## ORMでは知らぬうちに大量のクエリが発行されているかもしれない
私が触ったことのあるフレームワークはRails、Djangoだけなので、ORマッパーがあるのが当たり前という環境で育ってきました。

そのため、DBにアクセスするためにSQLが発行されていることをあまり意識してきませんでした。（お恥ずかしい限りですが）

これから職業プログラマーとして成長していくためにはそんなんじゃあかんという訳で、絶賛試行錯誤中です。

今回は私が調べたり、先輩から教えてもらったクエリ数を抑える工夫やテクニックを紹介していこうと思います。


## クエリ数を観測するには、「django-debug-toolbar」を使う
まず、クエリ数を改善するためには、何のSQLがどれくらい走っているのか計測できる必要があります。

そこで取り入れるのが、「django-debug-toolbar」というパッケージです。

こんな感じのサイドバーが画面に表示されて、直前の処理でどれくらいSQLが走ったのか、見れるようになります。
![スクリーンショット 2018-12-13 15.36.07.png](https://qiita-image-store.s3.amazonaws.com/0/158916/957d186e-fda1-b8c4-2d21-7c2b0614c805.png)

### インストール
公式DOCSにインストールの手順が書かれています。順にコピペしていくだけでオッケーです。
https://django-debug-toolbar.readthedocs.io/en/stable/installation.html


## クエリ数を減らすのに役立つテクニック集
では、ここから実際にクエリ数を減らすテクニックを書いていきます。

### ループの中でクエリが走る処理を書かない
テクニックというか、心がけ。

ループの中でUser.objects.filter(name="hoge")とか書いてるコードに違和感を持てるようになろう。

### select_related()
公式DOCSのここに詳細が書いてあります。
https://docs.djangoproject.com/ja/2.1/ref/models/querysets/#select-related

公式の例をそのまま引っ張ってくると、

```
# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)

# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog
```

Entryクラスのリレーション先である、Blogクラスのデータもselect_related(）が呼ばれたタイミングでDBから引っ張ってきているので、最後の行で`e.blog`を実行した時にクエリが走りません。

的なことが書いてあります。

もし、select_related()を実行せず、get()だけを使ってEntryクラスのインスタンスを`e`に格納した場合、最後の`e.blog`を実行したタイミングでもう一度クエリが走ってしまうことになります。

上記のような簡単な例では、クエリ数にさほど差は出てきませんが、取得したインスタンスのリレーション先のインスタンスをループ処理の中などで取り出す処理を書いていたりしたら、select_relatedの有無による差は絶大になります。

ちなみに、リレーション先が複数ある場合、

```
e = Entry.objects.select_related('blog', 'something').get(id=5)
```

みたいに、コンマつなぎで一気に書けます。

### bulk_create()
公式DOCSはこちら
https://docs.djangoproject.com/en/2.1/ref/models/querysets/#bulk-create

何かデータをcreateする時は、当然ながらクエリが走ります。

１件ずつ逐一createしていると、登録件数が増えるほど、クエリ数が増えてしまいます。

ある程度まとまった量のデータをまるっと処理することも当然よくあるので、それでは困ってしまいます。

Djangoはbulk_createというやつを用意してくれています。

以下、公式記載の例

```
>>> Entry.objects.bulk_create([
...     Entry(headline='This is a test'),
...     Entry(headline='This is only a test'),
... ])
```

このように、インスタンスを要素にした配列を引数にとって、1クエリで全てのレコードを作成することができます。

バッチ処理とも相性が良く、公式にはその例も載っているので、一目見ておくと良いと思います。

### bulk_update()
複数のレコードを更新したい時に便利なパッケージ。

何かのレコードを変更し、save()で保存する時、UPDATEというクエリが走ります。

変更レコードが1件増えるごとに1クエリ増えていってしまいます。

そこで、`bulk_update`を使うと、変更したいインスタンスを配列に格納しておけば、1つのクエリで全て更新できるようになります。

使用イメージとしては、こんな感じ。

```
from django_bulk_update.helper import bulk_update

updates = []

for instance in instances:
    instance.hoge = "fuga"
    updates.append(instance)

bulk_update(updates, update_fields=['hoge'])
```

#### インストール
Djangoのbuilt-inではなく、パッケージをインストールして使います。

詳細は公式のGithubを見てください。
https://github.com/aykut/django-bulk-update

こちらサイトも参考にさせてもらいました。調べてると良くお見かけするサイトさんです。いつもお世話になっております。
https://tokibito.hatenablog.com/entry/20160128/1453914673
年度を多用する場合の考え方

#年度を使用するにあたって多いコード
``` Java
public int getNendo(Date date){
    //1月～3月なら
    ...
    //4月～12月なら
    ...
}
```

こんなコードをよく見る。
考え方だけメモ。
必要な月数分ずらしたカレンダーみたいなものを用意して、そのカレンダー上、与えたDateが属する年を返却してくれれば良いのではないか。
（そういうカレンダークラスがあればなあ・・・）
余裕があったら作りたい。

追記

``` Java
import java.util.Calendar;
import java.util.Date;

public class CustomCalendar {
    private int startMonth;

    public CustomCalendar(int startMonth) {
        if (startMonth < 1 || 12 < startMonth) {
            throw new IllegalArgumentException("開始月は1～12を指定してください。");
        }
        this.startMonth = startMonth;
    }

    public int getNend(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1 * (startMonth));
        return calendar.get(Calendar.YEAR);
    }

    public static int getNend(int startMonth, Date date) {
        CustomCalendar cal = new CustomCalendar(startMonth);
        return cal.getNend(date);
    }

    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        for (int nendStart = 1; nendStart <= 12; nendStart++) {
            for (int dateMonth = 1; dateMonth <= 12; dateMonth++) {
                cal.set(2018, dateMonth, 1);
                int nend = CustomCalendar.getNend(nendStart, cal.getTime());
                System.out.println(String.format("年度開始月:%2d、カレンダーの月:%2dの場合、年度は%d", nendStart, dateMonth, nend));
            }
            System.out.println();
        }
    }
}
```

こんなもんでどうだろうか
Xamarin.Formsで数値の±で着色するLabelを作る

値に応じた色付けをするような時、画面コントロールではなくてLabel部品側で色をつけたいところ

### Styleを作る

````csharp
<?xml version="1.0" encoding="UTF-8"?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
                    xmlns:common="clr-namespace:hoge.Common"
                    x:Class="hoge.Asset.Styles">

    <x:Double x:Key="DefaultFontSize">16</x:Double>
    <Color x:Key="DefaultTextColor">#000000</Color>

    <Style  x:Key="RegularFontStyle" TargetType="Label">
        <Setter Property="FontSize" Value="{StaticResource DefaultFontSize}" />
        <Setter Property="TextColor" Value="{StaticResource DefaultTextColor}" />
    </Style>
    
    <Style TargetType="common:ValueLabel" BasedOn="{StaticResource RegularFontStyle}">
    </Style>
    
</ResourceDictionary>
````

ここでは自動着色するLabelを`common:ValueLabel`として定義してます


### 起動時にスタイルを読み込む

````csharp
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:theme="clr-namespace:hoge.Asset"
             x:Class="hoge.App">
    <Application.Resources>
        <theme:Styles />
    </Application.Resources>
</Application>
````

App.xamlで読み込む


### Labelクラスを作る

````csharp
using System;
using System.Runtime.CompilerServices;
using Xamarin.Forms;

namespace hoge.Common
{
    public class ValueLabel : Label
    {
        public ValueLabel()
        {
        }

        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);
            if (propertyName == "Text")
            {
                if (!string.IsNullOrEmpty(Text) && Text.Contains("+"))
                {
                    TextColor = (Color)App.GetStyle()["PlusColor"];
                }
                else if (!string.IsNullOrEmpty(Text) && Text.Contains("-"))
                {
                    TextColor = (Color)App.GetStyle()["MinusColor"];
                }
            }
        }

    }
}
````

数値処理は省略してますが、とりあえず＋かーかが含まれてたら色をつけるというロジックにしてます
`OnPropertyChanged`での判定が楽なのでこんな処理にしてますがパフォーマンスはあまり良くないと思います
Docker使ってZabbix。でもデータベースが作成できない！

Zabbix Advent Calendar 2018の13日目です。

ここで小ネタを1つ。

DockerコンテナでZabbixを構築しようとした時にこんなことが。

> ベースのOSとしてCentOSを指定してZabbixはパッケージを利用してインストールっと。
> よし、あとはデータベースの作成だ！
> ん？あれ？データベース作成用のファイル(create.sql.gz)が無い？

と止まっている方がまだいらっしゃるようなので、ここにも書いておきます。

DockerのLinuxのイメージによっては、コンテナのサイズ削減のため、パッケージをインストールする時にドキュメント属性のファイルをインストールしないようにする設定がされている場合があります。centos:centos7でもそのような設定がされています。

そのような環境にZabbix公式のパッケージを使用してインストールしようとした場合は、データベース作成用のSQL文が入っているファイル(create.sql.gz)はドキュメント属性となっているのでインストールされません。

具体的にどのような設定になっているかというと、/etc/yum.conf内に以下のような設定が行われているはずです。

```
tsflags=nodocs
```

これがあるとドキュメント属性のファイルがインストールされません。

対策としては、yum.conf内のこの設定行をコメントアウトするか、yumコマンドでパッケージをインストールする際に、コマンドのオプションでtsflagsを設定する方法が考えられます。

```sh
# yum --setopt=tsflags='' install zabbix-server-mysql
```

Zabbix以外の他のソフトウェアでも、ドキュメント属性のファイルだと同様にインストールされませんので、パッケージに入っているはずなのにインストールされないという時は、このyumコマンドのオプションのことを思い出してください。
Webサービスバックエンドライブラリー　Materia

# Materia とは

弊社カラビナテクノロジーで開発中のElixir/Phoenix製サービスバックエンドライブラリーです。

私の所属チームでは複数のお客様のWebシステム構築をElixir/Phoenixを使って行っており、
Webサービス構築において共通する要件（ユーザー認証/権限管理/トランザクション制御）などをより効率的に実装したいという想いから開発をはじめました。

SPA(Single Page Application)での開発を想定したバックエンドAPIを提供します。

ElixirにはPhoenixという優れたWebフレームワークがありますが、
サービスとして公開するためにはPhoenix上で様々なライブラリーを駆使して実装が必要な要件があります。
そういった一般的に必要な機能（というか弊社で必要だった機能）をモデル＆エンドポイント（API)レベルで汎用化したものとなります。

Mateiaを導入することで、サービスとして特色のないユーザー管理や認証といった部分のバックエンド機能を個別開発せずに、本来実装したいサービスの特色となる機能の開発に注力することができます。

現在Docの整備などOSSとして正式に公開する為の準備を進めております。

Materia
|> [Materiaを導入してログイン認証してみる](https://qiita.com/tuchiro/private/ee6fdf487665b9789540)
|> [Materia.Grantsを使って実行権限チェックを行う](https://qiita.com/tuchiro/private/e4a7607d045335b1cc0a)

# 構成

現状は以下の２つのライブラリから構成されます。

- MateriaUtils ・・・　Mateira内で共通で使用する関数をまとめたユーティリティー集（単独でも利用可能）
- Materia・・・Webサービスで共通して必要となるモデルおよびJsonAPIを提供するサービス基盤(MateiaUtilsに依存)

今後、ユーザー間のメッセージング機能など、異なる分野ごとに必要に応じて選択・追加する周辺ライブラリを実装していく予定です。

# MateriaUtils機能

#### MateriaUtils.Calendar.CalendarUtil

現在日時、翌日日時の取得や、ローカル時刻<-->UTCの時刻変換機能などを提供
デフォルトでは正しく時刻関係を解釈できないEmum.max_by()に変わるmax_by関数も提供
時刻操作ライブラリとして[Timex](https://github.com/bitwalker/timex)を使用

#### MateriaUtils.Ecto.EctoUtil

Ecto関連のWrapper実装を提供

- Ecto.Adapters.SQLをWrappしたSQLの直接実装
- フロント側で検索条件を指定できる汎用検索API用関数

#### MateriaUtils.Enum.EnumLikeSqlUtil

Enumでのgrup_by,count,sumをSQLライクに書く為の関数を提供

#### MateriaUtils.Perser.TsvPerser

テストやpriv/repo/seeds.exsでのデータ定義をTSVで楽に行う為のパース機能を提供

# Materia基本機能

#### 認証Pipeline

Routerに設定するだけでjwt認証を提供するplug pipeline実装

- Materia.AuthenticatePipeline ・・・　ログイン認証後のjwt認証用
- Materia.UserRegistrationAuthPipeline　・・・ユーザー仮登録用
- Materia.PasswordResetAuthPipeline・・・パスワードリセット用

#### 権限チェックPipeline

Routerに設定するだけでAPIの実行権限チェックを提供するplug pipeline実装

- Materia.Plug.GrantChecker ・・・ユーザーのroleとgrantsテーブルの設定によってAPIの実行権限チェックを行う


#### トランザクション制御＆エラーハンドリング

Ecto.Multiを使ったトランザクション制御、および、共通エラーハンドリング

- MateriaWeb.ControllerBase ・・・ 各Controllerで使用することで呼び出した関数のトランザクション制御および共通エラーハンドリングを提供するEcto.MultiのWrapper実装
- Materia.Errors.BusinessError ・・・ 任意で業務エラーを返したい場合に使用する独自Errorモジュール。MateriaWeb.FallbackControllerに対応
- MateriaWeb.FallbackController　・・・ 各Controllerでaction_fallbackに設定することで、ControllerBaseでハンドリングしたErrorをJsonフォーマットに整形する後処理


# Materiaコンポーネント

#### Materia.Accounts

メール認証をベースとしてユーザー、権限管理APIを提供

- 管理者向けのユーザー情報の参照・更新API
- 管理者向けの権限情報管理API
- 自身のユーザー情報のみ参照更新なエンドユーザー向けAPI
- メールによる本人確認付きのユーザー仮登録＆本登録API
- メールによる本人確認付きのパスワードリセットAPI

#### Mateia.Authenticator

Materia.Accountsで実装されたユーザーに対するjwt認証機能を提供
認証ライブラリとして[guardian](https://hex.pm/packages/guardian)を使用し以下のAPIを提供

- メールアドレス、パスワードによるaccess_token、refresh_tokenの発行
- refresh_tokenによるaccess_token認証の再取得
- アカウントステータスによるログイン認証の妥当性チェック


#### Materia.Mails

認証やユーザー通知の為のメール送信およびメールテンプレート管理機能
ユーザー登録やパスワードリセット時の本人認証やユーザー個別への通知を目的としたメール送信を想定
マーケッティングメールなどバルク送信には現在未対応

- メール送信機能。AWS SES（要AWSCLI）、SendGridおよびテスト用Stubに対応
- メールテンプレート管理API
- メール送信機能は登録されたテンプレート（定型文）に対するユーザー名等置換機能を提供

#### そのほかAccounts周辺モデル

- Materia.Organizations ・・・複数のユーザーを所属管理する組織情報APIを提供
- Materia.Locations ・・・　AccountsおよびOrganizationsに紐づく複数の住所情報管理APIを提供
世界で一番簡単にLGTM画像を作る方法

- ペンで書く
- 撮影
- 以上


透明プラカード

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/f9910795-7676-2809-b7e7-0d5e3cbe0be7.png)

神に筆ペンで描く

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/cbfe7897-00ec-86ad-e3f3-cb3acd616309.png)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Xcodeのテンプレートファイルの User Interface の種類について

##はじめに
　今回はXcodeにテンプレートファイルを追加する際に、いつもはCocoaTouchClassやSwift File...を使うことが多いかと思いますが、今回はその下にあったUserInterfaceについて何だろうかなと思っていました。
　そこで使い方を調べたところこれは今のやっているプロジェクトに応用できるのでは？と思い備忘録的にまとめます。
<img width="731" alt="TWScanViewController_m.png" src="https://qiita-image-store.s3.amazonaws.com/0/235810/12e3b694-bb15-9b12-8056-c989e08daa16.png">

##UserInterfaceのテンプレートについて
　StoryBordが煩雑になるから**StoryBordを分けたい**といった時に一番用いられるのではにかと思います。
　今やっているからそう思うだけかも知れませんが...

##UserInterfaceテンプレートの種類について

以下の表にまとめましたので参考にしてください
<img width="532" alt="名称未設定_numbers.png" src="https://qiita-image-store.s3.amazonaws.com/0/235810/bbb4856f-64c9-1492-a946-d5c823a813e6.png">

##最後に
　Xcode初心者が勉強の備忘録として記載しています。
　間違いがありましたらコメントしていただけると助かります！
　よろしくお願いします！
AWSってどこまで手ぇ広げてんねんな話

# はじめに

最近、諸般の事情でAWSを勉強しております。まずはAWSの全体像を俯瞰してみようとAWSのサイトを開いてみたわけですが、

**あまりにも提供しているサービスが多すぎて口笛吹きそう**

どんなのがあるのかは、AWSのサイトにあるナビゲートバーの「製品」にマウスカーソルを合わせるとカテゴリが出てきて、さらにサービスのリストが出てくる仕掛けとなっております。

[AWSのトップページ](https://aws.amazon.com/jp/?nc2=h_lg)

今回は、「ここまで手ぇ伸ばしますか！？」と唸り、強烈な印象を植えつけたサービスを３つ紹介したいなと思います。

## １．人工衛星の地上局

[AWS Ground Station](https://aws.amazon.com/jp/ground-station/?nc2=h_m1)

いきなりパンチの効いたサービスです。
人工衛星とのやりとりをクラウドに任せてしまおうというものです。

Amazonが持っているアンテナ（パラボラアンテナ？）と人工衛星をつなぐ形で利用でき、料金はアンテナとつないでいる時だけ発生するという大胆な体系です。[^1]

Amazonにとっては、IoTも人工衛星もお手の物というものなのでしょうか。

## ２．VR/ARの空間構築

[Amazon Sumerian](https://aws.amazon.com/jp/sumerian/?nc2=h_m1)

以前から、[Lumberyard](https://aws.amazon.com/jp/lumberyard/?nc2=h_m1)などゲーム関連のサービスにも手を出しているAWS、一歩進んでVRやARの環境を提供し始めました。

驚きなのは、Webブラウザで環境を構築できること（WebGLやWebVRの対応必須）。ブラウザ上にある３D空間に部品を組み込んでビジュアルプログラミングで動作を決められるのにもかかわらず、専用のソフトは必要ないというポータブルな環境です。

出来上がった空間はWebGL向けやiOS向けにパブリッシュでき、スマホVRがお手軽にできるのは興味あります。

いつかは、[カスタムキャスト](https://customcast.jp/)や[VRoid](https://vroid.pixiv.net/)とかいったvTuber向けのサービスも提供するのでしょうか？（え、その基幹を提供する方じゃないかって？　ごもっとも…）

## ３．ブロックチェーン

[Amazon Managed Blockchain(英語)](https://aws.amazon.com/jp/managed-blockchain/?nc2=h_m1)

泣く子も黙る仮想通貨の世界にもAmazonは果敢に手を出していますね。
このサービスを使えば、自前でブロックチェーンを持つことができます[^2]し、掘ることも可能のようです。

英語のページしか無いことからも分かる通り、まだまだ発展途上のようですが、本格普及の足がかりとなるのでしょうか？（その前に破産しそうだけど…）

個人的には税金が大変なことになるので手を出しづらい…（確定申告では雑費扱いになる）

# おわりに

駆け足で強烈なインパクトを持つサービスを３つ紹介いたしましたがいかがでしょうか？

これらを見ても分かる通り、Amazonサンはビビッときたビジネスチャンスにはとにかく参画しようという旺盛な意欲を見せつけられます（そのかわり、技術者やAWS関係のSIerにとっては阿鼻叫喚ですが…もう全部把握できる人なんていないのでは…)。

この世界、まだまだ目を離せないようです！


[^1]: もちろん、データの保持にS3やDynamoDB、処理用にBeanstalkやEC2使うとなると料金が別途必要です。
[^2]: ブロックチェーンについては[こちらのWeb記事](https://ferret-plus.com/7706)や[Qiitaでの記事](https://qiita.com/KazukiKawamura/items/68cb6c16a7d95b9c5a02)をご参照くださいませ
Oracle Database 18c インストールが途中で止まる

Oracle Database 18c インストールが「Oracleインスタンスの作成および起動中(進行状況 52%)」で止まります。

ーー 試したこと ーー

・ユーザー(英数大文字のみ)を変更してインストール
・Java の PATH と JAVA_HOME の設定
・環境変数を「Path」を 「PATH」に変更
・環境変数「PATH」の最大文字数を1023文字以下に変更
・インストールファイルをダウンロードし直したり解凍し直したりした

ーー マシン環境 ーー
・Windows 10 pro
・メモリ 8G
・空き容量 131GB

以前、Oracle Database 11g も同じところで止まってたと記憶してますが、どうすればインストールできますか？
FileMaker//AppleMapを表示する

FileMakerでAppleMapを使うにはどうしたらいいかという「[さぽらぼ](https://supportaslab.peatix.com/)」で得たひらめきをサンプルにしてみました。[こちらの記事](https://qiita.com/yasuhikoc/items/c2de70d1e2dea18ad16a)からの続きです

##リファレンス
[Apple URL Scheme Reference](https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html)
以下、これを元に作ってみたカスタムApp製作工程です

#作成サンプル：AppleMapを使う
AppleのMapをFileMakerに埋め込む(=Webビューアに入れる)のはハードル高そうなのですが、**「餅は餅屋、Mapの機能はMapでやってもらえば」**という参加者の方のアドバイスもあり、以下のようなカスタムAppを作ってみました
##基本レイアウトはこんな感じ
![サンプル.png](https://qiita-image-store.s3.amazonaws.com/0/181254/4135248f-81ef-7927-bf19-45dd51576cd1.png)
各項目を設定して、いらすとやさんのボタンをクリックすると、AppleMapが開いて結果を表示してくれるようにしようと思います

##フィールド名はこんな感じ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181254/56866924-08ea-56c4-7969-eeea6031ed4a.png)
上から5つのフィールドはFM17が勝手に作ってくれるので、実際に追加したのは下の4フィールドだけです

```FileMaker:AppleMapスクリプト
# -------------------------------------------------
# AppleMapを呼び出すスクリプト
# -------------------------------------------------
変数を設定 [ $saddress ; 値: MAP::出発地点 ] 
変数を設定 [ $daddress ; 値: MAP::目標地点 ] 
変数を設定 [ $maptype ; 値: Case ( MAP::MapType = "サテライト" ; "k"; MAP::MapType = "ハイブリッド" ; "h"; MAP::MapType = "交通機関" ; "r";  "ｍ") ] 
変数を設定 [ $transittype ; 値: Case ( MAP::交通タイプ ="公共交通機関" ; "r"; MAP::交通タイプ ="徒歩" ; "w";  "d" ) ] 
変数を設定 [ $query ; 値: "saddr=" & $saddress & "&daddr=" & $daddress & "&t=" & $maptype & "&dirflg=" & $transittype ] 
# 
URL を開く [ ダイアログあり: オフ ; "http://maps.apple.com/?" & $query ] 
```
1 出発地点
2 目標地点
3 マップのタイプ(ラジオボタンの結果をURLスキーマのValueに変換)
4 交通手段(ラジオボタンの結果をURLスキーマのValueに変換)
の４つの変数を得て、URLスキーマ`http://maps.apple.com/?`にくっつけます


##実行結果
<img width="1004" alt="スクリーンショット 2018-12-13 14.50.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/181254/3bc21955-5358-990b-70dd-005fb3b7e646.png">
Mapアプリが起動して、経路を表示してくれました
・Windowsで実行するとどうなるか試してみたのですが、その場合は規定のブラウザを呼び出した上でGoogleMapで表示するようです。

##iOSで開けない？
このファイルをiOS上で実行した時に、URLが開けない問題が発生中
Version16だと開くことができます
１７特有のバグと考えて、以下のように回避策をとりあえず設定しています

```FileMaker:Go17の場合はGoogleMapを開くようにする
If [ PatternCount ( Get ( アプリケーションバージョン ) ; 17 ) and Get ( システムプラットフォーム )=3] 
	# Version17では表示できない症状を確認したため、一時的にGoogleMapに避難
	変数を設定 [ $directionmode ; 値: Case (  $transittype="w" ; "walking" ;  $transittype="r" ; "transit" ; "driving") ] 
	URL を開く [ ダイアログあり: オフ ; "comgooglemapsurl://maps.google.com/maps?saddr=" & $saddress  & "&daddr=" & $daddress & "&directionmode=" & $directionmode ] 
Else
	URL を開く [ ダイアログあり: オン ; "https://maps.apple.com/?" & $query ] 
End If
```
##SpecialThanks〜年末の挨拶に代えて〜
さぽらぼで色々教えていただいたp388cellさん、アドベントカレンダーを起案いただいたtyumaさんほか一緒に勉強している皆様、場所と楽しい時間を提供いただいている株式会社サポータスの佐々木さん・杉浦さんほか会社の皆様のおかげで、FileMakerで何かを作るどころか記事を書くことができるようになりました。
今年も本当にありがとうございました。来年もよろしくお願いいたします