/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//	LO SmartForce教材 サーバクラス
//			変更履歴
//				2004.01.08	新規作成	鈴木　敏子
//
package jp.co.ntt.lms.lo.Face2Face;

import jp.co.ntt.lms.lo.*;
import jp.co.ntt.lms.xmo.util.*;

import java.sql.SQLException;
import jp.co.ntt.lms.xmo.DataAccess;
import jp.co.ntt.lms.Common.status.*;

import jp.co.ntt.lms.xmo.Lo.MaterialData;
import jp.co.ntt.lms.xmo.MenuData;
import jp.co.ntt.lms.xmo.MessageData;
import jp.co.ntt.lms.xmo.Lo.LoClient;

import jp.co.ntt.lms.lo.LoLogDataAccess;
import jp.co.ntt.lms.lo.LoLogSessionDataAccess;
import jp.co.ntt.lms.lo.LoLogRecord;

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.util.*;
import java.sql.*;

/**
 * LO Face2Face教材 サーバクラスです。<BR>
 * 上位にLoServerクラスを持ち、LoTopとLoPropertyDefを実装します。
 *
 * @author T.Suzuki
 * @version 0.0.0.1 2004/01/08
 */
public class Face2FaceLo extends LoServer
	implements LoTop, Face2FaceLoPropertyDef
{
	//////////////////////////////////////////////////////////////////
	// メソッド名定義
	//////////////////////////////////////////////////////////////////
	/** 共通ログを更新するメソッドです */
	private static final String METHOD1 = "updateLoLog";
	/** 共通ログを検索するメソッドです */
	private static final String METHOD2 = "selectLoLog";


	/** テーブル定義 */
	private static final String LOID = "LOID";						// コースID
	private static final String USERID = "UserID";					// ユーザID
	private static final String EXECISE_POINT = "execise_point";	// 得点
	private static final String PASSDAY = "passday";				// 合格日
	private static final String STUDY_END_DATE = "study_end_date";	// 修了日

	/**
	 * コンストラクタです。
	 */
	public Face2FaceLo() throws LOException, RemoteException
	{
		// リモートオブジェクトをエクスポートする
		// java.rmi.server.UnicastRemoteObject の
		// 引数なしのコンストラクタを呼び出す
		super();

		try
		{
			mobjMenuMakerIF		= new Face2FaceMenuMaker();
			mobjSetupIF			= new Face2FaceSetup();
		}
		catch(Exception e)
		{
			throw new LOException(this.getClass().getName() + " :: ロード失敗 ");
		}
	}

	/**
	 * 教材一覧を返します
	 *
	 * @param Hathtable パラメータ
	 * @return Vector 教材一覧
	 */
	public Vector getMaterialList(Hashtable htbParam)
	{
		// 何もしない
		return new Vector();
	}

	/**
	 * メソッドリストを返します
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータとメソッドリスト
	 */
	public Vector getMethodList(Hashtable htbParam)
	{
		// @pending ここに処理を記述します
		return new Vector();
	}

	/**
	 * データ取得処理
	 *
	 * @param String
	 * @param Hashtable パラメータリスト
	 * @return Vector メッセージデータと実行結果データ
	 */
	public Vector getData(Hashtable htbParam)
	{
		Vector vecReturn = new Vector();
		Vector vecReturn2 = new Vector();
		Vector vecRet     = new Vector();
		Face2FaceLoData[] objData = new Face2FaceLoData[1];
		MessageData objMd = null;
		Object objRet     = null;
		try {
			Face2FaceLoDataAccess objDataAccess = new Face2FaceLoDataAccess();
			vecReturn = objDataAccess.getData( htbParam );
			vecReturn2 = (Vector)vecReturn.get(0);
			Face2FaceLoData objLoData = (Face2FaceLoData)vecReturn2.get(0);
			objData[0] = objLoData;
		}
		catch(LOException le) {
			// メッセージデータオブジェクトが取得できない場合は
			// システムエラーメッセージオブジェクトを生成
			objMd = createSystemErrMessage(le.getMessage());
		}
		// 配列の1番目にメッセージデータを格納
		vecRet.add(objMd);
		// 配列の2番目に個別テーブルデータを格納
		vecRet.add(objData);
		return vecRet;
	}

	/**
	 * 各Loに登録されているメソッドを起動します
	 * @param strMehodName 起動するメソッド名
	 * @param objParams 起動するメソッドのパラメータ
	 * @return Vector メッセージデータと実行結果
	 */
	public Vector execute(String strMethodName, Hashtable htbParams)
	{
		Vector vecRet     = new Vector();
		MessageData objMd = null;
		Object objRet     = null;

		if( strMethodName.equals( METHOD1 ) )
		{
			vecRet = updateLoLog( htbParams );
		}
		else if( strMethodName.equals( METHOD2 ) )
		{
			vecRet = selectLoLog( htbParams );
		}
		return vecRet;
	}

	/**
	 * 共通ログの取得を行います
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータと共通ログ取得結果
	 */
	public Vector getLoLog( Hashtable htbParam )
	{
		Vector vecRet     = new Vector();
		Object objRet     = null;
		MessageData objMd = null;
		try {
			LoLogDataAccess objDataAccess = new LoLogDataAccess();
			objRet = objDataAccess.select( htbParam );
		}
		catch(LOException le)
		{
			// メッセージデータオブジェクトが取得できない場合は
			// システムエラーメッセージオブジェクトを生成
			objMd = createSystemErrMessage(le.getMessage());
		}
		vecRet.add(objMd);
		vecRet.add(objRet);
		return vecRet;
	}

	/**
	 * 個別ログの取得を行います
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータと個別ログ取得結果
	 */
	public Vector getIndividualLog( Hashtable htbParam )
	{
		Vector vecRet     = new Vector();
		MessageData objMd = null;

		StringBuffer sbCondition = new StringBuffer();
		try
		{
			//検索条件を作成します
			String strLOID = (String)htbParam.get(LOID);
			//検索
			Face2FaceLoDataAccess objDataAccess = new Face2FaceLoDataAccess();
			vecRet = objDataAccess.getData( htbParam );
		}
		catch(LOException le)
		{
			// メッセージデータオブジェクトが取得できない場合は
			// システムエラーメッセージオブジェクトを生成
			objMd = createSystemErrMessage(le.getMessage());
		}
		// 配列の1番目にメッセージデータを格納
		vecRet.add( 0, objMd );
		return vecRet;
	}

	/**
	 * 共通ログの更新を行います
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータ
	 */
	public Vector updateLoLog( Hashtable htbParam){
		Vector vecRet     = new Vector();
		Object objRet     = null;
		MessageData objMd = null;
		StringBuffer sbCondition = new StringBuffer();
		try
		{
			//更新条件を作成します
			String strLOID = (String)htbParam.get(LOID);
			String strUserID = (String)htbParam.get(USERID);
			String[] strUpdateInfo = new String[4];
			strUpdateInfo[0] = (String)htbParam.get(EXECISE_POINT);		// 更新後 得点
			strUpdateInfo[1] = (String)htbParam.get(PASSDAY);			// 更新後 合格日
			strUpdateInfo[2] = (String)htbParam.get(STUDY_END_DATE); 	// 更新後 修了日
			strUpdateInfo[3] = (String)htbParam.get(EXECISE_POINT);		// 更新後 得点
			String strResidanceTime = "";
			String strHighScore = "";
			String strLowScore = "";
			String strStartDate = "";
			String strEndDate = "";
			String strPassDate = "";
			String strExecisePoint = "";
			String strFullScore = "";
			long lngAccessCnt = 0;

			// APPEND ステータス伝搬
			// データアクセスクラスをインスタンス化します
			DataAccess objDataAccess = new DataAccess("LOLog");
			try{
				LoLogSessionDataAccess objSessionDataAccess = new LoLogSessionDataAccess();
				int intStudyCount = objSessionDataAccess.getStudyCount( strUserID, strLOID ) + 1;
				String strSessionID = intStudyCount + "";
				// トランザクションの開始
				objDataAccess.trans();

				// 本日日付の取得
				String strNow = XMODate.parseTime( new java.util.Date() );
				LoLogDataAccess objLoLogDataAccess = new LoLogDataAccess();
				// ステータスログクラス取得
				LoLogRecord objRecord = objLoLogDataAccess.getLoLog( strUserID, strLOID );
				
				// LOLogレコードが存在しない場合、LoLogRecordをインスタンス化します。
				if(objRecord == null){
					objRecord = new LoLogRecord();
				}
				
				strResidanceTime = objRecord.getResidanceTime();
				strHighScore = objRecord.getHighScore();
				strLowScore = objRecord.getLowScore();
				strStartDate = objRecord.getStudyStartDate();
				strEndDate = objRecord.getStudyEndDate();
				strPassDate = objRecord.getPassday();
				strExecisePoint = objRecord.getExecisePoint();
				
				// 累積滞在時間
				if(strResidanceTime == null){
					strResidanceTime = "0";
				}
				// 最高点
				if(strHighScore == null){
					strHighScore = "0";
				}
				// 最低点
				if(strLowScore == null){
					strLowScore = "0";
				}
				// 開始日
				if(strStartDate == null){
					strStartDate = strNow;
				}
				// 満点
				if(strFullScore == null){
					strFullScore = "";
				}
				
				// 得点、合格日、修了日が更新されているかチェックします。
				boolean boolUpdateFlg = false;
				// 得点
				if((strExecisePoint == null || strExecisePoint.equals("")) && (strUpdateInfo[0] != null && !strUpdateInfo[0].equals(""))){
					boolUpdateFlg = true;
				}
				if((strUpdateInfo[0] == null || strUpdateInfo[0].equals("")) && (strExecisePoint != null && !strExecisePoint.equals(""))){
					boolUpdateFlg = true;
				}
				if(strExecisePoint == null || strExecisePoint.equals("")){
					strExecisePoint = "0";
				}
				if(strUpdateInfo[0] == null || strUpdateInfo[0].equals("")){
					strUpdateInfo[0] = "0";
				}
				if(Double.parseDouble(strExecisePoint) != Double.parseDouble(strUpdateInfo[0])){
					boolUpdateFlg = true;
				}
				// 合格日
				if(strPassDate == null || strPassDate.equals("")){
					if(strUpdateInfo[1] != null && !strUpdateInfo[1].equals("")){
						boolUpdateFlg = true;
					}
				}
				// 修了日
				if(strEndDate == null || strEndDate.equals("")){
					if(strUpdateInfo[2] != null && !strUpdateInfo[2].equals("")){
						boolUpdateFlg = true;
					}
				}
				
				// 得点、合格日、修了日が更新された場合、更新処理をします。
				if( objRecord != null && boolUpdateFlg) {
					
					
					// 合格日
					if(strPassDate == null || strPassDate.equals("")){
						strPassDate = (String)htbParam.get(PASSDAY);
					}
					// 修了日
					if(strEndDate == null || strEndDate.equals("")){
						strEndDate = (String)htbParam.get(STUDY_END_DATE);
					}
					if(strUpdateInfo[0] != null && !strUpdateInfo[0].equals("")){
						// 得点が最高点より高い場合、得点を最高点とします。
						if(Double.parseDouble(strHighScore) < Integer.parseInt(strUpdateInfo[0])){
							strHighScore = strUpdateInfo[0];
						}
						// 満点
						strFullScore = "100";
					
					}else{
						// 満点
						strFullScore = "";
					}

					// 得点
					strExecisePoint = strUpdateInfo[3];
					
					// 2回目以降に学習する場合、前回までのアクセス回数に＋１して設定
					if(objRecord.getAccessCnt() != null){
						lngAccessCnt = new Float( objRecord.getAccessCnt() ).longValue() + 1;
					}else{
						// 初回のステータス更新の場合(アクセス回数:1)
						lngAccessCnt += 1;
					}
					objRecord.setAccessCnt( lngAccessCnt + "" );
					
					// 最終アクセス日時設定
					objRecord.setLastAccess( strNow );
					
					objRecord.setResidanceTime( strResidanceTime );	// 累積滞在時間
					objRecord.setHighScore( strHighScore );			// 最高点
					objRecord.setLowScore( strLowScore );			// 最低点
					objRecord.setStudyStartDate( strStartDate );	// 開始日
					objRecord.setStudyEndDate( strEndDate );		// 修了日
					objRecord.setPassday( strPassDate );			// 合格日
					objRecord.setExecisePoint( strExecisePoint );	// 得点
					objRecord.setFullScore( strFullScore );			// 満点
					objRecord.setUserID( strUserID );				// ユーザID
					objRecord.setLoID( strLOID );					// LOID
					
					// 登録処理
					objLoLogDataAccess.insertUpdate( objRecord, strUserID, strLOID, objDataAccess );
					
					// 参照LOIDリストを取得します
					LoClient objLoClient = new LoClient();
					if(!objLoClient.getListFromRealLOID( strLOID )){
						new LOException("参照LOIDリストの取得失敗しました。");
					}
					String[] strRefList = objLoClient.getRefListResult();
					
					// 参照リスト分ステータス伝播
					for(int i = 0; i < strRefList.length; i++){
						// ステータス伝搬処理
						StatusPropagation objStatus = new StatusPropagation( strUserID, strRefList[i] );

						PropagateControl.getInstance().addPropagate(objStatus);
					}

					// セッションテーブルの登録レコード生成
					LoLogSessionRecord objSessionData = new LoLogSessionRecord();
					// セッションテーブルのインスタンス化
					objSessionData = new LoLogSessionRecord();
					// セッションレコードにコピー
					objSessionData.setStudyStartDate( strNow );				// 開始日
					objSessionData.setResidanceTime( strResidanceTime );	// 累積滞在時間
					objSessionData.setPassday( strPassDate );				// 合格日
					objSessionData.setStudyEndDate( strEndDate );			// 修了日
					objSessionData.setHighScore( strHighScore );			// 最高点
					objSessionData.setLowScore( strLowScore );				// 最低点
					objSessionData.setExecisePoint( strExecisePoint );		// 得点
					objSessionData.setFullScore( strFullScore );			// 満点
					objSessionData.setUserID( strUserID );					// ユーザID
					objSessionData.setLoID( strLOID );						// LOID
					objSessionData.setSessionID( strSessionID );			// SessionID

					// セッションテーブル登録処理
					objSessionDataAccess.insert( objSessionData, objDataAccess );
				}

				// コミット
				objDataAccess.commit();
			}
			catch( SQLException e ) {
				e.printStackTrace();
				DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
				// ロールバック
				try { objDataAccess.rollback(); } catch( Exception ex ) {}
				// データベースエラーを設定
				throw new LOException( e.getMessage() );
			}
			catch( LOException le ) {
				le.printStackTrace();
				DebugLog.write( this.getClass(), le, DebugLog.HIGHT );
				// ロールバック
				try { objDataAccess.rollback(); } catch( Exception ex ) {}
				// データベースエラーを設定
				throw new LOException( le.getMessage() );
			}
			catch( Exception ex ) {
				DebugLog.write( this.getClass(), ex, DebugLog.HIGHT );
				throw new LOException( ex.getMessage() );
			}
		}
		catch(LOException le)
		{
			// メッセージデータオブジェクトが取得できない場合は
			// システムエラーメッセージオブジェクトを生成
			objMd = createSystemErrMessage(le.getMessage());
		}
		vecRet.add(objRet);
		vecRet.add(objMd);
		return vecRet;
	}

	/**
	 * 共通ログの検索を行います
	 * @param htbParam パラメータ
	 * @return Vector メッセージデータ
	 */
	public Vector selectLoLog( Hashtable htbParam){
		Vector vecRet     = new Vector();
		Object objRet     = null;
		MessageData objMd = null;
		StringBuffer sbCondition = new StringBuffer();
		try
		{
			//検索
			LoLogDataAccess objDataAccess = new LoLogDataAccess();
			vecRet = objDataAccess.select( htbParam );
		}
		catch(LOException le)
		{
			// メッセージデータオブジェクトが取得できない場合は
			// システムエラーメッセージオブジェクトを生成
			objMd = createSystemErrMessage(le.getMessage());
		}
		// 配列の1番目にメッセージデータを格納
		vecRet.add( 0, objMd );
		return vecRet;
	}

}

