jq で shuffle を実装する

諸事情で jq で Array shuffle を実装したので、 実装や実装に必要となった初歩的なアルゴリズムについて記録する。

とりあえずできたものはこちら。 jq -nrcf usage.jq でシャッフルされた配列が返ってくるはず。 gist.github.com

jqとは

jq には

jq is a lightweight and flexible command-line JSON processor.

と書かれている。 JSONを入力として、それに対するフィルターを書くことでJSONの加工が行えるくん。なのだけれども、JSONを入力とせずともフィルターのみでコーディングすればおおよそなんでもできる。

jqが用意してくれているもの

条件分岐

jq は if 文が使える。

2 | if . == 0 then "zero" elif . == 1 then "one" else "many" end
# => "many"

関数

jq は関数を作ることができる。作った関数はパイプを通すことができる。引数も渡せる。

def increment: . + 1;

1 | increment
# => 2

変数

jq は変数を定義できる。

["Amy", "Basil", "Clara"] as $children

と書いておけばパイプの後からでも $children を呼べる。

これら以外にもたくさん jq はできることがあって、それらは jq Manual (development version) に記載されている。変数宣言が "Advanced features" の項目にいるのは、本来の使い方を考えるとまあそうだよね。といった感じ。

モジュール

jq は別のjqファイルを読み込むことができる。 上の usage.jq でやっているように import PATH as Name でPATHを読み込む。読み込んだファイルの関数は Name::function のように呼べる。

デバッグ出力

jq は debug 関数を使うことで計算途中でも関数実行時点での値を出力することができる。実装中長いパイプを通す必要が出てきたときに重宝した。

["A", "B", "C", "D", "E", "F", "G"] | { "key": .[] }
# {"key":"A"}
# {"key":"B"}
# {"key":"C"}
# {"key":"D"}
# {"key":"E"}
# {"key":"F"}
# {"key":"G"}
["A", "B", "C", "D", "E", "F", "G"] | { "key": (.[] | debug) }
# ["DEBUG:","A"]
# {"key":"A"}
# ["DEBUG:","B"]
# {"key":"B"}
# ["DEBUG:","C"]
# {"key":"C"}
# ["DEBUG:","D"]
# {"key":"D"}
# ["DEBUG:","E"]
# {"key":"E"}
# ["DEBUG:","F"]
# {"key":"F"}
# ["DEBUG:","G"]
# {"key":"G"}

jq が用意してくれていないもの

乱数

jq には乱数が用意されていない。精度はまったく気にしていなかったので、擬似乱数について調べた。線形合同法を用いた疑似乱数が古典的でシンプルというのを見たので雑に書いた。定数はC言語のライブラリにある Park and Millerによって提案された「最小標準」の実装を参考にした。 ちょっと散らすために何回か繰り返しかけるようにしているが、個人的なおまじないレベル。

refs: Question 13.15

シャッフル

jq には配列のシャッフル関数が用意されていない。乱数が用意されていないのでそれはそう。どういったアルゴリズムが適しているのか調べると、 フィッシャー-イェーツのシャッフルというアルゴリズムがあることを知った。配列の要素ごとに無作為に選んだ要素と場所を入れ替える、というのを要素数分繰り返すことでシャッフルを実現している。畳み込みでも実現できそうだったので、今回は reduce を使って畳み込むことにした。配列の要素を指定してSwapした結果を別の配列として返す、というのが意外とめんどくさくて、上の実装では Array Slice を使って無理やり配列を組み立てている。もう少しどうにかなりそう。

refs: Fisher–Yates Shuffle

懸念していること

乱数の偏りについてなにも考えられていないので検証が必要。カルドセプト サーガを思い出した。

学び

  • 乱数、シャッフルの初歩的なアルゴリズムの復習ができた
  • jq 意外と何でもできることがわかった
    • 上記のような変なこと意外にも関数一通り眺めたので、どんなことができるかは把握できた。
  • ついでに配列、ハッシュの操作を行うコードも別件でちゃんと書いたので、大体jqわかった。

なぜこのようなことを

知り合いがjqでProject Eulerを解いているという話を聞いて興味が出たので。

参考

Raspberry Pi 4 + DAC + Volumio で音楽を聴けるようになるまで

仕事用のPC以外から家のNASに入ってる音楽を聴きたい〜って考えたとき、タブレットから再生するのが速そうと思ったのだけれども、Android / iOS だといい塩梅のアプリがなくてじゃあRaspiだとなったのであれこれ買って試した話。

用意したもの

Raspberry Pi 4

家に元々あったやつ。詳しくは後述。

Raspberry Pi 4のヒートシンク

Amazon | Raspberry Pi 4(Model B)用アルミヒートシンクケース (レッド) | Side3 | PCケース 通販

DAC

Kuman PIFI Digital DAC+ Amazonで買った。Raspberry Pi のソケットに刺さるタイプのDAC。チップとかそこまでこだわっていなかったので、適当に良さそうなのを選んだ。これがあるとRaspberry Pi の本体からよりは相対的に音が良くなる。

とても背の高いピンソケット

とても背の高いピンソケット2×20(40P) - スイッチサイエンス

スイッチサイエンスで買った。これも後述

Volumioの入ったmicro SD

Volumioという音楽再生に特化したディストリビューションがあって、それを焼いたもの。

組む

実はRaspi 3も家にあって、それを流用するつもりだったのだけれども、いざDACが届いたときに通電確認したらpow LEDが点灯すらせず文鎮と化したので予備で用意していたRaspi 4を渋々使った、という経緯がある。Raspi 4は熱がヤバいと聞いていたので、ヒートシンクも慌てて買った形となっている…

そして予想はしてたけれど、素の状態だとヒートシンクDACに干渉してしまったので、とても背の高いピンソケットを間に挟むことで解決した。スイッチサイエンス最高。

Volumioの設定

ハマったと言うか、調べないとわからなかったこと

NAS接続

使っているNASの問題なのか、 smb のバージョン設定を入れないと接続できなかった。 オプションに vers=1.0 を入れると接続できた。 f:id:uvb_76:20200616222136p:plain

コンピレーション問題

アルバムリストを表示したときにアーティストごとにアルバムが増殖するよくあるやつ。よく聴く音楽ジャンルの都合上そこそこの数のコンピレーションアルバムを管理している。iTunesだと何も考えずにコンピレーションとして認識させればよかったのだけれども、そんな親切なものは無いので、別の手段を使って、コンピレーションで有ることを伝える必要がある。今回はアルバムアーティストのタグを Compilation Metadata Fields として認識っせることで対処した。ただ、 mp3タグが不完全なアルバムもあったので、これを期に設定し直した。 f:id:uvb_76:20200616221505p:plain

使ってみて

同じネットワークからブラウザで volumio.local にアクセスするとVolumioの再生画面を表示できる。ブラウザで一通りの操作が完結できるのは強いと思う。スマホからでも同様にアクセスできる。レスポンシブデザイン対応しているのは親切だなーと感じた。ただ、Rapi4で音楽再生するだけなのはオーバースペックっぽいと思うので、別用途でもなにか動かせないか模索しているところ。また、Volumioで提供されている Spotify Plugin のログインが未だにうまく行っていないのでどうにかしたい。うまく行けばNexus 7から脱却できるんじゃ…

参考

Raspberry Piで部屋のオーディオ環境を改善した話 - しろうまの小屋

Volumioでコンピレーション・アルバムの再生ができない場合の対処方法 - Qiita

静的ページ生成のブログにVssueを使ってコメント欄を置く

VssueというVueのライブラリがある。これを使うとページに簡単にコメント欄を置くことができる。VuePressで作ってた日記に導入してみたので、ライブラリの紹介も兼ねて書く。

github.com

しくみ、やったこと

コメントを残す、ということはどこかにコメントデータを保持しておかなくてはいけない。静的ページでどうやって? Vssueはその問題をGit ホスティングサービスのIssueにAPI経由で読み書きすることで解決している。コメントの編集、削除はもちろん、 絵文字のリアクションもつけることができる。 もちろん Issueの emoji reaction を利用している。そりゃそうだよねと言った感じだけど。

対応しているGitホスティングサービスは以下のとおり。今回はGitHub(V3)を採用した。

詳細は Introduction | Vssue が詳しい。

GitHubAPIを叩いてコメントを読み書きするので、OAuth2のGitHubアプリを作る必要がある。ClientIDとClientSecretを払い出したら環境変数に隠して置く必要はある。この日記はNetrifyにデプロイしているので、環境変数はSettings→Build & deploy → Environment variablesで設定すれば良い。

現物

実際のもの、作業記録は以下から確認することができる。

1つの記事に対して1つのIssueでコメントを保存している。 誰もコメントしてないときはコメント欄が disabled になっているが、Click to create issue を選択することでVssueがリポジトリにIssueを新規作成してくれる。この状態でコメントを書いて投稿すると、Issueのコメントとして連なる、という仕組み。

f:id:uvb_76:20200527030950p:plain
コメントする前

コメントを書くのにGitHubのアカウントが必要だったり、たまーに表示されなくなって更新するとまた出てくるなどちょっと不安なところはあるけれど、なかなかおもしろいライブラリだと思った。

MacでCanonのカメラをビデオチャットのカメラとして使う

在宅勤務で外に出なくなり一眼レフの出番が消え失せたのでなにか使い所がないか考えていたところ、MacWebカメラとして使えるのではと思い至り、調べてた。

lowreal.net 5年前の情報だけど、ここの記事の内容がそのまま使えたよという記録。

用意したもの

設定も単純で、カメラの電源を入れたあと Camera Live とCam Twist を起動して以下のように設定するだけ。

f:id:uvb_76:20200412142349p:plain
アプリケーションの設定

EOS Utility を一緒にインストールしていると、 カメラの電源 ON 時に EOS Utility が起動し Camera Live の認識とぶつかって両方ともフリーズしてしまうので、自動起動の設定を切った。 f:id:uvb_76:20200412141910p:plain

これで一眼カメラを入力としてWebカメラの内容として出力できる。

仮想カメラを入力ソースとして使えるか

ただ、そもそも Cam Twist が各種ビデオチャットのカメラソースとして使えるかという問題が存在する。この記事を書いた時点で

  • 使用可能(Cam Twist が選択できる)
  • 使用不可能 (Cam Twist が Video Settings の選択肢として表示されない)
    • Slack Call
    • Zoom
    • Discord

という状態を確認した。Zoomは仮想カメラを無効にした話を聞いたが、Slack Call も認識しなかったのは想定していなかった。


というわけで、手元で余しているものを転用する話でした。社内で受肉しながらMeet通話している人たちがCam Twist使っている話はちらっと聞いたけど、話が繋がって学びになった。Syphon初めて知ったけど、間に編集挟めば楽しそうなことができそうなこともわかった。バッテリー問題や置き場所問題があるのでこれを実用するかどうかは別だけど… OSMO PocketあたりをWebカメラとして使えるようにならないかな、というメーカーへの期待は別に持っていたりする。

GitHub Actions 実践入門を読んだ

booth.pm

技術書典8が中止になったので、興味ある本は買っていこうと思い買った本のうちの一つ。この前読みながら写経してたので記録に残す。

どんな本か

GitHub Actions ができること、yamlファイルの記載方法、GitHub Actionsから実行できるアクションの作成方法、公開方法についてがコンパクトに纏められている。

あまり、CIに触れてきていなかったので、マトリックステストの項目ではそんなことできるの〜と感心してしまった。また、GitHub Actionsを公開できることで、CIに必要な機能をサクッと拾ってこれるのもとても便利だと感じた。

GitHub Actions で感心したこと、メモ

仮想環境内に入っているツール、言語類がまとまっている記載

ワークフローのトリガーとなるイベント

秘匿情報

リポジトリのSettings Secrets から設定し、 secrets.FOO の形で参照できる。Actionsの実行ログはちゃんと *** でマスクされる。

f:id:uvb_76:20200403030726p:plain

組み合わせテスト

storategy を設定することによって、複数の環境での組み合わせテストも簡単に実行できる。便利。

成果物

actions/upload-artifact というActionsを使うと、CIを実行中に生成した成果物をGitHub上にアップロードできる。ダウンロードも同様にActionsが提供されている。setup-ruby もそうなんだけど、 https://github.com/actions/ の一覧を見れば大体のことはできそう。


ymlの書き方から、実際に手を動かして自動テストをCIで実現するまでを体験できるので、GitHub Actions からCIを触る人にもおすすめ。

次はOpenAPI 3を完全に理解できる本か やりかけの RubyでつくるRubyのどちらかを読んで行こうかな。

VP2785-4Kを買った + 在宅状況近況

f:id:uvb_76:20200220221002p:plain 2020/02/03 1月近況 - 鳥人雑技団なんて地元にはない でも書いたんだけど1月末からの在宅勤務体制がしばらく続きそうだったので、学生の頃から10年使っていてたディスプレイを買い換えることにした。

届いた様子はこちら。

選ぶときに考えたこと

  • いつ使うか
    • 在宅中のMBPでの作業
    • 私物のMBPでの作業
    • 私物のWindowsでの作業
  • 何に使うか
    • インターネットサーフィン(死語?)
    • コード書く
    • 写真現像
    • WindowsでPCゲームする
      • あわよくばSwitchがつながる
  • 必須要件
    • 4K
    • 27インチ
    • sRGB 100%
  • あるといいな
    • AdobeRGB 99% ↑
    • USB-C給電の端子
    • KVM(WInとMacの切り替え)
    • 垂直周波数75Hz以上

みたいな感じでぱっと探すと以下の候補が出てくる

LGの方はUSB-Cの給電がついていて、BenQ PD2700Uの方はKVMがついているんだけど、USB-C端子が無いので、ケーブルの取り回しがだるいなーと考えていた。PD2720Uは流石に予算オーバー。

27UL850-Wでいいかーとか考えたけど、みんな使ってて面白みが無いとかいう本当にしょうもない理由で避けてた。そして、探して出てきたのが VP2785-4K AdobeRGB 99%カバー 27型 4K IPSカラーマネージメントディスプレイ - ViewSonic JP で、結論タイトルに有るようにこのディスプレイを買うことになった。

なぜVP2785-4Kを選んだか

4Kで27インチでAdobeRGB99%でUSB-Cで60W給電できてKVMついててLGじゃなくてフルHDで出力すると垂直周波数120Hz出て(!)10万前後で買えるのがこれだったから。PD2720Uはちょっと高かかった。

ただ、店頭にはどこにもおいてないので、調べる限りネットで買う以外に方法は無い。ドスパラNTT-X、イートレンド当たりで扱っていて、今回はイートレンドで買った。ViewSonicって知らないメーカーだったんだけど、アメリカで30年続いてるディスプレイとプロジェクターのメーカーだった。最近日本に再参入したらしい。

どう使っているか

今はこんなかんじで使ってる。デスクトップにはもう一枚HDMIでディスプレイが接続されているけど今回は割愛。

f:id:uvb_76:20200220231313p:plain
今の状況

これでKVMがいい感じに効いてWindowsのデスクトップPCとMBPが同じキーボードとマウスで操作できる。USB Type-C1本でこれが実現できるの本当に良いと思った。

120Hzで動くらしい。

これどこにも書いてないので特筆しておきたい。

公式の仕様を眺めていたら、以下の記載を見つけた。

走査周波数 水平: 15 - 204 KHz 垂直: 24 - 120 Hz

垂直周波数 120Hz ということはゲームでも使えそう。ただ、ガイドには120Hzで設定できる旨の記載はなかったので念の為サポートに確認した。回答は以下のとおり。

VP2785-4Kの垂直走査周波数につきまして VP2785-4Kは解像度「1920×1080」での利用時のみ、120Hz動作に対応しております。 垂直走査周波数120Hzをご利用いただくには、「1920×1080/120Hz」対応のPCまたは、 グラフィックボードが必要となりますので、ご参考にしていただければ幸いでございます。 ※解像度「1920×1080」対応製品であっても、「1920×1080/120Hz」に対応していない製品もございます。  詳しくはお使いのPC・グラフィックボードのメーカー様にお問合せください。

流石である。

ただし、Windowsのデフォルトの解像度設定では120Hzの設定が存在しない。そこで、Nvidiaのコントロールパネルから解像度を新規に追加して対応する。ちなみにデスクトップのグラフィックボードは ZOTAC GeForce® GTX 1070 Mini 8GB | ZOTAC を使用している。

「解像度の変更」→「カスタマイズ」→「カスタム解像度の作成」から新規に解像度を作り、「リフレッシュレート」を120に変更する。

f:id:uvb_76:20200220212109p:plain
作成した解像度設定

これを適用することにより、120Hzで動作する。すごい。ただ、メーカーの設定にはないので、ディスプレイの寿命は縮みそう。それと、この120Hzの設定はフルスクリーンには対応していないので、ウィンドウモードのままゲームをすることになる。最近のPCゲームはタイトルバーレスのウィンドウモードで動作するものも多いので、それで。

変えて感じたこと

ディスプレイ1枚で良さそうと思えるくらい情報を表示できる。

今2枚外部ディスプレイ使ってるけど、27インチ1枚で完結しそう。2枚あると逆に各ディスプレイの文字の大きさがバラバラになったり首の振り幅が多くなって、目がや首が疲れる。これは要調整。

普通にゲームできる

色に気を使ったディスプレイだとスマブラSPとPortal2やった感じでは全然気にならない。流石にゲーミングディスプレイには負けるけど、そこまで気にしていないので良い。DJMAXやると普通のディスプレイ同様の残像が出て気になるかも。って感じ。

新しいディスプレイは眩しい

部屋を明るくしたほうがよい。あとディスプレイの輝度ガッツリ下げたり、ブルーライトカットで対処した。ワンボタンで色温度変更できて便利。

ということで今の所かなり満足。10年使えば実質無料みたいなところあると思うので先代同様長生きしてほしい。 それと、机の上のケーブル類の散乱がやばいのでどうにかしてスッキリさせたい。

在宅の話

あらすじ

同じく 2020/02/03 1月近況 - 鳥人雑技団なんて地元にはない に経緯は書いてます。

どうですか

自分の見えている範囲のみの話をする。

  • 普通に仕事できてる感がある
    • 家で仕事が完結する下地があることに感謝したい
    • 在宅でこなせない仕事があり、出社している人にも感謝したい
  • 通勤がなくなるのは最高
    • 一方で通勤で歩くことにより目を覚ましていることに気が付かされた
  • 体を意識的に動かさないとどんどん凝り固まっていく
  • 座り心地が悪い椅子で作業すると腰と首は破壊される
    • 整体に行く頻度が上がる
  • 意外と家の周りに飯屋がない
  • 自分は自宅に環境が整備されているけど、出社を前提として環境を整備している人はつらそうに見える
    • これまで家に有線引く必要がなかった人は存在しそう
      • Bring your own Infrastracture を強いられている
  • まだ1ヶ月だけど2ヶ月以上続くとなると結構辛くなりそう
    • 来月の電気代が怖い
    • 自由に在宅で仕事していいよ、じゃなくて出社を控えましょう、という形の在宅なので
      • 乱暴だけど避難所生活、集団疎開という言葉が頭をよぎった
  • Discordのボイスチャンネルはマジでリモートワーク向いてると感じる

おまけの定点観測

在宅が始まったときから机の定点観測を撮っていた

f:id:uvb_76:20200220213228p:plain
1月末
f:id:uvb_76:20200220213258p:plain
2月上旬
f:id:uvb_76:20200220213326p:plain
購入直後

順調に汚くなっているのがよく分かる。

というわけでディスプレイ買った話と近況でした。

PowerShellでghq + fzf環境を作る

Windowsでもghqを使ったリポジトリ管理を行いたくて、最初WSLからUbuntuを使おうと思ったんだけど、ダルくなったのでPowerShellでやることにした。

PS>go version
go version go1.9.2 windows/amd64

PS>$Psversiontable

Name                           Value
----                           -----
PSVersion                      6.2.4
PSEdition                      Core
GitCommitId                    6.2.4
OS                             Microsoft Windows 10.0.18362 
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0窶ヲ}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

golangとgitは昔インストールしてたやつが残ってたんだけど、あまりにも古すぎるので別途アップデートする…

ghq と fzfのインストール

Windowsでのパッケージマネージャーは見直すたびに今はこれだーと入れ替わっている印象がある。今回はscoopを使うことにした。

scoop.sh

PS>Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force  
PS> iex (New-Object net.webclient).downloadstring('https://get.scoop.sh')

PS>scoop install fzf 
PS>scoop install ghq

ghq rootのパスを決める

Windoesでもghq rootのパスはgit configで変更できる

git config --global ghq.root D:\dev\src\

Profileの編集してリポジトリを選択できるようにする

bashでいう .bash_profile のようにPowerShellにもプロファイルが存在する。パスが変数に入っているので便利。

PS>$profile
C:\Users\User\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

自分は $Profileの中身で $PSInclude という変数を定義して、そのフォルダ内のスクリプトをぜんぶ読み込むということをしている。これで$Profileが長くならずに済む。

$PSInclude = "C:\Users\User\Documents\PowerShell\include\"
ls $PSInclude  *.ps1 | 
    %{
        $_.Name
        $path = $PSInclude  + $_.Name
        . $path
    }

そしてそのなかにPowerShellスクリプトを置く。

function ghq-fzf {
  $repo = $(ghq list | fzf)
  Set-Location ( Join-Path $(ghq root) $repo)
}

これで ghq-fzf を叩くといつものリポジトリの選択画面になり、選択後そのフォルダに飛べるようになる。毎度関数を叩きたくないのでショートカットにする。Set-PSReadLineKeyHandler を使うと良さそう。今回はCtrl+gで選択画面に飛べるようにした。

function ghq-fzf {
  $repo = $(ghq list | fzf)
  Set-Location ( Join-Path $(ghq root) $repo)
}

Set-PSReadLineKeyHandler -Chord Ctrl+g -ScriptBlock { 
  ghq-fzf
  [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() 
}

[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() が無いと選択後もう一度Enterを押さないと先に進まないので入れている。

これでPowerShellでもリポジトリが検索できるようになりましたとさ。

Historyも検索したい(おまけ)

ここまでやってPowerShellHistoryファイルから過去実行したコマンドを再実行できると便利なのでは、と思ったのでついでにやる。

function history-fzf {
  Invoke-Expression ((Get-Content $(Get-PSReadLineOption).HistorySavePath) | fzf)
}

Set-PSReadLineKeyHandler -Chord Ctrl+l -ScriptBlock {
  [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
  history-fzf 
}

PowerShellの履歴ファイルのパスは Get-PSReadLineOptionで取得できるプロパティの一つから取得できる。それをfzfで選択してInvoke-Expressionで実行するだけ。

今のままだとファイルの頭から読んでしまうので、Historyの最近実行した順番に並んでくれるとそれっぽい。fzfの --reverse オプションでうまく行かないのでどうやればいいんだろう~って考えたのが今。それと、PowerShellの関数の命名規則に疎いのでもう少ししきたりに習ってよく書けるのだろうかとも考えている。