/*------------------------------------------------------------------------------*
 * File Name: StatsOpBase.h														*
 * Creation: 																    *
 * Purpose: 																	*
 * Copyright (c) OriginLab Corp.2004											*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Forest 02/04/05 ADD_WEIGHT_TO_STATS_QUANTILES								*
 * Echo 3/22/05 v8.0207 QA70-6204 ADD_GSD										*
 * Iris 3/22/05 UPDATE_COLUMN_LABEL_FOR_GROUP_DATA								*
 * Iris 3/22/05 UPDATE_VARIANCE_TABLE_LABEL										*
 * Iris 3/22/05 FIX_GROUP_DATA_ONLY_ONE_BOX_CHART								*
 *	ML 4/14/2005 PROPER_LABELS_WITH_FACTORS										*
 *	CPY 4/22/05 QA70-7651 DESC_STATS_ON_ROWS_CLEAN								*
 *  Iris 5/20/05 QA70-6367 DESC_STATS_APPEAR_QUANTILES_RESULT					*
 *	Liko 08/22/2005 PLOT_HISTOGRAM_POSITION_CHANGE								*
 *	Kevin 09/01/05 CHANGE_STATISTICS_NAME										*
 *  Iris 9/06/05 QA70-7099-P7 SET_BINWKS_TABLE_HIDDEN							*
 *  Iris 9/09/05 QA70-7074-P6 REMOVE_GROUPING_DATA_OPTION						*
 *  Iris 9/09/05 KEEP_CUSTOM_PERCENTS_ORDER										*
 *  Iris 9/29/05 ANOVA_NEED_REMOVE_NANUM										*
 *  Iris 10/21/05 CLEANUP_STATS_REPORT_GRAPH_CODES								*
 *	ML 10/24/2005 ANOVAS_INDEXED_RAW											*
 *	ML 10/26/2005 QA70-8225 ESCAPED_OPER_STRINGS_ANOVAS							*
 *  Iris 11/18/05 QA70-7112-P2 INTERPOLATE_ALWAYS_BE_0_FOR_ORIGIN				*
 *  Iris 11/18/05 CONVENTION_NAME_OF_P_VALUE									*
 *  Jim 01/17/06 CREATE_PLOTS_BRANCH_IN_MAIN_NODES								*
 *  Iris 2/22/06 FOOTNOTE_REPLACE_WITH_WARN_LABEL								*
 *  Thomas 3/13/06 REPLACE_DATALABLE_WITH_FACTOR								*
 *  Jim 3/15/06 ADD_TABLE_FOOTNOTE	                                            *
 *  Alex 04/11/06 GET_COLNAME_OF_FACTOR_TO_LAST_BRANCH_OF_TOWWAYRMANOVA         *
 *	Iris 4/19/06 NEED_INCLUDE_NANUM_FOR_ANOVA									*
 *	Echo 5/30/06 DESC_STATS_CHANGE_FOR_EFFICIENCY								*
 *	Thomas 6/1/06 MOVE_ADDONEROWTOINPUTDATATABLE_FROM_ANOVAREPORTOPERATION_TO_STATSOPBASE	*
 *  Alex 06/05/06 MODIFY_DEFAULTGUI_CLOSE_PLOTS_BRANCH                          *
 *	ML 8/16/2006 CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG				*
 *	///Echo 8/22/06 USE_STANDARD_NAME											*
 *	Arvin 10/11/06 STATS_ON_COL_HISTOGRAM_PLOT									*
 * 	Arvin 10/17/06 PCH_CAN_NOT_USE_STATIC_VECTOR								*
 * 	Arvin 10/23/06 FITTING_RESIDUALS_HISTOGRAM_PLOT_CENTRALIZED					*
 *	Arvin 23/03/07 HISTOGRAM_AND_BOX_CHART_PLOT_WRONG_IN_STATSONCOLUMN_AND_NORMALITY_TEST
 *	Arvin 03/29/07 v8.0592 CAN_NOT_PLOT_MULTI_HISTOGRAMS_FOR_MULTI_DATASET		*
 *	Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
 *	Cheney 2007-5-23 QA70-9805 SPEED_UP_STATISTIC_ON_ROW						*
 *	Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS	*
 *	Arvin 06/21/07 v8.0646 WRONG_NUMBER_BOX_CHART_PLOT							*
 *  Arvin 07/25/07 v8.0667 WRONG_INPUT_DATA_TABLE_FOR_MULTI_DATA_AND_FACTORS	*
 *	Arvin 08/14/07 v8.0681 WRONG_MAX_AND_MIN_INDEX_IN_QUANTILES_WHEN_DATA_HAS_FACTORS
 *	Arvin 08/14/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
 *	Arvin 09/07/07 SHOULD_NOT_SHOW_INTERACTION_RESULT_WHILE_UNCHECK_AFTER_CHANGE_PARAM
 *	YuI 09/10/07 QA70-10358 ANOVA_RECALCULATE_FAILS_AFTER_RENAME				*
 *	Arvin 09/26/07 QA70-10421 WRONG_REPEAT_FACTOR_IN_REPORT_TABLE				*
 *	Arvin 09/26/07 ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS						*
 *	Arvin 09/29/07 GET_WRONG_VALUE_WHILE_UNCHECK_INTERACTION					*
 *	Max 10/09/07 QA70-10491 USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION			*
 *	Arvin 10/16/07 USER_SETTED_PERCENTILES_SHOULD_NOT_EFFECT_HISTOGRAM_AND_BOX_CHART_GRAPHS as max said
 *	Arvin 10/17/07 CLEAN_ANOVA_TOOLS_CODE										*
 *	Hong 10/24/07 v8.0732 LOCALISED_REPORTTREE_ISSUE							*
 *	Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS									*
 *	Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE								*
 *	Arvin 11/10/07 XOP_NEED_SUPPORT_CHANGE_FUNCTION								*
 *	Max 07-11-13 REPLACE_IN_XF_AND_NOT_USED										*
 *	Arvin 11/16/07 QA70-10669 IMPROVE_TABLES_ROW_LABELS_FOR_ANOVA_TOOLS			*
 *	Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO*
 *	ML 11/20/2007 QA70-10716 INPUT_DATA_NODE_PROPER_LANGUAGE_WHEN_LOADING_OPER	*
 *	Arvin 01/07/08 QA70-10903 ADD_CHECK_ALL_BOX_FOR_BRANCH						*
 *	Arvin 01/28/07 SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER	*
 *	Arvin  01/31/08 ANOVA_REPORT_DATA_SHOULD_NOT_OUTPUT_TO_SOURCE				*
 *	Arvin  01/31/08 WRONG_REPORT_DATA_LABEL_IN_ANOVA							*
 *	Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
 *  Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet*
 *  Iris 3/20/2008 v8.0828 QA80-11282-P2 NO_SELECTED_SHOULD_NOT_OUTPUT_PLOT_DATA*
 *  Iris 3/20/2008 v8.0828 QA80-11676-P2 BETTER_LEGEND_FOR_MEAN_COMP_PLOT		*
 *  Iris 3/20/2008 v8.0828 QA80-11676-P1 MEANS_COMP_PLOT_NEED_SMYBOL_INDEXED_BY_SIG_COL*
 *	TD ML 05-30-2008 QA80-11622 UPDATING_ANOVA_HANDLERS_ON_RECALCULATE_FROM_OPJ	*
 *	YuI 06/06/08 QA70-11619 MORE_CLEAR_WORKSHEET_PROBLEM						*
 *	ML 6/16/2008 MULTIFACTOR_OP_ESCAPED_STRING									*
 *	Hong 08/12/08 QA80-11986 FIX_FITTED_CURVE_PLOT_FAIL_RESCALE_WHEN_SOURCE_PLOT_HAVE_ERR_BAR
 *	Sim 09-03-2008 QA80-12137 NEW_OPERATION_MECHANISM							*
 *	Sophy 12/5/2008 v8.0982d IMPROVE_GIVE_A_REASONABLE_COLUMN_LONG_NAME_FOR_PLOT_DATA_OF_STATS_ON_COLUMN
 *	Sophy 12/17/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
 *	YuI 12/18/08 QA70-12800 PD_DIALOG_TO_CONTROL_HISTOGRAM_CREATED_BY_OPERATION	*
 *	Kyle 01/05/2009 QA80-12676-P1 MEANS_COMP_PLOT_SET_COLOR_MAP_ON_SIG			*
 *	Folger 01/21/09 RESET_ALL_GRAPHS_FAILS_TO_PLOT_HISTOGRAM_IN_NLFIT			*
 *	YuI 02/20/09 QA70-13152 PROPER_OPERATION_AUTO_BIN_INITIALIZATION_FOR_DATA_WITH_GROUPS*
 *	Sophy 2/24/2009 v8.0985 QA80-13152 AUTO_BIN_FOR_DATA_SHOULD_IGNORE_GROUP_AND_WEIGHT_DATA
 *  Iris 2/25/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE			*
 *  Iris 3/02/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE		*
 *	Sophy 3/2/2009 v8.0989b FIX_OLD_STATS_OPJ_SHOW_WRONG_ERR_MSG_WHEN_CHANGE_PARAMS_IN_SR5
 *	Sophy 3/3/2009 v8.0990 QA80-13152 AUTO_BIN_FOR_DATA_SHOULD_IGNORE_GROUP_AND_WEIGHT_DATA
 *	Iris 3/20/2009 QA80-13321 ANOVA_BAR_CHART_INDEX_DATA_SHOULD_USE_FACTOR_STR	*
 *  Iris 3/23/2009 QA80-13285-P6 CLEAN_ANOVE_REPORT_DATA_LABEL					*
 *	Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
 *	YuI 04/01/09 QSA70-13389 BINNING_IS_WRONG_IN_REPORT_HISTOGRAM_FROM_SR4_TO_SR5*
 *  Iris 4/02/2009 QA80-13392-P2 IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE	*
 *	Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE	*
 *	YuI 04/06/09 QA70-12784-P1 HISTOGRAM_CREATE_BY_OPERATION_PROBLEMS			*
 *  Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH					*
 *  Iris 4/09/2009 QA80-12784-P1 FIX_SR4_ANOVA1WAY_REPORT_FAIL_CHANGE_PARAM_IN_SR5
 *  Iris 4/13/2009 QA80-13392-P2 FIX_INPUT_TABLE_ANOVA2WAY_RM_REPEAT_WITH_NOT_REPEAT
 *  Iris 04/20/09 QA80-12574-P1 RESET_ALL_GRAPHS_FAILS_TO_PLOT_RESIDUAL_HISTOGRAM_IN_SR4_OPJ
 *  Iris 4/28/2009 QA80-12784-P3 FIX_HITOGRAM_BIN_INFO_NOT_UPDATE_WHEN_DATA_CHANGE
 *  Iris 4/28/2009 QA80-12784-P4 FIX_HITOGRAM_BIN_INFO_NOT_UPDATE_WHEN_CHANGE_DATA_MODE
 *  Iris 5/19/2009 FAIL_REPORT_MEAN_COMP_CURVE_DATA_IN_JOS						*
 *	Sophy 2/26/2009 MORE_REASONABLE_LEGEND_FOR_REPORT_GRAPH_WHEN_MULTIPLE_GROUPS_EXIST_IN_STATS_ON_COLUMN
 *	Sim 06-18-2009 QA80-13403-P1 FIX_HISTOGRAMS_BIN_SETTINGS_ERROR_WHEN_LOAD_SR4_OPJ
 *	YuI 08/14/09 QA70-14138 REDUCE_STATS_TREE_SIZE_IN_SERIES_STORAGE			*
 *  Iris 10/19/2009 QA80-11710-P4 SHOULD_SHOW_ERR_REPORT_TO_CB_OUTPUT_WND		*
 *  Iris 10/26/2009 FIX_FIT_LINEAR_PLOT_RESIDUAL_HISTOGRAM_IN_ONE_LAYER			*
 *  Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED			*
 *  Iris 12/04/2009 QA81-12784-P6&P8 FIX_NOT_CORRECTLY_UPDATE_BINNING_INFO_BUG	*
 *  Iris 12/17/2009 QA81-12784-P8 FIX_CHANGE_PARAM_AUTO_BIN_BUG					*
 *  Iris 4/09/2010 QA81-15296 FIX_INCORRECT_INPUTDATA_GUI_FOR_XOP_ONE_WAY_ANOVA	*
 *	Folger 10/12/2010 ORG-1240-P2 MULTIPLE_GROUPING_DATA_WRONG_FOR_STATS_ON_COLUMN_REPORT
 *------------------------------------------------------------------------------*/

#ifndef _STATS_OPBASE_H
#define _STATS_OPBASE_H

///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
#ifndef _OCUTILSEX_H
#include <ocu.h>
#endif 

#ifndef _OK_OC_UTILS_H
#include <okocUtils.h>
#endif 
///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS

//------ Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE
#define STR_CAT_STATS "Statistics"
//------ End CATEGORY_NEEDED_WHEN_LOCALIZE

/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
#define	STAT_HISTOGRAM_REPORT_LABEL			_L("Histograms")
#define	STAT_BOXCHART_REPORT_LABEL			_L("Box Charts")
///Sophy 12/17/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
#define	STR_OUTPUT_HISTOGRAM_PLOT_CONFIG				_L("Histogram Configuration")
#define	STR_OUTPUT_HISTOGRAM_PLOT_AUTO_BINNING			_L("Automatic Binning")
#define	STR_OUTPUT_HISTOGRAM_PLOT_BIN_SIZE				_L("Bin Size")
#define	STR_OUTPUT_HISTOGRAM_PLOT_BEGIN					_L("Begin")
#define	STR_OUTPUT_HISTOGRAM_PLOT_END					_L("End")
#define	STR_OUTPUT_HISTOGRAM_NUM_OF_BINS				_L("Number of Bins")

#define	STR_HISTOGRAM_CONFIG_TAGNAME		"HistogramConfig"
#define	STR_HISTOGRAM_NUM_OF_BINS_TAG_NAME	"NumOfBins"
///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS

#define TABLE_DESC_STATS					"Statistics"

///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
#define	STR_STAT_HISTOGRAM_REPORT_TABLE			"Histogram"
#define	STR_STAT_BOXCHART_REPORT_TABLE			"BoxChart"
///END WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS

///Sophy 8/12/2008 QA80-12000-S2 DEFAULT_TURN_OFF_REPORT_MISSING_DATA_FOR_STATS_TOOL
#define	STR_FOOTNOTE_HAS_MISSING_VALUE	"There exist missing values in the input data."
#define	STR_FOOTNOTE_HAS_MASKED_VALUE	"There exist masked values in the input data."
///end DEFAULT_TURN_OFF_REPORT_MISSING_DATA_FOR_STATS_TOOL

///Arvin 10/17/06 PCH_CAN_NOT_USE_STATIC_VECTOR
/*
static vector l_vPercents = {1, 5, 10, 25, 50, 75, 90, 95, 99};
static vector l_vPercentilePosition = 
{
	PDSP_PERC_1,
	PDSP_PERC_5,
	PDSP_PERC_10,
	PDSP_PERC_25,
	PDSP_PERC_50,
	PDSP_PERC_75,
	PDSP_PERC_90,
	PDSP_PERC_95,
	PDSP_PERC_99
};
*/
///end  PCH_CAN_NOT_USE_STATIC_VECTOR
/// end PICTURE_IN_REPORT_IMPROVEMENT

/// Iris 10/21/05 CLEANUP_STATS_REPORT_GRAPH_CODES
enum
{
	GRAPH_STATS_HISTOGRAM = 0,
	GRAPH_STATS_BOX,
	
	GRAPH_STATS_MAX_SIZE
};
///End CLEANUP_STATS_REPORT_GRAPH_CODES



#define IDST_TEMP_PERCENTILES_ONE_SET	2000	


///Sophy 12/17/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
static int _check_histogram_plot_bin_configuration(TreeNode trGUI, string& strErr)
{
	/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
	//TreeNode trHistogramConfig = trGUI.Output.GetNode(STR_HISTOGRAM_CONFIG_TAGNAME);
	//TreeNode trHistogramPlot;
	//if ( trGUI.Plots )
	//	trHistogramPlot = trGUI.Plots.FindNodeByAttribute(STR_LABEL_ATTRIB, STAT_HISTOGRAM_REPORT_LABEL);
	//if ( trHistogramPlot && tree_is_true(trHistogramPlot) && trHistogramConfig )
	/// Iris 10/29/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
	//TreeNode trHistogramConfig = trGUI.Plots.Graph1;
	TreeNode trHistogramConfig = OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(trGUI).Graph1;
	///end OP_DLG_NEW_STRUCTURE
	if( trGUI.Plots && trGUI.Plots.Show && trHistogramConfig && trHistogramConfig.Show && tree_is_true(trHistogramConfig) && !trHistogramConfig.AutoBin.nVal )
	///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
	{
		double dMin = trHistogramConfig.Begin.dVal;
		double dMax = trHistogramConfig.End.dVal;
		if ( !check_min_max(dMin, dMax) )
			return CER_MIN_MAX;
		
		double dBinSize = trHistogramConfig.BinSize.dVal;
		if ( dBinSize <= 0 || is_missing_value(dBinSize) )
		{
			strErr = "BinSize";
			return CER_MUST_LARGE_THAN_0;
		}
	}
	return CER_NO_ERROR;
}

/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
/*
static bool _operation_histogram_plot_changed(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg)
{
	bool		bEnable = tree_is_true(trNode);
	TreeNode trHistogramConfig = tree_get_node_by_tagname(tr.Output, STR_HISTOGRAM_CONFIG_TAGNAME, true);
	if ( trHistogramConfig )
	{
		trHistogramConfig.Enable = bEnable;		
	}
	
	return true;
}
*/

static void _update_histogram_bin_info_in_event1(TreeNode& tr, LPCSTR lpcszNodeName, int nEvent)
{
	/// Iris 4/16/2009 FIX_RUNTIME_ERR_IN_STATS_ON_COLS_WITH_THEME
	// lpcszNodeName is NULL when do stats on columns with theme without dialog
	if(NULL == lpcszNodeName || !tr)
		return;
	///END FIX_RUNTIME_ERR_IN_STATS_ON_COLS_WITH_THEME
		
	if( 0 == strcmp(lpcszNodeName, "AutoBin") || 0 == strcmp(lpcszNodeName, "Graph1") 
		|| 0 == strcmp(lpcszNodeName, "X") || 0 == strcmp(lpcszNodeName, "F") /// Iris 4/28/2009 QA80-12784-P3 FIX_HITOGRAM_BIN_INFO_NOT_UPDATE_WHEN_DATA_CHANGE
		|| 0 == strcmp(lpcszNodeName, "InputData") /// Iris 4/28/2009 QA80-12784-P4 FIX_HITOGRAM_BIN_INFO_NOT_UPDATE_WHEN_CHANGE_DATA_MODE
		|| GETNE_ON_INIT == nEvent || GETNE_ON_THEME == nEvent)
	{
		/// Iris 10/29/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
		//TreeNode trHistogram = tr.Plots.Graph1;	
		TreeNode trHistogram = OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(tr).Graph1;
		///end OP_DLG_NEW_STRUCTURE
		if( tr.Plots && tr.Plots.Show && trHistogram && trHistogram.Show )
		{
			/// Iris 12/17/2009 QA81-12784-P8 FIX_CHANGE_PARAM_AUTO_BIN_BUG
			//_update_histogram_plot_bin_configuration_by_input(tr, trHistogram, GETNE_ON_THEME == nEvent);
			_update_histogram_plot_bin_configuration_by_input(tr, trHistogram, GETNE_ON_THEME == nEvent, nEvent);
			///End FIX_CHANGE_PARAM_AUTO_BIN_BUG
		
			_on_histogram_auto_binning_changed(trHistogram, trHistogram.AutoBin);
		}
	}
}
///end IMPROVE_HISTOGRAM_CONFIG_BRANCH


///Sophy 12/19/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS fix bin config not updated when change input data
/// Iris 12/17/2009 QA81-12784-P8 FIX_CHANGE_PARAM_AUTO_BIN_BUG
//static bool _update_histogram_plot_bin_configuration_by_input(TreeNode& trGUI, TreeNode& trHistogramConfig, bool bFromTheme = false)
static bool _update_histogram_plot_bin_configuration_by_input(TreeNode& trGUI, TreeNode& trHistogramConfig, bool bFromTheme = false, int nEvent = 0)
///End FIX_CHANGE_PARAM_AUTO_BIN_BUG
{
	/// Iris 10/29/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
	//if ( !trGUI || !trHistogramConfig || trGUI.Plots && !trGUI.Plots.Show || !trHistogramConfig.Show )
	if ( !trGUI || !trHistogramConfig || OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(trGUI) && !OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(trGUI).Show || !trHistogramConfig.Show )
	///end OP_DLG_NEW_STRUCTURE
		return false;
	
	//Get Input Data Begin
	pfn_get_input_output_node pfn = Project.FindFunction("get_inputdata_node", "OriginLab\\wksoperation.c", TRUE);
	if ( !pfn )
		return false;
		
	TreeNode trInput = pfn(trGUI);
	if ( !trInput )
	{
		ASSERT(FALSE);
		return false;
	}
	DataRange drInput;
	drInput.Create();
	drInput.SetTree(trInput);
	if ( !drInput )
		return false;
	
	vector 	vData;
	int		nDataRules;
	string	strDescript;

	/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
	//nDataRules = DRR_NO_FACTORS;///Sophy 3/4/2009 auto binning should ignore factor to get all data of the first dataset, no need to get original datarules here.
	//drInput.GetData(nDataRules, 0, NULL, &strDescript, &vData);	
	if( !trInput.GetAttribute(STR_DATA_RULES_ATTRIB, nDataRules) )
		nDataRules = DRR_NO_FACTORS;
	/// Iris 4/28/2009 QA80-12784-P4 FIX_HITOGRAM_BIN_INFO_NOT_UPDATE_WHEN_CHANGE_DATA_MODE
	//int nNumData = drInput.GetNumData(nDataRules);
	DWORD dwRules = nDataRules;
	tree_oper_multidata_mode_update_rules(dwRules, trGUI);
	int nNumData = drInput.GetNumData(dwRules);
	///end FIX_HITOGRAM_BIN_INFO_NOT_UPDATE_WHEN_CHANGE_DATA_MODE
	
	vector vMin, vMax, vBinSize, vBinCount, vAllData;
	for(int ii = 0; ii < nNumData; ii++)
	///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
	{
		drInput.GetData(dwRules, ii, NULL, &strDescript, &vData);
		vAllData.Append(vData);
		
		double dMin, dMax, dBinSize;
		vData.GetMinMax(dMin, dMax);
		RoundBinningRange(&dMin, &dMax, vData.GetSize(), LINEAR_SPACE, &dBinSize);
		
		/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
		/*
		trHistogramConfig.Begin.dVal = dMin;
		trHistogramConfig.End.dVal = dMax;
		trHistogramConfig.BinSize.dVal = dBinSize;
		if ( dBinSize <= 0 )
		{
			ASSERT(FALSE);
			return false;
		}
		trHistogramConfig.NumOfBins.nVal = ceil((dMax - dMin)/dBinSize);
		*/
		vMin.Add(dMin);
		vMax.Add(dMax);
		vBinSize.Add(dBinSize);
		double dBinCount = ceil((dMax - dMin)/dBinSize);
		vBinCount.Add(dBinCount);
		///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
	}
	
	/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
	if( trHistogramConfig.AutoBin && trHistogramConfig.AutoBin.nVal )
	{
		vector<string> vsMin, vsMax, vsBinSize, vsBinCount;
		convert_double_vector_to_string_vector(vMin, vsMin, vMin.GetSize());
		convert_double_vector_to_string_vector(vMax, vsMax, vMax.GetSize());
		convert_double_vector_to_string_vector(vBinSize, vsBinSize, vBinSize.GetSize());
		convert_double_vector_to_string_vector(vBinCount, vsBinCount, vBinCount.GetSize());
		
		int nDisplayNum = 3;
		string strSep = ", ";
		trHistogramConfig.Begin.strVal = get_display_string(vsMin, nDisplayNum, strSep);
		trHistogramConfig.End.strVal = get_display_string(vsMax, nDisplayNum, strSep);
		trHistogramConfig.BinSize.strVal = get_display_string(vsBinSize, nDisplayNum, strSep);
		trHistogramConfig.NumOfBins.strVal = get_display_string(vsBinCount, nDisplayNum, strSep);
	}
	else
	{
		/// Iris 12/04/2009 QA81-12784-P6&P8 FIX_NOT_CORRECTLY_UPDATE_BINNING_INFO_BUG
		int nExecMode;
		bool bRet = trGUI.GetAttribute(STR_EXEC_MODE_ATTRIB, nExecMode);
		ASSERT(bRet);
		/// Iris 12/17/2009 QA81-12784-P8 FIX_CHANGE_PARAM_AUTO_BIN_BUG
		//if( bRet && OEXEM_ON_CHANGEPARAM == nExecMode )
		if( bRet && OEXEM_ON_CHANGEPARAM == nExecMode && GETNE_ON_INIT == nEvent )
		///End FIX_CHANGE_PARAM_AUTO_BIN_BUG
		{
			// do nothing...
			// Change parameter moment, should keep the bin settings if Auto Bin is unchecked
		}
		else
		{
		///end FIX_NOT_CORRECTLY_UPDATE_BINNING_INFO_BUG
			if(!bFromTheme) // if AutoBin is unchecked, should keep bin settings from theme
			{	
				double dMin, dMax, dBinSize;
				dMin = min(vAllData);
				dMax = max(vAllData);
				RoundBinningRange(&dMin, &dMax, vAllData.GetSize(), LINEAR_SPACE, &dBinSize);
				
				trHistogramConfig.Begin.strVal = ftoa( dMin );
				trHistogramConfig.End.strVal = ftoa( dMax );
				trHistogramConfig.BinSize.strVal = ftoa( dBinSize );
				double dBinCount = ceil((dMax - dMin)/dBinSize);
				trHistogramConfig.NumOfBins.strVal = ftoa( dBinCount );	
			}
		}
	}	
	///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
	
	return true;
}
///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS

/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
static void _on_histogram_auto_binning_changed(TreeNode& trHistogram, TreeNode& trAutoBin)
{
	if(!trHistogram || !trAutoBin)
		return;
	
	bool		bEnabled = tree_is_true(trHistogram);
	bool		bAutoChecked = tree_is_true(trAutoBin);
	trHistogram.Begin.Enable = bEnabled && !bAutoChecked;
	trHistogram.End.Enable = bEnabled && !bAutoChecked;
	trHistogram.BinSize.Enable = bEnabled && !bAutoChecked;	
}
///end IMPROVE_HISTOGRAM_CONFIG_BRANCH

static bool _operation_histogram_auto_binning_changed(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg)
{
	/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
	/*
	TreeNode	trHistogramConfig = trNode.Parent();
	bool		bEnabled = trHistogramConfig.Enable;
	
	bool		bAutoChecked = tree_is_true(trNode);
	if ( bEnabled && bAutoChecked )
	{
		///Sophy 12/19/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS fix bin config not updated when change input data
		_update_histogram_plot_bin_configuration_by_input(tr, trHistogramConfig);
		///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
	}
	
	if ( bEnabled )
	{
		trHistogramConfig.Begin.Enable = !bAutoChecked;
		trHistogramConfig.End.Enable = !bAutoChecked;
		trHistogramConfig.BinSize.Enable = !bAutoChecked;
	}
	*/
	if(!trNode)
		return false;
	
	TreeNode	trHistogram = trNode.Parent();
	_on_histogram_auto_binning_changed(trHistogram, trNode);
	///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
	
	return true;
}

static bool _operation_histogram_customized_binning_changed(TreeNode& tr, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg)
{
	if(!trNode)
		return false;
	
	TreeNode	trHistogramConfig = trNode.Parent();
	/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
	//bool		bEnabled = trHistogramConfig.Enable;
	bool		bEnabled = tree_is_true(trHistogramConfig);
	///emd IMPROVE_HISTOGRAM_CONFIG_BRANCH
	if ( !bEnabled )
		return false;
	
	/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
	if(trHistogramConfig.AutoBin && trHistogramConfig.AutoBin.nVal) // if AutoBin is true, the following settings will not used for histogram plot just for display, so no need check error
		return false;
	///emd IMPROVE_HISTOGRAM_CONFIG_BRANCH
	
	double dMin, dMax, dBinSize;	
	dMin = trHistogramConfig.Begin.dVal;
	dMax = trHistogramConfig.End.dVal;
	dBinSize = trHistogramConfig.BinSize.dVal;
	if ( dBinSize <= 0 || dMin >= dMax )
	{
		ASSERT(FALSE);
		return false;
	}
	trHistogramConfig.NumOfBins.nVal = ceil((dMax - dMin)/dBinSize);

	return true;
}
///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS

	
//////////////////////////////////////////////////////////////////////////////////
// Class StatsOpBase
//////////////////////////////////////////////////////////////////////////////////
#define VER_STATS_OP_BASE 2.0 ///---Sim 04-02-2009 QSA70-13389 BINNING_IS_WRONG_IN_REPORT_HISTOGRAM_FROM_SR4_TO_SR5
#define STR_OP_NAME_STATS_BASE "StatsOpBase"///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
///---Sim 09-03-2008 QA80-12137 NEW_OPERATION_MECHANISM
//class OC_REGISTERED StatsOpBase : public WksReportOperation
#ifdef _OPERATION_EX_
class OC_REGISTERED StatsOpBase : public OperationEx
#else
class OC_REGISTERED StatsOpBase : public WksReportOperation
#endif
///---END QA80-12137 NEW_OPERATION_MECHANISM
{
///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
public:
	StatsOpBase()
	{
		m_mvCur.AddVersion(STR_OP_NAME_STATS_BASE, VER_STATS_OP_BASE);
	}
///---END QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
protected:
	/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
	//virtual
	bool	IsPlotStatsGraph(TreeNode& trOp)
	{
		int nCount = 0;
		TreeNode trPlots = OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(trOp.GUI);
		if( trPlots )
		{			
			foreach(TreeNode trN in trPlots.Children)
				nCount += tree_is_true(trN);
		}
		return 0 != nCount;
	}
	
	TreeNode GetGUIGraphNodesEx(const TreeNode& trGUI, int nGraphIndex)
	{
		TreeNode trGraph = WksReportOperation::GetGUIGraphNodesEx(trGUI, nGraphIndex);
		if( trGraph )
			return trGraph;
		
		TreeNode trPlots = OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(trGUI);
		ASSERT(trPlots);
		
		if( trPlots )
			trGraph = trPlots.GetNode(op_get_graph_tag_name(nGraphIndex));
		return trGraph;
	}
	///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED

	/// Iris 10/21/05 CLEANUP_STATS_REPORT_GRAPH_CODES
	int	ReportGetPicureIndexFromDataIndex(int nGraphIndex, int nDataIndex)
	{
		switch( ReportGetPlotTypeFromGraphIndex(nGraphIndex) )
		{
		case IDM_PLOT_HISTOGRAM_TYPE:
			return nDataIndex;
			
		case IDM_PLOT_BOX:
			return nDataIndex;
		}
		
		return -1;
	}
	
	int	ReportGetPlotTypeFromGraphIndex(int nGraphIndex)
	{
		switch( nGraphIndex )
		{
		case GRAPH_STATS_HISTOGRAM:
			return IDM_PLOT_HISTOGRAM_TYPE;
			
		case GRAPH_STATS_BOX:
			return IDM_PLOT_BOX;
		}		
		return -1;
	}
	
	string		GetOneResultCurvesTableTagName(int nGraphIndex)
	{		
		string strTable;
		switch(nGraphIndex)
		{			
		case GRAPH_STATS_BOX:
			strTable = CALCULATION_BIN_DATA_TABLE;
		}
		return strTable;
	}
	///End CLEANUP_STATS_REPORT_GRAPH_CODES
	
	int	 GetOutputRangeIndex(TreeNode& trOp, int nGraphIndex)
	{		
		return OUTPUT_RESULT_CURVE_FIT_CURVES_SHEET;
	}
	
	/// Iris 02/03/2007 v8.0554 PLOT_ALL_BOX_CHART_IN_ONE_GRAPH
	//virtual 
	///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	//int	GetNumberLayersInOneGraph(TreeNode& trOp, int nGraphIndex)
	virtual int	GetNumberLayersInOneGraph(TreeNode& trOp, int nGraphIndex)
	///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	{
		///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
		//if(!IsPlotAllPlotsInOneGraph(trOp))
		if(!IsPlotAllPlotsInOneGraph(trOp, nGraphIndex))
		///end 	UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
			return 1;
		
		/// Iris 10/26/2009 FIX_FIT_LINEAR_PLOT_RESIDUAL_HISTOGRAM_IN_ONE_LAYER
		//if(GRAPH_STATS_BOX == nGraphIndex)
		if( IDM_PLOT_BOX == ReportGetPlotTypeFromGraphIndex(nGraphIndex) )
		///end FIX_FIT_LINEAR_PLOT_RESIDUAL_HISTOGRAM_IN_ONE_LAYER
			return 1;		
		
		/// Iris 10/26/2009 FIX_FIT_LINEAR_PLOT_RESIDUAL_HISTOGRAM_IN_ONE_LAYER
		//if(GRAPH_STATS_HISTOGRAM == nGraphIndex)
		if( IDM_PLOT_HISTOGRAM_TYPE == ReportGetPlotTypeFromGraphIndex(nGraphIndex) )
		///end FIX_FIT_LINEAR_PLOT_RESIDUAL_HISTOGRAM_IN_ONE_LAYER
		{	
			/// Iris 9/10/2009 QA80-11710-P2 IMPROVE_REPORT_GRAPH_WHEN_PLOT_IN_ONE_GRAPH_WITH_GROUPING_DATA
			//return GetTotalNumData(trOp);		
			return GetNumPlotsInOneGraph(trOp);
			///end IMPROVE_REPORT_GRAPH_WHEN_PLOT_IN_ONE_GRAPH_WITH_GROUPING_DATA
		}
		
		
	}
	///end PLOT_ALL_BOX_CHART_IN_ONE_GRAPH
	
	/// ML 11/20/2007 QA70-10716 INPUT_DATA_NODE_PROPER_LANGUAGE_WHEN_LOADING_OPER
	// virtual
	int		getLocUpdateInputDataStringsMode()
				{ return LUIDMODE_FIXED_STRUCTURE; }
	/// end INPUT_DATA_NODE_PROPER_LANGUAGE_WHEN_LOADING_OPER
	
	/// Iris 10/21/05 USE_DUPLICATE_PRECENT_NODE_IN_TEMP
	TreeNode 	CheckCreateTempPercentilesOneTable(TreeNode& trOp, int nDataIndex)
	{
		TreeNode trTable = tree_check_get_node(RESULT_CURVE_BRANCH(trOp), "Percentiles");
		trTable.Show = false; //hidden this table, but in fact, temp node should always be hidden already.		
		
		TreeNode trRow = check_add_enumerated_node(trTable, CALCULATION_REPORT_TABLE_COL_PREFIX, nDataIndex + 1, IDST_TEMP_PERCENTILES_ONE_SET);

		return trRow;
	}
	
	void 		CopyPercentilesToTemp(TreeNode& trOp, int nDataIndex)
	{
		TreeNode 	trStats = tree_check_get_node(trOp.Calculation, TABLE_DESC_STATS, IDST_DESC_STATS_RESULTS);		
		string 		strParameter = CALCULATION_REPORT_TABLE_COL_PREFIX + (nDataIndex+1);
		TreeNode 	trParameter = trStats.GetNode(strParameter);
		
		TreeNode trPercentilesDest = CheckCreateTempPercentilesOneTable(trOp, nDataIndex);
		TreeNodeCollection trCollection(trParameter, CALCULATION_PERCENTILE_PREFIX);
		foreach(TreeNode trPrec in trCollection)
		{
			TreeNode trSub = tree_check_get_node(trPercentilesDest, trPrec.tagName);
			trSub.Replace(trPrec);
		}
		
	}
	///End USE_DUPLICATE_PRECENT_NODE_IN_TEMP
	///Jim 01/17/06 v8.0358 CREATE_PLOTS_BRANCH_IN_MAIN_NODES	
	virtual void	FilterStatsGUI(TreeNode& trOp) 
	{
#ifndef OP_DLG_TOTALLY_NEW_STRUCTURE
		rebuildStatsGraphs(trOp);
		
		///Arvin 01/07/08 QA70-10903 ADD_CHECK_ALL_BOX_FOR_BRANCH
		TreeNode trOptionalReport = trOp.GUI.Output.Create;
		if(trOptionalReport)
			AddCheckAllBoxForOptionalReport(trOptionalReport);
		
		TreeNode trPlots = trOp.GUI.Plots;
		if(trPlots)
			AddCheckAllBoxForPlotsNode(trPlots);
		///END ADD_CHECK_ALL_BOX_FOR_BRANCH		
#endif //OP_DLG_TOTALLY_NEW_STRUCTURE
	}	
	///END CREATE_PLOTS_BRANCH_IN_MAIN_NODES
	
	/// Iris 11/16/06 CLEAR_OUT_TABLES_BEFORE_CALC_WHEN_DO_CHANGE_PARAMS
	//virtual
	///Arvin 11/10/07 XOP_NEED_SUPPORT_CHANGE_FUNCTION	
	//Need call this method from oc code, so move it to public session
	//void  ClearOutputTables(TreeNode& trOperation)
	//{
		//WksReportOperation::ClearOutputTables(trOperation);	
		//
		//bool		bKeepAttrib = true;
		//TreeNode 	trOut = trOperation.Calculation;
		/////Arvin 09/26/07 ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS
		////if(trOut.Statistics)
		////	trOut.Statistics.Reset(bKeepAttrib);	
		////if(trOut.ANOVAs)
		////	trOut.ANOVAs.Reset(bKeepAttrib);
		//if(trOut)
		//{
			//int bNotes = true;
			//foreach(TreeNode trSubNode in trOut.Children)
			//{
				//if(bNotes)
				//{
					//bNotes = false;
					//continue;
				//}
				//
				//if(trSubNode.GetNodeCount() > 0)
					//trSubNode.Reset(bKeepAttrib);
			//}
		//}
		/////end ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS
	//}
	///end XOP_NEED_SUPPORT_CHANGE_FUNCTION
	///end CLEAR_OUT_TABLES_BEFORE_CALC_WHEN_DO_CHANGE_PARAMS
	
	///Arvin 02/13/07 SET_BIN_DATA_WITH_SAME_MIN_MAX_AND_BINSIZE_WHEN_PLOT_ALL_HISTOGRAM_IN_ONE_GRAPH
	///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	//bool 	GetCombinedMinMaxAndBinNumber(TreeNode & trOp, double& dMin, double& dMax)
	virtual bool 	GetCombinedMinMaxAndBinNumber(TreeNode & trOp, double& dMin, double& dMax)
	///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	{
		DataRange dr;
		if(!GetInput(dr))
			return error_report("Fail to get input data.");
		
		vector	vCombinedData;
		//nBins = 0;
		for(int ii = 0; ii < GetTotalNumData(trOp); ii++)
		{
			DWORD	dwPlotUID;
			vector	vData;
			vector	vW;
			dr.GetData(GetDataRules(trOp), ii, &dwPlotUID, NULL, &vData, NULL, NULL, NULL, &vW);
			//int nTemp = 0.5 + sqrt(vData.GetSize() + 1);
			//nBins = nTemp > nBins ? nTemp : nBins;
			vCombinedData.Append(vData);
		}
		
		vCombinedData.GetMinMax(dMin, dMax);
		return true;
	}
	///end SET_BIN_DATA_WITH_SAME_MIN_MAX_AND_BINSIZE_WHEN_PLOT_ALL_HISTOGRAM_IN_ONE_GRAPH
	
	///Arvin 08/17/07 ADD_WEIGHT_DATA_TABLE_IN_INPUT_DATA_TABLE
	virtual bool IsDatasetHasWeight(TreeNode& trInput, int nIndex = 0, string& strWeight = NULL)
	{
		return false;
	}
	
	bool CheckAddWeightInfoRowForInputTable(const TreeNode& trInputData, TreeNode& trRow, int index = 0, LPCSTR lpcszTageName = NULL, LPCSTR lpcszRowLabel = NULL)
	{
		string strWeight;
		if(IsDatasetHasWeight(trInputData, index, strWeight))
		{
			if(!trRow.IsValid())
				return false;
			
			string strTageName(lpcszTageName), strRowLabel(lpcszRowLabel);
			if(strTageName.IsEmpty())
				strTageName = _L("W");
			if(strRowLabel.IsEmpty())
				strRowLabel = WKSH_OPERATION_INFO_WEIGHT_DATA_SOURCE;
			
			//When weight method is No Weighting or Direct Weighting, the Weight data string gotten by report_get_escaped_data_string
			//in AddOneInputDataTableCell can not be coverted to a valid rang string, so I use input string directly. 
			//AddOneInputDataTableCell(trRow, WKSH_OPERATION_INFO_WEIGHT_DATA_SOURCE, indexLT, FALSE, 'P', 'W');
			TreeNode	trCol = tree_check_get_node(trRow, strTageName, IDE_INPUT_WEIGHT,  STR_LABEL_ATTRIB, strRowLabel);
			if(trCol)
				trCol.strVal = strWeight;
			
			return true;
		}
		
		return false;
	}		
	///end ADD_WEIGHT_DATA_TABLE_IN_INPUT_DATA_TABLE
	
	///Arvin 07/25/07 v8.0667 WRONG_INPUT_DATA_TABLE_FOR_MULTI_DATA_AND_FACTORS
	void AddMultiInputDataWithFactorSourceTable(TreeNode& trOp, LPCSTR lpcszDataLabel = NULL, LPCSTR lpcszFactorLabel = NULL,  DWORD dwRules = 0) 
	{
		TreeNode trInputTable = trOp.Calculation.Input;
		DataRange dr;
		GetInput(dr);
		vector<int> vFactorSizes;
		int nNumData = dr.GetNumData(dwRules, NULL, NULL, &vFactorSizes);
		dwRules |= DRR_NO_FACTORS;
		int nFactNumDataCol = dr.GetNumData(dwRules);
		string strDataLabel(lpcszDataLabel), strFactorLabel(lpcszFactorLabel);
		if(strDataLabel.IsEmpty())
			strDataLabel= _L("Data");
		if(strFactorLabel.IsEmpty())
			strFactorLabel = _L("Factors");
		string strRange = _L("Range");
		
		int indexLT = 0;
		///Arvin 08/17/07 ADD_WEIGHT_DATA_TABLE_IN_INPUT_DATA_TABLE
		TreeNode trInputData = trOp.GUI.InputData;
		///end ADD_WEIGHT_DATA_TABLE_IN_INPUT_DATA_TABLE
		for(int ii = 0; ii < nFactNumDataCol; ii++)
		{
			indexLT++;
			TreeNode	trRow = check_add_enumerated_node(trInputTable, "C", indexLT, make_one_set_ID(IDST_REPORT_INPUT_ONE_SET, indexLT), STR_LABEL_ATTRIB, strDataLabel);
			AddOneInputDataTableCell(trRow, strDataLabel, ii+1, FALSE, 'P', 0, 'D');		// Data
			AddOneInputDataTableCell(trRow, strRange, ii+1, FALSE, 'G', 'R', 'D');		// Range
			///Arvin 08/17/07 ADD_WEIGHT_DATA_TABLE_IN_INPUT_DATA_TABLE
			CheckAddWeightInfoRowForInputTable(trInputData, trRow, ii);
			///end ADD_WEIGHT_DATA_TABLE_IN_INPUT_DATA_TABLE
		}
			
		for(ii = 0; ii < vFactorSizes.GetSize(); ii++)
		{
			indexLT++;
			TreeNode	trRow = check_add_enumerated_node(trInputTable, "C", indexLT, make_one_set_ID(IDST_REPORT_INPUT_ONE_SET, indexLT), STR_LABEL_ATTRIB, strFactorLabel);
			
			///------ Folger 10/12/2010 ORG-1240-P2 MULTIPLE_GROUPING_DATA_WRONG_FOR_STATS_ON_COLUMN_REPORT
			//AddOneInputDataTableCell(trRow, strFactorLabel, 1, FALSE, 'P', 0, 'F');		
			//AddOneInputDataTableCell(trRow, strRange, 1, FALSE, 'G', 'R', 'F');
			AddOneInputDataTableCell(trRow, strFactorLabel, ii + 1, FALSE, 'P', 0, 'F');		
			AddOneInputDataTableCell(trRow, strRange, ii + 1, FALSE, 'G', 'R', 'F');
			///------ End MULTIPLE_GROUPING_DATA_WRONG_FOR_STATS_ON_COLUMN_REPORT
		}
		
	}
	///END WRONG_INPUT_DATA_TABLE_FOR_MULTI_DATA
	
	/// Iris 04/20/09 QA80-12574-P1 RESET_ALL_GRAPHS_FAILS_TO_PLOT_RESIDUAL_HISTOGRAM_IN_SR4_OPJ
	bool CalcAddStatsHistPlotData(TreeNode& trOp, int index, const vector& vResidual, const vector& vWeights, const vector<string>& vstrFactors, LPCSTR lpcszDataLabel)
	{
		double dMin, dMax;
		vResidual.GetMinMax(dMin, dMax);
		if((is_double_legal(&dMin) && is_double_legal(&dMax)) || (is_missing_value(dMin) && is_missing_value(dMax)))
		{
			AddBinDataTableAndGraphNodes(trOp, index, vResidual, vstrFactors, lpcszDataLabel);
		}
		if(!calcStatsData(trOp, index, vResidual, vWeights))
			return false;
		return true;
	}
	///end RESET_ALL_GRAPHS_FAILS_TO_PLOT_RESIDUAL_HISTOGRAM_IN_SR4_OPJ
	
	void PutTempStatsTreeNode(TreeNode& trOp, DataRange& dr, int nDataIndex, int nGraphIndex)
	{
		int r1, c1, r2, c2;
		Datasheet ds; 
		string strRange;
		if(dr)
		{
			int ii = 0; //The DataRange dr have only one data, when plot histogram
			dr.GetRange(ii, r1, c1, r2, c2, ds, &strRange);
			DatasetObject dsObj;
			Worksheet wks(ds);
			if(wks.IsValid())
			{
				Column col(wks, c2);
				DatasetObject dsObjTemp(col);
				dsObj = dsObjTemp;
			}
			else
			{
				MatrixLayer ml(ds);	
				if(ml)
				{
					MatrixObject mo = ml.MatrixObjects(ii);
					DatasetObject dsObjTemp(mo);
					dsObj = dsObjTemp;
				}
			}
			
			/// Iris 04/20/09 QA80-12574-P1 RESET_ALL_GRAPHS_FAILS_TO_PLOT_RESIDUAL_HISTOGRAM_IN_SR4_OPJ
			//TreeNode trStats = getTempStatsTreeNode(trOp, ii+nDataIndex-1);
			int nStatsNodeIndex = ii+nDataIndex-1;
			TreeNode trStats = getTempStatsTreeNode(trOp, nStatsNodeIndex);
			if( trStats.IsEmpty() ) // trStats node not existed in SR4 opj, so do Reset All Graphs for SR4 opj in SR5 Histogram Residual plot will be empty.
			{
				vector vResidual;
				dr.GetData(vResidual, ii); // get residual data from report sheet
				
				string strDataLabel;
				GetEscapedMainDataString(trOp, strDataLabel, nDataIndex);
				
				DataRange 		drInput;
				vector<string> 	vstrFactors;
				vector			vWeights;
				if(GetInput(drInput))
				{
					drInput.GetData(GetDataRules(trOp), nDataIndex-1, NULL, NULL, NULL, NULL, NULL, &vstrFactors, &vWeights);
				}
				
				bool bRet = CalcAddStatsHistPlotData(trOp, nDataIndex-1, vResidual, vWeights, vstrFactors, strDataLabel);
				ASSERT(bRet);
				trStats = getTempStatsTreeNode(trOp, nStatsNodeIndex);
			}
			///end RESET_ALL_GRAPHS_FAILS_TO_PLOT_RESIDUAL_HISTOGRAM_IN_SR4_OPJ
			
			string strTag;
			GetDataPlotEventHandlerName(strTag, nDataIndex-1);
			okutil_make_valid_c_name(&strTag);
			dsObj.PutBinaryStorage(strTag, trStats);
			///Arvin 04/06/07 v8.0596 THE_10TH_HISTOGRAM_CAN_NOT_PLOTTED
			if(IsStatsTreeRemovable(trOp, nGraphIndex))
				trStats.Remove();
			///------
		}
		///Arvin 04/06/07 v8.0596 THE_10TH_HISTOGRAM_CAN_NOT_PLOTTED
		//if( trOp.Temp )
		//{
			//string strLabel = STATS_TREE_NODE_PREFIX + ftoa(nDataIndex); 
			//trOp.Temp.RemoveChildrenWithPrefix(strLabel);
		//}
		///END THE_10TH_HISTOGRAM_CAN_NOT_PLOTTED
	}
	///Sophy 8/12/2008 QA80-12000-S2 DEFAULT_TURN_OFF_REPORT_MISSING_DATA_FOR_STATS_TOOL
	//virtual
	bool 	AddHintsForMissingAndMasked(TreeNode& trOperation)
	{
		TreeNode 	trFootNote = tree_check_get_node(trOperation.Calculation.Input, "Footnote", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
		bool		bEmptyFootnote = trFootNote.strVal.IsEmpty()? true : false;
		if(IsHasMaskedData())
			trFootNote.strVal += bEmptyFootnote? STR_FOOTNOTE_HAS_MASKED_VALUE : "\r\n" + STR_FOOTNOTE_HAS_MASKED_VALUE;

		bEmptyFootnote = trFootNote.strVal.IsEmpty()? true : false;
		if(IsHasMissingData())
			trFootNote.strVal += bEmptyFootnote? STR_FOOTNOTE_HAS_MISSING_VALUE : "\r\n" + STR_FOOTNOTE_HAS_MISSING_VALUE;
		
		return true;
	}
	///end DEFAULT_TURN_OFF_REPORT_MISSING_DATA_FOR_STATS_TOOL
public:
	
	///Arvin 11/10/07 XOP_NEED_SUPPORT_CHANGE_FUNCTION	
	//Need call this method from oc code, so move it to public session
	///Arvin 01/28/07 SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER
	//void  ClearOutputTables(TreeNode& trOperation)
	virtual void  ClearOutputTables(TreeNode& trOperation)
	///end SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER
	{
		WksReportOperation::ClearOutputTables(trOperation);	
		
		bool		bKeepAttrib = true;
		TreeNode 	trOut = trOperation.Calculation;
		///Arvin 09/26/07 ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS
		//if(trOut.Statistics)
		//	trOut.Statistics.Reset(bKeepAttrib);	
		//if(trOut.ANOVAs)
		//	trOut.ANOVAs.Reset(bKeepAttrib);
		if(trOut)
		{
			int bNotes = true;
			foreach(TreeNode trSubNode in trOut.Children)
			{
				if(bNotes)
				{
					bNotes = false;
					continue;
				}
				
				if(trSubNode.GetNodeCount() > 0)
					trSubNode.Reset(bKeepAttrib);
			}
		}
		///end ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS
	}
	///end XOP_NEED_SUPPORT_CHANGE_FUNCTION
	
	/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
	/// YuI 08/15/06 MORE_WORK_ON_STATISTICAL_PLOTS
	/*
	virtual bool	UpdatePercentileDataset(DataPlot& dp, int nDataIndex)
	{
		out_str("StatsOpBase is updating percentile dataset");
		string strDatasetName;
		if( dp.GetLinkedDatasetName(strDatasetName) )
		{
			Dataset ds(strDatasetName);
			if( ds.IsValid() )
			{
				TreeNode trOp;
				GetTree(trOp);
				/// Iris 10/21/05 CLEANUP_STATS_REPORT_GRAPH_CODES
				//TreeNode trTable = tree_check_get_node(trOp.Calculation, CALCULATION_BIN_DATA_TABLE, IDST_BIN_WKS);
				TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, nDataIndex, -1, GRAPH_STATS_BOX, CALCULATION_BIN_DATA_TABLE, IDST_BIN_WKS, "Bin Wks", strDatasetName);
				///End CLEANUP_STATS_REPORT_GRAPH_CODES

		
				string	strNodeX, strNodeY;
				uint	unXid, unYid;
				getXYnodeNames(nDataIndex, unXid, unYid, strNodeX, strNodeY);
		
				TreeNode trBinx = tree_check_get_node(trTable, strNodeX, unXid, STR_LABEL_ATTRIB, NULL);
				TreeNode trBiny = tree_check_get_node(trTable, strNodeY, unYid, STR_LABEL_ATTRIB, NULL);
				
				vector vCounts;
				vCounts = trBiny.dVals;
				vector vBins;
				vBins = trBinx.dVals;
				///Liko 08/22/2005 v8.0290 PLOT_HISTOGRAM_POSITION_CHANGE
				double dinc = vBins[1] - vBins[0];
				vBins-=0.5*dinc;
				/// end PLOT_HISTOGRAM_POSITION_CHANGE
				
				if( vCounts.GetSize() < 2 || (vBins.GetSize() != vBins.GetSize()) )
					return false;
				
				ds = vCounts;
				ds.SetSize(PDSP_UP_MEDIAN_CONFIDENCE + 1);
				ds[PDSP_NUM_HIST] = vCounts.GetSize();
				
				trTable = tree_check_get_node(trOp.Calculation, "Statistics", IDST_DESC_STATS_RESULTS);
			
				string strParameterNode = CALCULATION_REPORT_TABLE_COL_PREFIX;
				strParameterNode += (nDataIndex + 1);
				TreeNode trParameter = tree_check_get_node(trTable, strParameterNode, IDST_TEMP_ONE_SET);
				DescStatResults		stStats;
				QuantileResults		stQuantiles;
				stStats = trParameter;
				stQuantiles = trParameter;
						
				ds[PDSP_DATA_SIZE] = stStats.N;
				
				ds[PDSP_HIST_MIN] = vBins[0];
				ds[PDSP_HIST_INC] = vBins[1] - vBins[0];
				
				ds[PDSP_PERC_MIN] = stQuantiles.Min;
				ds[PDSP_PERC_MAX] = stQuantiles.Max;
				ds[PDSP_PERC_MEAN] = stStats.Mean;
				ds[PDSP_PERC_SD] = stStats.SD;
				ds[PDSP_PERC_SE] = stStats.SEM;
			///Kevin 09/01/05 CHANGE_STATISTICS_NAME
				//ds[PDSP_LOW_MEDIAN_CONFIDENCE] = stStats.LCI;
				//ds[PDSP_UP_MEDIAN_CONFIDENCE] = stStats.UCI;
				ds[PDSP_LOW_MEDIAN_CONFIDENCE] = stStats.LCL;
				ds[PDSP_UP_MEDIAN_CONFIDENCE] = stStats.UCL;
			///End CHANGE_STATISTICS_NAME

				vector vPercents;
				vector vPercentiles;
				/// Iris 10/21/05 USE_DUPLICATE_PRECENT_NODE_IN_TEMP
				//GetPercentilesFromTree(trParameter, vPercents, vPercentiles);
				GetPercentilesFromTree(trOp, nDataIndex, vPercents, vPercentiles);
				///End USE_DUPLICATE_PRECENT_NODE_IN_TEMP
				for( int ii = 0; ii < vPercents.GetSize(); ii++ )
				{
					int nTemp = IsRequiredPercentValue(vPercents[ii]);
					if( nTemp >= 0 )
					{
						ds[l_vPercentilePosition[nTemp]] = vPercentiles[ii];
					}
				}
		
				return true;
			}
		}
		return false;
	}
	*/
	
	virtual bool	UpdateStatsTree(TreeNode& trStats, int nDataIndex, BOOL& bUpdated)
	{
		bUpdated = FALSE;
		return true;
	}
	#define	STATS_TREE_NODE_PREFIX	"Stats"
	virtual void	OnAfterCalculations(TreeNode& trOp)
	{
		WksReportOperation::OnAfterCalculations(trOp);
		
		// we need to update stats results
		///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
		//Now, because input data may have factors, so we add a report table to plot Histogram and box chart
		///Arvin 08/14/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
		//if(!HasFactor(trOp))
		if(!HasFactor(trOp) && !IsCombinedMultiAsSingle(trOp))
		///end 	WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
		{
		///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
			DataRange dr;
			GetInput(dr);
			int nNumData = GetNumData(trOp, dr);
			DWORD dwRules = GetDataRules(trOp);
			for( int ii = 0; ii < nNumData; ii++ )
			{
				string strData; 
				if( 0 <= dr.GetData(dwRules, ii, &strData) )
				{
					DatasetObject dsObj(strData);
					TreeNode trStats = getTempStatsTreeNode(trOp, ii);
					string strTag;
					GetDataPlotEventHandlerName(strTag, ii);
					okutil_make_valid_c_name(&strTag);
					/// YuI 08/14/09 QA70-14138 REDUCE_STATS_TREE_SIZE_IN_SERIES_STORAGE
					// before we put stats tree into storage we need to remove missing values nodes from it, will make it smaller
					TreeNode trStatsResults = trStats.Results;
					if( trStatsResults )
					{
						TreeNode trLeaf = trStatsResults.FirstNode;
						while( trLeaf )
						{
							TreeNode trTemp = trLeaf.NextNode;
							if( NANUM == trLeaf.dVal )
							{
								trStatsResults.RemoveChild(trLeaf);
							}
							trLeaf = trTemp;
						}
					}
					/// end REDUCE_STATS_TREE_SIZE_IN_SERIES_STORAGE
					dsObj.PutBinaryStorage(strTag, trStats);
				}
			}
			if( trOp.Temp )
				trOp.Temp.RemoveChildrenWithPrefix(STATS_TREE_NODE_PREFIX);
			
		}///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	}
	/// end MORE_WORK_ON_STATISTICAL_PLOTS
	
	virtual bool	GetTickLabel(DataPlot& dp, int nDataIndex, string& strLabel)
	{
		TreeNode trOp;
		GetTree(trOp);
		DataRange dr;
		GetInput(dr);
		DWORD dwRules = GetDataRules(trOp);
		string strData;
		vector<string> vFacotrs;
		dr.GetData(dwRules, nDataIndex, NULL, NULL, NULL, NULL, NULL, &vFacotrs);
		if( vFacotrs.GetSize() > 0 )
		{
			for( int ii = 0; ii < vFacotrs.GetSize(); ii++ )
			{
				if( ii == 0 )
					strLabel = vFacotrs[0];
				else
					strLabel += "\r\n" + vFacotrs[ii]
			}
		}
		else if( 0 <= dr.GetData(dwRules, nDataIndex, &strData) )
		{
			strLabel = strData;	
		}
		return true;
	}
	/// end PICTURE_IN_REPORT_IMPROVEMENT
	
	///Echo 11/22/05 v8.0339 ADD_MODE
	/////Echo 3/22/05 v8.0207 QA70-6204 ADD_GSD
	//void	FilterDescStats(TreeNode& trRow)
	//{
	/////Kevin 09/01/05 CHANGE_STATISTICS_NAME	
		////vector<int> vnNodesToHide = {IDE_NUM_MISSING, IDE_SUM, IDE_GEO_MEAN, IDE_GEO_SD, IDE_LCI, IDE_UCI, IDE_SD_X_2, 
		//vector<int> vnNodesToHide = {IDE_NUM_MISSING, IDE_SUM, IDE_GEO_MEAN, IDE_GEO_SD, IDE_LCL, IDE_UCL, IDE_SD_X_2, 
	/////End CHANGE_STATISTICS_NAME
		//IDE_SD_X_3, IDE_VARIANCE, IDE_COV, IDE_SKEWNESS, IDE_KURTOSIS, IDE_MAD, IDE_UNCORSUMSQ,	IDE_CORSUMSQ, 
		//IDE_WEIGHTSUM,
		//IDE_MIN, IDE_IMIN, IDE_P25, IDE_MEDIAN, IDE_P75, IDE_MAX, IDE_IMAX, IDE_IQR, IDE_RANGE};
		//
		//tree_set_attributes(trRow, vnNodesToHide, "0");		
	//}
	void	FilterDescStats(TreeNode& trRow)
	{
		vector<int> vnNodesToHide = {IDE_NUM_MISSING, IDE_SUM, IDE_MODE, IDE_GEO_MEAN, IDE_GEO_SD, IDE_LCL, IDE_UCL, IDE_SD_X_2, 
		IDE_SD_X_3, IDE_VARIANCE, IDE_COV, IDE_SKEWNESS, IDE_KURTOSIS, IDE_MAD, IDE_UNCORSUMSQ,	IDE_CORSUMSQ, 
		IDE_WEIGHTSUM,
		IDE_MIN, IDE_IMIN, IDE_P25, IDE_MEDIAN, IDE_P75, IDE_MAX, IDE_IMAX, IDE_IQR, IDE_RANGE};
		
		tree_set_attributes(trRow, vnNodesToHide, "0");	
		
		//--- Iris 11/02/06 v8.0502e COL_LABEL_DISAPPEAR_IN_STATS_TABLE_IN_ANOVE_1_WAY
		trRow.N.SetAttribute(STR_LABEL_ATTRIB, _L("Sample Size"));
		trRow.Mean.SetAttribute(STR_LABEL_ATTRIB, _L("Mean"));
		trRow.SD.SetAttribute(STR_LABEL_ATTRIB, _L("Standard Deviation"));
		trRow.SEM.SetAttribute(STR_LABEL_ATTRIB, _L("SE of Mean"));
		//--- 
	}
	///end ADD_MODE

	///Iris 3/22/05 UPDATE_COLUMN_LABEL_FOR_GROUP_DATA
	bool GetOneDataLabel(TreeNode &trOp, int index, int nRowColIndex, string& strDataLabel, const vector<string> &vstrFactors = NULL)
	{
		if(WksReportOperation::GetOneDataLabel(trOp, index, nRowColIndex, strDataLabel) && NULL != vstrFactors)
		{
			if(vstrFactors.GetSize())
			{
				strDataLabel = vstrFactors[0]; ///Iris 3/22/05 temporary, cannot make sure if Factor only have one cell
				return true;
			}
		}
		return false;
	}

	/// YuI 08/15/06 MORE_WORK_ON_STATISTICAL_PLOTS
	TreeNode getTempStatsTreeNode(TreeNode& trOp, int index)
	{
		string strLabel;
		strLabel.Format("%s%d", STATS_TREE_NODE_PREFIX, index + 1);
		return tree_check_get_node(trOp.Temp, strLabel);
	}
	/// end MORE_WORK_ON_STATISTICAL_PLOTS

	///------ Folger 01/21/09 RESET_ALL_GRAPHS_FAILS_TO_PLOT_HISTOGRAM_IN_NLFIT
	/*
	///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	//For statistics on column, StatsTree is used for histogram and boxchart, so we should not
	//remove it after histogram plotting
	virtual bool IsStatsTreeRemovable(TreeNode& trOp, int nGraphIndex)
	{
		return true;
	}
	
	
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	*/
	bool IsStatsTreeRemovable(TreeNode& trOp, int nGraphIndex)
	{
		int		nPlotType = ReportGetPlotTypeFromGraphIndex(nGraphIndex);
		if( ( nPlotType == IDM_PLOT_HISTOGRAM_TYPE && IsCreateHistogramGraph(trOp) ) ||( nPlotType == IDM_PLOT_BOX && IsCreateBoxChartGraph(trOp) ) )
			return false;
		
		return true;
	}
	///------ End RESET_ALL_GRAPHS_FAILS_TO_PLOT_HISTOGRAM_IN_NLFIT
	
	///Arvin 10/19/07 USER_SETTED_PERCENTILES_SHOULD_NOT_EFFECT_HISTOGRAM_AND_BOX_CHART_GRAPHS as max said
	void    UpdatePercentilesInfoForHistAndBoxPlots(TreeNode& trStats, vector& vPercents, vector& vPercentiles)
	{
		vector<uint> vn;
		vPercents.Sort(SORT_ASCENDING, true, vn);
		vPercentiles.Reorder(vn);
		trim_custom_percentiles(vPercents, vPercentiles);
		tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
	}
	///end USER_SETTED_PERCENTILES_SHOULD_NOT_EFFECT_HISTOGRAM_AND_BOX_CHART_GRAPHS
	
	///Arvin 08/14/07 v8.0681 WRONG_MAX_AND_MIN_INDEX_IN_QUANTILES_WHEN_DATA_HAS_FACTORS
	//bool 	AddDescStatsTable(TreeNode& trOp, int index, const vector& vData, string& strDataLabel, 
	//		vector& vWeights, const vector<string> &vstrFactors = NULL, bool bIsDescTool = false, bool bAddFactorLabels = true, bool* pbMultiModes = NULL)
	bool 	AddDescStatsTable(TreeNode& trOp, int index, const vector& vData, string& strDataLabel, 
			vector& vWeights, const vector<string> &vstrFactors = NULL, bool bIsDescTool = false, bool bAddFactorLabels = true, bool* pbMultiModes = NULL, const vector<int>& vintRowsInSource = NULL)
	///END 	WRONG_MAX_AND_MIN_INDEX_IN_QUANTILES_WHEN_DATA_HAS_FACTORS	
	{
		int iDenFlag = bIsDescTool? trOp.GUI.Computation.VarDivisor.nVal : DS_SAS1_DOF;
		
		DescStatResults		stDescStats;		
		vector				vPercents;
		vector				vPercentiles;
		vector<bool>		vShow;
		QuantileResults		stQuantiles;
		
		//
		
		//if( STATS_NO_ERROR == stats_descriptive(vData, stDescStats, &vWeights, SU_DEFAULT_CONF_LEVEL, iDenFlag) &&
		//		CalcOneDataPercentilesAndRange(trOp, vData, vPercents, vPercentiles, vShow, stQuantiles))///Forest 02/04/05 ADD_WEIGHT_TO_STATS_QUANTILES
	
		//if( STATS_NO_ERROR == stats_descriptive(vData, stDescStats, &vWeights, SU_DEFAULT_CONF_LEVEL, iDenFlag) &&
				//CalcOneDataPercentilesAndRange(trOp, vData, vPercents, vPercentiles, vShow, vWeights, stQuantiles))///Echo 5/30/06 DESC_STATS_CHANGE_FOR_EFFICIENCY
		if( CalcOneDataMoment(trOp, vData, vWeights, stDescStats, pbMultiModes) &&
				/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
				//CalcOneDataPercentilesAndRange(trOp, vData, vPercents, vPercentiles, vShow, vWeights, stQuantiles))
				CalcOneDataPercentilesAndRange(trOp, vData, vPercents, vPercentiles, vShow, vWeights, stQuantiles, index))
				///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED		
		{
			//---- CPY 4/22/05 QA70-7651 DESC_STATS_ON_ROWS_CLEAN	
			/*
			///Forest 01/31/04 MODIFY_MIN_MAX_INDEX
			if(stQuantiles.iMin >= 0)	
				stQuantiles.iMin++;
			if(stQuantiles.iMax >= 0)
				stQuantiles.iMax++;
			///End MODIFY_MIN_MAX_INDEX
			*/

			TreeNode		trTable = tree_check_get_node(trOp.Calculation, TABLE_DESC_STATS, IDST_DESC_STATS_RESULTS, STR_LABEL_ATTRIB, _L("Descriptive Statistics"));
			/// ML 4/14/2005 PROPER_LABELS_WITH_FACTORS
			/////Iris 3/22/05 UPDATE_COLUMN_LABEL_FOR_GROUP_DATA
			//if(NULL != vstrFactors && 0 != vstrFactors.GetSize())
			//	strDataLabel = vstrFactors[0];
			/////end UPDATE_COLUMN_LABEL_FOR_GROUP_DATA
			if(!bAddFactorLabels && NULL != vstrFactors && 0 != vstrFactors.GetSize())
				strDataLabel = vstrFactors[0];
			/// end PROPER_LABELS_WITH_FACTORS
			
			string			strtagNamePrefix = bIsDescTool? CALCULATION_REPORT_TABLE_COL_PREFIX : CALCULATION_REPORT_TABLE_ROW_PREFIX;
			TreeNode		trRow = check_add_enumerated_node(trTable, strtagNamePrefix, index + 1, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, strDataLabel);
			///Iris 3/22/05 UPDATE_COLUMN_LABEL_FOR_GROUP_DATA
			//if(NULL != vstrFactors)
			//	tree_add_more_labels(trRow, vstrFactors);
			///end UPDATE_COLUMN_LABEL_FOR_GROUP_DATA
			/// ML 4/14/2005 PROPER_LABELS_WITH_FACTORS
			if (bAddFactorLabels && NULL != vstrFactors)
				tree_add_more_labels(trRow, vstrFactors);
			/// end PROPER_LABELS_WITH_FACTORS
			
			trRow += stDescStats;
			/// Iris 5/20/05 QA70-6367 DESC_STATS_APPEAR_QUANTILES_RESULT
			////---- CPY 4/22/05 QA70-7651 DESC_STATS_ON_ROWS_CLEAN
			////trRow += stQuantiles;	
			////SetPercentilesToTree(trRow, vPercents, vPercentiles, vShow);
			//if(vPercentiles.GetSize() > 0)
			//{
				//trRow += stQuantiles;	
				//SetPercentilesToTree(trRow, vPercents, vPercentiles, vShow);
			//}
			////----
			///Arvin 08/14/07 v8.0681 WRONG_MAX_AND_MIN_INDEX_IN_QUANTILES_WHEN_DATA_HAS_FACTORS
			if(vintRowsInSource)
			{
				if(stQuantiles.iMin >= 0 && stQuantiles.iMin < vintRowsInSource.GetSize())
					stQuantiles.iMin = vintRowsInSource[stQuantiles.iMin]; //Convert to LT index
				
				if(stQuantiles.iMax >= 0 && stQuantiles.iMax < vintRowsInSource.GetSize())
					stQuantiles.iMax = vintRowsInSource[stQuantiles.iMax]; //Convert to LT index 
			}
			///end WRONG_MAX_AND_MIN_INDEX_IN_QUANTILES_WHEN_DATA_HAS_FACTORS
			trRow += stQuantiles;
			SetPercentilesToTree(trRow, vPercents, vPercentiles, vShow);
			///end DESC_STATS_APPEAR_QUANTILES_RESULT
			///Cheney 2007-5-23 QA70-9805 SPEED_UP_STATISTIC_ON_ROW
			//setColTypeForNode(trRow);   /// Iris 11/18/05 QA70-8320 SET_COL_TYPE_FOR_CALC_ON_ROW
			SetColTypeForNode(trRow);
			///end SPEED_UP_STATISTIC_ON_ROW
			
			trRow.ID = make_one_set_ID(IDST_DESC_STATS_ONE_SET, index);
			
			/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
			if( IsPlotStatsGraph(trOp) )
			///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
			{
				/// Iris 10/21/05 USE_DUPLICATE_PRECENT_NODE_IN_TEMP
				///copy percentiles tree to trOp.Temp since many percentiles node in trOp.Calculation.Statistics are hidden and they will be remove in FilterReport function
				CopyPercentilesToTemp(trOp, index);		
				///End USE_DUPLICATE_PRECENT_NODE_IN_TEMP			
				
				/// YuI 08/15/06 MORE_WORK_ON_STATISTICAL_PLOTS
				TreeNode trStats = getTempStatsTreeNode(trOp, index);
				
				/// Iris 02/05/2007 v8.0554 PLOT_ALL_BOX_CHART_IN_ONE_GRAPH
				///Arvin 02/05/07 v8.0554 JUST_ROLLED_BACK_IRIS_CODE
				/*
				//tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
				//tree_stats_get_set_stats_results(trStats, stDescStats, stQuantiles.Min, stQuantiles.Max, FALSE);
				if(!IsPlotAllPlotsInOneGraph(trOp))
				{
					tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
					tree_stats_get_set_stats_results(trStats, stDescStats, stQuantiles.Min, stQuantiles.Max, FALSE);
				}
				else
				{
					setStatsTreeOnCombinedData(trOp, trStats);				
				}
				*/
				///Arvin 10/19/07 USER_SETTED_PERCENTILES_SHOULD_NOT_EFFECT_HISTOGRAM_AND_BOX_CHART_GRAPHS as max said
				//tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
				vector vPercentsTmp, vPercentilesTmp;
				vPercentsTmp = vPercents; 
				vPercentilesTmp = vPercentiles;
				UpdatePercentilesInfoForHistAndBoxPlots(trStats, vPercentsTmp, vPercentilesTmp);
				///end USER_SETTED_PERCENTILES_SHOULD_NOT_EFFECT_HISTOGRAM_AND_BOX_CHART_GRAPHS
				tree_stats_get_set_stats_results(trStats, stDescStats, stQuantiles.Min, stQuantiles.Max, FALSE);
				///END JUST_ROLLED_BACK_IRIS_CODE
				///end PLOT_ALL_BOX_CHART_IN_ONE_GRAPH
			}
				
			/// end MORE_WORK_ON_STATISTICAL_PLOTS

			if( !bIsDescTool) // if not part of Desc Stats, so only basic things are needed
				FilterDescStats(trRow);
			
			///Cheney 2007-5-23 QA70-9805 SPEED_UP_STATISTIC_ON_ROW
			//checkUpdateOriginSpecificValues(trOp, index);
			///Arvin 10/16/07 v8.0681 WRONG_MAX_AND_MIN_INDEX_IN_QUANTILES_WHEN_DATA_HAS_FACTORS
			//I don't think we need do this
			//CheckUpdateOriginSpecificValues(trOp, index);
			///end WRONG_MAX_AND_MIN_INDEX_IN_QUANTILES_WHEN_DATA_HAS_FACTORS
			///end SPEED_UP_STATISTIC_ON_ROW
			return true;
		}
				
		return false;
		
	}
	
private:
	
	/// Iris 02/05/2007 v8.0554 PLOT_ALL_BOX_CHART_IN_ONE_GRAPH
	//set Stats tree on combined data for plot histogram in one report graph
	bool	setStatsTreeOnCombinedData(TreeNode & trOp, TreeNode &trStats)
	{
		DataRange dr;
		if(!GetInput(dr))
			return error_report("Fail to get input data.");

	
		vector	vCombinedData;
		vector	vCombinedWeights;
		for(int ii = 0; ii < GetTotalNumData(trOp); ii++)
		{
			DWORD	dwPlotUID;
			vector	vData;
			vector	vW;
			dr.GetData(GetDataRules(trOp), ii, &dwPlotUID, NULL, &vData, NULL, NULL, NULL, &vW);
			vCombinedData.Append(vData);
			vCombinedWeights.Append(vW);
		}
		
		DescStatResults		stDescStats;
		vector				vPercents;
		vector				vPercentiles;
		vector<bool>		vShow;
		QuantileResults		stQuantiles;
		
		if(CalcOneDataMoment(trOp, vCombinedData, vCombinedWeights, stDescStats) &&
			CalcOneDataPercentilesAndRange(trOp, vCombinedData, vPercents, vPercentiles, vShow, vCombinedWeights, stQuantiles))
		{
			tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
			tree_stats_get_set_stats_results(trStats, stDescStats, stQuantiles.Min, stQuantiles.Max, FALSE);
			return true;
		}
		
		return error_report("Fail to do CalcOneDataMoment or CalcOneDataPercentilesAndRange on combined data.");
	
	}
	///end PLOT_ALL_BOX_CHART_IN_ONE_GRAPH
	
	///Jim 01/17/06 v8.0358 CREATE_PLOTS_BRANCH_IN_MAIN_NODES	
	void 	rebuildStatsGraphs(TreeNode& trOp)
	{
		if(GetNumGraphs() <= 0) 
			return;
		
		int index;
		TreeNode trGUI = trOp.GUI;
		TreeNode trCreate = op_get_optional_tables(trGUI);	
		
		//add new plots branch 
		GETN_USE(trGUI)		
                GETN_BEGIN_BRANCH(Plots, _L("Plots")) GETN_OPTION_BRANCH(GETNBRANCH_KEEP_SIZE_ON_COLLAPSE)//Alex 06/05/06 MODIFY_DEFAULTGUI_CLOSE_PLOTS_BRANCH
		GETN_END_BRANCH(Plots)		
		
		//add graph nodes to Plots branch 
		for(index = 0; index<GetNumGraphs(); index++)
		{
			TreeNode trPlots = trGUI.Plots;
			TreeNode trN = tree_check_get_node(trPlots, op_get_graph_tag_name(index), IDE_RESULT_GRAPHS+index);
			trN.Replace(tree_check_get_node(trCreate, op_get_graph_tag_name(index)));
			trN.nVal = 0;   //initialize all Residual check box to unchecked
			trN.ID = TRGP_CHECK;
			trN.RemoveAttribute(STR_USE_ATTRIB);
		}		
			
		//remove the original graph nodes
		for(index = 0; index<GetNumGraphs(); index++)
		{
			TreeNode trGraph = tree_check_get_node(trCreate, op_get_graph_tag_name(index));
			if(trGraph)
				trGraph.Remove();
		}
	}
	///END CREATE_PLOTS_BRANCH_IN_MAIN_NODES
	
///Cheney 2007-5-23 QA70-9805 SPEED_UP_STATISTIC_ON_ROW
protected:
	///// Iris 11/18/05 QA70-8320 SET_COL_TYPE_FOR_CALC_ON_ROW
	//void setColTypeForNode(TreeNode& trRow)
	void SetColTypeForNode(TreeNode& trRow)
///end SPEED_UP_STATISTIC_ON_ROW
	{
		///Sophy 4/1/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		/*
		//---- Iris 02/07/2007 v8.0576 set all columns to Y except SD & SE on Max's suggestion.
		//trRow.Mean.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
		foreach(TreeNode trN in trRow.Children)
		{
			trN.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
		}
		//----
		trRow.SD.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		trRow.SEM.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		*/
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y, true);
		if ( trRow.SD )
			trRow.SD.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		
		if ( trRow.SEM )
			trRow.SEM.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		
		if ( trRow.MAD )
			trRow.MAD.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		
		if ( trRow.SDx2 )
			trRow.SDx2.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		
		if ( trRow.SDx3 )
			trRow.SDx3.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		
		if ( trRow.GeoSD )
			trRow.GeoSD.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);	
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	}
	///End SET_COL_TYPE_FOR_CALC_ON_ROW
//protected: ///Cheney 2007-5-23 QA70-9805 SPEED_UP_STATISTIC_ON_ROW
	/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
	/*
	bool PlotReportGraph(int index, GraphLayer& gl, Worksheet& wksReport, DataRange& rReport, TreeNode& trOp, int nTotalNumData, int nGraphIndex = 0)
	{
		if(nGraphIndex)
			return true;
		
		uint unNodeX, unNodeY;
		getXYnodeNames(index, unNodeX, unNodeY);
		/// Iris 10/27/04 PLOT_REPORT_WITHOUT_X_DATA
		//int nPlot = PlotReportXYData(gl, rReport, IDST_BIN_WKS, unNodeX, unNodeY, IDM_PLOT_COLUMN);
		int nPlot = PlotReportXYData(gl, rReport, IDST_BIN_WKS, IDM_PLOT_COLUMN, unNodeY, unNodeX);

		if( nPlot >= 0 )
		{
			// we need to set the proper X axis scales
			Worksheet wks;
			int nXcol = GetWksCol(rReport, IDST_BIN_WKS, unNodeX, &wks);
			gl.Rescale();
			if(wks.IsValid() && nXcol >= 0)
			{
				Dataset dx(wks, nXcol);
				int nLast = dx.GetUpperIndex();
				if( nLast > 0)
				{
					gl.X.Inc = dx[1] - dx[0];
					gl.X.From = dx[0] - gl.X.Inc/2;
					gl.X.To = dx[nLast] + gl.X.Inc/2;
				}
			}			
			return true;
		}
		return error_report("Desc Stats failed PlotReportGraph");			
		
		int nPlotType = ReportGetPlotTypeFromGraphIndex(nGraphIndex);
		DataRange dr;
		GetInput(dr);
		DWORD dwRules = GetDataRules(trOp);
		string strData;
		if( 0 <= dr.GetData(dwRules, index, &strData) )
		{
			Curve cuv(strData);
			if( !cuv )
			{
				error_report("plotFitCurve found curve constructed but invalid");
				return -1;
			}
			
			if(cuv.GetUpperIndex() > 1)
			{
				int nPlot = gl.AddPlot(cuv, nPlotType);
				if(nPlot >= 0)
				{
					DataPlot dp = gl.DataPlots(nPlot);
					
					
					string strGUID;
					int nUID = GetUID(TRUE, &strGUID);
					string strHandlerUID = nUID;
					strHandlerUID += " " + strGUID + " ";
					strHandlerUID += index;
					dp.SetEventHandler(strHandlerUID);
					gl.Rescale();
					return true;
				}
			}
		}
		return false;
		/// end PICTURE_IN_REPORT_IMPROVEMENT
	}
	*/
	
	
	//---- CPY 5/6/04 QA70-6367 HISTOGRAM_GRAPHS
	
	/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
	/*
	bool AddBinDataHistogramGraph(TreeNode& trOp, int index, const vector& vData, const vector<string> &vstrFactors, int nGraphIndex = 0, LPCSTR lpcszDataLabel = NULL)
	{
		
		//int nGraphIndex = 0;
		/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
		//	ReportCreateGraphHelper crtGraph(CREATE_GRAPH_PREPARE_TREE, trOp, index, nGraphIndex, lpcszDataLabel, &vstrFactors);
		int nPictureIndex = ReportGetPicureIndexFromPlotIndex(nGraphIndex, index);
		ReportCreateGraphHelper crtGraph(CREATE_GRAPH_PREPARE_TREE, trOp, index, nGraphIndex, lpcszDataLabel, &vstrFactors, nPictureIndex);
		/// end PICTURE_IN_REPORT_IMPROVEMENT
		
		bool bCreateGraph = crtGraph.IsCreate();
		
		if(!addBinDataWksTable(trOp, index, vData, bCreateGraph, vstrFactors, lpcszDataLabel))
			return false;
		
		if(bCreateGraph)
		{
			/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
			SetTree(trOp); 
			/// end PICTURE_IN_REPORT_IMPROVEMENT
			if(!crtGraph.AddGraphToTreeNode())
				return false;
		}
		
		return true;
	}
	
	//------- CPY 11/3/04	QA70-7122 ADD_BOX_CHART_TO_DESC_STATS
	bool AddPercentilesAndMakeBoxCharts(TreeNode& trOp, int index, const vector& vData, const vector<string> &vstrFactors, int nGraphIndex, LPCSTR lpcszDataLabel = NULL)
	{
		//int nGraphIndex = 1;
		
		/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
		//	ReportCreateGraphHelper crtGraph(CREATE_GRAPH_PREPARE_TREE, trOp, index, nGraphIndex, lpcszDataLabel, &vstrFactors);
		int nPictureIndex = ReportGetPicureIndexFromPlotIndex(nGraphIndex, index);
		ReportCreateGraphHelper crtGraph(CREATE_GRAPH_PREPARE_TREE, trOp, index, nGraphIndex, lpcszDataLabel, &vstrFactors, nPictureIndex);
		/// end PICTURE_IN_REPORT_IMPROVEMENT
		bool bCreateGraph = crtGraph.IsCreate();
		if(bCreateGraph)
		{
			/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
			SetTree(trOp); 
			/// end PICTURE_IN_REPORT_IMPROVEMENT
			if(!crtGraph.AddGraphToTreeNode())
				return false;
		}
		else
		{
		}
		return true;
	}
	*/
	
	//-------- CPY 12/31/04 PICTURE_IN_REPORT_IN_BASE_CLASS
	/*
	bool AddBinDataHistogramGraph(TreeNode& trOp, int index, const vector& vData, const vector<string> &vstrFactors, int nGraphIndex = 0, LPCSTR lpcszDataLabel = NULL)
	{
		bool bCreateGraph = IsCreateReportGraph(trOp, nGraphIndex);
		if(!addBinDataWksTable(trOp, index, vData, bCreateGraph, vstrFactors, lpcszDataLabel))
			return false;

		if( bCreateGraph )
			SetTree(trOp);
		// histogram plot  graphindex is 0, picture index is equal to data index
		TreeNode trImage = CheckCreateImageNode(trOp, nGraphIndex, index, lpcszDataLabel);
		UpdateImageNodePlottingInfo(trImage, index);
		return true;
	}
	
	bool AddPercentilesAndMakeBoxCharts(TreeNode& trOp, int index, const vector& vData, const vector<string> &vstrFactors, int nGraphIndex, LPCSTR lpcszDataLabel = NULL)
	{
		// box chart plot grpah index is 1 picture index is 0
		TreeNode trImage = CheckCreateImageNode(trOp, nGraphIndex, 0, lpcszDataLabel);
		UpdateImageNodePlottingInfo(trImage, index);
		return true;
	}
	/// end PICTURE_IN_REPORT_IMPROVEMENT
	//------- end ADD_BOX_CHART_TO_DESC_STATS
	*/
	///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	virtual bool IsCreateHistogramGraph(TreeNode& trOp)
	{
		return IsCreateReportGraph(trOp, 0);
	}
	
	virtual bool IsCreateBoxChartGraph(TreeNode& trOp)
	{
		return IsCreateReportGraph(trOp, 1);
	}
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	
	///Arvin 08/14/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
	virtual bool	IsCombinedMultiAsSingle(const TreeNode& trOp)
	{	
		return false;
	}
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
	
	bool AddBinDataTableAndGraphNodes(TreeNode& trOp, int index, const vector& vData, const vector<string> &vstrFactors, LPCSTR lpcszDataLabel = NULL, bool bPrepareGraph = true)
	{
		/// Iris 6/15/05 check two graphs is selected or not
		//bool bCreateGraph = IsCreateReportGraph(trOp);
		///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
		/*
		bool bCreateGraph = IsCreateReportGraph(trOp, 0);
		///
		bCreateGraph = IsCreateReportGraph(trOp, /*1GRAPH_RESIDUALS_HISTOGRAM) || bCreateGraph; ///Arvin 12/02/06 CALC_BIN_DATA_WHEN_CHECKED_IT
		*/
		bool bCreateGraph = IsCreateHistogramGraph(trOp) | IsCreateBoxChartGraph(trOp);
		
		///Arvin 08/14/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
		//if(HasFactor(trOp) && bCreateGraph)
		if((HasFactor(trOp) || IsCombinedMultiAsSingle(trOp)) && bCreateGraph)
		///end WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET	
		{
			string strDataLabel(lpcszDataLabel);
			///Arvin 08/14/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
			//string strFactorLabel = vstrFactors[0]; //As Iris' code in function GetOneDataLabel
			string strFactorLabel;
			if(IsCombinedMultiAsSingle(trOp))
				strDataLabel = _L("Combined Data");
			else
				///Sophy 2/26/2009 MORE_REASONABLE_LEGEND_FOR_REPORT_GRAPH_WHEN_MULTIPLE_GROUPS_EXIST_IN_STATS_ON_COLUMN
				//strFactorLabel = vstrFactors[0];
#ifdef	MORE_REASONAL_LEGEND_FOR_STATS_ON_COL
				strFactorLabel.SetTokens(vstrFactors, ',');
#else
				strFactorLabel = vstrFactors[0];
#endif	//MORE_REASONAL_LEGEND_FOR_STATS_ON_COL
				///end MORE_REASONABLE_LEGEND_FOR_REPORT_GRAPH_WHEN_MULTIPLE_GROUPS_EXIST_IN_STATS_ON_COLUMN
			///end WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
				
			AddHistogramAndBoxChartTables(trOp, index, vData, strDataLabel, strFactorLabel);
		}
		///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
		if(!addBinDataWksTable(trOp, index, vData, bCreateGraph, vstrFactors, lpcszDataLabel))
			return false;
		///Arvin 03/29/07 v8.0592 CAN_NOT_PLOT_MULTI_HISTOGRAMS_FOR_MULTI_DATASET
		//if( bCreateGraph )
		//	SetTree(trOp);
		///END CAN_NOT_PLOT_MULTI_HISTOGRAMS_FOR_MULTI_DATASET
		
		/// Thomas 03/13/2006 REPLACE_DATALABLE_WITH_FACTOR
		/*
		if(bPrepareGraph) 
			PrepareGraphNodes(trOp, GetNumGraphs(), index, lpcszDataLabel);
		*/
		/// Iris 01/08/2007 v8.0538 REPORT_GRAPHS_ARRANGEMENT, ////commented out it temp/////
		//if(bPrepareGraph) {
			//string strTemp = lpcszDataLabel;
			//if(vstrFactors && vstrFactors.GetSize()) strTemp = vstrFactors[0];
			//PrepareGraphNodes(trOp, GetNumGraphs(), index, strTemp);
		//}
		///end REPORT_GRAPHS_ARRANGEMENT
		/// End REPLACE_DATALABLE_WITH_FACTOR
		
		return bCreateGraph;
	}
	//-------- end PICTURE_IN_REPORT_IN_BASE_CLASS
	
	///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	virtual uint GetResultCurveTableID(TreeNode& trOp, int nDataIndex, int nTotalNumData = -1, int nGraphIndex = 0)
	{
		///Arvin 08/14/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
		//if(HasFactor(trOp))
		if(HasFactor(trOp) || IsCombinedMultiAsSingle(trOp))
		///end WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET	
		{
			switch( nGraphIndex )
			{
			case GRAPH_STATS_HISTOGRAM:
				return make_one_set_ID(IDST_STAT_HISTOGRAM_TABLE+nDataIndex+1, nDataIndex+1);
				break;
			case GRAPH_STATS_BOX:
				return make_one_set_ID(IDST_STAT_BOX_CHART_TABLE+nDataIndex+1, nDataIndex+1);
				break;
			}
		}
		
		return 0;
	}
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	
	///Echo 5/30/06 DESC_STATS_CHANGE_FOR_EFFICIENCY
	void InitMoments(DescStatOptions& opMoments)
	{
		Tree trTemp;
		TreeNode trMoments = trTemp.AddNode("Moments");
		trMoments = opMoments;
		foreach(TreeNode trChild in trMoments.Children)
			trChild.nVal = 1;			
		opMoments = trMoments;
		
		opMoments.VarDivisor = DS_NAG;
		
	}
	
	bool CalcOneDataMoment(TreeNode &trOp, const vector &vData, const vector& vWeights, DescStatResults& stDescStats, bool* pbMultiModes = NULL)
	{
		bool     bIsDescTool = false;
		TreeNode trGUI = trOp.GUI;
		TreeNode trStatsOptions = trGUI.Quantities;
		if(trStatsOptions && trStatsOptions.Quantiles)
			bIsDescTool = true;
		
		DescStatOptions opMoments;		
		if(bIsDescTool)
		{
			opMoments = trStatsOptions.Moments;
			opMoments.VarDivisor = trGUI.Computation.VarDivisor.nVal;
		}
		else
		{
			InitMoments(opMoments);
		}

		///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
		//if (STATS_NO_ERROR == stats_desc_stats(vData, opMoments, stDescStats, &vWeights, SU_DEFAULT_CONF_LEVEL, pbMultiModes))
		//	return true;
		//else
		//	return false;
		if (stats_desc_stats(vData, opMoments, stDescStats, &vWeights, SU_DEFAULT_CONF_LEVEL, pbMultiModes))
		{
			string strErr;
			if( ocu_load_err_msg_str(CER_FAILED_GET_MOMENTS, &strErr) )
				///Cheney 2007-9-26 USE_ERROR_REPORT_TO_SHOW_OPERATION_ERR
				//okoc_out_msg(strErr);
				/// Iris 6/13/2008 SHOW_ERR_INFO_TO_SCRIPT_WND_FOR_USER
				//error_report(strErr);
				okoc_out_msg(strErr);
				///end SHOW_ERR_INFO_TO_SCRIPT_WND_FOR_USER
				///end USE_ERROR_REPORT_TO_SHOW_OPERATION_ERR
		}
		return true;
		///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
		
	}
	
	
	void InitQuantiles(QuantileOptions& opQuantiles, string& strCustomPercents)
	{
		Tree trTemp;
		TreeNode trQuantiles = trTemp.AddNode("Quantiles");
		trQuantiles = opQuantiles;
		foreach(TreeNode trChild in trQuantiles.Children)
			trChild.nVal = 1;			
		opQuantiles = trQuantiles;
		
		//opQuantiles.Interpolate = 0;	/// Iris 11/18/05 QA70-7112-P2 INTERPOLATE_ALWAYS_BE_0_FOR_ORIGIN
		opQuantiles.Interpolate = INTERPOLATE_WEIGHT_AVER_RIGHT;
		
		strCustomPercents = "";
	}
	
	/// YuI 12/07/04 v7.5172 PICTURE_IN_REPORT_IMPROVEMENT
	//bool CalcOneDataPercentilesAndRange(TreeNode &trOp, const vector &vData, vector& vPercents, vector& vPercentiles, vector<bool>& vShow, QuantileResults& quantiles)///Forest 02/04/05 ADD_WEIGHT_TO_STATS_QUANTILES
	/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
	//bool CalcOneDataPercentilesAndRange(TreeNode &trOp, const vector &vData, vector& vPercents, vector& vPercentiles, vector<bool>& vShow, const vector& vWeights, QuantileResults& quantiles)
	bool CalcOneDataPercentilesAndRange(TreeNode &trOp, const vector &vData, vector& vPercents, vector& vPercentiles, vector<bool>& vShow, const vector& vWeights, QuantileResults& quantiles, int index = 0)
	///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
	{
		///Iris 01/22/05 MOVE_DESCSTATS_TO_BASE_CLASS
		/*
		TreeNode trGUI = trOp.GUI;
		TreeNode trStatsOptions = trGUI.Quantities;
		if(!trStatsOptions)
			return error_report("Desc Stats trGUI does not have Quantities branch");

		QuantileOptions opQuantiles;		
		opQuantiles = trStatsOptions.Quantiles;
		opQuantiles.Interpolate = trGUI.Computation.Interpolate.nVal;   ///Iris 12/20/04 MOVE_TO_COMPCONTROL_BRANCH
		vPercents.SetSize(0);
		string strCustomPercents;
		if( trStatsOptions.Quantiles.CustomPercentiles.nVal )
			strCustomPercents = trStatsOptions.Quantiles.PercentileList.strVal;
		*/
		bool     bIsDescTool = false;
		TreeNode trGUI = trOp.GUI;
		TreeNode trStatsOptions = trGUI.Quantities;
		if(trStatsOptions && trStatsOptions.Quantiles)
			bIsDescTool = true;
		
		QuantileOptions opQuantiles;		
		string strCustomPercents;
		if(bIsDescTool)
		{
			opQuantiles = trStatsOptions.Quantiles;
			opQuantiles.Interpolate = trGUI.Computation.Interpolate.nVal;
			if( trStatsOptions.Quantiles.CustomPercentiles.nVal )
				strCustomPercents = trStatsOptions.Quantiles.PercentileList.strVal;
		}
		else
		{
			InitQuantiles(opQuantiles, strCustomPercents);
		}
		///end MOVE_DESCSTATS_TO_BASE_CLASS
		
		vPercents.SetSize(0);
		int nRet = 0;		
		/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
		// only get custom percentiles once time to improve speed
		//if( GetPercentsForPercentiles(trOp, strCustomPercents, vPercents, vShow) )
		bool bRet = false;
		if( 0 == index )
		{
			bRet = GetPercentsForPercentiles(trOp, strCustomPercents, vPercents, vShow);
			if( bRet )
			{
				m_vPercents = vPercents;
				m_vPercentShow = vShow;
			}
		}
		else
		{
			bRet = m_vPercents.GetSize()>0;
			if( bRet )
			{
				vPercents = m_vPercents;
				vShow = m_vPercentShow;
			}
		}
		if( bRet )
		///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
		{
			if( vShow.GetSize() != vPercents.GetSize() )
				return false;
			vPercentiles.SetSize(vPercents.GetSize());
			//return stats_quantiles(vData, opQuantiles, quantiles, vPercents, vPercentiles) == STATS_NO_ERROR ? true:false;///Forest 02/04/05 ADD_WEIGHT_TO_STATS_QUANTILES
			///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
			//return stats_quantiles(vData, opQuantiles, quantiles, vPercents, vPercentiles, &vWeights) == STATS_NO_ERROR ? true:false;
			nRet = stats_quantiles(vData, opQuantiles, quantiles, vPercents, vPercentiles, &vWeights);
			///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
		}
		/// Iris 5/20/05 QA70-6367 DESC_STATS_APPEAR_QUANTILES_RESULT
		else
		{
			///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
			//return stats_quantiles(vData, opQuantiles, quantiles, NULL, NULL, &vWeights) == STATS_NO_ERROR ? true:false;
			nRet = stats_quantiles(vData, opQuantiles, quantiles, NULL, NULL, &vWeights) == STATS_NO_ERROR ? true:false;
			///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
		}
		///end DESC_STATS_APPEAR_QUANTILES_RESULT
		
		///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
		if (nRet)
		{
			string strErr;
			if( ocu_load_err_msg_str(CER_FAILED_GET_QUANTITIES, &strErr) )
				///Cheney 2007-9-26 USE_ERROR_REPORT_TO_SHOW_OPERATION_ERR
				//okoc_out_msg(strErr);
				/// Iris 6/13/2008 SHOW_ERR_INFO_TO_SCRIPT_WND_FOR_USER
				//error_report(strErr);
				/// Iris 10/19/2009 QA80-11710-P4 SHOULD_SHOW_ERR_REPORT_TO_CB_OUTPUT_WND
				//okoc_out_msg(strErr);
				error_report(strErr);
				///end SHOULD_SHOW_ERR_REPORT_TO_CB_OUTPUT_WND
				///end SHOW_ERR_INFO_TO_SCRIPT_WND_FOR_USER
				///end USE_ERROR_REPORT_TO_SHOW_OPERATION_ERR
		}
		///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
		
		return true;
	}
	
	
	#define	DOUBLE_PERCENTILE_PERCENT_ATTRIBUTE		"PercentilePercent"
	/// Iris 10/21/05 USE_DUPLICATE_PRECENT_NODE_IN_TEMP
	//void	GetPercentilesFromTree(TreeNode& tr, int nDataIndex, vector& vPercents, vector& vPercentiles)
	void	GetPercentilesFromTree(TreeNode& trOp, int nDataIndex, vector& vPercents, vector& vPercentiles)
	///End USE_DUPLICATE_PRECENT_NODE_IN_TEMP
	{
		/// Iris 10/21/05 USE_DUPLICATE_PRECENT_NODE_IN_TEMP
		TreeNode tr = CheckCreateTempPercentilesOneTable(trOp, nDataIndex);
		if(!tr)
			return;
		///End USE_DUPLICATE_PRECENT_NODE_IN_TEMP
		
		// need to loop over nodes with CALCULATION_PERCENTILE_PREFIX
		TreeNodeCollection trCollection(tr, CALCULATION_PERCENTILE_PREFIX);
		vPercents.SetSize(trCollection.Count());
		vPercentiles.SetSize(trCollection.Count());
		int nIndex = 0;
		foreach(TreeNode trPerc in trCollection)
		{
			vPercentiles[nIndex] = trPerc.dVal;
			double dPercent;
			trPerc.GetAttribute(DOUBLE_PERCENTILE_PERCENT_ATTRIBUTE, dPercent);
			vPercents[nIndex] = dPercent;
			nIndex++;
		}
	}
	
	void	SetPercentilesToTree(TreeNode& tr, vector& vPercents, vector& vPercentiles, vector<bool>& vShow)
	{
		string strTemp;
		for( int ii = 0; ii < vPercents.GetSize(); ii++ )
		{
			strTemp.Format("P%s", ftoa(vPercents[ii]));
			TreeNode	trPerc = check_add_enumerated_node(tr, CALCULATION_PERCENTILE_PREFIX, ii + 1, IDE_CUSTOM_PERCENTILES + ii, STR_LABEL_ATTRIB, strTemp);
			trPerc.SetAttribute(DOUBLE_PERCENTILE_PERCENT_ATTRIBUTE, vPercents[ii]);
			trPerc.dVal = vPercentiles[ii];
			trPerc.Show = vShow[ii];
		}		
	}
	
	int		IsRequiredPercentValue(double& dPercent)
	{
		///Arvin 10/17/06 PCH_CAN_NOT_USE_STATIC_VECTOR
		/*
		for( int ii = 0; ii < l_vPercents.GetSize(); ii++ )
		{
			if( dPercent == l_vPercents[ii] )
			{
				return ii;
			}
		}

		return -1;
		*/
		return is_percentile_value(dPercent);
		///end PCH_CAN_NOT_USE_STATIC_VECTOR
	}
	
	bool	GetPercentsForPercentiles(TreeNode& trOp, string& strCustom, vector& vPercents, vector<bool>& vShow)
	{
		/// Iris 9/09/05 KEEP_CUSTOM_PERCENTS_ORDER
		/*
		bool bVisible = false;
		BOOL bBoxChart = (ReportHasGraph(trOp, IDM_PLOT_BOX, bVisible) && bVisible);
		if( bBoxChart )
		{
			vPercents = l_vPercents;
			vShow.SetSize(vPercents.GetSize());
			for( int ii = 0; ii < vShow.GetSize(); ii++ )
			{
				vShow[ii] = false;
			}
		}
		
		
		vector vCustomPercents;
		get_tokens_check_range(strCustom, vCustomPercents);
		for( int ii = 0; ii < vCustomPercents.GetSize(); ii++ )
		{
			int nPos = bBoxChart ? IsRequiredPercentValue(vCustomPercents[ii]) : ii;
			if( nPos >= 0 && bBoxChart )
			{
				vShow[nPos] = true;
			}
			else
			{
				int nNewIndex = vPercents.Add(vCustomPercents[ii]);
				
				vShow.SetAtGrow(nNewIndex, true);
			}
		}
		
		*/
		int 	ii = 0;
		get_tokens_check_range( strCustom, vPercents );
		for(ii=0; ii<vPercents.GetSize(); ii++)
		{
			vShow.Add(true);
		}
		
		/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED, unuseful codes
		/*
		bool 	bVisible = false;
		BOOL 	bBoxChart = (ReportHasGraph(trOp, IDM_PLOT_BOX, bVisible) && bVisible);
		*/
		///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
		
		///Arvin 10/11/06 STATS_ON_COL_HISTOGRAM_PLOT
		//if( !bBoxChart )
		//	return vPercents.GetSize();
		///end STATS_ON_COL_HISTOGRAM_PLOT
		
		///Arvin 10/17/06 PCH_CAN_NOT_USE_STATIC_VECTOR
		vector l_vPercents;
		is_percentile_value(0, &l_vPercents);
		///end PCH_CAN_NOT_USE_STATIC_VECTOR
		for(ii=0; ii<l_vPercents.GetSize(); ii++)
		{
			vector<uint> 	vnIndex;
			int 			nFindSum = vPercents.Find(vnIndex, l_vPercents[ii], l_vPercents[ii]);
			if(nFindSum <= 0)
			{
				int 	nNewIndex = vPercents.Add(l_vPercents[ii]);
				vShow.SetAtGrow(nNewIndex, false);
			}			
		}
		
		return vPercents.GetSize() > 0;
		///End KEEP_CUSTOM_PERCENTS_ORDER
		
	}
	/// end PICTURE_IN_REPORT_IMPROVEMENT

///Cheney 2007-5-23 QA70-9805 SPEED_UP_STATISTIC_ON_ROW
//private:
	/////Iris 2/28/05
	////add this function to make the index of min and max consistent with the index of original data in worksheet.
	//void checkUpdateOriginSpecificValues(TreeNode& trOp, int index)
protected:
	void CheckUpdateOriginSpecificValues(TreeNode& trOp, int index)
///end checkUpdateOriginSpecificValues
	{
		TreeNode trDesc = trOp.Calculation.Statistics;
		if(!trDesc)
			return;
		
		Worksheet 	wks;		
		int 		r1, c1, r2, c2;
		DataRange	rngInput;
		if ( !GetInput(rngInput) )
		{
			error_report("checkUpdateOriginSpecificValues found no input range");
			return;
		}
		rngInput.GetRange(0, r1, c1, r2, c2, wks);
		//--- CPY 4/22/05 QA70-7651 DESC_STATS_ON_ROWS_CLEAN
		c1++; r1++;// to convert from C to LT index
		//---
		//TreeNodeCollection	trColl(trDesc, CALCULATION_REPORT_TABLE_COL_PREFIX);
		//TreeNode trNode = trColl.Item(index);
		index++;
		TreeNode trNode = trDesc.GetNode(CALCULATION_REPORT_TABLE_COL_PREFIX+index);
		TreeNode trOption = trOp.GUI.StatsOnRows;
		if(trNode && trNode.iMin && trNode.iMax && trOption)
		{
			if(trOption.nVal)
			{
				trNode.iMin.nVal += c1;
				trNode.iMax.nVal += c1;
			}
			else
			{
				trNode.iMin.nVal += r1;
				trNode.iMax.nVal += r1;
			}
		}	
	}
	///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	bool AddHistogramAndBoxChartTables(TreeNode& trOp, int index, const vector& vData, LPCSTR lpcszDataLabel, LPCSTR lpcszFactorLabel = NULL)
	{
		string	strConvertedDataLabel(lpcszDataLabel);
		ConvertEscapedString(strConvertedDataLabel);
		string strLabel = strConvertedDataLabel;
		///Arvin 08/14/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
		//if(lpcszFactorLabel != NULL)
		//{
		//	string strFactorLabel(lpcszFactorLabel);
		//	strLabel += "_" + strFactorLabel;
		//}
		string strFactorLabel(lpcszFactorLabel);
		if(!strFactorLabel.IsEmpty())
			strLabel += "_" + strFactorLabel;
		///end WRONG_HISTOGRAM_AND_BOXCHART_PLOT_WHEN_COMBINED_MUTI_AS_SINGLE_DATASET
		
		vector vTempData;
		vTempData = vData;
		///Cheney 2007-9-13 NO_NEED_NANUM_AS_SETREPORTTREE_BUG_FIXED
		if(vTempData.GetSize() < 1)
			vTempData.Add(NANUM);
		///end NO_NEED_NANUM_AS_SETREPORTTREE_BUG_FIXED
		
		if(IsCreateHistogramGraph(trOp))
		{
			string 		strTableLabel = STR_STAT_HISTOGRAM_REPORT_TABLE + ftoa(index+1);
			TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, index, -1/*nTotalNumData*/, GRAPH_STATS_HISTOGRAM, strTableLabel, IDST_STAT_HISTOGRAM_TABLE+index+1, STAT_HISTOGRAM_REPORT_LABEL, strConvertedDataLabel);
			///Sophy 12/5/2008 v8.0982d IMPROVE_GIVE_A_REASONABLE_COLUMN_LONG_NAME_FOR_PLOT_DATA_OF_STATS_ON_COLUMN
			//string 		strHistLabel = _L("Histogram of") + " " + strLabel; 
			string 		strHistLabel = strFactorLabel; 
			///end IMPROVE_GIVE_A_REASONABLE_COLUMN_LONG_NAME_FOR_PLOT_DATA_OF_STATS_ON_COLUMN
			TreeNode 	trHist = tree_check_get_node(trTable, STR_STAT_HISTOGRAM_REPORT_TABLE, make_one_set_ID(IDST_STAT_HISTOGRAM_TABLE, index+1), STR_LABEL_ATTRIB, strHistLabel); 
			if(!trHist)
				return false;
			
			trHist.dVals = vTempData;
			trHist.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
		}
			
		if(IsCreateBoxChartGraph(trOp))
		{
			string 		strTableLabel = STR_STAT_BOXCHART_REPORT_TABLE + ftoa(index+1);
			TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, index, -1/*nTotalNumData*/, GRAPH_STATS_BOX, strTableLabel, IDST_STAT_BOX_CHART_TABLE+index+1, STAT_BOXCHART_REPORT_LABEL, strConvertedDataLabel);
			///Sophy 12/5/2008 v8.0982d IMPROVE_GIVE_A_REASONABLE_COLUMN_LONG_NAME_FOR_PLOT_DATA_OF_STATS_ON_COLUMN
			//string 		strBoxLabel = _L("Box Chart of") + " " + strLabel;
			string	strBoxLabel = strFactorLabel;
			///end IMPROVE_GIVE_A_REASONABLE_COLUMN_LONG_NAME_FOR_PLOT_DATA_OF_STATS_ON_COLUMN
			TreeNode 	trBoxChart = tree_check_get_node(trTable, STR_STAT_BOXCHART_REPORT_TABLE, make_one_set_ID(IDST_STAT_BOX_CHART_TABLE, index+1), STR_LABEL_ATTRIB, strBoxLabel); 
			if(!trBoxChart)
				return false;
			
			trBoxChart.dVals = vTempData;
			trBoxChart.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
		}
		
		return true;	
	}
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	
private:	///Cheney 2007-5-23 QA70-9805 SPEED_UP_STATISTIC_ON_ROW
	void getXYnodeNames(int nIndex, uint& unXid, uint& unYid, string& strX=NULL, string& strY=NULL)
	{
		unXid = make_one_set_ID(IDST_BIN_X_ONE_SET, nIndex);
		unYid = make_one_set_ID(IDST_BIN_COUNT_ONE_SET, nIndex);
		if(strX)		
			strX.Format("%s%d", "BinCtr", nIndex + 1);
		if(strY)
			strY.Format("%s%d", "Count", nIndex + 1);
		
	}
	
	bool addBinDataWksTable(TreeNode& trOp, int index, const vector& vData, bool bCreateGraph, const vector<string> &vstrFactors = NULL, LPCSTR lpcszDataLabel = NULL, bool bFactorAsLabel = false)
	{
		string strDataLabel;
		if( bFactorAsLabel && NULL != vstrFactors)
			strDataLabel = vstrFactors[0];
		else
			strDataLabel = lpcszDataLabel;
		
		ConvertEscapedString(strDataLabel); /// Iris 8/26/2008 QA80-12098 FIX_ONE_WAY_RM_FAIL_CONVERT_RESULT_CURVE_OP_STR
		
		/// Iris 10/21/05 CLEANUP_STATS_REPORT_GRAPH_CODES
		//TreeNode trTable = tree_check_get_node(trOp.Calculation, CALCULATION_BIN_DATA_TABLE, IDST_BIN_WKS);
		TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, index, -1/*nTotalNumData*/, GRAPH_STATS_BOX, CALCULATION_BIN_DATA_TABLE, IDST_BIN_WKS, _L("Bin Wks"), strDataLabel);
		///End CLEANUP_STATS_REPORT_GRAPH_CODES
		
		// saving the bin data, col(0)= x and col(1) = counts
		///Iris 9/06/05 QA70-7099-P7 SET_BINWKS_TABLE_HIDDEN
		//tree_check_set_hidden(trTable, bCreateGraph?false:true);
		tree_check_set_hidden(trTable, true);
		///End SET_BINWKS_TABLE_HIDDEN
		trTable.SetAttribute(TREE_Table, GetTableStringDatasets()); //set table attribute

		string	strNodeX, strNodeY;
		uint	unXid, unYid;
		getXYnodeNames(index, unXid, unYid, strNodeX, strNodeY);
		
		TreeNode trBinx = tree_check_get_node(trTable, strNodeX, unXid, STR_LABEL_ATTRIB, _L("Bin Ctr"));
		//tree_add_more_labels(trBinx, vstrFactors, 0, "Bin Ctr");
		trBinx.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_X);
		TreeNode trBiny = tree_check_get_node(trTable, strNodeY, unYid, STR_LABEL_ATTRIB, _L("Count"));
		//tree_add_more_labels(trBiny, vstrFactors, 0, "Count");
		trBiny.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
		
		if(bCreateGraph)
		{
			/// Iris 9/01/06 FREQENCY_COUNT_HISTGAM_PLOT_NEED_CENTRLIZE
			//double dMin, dMax;
			//if( !vData.GetMinMax(dMin, dMax) )
				//return false;
			//
			//int nBins = 0.5 + sqrt(vData.GetSize() + 1);// need customization on this later
			//vector vbx, vby;
			//
			///// YuI 08/15/06 MORE_WORK_ON_STATISTICAL_PLOTS
			////	if(!_create_bin_data(vData, dMin, dMax, vbx, vby, nBins))
			////		return error_report("Failed to create bin data");			
			//double dBinMin;
			//double dBinMax;
			//double dBinSize;
			//if(!_create_bin_data(vData, dMin, dMax, vbx, vby, dBinMin, dBinMax, dBinSize, nBins))
				//return error_report("Failed to create bin data");
			vector vbx, vby;
			double dBinMin;
			double dBinMax;
			double dBinSize;
			if( !CreateBinData(trOp, index, vData, vbx, vby, dBinMin, dBinMax, dBinSize) )
				///Arvin 05/23/07 v8.0624 EMPTY_DATA_SET_RUNTIME_ERROR
				//return error_report("Failed to create bin data");
				error_report("Failed to create bin data");
				///end EMPTY_DATA_SET_RUNTIME_ERROR
			///End FREQENCY_COUNT_HISTGAM_PLOT_NEED_CENTRLIZE
			
			TreeNode trStats = getTempStatsTreeNode(trOp, index);
			/// YuI 12/18/08 QA70-12800 PD_DIALOG_TO_CONTROL_HISTOGRAM_CREATED_BY_OPERATION
			//	tree_stats_get_set_counts(trStats, vby, FALSE);
			//	tree_stats_get_set_bin_info(trStats, dBinMin, dBinMax, dBinSize, FALSE);
			octree_stats_get_set_counts(&trStats, &vby, FALSE);
			octree_stats_get_set_bin_info(&trStats, &dBinMin, &dBinMax, &dBinSize, FALSE);
			/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
			//TreeNode trHistogramConfig = trOp.GUI.Output.GetNode(STR_HISTOGRAM_CONFIG_TAGNAME);			
			//if ( trHistogramConfig )
			//{
			//	octree_stats_set_bin_auto(&trStats, trHistogramConfig.AutoBin.nVal);
			//}
			TreeNode trHistogram = GetGUIGraphNodes(trOp, GRAPH_STATS_HISTOGRAM);
			if( trHistogram && tree_is_true(trHistogram) && trHistogram.AutoBin )
			{
				octree_stats_set_bin_auto(&trStats, trHistogram.AutoBin.nVal);
			}
			///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
			/// end PD_DIALOG_TO_CONTROL_HISTOGRAM_CREATED_BY_OPERATION
			/// end MORE_WORK_ON_STATISTICAL_PLOTS
			
			trBinx.dVals = vbx;
			trBiny.dVals = vby;			
		}
		else
		{
			vector vv(2);
			vv = 0;
			trBinx.dVals = vv;
			trBiny.dVals = vv;
		}
		return true;
	}
	
	// assume wksBin with nBinX and nBinY cols already existed
	/// YuI 08/15/06 MORE_WORK_ON_STATISTICAL_PLOTS
	/*
	static bool _create_bin_data(const vector& vdata, double dmin, double dmax, vector& vbx, vector& vby, int nBins = 10)
	{
		double d1 = dmin, d2 = dmax, dinc = 0;
		RoundLimits(&d1, &d2, &dinc, nBins);
		vector<int> vn;
		vdata.FrequencyCount(d1, d2, dinc, vn);
		vbx.Data(d1 + 0.5*dinc, d2 - 0.5*dinc, dinc); // bin centers 
		vby = vn;
		return true;
	}
	*/
	
	/// Iris 9/01/06 FREQENCY_COUNT_HISTGAM_PLOT_NEED_CENTRLIZE
	//static bool _create_bin_data(const vector& vdata, double dmin, double dmax, vector& vbx, vector& vby, double& dBinMin, double& dBinMax, double& dBinSize, int nBins = 10)
	//{			
		//dBinMin = dmin;
		//dBinMax = dmax;
		//RoundLimits(&dBinMin, &dBinMax, &dBinSize, nBins);
		//vector<int> vn;
		//vdata.FrequencyCount(dBinMin, dBinMax, dBinSize, vn);
		//vbx.Data(dBinMin + 0.5*dBinSize, dBinMax - 0.5*dBinSize, dBinSize); // bin centers 
		//vby = vn;
		//return true;
	//}
	///end FREQENCY_COUNT_HISTGAM_PLOT_NEED_CENTRLIZE
	/// end MORE_WORK_ON_STATISTICAL_PLOTS
/// Thomas 6/1/06 MOVE_ADDONEROWTOINPUTDATATABLE_FROM_ANOVAREPORTOPERATION_TO_STATSOPBASE

protected:
	virtual bool CreateBinData(TreeNode& trOp, int index, const vector& vdata, vector& vbx, vector& vby, double& dBinMin, double& dBinMax, double& dBinSize)
	{			
		/// YuI 04/01/09 QSA70-13389 BINNING_IS_WRONG_IN_REPORT_HISTOGRAM_FROM_SR4_TO_SR5
		/*
		double dMin, dMax;
		///Arvin 02/13/07 SET_BIN_DATA_WITH_SAME_MIN_MAX_AND_BINSIZE_WHEN_PLOT_ALL_HISTOGRAM_IN_ONE_GRAPH
		///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
		//if( !vdata.GetMinMax(dMin, dMax) )
		//	return false;
		//int nBins = 0.5 + sqrt(vdata.GetSize() + 1);// need customization on this later;
		//if(IsPlotAllPlotsInOneGraph(trOp))
		//{
			//if(!GetCombinedMinMaxAndBinNumber(trOp, dMin, dMax))
				//return false;
		//}
		//else
		//{
		///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
			//if( !vdata.GetMinMax(dMin, dMax) )
				//return false;
			//
			//nBins = 0.5 + sqrt(vdata.GetSize() + 1);// need customization on this later ///Arvin 06/06/07 WRONG_NUMBER_BINS_FOR_HISTOGRAM	
		//} 
		if( !vdata.GetMinMax(dMin, dMax) )
			return false;
		///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
		///end SET_BIN_DATA_WITH_SAME_MIN_MAX_AND_BINSIZE_WHEN_PLOT_ALL_HISTOGRAM_IN_ONE_GRAPH
		///Arvin 06/06/07 WRONG_NUMBER_BINS_FOR_HISTOGRAM
		dBinMin = dMin;
		dBinMax = dMax;	
		//RoundLimits(&dBinMin, &dBinMax, &dBinSize, nBins);
		///Sophy 12/17/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
		//RoundLimits(&dBinMin, &dBinMax, &dBinSize);
		//---- CPY  03/03/2009 QA80-13149 RoundBinningRange_SUPPORT_SPECIFYING_INCREMENT
		//int nSpace;
		//BOOL bRoundToMinorTick;
		//RoundBinningRange(&dBinMin, &dBinMax, vdata.GetSize(), nSpace, &dBinSize, bRoundToMinorTick);
		RoundBinningRange(&dBinMin, &dBinMax, vdata.GetSize(), LINEAR_SPACE, &dBinSize);
		//----
		///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
		///end WRONG_NUMBER_BINS_FOR_HISTOGRAM
		///Sophy 12/17/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
		TreeNode trPlots = trOp.GUI.Plots;
		if ( trPlots )
		{
			TreeNode trHistogram = trPlots.GetNode(op_get_graph_tag_name(GRAPH_STATS_HISTOGRAM));
			if ( trHistogram && tree_is_true(trHistogram) )
			{
				TreeNode trHistogramConfig = trOp.GUI.Output.GetNode(STR_HISTOGRAM_CONFIG_TAGNAME);
				if ( trHistogramConfig )
				{
					dBinMin = trHistogramConfig.Begin.dVal;
					dBinMax = trHistogramConfig.End.dVal;
					dBinSize = trHistogramConfig.BinSize.dVal;
				}
			}
		}
		///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
		vector<int> vn;
		///Sophy 12/23/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS fix bin centers error
		/////Arvin 06/06/07 WRONG_NUMBER_BINS_FOR_HISTOGRAM
		////vdata.FrequencyCount(dBinMin, dBinMax, dBinSize, vn);
		////vdata.FrequencyCount(dBinMin, dBinMax + 0.5*dBinSize, dBinSize, vn);
		/////end WRONG_NUMBER_BINS_FOR_HISTOGRAM
		////vbx.Data(dBinMin + 0.5*dBinSize, dBinMax - 0.5*dBinSize, dBinSize); // bin centers 
		vdata.FrequencyCount(dBinMin, dBinMax, dBinSize, vn);
		vbx.Data(dBinMin, dBinMax, dBinSize);
		///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
		vby = vn;
		return true;
		*/
		
		BOOL bBinCalculationIsNeeded = TRUE;
		/// Iris 11/02/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
		//TreeNode trPlots = trOp.GUI.Plots;
		TreeNode trPlots = OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(trOp.GUI);
		///end OP_DLG_NEW_STRUCTURE
		if ( trPlots )
		{
			TreeNode trHistogram = trPlots.GetNode(op_get_graph_tag_name(GRAPH_STATS_HISTOGRAM));
			if ( trHistogram && tree_is_true(trHistogram) && trHistogram.AutoBin && trHistogram.Begin && trHistogram.End && trHistogram.BinSize )
			{
				/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
				/*
				TreeNode trHistogramConfig = trOp.GUI.Output.GetNode(STR_HISTOGRAM_CONFIG_TAGNAME);
				/// YuI 04/06/09 QA70-12784-P1 HISTOGRAM_CREATE_BY_OPERATION_PROBLEMS
				// if autobin is selected we need to recalculate it for every data
				//	if ( trHistogramConfig )
				if ( trHistogramConfig && 0 == trHistogramConfig.AutoBin.nVal )
				/// end HISTOGRAM_CREATE_BY_OPERATION_PROBLEMS
				if ( 0 == trHistogram.AutoBin.nVal )
				{
					dBinMin = trHistogramConfig.Begin.dVal;
					dBinMax = trHistogramConfig.End.dVal;
					dBinSize = trHistogramConfig.BinSize.dVal;
					bBinCalculationIsNeeded = FALSE;
				}
				*/
				if ( 0 == trHistogram.AutoBin.nVal )
				{
					dBinMin = trHistogram.Begin.dVal;
					dBinMax = trHistogram.End.dVal;
					dBinSize = trHistogram.BinSize.dVal;
					bBinCalculationIsNeeded = FALSE;
				}
				///emd IMPROVE_HISTOGRAM_CONFIG_BRANCH
			}
		}
		if( bBinCalculationIsNeeded )
		{
			double dMin = NANUM;
			double dMax = NANUM;
			if( !vdata.GetMinMax(dMin, dMax) )
				return false;
			dBinMin = dMin;
			dBinMax = dMax;	
		
			RoundBinningRange(&dBinMin, &dBinMax, vdata.GetSize(), LINEAR_SPACE, &dBinSize);
		}
		
		vector<int> vn;
			vdata.FrequencyCount(dBinMin, dBinMax, dBinSize, vn);
		vbx.Data(dBinMin, dBinMax, dBinSize);
		vby = vn;
		return true;
		/// end BINNING_IS_WRONG_IN_REPORT_HISTOGRAM_FROM_SR4_TO_SR5
	}
	
	/// YuI 04/01/09 QSA70-13389 BINNING_IS_WRONG_IN_REPORT_HISTOGRAM_FROM_SR4_TO_SR5
	///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
	//virtual void	GUIOnUpdateTreeBeforeRunning(TreeNode &trGUINew, TreeNode &trGUIOriginal, TreeNode& trOperation)
	virtual void	GUIOnUpdateTreeBeforeRunning(const MultipleVersion& mvOld, TreeNode &trGUINew, TreeNode &trGUIOriginal, TreeNode& trOperation)
	///---END QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
	{
		///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
		//WksReportOperation::GUIOnUpdateTreeBeforeRunning(trGUINew, trGUIOriginal, trOperation);
		WksReportOperation::GUIOnUpdateTreeBeforeRunning(mvOld, trGUINew, trGUIOriginal, trOperation);
		///---END QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
		///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
		if ( is_integer_part_less_then(mvOld.GetVersion(STR_OP_NAME_STATS_BASE), m_mvCur.GetVersion(STR_OP_NAME_STATS_BASE)) )
		{
		///---END QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
			/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
			/*
			TreeNode trHistogramConfigOriginal = trGUIOriginal.Output.GetNode(STR_HISTOGRAM_CONFIG_TAGNAME);
			// if operation was created by the version that did not have HistoghramCOnfig branch
			// we need to udpate it 
			if( !trHistogramConfigOriginal.IsValid() )
			{
				//TreeNode trHistogramConfigNew = trGUINew.Output.GetNode(STR_HISTOGRAM_CONFIG_TAGNAME);
				TreeNode trHistogramConfigNew = GetGUIGraphNodes(trGUINew, GRAPH_STATS_HISTOGRAM);
				if( trHistogramConfigNew )
				{
					_update_histogram_plot_bin_configuration_by_input(trGUINew, trHistogramConfigNew);
				}
			}
			*/
			/// Iris 4/09/2009 QA80-12784-P1 FIX_SR4_ANOVA1WAY_REPORT_FAIL_CHANGE_PARAM_IN_SR5
			if( IDM_PLOT_HISTOGRAM_TYPE == ReportGetPlotTypeFromGraphIndex(GRAPH_STATS_HISTOGRAM) )
			///END FIX_SR4_ANOVA1WAY_REPORT_FAIL_CHANGE_PARAM_IN_SR5
			{
				TreeNode trHistogramOriginal = GetGUIGraphNodesEx(trGUIOriginal, GRAPH_STATS_HISTOGRAM);
				if( 0 == trHistogramOriginal.GetNodeCount() )
				{
					TreeNode trHistogramNew = GetGUIGraphNodesEx(trGUINew, GRAPH_STATS_HISTOGRAM);
					if( trHistogramNew )
					{
						///---Sim 06-18-2009 QA80-13403-P1 FIX_HISTOGRAMS_BIN_SETTINGS_ERROR_WHEN_LOAD_SR4_OPJ
#ifdef __FIX_STATS_COLUMN_HISTOGRAMS_BIN_SETTINGS_WHEN_LOAD_SR4_OPJ
						DWORD dwDataRules = GetDataRules(trOperation);
						pfn_get_input_output_node pfn = Project.FindFunction("get_inputdata_node", "OriginLab\\wksoperation.c", TRUE);
						if ( pfn )
						{
							TreeNode trInput = pfn(trGUINew);
							if ( trInput )
								trInput.SetAttribute(STR_DATA_RULES_ATTRIB, dwDataRules);
						}
#endif // __FIX_STATS_COLUMN_HISTOGRAMS_BIN_SETTINGS_WHEN_LOAD_SR4_OPJ
						///---END QA80-13403-P1 FIX_HISTOGRAMS_BIN_SETTINGS_ERROR_WHEN_LOAD_SR4_OPJ
												
						_update_histogram_plot_bin_configuration_by_input(trGUINew, trHistogramNew);
					}
				}
			}
			///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
			
		}///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
	}
	/// end BINNING_IS_WRONG_IN_REPORT_HISTOGRAM_FROM_SR4_TO_SR5
	
	///Sophy 12/17/2008 v8.0987d  QA80-12784 ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS add for stats tool(stats column, normality test
	bool		AddHistogramPlotConfigBranch(TreeNode& trOperation, TreeNode& trParent)
	{
		if ( !trParent )
			return false;
		
		/// Iris 10/29/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
		//if ( trOperation.GUI.Plots )
		if( OP_GUI_BRANCH_OF_STATS_PLOTS_CHECKBOX(trOperation.GUI) )
		///end OP_DLG_NEW_STRUCTURE
		{
			TreeNode trHistogramPlot = GetGUIGraphNodes(trOperation, GRAPH_STATS_HISTOGRAM);
			if ( trHistogramPlot )
			{
				GETN_USE(trOperation.GUI.Plots)				
				_tmpSubNode = trHistogramPlot; //Sophy, avoid duplicate code in macro GETN_OPTION_EVENT_EX
				/// Iris 4/07/2009 QA80-12784 IMPROVE_HISTOGRAM_CONFIG_BRANCH
				/*
				GETN_OPTION_EVENT_EX(_operation_histogram_plot_changed);				
				
				if ( trParent )
				{
					GETN_USE(trParent)
					GETN_BEGIN_BRANCH(HistogramConfig, STR_OUTPUT_HISTOGRAM_PLOT_CONFIG)
						GETN_CHECK(AutoBin, STR_OUTPUT_HISTOGRAM_PLOT_AUTO_BINNING, true) GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_AUTO) GETN_OPTION_EVENT_EX(_operation_histogram_auto_binning_changed)						
						GETN_NUM(BinSize, STR_OUTPUT_HISTOGRAM_PLOT_BIN_SIZE, 1) GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_SIZE) GETN_OPTION_EVENT_EX(_operation_histogram_customized_binning_changed)
						GETN_NUM(Begin, STR_OUTPUT_HISTOGRAM_PLOT_BEGIN, 0) GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_BEGIN) GETN_OPTION_EVENT_EX(_operation_histogram_customized_binning_changed)
						///Sophy 3/2/2009 v8.0989b FIX_OLD_STATS_OPJ_SHOW_WRONG_ERR_MSG_WHEN_CHANGE_PARAMS_IN_SR5
						//GETN_NUM(End, STR_OUTPUT_HISTOGRAM_PLOT_END, 0) GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_END) GETN_OPTION_EVENT_EX(_operation_histogram_customized_binning_changed)
						GETN_NUM(End, STR_OUTPUT_HISTOGRAM_PLOT_END, 1) GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_END) GETN_OPTION_EVENT_EX(_operation_histogram_customized_binning_changed)
						///end FIX_OLD_STATS_OPJ_SHOW_WRONG_ERR_MSG_WHEN_CHANGE_PARAMS_IN_SR5
						GETN_NUM(NumOfBins, STR_OUTPUT_HISTOGRAM_NUM_OF_BINS, 7) GETN_ID(IDE_HISTOGRAM_GRAPH_NUM_OF_BINS) GETN_READ_ONLY
					GETN_END_BRANCH(HistogramConfig)
				}	
				*/
				_tmpSubNode.ID = TRGP_BRANCH;
				_tmpNode = trHistogramPlot;
				_tmpNode.Use = trHistogramPlot.nVal;
						GETN_CHECK(AutoBin, STR_OUTPUT_HISTOGRAM_PLOT_AUTO_BINNING, true) GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_AUTO) GETN_OPTION_EVENT_EX(_operation_histogram_auto_binning_changed)						
						GETN_STR(BinSize, STR_OUTPUT_HISTOGRAM_PLOT_BIN_SIZE, "") GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_SIZE) GETN_OPTION_EVENT_EX(_operation_histogram_customized_binning_changed)
						GETN_STR(Begin, STR_OUTPUT_HISTOGRAM_PLOT_BEGIN, "") GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_BEGIN) GETN_OPTION_EVENT_EX(_operation_histogram_customized_binning_changed)
						GETN_STR(End, STR_OUTPUT_HISTOGRAM_PLOT_END, "") GETN_ID(IDE_HISTOGRAM_BINS_CONFIG_END) GETN_OPTION_EVENT_EX(_operation_histogram_customized_binning_changed)
						GETN_STR(NumOfBins, STR_OUTPUT_HISTOGRAM_NUM_OF_BINS, "") GETN_ID(IDE_HISTOGRAM_GRAPH_NUM_OF_BINS) GETN_READ_ONLY
				///end IMPROVE_HISTOGRAM_CONFIG_BRANCH
			}
		}
		return true;
	}
	///end ADD_BINNING_CONTROL_FOR_HISTOGRAM_PLOT_IN_STATS_TOOLS
	
	///Arvin 08/30/07 WRONG_INPUT_TABLE_FOR_MULTI_DATA_COLS
	//virtual void AddOneRowToInputDataTable(TreeNode &trInputTable, int index, char chDataFactSubj, int indexAux = 0)
	virtual void AddOneRowToInputDataTable(TreeNode &trInputTable, int index, char chDataFactSubj, int indexAux = 0, int nIndexForCellNode = 1)
	///end WRONG_INPUT_TABLE_FOR_MULTI_DATA_COLS
	{
		int			indexLT = index + 1;
		string		strLabel;
		//int			nIndexForCellNode = 1; ///Arvin 08/30/07 WRONG_INPUT_TABLE_FOR_MULTI_DATA_COLS
		switch(chDataFactSubj)
		{
			case 'D':		// data
				strLabel = _L("Dependent Variable");
				break;
	
			case 'F':		// factors
				if (indexAux < 0)			// one-way
					strLabel = _L("Factor");
				else if (0 < indexAux)
				{
					strLabel = _L("Factor B");
					nIndexForCellNode = 2;
				}
				else
					strLabel = _L("Factor A");
				break;
	
			case 'S':		// subjects
				strLabel = _L("Subjects");
				break;

			default:
				ASSERT(FALSE);
				return;
		}

		TreeNode	trRow = check_add_enumerated_node(trInputTable, "C", indexLT, make_one_set_ID(IDST_REPORT_INPUT_ONE_SET, index), STR_LABEL_ATTRIB, strLabel);
	
		AddOneInputDataTableCell(trRow, _L("Data"), nIndexForCellNode, FALSE, 'P', 0, chDataFactSubj);		// Data
		AddOneInputDataTableCell(trRow, _L("Range"), nIndexForCellNode, FALSE, 'G', 'R', chDataFactSubj);		// Range

	}

/// End MOVE_ADDONEROWTOINPUTDATATABLE_FROM_ANOVAREPORTOPERATION_TO_STATSOPBASE

///Arvin 10/23/06 FITTING_RESIDUALS_HISTOGRAM_PLOT_CENTRALIZED
public:
	bool calcStatsData(TreeNode& trOp, int index, vector& vData, vector& vWeights, double* fromMin = NULL, double* toMax = NULL)
	{
		DescStatResults		stDescStats;
 		vector				vPercents;
		vector				vPercentiles;
		vector<bool>		vShow;
		QuantileResults		stQuantiles;
		if( CalcOneDataMoment(trOp, vData, vWeights, stDescStats) &&
			/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
			//CalcOneDataPercentilesAndRange(trOp, vData, vPercents, vPercentiles, vShow, vWeights, stQuantiles))
			CalcOneDataPercentilesAndRange(trOp, vData, vPercents, vPercentiles, vShow, vWeights, stQuantiles, index))
			///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
   		{
   			TreeNode trStats = getTempStatsTreeNode(trOp, index);
			tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
			if(fromMin && toMax)
				tree_stats_get_set_stats_results(trStats, stDescStats, *fromMin, *toMax, FALSE);
			else
				tree_stats_get_set_stats_results(trStats, stDescStats, stQuantiles.Min, stQuantiles.Max, FALSE);
			return true;

   		}
   		else
   			return false;
	}
///end FITTING_RESIDUALS_HISTOGRAM_PLOT_CENTRALIZED
private:
	/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
	vector				m_vPercents;
	vector<bool>		m_vPercentShow;
	///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
};


#define	TABLE_T_TEST							"tTest"
#define TABLE_CHI_SQUARE						"ChiSquare"
#define TABLE_CONFIDENCE_INTERVAL_FOR_MEAN		"MeanConfInts"
#define TABLE_CONFIDENCE_INTERVAL_FOR_VARIANCE	"Variance"
#define TABLE_POWERS							"Powers"

#define OUTPUT_DESC_STATS						_L("Descriptive Statistics")
#define OUTPUT_TTEST							_L("t-Test")
#define OUTPUT_CONFIDENCE_INTERVAL_FOR_MEAN		_L("Confidence Intervals for Mean")
#define OUTPUT_CHI_SQUARE_TEST					_L("Chi-Square Test")
#define OUTPUT_F_TEST		   					_L("F Test")
#define OUTPUT_CONFIDENCE_INTERVAL_FOR_VARIANCE	_L("Confidence Intervals for Variance")
#define OUTPUT_POWERS							_L("Powers")

#define		LABEL_EQUAL_VAR						_L("Equal Variances assumed")
#define		LABEL_UNEQUAL_VAR					_LE("Equal Variances NOT assumed")

class OC_REGISTERED tTestReportOperation : public StatsOpBase
{
public:
	//---- CPY 5/15/05 CONSOLIDATE_INIT_INPUT_DATA_RANGE
	//bool	InitFromSelection(TreeNode &trOperation);
	//virtual
	DWORD	GetDataRules(const TreeNode& trOp, bool bIgnoreCombineInfo = false )
	{
		/// Iris 9/26/05 QA70-7076-P4 REMOVE_GET_MISSING_DATA_OPTION
		///// Iris 9/09/05 QA70-7074-P6 REMOVE_GROUPING_DATA_OPTION
		////DWORD dwRet =  DRR_GET_MISSING | DRR_NO_WEIGHTS;	
		//DWORD dwRet =  DRR_GET_MISSING | DRR_NO_WEIGHTS | DRR_NO_FACTORS;
		DWORD dwRet =  DRR_NO_WEIGHTS | DRR_NO_FACTORS;
		//////End REMOVE_GROUPING_DATA_OPTION
		///End REMOVE_GET_MISSING_DATA_OPTION
		
		return CheckDataRules(trOp, dwRet, bIgnoreCombineInfo);
	}
	//---- end CONSOLIDATE_INIT_INPUT_DATA_RANGE
	/// Iris 10/21/05 CLEANUP_STATS_REPORT_GRAPH_CODES
	//int		ReportGetPicureIndexFromDataIndex(int nGraphIndex, int nDataIndex);
	//int		ReportGetPlotTypeFromGraphIndex(int nGraphIndex);	
	///End CLEANUP_STATS_REPORT_GRAPH_CODES
	
	void 	UpdateReportingTables(TreeNode &trOperation, int nTotalNumData, int nExeMode);
	void 	ConstructAddtTestReport(TreeNode& trOperation);		

	void 	UpdatatTestTable(TreeNode& trOp, int index, const string strDataLabel, int nCalcResult,
							const tTestResults& tTestResEqual, const tTestResults& tTestResUnequal = NULL);
	bool	AddTTestFootnote(TreeNode& trOp, int nTableID, bool bIstTest, bool bOneSample);

///Kevin 09/01/05 CHANGE_STATISTICS_NAME
	//void 	UpdateMeanConfInsTable(TreeNode& trOp, int index, int nID, int nCalcResult, string strLabel, string strDataLabel, const vector& vPercent, const vector& vLCIs, const vector& vUCIs, bool bPaired = false);
	//void 	UpdateVarianceConfInsTable(TreeNode& trOp,int index, int nID, int nCalcResult, string strTableLabel, string strDataLabel, const vector& vPercent, const vector& vLCIs, const vector& vUCIs);
	void 	UpdateMeanConfInsTable(TreeNode& trOp, int index, int nID, int nCalcResult, string strLabel, string strDataLabel, const vector& vPercent, const vector& vLCLs, const vector& vUCLs, bool bPaired = false);
	void 	UpdateVarianceConfInsTable(TreeNode& trOp,int index, int nID, int nCalcResult, string strLabel, string strDataLabel, const vector& vPercent, const vector& vLCLs, const vector& vUCLs);
///End CHANGE_STATISTICS_NAME
	void 	UpdatePowersTable(TreeNode& trOp, int index, string strDataLabel, int nCalcResult, double& dSigLevel, vector& vSampleSizes, vector& vPowers,  bool bIsActualPower = false);
	
private:
	void 	getRowHeaderNames(int nIndex, int nBaseID, vector<uint>& vuIDs, StringArray& saNames);
///Kevin 09/01/05 CHANGE_STATISTICS_NAME
	//void    insertConfLevelTable(TreeNode& trTable, int index, int nID, string strLabel, string strDataLabel, const vector& vPercent, const vector& vLCIs, const vector& vUCIs);
	void    insertConfLevelTable(TreeNode& trTable, int index, int nID, string strLabel, string strDataLabel, const vector& vPercent, const vector& vLCLs, const vector& vUCLs);
///End CHANGE_STATISTICS_NAME
	void 	addErrorRowToTable(TreeNode& trTable, string strError, int nID);
	void 	errInfoTTest(TreeNode& trTable, int nErr);
	void	errInfoMeanConfIns(TreeNode& trTable, int nErr);
	void	errInfoPower(TreeNode& trTable, int nErr, int nCalc=0);//0, Actual power; 1, Hypothetical power.

};


/// Iris 10/21/05 CLEANUP_STATS_REPORT_GRAPH_CODES
/*
//virtual 
int		tTestReportOperation::ReportGetPicureIndexFromDataIndex(int nGraphIndex, int nDataIndex)
{
	switch( ReportGetPlotTypeFromGraphIndex(nGraphIndex) )
	{			
	case IDM_PLOT_BOX:
		//return 0;
		return nDataIndex;  ///Iris 3/22/05 FIX_GROUP_DATA_ONLY_ONE_BOX_CHART
	}
	
	return -1;
}

//virtual 
int		tTestReportOperation::ReportGetPlotTypeFromGraphIndex(int nGraphIndex)
{
	switch( nGraphIndex )
	{
	case 0:
		return IDM_PLOT_BOX;			
	}
	
	return -1;
}
*/
///End CLEANUP_STATS_REPORT_GRAPH_CODES	
		
//virtual
void 	tTestReportOperation::UpdateReportingTables(TreeNode &trOperation, int nTotalNumData, int nExeMode)
{
	WksReportOperation::UpdateReportingTables(trOperation, nTotalNumData, nExeMode);		
	
	TreeNode 	trCalc = trOperation.Calculation;
	
	TreeNode		trTable = trCalc.Statistics;		
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain(false));		
	else
		error_report("t Test found invalid Calculation.Statistics node");	
	
	trTable = trCalc.GetNode(TABLE_T_TEST);		
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain(false));		
	else
		error_report("t Test found invalid Calculation.tTestResult node");
	
	trTable = trCalc.GetNode(TABLE_CHI_SQUARE);
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain(false));		
	
	trTable = trCalc.GetNode(TABLE_CONFIDENCE_INTERVAL_FOR_MEAN);	
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain());
	
	trTable = trCalc.GetNode(TABLE_CONFIDENCE_INTERVAL_FOR_VARIANCE);
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain());		
	
	trTable = trCalc.GetNode(TABLE_POWERS);
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain(false));	
	
}

void 	tTestReportOperation::ConstructAddtTestReport(TreeNode& trOperation)
{	
	TreeNode 	trOut = trOperation.Calculation; 
	
	trOut.Statistics.ID = IDST_DESC_STATS_RESULTS;
	trOut.tTest.ID = IDST_T_TEST_RESULT;				
	trOut.MeanConfInts.ID = IDST_T_TEST_MEAN_1SAMPLE_RESULTS;			
	trOut.ChiSquare.ID = IDST_CHI_SQ_VAR_1SAMPLE_RESULTS;			
	trOut.Variance.ID = IDST_T_TEST_VARIANCE_1SAMPLE_RESULTS;			
	trOut.Powers.ID = IDST_T_TEST_POWERS_1SAMPLE_RESULTS;
}

void 	tTestReportOperation::UpdatatTestTable(TreeNode& trOp, int index,  const string strDataLabel, int nCalcResult, 
									const tTestResults& tTestResEqual, const tTestResults& tTestResUnequal)
{	
	int nTableID = IDST_T_TEST_RESULT;	
	TreeNode trTable = tree_check_get_node(trOp.Calculation, TABLE_T_TEST, nTableID, STR_LABEL_ATTRIB, OUTPUT_TTEST);
	if( STATS_NO_ERROR !=  nCalcResult)
	{
		errInfoTTest(trTable, nCalcResult);
		return;
	}	 
	
	string strLabel = (NULL == tTestResUnequal) ? strDataLabel : LABEL_EQUAL_VAR;
	
	TreeNode trRow;
	trRow = check_add_enumerated_node(trTable, CALCULATION_REPORT_TABLE_COL_PREFIX, index*2, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, strLabel);				
	trRow += tTestResEqual;		
	trRow.ID = make_one_set_ID(nTableID, index*2);	
	trRow.Prob.SetAttribute(STR_LABEL_ATTRIB, _L("Prob>t")); ///Iris  11/18/05 CONVENTION_NAME_OF_P_VALUE
	
	if( NULL == tTestResUnequal)
		return;	
		
	trRow = check_add_enumerated_node(trTable, CALCULATION_REPORT_TABLE_COL_PREFIX, index*2 + 1, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, GetLocalized(LABEL_UNEQUAL_VAR));				
	trRow += tTestResUnequal;		
	trRow.ID = make_one_set_ID(nTableID, index*2+1);
	trRow.Prob.SetAttribute(STR_LABEL_ATTRIB, _L("Prob>t")); ///Iris  11/18/05 CONVENTION_NAME_OF_P_VALUE
		
}
/// Max 07-11-13 REPLACE_IN_XF_AND_NOT_USED
/*
bool 	tTestReportOperation::AddTTestFootnote(TreeNode& trOp, int nTableID, bool bIstTest, bool bOneSample)
{
	TreeNode	trGUIBranch = bIstTest? trOp.GUI.tTest : trOp.GUI.ChiSquareTest;
	if(!trGUIBranch)
		return false;
	
	//TreeNode trTable = tree_check_get_node(trOp.Calculation, TABLE_T_TEST, IDST_T_TEST_2SAMPLES_RESULT, STR_LABEL_ATTRIB, OUTPUT_TTEST);
	TreeNode trTable = tree_get_node_by_id(trOp.Calculation, nTableID, true);	
	TreeNode trFooter = tree_check_get_node(trTable, "Footnote", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
	
	//1st line
	string strFoot = _LR("Null Hypothesis:") + "" + trGUIBranch.NulHypot.strVal + "\n";
	
	//2nd line
	int nTailTypeComboIndex = trGUIBranch.TailType.nVal;
	string strTailTypeCombo;
	trGUIBranch.TailType.GetAttribute(STR_COMBO_ATTRIB, strTailTypeCombo);
	vector<string> vList;
	strTailTypeCombo.GetTokens(vList, '|');
	strFoot += _LR("Alternative Hypothesis:") + "" +  vList[nTailTypeComboIndex] + "\n";
	
	//remain lines
	int 	nHypotValue = trGUIBranch.HypotValue.nVal;
	TreeNodeCollection trColl(trTable, "P");
	bool beBegin = true;
	foreach(TreeNode trN in trColl)
	{
		if(!beBegin)
			strFoot += "\n";
		beBegin = false;
		
		double 	dPValue;
		if(bIstTest)
			dPValue = trN.Prob.dVal;
		else //ChiSqProb for one sample; FProb for two sample
			dPValue = bOneSample? trN.ChiSqProb.dVal : trN.FProb.dVal;
		
		string 	strSign = dPValue < 0.05? "" : _LR("not");
		strSign += _LR("significantly");
		
		strFoot += _LR("At the 0.05 level,") +"";
		if(bOneSample)
		{
			string	strMeanVariance = bIstTest? _LR("mean") : _LR("variance");
			strFoot += _LR("the difference of the population") + "" + strMeanVariance + "" + _LR("is") + strSign + "" + _LR("different than the") + "" + strMeanVariance + _LR("difference (") + nHypotValue + ").";
		}
		else
		{
			if(bIstTest)
				strFoot += _LR("the difference of the population means is") + "" + strSign + "" + _LR("different than the test difference (") + nHypotValue + ").";
			else
				strFoot += _LR("the ratio of the population variances is") + "" + strSign + "" + _LR("different than the test ratio (") + nHypotValue + ").";
		}
	}
	
	trFooter.strVal = strFoot;
	return true;
}
*/
/// END REPLACE_IN_XF_AND_NOT_USED	
	
///Kevin 09/01/05 CHANGE_STATISTICS_NAME
/*void 	tTestReportOperation::UpdateMeanConfInsTable(TreeNode& trOp, int index, int nID, int nCalcResult, string strLabel, string strDataLabel, 
			const vector& vPercent, const vector& vLCIs, const vector& vUCIs, bool bPaired)*/
void 	tTestReportOperation::UpdateMeanConfInsTable(TreeNode& trOp, int index, int nID, int nCalcResult, string strLabel, string strDataLabel, 
			const vector& vPercent, const vector& vLCLs, const vector& vUCLs, bool bPaired)
///End CHANGE_STATISTICS_NAME
{
	TreeNode trTable = tree_check_get_node(trOp.Calculation, TABLE_CONFIDENCE_INTERVAL_FOR_MEAN, IDST_T_TEST_MEAN_1SAMPLE_RESULTS, STR_LABEL_ATTRIB, OUTPUT_CONFIDENCE_INTERVAL_FOR_MEAN);
		
	if(STATS_NO_ERROR != nCalcResult)
	{
		errInfoMeanConfIns(trTable, nCalcResult);
		return;
	}
	
	//if(0 == strLabel.Compare(LABEL_UNEQUAL_VAR))
	if(compare_string_localization(strLabel, LABEL_UNEQUAL_VAR))
		index = 1;
///Kevin 09/01/05 CHANGE_STATISTICS_NAME
	//insertConfLevelTable(trTable, index, nID, strLabel, strDataLabel, vPercent, vLCIs, vUCIs);
	insertConfLevelTable(trTable, index, nID, strLabel, strDataLabel, vPercent, vLCLs, vUCLs);
///End CHANGE_STATISTICS_NAME			
}

///Kevin 09/01/05 CHANGE_STATISTICS_NAME
/*void 	tTestReportOperation::UpdateVarianceConfInsTable(TreeNode& trOp, int index, int nID, int nCalcResult, string strTableLabel, 
				string strDataLabel, const vector& vPercent, const vector& vLCIs, const vector& vUCIs)*/
void 	tTestReportOperation::UpdateVarianceConfInsTable(TreeNode& trOp, int index, int nID, int nCalcResult, string strLabel, 
				string strDataLabel, const vector& vPercent, const vector& vLCLs, const vector& vUCLs)
///End CHANGE_STATISTICS_NAME
{
	TreeNode trTable = tree_check_get_node(trOp.Calculation, TABLE_CONFIDENCE_INTERVAL_FOR_VARIANCE, IDST_T_TEST_VARIANCE_1SAMPLE_RESULTS, STR_LABEL_ATTRIB, OUTPUT_CONFIDENCE_INTERVAL_FOR_VARIANCE);
	if(STATS_NO_ERROR != nCalcResult)
	{
		errInfoMeanConfIns(trTable, nCalcResult);
		return;
	}
	
///Kevin 09/01/05 CHANGE_STATISTICS_NAME
	//insertConfLevelTable(trTable, index, nID, "", strDataLabel, vPercent, vLCIs, vUCIs);
	insertConfLevelTable(trTable, index, nID, strLabel, strDataLabel, vPercent, vLCLs, vUCLs);
///End CHANGE_STATISTICS_NAME
}

void 	tTestReportOperation::UpdatePowersTable(TreeNode& trOp, int index, string strDataLabel, int nCalcResult, double& dSigLevel, vector& vSampleSizes, vector& vPowers,  bool bIsActualPower)
{
	TreeNode		trTable = tree_check_get_node(trOp.Calculation, TABLE_POWERS, IDST_T_TEST_POWERS_1SAMPLE_RESULTS + index, STR_LABEL_ATTRIB, OUTPUT_POWERS); //Label is Powers
	
	if(STATS_NO_ERROR != nCalcResult)		
	{
		errInfoPower(trTable, nCalcResult, 0);
		return;
	}
	
	PowerResults*	pstPowers;
	pstPowers = (PowerResults*)calloc(vPowers.GetSize(), sizeof(PowerResults));	
	stats_power_output(vPowers, vSampleSizes, dSigLevel, pstPowers, vPowers.GetSize());
	
	int 	nRow;
	string 	strLabel;
	if(bIsActualPower)
	{
		//nRow = 0;
		//------ Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE
		//strLabel = _LR("Actual Power");
		strLabel = _LC("Actual Power", STR_CAT_STATS);
		//------ End CATEGORY_NEEDED_WHEN_LOCALIZE
	}
	else
	{
		//nRow = 1;
		//------ Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE
		//strLabel = _LR("Hypothesis Powers");
		strLabel = _LC("Hypothesis Powers", STR_CAT_STATS);
		//------ End CATEGORY_NEEDED_WHEN_LOCALIZE
	}
	
	vector<string> vsEmpty;
	string strRowName = "Row";
	TreeNodeCollection trColl(trTable, strRowName);
	int nCount = trColl.Count();
	for(int ii=0; ii<vPowers.GetSize(); ii++)
	{
		nRow = nCount + ii;
		if( strDataLabel.IsEmpty() )
			strDataLabel = strLabel;
		
		TreeNode trRow = tree_check_get_node(trTable, strRowName + nRow, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, strDataLabel);
		if( strDataLabel != strLabel)
			tree_add_more_labels(trRow, vsEmpty, 0, strLabel);
		
		trRow += pstPowers[ii];
		trRow.ID = make_one_set_ID( IDST_T_TEST_POWERS_1SAMPLE_RESULTS, nRow + 1);					
	}
	free(pstPowers);
	
}
	
void 	tTestReportOperation::getRowHeaderNames(int nIndex, int nBaseID, vector<uint>& vuIDs, StringArray& saNames)
{
	int nRows = 3;
	if(vuIDs)
		vuIDs.RemoveAll();		
	for(int nRow=0; nRow< nRows; nRow++)
	{
		vuIDs.Add( make_one_set_ID(nBaseID, nIndex*nRows  + nRow) );
	}
	if(saNames)
	{
		saNames.SetSize( nRows );		
		saNames[0] = "Levels" + nIndex;
///Kevin 09/01/05 CHANGE_STATISTICS_NAME
		//saNames[1] = "LCI" + nIndex;
		//saNames[2] = "UCI" + nIndex;
		saNames[1] = "LCL" + nIndex;
		saNames[2] = "UCL" + nIndex;
///End CHANGE_STATISTICS_NAME
	}
	
}

///Kevin 09/01/05 CHANGE_STATISTICS_NAME
//void    tTestReportOperation::insertConfLevelTable(TreeNode& trTable, int index, int nID, string strLabel, string strDataLabel, const vector& vPercent, const vector& vLCIs, const vector& vUCIs)
void    tTestReportOperation::insertConfLevelTable(TreeNode& trTable, int index, int nID, string strLabel, string strDataLabel, const vector& vPercent, const vector& vLCLs, const vector& vUCLs)
///End CHANGE_STATISTICS_NAME
{
	vector<uint> 	vuIDs;
	StringArray 	saNames;
	getRowHeaderNames(index, nID, vuIDs, saNames);	

	int 			ii, nLabelRow = 0;
	/// Iris 12/12/05 CLERNUP_TTEST_CODES
	/*
	vector<string> 	vsEmpty, vsLabels;
	if( !strLabel.IsEmpty() )
		vsLabels.Add(strLabel);
	if( !strDataLabel.IsEmpty() )
	vsLabels.Add(strDataLabel);	
	*/
	strLabel = strLabel.IsEmpty()? strDataLabel : strLabel;
	int nLabelIndex = strLabel.IsEmpty()? -1 : 0;
	///End CLERNUP_TTEST_CODES
	
	if(0 == index)
	{	
		/// Iris 12/12/05 CLERNUP_TTEST_CODES
		/*
		vsLabels.Add("Levels");
	
		TreeNode	trLevels = tree_check_get_node(trTable, saNames[0], vuIDs[0], STR_LABEL_ATTRIB, vsLabels[0]);
		for(ii=1, nLabelRow=0; ii<vsLabels.GetSize(); ii++)
		{
			tree_add_more_labels(trLevels, vsEmpty, nLabelRow, vsLabels[ii]);
		}
		trLevels.dVals = vPercent;
		vsLabels.RemoveAt(vsLabels.GetSize()-1);
		*/
		TreeNode	trLevels = tree_check_get_node(trTable, saNames[0], vuIDs[0], STR_LABEL_ATTRIB, " ");
		tree_add_one_label(trLevels, _LR("Levels"), nLabelIndex); 
		trLevels.dVals = vPercent;
		///End CLERNUP_TTEST_CODES
	}
	
	/// Iris 12/12/05 CLERNUP_TTEST_CODES
	/*
	vsLabels.Add("LCLs");
	TreeNode	trLCL = tree_check_get_node(trTable, saNames[1], vuIDs[1], STR_LABEL_ATTRIB, vsLabels[0]);
	for(ii=1, nLabelRow=0; ii<vsLabels.GetSize(); ii++)
	{
		tree_add_more_labels(trLCL, vsEmpty, nLabelRow++, vsLabels[ii]);
	}
	*/
	TreeNode	trLCL = tree_check_get_node(trTable, saNames[1], vuIDs[1], STR_LABEL_ATTRIB, strLabel);
	tree_add_one_label(trLCL, _LR("LCLs"), nLabelIndex);
	///End CLERNUP_TTEST_CODES
	trLCL.dVals = vLCLs;

	/// Iris 12/12/05 CLERNUP_TTEST_CODES
	/*
	vsLabels.RemoveAt(vsLabels.GetSize()-1);
	vsLabels.Add("UCLs");
	TreeNode	trUCL = tree_check_get_node(trTable, saNames[2], vuIDs[2], STR_LABEL_ATTRIB, vsLabels[0]);
	for(ii=1, nLabelRow=0; ii<vsLabels.GetSize(); ii++)
	{
		tree_add_more_labels(trUCL, vsEmpty, nLabelRow++, vsLabels[ii]);
	}
	*/
	TreeNode	trUCL = tree_check_get_node(trTable, saNames[2], vuIDs[2], STR_LABEL_ATTRIB, strLabel);
	tree_add_one_label(trUCL, _LR("UCLs"), nLabelIndex);
	///End CLERNUP_TTEST_CODES	
	trUCL.dVals = vUCLs;

}
	
void 	tTestReportOperation::addErrorRowToTable(TreeNode& trTable, string strError, int nID)
{
	TreeNode    trRow = tree_check_get_node(trTable, "Error", nID, STR_LABEL_ATTRIB, _LR("Attention!"));
	trRow.strVal = strError;
}

void 	tTestReportOperation::errInfoTTest(TreeNode& trTable, int nErr)
{
	if (nErr == STATS_ERROR_ALL_ELEMENT_EQUAL)
		addErrorRowToTable(trTable, "All the values must not be equal!", IDST_T_TEST_RESULT);
	if( nErr == STATS_ERROR_DATA_DIFF_SIZE)
		addErrorRowToTable(trTable, "The size of input values must be equal for pair!", IDST_T_TEST_RESULT);		
}

void	tTestReportOperation::errInfoMeanConfIns(TreeNode& trTable, int nErr)
{
	if (nErr == STATS_ERROR_ALL_ELEMENT_EQUAL)
		addErrorRowToTable(trTable, "All the values must not be equal!", IDST_T_TEST_MEAN_1SAMPLE_RESULTS);
}

void	tTestReportOperation::errInfoPower(TreeNode& trTable, int nErr, int nCalc)//=0
{
	if (STATS_ERROR_TOO_FEW_DATA_PTS == nErr)
		addErrorRowToTable(trTable, "Hypothetical sample size need not be less than 1!", IDST_T_TEST_POWERS_1SAMPLE_RESULTS);					
	if( STATS_ERROR_SETTING == nErr)
		addErrorRowToTable(trTable, "Error setting", IDST_T_TEST_POWERS_1SAMPLE_RESULTS);				
		
}

enum{
	GRAPH_STATS_BAR,	
	GRAPH_STATS_BOX_PLOT,
	GRAPH_STATS_MEANS_SD_PLOT, 
	GRAPH_STATS_MEANS_SE_PLOT, 
	GRAPH_STATS_MEANS_COMP_PLOT
};

/// Iris 3/20/2008 v8.0828 QA80-11676-P1 MEANS_COMP_PLOT_NEED_SMYBOL_INDEXED_BY_SIG_COL
#define		SYMBOL_COLOR_INDEX_OFFSET	100
#define		SYMBOL_COLOR_MAP_OFFSET		4194404  /// Iris 4/17/2008 QA80-11676 MEANS_COMP_PLOT_CHANGE_SMYBAO_TO_COLOR_MAP_ON_SIG
enum{
	MEANS_COMP_COL_INDEX = -1,
	MEANS_COMP_COL_MEANDIFF,
	MEANS_COMP_COL_SEM,
	MEANS_COMP_COL_SIG
};
///END MEANS_COMP_PLOT_NEED_SMYBOL_INDEXED_BY_SIG_COL

#define STAT_MEANS_SD_PLOT_REPORT_LABEL _L("Means Plot (SD as Error)")
#define STAT_MEANS_SE_PLOT_REPORT_LABEL _L("Means Plot (SE as Error)")
#define STAT_BAR_REPORT_LABEL 			_L("Bar Chart")
#define STAR_MEAN_DIFF_LABEL			_L("Means Comparison Plot")

class OC_REGISTERED ANOVAReportOperation : public StatsOpBase
{
protected:
	/// YuI 09/10/07 QA70-10358 ANOVA_RECALCULATE_FAILS_AFTER_RENAME
	virtual DWORD	GetDWCTRLForUpdateInputDataTree()	{return TREE_COPY_BY_ORDER_ONLY;}
	/// end ANOVA_RECALCULATE_FAILS_AFTER_RENAME
	//virtual
	string  GetResultCurveGUIName(TreeNode& trGUI);  /// Iris 5/30/2008 CENTRALIZE_SET_RESULT_CURVE_BRANCH_NAME_CODES

	virtual void 	ConstructOutputTable(TreeNode& trOperation);
	///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	//virtual DWORD	GetOutputOptions();
	virtual DWORD	GetOutputOptions(const TreeNode& trOp);
	///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	
	/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	int 	ConstructGraphNumber() 	{ return 0; }
	
	string 	GetGraphTemplate(int nGraphIndex = 0);
	
	int		ReportGetPicureIndexFromDataIndex(int nGraphIndex, int nDataIndex);
	
	int		ReportGetPlotTypeFromGraphIndex(int nGraphIndex);
	
	string 	GetResultCurveBookName(TreeNode& trOperation, int nDataIndex = 0, int nOption = -1, bool bSeparateSheetForDataset = false);
	
	/// Iris 4/11/2008 SET_BOTH_LONG_NAME_AND_SHORT_NAME_FOR_REPORT_BOOK
	//virtual
	string 	GetResultCurveBookShortName(TreeNode& trOperation, int nIndex = 0, int nOption = -1);
	///end SET_BOTH_LONG_NAME_AND_SHORT_NAME_FOR_REPORT_BOOK
	
	bool 	GetCustomGraphTypeName(string& strName, int nIndex = 0);
	
	virtual uint GetResultCurveTableID(TreeNode& trOp, int nDataIndex, int nTotalNumData = -1, int nGraphIndex = 0);
	
	bool 	IsGraphTableInsertBackToSourceType(int nGraphIndex);
	
	string	GetResultCurveSheetName(TreeNode& trOperation, int nIndex = 0, int nOption = OUTPUT_RESULT_CURVE_FIT_CURVES_SHEET);
	
	bool 	IsOutputSeparateResultCurveSheet(const TreeNode& trOp);	
	
	int 	GetTotalNumPictureForOneGraphType(TreeNode& trOp, int nGraphIndex = -1);
	
	string  GetReportGraphLabel(TreeNode& trOp, int nGraphIndex, int nPicRow, int nPicCol);
	////end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	
	///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	virtual bool IsCreateHistogramGraph(TreeNode& trOp)
	{
		return false;
	}
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	
	///Cheney 2007-10-25 ANOVA_TOOLS_HANDLE_AUTO_WRONG
	//virtual
	int	GetReportOutPutDestination(const TreeNode& trInput);	
	virtual bool GetAnovaToolsOption(bool bRow, int& nOption){ return false; }
	///end ANOVA_TOOLS_HANDLE_AUTO_WRONG
	///Arvin 01/15/08 SHOULD_REMOVE_MEAN_SD_SE_TABLE_AFTER_RECALCULATE
	//virtual
	/// Hong 08/12/08 QA80-11986 FIX_FITTED_CURVE_PLOT_FAIL_RESCALE_WHEN_SOURCE_PLOT_HAVE_ERR_BAR
	//virtual void RescaleReportGraph(TreeNode& trOp, GraphLayer& gl, int nGraphIndex, int nPicRowIndex, int nPicColIndex);
	virtual void RescaleReportGraph(TreeNode& trOp, GraphLayer& gl, int nGraphIndex, int nPicRowIndex, int nPicColIndex, int nFirstFittedPlotIndex);
	/// end FIX_FITTED_CURVE_PLOT_FAIL_RESCALE_WHEN_SOURCE_PLOT_HAVE_ERR_BAR
	///end SHOULD_REMOVE_MEAN_SD_SE_TABLE_AFTER_RECALCULATE
		
	//virtual 
	bool SetupPlotDetails(const TreeNode& trOp, GraphLayer& gl, int nFittedPlot, int nNumPlots = 1, int nGraphIndex = 0, int nDataIndex = 0, bool bIsSourceGraph = false, bool bUpdateExistedReportGraph = false);/// Iris 3/20/2008 v8.0828 QA80-11676-P1 MEANS_COMP_PLOT_NEED_SMYBOL_INDEXED_BY_SIG_COL
	
	/// Iris 10/28/2009 QA81-14546 CHANGE_GUI_REPORT_TABLE_LABEL
	/*
	//virtual	
	string	GetReportTableGUIName(TreeNode& trGUI); /// Iris 4/17/2008 SPECIAL_REPORT_TABLE_NAME_FOR_DIFF_TOOLS
	*/
	///end CHANGE_GUI_REPORT_TABLE_LABEL
	
	//virtual
	bool	InitOutputGUIManagerPointer(const TreeNode& trGUI);  /// Iris 5/27/2008 v8.0871 NO_RESULT_CURVE_REPORT_IN_1WAY_ANOVA

	/// TD ML 05-30-2008 QA80-11622 UPDATING_ANOVA_HANDLERS_ON_RECALCULATE_FROM_OPJ
	//virtual 
	/// YuI 06/06/08 QA70-11619 MORE_CLEAR_WORKSHEET_PROBLEM
	//	void	GUIOnUpdateTreeBeforeRunning(TreeNode &trGUINew, TreeNode &trGUIOriginal)
	///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
	//void	GUIOnUpdateTreeBeforeRunning(TreeNode &trGUINew, TreeNode &trGUIOriginal, TreeNode& trOperation)
	void	GUIOnUpdateTreeBeforeRunning(const MultipleVersion& mvOld, TreeNode &trGUINew, TreeNode &trGUIOriginal, TreeNode& trOperation)
	///---END QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
	/// end MORE_CLEAR_WORKSHEET_PROBLEM
	{
		TreeNode	trInputData = trGUINew.InputData;
		okutil_anova_update_handlers(&trInputData, IsOneWay(), IsRM());
		/// YuI 06/06/08 QA70-11619 MORE_CLEAR_WORKSHEET_PROBLEM
		//	StatsOpBase::GUIOnUpdateTreeBeforeRunning(trGUINew, trGUIOriginal);
		///---Sim 04-02-2009 QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
		//StatsOpBase::GUIOnUpdateTreeBeforeRunning(trGUINew, trGUIOriginal, trOperation);
		StatsOpBase::GUIOnUpdateTreeBeforeRunning(mvOld, trGUINew, trGUIOriginal, trOperation);
		///---END QA80-13403 ADD_INDIVIDUAL_OP_VERSION_FOR_CONVERT_GUI_TREE
		/// end MORE_CLEAR_WORKSHEET_PROBLEM
	}
	/// end UPDATING_ANOVA_HANDLERS_ON_RECALCULATE_FROM_OPJ
	///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	virtual bool		IsPlotAllPlotsInOneGraph(TreeNode& trOperation, int nGraphIndex = -1);
	///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
	///Arvin 01/28/07 SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER
	virtual void 	CheckRemoveAndDestroyOutput(TreeNode& trOperation);
	///end SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER

	//virtual
	bool	IsPlotStatsGraph(TreeNode& trOp); /// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
public:	
	void    UpdateOverallANOVAColumnLabel(TreeNode& trRow);
	/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	//void	GetMeanCompColumnLabels(const vector<string>& vsFactors, vector<string>& vsCompLabels);
	void	GetMeanCompColumnLabels(TreeNode &trOp, const vector<string> &vsFactors, vector<string> &vsCompLabels, bool bIsDunnType = false, int nFactorIndex = 1, bool bInteraction = false);
	///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	void    SetupMeanCompasionTableRows(TreeNode &trRow, int nType);
	void    UpdateMeanCompasionStatRowName(TreeNode &trTable, int nType);
	/// Iris 3/02/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE
	// nPairwiseComparisonTableIndex only effect on Two Way ANOVA
	//void 	GetMeanCompNodeInfo(string& strName, string &strLabel, int &nID, int nType = ANOVA_BONFERRON);
	void 	GetMeanCompNodeInfo(string& strName, string &strLabel, int &nID, int nType = ANOVA_BONFERRON, int nPairwiseComparisonTableIndex = 0);
	///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE
	
	//---- CPY 5/15/05 CONSOLIDATE_INIT_INPUT_DATA_RANGE
	//bool	InitFromSelection(TreeNode &trOperation);
	//virtual
	DWORD	GetDataRules(const TreeNode& trOp, bool bIgnoreCombineInfo = false )
	{
		DWORD dwRet = DRR_NO_WEIGHTS;
  
		/// ML 10/24/2005 ANOVAS_INDEXED_RAW
		//return CheckDataRules(trOp, dwRet, bIgnoreCombineInfo);
		//
		// ANOVAs never use combined modes.
		return CheckDataRules(trOp, dwRet, true);
		/// end ANOVAS_INDEXED_RAW
	}
	//---- end CONSOLIDATE_INIT_INPUT_DATA_RANGE
	/// YuI 09/26/05 ANOVA_DATA_SELECTION_GUI
	virtual bool	IsRM()		{return false;}
	/// end ANOVA_DATA_SELECTION_GUI
	
	/// ML 11/20/2007 QA70-10716 INPUT_DATA_NODE_PROPER_LANGUAGE_WHEN_LOADING_OPER
	// virtual
	int		getLocUpdateInputDataStringsMode();
	// virtual
	bool	customLocUpdateInputDataStrings(TreeNode &trInputDataConstructed, TreeNode &trInputDataLoaded);
	/// end INPUT_DATA_NODE_PROPER_LANGUAGE_WHEN_LOADING_OPER

	
	/// ML 10/26/2005 QA70-8225 ESCAPED_OPER_STRINGS_ANOVAS
	bool	IsIndexedData(TreeNode &trOp);
	// virtual
	void	UpdateDataSourceInReportingHeader(TreeNode &trInputTable, const vector<string> &vstrFactors, int ii, LPCSTR lpcszXLabel = NULL, int numSubRanges = 0, DWORD dwRules = 0);
	
	/// Thomas 6/1/06 MOVE_ADDONEROWTOINPUTDATATABLE_FROM_ANOVAREPORTOPERATION_TO_STATSOPBASE
	//void	AddOneRowToInputDataTable(TreeNode &trInputTable, int index, char chDataFactSubj, int indexAux = 0);
	/// End MOVE_ADDONEROWTOINPUTDATATABLE_FROM_ANOVAREPORTOPERATION_TO_STATSOPBASE
	
	/// end ESCAPED_OPER_STRINGS_ANOVAS

	/// Iris 12/13/05 ADD_CONTROL_LEVEL_FOR_DUNNETT_MEAN_COMP
	bool	OnLevelNameChange(TreeNode &trOperation, bool bTwoWay = false);
	bool 	initControlListForOneWay(TreeNode &trInputData);
	bool 	initControlListForTwoWay(TreeNode &trInputData);
	bool 	initControlList(TreeNode &trLevels, int nDataType);
	///End ADD_CONTROL_LEVEL_FOR_DUNNETT_MEAN_COMP
	
	/// Iris 12/27/05
	virtual bool	IsOneWay()		{return true;}
	virtual bool	GetFactors(TreeNode &trOp, int index = 0, const vector<string> &vstrFactors = NULL);
	BOOL 	Construct(TreeNode& trOperation, int nOption);
	int		GetDRTreeOption(TreeNode &trOperation);
	void	GetDependentData(const vector& vData);
	void	GetWeights(vector vWeights);	
	///End 
	
	/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	//void 	AddReportCurveTables(TreeNode &trOp, int nTotalNumData, string strLabel);
	void 	AddReportCurveTables(TreeNode &trOp, int nTotalNumData, string strLabel, int index = 0);
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	bool 	GetDescStatsValues(TreeNode& trOp, vector& vMeans = NULL, vector& vSD = NULL, vector& vSE = NULL);
	///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	
	///Arvin 10/17/07 CLEAN_ANOVA_TOOLS_CODE
	int OnInitOperationTreeFromOCLT(TreeNode &trOp, TreeNode& trOCLT, bool bInitTree = true);
	///end CLEAN_ANOVA_TOOLS_CODE
	
private:
	void    getLevelsNameForRow(TreeNode &trInput, vector<string>& vsFactors, int index, int nFactor);
	///Arvin 09/26/07 QA70-10421 WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
	//void    getFactorNameForIndexed(TreeNode &trInput, string& strName, bool bIsOneWay = true, int nFactor = 0);
	///end WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
	
	/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	int		getMeanDiffTableNumber(TreeNode& trOp);
	///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	//void 	addBarDataTable(TreeNode& trOp);
	//void 	addMeansWksTable(TreeNode& trOp, int nGraphIndex, string strTable, int nID, 
	//					const vector<string>& vsNames, const vector<string>& vsLabels, bool bIsSD = true);						
	//void 	addMeansSDWksTable(TreeNode& trOp);
	//void	addMeansSEWksTable(TreeNode& trOp);
	//void	addMeansDiffWksTable(TreeNode& trOp);
	void 	addBarDataTable(TreeNode& trOp, int index = 0);
	void 	addMeansWksTable(TreeNode& trOp, int nGraphIndex, string strTable, int nID, 
						const vector<string>& vsNames, const vector<string>& vsLabels, bool bIsSD = true, int index = 0);						
	void 	addMeansSDWksTable(TreeNode& trOp, int index = 0);
	void	addMeansSEWksTable(TreeNode& trOp, int index = 0);
	void	addMeansDiffWksTable(TreeNode& trOp, int index = 0);
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	void 	addNodeToMeanWksTable(TreeNode& trTable, vector<string> vsNames, vector<string> vsLabels, int nBaseID);
	bool	addOneMeansDiffWksTable(TreeNode& trOp, int iType, int index);	
	///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	
	///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	TreeNode    getOneMeanDiffResultNode(TreeNode& trOp, int iType, string& strName = NULL, string& strLabel = NULL, int* pID = NULL);
	bool getOneMeanDiffSigValues(TreeNode& trOp, int iType, vector& vSig);
	void getMeanDiffPlotTypes(TreeNode& trOp, vector& vTypes);
	///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	string 	getStrFromSigValue(int nSigValue); /// Iris 3/20/2008 v8.0828 QA80-11676-P2 BETTER_LEGEND_FOR_MEAN_COMP_PLOT

	/// Iris 4/02/2009 QA80-13392-P2 IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE
	void 	updateIndexedDataSourceInReportingHeader(TreeNode &trInputTable, const vector<string> &vstrFactors, int ii, LPCSTR lpcszXLabel = NULL, int numSubRanges = 0, DWORD dwRules = 0);
	void 	updateRawDataSourceInReportingHeader(TreeNode &trInputTable, const vector<string> &vstrFactors, int ii, LPCSTR lpcszXLabel = NULL, int numSubRanges = 0, DWORD dwRules = 0);
	///end IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE

protected:
	///Arvin 10/17/07 CLEAN_ANOVA_TOOLS_CODE
	bool 	AddMeanComparisonFootnote(TreeNode &trOp); 
	void 	AddErrorRowToTable(TreeNode& trTable, string strError, int nID);
	void 	AddErrInfoToTable(TreeNode& trTable, int nID, int nErr, bool bOneWay = true);
	int 	GetPowerInfo(TreeNode trOp);
	bool 	GetSampleSizeByPowerType(const TreeNode& trOp, int iPower, int iLevels, vector& vSampleSizes);
	void    AddPowerTableRows(TreeNode trTable, vector vPowers, vector vSampleSizes, double dSigLevel, int iPower, int nID, int nRet);
	bool	AddMeanComparisonRows(TreeNode& trOp, TreeNode& trTable, const vector<string>& vsFactors, MeanCompStats* pstMeanCompstats, int nSizeMeanComp, int nID, int nIntervalType);
	///end CLEAN_ANOVA_TOOLS_CODE
	
	///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	bool  AppendLegendForAddedPlot(TreeNode& trOp, GraphLayer& gl,  int nPlotIndex, LPCSTR lpcszExtraFormat, int nGraphIndex, int nPictureIndex);
	///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO

	/// YuI 09/27/06 TWO_WAY_ANOVA_TREE_RESOLUTION_SCREWUP
	virtual void	GetRelevantInputDataTreeNode(TreeNode& trOp, TreeNode& trRelevant, TreeNode& trInputData)
	{
		// in case of Raw we need resolve only Data branch
		int nUse;
		if( trInputData.GetAttribute(STR_USE_ATTRIB, nUse) && nUse != 0 )
			trRelevant = trInputData.Data;
		else
			trRelevant = trInputData;
	}
	/// end TWO_WAY_ANOVA_TREE_RESOLUTION_SCREWUP
	
	///Arvin 09/26/07 QA70-10421 WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
	void    GetFactorNameForIndexed(TreeNode &trInput, string& strName, bool bIsOneWay = true, int nFactor = 0);
	///end WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
	
	///Arvin 01/07/08 QA70-10903 ADD_CHECK_ALL_BOX_FOR_BRANCH
	virtual bool AddCheckAllBoxForPlotsNode(TreeNode& trPlots)
	{
		return tree_set_branch_attribute_for_branch(trPlots, GETNBRANCH_CHECK_CONTROL|GETNBRANCH_CHECK_CONTROL_ONE_EVENT);
	}
	///end ADD_CHECK_ALL_BOX_FOR_BRANCH
	
	///Arvin  01/31/08 ANOVA_REPORT_DATA_SHOULD_NOT_OUTPUT_TO_SOURCE 
	bool 	IsAllowReportToSource(TreeNode& trGUI) {return false;}
	///end ANOVA_REPORT_DATA_SHOULD_NOT_OUTPUT_TO_SOURCE
protected:	
	vector				m_vData;
	vector<int>			m_vnIndex;
	vector<string>		m_vsFactors; //the factor levels
	vector<string>		m_vsFactors2; //the second factor levels for two way anova // the RV or Non RV factor levels for two wan RM anova
	
	vector				m_vWeights;
	int					m_nFactors;
	string				m_strFactor; //the name of factor
	string				m_strFactor2; //the name of the second factor name for two way anova // the RV or Non RV factor name for two wan RM anova


};

///Arvin 01/28/07 SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER
//virtual 
void  ANOVAReportOperation::CheckRemoveAndDestroyOutput(TreeNode& trOperation)
{
	bool			bKeepAttrib = true;
	vector<int>    	vnGraphIndex = {GRAPH_STATS_BAR,	
									GRAPH_STATS_BOX_PLOT,
									GRAPH_STATS_MEANS_SD_PLOT, 
									GRAPH_STATS_MEANS_SE_PLOT, 
									GRAPH_STATS_MEANS_COMP_PLOT};
	int 			nDataIndex = 0;
	TreeNode 		trRC = GetResultCurvesBranch(trOperation, nDataIndex, -1);
	while(trRC)
	{
		for(int ii = 0; ii < vnGraphIndex.GetSize(); ii++)
		{
			DataRange rgFitCurvesTable;
			int 		nGraphIndex = vnGraphIndex[ii];
			if(GetResultCurvesDataRange(trOperation, rgFitCurvesTable, nDataIndex, nGraphIndex, GetOutputRangeIndex(trOperation, nGraphIndex)) && rgFitCurvesTable)
			{
				RemoveOutput(rgFitCurvesTable);
				
				int c1, c2;
				Worksheet wks;
				int nColBegin = -1, nColEnd = -1;
				int nNumRanges = rgFitCurvesTable.GetNumRanges();
				for(int iRange = 0; iRange < nNumRanges; iRange++)
				{
					rgFitCurvesTable.GetRange(wks, c1, c2, iRange);
					if(c2 >= c1 && c1 >= 0)
					{
						if(nColBegin < 0 || c1 < nColBegin)
							nColBegin = c1;
						if(c2 > nColEnd)
							nColEnd = c2;
					}
				}
				
				if(wks)
				{
					int nCols = wks.GetNumCols();
					if(nColBegin == 0 && nColEnd == nCols-1)
						wks.Destroy();
					else
					{
						for(int iCol = nColEnd; iCol >= nColBegin; iCol--)
							wks.DeleteCol(iCol);
					}
				}
			}
		}
		trRC.Remove();
		nDataIndex++;
		trRC = GetResultCurvesBranch(trOperation, nDataIndex, -1);
	}
}
///end SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER
	
/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
bool	ANOVAReportOperation::IsPlotStatsGraph(TreeNode& trOp)
{
	TreeNode trBoxPlot = GetGUIGraphNodes(trOp, GRAPH_STATS_BOX);
	if( trBoxPlot && trBoxPlot.nVal )
		return true;
	return false;	
}
///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED

///Arvin 10/17/07 CLEAN_ANOVA_TOOLS_CODE
int ANOVAReportOperation::OnInitOperationTreeFromOCLT(TreeNode &trOp, TreeNode& trOCLT, bool bInitTree)
{
	int nRet;
	TreeNode trOutGUI = trOCLT.GetNode("GUI");
	TreeNode trInputData = trOutGUI.InputData;
	if(!trInputData)
		return OP_INVALID_INPUT_DATA_NODE;
		
	if(ANOVA_INDEXED_DATA == trInputData.Use)
	{
		/// Iris 4/09/2010 QA81-15296 FIX_INCORRECT_INPUTDATA_GUI_FOR_XOP_ONE_WAY_ANOVA
		//nRet = okutil_anova_switch_to_indexed_data(&trInputData, true, false);			
		nRet = okutil_anova_switch_to_indexed_data(&trInputData, !IsOneWay(), IsRM());
		///End FIX_INCORRECT_INPUTDATA_GUI_FOR_XOP_ONE_WAY_ANOVA
	}
	else
	{
		/// Iris 4/09/2010 QA81-15296 FIX_INCORRECT_INPUTDATA_GUI_FOR_XOP_ONE_WAY_ANOVA
		//nRet = okutil_anova_switch_to_raw_data(&trInputData, true, false);
		nRet = okutil_anova_switch_to_raw_data(&trInputData, !IsOneWay(), IsRM());
		///End FIX_INCORRECT_INPUTDATA_GUI_FOR_XOP_ONE_WAY_ANOVA
	}
		
	return nRet;
}

bool ANOVAReportOperation::AddMeanComparisonFootnote(TreeNode &trOp)
{
	TreeNode	trRoot = tree_check_get_node(trOp.Calculation, "ANOVAs", IDST_ANOVAS);
	TreeNode 	trMeanComp = tree_check_get_node(trRoot, "MeanComp", IDST_ANOVAS_MEAN_COMP, STR_LABEL_ATTRIB, _L("Means Comparisons"));
	TreeNode 	trFooter = tree_check_get_node(trMeanComp, "Footnote", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
	string strSigLevel;
	///Arvin 07/17/07 v8.0661 WRONG_DOUBLE_PRESION_NUMBER
	//strSigLevel.Format("%f",trOp.GUI.MeansComp.SigLevel.dVal);
	double dSigLevel = trOp.GUI.MeansComp.SigLevel.dVal;
	strSigLevel = ftoa(dSigLevel);
	///end WRONG_DOUBLE_PRESION_NUMBER
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
	//trFooter.strVal = "Sig equals 1 indicates that the means difference is significant at the " + strSigLevel + " level.\n";
	//trFooter.strVal += "Sig equals 0 indicates that the means difference is not significant at the " + strSigLevel + " level.";
	string strFooter = "Err: Mean comparision string not in oErrMsg";
	ocu_load_msg_str(FOOTNOTE_MEAN_COMP, &strFooter, strSigLevel, NULL, strSigLevel);
	trFooter.strVal = strFooter;
	///end LOCALIZED_FOOTNOTES_STRINGS
	return true;
}

static string _get_error_msg(int nErr, bool bOneWay = true)
{
	string strErr;
	string strToolName;
	if(bOneWay)
		strToolName = _L("One-Way ANOVA");
	else
		strToolName = _L("Two-Way ANOVA");
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
	//strErr = "Error(" + ftoa(nErr) + "): " + strToolName +" computational error.";
	ocu_load_msg_str(ANOVA_ERROR_TABLE, &strErr, strToolName, &nErr);
	///END LOCALIZED_FOOTNOTES_STRINGS
	return strErr;
}

void 	ANOVAReportOperation::AddErrorRowToTable(TreeNode& trTable, string strError, int nID)
{
	TreeNode    trRow = tree_check_get_node(trTable, "Error", nID, STR_LABEL_ATTRIB, _LR("Attention!"));
	trRow.strVal = strError;
}	

void 	ANOVAReportOperation::AddErrInfoToTable(TreeNode& trTable, int nID, int nErr, bool bOneWay)
{
	string 		strError; //need wait Echo add related error info
	///Arvin 08/09/07 QA70-7100 ADD_ERROR_MESSAGE
	strError = _get_error_msg(nErr, bOneWay);
	///end ADD_ERROR_MESSAGE
	AddErrorRowToTable(trTable, strError, IDST_ANOVA_DESC_STATS);
}

int 	ANOVAReportOperation::GetPowerInfo(TreeNode trOp)
{
	TreeNode trActualPower = trOp.GUI.PowerBranch.ActualPower;
	TreeNode trHypotPower = trOp.GUI.PowerBranch.HypotPower;
	int		iPower = 0;
	if(trActualPower && trActualPower.Enable && trActualPower.nVal)
	{
			iPower |= ANOVA_POWER_ACTUAL; 
	}
	if(trHypotPower && trHypotPower.Enable && trHypotPower.nVal)
		iPower |= ANOVA_POWER_HYPOTHESIS; 
		
	return iPower;
}

bool 	ANOVAReportOperation::GetSampleSizeByPowerType(const TreeNode& trOp, int iPower, int iLevels, vector& vSampleSizes)
{
	if(ANOVA_POWER_ACTUAL & iPower) 
	{
		vSampleSizes.Add(iLevels);
	}
	
	if(ANOVA_POWER_HYPOTHESIS & iPower)
	{
		TreeNode trHypotSizes = trOp.GUI.PowerBranch.HypotSizes;
		if(!trHypotSizes)
			return false;
		
		string 			strSamples = trHypotSizes.strVal;
		vector		 	vsTemp;
		strSamples.GetTokens(vsTemp, ' ');
		vSampleSizes.Append(vsTemp);
	}
	
	return true;
}

void ANOVAReportOperation::AddPowerTableRows(TreeNode trTable, vector vPowers, vector vSampleSizes, double dSigLevel, int iPower, int nID, int nRet)
{
	PowerResults*	pstPowers;
	pstPowers = (PowerResults*)calloc(vPowers.GetSize(), sizeof(PowerResults));	
	stats_power_output(vPowers, vSampleSizes, dSigLevel, pstPowers, vPowers.GetSize());
    
	for(int nRow=0; nRow<vPowers.GetSize(); nRow++)
	{
		/// Iris 05/10/2007 v8.0615 REMOVE_BRANCH_CHECK_BOX
		//string strLabel = (0 == nRow)? "Actual Power" : "Hypothesis Powers";
		//------ Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE
		//string strLabel = (0 == nRow && ANOVA_POWER_HYPOTHESIS != iPower)? _LR("Actual Power") : _LR("Hypothesis Powers");
		string strLabel = (0 == nRow && ANOVA_POWER_HYPOTHESIS != iPower)? _LC("Actual Power", STR_CAT_STATS) : _LC("Hypothesis Powers", STR_CAT_STATS);
		//------ End CATEGORY_NEEDED_WHEN_LOCALIZE
		///end REMOVE_BRANCH_CHECK_BOX
			
		TreeNode	trRow = tree_check_get_node(trTable, "Row" + nRow, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, strLabel);
		trRow += pstPowers[nRow];
		trRow.ID = make_one_set_ID( nID, nRow);	
		//----Iris 11/01/06 v8.0502d NO_COL_LABEL_IN_POWER_TABLE
		trRow.Alpha.SetAttribute(STR_LABEL_ATTRIB, _LR("Alpha"));
		trRow.SampleSize.SetAttribute(STR_LABEL_ATTRIB, _LR("Sample Size"));
		//------ Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE
		//trRow.Power.SetAttribute(STR_LABEL_ATTRIB, _LR("Power"));
		trRow.Power.SetAttribute(STR_LABEL_ATTRIB, _LC("Power", STR_CAT_STATS));
		//------ End CATEGORY_NEEDED_WHEN_LOCALIZE
		//----		
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y); 
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES

	}
	///Arvin 08/09/07 QA70-7100 P15-L3 WRONG_POWER_ANALYSIS_TABLE
     if( 0 != nRet)
     	///Arvin 10/17/07 CLEAN_ANOVA_TOOLS_CODE
     	//addErrInfoANOVAPower(trTable, nID, nRet);
     	AddErrInfoToTable(trTable, nID, nRet, false);
     	///end CLEAN_ANOVA_TOOLS_CODE
     ///END WRONG_POWER_ANALYSIS_TABLE
    free(pstPowers);
}

bool ANOVAReportOperation::AddMeanComparisonRows(TreeNode& trOp, TreeNode& trTable, const vector<string>& vsFactors, MeanCompStats* pstMeanCompstats, int nSizeMeanComp, int nID, int nIntervalType)
{
	vector<string>	vsCompLabels;
	///Iris 02/16/05 BASE_CALSS_FUNCTION_INSTEAD_ADD_DESCSTAT_TABLE
	//getMeanCompColLabels(m_vsFactors, vsCompLabels);
	GetMeanCompColumnLabels(trOp, vsFactors, vsCompLabels);
	///End BASE_CALSS_FUNCTION_INSTEAD_ADD_DESCSTAT_TABLE
	
	for(int nRow=0; nRow < nSizeMeanComp; nRow++)
	{
		///Arvin 09/30/07 SHOULD_GET_LABEL_WITH_INDEXCOMP_FOR_BONHOLM_AND_SIDAKHOLM as max said
		//TreeNode trRow = tree_check_get_node(trTable, CALCULATION_REPORT_TABLE_ROW_PREFIX + nRow, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, vsCompLabels[nRow]);  //Use Row as temp label 
		int nLabelRow = nRow;
		if(nIntervalType == ANOVA_BONHOLM || nIntervalType == ANOVA_SIDAKHOLM)
		{
			nLabelRow = pstMeanCompstats[nRow].IndexComp;	
			if(nLabelRow >= vsCompLabels.GetSize())
				return false;
		}	
		TreeNode trRow = tree_check_get_node(trTable, CALCULATION_REPORT_TABLE_ROW_PREFIX + nRow, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, vsCompLabels[nLabelRow]);  
		///end SHOULD_GET_LABEL_WITH_INDEXCOMP_FOR_BONHOLM_AND_SIDAKHOLM
		trRow += pstMeanCompstats[nRow];
		//trRow.ID = nIntervalTypeID + nRow + 1;
		trRow.ID = make_one_set_ID(nID, nRow + 1);
		//--- Iris 11/2/0/06 the node only used to debug, so commented out it
		if(trRow.IndexComp)
			trRow.IndexComp.Show = 0;
		//---
		///Arvin 09/30/07 HIDE_DOF_COL_FOR_MEAN_COMP_TABLE as max said
		if(trRow.DOF)
			trRow.DOF.Show = false;
		///end HIDE_DOF_COL_FOR_MEAN_COMP_TABLE
		
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y); 
		if ( trRow.SEM )
			trRow.SEM.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	}
	
	///Iris 3/22/05 ADD_MORE_MEAN_COMPARISON_CASE
	SetupMeanCompasionTableRows(trTable, nIntervalType);
	UpdateMeanCompasionStatRowName(trTable, nIntervalType);

	free(pstMeanCompstats);	
	return true;
}
///end CLEAN_ANOVA_TOOLS_CODE
///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL	
//DWORD	ANOVAReportOperation::GetOutputOptions()
DWORD	ANOVAReportOperation::GetOutputOptions(const TreeNode& trOp)
///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
{
	return 0;
}

/// Iris 12/27/05 CONSTRUCT_RM_BASE_CLASS
/// ML 11/20/2007 QA70-10716 INPUT_DATA_NODE_PROPER_LANGUAGE_WHEN_LOADING_OPER
// virtual
int		ANOVAReportOperation::getLocUpdateInputDataStringsMode()
{
	return LUIDMODE_CUSTOM;
}

// virtual
bool	ANOVAReportOperation::customLocUpdateInputDataStrings(TreeNode &trInputDataConstructed, TreeNode &trInputDataLoaded)
{
	BOOL	bTwoWay = !IsOneWay();
	BOOL	bRM = IsRM();
	return okutil_anova_input_data_labels_proper_language(&trInputDataLoaded, bTwoWay, bRM);
}
/// end INPUT_DATA_NODE_PROPER_LANGUAGE_WHEN_LOADING_OPER

BOOL 	ANOVAReportOperation::Construct(TreeNode& trOperation, int nOption)
{
	if( WksReportOperation::Construct(trOperation, nOption) )
	{		
		ConstructOutputTable(trOperation);
		
		TreeNode	trGUI = ConstructAddGUI(trOperation);
 		if( IsOneWay() )
			ConstructOneWayANOVAGUITree(trGUI, nOption, IsRM() );
		else
			ConstructTwoWayANOVAGUITree(trGUI, nOption, IsRM() );
		///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL	
		//DWORD dwOptions = GetOutputOptions();
		DWORD dwOptions = GetOutputOptions(trOperation);
		///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
		ConstructAddReportCommon(trOperation, dwOptions, IDST_OUTPUT_RESULTS_OPTIONS, true);
		
		/// Iris 5/30/2008 CENTRALIZE_SET_RESULT_CURVE_BRANCH_NAME_CODES
		/*
		///Arvin  01/31/08 WRONG_REPORT_DATA_LABEL_IN_ANOVA
		TreeNode trData = trOperation.GUI.Output.Data;
		if(trData)
		{			
			trData.SetAttribute(STR_LABEL_ATTRIB, STR_OUTPUT_ANOVA_RESULT_CURVE_TABLES);			
		}
		///end WRONG_REPORT_DATA_LABEL_IN_ANOVA
		*/
		///end CENTRALIZE_SET_RESULT_CURVE_BRANCH_NAME_CODES
		
		FilterStatsGUI(trOperation);    ///Jim 01/17/06 v8.0358 CREATE_PLOTS_BRANCH_IN_MAIN_NODES			
		
		Operation::ConstructAddCommonBottom(trGUI);		

		return TRUE;
	}
}

/// Iris 5/30/2008 CENTRALIZE_SET_RESULT_CURVE_BRANCH_NAME_CODES
//virtual 
string  ANOVAReportOperation::GetResultCurveGUIName(TreeNode& trGUI)
{
	return STR_OUTPUT_ANOVA_RESULT_CURVE_TABLES;
}	
///end CENTRALIZE_SET_RESULT_CURVE_BRANCH_NAME_CODES

int		ANOVAReportOperation::GetDRTreeOption(TreeNode &trOperation)
{
	bool		bIsIndexed = IsIndexedData(trOperation);
	int			nDRTreeOption;
	if( IsOneWay() )
	{
		nDRTreeOption = bIsIndexed ? DRTREE_ANOVA_ONE_WAY_INDEXED : DRTREE_ANOVA_ONE_WAY_RAW;
	}
	else
	{
		nDRTreeOption = bIsIndexed ? DRTREE_ANOVA_TWO_WAY_INDEXED : DRTREE_ANOVA_TWO_WAY_RAW;
	}
	return nDRTreeOption;
}

void	ANOVAReportOperation::GetDependentData(const vector& vData)
{
	m_vData.Append(vData);
	m_vnIndex.Add(vData.GetSize());
}

void    ANOVAReportOperation::getLevelsNameForRow(TreeNode &trInput, vector<string>& vsFactors, int index, int nFactor)
{
	string strFactor = "Factor" + nFactor;	
	TreeNode	trFactor = trInput.GetNode(strFactor);
	if(!trFactor)
		return;	
	
	TreeNode	trLevels = trFactor.Levels;
	if(index >= trLevels.Children.Count() )
		return;	
	
	TreeNode	trLevel = trLevels.Children.Item(index);
	
	int nLast = vsFactors.GetSize() - 1;
	if( index > nLast )
		vsFactors.Add(trLevel.strVal);
	else
		vsFactors[index] = trLevel.strVal;	
}

///Arvin 09/26/07 QA70-10421 WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
//void    ANOVAReportOperation::getFactorNameForIndexed(TreeNode &trInput, string& strName, bool bIsOneWay, int nFactor)
void    ANOVAReportOperation::GetFactorNameForIndexed(TreeNode &trInput, string& strFactorName, bool bIsOneWay, int nFactor)
///end WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
{
	///Arvin 02/15/08 QA70-11097 KEEP_ESCAPED_STRINGS
	/*
	string strVal;
	if(bIsOneWay)
		strVal = trInput.Factor.strVal;
	else
	{
		string strFactor = "Factor" + nFactor;
		TreeNode trFactor = trInput.GetNode(strFactor);
		strVal = trFactor.strVal;
		
		///Alex 04/11/06 GET_COLNAME_OF_FACTOR_TO_LAST_BRANCH_OF_TOWWAYRMANOVA 
		//strVal = strVal.GetToken(1, ':');
		///Arvin 11/16/07 QA70-10669 IMPROVE_TABLES_ROW_LABELS_FOR_ANOVA_TOOLS		
		//DataRange dr;
		//dr.Add("Range1", strVal);
		//strVal=range_get_col_name(dr,0);
		///end IMPROVE_TABLES_ROW_LABELS_FOR_ANOVA_TOOLS
		///End GET_COLNAME_OF_FACTOR_TO_LAST_BRANCH_OF_TOWWAYRMANOVA
	}
	
	///Arvin 09/26/07 QA70-10421 WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
	//if(0 == nFactor)
	//	//m_strFactor = strVal.GetToken(0, '['); //get the column name of factor data as factor name
	//    m_strFactor = strVal;///Alex 04/11/06 GET_COLNAME_OF_FACTOR_TO_LAST_BRANCH_OF_TOWWAYRMANOVA
	//else
	//	//m_strFactor2 = strVal.GetToken(0, '['); //get the column name of factor data as factor name
	//	m_strFactor2 = strVal;///Alex 04/11/06 GET_COLNAME_OF_FACTOR_TO_LAST_BRANCH_OF_TOWWAYRMANOVA
	///Arvin 11/16/07 QA70-10669 IMPROVE_TABLES_ROW_LABELS_FOR_ANOVA_TOOLS		
	DataRange dr;
	dr.Add("Range1", strVal);
	strVal=range_get_col_name(dr,0);
	///end IMPROVE_TABLES_ROW_LABELS_FOR_ANOVA_TOOLS
	strFactorName = strVal;
	///end WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
	*/
	int nIndex = nFactor+1;
	if(bIsOneWay)
		nIndex = 1;
	report_get_escaped_data_string(&strFactorName, nIndex, FALSE, 'A', 0, ESC_LABEL_ADD_NONE, 'F');
	///end KEEP_ESCAPED_STRINGS
}

/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
int		ANOVAReportOperation::getMeanDiffTableNumber(TreeNode& trOp)
{
	int nNum = 0;
	TreeNode trMeanDiff = trOp.GUI.MeansComp;
	foreach(TreeNode trN in trMeanDiff.Children)
	{
		if(trN.ID == TRGP_CHECK || trN.ID == TRGP_BRANCH) //node is check box or branch
		{
			string str;
			if(trN.GetAttribute(STR_USE_ATTRIB, str))
				nNum += trN.Use;
			else
				nNum += trN.nVal;
		}
	}
	
	return nNum;
	
}

///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
//void 	ANOVAReportOperation::addBarDataTable(TreeNode& trOp)
void 	ANOVAReportOperation::addBarDataTable(TreeNode& trOp, int index)
///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
{	
	int nGraphIndex = GRAPH_STATS_BAR;
	
	///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	//TreeNode trTable = CheckCreateOneResultCurvesTable(trOp, 0, -1, nGraphIndex, "BarChart", IDST_ANOVA_BAR_CHART_WKS_TABLE, STAT_BAR_REPORT_LABEL);
	TreeNode trTable = CheckCreateOneResultCurvesTable(trOp, index, -1, nGraphIndex, "BarChart", IDST_ANOVA_BAR_CHART_WKS_TABLE, STAT_BAR_REPORT_LABEL);
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	
	/// Iris 3/20/2009 QA80-13321 ANOVA_BAR_CHART_INDEX_DATA_SHOULD_USE_FACTOR_STR
	//vector vIndex;
	///end ANOVA_BAR_CHART_INDEX_DATA_SHOULD_USE_FACTOR_STR
	vector vMeans;
	if( !GetDescStatsValues(trOp, vMeans) )
		return;	
	/// Iris 3/20/2009 QA80-13321 ANOVA_BAR_CHART_INDEX_DATA_SHOULD_USE_FACTOR_STR
	//vIndex.Data(1, vMeans.GetSize(), 1);
	///end ANOVA_BAR_CHART_INDEX_DATA_SHOULD_USE_FACTOR_STR
	
	//add index column
	/// Iris 3/23/2009 QA80-13285-P6 CLEAN_ANOVE_REPORT_DATA_LABEL
	//TreeNode trIndex = tree_check_get_node(trTable, "X", make_one_set_ID(IDST_ANOVA_BAR_CHART_WKS_TABLE, 1), STR_LABEL_ATTRIB, _L("Index")); 
	TreeNode trIndex = tree_check_get_node(trTable, "X", make_one_set_ID(IDST_ANOVA_BAR_CHART_WKS_TABLE, 1), STR_LABEL_ATTRIB, STR_REPORT_ANOVE_X_DATA_LABEL); 
	//end CLEAN_ANOVE_REPORT_DATA_LABEL
	/// Iris 3/20/2009 QA80-13321 ANOVA_BAR_CHART_INDEX_DATA_SHOULD_USE_FACTOR_STR
	//trIndex.dVals = vIndex;
	ASSERT( m_vsFactors.GetSize() == vMeans.GetSize() );
	trIndex.strVals = m_vsFactors;
	///end ANOVA_BAR_CHART_INDEX_DATA_SHOULD_USE_FACTOR_STR
	trIndex.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_X);
	
	//add mean data
	/// Iris 3/23/2009 QA80-13285-P6 CLEAN_ANOVE_REPORT_DATA_LABEL
	//TreeNode trMeans = tree_check_get_node(trTable, "Y", make_one_set_ID(IDST_ANOVA_BAR_CHART_WKS_TABLE, 2), STR_LABEL_ATTRIB, _L("Mean")); 
	TreeNode trMeans = tree_check_get_node(trTable, "Y", make_one_set_ID(IDST_ANOVA_BAR_CHART_WKS_TABLE, 2), STR_LABEL_ATTRIB, STR_REPORT_ANOVE_MEAN_DATA_LABEL); 
	///end CLEAN_ANOVE_REPORT_DATA_LABEL
	trMeans.dVals = vMeans;
	trMeans.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);

}


///Arvin 01/15/08 SHOULD_REMOVE_MEAN_SD_SE_TABLE_AFTER_RECALCULATE
//virtual
/// Hong 08/12/08 QA80-11986 FIX_FITTED_CURVE_PLOT_FAIL_RESCALE_WHEN_SOURCE_PLOT_HAVE_ERR_BAR
//void 	ANOVAReportOperation::RescaleReportGraph(TreeNode& trOp, GraphLayer& gl, int nGraphIndex, int nPicRowIndex, int nPicColIndex)
void 	ANOVAReportOperation::RescaleReportGraph(TreeNode& trOp, GraphLayer& gl, int nGraphIndex, int nPicRowIndex, int nPicColIndex, int nFirstFittedPlotIndex)
/// end FIX_FITTED_CURVE_PLOT_FAIL_RESCALE_WHEN_SOURCE_PLOT_HAVE_ERR_BAR
{
	int nRescaleOption = ReportGraphGetRescaleOption(trOp, nGraphIndex);
	if(nRescaleOption >= 0)
	{
		//When change parameters to more datasets, plots of Mean SD and Mean SE don't shows good enough.
		//So, I use this function to rescale it temporarily,
		if(nGraphIndex == GRAPH_STATS_MEANS_SD_PLOT || nGraphIndex == GRAPH_STATS_MEANS_SE_PLOT)
			gl.Rescale();
		///Kyle 01/05/2009 QA80-12676-P1 MEANS_COMP_PLOT_SET_COLOR_MAP_ON_SIG
		else if(nGraphIndex == GRAPH_STATS_MEANS_COMP_PLOT)
			gl.Rescale(OKAXISTYPE_Z);		// not to rescale Z, the colormap set in ANOVAReportOperation::SetupPlotDetails
		///End MEANS_COMP_PLOT_SET_COLOR_MAP_ON_SIG
		else
			/// Hong 08/12/08 QA80-11986 FIX_FITTED_CURVE_PLOT_FAIL_RESCALE_WHEN_SOURCE_PLOT_HAVE_ERR_BAR
			//WksReportOperation::RescaleReportGraph(trOp, gl, nGraphIndex, nPicRowIndex, nPicColIndex);
			WksReportOperation::RescaleReportGraph(trOp, gl, nGraphIndex, nPicRowIndex, nPicColIndex, nFirstFittedPlotIndex);
			/// end FIX_FITTED_CURVE_PLOT_FAIL_RESCALE_WHEN_SOURCE_PLOT_HAVE_ERR_BAR
	}
}
///end 	SHOULD_REMOVE_MEAN_SD_SE_TABLE_AFTER_RECALCULATE

/// Iris 3/20/2008 v8.0828 QA80-11676-P1 MEANS_COMP_PLOT_NEED_SMYBOL_INDEXED_BY_SIG_COL
bool 	ANOVAReportOperation::SetupPlotDetails(const TreeNode& trOp, GraphLayer& gl, int nFittedPlot, int nNumPlots, int nGraphIndex, int nDataIndex, bool bIsSourceGraph, bool bUpdateExistedReportGraph)	
{
	if( !WksReportOperation::SetupPlotDetails(trOp, gl, nFittedPlot, nNumPlots, nGraphIndex, nDataIndex, bIsSourceGraph, bUpdateExistedReportGraph))
		return false;	
		
	if(GRAPH_STATS_MEANS_COMP_PLOT == nGraphIndex && gl)
	{
		DataPlot dp = gl.DataPlots(nFittedPlot);
		if(dp)
		{
			///Kyle 01/05/2009 QA80-12676-P1 MEANS_COMP_PLOT_SET_COLOR_MAP_ON_SIG
			Tree trColorMap;
			vector vZLevels = {-1, 0, 1, 1};
			vector<uint> vnFillColors = {SYSCOLOR_RED, SYSCOLOR_GREEN, SYSCOLOR_BLUE};
			uint ncAbove = SYSCOLOR_BLUE, ncBelow = SYSCOLOR_RED;
			dp.SetColormap(vZLevels, FALSE, &vnFillColors, &ncBelow, &ncAbove);
			///END MEANS_COMP_PLOT_SET_COLOR_MAP_ON_SIG
			Tree tr;
			
			/// Iris 4/17/2008 QA80-11676 MEANS_COMP_PLOT_CHANGE_SMYBAO_TO_COLOR_MAP_ON_SIG
			//tr.Root.Symbol.EdgeColor.nVal = SYMBOL_COLOR_INDEX_OFFSET + MEANS_COMP_COL_SIG;
			tr.Root.Symbol.EdgeColor.nVal = SYMBOL_COLOR_MAP_OFFSET + MEANS_COMP_COL_SIG;
			///end MEANS_COMP_PLOT_CHANGE_SMYBAO_TO_COLOR_MAP_ON_SIG
			dp.UpdateThemeIDs(tr.Root);
			return dp.ApplyFormat(tr, true, true);
		}
	}
	return true;
	
}
///end MEANS_COMP_PLOT_NEED_SMYBOL_INDEXED_BY_SIG_COL

/// Iris 10/28/2009 QA81-14546 CHANGE_GUI_REPORT_TABLE_LABEL
/*
/// Iris 4/17/2008 SPECIAL_REPORT_TABLE_NAME_FOR_DIFF_TOOLS
//virtual	
string	ANOVAReportOperation::GetReportTableGUIName(TreeNode& trGUI)
{
	return STR_OUTPUT_ANOVA_REPORT_TABLE;
}
///end SPECIAL_REPORT_TABLE_NAME_FOR_DIFF_TOOLS
*/
///end CHANGE_GUI_REPORT_TABLE_LABEL

///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
//void 	ANOVAReportOperation::addMeansWksTable(TreeNode& trOp, int nGraphIndex, string strTable, int nID, const vector<string>& vsNames, const vector<string>& vsLabels, bool bIsSD)
void 	ANOVAReportOperation::addMeansWksTable(TreeNode& trOp, int nGraphIndex, string strTable, int nID, const vector<string>& vsNames, const vector<string>& vsLabels, bool bIsSD, int index)
///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
{
	string strName = "Mean" + nGraphIndex;
	///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	//TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, 0, -1, nGraphIndex, strName, nID, strTable);
	TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, index, -1, nGraphIndex, strName, nID, strTable);
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	
	bool  bCreateGraph = IsCreateReportGraph(trOp, nGraphIndex);
	tree_check_set_hidden(trTable, bCreateGraph? false:true);
	
	addNodeToMeanWksTable(trTable, vsNames, vsLabels, nID);	
	
	//vector<int> vnIndex;
	vector		vMeans;
	vector		vSD, vSE;
	if( !GetDescStatsValues(trOp, vMeans, vSD, vSE) )
	{
		error_report("GetDescStatsValues returns false in addMeansWksTable");
		return;
	}
	//vnIndex.Data(1, vMeans.GetSize(), 1);
	
	TreeNode trIndex = trTable.GetNode(vsNames[0]);
	if(trIndex) 	
	{
		//trIndex.nVals = vnIndex;
		trIndex.strVals = m_vsFactors;
		trIndex.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_X);
		trIndex.SetAttribute(STR_COL_FORMAT_ATTRIB, OKCOLTYPE_TEXT);
	}
		
	TreeNode trMean = trTable.GetNode(vsNames[1]);
	if(trMean)	
	{
		trMean.dVals = vMeans;
		trMean.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
	}
	TreeNode trSTD = trTable.GetNode(vsNames[2]);
	if(trSTD)
	{
		trSTD.dVals = bIsSD? vSD : vSE;		
		trSTD.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
	}	
	
}

///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
//void 	ANOVAReportOperation::addMeansSDWksTable(TreeNode& trOp)
void 	ANOVAReportOperation::addMeansSDWksTable(TreeNode& trOp, int index)
///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
{			
	/// Iris 3/23/2009 QA80-13285-P6 CLEAN_ANOVE_REPORT_DATA_LABEL
	//vector<string> vsNames = {"Index", "Mean", "SD"};
	/// Iris 5/19/2009 FAIL_REPORT_MEAN_COMP_CURVE_DATA_IN_JOS
	/*
	vector<string> vsNames;
	vsNames.Add(STR_REPORT_ANOVE_X_DATA_LABEL);
	vsNames.Add(STR_REPORT_ANOVE_MEAN_DATA_LABEL);
	vsNames.Add(STR_REPORT_ANOVE_SD_DATA_LABEL);	
	///END CLEAN_ANOVE_REPORT_DATA_LABEL
	
	///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	//addMeansWksTable(trOp, GRAPH_STATS_MEANS_SD_PLOT, "Mean SD Plot", IDST_ANOVA_MEAN_SD_WKS_TABLE, vsNames, vsNames);
	addMeansWksTable(trOp, GRAPH_STATS_MEANS_SD_PLOT, "Mean SD Plot", IDST_ANOVA_MEAN_SD_WKS_TABLE, vsNames, vsNames, true, index);
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	*/	
	vector<string> vsNames = {"Factor", "Mean", "SD"};
	vector<string> vsLabels;
	vsLabels.Add(STR_REPORT_ANOVE_X_DATA_LABEL);
	vsLabels.Add(STR_REPORT_ANOVE_MEAN_DATA_LABEL);
	vsLabels.Add(STR_REPORT_ANOVE_SD_DATA_LABEL);
	
	addMeansWksTable(trOp, GRAPH_STATS_MEANS_SD_PLOT, "Mean SD Plot", IDST_ANOVA_MEAN_SD_WKS_TABLE, vsNames, vsLabels, true, index);
	///end FAIL_REPORT_MEAN_COMP_CURVE_DATA_IN_JOS
}

///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
//void	ANOVAReportOperation::addMeansSEWksTable(TreeNode& trOp)
void	ANOVAReportOperation::addMeansSEWksTable(TreeNode& trOp, int index)
///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
{	
	/// Iris 3/23/2009 QA80-13285-P6 CLEAN_ANOVE_REPORT_DATA_LABEL
	//vector<string> vsNames = {"Index", "Mean", "SEM"};	
	/// Iris 5/19/2009 FAIL_REPORT_MEAN_COMP_CURVE_DATA_IN_JOS
	/*
	vector<string> vsNames;
	vsNames.Add(STR_REPORT_ANOVE_X_DATA_LABEL);
	vsNames.Add(STR_REPORT_ANOVE_MEAN_DATA_LABEL);
	vsNames.Add(STR_REPORT_ANOVE_SEM_DATA_LABEL);
	///END CLEAN_ANOVE_REPORT_DATA_LABEL
	
	///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	//addMeansWksTable(trOp, GRAPH_STATS_MEANS_SE_PLOT, "Mean SEM Plot", IDST_ANOVA_MEAN_SE_WKS_TABLE, vsNames, vsNames, false);
	addMeansWksTable(trOp, GRAPH_STATS_MEANS_SE_PLOT, "Mean SEM Plot", IDST_ANOVA_MEAN_SE_WKS_TABLE, vsNames, vsNames, false, index);
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	*/
	vector<string> vsNames = {"Factor", "Mean", "SEM"};
	vector<string> vsLabels;
	vsLabels.Add(STR_REPORT_ANOVE_X_DATA_LABEL);
	vsLabels.Add(STR_REPORT_ANOVE_MEAN_DATA_LABEL);
	vsLabels.Add(STR_REPORT_ANOVE_SEM_DATA_LABEL);
	addMeansWksTable(trOp, GRAPH_STATS_MEANS_SE_PLOT, "Mean SEM Plot", IDST_ANOVA_MEAN_SE_WKS_TABLE, vsNames, vsLabels, false, index);	
	///end FAIL_REPORT_MEAN_COMP_CURVE_DATA_IN_JOS
}

///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
//void	ANOVAReportOperation::addMeansDiffWksTable(TreeNode& trOp)
void	ANOVAReportOperation::addMeansDiffWksTable(TreeNode& trOp, int index)
///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
{
	//int index=0; ///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	for(int iType = ANOVA_TUKEY; iType<ANOVA_LAST_ITEM; iType++)
	{
		///Arvin 01/28/07 SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER
		//if(addOneMeansDiffWksTable(trOp, iType, index))
		//		index++; 
		addOneMeansDiffWksTable(trOp, iType, index);
		///end SHOULD_REMOVE_REDUNDANT_DATA_TABLE_AFTER_CHANGE_PARAMETER
	}	
}

///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
TreeNode    ANOVAReportOperation::getOneMeanDiffResultNode(TreeNode& trOp, int iType, string& strName, string& strLabel, int* pID)
{
	int nIDTmp;
	string strNameTmp, strLabelTmp;
	GetMeanCompNodeInfo(strNameTmp, strLabelTmp, nIDTmp, iType);
	if(strName)
		strName = strNameTmp;
	if(strLabel)
		strLabel = strLabelTmp;
	if(pID)
		*pID = nIDTmp;
	
	TreeNode 	trResult = tree_get_node_by_id(trOp.Calculation, nIDTmp, true);
	return trResult;
}

bool 	ANOVAReportOperation::getOneMeanDiffSigValues(TreeNode& trOp, int iType, vector& vSig)
{
	TreeNode 	trResult = getOneMeanDiffResultNode(trOp, iType);
	if(!trResult)
		return false;
	
	vSig.SetSize(0);
	foreach(TreeNode trN in trResult.Children)
	{
		TreeNode 	tr;
		tr = trN.Sig;
		if(tr)
			vSig.Add(tr.dVal);
	}
	
	return vSig.GetSize() == 0 ? false : true;
}

void 	ANOVAReportOperation::getMeanDiffPlotTypes(TreeNode& trOp, vector& vTypes)
{
	vTypes.SetSize(0);
	for(int iType = ANOVA_TUKEY; iType<ANOVA_LAST_ITEM; iType++)
	{
		TreeNode 	trResult = getOneMeanDiffResultNode(trOp, iType);
		if(trResult)
			vTypes.Add(iType);
	}	
}

bool ANOVAReportOperation::AppendLegendForAddedPlot(TreeNode& trOp, GraphLayer& gl, int nPlotIndex, LPCSTR lpcszExtraFormat, int nGraphIndex, int nPictureIndex)
{
	if(nGraphIndex != GRAPH_STATS_MEANS_COMP_PLOT)
		return WksReportOperation::AppendLegendForAddedPlot(trOp, gl, nPlotIndex, lpcszExtraFormat, nGraphIndex, nPictureIndex);
	
	vector vMeanCompPlotTypes;
	getMeanDiffPlotTypes(trOp, vMeanCompPlotTypes);
	if(nPictureIndex < 0 || nPictureIndex >= vMeanCompPlotTypes.GetSize())
		return false;
	
	vector vSigValues;
	int iMeanCompPlotType = vMeanCompPlotTypes[nPictureIndex];
	getOneMeanDiffSigValues(trOp, iMeanCompPlotType, vSigValues);
	if(vSigValues.GetSize() < 1)
		return WksReportOperation::AppendLegendForAddedPlot(trOp, gl, nPlotIndex, lpcszExtraFormat, nGraphIndex, nPictureIndex);
	vector<int> vUniqueIndices;
	if(find_unique_values(vSigValues, vUniqueIndices) <= 0)
		return false;
	
	if(nPlotIndex == 0)
	{
		//legend_delete_plot(gl, nPlotIndex);
		GraphObject	goLegend = gl.GraphObjects(GO_LEGEND_NAME);
		if(!goLegend)
		{
			return false;
		}
		string		strText = goLegend.Text;
		strText.Empty();
		int nUnique = vUniqueIndices.GetSize();
		for(int ii = 0; ii < nUnique; ii++)
		{
			string strLegend = construct_one_legend_LT_text(goLegend, gl, nPlotIndex, lpcszExtraFormat, vUniqueIndices[ii]);
			if(!strLegend.IsEmpty())
			{
				/// Iris 3/20/2008 v8.0828 QA80-11676-P2 BETTER_LEGEND_FOR_MEAN_COMP_PLOT
				//strLegend = strLegend + " (" + _L("Sig") + " = " + ftoa(vSigValues[vUniqueIndices[ii]]) + ")";
				strLegend = strLegend + " (" + getStrFromSigValue(vSigValues[vUniqueIndices[ii]]) + ")";				
				///end BETTER_LEGEND_FOR_MEAN_COMP_PLOT
				if(ii != nUnique-1)
					strLegend += "\r\n";
			}
			strText += strLegend;
		}
		goLegend.Text = strText;
	}
	
	return true;
}
///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO

/// Iris 3/20/2008 v8.0828 QA80-11676-P2 BETTER_LEGEND_FOR_MEAN_COMP_PLOT
string  ANOVAReportOperation::getStrFromSigValue(int nSigValue)
{
	string str;
	switch(nSigValue)
	{
	case 0:
		str = "nonsignificant difference";
		break;
	case 1:
		str = "significant difference";
		break;
	case -1:
		str = "no conclusion";
		break;
	default:
		break;
	}
	return str;
		
}
///end BETTER_LEGEND_FOR_MEAN_COMP_PLOT

bool	ANOVAReportOperation::addOneMeansDiffWksTable(TreeNode& trOp, int iType, int index)
{
	//get the values from the result table of mean comparison
	int 	nID;
	string 	strName, strLabel;
	///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	//GetMeanCompNodeInfo(strName, strLabel, nID, iType);	
	//
	///// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	////TreeNode 	trResult = tree_get_node_by_id(trOp.Calculation.ANOVAs.MeanComp, nID, true);	
	//TreeNode 	trResult = tree_get_node_by_id(trOp.Calculation, nID, true);
	TreeNode 	trResult = getOneMeanDiffResultNode(trOp, iType, strName, strLabel, &nID);
	///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	if(!trResult)
		return false;
	
	vector<string> vsCompLabels;
	vector 		vMeanDiff, vSEM, vSig;
	foreach(TreeNode trN in trResult.Children)
	{
		/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		string strLabel;
		if( trN.GetAttribute(STR_LABEL_ATTRIB, strLabel) )
			vsCompLabels.Add(strLabel);
		///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		
		TreeNode 	tr;
		tr = trN.MeanDiff;
		if(tr)
			vMeanDiff.Add(tr.dVal);
		
		tr = trN.SEM;
		if(tr)
			vSEM.Add(tr.dVal);	
			
		tr = trN.Sig;
		if(tr)
			vSig.Add(tr.dVal);
	}
	if(0 == vMeanDiff.GetSize() || 0 == vSEM.GetSize() || 0 == vSig.GetSize())
		return false;
	//vnIndex.Data(1, vMeanDiff.GetSize(), 1);
	
	
	// construct report data table of mean compasion 
	int nGraphIndex = GRAPH_STATS_MEANS_COMP_PLOT;
	///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	//int nTableID = IDST_ANOVA_MEAN_COMP_WKS_TABLE + index;
	int nTableID = make_one_set_ID(IDST_ANOVA_MEAN_COMP_WKS_TABLE, iType);
	///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	//string 		strTableLabel = "Mean Diff for " + strLabel;
	string 		strTableLabel = _L("Mean Diff for") + " " + strLabel; /// Hong 10/24/07 v8.0732 LOCALISED_REPORTTREE_ISSUE
	///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	//TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, index, -1, nGraphIndex, strName, nTableID, strTableLabel);	
	TreeNode	trTable = CheckCreateOneResultCurvesTable(trOp, index, -1, nGraphIndex, strName, nTableID, strTableLabel, NULL, false);	
	///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	if(!trTable)
	{
		///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
		//trTable = CheckCreateOneResultCurvesTable(trOp, index, -1, nGraphIndex, strName, nTableID, strTableLabel, "temp");
		/// Iris 3/23/2009 QA80-13285-P7 CLEAN_ANOVE_REPORT_DATA_COMMENTS_LABEL
		//trTable = CheckCreateOneResultCurvesTable(trOp, index, -1, nGraphIndex, strName, nTableID, strTableLabel, _L("ANOVA Plots"), false);
		trTable = CheckCreateOneResultCurvesTable(trOp, index, -1, nGraphIndex, strName, nTableID, strTableLabel, STR_REPORT_ANOVE_PLOTS_DATA_LABEL, false);
		///end CLEAN_ANOVE_REPORT_DATA_COMMENTS_LABEL
		
		///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
	}
	if(!trTable)
		return false;
	
	/// Iris 3/23/2009 QA80-13285-P6 CLEAN_ANOVE_REPORT_DATA_LABEL
	//vector<string> vsNames = {"Index", "MeanDiff", "SEM", "Sig"};
	/// Iris 5/19/2009 FAIL_REPORT_MEAN_COMP_CURVE_DATA_IN_JOS
	/*
	vector<string> vsNames;
	vsNames.Add(STR_REPORT_ANOVE_X_DATA_LABEL);
	vsNames.Add(STR_REPORT_ANOVE_MEAN_DIFF_DATA_LABEL);
	vsNames.Add(STR_REPORT_ANOVE_SEM_DATA_LABEL);
	vsNames.Add(STR_REPORT_ANOVE_SIG_DATA_LABEL);
	///end CLEAN_ANOVE_REPORT_DATA_LABEL
	
	addNodeToMeanWksTable(trTable, vsNames, vsNames, nTableID);	
	*/
	vector<string> vsNames = {"Factor", "MeanDiff", "SEM", "Sig"};
	vector<string> vsLabels;
	vsLabels.Add(STR_REPORT_ANOVE_X_DATA_LABEL);
	vsLabels.Add(STR_REPORT_ANOVE_MEAN_DIFF_DATA_LABEL);
	vsLabels.Add(STR_REPORT_ANOVE_SEM_DATA_LABEL);
	vsLabels.Add(STR_REPORT_ANOVE_SIG_DATA_LABEL);
	
	addNodeToMeanWksTable(trTable, vsNames, vsLabels, nTableID);		
	///end FAIL_REPORT_MEAN_COMP_CURVE_DATA_IN_JOS
	
	//set value for each node in the report data table of mean compasion
	/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	//vector<string> 	vsIndex;
	//GetMeanCompColumnLabels(trOp, m_vsFactors, vsIndex);
	///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	TreeNode 		trNode;
	trNode = trTable.GetNode(vsNames[0]);
	if(trNode) 	
	{
		/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		//trNode.strVals = vsIndex;
		trNode.strVals = vsCompLabels;
		///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		trNode.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_X);
		trNode.SetAttribute(STR_COL_FORMAT_ATTRIB, OKCOLTYPE_TEXT);
	}
		
	trNode = trTable.GetNode(vsNames[1]);
	if(trNode)	
	{
		trNode.dVals = vMeanDiff;
		trNode.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_Y);
	}	
	
	trNode = trTable.GetNode(vsNames[2]);
	if(trNode)	
	{
		trNode.dVals = vSEM;
		trNode.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
	}
	
	trNode = trTable.GetNode(vsNames[3]);
	if(trNode)	
	{
		trNode.dVals = vSig;
		trNode.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_NONE);
	}	return true;
}

void 	ANOVAReportOperation::addNodeToMeanWksTable(TreeNode& trTable, vector<string> vsNames, vector<string> vsLabels, int nBaseID)
{		
	for(int index=0; index<vsNames.GetSize(); index++)
	{
		tree_check_get_node(trTable, vsNames[index], make_one_set_ID(nBaseID, index+1), STR_LABEL_ATTRIB, vsLabels[index]);
	}
}


bool 	ANOVAReportOperation::GetDescStatsValues(TreeNode& trOp, vector& vMeans, vector& vSD, vector& vSE)
{
	TreeNode 	trDescStats = trOp.Calculation.GetNode(TABLE_DESC_STATS);
	if(!trDescStats)
	{
		return error_report("fail to get Statistics node in getDescStatsValues");
	}
	
	foreach(TreeNode trN in trDescStats.Children)
	{
		TreeNode 	tr;
		tr = tree_get_node_by_id(trN, IDE_MEAN, true);
		if( tr && vMeans)
			vMeans.Add(tr.dVal);
		
		tr = tree_get_node_by_id(trN, IDE_SD, true);
		if( tr && vSD)
			vSD.Add(tr.dVal);
		
		tr = tree_get_node_by_id(trN, IDE_SEM, true);
		if( tr && vSE)
			vSE.Add(tr.dVal);		
	}	
		
	return true;
}
///Arvin 06/19/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
//void 	ANOVAReportOperation::AddReportCurveTables(TreeNode &trOp, int nTotalNumData, string strLabel)
//{
//	addBarDataTable(trOp);
//	addMeansSDWksTable(trOp);
//	addMeansSEWksTable(trOp);
//	addMeansDiffWksTable(trOp);
//}
void 	ANOVAReportOperation::AddReportCurveTables(TreeNode &trOp, int nTotalNumData, string strLabel, int index)
{
	/// Iris 3/20/2008 v8.0828 QA80-11282-P2 NO_SELECTED_SHOULD_NOT_OUTPUT_PLOT_DATA
	//addBarDataTable(trOp, index);
	//addMeansSDWksTable(trOp, index);
	//addMeansSEWksTable(trOp, index);
	//addMeansDiffWksTable(trOp, index);
	TreeNode trGraphBar = GetGUIGraphNodes(trOp, GRAPH_STATS_BAR);
	if(tree_is_true(trGraphBar))
		addBarDataTable(trOp, index);
	
	TreeNode trGraphMeansSD = GetGUIGraphNodes(trOp, GRAPH_STATS_MEANS_SD_PLOT);
	if(tree_is_true(trGraphMeansSD))
		addMeansSDWksTable(trOp, index);
	
	TreeNode trGraphMeansSE = GetGUIGraphNodes(trOp, GRAPH_STATS_MEANS_SE_PLOT);
	if(tree_is_true(trGraphMeansSE))
		addMeansSEWksTable(trOp, index);
	
	TreeNode trGraphComp = GetGUIGraphNodes(trOp, GRAPH_STATS_MEANS_COMP_PLOT);
	if(tree_is_true(trGraphComp))
		addMeansDiffWksTable(trOp, index);
	///end NO_SELECTED_SHOULD_NOT_OUTPUT_PLOT_DATA
}
///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS

///Cheney 2007-10-25 ANOVA_TOOLS_HANDLE_AUTO_WRONG
//virtual
int	ANOVAReportOperation::GetReportOutPutDestination(const TreeNode& trInput)
{
	DataRange drData;
	drData.Create();
	
	int nUse = 0;
	if( !trInput.GetAttribute( STR_USE_ATTRIB, nUse) )
		return STR_NEW;
	
	int nOption = 0;
	if( !GetAnovaToolsOption(nUse, nOption) )
		return STR_NEW;
	
	drData.SetTree(trInput, nOption);
	if(!is_range_from_normal_book(drData))
		return PDS_NEW;
	return PDS_SOURCE;
}
///end ANOVA_TOOLS_HANDLE_AUTO_WRONG

//virtual 
string ANOVAReportOperation::GetReportGraphLabel(TreeNode& trOp, int nGraphIndex, int nPicRow, int nPicCol)
{
	string 	strLabel;
	int		nPicIndex = nPicRow * GetReportGraphTableColNum(trOp) + nPicCol;
	if(GRAPH_STATS_BOX_PLOT == nGraphIndex)
	{
		DataRange dr;
		GetInput(dr);
		if(dr)
		{
			vector<string> vstrFactors;
			if( 0 <= dr.GetData(GetDataRules(trOp), nPicIndex, NULL, NULL, NULL, NULL, NULL, &vstrFactors) )
				strLabel = vstrFactors[0];
		}			
	}
	
	if(GRAPH_STATS_MEANS_COMP_PLOT == nGraphIndex)
	{
		int ii = 0;
		foreach(TreeNode trN in trOp.GUI.MeansComp.Children)
		{
			if( TRGP_BRANCH == trN.ID || TRGP_CHECK == trN.ID)
			{				
				int 	nCheck;
				if( !trN.GetAttribute(STR_USE_ATTRIB, nCheck) )
					nCheck = trN.nVal;
				if(nCheck)
				{
					if(ii == nPicIndex)
					{
						trN.GetAttribute(STR_LABEL_ATTRIB, strLabel);
						break;
					}
					ii++;
				}
			}			
		}
		
	}	
	return strLabel;
}
///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY

bool	ANOVAReportOperation::GetFactors(TreeNode &trOp, int index, const vector<string> &vstrFactors)
{
	TreeNode	trInput = trOp.GUI.InputData;	
	
	/// ML 10/24/2005 ANOVAS_INDEXED_RAW
	int nDRTreeOption = GetDRTreeOption(trOp);
	if (DRTREE_ANOVA_ONE_WAY_RAW == nDRTreeOption || DRTREE_ANOVA_TWO_WAY_RAW == nDRTreeOption)
	{
		// If raw, then factor values are not obtained from the DataRange, but are instead defined by user
		// in GUI and stored in the tree.
		//ASSERT(0 == vstrFactors.GetSize());
		//vstrFactors.SetSize(1);		
		getLevelsNameForRow(trInput, m_vsFactors, index, 0);		
		m_strFactor = trInput.Factor0.Name.strVal;  //get factor name for row data
		
		if( !IsOneWay() )
		{
			TreeNode 	trRepeat0 = trInput.Factor0.Repeat;
			TreeNode 	trRepeat1 = trInput.Factor1.Repeat;
			
			bool		bNormalTwoWay = !trRepeat0 && !trRepeat1? true : false; //for normal two way anova
			bool		bTwoRepeated = trRepeat0 && trRepeat1 && trRepeat0.nVal && trRepeat1.nVal? true : false; //for Two ANOVA RM one repeated data
			if( bNormalTwoWay || bTwoRepeated)
			{
				getLevelsNameForRow(trInput, m_vsFactors2, index, 1);	
				m_strFactor2 = trInput.Factor1? trInput.Factor1.Name.strVal : "";				
			}
			else
			{			
				//only get repeated factor levels for RM Two ANOVA
				if(trRepeat0 && trRepeat1)
				{				
					if(trRepeat0.nVal)//Factor0 is repeated
					{
						getLevelsNameForRow(trInput, m_vsFactors, index, 0);
						m_strFactor = trInput.Factor0? trInput.Factor0.Name.strVal : "";
						m_strFactor2 = trInput.Factor1? trInput.Factor1.Name.strVal : "";
					}
					if(trRepeat1.nVal)//Factor1 is repeated
					{
						getLevelsNameForRow(trInput, m_vsFactors, index, 1);
						m_strFactor = trInput.Factor1? trInput.Factor1.Name.strVal : ""; // m_strFactor always contains repeated items
						m_strFactor2 = trInput.Factor0? trInput.Factor0.Name.strVal : "";// m_strFactor2 always contains repeated or non repeated items
					}
					if( !trRepeat0.nVal && !trRepeat1.nVal)
						return error_report("Error: Two Factors both are not repeated in ANOVA TWO WAY RM");
				}
			}

		}		
	}
	/// end ANOVAS_INDEXED_RAW
	else
	{
		//only conside one way normal anova here, since rm anove get factor list from GetData and two way normal anova has ANOVATwoWay::getFactors to get by the diff way 
		if(NULL != vstrFactors && 0 != vstrFactors.GetSize())
		{	
			string strTemp = vstrFactors[0];
			if( -1 == m_vsFactors.Find(strTemp) )
				m_vsFactors.Add(strTemp);
		}
		
		//get factor name for indexed data
		///Arvin 09/26/07 QA70-10421 WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
		//getFactorNameForIndexed(trInput, m_strFactor, IsOneWay(), 0);
		//getFactorNameForIndexed(trInput, m_strFactor2, IsOneWay(), 1);
		GetFactorNameForIndexed(trInput, m_strFactor, IsOneWay(), 0);
		GetFactorNameForIndexed(trInput, m_strFactor2, IsOneWay(), 1);
		///end WRONG_REPEAT_FACTOR_IN_REPORT_TABLE
	}
	
	return true;
	
}

void	ANOVAReportOperation::GetWeights(vector vWeights)
{
	m_vWeights.Append(vWeights);
}
///End CONSTRUCT_RM_BASE_CLASS


virtual void 	ANOVAReportOperation::ConstructOutputTable(TreeNode& trOperation)
{	
	TreeNode 	trOut = trOperation.Calculation; 
	
	trOut.Statistics.ID = IDST_DESC_STATS_RESULTS;
	trOut.ANOVAs.ID = IDST_ANOVAS;
	//trOut.ANOVAs.OvarallANOVA.ID = IDST_ANOVAS_OVERALL;
	//trOut.ANOVAs.FitStats.ID = IDST_ANOVAS_FIT_STATS;
	//trOut.ANOVAs.MeanComp.ID = IDST_ANOVAS_MEAN_COMP;
	//trOut.ANOVAs.EqualVari.ID = IDST_ANOVAS_TEST_EQUAL_VAR;
	//trOut.ANOVAs.Powers.ID = IDST_ANOVAS_HYPOTPOWER;	
}

/// Iris 5/27/2008 v8.0871 NO_RESULT_CURVE_REPORT_IN_1WAY_ANOVA
bool	ANOVAReportOperation::InitOutputGUIManagerPointer(const TreeNode& trGUI)
{
	if(m_pOutputManager)//already init
		return true;
	
	m_pOutputManager = new ANOVAOutputGUIManager;	
	if(NULL == m_pOutputManager)
		return false;
	
	return true;
}
///end NO_RESULT_CURVE_REPORT_IN_1WAY_ANOVA

void    ANOVAReportOperation::UpdateOverallANOVAColumnLabel(TreeNode& trRow)
{
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
	//vector<string> vsLabels = {"DF", "Sum of Squares", "Mean Square", "F Value", "P Value"};
	vector<string> vsLabels;
	vsLabels.Add(_L("DF"));
	vsLabels.Add(_L("Sum of Squares"));
	vsLabels.Add(_L("Mean Square"));
	vsLabels.Add(_L("F Value"));
	vsLabels.Add(_L("P Value"));
	///end LOCALIZED_FOOTNOTES_STRINGS
	if(trRow.Children.Count() != vsLabels.GetSize())
		return;
	
	int 	index = 0;
	foreach(TreeNode tr in trRow.Children)
		tr.SetAttribute(STR_LABEL_ATTRIB, vsLabels[index++]);
	
}	

/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
//void	ANOVAReportOperation::GetMeanCompColumnLabels(const vector<string>& vsFactors, vector<string>& vsCompLabels)
void	ANOVAReportOperation::GetMeanCompColumnLabels(TreeNode &trOp, const vector<string> &vsFactors, vector<string> &vsCompLabels, bool bIsDunnType, int nFactorIndex, bool bInteraction)
///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
{	
	int iLevels = vsFactors.GetSize();
	for(int ii=1; ii<iLevels; ii++)
		for(int jj=0; jj<ii; jj++)
		{
			if(ii == jj) continue;
			string strTemp;
			strTemp.Format("%s  %s", vsFactors[ii], vsFactors[jj]);
			vsCompLabels.Add(strTemp);
		}
}	

void    ANOVAReportOperation::SetupMeanCompasionTableRows(TreeNode &trTable, int nType)
{
	if(!trTable)
		return;
	
	vector<int> vnShowIDs, vnHiddenIDs;	
	switch(nType)
	{
	case ANOVA_BONFERRON:
	case ANOVA_TUKEY:
	case ANOVA_SCHEFFE:
	case ANOVA_SIDAK:
	case ANOVA_FISHER:
	case ANOVA_DUNNETT:
		//vnShowIDs.Add(IDE_ANOVA_INDEXCOMP);
		//vnShowIDs.Add(IDE_ANOVA_MEANDIFF);
		//vnShowIDs.Add(IDE_ANOVA_SEM);
		//vnShowIDs.Add(IDE_ANOVA_STAT);
		//vnShowIDs.Add(IDE_ANOVA_PROB);
		//vnShowIDs.Add(IDE_ANOVA_SIG);
		//vnShowIDs.Add(IDE_ANOVA_ALPHA);
	///Kevin 09/01/05 CHANGE_STATISTICS_NAME	
		//vnShowIDs.Add(IDE_ANOVA_LCI);
		//vnShowIDs.Add(IDE_ANOVA_UCI);
		vnShowIDs.Add(IDE_ANOVA_LCL);
		vnShowIDs.Add(IDE_ANOVA_UCL);
	///End CHANGE_STATISTICS_NAME
		tree_set_attributes(trTable, vnShowIDs, "1");
		break;
		
	case ANOVA_BONHOLM:
	case ANOVA_SIDAKHOLM:		
	///Kevin 09/01/05 CHANGE_STATISTICS_NAME	
		//vnHiddenIDs.Add(IDE_ANOVA_LCI);
		//vnHiddenIDs.Add(IDE_ANOVA_UCI);		
		vnHiddenIDs.Add(IDE_ANOVA_LCL);
		vnHiddenIDs.Add(IDE_ANOVA_UCL);		
	///End CHANGE_STATISTICS_NAME
		tree_set_attributes(trTable, vnHiddenIDs, "0");			
		break;
	default:
		break;
	}
}

void    ANOVAReportOperation::UpdateMeanCompasionStatRowName(TreeNode &trTable, int nType)
{
	if(!trTable)
		return;
	foreach(TreeNode trRow in trTable.Children)
	{
		trRow.IndexComp.SetAttribute(STR_LABEL_ATTRIB, _L("IndexComp"));
		trRow.MeanDiff.SetAttribute(STR_LABEL_ATTRIB, _L("MeanDiff"));
		trRow.SEM.SetAttribute(STR_LABEL_ATTRIB, _L("SEM"));
		trRow.DOF.SetAttribute(STR_LABEL_ATTRIB, _L("DF"));
		trRow.Prob.SetAttribute(STR_LABEL_ATTRIB, _L("Prob"));
		trRow.Alpha.SetAttribute(STR_LABEL_ATTRIB, _L("Alpha"));
		trRow.Sig.SetAttribute(STR_LABEL_ATTRIB, _L("Sig"));
		trRow.LCL.SetAttribute(STR_LABEL_ATTRIB, _L("LCL"));
		trRow.UCL.SetAttribute(STR_LABEL_ATTRIB, _L("UCL"));
		
		TreeNode trStat = trRow.GetNode("Stat");
		if(trStat)
		{
			switch(nType)
			{
			case ANOVA_BONFERRON:
			case ANOVA_SIDAK:
			case ANOVA_FISHER:
			case ANOVA_BONHOLM:
			case ANOVA_SIDAKHOLM:
				trStat.SetAttribute(STR_LABEL_ATTRIB, _L("t Value"));
				break;
			case ANOVA_TUKEY:
			case ANOVA_DUNNETT:
				trStat.SetAttribute(STR_LABEL_ATTRIB, _L("q Value"));
				break;
			case ANOVA_SCHEFFE:
				trStat.SetAttribute(STR_LABEL_ATTRIB, _L("F Value"));
				break;			
			default:
				break;
			}	
		}
	}
}

/// Iris 3/02/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE
//void 	ANOVAReportOperation::GetMeanCompNodeInfo(string& strNode, string &strLabel, int &nID, int nType)
void 	ANOVAReportOperation::GetMeanCompNodeInfo(string& strNode, string &strLabel, int &nID, int nType, int nPairwiseComparisonTableIndex)
///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE
{
	/// Hong 10/24/07 v8.0732 LOCALISED_REPORTTREE_ISSUE
	// i find this function is generate info for report sheet usage, so i localize strLabel here 
	// as it should suppose to be only used as label that need localize
	/// end LOCALISED_REPORTTREE_ISSUE
	switch(nType)
	{
	case ANOVA_BONFERRON:
		strNode = "Bonferr";
		strLabel = _L("Bonferroni Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_BONF_TABLE;
		break;
	case ANOVA_TUKEY:
		strNode = "Turey";
		strLabel = _L("Tukey Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_TUK_TABLE;
		break;
	case ANOVA_SCHEFFE:
		strNode = "Scheffe";
		strLabel = _L("Scheffe Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_SCHE_TABLE;
		break;
	case ANOVA_SIDAK:
		strNode = "Sidak";
		strLabel = _L("Sidak Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_SIDAK_TABLE;
		break;	
	case ANOVA_FISHER:
		strNode = "Fisher";
		strLabel = _L("Fisher Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_FISHER_TABLE;
		break;	
	case ANOVA_BONHOLM:
		strNode = "Bonholm";
		strLabel = _L("Bonholm Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_BONHOLM_TABLE;
		break;	
	case ANOVA_SIDAKHOLM:
		strNode = "Sidakholm";
		strLabel = _L("Sidakholm Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_SIDAKHOLM_TABLE;
		break;
	case ANOVA_DUNNETT:
		strNode = "Dunnett";
		strLabel = _L("Dunnett Test");
		nID = IDST_ANOVA2_MEAN_COMPARE_DUNN_TABLE;
		break;	
	default:
		break;
	}
	nID = make_one_set_ID(nID, nPairwiseComparisonTableIndex+1); /// Iris 3/02/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE 
}

/// ML 10/26/2005 QA70-8225 ESCAPED_OPER_STRINGS_ANOVAS
bool	ANOVAReportOperation::IsIndexedData(TreeNode &trOp)
{
	TreeNode	trInputData = trOp.GUI.InputData;
	return trInputData.Use == ANOVA_INDEXED_DATA;
}

/// Iris 4/02/2009 QA80-13392-P2 IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE
void ANOVAReportOperation::updateIndexedDataSourceInReportingHeader(TreeNode &trInputTable, const vector<string> &vstrFactors, int ii, LPCSTR lpcszXLabel, int numSubRanges, DWORD dwRules)
{
	if (0 != ii)
		return;		// for indexed everyhting done on the first data call
	
	/*
	string		strLabel = _L("Data");
	if ( 1 < numSubRanges )
	{
		AddCombinedDataSourcesToReportInputTable(trInputTable, vstrFactors, ii, strLabel, numSubRanges, dwRules);
		return;
	}
	
	TreeNode	trRow = AddXDataSourceToReportInputTable(trInputTable, vstrFactors, ii, strLabel, 0, numSubRanges, dwRules);
	// The Range column:
	AddOneInputDataTableCell(trRow, WKSH_OPERATION_INFO_DATA_SOURCE_RANGE, ii + 1, FALSE, 'G', 'R');
	*/
	int				indexRow = 0;
	///Arvin 08/30/07 WRONG_INPUT_TABLE_FOR_MULTI_DATA_COLS
	//AddOneRowToInputDataTable(trInputTable, indexRow++, 'D');		// dependent var
	DataRange dr;
	GetInput(dr);
	dwRules |= DRR_NO_FACTORS;
	int nNumDataCol = dr.GetNumData(dwRules);
	for(int iCol = 0; iCol < nNumDataCol; iCol++)
		AddOneRowToInputDataTable(trInputTable, indexRow++, 'D', 0, iCol+1);
	///end WRONG_INPUT_TABLE_FOR_MULTI_DATA_COLS
	int				numFcts = vstrFactors.GetSize();
	AddOneRowToInputDataTable(trInputTable, indexRow++, 'F', numFcts < 2 ? -1 : 0);		// the first factor
	if (1 < numFcts)
		AddOneRowToInputDataTable(trInputTable, indexRow + 1, 'F', 1);	// the second factor
	
	if ( IsRM() )
		AddOneRowToInputDataTable(trInputTable, indexRow + 2, 'S');		// the subjects	
}

void ANOVAReportOperation::updateRawDataSourceInReportingHeader(TreeNode &trInputTable, const vector<string> &vstrFactors, int ii, LPCSTR lpcszXLabel, int numSubRanges, DWORD dwRules)
{	
	vector<string> vstrLabels;
	if( IsOneWay() )
	{		
		if( ii < m_vsFactors.GetSize() )
		{
			vstrLabels.Add(m_vsFactors[ii]);
		}		
	}
	else //two way
	{
		Tree trOp;
		GetTree(trOp);
		
		TreeNode trFactorARepeat = trOp.GUI.InputData.Factor0.Repeat;
		TreeNode trFactorBRepeat = trOp.GUI.InputData.Factor1.Repeat;
		// the case one Factor is repeat and another facotr is NOT repeat
		if( trFactorARepeat && trFactorBRepeat && 1 == trFactorARepeat.nVal + trFactorBRepeat.nVal)
		{
			vstrLabels.Add(m_vsFactors[ii]);
			
			/// Iris 4/13/2009 QA80-13392-P2 FIX_INPUT_TABLE_ANOVA2WAY_RM_REPEAT_WITH_NOT_REPEAT
			// for 2 way anova rm by raw data one factor is repeat and one factor is NOT repeat case, 
			// the index of repeat factor is number of factors * index of level (0 offset), 
			// for example, if the number of factors of non repeat is 2, the index of one level of repeat factor is 0, 2, 4(0 offset)
			// so the tagName is C1, C3...CN, the data index is 1,3,5...
			ii = m_vsFactors2.GetSize() * ii;	// m_vsFactors2.GetSize is the number of levels of NON repeat factor whatever Factor A or Factor B is NONE repeat.			
			///end FIX_INPUT_TABLE_ANOVA2WAY_RM_REPEAT_WITH_NOT_REPEAT
		}
		else
		{
			int nFactor1Index = ii/ m_vsFactors2.GetSize();
			ASSERT( nFactor1Index >= 0 && nFactor1Index < m_vsFactors.GetSize() );
			
			int nFactor2Index = mod(ii, m_vsFactors2.GetSize());
			ASSERT( nFactor2Index >= 0 && nFactor2Index < m_vsFactors2.GetSize() );
			
			vstrLabels.Add(m_vsFactors[nFactor1Index]);
			vstrLabels.Add(m_vsFactors2[nFactor2Index]);		
		}
	}	
	StatsOpBase::UpdateDataSourceInReportingHeader(trInputTable, vstrLabels, ii, lpcszXLabel, numSubRanges, dwRules);	

}
///end IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE

// virtual
void	ANOVAReportOperation::UpdateDataSourceInReportingHeader(TreeNode &trInputTable, const vector<string> &vstrFactors, int ii, LPCSTR lpcszXLabel, int numSubRanges, DWORD dwRules)
{
	TreeNode		trOp = trInputTable.Parent().Parent();
	bool			bIndexed = IsIndexedData(trOp);
	
	/// Iris 4/02/2009 QA80-13392-P2 IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE
	/*
	if (!bIndexed)
	{
		StatsOpBase::UpdateDataSourceInReportingHeader(trInputTable, vstrFactors, ii, lpcszXLabel, numSubRanges, dwRules);
		return;
	}
	
	//if (0 != ii)
		//return;		// for indexed everyhting done on the first data call
	//
	//
	//string		strLabel = _L("Data");
	//if ( 1 < numSubRanges )
	//{
		//AddCombinedDataSourcesToReportInputTable(trInputTable, vstrFactors, ii, strLabel, numSubRanges, dwRules);
		//return;
	//}
	//
	//TreeNode	trRow = AddXDataSourceToReportInputTable(trInputTable, vstrFactors, ii, strLabel, 0, numSubRanges, dwRules);
	//// The Range column:
	//AddOneInputDataTableCell(trRow, WKSH_OPERATION_INFO_DATA_SOURCE_RANGE, ii + 1, FALSE, 'G', 'R');
	
	int				indexRow = 0;
	///Arvin 08/30/07 WRONG_INPUT_TABLE_FOR_MULTI_DATA_COLS
	//AddOneRowToInputDataTable(trInputTable, indexRow++, 'D');		// dependent var
	DataRange dr;
	GetInput(dr);
	dwRules |= DRR_NO_FACTORS;
	int nNumDataCol = dr.GetNumData(dwRules);
	for(int iCol = 0; iCol < nNumDataCol; iCol++)
		AddOneRowToInputDataTable(trInputTable, indexRow++, 'D', 0, iCol+1);
	///end WRONG_INPUT_TABLE_FOR_MULTI_DATA_COLS
	int				numFcts = vstrFactors.GetSize();
	AddOneRowToInputDataTable(trInputTable, indexRow++, 'F', numFcts < 2 ? -1 : 0);		// the first factor
	if (1 < numFcts)
		AddOneRowToInputDataTable(trInputTable, indexRow + 1, 'F', 1);	// the second factor
	
	if ( IsRM() )
		AddOneRowToInputDataTable(trInputTable, indexRow + 2, 'S');		// the subjects
	*/
	if(bIndexed)
	{
		updateIndexedDataSourceInReportingHeader(trInputTable, vstrFactors, ii, lpcszXLabel, numSubRanges, dwRules);
	}
	else
	{
		updateRawDataSourceInReportingHeader(trInputTable, vstrFactors, ii, lpcszXLabel, numSubRanges, dwRules);
	}		
	///end IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE
}

/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
string 	ANOVAReportOperation::GetGraphTemplate(int nGraphIndex)
{
	if(nGraphIndex == GRAPH_STATS_MEANS_COMP_PLOT)
		return "ReportMeanComp";
	/// Iris 05/08/2007 v8.0613 SUGGESTION_ON_BAR_CHART
	if(nGraphIndex == GRAPH_STATS_BAR)
		return "ReportBar";
	///end SUGGESTION_ON_BAR_CHART
	
	return WksReportOperation::GetGraphTemplate(nGraphIndex);
}

int	ANOVAReportOperation::ReportGetPicureIndexFromDataIndex(int nGraphIndex, int nDataIndex)
{
	switch( nGraphIndex )
	{
	case GRAPH_STATS_BOX_PLOT:
	case GRAPH_STATS_MEANS_COMP_PLOT:
		return nDataIndex; 
	default:
		return 0; //Iris 12/22/05 bar chart of mean, line of mean sd, line of mean se, all just include one picture.
	}
	
	return -1;
}

int	ANOVAReportOperation::ReportGetPlotTypeFromGraphIndex(int nGraphIndex)
{
	switch( nGraphIndex )
	{
	case GRAPH_STATS_BOX_PLOT:
		return IDM_PLOT_BOX;
		
	case GRAPH_STATS_MEANS_SD_PLOT:
	case GRAPH_STATS_MEANS_SE_PLOT:
		return IDM_PLOT_LINESYMB;
	case GRAPH_STATS_MEANS_COMP_PLOT:
		return IDM_PLOT_SCATTER;
	case GRAPH_STATS_BAR:
		/// Iris 05/08/2007 v8.0613 SUGGESTION_ON_BAR_CHART
		//return IDM_PLOT_BAR;
		return IDM_PLOT_COLUMN; 
		///end SUGGESTION_ON_BAR_CHART
	}
	
	return -1;
}

string ANOVAReportOperation::GetResultCurveBookName(TreeNode& trOperation, int nDataIndex, int nOption, bool bSeparateSheetForDataset)
{
	return _L("Means Plot");
}

//virtual
string ANOVAReportOperation::GetResultCurveBookShortName(TreeNode& trOperation, int nIndex, int nOption)
{
	return _L(E_STR_ANOVA_BOOK_SHORT_NAME);
}


bool ANOVAReportOperation::GetCustomGraphTypeName(string& strName, int nIndex)
{
	switch( nIndex )
	{
	case GRAPH_STATS_BOX_PLOT:
		strName = STAT_BOXCHART_REPORT_LABEL;
		break;
	case GRAPH_STATS_MEANS_SD_PLOT:
		strName = STAT_MEANS_SD_PLOT_REPORT_LABEL;
		break;
	case GRAPH_STATS_MEANS_SE_PLOT:
		strName = STAT_MEANS_SE_PLOT_REPORT_LABEL;
		break;
	case GRAPH_STATS_BAR:
		strName = STAT_BAR_REPORT_LABEL;
		break;
	case GRAPH_STATS_MEANS_COMP_PLOT:
		strName = STAR_MEAN_DIFF_LABEL;
		break;
	}
		
	return true;
}

uint ANOVAReportOperation::GetResultCurveTableID(TreeNode& trOp, int nDataIndex, int nTotalNumData, int nGraphIndex)
{
	switch( nGraphIndex )
	{
	case GRAPH_STATS_MEANS_SD_PLOT:
		///Arvin 06/06/07 WRONG_TABLE_ID_FOR_GRAPH
		//return IDST_ANOVA_MEAN_SD_WKS_TABLE;
		return make_one_set_ID(IDST_ANOVA_MEAN_SD_WKS_TABLE, nDataIndex+1);
		///END WRONG_TABLE_ID_FOR_GRAPH
	case GRAPH_STATS_MEANS_SE_PLOT:
		///Arvin 06/06/07 WRONG_TABLE_ID_FOR_GRAPH
		//return IDST_ANOVA_MEAN_SE_WKS_TABLE;
		return make_one_set_ID(IDST_ANOVA_MEAN_SE_WKS_TABLE, nDataIndex+1);
		///END WRONG_TABLE_ID_FOR_GRAPH
	case GRAPH_STATS_BAR:
		///Arvin 06/06/07 WRONG_TABLE_ID_FOR_GRAPH
		//return IDST_ANOVA_BAR_CHART_WKS_TABLE;
		return make_one_set_ID(IDST_ANOVA_BAR_CHART_WKS_TABLE, nDataIndex+1);
		///END WRONG_TABLE_ID_FOR_GRAPH
	case GRAPH_STATS_MEANS_COMP_PLOT:
		///Arvin 06/06/07 WRONG_TABLE_ID_FOR_GRAPH
		//return IDST_ANOVA_MEAN_COMP_WKS_TABLE + nDataIndex;
		///Arvin 11/16/07 QA70-10676 UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
		//return make_one_set_ID(IDST_ANOVA_MEAN_COMP_WKS_TABLE + nDataIndex, nDataIndex+1);
		vector vTypes;
		getMeanDiffPlotTypes(trOp, vTypes);
		int nID = make_one_set_ID(IDST_ANOVA_MEAN_COMP_WKS_TABLE, nDataIndex);
		//In order to keep plot ID same as report table ID, we use its type produce ID
		if(nDataIndex >= 0 && nDataIndex < vTypes.GetSize())
			nID = make_one_set_ID(IDST_ANOVA_MEAN_COMP_WKS_TABLE, vTypes[nDataIndex]);
		return nID;
		///end UPDATE_MEANS_COMPARISION_PLOT_LEGENT_WITH_SIG_INFO
		///END WRONG_TABLE_ID_FOR_GRAPH
	///Arvin 06/15/07 WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	case GRAPH_STATS_BOX_PLOT:
		if(HasFactor(trOp))
			return make_one_set_ID(IDST_STAT_BOX_CHART_TABLE+nDataIndex+1, nDataIndex+1);
	///end WRONG_HISTOGRAM_AND_BOXCHART_PLOTS_WHILE_DATA_HAVE_FACTORS
	}
	
	return 0;
}
bool ANOVAReportOperation::IsGraphTableInsertBackToSourceType(int nGraphIndex)
{		
	return false;
}

//--- Iris 11/02/06 v8.0502e SHOW_HIDDEN_REPORT_DATA_SHEET_EVEN_NO_NEED_OUTPUT_GRAPH
//give a better name
//virtual
string	ANOVAReportOperation::GetResultCurveSheetName(TreeNode& trOperation, int nIndex, int nOption)
{
	//---- Iris 01/03/2007 discussed with Max, give a better name for curve sheet.
	//return "Means";
	return _LE(E_STR_ANOVA_CURVE_SHEET_NAME);
	//----
}

bool ANOVAReportOperation::IsOutputSeparateResultCurveSheet(const TreeNode& trOp) 
{
	if( StatsOpBase::IsOutputSeparateResultCurveSheet(trOp) )
	{
		foreach(TreeNode trPlot in trOp.GUI.Plots.Children)
			if(trPlot.nVal)
				return true;
	}
	return false;
}
//--- 

int ANOVAReportOperation::GetTotalNumPictureForOneGraphType(TreeNode& trOp, int nGraphIndex)
{
	int nNum = 0;
	if(-1 == nGraphIndex)
	{
		//--- Iris 11/02/06 v8.0502e SHOW_HIDDEN_REPORT_DATA_SHEET_EVEN_NO_NEED_OUTPUT_GRAPH
		//getMeanDiffTableNumber(trOp);
		//if( NULL != nTotalNumData && nTotalNumData>nNum )
			//nNum = nTotalNumData;
		/// Iris 01/03/2007 FAIL_TO_PLOT_MEAN_SD_SE_IF_NOT_PLOT_MEAN_COMP
		/*
		nNum = 1;
		if(trOp.GUI.Plots.Graph5.nVal)//Graph5, mean comparison plot
		{
			nNum = getMeanDiffTableNumber(trOp);
		}
		else if(trOp.GUI.Plots.Graph2.nVal)//Graph2, Box chart, plot from source data
		{
			nNum = 0;
		}
		*/
		TreeNode	trPlots = trOp.GUI.Plots;
		if(trPlots.Graph1.nVal || trPlots.Graph3.nVal || trPlots.Graph4.nVal) //Graph1: Bar Chart; Graph3: Mean SD; Graph4: Mean SE
		{
			nNum = 1;
		}
		if(trPlots.Graph5.nVal)//Graph5, mean comparison plot
		{
			nNum = getMeanDiffTableNumber(trOp);//if check mean comparison plot, nNum >= 1
		}
		///end FAIL_TO_PLOT_MEAN_SD_SE_IF_NOT_PLOT_MEAN_COMP
		//--- 
	}
	else
	{	
		switch( nGraphIndex )
		{
		case GRAPH_STATS_BAR:
		case GRAPH_STATS_MEANS_SD_PLOT:
		case GRAPH_STATS_MEANS_SE_PLOT:
			nNum = 1;
			break;
			
		case GRAPH_STATS_MEANS_COMP_PLOT:
			nNum = getMeanDiffTableNumber(trOp);
			break;
			
		case GRAPH_STATS_BOX_PLOT:
			///Arvin 06/21/07 v8.0646 WRONG_NUMBER_BOX_CHART_PLOT
			//I don't know who write this hard code, but this code is terribly wrong 
			//nNum = 3; //GetTotalNumData(trOp);
			nNum = GetTotalNumData(trOp);
			///END WRONG_NUMBER_BOX_CHART_PLOT
			break;
		}
	}	
	return nNum;
}
///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY

///Arvin 02/14/08 QA70-11094 SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL
bool	ANOVAReportOperation::IsPlotAllPlotsInOneGraph(TreeNode& trOperation, int nGraphIndex)
{
	bool	bPlotInOneGraph = false;
	/// Iris 10/29/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
	//TreeNode	trPlotOneGraph = trOperation.GUI.Output.PlotSettings.PlotInOneGraph;
	TreeNode	trPlotOneGraph = OP_GUI_GRAPH_ARRANGEMENT_NODE(trOperation.GUI).PlotInOneGraph;
	///end OP_DLG_NEW_STRUCTURE
	int nPlotType = ReportGetPlotTypeFromGraphIndex(nGraphIndex);
	if(trPlotOneGraph &&( (nGraphIndex < 0) || (nPlotType == IDM_PLOT_HISTOGRAM_TYPE || nPlotType == IDM_PLOT_BOX) ))
		bPlotInOneGraph = trPlotOneGraph.nVal;
	
	return bPlotInOneGraph;
}
///end SUPPORT_PLOT_MULTI_FITTED_CURVES_IN_ONE_GRAPH_IN_LR_PR_AND_FITNL

/// Thomas 6/1/06 MOVE_ADDONEROWTOINPUTDATATABLE_FROM_ANOVAREPORTOPERATION_TO_STATSOPBASE
/*
void	ANOVAReportOperation::AddOneRowToInputDataTable(TreeNode &trInputTable, int index, char chDataFactSubj, int indexAux)
{
	int			indexLT = index + 1;
	string		strLabel;
	int			nIndexForCellNode = 1;
	switch(chDataFactSubj)
	{
	case 'D':		// data
		strLabel = "Dependent Variable";
		break;
	
	case 'F':		// factors
		if (indexAux < 0)			// one-way
			strLabel = "Factor";
		else if (0 < indexAux)
		{
			strLabel = "Factor B";
			nIndexForCellNode = 2;
		}
		else
			strLabel = "Factor A";
		break;
	
	case 'S':		// subjects
		strLabel = "Subjects";
		break;

	default:
		ASSERT(FALSE);
		return;
	}

	TreeNode	trRow = check_add_enumerated_node(trInputTable, "C", indexLT, make_one_set_ID(IDST_REPORT_INPUT_ONE_SET, index), STR_LABEL_ATTRIB, strLabel);
	
	AddOneInputDataTableCell(trRow, "Data", nIndexForCellNode, FALSE, 'P', 0, chDataFactSubj);		// Data
	AddOneInputDataTableCell(trRow, "Range", nIndexForCellNode, FALSE, 'G', 'R', chDataFactSubj);		// Range

}
*/
/// End MOVE_ADDONEROWTOINPUTDATATABLE_FROM_ANOVAREPORTOPERATION_TO_STATSOPBASE

/// end ESCAPED_OPER_STRINGS_ANOVAS


//////////////////////////ANOVARMReportOperation//////////////////////////
#define 	TABLE_RM_DEST_STATS			_L("Descriptive Statistics")
#define 	TABLE_RM_MULTI_TEST			_L("Multivariate Tests")
#define 	TABLE_RM_SPHERICITY_TEST	_L("Mauchly's Test of Sphericity")
#define 	TABLE_RM_WS_ANOVA			_L("Tests of Within-Subjects Effects")
#define 	TABLE_RM_BS_ANOVA			_L("Tests of Between-Subjects Effects")
#define 	TABLE_RM_MEAN_COMP			_L("Pairwise Comparison")

#define		TABLE_RM_ROW_PREFIX			"row"

#define		NAG_ANOVA_RM_NO_ERR 				0
#define		NAG_ANOVA_RM_ERR_INPUT_PARAM		1
#define		NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_TEST				2
#define		NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MULTI_TEST				3
#define		NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_OR_MULTI_TEST		4
#define		NAG_ANOVA_RM_ERR_INTERNAL			99
#define		NAG_ANOVA_RM_ERR_MEMORY_ALLOCATION	301
#define		NAG_ANOVA_RM_ERR_UNBALANCED_DESIGN 	STATS_ERROR_UNBALANCED_DESIGN



#define		NUM_MULTI_TEST_SUB_SIZE			4

class OC_REGISTERED ANOVARMReportOperation : public ANOVAReportOperation
{
protected:
	virtual void 	ConstructOutputTable(TreeNode& trOperation) { }
	virtual void 	UpdateReportingTables(TreeNode &trOperation, int nTotalNumData, int nExeMode);
	
public:
	virtual bool	IsRM()		{return true;}	
	DWORD	GetDataRules(const TreeNode& trOp, bool bIgnoreCombineInfo = false );	
	//int 	ConstructGraphNumber() 	{ return 0; } /// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	int		GetResultCurvesID() { return 0; }
	bool	GetMeanCompMethod(TreeNode &trOp, MeanCompMethod& stMethods, int& ncntrl, int& ncntrl2=NULL, bool bIsOneWay = true);
	/// Max 10/09/07 QA70-10491 USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
	//bool    GetMeanCompColumnLabels(TreeNode &trOp, const vector<string> &vsFactors, vector<string> &vsLabels1, vector<string> &vsLabels2, bool bIsDunnType = false, int nFactorIndex = 1);
	bool    GetMeanCompColumnLabels(TreeNode &trOp, const vector<string> &vsFactors, vector<string> &vsCompLabels, bool bIsDunnType = false, int nFactorIndex = 1, bool bInteraction = false);
	/// END USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
protected:
	virtual bool	CalcMultiData(TreeNode& trOp, DataRange& dr, int &nNumData, int nExeMode, DWORD dwExecCntrl);
	virtual bool	CalcOneData(TreeNode &trOp, int nSizeSubject, int nSizeFactor, int& nSizeFactor2 = NULL);
	virtual bool    ExtractData(TreeNode &trOp, DataRange& dr, int& nSizeSubject, int& nSizeFactor, int& nSizeFactor2 = NULL);
	virtual int     ExtractRawData(TreeNode &trOp, DataRange& dr, matrix& mData, int& nSizeSubject, int& nSizeFactor, int& nSizeFactor2 = NULL);
	virtual int     ExtractIndexedData(TreeNode &trOp, DataRange& dr, matrix& mData, int& nSizeSubject, int& nSizeFactor, int& nSizeFactor2 = NULL);
	virtual bool    ConvertData(const matrix& matData);
	virtual	int		GetMeanCompTableSize(int* pnSizeFactor = NULL, int* pnSizeFactor2 = NULL, int iInteraction = -1);

	bool	AddMultiTestTable(TreeNode &trOp, MultiTestTable &RVMultiStats, int index = 0, LPCSTR lpcszFactor = NULL);
	bool	AddSphericityTestTable(TreeNode &trOp, SphericityStats &RVSphericStats, EpsilonStats &RVEpsilonStats, bool bWarnning, int index = 0, LPCSTR lpcszLabel = NULL);
	bool	AddANOVATable(TreeNode &trOp, RMANOVARow* pstRMANOVARows, int nSize, LPCSTR lpcszRVFactor = NULL, LPCSTR lpcszRVOrNonRVFactor = NULL, bool bIsTwoWay = false, bool bInteraction = false, bool bBothRV = false);
	bool	AddDestStatsTable(TreeNode &trOp, TreeNode &trTable, RMANOVADescStats* pDescStats, uint nSizeDescStat, const vector<string>& vsRowLabels1, const vector<string>& vsRowLabels2 = NULL);
	/// Iris 2/25/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
	//int		AddMeanComparisonTable(TreeNode &trOp, TreeNode &trMeanReport, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nSizeFactor, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors = NULL, bool bInteraction = false, LPCSTR lpcszFixFactor = NULL, LPCSTR lpcszNonFixFactor = NULL, int nFactorIndex = 1);
	int		AddMeanComparisonTable(TreeNode &trOp, TreeNode &trMeanReport, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nSizeFactor, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors = NULL, bool bInteraction = false, LPCSTR lpcszFixFactor = NULL, LPCSTR lpcszNonFixFactor = NULL, int nFactorIndex = 1, int nPairwiseComparisonTableIndex = 0);
	///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE

	void	AddMultiTestErrorTable(TreeNode &trOp);
	//void	AddSphericityTestErrorTable(TreeNode &trOp);
	///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
	void	CheckANOVARMErr(int nErr);
	///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
	///Sophy 1/9/2009 v8.0995 QA80-12000-P2 ANOVAONEWAY_RM_DONT_SUPPORT_REPORT_MASKED_AND_MISSING_DATA centralize code
	//virtual 
	void	FilterStatsGUI(TreeNode& trOp) ;
	///Arvin 09/07/07 SHOULD_NOT_SHOW_INTERACTION_RESULT_WHILE_UNCHECK_AFTER_CHANGE_PARAM
	//virtual void  ClearOutputTables(TreeNode& trOperation); ///Arvin 09/26/07 ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS
	///end SHOULD_NOT_SHOW_INTERACTION_RESULT_WHILE_UNCHECK_AFTER_CHANGE_PARAM
private:
	/// Iris 2/25/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
	//int	    addOneMethodMeanCompTable(TreeNode &trOp, TreeNode &trMethod, TreeNode &trMeanReport, int nType, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nStart, int nEnd, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors, bool bInteraction = false, LPCSTR lpcszFixFactor = NULL, LPCSTR lpcszNonFixFactor = NULL, int nFactorIndex = 1);
	int	    addOneMethodMeanCompTable(TreeNode &trOp, TreeNode &trMethod, TreeNode &trMeanReport, int nType, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nStart, int nEnd, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors, bool bInteraction = false, LPCSTR lpcszFixFactor = NULL, LPCSTR lpcszNonFixFactor = NULL, int nFactorIndex = 1, int nPairwiseComparisonTableIndex = 0);
	///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
	bool    addOneMeanCompTable(TreeNode &trOp, TreeNode &trTable, int nTableID, int nType, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nStart, int nEnd, const vector<string>& vsFixFactors, bool bInteraction = false, int nFactorIndex = 1);
	bool	addANOVABSTable(TreeNode &trOp, RMANOVARow* pstRMANOVARows, int nSize, int& index, const vector<string>& vsANOVAColLabels, LPCSTR lpcszRVFactor = NULL, LPCSTR lpcszRVOrNonRVFactor = NULL, bool bIsTwoWay = false, bool bInteraction = false, bool bBothRV = false);
	bool	addANOVAWSTable(TreeNode &trOp, RMANOVARow* pstRMANOVARows, int nSize, int& index, const vector<string>& vsANOVAColLabels, LPCSTR lpcszRVFactor = NULL, LPCSTR lpcszRVOrNonRVFactor = NULL, bool bIsTwoWay = false, bool bInteraction = false, bool bBothRV = false);
	string  getConfiLevelLabel(TreeNode &trOp, bool bIsLow);
};
int		ANOVARMReportOperation::GetMeanCompTableSize(int* pnSizeFactor, int* pnSizeFactor2, int iInteraction) //nSizeFactor2 is non repeated factor
{
	if(NULL == pnSizeFactor && NULL == pnSizeFactor2)
		return error_report("eroor parameters in ANOVARMReportOperation::GetMeanCompTableSize");	
	
	if(iInteraction < 0)
	{			
		int nFactor;
		if(NULL != pnSizeFactor)
			nFactor = *pnSizeFactor;
		else
			nFactor = *pnSizeFactor2;
		
		return (ANOVA_LAST_ITEM - 2)* nFactor*(nFactor-1)/2 + nFactor -1;		
	}
	else
	{
		if( (NULL == pnSizeFactor || NULL == pnSizeFactor2) && 1 == iInteraction )
			return error_report("eroor parameters in ANOVARMReportOperation::GetMeanCompTableSize");	
		
		//return (ANOVA_LAST_ITEM - 2)* nSizeFactor2*(nSizeFactor+1)/2 -1;
		
		return (ANOVA_LAST_ITEM - 2) * (*pnSizeFactor2) * (*pnSizeFactor) * (*pnSizeFactor-1) / 2 + *pnSizeFactor - 1;
	}
}

bool	ANOVARMReportOperation::CalcMultiData(TreeNode& trOp, DataRange& dr, int &nNumData, int nExeMode, DWORD dwExecCntrl)
{
	int nSizeSubject, nSizeFactor, nSizeFactor2;
	if( !ExtractData(trOp, dr, nSizeSubject, nSizeFactor, nSizeFactor2))
		return error_report("Fail to get input data");
	
	/// Iris 8/26/2008 QA80-12098 FIX_ONE_WAY_RM_FAIL_CONVERT_RESULT_CURVE_OP_STR, moved from below
	///Iris 1/19/06 ADD_INPUT_DATA_REPORT_TABLE
	//--- Iris 4/28/06 not get really data number, just get the number column
	//DWORD		dwRules = GetDataRules(trOp);
	DWORD		dwRules = DRR_NO_FACTORS | DRR_NO_WEIGHTS;
	//---
	int			numSubRanges;
	/// ML 8/16/2006 CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	//nNumData = dr.GetNumData(dwRules, NULL, NULL, NULL, &numSubRanges);
	TreeNode	trAdditionalData = tree_check_get_node(trOp,TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME); 
	nNumData = dr.GetNumData(dwRules, trAdditionalData, NULL, NULL, &numSubRanges);
	/// end CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	if(nNumData<=0)
		return false;
	/// ML 8/16/2006 CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	SetTree(trOp);
	/// end CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	///end FIX_ONE_WAY_RM_FAIL_CONVERT_RESULT_CURVE_OP_STR
	
	/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	//Prepare Stats node for Box Chart plots
	if(trOp.GUI.Plots) 
	{
		trOp.Temp.ID = 1; //prepare Temp node to save Temp.Stats nodes
		for(int index=0; index<nSizeFactor; index++)
		{
			vector	vTempData;
			m_vData.GetSubVector(vTempData, index*nSizeSubject, (index+1)*nSizeSubject-1);

			
			DescStatResults		stDescStats;		
			vector				vPercents;
			vector				vPercentiles;
			vector<bool>		vShow;
			QuantileResults		stQuantiles;
			vector				vWeights(vTempData.GetSize());
			vWeights = 1;
			
			if( CalcOneDataMoment(trOp, vTempData, vWeights, stDescStats) &&
					/// Iris 11/09/2009 QA81-14599 IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
					//CalcOneDataPercentilesAndRange(trOp, vTempData, vPercents, vPercentiles, vShow, vWeights, stQuantiles))
					CalcOneDataPercentilesAndRange(trOp, vTempData, vPercents, vPercentiles, vShow, vWeights, stQuantiles, index))
					///end IMPROVE_STATS_ON_COLS_CALCULATION_SPEED
			{
				TreeNode trStats = getTempStatsTreeNode(trOp, index);
				tree_stats_get_set_percentiles(trStats, vPercentiles, FALSE);
				tree_stats_get_set_stats_results(trStats, stDescStats, stQuantiles.Min, stQuantiles.Max, FALSE);
			}
			
			/// Iris 3/23/2009 QA80-13285-P7 CLEAN_ANOVE_REPORT_DATA_COMMENTS_LABEL	
			//AddBinDataTableAndGraphNodes(trOp, index, vTempData, m_vsFactors, m_strFactor, false);		
			AddBinDataTableAndGraphNodes(trOp, index, vTempData, m_vsFactors, STR_REPORT_ANOVE_PLOTS_DATA_LABEL, false);
			///end CLEAN_ANOVE_REPORT_DATA_COMMENTS_LABEL
		}
	}
	///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	
	/// Iris 5/29/2008 FIX_ESCAPED_STRING_IN_ANOVA_WS_TABLE_LABEL
	// ConvertEscapedString fail to work since have not trAdditionalData node at this time, so moved CalcOneData to below after add trAdditionalData node
	//if( !CalcOneData(trOp, nSizeSubject, nSizeFactor, nSizeFactor2))
	//	return error_report("One data calculation failed");
	///end FIX_ESCAPED_STRING_IN_ANOVA_WS_TABLE_LABEL


	/// Iris 8/26/2008 QA80-12098 FIX_ONE_WAY_RM_FAIL_CONVERT_RESULT_CURVE_OP_STR
	//AddBinDataTableAndGraphNodes to add result curve nodes with op str, so need move dr.GetNumData codes to above
	/*
	///Iris 1/19/06 ADD_INPUT_DATA_REPORT_TABLE
	//--- Iris 4/28/06 not get really data number, just get the number column
	//DWORD		dwRules = GetDataRules(trOp);
	DWORD		dwRules = DRR_NO_FACTORS | DRR_NO_WEIGHTS;
	//---
	int			numSubRanges;
	/// ML 8/16/2006 CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	//nNumData = dr.GetNumData(dwRules, NULL, NULL, NULL, &numSubRanges);
	TreeNode	trAdditionalData = tree_check_get_node(trOp,TREE_INPUTRANGE_ADDITIONAL_DATA_NODE_NAME); 
	nNumData = dr.GetNumData(dwRules, trAdditionalData, NULL, NULL, &numSubRanges);
	/// end CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	if(nNumData<=0)
		return false;
	/// ML 8/16/2006 CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	SetTree(trOp);
	/// end CANNOT_TRANSLATE_ESCAPED_STRINGS_IN_RMANOVAS_BUG
	*/
	///end FIX_ONE_WAY_RM_FAIL_CONVERT_RESULT_CURVE_OP_STR
	
	/// Iris 5/29/2008 FIX_ESCAPED_STRING_IN_ANOVA_WS_TABLE_LABEL
	if( !CalcOneData(trOp, nSizeSubject, nSizeFactor, nSizeFactor2))
		return error_report("One data calculation failed");
	///end FIX_ESCAPED_STRING_IN_ANOVA_WS_TABLE_LABEL
	
	//ASSERT(1==nNumData);
	for(int ii = 0; ii < nNumData; ii++)
	{
		Worksheet 	wksData;
		int 		r1, c1, r2, c2;
		dr.GetRange(ii, r1, c1, r2, c2, wksData);
		
		vector<string> vsFactorNames;
		vsFactorNames.Add(m_strFactor);
		if(!IsOneWay())
			vsFactorNames.Add(m_strFactor2);
		UpdateDataSourceInReportingHeader(trOp, vsFactorNames, wksData, ii, numSubRanges, dwRules);		
		
		//remove unused data /// Sophy, current ANOVARM doesn't support missing&masked data report, GUI checkbox should be hidden
		TreeNode trNode = trOp.Calculation.MaskedData;
		if(trNode)
			trNode.Remove();
		trNode = trOp.Calculation.MissingData;
		if(trNode)
			trNode.Remove();		
	}
	
	/// Iris 4/02/2009 QA80-13392-P2 IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE
	// Add factor row in Input table for RM TWO WAY ANOVA 
	if(!IsOneWay())
	{
		TreeNode trFactorAReport = trOp.GUI.InputData.Factor0.Repeat;
		TreeNode trFactorBReport = trOp.GUI.InputData.Factor1.Repeat;
		if( trFactorAReport && trFactorBReport )
		{
			if( 1 == trFactorAReport.nVal + trFactorBReport.nVal ) // one factor repeat and one factor NOT repeat
			{
				/// Iris 4/13/2009 QA80-13392-P2 FIX_INPUT_TABLE_ANOVA2WAY_RM_REPEAT_WITH_NOT_REPEAT
				// for 2 way anova rm by raw data one factor is repeat and one factor is NOT repeat case, 
				// the index of repeat factor is (index of level * number of factors)+1, 
				// for example, if the number of factors of non repeat is 2, the tagName of raw data row of input data table is C1, C3...CN,
				// so to avoid duplicate the tagName of not repeat factor is C(N+1)
				//AddOneRowToInputDataTable(trOp.Calculation.Input, nNumData, 'F', 0);
				int index = m_vsFactors.GetSize() * m_vsFactors2.GetSize() - 1;
				AddOneRowToInputDataTable(trOp.Calculation.Input, index, 'F', 0);
				///end FIX_INPUT_TABLE_ANOVA2WAY_RM_REPEAT_WITH_NOT_REPEAT
				
				TreeNode trFactorRange = trOp.Calculation.Input.LastNode; // added node just now
				string strLabel = m_strFactor2;
				trFactorRange.SetAttribute(STR_LABEL_ATTRIB, strLabel);
			}
		}
	}
	///end IMPROVE_TWO_WAY_ANOVA_RAW_TYPE_INPUTDATA_TABLE	
	///End ADD_INPUT_DATA_REPORT_TABLE 
	
	return true;	
}

bool    ANOVARMReportOperation::ExtractData(TreeNode &trOp, DataRange& dr, int& nSizeSubject, int& nSizeFactor, int& nSizeFactor2)
{
	matrix 		mData;
	
	int 		nRet, nDRTreeOption = GetDRTreeOption(trOp);
	if( DRTREE_ANOVA_ONE_WAY_RAW == nDRTreeOption || DRTREE_ANOVA_TWO_WAY_RAW == nDRTreeOption)
	{
		nRet = ExtractRawData(trOp, dr, mData, nSizeSubject, nSizeFactor, nSizeFactor2);
	}
	else
	{
		nRet = ExtractIndexedData(trOp, dr, mData, nSizeSubject, nSizeFactor, nSizeFactor2);
	}
	if(-1 == nRet)
		return error_report("Invalid RM ANOVA data!");
	if(-2 == nRet)
		return error_report("Cannot extract RM ANOVA data!");
	
	//put data into m_vData from mData
	ConvertData(mData);
	
	return true;			
	
}

//convert data from matrix to m_vData
bool    ANOVARMReportOperation::ConvertData(const matrix& matData)
{
	vector 	vTemp;
	m_vData.RemoveAll();
	for(int nRow = 0; nRow < matData.GetNumRows(); nRow++)
	{
		matData.GetRow(vTemp, nRow);
		m_vData.Append(vTemp);
	}
	return true;
	
}
bool	ANOVARMReportOperation::CalcOneData(TreeNode &trOp, int nSizeSubject, int nSizeFactor, int& nSizeFactor2)
{
	return false;
}

int    ANOVARMReportOperation::ExtractRawData(TreeNode &trOp, DataRange& dr, matrix& mData, int& nSizeSubject, int& nSizeFactor, int& nSizeFactor2)
{
	Worksheet wksFirstRange;
	//DWORD	dwRules = ANOVAReportOperation::GetDataRules(trOp); //get the data rules of normal anova tool
	DWORD	dwRules = GetDataRules(trOp);
	int nNumData = dr.GetNumData(dwRules, NULL, &wksFirstRange, NULL, NULL);
	if (nNumData <= 0)
	{
		return -1;
	}
	
	vector			vData;
	DWORD			dwPlotUID;
	vector<string>	vstrFactors;
	for (int ii = 0; ii < nNumData; ii++)
	{
		int	nRet = dr.GetData(dwRules, ii, &dwPlotUID, NULL, &vData, NULL, NULL, &vstrFactors);
		if(nRet < 0)
			return -2;
		
		mData.SetSize(vData.GetSize(), ii+1, true);
		mData.SetColumn(vData, ii); //get data
		GetFactors(trOp, ii, vstrFactors); //get factor's level name
		nSizeSubject = vData.GetSize(); //get the size of subject
	}
	
	nSizeFactor = m_vsFactors.GetSize();
	nSizeFactor2 = m_vsFactors2.GetSize();
	
	return 0;

}

int    ANOVARMReportOperation::ExtractIndexedData(TreeNode &trOp, DataRange& dr, matrix& mData, int& nSizeSubject, int& nSizeFactor, int& nSizeFactor2)
{
	return -1; //must be overload
}

/// Max 10/09/07 QA70-10491 USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
//bool   ANOVARMReportOperation::GetMeanCompColumnLabels(TreeNode &trOp, const vector<string> &vsFactors, vector<string> &vsLabels1, vector<string> &vsLabels2, bool bIsDunnType, int nFactorIndex)
/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
//bool   ANOVARMReportOperation::GetMeanCompColumnLabels(TreeNode &trOp, const vector<string> &vsFactors, vector<string> &vsLabels1, vector<string> &vsLabels2, bool bIsDunnType, int nFactorIndex, bool bInteraction)
bool   ANOVARMReportOperation::GetMeanCompColumnLabels(TreeNode &trOp, const vector<string> &vsFactors, vector<string> &vsCompLabels, bool bIsDunnType, int nFactorIndex, bool bInteraction)
///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
/// END USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
{
	if( vsFactors.GetSize() <= 1)
		return false;
	
	if(bIsDunnType)
	{
		/// Max 10/09/07 QA70-10491 USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
		if(bInteraction)
			nFactorIndex = (nFactorIndex == 1) ? 2 : 1;
		/// END USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
		
		/// Iris 7/11/06 QA70-7100-P10 ERR_LABEL_IN_DUNNETT_TABLE
		//int ncntrl = trOp.GUI.MeansComp.Dunnett.CtrlLevel1.nVal;
		string 		strNode = "CtrlLevel" + nFactorIndex;
		TreeNode 	trCtrlLevel = trOp.GUI.MeansComp.Dunnett.GetNode(strNode);
		if(!trCtrlLevel)
			return error_report("found invalid CtrlLevel tree node!");
		int 		ncntrl = trCtrlLevel.nVal;
		/// end ERR_LABEL_IN_DUNNETT_TABLE
		
		for(int ii=0; ii<vsFactors.GetSize(); ii++)
		{
			if(ncntrl == ii)
				continue;
			//if(ncntrl > vsFactors.GetSize())
			if(ncntrl >= vsFactors.GetSize())
				break;
			/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
			//vsLabels1.Add(vsFactors[ii]);
			//vsLabels2.Add(vsFactors[ncntrl]);
			vsCompLabels.Add(vsFactors[ii] + " " + vsFactors[ncntrl]);
			///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		}
		return true;
	}
	
	/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	//vsLabels1.RemoveAll();
	//vsLabels2.RemoveAll();
	vsCompLabels.RemoveAll();
	///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	for(int ii=0; ii<vsFactors.GetSize(); ii++)
		for(int jj=0; jj<vsFactors.GetSize(); jj++)
		{
			if(ii >= jj)
				continue;
			
			/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
			//vsLabels1.Add(vsFactors[ii]);
			//vsLabels2.Add(vsFactors[jj]);
			vsCompLabels.Add(vsFactors[ii] + " " + vsFactors[jj]);
			///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		}
	
	return true;
}

bool	ANOVARMReportOperation::GetMeanCompMethod(TreeNode &trOp, MeanCompMethod& stMethods, int& ncntrl, int& ncntrl2, bool bIsOneWay)
{
	TreeNode trMeanComp = trOp.GUI.MeansComp;	
	stMethods.TUKEY = trMeanComp.Tukey.nVal;
	stMethods.BONF = trMeanComp.Bonferroni.nVal;
	stMethods.SIDAK = trMeanComp.DunnSidak.nVal;
	stMethods.FISHER = trMeanComp.FisherLSD.nVal;
	stMethods.SCHEFFE = trMeanComp.Scheffe.nVal;
	/// Iris 05/08/2007 v8.0613 DUNNETT_ONLY_SHOW_FOR_RM_ANOVA, by Max suggestion
	//stMethods.DUNNETT = trMeanComp.Dunnett.Use : 0;
	stMethods.DUNNETT = trMeanComp.Dunnett? trMeanComp.Dunnett.Use : 0;
	///end DUNNETT_ONLY_SHOW_FOR_RM_ANOVA
	stMethods.HOLMBONF = trMeanComp.HolmBonf.nVal;
	stMethods.HOLMSIDAK = trMeanComp.HolmSidak.nVal;
	
	if(trMeanComp.Dunnett.Use)
	{
		ncntrl = trMeanComp.Dunnett.CtrlLevel1.nVal + 1;
		if( !bIsOneWay && NULL!= ncntrl2)
			ncntrl2 = trMeanComp.Dunnett.CtrlLevel2.nVal + 1;
	}
	else
	{
		ncntrl = 0;
		if(NULL!= ncntrl2)
			ncntrl2 = 0;
	}
	
	return true;
}

DWORD	ANOVARMReportOperation::GetDataRules(const TreeNode& trOp, bool bIgnoreCombineInfo)
{
	int 	nDRTreeOption = GetDRTreeOption(trOp);
	DWORD 	dwRet;
	if (DRTREE_ANOVA_ONE_WAY_RAW == nDRTreeOption || DRTREE_ANOVA_TWO_WAY_RAW == nDRTreeOption)
		//return ANOVAReportOperation::GetDataRules(trOp, bIgnoreCombineInfo);
		dwRet = DRR_GET_MISSING | DRR_NO_WEIGHTS;
	else
		dwRet = DRR_RM_ANOVA;
	
	return dwRet;
}


void 	ANOVARMReportOperation::UpdateReportingTables(TreeNode &trOperation, int nTotalNumData, int nExeMode)
{
	WksReportOperation::UpdateReportingTables(trOperation, nTotalNumData, nExeMode);	
		
	if(!UpdateTableString(trOperation.Calculation.MultiTest, false, false, atof(GetTableStringMain(false)) ))
		error_report("ANOVA One Way found invalid Calculation.MultiTest node");
	
	UpdateTableString(trOperation.Calculation.SphericityTest, false, false, atof(GetTableStringMain(false)) );
	
	UpdateTableString(trOperation.Calculation.ANOVAWS, false, false, atof(GetTableStringMain(false)) );
	UpdateTableString(trOperation.Calculation.ANOVABS, false, false, atof(GetTableStringMain(false)) );
	
	UpdateTableString(trOperation.Calculation.Statistics, false, false, atof(GetTableStringMain(false)) );
	
	UpdateTableString(trOperation.Calculation.MeansComp, true, true, atof(GetTableStringMain(false)) );
	
	///Jim 3/10/06 v8.0373 ADD_TABLE_FOOTNOTE 
	trOperation.Calculation.MeansComp.Footnote.RemoveAttribute(TREE_Table);
	///END ADD_TABLE_FOOTNOTE	
}

///Arvin 09/07/07 SHOULD_NOT_SHOW_INTERACTION_RESULT_WHILE_UNCHECK_AFTER_CHANGE_PARAM
///Arvin 09/26/07 ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS
/*
void  ANOVARMReportOperation::ClearOutputTables(TreeNode& trOperation)
{
	StatsOpBase::ClearOutputTables(trOperation);	
		
	bool		bKeepAttrib = true;
	TreeNode 	trOut = trOperation.Calculation;
	if(trOut)
	{
		int bNotes = true;
		foreach(TreeNode trSubNode in trOut.Children)
		{
			if(bNotes)
			{
				bNotes = false;
				continue;
			}
			
			if(trSubNode.GetNodeCount() > 0)
				trSubNode.Reset(bKeepAttrib);
		}
	}
	
}
*/
///end ADD_SUMMARY_TABLE_FOR_MULTI_DATA_COLUMNS
///end SHOULD_NOT_SHOW_INTERACTION_RESULT_WHILE_UNCHECK_AFTER_CHANGE_PARAM
	
bool	ANOVARMReportOperation::AddMultiTestTable(TreeNode &trOp, MultiTestTable &RVMultiStats, int index, LPCSTR lpcszFactor)
{	
	TreeNode	trTable = tree_check_get_node(trOp.Calculation, "MultiTest", IDST_RM_ANOVA_MULTI_TEST, STR_LABEL_ATTRIB, TABLE_RM_MULTI_TEST);
	
	int nStart = index * NUM_MULTI_TEST_SUB_SIZE;
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
	//vector<string> vsLabels = {"Pillai's Trace", "Wilks' Lambda", "Hotelling's Trace", "Roy's Largest Root"};	
	vector<string> vsLabels;
	vsLabels.Add(_L("Pillai's Trace"));
	vsLabels.Add(_L("Wilks' Lambda"));
	vsLabels.Add(_L("Hotelling's Trace"));
	vsLabels.Add(_L("Roy's Largest Root"));
	///end LOCALIZED_FOOTNOTES_STRINGS
	for(int ii=0; ii<vsLabels.GetSize(); ii++)
	{
		string 	strName;
		strName.Format( "row%d", nStart+ii );
		string 	strLabel(lpcszFactor);
		if( strLabel.IsEmpty() )
			strLabel = m_strFactor;
		
		TreeNode trRow = tree_check_get_node(trTable, strName, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, strLabel);
		trRow += RVMultiStats.MTestTable[ii];		
		trRow.ID = make_one_set_ID(IDST_RM_ANOVA_MULTI_TEST, nStart+ii+1);
		tree_add_one_label(trRow, vsLabels[ii], 0);
			
		int nn=0;
		///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
		//vector<string> vsLabels = {"Value", "F", "Num df", "DF", "Prob>F"};
		vector<string> vsLabels;
		vsLabels.Add(_L("Value"));
		vsLabels.Add(_L("F"));
		vsLabels.Add(_L("Num df"));
		vsLabels.Add(_L("DF"));
		vsLabels.Add(_L("Prob>F"));
		///end LOCALIZED_FOOTNOTES_STRINGS
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		foreach(TreeNode trN in trRow.Children)
			trN.SetAttribute(STR_LABEL_ATTRIB, vsLabels[nn++]);
	}
			
	return true;
}
void	ANOVARMReportOperation::AddMultiTestErrorTable(TreeNode &trOp)
{
	TreeNode	trTable = tree_check_get_node(trOp.Calculation, "MultiTest", IDST_RM_ANOVA_MULTI_TEST, STR_LABEL_ATTRIB, TABLE_RM_MULTI_TEST);
	///Jim 3/15/06 v8.0374 ADD_TABLE_FOOTNOTE 
	//TreeNode    trRow = tree_check_get_node(trTable, "row0", IDST_RM_ANOVA_MULTI_TEST+1, STR_LABEL_ATTRIB, "Warnning!");
	//TreeNode    trN = tree_check_get_node(trRow, "Err", IDST_RM_ANOVA_MULTI_TEST+2, STR_LABEL_ATTRIB, " ");
	//trN.strVal = "No Multivariate test performed due to insufficient degrees of freedom.";
	TreeNode 	trFooter = tree_check_get_node(trTable, "Footnote", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
	trFooter.strVal = "Warning: No Multivariate test performed due to insufficient degrees of freedom.";
	///END ADD_TABLE_FOOTNOTE
}

bool	ANOVARMReportOperation::AddSphericityTestTable(TreeNode &trOp, SphericityStats &RVSphericStats, EpsilonStats &RVEpsilonStats, bool bWarnning, int index, LPCSTR lpcszLabel)
{
	string strTableLabel = TABLE_RM_SPHERICITY_TEST;
	/// Iris 2/22/06 FOOTNOTE_REPLACE_WITH_WARN_LABEL
	//if(bWarnning)
	//	strTableLabel += "(Warnning: No Sphericity test performed due to insufficient degrees of freedom.)";
	/// End FOOTNOTE_REPLACE_WITH_WARN_LABEL
	
	TreeNode	trTable = tree_check_get_node(trOp.Calculation, "SphericityTest", IDST_RM_ANOVA_SPHERICITY_TEST, STR_LABEL_ATTRIB, strTableLabel);
		
	string 		strName = TABLE_RM_ROW_PREFIX + index;
	string 		strLabel(lpcszLabel);
	if(strLabel.IsEmpty())
		strLabel = m_strFactor;
	
	TreeNode 	trRow = tree_check_get_node(trTable, strName, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, strLabel);
	trRow += RVSphericStats;
	trRow += RVEpsilonStats;
	trRow.ID = make_one_set_ID(IDST_RM_ANOVA_SPHERICITY_TEST, index+1);
	
	int ii=0;
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
	//vector<string> vsLabels = {"Mauchly's W", "Approx. Chi-Square", "DF", "Prob>ChiSq", "Greenhouse-Geisser Epsilon", "Huynh-Feldt Epsilon", "Lower-bound Epsilon"};
	vector<string> vsLabels;
	vsLabels.Add(_L("Mauchly's W"));
	vsLabels.Add(_L("Approx. Chi-Square"));
	vsLabels.Add(_L("DF"));
	vsLabels.Add(_L("Prob>ChiSq"));
	vsLabels.Add(_L("Greenhouse-Geisser Epsilon"));
	vsLabels.Add(_L("Huynh-Feldt Epsilon"));
	vsLabels.Add(_L("Lower-bound Epsilon"));
	///end LOCALIZED_FOOTNOTES_STRINGS
	///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
	///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	foreach(TreeNode trN in trRow.Children)
	{
		tree_add_one_label(trN, vsLabels[ii++]);
	}
	
	/// Iris 2/22/06 FOOTNOTE_REPLACE_WITH_WARN_LABEL
	if(bWarnning)
	{
		TreeNode trFooter = tree_check_get_node(trTable, "Footer", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
		///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
		//trFooter.strVal = "Warnning: No Sphericity test performed due to insufficient degrees of freedom.";
		string strFooter = "Err: Sphericity Test string not in oErrMsg";
		ocu_load_msg_str(FOOTNOTE_SPHERICITY_TEST, &strFooter);
		trFooter.strVal = strFooter;
		///END LOCALIZED_FOOTNOTES_STRINGS
	}
	/// End FOOTNOTE_REPLACE_WITH_WARN_LABEL
	
	return true;
}

//void	ANOVARMReportOperation::AddSphericityTestErrorTable(TreeNode &trOp)
//{
	//TreeNode	trTable = tree_check_get_node(trOp.Calculation, "SphericityTest", IDST_RM_ANOVA_SPHERICITY_TEST, STR_LABEL_ATTRIB, TABLE_RM_SPHERICITY_TEST);
	//TreeNode    trRow = tree_check_get_node(trTable, "row0", IDST_RM_ANOVA_SPHERICITY_TEST+1, STR_LABEL_ATTRIB, "Warnning!");
	//TreeNode    trN = tree_check_get_node(trRow, "Err", IDST_RM_ANOVA_SPHERICITY_TEST+2, STR_LABEL_ATTRIB, " ");
	//trN.strVal = "No Sphericity test performed due to insufficient degrees of freedom.";
//}

bool	ANOVARMReportOperation::AddANOVATable(TreeNode &trOp, RMANOVARow* pstRMANOVARows, int nSize, LPCSTR lpcszRVFactor, LPCSTR lpcszRVOrNonRVFactor, bool bIsTwoWay, bool bInteraction, bool bBothRV)
{	
	int index = 0;
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
	//vector<string> 	vsANOVAColLabels = {"Sum of Squares", "DF", "Mean Square", "F", "Prob>F"}; //the column header for ANOVA WS & BS Table
	vector<string> 	vsANOVAColLabels;
	vsANOVAColLabels.Add(_L("Sum of Squares"));
	vsANOVAColLabels.Add(_L("DF"));
	vsANOVAColLabels.Add(_L("Mean Square"));
	vsANOVAColLabels.Add(_L("F"));
	vsANOVAColLabels.Add(_L("Prob>F"));
	///end LOCALIZED_FOOTNOTES_STRINGS
	addANOVABSTable(trOp, pstRMANOVARows, nSize, index, vsANOVAColLabels, lpcszRVFactor, lpcszRVOrNonRVFactor, bIsTwoWay, bInteraction, bBothRV);
	
	addANOVAWSTable(trOp, pstRMANOVARows, nSize, index, vsANOVAColLabels, lpcszRVFactor, lpcszRVOrNonRVFactor, bIsTwoWay, bInteraction, bBothRV);
	
	return true;
}

static void _remove_F_and_P_node(TreeNode& trRow, LPCSTR lpcszLabel)
{
	string str(lpcszLabel);
	if( str.Find("Error") >= 0 )
	{
		if(trRow.Fvalue)
			trRow.Fvalue.Remove();
		if(trRow.Pvalue)
			trRow.Pvalue.Remove();
	}
	
}

static void _set_labels(TreeNode& trRow, const vector<string>& vsLabels)
{
	int 	index = 0;
	foreach(TreeNode trN in trRow.Children)
		trN.SetAttribute(STR_LABEL_ATTRIB, vsLabels[index++]);		
}

static string _add_error_prefix(LPCSTR lpcszLabel)
{
	string str(lpcszLabel);
	//str = _L("Error(") + str + _L(")");
	str = _L("Error") + "(" + str + ")"; /// Hong 11/07/07 v.8.0742 FIX_ERROR_LOCALIZED
	return str;
}
// add Tests of Between-Subjects Effects Table
bool	ANOVARMReportOperation::addANOVABSTable(TreeNode &trOp, RMANOVARow* pstRMANOVARows, int nSize, int& index, const vector<string>& vsANOVAColLabels, LPCSTR lpcszRVFactor, LPCSTR lpcszRVOrNonRVFactor, bool bIsTwoWay, bool bInteraction, bool bBothRV)
{
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS	
	//vector<string> 	vsLabels = {"Intercept", "Error"};
	vector<string> 	vsLabels;
	vsLabels.Add(_L("Intercept"));
	vsLabels.Add(_L("Error"));
	///end LOCALIZED_FOOTNOTES_STRINGS
	// Between-Subjects Effects Table should contain non repeated factor
	//add non repeated factor name as the second row header for two way one repeated facto case
	string strRVOrNonRVLabel(lpcszRVOrNonRVFactor);
	if( !strRVOrNonRVLabel.IsEmpty() && !bBothRV)
		vsLabels.InsertAt(1, strRVOrNonRVLabel);
	
	TreeNode		trTable = tree_check_get_node(trOp.Calculation, "ANOVABS", IDST_RM_ANOVA_BS_ANOVA, STR_LABEL_ATTRIB, TABLE_RM_BS_ANOVA);
	for(int ii=0; ii<vsLabels.GetSize(); ii++)
	{
		RMANOVARow stTest;
		stTest = pstRMANOVARows[index];		
		
		string 		strName = TABLE_RM_ROW_PREFIX + ii;
		TreeNode 	trRow = tree_check_get_node(trTable, strName, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, vsLabels[ii]);
		trRow += pstRMANOVARows[index];
		trRow.ID = make_one_set_ID(IDST_RM_ANOVA_BS_ANOVA, index+1);
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		
		//remove F and Prob>F item from Error row
		_remove_F_and_P_node(trRow, vsLabels[ii]);
		
		_set_labels(trRow, vsANOVAColLabels);
		
		index++;
	}	
	return true;
}

// add Tests of Within-Subjects Effects table
bool	ANOVARMReportOperation::addANOVAWSTable(TreeNode &trOp, RMANOVARow* pstRMANOVARows, int nSize, int& index, const vector<string>& vsANOVAColLabels, LPCSTR lpcszRVFactor, LPCSTR lpcszRVOrNonRVFactor, bool bIsTwoWay, bool bInteraction, bool bBothRV)
{	
	//the first labels	
	vector<string> 	vsFirstLabels;	
	
	//get the first factor name, assume A here
	string strRVFactor(lpcszRVFactor);
	if( strRVFactor.IsEmpty() )
		strRVFactor = m_strFactor;	
	ConvertEscapedString(strRVFactor); /// Iris 5/29/2008 FIX_ESCAPED_STRING_IN_ANOVA_WS_TABLE_LABEL
		
	//get the second factor name, assume B here
	string strRVOrNonRVLabel(lpcszRVOrNonRVFactor);
	if( strRVOrNonRVLabel.IsEmpty() )
		strRVOrNonRVLabel = m_strFactor2;
	ConvertEscapedString(strRVOrNonRVLabel); /// Iris 5/29/2008 FIX_ESCAPED_STRING_IN_ANOVA_WS_TABLE_LABEL
	
	//get the Interaction name
	string strInter = strRVFactor + " * " + strRVOrNonRVLabel; // "A * B"
		
	vsFirstLabels.Add(strRVFactor); //add the first factor A
	
	if( bIsTwoWay && bInteraction && !bBothRV)
		vsFirstLabels.Add(strInter); //add Interaction name for one repeated
	
	vsFirstLabels.Add( _add_error_prefix(strRVFactor) ); //add "Error(A)"
	
	if( bBothRV )
	{
		vsFirstLabels.Add(strRVOrNonRVLabel); //add the second factor B
		vsFirstLabels.Add( _add_error_prefix(strRVOrNonRVLabel) ); //add "Error(B)"
		
		if( bIsTwoWay && bInteraction )
		{			
			vsFirstLabels.Add(strInter); // add interaction 
			vsFirstLabels.Add(_add_error_prefix(strInter) ); //add 	"Error(A * B)"	
		}
	}
	
	
	//the second labels
	//vector<string> 		vsSecondLabels_1 = {"Sphericity Assumed", "Greenhouse-Geisser", "Huynh-Feldt", "Lower-bound"};
	//vector<string> 		vsSecondLabels, vsSecondLabels_2(1);
	//vsSecondLabels_2[0] = vsSecondLabels_1[0];	
	//vsSecondLabels = bCalcMauchly?  vsSecondLabels_1 : vsSecondLabels_2;//if not calculate and output Mauchly table, then just output "Sphericity Assumed" here
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS	
	//vector<string> 		vsSecondLabels = {"Sphericity Assumed", "Greenhouse-Geisser", "Huynh-Feldt", "Lower-bound"};
	vector<string> 		vsSecondLabels;
	vsSecondLabels.Add(_L("Sphericity Assumed"));
	vsSecondLabels.Add(_L("Greenhouse-Geisser"));
	vsSecondLabels.Add(_L("Huynh-Feldt"));
	vsSecondLabels.Add(_L("Lower-bound"));
	///end LOCALIZED_FOOTNOTES_STRINGS
	TreeNode 		trTable = tree_check_get_node(trOp.Calculation, "ANOVAWS", IDST_RM_ANOVA_WS_ANOVA, STR_LABEL_ATTRIB, TABLE_RM_WS_ANOVA);
	
	for(int ii=0; ii<vsFirstLabels.GetSize(); ii++)
	{
		for(int jj=0; jj<vsSecondLabels.GetSize(); jj++)
		{
			string 		strName = TABLE_RM_ROW_PREFIX + index;
			TreeNode 	trRow = tree_check_get_node(trTable, strName, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, vsFirstLabels[ii]);
			tree_add_one_label(trRow, vsSecondLabels[jj], 0);
			///Arvin 09/29/07 GET_WRONG_VALUE_WHILE_UNCHECK_INTERACTION
			//trRow += pstRMANOVARows[index];
			//trRow.ID = make_one_set_ID(IDST_RM_ANOVA_WS_ANOVA, index+1);
			int nIndex = index;
			if(!bInteraction && bIsTwoWay && !bBothRV && RMANOVATWOWAYONERV_WITHIN_SUBJECT_FACTOR_LB < index) 
					nIndex = index+RMANOVATWOWAYONERV_INTERACTION_LB-RMANOVATWOWAYONERV_WITHIN_SUBJECT_FACTOR_LB;
			trRow += pstRMANOVARows[nIndex];
			trRow.ID = make_one_set_ID(IDST_RM_ANOVA_WS_ANOVA, nIndex+1);
			///end GET_WRONG_VALUE_WHILE_UNCHECK_INTERACTION
			///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
			tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
			///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		
			//remove F and Prob>F item from Error row
			_remove_F_and_P_node(trRow, vsFirstLabels[ii]);	
			
			_set_labels(trRow, vsANOVAColLabels);
			
			index++;
		}
		

		//if( !bCalcMauchly ) //only add the first one and skip others, but result strcut has the fixed allocation for each row
		//	index += vsSecondLabels_1.GetSize() - 1;
	}
		
	return true;
}

bool	ANOVARMReportOperation::AddDestStatsTable(TreeNode &trOp, TreeNode &trTable, RMANOVADescStats* pDescStats, uint nSizeDescStat, const vector<string>& vsRowLabels1, const vector<string>& vsRowLabels2)
{
	if(vsRowLabels1.GetSize() < nSizeDescStat)
		return false;
	
	for(int ii=0; ii<nSizeDescStat; ii++)
	{
		string strName = TABLE_RM_ROW_PREFIX + ii;
		TreeNode trRow = tree_check_get_node(trTable, strName, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, vsRowLabels1[ii]);
		trRow += pDescStats[ii];		
		trRow.ID = make_one_set_ID(IDST_RM_ANOVA_DEST_STATS, ii+1);
		if(NULL != vsRowLabels2)
			tree_add_one_label(trRow, vsRowLabels2[ii], 0);
		
		///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS	
		//vector<string> vsLabels = {"Mean", "Std. Error"};	
		vector<string> vsLabels;
		vsLabels.Add(_L("Mean"));
		vsLabels.Add(_L("Std. Error"));
		///end LOCALIZED_FOOTNOTES_STRINGS
		vsLabels.Add( getConfiLevelLabel(trOp, true) );
		vsLabels.Add( getConfiLevelLabel(trOp, false) );
		
		int index=0;
		foreach(TreeNode trN in trRow.Children)
			trN.SetAttribute(STR_LABEL_ATTRIB, vsLabels[index++]);	
		
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
		if ( trRow.SEM )
			trRow.SEM.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES

		/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
		// To make consisten id with OneWay Statistics table to use id to get Mean & SE value for plotting 
		if(trRow.Mean)
			trRow.Mean.SetAttribute(STR_DATAID_ATTRIB, IDE_MEAN);
		if(trRow.SEM)
			trRow.SEM.SetAttribute(STR_DATAID_ATTRIB, IDE_SEM);
		///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	}
	
	return true;
}

string  ANOVARMReportOperation::getConfiLevelLabel(TreeNode &trOp, bool bIsLow)
{
	string str;
	str.Format("%d", (int)((1-trOp.GUI.MeansComp.SigLevel.dVal)*100) );
	str += bIsLow? "% LCL" : "% UCL";
	return str;
}

/// Iris 2/25/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
//int    ANOVARMReportOperation::addOneMethodMeanCompTable(TreeNode &trOp, TreeNode &trMethod, TreeNode &trMeanReport, int nType, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nStart, int nEnd, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors, bool bInteraction, LPCSTR lpcszFixFactor, LPCSTR lpcszNonFixFactor, int nFactorIndex)
int    ANOVARMReportOperation::addOneMethodMeanCompTable(TreeNode &trOp, TreeNode &trMethod, TreeNode &trMeanReport, int nType, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nStart, int nEnd, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors, bool bInteraction, LPCSTR lpcszFixFactor, LPCSTR lpcszNonFixFactor, int nFactorIndex, int nPairwiseComparisonTableIndex)
///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
{	
	bool bChecked = TRGP_BRANCH == trMethod.ID? trMethod.Use : trMethod.nVal;
	if(!bChecked)
		return 0; //user not select this type to do calculation
		
	// construct Table and the low level table of each method
	//TreeNode	trTable = tree_check_get_node(trOp.Calculation, "MeansComp", IDST_RM_ANOVA_MEAN_COMP, STR_LABEL_ATTRIB, TABLE_RM_MEAN_COMP);	
	/// Iris 05/21/2007 v8.0622 NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	//int 		nSubTableID = IDST_RM_ANOVA_ONE_MEAN_COMP + nType;
	//string 		strName = trMethod.tagName;
	//string 		strLabel;
	//trMethod.GetAttribute(STR_LABEL_ATTRIB, strLabel);
	int 		nSubTableID;
	string 		strName, strLabel;
	/// Iris 3/02/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE
	//GetMeanCompNodeInfo(strName, strLabel, nSubTableID, nType);
	//nSubTableID = make_one_set_ID(nSubTableID, nPairwiseComparisonTableIndex+1); /// Iris 2/25/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
	GetMeanCompNodeInfo(strName, strLabel, nSubTableID, nType, nPairwiseComparisonTableIndex);
	///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE_MORE
	
	///end NEED_REPORT_PLOTS_IN_RM_ONE_WAY
	TreeNode    trSubTable = tree_check_get_node(trMeanReport, strName, nSubTableID, STR_LABEL_ATTRIB, strLabel);
	trSubTable.SetAttribute(TREE_Table, atof(GetTableStringMain(false)));
	
		
	if(bInteraction)
	{
		int 	nTables = vsNonFixFactors.GetSize(); //the number of intereaction tables		
		int 	nRows = vsFixFactors.GetSize() * (vsFixFactors.GetSize() - 1) / 2; //get the row number of one intereaction table
		if(ANOVA_DUNNETT == nType)
		{
			nTables = 1; //only show one table according to the selected level in Control Level combo box
			nRows = vsFixFactors.GetSize() -1;
		}
		
		int 	nEndRows = nStart + nRows - 1; //the index of the end row of one interaction tables
		
		for(int ii=0; ii<nTables; ii++)
		{
			int 	nCount = trSubTable.Children.Count();
			strName = "InterMeans" + nCount;
			
			string	strNonFixFactor = vsNonFixFactors[ii];
			if(ANOVA_DUNNETT == nType)
			{
				string str;
				str.Format("%s%d","CtrlLevel", nFactorIndex);
				TreeNode trCtrl = trOp.GUI.MeansComp.Dunnett.GetNode(str);
				int nLevel = trCtrl.nVal;
				if( nLevel < vsNonFixFactors.GetSize() )
					strNonFixFactor = vsNonFixFactors[nLevel];
			}
			/// ML 6/16/2008 MULTIFACTOR_OP_ESCAPED_STRING
			//strLabel.Format("%s within %s = %s", lpcszFixFactor, lpcszNonFixFactor, strNonFixFactor);
			LPCSTR			lpcszFixFctNoPrefix = strstr(lpcszFixFactor, OPERATION_ESCAPE_STRING_PREFIX);
			LPCSTR			lpcszNonFixFctNoPrefix = strstr(lpcszNonFixFactor, OPERATION_ESCAPE_STRING_PREFIX);
			if (lpcszFixFctNoPrefix == lpcszFixFactor && lpcszNonFixFctNoPrefix == lpcszNonFixFactor)		// if both have "?:OP:" at the beginning
			{
				int			nn = strlen(OPERATION_ESCAPE_STRING_PREFIX);
				lpcszFixFctNoPrefix += nn;
				lpcszNonFixFctNoPrefix += nn;
				strLabel.Format("%s(%s) (\" within \") (%s) (\" = %s\")", OPERATION_ESCAPE_STRING_PREFIX, lpcszFixFctNoPrefix, lpcszNonFixFctNoPrefix, strNonFixFactor);	// this should probably never execute
			}
			else
				strLabel.Format("%s within %s = %s", lpcszFixFactor, lpcszNonFixFactor, strNonFixFactor);	// this should probably never execute
			/// end MULTIFACTOR_OP_ESCAPED_STRING
			
			int nInterTableID = make_one_set_ID(nSubTableID, nCount);
			TreeNode trInter = tree_check_get_node(trSubTable, strName, nInterTableID, STR_LABEL_ATTRIB, strLabel);
			trInter.SetAttribute(TREE_Table, atof(GetTableStringMain(false)));
			
			try
			{
				addOneMeanCompTable(trOp, trInter, nInterTableID, nType, pMeanCompStats, nSizeMeanComp, nStart, nEndRows, vsFixFactors, bInteraction, nFactorIndex);
			}
			catch(int nErr)
			{
				return error_report("Runtime error in ANOVARMReportOperation::addOneMeanCompTable");	
			}
			
			nStart = nEndRows + 1;
			nEndRows += nRows;
		}
	}
	else
		addOneMeanCompTable(trOp, trSubTable, nSubTableID, nType, pMeanCompStats, nSizeMeanComp, nStart, nEnd, vsFixFactors, bInteraction, nFactorIndex);
	
	return 1;
}

bool    ANOVARMReportOperation::addOneMeanCompTable(TreeNode &trOp, TreeNode &trTable, int nTableID, int nType, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nStart, int nEnd, const vector<string>& vsFixFactors, bool bInteraction, int nFactorIndex)
{
	/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	//construct row names vector
	//vector<string>	vsLabels1, vsLabels2;
	///// Max 10/09/07 QA70-10491 USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
	////GetMeanCompColumnLabels(trOp, vsFixFactors, vsLabels1, vsLabels2, (ANOVA_DUNNETT == nType), nFactorIndex);
	//GetMeanCompColumnLabels(trOp, vsFixFactors, vsLabels1, vsLabels2, (ANOVA_DUNNETT == nType), nFactorIndex, bInteraction);
	///// END USE_WRONG_INDEX_IN_DUNNETT_WHEN_INTERACTION
	vector<string>	vsCompLabels;
	GetMeanCompColumnLabels(trOp, vsFixFactors, vsCompLabels, (ANOVA_DUNNETT == nType), nFactorIndex, bInteraction);
	///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
	
	//construct column names vector
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS	
	//vector<string> vsColLabels = {"Index", "Mean Difference", "Std. Error", "DF", "|t|  value", "Prob>|t|", "Alpha", "Sig Flag"};
	vector<string> vsColLabels;
	vsColLabels.Add(_L("Index"));
	vsColLabels.Add(_L("Mean Difference"));
	vsColLabels.Add(_L("Std. Error"));
	vsColLabels.Add(_L("DF"));
	vsColLabels.Add(_L("|t|  value"));
	vsColLabels.Add(_L("Prob>|t|"));
	vsColLabels.Add(_L("Alpha"));
	vsColLabels.Add(_L("Sig Flag"));
	///end LOCALIZED_FOOTNOTES_STRINGS
	vsColLabels.Add( getConfiLevelLabel(trOp, true) );
	vsColLabels.Add( getConfiLevelLabel(trOp, false) );

	int 		nSize = nEnd - nStart + 1; //the row number of this table
	for(int ii=0; ii<nSize; ii++)
	{
		if(nStart + ii > nEnd || nStart >= nSizeMeanComp || nEnd >= nSizeMeanComp)
			return error_report("incorrect struct index in ANOVARMReportOperation::addOneMeanCompTable");
		
		string 		strName = TABLE_RM_ROW_PREFIX + ii;
		int			nLabelIndex = (ANOVA_BONHOLM == nType || ANOVA_SIDAKHOLM == nType)? pMeanCompStats[nStart+ii].IndexComp : ii;
		if(nLabelIndex >= nSize)
			return error_report("incorrect comparison index in ANOVARMReportOperation::addOneMeanCompTabl");
		
		/// Iris 3/20/2008 v8.0828 QA80-11282-P1 ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		//TreeNode 	trRow = tree_check_get_node(trTable, strName, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, vsLabels1[nLabelIndex]);
		//tree_add_one_label(trRow, vsLabels2[nLabelIndex], 0);
		TreeNode 	trRow = tree_check_get_node(trTable, strName, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, vsCompLabels[nLabelIndex]);
		///end ERR_MEANS_COMP_LABEL_IN_ANOVAOneWayPlots_DataSheet
		trRow += pMeanCompStats[nStart+ii];		
		trRow.ID = make_one_set_ID(nTableID, ii);
		//trRow.IndexComp.Remove(); //no need show
		
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
		if ( trRow.SEM )
			trRow.SEM.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES

		//set col name for this table
		int index=0;
		foreach(TreeNode trN in trRow.Children)
			trN.SetAttribute(STR_LABEL_ATTRIB, vsColLabels[index++]);		
		
		// setup table according to method type
		if(ANOVA_BONHOLM == nType || ANOVA_SIDAKHOLM == nType)
		{
			trRow.LCL.Remove();
			trRow.UCL.Remove();
		}		
	}	
	return true;

}
/// Iris 2/25/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
//int	ANOVARMReportOperation::AddMeanComparisonTable(TreeNode &trOp, TreeNode &trMeanReport, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nSizeFactor, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors, bool bInteraction, LPCSTR lpcszFixFactor, LPCSTR lpcszNonFixFactor, int nFactorIndex)
int	ANOVARMReportOperation::AddMeanComparisonTable(TreeNode &trOp, TreeNode &trMeanReport, MeanCompStats* pMeanCompStats, uint nSizeMeanComp, int nSizeFactor, const vector<string>& vsFixFactors, const vector<string>& vsNonFixFactors, bool bInteraction, LPCSTR lpcszFixFactor, LPCSTR lpcszNonFixFactor, int nFactorIndex, int nPairwiseComparisonTableIndex)
///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
{
	TreeNode trMeanComp = trOp.GUI.MeansComp;
	if( !trMeanComp || nSizeFactor <= 1)
		return -1;
	
	int nInc = nSizeFactor * (nSizeFactor - 1) / 2;
	if(bInteraction)
	{
		nInc = vsNonFixFactors.GetSize() * nInc;
	}
	
	int nStart = 0;
	int nEnd = nInc - 1;
	int nType = ANOVA_TUKEY;
	int nTables = 0; //the number of means comparison table of one method
	
	foreach(TreeNode trN in trMeanComp.Children) //to add each mean comp table for the specail type if selected by user
	{
		if(TRGP_CHECK != trN.ID && TRGP_BRANCH != trN.ID)
			continue;		
				
		/// Iris 2/25/2009 REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
		//nTables += addOneMethodMeanCompTable(trOp, trN, trMeanReport, nType++, pMeanCompStats, nSizeMeanComp, nStart, nEnd, vsFixFactors, vsNonFixFactors, bInteraction, lpcszFixFactor, lpcszNonFixFactor, nFactorIndex);
		nTables += addOneMethodMeanCompTable(trOp, trN, trMeanReport, nType++, pMeanCompStats, nSizeMeanComp, nStart, nEnd, vsFixFactors, vsNonFixFactors, bInteraction, lpcszFixFactor, lpcszNonFixFactor, nFactorIndex, nPairwiseComparisonTableIndex);
		///end REPEAT_ID_CAUSE_JUNK_RANGE_STR_AFTER_SET_AU_TO_NONE
		if(nType > ANOVA_LAST_ITEM)
			return -1;
		
		nStart = nEnd + 1;	
		TreeNode trNext = trN.NextNode;
		if(trNext && TRGP_CHECK == trNext.ID)
		{	
			nEnd += nInc;
		}		
		if(trNext && TRGP_BRANCH == trNext.ID) //Method Type is ANOVA_DUNNETT
		{
			nEnd += nSizeFactor - 1; 
		}
	}	
	
	///Jim 3/15/06 v8.0374 ADD_TABLE_FOOTNOTE 
	TreeNode 	trFooter = tree_check_get_node(trMeanReport, "Footnote", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); // just need the TREE_Footnote attribute, value does not matter, so 1 is good
	string strSigLevel;
	///Arvin 07/24/07 v8.0661 WRONG_DOUBLE_PRESION_NUMBER
	//strSigLevel.Format("%f",trOp.GUI.MeansComp.SigLevel.dVal);
	double dSigLevel = trOp.GUI.MeansComp.SigLevel.dVal;
	strSigLevel = ftoa(dSigLevel);
	///end WRONG_DOUBLE_PRESION_NUMBER
	///Arvin 10/27/07 LOCALIZED_FOOTNOTES_STRINGS
	//trFooter.strVal = "Sig equals 1 indicates that the means difference is significant at the " + strSigLevel + " level.\n";
	//trFooter.strVal += "Sig equals 0 indicates that the means difference is not significant at the " + strSigLevel + " level.\n";
	//trFooter.strVal += "Sig equals -1 indicates that the means difference is not tested.";
	string strFooter = "Err: Mean comparision string not in oErrMsg";
	ocu_load_msg_str(FOOTNOTE_MEAN_COMP, &strFooter, strSigLevel, NULL, strSigLevel);
	string strFooter1;
	ocu_load_msg_str(FOOTNOTE_MEAN_COMP_EX, &strFooter1);
	trFooter.strVal = strFooter + "\n" + strFooter1;
	///end LOCALIZED_FOOTNOTES_STRINGS
	//END ADD_TABLE_FOOTNOTE
	
	return nTables;
}

///Cheney 2007-5-21 NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
void	ANOVARMReportOperation::CheckANOVARMErr(int nErr)
{
	string strErr;
	switch(nErr)
	{
	case NAG_ANOVA_RM_NO_ERR:
		break;
	case NAG_ANOVA_RM_ERR_INPUT_PARAM:
		ocu_load_err_msg_str(CER_ANOVA_RM_ERR_INPUT_PARAM, &strErr);
		break;
	case NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_TEST:
		ocu_load_err_msg_str(CER_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_TEST, &strErr);
		break;
	case NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MULTI_TEST:
		ocu_load_err_msg_str(CER_ANOVA_RM_WARNNING_CANNOT_CALC_MULTI_TEST, &strErr);
		break;
	case NAG_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_OR_MULTI_TEST:
		ocu_load_err_msg_str(CER_ANOVA_RM_WARNNING_CANNOT_CALC_MAUCHLY_OR_MULTI_TEST, &strErr);
		break;
	case NAG_ANOVA_RM_ERR_INTERNAL:
		ocu_load_err_msg_str(CER_ANOVA_RM_ERR_INTERNAL, &strErr);
		break;
	case NAG_ANOVA_RM_ERR_MEMORY_ALLOCATION:
		ocu_load_err_msg_str(CER_ANOVA_RM_ERR_MEMORY_ALLOCATION, &strErr);
		break;
	case NAG_ANOVA_RM_ERR_UNBALANCED_DESIGN:
		ocu_load_err_msg_str(CER_ANOVA_RM_ERR_UNBALANCED_DESIGN, &strErr);
		break;
	default:
	}
	
	if(!strErr.IsEmpty())
		///Cheney 2007-9-26 USE_ERROR_REPORT_TO_SHOW_OPERATION_ERR
		//okoc_out_msg(strErr);	
		/// Iris 6/13/2008 SHOW_ERR_INFO_TO_SCRIPT_WND_FOR_USER, QA reported not return or error info when do ANOVA RM 2 way on Normal Randoms Numbers, error_report only show error info in CB output window
		//error_report(strErr);	
		okoc_out_msg(strErr);	
		///end SHOW_ERR_INFO_TO_SCRIPT_WND_FOR_USER
		///end USE_ERROR_REPORT_TO_SHOW_OPERATION_ERR
}
///end NEED_UPDATE_ERROR_CHECKING_OF_REPORT_TABLE_FOR_OPERATION_BASED_TOOLS
///Sophy 1/9/2009 v8.0995 QA80-12000-P2 ANOVAONEWAY_RM_DONT_SUPPORT_REPORT_MASKED_AND_MISSING_DATA centralize code
//virtual 
void ANOVARMReportOperation::FilterStatsGUI(TreeNode& trOp) 
{
	ANOVAReportOperation::FilterStatsGUI(trOp);

	/// Iris 10/29/2009 QA81-14546 OP_DLG_NEW_STRUCTURE
	//trOp.GUI.Output.Create.MaskedData.Show = false;
	//trOp.GUI.Output.Create.MissingData.Show = false;
	OP_GUI_OUTPUT_TABLES_BRANCH(trOp.GUI).MaskedData.Show = false;
	OP_GUI_OUTPUT_TABLES_BRANCH(trOp.GUI).MissingData.Show = false;
	///end OP_DLG_NEW_STRUCTURE
}
///end ANOVAONEWAY_RM_DONT_SUPPORT_REPORT_MASKED_AND_MISSING_DATA
//////////////////////////ANOVARMReportOperation//////////////////////////



#define		STR_NONPARAMETRIC_TABLE		"NonparametricTest"
#define 	STR_RANKS_TABLE				"Ranks"
class OC_REGISTERED NonparametricStats : public StatsOpBase
{
protected:
	//virtual 
	DWORD	GetDataRules(const TreeNode& trOp, bool bIgnoreCombineInfo = false );
	
	//virtual 
	int 	ConstructGraphNumber();
	
	void 	UpdateReportingTables(TreeNode &trOperation, int nTotalNumData, int nExeMode);
	
	//to decide which node should be hidden, or be show, and to update label name if needed
	void    FilterDescStatsTable(TreeNode &trOp);	
	
	BOOL	CalcOneData(TreeNode &trOp, int index, int nTotalNumData, const vector<int> &vFactorSizes,
					const vector<string> &vstrFactors, vector &vData, vector &vDummy, matrix &mDummy, vector &vWeights, DWORD dwPlotObjUID, int nRowColIndex, const vector<int>& vintRowsInSource = NULL);
	
	void 	AddTESTTable(TreeNode& trOp, const NPHStats& stStats, LPCSTR lpcszTableLabel=NULL, const vector<string>& vsColLabels=NULL,
			vector<int>& vnShow=NULL);
			
	void 	AddRanksTable(TreeNode& trOp, NPHRanks* pstKruRanks, int iLevels, LPCSTR lpcszDataLabel, const vector<string>& vsMoreDataLabels=NULL);

private:
	void	getDependentData(const vector& vData);

protected:
	vector			m_vDepVars;
	vector<string>  m_vsDataLabels;

};

DWORD 	NonparametricStats::GetDataRules(const TreeNode& trOp, bool bIgnoreCombineInfo )	
{
	/// Iris 11/03/05 should remove missing data before calculation
	//DWORD dwRet =  DRR_GET_MISSING|DRR_NO_WEIGHTS;
	DWORD dwRet =  DRR_NO_WEIGHTS;
	return CheckDataRules(trOp, dwRet, bIgnoreCombineInfo);
}
	
void 	NonparametricStats::UpdateReportingTables(TreeNode &trOperation, int nTotalNumData, int nExeMode)
{
	StatsOpBase::UpdateReportingTables(trOperation, nTotalNumData, nExeMode);
	
	TreeNode 	trTable = trOperation.Calculation.GetNode(TABLE_DESC_STATS);
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain(false)); 

	trTable = trOperation.Calculation.GetNode(STR_NONPARAMETRIC_TABLE);
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain(true));

	trTable = trOperation.Calculation.GetNode(STR_RANKS_TABLE);
	if(trTable)
		trTable.SetAttribute(TREE_Table, GetTableStringMain(false));

}

void    NonparametricStats::FilterDescStatsTable(TreeNode &trOp)
{
	TreeNode trStats = trOp.Calculation.Statistics;
	if( !trStats )
		return;
	
	TreeNodeCollection trColl( trStats, CALCULATION_REPORT_TABLE_COL_PREFIX);
	foreach(TreeNode trNode in trColl)
	{
		//move Median before Min
		TreeNode trMedTemp = trNode.Median.Clone();
		trNode.Median.Remove();
		TreeNode trMed = trNode.InsertNode(trNode.Min, "Junk");
		trMed.Replace(trMedTemp);
		trMed.Show = true;
		
		trNode.Mean.Show = false;
		trNode.SD.Show = false;
		trNode.SEM.Show = false;			
		
		//set some nodes show and change label attribute to give full name
		trNode.Min.Show = true;
		trNode.Min.SetAttribute(STR_LABEL_ATTRIB,_L("Minimum"));

		///Echo 8/22/06 USE_STANDARD_NAME
		//trNode.Q25.Show = true;
		//trNode.Q75.Show = true;
		trNode.Q1.Show = true;
		trNode.Q3.Show = true;
		///END USE_STANDARD_NAME
		
		trNode.Max.Show = true;
		trNode.Max.SetAttribute(STR_LABEL_ATTRIB,_L("Maximum"));

	}	
}

BOOL	NonparametricStats::CalcOneData(TreeNode &trOp, int index, int nTotalNumData, const vector<int> &vFactorSizes,
				const vector<string> &vstrFactors, vector &vData, vector &vDummy, matrix &mDummy, vector &vWeights, DWORD dwPlotObjUID, int nRowColIndex, const vector<int>& vintRowsInSource)
{
	getDependentData(vData);
	
	if(NULL != vstrFactors && vstrFactors.GetSize()>0 )
		m_vsDataLabels.Add(vstrFactors[0]);
	else
	{
		string			strDataLabel;
		GetOneDataLabel(trOp, index, nRowColIndex, strDataLabel);
		m_vsDataLabels.Add(strDataLabel);
	}

	
	return true;
	
}

void 	NonparametricStats::AddTESTTable(TreeNode& trOp, const NPHStats& stStats, LPCSTR lpcszTableLabel, const vector<string>& vsColLabels,
			vector<int>& vnShow)
{								
	TreeNode	trTable = tree_check_get_node(trOp.Calculation, STR_NONPARAMETRIC_TABLE, IDST_TEMP_ONE_SET, STR_LABEL_ATTRIB, lpcszTableLabel);	

	trTable += stStats;
	trTable.ID = IDST_NONPARAMETRIC_TTEST_RESULT;
	
	int index=0;
	foreach(TreeNode trSub in trTable.Children)
	{
		if( vnShow && index<vnShow.GetSize() )
			trSub.SetAttribute(STR_SHOW_ATTRIB, vnShow[index]);
		
		if( vsColLabels && index<vsColLabels.GetSize() )
			trSub.SetAttribute(STR_LABEL_ATTRIB, vsColLabels[index]);
		
		index++;
	}	
}
	
void 	NonparametricStats::AddRanksTable(TreeNode& trOp, NPHRanks* pstKruRanks, int iLevels, LPCSTR lpcszDataLabel, const vector<string>& vsMoreDataLabels)
{								
	TreeNode	trTable = tree_check_get_node(trOp.Calculation, STR_RANKS_TABLE, IDST_KWANOVA_RANKS_RESULT, STR_LABEL_ATTRIB, _L("Ranks"));	
	for(int nRow=0; nRow<iLevels; nRow++)
	{
		TreeNode	trRow = check_add_enumerated_node(trTable, 
											CALCULATION_REPORT_TABLE_COL_PREFIX, 
											nRow+1, 
											IDST_TEMP_ONE_SET,
											STR_LABEL_ATTRIB,
											lpcszDataLabel												
											);
		trRow += pstKruRanks[nRow];
		trRow.ID = IDST_KWANOVA_RANKS_RESULT+nRow;
		
		vector<string> 	vsOneFactor;
		if(NULL == vsMoreDataLabels)
			vsOneFactor.Add( m_vsDataLabels[nRow] );
		else
			vsOneFactor.Add( vsMoreDataLabels[nRow] );
		tree_add_more_labels(trRow, vsOneFactor);
		
		trRow.MeanRank.SetAttribute(STR_LABEL_ATTRIB, _L("Mean Rank"));
		trRow.SumRank.SetAttribute(STR_LABEL_ATTRIB, _L("Sum Rank"));
	}		
}
	
void	NonparametricStats::getDependentData(const vector& vData)
{
	m_vDepVars.Append(vData);
}
	
int 	NonparametricStats::ConstructGraphNumber()
{
	return 0;
}	
#endif //_STATS_OPBASE_H
