FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【英国見聞録 No.9】カレドニアン・スリーパー

亀のようにのんびりと続くこの連載、もしもお付き合いいただいている読者の方がいらっしゃいましたら、誠にありがとうございます。
カープは見事に3連覇してくれましたが、鷹の鉄壁はどうしても破れなかったのが悔しいところ。夢というものは簡単には叶いません。丸と長野が入れ替わるという大ニュースが流れたのも記憶に新しいですが、盤石の布陣で次のシーズンも楽しみなところです。



島国イギリスでは、現在でも2つの寝台列車(スリーパートレイン)が運転されています。
ひとつは、ロンドンと西部のペンザンスを結ぶ「ナイト・リビエラ」、そしてもうひとつが、今回旅行記でご紹介する、ロンドンとエディンバラ・グラスゴー・インヴァネスなどを結ぶ「カレドニアン・スリーパー」です。

今回私が乗車したのは「ロンドン・ユーストン駅発、エディンバラ・ウェイヴァリー駅行」の便…のはずでした。列車には「グラスゴー・セントラル駅行」も併結されています。


Caledonian Sleeper
ユーストン駅で発車を待つ「カレドニアン・スリーパー」。
眼鏡がお似合いの女性の車掌さんが乗務。日本ではまず目にすることのなかった光景だ

使用される客車は、1964年登場の「マーク2」型と1975年登場の「マーク3」型です。
そのドアは昔ながらのイギリス客車のスタイルを継承し、ドアは手動式となっています。ドアノブは車外側にしか取り付けられていないため、車内から開ける場合にはドア窓を降ろしてから手を車外側に回し、車外側のノブをひねる必要があります。

なお、2018年春から客車を新形式に置き換える計画がありましたが、予定より遅れて今年2019年春からの投入予定となっています。ドアノブひねりを体験するのなら、ぜひお早目に。


列車は、1等・2等の寝台車と座席車で構成されています。
1等寝台車は1人用個室、2等寝台車は2段ベッドの2人用個室(1人利用の場合は相室)となっていますが、2等寝台車を1人で利用してもほかの利用者がいなければ実質的には個室になり、大変快適に利用することができます。


Caledonian Sleeper

Caledonian Sleeper
2等寝台車の個室。筆者は下段を予約したが、当日はガラガラで上段に客がおらず、実質的には2人用個室を独占することになった。
各寝台には、ミネラルウオーター・石鹸・耳栓・アイマスクなどのアメニティが無料でつく。
なお、窓際のスペースは洗面台を兼ねている


Caledonian Sleeper
寝台車の廊下。その狭さは今はなき日本の寝台客車と似たようなものだ

列車にはラウンジカーが連結されており、食事や飲み物を注文することができます。スコットランド料理を基本として、ビールやウイスキーも充実したメニューです。利用は1等寝台の利用者が優先となり、ラウンジが満席の場合には注文の品を自室まで届けてもらう形での利用が可能です。

Caledonian Sleeper
高級感あふれるラウンジカー

さて、目を覚まして車掌さんに用意してもらったコーヒーを楽しんでいると、小さな駅で列車が止まり、なぜか車掌さんに個室をノックされました。
車掌さん「エディンバラに行くなら今降りて。乗換よ。この列車はエディンバラには行かないわよ」
(窓の外のホームを見ると確かに乗客がぞろぞろ降りていく)
私「あれ、エディンバラまでの寝台券を買ったはずなのですが?」
車掌さん「今日は都合で全車両がグラスゴーに行くのよ…」
(少し考えて)
私「(もうちょっと寝台車に揺られたかったので)わかりました。ならこのままグラスゴーまで乗っちゃってもいいですか」
そんなやりとりをして、車掌さんもここで下車。
もともとその日はエディンバラとグラスゴーの両方を巡るつもりで、その日の晩までにリヴァプールに着ければ十分だったので、咄嗟の判断で巡る順序を入れ替えることにしたのでした。

さて、イギリスの乗車券には日本の鉄道のような「乗車券の運賃と特急列車の特急料金」の別はありませんが、寝台列車の寝台料金については、運賃とは別建ての設定となっています。
乗車する際は、運賃と寝台料金のセット料金を支払うか、我々外国人旅行者のようにレールパスを所持している身であれば、別途寝台券のみ購入するだけで乗車できます。
日本ではすっかり希少になった寝台列車での夜汽車旅、海の外に目を向ければ、まだまだ存分にお楽しみいただけますよ。ぜひ。



くわしいことは: カレドニアン・スリーパー 公式サイト (英語)


スポンサーサイト

JSON勉強記

スマホ全盛、呼吸するようにTwitterをするという時代、正直、ホームページへのアクセス数など日に数十PVあればいいものです。
そのために日々デザインに凝ることは正直時間と労力の無駄遣いでしょう。

今はむしろ、自身のITスキルの勉強の題材として活用していることも多いです。
社会人1年目の私は、実はある会社で乗換案内のプログラムを作っていたりします。
「KR鉄道館」を運営する中で、HTMLからCSS、JavaScriptくらいは一通り経験していますが、C言語でさえ就職して初めて触ったもの。
なにぶんにもIT技術に関する専門教育を受けてきたわけではないため、実務のためには自分でいろいろ勉強してみる必要があります。

今回はサイトの情報をデータベース管理するため、JSONを導入してみました。
そもそも今ほとんどホームページを更新できていないのですが、たまに更新するときにいつも行っているルーチンワークで、こんな悩みがありました。

  • 更新情報の作成に、細かい作業が多く、煩雑である。
  • 更新情報をトップページと更新情報ページのそれぞれに同一内容を表示させているのに、それぞれ手作業で更新していたため、面倒である。

そこで今回、次のような仕様で、更新作業を簡略化すべく考えました。

  • 更新情報データはデータベース化して、複数のページから同じファイルに情報を呼びにいく。
  • HTMLを自動生成する際、トップページ用と更新情報ページ用で、生成方法を分ける。
  • トップページ用:データベースのうち最新の5件を表示する。
  • 更新情報ページ用:指定された年の情報をすべて表示する。
  • 見た目はJSON導入前後で変化しないよう配慮する。

「てつたのアルバム」も、各アルバム情報(タイトル、キャプション、作成日等)のデータベースを作り、そこから各ページを接続させて構築しているのですが、JSONをまともに知らなかった時分、JavaScriptの配列を使ってこれを実現していました。
しかし、JavaScriptの配列をそのままデータベースとして使うのはあまりスマートとはいえないため、もっときれいに作りたいと考えていました。

そこで今回は、JSONを使ってデータベースを作り、そのデータを基に自動でページ内容が更新できるようにしました。

1.データベースの作成


JSONでデータを作ります。今回はこんな感じにしてみました。

data.json
{
	"data" : [
		{
			"ymd"	:	20170218,
			"mark"	:	"a",
			"url"	:	"album/",
			"text"	:	"「増毛の記憶~2016」ほかアルバム3点を公開しました。"
		},
		{
			"ymd"	:	20160522,
			"mark"	:	"o",
			"url"	:	"selfintro.html",
			"text"	:	"「管理人紹介」を更新しました。"
		},
		{
			"ymd"	:	20160604,
			"mark"	:	"o",
			"url"	:	"link.html",
			"text"	:	"リンク集を更新しました。"
		},
		{
			"ymd"	:	20160529,
			"mark"	:	"o",
			"url"	:	"selfintro.html",
			"text"	:	"「管理人紹介」を更新しました。"
		},
		{
			"ymd"	:	20160405,
			"mark"	:	"o",
			"url"	:	"selfintro.html",
			"text"	:	"「管理人紹介」を更新しました。"
		},
		{
			"ymd"	:	19001231,
			"mark"	:	"m",
			"url"	:	"",
			"text"	:	"JSONテストデータ3"
		},
		{
			"ymd"	:	19001101,
			"mark"	:	"s",
			"url"	:	"",
			"text"	:	"JSONテストデータ2-1"
		},
		{
			"ymd"	:	19001031,
			"mark"	:	"si",
			"url"	:	"",
			"text"	:	"JSONテストデータ2"
		},
		{
			"ymd"	:	19000101,
			"mark"	:	"b",
			"url"	:	"index.html",
			"text"	:	"JSONテストデータ1"
		}
	],
	
	"markdef" : {
		"a" : "アルバム",
		"b" : "BVE",
		"s" : "駅",
		"m" : "動画・音",
		"si": "サイト",
		"o" : "その他"
	}

}

{ }(大かっこ)を使うと連想配列:オブジェクトを作成でき、「"key" : "value"」の形で値が設定できます。
また、[ ](角かっこ)を使うことで、0番から始まる各種プログラム言語でおなじみの配列をつくることができます。

今回はこれを組み合わせて、"data"のキーに各更新情報の配列をつくり、その中にそれぞれオブジェクトを作りました。
"ymd":更新日。データの整理に最も重要。
"mark":行頭のジャンルマーク。
"url":リンク先URL。ルートディレクトリを基準に相対パスで記述しています。
"text":更新情報文の本文。

最初の5件は実際に使うデータ、残りの1900年を指定したデータはテスト用のダミーデータです。

なお、"markdef"キーには、各ジャンルマークの記号に対する日本語名を定義しています。ジャンルマーク画像の代替テキストとして使用します。

2.JavaScriptコードの作成


そして、このJSONを呼び出すために書いたソースがこちらです。

updates.js
// HTTP通信用、共通関数
function createXMLHttpRequest(cbFunc)
{
	var XMLhttpObject = null;
	try{
		XMLhttpObject = new XMLHttpRequest();
	}catch(e){
		try{
			XMLhttpObject = new ActiveXObject("Msxml2.XMLHTTP");
		}catch(e){
			try{
				XMLhttpObject = new ActiveXObject("Microsoft.XMLHTTP");
			}catch(e){
				return null;
			}
		}
	}
	if (XMLhttpObject) XMLhttpObject.onreadystatechange = cbFunc;	//ファイルの読み込み完了時の動作
	return XMLhttpObject;
}

// document.getElementById
function $(tagId)
{
	return document.getElementById(tagId);
}

function writeData(position, mode)	//ファイル名、表示するID、動作モード
{
	fName = 'updates/data.json'
	httpObj = createXMLHttpRequest(function(){displayData(position, mode)});	//クロージャにすると引数を収められる
	if (httpObj)
	{
		//リクエストのタイプを設定
		httpObj.open("GET", fName, true);
		//キャッシュは読みに行かせない
		httpObj.setRequestHeader('Pragma', 'no-cache');   
		httpObj.setRequestHeader('Cache-Control', 'no-cache');                    
		httpObj.setRequestHeader('If-Modified-Since', 'Sat, 01 Jan 2000 00:00:00 GMT');
		//リクエストを送信
		httpObj.send();
	}
}
function displayData(position, mode)
{
	if ((httpObj.readyState == 4) && (httpObj.status == 200))	//読み込み完了
	{
		$(position).innerHTML = parseJSON(httpObj.responseText, mode);
	}
}
// JSONのデータを解析して表示
function parseJSON(jsData, mode)
{
	var data = JSON.parse(jsData);
	var resultData = "";
	for(var i=0; i<data.data.length; i++)
	{
		//データを変数に収める
		var ymd		= 	data.data[i].ymd;	// 日付
		var mark	= 	data.data[i].mark;	// マーク記号
		var url		= 	data.data[i].url;	// URL
		var text	=	data.data[i].text;	// 情報内容
		
		var hit = false;
		
		if(mode >= 1900){	//年指定モード
			if(Math.floor(ymd / 10000) == mode){
				hit = true;
			}
		}
		else{				//表示数指定モード
			if(i < mode){
				hit = true;
			}
			else{
				break;
			}

		}
		
		if(hit){
			var showymd = (("0" + Math.floor(ymd / 10000) % 100).slice(-2)) + '.' + Math.floor(ymd / 100) % 100 + '.' + ymd % 100;
			resultData += '<p><img src="m_' + mark + '.gif" width="50" height="15" alt="' + data.markdef[mark] + '" class="umark">'
					+ showymd + ' ';
			
			//URL指定がないときはリンクを外す
			if(url != ""){
				resultData += '<a href="' + url + '">';
			}
			
			resultData += text;
			
			if(url != ""){
				resultData += '</a>';
			}
			
			resultData += '</p>';
		}
	}
	return resultData;
}



ページには次のようにしてコードを埋めました。

(<head>~</head>内)
<script type="text/javascript" src="updates/updates.js"></script>

(トップページ:<body>~</body>内)
<div id = "jsondata"></div>
<!-- JSON化 2017.2.18 -->
<script type="text/javascript">
	writeData('jsondata', 5)
</script>

(更新情報ページ:<body>~</body>内)
<div id="u_body2">
</div>
<script type="text/javascript">
	writeData('u_body2', 2017)
</script>

各ページから、writeData関数で指定したIDの位置に情報を出力します。
引数として、第一引数に出力先のID、第二引数に出力モードを設定しました。
第二引数の出力モードは、1900以上の時はその年の全データを出力、1900未満の時は最新のデータから指定した件数のデータを出力させることとしました。

writeData関数から呼び出すcreateXMLHttpRequest()関数で、まずAjaxのXMLHttpRequestオブジェクトを作成します。
このとき、引数に、JSONファイル(data.json)の読み込みが終了したときに行う処理を記載するのですが、関数を記載する際、そのまま「関数(引数)」と記述すると、指定した関数の実行前に引数の内容が評価され実行されてしまいます。
そうではなくて、ちゃんと必要な時にその引数を伴って関数が実行できるようにするために、クロージャの形を使って、処理させたい関数をもう一度"function(){}"の形で包んであげると、中身を実行させないで引数として渡すことができました(31行目)。

無事にXMLHttpRequestオブジェクトが作成できれば、このオブジェクトのhttpObj.onreadystatechangeの中に先の関数名を埋め込みます(18行目)。

ブラウザはJSONデータについて、結構キャッシュを利用してしまいます。
更新情報は常に最新のものを使用したいので、ブラウザのキャッシュは使用せず、都度ファイルを読みにいくように設定しています(37~39行目)。

さて、data.jsonが読み込まれると、関数displayData()が実行されます。
onreadystatechangeはreadystateが変化するたびに呼び出されますが、
readystate=4、status=200のときがロード成功を指すそうなので、このときに関数parseJSON()を呼びます。
この第一引数のhttpObj.responseTextに、data.jsonの文字列が入っています。

まず54行目で、eval()関数JSON.parse()がdata.jsonの内容を解釈してJavaScriptで使うオブジェクトの形に変換します。
「この関数一つでJSONを解釈できる、だからとても扱いやすい!」が標榜されているのですが、JSONの記述法は結構厳しめで、ここでちゃんとエラーなく変換できるまでに時間がかかりました。
現在eval()関数は推奨されていないということで、記法を訂正しました。ご指摘いただきました竹麻呂さま、ありがとうございました。(2/19 4:30)

更新情報データの一つ一つがオブジェクトとその配列で構成されているので、for文をぶん回して項目ごとに内容を解釈していきます(59~62行目)。
ここでやっと、HTMLから引き継いできた引数modeを使います。
modeが1900以上なら年指定モードとみなし、指定した年のデータのみを使うように処理します。
また、modeがそれ未満なら表示数指定モードとし、ループカウンタ変数iの値を利用して指定個数だけデータを抽出します。

抽出したデータだけを変数resultDataに蓄積して返り値としてリターンします。
$(position).innerHTMLを使って、positionに指定したIDの位置にデータを書き出します。
document.getElementByldという長ったらしいオブジェクト名を省略するために、$()という関数の形に括って出力しているそう。jQueryでよく使う記法らしいです。

こうして一日かけて更新情報データベースのJSON化が完成しました。
実際のところ、この工数にペイできるほど今後の更新があるのか未知数ですが(笑)、現在様々な分野で導入が進むJSONを学ぶいい機会になったと思います。

ITは目的ではなく手段でなければなりませんので、やりたいことを確実に実現させる方法として、必要なものはこれからも吸収していきたいと思っています。

参考文献



祝、カープ優勝。

広島東洋カープ、25年ぶりリーグ優勝おめでとうございます!

ここ数年調子が上がっていましたが、今年私が観戦した3試合はすべて敗北。
むしろ運がよいと言われました。

生まれて初めての優勝ともあり大変興奮しております。

ここまで来れたのも、ひとえに広島の力。
みんなの思いが実ってきょうを迎えられたのでしょうね。

まずはお祝いを。


日本のドライバーに関する所感


米大統領予備選。
アメリカ式のジョークを日本語字幕にするとどうしてマヌケな印象が抜けないのでしょうかw
でも「政治ネタ」の会話をタブーにする日本より全然マシな国だと思いますよ。



久しぶりに、長距離のドライブをしてきました。

とあるレンタカー店でデミオのMT車があることを知り、予約。当日出会ったその車はなんと昨年11月に納車されたばかりの最新4代目でした。
発進操作でアイドリングストップ機能と悪戦苦闘しながら1,000kmあまり。北は富山県五箇山から南は和歌山潮岬まで、青空の下もドカ雪の中も走り抜けました。

さてさて、私が単純に免許歴約2年、運転が下手だからかもしれませんが、こう時々長距離のドライブをしていて、しばしば周囲の交通状況について怖い目に遭っています。その中で感じた、「日本のドライバーに対して思う所感」を、いくつか述べたいと思います。


1.とらない車間

車間距離がとにかく短い。追突したら誰が責任をとるのか、と思わんばかり。
高速道路を走行する場合、一般に乾燥路面で100km/h走行時に100mの車間距離を要するとされています。急に前車が停止した場合に安全に停止できる距離、すなわちその速度で走行したときの停止距離に相当します。
しかし実際に走ってみると、とにかく車間をとらないとらない。前の車に速度を煽る目的なのか何か知りませんがとにかく車間を詰める。
本当なら、後ろの車が車間距離を詰めてくるのであれば、追突されないように車間距離に応じてこちらも減速しなければなりませんから、車間を詰めて煽る行為はむしろ逆効果をもたらすということ、ちょっと考えればわかりませんかね。

関連してなのですが、上り勾配で停車時にものすごくひっついて止まる車ありますよね。みんなAT車だと思っている。
しかし、発進前にちょっと退行してしまう可能性を考えて上り勾配では少し離して止まるのも常識ではないでしょうかねぇ?せめて1mは距離が欲しいです。


2.カーブで減速しない

見通し不良区間で速度が出すぎる。そして私が安全な速度で運転しようとするとまた周囲に煽られる。
前方を見通せない範囲にはどんな危険があるとも知れないから、見えない場所に至る前に停止できる距離、つまり「見通し可能な距離>停止距離」で走ることは自動車運転の常識ではないでしょうか…この不等式が逆転することが許されるのは専用通路を設けた鉄道だけですw
さらに雪道のような滑りやすい道では極力曲線通過中に制動せず走行するため、手前の直線で十分減速する必要があります。そういった「安全のための運転」を、きちんと受け入れていただきたいと思います。


3.車線の使い方が酷い

同一方向に複数の車両通行帯があるとき、一番右の車線は何に使うのでしょうか…?
追越車線、ですよね?
なんだかどの道を走っていても同じような速度で車が走っており、その車線の意味を成していません。追越車線を自分のペースでちんたらと走り続けている車さえ見かけます。
東京の幹線道路のように、車線をフルに使わなければ交通量をさばけないような場合はいささか仕方がありません。しかし左の走行車線で十分余裕がある場合でさえこの追越車線が普通の車線と同様に扱われている状態に疑問を感じます。聞いたところでは、ドイツのアウトバーンではこのような光景は全く見られないそうです。



ドライブにおいてもっとも心地よいのは、自分のペースで安全に運転できることでずが、もちろん他者の気持ちを考えてストレスを与えないようにすることも当然必要です。
しかし、法や安全を考慮した運転さえも嫌な目をされなければいけないのも、どうかと思います。

警察の取り締まりも、安全性に直結しない場所でのネズミ捕りではなくて、車線違反や無灯火など、事故に直結しかねない危険な運転すなわち「事故の芽」を重点的に扱っていく姿勢を作ってほしいと思います。

より安全な日本の道路を目指して、人口減少とともに自動車学校の市場規模の縮小はすでに非可逆の趨勢ではありますが、運転教育者にはより一層の安全重視の教育を求めたいものです。

テーマ:思うこと - ジャンル:学問・文化・芸術

戯言

今年2016年は、小学2年次、私がKR鉄道館の前身となるホームページを立ち上げてから15年にあたります。
また、2011年にTwitterアカウントを持ってから数えても、はや5年となります。

比較的早い段階でネットに飛び込み、その世界を見てきた人間としては、その世界の日進月歩ぶりが逍遥感をも覚える今日この頃です。

しかし、ここまでたくさんの情報に、瞬間的かつ大量に接することができるようになって、本当に暮らしは豊かになったといえるのか。…そんな哲学的議論は様々な分野ですでになされていることと思いますが、ここでは「鉄道趣味界」にスポットを当てて考えてみます。

パソコンやスマートフォンなどが若年層に至るまで広く普及し、行動力が特に活発な若い鉄道ファンにとっては、最新の鉄道情報をそれこそ「いつでも・どこでも」入手できる環境を手に入れたことにになります。
それゆえ、日々噴き出す新しい情報に対して常に敏感になり、機敏な行動をとれるようになったことは言うまでもありません。

しかし、それによって、所謂「撮影地探し」あるいは「葬式鉄」などといった趣味行動が、以前にも増して加速してしまったのではないでしょうか。
「○○がなくなる。みんなで見に、撮影しにいこう」そういった動きが、Twitterのタイムラインを通じて広く伝わり、大きな「鉄界の世論」となって駆けまわります。
するといつの間にか、「これは絶対に撮りに行かなければならない」といった義務感に苛まれるようになり、自分を見失ってしまった人が、少なくないように思います。

一般にインターネットは、マス・コミュニケーションがあまり持ちえなかった一般人の世論を簡単に世界に発信する環境を具備したことから、個人主義を加速する道具になったとされます。しかし実際のところは、「○○しなければならない」という認識を大きく広め、集団行動の激化をもたらしたのではないでしょうか。
同じことは、旅行やグルメの口コミサイトにも言えることです。今までにはなかった方法で、実際にその地を訪ねた人々の情報が集まり、統計化され、ランキング付けがなされる。すると評価の高い物件だけに特に注目が集まり、そこに人が集中する。…鉄道に限らず、あらゆることについて最近見ていて思うのは、インターネットがかえって、行動の集団化・大衆化を引き起こしたということです。

皆が同じことを繰り返したところで、そこに「個」が輝くことはありません。
人と同じ行動をとるだけでは、人を超えることはできない。そんなことをどこかの偉人は語っていたような気がします。

ネットによって多くの情報を仕入れられるようになったからこそ、その中で必要な情報を手に入れて、「自分」をしっかりと持ちましょう。
そして、しっかりと自分の意見・「したいこと」を持ち、もし鉄道撮影に勤しむ身であれば、写真をきちんと「コミュニケーションツール」として捉えたいもの。写真は数多の伝達メディアのひとつであり、写真は何かを「伝える」ものでなくてはならないと思います。

日々ファインダーを通じて世界をみるとき、今までの人生で蓄積してきたものを土台にして、自分なりに世界をみつめ、それを伝えよう、そういった気持ちでおりたいものです。


プロフィール

てつた

Author:てつた
KR鉄道館

元駅員さん。
社会人3年目の、法学部卒
へっぽこ新米プログラマー。
たまには旅に出たい。

カレンダー
05 | 2019/06 | 07
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 - - - - - -
最新記事
最新コメント
最新トラックバック
カテゴリ
月別アーカイブ
検索フォーム
RSSリンクの表示
リンク
QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。