人生シーケンスブレイク

シーケンスブレイク(Sequence breaking、シークエンスブレイクとも)とは、テレビゲームにおいて開発が想定している攻略ルートを逸脱し、ショートカットする行為のことである。

El CapitanのPreviewでKindle用にイイカンジにPDF圧縮する

手持ちの自炊したPDFや、PDF購入した電子書籍Kindle Paperwhiteでも読みたいのでイイカンジ圧縮したい。

しかし、Previewのファイルサイズ圧縮は低解像度過ぎる。
ということで、従来はColorSync Utilityで新しいフィルターを追加するというやり方があったが、El Capitanだと新規に追加したフィルターがPreviewで選択できず、選択可能にするにはCLIでsudoしたりしないといけない。

で、GUI操作の為にTerminal使うのはちょっと違うなと思ったので、標準アプリケーションのみでGUI操作で完結する方法を模索。

環境

  • Kindle Paperwhite 第7世代(2015年以降のモデル, 300ppi, 1,072×1,448)
  • OS X El Capitan
  • Kindleパーソナルドキュメントは50MBまでだけど、Gmailは25MBまでだから実質25MBに圧縮しないといけない人。

解決策

Automatorを使う。

手順

1. ColorSync UtilityでKindle用のフィルタを追加する

元々あるフィルタ'Reduce File Size'を複製し、Kindle用のフィルタを作成する。
今回は'for Kindle'という名前にした。

Web上の情報から、 Image Sampling > Max の値を元の512pxより大きくするとより解像度が上がることが分かっていたので、今回はKindle Paperwhiteの横解像度と同じ1072pxに指定したフィルタを作成した。 f:id:ShineSpark:20160527165453p:plain

2. Automatorアプリケーションを作成する

Kindle用のフィルタをPreview上で利用可能にするにはuser以下のlibralyディレクトリのフィルタを/System/Library/Filters/に移動させる必要があるのでめんどい。カンタンにAutomatorアプリケーションを作成する。

まず、Automatorを立ち上げる。Spotlight便利。

f:id:ShineSpark:20160527171207p:plain

新規にアプリケーションを選択する。

f:id:ShineSpark:20160527171241p:plain

アクションを登録していく。今回登録するアクションは以下の4つ。

  • Ask for Finder Items でどのファイルかを尋ねるようにする
  • Filter Finder Items で念の為PDFファイルのみに限定する
  • Copy Finder Items で元々のPDFファイルをデスクトップに複製する
  • Apply Quartz Filter to PDF Documents でコピーしたPDFファイルにフィルタを適用する

を行う。日本語でのアクション名はそれっぽいものを探してください。

f:id:ShineSpark:20160527171416p:plain

右上の 'Run' ボタンからテスト実行できるので、それで実際にどのように動作するのか確認しながら作るとよい。

上手く動作したらイイカンジの名前を付けて保存。

3. 使う。

アプリケーションとして保存したので、以後は作成したAutomatorアプリケーションを実行してPDF圧縮を行う。
イイカンジの名前を付けておくと、Spotlightから呼び出しやすい。

f:id:ShineSpark:20160527172407p:plain

上記すらだるい人

USBでKindleを繋いで同期しましょう。50MB越えてても大丈夫です。

Amazon.co.jp ヘルプ: USB経由でFireタブレットまたはKindle端末にパーソナル・ドキュメントを転送する

手持ちのPDF書籍の閲覧には多少工夫が入りますが、'本を読む' には軽さやバッテリー持ちの良さからiPadよりKindleの方が便利です。まだ買ってない人は買いましょう。

手頃な値段なので、ケースも保証も要らないです。壊れる頃には新世代のものが出てるので新しいのを買いましょう。 アダプタも他のUSBアダプタで代用できるので改めて買う必要はないです。

広告有無は1タップ減るので広告無し版を買いましょう。

Kindle Paperwhite Wi-Fi、ブラック

Kindle Paperwhite Wi-Fi、ブラック

参考

CentOSにDockerをインストールする

この記事内容は公式の

docs.docker.com

ままなので、英語が読める人は公式のドキュメントに従いましょう。

Dockerのインストール

元々のyum repoは古いので、Dockerのyum repoを追加する

# 一度yumの更新
$ sudo yum update 

# docker.repoの追加
$ sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

# docker-engineのインストール
$ sudo yum install docker-engine

# dockerの起動
$ sudo service docker start

# テスト起動
$ sudo docker run hello-world
sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from hello-world
d59cd4c39e50: Pull complete
f1d956dc5945: Pull complete
Digest: sha256:4f32210e234b4ad5cac92efacc0a3d602b02476c754f13d517e1ada048e5a8ba
Status: Downloaded newer image for hello-world:latest

Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
 https://hub.docker.com

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

OK.

docker グループを作る

DockerデーモンはTCPポート代替として機能するUnixソケットに紐付いており、そのUnixソケットはデフォルトでrootがオーナーになっている為、Dockerはrootかsudoでしか動作しない。
ということで、docker グループを作ってそこにユーザを追加する。

この docker グループはDockerに於いてrootユーザ同等の権限を持つ。
Docker Daemon Attack Surface と呼ばれるセキュリティ上の影響を考慮する必要がある。

Docker security | Docker Documentation

# dockerグループの作成
$ sudo groupadd docker

# dockerグループにuserを追加する
$ sudo usermod -aG docker your_username

一度ログアウトし、先述のyour_usernameでログインする。
念の為、sudoなしで起動できることを確認する。

$ docker run hello-world

起動時にdocker daemon自動起動する

いつもの

$ sudo chkconfig docker on

Dockerのアンインストール

# インストールしているyumパッケージの確認
$ yum list installed | grep docker
docker-engine.x86_64  1.7.1-1.el6       @dockerrepo

# 該当パッケージを削除
$ sudo yum remove docker-engine.x86_64

# イメージとコンテナとボリュームの削除
$ rm -rf /var/lib/docker

参考

https://docs.docker.com/engine/installation/linux/centos/

CentOSからNode.js / npm をアンインストールする

CentOSのrootからやたらとnpmが古いぞとメールが来るのだけれども、そもそもnvm上のNode.js / npmしか利用していないのでグローバルのNode.js / npmはアンインストールすることにした。

しかし、Node.js / npmのアンインストール方法が公式にないぞ...ということでその記録。

Node.jsのアンインストール

ソースコードがある場合(未確認)

# cd <ソースコードのディレクトリ>
# make uninstall

上記で安全にアンインストール可能らしいのだが、生憎未確認。

ソースコードがない場合

ソースコードが手元に無かった為、こちらのやり方で実施した。
まずnodeのパスを確認し、それに基づいてbin, lib, manを削除するだけである。
念の為verboseオプションを付与している。

# where node
/usr/bin/node

# rm -rfv /usr/{bin/node,lib/node,share/man/*/node.*}

npm のアンインストール

アンインストールコマンドが用意されているのでそちらを利用する。

# npm uninstall npm -g
- abbrev@1.0.7 node_modules/npm/node_modules/abbrev
- ansi-regex@2.0.0 node_modules/npm/node_modules/ansi-regex
- ansicolors@0.3.2 node_modules/npm/node_modules/ansicolors
- ansistyles@0.1.3 node_modules/npm/node_modules/ansistyles
- aproba@1.0.1 node_modules/npm/node_modules/aproba
- archy@1.0.0 node_modules/npm/node_modules/archy
- chownr@1.0.1 node_modules/npm/node_modules/chownr
- clone@1.0.2 node_modules/npm/node_modules/columnify/node_modules/wcwidth/node_modules/defaults/node_modules/clone

...

- npm@3.9.2 node_modules/npm

ホームディレクトリに .npm/ が残っていたのでこれも削除

# rm -rf .npm

これでアンインストール完了。

参考

サーバサイドJavaScript Node.js入門 (アスキー書籍)

サーバサイドJavaScript Node.js入門 (アスキー書籍)

Dein.vimにしたので折角だしこのタイミングでvimrc構成を整える

NeoBundle.vimからDein.vim移行に伴い、Vimの設定ファイル群の整理も行ったのでその記録。

設定ファイル群の構成

ざっくり以下の構成に整えました。

dotfiles/
└── .vim/
     ├── colors/     // カラースキーム置き場(今回は説明しません)
     ├── ftplugin/   // filetypeごとの固有設定ファイル置き場
     ├── gvimrc
     ├── rc/
     │   └── *.vim   // 各種設定ファイル
     ├── template/   // template置き場
     └── vimrc       // メインのvimrc

vimrc, gvimrc の設置箇所について

:help vimrc によると、

個人の初期化ファイルの配置場所:
Unix $HOME/.vimrc、$HOME/.vim/vimrc

初期化ファイルは上記の順に検索され、最初に見つかったものだけが読み込まれる。

推奨: Vimの設定ファイルは全て $HOME/.vim/ ディレクトリ(MS-Windowsでは$HOME/vimfiles/)に置くこと。そうすれば設定ファイルを別のシステムにコピーするのが容易になる。

とあります。

今まで$HOME直下にVim設定ファイルとして、 .vimrc, .vim/, .gvimrc の3つをシンボリックリンクでつなげてましたが、$HOME直下は.vim/だけで済むようにしました。

ftplugin ディレクトリについて

ファイルタイプごとに固有の設定は

.vim/ftplugin/<filetype>.vim
.vim/ftplugin/<filetype>_<name>.vim
.vim/ftplugin/<filetype>/<name>.vim

の箇所に配置すると、各ファイルタイプに応じて読み込まれます。
pythonを例にすると、python.vim でも python_hoge.vim でも python/hoge.vim でも読み込まれます。

.vimrc にすべてのファイルタイプの設定を書くのでなく、
各ファイルタイプごとに設定ファイルを用意することでリーダブルにします。

rc ディレクトリについて

私のVim環境下では、 .vim/rc/以下の *.vim ファイルをすべて読み込むように設定しています。
こうすることで、例えば Dein用の設定ファイルは.vim/rc/dein.vimのように、pluginごとの設定は.vim/rc/<plugin_name>.vim に分割することが可能です。

設定方法は、大本のvimrcに以下のように記述するだけです。

set rtp+=$HOME/.vim/
runtime! rc/*.vim

Dein.vim 用の call dein#add(...) を記述しまくった設定ファイルもここに設置しています。

template ディレクトリについて

テンプレートファイル置き場です。
Vimでのテンプレートは以下の設定で実現可能です。

例: Pythonのテンプレートファイルを設置する場合

.vim/template/skeleton.py として、以下を記述したファイルを設置します。

# coding: utf-8

次に、 .vim/rc/skeleton.vim に以下を記述したファイルを設置します。
(.vim/ftplugin/python.vim 内に記述しても可能です。)

augroup template
  autocmd!
  autocmd BufNewFile *.py 0r $HOME/.vim/template/skeleton.py
augroup END

$ vim new.py とすると、自動で "# coding: utf-8" が挿入されます。

:help skeleton もご参照ください。

まとめ

上記のような構成にすることで、Vimの設定ファイルをすべて .vim/ 配下で完結しつつ、ファイルタイプや用途ごとに適切に分割することができました。

以前より見通しがよくなった為、管理もしやすいです。
もし今まで.vimrcひとつで管理してた人は、分割も試してみてはいかがでしょうか?

それでは良いVimライフを!!

Activité Pop のバッテリーは3ヶ月程度しか持たなかったよ

Withings Activité Pop を買って7ヶ月ほど経ちました。

f:id:ShineSpark:20160116234926p:plain

Withings Activité Pop

歩数、運動量、睡眠のトラッキングが可能な腕時計。
公式だと20,800円だが、Amazonでは現在15,000円ほど。

値段に対する満足度としては非常に満足している。

Apple Watch が出る直前に並行輸入で購入したのだけれども、アナログな文字盤と歩数達成率のシンプルなデザインで非常に使いやすい。

同メーカーのハイエンドモデルである Activité の方がデザインは洗練しているが、 運動、睡眠計測の為に付けっぱなしになりがちであることから、安価な Activité Pop の方が気楽に使用できるのでこちらを購入した。

f:id:ShineSpark:20160117000325j:plain
アプリの画面。元々Withingsアプリで健康管理を行っている人には違和感なく移行できると思う。

バッテリー持ち

f:id:ShineSpark:20160116234945p:plain

公称ではバッテリーが8ヶ月と謳っている。Apple Watch のバッテリーが1日しか持たないと話題になっていた時期だったのもあり、Activité Pop は非常にバッテリー持ちするように見受けられる。

ところが...

f:id:ShineSpark:20160116234943p:plain

バッテリー残量が足りなくなると届くメール通知。

6月購入から、どう見ても3ヶ月程度しか持ってません。本当にありがとうございました。

しかも、上記のメール通知が届く前後から時計がズレ始める。時計なのに正しい時刻を示さなくなるなんて...

早く電池を交換しろってことか...と思い、電池を交換したらまた再び正しい時刻を示すようになった。

ついでなので電池交換の仕方

Activité Pop は自分で電池交換可能です。

f:id:ShineSpark:20160116235044j:plain

コンビニでも売っているボタン電池 CR2025 と、付属の時計蓋外しを用意して、

f:id:ShineSpark:20160116235012j:plain
パカーっと裏を外して、

f:id:ShineSpark:20160116235035j:plain

電池を外すと、「この向きで電池嵌めるんやでー」っと書いてあるのでその通りに嵌めるだけ。

蓋を閉める際は、防水仕様もあってかかなり力を要する。 テーブルの上に時計を置いた状態で、手のひらを時計の上に載せて、ちょっとジャンプして全体重を掛ける位でやっと嵌まる。

f:id:ShineSpark:20160116235004j:plain

これでまた3ヶ月は使えます。 最大8ヶ月というのは、きっとアラームを使わず、運動量の計測もあまりしない時なんだろうな...

とはいえ

スマートウォッチとしては非常に満足しています。 電池交換自体には2回目というのもあって全然時間がかからないし、8ヶ月も3ヶ月も電池交換に要する感覚としては苦になっていない。 むしろ、毎日の睡眠の記録や、歩いた距離に応じたachievementの通知が楽しいのでもっともっと使いたい。

値段もお手頃なので買って後悔はしないですよ。

NERDCommenterでfiletypeごとのコメントフォーマットを変更したい

SCSSを scss-lint でチェックしてるんだけど、デフォルトで推奨されているコメントが // となっている。 しかし、NERDCommenterコメントアウトした際には /* */ となっていて面倒なのでSCSSのデフォルトのコメント設定を変更したい。

.vimrc に以下のように追記する

let g:NERDCustomDelimiters = {
  \  'scss': { 'left': '//'}
  \}

まだ著作権表記で消耗してるの?

年末年始対応の時期ですね。

f:id:ShineSpark:20151216014450p:plain
svg画像を 著作権表示 - Wikipedia より。

企業で働くエンジニアは、あけおめ対策をはじめとした年末年始の対応準備に時間を割いていることでしょう。
その中でも、毎年恒例の著作権表記、特に年号更新の対応に追われる方が多いでしょう。

アレ、不要なので辞めましょう。

要点

  • 著作権表記は現在いちいち書く必要性はありません。
  • 年号表記も特に意味はありません。
    • そんな対応に時間をとられる必要はありません。辞めましょう。
  • もっと言えば "All rights reserved." も不要です。辞めましょう。

どゆこと?

そもそも著作権表記とは?

著作権表示(ちょさくけんひょうじ)は、著作物の複製物につける著作権者や著作物の発行年等に関する表示である。著作者が著作権を取得するため、著作物の創作のほか、何らかの手続き等(方式)が必要な法域においては、著作権表示は重要な意味があるが、現在は、ほぼ全ての法域で著作権は、著作物の創作とともに発生するので、重要性は失われている。
著作権表示 - Wikipedia より引用

日本国内に於いては、1971年7月24日にパリで改正された万国著作権条約に受諾しており、現在はこちらの内容に批准しています。 その第三条四項には以下のように定められています。

4  各締約国は、他の締約国の国民の発行されていない著作物を、方式の履行を要することなく保護するための法的手段を確保する。
千九百七十一年七月二十四日にパリで改正された万国著作権条約 - Wikisource より引用

ここでいう "方式" とは、著作権の無方式主義と方式主義のことです。

無方式主義 著作物を著作もしくは発表した時点で自動的に著作権が発生し、それ以外には何らの方式(又は手続)の履行を要求しない法制 方式主義 納入、登録、表示、官庁への納入、登録、登録手数料の支払い、自国内における製造もしくは発行などといった「方式」を履行することにより著作権の発生要件とする法制
著作権表示 - Wikipedia より引用

またまたWikipedia引用ですみません。ちなみに私はこの件について8年程前から疑問を抱き、毎年この時期になる度に当該Wikipediaページをwatchして参りました(編集は一切してない)。昔に比べると非常に明瞭になっており、私以外にもこの件で戦ってきた人が居るのかと思うと非常に感慨深いものがあります。 当時はガラケー全盛期の為、All rights reserved. を書くだけでフッターに無駄な改行が入ったのです。

要するに、「万国著作権条約に締約している国の国民は、何もせずとも著作物の権利を保護する法的手段を持っている。」ということになります。
何もせずとも、です。

つまり要らないのです。

ちなみに (c) 表記について

前述の通り不要なのですが、方式主義に於いて認められているのは © であり、(c) は認められていません。

その為、.txt ファイルとかに (c) と書いていても無効なので書くのは辞めましょう。

ちなみにAll rights reserved.は?

こちらは万国著作権条約には関係ありません。万国著作権条約制定前に策定されたブエノスアイレス条約という条約があるのですが、この条約では「権利を所有している」表記が必要でした(方式主義)。

アメリカ合衆国をはじめとした国々が締約し、「権利を所有している」表記として、All rights reserved. が使われました。 現在では、アメリカを含め殆どの国がベルヌ条約*1及び万国著作権条約にも締約している為、この表記は現在は不要です。

ちなみに、 日本はこのブエノスアイレス条約に締約していません。
したがって、 日本では全く意味がありません。
アメリカ企業の権利表記を日本企業がコピペしたものが蔓延したんでしょうねぇ...

All rights reserved. のデメリット

All rights reserved. の直訳は、「すべての権利を保有している」です。
イマドキのWebサービスに於いて、そのようなケースが果たして本当に成立しているのでしょうか?

  • CGM
    • ユーザが投稿した写真やデータ。規約にも運営側に帰属する旨記載して、規約との齟齬はありませんか?
    • ユーザが投稿した歌詞や第三者が著作権を保有している画像。これも運営者が権利を保有しているのでしょうか?
  • 外部データ
    • 他者からAPI取得 または購入したデータ
    • オープンデータ
    • OSSやライブラリ

意味の無い All rights reserved. を書くことで、逆に訴訟や炎上リスクを招く可能性もありそうです。

規約の話ではありますが、mixi規約改定時に問題になりましたね。
ミクシィの利用規約改定問題が示すCGM時代の権利処理のあり方 - ビジネススタイル - nikkei BPnet

他の例として、有名なCGMサービスとして ボケてがありますが、全ページのフッターに All rights reserved. と書いてあります。
しかし、利用規約には、

第17条 弊社の財産権
( 1 ) 利用者が送信(発信)したコンテンツおよび情報を除き、本サービスに含まれる一切のコンテンツおよび情報に関する財産権は弊社に帰属します。

と書いてあり、Allとは一体...うごごごごご...と思ったりします。*2

利用者が投稿したコンテンツおよび(他者の著作物を含む)画像の権利の帰属を宣言しない辺り、ボケてはしっかりしている方かも知れません。

お前専門家じゃねーだろ。ただのエンジニアがナマいってんじゃねーぞ。

はい。専門家ではありません。ぜひとも専門家からの意見もいただきたいところです。 弁護士ドットコム - 無料法律相談や弁護士、法律事務所の検索 でニュースとして取り上げていただけること、お待ちしております。

とはいえ根拠も無いままではアレなので、ここは最強法務部と名高い任天堂法務部のチェックを通ったであろう任天堂公式サイトを確認してみましょう。

f:id:ShineSpark:20151216005543p:plain
任天堂ホームページ|Nintendo より

お、超シンプルです。私が思う理想形です。

先日 サムスンから賠償金5億4800万ドルせしめた Appleはというと、

f:id:ShineSpark:20151216005906p:plain
Apple より

あ、年号もAll right reserved. がありました。

お次はGoogleです。
f:id:ShineSpark:20151216011814p:plain
Google より

本気で何も書いてない...

思ったよりバラバラの模様です。

対応

原理主義的な話を散々述べましたが、本懐は「毎年毎年、年号を更新するだけの無駄なクソ作業を無くしたい」です。
現実として、社内の一エンジニアや受託エンジニアでまるっと無くすというのは現実的ではないでしょう。

その場合の対応として、以下の解決策を検討しましょう。

動的ページ

Date() 関数などから現在の年号を表記するなどして動的に出力しましょう。

静的ページ

404.html とか 500.html などは、コンテンツなんてあってないようなページなので、© 会社名 または© 会社名 All rights reserved. にして年号は無くしましょう。

クライアント側で実行するJavaScriptでの年号出力は推奨しませんが、どうしても上長がOKしてくれない場合や、一時的なキャンペーンページなどの静的ページではJavaScriptでの実行もアリかもしれません。JavaScript無効設定での著作権表記について問題視する上長ならば、著作権表記自体の不要性やコストについても議論の余地がありそうです。

いずれにせよ手動更新は辞めましょう。

上長を説得する材料として

以下のサイトを判断材料にしてもらいましょう。

こんなことに時間を浪費しているうちはスピーディな開発なんて出来やしない。

*1:長くなるのでこのエントリでは言及しない。

*2:CGMとして有名な為取り上げましたが、All rights reserved.の含有する矛盾を問題提起するのが目的であり、ボケてサービスを批判する意図は全くありません。