kondoumh のブログ

- とあるソフトウェアエンジニアのめったに更新されないブログ -

VS Code の ChangeLog メモ用 Extension その後

年明けに作っていた ChangeLog 用 Extension

blog.kondoumh.com

日付+メルアドのヘッドライン挿入ぐらいしか作ってなくて、ローカルでアドホックに修正して使ってましたが、ちょいちょいコード修正するのが面倒になってきたので見直しました。

シンタックスハイライトの統合

まず、シンタックスハイライトの定義を別 Extension で作っていたので統合しました。

項目(タグ)のセットを挿入

ヘッドラインと一緒に定型的な項目(タグ)のセットを一式挿入できるようにしました。

f:id:kondoumh:20180609143752g:plain

VS Code 設定画面での設定

メールアドレスや、項目セットの設定を VS Code の設定画面で書けるようにしました。

f:id:kondoumh:20180608163957p:plain

設定用の JSON データのサンプルです。

    "changelog.mailaddress": "kondoh@local",
    "changelog.weekdayitems": [
        "task",
        "meeting"
    ],
    "changelog.weekenditems": [
        "running"
    ]

平日と週末で異なる項目セットを定義できるようにしました*1

スニペット

一括挿入ではなく個別に項目(タグ)を入力するためのスニペットを使えるようにしました。tag と打つことでスニペットが入力できます。

f:id:kondoumh:20180609143822g:plain

スニペットにするほどの入力量でもないんですが、まあ一応。

マーケットプレイスへの公開

めんどくさそうでまだやってません。

github.com

*1:設定用の名前空間の衝突とかありそうですね。

HHKB Pro JP を macOS High Sierra に最適化 - with Karabiner-Elements & DIP switch

Mojave ではどうなるかわかりませんが・・

macOS Sierra 以降 Seil が動かなくなりアンインストールして、Magic Keyboard だけで生活してきました。

blog.kondoumh.com

久々に Realforce 91UBK を常駐先から持ち帰って、オールドな Windows キーボードもよいものだと思い、MacBook Pro に接続してみました。

blog.kondoumh.com

91UBK はもう生産してないんですね*1

接続してすぐに Seil がないから日本語と英語の切り替えがストレスフルだったのを思い出しました。この辺はもうそろそろ解決されてるんじゃないかとぐぐったら、Karabiner-Elements という後継ツールがいい感じに進化している模様。

早速インストールしたところ、変換 -> かな無変換 -> 英数 というマッピングが簡単にできて Seil の環境が復活しました。

常駐先での強い味方である Realforce 91UBK はテンキーレスではあるものの Magic Keyboard を使っている自宅の机にはちょっとでかいです。そこで、久々に Happy Hacking Keyboard Professional JP を引っ張り出してきました。サイズ感がちょうどよくて自宅使いにフィットします。

blog.kondoumh.com

ただ、HHKB JP は Realforce と比べ、メインキーのサイズこそほぼ同じですが、最下段のキー(漢字Alt無変換変換kana) がちんまりしていて、親指のポジショニングがシビアです。そこで、変換 の右にある kanaかな にマッピングしてしまいます。これで日本語と英語の切り替えで誤操作は無くなります。このマッピングは Realforce のようなフルピッチのキーキャップのキーボードでも設定してます。kana (カタカナ/ひらがな) って全然使わないので。

最下段キーが小さいことで、macOS の を駆使するショートカットと、Alt 系のショートカット( Emacs のMeta など) で打ち間違う問題があります。特に、Alt の位置が MacBook の配列と逆なので混乱を助長させます。これって入れ替えられないのかなあと HHK 裏面のディップスイッチの説明をよく見ると SW5 で入れ替え可能じゃないですか。

f:id:kondoumh:20180604235528j:plain

買ってから10年目で気づきました。早速 SW5 をオンにして、引き抜き工具で2つのキートップを入れ替えました。

ちなみに HHKB のディップスイッチ では SW1 を ON ( にマップ)、SW2 を ON (左 FnCtrl にマップ) してます。左 FnCtrl にすることで、Emacs キーバインドで多用する Ctrl を左小指の肉球で押せるため、左小指がつりそうになるのを防止できます。

最後に、漢字 です。HHKB JP の漢字 は 最下段の左 Fn の右という変態位置に申し訳程度に配置されていますが、これはさすがに誰も使っていないのではないかと思います*2漢字 は Karabiner-Elements では grave_accent_and_tilde(`) という分かりづらい名前で指定できます。HHKB に限りこのキーを 左 Alt(option) キーに変えてしまいます。

f:id:kondoumh:20180604235815p:plain

これで、Alt の数が増えて打ちやすくなりました。キーボード毎にきめ細かく設定できるのも Karabiner-Elements の素晴らしいところです。

以上を纏めますと以下のようになります。

マップ元 マップ先 方法
SW1
Fn Ctrl SW2
Alt SW5
Alt SW5
漢字 Alt Karabiner-Elements
変換 かな Karabiner-Elements
kana かな Karabiner-Elements
無変換 英数 Karabiner-Elements

ということで、自宅では暫く HHKB Pro JP (墨) に回帰してみます。しかし墨ってほぼ無刻印ですね。キートップの印字がくっきりしてるモデルの方がいいなあと10年経って思いました。

f:id:kondoumh:20140204000402j:plain

*1:後継の静音タイプ UBK-S も今年6月に生産終了

*2:HHK JP からこのキーを取っ払って最下段のキーピッチを広くしてもらいたいと思うのは僕だけではないでしょう。

WPF に再入門中

久々に使うことになりそうなので、再入門しています。

.NET Framework 3.0 で Avalon のコードネームで搭載され、3.5 で WPF として登場した GUI フレームワーク。当時のプロジェクトで運用系ツールの画面で使いましたが、多くのプロジェクトでは Windows Forms が使われ続け早10年。ただ Silverlight, Windows Mobile, UWP, Xamarin ... と XAML 系 GUI プラットフォームが数年置きに登場する*1ため断続的に触っており、プログラミングモデル自体には結構なじみがあります。

XAML 編集用に Blend という別 IDE が提供されていますが、Visual Studio 本体でも地味に GUI デザイナーが進化しています。

リハビリがてら、RSS Reader 的なサンプルを作っているところです。

github.com

参考記事:[C# / WPF] 最新のC# 6.0でMVVMパターンを実装する

WPF 登場時はプロパティベースのデータバインディングが新鮮でした*2が、プロパティの更新通知のためにプロパティ名をハードコーディングしなくてはならず、リファクタリングでイベントが発火しなくなる恐れがあるのが残念でした。

    private string hoge;
    public string Hoge
    {
        get { return this.hoge; }
        set
        {
            this.hoge = value;
            OnPropertyChanged("Hoge");
        }
    }

C# 6 で nameof 演算子が導入されプロパティ名のリテラルが取れるようになったので、リファクタリングも大丈夫になりました。

    private string hoge;
    public string Hoge
    {
        get { return this.hoge; }
        set
        {
            this.hoge = value;
            OnPropertyChanged( nameof(Hoge) );
        }
    }

実は Behavior という Blend 由来の仕組みを使えば更新通知も簡単に実装できるようですが、別途 Blend SDK が必要となります*3。今回はとりあえず Behavior は使っていません。

  • イベントハンドラではなく、Command バインディングで書く
  • リモート API の非同期呼び出し - 呼び出し中に画面を固まらせない
  • 呼び出し中の Command 呼び出し無効化 - 呼び出し中に更新ボタンを押せなくする

あたりを意識して書いてみました。

Command バインディング (正式な呼び方ではないかもしれません) は、画面のボタンに対応する Command を実装して XAML にバインドする書き方です。

    <Button
        Content="Update"
        Command="{Binding FetchCommand}" />

Command の実装はこんな感じ。

    class FetchRSSCommand : ICommand
    {
        // 中略

        public bool CanExecute(object parameter)
        {
            return !Fetching;
        }

        public async void Execute(object parameter)
        {
            Fetching = true;
            var contents = await Task.Run(() => FetchRssAsync());
            foreach (var content in contents)
            {
                _vm.Items.Add(content);
            }
            Fetching = false;
        }

        private Task<List<RSSViewModel.RSSContent>> FetchRssAsync()
        {
            using (var reader = XmlReader.Create(_vm.Url))
            {
                var feed = SyndicationFeed.Load(reader);
                // 中略
                var result = (from f in feed.Items
                              select new RSSViewModel.RSSContent()
                              {
                                  Title = f.Title.Text,
                                  Summary = f.Summary.Text,
                                  PubDate = f.PublishDate.DateTime,
                                  Link = f.Id
                              }).ToList();
                return Task.FromResult(result);
            }
        }
    }

XmlReader には非同期用メソッドがないみたいなので、取得処理を Task にラップして、async / await で呼んでます。

Execute の前後でFetching というプロパティを変化させて強制的に Button の Disable / Enable を切り替えています。 Fetching プロパティの実装は次のようになっています。

    private bool _fetching = false;
    public bool Fetching
    {
        get { return _fetching; }
        set
        {
            _fetching = value;
            RaiseCanExecuteChanged();
        }
    }

    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

RSS 取得中かどうかを保持する bool 値 _fetching の setter で CanExecute 状態変化を通知するためのメソッドを呼び出しています。

昨今の JS の Single Page Application のような、非同期に Web API を叩いて結果を画面表示するアプリはサクッと書きたいのですが、なかなか定石が分からず迷いますね。.NET Framework や C# はがんがんバージョンアップしているので、ドキュメントもリニューアルされると嬉しいのですが、公式の WPF 関連情報は滞っている印象です

今は UWP や Xamarin 推しなのでしょうけどエンプラユーザーのことも時々ケアが必要。

*1:そして衰退していく・・あ、Xamarin は現役ですね。

*2:昨今の JS フレームワークでは普通ですね。

*3:標準に取り込んで欲しいものです。

Electron 版 Twitter クライアントを急造 - macOS PWA 版までのつなぎ

2月に macOS の公式 Twitter クライアントはディスコンになりました。

iphone-mania.jp

僕のマシンでは最後の方は接続エラーが出まくるようになっていたので、使わなくなっていました。代替として推奨されている TweetDeck をインストールしたのですが、Web 版やスマートフォンアプリとの UI の違いが大きくて馴染めずに起動することもなくなっていました。

最近はずっと Chrome で Twitter やってましたがブラウザの1タブなので閉じてしまうことも多く、タイムラインが常駐している感じがなくなりました。

2月に Microsoft は Web フロントエンドディベロッパーの取り込みを狙って Windows 10 における PWA (Progressive Web Apps) サポートを発表しました。

blogs.windows.com

Windows 10 UWP 版 Twitter アプリが先日 PWA 対応の一環でリニューアルされました。

japanese.engadget.com

www.microsoft.com

Twitter のタイムラインでは使いにくいみたいな声が目につきましたが、ライトユーザーである (と思っている) 自分にはスマホと同じ UI で馴染みやすい感じでした。

VMware Fusion の Windows 10 で、新 Twitter アプリと Edge *1を並べて使うと macOS 本体側と Twitter & ネット記事閲覧環境が分離できていい感じになりました。

f:id:kondoumh:20180504201302p:plain

ボーっとタイムライン眺めてる時間と作業用スペースがスワイプで切り替えられるのでコンテキストの切り替えが楽になる気がします。

Edge なので Twitter で出会った記事をストックするために Pocket 拡張を入れました*2。でも Tumblr に Quote 流したいなあと思うとブックマークレット必要ですが Edge でブックマークレットを使うのはとてつもなく面倒そうに見えました。英語のページだったら翻訳して読んだりしたいし・・・ここで、仮想マシンに Chrome を入れたら負けです。

macOS でも PWA 対応は進められているようで、もう数ヶ月したら、Windows 10 と同様の PWA 版 の公式 Twitter アプリが AppStore に登場しそうな気がします。

www.publickey1.jp

それをちょっと先に体験したくて Electron で Mobile 版 Twitter サイトをデスクトップアプリ化するの試してみました。

Electron は数年前に少し触ったきりだったので、ローカルの NPM パッケージが壊れてたりしました。公式サイトから Quick Start プロジェクトをダウンロードしてきて改造。起動時に外部リンクを開くための EventListener を追加したり、ウィンドウいっぱいに WebView 描画するようにした程度。

Mobile Twitter のシンプルな画面 はデスクトップでも邪魔にならないし、作業用とは別のデスクトップに 閲覧専用 Chrome のウィンドウを置いて、その隣に置くと 仮想マシンの Edge と Twitter アプリは不要になりました。

1日使ってみて、Mobile 版 Twitter をデスクトップで使うとスマホの引っ張って更新 (Pull to Reflesh) が使えないので、無意味に下にスクロールしたり、画面内リンク踏んだりしなければいけないところが微妙に感じました。PC 版サイトだと、未読ツイートが溜まってくるとツイートの一番上に 「新しいツイート n 件を見る」というリンクが勝手に出てくれるので楽です。

ということで、デフォルトは Mobile 版ですが、PC サイト版 Twitter に切り替えられるようにしてみました。PC 版だとユーザーアイコンにマウスオーバーするとユーザー情報をポップアップしてくれたり細かいところで使い勝手もよいですし。

これでかなり快適なタイムライン閲覧環境になりました。

f:id:kondoumh:20180504204157p:plain

自分用に作ったため特に配布予定はないですが、GitHub にソースコードは置いておきました。

github.com

PS. 作った後でこれ思い出した。

jackhanford.com

*1:仮想マシンには Chrome 入れないポリシー

*2:Edge の拡張機能もストア経由でインストールします。

Typora - WYSIWYG でクロスプラットフォームな Markdown(GFM) エディタ

去年の記事ですが、これ読んで Typora 知りました。

etc9.hatenablog.com

この記事を書いたときは、モバイルも視野に入れてたので、デスクトップ専用アプリは見てませんでした。

blog.kondoumh.com

Typora 公式サイト

Typora — a markdown editor, markdown reader.

今のところ Preview 版ということで無償で利用できます*1

画面はとてもシンプルで、サイドバー出してないと「メモ帳?」っていう感じ。Theme も色々提供されているようです。おそらく Electron 製のアプリと思われます。

f:id:kondoumh:20180502205226p:plain

サイドバーは、見出しを Word のナビゲーションのように表示できるので、アウトラインプロセッサー的に使えなくもないです。

既存の Markdown エディタは (ATOM や VS Code などアドオン的な実装も含め) 、編集画面とプレビュー画面が分離しているものが普通でしたが、Typora は WYSIWYG な感じで見た目のスタイリングと Markdown 形式を両立させているエディタです。

Scrapbox と同様、画像や数式の行にカーソルが来るとインライン編集用エディタが現れ、画像のパスや数式やを編集できるという UI です。

通常表示

f:id:kondoumh:20180502205453p:plain

インライン編集時

f:id:kondoumh:20180502205505p:plain

通常表示

f:id:kondoumh:20180502205610p:plain

インライン編集時

f:id:kondoumh:20180502205622p:plain

テーブルは、インラインのツールバーから GUI で編集できます。

通常表示

f:id:kondoumh:20180502205730p:plain

インライン編集時

f:id:kondoumh:20180502205742p:plain

Scrapbox や Dropbox Paper など WYSIWYG 的サービスが流行っているので、このようなデスクトップアプリが出てくるのも自然な気がします。エディタというよりも、1周回って Word とか Pages のようですが。独自形式じゃないところが安心感あります。

ドキュメントによれば、Github Flavored Markdown (GFM) といくつかの拡張をサポートしているようです*2。そういえば、最近このブログは構造化とかせずにダラっと流し書きしていて Markdown ほぼ使ってなかったりしますが・・

各種プログラミング言語に対応したコードブロックももちろんあります。

f:id:kondoumh:20180502205834p:plain

箇条書きでは Emacs OrgMode 形式のタスクリストも作成できます。

f:id:kondoumh:20180502205949p:plain

ダイヤグラムについては、PlantUMLのような記法でシーケンス図やフローチャートを描けます*3

フローチャート

f:id:kondoumh:20180502210156p:plain

シーケンス図

f:id:kondoumh:20180502210211p:plain

脚注書式 (footnote) も利用できます。

f:id:kondoumh:20180502210334p:plain

PDF 出力するとちゃんと脚注として出ています。

f:id:kondoumh:20180502210355p:plain

あと、ヘルプシステムがちょっと変わっていて、ヘルプドキュメントも Typora で記述され Typora に読み込まれて (別ウィンドウで) 起動します。

ということで Typora なかなか素敵な UI で文書作成に集中できそうです。本格的な原稿を Markdown ベースで執筆できます。ダイヤグラムなどグラフィカル要素も極力テキストで扱おうという思想が感じられます。

Scrapbox や Dropbox Paper もよいですが、ローカルファイルとして作成し Dropbox や Git で管理したい場合など、有力な選択肢になりそうです。こういうのが出てくるともう Emacs OrgMode も存在感薄くなってきましたね。

*1:正式リリースされたらどういう課金モデルになるでしょうか。

*2:GFM は Markdown の亜種ですが表現力を高めるための拡張は歓迎すべきでしょう。

*3:JavaScript のグラフ系ライブラリを利用して実現されています。

CodePen で手軽に Web UI を推敲する

HTML / CSS / JavaScript の Playground は JSFiddle などが有名ですが、結構前から CodePen と言うサービスが普及しているようで。最近になって知りました。

codepen.io

Qiita でも最近記事内に CodePen を埋め込めるようになったりしています。

qiita.com

類似サービスのまとめ記事

www.webprofessional.jp

CodePen は Playground なので、大規模なプログラムを書くのには適していませんが、ライブラリの書き味とかを試すのに手元で環境を構築することなく開始できるのがよいところです。最近は、Web フロントエンドのメジャーなフレームワークは環境構築が一仕事になっており、余暇でやろうとしてもコードを書き始めるまでに力尽きることが多いため、お手軽さ重要です。

1枚の HTML ファイルに CSS/JavaScript を混ぜて書くぐらいの感じで*1、ライブプレビュー付きでコードを書けます。Popular なライブラリはクイックに追加できるようになっています。

f:id:kondoumh:20180422145301p:plain

CDN に配置されたライブラリの検索も楽ですので、好みのライブラリ・バージョンを使えます。

トランスパイラも選べます。

f:id:kondoumh:20180423011822p:plain

JavaScript のデバッグは Chrome の DevTools が使えますが、console.log で Console ウィンドウに情報を出せます。オブジェクトは JSON の Pretty print で出力されるので見易いです。 これなら、DevTools が使えない iPad の Safari や Chrome でもライブプレビュー、デバッグ出力を見ながらコードを書けますね*2

f:id:kondoumh:20180422155108p:plain

数年前、Meteor がまだ勢いがあった頃に HTML5 Canvas を駆使するメディア系ライブラリ KineticJS を使ってダイヤグラムエディタのおもちゃを書いてたのですが、その UI 部分を CodePen で動くようにしてみました。

See the Pen Konva-dia by kondoumh (@kondoumh) on CodePen.

KineticJS をフォークした Konva.js を使いました。

github.com

CoffeeScript 久々に触りました。コードエディタが一画面なので、これぐらいの長さのコードになるとちょっとつらいですね。リファクタリングも手打ちですし。

CodePen ではこういった Pen と呼ばれるコード片の他に、Project を生成して Web IDE としても使える模様です。

追記) CodePen で Picked Pens 入りしてました。

f:id:kondoumh:20180425010112p:plain

*1:実際、Pen を export すると、index.html / index.js / style.css ぐらいの単純構成です。

*2:今回の記事タイトルを「iPad でコードを書く - CodePen 編」にしようかとも思ったのですが、iOS のブラウザだと、テキストエディタの検索用キーショートカットが ⌘ + F になっててブラウザの方に吸われてしまい、長いコードは書きづらいということでやめました。

AWS Lambda で Alexa スキル開発 (Hello World 編)

blog.kondoumh.com

Echo Dot 買ったら Alexa スキルで Voice UI 開発ということで Hello World してみました。

Alexa スキルは AWS Lambda で実装しますが、以前 Web IDE の Cloud 9 を試すときに AWS アカウントを作っていたのでしばらく無料で試せます。

blog.kondoumh.com

Alexa Skills のエンドポイント作成とテストは AWS ではなく Amazon Developer のサイトで行います。AWS 側では Lambda 関数を作って Alexa とのやり取り部分を実装します。

developer.amazon.com

Amazon Developer では普段使ってる Amazon のアカウントでログインすべきで、新しくアカウントを作るとハマるそうです。

Alexa 開発者アカウント作成時のハマりどころ : Alexa Blogs

ブラウザのタブを2枚開いて Alexa Developer Console (Amazon アカウント) と Lambda Management Console (IAM ユーザ) を交互に操作して開発を進めます。

そもそもクラウド開発に不慣れなオンプレミスディベロッパーなので Hello World もすんなり行きませんでした。公式チュートリアルを見ても AWS の設定画面の方が更新されてますし。権限もよくわかっておらず・・・。

AWS では作業用アカウントはルートアカウントではなく、必要な権限のみ付与した IAM ユーザとして作成するのがベストプラクティスとされています。前回 Cloud 9 を使うために IAM ユーザのグループに AWSCloud9User を割り当てていて、今回新たに AWSLambdaFullAccess を追加しました。これで Lambda の機能はフルに使えるはずですが、Lambda Management Console で 関数を作ろうとしてると権限が足りないエラーが。

not authorized to perform: iam:CreateRole on resource: role/lambda_basic_execution

エラーが出る度にびルートで IAM Console にログインして権限を追加。権限設定ができるまでは IAM ユーザでログインしたメインのブラウザ(Chrome など)と IAM Console にログインしたサブのブラウザ(Safari など)を起動した方が楽です*1 。結局、グループに割り当てた AWSLambdaFullAccess に加えて、インラインポリシーとして iam:PutRolePolicyiam:CreateRole を追加する必要がありました。

f:id:kondoumh:20180406151602p:plain

これで Lambda 関数の追加ができるようになりました。今回は設計図(テンプレート)から作成を選びました。

f:id:kondoumh:20180406152359p:plain

設計図としては、alexa-skill-kit-sdk-factskill を選択。

Lambda の編集画面には Cloud 9 のエディタがプロジェクトごと埋め込まれていました (フルスクリーンにして利用可能です)。

f:id:kondoumh:20180406154409p:plain

ひとまず Lambda 関数を作成したら、Alexa Developer Console 側でスキルの対話モデルを定義します。まずスキルの呼び出し名をつけてインテントを追加します。テンプレートが太陽系の惑星についての豆知識を教えてくれるサンプルになっていたので、「惑星くん」と名付けました。インテントは適当に Sandbox としておきました。

f:id:kondoumh:20180406153313p:plain

サンプル発話の登録画面です。今回は適当に1個追加したのみです。

f:id:kondoumh:20180406153655p:plain

対話モデルを 「JSON エディター」で見ると以下のようになりました。

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "惑星くん",
            "intents": [
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "Sandbox",
                    "slots": [],
                    "samples": [
                        "教えて"
                    ]
                }
            ],
            "types": []
        }
    }
}

次に、スキルのエンドポイントの設定です。Lambda Management Console で作成した関数の ARN を設定します。

f:id:kondoumh:20180406154156p:plain

Lambda Management Console の Cloud 9 エディタで関数を編集します。

'use strict';
const Alexa = require('alexa-sdk');
const APP_ID = 'amzn1.ask.skill.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
const SKILL_NAME = 'MyFactSkill';
const GREETING_MESSAGE = "オーケー: ";
const HELP_MESSAGE = 'You can say tell me a space fact, or, you can say exit... What can I help you with?';
const HELP_REPROMPT = 'What can I help you with?';
const STOP_MESSAGE = 'Goodbye!';

const data = [
    '水星の1年は88日だよ。',
    '太陽からの距離は水星より遠いにもかかわらず、金星は水星より気温が高いよ。',
    '金星は反時計回りに回転するよ。おそらく過去の小惑星との衝突のせいだね。',
    '火星では、太陽は地球上で見るのと半分ぐらいの大きさだよ。',
    '地球は神にちなんで命名されていない唯一の惑星だよ。',
    '木星はすべての惑星の中でもっとも1日が短いよ。',
    '天の川銀河は約50億年後にアンドロメダ銀河と衝突するよ。',
    '太陽だけで太陽系の質量の99.86%を占めてるんだよ。',
    '太陽はほぼ完璧な球体だよ。',
    '皆既日食は1〜2年に一度発生するよ。これはとても珍しい事象だよ。',
    '土星は、太陽から受けるより2.5倍のエネルギーを宇宙空間に放射してるんだよ。',
    '太陽の内部温度は摂氏1500万度に達することがあるよ。',
    '月は我々の惑星から毎年約3.8cm離れていくよ。',
];

const handlers = {
    'LaunchRequest': function () {
        this.emit('GetNewFactIntent');
    },
    'GetNewFactIntent': function () {
        const factArr = data;
        const factIndex = Math.floor(Math.random() * factArr.length);
        const randomFact = factArr[factIndex];
        const speechOutput = GREETING_MESSAGE + randomFact;

        this.response.cardRenderer(SKILL_NAME, randomFact);
        this.response.speak(speechOutput);
        this.emit(':responseReady');
    },
    'AMAZON.HelpIntent': function () {
        const speechOutput = HELP_MESSAGE;
        const reprompt = HELP_REPROMPT;

        this.response.speak(speechOutput).listen(reprompt);
        this.emit(':responseReady');
    },
    'AMAZON.CancelIntent': function () {
        this.response.speak(STOP_MESSAGE);
        this.emit(':responseReady');
    },
    'AMAZON.StopIntent': function () {
        this.response.speak(STOP_MESSAGE);
        this.emit(':responseReady');
    },
};

exports.handler = function (event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);
    alexa.APP_ID = APP_ID;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

ほとんどテンプレートのまま。豆知識を翻訳しただけです。handlers の LaunchRequest プロパティが Amazon Echo からのエントリーポイントになります。GetNewFactIntent プロパティの function を呼び出して、応答を生成し Alexa に返しています。

Alexa Developer Console のテスト画面で Alexa にスキルを呼び出してもらうことができます。PC のマイクを有効にすれば、自分の声で話しかけることもできますし、チャットの UI にテキストを打ち込んで送信することも可能です。

「アレクサ 惑星くんを開いて」と送信したところ無事に惑星くんのスキルを開いて応答を返してくれました。

f:id:kondoumh:20180406155413p:plain

スキルI/O (Alexa へのリクエストとレスポンス) の JSON も確認できます。

ここまでくれば、開発者アカウントに紐付いた Amazon Echo の実機で作成したスキルを試せます。あっさり Echo Dot から惑星くんが起動できたのでちょっと驚きました*2

最初は権限周りでちょっと戸惑いましたが、これでスキル開発に取りかかれそうです。それにしてもサーバーレスな AWS Lambda は Alexa のスキル実行基盤として最適ですね。

*1:IAM ユーザとルートアカウントは同時ログインできないため

*2:他の人に使ってもらうには ベータテストの設定が必要のようです。