pslaboが試したことの記録

はてなダイヤリーからはてなブログに引っ越してきました

この日記は現在実行中の減量記録を含む個人的なメモとして始めましたが、最近はコンピュータやガジェット、ハック、セキュリティネタのほうがメインになっております。

はてなダイヤリー時代はカテゴリ分けが適当だったのですが、これはそのうち直します。


古いDelphiプロジェクトを調査するUnicode Statistics Toolが少し使いにくい点を修正する

Delphi のバージョン 2007 より前のバージョンで開発されたプロジェクトは標準の文字コードAnsiなので、マイグレーション時にはこれをUnicode対応する必要がありますが、その予備調査に使用できるUnicode Statistics Toolが下記のURLから入手できます。 https://cc.embarcadero.com/item/27398

しかし、このツールのUIは次の点が使いづらいです。

  • 調査対象のプロジェクトを含むディレクトリの指定は、SelectDirectory() で表示されるダイアログからしか行えない
  • SelectDirectory() は階層の深いディレクトリを辿るのがめんどくさい

幸いなことに、このツールはソースコードを含む形で配布されているので、ソースコードを変更してこの問題を解決することにします。本当は変更後のソースコードGitHub リポジトリにのせておけばよいと思うのですが、元アーカイブのライセンス条件が不明のため、変更差分の情報のみをメモとして残します。

ディレクトリを Explorer などからコピペできるようにする

UIの雰囲気から考えるとディレクトリ名を表示する TEdit (edtDirectory) にコピペするだけで動きそうに見えるのですが、このツールはそのような動作をしません。

このツールでは procedure RefreshFileList を実行して対象ファイルのファイルをリストアップした状態で動作するように実装されているからです。

そこで edtDirectory の onChange イベントに下記の実装を追加することにします。

procedure TForm2.edtDirectoryChange(Sender: TObject);
begin
  RefreshFileList;
end;

これで TEdit にディレクトリのフルパスをコピペするだけで動作するようになります。

Change ボタンで SelectDirectory ではなく OpenDialog を使用するように変える

Change (btnChangeDir) は SelectDirectory() で対象のディレクトリを指定するように実装されていますが、このUIは使いづらいと思うので、OpenDialog を利用する実装に変えます。

以下の実装は btnChangeDir の onClick の実装の変更例です。 予めフォームに TOpenDialog を配置した状態で以下の実装に変えるだけです。

procedure TForm2.btnChangeDirClick(Sender: TObject);
var
  Dir : String;
begin
  OpenDialog1.Title  := 'All files in the selected directory will be processed';
  OpenDialog1.Filter := '*.*';
processed';
  if (OpenDialog1.Execute) then
  begin
    edtDirectory.Text := ExtractFileDir(OpenDialog1.FileName);
    RefreshFileList;
  end;
end;

ソースコードの行数をカウントできるohcountの対象ファイルにDelphiプロジェクトファイル dpr を追加する

ソースコードの行数を数えるというのは、プロジェクトの規模を確認したいときの指標の一つになると思います。ohcount はそういう場合に利用できるツールの一つであり、200を超える拡張子を対象に調査できます。私が普段触ることのある言語だと、Pascal(Delphi), C++, JavaScript, awk, sh などは当然カバーされています。

しかし、Delphi プロジェクトファイル dpr の行数はカウントされないことに気付きました。dpr はプロジェクトファイルであると同時にソースコードの一部でもあり、コンソールアプリなら dpr だけで完結するケースがありますし、そうでなくてもアプリケーションの初期化処理などを含むケースがあります。プロジェクト全体から見れば些細な分量とはいえ、ソースコードとして解析したい対象です。

そこで、ohcount のソースコードを修正して dpr を調査対象に含めることにしました。私は ohcount を WSL 上の Ubuntu 18.04 LTS で使っていますので、この環境での変更方法を手順として残しておきます。個人的なメモなので、内容は割と雑に書いてますが、Ubuntu / Debian が分かる方なら対応可能と思います。

  • ソースパッケージをダウンロードできるように /etc/apt/sources.list を修正する
  • apt-get source ohcount を実行してソースパッケージを取得する
  • ソースコードの下記の箇所を修正する
--- src/hash/extensions.gperf.orig      2020-07-08 19:41:30.072570000 +0900
+++ src/hash/extensions.gperf   2020-07-08 19:17:12.717217100 +0900
@@ -52,6 +52,7 @@
 d, LANG_DMD
 dat, DISAMBIGUATE("dat")
 def, DISAMBIGUATE("def")
+dpr, LANG_PASCAL
 di, LANG_DMD
 doc, BINARY
 dtx, LANG_TEX_DTX
  • dpkg-buildpackage -b -uc を実行してビルド
  • sudo dpkg -i ohcount_3.1.0-2_amd64.deb を実行してパッケージをインストール

この修正を行う前後で ohcount の実行結果を比較すると、Files, Code などの集計結果が変わっていることが確認できます。実行結果の比較は Delphi 10.4 のサンプルプロジェクト Samples/Object Pascal/RTL/HttpDownload を使用しました。

# Samples/Object Pascal/RTL/HttpDownload のファイル一覧
$  ls | cat
FDownloadDemo.fmx
FDownloadDemo.pas
HttpDownloadDemo.dpr
HttpDownloadDemo.dproj
readme.md

# 修正前
$ ohcount .
                          Ohloh Line Count Summary

Language          Files       Code    Comment  Comment %      Blank      Total
----------------  -----  ---------  ---------  ---------  ---------  ---------
pascal                1        282         20       6.6%         46        348
----------------  -----  ---------  ---------  ---------  ---------  ---------
Total                 1        282         20       6.6%         46        348
Examining 5 file(s)


# 修正後
$ ohcount .
                          Ohloh Line Count Summary

Language          Files       Code    Comment  Comment %      Blank      Total
----------------  -----  ---------  ---------  ---------  ---------  ---------
pascal                2        292         29       9.0%         52        373
----------------  -----  ---------  ---------  ---------  ---------  ---------
Total                 2        292         29       9.0%         52        373

ソースコードのインデントを外すスクリプトを書く

既存プロジェクト内に含まれる類似実装を調査するために「全部のソースコードを連結して sort し、同一実装の出現数を uniq -c で数える」という方法を考えました。

しかしこれだとインデントの状態によって同一と数えることができなくなるので、インデントを外すスクリプトを書いてみました。

次の awk スクリプトを通すと、行の前後のスペースやタブ文字を消してコード部分だけを抽出できます。

#!/usr/bin/awk -f

match($0, /^[ \t]+?(.+?)[ \t]+?$/, matched) {
    # print $0
    print matched[1]
}

アプリケーションのソースコードの頻出キーワードを探すためにmecabでの形態素解析を試す

古いアプリケーションプロジェクトをリファクタリングする際の予備調査として、ソースコードmecab にかけて形態素解析を行い、頻出キーワードを探すという、実用性があるともないともよくわからない方法を思いつきました。

grep みたいな方法で探すと、たとえば Length というキーワードで探したときに MaxLength や MinLength もヒットしてしまうため、Length 自体を抽出できません。

しかし形態素解析すれば MaxLength や MinLength と Length は区別されますので、Length だけをチェックできます。

とりあえず試行中の手順をメモとして残しておきます。

まず、こうすると、形態素解析した結果が手に入ります。

find . -type f -name '*.c' | xargs -n1 mecab >> mecab.txt
find . -type f -name '*.cc' | xargs -n1 mecab >> mecab.txt
find . -type f -name '*.h' | xargs -n1 mecab >> mecab.txt

mecab の出力結果は実際にやってみればわかるので省略。

この結果を次のように sort | uniq -c | sort -nr すれば頻出回数の多い順にキーワードが並びます。sort | uniq -c に時間がかかるので、できれば別の方法を使ってキーワードの頻出回数を集計したほうがよいでしょう。

sort mecab.txt | uniq -c | sort -nr > result.txt

ただし結果は記号も含めて形態素解析されてしまうのでノイズが多いことに注意が必要です。

ARMのApple Silicon製MacにはParallelsは対応予定、VMwareとVirtualBoxは不明

ARMアーキテクチャApple Silicon製Macが年内に販売開始されることが発表されましたが、開発者にとって重要なのは、仮想マシン環境がApple Siliconでどのようにサポートされるか、という点だと思います。

Apple SiliconでIntelバイトコードを実行できる Rosetta2 は仮想マシンの実行には対応しない旨が発表されているので、Apple Silicon版MacIntel CPU向けのWindows10を動かしてWindows向け開発ツールを使うには、仮想マシン環境を提供する個々のアプリケーション(VMWare, ParallelsVirtualBox)側での対応が必須ですが、現時点での対応予定はそれぞれ次のように異なります。

ソフトウェア 対応予定 詳細
Parallels 対応予定 ブログ記事で対応予定と表明。ただし時期不明、また対応内容も不明。
VMware Fusion 未定 2020年7月に macOS Big Sur対応のTech Preview版をリリース予定だが、のリリースにはApple Silicon対応は含まれない可能性が高い
VirtualBox 不明 明確な発表なし

Parallelsの発表はこちらに。 www.parallels.com

VMwaremacOS Big Sur 対応についてツイートしています。

手元のMacBook Pro Retina 13inchは購入が2013年だからそろそろ買換え時ではあるのですが、Apple Siriconへの各社の対応を注視しつつ、実際の機種の発売をのんびり待ちたいと思っています。もし、仮想マシン環境で Intel バイナリが動作するものがリリースされず、マイクロソフトが ARM 向け Windows10 を一般向けに提供しないようなら、Windows 上のIDE(RAD Studio)で開発しつつ macOSiOS 向けアプリをビルドするには Intel CPU の Mac しか選択肢がなくなります。

Kensington Slimblade Trackball の Bluetooth or Wireless 版が欲しい

ここ10年くらい、Kensington のトラックボールを愛用しているのですが、トラックボールと一言で言っても、少なくとも次の2種類の派閥に分かれます。

  • 大玉派(人差し指、中指、小指で操作するタイプ)
  • 小玉派(親指で操作するタイプ)

そして Kensington の場合は、好みにより、さらに次の派閥に分かれます。

  • Slimblade Trackball
  • Expert Mouse(名前は Mouse ですが、実際には Trackball です)
  • Orbit
  • Profit

この中で明らかに特殊なのは Slimblade Trackball なのですが、このトラックボールにはスクロールのホイールがなく、その代わりにボール自体を捻る操作がスクロールのホイールに該当します。

www.kensington.com

Export Mouse の場合はトラックボールの周囲にスクロール操作のためのリングがついていて、これを回すことでスクロール操作になります。

操作系は似ているものの、実際の操作は全く異なるので、Slimblade Trackball に慣れた方が Expert Mouseを操作すると指がスクロールリングに触れてしまって意図しないスクロールが発生してしまいます。

たまたま、Expert Mouse Wireless を手に入れることができたので先日から使ってみたのですが、この点がどうも感覚的に合わなくて、久々に Slimblade Trackball に切り替えてみたら、やはりこちらのほうがしっくりくる。Expert Mouse Wireless はUSBドングルまたはBluetoothで接続できるから便利なのですが、ホイール操作の違いになじめないので、一旦お蔵入りにしようかと思っています。

Slimblade Trackball のワイヤレス版があれば自分的にはニーズが満たされるのですが、Trackball 自体がニッチな製品なので、なかなかそういうものは出てこないようです。

接触確認アプリを周囲の方がどの程度使っているかを調べるためにAndroidにBeaconScopeをインストールする

AndroidアプリのBeaconScopeが、接触確認アプリから発せられるBluetooth Beacon情報の受信に対応しているらしいので、インストールしてみました。

アプリは Google Play からダウンロードできます。

play.google.com

また、このアプリの作者が接触感染アプリで使用する"Contact Tracing Beacons"について書いているページがこちらにあります。

www.davidgyoungtech.com

このアプリについて、考察したことをちょっと書いてみます。

BeaconScope が接触確認アプリの電波を受信する仕組み

接触確認アプリはAppleGoogleAPIを用いてBluetooth LEの仕様で定期的に非常に弱い電波を発信しています。これ自体はiBeaconやEddystoneなどのBluetooth LEビーコンと同様の挙動です。しかし、iBeaconやEddystoneが送信する情報とは異なる情報を送信しています。iBeaconやEddystoneの情報を受信できるスマホアプリは色々ありますが、既存の実装では接触確認アプリの情報を正しく扱えないため、それを処理するコードが必要です。

BeaconScopeは接触確認アプリで用いられる形式のデータに対応しているので、このアプリで周囲をスキャンすると、接触確認アプリをインストールしたデバイスがどの程度の距離にあるかを表示できます。

ただし、このアプリは接触確認アプリ以外のBeaconも拾うので、リストされたデバイスがすべて接触確認アプリをインストールしたスマートフォンというわけではありません。

距離計算のしくみ

バイスで受信した電波の強度は RSSI という数値で表示されます。電波を発信したときの電波強度が分かっていれば、それらの数値からの計算で距離がわかります。

iBeaconの場合はビーコン自身が送信する情報の中に TxPower という項目があり、ここには「ビーコンの電波を1m離れた場所で受信したときの RSSI の値」が渡されます。(Eddystoneの場合は0m地点の強度です)

そして、TxPowerとRSSIの値を用いて次のように計算すると、ビーコンまでの距離を計算できます。n は理想的な空間では 2 とします。

d = 10 ^ ((TxPower - RSSI) / 10n )

計算された距離が必ずしも安定しない理由

Beaconの電波は2.4GHzの周波数を使っていますが、この周波数は人体などに吸収されやすいので、障害物があると受信時の電波強度が減衰します。また、他の物体に当たって反射した電波を受信するケースもありますので、この場合も減衰した電波を受信しています。

このように減衰した電波を受信することで距離計算の結果が変わります。

接触確認アプリでは1m以内に15分以上という方法で検知しますが、電波の減衰による誤差の影響を除外するためには、数秒程度の受信データでは補正ができないので、それなりに長時間計測したデータの中で1m以内の距離計算結果が一定数以上存在した場合に接触とみなす、などの確率的な処理を組み込む必要があるわけです。