2016-10-31

Animes in the 3rd quarter of 2016

アニメは IT エンジニアの必須科目です。 ということで簡単なレビューを。

またタイムリープかと思ったのも束の間、序盤は神展開。その反動か中盤は糞展開。終盤に持ち直す感じ。あと意図的だとは思うが、主人公がやたらイラッとくる。あの軽薄さで引きニート設定は無理があるかと。

各キャラの掘り下げが上手いのが Key 作品の特徴なのだろうか。特に委員長のくだりはずるい。しかし終わらせ方はあれで良かったのか疑問。ひょっとして次は True End バージョンが来る?

今期の一番はこれ。主人公の知略はもちろんのこと、ヒロインとの厚い信頼関係が見ていてとても心地よい。早く続きを作って欲しいところだが、種田梨沙が休業ってそんなー。

一見、NHK 教育でやってそうな雰囲気の作品。いわゆる悪役っぽいのも出てくるが、最後はきっちり拾い上げるし、本当に NHK でやってもおかしくない内容だと思う。

初話を見てかなり強引だなと思いつつも、結局最後まで見てしまった。ばらかもんのスピンオフだと気付いたのは途中から。最初はパクリかと思った。でもやはり設定に無理があると思う。

今期コメディ枠の一番。とにかく、ヒロインと小澤亜李の親和性に尽きる。この手のキャラを演らせたら、彼女の右に出る者は居ない。個人的にはコレットさんもお気に入り。

今度はゲーム制作業界の話か、と思ったら、業界の具体的な描写はほぼ無し。もっと SHIROBAKO みたいなのを期待した。ただし作品自体は絵調や雰囲気など好みで、単に想像と違ったというだけ。

序盤こそ良感触だったが、中盤からどんどん安っぽくなっていく。特に最終話が酷かった。これで「次期もあるよ」とか言われても、面白くない予感しかしない。

この手の女子向けは基本スルーだが、志倉千代丸が企画ということで視聴。結果、他の女子向け作品と余り大差なかった。A&R という職種も謎。ただ、つばさちゃんはいい娘だと思います。

わざわざ新キャラにする意味が分からなかったが、結果から言えば 1st よりも楽しめたので、これで良かったのかも。しかし CG をそのままアニメに使うのは手抜き。その辺はアイマスを見習うべき。

始まったと思ったら終わっていた。何を言っているか(ry。ていうか何故 4 話だけやろうと思ったのか。

最初は渋めでいい感じに始まるも、それ以降が盛り上がらなかった。復讐というには主人公の冷徹さが足りず、いろいろと中途半端だったように思う。

言い方は悪いのだろうが、夏目友人帳の明るめバージョン。他に言葉が見つからない。安倍晴明とか出てくるし、原作者はきっと女性とみた。

前期より視聴。ちょうどこの辺まで原作を読んでたっぽい。これから未知の領域へ、と思ったところで終わった。ちょっと短くないですかね。あとやっぱり絵が原作の雰囲気に合わないと思う。

歌と三角関係とバトル、というマクロスの三大要素はきっちり入っている。しかしフロンティアの壁は厚かった。超えられたのは楽曲だけだと思う。何だかんだでやっぱりシェリルは偉大。

シリーズ通して視聴。舞台が変わっても、バカやってるときは面白いがバトルになるとつまらなくなるのは変わらず。バカやってる間は文句なく面白いので、ずっとそうしてれば良いのに。

主人公がなかなか本気出さないので全然盛り上がらない。ようやく本気出したと思ったら一番いい所で終了。って何これ。流石にこれは評価できない。ノイタミナ枠でこんなひどいのは初めて見た。

最近は名前ばかりのガンダムが多いが、これは紛れもなくガンダム。冨野作と聞いても疑わないレベル。老人は見ておくべき。逆に、若者がこれをどれほど面白いと思えるのか興味がある。

2016-10-27

Windows batch: Multi-level variable expansion

この間 getopt.cmd を書いていて思った。変数展開した結果を変数展開するにはどうすればいいんだろう?、と。言葉にすると難しいが、要は C 言語でいうところの、ポインターのポインターから元データを参照する感じ。

call を使うのがいいようだ。call には変数展開後の文字列が引数として渡るので、どんなコマンドにも応用できる。call にこんな使い方があったとは。

test.bat:

@echo off
set hoge=HOGE
set r_hoge=hoge
set rr_hoge=r_hoge
echo %hoge%
call echo %%%r_hoge%%%               & rem run 'echo %hoge%'
call call echo %%%%%%%rr_hoge%%%%%%% & rem run 'call echo %%%r_hoge%%%'
>test.bat
HOGE
HOGE
HOGE

Windows バッチはこういう妙なところで懐が深かったりする。やろうと思えば大抵のことは(頑張れば)できる。でもどんな良い面があっても、圧倒的マイナス面で ks 扱いされる Windows バッチさん。

2016-10-23

Windows batch: Getopt

Windows バッチが ks なことは今さら言うまでもないが、最もお手軽な手段であることも事実。特にユーザーに配布して実行させたい場合、環境の差異を気にしないくて良いのは何にも勝る利点だ。同様の意味で WSH も素晴らしいが、結果が同じならよりシンプルな方を選びたい。

という訳で私はよくバッチも書くが、ちょっと凝ったバッチを書こうとしたとき、オプション処理にはいつも悩まされる。きちんとやろうとすると面倒だし、どうせならこの手の処理は共通化したい。誰か getopt みたいなやつ作ってねーのかよ、と偶にググってみても、これといったものが見つかった試しがない。

まあ、もしバッチでできたらとっくに誰か作ってるよねー、と今までは諦めていたのだが、今回ふと思って試してみた。

test.bat:

@echo off
setlocal
set opt=hoge
set opt_%opt%=HOGE
echo opt_hoge=%opt_hoge%
>test.bat
opt_hoge=HOGE

え!? set の左辺で変数展開できちゃうの?

そうか、set もコマンドだから、引数中の変数は展開されてから set に渡るのか。ていうか、これ使えば getopt できるんじゃね?

getopt.cmd:

@echo off

if not "%~1"=="/?" goto :main
echo.Usage:
echo.  call %~nx0 [/OPTION[:VALUE]]...
echo.
echo.Description:
echo.  Parse options and define 'OPT_^<OPTION^>' variables, and set 'OPTIND' as
echo.  the number of processed arguments.
echo.
echo.Exsample:
echo.  When a batch file is invoked with arguments,
echo.
echo.    ^>example.bat /foo /bar:BAR /baz:"B A Z" arg1 arg2 ...
echo.
echo.  In the batch file, a typical usage is:
echo.
echo.    call %~nx0 %%*
echo.    for /L %%%%i in (1,1,%%OPTIND%%) do shift /1
echo.
echo.  Then a boolean option '/foo' can be tested as below.
echo.
echo.    if defined OPT_FOO ^(
echo.      echo /foo was given
echo.    ^) else ^(
echo.      echo /foo was not given
echo.    ^)
echo.
echo.  Other options have a value can be used as regular variable.
echo.
echo.    echo bar=%%OPT_BAR%%
echo.    echo baz=%%OPT_BAZ%%
echo.
echo.  Remaining arguments are referred through batch parameter.
echo.
echo.    echo args=%%1 %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9
echo.
echo.  Note that '%%*' batch parameter is never updated by 'shift'.
exit /b 1

:main
set OPTIND=0

:_loop_args
  set _getopt_arg=%1
  if defined _getopt_arg (
    call :parse_arg %_getopt_arg%
    if not errorlevel 1 (
      shift /1
      set /a OPTIND+=1
      goto :_loop_args
    )
  )
set _getopt_arg=
set _getopt_opt=
set _getopt_value=
set _getopt_bool=
exit /b 0

:parse_arg
set _getopt_opt=
set _getopt_value=%~1
set _getopt_bool=1
if not "%_getopt_value:~0,1%"=="/" goto :_parse_arg_ret
set _getopt_value=%_getopt_value:~1%
:_loop_arg_chars
  if not defined _getopt_value goto :_parse_arg_ret
  if "%_getopt_value:~0,1%"==":" (
    set _getopt_bool=
    set _getopt_value=%_getopt_value:~1%
    goto :_parse_arg_ret
  ) else (
    set _getopt_opt=%_getopt_opt%%_getopt_value:~0,1%
    set _getopt_value=%_getopt_value:~1%
  )
  goto :_loop_arg_chars
:_parse_arg_ret
if not defined _getopt_opt exit /b 1
if defined _getopt_bool (
  call :set_opt %_getopt_opt% %_getopt_bool%
) else (
  call :set_opt %_getopt_opt% %_getopt_value%
)
exit /b 0

:set_opt
set OPT_%1=%~2
exit /b 0

できちゃった :-D。使い方は次の通り。

test_getopt.bat:

@echo off
setlocal

call getopt.cmd %*
for /L %%i in (1,1,%optind%) do shift /1

if defined opt_hoge echo /hoge was given
if not defined opt_hage echo /hage was not given
echo /piyo=%opt_piyo%
echo /fuga=%opt_fuga%
echo /boke=%opt_boke%
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
>test_getopt.bat /hoge /piyo:PIYO /fuga:"FU GA" /boke: arg1 arg2 ...
/hoge was given
/hage was not given
/piyo=PIYO
/fuga=FU GA
/boke=
arg1 arg2 ...

まだ改良の余地はあると思うが、私が使うには当面これで十分。

ところで今回の件で、Windows バッチは変数名に記号(どころか空白も!)を使えることを知ったが、ならば getopt.cmd に /? を渡せば変数 opt_? を定義してくれそうに思う。しかしそれは叶わない。

>call getopt.cmd /?
バッチ プログラムを別のバッチ プログラムから呼び出します。

CALL [ドライブ:][パス]ファイル名 [バッチパラメーター]

  バッチパラメーター   バッチ プログラムで必要なコマンド ライン情報を指定します。

コマンド拡張機能を有効にすると、CALL は次のように変更されます:

<...snip...>

call が /? を奪い取る模様。やっぱ Windows バッチって ks だわ。

2016-10-11

ADODB.Stream: Read write-locked file

あるシステムのログ集計を、Excel マクロでやろうとしたときのこと。

ログは UTF-8 で書かれており、ググれば ADODB.Stream を使えば良いことは直ぐに分かる。ほどなくマクロは完成し、本番投入の直前、その問題は発覚した。

ADODB.Stream.LoadFromFile は、書き込みロックが掛かったファイルを読み込めない!

それはつまり、システムが開いている当日分のログを集計できないことを意味する。しかし、今回の要件としてそれは受け入れられない。何てこった。そんなこと Google 先生も教えてくれなかったよ。

Sub Test1()
    With CreateObject("ADODB.Stream")
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        .Open
        .LoadFromFile "WriteLocked.txt"
        ' ReadText...
        .Close
    End With
End Sub

ならば、アクセスモード(Stream.Mode)を読み取り専用(adModeRead)にすれば開けるはず・・・、

Sub Test2()
    With CreateObject("ADODB.Stream")
        .Mode = 1   ' 1=adModeRead
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        .Open
        .LoadFromFile "WriteLocked.txt"
        ' ReadText...
        .Close
    End With
End Sub

どういうことなの。

恐らく、アクセスモードは Stream に対してのものであり、Stream が読み取り専用となったために Stream への書き込みメソッドである LoadFromFile がブロックされたのだと思われる。そうすると LoadFromFile に対してアクセスモードを指定する術がない以上、この方向での解決策は絶望的に思える。

ではファイルの読み込みは別の手段で行い、それを Stream に食わせたらどうか?

じゃそれ FileSystemObject で! と思ったら、FileSystemObject はバイナリファイルを読み込めないときた。ダメ元で無理やり読み込ませてみたら、化け化けになった。泣きたい。

結局、最も基本的な方法で読み込ませることで上手くいった。

Sub Test3()
    Dim fd As Long, _
        buf() As Byte
    fd = FreeFile
    Open "WriteLocked.txt" For Binary As #fd
    ReDim buf(LOF(fd))
    Get #fd, , buf
    Close #fd

    With CreateObject("ADODB.Stream")
        .Type = 1   ' 1=adTypeBinary
        .Open
        .Write buf
        .Position = 0
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        ' ReadText...
        .Close
    End With
End Sub

この方法の欠点は、ファイル全体をメモリに読み込んでしまうこと。できれば 1 行ずつ読み込ませたいが、バッファリング制御の実装とか大変そう過ぎて、やってみる気すら起きない。