2023年12月30日土曜日

シミュレーションゲームを使った行動分析

Twineというツールがある.もともとこのツール,「対話的非線形物語(interactive, nonlinear stories)」あるいは「あなた自身の冒険を作成(create-your-own-adventure)」と呼ばれる,オンライン版のテキストアドベンチャーゲームを作成するツールである.

このツールを用いて行動分析できないかと今年の卒研生が考えた.彼らは「避難行動のシミュレーションゲーム」を作成し,いま,その分析をしながら卒論を書いている.

もとより簡単な行動ログを記録する機能が用意されていたが,より簡便かつ確実に,詳細な行動記録を取れるように拡張してみた.本稿ではその概要を説明する.

Snowmanの利用

まず,Twine上で動作させるstory formatとしてSnowmanと呼ばれるものを利用する.Twineでは,いくつかのスクリプティングシステムを切り替えて活用できる.そのスクリプト言語のことをstory formatと呼んでいる.

デフォルトではHarloweと呼ばれるものが組み込まれているが,これを,Snowmanと呼ばれるstory formatに切り替える.Snowmanは,CSSやJavaScriptをある程度理解している人向けに用意されているもので,PHPやERB(Embedded Ruby)のように,<% …… %>や<%= …… %>といったタグを用いてJavaScriptをそのまま埋め込められる.

なお,Snowmanへの切り替えは,Twine編集画面のStoryタブにあるDefaultsメニューから行う.

Story JavaScriptの設定

Story formatをSnowmanに切り替えたら,まず,StoryタブのJavaScriptメニューを開き,Story JavaScriptに以下のコードを記載する.

window.story.state.hash = {};


// create a unique ID

window.story.state.uid = Date.now().toString(16) +

            Math.floor(1000 * Math.random()).toString(16);


$(window).on('sm.passage.shown', 

             function (eventObject, passageObject) {

  window.story.state.

    hash[passageObject.passage.name] = eventObject.timeStamp


  // disable the browser's back button

  history.pushState(null, null, null);

  return;

});


// to show the alert to quit the game

$(window).on('beforeunload', function (event) {

  event.preventDefault();

  return;

});

このコードは,ストーリーが起動されたときに最初に走るJavaScriptのプログラムである.なお,Snowmanでは,JavaScriptの動作スコープは各passage(ページのこと)内に閉じられており,グローバル変数をwindow.story以外に持たない.したがって,ストーリー全体でデータをやりとりしたい場合には,基本的にはwindow.story.state変数にいろいろと付け加えていくしかない.

そのような理由により,まずは,window.story.state.hashという連想配列を用意し,動作状況はそこに記録していくことにする.

なお,もうひとつ,window.story.state.uidというユーザIDを記録する変数も用意し,そこに一意な文字列として作成するIDを格納する.

Snowmanでは,passage(ページ)遷移時にsm.passage.shownというイベントを発火する.各passageのアクセス記録を取りたければ,そのイベントを受けて,先の連想配列に,passage名をキー,その時点でのタイムスタンプ(Unixエポック)をバリューとして,記録するようにしておけばよい.passage名はpassageObject.passage.nameとして,タイムスタンプはeventObject.timestampとして与えられるので,それを連想配列に記録する.

残りのコードは,ブラウザの「戻る」ボタンを無効にしたり,途中でやめようとしたときにアラートを発したりという設定を行うものである.

記録のテスト

簡単なストーリーを用意した.次の図は,四つのpassageから成るストーリーである.Story JavaScriptには先のコードが入れられており,最後のページには,記録されたユーザIDとJSON形式で提示されるアクセス一覧を表示するコードが埋め込まれている.

このストーリーを実行して最後のページ(The last page)まで遷移すると,次の画面が現れる.

一意なユーザIDと,JSON形式で表現されたアクセスログが表示されていることを確認できる.

ところで,ここまで注意深く読んできたひとは,"The last page"が記録されていないじゃないか?ということに気付いただろう.そのとおり.残念ながら最後のページの記録が残らない.これは,どうも,sm.passage.shownというイベントが,ページのレンダリングの「後で」発火するから,という仕様によるものらしい.

なお,ドキュメントにはsm.passage.hideやsm.passage.showというイベントもあると書いてあり,shownではなくshowを使えば最後のページも記録できそうなものだが,現時点で利用できるTwine 2.8.0とSnowman 2.0.2の組合せではsm.passage.shownしか使えなかった.残念だが,致し方ないところである.最後まで記録するためには,最後にもうひとつ,ダミーのページを用意して対処する必要がある.この点には注意しなければならない.

サーバへ送信

さて,ここまで確認できれば,あとは,最後のpassageにサーバへ記録を送信するコードを埋め込み,サーバ側ではその送信を受け取るコードを用意すればよいだけである.

<%

  $.ajax({

    url: 'https://your.server.domain/php/tlog.php',

    type: 'POST',

    data: { 'uid': window.story.state.uid,

            'log': JSON.stringify(window.story.state.hash) },

    dataType: 'json'

  });

%>

このコードはyour.server.domainというサーバに結果を送信するAJAXのコードである.ユーザIDとJSON形式で表現したアクセスログを送っている.

なお,アクセスログのデータは ... 'log': JSON.stringify(window.story.state.hash) }ではなく... 'log': window.story.state.hash }としてもそのままJSONデータとして送信できるが,サーバ側での処理を簡易化するため,この段階で文字列データ化して送信している点に注意.

サーバ側の処理

サーバ側のプログラムは,/var/www/html/php/tlog.phpというファイルにおいて,次のように記述する(サーバ側はUbuntu 20.04, PHP 7.4.3 および SQLite3 3.31.1を使用).

<?php

  $uid = $_POST['uid'];

  $log = $_POST['log'];


  $dbfile = './tlog_data.sqlite3';

  $conn = new PDO('sqlite:' . $dbfile);


  // create table

  $ddl = 'CREATE TABLE IF NOT EXISTS userdata(

             id integer primary key autoincrement, 

             uid string, log text)';

  $conn->query($ddl);


  // insert posted data

  $sql = 'INSERT INTO userdata(uid, log) 

          VALUES (:uid, :log)';

  $stmt = $conn->prepare($sql);

  $stmt->execute(array(':uid' => $uid, ':log' => $log));

?>

以上の比較的単純なコードで,ユーザ行動を記録できる.次のスクリーンショットは,記録の例である.左からID,ユーザID,アクセスログが記録されている状況を確認できよう.

今回は単純な線形のストーリーであるため,全て同じ行動でタイムスタンプが違うだけだが,複雑な非線形ストーリーを用意すれば,全ての選択行動をデータベースに記録でき,その結果を分析すればユーザの判断行動もわかるという仕組みである.

行動分析の例

最後に,行動分析の事例を紹介しておこう.いま卒論に取り組んでいる学生たちが用意したストーリーで得られた,ユーザの選択行動データである.テーマは「避難行動」,大地震に遭遇したときの避難状況において,ユーザはどういった判断をするのかという分析である.

次の図は,アクセスログから解析した行動状況を示すものである.ノードは各passageを示し,ノードに付記されている数値は,そのpassageを通過したユーザの数を表す.また,ノードの色は滞在時間の平均値から計算されたものであり,寒色系は短い時間,暖色系は長い時間を表している.白は誰も通過しなかったノード,および,最後のノードである(最後のノードはそもそも滞在時間を計測できないため).

この図は,アクセスログと,Twineから出力される.tweeファイルに基づき,PythonとGraphvizを用いて作成した.アクセスログだけでなく.tweeファイルも必要な理由は,誰も通過しなかったノードはアクセスログから掘り起こせないからである(なお,その作業を行ったことにより,どこからも参照され得ない不適切なノードの存在も発覚した.そのような不適切なノードは分析作業の対象外として,先の図には表していない).

この結果から,いくつか意義のある分析結果が得られている.ここでは,ひとつの興味深い事例を紹介しよう.


「道が分かれている」というpassageでは,ハザードマップを見たことがあるか否かの質問を投げかけている.「はい」を選んだグループと「いいえ」を選んだグループでは,明らかに,その後に投げかけられた「どの場所を通っていきますか?」という設問の回答に差が出ている.

見ただけで,ハザードマップを見たことがあるグループは大通りを選ぶ傾向がある一方で,見たことがないグループはそうでもないことがわかる.実は,ハザードマップには大通りを選ぶべきであるヒントが記されていた.したがって,素直に解釈すればハザードマップを見たグループは大通りを選ぶ一択になるはずなのである.この結果に対してカイ二乗検定を実施したところ,1%水準で有意差が示された.

2023年12月9日土曜日

悪質タクシーにご用心

ゆうべ,こんなことがあった.

昨日はサイバーワールド研究会が三田のNECで開催されたため,夜はNEC芝倶楽部で懇親会をした.懇親会を早い時間から始めたので,お開きになったのは20時頃.そして昨夜は,たまたまMRIの元同僚の皆さんが赤坂で飲んでいるとかでそちらからも声がかかっており,三田から赤坂に移動することにした.

三田で飲んでいたOさんと二人で赤坂に向かうことになったが,すでにかなり酔っ払っていて田町から赤坂までの最適な移動方法がすぐに思い浮かばない.大柄なOさんということもあって「面倒だからタクシーで行っちゃおう」と,OさんがタクシーGOというアプリで車を呼んだ(※ここ重要なので覚えといてね).

しばらくして個人タクシーが一台やってきて,我々はそれに乗車,赤坂に向かった.なお,座席は私が奥で運転手の後ろ,Oさんは入り口側である.タクシーに乗るのはずいぶんと久しぶりで,(初乗り500円だけど,100円ずつ,けっこういい調子でメーターが上がっているなあ)などと酔った頭でボーッと見ていた.

よく喋る運転手で,Oさんと運転手はずいぶんいろいろ話をしていた.タクシーやるなら個人タクシー,リスクもあるけど儲かる,なんて話.私はなんとなく億劫になっていて,それを聞くともなく,外を見たりメーターを見たりと所在無げにしていた.

さて,赤坂に近づき「どのへんでお降りになります?」と尋ねられたので「TBSのあたりで」と答えた.赤坂の手前,溜池山王を過ぎて日枝神社の前を赤坂に曲がる交差点でちょうど赤になったので,「あ,いまちょうど赤信号だから」と,我々はそこで降りることにした.

メーターを見たら2,400円.そんなもんかなと,財布から1,000円札を2枚出す.ポッケのなかの小銭を探していたら「あ,2,000円でいいですよ」と運転手.「えらいまあ気前のいい運転手だなあ,メーターがやたらと早く回るタクシーだから,それ差っ引いてそういうサービスなのかなあ」などと酔った頭で考えつつ,千円札2枚,2,000円を支払って車を降りた.

さて,先に降りていたOさんと歩道で歩きながら,その件に付いて話し出すと……

「え?お金払っちゃったの?タクシーGOで呼んでるから,2,500円,俺のクレジットカードから支払われるんだよ?」と,アプリの画面に大きく2,500円の文字が出ているのを見せるOさん.

おいおい,さっきの2,000円,いったい何だったんだ?

幸にして,ちょうど信号が変わった直後のタイミングだったので,左に曲がろうとしていたタクシーに追いついた.窓を叩いたら,運転手が窓を開けて「これでしょ」と2,000円を返してきた.

_人人人人人人人人人人人人人人人人_
> 「これでしょ」じゃねーだろ! <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄

わかってて,しれっとカネ受け取りやがったな.

アプリで呼んだので,素性はバレている.車のなかで「タクシーセンターに苦情を3回入れられると営業できなくなる」なんて話をしていた.さすがに苦情入れられるのが怖くなったかな?

タクシーGOの仕組みを知らなかった私もうっかりしていたが,忘年会,新年会で酔っ払ってまともな判断力を失いそうになるこの季節,皆さんも.お気をつけあれ.



2023年12月2日土曜日

名前なんて飾りです偉いひとには(以下略

「飯尾」という名前,とくにありふれているわけでもなく,かといってさほど珍しいわけでもなく,なんとなく中途半端な位置付けにある.全国には1万人弱くらいの飯尾さんが居て,その順位は1,600番目くらいだそうだ.最近ではお笑い芸人のコンビ「ずん」の飯尾がTVで多少は活躍しているようで,それなりに認知度が上がってきたか?という感じ.

1994年,三菱総研に入社したときに,1,000人に満たない規模の会社にもかかわらず別の飯尾さんがいらっしゃり,社員名簿に「飯尾(淳)」とカッコ書きで下の名前が付記された.学生時代には経験したことがなかった体験だったので,そのときは少し興奮した.なお,その後,同様の経験はなく,しばらくして先輩の飯尾さんは定年退社したため,カッコ書きは取れてしまった.今ではそもそも,社員名簿そのものが作られないご時世だ.

そんな飯尾という名前に多少の愛着はないこともないが,困るのが海外に行くとしばしば Lio にされてしまうことである.子音が一切なく母音だけ3文字という名前は奇異にみえるらしく,最初のI(アイ)を小文字のl(エル)だと勝手に判断された結果,Lioにされてしまう.

その件で初めて困ったのは,2007年にドイツに出張したときのこと.日本からの飛行機は,夕方,フランクフルトに着陸し,私は空港から電車を乗り継いで,その郊外にあるダルムシュタットという街に赴いた.翌日の予定として,その街にあるフラウンフォーファー研究所への訪問が目的だったが,とにかく,ダルムシュタットの街中にある予約してあったホテルに着いたのは,もう日も落ちて20時を超えた時間だった.

小雨模様でうら寂しい状況であり,かつ,季節は初冬でたいへん寒い.駅からタクシーでホテルの前まで送ってもらい,ホテルを見つけたときには,とにかく落ち着けそうだと安堵した.しかし,その宿はずいぶんと小さな宿で,夜になっていたので通りに面した入り口はすでにシャッターが降りていた.せっかく到着したのに入れないじゃないか.

とにかく部屋に入りたいとあたりを見回してみると,傍に2階へ上がる階段があり,その入り口にキーのディスペンサーが設置してあった.インストラクションを読むと「If you have a reservation, enter your surname as the password to deliver the key for your room.(予約がある方は,姓を部屋の鍵のパスワードとして入力してください)」とある.

そこで何度も I, I, O と入力してみたのだが,キーは出てこない.このときはまだ Lio に間違えられた経験も少なく,まさか Lio として登録されているなどとは思いもよらなかった.

予約がなくとも,部屋が空いていればクレジットカードで部屋を確保できるよとの指示があり,クレジットカードで部屋を押さえることができた.ひと安心して部屋に入ると,部屋の電話がすぐに鳴り「もうひと部屋必要になったのか?」と宿のマスターが尋ねてきた.

そうではないと断り,その夜はそれで一件落着となった.Lio で登録されていたからキーが出てこなかったのだと知ったのは翌朝,食堂でマスターと話をして正確な状況を確認できたときである.

このときの出張はドイツ,イタリア,フランス,イギリスと1週間で4国を回る弾丸出張で,結局のところ,泊まった4箇所のホテルのうち3箇所で Lio と間違えられていたことが判明した.なんてこったい.ちなみに,最後に訪問したイギリスでは,いつ帰る?と入国審査官に尋ねられ,「tomorrow(明日)」と答えたら,「ワーカホリックの日本人よ,もっとグレートブリテン訪問を楽しみなさい,次に来るときには絶対に1週間以上滞在すること!」と叱られた.余計なお世話じゃ.

なお,JALやらANAやら,日系の航空会社に乗ると「イトー」様と呼ばれることが頻繁にある.彼ら彼女らは Iio ではなく Ito に見慣れているからだ.「伊藤様,いつもご利用ありがとうございます」と何度言われたことか.こちらもすでに慣れっこであり,心はすでに伊藤淳である.なお,大学時代に同じ学科で学んだ同級生に伊藤淳史という友人がいる.彼の名は「いとうあつし」.同姓同名である俳優の伊藤淳史は我が家の近くに住んでいたはずで,彼のご子息がうちの息子と同級生だか一つ下だったか,というのは完全に余計な話.

IT業界には(もうすでにお亡くなりになっているが)itojun氏という有名な方がいて,Googleなど,iiojun でエゴサーチすると「もしかして itojun」などと言ってくる.全く,失礼千万である.名前なんて飾りだとはわかっていても,これはちょいとばかり酷くない?

さて,だいぶ話が脱線してしまったので,元の話に戻そう.今回参加した国際会議もネームプレートには Lio と記されていた.こちらも逆手にとって「外国の皆さんからするとヘンな名前だってことは知ってるから,驚かない.Junって呼んでね」と自己紹介のネタにする.全国の飯尾さんにおかれましては,国際的な自己紹介に使えるネタですよ?

最後に,「脚なんて飾りです,偉い人には……」という某アニメの有名なセリフを借りて,名前なんて飾りにすぎないとあらためて主張したい.やれハシゴ高だツチ吉だとこだわる人をたまに見かけるが,中身で勝負せいと言うのはお節介か.

ところで,うちに「昔の漢字コードだと対応する字がないのではてなマークにされちゃうんです.だからカタカナ表記にしています」という学生が一人いる.それはさすがに可哀想すぎる.聞けば,成績証明書の発行システムだかなんだかが対応していないらしい.Unicodeだと対応できているようなので,古いシステムを使っている組織は早いとこ新しいシステムにリプレイスしてあげてほしい.

2023年11月29日水曜日

2023冬季HCD研究発表会振り返り

2023年度冬季HCD研究発表会が11月25日,鹿児島女子短期大学にて開催された.かなり昔に札幌でHCD研究発表会が開催されたことがあるとは聞くものの,少なくとも私が関与するようになってからは,初めての地方開催である.今回の開催にあたり,ローカルのマネジメントに尽力くださった近藤先生とサポートくださった皆様方には感謝を申し上げたい.

今回のHCD研究発表会は,鹿児島での地方開催というだけでなく,東京の芝浦工科大学豊洲キャンパスをサテライト会場とした二会場開催という点でもきわめて挑戦的な開催であった.コロナ禍以降,現地参加とオンライン参加を許容するハイブリッド開催で実施していた本研究発表会ではあるが,今回は地方開催ということもあり,東京は豊洲にサテライト会場を設置して二元中継を行う新しい試みに挑戦した.

しかも,サテライト会場からの口頭発表だけでなく,ポスターセッションを鹿児島会場と豊洲会場の二ヶ所で行うという,あまり聞いたことのない斬新な試みにも挑んだ.ポスター発表を2会場で行う点に関しては,HCD研究発表会名物?の「ポスター発表中継隊」が大活躍してくれた.これもICT進化の恩恵であろう.

さらには「実践発表」カテゴリを設けたことにより,発表数が例年になく増えた(口頭発表とポスター発表を合わせて28件というのは例年の1.5倍相当である).実践発表の是非については本稿では省略するが,気軽に発表できる機会を提供できた点は,自画自賛ながら,評価に値するのではないかと考える.そのため,口頭発表の件数も20件となり,1日に実施するにはギリギリのスケジュールとなった.

シングルトラックで実施するにはほぼ限界の発表件数のため,今後は,マルチトラックにして対応せざるを得ないかもしれない.自作の研究会マネジメントシステムには,その含みを持たせてある.研究会規模の拡大がいよいよ現実味を帯びてきた.今回の開催がHCD研究発表会をさらに発展させるための試金石となっている状況をひしひしと感じる.これからの発展が楽しみである.

なお,HCD研究発表会のウリの一つに,発表に対するコメントを発表者にフィードバックするという特典がある.研究会に参加しているHCD-Netの理事と評議委員には,発表の評価と(できるだけ前向きな)コメントの記載をお願いしている.

そして,これも自画自賛になるものの,自作のシステムにより発表の評価とコメントをリアルタイムで集計するしくみが出来上がっている.集計されたコメントは,翌日にメールで発表者にフィードバックされる(この作業はいまのところ私が手作業で実施しているが,これもシステム化して自動でメールを送れるようにしたいところである).これは参加者におおむね好評で,これも発表者を増やすための一つのアイデアとして効果があるだろう.

いずれにしても,今後のHCD研究発表会のあり方として,春季冬季のいずれかは東京開催,そして他方は地方開催というルーチンを確立できればと画策している.そのためには,地方の拠点を確固たるものとせねばならない.

2023年11月23日木曜日

オンライン学習状況を可視化すると何が分かるか

IT系の某オンライン学習サイトの模擬試験受験状況データをいただいて,その分析を進めている.なかなか興味深い結果がみえてきているので,その一部を紹介したい.なお,このオンライン学習サイトは,無料で模擬試験を受けられるもの.その模擬試験は40問ひとセットで,40問の問題はランダムに出題される.

まず,どれだけのユーザがどのくらい模擬試験にチャレンジしているか?というデータを集計してみた.1回の試験にIDが振られているので,それらの数をユーザごとに集計する.その結果,最大で593回も受験しているユーザがいた(なお,次点が403回,その次が121回で,それ以下は100回以下である).

ほとんどが数回から十数回のチャレンジであるため,25回以下に限定してヒストグラムを描いてみた.その結果が次の図である.

1回しか挑戦していないユーザが多いのは予想通りで,指数関数的な分布を描くであろうという状況もほぼ予想したとおりである.特異的な値がみられず,比較的きれいなカーブを描いているのは,回数に注意するユーザはほぼいないことを示唆していると考えられる.

ところで,40個の問題が出される模擬試験だが,途中で諦めてしまうユーザも多いはずだと考えた.そこで,何問まで解答したか?について集計してみた.

ところがこれが意外なことに,ほとんどのユーザが40問,最後まで解答している.皆さん真面目だなあ.

しかし,それでも途中で諦めてしまうユーザも少なからずいる.そこで,何問まで解答して,そのあと諦めてしまったのかを,39問の解答までに限って集計し,ヒストグラムを描いてみた.次の図をみていただきたい.

こちらも,ところどころ特異点があることと,35問以降を除くと,指数関数で近似できるかできないか微妙な感じではあるが緩やかに減少するカーブを描いている.

しかし,先のグラフと異なるのは,5, 10, 20といった,明らかに特異点と考えられる点が観察できることである.これは,5問やってもういいや,10問やったからやめよう,20問まで頑張った……というように,キリの良い数でリタイアしている状況を表している.

35問から徐々に増えていることについては次のように考えられよう.すなわち,そこで諦めたというよりは,それ以降,答えがわからないのでスキップした,という状況が一定数あるとの示唆である.とくに39問が極端に多くなっている理由は,39問は解答したが40問目がわからなかった,という状況であろう.

(追記)学生から,タイムアップの影響じゃないですか?との指摘を受けた.たしかに,制限時間があるため,最後のほうは制限時間以内に解けなかったためにスキップされていると考えるほうが自然かもしれない.

2023年11月18日土曜日

すっぽんパワー

西麻布から六本木にかけて散歩した.たまの散歩はいろいろと面白いものを発見するので楽しい.

いきなりのスッポンスープ,高額自販機,ひと缶1,000円なりィの缶スープである.(缶飲料としては)破格のお値段.

遠目にみたら,自販機の横に「日々是好日 だしのある風景」とあった.

(ああ,最近よく見るだしの自動販売機だなあ)と思いつつ近づいていくと,まさかのスッポンスープである.スッポンスープにもノーマルとプレミアム版,2種類あるのが面白い.廉価版はひと缶760円と,プレミアム版に比べるとリーズナブル.いうて滅多に見られない価格設定ではあるが.

このスッポンスープ缶,いったいどんな人が買うんだろう?

場所柄,「これからいっちょ決めてやんべ!」とハッスルハッスルなオッサンが,1,000円札をズバッと投入,ガコンッと出てきたスッポン缶を腰に手を当ててグイッと飲み干すとか.そんでもって「オレ様の波動砲,エネルギー充填120パーセントッ!」なんて下品な冗談飛ばしながらガハハと笑いつつ,夜の六本木に消えていく…… なんて光景が目に浮かんだが,さすがに昭和な風景すぎますか?

2023年11月10日金曜日

横浜ぶらり旅

横浜にオフィスを構える某社を訪れて打合せする約束があった.午後イチの訪問予定だったので,少し早めに行って中華街で腹ごしらえを目論んだ.目指すは横浜中華街,香港路は安記のお粥である.

久しく訪れていなかった中華街,前回はいつ来たろうか.何年も前なことは間違いがない.みなとみらい線の元町中華街駅から歩き,東門から入る.道路がきれいになっていて,ずいぶんと垢抜けた印象を受けた.昼食にはいささか早い時間帯だったものの,焼き小籠包や大ぶりの肉まんなど,今でもあちこちで行列ができている.

香港路……,香港路……,中華街のメインストリートを西に向かって歩いていけば,左側に隠れるような入り口があるはず.少し歩くと……,見ぃつけた.

お粥の名店,安記は香港路に入ってすぐのところにある.なお,この路地には他にも海員閣という老舗の名店があるが,最近はお店の事情で営業をだいぶ縮小しているらしい.営業しているうちに,また行っておいたほうがよいかも.

さて,今日は安記である.もうすっかりお粥の口になっている.扉を開けて,店に入るなり,おばちゃんが「今の時間はお粥だけだけど」と告げてくる.ばっち来いやー!こちらはそのつもりで来ているのだよ.

メニューを見ずに,一言,「とりのお粥」と注文.880円.昔はもっと安かったような気がするが,このご時世だもの,仕方ないか.

待つことしばし,あっつあっつのお粥が運ばれてきた.これこれ.シンプルながら,抜群に旨い中華粥である.

レンゲで掬いながら,ふうふうして食べる.美味しいからといって,慌てて口に入れてはいけない.ヤケドする.

もう,一口一口が幸せを感じる旨さ.食べ進むと下のほうから鶏肉片たちがひょっこり顔を出す.これも旨い.トッピングの油条スライスもいい感じにふやけて旨い.途中で薬味を投入,それも旨い.気付けばあっという間に食べ終わっていた.

修学旅行のシーズンなのか,中華街は中高生で溢れていた.あいにくの雨模様だったが,久しぶりの中華街,安記のお粥で大満足である.

2023年11月7日火曜日

貴重な経験をした

エレベータの中に閉じ込められるという経験をした.人生で初めての経験である.ちょっとドキドキした.

それは,お昼休みに会議が予定されていて,早めの昼食に出た帰りのこと.自室に戻ろうと,エレベータに乗り13Fのボタンを押した.カゴに乗っていたのは自分ひとり.いつもどおり順調に階の表示が上がっていき,13になったところで,ガコンッと大きく揺れて停止した.

(ん?地震?)

最初に考えたのは,地震が来たかな?というものである.地震を検知して止まったのかな,と考えた.しかし,揺れは来ない.地震ではないらしい.

非常停止を検知したらしいエレベータから,「非常通話ボタンを押して,オペレータとお話ください」と音声案内が流れた.非常ボタンを押すなんて,これも初めての経験である.

ボタンを押す.すると,かなり大きな音でプーとブザー音が鳴り響く……ちょっと躊躇するレベル.まあでも,どうせ自分ひとりしかいないし,押し続けないとなあ.

頑張ってずっと押し続けていると,オペレータ氏と話が通じた.

オペレータ(以下「オ」):「聞こえますかー」「聞こえますかー」

私:「聞こえてますけど,こっちの声,聞こえますかー?」

向こうの声は聞こえるが,こちらの声が届きづらいらしい.非常ボタンをプッププップと押してみたり,あれやこれや試してみたりしてなんとか意思疎通を試みたところ,大きな声で喋れば会話も通じることが分かった.

オ:「いまどうなってますかー」

私:「13Fに向かってたんですけど,13Fになったところで,ガコンッって大きな音がして,止まっちゃいました」

オ:「開くボタン押してみてください」

私:「押しましたー.開きませーん」

オ:「そちら,どういう状況ですかー」

私:「わたしひとりです」

オ:「現場に連絡しますので,落ち着いて,お待ちくださいー」

落ち着いてと言われても,(このまま落っこちたりしないだろうな?)って,やっぱり心配になる.けっこう大きな音で,ガッコンッっていってたし.

そして,やはり気になったのはこの後の会議のことだ.ワーカホリックな私.幸にして電波が届くようだったので,事務室に電話する.「あ,飯尾ですけど……,エレベータに閉じ込められちゃいまして」間抜けなメッセージに,電話の向こうもびっくりしたのではなかろうか.

ひと通り経緯と状況を電話で説明し,はてさてどうしたもんかなと考えあぐねていたら,再びインターホンからオペレータ氏の声が.

オ:「いまから15分くらいで係員が向かいますのでー」

え?15分も待たされるの?さっきからもう10分は経ってるよ?

しばらくしたら,外から声がする.「おーい」ダメもとで声をかけてみると「大丈夫ですかー?」と呑気な呼びかけが扉越しに響いてきた.

「閉じ込められちゃいましたー」

こちらも負けずに間抜けな声で応答する.「もう少し待っててくださいねー」「待ちまーす」みたいな牧歌的なやり取り.しかし客観的にみたら,閉じ込められてる私,これってけっこうピンチでは?

閉じ込められてから20分くらい経っただろうか.「いま開けますね!」と,ようやく明るい希望の声が聞こえた.そして開けられるエレベータの扉から,パァアアア…… と広がる明るい光.いや,冗談じゃなくて.助けに来てくださった作業員の方には,たしかに後光が差していた.

次の写真を見ていただきたい.扉が開いたときの状況である.惜しい.あと1メートル.

助けに来てくれた方が「よじ登れますか?」と私に問う.何を仰いますやら,よじ登ってみますとも.まあ,1メートルくらいの段差,造作もない.よじ登ったときの衝撃でガコンとカゴが落ちて,胴体から真っ二つ……なんてことになったらヤダなあ,みたいな縁起でもないことは,考えないようにして,とにかく脱出成功.助かった.

以上が本日の顛末である.振り返ってみれば貴重な経験をしたといえるが,も一度体験したい?と問われればそれはもちろんNoだ.

2023年11月4日土曜日

ハーブの想い出

ハーブが好きだ.東南アジア諸国,とくにベトナムで食べられる,あの得体の知れない謎の薬草に魅せられている.しかし,日本で生活しているとあの謎の草を食べる機会にほとんど恵まれないのが残念でならない.

タイの中南部,ナコーンシンタンマラートという地方都市に出張した.いろいろ案内してくれた現地の担当者が「ここまで来てカノムジーンを食べないでは帰させない」と,カノムジーンの名店に連れてきてくれた.

カノムジーンとは,米を原料とする素麺のような麺に,ピクルスや豆などの付け合わせや鶏の揚げたものを添えて食べる料理である.単なる素麺ではなく,その上から何種類ものカレーソースから好みのものを選んでかける.辛いものからマイルドなものまでたくさんの種類を選べる.シーフードあり,チキンあり,どれも美味しい.お好みでミックスしても構わない.さらに,写真のようなたくさんの種類の葉っぱを好きなだけちぎり,最後に全部を混ぜて食べる.

雰囲気としてはベトナムのブンボーフエに似ている.ただし,こちらのほうがバラエティに富んでいて楽しい.

食べ方としてはこんな感じ.ただしこれは混ぜ混ぜする前の写真である.

ドライハーブとフレッシュハーブ

以前,ASEANの仕事に関わったことがあり,その際に,タイとベトナムから来ていた方々と話をした.曰く,「タイ料理はドライハーブを使い,ベトナム料理はフレッシュハーブを使うのだ」という.私はタイ料理もベトナム料理もどちらも好きだが,どちらがより好きか?と問われれば,草(ハーブ)だいすきという意味ではベトナム料理が優っているし,料理のバラエティからすればタイ料理も捨てがたいと感じていた.

さらに,タイの東北部,イサーン地方の料理に好きなものが多く,フレッシュなハーブを多用するラープはタイ料理のなかでも大好きなもののひとつである.イサーン地方はラオスを挟んでベトナムにも近い.さもありなん……と,これまでは思っていた.

ところが今回のカノムジーンである.ベトナムからは遠く離れたタイ中南部.ここでもこんなにフレッシュなハーブ使うんじゃん?

葉っぱはどこから?

ところでこの草たち,いったいどこから持ってきているのだろう,という疑惑がむくむくと湧き上がる.

今回連れて行ってもらったカノムジーンの店は郊外にあり,ど田舎の一軒家という風情の店だった.食卓はテラス席,といえば聞こえはよいが,庭に無造作に建てられた日除けの下,アウトドア席である.天気もよいので,これはこれで,なかなか気持ちのよい食事ができる.

さて,草である.

裏手に大きな鉢がいくつか転がっていたのだが,その鉢でいろいろな植物を育てている様子が窺えた.どうも,そこでこれらのハーブを栽培しているらしい.そこから収穫して持ってきているようにみえる.まあ,それはそれで全く構わないし,美味しいのだから問題ない.

夏に学生たちをベトナムに連れて行ったときに,この草の由来が問題になった.連れて行った学生のひとりが,「そもそもどこから持ってきた草なのか怪しすぎて食べたくありません」と言うのだ.

ホーチミン市の近代的な食堂である.タイの片田舎(といっては失礼だが)の郊外にある大自然に囲まれた店とは違う.それらの草はマーケットで買ってきた,「ちゃんとした」ものだろう.当該学生と一緒に市内のスーパーマーケットに行く機会があり,野菜売り場を覗いてみた.そこには多様なハーブがたくさん並んでいた.

「どう?これで大丈夫と思った?」と聞いてみたが,やはり抵抗があるとか.まあ,人それぞれか.

薬草だから大丈夫

話はいまから20年前,2003年に遡る.私が東南アジア関係の仕事に関わりはじめたころで,初めて東南アジアに出張したときのことだ.行き先はベトナム,よくある話で「水には気をつけろ.不衛生な水で洗っているから,生野菜は食べないほうがいい」などと脅かされていた.

いまでは「そんなことなかろう」と笑って済ませる話だが,なにしろ右も左も分からなかった当時のこと,忠実に言いつけを守っていた.しかし,1週間ほど滞在した最終日に,案の定,腹を下してしまう.

そのときに,現地駐在の長かった某社現地法人の支社長から「ハーブを食べなさい.これは薬草だから大丈夫」と,諭されたことを今でもはっきりと覚えている.

おそらく冗談半分だったろうが,強く印象に残っている.その後,生野菜なんかよりもっと危ない食べ物を口にして腹を思いっきり下したこともあり,いろいろな体験をした結果,私も成長した.東南アジア各国のどこに行っても生野菜は平気で食べるし,ビールも氷を入れて飲む東南アジアのスタイルじゃないと飲んだ気がしない.

2023年10月31日火曜日

データサイエンス・アイデアコンテスト

3大学(関西・中央・法政)共催 データサイエンス・アイデアコンテスト(協賛 マイナビ)の最終選考会に出場した4チームのうち,iDS飯尾ゼミから出場した2チームが特別賞を受賞しました.おめでとう!

大学からのニュースリリースはこちら,「開催報告:3大学(関西・中央・法政)共催 データサイエンス・アイデアコンテスト(協賛 マイナビ)最終選考会」です.

最終選考に残らなかったチームも,頑張りました.惜しかった.次回は全員入賞を目指すぞ!

2023年10月28日土曜日

ビデオ授業の難しさ

RubyとRuby on Railsの基礎に関するオンライン授業を担当し3年目になる.全学部の希望者を対象としたビデオ授業,いわゆる,オンデマンド型オンライン授業という形式で実施している.この分野は進化が激しく,また,学生のレベルに合わせて内容を調整しながら進めているため,今年は3年目にして動画解説を撮影しなおしている.いちど動画を撮影してしまえばあとはラク……というわけにはいかないので,なかなか大変である.

ビデオ授業のため,教室での教員と学生のインタラクションが実現できない.そのため,LMSの掲示板を利用して質問を受け付けるようにしている.なにしろ100人を超える受講者がいるため,質問も頻繁に投稿される.そのため,質問対応にTAの手を借りているが,私もちょいちょい掲示板を覗いて回答するように心がけている.

上に挙げた例のように,ビデオ講義の動画でしっかり説明しているにも関わらず,それらの内容について質問してくる学生は多い.これはいったいどうしたものか.

ある学生との対話による気付き

あるとき,「どうしてもうまくできないんです」と研究室を訪ねてきた学生がいた.その意気やよし,というところだが,「エラーの状況を再現してみ?」というと,動画を小刻みにスキップして参照しながら,作業を進めようとする.

それじゃダメだよ……

物事には順序があり,とくにプログラミングにおいては順序どおりやらないと,うまくいかない.動画をスキップしたところでも,重要なポイントが説明されているはずだ.そのとおり進めないからエラーになるのである.

教室での講義であればしっかり聞いているかと問えば,そうでもないだろう.しかし,教室で演習をしていれば,つまづいたところでは周囲と助け合ったり,その時点で誤りを指摘できたりと,確認しながら進められる.しかし,オンデマンド講義で,しかも2倍速で視聴していたり,必要そうなところだけ摘み食い的に視聴していたりしているのでは,漏れがあるのもさもありなん,というところだろう.

いかに漏れなく伝えるか

とくにプログラミングに関する授業では,「必要なことをいかに確実に伝えるか」という配慮が教員側にも必要になる.A→B→C→D→……という作業手順があるとして,なぜこの順番でやるのか,あるいは,A,B,という手順がなぜそれでよいのか,という個別のポイントを,丁寧に伝えられるかという技量が求められる.

作業に慣れている,原理を理解している教員側は,さも当たり前のこととして「A→B→C→D→……」という作業手順を説明する.しかし,初見の学生は,なぜそれでよいのかとか,それを行うための前提知識などがわからない.そのため,「前提知識がないこと」を前提として,必要以上に丁寧に説明するように心がけがほうがよい.

それだけ配慮していても,説明が漏れることがある.そのうえで,ビデオ授業だと,先に述べたような視聴態度をとる学生は,A→C→D(Bをすっ飛ばす)というような理解をする.それではうまくいくわけがない.

このような,情報の欠如をいかに防ぐか,これは学生だけの問題ではなく,教員側の配慮も必要になろう.

なお,補足する手段として掲示板での質問を推奨している.掲示板での質問が活性化することは,基本的にはウェルカムである.しかし,無駄な質疑はできるだけ避けたいところ.そのために,全受講者に対してオープンな掲示板で質問しなさいと指導している.Q&Aが溜まればそれはひとつの財産になるし,重複した質問を避けられる利点があるからである.

2023年10月21日土曜日

散歩のすすめ

昨日,半蔵門で地下鉄を降りて市ヶ谷に向かっていたら「エクセル麹町」というマンションの前を通りかかった.そして今日,巣鴨から駒込までぶらぶら散歩していたら,「エクセル巣鴨」を発見.昨日の今日なので,驚いた.

調べてみたら,エクセル早稲田やエクセル大塚,エクセル駒込,エクセル千石,エクセル茗荷谷など,エクセルシリーズが街ごとにあるらしい.

散歩しているとこういうことに気づく.散歩していないとなかなか気づかない.散歩は面白い.

2023年10月19日木曜日

OSS万歳\(^o^)/

事の発端はこれ.学生たちがTwineというツールを使い,とあるシミュレータを作ろうとしているのだが,操作ログを記録してユーザの挙動を分析したい,なんてことを言っていた.TwineではHarloweという簡易なスクリプト言語というかマクロ?を利用でき,それを使えばできそうだなとやってみた.

(history:)というコマンドがあって,最後のページでそれを評価すればユーザの操作履歴は追える.しかし,残念ながらタイムスタンプまでは記録されない.したがってタイムスタンプ付きで記録を取るには,自前のスクリプトを書く必要がありそうだ.少し考えた末,(current-time:) というコマンドを使って,変数に逐一記録していけばできそうだと試してみた結果が次の画面である.

できるにはできたが……惜しい.なんということか,(current-time:)の粒度が粗すぎる.さて,ではこの(current-time:)をなんとかしようか,と手を出してしまったのが,今回報告する顛末の発端である.

Twineを調査

まずは,Twineのソースコードを調査する.GitHubから同プロジェクトのソースコードをダウンロードしてきて,"current-time"をキーワードにgrepしてみるも,それらしいコードが見当たらない.

そもそもHarloweのスクリプトをレンダリングしているのはどこのタイミングなんだろう?これがよくわからない.Google ChromeでF12キーを押してWeb開発ツールでデバッグしてみようにも,どうにもよくわからなくてお手上げである.

そこでHarlowe関連のドキュメントを探ってみた.ん?Harloweって,Twine関係ないんじゃないの?と気付いたのが迷路から脱出できた鍵となった.決定打は「Where can I find the "Twine engine code"? #649」というGitHubのイシュー.「Twine engine code」がキーである.

なんということはない,Harloweスクリプトは,Twineが出力するHTMLに埋め込まれた難読化されたTwine engine codeのJavaScriptが解析し,その動作を決定していたというわけだ.そこで,次はHarloweのソースコードにあたる.こちらをダウンロードして,解読した.

Harloweエンジンの調査

ここから先は一本道だった.Harloweのソースコードを入手,展開し,再び"current-time"をキーワードにしてgrepする.

BINGO!当該コマンドを処理するソースコードに辿り着いた.案の定,new Date() して日付オブジェクトを取得したあと,時間と分を得て,文字列を生成している.ここに秒を取得するコードを追加すればよいだけである.

以上の追跡結果から,Twineの出力に埋め込まれた難読化JavaScriptの該当部分にパッチを当てれば望んだ出力が得られるということがわかった.

これで問題は解決したのだが,ここまで3時間.やはり,他人様の書いたコードを解読するのは難儀な仕事よのうと思ったとか思わなかったとか.

2023年10月7日土曜日

AのBのCのD問題

「AのBのCのD」と題したが,「α of β of γ of δ」でも同様,すなわち,日本語でも英語でも避けるべき表現で,多くの言語に共通する話題である.

あるXのポストがちょっとした話題になっていた.次の図はそのキリトリである.なお,IDを特定できる部分は,自分のアイコンを除いて,モザイクをかけた.

ここで問題になっているのが,「高校の国語の教員の妻」という表現である.「の」の数が間違っているのはご愛嬌として,この表現が悪文であるとの指摘に私も異論はない.

悪文の理由

なぜこのような表現が悪文とされるのだろうか.ひとつには,〜の,〜の,〜の……という,単調なリズムの問題がある.これは若干,感覚的なものかもしれないが,文章において単調なリズムが繰り返されると,違和感を覚える.

よく例に挙げられるのは,「Aである,そしてBである,そしてCである,そしてDである」というような表現.「そして」という接続詞で文を淡々と繋げる表現は「小学生の作文じゃあるまいし」と指摘されるだろう.

文末が同じ表現で続くような文章も同様である.上記の「〜である」が続くのも端的な例であろう.文を書き慣れている人であれば,それを避けるために,形容詞で終わらせたり,多様な動詞で終わらせたりといった工夫を自然と加えているはずである.

「『の』や『of』で繋ぐのは安易だ」という指摘もできよう.上記の「高校の国語の教員の妻」という表現は,「高校で国語を教えている妻」と言い換えられる.「の」を一切使わずに同じ意味を表現できる.

曖昧性の忌避

上記の言い換えに関し,「え?意味変わってね?」と思われた方もいるかもしれない.それは,おそらく「高校の国語の教員の妻」を「高校の国語教員(をしている人)の妻」と解釈していた方だろう.

このように,「AのBのCのD」と「の」を重ねた表現は,解釈の多義性が生まれかねないリスクを孕む.もっと別の例で考えてみよう.「前の会社の管理職の妻」ではどうだろうか.

  • 「以前勤めていた会社で管理職として働く妻」
  • 「以前勤めていた会社の管理職である人の妻」
  • 「目の前にある会社で働く管理職の人の妻」
  • 「目の前にある会社で働いている管理職である妻」

など,いろいろな解釈が可能で,もはや収集がつかない(他にも考えられるはず.考えてみてください).

文脈に強く依存しがちな日本語

さて,当該スレでは議論が盛り上がっていて,リプ欄を追っかけていたら,この文章は曖昧で複数の意味に解釈できるから悪文であるという指摘に対して「日本人なら一意に解釈できるでしょ」って噛みついている人がいた.

「いいと思う?最低です.高校の国語の教員の妻も同意見です」という元文章だけだと分かりづらいが,私なら次のように考えるだろう.

何かについて「最低だ」と言っていて,妻も同意見だと補足している,話題に出ているのは「日本語の作文技術」っていう本で,あーだから高校の国語の教員なのか,じゃあ,本人が教員だったら,あえて「妻も同意」っていうのはおかしいな?と考えると,教員なのは奥さんなんだな……

このような推測に基づき,多くの日本語話者が「高校の国語の教員をしている奥さん」と考える.だから「日本人なら分かるでしょ」となる.

日本語は主語を省略してもよいくらい,文脈に強く依存する言語である.そのことに鑑みれば,カミツキ氏の主張は分からぬでもない.しかし,読み手に負担をかける,認知負荷を強要するという点で,避けるべき表現であるという指摘は譲れない.なので,上記のように考えなかった人も悲観することはない.ご安心を!

いずれにしても,どのような言語にしても,分かりやすい文章表現と分かりにくい文章表現はあり,分かりやすい表現を心がけないといけない.そう考えると,やはり「AのBのCのD」のような表現は避けるべきである.私なら「AのBのC」も避ける.「の」に限らない.同じ助詞が続くような表現は使わないように気をつけている.英語でも同じである.

2023年10月3日火曜日

今日の教育ぷちDX

例年,ちょっとした反転授業というか,履修者から提出された課題のフィードバックを次の授業時間の冒頭でそれなりに時間をかけて念入りに解説するようにしている.履修者の満足度は高く,それゆえに学習効果も高くなるであろうことが期待される手法と考え,数年前から導入している方法である.

ところが,実際にこれをやろうとすると,その準備がけっこう大変である.提出物を一括してダウンロードするところまでは,LMSの機能を用いれば簡単にできる.そのファイルに対して,例年は,匿名化し,順序をシャッフルしたうえで一つのファイルにまとめ,誰の提出課題かわからないように示すという作業を,手で行なっていたからである.

手作業でやっていた理由は簡単で,例年の履修者が10数人といった規模だったので,手作業でやってもせいぜい30分くらいの作業で済んでいたから,なんとなく惰性でやっていたにすぎない.

ところが今年は,なぜか履修者数が50名を超えた.1回めの受講状況はその6割といったところで,課題提出者は30数名であった.しかし,30もあると手作業でやるのは,やや,しんどい.

というわけで重い腰を上げて,簡単なスクリプトを書いて処理することにした.

まずはファイルをランダムに並べ直してファイル名を匿名化するコードを考えた.Rubyのshuffleメソッドを使えば簡単に実現できるな?と思って書いたスクリプトが次のものである.LMSからダウンロードした履修者のファイル,そのファイル名は,学籍番号コード文字列の後に履修者が提出したファイルの元の名前が続く,という仕様になっているため,2桁の数字の後に「G」が続くという学籍番号の特徴を利用して,それらのファイルだけを選択してファイル名を変えるようにした.

#!/usr/bin/env ruby


system("rm reportlist.xlsx")

files = IO.readlines("| ls | grep [123][0-9]G")

files.shuffle!

files.each_with_index{|filename,i|

  filename.chomp!

  (body, ext) = filename.split('.')

  system("mv \"#{filename}\" file%02d.#{ext}" % i)

}

続いては,ファイル内に記載された指名と学籍番号の削除である.これも実にいい加減なクイックハックで,提出されるファイルが「こちらがあらかじめ用意したワークシート」であることをいいことに,2行目と3行目に書かれるであろう氏名と学籍番号を,単純に削除するだけのもの.こちらはPythonのpython-docxライブラリを用いた.

#!/usr/bin/env python


import docx

import sys


filename = sys.argv[1]

doc = docx.Document(filename)

doc.paragraphs[1].text = ''

doc.paragraphs[2].text = ''

doc.save(filename)

あとは,binディレクトリに置いておいた先のファイル名変更スクリプト(rename.rb)と,こちらの匿名化スクリプト(removeid.py)を,シェルスクリプトのバッチファイル(batch.sh)で回すだけである.

#!/bin/sh


../bin/rename.rb


for f in file*.docx; do

  /bin/echo -n "processing $f ... "

  ../bin/removeid.py $f

  echo done

done

実に簡単.手間いらず.LMSからダウンロードした提出物を展開して,このバッチファイル一発かますだけ!

今日は少し時間と手間を掛けてしまったが,来週から準備も楽になるなーと思うと,少し楽しい気分になる.