package jp.ac.takushoku_u.cs;

/**
* SSAnalysisクラスはSS分析を計算するためのクラスです。<BR>
* 1からnまでのn段階のアンケートデータを分析することができます。
* @version 1.2
* @author 笠島 裕史(Kasajima Hiroshi)
*/
/*
* 最終更新日 2004年11月24日
*/
public class SSAnalysis{

/**
* 分析元のマトリクスを保持したマトリクス。
*/
	private ArithmeticMatrix matrix;

/**
* アンケートの型を保持した変数。
*/
	private int scaleType;

/**
* 評定の最大値を保持した変数。
*/
	private int valueRating;

/**
* しきい値を保持した変数。
*/
	private double thresholdValue;

/**
* アンケートの型（I型）を表す定数。
*/
	private static final int SSANALYSIS_SCALE_TYPE_ASCENDING = 1;

/**
* アンケートの型（II型）を表す定数。
*/
	private static final int SSANALYSIS_SCALE_TYPE_MIDDLE = 2;

/**
* アンケートの型（III型）を表す定数。
*/
	private static final int SSANALYSIS_SCALE_TYPE_NONSORT = 3;

/**
* マトリクスの大きさの初期値。
*/
	private static final int SSANALYSIS_MATRIX_VALUE = 5;

/**
* しきい値の初期値。
*/
	private static final double SSANALYSIS_THRESHOLD = 0.93;

/**
* 評定値の最大値の初期値。
*/
	private static final int SSANALYSIS_VALUE_RANGE = 1;

/**
* アンケートの型の初期値。
*/
	private static final int SSANALYSIS_SCALE_TYPE = SSANALYSIS_SCALE_TYPE_ASCENDING;

/**
* SSマトリクスとスケルトンマトリクスに入る値(順序関連がある場合）。
*/
	private static final int SSANALYSIS_SEQUENCE_TRUE = 1;

/**
* SSマトリクスとスケルトンマトリクスに入る値(順序関連がない場合）。
*/
	private static final int SSANALYSIS_SEQUENCE_FALSE = 0;

/**
* 設定されているデフォルトのサイズで分析を行うマトリクスを設定します。<BR>
* 分析を行うマトリクスの要素は全て0に、アンケートの型はI型、
* 評定の最大値はマトリクス内の最大値に、しきい値はデフォルト値となります。
*/
	public SSAnalysis(){
		ArithmeticMatrix baseMatrix = new ArithmeticMatrix(SSANALYSIS_MATRIX_VALUE,SSANALYSIS_MATRIX_VALUE);		//初期マトリクスの作成
		setMatrix(baseMatrix);		//マトリクスの生成
		setScale(SSANALYSIS_SCALE_TYPE);		//アンケートの型の生成
		matrix.clearMatrix();		//マトリクスの要素を初期化
		setRating(SSANALYSIS_VALUE_RANGE);		//評定の最大値の設定
		setThreshold(SSANALYSIS_THRESHOLD);		//しきい値の設定
	}

/**
* 引数を元に分析を行うマトリクスを設定します。<BR>
* アンケートの型はI型、評定の最大値はマトリクス内の最大値に、しきい値はデフォルトとなります。
* @param baseMatrix 分析を行うマトリクス
*/
	public SSAnalysis(ArithmeticMatrix baseMatrix){
		setMatrix(baseMatrix);
		setScale(SSANALYSIS_SCALE_TYPE);
		setRating((int) matrix.getMaxCell());
		setThreshold(SSANALYSIS_THRESHOLD);
	}

/**
* 引数を元に分析を行うマトリクスとアンケートの型を設定します。<BR>
* 評定の最大値はマトリクス内の最大値に、しきい値はデフォルトとなります。
* @param baseMatrix 分析を行うマトリクス
* @param scale アンケートの型
* @exception SetValueOutOfBoundsException アンケートの型が不正である場合
*/
	public SSAnalysis(ArithmeticMatrix baseMatrix, int scale){
		setMatrix(baseMatrix);
		setScale(scale);
		setRating((int) matrix.getMaxCell());
		setThreshold(SSANALYSIS_THRESHOLD);
	}

/**
* 引数を元に分析を行うマトリクス、アンケートの型、しきい値を設定します。<BR>
* 評定の最大値はマトリクス内の最大値となります。
* @param baseMatrix 分析を行うマトリクス
* @param scale アンケートの型
* @param threshold しきい値
* @exception SetValueOutOfBoundsException アンケートの型が不正である場合、しきい値が設定できる範囲外の場合
*/
	public SSAnalysis(ArithmeticMatrix baseMatrix, int scale, double threshold){
		setMatrix(baseMatrix);
		setScale(scale);
		setRating((int) matrix.getMaxCell());
		setThreshold(threshold);
	}

/**
* 引数を元に分析を行うマトリクス、アンケートの型、しきい値、評定の最大値を設定します。<BR>
* 評定の最大値は設定した値とマトリクス内の最大値のいずれか大きい方となります。
* @param baseMatrix 分析を行うマトリクス
* @param scale アンケートの型
* @param threshold しきい値
* @param rating 評定の最大値
* @exception SetValueOutOfBoundsException アンケートの型が不正である場合、またはしきい値が設定できる範囲外の場合
*/
	public SSAnalysis(ArithmeticMatrix baseMatrix, int scale, double threshold, int rating){
		setMatrix(baseMatrix);
		setScale(scale);
		setRating(rating);
		setThreshold(threshold);
	}


/**
* SSマトリクスを返します。
* @return SSマトリクス
* @see #getCoefficientMatrix()
* @see #getSkeletonMatrix()
*/
	public ArithmeticMatrix getSSMatrix(){
		
		//返すSSマトリクス
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(matrix.getColLength(), matrix.getColLength(), 
			matrix.getColNameArray(), matrix.getColNameArray());
		
		//順序（包含）係数表を求める
		ArithmeticMatrix coefficientMatrix = new ArithmeticMatrix(matrix.getColLength(), matrix.getColLength());
		coefficientMatrix.matrixCopy(getCoefficientMatrix());
		
		int value;
		for (int i = 0; i <  matrix.getColLength(); i++){
			for (int j = 0; j <  matrix.getColLength(); j++){
				if (thresholdValue <= coefficientMatrix.getCell(i, j)){	//順序性があるかどうか調べ0,1を設定する
					value = SSANALYSIS_SEQUENCE_TRUE;
				}
				else{
					value = SSANALYSIS_SEQUENCE_FALSE;
				}
				returnMatrix.setCell(i, j, value);
			}
		}
		return returnMatrix;
	}

/**
* 順序（包含）性係数表をマトリクスで返します。
* @return 順序性係数表マトリクス
* @see #getSSMatrix()
* @see #getSkeletonMatrix()
*/
	public ArithmeticMatrix getCoefficientMatrix(){
		
		//返す順序（包含）性係数表
		 ArithmeticMatrix returnMatrix = new ArithmeticMatrix(matrix.getColLength(), matrix.getColLength(),
		 	matrix.getColNameArray(), matrix.getColNameArray());
		
		for (int i = 0; i < matrix.getColLength(); i++){
			for (int j = 0; j < matrix.getColLength(); j++){
				returnMatrix.setCell(i, j, getCoefficient(i, j));
			}
		}
		return returnMatrix;
	}

/**
* ある項目Ijから項目Ikへの順序（包含）性係数を求めます。
* @param Ij 項目Ij
* @param Ik 項目Ik
* @return 項目Ijから項目Ikへの順序性係数
* @exception NotElementException 指定した要素番号が存在しない場合
*/
	public double getCoefficient(int Ij, int Ik){
		if (matrix.isMatrixEntityPoint(Ij, Ik)){
			double value = 0;
			if (getScaleType() == SSANALYSIS_SCALE_TYPE_ASCENDING){		//I型
				value = getAscendingCoefficient(Ij, Ik);
			}
			else if (getScaleType() == SSANALYSIS_SCALE_TYPE_MIDDLE){	//II型
				value = getMiddleCoefficient(Ij, Ik);
			}
			else if (getScaleType() == SSANALYSIS_SCALE_TYPE_NONSORT){	//III型
				value = getNonSortCoefficient(Ij, Ik);
			}
			else{		//デフォルト
				value = getAscendingCoefficient(Ij, Ik);
			}
			return value;
		}
		else{
			throw new NotElementException
				("point(" + Ij + "," + Ik + ")");
		}
	}

/**
* ある項目Ijと項目Ik間の度数分布表を求めます。
* @param Ij 項目Ij
* @param Ik 項目Ik
* @return 項目Ijから項目Ikへの度数分布表
* @exception NotElementException 指定した要素番号が存在しない場合
*/
	public ArithmeticMatrix getFrequencyMatrix(int Ij, int Ik){
		if (matrix.isMatrixEntityPoint(Ij, Ik)){
			
			//返す度数分布表
			ArithmeticMatrix returnTable = new ArithmeticMatrix(getMaxValue(), getMaxValue());
			returnTable.clearMatrix();
			for (int i = 0; i < matrix.getRowLength(); i++){		//度数分布表の作成
				double value = returnTable.getCell((int) matrix.getCell(i, Ij) -1,
					(int) matrix.getCell(i, Ik) -1) +1;
				returnTable.setCell((int) matrix.getCell(i, Ij) -1,
					(int) matrix.getCell(i, Ik) -1, value);
			}
			 return returnTable;
		}
		else{		//指定した要素が存在しない場合
			throw new NotElementException
				("point(" + Ij + "," + Ik + ")");
		}
	}

/**
* I型の順序性係数を求めます。
* @param Ij 項目Ij
* @param Ik 項目Ik
* @return 項目Ijから項目Ikへの順序性係数
*/
	private double getAscendingCoefficient(int Ij, int Ik){
		double value = 0;
		ArithmeticMatrix frequencyMatrix = new ArithmeticMatrix(getMaxValue(), getMaxValue());
		frequencyMatrix = getFrequencyMatrix(Ij, Ik);	//度数分布表を求める

		for (int i = 1; i <= ( frequencyMatrix.getRowLength() - 1); i++){	//順序性係数を求める
			for (int j=i+1; j <=  frequencyMatrix.getColLength(); j++){
				value = (j - i) * frequencyMatrix.getCell(j-1, i-1) + value;
			}
		}
		value = 1 - value / (matrix.getRowLength() * ( frequencyMatrix.getColLength() - 1));
		return value;
	}

/**
* II型の順序性係数を求めます。
* @param Ij 項目Ij
* @param Ik 項目Ik
* @return 項目Iから項目Jへの順序性係数
*/
	private double getMiddleCoefficient(int Ij, int Ik){
		double value = 0;
		double centerRating = (getMaxValue() + 1) / 2;		//評定の中央値
		double numeratorU = (matrix.getRowLength() *
			(getMaxValue() - 1) * (getMaxValue() - 1)) / 4;	//分子
		double gravity;		//重み((r-m0)^2-(q-m0)^2)
		ArithmeticMatrix frequencyMatrix = new ArithmeticMatrix(getMaxValue(), getMaxValue());
		frequencyMatrix = getFrequencyMatrix(Ij, Ik);		//度数分布表を求める

		for (int i = 1; i <= getMaxValue(); i++){		//順序性係数を求める
			for (int j = 1; j <= getMaxValue(); j++){
				if (Math.abs(i - centerRating) > Math.abs(j - centerRating)){
					gravity = ((i - centerRating) * (i - centerRating)) -
					((j - centerRating) * (j - centerRating));
					value = ((gravity * frequencyMatrix.getCell(j-1, i-1)) / numeratorU) + value;
				}
			}
		}
		value = 1- value;
		return value;
	}

/**
* III型の包含性係数を求めます。
* @param Ij 項目Ij
* @param Ik 項目Ik
* @return 項目Iから項目Jへの包含性係数
*/
	private double getNonSortCoefficient(int Ij, int Ik){
		double value = 0;

		//シグマ部分の最大値d0
		double numeratorD = ((matrix.getRowLength() * matrix.getRowLength()) *
			(getMaxValue() - 1)) / (2 * getMaxValue());
		ArithmeticMatrix frequencyMatrix = new ArithmeticMatrix(getMaxValue(), getMaxValue());
		frequencyMatrix.matrixCopy(getFrequencyMatrix(Ij, Ik));	//度数分布表を求める

		for (int i = 1; i <= getMaxValue(); i++){		//包含性係数を求める
			for (int j = 1; j <= getMaxValue(); j++){
				for (int k = 1; k <= getMaxValue(); k++){
					if (j != k){		//r!=r'ならば
						value = (frequencyMatrix.getCell(j, i) *
							frequencyMatrix.getCell(k, i)) + value;
					}
				}
			}
		}
		value = 1 - (value / numeratorD);
		return value;
	}

/**
* SSグラフを描くためのスケルトンマトリクスを返します。
* このマトリクスはSSグラフを描く際の隣接マトリクスを表します。
* @return スケルトンマトリクス
* @see #getSSMatrix()
* @see #getCoefficientMatrix()
*/
	public ArithmeticMatrix getSkeletonMatrix(){
		ArithmeticMatrix SkeletonMatrix = new ArithmeticMatrix(matrix.getColLength(), matrix.getColLength(),
			matrix.getColNameArray(), matrix.getColNameArray());
		
		int[] highOrder = new int[matrix.getColLength()];
		System.arraycopy(getGraphElementArray(), 0, highOrder, 0, highOrder.length);
		SkeletonMatrix.clearMatrix();
		
		//SSマトリクスを得る
		ArithmeticMatrix ssMatrix = new ArithmeticMatrix(matrix.getColLength(), matrix.getColLength());
		ssMatrix.matrixCopy(getSSMatrix());
		
		for (int i = 0; i < SkeletonMatrix.getRowLength(); i++){
			int searchRow = highOrder[i];	 //実際に検索を行う行（平均評定値の高い順の要素）
			int branchCount = 0;		//その要素から他の要素にいくつ枝を描いたか
			boolean isUnder = true;		//その要素より評定値が低い要素を検索中か

			for (int j = SkeletonMatrix.getRowLength() - 1; j >= 0; j--){
				int searchCol = highOrder[j];	//実際に検索を行う列（要素）

				if (searchRow == searchCol){		//同じ要素を調べようとしているか
					isUnder = false;
					branchCount = 0;		//もう一度初期化
				}
				else{
				//他の要素と順序関係があるかどうか
					if (ssMatrix.getCell(searchRow, searchCol) == SSANALYSIS_SEQUENCE_TRUE){

						/*
						* 枝を描く条件であるか
						* 1.未だこの要素より評定値が低い要素を検索しているか
						* 2.この要素から他の要素に枝をまだ描かれていないか
						* 3.この要素より上の要素から枝が描かれているか 
						*/
						if ((branchCount == 0) || (isUnder)||
								(SkeletonMatrix.getCell(searchCol,searchRow) ==
									SSANALYSIS_SEQUENCE_TRUE)){
							SkeletonMatrix.setCell
										(searchRow, searchCol, SSANALYSIS_SEQUENCE_TRUE);
							branchCount = branchCount + 1;
							}
						else{		//他の要素に枝を描いている場合、どこの要素に枝を描いたか探す
							int counter = 0;	//カウンター
							for (int k = ssMatrix.getRowLength() - 1; k > j; k--){
								
								//描いた枝の先の要素から検索を行っている要素へ順序関連が全ての枝においてないか探す
								if ((SkeletonMatrix.getCell(searchRow, highOrder[k]) ==
										SSANALYSIS_SEQUENCE_TRUE) &&
									(ssMatrix.getCell(highOrder[k], searchCol) ==
											SSANALYSIS_SEQUENCE_FALSE)){
										counter = counter + 1;		//ない場合はカウンターを増やす
									}
							}

							//描いた全ての他の枝の先からその要素へ順序関連がない場合は枝を描く
							if (branchCount == counter){
								SkeletonMatrix.setCell
									(searchRow, searchCol, SSANALYSIS_SEQUENCE_TRUE);
								branchCount = branchCount + 1;
							}
						}
					}
				}
			}
		}
		return SkeletonMatrix;
	}

/**
* 項目をグラフを描く順に並べ替えた項目番号の配列を返します。
* @return グラフを描く順に並べ換えた列番号（項目）が入った配列
* @see #getGraphHeightArray()
*/
	public int[] getGraphElementArray(){

		if (getScaleType() == SSANALYSIS_SCALE_TYPE_ASCENDING){		//I型
			return getAscendingGraphArray();
		}
		else if (getScaleType() == SSANALYSIS_SCALE_TYPE_MIDDLE){		//II型
			return getMiddleGraphArray();
		}
		else if (getScaleType() == SSANALYSIS_SCALE_TYPE_NONSORT){		//III型
			return getNonSortGraphArray();
		}
		else{		//該当しない場合
			return getAscendingGraphArray();
		}
	}

/**
* SSグラフを描く際の縦軸となる各項目の値を配列で返します。
* @return 各項目の縦軸となる値を配列
* @see #getGraphElementArray()
*/
	public double[] getGraphHeightArray(){
		double[] returnArray = new double[matrix.getColLength()];

		if (getScaleType() == SSANALYSIS_SCALE_TYPE_ASCENDING){		//I型
			System.arraycopy(getAscendingAverageArray(), 0, returnArray, 0, returnArray.length);
		}
		else if (getScaleType() == SSANALYSIS_SCALE_TYPE_MIDDLE){	//II型
			System.arraycopy(getMiddleAverageArray(), 0, returnArray, 0, returnArray.length);
		}
		else if (getScaleType() == SSANALYSIS_SCALE_TYPE_NONSORT){	//III型
			System.arraycopy(getNonSortCategoryArray(), 0, returnArray, 0, returnArray.length);
		}
		else{		//デフォルト
			System.arraycopy(getAscendingAverageArray(), 0, returnArray, 0, returnArray.length);
		}
		return returnArray;
	}

/**
* 各項目の評定平均値の配列を返します。<BR>
* I型分析の際に使用します。
* @return 平均値の配列が入った配列
*/
	private double[] getAscendingAverageArray(){
		double[]  returnArray = new double[matrix.getColLength()];		//各項目の平均値を格納する
		System.arraycopy(matrix.getColAverageArray(), 0, returnArray, 0, returnArray.length);
		return returnArray;
	}

/**
* 項目をグラフを描く順に並べ替えた項目番号の配列を返します。<BR>
* 平均評定値の高い順に項目番号を並べ変えます。
* I型分析の際に利用します。
* @return グラフを描く順に並べ換えた列番号（項目）が入った配列
*/
	private int[] getAscendingGraphArray(){
		double[]  averageRating = new double[matrix.getColLength()];		//各項目の平均値を格納する
		int[] returnArray = new int[matrix.getColLength()];		//平均評定値の高い順に並べた時の列番号（項目）を入れる
		System.arraycopy(getGraphHeightArray(), 0, averageRating, 0, averageRating.length);
		
		for (int i = 0; i < averageRating.length; i++){
			double maxAverage = averageRating[0];		//初期値
			int maxNumber = 0;
			for (int j = 1; j <  averageRating.length; j++){		//比較を行う
				if (maxAverage < averageRating[j]){
					maxAverage = averageRating[j];
					maxNumber = j;
				}
			}
			averageRating[maxNumber] = 0;	 //比較対象からはずす
			returnArray[i] = maxNumber;
		}
		return returnArray;
	}

/**
* 評定の中央値から外れている度合を表したマトリクスを返します。<BR>
* II型分析の際に利用します。
* @return 元のマトリクスの要素を中央値から引いた絶対値が入ったマトリクス
*/
	private ArithmeticMatrix getMiddleMomentMatrix(){
		ArithmeticMatrix returnMatrix = new ArithmeticMatrix(matrix.getRowLength(), matrix.getColLength(), matrix.getRowNameArray(),
			matrix.getColNameArray());
		double centerRating = (getMaxValue() + 1) / 2;		//評定の中央値
		for (int i = 0; i < matrix.getRowLength(); i++){
			for (int j = 0; j < matrix.getColLength(); j++){
				returnMatrix.setCell(i, j, Math.abs(matrix.getCell(i, j) - centerRating));
			}
		}
		return returnMatrix;
	}

/**
* 評定の中央値から外れている値の配列を返します。<BR>
* II型分析の際に利用します。
* @return 中央値から引いた絶対値の配列が入った配列
*/
	private double[] getMiddleAverageArray(){
		ArithmeticMatrix calculationMatrix = new ArithmeticMatrix(matrix.getRowLength(), matrix.getColLength(), matrix.getRowNameArray(),
			matrix.getColNameArray());
		calculationMatrix.matrixCopy(getMiddleMomentMatrix());
		return calculationMatrix.getColAverageArray();
	}

/**
* 項目をグラフを描く順に並べ替えた項目番号の配列を返します。
* II型分析の際に利用します。
* @return グラフを描く順に並べ換えた列番号（項目）が入った配列
*/
	private int[] getMiddleGraphArray(){
		double[]  averageRating = new double[matrix.getColLength()];		//各項目の中央から外れた合計値を格納する
		int[] returnArray = new int[matrix.getColLength()];	//外れた値が少ない順に並べた時の列番号（項目）を入れる
		System.arraycopy(getGraphHeightArray(), 0, averageRating, 0, averageRating.length);
		for (int i = 0; i < averageRating.length; i++){
			double minAverage = averageRating[0];	//初期値
			int minNumber = 0;
			for (int j = 1; j <  averageRating.length; j++){  //比較を行う
				if (averageRating[j] < minAverage){
					minAverage = averageRating[j];
					minNumber = j;
				}
			}
			averageRating[minNumber] = getMaxValue() * matrix.getRowLength(); //比較対象からはずす
			returnArray[i] = minNumber;
		}
		return returnArray;
	}

/**
* 各項目の有効カテゴリー数を求めた配列を返します。<BR>
* III型分析の際に利用します。
* @return 有効カテゴリー数が入った配列
*/
	private double[] getNonSortCategoryArray(){
		double[] returnArray = new double[matrix.getColLength()];
		ArithmeticMatrix frequencyTable = new ArithmeticMatrix(getMaxValue(), getMaxValue());

		for (int i = 0; i < matrix.getColLength(); i++){		//有効カテゴリー数を求める
			double value = 0;
			frequencyTable.matrixCopy(getFrequencyMatrix(i,i));
			for (int j = 0; j < getMaxValue(); j++){
				value = (frequencyTable.getCell(j,j) / matrix.getRowLength())
				* (frequencyTable.getCell(j,j) / matrix.getRowLength()) + value;
			}
			returnArray[i] = 1 / value;
		}
		return returnArray;
	}

/**
* 項目をグラフを描く順に並べ替えた項目番号の配列を返します。<BR>
* III型分析の際に利用します。
* @return グラフを描く順に並べ換えた列番号（項目）が入った配列
*/
	private int[] getNonSortGraphArray(){
		int[] returnArray = new int[matrix.getColLength()];

		double[]  averageRating = new double[matrix.getColLength()];		//各項目の有効カテコリー値を格納する
		System.arraycopy(getGraphHeightArray(), 0, averageRating, 0, averageRating.length);
		for (int i = 0; i < averageRating.length; i++){
			double minAverage = averageRating[0];	//初期値
			int minNumber = 0;
			for (int j = 1; j <  averageRating.length; j++){  //比較を行う
				if(averageRating[j] < minAverage){
					minAverage = averageRating[j];
					minNumber = j;
				}
			}
			averageRating[minNumber] = getMaxValue() * matrix.getRowLength(); //比較対象からはずす
			returnArray[i] = minNumber;
		}
		return returnArray;
	}

/**
* 分析を行う前のマトリクスを返します。
* @return 分析を行う前の元のマトリクス
*/
	public ArithmeticMatrix getMatrix(){
		return matrix;
	}

/**
* アンケートの型を返します。
* @return アンケートの型
*/
	public int getScaleType(){
		return scaleType;
	}

/**
* 評定の最大値を返します。
* @return 評定の最大値
*/
	public int getMaxValue(){
		return valueRating;
	}

/**
* しきい値を返します。
* @return しきい値
*/
	public double getThreshold(){
		return thresholdValue;
	}

/**
* SS分析の対象となるマトリクスを設定します。
* @param baseMatrix 設定する分析対象のマトリクス
* @see #setElement(int row, int col, int value)
*/
	public void setMatrix(ArithmeticMatrix baseMatrix){
		matrix = new ArithmeticMatrix(baseMatrix.getRowLength(), baseMatrix.getColLength());
		matrix.matrixCopy(baseMatrix);		//マトリクスの設定
	}

/**
* SS分析の対象となるマトリクスの要素を修正します。
* @param row 修正する要素の行
* @param col 修正する要素の列
* @param value 修正値
* @exception NotElementException 指定した要素が存在しない場合
* @see #setMatrix(ArithmeticMatrix baseMatrix)
*/
	public void setElement(int row, int col, int value){
		if (matrix.isMatrixEntityPoint(row, col)){
			matrix.setCell(row, col, value);
		}
		else{
			throw new NotElementException("Point(" + row + "," + col + ")");
		}
	}
	
/**
* しきい値を設定します。<BR>
* しきい値は0から1までの間で設定します。
* @param threshold 設定するしきい値
* @exception SetValueOutOfBoundsException しきい値が設定できる範囲外の場合
*/
	public void setThreshold(double threshold){
		if(isThreshold(threshold)){
			thresholdValue = threshold;
		}
		else{		//エラーの場合
			throw new SetValueOutOfBoundsException("Threshold(" + threshold + ")");
		}
	}


/**
* アンケートの型を設定します。<BR>
* アンケートの型は 1 、 2 、 3 のいずれかで設定します。
* @param scale 設定するアンケートの型
* @exception SetValueOutOfBoundsException アンケートの型が不正である場合
*/
	private void setScale(int scale){
		if (isScale(scale)){
			scaleType = scale;
		}
		else{		//エラーの場合
			throw new SetValueOutOfBoundsException("scale(" + scale + ")");
		}
	}

/**
* 評定の最大値を設定します。<BR>
* 設定する値よりも分析対象となる元のマトリクスの要素にある最大値の方が大きい場合は最大値を設定します。<BR>
* その際最大値が実数である場合は、小数点以下を切り上げ整数にします。
* @param rating 設定する評定の最大値
*/
	private void setRating(int rating){
		if (isRating(rating)){
			valueRating = rating;
		}
		else{		//エラーの場合
			valueRating = (int)Math.ceil(matrix.getMaxCell());
		}
	}

/**
* アンケートの型が正しいかチェックします。
* @param checkScale チェックするアンケートの型
* @return アンケートの型が正常であればtrueを、範囲外であればfalseを返します
*/
	private boolean isScale(int checkScale){
		return ((checkScale == SSANALYSIS_SCALE_TYPE_ASCENDING) ||
			(checkScale == SSANALYSIS_SCALE_TYPE_MIDDLE) ||
		(checkScale == SSANALYSIS_SCALE_TYPE_NONSORT));
	}

/**
* しきい値が正しい範囲内かチェックします。
* @param checkThreshold チェックするしきい値
* @return しきい値が範囲内であればtrueを、範囲外であればfalseを返します
*/
	private boolean isThreshold(double checkThreshold){
		return ((0 <= checkThreshold) && (checkThreshold <= 1));
	}

/**
* 評定の最大値が分析を行うマトリクスの要素の最大値より大きいかチェックします。
* @param checkRating チェックするしきい値
* @return 評定の最大値の方が大きければtrueを、小さければfalseを返します
*/
	private boolean isRating(int checkRating){
		return (matrix.getMaxCell() <= checkRating);
	}

}