//
// CopyRight (C) 2002, IPA, eLC, NTT Resonant Inc. All rights reserved.
//
//	SCORMCommunicationModule
//
//	変更履歴
//		2002.12.25  新規作成
//

package jp.co.ntt.lms.lo.scorm.kernel;

import java.io.File;
import java.math.BigDecimal;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;

import jp.co.ntt.lms.lo.scorm.cbtcom.CMICBT;
import jp.co.ntt.lms.lo.scorm.cbtcom.CMIElement;
import jp.co.ntt.lms.lo.scorm.cbtcom.CMIS13ModelUtil;
import jp.co.ntt.lms.lo.scorm.cbtcom.S13LogFormatException;
import jp.co.ntt.lms.lo.scorm.kernel.Resource;
import jp.co.ntt.lms.lo.scorm.kernel.exception.CommunicationModuleWrapperException;

/**
*  SCORM Communication Module クラス<BR>
*  外部アダプタクラス<BR>
*/
public class SCORMCommunicationModule extends CommunicationModuleWrapper {
	/** cbtcom */
	private CMICBT cbtcom;

	/** objective id - cmi.objectives.[n] マッピング */
	private Hashtable objectiveIDToNumber;

	/** */
	private boolean noCBTURL;

	/**
	 * デフォルトコンストラクタ <BR>
	 */
	public SCORMCommunicationModule() {}

	/**
	 * コンストラクタ
	 *
	 * @param activity アクティビティ
	 */
	public SCORMCommunicationModule(Activity activity) {
		super(activity);
	}

	/**
	 * 初期化<BR>
	 *
	 * @param	initialParameter		初期化パラメータ。Hashtableの値には以下のキーが必要<BR>
	 *						userID 		ユーザID<BR>
	 *						userName	ユーザ名<BR>
	 *						URL			AICCへのURL<BR>
	 *
	 * @param	savedValue	保存されたデータ。保存データが存在しない場合はnullを指定する<BR>
	 */
	public void initialize(Hashtable initialParameter, String savedValue)
		throws CommunicationModuleWrapperException {

		try {
			// リーフでない
			if (activity.hasChildren()) {
				throw new CommunicationModuleWrapperException("SCORMCommunicationModuleの初期化に失敗しました。");
			}

			// resourceの読み込み
			Resource resource = activity.getResource();
			String href = "";

			if (resource != null) {
				href = resource.getHref();
				if (href == null) {
					href = "";
				}
			}

			noCBTURL = href.equals("");

			String userID = (String)initialParameter.get("userID");
			String userName = (String)initialParameter.get("userName");
			String URL = (String)initialParameter.get("URL");
			String encoding = (String)initialParameter.get("encoding");

			cbtcom = new CMICBT(encoding);

			/**
			 *  中断情報がない場合は CBTCOM の初期化処理を行う
			 *  ある場合は中断情報のセットを行う
			 */
			cbtcom.setValue("cmi.completion_status", "unknown");
			cbtcom.setValue("cmi.credit", "credit");
			cbtcom.setValue("cmi.entry", "ab-initio");
			cbtcom.setValue("cmi.launch_data", activity.getDataFromLMS());
			cbtcom.setValue("cmi.completion_threshold", activity.getCompletionThreshold());
			// 2011.09.09 taku-harada mod >>
			//cbtcom.setValue("cmi.progress_measure", null); // 初期値はnull
			cbtcom.setValue("cmi.progress_measure", activity.getProgressMeasure());
			// 2011.09.09 taku-harada mod <<
			cbtcom.setValue("cmi.learner_id", userID);
			cbtcom.setValue("cmi.learner_name", userName);

			String value;

			value = activity.getSequencing().getLimitConditionString("attemptAbsoluteDurationLimit");
			if (value != null) {
				cbtcom.setValue("cmi.max_time_allowed", value);
			}

			cbtcom.setValue("cmi.mode", "normal");

			LocalObjective[] localObjective = activity.getSequencing().getObjective();
			objectiveIDToNumber = new Hashtable();

			int j = 0;
			for (int i = 0; i < localObjective.length; i++) {
				// 20040801 MOD NTTR
				// ここにIDの判定を追加
				if(localObjective[i].getHasObjectiveID() == false){
					//なにもしない
				//}
					objectiveIDToNumber.put(localObjective[i].getObjectiveID(), Integer.toString(i));

					cbtcom.setValue("cmi.objectives." + j + ".id", localObjective[i].getObjectiveID());
					cbtcom.setValue("cmi.objectives." + j + ".score.scaled", "");
					cbtcom.setValue("cmi.objectives." + j + ".score.raw", "");
					cbtcom.setValue("cmi.objectives." + j + ".score.min", "");
					cbtcom.setValue("cmi.objectives." + j + ".score.max", "");
					cbtcom.setValue("cmi.objectives." + j + ".success_status", "unknown");
					cbtcom.setValue("cmi.objectives." + j + ".completion_status", "unknown");
					j++;
				}
			}

			BigDecimal scaledPassingScore =
				activity.getSequencing().getObjectiveContributeToRollup().getMinNormalizedMeasure(false);
			if (scaledPassingScore != null) {
				cbtcom.setValue("cmi.scaled_passing_score", scaledPassingScore.toString());
			}

			cbtcom.setValue("cmi.score.scaled", "");
			cbtcom.setValue("cmi.score.raw", "");
			cbtcom.setValue("cmi.score.min", "");
			cbtcom.setValue("cmi.score.max", "");

			cbtcom.setValue("cmi.success_status", "unknown");

			value = activity.getTimeLimitAction();
			if (value != null) {
				cbtcom.setValue("cmi.time_limit_action", value);
			}

			cbtcom.setValue("cmi.launch.aicc_url", URL);
			cbtcom.setValue("cmi.launch.aicc_sid_seed", "SID_SEED");

			cbtcom.setValue("cmi.launch.cbt_url", href);

			value = activity.getParameters();

			cbtcom.setValue("cmi.launch.launch_params", (value == null) ? "" : value);
			cbtcom.setValue("cmi.location", null);

			if (savedValue != null) {
				cbtcom.setAllValue(savedValue);
			}
			
//			// 2010.10.04 taku-harada add >>
//			Vector<Map<String, String>> vec = activity.getData();
//			
//			for(int i=0; i<vec.size(); i++){
//				Map<String, String> map = vec.get(i);
//				cbtcom.setValue("adl.data." + i + ".id", map.get("targetID"));
//			}
//			// 2010.10.04 taku-harada add <<
			
			
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 初期化<BR>
	 *
	 * @param	initialParameter		初期化パラメータ。Hashtableの値には以下のキーが必要<BR>
	 *						userID 		ユーザID<BR>
	 *						userName	ユーザ名<BR>
	 *						URL			AICCへのURL<BR>
	 *
	 * @param	savedValue	保存されたデータ。保存データが存在しない場合はnullを指定する<BR>
	 */
	public void initialize2(Hashtable initialParameter)
		throws CommunicationModuleWrapperException {

	    try {
			cbtcom.setAllValue(cbtcom.getAllValue());
			//cbtcom.setValue("cmi.completion_status", "unknown");
			cbtcom.setValue("cmi.entry", "");
			LocalObjective[] localObjective = activity.getSequencing().getObjective();
			objectiveIDToNumber = new Hashtable();

			int j = 0;
			for (int i = 0; i < localObjective.length; i++) {
				// 20040801 MOD NTTR
				// ここにIDの判定を追加
				if(localObjective[i].getHasObjectiveID() == false){
					//なにもしない
				//}
					objectiveIDToNumber.put(localObjective[i].getObjectiveID(), Integer.toString(i));

					cbtcom.setValue("cmi.objectives." + j + ".id", localObjective[i].getObjectiveID());
					cbtcom.setValue("cmi.objectives." + j + ".score.scaled", "");
					cbtcom.setValue("cmi.objectives." + j + ".score.raw", "");
					cbtcom.setValue("cmi.objectives." + j + ".score.min", "");
					cbtcom.setValue("cmi.objectives." + j + ".score.max", "");
					cbtcom.setValue("cmi.objectives." + j + ".success_status", "unknown");
					cbtcom.setValue("cmi.objectives." + j + ".completion_status", "unknown");
					j++;
				}
			}

			BigDecimal scaledPassingScore =
				activity.getSequencing().getObjectiveContributeToRollup().getMinNormalizedMeasure(false);
			if (scaledPassingScore != null) {
				cbtcom.setValue("cmi.scaled_passing_score", scaledPassingScore.toString());
			}

			//cbtcom.setValue("cmi.score.scaled", "");
			//cbtcom.setValue("cmi.score.raw", "");
			//cbtcom.setValue("cmi.score.min", "");
			//cbtcom.setValue("cmi.score.max", "");

			//cbtcom.setValue("cmi.success_status", "unknown");
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 中断情報取得<BR>
	 *
	 * @return   保存データ<BR>
	 */
	public String save() throws CommunicationModuleWrapperException {
		try {
			if (cbtcom != null) {
				
				// 2011.01.12 taku-harada add >>
				setTotal_time();
				// 2011.01.12 taku-harada add <<
				
				close();
				return cbtcom.getAllValue();
			}

			return null;
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 終期化<BR>
	 */
	public void terminate() throws CommunicationModuleWrapperException {
		try {
			close();
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * CBTCOMをオープンする
	 *
	 * @param learningLogFolder
	 * @return 次画面へのURL
	 */
	public String open(String learningLogFolder) throws CommunicationModuleWrapperException {
		try {
			new File(learningLogFolder).mkdirs();

			cbtcom.setValue("cmi.evaluation.course_id", activity.getCourseIdentifier());
			cbtcom.setValue("cmi.evaluation.lesson_id", activity.getIdentifier());
			cbtcom.setValue("cmi.evaluation.parameter", learningLogFolder + activity.getIdentifier() + ".prm");
			cbtcom.setValue("cmi.evaluation.comments", learningLogFolder + activity.getIdentifier() + ".cmt");
			cbtcom.setValue("cmi.evaluation.interactions", learningLogFolder + activity.getIdentifier() + ".int");

			String nextURL = cbtcom.open();

			if (noCBTURL) {
				return null;
			}

			Resource resource = activity.getResource();

			if (resource == null) {
				return null;
			}
			StringBuffer retUrl = new StringBuffer("");
			retUrl.append(resource.getBaseURL());
			retUrl.append(nextURL);
			//@20040603 DEL NTTR
			//if (resource.getScormType().equals("asset")) {
			//	return resource.getHref();
			//}
			//@20040603 END

			return retUrl.toString();
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * CBTCOMをクローズする
	 *
	 */
	public void close() throws CommunicationModuleWrapperException {
		try {
			if (cbtcom != null) {
				if (cbtcom.isOpen()) {
					cbtcom.close();
				}
			}
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * CBTCOMに対しhacpを行う
	 *
	 * @return クライアントへ返却する為の"text/plain"文字列
	 */
	public String hacp(String param) throws CommunicationModuleWrapperException {
		try {
			return cbtcom.hacp(param);
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * CBTCOMに対しsetValueを行う
	 *
	 */
	public void setValue(String key, String value) {
		cbtcom.setValue(key, value);
	}

	/**
	 * CBTCOMに対しgetValueを行う
	 *
	 * @return 取得できた値
	 */
	public String getValue(String key) {
		return cbtcom.getValue(key);
	}

	/**
	 * 外部APIAdpaterの再開を行う
	 */
	public void resumeAPIAdapter() throws CommunicationModuleWrapperException {
		try {
			cbtcom.setAllValue(cbtcom.getAllValue());
			cbtcom.setValue("cmi.entry", "resume");
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * トラッキング情報の同期
	 */
	public void synchronizeTrackingModel() throws CommunicationModuleWrapperException {
		try {
			String value = cbtcom.getValue("cmi.exit");

			if ((value != null) && (value.equals("suspend"))) {
				cbtcom.setValue("cmi.entry", "resume");
				activity.setSuspended(true);
			}
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成状態を有効にする<BR>
	 * @param objectiveID 学習目標ID<BR>
	 * @param status true   有効<BR>
	 *               false  無効<BR>
	 */
	public void setObjectiveProgressStatus(String objectiveID, boolean status)
		throws CommunicationModuleWrapperException {

		try {
			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				if (status) {
					// true の場合は設定しない。
				}
				else {
			//		cbtcom.setValue("cmi.success_status", "unknown");
				}
			}
			
			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

			
				if (n == null) {
					throw new CommunicationModuleWrapperException(objectiveID + ", " + activity.getIdentifier());
				}

				if (status) {
					// true の場合は設定しない。
				}
				else {
			//		cbtcom.setValue("cmi.objectives." + n + ".success_status", "unknown");
				}
			}
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成状態の有効、無効フラグを取得する<BR>
	 * 
	 * @param    objectiveID    学習目標ID<BR>
	 * @return   有効か否かを示すBoolean<BR>
	 */
	public Boolean getObjectiveProgressStatus(String objectiveID) throws CommunicationModuleWrapperException {
		try {
			/*
			 *  objectiveID から objectiveを特定して値を CBTCOM から取得する
			 *  
			 */
			String value;

			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				value = cbtcom.getValue("cmi.success_status");

				if (!value.equals("unknown")) {
					return Boolean.TRUE;
				}
			}

			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

				if (n == null) {
					throw new CommunicationModuleWrapperException(objectiveID + ", " + activity.getIdentifier());
				}

				value = cbtcom.getValue("cmi.objectives." + n + ".success_status");

				return value.equals("unknown") ? Boolean.FALSE : Boolean.TRUE;
			}else{
				return Boolean.FALSE;
			}
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成状態を設定する<BR>
	 *
	 * @param    objectiveID 学習目標ID <BR>
	 * @param    status 進捗状態を指定する(true:完了 / false:未完了)<BR>
	 */
	public void setObjectiveSatisfiedStatus(String objectiveID, boolean status)
		throws CommunicationModuleWrapperException {

		try {
			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				if (status) {
					cbtcom.setValue("cmi.success_status", "passed");
				}
				else {
					cbtcom.setValue("cmi.success_status", "failed");
				}
			}

			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

				if (n == null) {
					throw new CommunicationModuleWrapperException(objectiveID + ", " + activity.getIdentifier());
				}

				if (status) {
					cbtcom.setValue("cmi.objectives." + n + ".success_status", "passed");
				}else{
					cbtcom.setValue("cmi.objectives." + n + ".success_status", "failed");
				}
			}
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成状態を取得する<BR>
	 *
	 * @param   objectiveID    学習目標ID <BR>
	 * @return  現在の進捗状態を返却する。
	 *			(プライマリオブジェクティブと)、オブジェクティブの進捗状態が"unknown"の場合はnullを返却する<BR>
	 */
	public Boolean getObjectiveSatisfiedStatus(String objectiveID) throws CommunicationModuleWrapperException {
		try {
			/**
			 *  objectiveID から objectiveを特定して値を CBTCOM から取得する
			 *  
			 */
			String value = "";

			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				value = cbtcom.getValue("cmi.success_status");

				if (value.equals("passed")) {
					return Boolean.TRUE;
				}
				else if (value.equals("failed")) {
					return Boolean.FALSE;
				}
				else if (value.equals("unknown")) {
					return null;
				}
				else if (!value.equals("unknown")) {
					throw new CommunicationModuleWrapperException(
						"cmi.success_status ボキャブラリ不正[" + value + "][" + objectiveID + "]");
				}
			}

			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

				if (n == null) {
					throw new CommunicationModuleWrapperException("一致 Objective ID 無し[" + objectiveID + "]");
				}

				value = cbtcom.getValue("cmi.objectives." + n + ".success_status");

				if (value.equals("passed")) {
					return Boolean.TRUE;
				}
				else if (value.equals("failed")) {
					return Boolean.FALSE;
				}
				else if (value.equals("unknown")) {
					return null;
				}
			}else{
				return null;
			}
			throw new CommunicationModuleWrapperException(
				value + ", " + objectiveID + ", " + activity.getIdentifier());
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成値有効／無効フラグの設定<BR>
	 * @param objectiveID 学習目標ID<BR>
	 * @param status     true 有効<BR>
	 *                   false 無効<BR>
	 */
	public void setObjectiveMeasureStatus(String objectiveID, boolean status)
		throws CommunicationModuleWrapperException {

		try {
			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				if (status) {
					// true の場合は設定しない。
				}
				else {
					cbtcom.setValue("cmi.score.scaled", "");
				}
			}

			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

				if (n == null) {
					throw new CommunicationModuleWrapperException(objectiveID + ", " + activity.getIdentifier());
				}

				if (status) {
					// true の場合は設定しない。
				}
				else {
					cbtcom.setValue("cmi.objectives." + n + ".score.scaled", "");
				}
			}
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成値(正規化)が有効か否かを示す<BR>
	 *
	 * @param objectiveID   学習目標ID<BR>
	 * @return 有効か否かを示す<BR>
	 */
	public Boolean getObjectiveMeasureStatus(String objectiveID) throws CommunicationModuleWrapperException {
		try {
			String score = "";

			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				score = cbtcom.getValue("cmi.score.scaled");
				if (!score.equals("")) {
					return Boolean.TRUE;
				}
			}
			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

				if (n == null) {
					throw new CommunicationModuleWrapperException(objectiveID + ", " + activity.getIdentifier());
				}

				score = cbtcom.getValue("cmi.objectives." + n + ".score.scaled");

				return score.equals("") ? Boolean.FALSE : Boolean.TRUE;
			}else{
				return Boolean.FALSE;
			}
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成値(正規化)を設定する<BR>
	 *
	 * @param   objectiveID	学習目標ID <BR>
	 * @param	value		学習目標達成値を9.9999形式(-1〜1)のBigDecimalで指定する<BR>
	 */
	public void setObjectiveNormalizedMeasure(String objectiveID, BigDecimal value)
		throws CommunicationModuleWrapperException {

		try {
			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				cbtcom.setValue("cmi.score.scaled", value.toString());
			}

			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

				if (n == null) {
					throw new CommunicationModuleWrapperException(objectiveID + ", " + activity.getIdentifier());
				}

				cbtcom.setValue("cmi.objectives." + n + ".score.scaled", value.toString());
			}
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習目標達成値(正規化)を取得する<BR>
	 *
	 * @param   objectiveID 学習目標ID<BR>
	 * @return  現在の学習目標達成値を取得する。(プライマリオブジェクティブと)オブジェクティブの<BR>
	 * 			学習目標達成値が設定されてない場合はnullを返却する
	 */
	public BigDecimal getObjectiveNormalizedMeasure(String objectiveID) throws CommunicationModuleWrapperException {

		try {
			String value = "";

			LocalObjective primary = activity.getObjectiveContributeToRollup();

			if (objectiveID.equals(primary.getObjectiveID())) {
				value = cbtcom.getValue("cmi.score.scaled");
				if (!value.equals("")) {
					return new BigDecimal(value).setScale(4, BigDecimal.ROUND_HALF_UP);
				}
			}
			
			if (primary.getHasObjectiveID() == false){
				String n = (String)objectiveIDToNumber.get(objectiveID);

				if (n == null) {
					throw new CommunicationModuleWrapperException(objectiveID + ", " + activity.getIdentifier());
				}

				value = cbtcom.getValue("cmi.objectives." + n + ".score.scaled");
				if (!value.equals("")) {
					return new BigDecimal(value).setScale(4, BigDecimal.ROUND_HALF_UP);
				}
			}
			return null;
		}
		catch (CommunicationModuleWrapperException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 *   学習完了状態有効／無効フラグの設定<BR>
	 *
	 *   @param status    true 有効<BR>
	 *                    false 無効<BR>
	 */
	public void setAttemptProgressStatus(boolean status) throws CommunicationModuleWrapperException {
		try {
			if (status) {
				// true の場合は設定しない。
			}
			else {
				cbtcom.setValue("cmi.completion_status", "unknown");
			}
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 *   学習完了状態有効／無効フラグの取得<BR>
	 *   @return    true     学習完了状態は有効<BR>
	 *               false    学習完了状態は無効<BR>
	 *
	 */
	public Boolean getAttemptProgressStatus() throws CommunicationModuleWrapperException {
		try {
			String value = cbtcom.getValue("cmi.completion_status");

			return value.equals("unknown") ? Boolean.FALSE : Boolean.TRUE;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 * 学習完了状態を設定する<BR>
	 *
	 * @param	value	完了状態を指定する(1.0〜.0.0の割合で示す)<BR>
	 */
	public void setAttemptCompletionAmount(BigDecimal value) {}

	/**
	 *    学習完了状態を取得する<BR>
	 *
	 *    @return     value  完了状態を示す(1.0〜.0.0の割合で示す)<BR>
	 */
	public BigDecimal getAttemptCompletionAmount() throws CommunicationModuleWrapperException {
		try {
			if (!cbtcom.getValue("cmi.completion_status").equals("completed")) {
				return new BigDecimal("0.0").setScale(4, BigDecimal.ROUND_HALF_UP);
			}

			return new BigDecimal("1.0").setScale(4, BigDecimal.ROUND_HALF_UP);
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 *    学習完了状態を設定する<BR>
	 *
	 *    @param     status 完了状態を指定する(true:完了 / false:未完了)<BR>
	 */
	public void setAttemptCompletionStatus(boolean status) throws CommunicationModuleWrapperException {
		try {
			if (status) {
				cbtcom.setValue("cmi.completion_status", "completed");
			}
			else {
				cbtcom.setValue("cmi.completion_status", "incomplete");
			}
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}

	/**
	 *    学習完了状態を設定する<BR>
	 *
	 *    @return	完了状態<BR>
	 */
	public Boolean getAttemptCompletionStatus() throws CommunicationModuleWrapperException {
		try {
			String value = cbtcom.getValue("cmi.completion_status");

			if (value.equals("completed")) {
				return Boolean.TRUE;
			}
			else if (value.equals("incomplete")) {
				return Boolean.FALSE;
			}

			return null;
		}
		catch (Exception ex) {
			throw new CommunicationModuleWrapperException(activity.getIdentifier(), ex);
		}
	}
	
	// 2011.01.12 taku-harada add >>
	/**
	 * 		resumeの時 total_timeを設定する<BR>
	 * 		
	 * 		@throws S13LogFormatException <BR>
	 */
	private void setTotal_time() throws S13LogFormatException {

		double dTotalSec = 0;
		
		CMIElement cmielement = cbtcom.getNChild("core.session_time");
		String strValue = cmielement.getLessonValue();
		if(strValue != null && "".equals(strValue) != true){
			dTotalSec = CMIS13ModelUtil.parseTimeintervalToLong(strValue);
		}
		
		CMIElement cmielement_total = cbtcom.getNChild("core.total_time");
		String strValue_total = cmielement_total.getLocalValue();
		if(strValue_total != null && "".equals(strValue_total) != true){
			dTotalSec = dTotalSec + CMIS13ModelUtil.parseTimeintervalToLong(strValue_total);
		}

		String strTime;
		strTime = CMIS13ModelUtil.formatS13Timespan((long)dTotalSec);
		cmielement_total.setLocalValue(strTime);

	}
	// 2011.01.12 taku-harada add <<
}
