2018年8月2日 Planckキーボードを作ってみた 2018年4月15日 Hugoで作成したブログをPWA対応した(ホーム画面に追加のみ) 背景 PWA(Progressive Web Apps)自体は以前から気にはなっていたのですが、最近iOS11.3のSafari11.1から対応されるとのことで周囲でちょっと盛り上がってたので自分のブログに対応させてみたくなってしまったので対応させました。 今回説明するのはホームスクリーンにアイコンを設置できるようにするところまでです。 前提 公式サイトによるとバナーが出る条件は以下のようになっています。 * 次の情報が記述されたウェブアプリ マニフェスト ファイルが存在する。 - short_name(ホーム画面で使用) - name(バナーで使用) - 192x192 の png アイコン(アイコンの宣言には MIME タイプ image/png の指定が必要) - 読み込み先の start_url * サイトに Service Worker が登録されている。 * HTTPS 経由で配信されている(Service Worker を使用するための要件)。 * 2 回以上のアクセスがあり、そのアクセスに 5 分以上の間隔がある。 対象のWebサイトのhttps対応が必須なので やられてない方はLet’s Encryptなどを用いてhttps対応してください。 (手間みそですが、さくらVPSに導入する記事です。https://qiita.com/kz_morita/items/ba9c171633ca54d72d2a) やったこと https対応はすでにしているので今回やらなきゃいけないことは以下の二つです。 manifestファイルの用意 ServiceWorkerの登録 順に説明していきます。 manifest.jsonの作成 以下のようなjsonファイルを作成しました。 { "icons": [ { "src": "images/logo/logo-512.png", "sizes": "512x512", "type": "image/png" }, { "src": "images/logo/logo-256.png", "sizes": "256x256", "type": "image/png" }, { "src": "images/logo/logo-192. 2017年12月2日 Elixirで線形回帰してみた この記事はElixir Advent Calendar 2017の17日目の記事です。 最近始めたElixirで何かOutputしたいということで線形回帰のアルゴリズムを実装してみました。 リポジトリはこちら https://github.com/foresta/mlex.git Elixirでも機械学習できないこともない(かもしれない)ことを書いていこうかなと思います。 背景 最近の私の興味があるものとしてEilxirと機械学習があります。 Elixirはサンプルアプリや簡単なツールを制作した程度、機械学習はcourseraのコースを一通りやり本を数冊読んだ程度です。 今回はその両方の学習と、どうせ機会学習アルゴリズム実装するなら書きごごちの良いElixirで書いてみたいと思い実装してみました。 線形回帰とは データを元に線形モデルを作成しその線形モデルを用いて未知のデータを予測するものです。 図1はデータの次元が2次元の場合の線形回帰の概念を示し、×印が与えられたデータ、直線が学習した結果の線形モデルを表しています。 図1 線形回帰のサンプルグラフ 詳しくはこちらのサイトを参照してください。 https://qiita.com/ynakayama/items/5732f0631c860d4b5d8b http://gihyo.jp/dev/serial/01/machine-learning/0008 学習データ 今回学習には以下のデータセットを使用しました。 linnerud_physiological.csv linnerud_exercise.scv linnerud_physiological.csvには体重・ウエスト・心拍数等の身体的特徴データが、 linnerud_exercise.csvには懸垂・腹筋・跳躍に関するデータがあります。 今回は身体的特徴と、懸垂のデータで線形回帰をしてみます。 実装 使用したライブラリは以下のような感じです。 defp deps do [ {:matrix, "~> 0.3.0"}, {:csv, "~> 2.0.0"}, {:explotter, git: "https://github.com/foresta/explotter.git"} ] end ソースコードは以下のような感じです。 mlex/apps/sample/lib/linnerud.ex def run do # 1. load dataset features = load_linnerud_feature_dataset() targets = load_linnerud_target_dataset() # 2. setup featuresex pulses = features[:pulse] waists = features[:waist] weights = features[:weight] number_of_data = length pulses bias = for _times <- 1. 2017年7月7日 alfred上でshellを実行する 日頃開発をしていて、面倒な作業をshellにするのはよくやられていることだと思うが、 毎回ターミナルから実行するのがちょっと面倒だった。 自分はalfredというランチャーソフトをつかっていて、Alt + Spaceで簡単によびだせる設定にしているので、ここからshellを実行できないもんかなーと思って調べてみたらできたのでまとめてみる。 環境 OS X El Capitan Alfred 1.2 方法 任意のシェルを作成する(hoge.sh)とする 実行権限をつける hoge.shをhoge.appにリネーム alfredから実行 これだけ。 シェルを作成しただけだと以下のようになって実行はできない。 がリネームするとこうなる。 ためしにデスクトップ通知をするだけのshellを書いてみる。 hoge.sh #!/bin/bash↲ if [ "$(uname)" == 'Darwin' ]; then↲ # デスクトップ通知↲ osascript -e 'display notification "hogehoge" with title "title"'↲ fi↲ これを実行すると次のようにちゃんと実行できる。 これは色々とはかどりそうで良いぞ。 こういうのでどんどん開発効率を上げていきたいですね。 2017年6月27日 Cocos2d-xで並列に通信をする 先に結論 シーケンシャルに通信するときは HttpClient::send(HttpRequest* request); パラレルに通信するときは HttpClient::sendImmediate(HttpRequest* request) を使用すれば良さそう。 背景 アプリケーションが画像などのアセットを取得するときに、1件ずつシーケンシャルにダウンロードするのではなく並列に通信したかった。 結論までの経緯 まず内部実装をみてみる。 それっぽいのがHttpClient::sendクラスだったのでその実装を見ていく。 //Add a get task to queue void HttpClient::send(HttpRequest* request) { if (false == lazyInitThreadSemphore()) { return; } if (!request) { return; } request->retain(); _requestQueueMutex.lock(); _requestQueue.pushBack(request); _requestQueueMutex.unlock(); // Notify thread start to work _sleepCondition.notify_one(); } 詳しくは見ないが、_requestQueueにリクエストを詰めているだけのようだ。 その_requestQueueはどこ使われているかというと 同じくHttpClientクラスのnetworkThread()で使用されていた。 // Worker thread void HttpClient::networkThread() { increaseThreadCount(); while (true) { HttpRequest *request; { std::lock_guard<std::mutex> lock(_requestQueueMutex); while (_requestQueue.empty()) { _sleepCondition.wait(_requestQueueMutex); } request = _requestQueue. 2017年6月21日 jenkinsさんが503 Service Unavailableと言ってるのを修正したメモ Jenkinsさんが動かなくなってしまったので対応したメモ 借りているさくらVPSのCentOS6.7で軽い気持ちで $ sudo yum update したらJenkinsが動かなくなってしまった。 具体的には503が返ってきてしまう。 とりあえず、原因を調査するためにlogを見てみる。 自分の環境では以下にある。 $ /var/log/jenkins ログの中には以下のような記述が。 ・・・ Jenkins requires Java7 or later, but you are running 1.7.0_79-b15 from /usr/java/jdk1.7.0_79/jre java.lang.UnsupportedClassVersionError: winstone/Launcher : Unsupported major.minor version 52.0 ・・・ Javaのバージョンによるエラーっぽかったので公式サイトを見てみる。 すると以下のissueがたってた https://issues.jenkins-ci.org/browse/JENKINS-43492 yum updateでJenkinsがアップデートされ、Java8が必須になったみたいなので対応していく。 Javaインストールが必要な場合は以下の記事が参考になると思う。 http://qiita.com/Sa2/items/8ba501294df745be8c78 自分の環境だと、すでにJava8はインストール済みだったのでalternativesでjavaのバージョンを変更する $ sudo alternatives --config java alternatives結果 このdefaultがjava8だったのでこれを使用するように変更したのちに、Jenkinsを再起動したら無事動きました。 よかったよかった。 参考にしたサイト様 http://blog.officekoma.co.jp/2017/04/jenkins-http-error-503-service.html 2017年6月13日 CentOS6系のyum updateでつまづいたのでメモ 背景 let’s encryptの証明書更新用に仕込んだcronがエラーを吐いているようで、 原因を調査したところyum install系で更新ができないエラー。 yum updateすればなおるかなーと思ったがそもそもyum updateも404返ってきてうまくいかない。 どうやら、yumのリポジトリのミラーが古いバージョンのままになったようでした。 環境 さくらVPS CentOS 6.7 解決方法 以下のサイトが非常に参考になったので、その通り下記の対応をしたら無事に解決した。 よかったよかった。 [tips][Linux]旧バージョンCentOSでyum更新できなくなった時 $ su - $ cd /etc/yum.repos.d $ cp -p CentOS-Base.repo CentOS-Base.repo_yymmdd $ sed -i -e "s|mirror\.centos\.org/centos/\$releasever|vault\.centos\.org/6.7|g" /etc/yum.repos.d/CentOS-Base.repo $ sed -i -e "s|#baseurl=|baseurl=|g" CentOS-Base.repo $ sed -i -e "s|mirrorlist=|#mirrorlist=|g" CentOS-Base.repo $ cp -p CentOS-SCL.repo CentOS-SCL.repo_yymmdd $ sed -i -e "s|mirror\.centos\.org/centos/\$releasever|vault\.centos\.org/6.7|g" /etc/yum.repos.d/CentOS-SCL.repo $ sed -i -e "s|#baseurl=|baseurl=|g" CentOS-SCL.repo $ sed -i -e "s|mirrorlist=|#mirrorlist=|g" CentOS-SCL. 2017年6月5日 DDD本を読んだのでメモ 導入〜第1章まで 前から読みたかったDDD本を、読み始めたので雑にメモしていく。 ドメインとは、そのシステムが解決したい問題の領域のこと。 DDDにおいてのモデルとは、以下のようなもの 設計と相互に形成し合う チームメンバが使用する言語の基盤 蒸留された知識 設計と相互に形成し合う これはDDDがモデル駆動開発で進められることを意味している。 設計時にモデルを書きそこからコードを書き始める。 また逆に、コードを書き始めて気づいたことなどをモデル側にも反映させることでモデルとコードを一緒に成長させていく。 チームメンバが使用する言語の基礎 これは後ほど出てくるユビキタス言語について。 チームメンバ同士がコミュニケーションする際には、モデルや実際にコード上で表現されている言葉を用いる(逆にコミュニケーションに用いられる言葉をコードに落とし込む) 蒸留された知識 モデルはドメインの知識をそのまま反映したものであるべき。 モデルと実装が紐付いていれば、コードから得た知見をモデルに反映できる。 そうして、どんどん知識は噛み砕かれてよりドメインを明確に表すものに蒸留されていく。 これらの設計を進めていくためには、ドメインの知識を噛み砕く必要がある 第1章 知識を噛み砕く ドメインエキスパートの頭の中にあったり、過去のシステムなどからドメインに関する知識を得ることが重要で、繰り返し継続的にドメインに関する知識を学習する必要がある。 得た知識の中から重要な概念を抽出し、それをそのままコードに落とし込む。 オブジェクト指向でよく言われる、名詞を抽出するという手法の他に、 ビジネスルールなども概念として抽出する。 ビジネスルールなどはよくif文の中などに現れる。 例えばATMでお金を引き出せる時間かどうかのロジックについて考えると、 以下のように書かれることがある。(適当な疑似コード) Time now = Time::Now(); Time am9 = Time(9,0,0); Time pm10 = Time(22,0,0): if (am9 < time && time < pm10) { // 引き落とし処理 } このようにしてしまうと、処理の中に重要な業務ルール(引き落とし可能時間) が隠れてしまう。 そこでPolicyクラスなどを作成すると良いとされている。 if (businessHourPolicy.isAllowed(Time::Now())) { // 引き落とし処理 } ただしこのような手の込んだ設計はどこにでも適用することは推奨されていない。 ドメインの中でも特に重要となる知識に対して行うことが重要。 このようにして書かれたコードはドメインエキスパート(非エンジニア)にもコードを見せることができ、プログラマの手助けがあれば理解することができる(はず)。 また、コードを書いたことによる気づきなどをモデルにフィードバックさせ、知識を深めていく。 深いモデル アプリケーションが解決しようとしている問題の核心を表すうまいモデルのこと。 深いモデルを見つけるために、開発を続け、ドメインの知識について継続的に学習・嚙み砕きを行うことが重要とされる。 雑なまとめ DDDはモデル駆動開発 モデルをコミュニケーションに活用する より深いモデルのためにドメイン知識の嚙み砕きを継続的に行う 2016年12月19日 OptionParserのソースコードを読む この記事はElixir (その 2)と Phoenix Advent Calendar 2016 の 1 9日目の記事です。 背景 書籍「プログラミング Elixir」の 13 章でお世話になった OptionParser がとても便利そうだったので、中身の理解と Elixir のソースコードに慣れる目的で、ソースコードを読んでみました。 メインである parse/2 を中心に説明します。 下記に記載するソースコードは全て、公式のものを引用しています。 環境 Elixir 1.3.3 ドキュメント ソースコード おおまかな流れ parse/2 (外部に公開するインターフェース) do_parse/6 (実際にパースの再帰処理を行っているところ) next/4 (パース処理) ソースコード parse/2 まずはメインの parse/2 です。 parse/2 @spec parse(argv, options) :: {parsed, argv, errors} def parse(argv, opts \\ []) when is_list(argv) and is_list(opts) do do_parse(argv, compile_config(opts), [], [], [], true) end 引数の opts をcomple_config/1を通して加工してdo_parseに渡しています。 また、do_parse/6の結果をそのまま返しています。 2015年8月12日 Homesteadに複数サイトを追加する二つの方法 2015年7月15日 Homesteadを使ってLaravel5を動かしてみる 2015年2月10日 UDPについてまとめてみた WebRTCにも使われているプロトコルであるUDPについてまとめてみました。 UDPとは UDP(User Datagram Protocol)とは、TCPと同じトランスポート層のプロトコルです。 RFC768によって策定されています。UDPの特徴として以下のようなものがあげられます。 コネクションレスなデータ通信 データの信頼性、順序などを保証しない 高いスループット(伝送速度) マルチキャスト、ブロードキャスト コネクションレスとは、通信相手との接続を確立しないということです。 送信側が送りたいデータを一方的に受信側に送るため、接続を確立せずに通信が行えます。 こういった特徴があるため、データの信頼性、順序性などは保証されませんが、高速な送信を実現できます。 また、TCPは接続を確立するため、ユニキャスト(1対1)しか行えませんが、UDPはコネクションレスのため、マルチキャスト、ブロードキャストに対応可能です。 その他に、TCPでは複雑な制御をするためにTCPヘッダを送りたいデータに付属させる必要があります。TCPヘッダのサイズは通常20 Byteほどです。UDPにもヘッダは必要なのですが8 Byteと少量のため、小規模なデータの送信などはUDPの方が効率よく行えます。 使用されているサービス UDPプロトコルは以下のような技術に使用されています。 DNS DHCP VoIP 動画ストリーミング DNSはIPアドレスとドメインを対応づけるプロトコルです。 DHCPはLAN内のパソコンなどにIPアドレスを動的に割り当てるプロトコルです。 VoIPはIPネットワーク上で音声データを通信する技術です。 ブロードキャストを行う必要があったり、信頼性よりもリアルタイム性が重要視される場面ではUDPが選択されることが多いです。 データグラム TCPではデータの通信の単位をパケットと呼びますがUDPでは「データグラム」といいます。 実際にネットワーク上を流れているデータは以下のようなものとなります。 UDPデータグラム UDPデータグラムの表 上の表の送信元ポート、送信先ポート、データグラム長、チェックサムまでがUDPヘッダとなり、 ペイロードが実際に送信したいデータになります。 0~15bitまでは16bitが送信元のポート番号を表します。 16~31bitまでは16bitが送信先のポート番号を表します。 32~47bitまではデータグラム長を表します。データグラム長は、UDPヘッダとUDPペイロードの合計値です。 48~64bitまではチェックサムを表します。チェックサムは、データ(ペイロード)の整合性の検査用データとなります。 それ以降がペイロードです。 UDPデータグラムのサイズですが、これはIPパケットのサイズに依存します。 IPパケットは65535 Byteの容量となり、IPヘッダが20 Byteのため、UDPデータグラムで使用可能な容量は65535 – 20 = 63315となります。そしてUDPヘッダが8Byteのため、UDPペイロードの容量は最大で65507 Byteということになります。 よってデータグラム長に入る値は8 ~ 65515ということになります。 まとめ UDPはコネクションレスの通信方法 信頼性を犠牲にして高スループットな通信を実現 ヘッダサイズが小さく、オーバーヘッドが少ない(複雑な制御を行わないため) 2015年2月8日 WebRTC Conference Japanに行ってきました(2日目) 2015年2月5日 WebRTC Conferrnce JAPANに行ってきました(1日目) 2015年2月1日 Swift初心者向け勉強会に行ってきました 2015年1月29日 coocs2d-xでの座標系について cocos2d-xの座標系でつまずいたのでメモ。 タッチイベントを取得する際に,getLocationInViewで判定していたらどうも思い通りの挙動にならない現象が起きてた。 具体的にはy座標が反転してしまうようだった。 結論からいうと、getLocationInViewでなく、getLocationを用いれば左下からの座標で取得できた。 調べると、基本的にcocos2d-xで用いられているのは、OpenGL座標系で「左下」が原点らしい。 cocos2d-xのリファレンスをみると、座標系を取得するメソッドとして、TouchクラスのgetLocationとgetLocationInViewがある。 (以下リファレンスから引用) Point getLocation() const returns the current touch location in OpenGL coordinates. Point getLocationInView() const returns the current touch location in screen coordinates. なるほど。座標系の違いでメソッドが分かれているのか。 やっぱりリファレンスちゃんと見なきゃだめだなと思いました。