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

//
//	Offline教材 演習回答状況データストアクラス
//			変更履歴
//				2004.01.08	新規作成	滝島　英幸
//
package jp.co.ntt.lms.lo.Offline.IndividualLog;

// Java API
import java.util.Vector;

import jp.co.ntt.lms.Common.RDF.RDFNode;

/**
 * 演習回答状況データストア<BR>
 * 
 * @author H.Takishima
 * @version 2.0.4.0.0 2004/01/08
 */
public class IndividualLogReplyStatusStoreData extends IndividualLogStoreData {

	/**LOID **/
	private String mstrLOID;
	
	/**GroupID **/
	private String mstrGroupID;
	
	/**LoType **/
	private String mstrLoType;
	
	/**セッションから取得した目次**/
	private RDFNode mobjNode;

	/**AU単位設問MAX数 SQL取得データ格納領域**/
	private String mstrSqlMAXData[ ][ ];

	/**AU単位設問MAX数 SQL→計算 格納領域**/
	Vector mvecMax;

	/**SQL取得データ格納領域**/
	private String mstrSqlData[ ][ ];

	/**演習成績分析データ（全件）**/
	private Vector mvecStoreData;
	
	/**
	 * コンストラクタ
	 * @param LOID
	 * @param GroupID（ユーザ指定時はユーザID、グループ指定時はグループID）
	 * @param LoType
	 * @param objNode
	 **/
	public IndividualLogReplyStatusStoreData(String strLOID,String strGroupID,String strLoType,RDFNode objNode ) {
		this.mstrLOID = strLOID;
		this.mstrGroupID = strGroupID;
		this.mstrLoType = strLoType;
		this.mobjNode = objNode;
	}

	/**
	 * 演習成績分析表データオブジェクト作成
	 * @return 正常、異常
	 **/
	public boolean makeStoreData( ) {
	
		try{
			//AU単位設問MAX数取得
			makeMaxSql( );
			
			//AU単位設問MAX数計算、一時格納
			setMaxCount( );

			//演習分析表作成
			makeReplySql( );

			//データが存在した場合
			if( mstrSqlData.length != 0 && mstrSqlData != null){
				//RecordSet→データObj
				setStoreData( );

				//IndividualLogStoreDataに作成した一覧表Objをセット
				setStoreDataObj(mvecStoreData);
			}
			return true;

		}catch(Exception e){
			return false;
		}
	}

	/**
	 * AU単位の設問のMAX件数を確保
	 * mvecMaxに[UID(String)][MAX件数(Integer)]を格納
	 * @param UID
	 **/
	private void setMaxCount(  ){

		int intRowCnt;
		int intMaxCnt;
		Integer IntegerMaxCnt;

		String strUID = new String( );
		String strOldUID = new String( );
		Vector vecMaxRow = new Vector( );
		mvecMax = new Vector( );
		
		//件数（行）
		intRowCnt = mstrSqlMAXData.length;
		
		intMaxCnt = 0;
		for(int i=0; i<intRowCnt; i++){
			strUID = mstrSqlMAXData[ i ][ REPLY_MAX_UID ];
			if( strUID.equals( strOldUID )){
				intMaxCnt = intMaxCnt + 1;
			}else if( strOldUID.equals( "" ) ){
				intMaxCnt = intMaxCnt + 1;
				strOldUID = strUID;
			}else{
				vecMaxRow = new Vector( );
				vecMaxRow.addElement( strOldUID );
				IntegerMaxCnt = new Integer( intMaxCnt );
				vecMaxRow.addElement( IntegerMaxCnt );
				mvecMax.addElement( vecMaxRow );
				//初期化
				intMaxCnt = 1;
				strOldUID = strUID;
			}
			if ( i == intRowCnt-1){
				vecMaxRow = new Vector( );
				vecMaxRow.addElement( strOldUID );
				IntegerMaxCnt = new Integer( intMaxCnt );
				vecMaxRow.addElement( IntegerMaxCnt );
				mvecMax.addElement( vecMaxRow );
			}
		}
	}

	/**
	 * AUIDを指定し、AU単位の設問(interaction_id)MAX数を返す。
	 * @param AUID
	 * @return MAX数
	 **/
	public int getInteractionIDMAX(String strPrmAUID ) {
		
		String strUID = new String( );
		Vector vecMaxRow = new Vector( );
		Integer IntegerMax;

		int intMax = 0;
		
		//データが0件の場合
		if( mvecMax == null ){
			return intMax;
		}
		for(int i=0; i < mvecMax.size( ); i++ ){
			vecMaxRow = ( Vector )mvecMax.get( i );
			strUID = vecMaxRow.get( REPLY_MAX_OBJ_UID ).toString( );
			//AUID検索
			if( strPrmAUID.equals( strUID ) ){
				//obj→int
				IntegerMax = ( Integer) vecMaxRow.get( REPLY_MAX_OBJ_MAX );
				intMax = IntegerMax.intValue( );
				return intMax;
			}
		}
		return intMax;
	}

	/**
	 * UID指定でその設問と正解解答を返す。
	 * @param UID
	 * @return [設問][正解解答]
	 */
	public Vector getCorrectResponse( String strPrmAUID ){
	
		int intRowCnt;
		int intFlg;
		Integer IntegerMaxCnt;
		Vector vecWrkCorrctRow;
		Vector vecCorrctResponseData;

		//件数（行）
		intRowCnt = mstrSqlMAXData.length;
		
		vecCorrctResponseData = new Vector( );
		intFlg = 0;
		for(int  i=0; i < intRowCnt; i++){
			if( strPrmAUID.equals(mstrSqlMAXData[ i ][ REPLY_MAX_UID ])){
				vecWrkCorrctRow = new Vector( );
				vecWrkCorrctRow.addElement( mstrSqlMAXData[ i ][ REPLY_MAX_INTERACTION_ID ] );
				vecWrkCorrctRow.addElement( mstrSqlMAXData[ i ][ REPLY_MAX_CORRECT_RESPONSE ] );
				vecCorrctResponseData.addElement( vecWrkCorrctRow );
				intFlg = 1;
			//mstrSqlMAXDataはAU順にソートされている為、返す値をセットし始め、AUが変わればセット完了
			}else if ( intFlg == 1 ) {
				break;
			}
		}
		return vecCorrctResponseData;
	}

	/**
	 * AU単位設問MAX数をDBより取得
	 * SQLを発行し、DBからデータ取得
	 **/
	private void makeMaxSql() throws Exception{
	
		Vector vecParam = new Vector();		//条件格納領域
		String strSQLID = new String( );			//SQLID
		
		// リアルLOIDを取得。
		String strRealLoID = new IndividualLogStoreData().getRealLoID(mstrLOID);

		//ユーザ指定
		if( mstrGroupID.substring(0, 2).equals( USERID_TOP ) ){
			//条件セット
			vecParam.addElement(strRealLoID);
			vecParam.addElement(mstrGroupID);
			strSQLID = SQLID_REPLY_MAX_USER;
		//グループ指定指定
		}else{
			//条件セット
			vecParam.addElement(strRealLoID);
			vecParam.addElement(mstrGroupID);
			strSQLID = SQLID_REPLY_MAX_GROUP;
		}
		mstrSqlMAXData = execute( mstrLoType, strSQLID,  vecParam);
		
	}

	/**
	 * 演習回答状況の一覧データをDBより取得
	 * SQLを発行し、DBからデータ取得
	 **/
	private void makeReplySql() throws Exception{
	
		Vector vecParam = new Vector();		//条件格納領域
		String strSQLID = new String( );			//SQLID
		
		// リアルLOIDを取得。
		String strRealLoID = new IndividualLogStoreData().getRealLoID(mstrLOID);

		//ユーザ指定
		if( mstrGroupID.substring(0, 2).equals( USERID_TOP ) ){
			//条件セット
			vecParam.addElement(mstrGroupID);
			vecParam.addElement(strRealLoID);
			strSQLID = SQLID_REPLY_USER;

		//グループ指定指定
		}else{
			//条件セット
			vecParam.addElement(strRealLoID);
			vecParam.addElement(mstrGroupID);
			strSQLID = SQLID_REPLY_GROUP;
		}
		mstrSqlData = execute( mstrLoType, strSQLID,  vecParam);
		
	}

	/**
	 * DBから取得したデータを編集し、表示するAU順にデータObjに格納
	 * 設定：	UID
	 *			目次一覧データ該当Row番号
	 *			UserID
	 *			ユーザ名称
	 *			SessionID
	 *			セッション日付
	 *			回答回数
	 *			得点
	 *			正解数
	 *			設問（InteractionID）
	 *			個人解答
	 *			正誤判定
	 * 設定順：目次データのAU名、UserID、セッション日付（降順）、回答回数の順に格納
	 */
	private void setStoreData( ){
		int intRowCnt;								//件数（行）
		int intColCnt;									//横（列）
		
		String strNodeUID = new String( );			//目次から取得したUID
		String strUID = new String( );				//DBから取得したUID
		String strSessionID = new String( );			//DBから取得したセッションID
		String strUserID = new String( );			//DBから取得したユーザID
		String strOldSessionID = new String( );		//編集時の一時格納セッションID
		String strOldUserID = new String( );			//編集時の一時格納ユーザID
		String strInteraction_id = new String( );		//DBから取得したInteraction_id
		String strOldInteraction_id = new String( );	//編集時の一時格納Interaction_id
		int intAnsCnt;									//回答回数

		//件数（行）
		intRowCnt = mstrSqlData.length;
		
		//横（列）
		intColCnt = mstrSqlData[0].length;
		
		//目次
		createRDFStoreData(mobjNode);
		
		int intStartRow=0;						//同じUserID、SessionIDのRowStart
		int intEndRow=-1;						//同じUserID、SessionIDのRowEnd
		
		int intRow = 0;							//mvecStoreDataにセットするRow位置
		
		mvecStoreData = new Vector( );		//データObj初期化

		//目次順にループ
		for(int i=0; i < getRDFMaxRow( ); i++){
			
			//セクション判定
			if(getRDFType(i).equals(IndividualLogRDFNode.STATUS_S)){
				continue;
			}

			strNodeUID = getRDFAUID( i );					//目次からのUID

			strOldUserID = "";
			strOldSessionID = "";
			strOldInteraction_id = "";
				
			//目次順のAUで、SQLから取得したデータを検索
			for(int j=0; j<intRowCnt; j++){							//目次のRow数Loop
				strUID = mstrSqlData[ j ][ REPLY_REC_UID ];

				//AUIDが一致したら
				if(strNodeUID.equals(strUID)){
					strUserID = mstrSqlData[ j ][ REPLY_REC_USER_ID ];				//UserID
					strSessionID = mstrSqlData[ j ][ REPLY_REC_SESSIONID ];			//SessionID
					strInteraction_id = mstrSqlData[ j ][ REPLY_REC_INTERACTION_ID ];		//Interaction_id

					//UserID、セッション日付単位（UserID、SessionIDが変わった）が同じ
					if( strUserID.equals(strOldUserID) && strSessionID.equals(strOldSessionID) ){
					
						//同じinteraction_idが繰り返されている
						if(strInteraction_id.equals( strOldInteraction_id )){
							intRow = intRow + 1;						//interaction_idが変われば、開始登録行へ
							if( intRow >intEndRow ){
								intEndRow = intRow;				//登録行が最終登録行より大きければ、最終登録行を調整する
							}
							//回答回数の計算
							intAnsCnt = intEndRow - intStartRow ;

							setmvecStoreData( i, j, intRow, intAnsCnt);

						//同じinteraction_idが変わった
						}else{
							intRow = intStartRow;					//interaction_idが変われば、開始登録行へ
							
							setmvecStoreData( i, j, intRow, 1);

						}

					//UserID、セッション日付単位（UserID、SessionIDが変わった）でBreak	
					}else{
						intRow = intEndRow + 1;						//mvecStoreDataに登録している最終行まで移動
						intStartRow = intEndRow + 1;				//Brakeした為、開始位置をずらす
						intEndRow = intEndRow+1;					//Brakeした為、終了位置をずらす

						setmvecStoreData( i, j, intRow ,1);

						strOldUserID = strUserID;
						strOldSessionID = strSessionID;
						
					}
					strOldInteraction_id = strInteraction_id;

				}
			}
		}
	}


	/**
	 * mvecStoreDataに要素番号が存在すれば変更する、しなければ追加
	 * @param 目次データのRow
	 * @param mstrSqlDataの配列Row
	 * @param mvecStoreData要素番号
	 * @param 回答回数
	 */
	private void setmvecStoreData(int intNodeRow, int intSqlRow, int intParamRow, int intAnsCnt ){
		
		Vector vecWrkRow;								//AUI単位のデータ
		String strCorrectCnt = new String( );			//正解数
		String strAnsJudge = new String( );				//正誤判定
		String strAnsCnt = new String( );				//回答回数
		int intMaxCnt;
		int intSetNo;
		
		String strDecimalFlg = "0";					// 数値解答フラグ

		//正誤判定
		strAnsJudge = judgeResult(mstrSqlData[ intSqlRow ][ REPLY_REC_RESULT ]);

		// resultにDecimal値を含む場合、数値解答フラグを立てます。
		if(!strAnsJudge.equals(DEF_CORREC) && !strAnsJudge.equals(DEF_NO_ANSWER) && !strAnsJudge.equals(DEF_WRONG)){
			strDecimalFlg = "1";
		}

		//回答回数変更 
		//int→String
		Integer IntegerAnsCnt = new Integer(intAnsCnt);
		strAnsCnt = IntegerAnsCnt.toString( );
		
		//登録要素番号intEndCntがmvecStoreDataより大きかったら
		if( mvecStoreData.size( ) == 0 || mvecStoreData.size( ) <= intParamRow ){
			vecWrkRow = new Vector( );	
			//UID目次Row数 int→String
			Integer IntegerNodeRow = new Integer(intNodeRow);
			String strNodeRow =  new String( );
			strNodeRow = IntegerNodeRow.toString( );
			//登録
			vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_UID ] );					//UID
			vecWrkRow.addElement( strNodeRow );														//UID目次Row数
			vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_USER_ID ] );			//UserID
			vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_USER_NAME ] );		//学習者名
			vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_SESSIONID ] );			//SessionID
			vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_STUDY_START_DATE ] );			//セッション日付
			vecWrkRow.addElement( strAnsCnt );														//回答回数
			vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_RAWSCORE ] );		//得点
			if( strAnsJudge.equals(DEF_CORREC)){
				vecWrkRow.addElement( new String("1") );												//正解数
			}else{
				vecWrkRow.addElement( new String("0") );												//正解数
			}
			
			//繰り返し部（interaction_id、個人解答、正誤判定）追加
			intMaxCnt = getInteractionIDMAX( mstrSqlData[ intSqlRow ][ REPLY_REC_UID ] );				//設問MAX件数取得
			//今回のデータでinteraction_id、個人解答、正誤判定をセットする位置
			intSetNo = getInteractionIdCol( mstrSqlData[ intSqlRow ][ REPLY_REC_UID ] ,mstrSqlData[ intSqlRow ][ REPLY_REC_INTERACTION_ID ] );
			//MAX件数分””をセット
			for( int i = 0; i<intMaxCnt; i++ ){
				if( i == intSetNo){
					vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_INTERACTION_ID ] );		//設問
					vecWrkRow.addElement( mstrSqlData[ intSqlRow ][ REPLY_REC_STUDENT_RESPONSE ] );		//個人解答
					vecWrkRow.addElement( strAnsJudge );												//正誤判定
				}else{
					vecWrkRow.addElement( new String(" ") );											//設問
					vecWrkRow.addElement( new String(" ") );											//個人解答
					vecWrkRow.addElement( new String(" ") );											//正誤判定
				}
			}
			// 数値解答フラグをVectorの最後に格納します。
			vecWrkRow.addElement( new String(strDecimalFlg) );											// 数値解答フラグ
			mvecStoreData.addElement( vecWrkRow );
		}else{
			vecWrkRow = new Vector( );	

			//mvecStoreDataのintEndCnt要素目を変更
			vecWrkRow = (Vector)mvecStoreData.get(intParamRow);
			
			//正解数変更
			if( strAnsJudge.equals(DEF_CORREC)){
				Integer IntegerCorrectCnt = new Integer( vecWrkRow.get(REPLY_OBJ_CORRECT_COL).toString( ) );
				//String→intして、１足す
				int intCorrectCnt =  IntegerCorrectCnt.intValue( ) ;
				intCorrectCnt = intCorrectCnt + 1;
				IntegerCorrectCnt = null;
				//int→String
				IntegerCorrectCnt = new Integer(intCorrectCnt);
				strCorrectCnt = IntegerCorrectCnt.toString( );
				vecWrkRow.set( REPLY_OBJ_CORRECT_COL, strCorrectCnt );
			}			
			//繰り返し部（interaction_id、個人解答、正誤判定）のみ追加
			//今回のデータでinteraction_id、個人解答、正誤判定をセットする位置
			intSetNo = getInteractionIdCol( mstrSqlData[ intSqlRow ][ REPLY_REC_UID ] ,mstrSqlData[ intSqlRow ][ REPLY_REC_INTERACTION_ID ] );
			//繰り返しデータ１件目セット位置＋intSetNo（設問単位のソート順の番号）*繰り返しデータCOL数
			vecWrkRow.set( REPLY_OBJ_INTERACTION_ID_COL + ( intSetNo * REPLY_OBJ_REPEAT_COL) ,
							 mstrSqlData[ intSqlRow ][ REPLY_REC_INTERACTION_ID ]);						//設問
			vecWrkRow.set( REPLY_OBJ_RESPONSE_COL + ( intSetNo * REPLY_OBJ_REPEAT_COL) ,
							 mstrSqlData[ intSqlRow ][ REPLY_REC_STUDENT_RESPONSE ]);					//個人解答
			vecWrkRow.set( REPLY_OBJ_RESULT_COL + ( intSetNo * REPLY_OBJ_REPEAT_COL) ,
							 strAnsJudge);																//正誤判定
			// 数値解答フラグをVectorの最後に格納します。
			vecWrkRow.addElement( new String(strDecimalFlg) );											// 数値解答フラグ
			mvecStoreData.set( intParamRow ,vecWrkRow );
		}

	}

	/**
	 * AU（UID）、設問（Interaction_id）指定で
	 * AU単位でのアスキー順の設問の順番を返す
	 * @param AUID
	 * @param Interaction_id
	 * @return 指定した設問の順番号
	 */
	public int getInteractionIdCol(String strPrmAUID ,String strParamInteraction_id ) {
		
		int intRowCnt;
		int intCnt;
		
		//件数（行）
		intRowCnt = mstrSqlMAXData.length;
		
		intCnt = -1;
		for( int i=0; i < intRowCnt; i++){
			if( strPrmAUID.equals(mstrSqlMAXData[ i ][ REPLY_MAX_UID ])){
				intCnt = intCnt +1;
				if( strParamInteraction_id.equals(mstrSqlMAXData[ i ][ REPLY_MAX_INTERACTION_ID ] ) ){
					break;
				}
			}
		}
		return intCnt;
	}

}