OmniAICreator/Qiita-1.07M huggingface dataset:
pythonで近似式の計算


#近似式の計算
# numpyによる方法
##polyfit
``import numpy as np``
``np.polyfit``を利用
``np.polyfit(x,y,1)``で1次近似，１を変えることで，次数を変えた計算ができる。
``np.poly1d(np.polyfit(x, y, 1))``で関数が生成される。
``np.poly1d(np.polyfit(x, y, 1))(引数)``で引数による数値が計算される。

```python

import numpy as np
from matplotlib import pyplot as plt

x= np.linspace(-10,10,20)
y= x**3 +  2*x**2 + 3*x + 10+ np.random.randn(20)*50

#近似式の係数
res1=np.polyfit(x, y, 1)
res2=np.polyfit(x, y, 2)
res3=np.polyfit(x, y, 3)
#近似式の計算
y1 = np.poly1d(res1)(x) #1次
y2 = np.poly1d(res2)(x) #2次
y3 = np.poly1d(res3)(x) #3次

#グラフ表示
plt.scatter(x, y, label='元データ')
plt.plot(x, y1, label='1次')
plt.plot(x, y2, label='2次')
plt.plot(x, y3, label='3次')
plt.legend()
plt.show()
```
###計算結果
![3ji.png](https://qiita-image-store.s3.amazonaws.com/0/117425/b218e319-55ff-f175-5c34-8ec58d51009a.png)

# scipyによる方法
## leastsqによる近似
``from scipy import optimize``
関数を定義して，``optimize.leastsq(func1, param1, args=(x, y))``で係数を求める。

```python

from scipy import optimize

# 1次式の近似
def func1(param,x,y):
    residual = y - (param[0]*x + param[1])
    return residual
param1 = [0, 0]
res_leas1 = optimize.leastsq(func1, param1, args=(x, y))#係数
# 2次式の近似
def func2(param,x,y):
    residual = y - (param[0]*x**2 + param[1]*x + param[2])
    return residual
param2 = [0, 0, 0]
res_leas2 = optimize.leastsq(func2, param2, args=(x, y))

# 3次式の近似
def func3(param,x,y):
    residual = y - (param[0]*x**3 + param[1]*x**2 + param[2]*x + param[3])
    return residual
param3 = [0, 0, 0, 0]
res_leas3 = optimize.leastsq(func3, param3, args=(x, y))
```

## curve_fitによる近似
``from scipy import optimize``
関数を定義して，``optimize.curve_fit(func_c1, x, y)``で係数を求める。

```python

from scipy import optimize

# 1次式の近似
def func_c1(x, a, b):
    return a*x + b
res_c1 = optimize.curve_fit(func_c1, x, y)#係数

# 2次式の近似
def func_c2(x, a, b, c):
    return a*x**2 + b*x + c
res_c2 = optimize.curve_fit(func_c2, x, y)

# 3次式の近似
def func_c3(x, a, b, c, d):
    return a*x**3 + b*x**2 + c*x +d
res_c3 = optimize.curve_fit(func_c3, x, y)
```
Google HomeとIFTTT(Gmail & Dropbox)で双方向コミュニケーシ

# やりたいこと
Google HomeとGmailで双方向のコミュニケーションをやりたいと思います。

1. Google Homeに声でしゃべる→メールが飛ぶ
2. メールで返信する→Google Homeがメールを読み上げてくれる

「Google Homeに声でしゃべる→メールが飛ぶ」はIFTTTだけで簡単にできて、
家にいる家族がしゃべると、メールでその内容を教えてもらえるというのはやっていました。
それだけだと、メールアドレスを持っていない子供には返信できません。

そこで、特定のルールのメールに反応して家に置いてあるGoogle Homeがメールを読みあげてくれるようにしたいと思います。

# 方法1. Google Homeに声でしゃべるとメールを送る
IFTTTだけでできます。

## this
Google Assistantの`Say a phrase with a text ingredient`を使用します
ここでは、「OK．Google パパにメール」の後にメールで送りたい内容を話せるようにします。

## that
Gmailの`Send an email`を使用します

こんな感じになります。
<img src="https://qiita-image-store.s3.amazonaws.com/0/31063/1c0f06d0-7493-0a38-05e6-4313d1ca5eb4.png" width=50%>

「OK．Google パパにメール 何時頃着くの？」としゃべると、こんなメールが届きます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/31063/e6882a4c-4215-669f-af74-7b0d2e20a79d.png" width=100%>

でも、これだけだと、何時に着くか答えられませんね。

# 方法2. メールで返信する→Google Homeがメールを読み上げてくれる
IFTTTでは、特定のタグ付されたメールが届くと、Dropboxにそれを置くようにしました。
ここは工夫しどころで、Google Homeにしゃべらせるために、Google Homeとネットワーク的に通信できるところからNotifierでリクエストを出す必要があります。

今回はDropboxを使って、クラウドと自宅ネットワークの壁を超えたメッセージ連携をやります。
この辺のいろんな方法が取れるのがIFTTTの良いところかなと思います。

**Gmail --> IFTTT --> Dropbox --> Notifierスクリプト（自宅マシン） --> Google Home**

## this
Gmailの`New email in inbox labeled`を使います
`google home`というラベルの付いたメールが来たらアクションを起こします。
ラベルはGmail側で行います。ここでは特定のメールアドレスにメールが来たらラベルを付けるようにしています。

## that
Dropboxの`Create a text file`を使います
- ファイル名（File name）は`ReceivedAt`を使って、受信日時でファイル名が作られます。
- ファイルの本文（Content)は`Subject`と`BodyPlain`で、メールの件名と本文を出力します。
- Dropbox folder pathは、任意のパスです。

こんな感じになります。
<img src="https://qiita-image-store.s3.amazonaws.com/0/31063/12f6a30b-cbc9-3b9a-08d8-e6e9a7fe090c.png" width=50%>

メールが届くと、こんな感じにファイルが作られます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/31063/cd827a38-8821-7a20-129c-771b6e1b30b2.png)

## Dropboxで同期されたファイルを切っ掛けにNotifierを送るスクリプト
```
const googlehome = require('google-home-notifier')
const language = 'ja';

// ファイルを読み込んでgoogle homeに通知する関数を呼び出します
function readFile(path) {
    fs.readFile(path, 'utf8', function (err, data) {
	ghome_notify(data);
    });
}

googlehome.device('Google-Home', language); 

// 引数でもらったテキストをGoogleにしゃべらせます
function ghome_notify(text) {
	googlehome.notify(text, function(res) {
		console.log(res);
	});
}

// Dropboxでファイルが同期される場所を監視します
var chokidar = require("chokidar");
var watcher = chokidar.watch("./inbox/",{
    ignored:/[\/\\]\./,
    persistent:true
});

var fs = require('fs');

// ファイルが追加されるとファイルを読み込んでGoogle Homeへ通知する関数を呼び出します
watcher.on('ready',function(){
    console.log("ready watching...");
    watcher.on('add',function(path){
	console.log(path + " added.");

	readFile(path);
    });
});
```


# まとめ
やっぱりGoogle Homeにしゃべらせることができたら楽しいですね。
notifierのサンプルを触ってるだけで、いろいろ遊べました。
願わくばnotifierのプロセスがGoogle Homeの上で動いてくれたら、別途ラズパイを用意するみたいことをしなくていいのでうれしいですね。

しゃべらせる系はいろんな方がやっていて参考にさせていただきました。
[GoogleHome x IFTTT で、寝る前にかかとにクリームを塗る！](https://qiita.com/sitopp/items/89add216c500de5ace4e)
ngrokを使って、ローカルのラズパイ上でサービスを動かして公開。Dropboxでやるよりシンプルですね。

[新着メールを知らせてくれるGoogle Home](https://qiita.com/tetotetote/items/4d6ac866b716695fa4c9)
Firebaseをメッセージハブ的に使っていて、ローカルのラズパイからFirebase Listenerでデータの更新を検知されてます。
テスト実行時に手戻りしないための小ネタ

#ノーモア手戻り
皆さん、テストで手戻りした経験はありますか？
私はいっぱいあります。
テストをやっているときは基本的にコードを書かないと思いますので、
退屈に感じる人も多いと思います。

でも、テストは大切な作業です。素早くミスなくきっちり終わらせたいものです。
手戻りをできるだけ回避するためのTIPSを、自分なりにまとめてみました。

#前提の整理
この記事では、「テスト実行時に、何らかの失敗をして、テスト実行をやり直すこと」を「手戻り」と呼びます。

- そもそものユーザーストーリーが間違っていた
-  実装をするための設計にミスがあった
- 実装が間違っていた
- テスト仕様書が噓をついていた

といった、「テスト実行より手前の段取りに不備があったこと」を理由にした「やり直し」については触れません。

#1.テスト実行前にやること
####テスト準備の不備をつぶす
- 「前提条件」をリスト化し、すべて確認する
    - テスト実行環境
    - テスト対象のリソース 
    - テスト実行ユーザ
    - テストデータ
    - (他にもいろいろ)

経験上、テストの手戻りでいちばんありがちなパターンが、
「前提条件を間違えていた」です。

例を挙げると、

- ひとつ前のリビジョンでテストをしていた
- 環境Aでやらなければならないテストを環境Bでやっていた
- 「女性」ユーザ限定の機能を確認するテストなのに「男性」ユーザを使用していた

などです。

これらの前提条件の準備に間違いがあると、テストをすべてやり直しする羽目になってしまいます。状況によって「何を網羅すれば準備完了といえるのか」は変わりますが、例えばそれをリスト化することによって、抜け漏れを検知することができます。

特に、プロジェクトに入って日が浅い人は、モブプログラミングのような形で、グループで「前提条件のリスト」をレビューしてあげると良いと思います。

#2.テスト実行中にやること
####とにかく落ち着いて、一つずつ
- テストケースをひとつ実行するたびに、いま何をしなければいけないかを確認する
    - 前提条件
    - テスト実行手順
    - 期待値を確認するタイミング
    - 期待値と、OK\NGの判断根拠

先ほどの例に似ていますが、例えば、テストケース№1～100までが「男性」ユーザのテストケースで、№101からが「女性」ユーザのテストケースだったとします。
前提条件を都度チェックせず、№101以降も「男性」ユーザでテストを進めてしまうと、手戻りが発生します。

####アナログな手法を活用する
- テスト仕様書の黙読を避ける
    - いま自分が読んでいる箇所を「指さし確認」する
    - ついでに「声に出して読む」
    - 読んだところに「取り消し線」を引く
    - 紙に印刷してしまう

実行者が人間である限り、ヒューマンエラーは起きます。
「前提条件を確認したつもり(だけど確認が漏れていた)」「この手順を実行したつもり(だけど異なる手順を実行していた)」といったことです。
実行した箇所をツールが自動的に「実行しました」とチェックしてくれるようなツールがあれば嬉しいのですが、2017年現在は、まだそのようなツールは世の中に出回っていません。
とてもアナログではありますが、例えば指さし確認をすることで、自分の意識をその箇所に集中させることができます。

#3.テスト実行後にやること
####実行ミスがないかチェックする
- 結果の評価にツールを使う
 - 事前にユニットテストを自動化しておく
 - Excelなどの数式で比較する
 - 差分比較ツールを使う→テキストファイル、画像、PDFなど

ここでも、実行者が人間である限り、ヒューマンエラーは起きます。
「実行ミスがないかチェックする」と口でいうのは簡単なのですが、
「実行ミスが実行ミスであることに正確に気づく」ことはとても大変です。
ツールなどを使って、「嫌でもミスに気付く」仕組みを作っていければ望ましいと思います。

#おわりに
上記に書いたことを、すべて実行できるとは限らないと思います。
指さし確認をしていたら「変な人だなあ」と思われることもありますし、
そんな悠長なことをやっていられない局面もあります。
けれども、「急がば回れ」が原則だと私は考えています。
ノーモア手戻り。あなたにとってテストが楽しく、充実した時間になりますように。
【随時更新】入れているChrome拡張機能の一覧

#はじめに
自分用のメモなので特に詳しい解説はしていません。

#常に動作させているもの
- [R Chrome Extension - Chrome ウェブストア](https://chrome.google.com/webstore/detail/r-chrome-extension/nmabekdmfpblgbgplficnahfkekbggil?utm_source=chrome-app-launcher-info-dialog)
    - 自分の練習用に開発したもので、URLのコピーやコードのコピーに利用
- [Adblock Plus - Chrome ウェブストア](https://chrome.google.com/webstore/detail/adblock-plus/cfhdojbkjhnklbpkdaibdccddilifddb)
    - Web上の広告を非表示にするもの
- [SearchPreview - Chrome ウェブストア](https://chrome.google.com/webstore/detail/searchpreview/hcjdanpjacpeeppdjkppebobilhaglfo/related?utm_source=chrome-app-launcher-info-dialog)
    - 検索結果のページにWebサイトごとのプレビューを表示してくれる
- [Google 翻訳 - Chrome ウェブストア](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb)
    - 文を選択してGoogle翻訳をポップアップ表示

#必要に応じて有効にしているもの
- [iKnow! ポップアップ辞書 - Chrome ウェブストア](https://chrome.google.com/webstore/detail/iknow-%E3%83%9D%E3%83%83%E3%83%97%E3%82%A2%E3%83%83%E3%83%97%E8%BE%9E%E6%9B%B8/omfegkgipldobddijcpagdabgifghdgb?hl=ja)
    - 単語にマウスをあわせると辞書がポップアップ表示される
- [Grammarly: Free Writing Assistant](https://www.grammarly.com/personalize?breadcrumbs=true&utm_source=chrome&page=install&install=true&utm_medium=store)
    - 英文の文法ミスを指摘&改善してくれる拡張機能



#導入にあたって参考にした情報
- [【2017年最新版】Google Chromeを10倍魅力的にする拡張機能【おすすめ】 | Sub.colle](http://www.subcolle.com/entry/chrome_function/)
- [私のChromeの拡張機能を晒す（2017の秋） - Qiita](https://qiita.com/ayataka555/items/b54be3b5dbe1d7302a06)
- [業務効率を上げるためのChromeアドオン - Qiita](https://qiita.com/yunomi/items/e74e1e0c313c4a0faa01)
MacからWindows 7 home premiumを操作する。（Chrome最強）

powershellを書いてみようと思い、試そうと思った。
普段はMacBook airでコードを書いているので、ちょっと触りたいだけなのに、モニターつけて、キーボード出して、マウス用意してデスクトップ(Win7)をやるのは手間が多い。。。
かといって、MacBook AirにBoot Campするのもスペック的に辛い。
そこで、リモートでWindowsにアクセスする方法を探したのですが、情弱のため手間取ったのでメモ的に残しておくことにしました。


##Microsoft Remote Desktopを使ってみる。
そういうわけで、まずはググる。
すると、「***Microsoft Remote Desktop***」というのが出て来た。
<img width="200" alt="257525C1-8F88-44E3-B01B-F96A3E3C29BF.png" src="https://qiita-image-store.s3.amazonaws.com/0/185846/30108945-82aa-3c1d-008c-e8c967c9cdb8.png">

早速試してみた。
だがしかし、エラーでリモートできない。。。
![スクリーンショット 2017-12-09 8.58.01.png](https://qiita-image-store.s3.amazonaws.com/0/185846/52bff62e-0cb4-ebe9-7e8b-a2a9bc66fe1c.png)

win7の設定をいじってみるが、やっぱりダメ。。。
>[リモートデスクトップ接続ができない場合の対処方法 ( Windows 7 )](http://faq3.dospara.co.jp/faq/show/6302?category_id=251&site_domain=default#anc03>)


###そもそもhome premiumだとリモート非対応だった！
ググると、リモートはwin7home premiumだとダメだということが判明！
>![スクリーンショット 2017-12-09 9.35.26.png](https://qiita-image-store.s3.amazonaws.com/0/185846/30319ac5-4a94-3690-ab7c-2a0da2cce58c.png)
>https://andronavi.com/2014/07/327834

ググると、Concurrent RDP Patcherというのがヒットした。
バッチを当てればいけるみたい！
>http://boku-pocket.blogspot.jp/2012/03/mac-remote-desktop-windows7.html

***しかし、当ててもやっぱりダメだった。***

ググると、Windows Updateで機能しなくなったみたい。。。
削除すれば、出来るみたいだが、躊躇。
>[Concurrent RDP Patcherが動かなくなった](https://seous.info/jobs/windows/1172/)


##Chromeが最強だった。
一夜明け、会社で先輩に聞いてみたら、***Chrome使えばすぐだよ！***
えーーー！！！

>![スクリーンショット 2017-12-09 10.07.41.png](https://qiita-image-store.s3.amazonaws.com/0/185846/ba2f3822-e3c6-49ee-970d-d6d2b960b352.png)
>[Chrome リモート デスクトップ](https://chrome.google.com/webstore/detail/chrome-remote-desktop/gbchcmhmhahfdphkhkmpfmihenigjmpp?hl=ja)

***手順***
1. リモートデスクトップする側とされる側双方にChromeとChromeリモートデスクトップをインストールする。
2. リモートされる側で、Chromeリモートデスクトップを起動して、リモートを有効にし、PINを設定する。
3. リモートする側で、Chromeリモートデスクトップを起動して、リモートしたいPC名を選択する。
4. PINを入力して、接続する。

***完成！***
ＥＳＰ３２でＧＡＭＥエミュレーターを動かす(GAME少年編)

# 概要
ＥＳＰ３２でエミュレータを動かすシリーズ第三弾。今度はＧＡＭＥ少年です。
良さげな元ネタを探して、比較的判り易かった下記を移植しました。
[Gambit]　https://github.com/mattrubin/Gambit
これでハードを都合すればオレだけの携帯機が作れます。
第四弾をどうするかは、考えておりません。

#やること、やった事
ハードは
[ＥＳＰ３２でＧＡＭＥエミュレーターを動かす]https://qiita.com/hi631/items/a0dfb6ee91b90c028445
を見てください。ピンの配置も全く一緒です。

ソフトは今回も変更が多いのでGitHubに上げました。
[esp32-gbemu]https://github.com/hi631/esp32-gbemu

元のソフトはios用に作られているようなので、これを一旦Windows上で動かし、動作確認の上でESP32に移植しました。
ダウンロードして、COMポートと通信速度をボードに合わせてコンパイルしてください。
make flash して、Resetすれば動くと思います。

動作確認用としてはこんなものが使えます。http://www.gambitstudios.com/FreeSoftware.asp
ファイルのフラッシュへの書き込みは下記のコマンドで行います。
esptool.py --chip esp32 --port "/dev/ttyxx" --baud $((921600)) write_flash -fs 4MB 0x140000 xxxx.gb(gbc)
"/dev/ttyxx"、xxxx.gbは自分の環境に合わせましょう。
一応2MBまでは動作するはずです。

#今回苦労した所
今回もgbemuをnesemuのI/Oに接ぎ木して動かしています。
開発環境が全く違うので、コンパイルエラーの多さに一時は暗澹となりましたが、何とか持ち直しました。
取敢えず動けばいいという発想の元、下記のようになっています。
(1)パレットとして256KBもメモリーを使っており、ESP32では最初はコンパイルできませんでした。
　　64KBに圧縮しましたが、画面全てに対応していないので、妙な画面(主に背景)が出る場合が有ります。
　　LCD.Cの561行からの、パレットの反転処理を各画面に入れれば治ると思いますが、やってません。
(2)一応、ちゃんと画面も音も出てコントローラーで遊ぶことができますが、処理が不足気味で、画面が大きく動くと全体的に遅くなります。
(3)処理が遅くなり間に合わなくなると音が途切れます。その場合はspi_lcd.cの142行当たりの
　　.sample_rate=SNDRATE*166/(116*2),の116を大きくしてください。ただし音が伸びます。
(4)ノーマルではあまりに画面が小さかったので、ほぼLCD一杯に拡大しています。spi_lcd.cの322行当たりの
　　int x, y, xss, yss, widths, heights, mug=2;の2を1にして下さい。ノーマルサイズに戻ります。
(5)フレーム当たりの処理速度を確認可能です。spi_lcd.cの84行当たりの
　　//wccnt++; のコメントを外すと、シリアルに処理に要した時間が10us単位で表示されます。
　　Lp=(一周期時間) Fr=(フレーム処理) cpu=(CPU処理) Dsp=(LCD処理) Snd=(サウンド処理) Wt=(サウンド出力待ち)
　　1234と表示された場合は、12.34ms要した事になります。
　　なお、Wtが0になると音が途切れる可能性があります。

#その他

　上記記載のハード、ソフトは無保証であり、各自の責任においてご利用願います。
　中身がよく判らないのに、動けばＯＫという勢いで改変していますので、何か傷を抱えているかもしれません。
　また蛇足ですが、世の中にはフリーでないプログラムも存在しますので、注意の上で遊ばれることをお勧めします。
Ruby技術者認定試験 Silver (2.1): Rubyの予約語

#まえがき
Ruby技術者認定試験Silverの試験勉強の一環。
Rubyの予約語についてはすでに先達がおられます。
　　[Ruby 予約語](https://qiita.com/daisuke-team-ai/items/7b1a58b343f6c737ca3f)
カテゴリ分けと説明（Rubyリファレンスマニュアル（2.1）に基づく）
をつけることで差別化したつもりです。

説明は一行で統一したかったのですが、制御構造とかはまとめきれませんでした。


# 演算子式
and
　　論理積（かつ）
or
　　論理和（または）
not
　　否定（ではない）


#変数と定数 (擬似変数)
self
　　現在のオブジェクト
nil
　　NilClassクラスのインスタンス
true
　　TrueClassクラスのインスタンス
false
　　FalseClassクラスのインスタンス
\_\_FILE\_\_
　　現在のソースファイル名
\_\_LINE\_\_
　　現在のソースファイル中の行番号
\_\_ENCODING\_\_
　　現在のソースファイルのスクリプトエンコーディング


#制御構造
do
　　do ... end でブロックを示す。 
　　while, until, for では do を省略できる。
end
　　ブロック構造を終える（Ruby用語集より） 

(条件分岐)
if
　　式　　：右にある式を評価した結果が真であるとき、then以下の式を評価
　　修飾子：右辺の条件が成立するとき、左辺の式を評価してその結果を返す。
then
　　if, unless と共に使う。省略可能
elsif
　　if と一緒に使う。ifの条件式が偽のときにelsifの条件を評価する。
　　unlessに対しては指定できない。
else
　　if, unless と一緒に使う。
　　全ての if と elsif の条件式が偽であったとき else 節があればその式が評価される。
　　unless の条件式が真であったとき else 節があればその式が評価される。
unless
　　式　　：右にある式を評価した結果が偽であるとき、then以下の式を評価
　　修飾子：右辺の条件が成立しないとき、左辺の式を評価してその結果を返す。
case
　　後に置いた式に対する一致判定による分岐を行う。
when
　　case式と一緒に使う。後に置いた式とcaseが指定した式を比較

（繰り返し処理)
while
　　後に置いた式を評価した値が真の間、本体を繰り返し実行
until
　　後に置いた式を評価した値が真になるまで、本体を繰り返して実行
for
in
　　以下の形で式を評価した結果のオブジェクトの各要素に対し本体を繰り返し実行
```　　for lhs... in 式 [do]
　　　式..
　　end
```

break
　　最も内側のループを脱出する。
next
　　nextはもっとも内側のループの次の繰り返しにジャンプする。
redo
　　ループ条件をチェックせず、現在の繰り返しをやり直す
retry
　　rescue節でbegin式をはじめからもう一度実行する。
　　※筆者注：リファレンス上でも繰り返しの項目に分類されています。

（例外処理）
begin
　　例外処理の開始を示す。
rescue
　　例外を捕捉
ensure
　　begin式を終了する直前に必ず評価される。
（その他）
return
　　式の値を戻り値としてメソッドの実行を終了する。
BEGIN
　　初期化ルーチンを登録（トップレベル以外で書くとエラー）
END
　　後始末ルーチンを登録


#メソッド呼び出し
super
　　現在のメソッドがオーバーライドしているメソッドを呼び出す。
yield
　　ブロック付きメソッドでブロックを呼び出す。


#クラス／メソッドの定義
class
　　クラスを定義する。
module
　　モジュールを定義する。
def
　　メソッドを定義する。
defined?
　　式が定義されていなければ偽、定義されていれば式の種別を表す文字列を返す
undef
　　メソッドの定義を取り消す。
alias
　　メソッド、グローバル変数に別名をつける


#オマケ：予約語っぽいけど予約語じゃないもの
raise
　　Kernel.#raise　例外を発生させる
include
　　Module#include　クラスに機能を追加
extend
　　Object.extend　特定のオブジェクトだけにモジュールの機能を追加
catch
　　Kernel.#catch　throw との組み合わせで大域脱出を行う。
throw
　　Kernel.#throw　catchとの組み合わせで大域脱出を行う。
\_\_END\_\_
　　プログラムの終わりを示す（前後に空白があると認識されない）
Web上からの解析データ取得（スクレイピング、最小単位のサンプルコード）

備忘録。

目的
---
まずは、なぜスクレイピングをやってみたくなったのかの理由について。

自然言語処理を行うにあたって、現在は写経等を繰り返し、用意された整ったデータを利用しているが、そろそろ生のデータを扱ってみたくなったため。

いろいろなサイトを調べてみたけど、パーサーを指定するための書式をうまく見つけられなかったので、書式を残す意味合いで。

まずは、小さなサンプル的な処理から。
次のブログを参考にしました。ありがとうございます。
https://runble1.com/scraping-beautifulsoup/
http://hideharaaws.hatenablog.com/entry/2016/05/06/175056

環境は、
Windows10 (Bash on Ubuntu on Windows)
python3.6
anaconda3-5.0.1
jupyter notebook

ではさっそく、

```
$ pip install beautifulsoup4
$ pip install lxml
$ pip install cssselect
```
成功。

簡単に調べてみると、「beautifulsoup4」が根本的に必要なもののようで、「lxml」と「cssselect」は、拡張機能のような感じ。

ソースコートは、参考サイトほぼそのままですが、パーサー（lxmlなど）の指定が重要っぽいので、いくつか試してみる。

パーサーの指定
---
まずはエラーが出るパターン。パーサの指定なし。

```
#https://runble1.com/scraping-beautifulsoup/

from urllib.request import urlopen
from bs4 import BeautifulSoup
 
html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bsObj = BeautifulSoup(html.read())#Y エラーがでるパターン。
print(bsObj.h1)#h1タグで挟まれた部分の出力

#出力結果
#The code that caused this warning is on line 193 of the file /home/*****/.pyenv/versions/anaconda3-5.0.1/lib/python3.6/runpy.py. To get rid of this warning, change code that looks like this:
# BeautifulSoup(YOUR_MARKUP})
#to this:
# BeautifulSoup(YOUR_MARKUP, "lxml")
#  markup_type=markup_type))
```

次にエラーが出ないパターン。パーサの指定あり。

```
#https://runble1.com/scraping-beautifulsoup/

from urllib.request import urlopen
from bs4 import BeautifulSoup
 
html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bsObj = BeautifulSoup(html.read(), "lxml")
#bsObj = BeautifulSoup(html.read(),"html.parser")#これもOK。
#bsObj = BeautifulSoup(html.read(), "html5lib")#これもOK。

print(bsObj.h1)#h1タグで挟まれた部分の出力

#出力結果
#<h1>An Interesting Title</h1>
```

以上。
[Excel VBA]複数セルに値を一発で書き込み(Rangeと配列のサイズが違ったら)

# 実験してみる
前回、[[Excel VBA]複数セルに値を一発で書き込み](https://qiita.com/jinka1997/items/fb6d7cd1fa53cf82d7f9)でやってみたことについて、
「あれ、Rangeと配列のサイズが違ったらどうなるの？」と思って、実験。

## Rangeと配列のサイズが同じとき
### コード
Rangeと配列のサイズが合ってる状態`Set r = w.Range("B2").Resize(RowSize, ColumnSize)`

### 実行結果
B2～F11に書き込みがされます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/221879/f5b86929-5fc7-b820-eece-083ef131c4c6.png)

## Rangeを狭くしてみた。
### コードを書き換え
Rangeを一列狭くしてみる。`Set r = w.Range("B2").Resize(RowSize, ColumnSize - 1)`

### 実行結果
Rangeの範囲にだけ書き込まれた。Rangeで指定されていないF列は書き込みなし。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/221879/68f58df6-6df2-1ed4-c6f4-4afa76a6674c.png)

## Rangeを広くしてみた。
### コードを書き換え
Rangeを一列広げてみる。`Set r = w.Range("B2").Resize(RowSize, ColumnSize + 1)`

### 実行結果
二次元配列上にない部分(G列)が「#N/A」に。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/221879/20578127-b941-2627-e83c-b7d300ee3c87.png)
Parcel触って見た（React × typescript）

昨日、[Parcel触ってみた（React編）](https://qiita.com/haradakunihiko/items/46419e8d73a2a25d6405)を書いんたんですが、ちょうど昨日Parcelがtypescriptに対応したので、React × typescriptをParcelで書いて見ます。

まずはReactとtypescriptをインストールします。

```
# まだ入れてなければparcelもインストール
npm install -g parcel-bundler

npm install --save-dev typescript

npm isntall --save react react-dom @types/react @types/react-dom
```

次にtsconfig.jsonを準備します。

```json:tsconfig.json
{
  "compilerOptions": {
    "jsx": "react"
  }
}
```

そしてindex.html

```html:index.html

<html>
  <body>
    <div id="app"></div>
    <script src="./assets/ts/index.tsx"></script>
  </body>
</html>
```

エントリーポイント

```ts:index.ts
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Application from './Application';

ReactDOM.render(<Application />, document.getElementById('app'));
```

コンポーネント

```ts:Application.tsx
import * as React from 'react';

export interface HelloProps { name: string; }

class Application extends React.Component<HelloProps, {}> {
  render() {
    return (
      <div>
        <h1>Hello {this.props.name}</h1>
      </div>
    );
  }  
}

export default Application;

```

そして実行。

```
parcel ./index.html
```

HMRをしたい場合は[Parcel触ってみた（React編）](https://qiita.com/haradakunihiko/items/46419e8d73a2a25d6405) と同じように `react-hot-loader` の対応でOKです。

簡単すぎる。。
emacsのorg-modeでFizzBuzz

これは、FizzBuzzアドベントカレンダー10日目の記事です。

emacsのorg-modeでは、単にアウトラインドキュメントを書くだけでなく、ソースコードをうめこんだり、表を作成したりと高度な機能を搭載していることが世間に広く知られています。
そして、org-modeのテーブルでは、表の値を利用して表計算をすることもできます。

今年のemacsアドベントカレンダーの7日目の話も、org-modeによる表計算の話でした。
[Emacs の org-mode は表計算もできてしまう]("https://qiita.com/yynozk/items/36a590b49a9237907335")

私が前振りとして書こうと思ってたところは、すべてこちらに書いていただいているので、org-mode？ org-modeで表計算？ という方はこちらをご覧ください。

さて、org-modeの表計算ですが、四則演算や合計等の基本的な計算だけでなく、任意のemacslispを式に投入することができます。
つまりこういったことができるわけですね。

![org-modeでFizzBuzz](https://qiita-image-store.s3.amazonaws.com/0/34657/73d6218d-2f50-cb14-b180-546e5a11e668.png)

$2というのはエクセルでいうところのB:Bのようなものです。A列の値をもとにB列の値を設定しているわけですね。
A列の値を、15で割った余りが0ならFizzBuzz、5で割った余りが0ならBuzz、3で割った余りが0ならFizz、すべてマッチしなければ値をそのまま、をB列の同じ行につっこむ、というように、これが一番素直だと思います！

式は、`C-c C-c`で評価できるので実行してみるとこんな感じ
![GIF.gif](https://qiita-image-store.s3.amazonaws.com/0/34657/3619c70d-db7c-b4cc-30a2-b56ec470ecfe.gif)

簡単かつ便利ですね。

ぜひあなたの生活もプレーンテキストにしましょう
AzureのパブリックIP範囲

## 公式サイト

* [Azure ネットワーク インターフェイスの IP アドレスの構成 | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/virtual-network/virtual-network-network-interface-addresses#assignment-methods)


![スクリーンショット_2017-12-10_09-42-58.png](https://qiita-image-store.s3.amazonaws.com/0/25728/c9375f86-0489-3901-5d2a-850508e31851.png)

## パブリックIP割当範囲が書かれた xml をダウンロード

![スクリーンショット_2017-12-10_09-43-48.png](https://qiita-image-store.s3.amazonaws.com/0/25728/eee2d0c4-7fd8-1538-0c42-b1b8144e8777.png)

ダウンロードした`PublicIPs_20171205.xml` を開くと一覧が確認できる。
※ 割当範囲が追加される可能性はある。

![スクリーンショット_2017-12-10_09-44-31.png](https://qiita-image-store.s3.amazonaws.com/0/25728/b4a547d1-79b4-25e9-826f-762b47f39605.png)


## パブリックIPの変更タイミング

* [Azureの仮想マシンでは、パブリックIPアドレスを固定できますか？ | Azure相談センター - ソフトバンクC&S](https://licensecounter.jp/azure/blog/faq/20160225-2.html)

> Azure App Serviceを利用してWebアプリやモバイルアプリを作成すると、「***.azurewebsites.net（***は任意）」というFQDN（Fully Qualified Domain Name＝完全修飾ドメイン名）とそれに紐づくパブリックIPアドレスが自動的に割り当てられます。これによりユーザーは、FQDNを使ってインターネット経由でアプリにアクセスすることが可能になるわけです。割り当てられているパブリックIPアドレスはAzureポータルから確認できるようになっており、azurewebsites.netの代わりに独自ドメイン（カスタムドメイン）の使用もサポートしています。
やはりお前らの継承は間違っている。

<p>ほぼ同じコードが複数の箇所に存在している場合、それを共通化すること自体は推奨されることだと思う。ただ、共通化の手法としてクラスの継承を使い、基底クラスに共通コードを実装する場合は手を動かす前に考えた方がいいと思う。オブジェクト指向という名前からも関連があるものがクラス化されるものだと思うが、共通化目的の場合、関連がないものも継承関係に含めてしまっていないかという事を。</p>

<p>これから失敗の事例を説明していく。</p>

<p>共通コードを〜Baseという名前で規定クラスで実装する。</p>

```swift
class MyBase {
    func aaa() {
        bbb();
    }
    
    func bbb() {
    }
}
 
class Xxx : MyBase {
    override bbb() {
    }
}
 
class Yyy : MyBase {
    override bbb() {
    }
}
```

<p>派生クラスの異なる部分をbbb()メソッドで実装する。この瞬間はうまくいっているように見える。</p>

<p>派生クラスXxxとYyyは関係が薄い場合、異なる方向で仕様が変わったとする。そして、上記のコードで都合が悪くなったとする。そんな時、以下のような修正をしてしまわないか？</p>

```swift
class MyBase {
    func aaa() {
        if n == abc {
            bbb(2);
        }
        else {
            bbb(1);
        }
    }
    
    func bbb(kind: Int) {
    }
}
 
class Xxx : MyBase {
    override bbb(kind: Int) {
    }
}
 
class Yyy : MyBase {
    override bbb(kind: Int) {
    }
}
```

<p>基底クラスに派生クラスを考慮したコードが入ってしまう。</p>

<p>この問題を解消するために、基底クラスと派生クラスの間に中間の基底クラスを作成してしまう。そしてクラスの数の大爆発と派生クラスのコードを読んでも意味が分からない。</p>

<p>この問題の回避は難しい。指摘しても、コードは共通化するものだ。逆にこの手の事をやってしまう人は、積極的にコード構成に意見する場合があるし。</p>

<p>こんな事を投稿してしまったので、マサカリがブーメランとなって自分のところに飛んでこない事を祈っている。</p>

関連情報
<a href="https://qiita.com/advent-calendar/2017/cocoa">Cocoa Advent Calendar 2017</a><br />
<a href="https://cocoa-kanto.connpass.com">Cocoa勉強会 BUKURO.swift (connpass)</a><br />
<a href="https://atnd.org/groups/cocoa-study">Cocoa勉強会 BUKURO.swift (ATND)</a><br />
<a href="http://cocoa-study.peatix.com">Cocoa勉強会 BUKURO.swift (Peatix)</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk>note</a><br />
<a href="https://qiita.com/m_yukio>Qiita</a><br />
OSM 日本ベクトルタイルを ArcGIS API for JavaScript で消費する

[ベクトルタイル Advent Calendar 2017の10日目](https://qiita.com/hfu/items/e7c0318bba67827d4327)でご案内した OSM 日本ベクトルタイルを[ArcGIS API for JavaScript 4.5](https://developers.arcgis.com/javascript/index.html)で消費するための HTML コードは、次の通りになります。

```html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>jp1710_aajs</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
<style>
html, body, #map {padding: 0; margin: 0; height: 100%; width: 100%; overflow: hidden;}
</style>
<script src="https://js.arcgis.com/4.5/"></script>
<script>
require(["esri/views/MapView", "esri/Map", "esri/layers/VectorTileLayer"],
function(MapView, Map, VectorTileLayer) {
  map = new Map({layers: [new VectorTileLayer({url: "https://hfu.github.io/jp1710/style.json"})]})
  view = new MapView({center: [138.731389, 35.362222], zoom: 5, container: "map", map: map})
})
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
```
このコードは、[gh:hfu/jp1710_aajs](https://github.com/hfu/jp1710_aajs/blob/master/index.html)に置いてあり、gh-pages で[デモサイト](https://hfu.github.io/jp1710_aajs/)もホストしています。現時点で ArcGIS API for JavaScript は、Mapbox style レベルで Mapbox GL JS との互換性を維持していますね。
いつの間にかいらすとやさんが...

#はじめに
この記事は[いらすとや Advent Calendar 2017](https://adventar.org/calendars/2356)の 12/10 に向けて書いたものです。

#出会い
LT用のイラストを探していた時に出会いました。

最初、いらすとやさんとは知らずに使っていたのですが、あちこちのLTで見かけるようになり、いらすとやさんであることがわかりました。

#好きな一枚
どこに使うんじゃって感じですが...
![kids_chuunibyou_girl.png](https://qiita-image-store.s3.amazonaws.com/0/103169/fa39fa08-4220-4f93-83d4-4fcc8dec3893.png)

[中二病でも恋がしたい！](http://www.anime-chu-2.com/)見てます。
block 要素からはみ出さないように改行する方法

css のプロパティで改行方法を指定できるのだが、いくつか異なる方法が有ったのでメモする。


```css
word-break: break-all;
overflow-wrap: break-word;
word-wrap: break-word;
```

`word-break: break-all;`の場合は空白が無くても改行はしてくれるのだが近くに改行可能な空白があっても無視して改行してしまう。

`overflow-wrap: break-word;`だと、改行可能な空白が無いときだけ単語の途中でも改行する動作になる。

`word-wrap`は`overflow-wrap`の別名とのことです。
Google Homeで帰宅時間になったら蛍の光を再生させる

# :beginner: はじめに
この記事は[オールアバウトアドベントカレンダー](https://qiita.com/advent-calendar/2017/allabout)10日目の記事です。

最近Google HomeとEcho dotを入手しまして、その便利さにまさに世はスマートスピーカー戦国時代だな〜と日々感じています。

今回は、散々やられているのでN番煎じネタだとは思いますが、帰宅時間になったら自動的に蛍の光を再生して「帰らなきゃ…」という気持ちにさせてくれるやつをGoogle Homeでやってみました！

# :pencil: 使用するもの
* Google Home
* PCまたはラズパイなどNode.jsを実行できる環境

# :smile: Google Homeに喋らせる

Google Homeに自発的に喋らせる方法として便利なライブラリがあります。Node.jsのライブラリである[google-home-notifier](https://github.com/noelportugal/google-home-notifier)です。
大体調べるとこのライブラリが使われているかともいます。

まずはサクッとディレクトリを作って、google-home-notifierを使える準備をしましょう。
このあたりの準備については下記の記事を参考にさせていただきました:bow:

[Google Home開発入門 / google-home-notifier解説 - Qiita](https://qiita.com/SatoTakumi/items/c9de7ff27e5b70508066)

```console
$ mkdir [ディレクトリ名]
$ cd [ディレクトリ名]
$ npm init // package.jsonが作成される
$ npm install google-home-notifier
$ npm install moment // 日付操作で便利なライブラリ
```

環境が整ったら`main.js`を作成し、サンプルコードを参考にGoogle Homeを喋らせてみます。

```js:main.js
var googlehome = require('google-home-notifier');
var language = 'ja';

googlehome.device('{{ここにGoogle Homeで設定したデバイス名を指定する}}', language);

googlehome.notify('こんにちは、Google Homeです。', function(res) {
  console.log(res);
});
```

# :loud_sound: Google Homeで音楽を再生する

次に、Google Homeで音楽を再生させる方法ですが、これもgoogle-home-notifierで実行することができます。
下記のように再生したい音楽のURL渡すと、自動的に再生します。
音楽ファイルはGoogle Homeから参照できる同一ネットワーク上などにアップロードしておくと良いのではないかと思います。

これだけでGoogle Homeに音楽を流すことができます。すごい簡単ですね :tada: 

```js:main.js
var googlehome = require('google-home-notifier');
var language = 'ja';

googlehome.device('{{ここにGoogle Homeで設定したデバイス名を指定する}}', language);

googlehome.play('http://ほげほげ/hotarunohikari.mp3', function(res) {
  console.log(res);
});
```

# :railway_car::runner_tone1: 帰宅時間の判定

音楽を流すことができたら、次はタイマーの設定です。
要件としては、例えば「平日18時になったら蛍の光を再生」だとします。

`setInterval`により定期的に現在時間を取得し、定時を過ぎていてかつ平日の場合のみ、Google Homeに音楽を再生させます。

こちらの実装方法については下記の記事を参考させていただきました :bow: 
[Google Homeに植物の気持ちをしゃべってもらいたい - Qiita](https://qiita.com/siwasu17@github/items/894ada839fa9d58cbbd6)


```js:main.js
var googlehome = require('google-home-notifier');
var language = 'ja';
var moment = require('moment');

googlehome.device('Google-Home', language);

const interval = 1000 * 60 * 60; // 1時間ごとに実行
setInterval(function() {
    let current = moment();
    if(isTimeToGoHome(current)){
        googlehome.play('http://ほげほげ/hotarunohikari.mp3', function(res) {
            console.log(res);
        });
        return;
    }
}, interval); 

// 帰宅時間かどうか判定
const isTimeToGoHome = function(currentMoment){
    console.log('帰宅時間かな？');
    let quittingTime = moment({hours: 18, minutes: 00});
    // 定時を過ぎてるかどうか判定
    if(!currentMoment.diff(quittingTime) > 0){
        console.log('まだ定時を過ぎていないようです。');
        return false;
    }

    // 休日だったら判定しない
    // 日:0, 月:1, 火:2, 水:3, 木:4, 金:5, 土:6
    if(currentMoment.day() == 0 || currentMoment.day() == 6) {
    console.log('今日は休日のようです。');
        return false
    }

    return true;
}
```

あとはこのスクリプトを`node main.js`で実行させ続けると、定時を過ぎると自動的にGoogle Homeが蛍の光を再生してくれます。

# 改善ポイント
これだとGoogle Homeはスピーカーとしての役割しかないため、あまりGoogle Homeでやる意味がないと思います。
なので、対話で設定できたりとか、帰宅時間が近づいてきたら部屋の照明を落としたりとか、そういう工夫をもう少ししたいところですね！
GraphQLに触れてみた

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

## 触れようと思ったきっかけ
Github APIがGraphQLを採用したということで存在を知って、[東京Node学園祭2017](http://nodefest.jp/2017/)での[GraphQLのセッション](https://speakerdeck.com/siakaramalegos/no-rest-for-the-weary-dot-dot-dot-introducing-graphql-nodefest-japan)でメリットを聞き、さらに興味を持ったため。

### GraphQLのメリット
+ 従来のREST APIであれば、複数回リクエストしなければ取得できないような情報を、GraphQLの場合は1回のリクエストで取得でき、通信が低コストで済む。
+ REST APIの場合、リクエストすると提供者側が定義した情報がレスポンスにすべて含まれるが、GraphQLの場合は利用者側が欲しい要素だけを指定でき、必要な情報だけを取得できるため、レスポンスが適切な量になる。

等々、便利な点があるそうです。

## 今回やってみた内容
+ GitHub上でマージされていない（Open）状態のプルリクエストをAPIで取得。
+ 取得した内容をSlack上で通知させてみる。

## クエリを作ってみる
最初は全くわからず、どうやって作るのか戸惑いましたが、[GitHubのGraphiQL](https://developer.github.com/v4/explorer/)（GraphQLをお試しできるブラウザ上のIDE）で組んでみると、クエリが試しやすく作りやすいです。
（実行前にエラーになるかどうかも判定してくれて大変便利です。）

また、[Migrating from REST](https://developer.github.com/v4/guides/migrating-from-rest/)というページにv3のAPI（REST API）に対応するGraphQLのクエリが書いてあって理解が進みました。

### 今回のクエリ
指定したリポジトリの最新10件のプルリクエストの中で、stateが「OPEN」になっているもののプルリクエスト番号を取得するようにしました。

```
{
  repository(owner: "${owner}", name: "${repo}") {
    pullRequests(last: 10, states:[OPEN]) {
      edges {
        node {
          number
        }
      }
    }
  }
}
```

（※　`${owner}`・ `${repo}`となっている部分は実際に参照したいリポジトリのオーナー名・リポジトリ名に適宜変更します。）

上記のクエリを投げると、レスポンスは下記のようなデータが返ってきます。

```
{
  "data": {
    "repository": {
      "pullRequests": {
        "edges": [
          {
            "node": {
              "number": 14
            }
          },
          {
            "node": {
              "number": 16
            }
          },
          {
            "node": {
              "number": 18
            }
          }
        ]
      }
    }
  }
}
```

## Slackに通知させてみる
とりあえずNode.jsでAWSのLambda関数にしてみました。
（コード自体は下記のGistに置いてみました。）
https://gist.github.com/nakano348/1f927f0cb189de30683b27e019f8f794

GraphQLでのリクエストをする場合は、[graphql-request](https://www.npmjs.com/package/graphql-request)が便利そうだったので使ってみています。

![graphql-sample-slack.png](https://qiita-image-store.s3.amazonaws.com/0/77692/12f6d5cb-573b-63b5-38ce-6c48e00ef871.png)

Lambda関数を実行してみると、地味ですが、上記画像のような通知が飛ばせるようになりました。
（通知メッセージに関しては、プルリクエストへのリンクを合わせて通知するなど、色々メッセージ内容は改修の余地がありますね:thinking:）

## まとめ
+ 最初はどうやってクエリを作るのか戸惑うものの、GraphiQLで実際に触ってみると理解が捗る。
+ 自分が指定した情報だけ返ってくるのというは、開発中に実際どんなデータが返ってきているのか内容を確認しやすくて便利に感じた。
MergePoint EMS WebGUI

* [GIGABYTE MergePoint WebGUI](https://www.servethehome.com/quick-gigabyte-motherboard-feature-web-bios-update/)
* [Rack Server - GIGABYTE](http://b2b.gigabyte.com/Rack-Server)

## WebGUIへのアクセス方法

https://ipaddress にアクセスすることで WebGUIにアクセスできる。

* 初期設定: admin : password

![Gigabyte-MergePoint-EMS-login.jpg](https://qiita-image-store.s3.amazonaws.com/0/25728/627be8ac-9631-02b2-75b0-d043283f62fb.jpeg)

言語の選択は英語と中国語のみ。

### EMS の Reboot

効果があるのか不明だが、EMSのRebootが用意されている。(サーバー自体は再起動されないのでサービスには影響ない。)
小さいがビープ音が鳴る。ログイン画面に戻る。

![スクリーンショット_2017-12-10_08-01-24.png](https://qiita-image-store.s3.amazonaws.com/0/25728/ccc086f0-e5ab-8643-20c4-fdf07a6cd989.png)

### firemware update

ファームウェアタイプがいくつもある。

![a.png](https://qiita-image-store.s3.amazonaws.com/0/25728/6b96a70a-5433-5966-d25e-57e378e43118.png)


### 本体LEDを光らせる

![スクリーンショット_2017-12-10_08-09-12.png](https://qiita-image-store.s3.amazonaws.com/0/25728/aab87237-95de-3bb8-8a7f-892797a227de.png)

### 電源OFF/ON (重要)

![スクリーンショット_2017-12-10_08-11-36.png](https://qiita-image-store.s3.amazonaws.com/0/25728/3eccf25d-fcc8-4817-72b8-59dbe33b035f.png)

* [コンピュータの電源投入・切断、システム起動・停止・再起動の英語表現](http://raven.air-nifty.com/night/2008/04/post_bdda.html)

### System Event Log 

![スクリーンショット_2017-12-10_08-16-41.png](https://qiita-image-store.s3.amazonaws.com/0/25728/1c3e22f7-664f-52a9-6ef5-ad8d90cd2de5.png)


### コンソール画面が確認できる

![スクリーンショット_2017-12-10_08-18-19.png](https://qiita-image-store.s3.amazonaws.com/0/25728/83c0eb7d-86e7-836f-d18d-55237941a04f.png)


## その他bios設定

* F10 でBOOTメニュー
よく使うWeb上のツール

# JSON
JSONきれい ～JSON整形ツール～
http://tools.m-bsys.com/development_tooles/json-beautifier.php

# XML
XML整形
http://tm-webtools.com/Tools/XMLBeauty

# 正規表現
Regexper
https://regexper.com/

Debuggex Beta
https://www.debuggex.com/

# Base64
https://www.base64decode.org/
実は内包表記を使わなくてもいい場合もある

この記事は [Pythonのコードを短く簡潔に書くテクニック Advent Calendar 2017](https://qiita.com/advent-calendar/2017/python-short-code) の10日目です。

# はじめに

Pythonでリストなどを作成する際には内包表記を使うことが多いです。
しかし実際には、内包表記を使わなくてもいい場面で使っているケースも少なくありません。

# 内包表記を使わなくてもいい例

[内包表記を使ってリストの作成を簡潔に書く]:https://qiita.com/tag1216/items/040e482f9844805bce7f

例えば、カレンダー1日目の[内包表記を使ってリストの作成を簡潔に書く]で最初に挙げた以下の例ですが、

```pycon
>>> [i for i in range(5)]
[0, 1, 2, 3, 4]
```

これは内包表記を使わずに`list()`で書くことができます。

```pycon
>>> list(range(5))
[0, 1, 2, 3, 4]
```

このほうが短く書けてスッキリします。

# 内包表記を使わなくてもいい条件

リスト内包表記の構文は以下のようになっています。[^1]

```py3
[expression for var in itr if filter_expr]
```

[^1]: 説明をわかりやすくするためにこの構文は簡略化しています。正確な構文は[Pythonドキュメント » Python 言語リファレンス » 6.2.4. リスト、集合、辞書の表示](https://docs.python.jp/3/reference/expressions.html#displays-for-lists-sets-and-dictionaries)を参照してください。

内包表記を使う必要がないのは、

- `expression`と`var`が同じ
- if節によるフィルター条件がない

の全てを満たす場合です。

この場合は`list(itr)`という書き方ができます。

辞書内包表記、セット内包表記も同様に`dict(itr)`、`set(itr)`で置き換えられます。

# 最後に

Pythonに慣れてくるとなんでも内包表記で書きたくなってしまいますが、本当に内包表記が必要なのか考えて使うようにしましょう。

---
Node.jsでPEG.jsでBrainf*ck

Node.jsでのBrainf*ckインタプリタ実装。[PEG.js](https://pegjs.org/)使用。
PEG.jsの勉強に作ってみました。PEG.js便利です。JSに馴染むぞぉ〜。

BF処理系として、工夫といえば工夫なのは、ループブロック構文[と]の対応を、実行時に命令列からスキャンするのではなく、パース/AST構築の段階でシンタックスの問題として解決するところ。まあ、普通に考えればそうなるべきな話ではあるのですが。

苦労したのは、1文字入力で、標準ライブラリを呼べばいいのかなと思ったら、見付けられなかったので作りました([別記事](https://qiita.com/uehaj/items/5d9fec1ba6cc4c76e378))。

require('./parser')しているところは、[PEG.js online](https://pegjs.org/online)で以下から生成させたパーサをparser.jsというファイル名でダウンロードし、同じディレクトリに保存してください。

```
code = (normal_insn / block_insn / otherchar) *

normal_insn = ch:[><+-.,] { return ch }
block_insn = '[' brk:block ']' { return brk  }

block = cod:code {
  return cod;
}

otherchar = [^><+-.,\[\]] {
  return undefined
}

```
実行例:

![bfjs.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/9979/a2428b6b-bb1e-2ff6-7ed0-c25ba2286b2a.gif)

以下、main.js

```js
const readline = require('readline');
const rl = readline.createInterface({input:process.stdin});
let buf = "";

function getchar() {
  if (buf.length == 0) {
    if (process.stdin.AtEndOfStream) {
      return Promise.resolve(null); // EOF
    }
    return new Promise((resolve, reject) => {
      rl.once('line', (line) => {
        buf = buf + line + "\n";
        resolve(getchar());
      });
    });
  } else {
    const result = buf.charCodeAt(0);
    buf = buf.substring(1);
    return Promise.resolve(result);
  }
}

/*
  code = (normal_insn / block_insn / otherchar) *

  normal_insn = ch:[><+-.,] { return ch }
  block_insn = '[' brk:block ']' { return brk  }

  block = cod:code {
  return cod;
  }

  otherchar = [^><+-.,\[\]] {
  return undefined
  }
*/
// generated with PEG.js from above peg syntax.
const parser = require("./parser.js"); 


const source = `
>>++++++++[->++++++++<]>>>>+++++++++[->++++++++++<]>[<<,[->+<<+<<+>>>]<<<[
->>>+<<<]>>>>>[->+>>+<<<]>[<<[->+>>+<<<]>>>[-<<<+>>>]<<[[-]<->]>-]>>[-<<<+
>>>]<<<<<<<[-<+<<+>>>]<[>>[-<+<<+>>>]<<<[->>>+<<<]>>[[-]>-<]<-]<<[->>>+<<<
]>>>>><[[-]>++++++++++++++++++++++++++++++++>[[-]<------------------------
-------->]<<]>>[-]<.>>]`;

const ast = parser.parse(source);

const memSize = 20;
let ptr = 0;
const memory = Array(memSize).fill(0);

async function run(code, prefix) {
  // console.log("run code=",code,'mem=',memory,'ptr=',ptr);
  for (const i of code) {
    // console.log("  ins=",i);
    if (Array.isArray(i)) {
      while (memory[ptr] !== 0) {
        await run(i, prefix+" ");
      }
    }
    else if (i === '>'){
      ptr += 1;
    }
    else if (i === '<'){
      ptr -= 1;
    }
    else if (i === '+'){
      memory[ptr] += 1;
    }
    else if (i === '-'){
      memory[ptr] -= 1;
    }
    else if (i === '.'){
      process.stdout.write(String.fromCharCode(memory[ptr]));
    }
    else if (i === ','){
      memory[ptr] = await getchar();
    }
  }
}

run(ast, "").then(()=>{
  console.log(memory);
  process.exit()
});
```
E2Eテストのboilerplateを書きました(SeleniumとZalenium)

このエントリは[Selenium/Appium Advent Calendar 2017](https://qiita.com/advent-calendar/2017/selenium)の10日目です。

### :point_up: はじめに
社内でE2Eテストを導入する流れになったので、他プロジェクトでも汎用的に使えるようにboilerplateを書いてみました。
いちおう社内で使ってるやつですが、運用し始めてからそんなに経っていないので、ベストプラクティスかどうかはあやしいところ。
また巷で話題の[Zalenium](https://github.com/zalando/zalenium)も試しています。

### :star: リポジトリ
https://github.com/re-fort/e2e-boilerplate

### :eyes: 技術選定
- Selenium
- WebdriverIO
- mocha
- power-assert

ブラウザだけだったら、TestCafeなんかもよさそうでしたが、アプリ周りのことを考えるとSeleniumにしといたほうが良いのではとなりました。
Seleniumは準備が大変そうなイメージがありましたが、公式でdockerイメージを配布してくれていたので環境構築が一瞬だったのも大きかったです。

他の3つに関しては、私がNode.jsに慣れているという理由です。

### :whale: docker-compose.yml
今回、公式のSelenium以外にもZaleniumを利用してテスト出来るようにdocker-compose.ymlを2つ用意しています。

### :question: Zaleniumとは
[公式](https://github.com/zalando/zalenium)に書いてあったことをまとめると、

- ZaleniumはSelenium Gridの拡張
- 公式のdocker-seleniumではなく、カスタマイズされたdocker-seleniumイメージを使用している
- カスタマイズされたdocker-seleniumイメージはChrome&FireFoxを内蔵しており、テストのビデオ録画機能などを提供している
- テストのリクエストを受けるとdocker-seleniumイメージを使ってノードを作り、
テストが終わると破棄される
- docker-seleniumが捌けないリクエストはSauceLabsとかに投げることが出来る

ということみたいです。

### :dark_sunglasses: どんな感じなの
テスト実行前
<img width="537" alt="Screen Shot 2017-12-10 at 6.00.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/98379/a2354a6c-0af7-c24b-9ab3-c2bcc721b5ee.png">

テスト実行中(ノードが増えてる)
<img width="540" alt="Screen Shot 2017-12-10 at 6.00.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/98379/298affc1-458c-4c23-94b7-e378e27123f2.png">

テスト実行中(VNCでテストの様子を見ることが出来る)
<img width="532" alt="Screen Shot 2017-12-10 at 5.44.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/98379/f6174368-d438-7277-67bb-9261107a8dd1.png">

テスト実行後(ノードが消えてる)
<img width="535" alt="Screen Shot 2017-12-10 at 6.14.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/98379/e520068a-a669-6e21-979e-4dbbe8d6e0fd.png">

テスト実行後(実行結果のビデオ&ログを残しておいてくれてる)
<img width="570" alt="Screen Shot 2017-12-10 at 6.01.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/98379/d64afafd-8b35-9120-aee9-69be6561a5e8.png">

めっちゃ便利ですね:sparkles:

### :skull: ハマったポイント
#### :scream: たまにブラウザを開こうとして固まる
原因の切り分けができてないけど、テストケースごとにブラウザを開こうとしていたので、テストケースを収集して1個の大きなテストとして実行するように変えました。
確実に良くないので、なんとかしたい...。

#### :scream: chromeOptionsが渡されない
ChromeDriver 2.3.2から`goog:chromeOptions`という名前に変わったみたいです。
真っ先にChromeDriverのページをみて、結果的にはちゃんと書いてあったんですけど、W3Cの新仕様にあわせたくらいしか書いてなくて、見逃してしまいました。
Seleniumの通信ログをみてたら、なんか新しいやつある〜となって気付きました。
W3Cの新仕様といっているのは[ここ](https://w3c.github.io/webdriver/webdriver-spec.html#dfn-extension-capability)だと思います。

以上となります。
このあとには、Zaleniumをk8sで動かしてみる話もあるみたいです。
楽しみですね:blush:
jupyter Notebookの紹介

アドベントカレンダーに投稿するネタを色々と考えていたんですが、色々と忙しく、とくに何もやっていなかったです。
(´･ω･`)
なので、最近良く使ってる jupyter Notebookという、ツールの簡単な紹介をしたいと思います。

# Jupyter Notebook とは

Jupyter Notebook (ジュピター・ノートブック) とは、プログラムを実行し、実行結果を記録できるツールです。主に、数値計算・データ解析を行うときに使われるツールですが当然、普通のプログラムにも使えます。
<img width="324" alt="スクリーンショット 2017-12-10 06.30.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/83335/a176b180-fe54-64c1-5b84-34480a909bb9.png">

もともとは、 IPython Notebook (アイパイソン・ノートブック) と呼ばれていて、Pythonを実行するためのツールでしたが、今はいろいろな言語に対応させることができます。
<img width="280" alt="スクリーンショット 2017-12-10 06.17.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/83335/fdbb90d6-a192-8c05-8234-e76e1f72f933.png">
(haskell勉強中ですが、jupyterでコード書いています、PHPはインストールしてないですが、当然PHPもjupyter上で使えます。)

プログラム内容や実行結果はnotebookという形式のファイルに保存され、再利用が可能です。
また、markdown言語が、使えますので、みたいなものも作成可能です。
簡単なプログラムやちょっとした繰り返し作業は、jupyter Notebookを使って作業しています。

# インストール
Pythonをインストールしていることが前提です。

1.インストール

```bash
pip install jupyter
```

2.起動

```bash
jupyter notebook
```
※最近はデフォルトでパスワード設定しないとアクセスできないので注意が必要
[参考] (https://qiita.com/SaitoTsutomu/items/aee41edf1a990cad5be6 )

起動後
http://localhost:8888 にアクセスすると一番上の画面にアクセスできると思います。[^注意1]

デフォルトではPythonのみ実行可能です。
[Jupyterでphpを使えるようにする in Windows 10](http://theartofzero.php.xdomain.jp/jupyter%E3%81%A7php%E3%82%92%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B-in-windows-10-1461/)


# 使ってみる

左上の「New」をクリックし、使用言語を選択しnotebookを作成します。

<img width="1202" alt="スクリーンショット 2017-12-10 07.41.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/83335/6cfad3b7-85ad-770b-99dc-8006e6efa74d.png">

作成後の notebookです。何も書かれていません。
右上にある「Untiled」をクリックするとファイル名を編集できるので、適当に名前を編集します。

<img width="1249" alt="スクリーンショット 2017-12-10 07.47.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/83335/c263fe08-1efd-6f31-0c2a-5feb658aff12.png">

コードを記述し実行します。（実行するセルを選択してSHIFT+ENTER）
結果はセルの下に表示されます。[^2]

<img width="652" alt="スクリーンショット 2017-12-10 07.53.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/83335/750ffefa-ab9e-4c45-40b5-53e41854793b.png">


# 最後に
駆け足ではありましたが、jupyter notebookを紹介しました。
トライアンドエラーが容易なので、ロジックを考えるときや、新しい言語を勉強するとき（jupyterで実行できるように設定するまでが大変かも）にすごく力を発揮すると思います。


時間があれば、もっと詳しい内容を追記していきたいと思います。


[^注意1]: 起動しているので上の方法は一般的なやり方をのせています。自身の環境はDockerコンテナ上で動かしています。

[^2]: jupyter notebookはプログラムの実行をセル単位で行います。セルは、最後尾のセル上でSHIFT+ENTERを押すと、増やすことができます。
Ansibleでユーザ管理

この記事は<a href="https://qiita.com/advent-calendar/2017/relux" target="_blank">Relux Advent Calendar</a>10日目の記事です。

サーバを増やす時やユーザを追加する時など、サーバの数やユーザ数が多ければ多いほどコマンドでの実行は辛い作業となります。
ユーザをAnsibleで管理していれば、各サーバに対してplaybookを実行するだけなのであまり手間がかかりません。

## 実行する内容
- (必要であれば)グループの作成
- ユーザの作成
    - ログイン用の公開鍵の登録
- (必要であれば)sudoersへの追加

以上の内容を実行するplaybookを作成します。

## 作成するファイル
relux_developers というグループに所属する ohsuka というユーザを 172.16.100.1 というアドレスのサーバに作成する例です。

### 構成
```
hosts
roles/
┗ user/
  ┣ authorized_keys/
  ┃ ┗ ohsuka
  ┗ tasks/
    ┗ main.yml
site.yml
```

### 内容
```text:hosts
[target]
172.16.100.1
```

```text:rolses/user/authorized_keys/ohsuka
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDaq4REfnEy7TFRfc33fE15GkNJuhRSk7FDdwcGI8Q4hxDbJHe/GNpfVVa9vq2yxN9bCioTYSrLzYlbbh19v+svxXp7PEK66dKDSOL+ZcYZxQOAPQIA1AFyJIyf/AvIubHNBNQvSuvH4CXcdZiBOTQNpNCWh/ABYg1jFDODVWV6EQAlCftyTz6XwjanKLxW0hy85DssXZ+UcpWx9x9T91LyvbHI2cHx/DqlRA++zgVkPgT+1yZ4BSZm8TDtqC1PWvDAB1Xls4OAaovkQep7CYIldVhR/FUNGcBpM/ACvTX2R1pgZR1Tn6xn4HP1eFYt8Wlwb6Y1wNNj0NweNQUGW/VYwMU+q6RenOdF8Pe293kWrpXS9pja36Pto4lmqqhaDoKWB+tTdID+dhGkjUPRC7VamxE0DXZ7TMALHq81vakgRp4FDBGcb73gCxbyDP8pRtECwRgUc2LvCY/XnnJo4FXYl3jZA51YfhU0nT7D8cneQOPiODo3kEgaDjeB3ShyTwDbwXbwHVH0HLvnCDnpd1Q5q68FBpLfJbwAf6djpdnYhNmP5cUzJUH/PQ1zMmVwG/viHaV6pnAfmbngU9Lq/roE5cOyBFnWJ1AgQ3i2KSmj0HM0jxa5pvw9AJVtme8F4MwvsaeooNAEZgxcThIESMe3pI1houpulI9TMyda80PX8w== ohsuka@localhost
```

```roles/user/tasks/main.yml
- name: create group relux_developers
  group:
    name: relux_developers
    state: present
- name: create user ohsuka
  user:
    name: ohsuka
    state: present
    group: relux_developers
    shell: /bin/bash
- file:
    path: /home/ohsuka/.ssh
    owner: ohsuka
    group: relux_developers
    state: directory
    mode: 0700
- name: set public key to login ohsuka
  copy:
    src: roles/user/authorized_keys/ohsuka
    dest: /home/ohsuka/.ssh/authorized_keys
    owner: ohsuka
    group: relux_developers
    mode: 0600
- name: add ohsuka to sudoers
  lineinfile:
    dest: /etc/sudoers
    backup: yes
    state: present
    regexp: '^ohsuka'
    line: 'ohsuka ALL=(ALL) NOPASSWD: ALL'
```

```site.yml
- hosts: all
  sudo: true
  roles:
    - role: user
```

### main.ymlの解説
<a href="http://docs.ansible.com/ansible/latest/group_module.html">groupモジュール</a>でグループを作成します。
システム上にすでにそのグループが存在すれば何もしません。

<a href="http://docs.ansible.com/ansible/latest/user_module.html" target="_blank">userモジュール</a>でユーザを作成します。
groupオプションで所属するグループを指定します。
shellオプションを指定しなかった場合には、システムのデフォルトのシェルがログインシェルとなります。

<a href="http://docs.ansible.com/ansible/latest/file_module.html" target="_blank">fileモジュール</a>で `~/.ssh` ディレクトリを作成します。
sshdの仕様上、`~/.ssh`のパーミッションは`0700`(`drwx------`)である必要があります。

<a href="http://docs.ansible.com/ansible/latest/copy_module.html">copyモジュール</a>で公開鍵を設置します。
公開鍵は`roles/user/authorized_keys/`以下にユーザごとに置くようにしました。
sshdの仕様上、パーミッションは`0600`(`-rw-------`)である必要があります。

<a href="http://docs.ansible.com/ansible/latest/lineinfile_module.html" target="_blank">lineinfileモジュール</a>でsudoersへの追記をします。
記述を間違えると最悪の場合誰もsudoできなくなるので、変更・追記する場合には壊れても良いような環境で一度試した方が安全です。

## 実行
```
ansible-playbook -i hosts site.yml
```
ベクトルタイルはCORSしよう

# ベクトルタイルは HTTPS で CORS しよう
タイルは自分のドメインのサイトで消費するだけではなく、他のドメインのサイトでも消費してもらった方が面白いです。他のドメインのサイトでも消費してもらえるベクトルタイルを提供するためには、次の２点をクリアしておくことがとても望ましいです。

1. ベクトルタイルを消費するサイトが HTTPS で提供されているときに mixed content になって問題が生じないよう、ベクトルタイルは HTTP ではなくて HTTPS で提供されていることが望ましいです。
2. ベクトルタイルを他のドメインで消費してもらうようにするためには、クロスオリジンリソース共有（Cross-Origin Resource Sharing; CORS）を有効にする必要があります。

上記のうち、1. を実現する方法はほぼ自明ですが、2.を実現するとはどういうことか、それほど知られているわけではないので、簡単にご紹介します。

# CORS されているとはどういうことか
CORS されているということは、ウェブブラウザがウェブの安全性のためにしかるべき手続きを取った時に、データを提供するサーバ側が、提供するコンテンツをドメインを超えて使用しても良いということを表明するということです。

プロトコルのレベルでの実際の手続きについては、例えば https://en.wikipedia.org/wiki/Cross-origin_resource_sharing が参考になると思います。

具体的な挙動の大雑把な理解の仕方は「サーバから access-control-allow-origin: * 」というレスポンスヘッダが戻る、というものです。地理院タイルのサーバに対して、http://www.example.com からのアクセスに対して CORS を許すか問い合わせる例を示すと次の通りです。

```sh
$ curl -X OPTIONS -H "Origin: http://www.example.com" -H "Access-Control-Request-Method: GET" -D - -o - https://cyberjapandata.gsi.go.jp/
HTTP/2 204 
date: Sat, 09 Dec 2017 21:07:52 GMT
access-control-allow-origin: *
access-control-allow-methods: GET, HEAD
server: AmazonS3
vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
age: 23
x-cache: Hit from cloudfront
via: 1.1 489b8983b91eb29fd0875b6f862935c2.cloudfront.net (CloudFront)
x-amz-cf-id: vKXd9x7vJOwqgqHm0RURTAJdJlFsK5QqWbb_5zecwjias3vfH3_pFg==
```

「access-control-allow-origin: * / access-control-allow-methods: GET, HEAD」というレスポンスヘッダが戻っていることから、地理院タイルのサーバは、GET と HEAD に対しては、CORS していることがわかります。

# gh-pages はこの要件をデフォルトでクリア
GitHub の gh-pages は「HTTPS で CORS」という要件をデフォルトでクリアしています。静的なコンテンツに限り、アクセス制限をかけることなく共有するというユースケースに特化するという gh-pages の思想からすると、このデフォルトは非常にセンスが良いと思います。gh-pages のプロダクトマネージャのこだわりがわかります。

GitLab Pages でも、https://gitlab.com/gitlab-org/gitlab-pages/issues/66 にあるように、CORS できるようにしているようですが、実際に CORS されているかについては、確認してみる必要があると思っています。
gh-pagesで OSM 日本ベクトルタイル提供

gh:openmaptiles/openmaptiles で生産したバイナリベクトルタイルを GitHub の gh-pages だけを使ってホストすることに成功していましたので、その方法を紹介します。結果からはじめて、各ステップを逆向きに紹介します。

# OSM 日本ベクトルタイル gh-pages サイト
今回解説するOSM 日本ベクトルタイルのサンプルサイトは、https://hfu.github.io/jp1710/ です。特に初回の読み込みの場合には、地図が表示され始めるまでに時間がかかるかもしれません。このサンプルサイトは gh-pages でホストされていて、もとのレポジトリは、https://github.com/hfu/jp1710 です。

同様に gh-pages を使った全国レベルのベクトルタイルとしては、eStat の [Chome (neighbourhood) level boundary polygon](https://github.com/nyampire/jp_chome_boundary) の[ベクトルタイル chome-vt](https://github.com/hfu/chome-vt) も作っています。

## 1GB を超えるベクトルタイルのデータセットを gh-pages でホストする
chome-vt の場合には、tippecanoe で作成した mbtiles ファイルを [fan-out.rb](https://github.com/hfu/chome-vt/blob/master/fan-out.rb) でレポジトリ内に展開し、それをプッシュすることで https://hfu.github.io/chome-vt/{z}/{x}/{y}.mvt という形でホストできました。OSM 日本ベクトルタイルの場合には、サイズが大きいために、もう一つ工夫が必要でした。

現時点で、GitHub の標準的なレポジトリのサイズの上限は 1GB です。このため、OSM 日本ベクトルタイルでは、ズームレベルごとにレポジトリを分割して配置することにし、https://hfu.github.io/jp1710_{z}/{x}/{y}.mvt というテンプレート URL で参照できるようにすることにしました。ズームレベルをレポジトリ名の一部にする、ということですね。

これを実現するために用意したレポジトリは、次の通りです。
- https://github.com/hfu/jp1710_0
- https://github.com/hfu/jp1710_1
- https://github.com/hfu/jp1710_2
- https://github.com/hfu/jp1710_3
- https://github.com/hfu/jp1710_4
- https://github.com/hfu/jp1710_5
- https://github.com/hfu/jp1710_6
- https://github.com/hfu/jp1710_7
- https://github.com/hfu/jp1710_8
- https://github.com/hfu/jp1710_9
- https://github.com/hfu/jp1710_10
- https://github.com/hfu/jp1710_11
- https://github.com/hfu/jp1710_12
- https://github.com/hfu/jp1710_13
- https://github.com/hfu/jp1710_14

### さらに大きなタイルセットをホストするとすれば...
さらに大きなタイルセットをホストするとすれば、おそらく x の mod でレポジトリを分けられるようにテンプレート URL の解釈系から作り変えるなどの工夫が必要そうです。それは、大掛かりな工夫になって、あまり現実的ではないかもしれません。なお、例えば gitlab のレポジトリサイズの上限はgithub よりも大きいようであり、gitlab page という仕組みもあるようなので、必要に迫られればそのような方向を追求するという線もあるかもしれません。

# 消費のためのコード（Mapbox GL JS）
今回ご紹介したベクトルタイルのテンプレート URL は https://hfu.github.io/jp1710_{z}/{x}/{y}.mvt であり、Mapbox style ファイルのサンプルは https://hfu.github.io/jp1710/style.json にあります。これを Mapbox GL JS を使って消費するための HTML コードは、次の通りです。

```html
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jp1710</title>
<link rel="stylesheet" type="text/css" href="https://api.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.css" />
<script src="https://api.mapbox.com/mapbox-gl-js/v0.34.0/mapbox-gl.js"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
//mapboxgl.setRTLTextPlugin('https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.1.0/mapbox-gl-rtl-text.js');
var map = new mapboxgl.Map({
  container: 'map', style: 'style.json',
  attributionControl: true, hash: true
});
map.addControl(new mapboxgl.NavigationControl());
</script>
</body>
</html>
```

なお、この HTML コードでは、フォントについても https://github.com/hfu/noto-jp でホストしているものを使っており、Mapbox さんのサーバインフラに頼ることなくベクトルタイルベースのウェブ地図を実現できることのデモにもなっています。