/*
このファイルの中身は、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) ______________________________________.
*/

//
//	スマートフォース個別ログファイル操作クラス
//			変更履歴
//				2004.01.08	新規作成	五木田 泰史
//
package jp.co.ntt.lms.lo.SmartForce;

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

// Java API
import java.util.Vector;
import java.util.Hashtable;
import java.io.IOException;
import java.sql.SQLException;

import org.apache.commons.lang.StringEscapeUtils;
// XMS API
import jp.co.ntt.lms.xmo.util.DBAccess;
import jp.co.ntt.lms.xmo.util.DebugLog;

public class SmartForceLoILogControl
	implements LoPropertyDef
{

	//////////////////////////////////////////////////////////////////
	// メンバ変数
	//////////////////////////////////////////////////////////////////
	DBAccess mobjDba;
	
	//////////////////////////////////////////////////////////////////
	// メンバ関数
	//////////////////////////////////////////////////////////////////
	
	/**
	 * コンストラクタ
	 **/
	public SmartForceLoILogControl()
	{
		;
	}
	
	/**
	 * 個別ログコンバートメソッド<BR>
	 * <PRE>
	 * 処理内容：教材ユニットログレコードクラスに
	 *           データを設定する。
	 * </PRE>
	 * @param String[] ユーザーIDリスト
	 * @param Stirng[] 教材IDリスト
	 * @return CourseUnitLogRecord[] 教材ユニットログレコードリスト
	 *
	 **/
	public CourseUnitLogRecord[] convert(
		String[] strUserIDList, String[] strCoursesIDList)
			throws LOException
	{
		// ログデータ
		int i = 0;
		int j = 0;
		
		CourseUnitLogRecord[] objClrList = null;								// 教材Unitログリスト
		CourseLogRecord[] objCrList      = null;								// 教材ログリスト
		
		// 教材ユニットログクラスリスト作成処理
		try
		{
			// DBAccessクラス生成
			mobjDba = new DBAccess();
			
			// DBAccessプロパティ設定処理
			SmartForceLoEnv objEnv = new SmartForceLoEnv();
			mobjDba.setDriver(objEnv.getDBDriver());
			mobjDba.setConStr(objEnv.getDBConStr());
			mobjDba.setUser(objEnv.getDBUser());
			mobjDba.setPass(objEnv.getDBPass());
			
			// NULLを出さないように実装側で調整しましょう
			// StudentIDリスト取得
			String[] strStudentIDList = getStudentIDList(strUserIDList);
			mobjDba.clearProperty();
			
			// DBから0件取得の場合のみNULLが戻る
			if(strStudentIDList == null)
			{
				// 配列0のオブジェクトを返す
				objClrList = new CourseUnitLogRecord[0];
				return objClrList;
			}
			
			// Unitリスト取得
			Vector vecUnitList = getUnitList(strCoursesIDList);
			mobjDba.clearProperty();
			
			// 教材ログリスト取得
			// CourseCode, StudentID, CourseName, LoginName, CompleteFlag,
			// PassFlag, AccessCount, TestCount, TestResultAve, TestResultMax
			Vector vecCourseResultTest = getCourseResultTest(strStudentIDList,
															 strCoursesIDList);
			mobjDba.clearProperty();
			DebugLog.write(this.getClass(), "教材ログリスト無事取得成功", DebugLog.ROW);
			
			// ユニットログリスト取得(ただし、UnitOrderとUnitNameはUnitInfoTableから取得)
			// CourseCode, StudentID, UnitOrder, UnitName, AccessCount, ProgressRate
			// TestCount, TestResultAve, TestResultMax, PassFlag
			Vector vecUnitResultTest = getUnitResultTest(strStudentIDList,
														 strCoursesIDList);
			mobjDba.clearProperty();
			DebugLog.write(this.getClass(), "Unitログリスト無事取得成功", DebugLog.ROW);
			
			// 教材ユニットリストマージ処理
			objClrList = makeCourseUnitList(vecCourseResultTest,
										vecUnitResultTest,
										vecUnitList);
			
			DebugLog.write(this.getClass(), "教材ユニットログリスト無事取得成功", DebugLog.ROW);
		}
		catch(LOException le)
		{
			throw le;
		}
		catch(SQLException se)
		{
			throw new LOException(se.getMessage());
		}
		catch(Exception e)
		{
			try
			{
				mobjDba.rollback();
			}
			catch(Exception ex)
			{
				throw new LOException("DBのクローズに失敗しました");
			}
			throw new LOException(e.getMessage());
		}
		
		try
		{
			mobjDba.commit();
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return objClrList;
	}
	
	/**
	 * ユーザーIDリストからStudentIDリストを作成する<BR>
	 * @param String[] ユーザーIDリスト
	 * @return String[] StudentIDリスト
	 */
	private String[] getStudentIDList(String[] strUserIDList)
		throws SQLException, Exception
	{
		String[] strRet = null;
		// WHERE句設定
		StringBuffer strWhereSQL = new StringBuffer();
		String strIDWhere     = makeIDWhere(strUserIDList);
		strWhereSQL.append("student_info.LoginName IN (");
		strWhereSQL.append(strIDWhere);
		strWhereSQL.append(")");
		String strWhere = strWhereSQL.toString();
		mobjDba.setCommand(DBAccess.CMD_SELECT);
		mobjDba.setItem(DBAccess.ITEM_ALL);
		mobjDba.setTableName("student_info");
		mobjDba.setWhere(strWhere);
		Vector vecList = mobjDba.execute();
		if(vecList.size() == 0)
		{
			// この場合のみNULLを返す
			return strRet;
		}
		strRet = new String[vecList.size()];
		for(int i = 0; i < vecList.size(); i++)
		{
			String[] strList = (String[])vecList.get(i);
			strRet[i] = strList[0];												// StudentIDは配列の0番目
		}
		return strRet;
	}
	
	/**
	 * 教材IDリストからStudentIDリストを作成する<BR>
	 * @param String[] 教材IDリスト
	 * @return Vector Unit情報
	 */
	private Vector getUnitList(String[] strCoursesIDList)
		throws SQLException, Exception
	{
		// WHERE句設定
		StringBuffer strItemSQL    = new StringBuffer();
		StringBuffer strWhereSQL   = new StringBuffer();
		StringBuffer strGroupBySQL = new StringBuffer();
		String strIDWhere          = makeIDWhere(strCoursesIDList);
		strItemSQL.append(" unit_info.CourseCode,");
		strItemSQL.append(" unit_info.UnitOrder,");
		strItemSQL.append(" unit_info.UnitName");
		strGroupBySQL.append(" unit_info.CourseCode,");
		strGroupBySQL.append(" unit_info.UnitOrder,");
		strGroupBySQL.append(" unit_info.UnitName");
		strWhereSQL.append("unit_info.CourseCode IN (");
		strWhereSQL.append(strIDWhere);
		strWhereSQL.append(")");
		String strItem = strItemSQL.toString();
		String strWhere = strWhereSQL.toString();
		String strGroupBy = strGroupBySQL.toString();
		mobjDba.setCommand(DBAccess.CMD_SELECT);
		mobjDba.setItem(strItem);
		mobjDba.setTableName("unit_info");
		mobjDba.setWhere(strWhere);
		mobjDba.setGroupBy(strGroupBy);
		Vector vecRet = mobjDba.execute();
		if(vecRet == null)
		{
			// NULLにしない
			vecRet = new Vector();
		}
		return vecRet;
	}
	
	/**
	 * StudentIDリストと教材IDリストから教材ログリストを取得する<BR>
	 * @param String[] StudentIDリスト
	 * @param String[] 教材IDリスト
	 * @return Vector 教材履歴リスト
	 */
	private Vector getCourseResultTest(String[] strStudentIDList,
										String[] strCoursesIDList)
		throws SQLException, Exception
	{
		Vector vecRet = new Vector();											// 教材履歴テストリスト
		Vector vecResult = new Vector();
		Vector vecTest = new Vector();
		// WHERE句設定
		StringBuffer strWhereSQL = new StringBuffer();
		String strStudentWhere   = makeIDWhere(strStudentIDList);
		String strCourseWhere    = makeIDWhere(strCoursesIDList);
		strWhereSQL.append("student_info.StudentID IN (");
		strWhereSQL.append(strStudentWhere);
		strWhereSQL.append(") AND course_info.CourseCode IN (");
		strWhereSQL.append(strCourseWhere);
		strWhereSQL.append(")");
		String strWhere = strWhereSQL.toString();
		// 項目名設定
		StringBuffer strItemSQL = new StringBuffer();
		strItemSQL.append(" course_info.CourseCode, student_info.StudentID, ");
		strItemSQL.append("course_info.CourseName, student_info.LoginName, ");
		strItemSQL.append("MAX(course_result.CompleteFlag) AS 修了, ");
		strItemSQL.append("MAX(course_result.CourseCount) AS 学習回数");
		String strItem = strItemSQL.toString();
		// テーブル名設定
		StringBuffer strTableNameSQL = new StringBuffer();
		strTableNameSQL.append("course_info INNER JOIN ");
		strTableNameSQL.append("course_result ON ");
		strTableNameSQL.append(
			"course_info.CourseCode = course_result.CourseCode AND ");
		strTableNameSQL.append(
			"course_info.CourseVersion = course_result.CourseVersion INNER JOIN ");
		strTableNameSQL.append("student_info ON ");
		strTableNameSQL.append(
			"course_result.StudentID = student_info.StudentID");
		String strTableName = strTableNameSQL.toString();
		// グループ化設定
		StringBuffer strGroupBySQL = new StringBuffer();
		strGroupBySQL.append("course_info.CourseCode, course_info.CourseName, ");
		strGroupBySQL.append("student_info.StudentID, student_info.LoginName, ");
		strGroupBySQL.append("course_info.CourseVersion");
		String strGroupBy = strGroupBySQL.toString();
		// 履歴リスト取得
		mobjDba.setCommand(DBAccess.CMD_SELECT);
		mobjDba.setItem(strItem);
		mobjDba.setTableName(strTableName);
		mobjDba.setWhere(strWhere);
		mobjDba.setGroupBy(strGroupBy);
		vecResult = mobjDba.execute();
		mobjDba.clearProperty();
		
		// 項目名設定
		strItemSQL = new StringBuffer();
		strItemSQL.append(" course_info.CourseCode, student_info.StudentID, ");
		strItemSQL.append("course_info.CourseName, student_info.LoginName, ");
		strItemSQL.append("MAX(course_test.PassFlag) AS 合格, ");
		strItemSQL.append("MAX(course_test.TestCount) AS テスト回数, ");
		strItemSQL.append("AVG(course_test.ResultTest) AS 平均, ");
		strItemSQL.append("MAX(course_test.ResultTest) AS 最高");
		strItem = strItemSQL.toString();
		// テーブル名設定
		strTableNameSQL = new StringBuffer();
		strTableNameSQL.append("course_test INNER JOIN ");
		strTableNameSQL.append("course_info ON ");
		strTableNameSQL.append(
			"course_test.CourseCode = course_info.CourseCode AND ");
		strTableNameSQL.append(
			"course_test.CourseVersion = course_info.CourseVersion INNER JOIN ");
		strTableNameSQL.append("student_info ON ");
		strTableNameSQL.append(
			"course_test.StudentID = student_info.StudentID");
		strTableName = strTableNameSQL.toString();
		// グループ化設定
		strGroupBySQL = new StringBuffer();
		strGroupBySQL.append("course_info.CourseCode, course_info.CourseName, ");
		strGroupBySQL.append("student_info.StudentID, student_info.LoginName, ");
		strGroupBySQL.append("course_info.CourseVersion");
		strGroupBy = strGroupBySQL.toString();
		// テストリスト取得
		mobjDba.setCommand(DBAccess.CMD_SELECT);
		mobjDba.setItem(strItem);
		mobjDba.setTableName(strTableName);
		mobjDba.setWhere(strWhere);
		mobjDba.setGroupBy(strGroupBy);
		vecTest = mobjDba.execute();
		
		// 教材リストマージ処理
		vecRet = mergeCourseList(vecResult, vecTest);
		return vecRet;
	}
	
	/**
	 * StudentIDリストと教材IDリストからユニットログリストを取得する<BR>
	 * @param String[] StudentIDリスト
	 * @param String[] 教材IDリスト
	 * @return Vector ユニットログリスト
	 */
	private Vector getUnitResultTest(String[] strStudentIDList,
									 String[] strCoursesIDList)
		throws SQLException, Exception
	{
		Vector vecRet = new Vector();
		Vector vecResult = new Vector();
		Vector vecTest = new Vector();
		// WHERE句設定
		StringBuffer strWhereSQL = new StringBuffer();
		String strStudentWhere   = makeIDWhere(strStudentIDList);
		String strCourseWhere    = makeIDWhere(strCoursesIDList);
		strWhereSQL.append("unit_result.StudentID IN (");
		strWhereSQL.append(strStudentWhere);
		strWhereSQL.append(") AND unit_info.CourseCode IN (");
		strWhereSQL.append(strCourseWhere);
		strWhereSQL.append(")");
		String strWhere = strWhereSQL.toString();
		// 項目名設定
		StringBuffer strItemSQL = new StringBuffer();
		strItemSQL.append(" unit_info.CourseCode, unit_result.StudentID, ");
		strItemSQL.append("unit_info.UnitOrder, ");
		strItemSQL.append("MAX(unit_result.AccessCount) AS 学習回数, ");
		strItemSQL.append("MAX(unit_result.UnitStatus) AS 学習進捗");
		String strItem = strItemSQL.toString();
		// テーブル名設定
		StringBuffer strTableNameSQL = new StringBuffer();
		strTableNameSQL.append("unit_info INNER JOIN unit_result ON ");
		strTableNameSQL.append("unit_info.CourseCode = unit_result.CourseCode AND ");
		strTableNameSQL.append(
			"unit_info.CourseVersion = unit_result.CourseVersion AND ");
		strTableNameSQL.append("unit_info.UnitOrder = unit_result.UnitOrder");
		String strTableName = strTableNameSQL.toString();
		// グループ化設定
		StringBuffer strGroupBySQL = new StringBuffer();
		strGroupBySQL.append("unit_info.CourseCode, unit_result.StudentID, ");
		strGroupBySQL.append("unit_info.UnitOrder, ");
		strGroupBySQL.append("unit_info.CourseVersion");
		String strGroupBy = strGroupBySQL.toString();
		// 履歴リスト取得
		mobjDba.setCommand(DBAccess.CMD_SELECT);
		mobjDba.setItem(strItem);
		mobjDba.setTableName(strTableName);
		mobjDba.setWhere(strWhere);
		mobjDba.setGroupBy(strGroupBy);
		vecResult = mobjDba.execute();
		mobjDba.clearProperty();
		
		// WHERE句設定
		strWhereSQL = new StringBuffer();
		strWhereSQL.append("unit_test.StudentID IN (");
		strWhereSQL.append(strStudentWhere);
		strWhereSQL.append(") AND unit_info.CourseCode IN (");
		strWhereSQL.append(strCourseWhere);
		strWhereSQL.append(")");
		strWhere = strWhereSQL.toString();
		// 項目名設定
		strItemSQL = new StringBuffer();
		strItemSQL.append(" unit_info.CourseCode, unit_test.StudentID, ");
		strItemSQL.append("unit_info.UnitOrder, ");
		strItemSQL.append("MAX(unit_test.TestCount) AS テスト回数, ");
		strItemSQL.append("AVG(unit_test.UnitResult) AS 平均, ");
		strItemSQL.append("MAX(unit_test.UnitResult) AS 最高, ");
		strItemSQL.append("MAX(unit_test.PassFlag) AS 合格");
		strItem = strItemSQL.toString();
		// テーブル名設定
		strTableNameSQL = new StringBuffer();
		strTableNameSQL.append("unit_info INNER JOIN ");
		strTableNameSQL.append(
			"unit_test ON unit_info.CourseCode = unit_test.CourseCode AND ");
		strTableNameSQL.append(
			"unit_info.CourseVersion = unit_test.CourseVersion AND ");
		strTableNameSQL.append("unit_info.UnitOrder = unit_test.UnitOrder");
		strTableName = strTableNameSQL.toString();
		// グループ化設定
		strGroupBySQL = new StringBuffer();
		strGroupBySQL.append("unit_info.CourseCode, unit_test.StudentID, ");
		strGroupBySQL.append("unit_info.UnitOrder, ");
		strGroupBySQL.append("unit_info.CourseVersion");
		strGroupBy = strGroupBySQL.toString();
		// テストリスト取得
		mobjDba.setCommand(DBAccess.CMD_SELECT);
		mobjDba.setItem(strItem);
		mobjDba.setTableName(strTableName);
		mobjDba.setWhere(strWhere);
		mobjDba.setGroupBy(strGroupBy);
		vecTest = mobjDba.execute();
		
		// 教材リストマージ処理
		vecRet = mergeUnitList(vecResult, vecTest);
		return vecRet;
	}
	
	/**
	 * 教材履歴リストと教材テストリストから教材ログリストを作成する<BR>
	 * @param Vector 教材ログリスト
	 * @param Vector ユニットログリスト
	 * @param Vector ユニットリスト
	 * @return CourseUnitLogRecord[] 教材ログリスト
	 */
	private CourseUnitLogRecord[] makeCourseUnitList(
										Vector vecCourseResultTest,
										Vector vecUnitResultTest,
										Vector vecUnitList)
	{
		int i = 0;
		int j = 0;
		int k = 0;
		int intCourseSize = vecCourseResultTest.size();
		int intUnitSize   = vecUnitResultTest.size();
		CourseUnitLogRecord[] objRet = null;									// 戻り値初期化

		String strTempStudentID  = "";
		String strTempCoursesID  = "";
		Vector vecList = new Vector();
		// 教材ログリストを基準とする
		for(i = 0; i < intCourseSize; i++)
		{
			String[] strCourseList = (String[])vecCourseResultTest.get(i);
			String strClCoursesID = strCourseList[0];
			String strClStudentID = strCourseList[1];
			CourseLogRecord objCr = new CourseLogRecord();
			objCr.initialize();													// 初期化
			objCr.setCoursesID(strCourseList[0]);								// 教材ID設定
			objCr.setStudentID(strCourseList[1]);								// StudentID設定
			objCr.setCoursesName(strCourseList[2]);								// 教材名設定
			objCr.setUserID(strCourseList[3]);									// ログイン名設定
			objCr.setCompleteFlag(strCourseList[4]);							// 学習終了設定
			objCr.setPassFlag(strCourseList[5]);								// 合否設定
			objCr.setAccessCount(strCourseList[6]);								// アクセス回数設定
			objCr.setTestCount(strCourseList[7]);								// テスト回数設定
			objCr.setAverageScore(strCourseList[8]);							// 平均点設定
			objCr.setHighestScore(strCourseList[9]);							// 最高点設定
			objCr.setUnitCount("0");											// ユニット数初期化
			// 指定教材IDのUnitリストを取得
			Vector vecUnitCourseList = getUnitCourseList(
										strCourseList[0], vecUnitList);			// 指定教材ユニットリスト
			Vector vecUnitRTList = new Vector();								// ユニット結果リスト
			int intProgressRateSum = 0;
			// ユニット数分繰り返す
			for(j = 0; j < vecUnitCourseList.size(); j++)
			{
				String[] strUnitList = (String[])vecUnitCourseList.get(j);		// 指定教材ユニットリスト
				String strUnitCourseID = strUnitList[0];						// ユニット教材ID
				String strUnitOrder = strUnitList[1];							// ユニットオーダー
				String strUnitName = strUnitList[2];							// ユニット名
				CourseUnitLogRecord objClr = new CourseUnitLogRecord();
				objClr.initialize();											// 初期化
				objClr.setCoursesID(objCr.getCoursesID());						// 教材ID設定
				objClr.setStudentID(objCr.getStudentID());						// StudentID設定
				objClr.setCoursesName(objCr.getCoursesName());					// 教材名設定
				objClr.setUserID(objCr.getUserID());							// ログイン名設定
				objClr.setCompleteFlag(objCr.getCompleteFlag());				// 学習終了設定
				objClr.setPassFlag(objCr.getPassFlag());						// 合否設定
				objClr.setAccessCount(objCr.getAccessCount());					// アクセス回数設定
				objClr.setTestCount(objCr.getTestCount());						// テスト回数設定
				objClr.setAverageScore(objCr.getAverageScore());				// 平均点回数設定
				objClr.setHighestScore(objCr.getHighestScore());				// 最高点回数設定
				objClr.setUnitOrder(strUnitOrder);								// Unitオーダー設定
				objClr.setUnitName(strUnitName);								// Unit名設定
				// ユニット統計ログリスト検索
				for(k = 0; k < intUnitSize; k++)
				{
					String[] strUnitRTList = (String[])vecUnitResultTest.get(k);
					String strUlCoursesID = strUnitRTList[0];
					String strUlStudentID = strUnitRTList[1];
					String strUlUnitOrder = strUnitRTList[2];
					if(strClStudentID != null && strClCoursesID != null &&
						strUnitOrder != null &&
						strClStudentID.equals(strUlStudentID) &&
						strClCoursesID.equals(strUlCoursesID) &&
						strUnitOrder.equals(strUlUnitOrder))
					{
						// ユニットログ設定
						objClr.setUnitAccessCount(strUnitRTList[3]);		// Unit学習回数設定
						objClr.setUnitProgress(strUnitRTList[4]);			// 平均進捗率
						objClr.setUnitTestCount(strUnitRTList[5]);			// Unitテスト回数設定
						objClr.setUnitAverageScore(strUnitRTList[6]);		// Unit平均点設定
						objClr.setUnitHighestScore(strUnitRTList[7]);		// Unit最高点設定
						objClr.setUnitPassFlag(strUnitRTList[8]);			// Unit合否設定
						objCr.setUnitCount(String.valueOf
											(vecUnitCourseList.size()));	// Unit数を設定
						if(objClr.getUnitProgress() != null)
						{
							int intProgressRate = Integer.parseInt(objClr.getUnitProgress());
							intProgressRateSum += intProgressRate;
						}
						else
						{
							objClr.setUnitProgress("0");
						}
					}
				}
				vecUnitRTList.add(objClr);
			}
			
			
			// ユニット統計ログリストがなかった場合、教材のみリストに追加
			if(objCr.getUnitCount().equals("0"))
			{
				CourseUnitLogRecord objClr = new CourseUnitLogRecord();
				objClr.initialize();									// 初期化
				objClr.setCoursesID(objCr.getCoursesID());				// 教材ID設定
				objClr.setStudentID(objCr.getStudentID());				// StudentID設定
				objClr.setCoursesName(objCr.getCoursesName());			// 教材名設定
				objClr.setUserID(objCr.getUserID());					// ログイン名設定
				objClr.setCompleteFlag(objCr.getCompleteFlag());		// 学習終了設定
				objClr.setPassFlag(objCr.getPassFlag());				// 合否設定
				objClr.setAccessCount(objCr.getAccessCount());			// アクセス回数設定
				objClr.setTestCount(objCr.getTestCount());				// テスト回数設定
				objClr.setAverageScore(objCr.getAverageScore());		// 平均点設定
				objClr.setHighestScore(objCr.getHighestScore());		// 最高点設定
				// ユニット数を0にすることでユニットリストを表示しない
				objClr.setUnitCount("0");								// Unit数を0に設定
				objClr.nullConvert();
				vecList.add(objClr);
			}
			else
			{
				// 学習進捗計算
				int intProgressRateAvg = 0;
				if(intProgressRateSum > 0)
				{
					intProgressRateAvg = intProgressRateSum / vecUnitCourseList.size();
				}
				for(j = 0; j < vecUnitRTList.size(); j++)
				{
					CourseUnitLogRecord objTempCulr = (CourseUnitLogRecord)
														vecUnitRTList.get(j);
					objTempCulr.setProgressRate(String.valueOf(intProgressRateAvg));
					objTempCulr.nullConvert();
					// ユニット数を0以外にする
					objTempCulr.setUnitCount(String.valueOf(vecUnitCourseList.size()));
					vecList.add(objTempCulr);
				}
			}
		}
		objRet = new CourseUnitLogRecord[vecList.size()];
		vecList.copyInto(objRet);
		return objRet;
	}
	
	/**
	 * IDリストからWhere文を作成する
	 * @param String[] IDリスト
	 * @return String IDWhere句
	 */
	private String makeIDWhere(String[] strIDList)
	{
		String strRet = "";
		StringBuffer strIDWhere = new StringBuffer();
		int intIndex = 0;
		while(intIndex < strIDList.length)
		{
			strIDWhere.append("'");
			strIDWhere.append(StringEscapeUtils.escapeSql(strIDList[intIndex++]));
			strIDWhere.append("'");
			strIDWhere.append(",");
				
		}
		// 最後の","を削除します
		strIDWhere.deleteCharAt(strIDWhere.length() - 1);
		strRet = strIDWhere.toString();
		return strRet;
	}
	
	/**
	 * 指定教材IDのUnitリストを取得する
	 * @param String 教材ID
	 * @param Vector ユニットリスト
	 * @return Vector 指定教材IDのユニットリスト
	 */
	private Vector getUnitCourseList(String strCourseID, Vector vecList)
	{
		Vector vecRet = new Vector();
		for(int i = 0; i < vecList.size(); i++)
		{
			String[] strUnitRecord = (String[])vecList.get(i);
			if(strCourseID.equals(strUnitRecord[0]))
			{
				vecRet.add(strUnitRecord);
			}
		}
		return vecRet;
	}

	/**
	 * 教材レコードマージ処理
	 * @param Vector 教材履歴リスト
	 * @param Vector 教材テストリスト
	 * @return Vector 教材履歴テストリスト
	 */
	private Vector mergeCourseList(Vector vecResultList, Vector vecTestList)
	{
		Vector vecRet = new Vector();								// 教材履歴テストリスト
		int i = 0;
		int j = 0;
		// 履歴リストがなくなるまで繰り返す
		for(i = 0; i < vecResultList.size(); i++)
		{
			// CourseCode, StudentID, CourseName, LoginName, CompleteFlag,
			// PassFlag, AccessCount, TestCount, TestResultAve, TestResultMax
			String[] strRec = new String[10];						// 教材履歴テストレコード
			// CourseCode, StudentID, CourseName, LoginName,
			// CompleteFlag, AccessCount
			String[] strResultRec = (String[])vecResultList.get(i);	// 教材履歴レコード
			// 履歴レコード設定
			strRec[0] = strResultRec[0];							// 教材ID
			strRec[1] = strResultRec[1];							// 学習者ID
			strRec[2] = strResultRec[2];							// 教材名
			strRec[3] = strResultRec[3];							// ログイン名
			strRec[4] = strResultRec[4];							// 修了フラグ
			strRec[6] = strResultRec[5];							// 学習回数
			// テストレコード検索
			for(j = 0; j < vecTestList.size(); j++)
			{
				// CourseCode, StudentID, CourseName, LoginName,
				// PassFlag, TestCount, TestResultAve, TestResultMax
				String strTestRec[] = (String[])vecTestList.get(j);	// 教材テストレコード
				// 学習者IDと教材IDの比較
				if(strResultRec[0] != null &&
					strResultRec[1] != null &&
					strResultRec[0].equals(strTestRec[0]) &&
					strResultRec[1].equals(strTestRec[1]))
				{
					strRec[5] = strTestRec[4];						// 合否フラグ
					strRec[7] = strTestRec[5];						// テスト回数
					strRec[8] = strTestRec[6];						// 平均点
					strRec[9] = strTestRec[7];						// 最高点
					vecTestList.remove(j);							// テストレコード削除
					break;
				}
			}
			vecRet.add(strRec);										// 教材履歴レコード追加
		}
		// テストレコードの残りを追加する
		for(i = 0; i < vecTestList.size(); i++)
		{
			String[] strRec = new String[10];
			String[] strTestRec = (String[])vecTestList.get(i);		// 教材テストレコード
			strRec[0] = strTestRec[0];								// 教材ID
			strRec[1] = strTestRec[1];								// 学習者ID
			strRec[2] = strTestRec[2];								// 教材名
			strRec[3] = strTestRec[3];								// ログイン名
			strRec[5] = strTestRec[4];								// 合否フラグ
			strRec[7] = strTestRec[5];								// テスト回数
			strRec[8] = strTestRec[6];								// 平均点
			strRec[9] = strTestRec[7];								// 最高点
			vecRet.add(strRec);
		}
		return vecRet;
	}
	
	/**
	 * ユニットレコードマージ処理
	 * @param Vector ユニット履歴リスト
	 * @param Vector ユニットテストリスト
	 * @return Vector ユニット履歴テストリスト
	 */
	private Vector mergeUnitList(Vector vecResultList, Vector vecTestList)
	{
		Vector vecRet = new Vector();								// ユニット履歴テストリスト
		int i = 0;
		int j = 0;
		// 履歴リストがなくなるまで繰り返す
		for(i = 0; i < vecResultList.size(); i++)
		{
			// CourseCode, StudentID, UnitOrder, AccessCount,
			// TestCount, TestResultAve, TestResultMax, PassFlag
			String[] strRec = new String[9];						// ユニット履歴テストレコード
			// CourseCode, StudentID, UnitOrder, AccessCount
			String[] strResultRec = (String[])vecResultList.get(i);	// 教材履歴レコード
			// 履歴レコード設定
			strRec[0] = strResultRec[0];							// 教材ID
			strRec[1] = strResultRec[1];							// 学習者ID
			strRec[2] = strResultRec[2];							// ユニットオーダー
			strRec[3] = strResultRec[3];							// 学習回数
			strRec[4] = strResultRec[4];							// 学習進捗
			// テストレコード検索
			for(j = 0; j < vecTestList.size(); j++)
			{
				// CourseCode, StudentID, CourseName, LoginName,
				// PassFlag, TestCount, TestResultAve, TestResultMax
				String strTestRec[] = (String[])vecTestList.get(j);	// ユニットテストレコード
				// 学習者IDと教材IDとユニットオーダーの比較
				if(strResultRec[0] != null &&
					strResultRec[1] != null &&
					strResultRec[2] != null &&
					strResultRec[0].equals(strTestRec[0]) &&
					strResultRec[1].equals(strTestRec[1]) &&
					strResultRec[2].equals(strTestRec[2]))
				{
					strRec[5] = strTestRec[3];						// テスト回数
					strRec[6] = strTestRec[4];						// 平均点
					strRec[7] = strTestRec[5];						// 最高点
					strRec[8] = strTestRec[6];						// 合否フラグ
					vecTestList.remove(j);							// テストレコード削除
					break;
				}
			}
			vecRet.add(strRec);										// 教材履歴レコード追加
		}
		// テストレコードの残りを追加する
		for(i = 0; i < vecTestList.size(); i++)
		{
			String[] strRec = new String[9];
			String[] strTestRec = (String[])vecTestList.get(i);		// 教材テストレコード
			strRec[0] = strTestRec[0];								// 教材ID
			strRec[1] = strTestRec[1];								// 学習者ID
			strRec[2] = strTestRec[2];								// ユニットオーダー
			strRec[5] = strTestRec[3];								// テスト回数
			strRec[6] = strTestRec[4];								// 平均点
			strRec[7] = strTestRec[5];								// 最高点
			strRec[8] = strTestRec[6];								// 合否フラグ
			vecRet.add(strRec);
		}
		return vecRet;
	}

}
