<?xml version='1.0' encoding='Shift_JIS' ?>
<doc xml:lang='ja'>
	<head>
	</head>
	<body>
		<p>
			前章では基本的なプレゼンテーションコンポーネントとして、時刻を取得して表示するプレゼンテーションコンポーネントを紹介しました。この章ではその発展としてグラフィカルなClockWindow、エージェントのデータを表示するプレゼンテーションコンポーネント、エージェントのデータをグラフ表示するプレゼンテーションコンポーネントを紹介します。</p>
		<subsection title="グラフィカルな時刻表示">
			<p>
				前章で作成したClockWindowは文字列で時刻を表示しました。しかし、せっかくプログラムを記述するのですから、もう少し描画処理を行いたいものです。そこで、１周を６０ステップとしたアナログ時計表示のプレゼンテーションコンポーネントを作成します。</p>
			<p>
				とはいっても、AnalogClockWindowから処理を変える部分は殆どありません。むしろ、時計を描画するパネルを１枚作成し、そこに必要な描画処理を記述します。それが以下のソースコードです。</p>
			<program title="AnalogClockWindow"
				src="marketforlemonsrc/presentation/AnalogClockWindow.java"
				normalizer="javasrc" javasrcSyntaxHilight="true"
				encoding="Shift_JIS" />
			<p>
				特に追加したクラスがインナークラスであるClockPanelです。このクラスのpaintComponent()の中に描画処理を記述しています。また、AnalogClockWindowのコンストラクタのGUI生成処理で、このパネルを追加しています。</p>
			<p>
				描画処理についての詳細はJava2DのAPIを見てもらえば詳細は分かると思いますが、(Graphicsクラス)drawLineメソッドを呼び出すことで線を描画します。</p>
			<p>
				また、リアルタイムでの描画を確実にするためにUpdateClockイベントを受け取るたびにrepaint()メソッドを呼ぶようにしています。</p>
			<figure id="fig:lastyear1" src="image/acw"
				title="グラフィカルなClockWindow" />
			<p>ちなみに、ここでは一周６０ステップとデフォルトで設定していますが、これが変更できるように修正するのもよいでしょう。</p>
		</subsection>
		<subsection title="エージェントのデータを表示する">
			<p>
				次は、毎回決まって取得できるデータではなく、特定のタイミングにおけるデータを表示するプレゼンテーションコンポーネントを作成してみます。</p>
			<p>
				ここでは、LemonSellerWorldの中でLemonSellerの持つ財（レモン、お金）の量を取引があるたびに表示するプレゼンテーションコンポーネントLemonSellerWindowを作成してみます。</p>
			<subsubsection title="対象エージェントの取得" >
				<p>まずやらなければいけないことは、ウィンドウで表示する対象エージェントの取得です。このように記述します。</p>
				<program title="LemonSellerWindow"
					src="marketforlemonsrc/presentation/LemonSellerWindow.java"
					javasrcKeyword="void worldOpened" normalizer="javasrc"
					javasrcSyntaxHilight="true" encoding="Shift_JIS" />

				<p>
					処理そのものはworldOpenedメソッド内に記述します。ここならば、必ずモデルが存在しているときに呼ばれるため、余計なエラー処理を書かなくて済みます。</p>
				<p>
					さて、処理内容ですが、レモンの売り手を全てのエージェントを順番に見ながら抽出します。レモンの売り手かどうかはBehaviorが存在するかで判定しています。AgentTypeによる判定は同じAgentTypeとして作成しているため、ここではできません。見つかればsellerというローカル変数に格納しています。</p>
			</subsubsection>
			<subsubsection title="データの取得・表示">
				<p>
					次にデータの取得及び描画です。レモンの売り手は既に取得できているので、そこからレモンとお金という２つのGoodsを取得し、表示する方法です。</p>
				<program title="LemonSellerWindow"
					src="marketforlemonsrc/presentation/LemonSellerWindow.java"
					javasrcKeyword="void showSeller" normalizer="javasrc"
					javasrcSyntaxHilight="true" encoding="Shift_JIS" />
				<p>
					取得及び表示するメソッドはprivateメソッドで独立させています。これは、モデル再読み込み時とイベント受信時に同じ処理を呼ぶためです。</p>
				<p>
					AgentクラスにはgetQuantity(GoodsType)メソッドがあるので、それで取得した量をそのまま表示させているだけです。</p>
			</subsubsection>
			<p>最後に全体のソースコードを記載しておきます。</p>
			<program title="LemonSellerWindow"
				src="marketforlemonsrc/presentation/LemonSellerWindow.java"
				normalizer="javasrc" javasrcSyntaxHilight="true"
				encoding="Shift_JIS" />
			<p>このようなウィンドウが表示されるようになります。</p>
			<figure id="fig:lastyear1" src="image/lsw" title="LemonSellerWindow"
				/>
		</subsection>
		<subsection title="エージェントのデータをグラフ表示する">
			<p>
				次にエージェントのデータをグラフで表示する方法について解説します。データを取得する方法そのものは前述したとおりですが、それをグラフとして表示するにはいくつか手順があります。</p>
			<subsubsection title="DataCollectorを作成する">
				<p>
					グラフ表示のためのクラスは今までのプレゼンテーションコンポーネントとは異なり、org.boxed_economy.components.datacollect.AbstractDataCollectComponentを継承したクラスを作成します。ここではLemonSellerDataCollectorとして作成します。しかし、それ以外はプレゼンテーションコンポーネントと同じで実装するリスナーインターフェースを指定してください。</p>
				<p>このようになります。</p>
				<program title="LemonSellerDataCollector"
					src="marketforlemonsrc/presentation/LemonSellerDataCollector1.java"
					normalizer="javasrc" javasrcSyntaxHilight="true"
					encoding="Shift_JIS" />
				<p>DataCollectiorの場合は今までのプレゼンテーションコンポーネントに加えて３つのメソッドが追加されています。</p>
				<dl>
					<dt>activate()</dt>
					<dd>
						DataCollectiorが活性化（メインウィンドウの「ツール」→「データ収集」）された時に呼ばれるメソッドです。ここにはリスナーへの追加処理を書くと良いでしょう</dd>
					<dt>deActivate()</dt>
					<dd>
						activate()とは逆にこのDataCollectorが非活性化されたときに呼ばれるメソッドです。ここにはリスナーからの削除処理を書くと良いでしょう</dd>
					<dt>getModels()</dt>
					<dd>
						メインウィンドウからグラフ描画に必要なデータを取得するために呼ばれます。このメソッドの返り値は必ずGraphModelクラスの集合を返すようにします（詳細は後述します）。</dd>
				</dl>
			</subsubsection>
			<subsubsection title="グラフモデルを生成・追加する処理を記述する">
				<p>
					DataCollectiorでは、BESPが用意しているグラフフレームワークを利用してデータをグラフとして表示します。実装の手順に入る前にこのグラフフレームワークについて簡単に解説します。以下の図をご覧下さい。</p>
				<figure id="fig:lastyear1" src="image/graphmodel"
					title="グラフフレームワークの概念図（簡略）" />
				<p>
					DataCollectorもプレゼンテーションコンポーネントの一種なので、モデルからイベントを受け取ります。今までのプレゼンテーションコンポーネントと異なるのは受け取って直接画面に表示することを行わず、グラフモデルをグラフ（このグラフウィンドウはBESPにあらかじめ用意されています）に対して渡すようになっていることです。</p>
				<p>このグラフモデルには要素として、以下のものが存在しています。実際のクラスと対応させながら説明します。</p>
				<dl>
					<dt>
						グラフモデル（org.boxed_economy.components.graph.SimpleGraphModel）</dt>
					<dd>
						グラフモデルそのものです。GraphModelとしてBESPから提供しているのはこのクラスだけではありませんが、現在はこのクラスを利用するとよいでしょう。</dd>
					<dt>ラベル</dt>
					<dd>グラフモデルに名前として設定します。</dd>
					<dt>X軸要素及びY要素（org.boxed_economy.components.graph.Axis）</dt>
					<dd>このクラスがX軸、Y軸としてグラフモデルに設定されます。</dd>
					<dt>それぞれの要素の単位(org.boxed_economy.components.graph.Unit)</dt>
					<dd>Axisクラスはこのクラスを含みます。</dd>
					<dt>点(java.awt.Point)</dt>
					<dd>
						このオブジェクトを追加することでグラフに点を描画します(awtのクラスをそのまま利用しています)。注意するべきは、ここで与えられる点の座標は単なる整数であり、その意味は前述のAxisクラスによって定義されるということです。</dd>
				</dl>
				<p>
					このグラフモデルを返すメソッドをDataCollectorで実装することで、DataCollectorがグラフにデータを渡します。</p>
				<p>グラフモデルは一般的にこのように作成します。</p>
				<program>Axis [X軸] = new Axis("[X軸要素名]", new Unit("[X軸の単位]"));
Axis [Y軸] = new Axis("[Y軸要素名]", new Unit("[Y軸の単位]"));
[グラフモデル] =new SimpleGraphModel("[ラベル]", [X軸], [Y軸]);</program>
				<p>サンプルではこのグラフモデルの作成及び取得は以下のように行っています。</p>
				<program title="LemonSellerDataCollector"
					src="marketforlemonsrc/presentation/LemonSellerDataCollector.java"
					javasrcKeyword="void worldOpened" normalizer="javasrc"
					javasrcSyntaxHilight="true" encoding="Shift_JIS" />
				<program title="LemonSellerDataCollector"
					src="marketforlemonsrc/presentation/LemonSellerDataCollector.java"
					javasrcKeyword="List getModels" normalizer="javasrc"
					javasrcSyntaxHilight="true" encoding="Shift_JIS" />
				<p>lemonGraphModelをインスタンス変数として保持しています。</p>
				<p>また、グラフモデルへの点の追加はこのようになっています。</p>
				<program title="LemonSellerDataCollector"
					src="marketforlemonsrc/presentation/LemonSellerDataCollector.java"
					javasrcKeyword="void addSellerData" normalizer="javasrc"
					javasrcSyntaxHilight="true" encoding="Shift_JIS" />
				<p>データを取得する部分は殆ど変えていません。このメソッドがUpdateClockEventを受け取る度に呼ばれます。</p>
			</subsubsection>
			<subsubsection title="プラグインにメニューを追加">
				<p>最後にプラグインにメニューを追加する処理を記述します。</p>
				<program>container.getPresentationContainer().addPresentationComponent(new [追加するDataCollectionのクラス名]());</program>
				<p>このような１行を追加します。</p>
			</subsubsection>
			<p>最後に全体のソースコードを記載しておきます。</p>
			<program title="LemonSellerDataCollector"
				src="marketforlemonsrc/presentation/LemonSellerDataCollector.java"
				normalizer="javasrc" javasrcSyntaxHilight="true"
				encoding="Shift_JIS" />
			<p>このように表示されるようになります。今回はモデルのおかげで、グラフっぽくは見えないのですが・・・</p>
			<figure id="fig:lastyear1" src="image/lsg" title="LemonSellerのグラフ表示"
				/>
		</subsection>
		<p>最終的なPluginクラスをここに記載しておきます。</p>
		<program title="MarketForLemonPlugin"
			src="marketforlemonsrc/presentation/MarketForLemonPlugin.java"
			normalizer="javasrc" javasrcSyntaxHilight="true"
			encoding="Shift_JIS" />
	</body>
</doc>
