2015年 06月 17日

Android File Transfer で表示されないファイルがある

  1. USB を一度抜く
  2. 設定→アプリケーション→メディアストレージ
  3. 「強制停止」
  4. 「データを消去」
  5. https://play.google.com/store/apps/details?id=com.gmail.jerickson314.sdscanner を実行する
  6. USB を繋ぐ

→ Android File Transfer が起動して見れるようになる。

.nomedia があるディレクトリはインデックス化されないみたい? なので、もし見たいディレクトリにあるなら、Android 側のファイラか何かで消しておく。

2015年 06月 09日

curl で大きなファイルを resume しながらファイルダウンロード

細い回線で Chrome のダウンローダだとうまくレジュームできないことが多々あって厳しい。キャンセルするとダウンロード途中のファイルが消えたりするし (余計なお世話だ)、大きなファイルはダウンロードしにくい。

ということで、curl でダウンロードすることにする。特にログインセッションが必要でなければ普通にやればいいが、ログインセッションが必要な場合、いちいちヘッダを全部書くのはだるいので、一度 Chrome 上で開発者ツールを開き、リクエストを発生させてすぐキャンセルし、Network ペインで該当リクエストを右クリックして Copy as cURL すると早い。

そのうえでお尻に -o filename -C - をつけてやる、つまり

$ noglob curl... -o filename -C -

curl... の部分はペースト。noglob は念のためつけておく。-o filename でダウンロード先ファイル名を指定し、-C - でレンジリクエストによるレジュームを有効にする。-C オプションはハイフンを指定すると、-o で指定したファイルの大きさから判断してレジュームをかけてくれる。ファイルがなくても -C オプションはエラーにはならないので、はじめからつけておいて良い。

Current Speed が0ちかくになったらやりなおせば良いし、ログインセッションが切れたら、ログインしなおしてクッキーを取得し、同じファイル名でレジュームを続ければ良い。

2015年 06月 05日

定期券を捨てて自転車通勤にして本当に金を節約できるか?

雨の日は走らない自転車通勤

自転車通勤を検討しようと思っても「雨の日は走らない」を前提に考えると「果たして定期券よりも安いのだろうか?」と不安になる。

そこで、過去30年の降水履歴を考慮しつつ、自転車通勤 vs 通勤定期のコスト差を出してみることにした。

定期券の場合、通勤にかかるコストは定期券料金だけである (普通は6ヶ月分を一括で買うが、この場合半額ぐらいになる)

雨の日は電車通勤する自転車通勤の場合、晴れの日の駐輪場料金のほか、雨の日の往復電車賃がかかる。

計算

Polymer 使って書いてみた

各値について

入力
  • 定期代:定期代
  • 期間:定期を買う期間
  • 雨天時往復料金:雨が降って自転車通勤しないときの往復料金
  • 駐輪場料金:晴れていて自転車通勤するときの駐輪場料金
  • 開始日:この日から定期の期間分の間の降水確率をもとめる
出力
  • 総通勤日数:期間中の土日を除いた日数
  • 期間中平均降水確率:1mmでも降水がある確率
  • 期待自転車通勤日数:雨の日を除く通勤日数
  • 損得分岐日数:この日数以上は最低でも自転車通勤しないと定期よりも損をするという日数

実装

降水確率

無駄に統計データを集計して使っている。

気象庁の統計データが csv でダウンロードできるので

http://www.data.jma.go.jp/gmd/risk/obsdl/index.php#

  • 東京
  • 1985-01-01 - 2014-12-31 までの29年
  • 降水量の合計
  • 日別

を選択してダウンロードし、日付単位で集計し、1mm でも降水があったら雨として降水確率を出している。29年なのは、1回でダウンロードできる限界だったから。

https://dl.dropboxusercontent.com/u/673746/Screenshots/2015-06-03%2010.34.39.png

Polymer

独自要素の style is="custom-style" は template 直下におかないと効かなくてハマった

this.notifyPath("obj"); だと obj の各キーに対する notify にならないらしく、this.notifyPath("obj.foo"); とかやる必要があった (this.set("obj.foo", newValue))

flex layout のドキュメントがどこにあるのか謎なので、iron-flex-layout/classes/iron-flex-layout.html を見る必要があった。

あとは特にDOMを複雑にいじるようなことはしていないので、非常に簡単に書けた。データバインディングがあるとこういうのはらくちんでいいですね。

2015年 06月 04日

Polymer 最小構成のペライチファイル

なにを入門するにせよ、とりあえず最小構成を確認したい、と思う人はいるでしょう。何を隠そう、僕もその一人です。

index.html

<!DOCTYPE html>
<html>
        <head>
                <title></title>
                <meta charset="utf-8"/>
                <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
                <script src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
                <link rel="import" href="bower_components/polymer/polymer.html"/>
                <link rel="import" href="bower_components/paper-input/paper-input.html"/>
                <link rel="import" href="bower_components/paper-material/paper-material.html"/>
                <link rel="import" href="bower_components/paper-styles/paper-styles.html"/>
        </head>
        <body class="horizontal center-justified layout">
                <dom-module id="my-app">
                        <template>
                                <div style="width: 300px">
                                        <paper-input label="Foo" type="number" value="{{foo::input}}"></paper-input>
                                        <paper-input label="Bar" type="number" value="{{bar::input}}"></paper-input>
                                </div>
                                <div class="result">
                                        Foo: <span>{{result(foo, bar)}}</span>
                                </div>
                        </template>
                </dom-module>

                <paper-material elevation="1" style="padding: 20px">
                        <my-app foo="1" bar="1"/>
                </paper-material>

                <script>
                        Polymer({
                                is: 'my-app',
                                properties: {
                                        foo: Number,
                                        bar: Number
                                },
                                result : function (foo, bar) {
                                        return +foo + +bar;
                                }
                        });
                </script>
        </body>
</html>

bower.json

{
  "name": "my",
  "version": "0.0.0",
  "authors": [
    "cho45 <cho45@lowreal.net>"
  ],
  "license": "Public Domain",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "paper-input": "PolymerElements/paper-input#^1.0.0",
    "paper-button": "PolymerElements/paper-button#^1.0.0"
  }
}


これら index.html と bower.json を特定のディレクトリにおき、bower update をかけてから、ブラウザで 直接 index.html をひらけば、なんとなく動く。

ただこれだと、せっかく Polymer を使っているのに、Chrome 以外でうごかない。というのも、HTML Import によって Polymer の依存が解決される前に (native で HTML Import が実装されていないブラウザでは) Polymer() がある script 要素が実行されてしまうからのようだ。dom-module を定義する場合 index.html で定義せず、別ファイル (app.html とか) にして rel="import" し、index.html では要素を書くだけでスクリプトは書かないのがセオリーのようだ。

どうしてもペライチのまま動かす場合、以下のように WebComponentsReady のタイミングで Polymer を呼べば、その後該当する要素はコンポーネントとして扱われて正しく動くようになった。

document.addEventListener('WebComponentsReady', function() {
    Polymer(...);
});

当然このまま動かすと、依存する html ファイルや css をたくさんリクエストするが、本当にちょっとしたアプリなら気にするほどでもなくとりあえずこれで開発して、あとから考えればよさそう。

Polymer のざっくりした考えかた

アプリケーションはコンポーネント(と呼ばれるエレメント)の集合体であり、アプリケーションもまた1つのコンポーネント(エレメント)であるというのが Web Components の考えかた、だと思う (コンポーネントの定義が見つからなかったので、正しくないかもしれない)。

Polymer は Web Components そのものではなく、あくまで Web Components の概念をベースにしたフレームワークなので、とりあえず Polymer は Polymer として使いかたを覚えたらよくて、Shadow DOMガー! とかいって Shadow DOM が何かを知る必要はない。というか Shadow DOM のポリフィルは使ってない。Polymer は双方向データバインディングの仕組みが template 要素を使って提供されているが、データバインディングの仕組みは Polymer 独自であり、標準化されているものではない。

2015年 05月 29日

Google Photo のリリースで無料分のサイズ拡大・アスペクト比別最大サイズの求めかた

今までは2048px以下なら無料というルールだったので、写真をあげるときは全て Lightroom 側で長辺 2048px でリサイズしていた。数年まえまでは「これで十分だろう」という感じだったが、昨今高解像度ディスプレイ(高ppi)が増えたため、これでは少し物足りないサイズ制限に感じるようになっていた。

今日 Google Photo というサービスがリリースされ、Google の写真ストレージがサービスとして再度分離された (Picasa → Google+ → Google Photo)。これに伴ない無料分の写真のサイズが緩和され、ヘルプによると16MPまでは無料ということになった。

デジタル一眼レフカメラのアスペクト比は 3:2 なので (コンデジは4:3)、4898×3265px までは無料アップロードできることになる。 (あとで追試するけど) これからは 現像時の設定で長辺 4898px に設定しても良さそう。

function getMaxPixelsForAspectRatio (ratio) {
	var pixels = 16e6;
	var a = Math.sqrt(pixels * ratio);
	var b = Math.sqrt(pixels) / Math.sqrt(ratio);
	return {
		width: Math.floor(Math.max(a, b)),
		height: Math.floor(Math.min(a, b))
	};
}

console.log(getMaxPixelsForAspectRatio(3/2));
//=> { width: 4898, height: 3265 }
console.log(getMaxPixelsForAspectRatio(4/3));
//=> { width: 4618, height: 3464 }
console.log(getMaxPixelsForAspectRatio(16/9));
//=> { width: 5333, height: 3000 }
2015年 05月 25日

ぷららモバイルLTE → めっちゃ遅い

今のところ、遅すぎて、もっと安いプランの128kbpsとかとあんま変わらないんじゃ、って感じ。

3Mbps 無制限のプランにしてみた。完全無制限によりはトラフィックが安定しているかな?という目論みだったが、そうでもなさそう…

朝6時ぐらいに一瞬3Mbpsぐらいまで出たことがあったが、基本的に 100〜500kbps か、それ以下にしか出ず、かなり遅く感じる。

300kbps 程度だと、画像があまりないページなら良いが、結構辛いページが多い。

ただ、au のときは、使いすぎで速度制限がかかった場合、QoS が下がって通信優先度が下げられるのか、速度だけではなく通信安定性も下がっていたが、ぷららモバイルLTEは今のところそういうことはなく、安定して遅い。なので大きいファイルは放っておけばダウンロードされる。

300kbps だと、8時間 (28800秒) で、1GBぐらいが限界。自宅にいる間に落とせるファイルサイズ限界がかなり厳しい。

音声通話つきのプランは半年間の最低契約期間がある (データ通信オンリーにはない) ので、ちょっと面倒だなあという感じ。

2015年 05月 22日

Zenfone2 を買ったぞ。

1.8GHz 2GB RAM 32GB Flash の安いモデル。ヨドバシで予約して発売日当日に届いた (実際は不在だったので翌日だったけど)。

HTC J butterfly (HTL21) からの買い替え。買い替え理由は

  • HTC J butterfly の OS バージョンが古い (特に Bluetooth LE が使えないのがつらい)
  • MVNO sim への移行のため sim フリーが欲しい

HTC J butterfly は大変良くできた端末で、気に入っていたので、端末ハードに不満はなく、ソフト的な理由が大きい。


ざっと触って特に不満に思うところがほとんどないので、翻って考えると良いと思う。

事前に良く調べてなかったんだけど、思いのほかデカかった。サイズ的には iPhone6 plus なみにデカい。薄いということになっているが、見た感じも持った感じの、そこまで薄くはない。

カメラはそれほど綺麗ではない感じ。一昔前のコンデジ画質といえる。ダイナミックレンジが狭く、光量が多いシーンだと白トビしやすい。普通のシーンなら十分綺麗だけど、昨今のコンデジ並の画質は期待しないほうが良い。

CPU が Atom で、ARM系じゃないのがちょっと珍しい? アーキテクチャが違うけど、どのアプリも特に問題なく動いてる。ただ、すこし CPU 酷使すると背面が結構熱くなる。

なお、下位モデルには高速充電用のACアダプタはついてないっぽい。高速充電用のACアダプタは9V 18Wのものらしいが、下位モデルは5Vのものしかついてこない。

2015年 04月 08日

速度計でケイデンスを計る

安い速度計オンリーのサイクルコンピュータを買ったが、別途ケイデンスを計れるものを買いなおしたので、1つ速度計のみが余った。

速度計とケイデンス計はセンサーは全く同じで (磁石+リードスイッチ)、取り付けかたと計算方法が違うだけなようだ。

最近エアロバイクも買っていて、暇なとき漕いているんだけど、ケイデンス表示がなくてペースがよくわからないので、余った速度計を転用することを思いついた。

速度と(タイヤの)回転数の関係はこんな感じになってる。len はタイヤ周長

ということで、計算するとタイヤ周長を 5000 / 3 にすると、speed = rotations となる。

が、5000 / 3 ≒ 1667 となり、タイヤ周長として異常なので普通入力外になる (手元のものはタイヤ周長としては100〜299までしか入力できなかった)。なので1桁ズラして、167[cm] をタイヤ周長として入力すれば、表示上 06.0[km/h] という形で 60rpm を表現できる。

ただし、速度計の場合 4km/h にならないと表示がオンにならないとか制約があったりするのであまりゆっくりだと測定できないことがある。

2015年 03月 31日

I/Q phase (直交信号) から周波数を求める

IQ信号からは、ベクトルの絶対値をとることで振幅が得られ、角度を求めることで atan(Q/I) 位相を得られる

その上で得られた位相を微分することで、周波数を求められる。

JavaScript で書かれたリードソロモン符号のエンコーダ・デコーダ

JavaScript だと、デコーダだけ、エンコーダだけ、というのはあったり、GF(2^8) オンリーなものはあったりするんだけど、汎用的なのがなくて悲しかった。

Zxing (バーコード読めるアプリ) の実装を見てみたら、読みやすい上で汎用的な実装だったのでリードソロモン部分だけ Java → JavaScript の移植を行った。

https://github.com/cho45/reedsolomon.js

他の目的があって移植してたけど、目的がなかなか達成できないのでとりあえずこれだけ npm にあげた。

久し振りに単純な移植作業をやった。特殊な依存が特になくほぼ計算なので

  • 型宣言を全部 var に
  • インスタンス変数の参照に this. をつける
  • System.arraycopy() を TypedArray#set() に置き換える

ぐらいを何も考えずに機械的に行なったい、テストもまるごと Zxing のものをパクって移植した。

覚書

(2が底なら?) 任意のガロア域を使えるようになっており、いろんな用途に使えそう。

new GenericGF(primitive, size, b) で作れるが、primitive polynomial (原始多項式) はビットで表現されている。

x^8 + x^5 + x^3 + x^2 + 1 という多項式なら、8 5 3 2 0 bit が立ち 100101101 となる。0ビット目は +1 を表現してる。これは一般的な表現方法らしく、このように表わされた状態を数字として 301 としたり 0x12d としたりするみたいだ。

http://octave-online.net/ で primpoly(6, 'all') とかやれば原始多項式を全部求められる。

あと、JT65 (6bit) は AZTEC_DATA_6 と同じっぽい。