#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
/*------------------------------------------------------------------------------*
*	Modification Log:															*
*	Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING					*
*	Echo 7/25/07 QA70-7191-P7 v8.0667 SA_COMP_NOT_SUPPORT_1_GROUP				*
*	Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT						*
*	Max 3/7/08 LOCALIZE_PREDEFINED_STRING										*
*	Max 3/7/08 SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION		*
*	Max 3/19/08 SHOULD_NOT_RESET_VARIABLE_VALUE_IN_LT							*
*	Folger 02/20/09 OUTPUT_NODES_SHOULD_BE_DISABLED_IN_CAHNGE_PARAM				*
*	Kyle 03/02/2009 SHOULD_NOT_CHANGE_OUTPUT_ON_GUI_ON_CHANGE_PARAMETERS		*
*   Iris 7/13/2009 QA80-8440 ADD_PLOT_WEIBULL_XF								*
*	Folger 08/26/2010 ORG-920-P2 KAPLAN_MEIER_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
*-------------------------------------------------------------------------------*/
//put additional include files here
#include <GetNBox.h>
#include <ReportTree.h>
#include <report_utils.h>
#include <stats_utils.h>
#include <event_utils.h>
#include <control.h>
#include <o8dlg.h>
//put your own support static functions here

#define KM_REPORT_TABLE 100    //Eric  2006/4/6
#define SA_QUAN_ESTM	3
#define	SUPPRESS_ALL_OUTPUT_MSG "All output have been suppressed. Please select at least one statistical display!"

#define IDST_SA_TIME          0x00000010
#define IDST_SA_KM_SE         0x00000012
#define IDST_SA_QE            0x10000001
#define IDST_SA_MEAN_EST      0x10020001
#define IDST_SA_COMP_TE       0x11000000
#define IDST_SA_COMP_LOGRANK  0x11000005
#define IDST_SA_COMP_BRESLOW  0x11000010
#define IDST_SA_COMP_TW       0x11000015

enum
{
	WARN_NO_GROUP = XF_LOCAL_ERR_BEGIN,
	ERR_TOO_FEW_GROUP,		
};



static void _get_km_estimates(SAEstim stSurvivEstim, vector<string>& vKMEstim)
{
	vKMEstim.SetSize(6);
	vKMEstim[0] = ftoa(stSurvivEstim.Time);
	vKMEstim[1] = (1 == stSurvivEstim.Status) ? "+" : " ";
	vKMEstim[2] = ftoa(stSurvivEstim.Surv);
	vKMEstim[3] = ftoa(stSurvivEstim.SD);
	vKMEstim[4] = ftoa(stSurvivEstim.Events);
	vKMEstim[5] = ftoa(stSurvivEstim.Remain);
	
}

static void _get_quantile_estimate(double dPerc, SAQuantEst stSAQuantEstim, vector& vQuanEstims)
{
	vQuanEstims.SetSize(4);
	vQuanEstims[0] = dPerc;
	vQuanEstims[1] = stSAQuantEstim.Perc;
	vQuanEstims[2] = stSAQuantEstim.LCL;
	vQuanEstims[3] = stSAQuantEstim.UCL;
}


static void _get_comp_results(SFComp stSFComp, vector& vCompRes)
{
	vCompRes.SetSize(3);
	vCompRes[0] = stSFComp.ChiSq ;
	vCompRes[1] = stSFComp.DOF ;
	vCompRes[2] = stSFComp.Prob ;
}

/// Iris 7/13/2009 QA80-8440 ADD_PLOT_WEIBULL_XF, moved to report_utils
/*
static void _get_surv_plot_data(const int nSurvivEstim, const SAEstim *pSurvivEstim, vector& vX, vector& vY, vector& vErrors)
{
	vX.SetSize(nSurvivEstim+1);
	vY.SetSize(nSurvivEstim+1);
	vErrors.SetSize(nSurvivEstim+1);
	vX[0] = 0;
	vY[0] = 1;
	//vErrors[0] = 1;
	vErrors[0] = 0;
	
	for (int ii = 0; ii < nSurvivEstim; ii++)
	{
		vX[ii+1] = pSurvivEstim[ii].Time;
		vY[ii+1] = pSurvivEstim[ii].Surv;
		vErrors[ii+1] = pSurvivEstim[ii].SD;
		
	}
}
*/
///end ADD_PLOT_WEIBULL_XF

void km_add_surv_estimate(ReportTable& outRT, const int nSurvivEstim, const SAEstim *pSurvivEstim)
{	
	//Kaplan-Meier Estimates
	ReportTable rtKaplan = outRT.CreateTable("KaplanMeier", _L("Kaplan-Meier Survival Estimates"), IDST_SA_KM_SE);
	vector<string> vstrKaplanLabels(6), vstrKMTagName;
	vstrKaplanLabels[0] = _L("Time");
	vstrKaplanLabels[1] = _L("Status");
	vstrKaplanLabels[2] = _L("Cumulative Survival");
	vstrKaplanLabels[3] = _L("Standard Error");
	vstrKaplanLabels[4] = _L("Cumulative Event");
	vstrKaplanLabels[5] = _L("Number Remaining");
	
	string strKMTagName = SA_KM_ESTIM;
	strKMTagName.GetTokens(vstrKMTagName, '|');
	
	int ii;
	vector<string> vSurvivEstims;
	vector vX,vY, vErrors;
	vX.SetSize(nSurvivEstim+1);
	vY.SetSize(nSurvivEstim+1);
	vErrors.SetSize(nSurvivEstim+1);
	vX[0] = 0;
	vY[0] = 1;
	vErrors[0] = 1;
	
	for (ii = 0; ii < nSurvivEstim; ii++)
	{
		_get_km_estimates(pSurvivEstim[ii], vSurvivEstims);
		string strRow = "T"+ftoa(ii+1);
		/// Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING
		//rtKaplan.AddRow(_L(""), vSurvivEstims, _L(" "), vstrKaplanLabels, NULL, make_one_set_ID(IDST_SA_KM_SE, ii));	
		rtKaplan.AddRow(strRow, vSurvivEstims, " ", vstrKaplanLabels, vstrKMTagName, make_one_set_ID(IDST_SA_KM_SE, ii));	
		/// End REMOVE_SPACE_LOCATION_STRING
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		TreeNode trRow = rtKaplan.GetNode(strRow);
		if ( trRow )
		{
			tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
			if ( trRow.SE )
				trRow.SE.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
		}
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	}
	
	// add footnode
	TreeNode trFooter = tree_check_get_node(rtKaplan, "Footer", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1");
	trFooter.strVal = _L("Observation with status as + are censored ones");
		
}

void km_add_quartile_estimates(ReportTable& outRT, const double dConfLevel, const SAQuantEst *pSAQuantEstim)
{
	ReportTable rtQuan = outRT.CreateTable("Quan", _L("Quartile Estimates"), IDST_SA_QE);
	vector<string> vstrQuanLabels(4), vstrTagName;
	vstrQuanLabels[0] = _L("Percent");
	vstrQuanLabels[1] = _L("Estimate");
	vstrQuanLabels[2] = ftoa(dConfLevel) + "% LCL";
	vstrQuanLabels[3] = ftoa(dConfLevel) + "% UCL";
	
	string strTagName = SA_KM_QUAN;
	strTagName.GetTokens(vstrTagName, '|');
	
	vector vQuanEstims, vPercent(SA_QUAN_ESTM);
	vPercent[0]= 25.0;
	vPercent[1]= 50.0;
	vPercent[2]= 75.0;
	for (int ii = 0; ii < SA_QUAN_ESTM; ii++)
	{
		_get_quantile_estimate(vPercent[ii], pSAQuantEstim[ii], vQuanEstims);
		string strRow = "Quan" + ftoa(ii+1);
		/// Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING
		//rtQuan.AddRow(_L(""), vQuanEstims, _L(" "), vstrQuanLabels, NULL, make_one_set_ID(IDST_SA_QE, ii));		
		rtQuan.AddRow(strRow, vQuanEstims, " ", vstrQuanLabels, vstrTagName, make_one_set_ID(IDST_SA_QE, ii));		
		/// End REMOVE_SPACE_LOCATION_STRING
		///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
		TreeNode trRow = rtQuan.GetNode(strRow);
		if ( trRow )
			tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
		///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	}
	
	
}

static void _get_mean_estim(const SAMeanEst& stSAMeanEst, vector& vMeanEstim)
{
	vMeanEstim.SetSize(4);
	vMeanEstim[0] = stSAMeanEst.Estimate;
	vMeanEstim[1] = stSAMeanEst.SE;
	vMeanEstim[2] = stSAMeanEst.LCL;
	vMeanEstim[3] = stSAMeanEst.UCL;
	
}

void km_add_mean_estim(ReportTable& outRT, const double dConfLevel, const SAMeanEst& stSAMeanEst)
{
	ReportTable rtMean = outRT.CreateTable("Mean", _L("Mean Estimate"), IDST_SA_MEAN_EST);
	vector<string> vstrMeanLabels(4);
	vstrMeanLabels[0] = _L("Estimate");
	vstrMeanLabels[1] = _L("Std.Error");
	vstrMeanLabels[2] = ftoa(dConfLevel) + "% LCL";
	vstrMeanLabels[3] = ftoa(dConfLevel) + "% UCL";
	
	vector<string> vstrTagName;
	string strTagName = SA_KM_MEAN;
	strTagName.GetTokens(vstrTagName, '|');
	
	vector vMeanEstim;
	_get_mean_estim(stSAMeanEst, vMeanEstim);
	/// Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING
	//rtMean.AddRow(_L(""), vMeanEstim, _L(" "), vstrMeanLabels, NULL, IDST_SA_MEAN_EST + 1);		
	rtMean.AddRow("Mean", vMeanEstim, " ", vstrMeanLabels, vstrTagName, IDST_SA_MEAN_EST + 1);		
	/// End REMOVE_SPACE_LOCATION_STRING
	///Sophy 3/30/2009 QA80-13352 SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	TreeNode trRow = rtMean.GetNode("Mean");
	if ( trRow )
	{
		tree_set_attribute_to_all_nodes(trRow, STR_COL_DESIGNATION_ATTRIB, (string)OKDATAOBJ_DESIGNATION_Y);
		if ( trRow.SE )
			trRow.SE.SetAttribute(STR_COL_DESIGNATION_ATTRIB, OKDATAOBJ_DESIGNATION_ERROR);
	}
	///end SUPPORT_SPECIFY_COLUMN_DESIGNATIONS_IN_REPORT_TABLES
	if (stSAMeanEst.Limited)
	{
		TreeNode trFooter = tree_check_get_node(rtMean, "Footer", IDE_FOOTNOTE_BEGIN, TREE_Footnote, "1"); 
		trFooter.strVal = _L("Estimation is underestimated because the largest observation is censored");		
		
	}
	
}


void km_add_overall_comp_report_tree(ReportTree& outRT, int nLogRank, int nBreslow, int nTarone, SFComp *pSFComp = NULL)
{
		//////////////////////////////////////////////////////////////////
	// Test Equality of SA Functions
	//////////////////////////////////////////////////////////////////
	ReportTable rtComp = outRT.CreateTable("Comp", _L("Test of Equality over Groups"), IDST_SA_COMP_TE);	
	vector vCompRes;
	vector<string> vstrCompLabels(3);
	vstrCompLabels[0] = _L("Chi-Square");
	vstrCompLabels[1] = _L("df");
	vstrCompLabels[2] = _L("Prob>Chi-Square");
	
	vector<string> vstrTagName;
	string strTagName = TEST_STATS_TABLE;
	strTagName.GetTokens(vstrTagName, '|');
	
	if (nLogRank)
	{
		_get_comp_results(pSFComp[0], vCompRes);
		rtComp.AddRow(_L("LogRank"), vCompRes, _L("Log Rank"), vstrCompLabels, vstrTagName, IDST_SA_COMP_LOGRANK);
	}
	if (nBreslow)
	{
		_get_comp_results(pSFComp[1], vCompRes);
		rtComp.AddRow(_L("Breslow"), vCompRes, _L("Breslow"), vstrCompLabels, vstrTagName, IDST_SA_COMP_BRESLOW);
	}
	if (nTarone)
	{
		_get_comp_results(pSFComp[2], vCompRes);
		rtComp.AddRow(_L("Tarone"), vCompRes, _L("Tarone-Ware"), vstrCompLabels, vstrTagName, IDST_SA_COMP_TW);
	}
			
	
}

static bool _at_least_1_output(const TreeNode& trGetN)
{
	if (trGetN.summary.nVal || trGetN.survfunc.nVal || trGetN.quartile.nVal || trGetN.sf.nVal || trGetN.omsf.nVal || trGetN.lsf.nVal)
		return true;
	else
		return false;
}

static int _get_comp_num(const TreeNode& trGetN)
{
	return trGetN.logrank.nVal + trGetN.breslow.nVal + trGetN.tarone.nVal;
}

static int km_check_input(TreeNode& trGetN)
{
	int nErr = CER_NO_ERROR;
	
	//If data is selected in Group Range
	TreeNode trRange = trGetN.irng;
	
	/// YuI 08/19/09 QA70-14173 BRANCHED_RANGES_MAY_BE_INPROPERLY_INITIALIZED_IF_EMPTY_STRING
	string strVal = trRange.strVal;
	if( !sa_check_range_string(strVal) )
		return CER_NOT_SA_DATA;
	/// end BRANCHED_RANGES_MAY_BE_INPROPERLY_INITIALIZED_IF_EMPTY_STRING	
	
	Range rData;
	okxf_resolve_tree_construct_range(&trRange, &rData);
	bool bNoGroup = true;
	if (rData)
	{
		vector vTime, vCensor, vGroup, vNumInGrp;
		vector<string> vstrGrpLab;
		int nRet = km_get_data(rData, vTime, vCensor, vGroup, vNumInGrp, vstrGrpLab);
		if (CER_NO_ERROR != nRet)
			return nRet;
		///Echo 7/25/07 QA70-7191-P7 v8.0667 SA_COMP_NOT_SUPPORT_1_GROUP
		double dMin, dMax;
		vGroup.GetMinMax(dMin, dMax);
		bNoGroup = (dMin == dMax) ? true : false;
	}
		///end SA_COMP_NOT_SUPPORT_1_GROUP
	
	//Without Group Range, Plot in one check box can not be selected
	//if( bNoGroup && trGetN.plotinone.nVal && CER_NO_ERROR == nErr)
	//{
		//nErr = CER_KM_NO_GROUP_PLOT;
	//}
		
	//Without Group Range, check boxes in Test Equality branch can not be selected
	if( bNoGroup && 0 != _get_comp_num(trGetN)  && CER_NO_ERROR == nErr)
	{
		nErr = CER_KM_NO_GROUP_EQUALITY;
	}
	if ( !_at_least_1_output(trGetN)  && CER_NO_ERROR == nErr)
	{
		nErr = CER_SUPPRESS_ALL_OUTPUT;
	}
	
	if (nErr == CER_NO_ERROR)
		nErr = check_valid_censoring(trGetN);
		
	if (!check_conf_level(trGetN.conf) && CER_NO_ERROR == nErr)
	{
		nErr = CER_INVALID_CONF_LEV;
	}
		
	//Plot in one check box and Confidence interval check box can not be selected together
	if( trGetN.plotinone.nVal && trGetN.sfci.nVal  && CER_NO_ERROR == nErr)
	{
		nErr = CER_SURV_PLOT;
	}
	
	return nErr;
		
}

void kaplanmeier(const Range& irng, const vector& censor, const int& summary, const int& survfunc, const int& quartile, const int& mean, const double& conf, const int& sf, const int& sfci, const int& omsf, const int& hazard, const int& lsf, const int& plotinone, const int& logrank, const int& breslow, const int& tarone, ReportData& rd, ReportTree& rt)
{
	
	vector vTime, vCensor, vGroup, vNumInGrp;
	vector<string> vstrGrpLab;
	int nRet = km_get_data(irng, vTime, vCensor, vGroup, vNumInGrp, vstrGrpLab);
	if (CER_COL_NUM_NOT_ONE_EX == nRet)
		XF_THROW_EX(CER_COL_NUM_NOT_ONE_EX, _L("Grouping Range"));
	if (CER_NO_ERROR != nRet)
		XF_THROW(nRet);
	
	int nGroup = vNumInGrp.GetSize();
	
	LPCSTR lpsczLabel = _L("Kaplan-Meier Estimates");
	report_tree_create(rt, lpsczLabel, "irng");	
	sa_add_note_time_ls_0(rt, vTime);	
	
	vNumInGrp.InsertAt(0,0);
	int nBegin = 0, nEnd;
	
	int nPlot = sf + omsf + hazard + lsf;
		
	for (int ii = 0; ii < nGroup; ii++)	
	{
		vector vSubTime, vSubCensor;
		nBegin = nBegin + (int)vNumInGrp[ii];
		nEnd = nBegin + (int)vNumInGrp[ii + 1];
		vTime.GetSubVector(vSubTime, nBegin, nEnd - 1);
		vCensor.GetSubVector(vSubCensor, nBegin, nEnd - 1);
	
		int nSizeSAEstm = vSubTime.GetSize();
		SAEstim* pSurvivEstim = (SAEstim*) malloc (nSizeSAEstm * sizeof(SAEstim));
		SAQuantEst pSAQuantEstim[SA_QUAN_ESTM];
		SASummary stSASumStats;
		SAMeanEst stSAMeanEst;	
		
		double dConfLevel = conf / 100;
		nRet = 	ocmath_kaplan_meier_surviv_fn(vSubTime, vSubTime.GetSize(), vSubCensor, vSubCensor.GetSize(), censor, censor.GetSize(), 
											dConfLevel, pSurvivEstim, nSizeSAEstm,pSAQuantEstim,SA_QUAN_ESTM, &stSASumStats, &stSAMeanEst);	
		
	    if(summary)
	    {
	       if (nGroup > 1)
	           rt_add_sa_summary(rt, stSASumStats, censor, vstrGrpLab[ii], ii);
	       else
		       rt_add_sa_summary(rt, stSASumStats, censor);
	    }
	
		if (survfunc || quartile)
		{
			ReportTable rtSA;
			string strSubsetName = "SA";
			string strGroup = "";
			int nID = IDST_SA_TIME;
			if (nGroup > 1)
			{
				strSubsetName += ftoa(ii+1);
				nID += ii;
				strGroup = vstrGrpLab[ii];
			}
			string strLongName;
			strLongName.Format(_L("Survival Analysis of Time (%s)"), strGroup);
			rtSA = rt.CreateTable(strSubsetName, strLongName, nID);	
			
			if (survfunc)
				km_add_surv_estimate(rtSA, nSizeSAEstm, pSurvivEstim);
			if (quartile)
				km_add_quartile_estimates(rtSA, conf, pSAQuantEstim);
			if (mean)
				km_add_mean_estim(rtSA, conf, stSAMeanEst);
	
		}
	    ///Kyle 03/02/2009 SHOULD_NOT_CHANGE_OUTPUT_ON_GUI_ON_CHANGE_PARAMETERS
	 	//if (nPlot != 0)   
	 	if (nPlot != 0 && rd)   
	 	///End SHOULD_NOT_CHANGE_OUTPUT_ON_GUI_ON_CHANGE_PARAMETERS
	 	{
			rd.ID = IDST_RESULT_CURVES;	
	 		vector vX, vY, vErrors;
	 		/// Iris 7/13/2009 QA80-8440 ADD_PLOT_WEIBULL_XF
	 		//_get_surv_plot_data(nSizeSAEstm, pSurvivEstim, vX, vY, vErrors);
	 		get_surv_plot_data(nSizeSAEstm, pSurvivEstim, vX, vY, vErrors);
	 		///end ADD_PLOT_WEIBULL_XF
			surv_update_report_data(rd, conf/100, vX, vY, vErrors,ii, vstrGrpLab, sf, hazard, sfci, omsf, lsf);
	 	}
	
		free(pSurvivEstim);
	}
	if(nPlot != 0)
	{
	   	survival_rd_plotting(rd, vstrGrpLab, rt, sf, hazard, sfci, omsf, lsf, plotinone, false);
	}
		
	if (logrank || breslow || tarone )									
	{
		if (0 == vGroup.GetSize())
		{
			XF_THROW(WARN_NO_GROUP);
		}
		if (nGroup < 2)
		{
			XF_THROW(ERR_TOO_FEW_GROUP);
		}
		
		SFComp pSFComp[3], stLogRank, stBreslow, stTarone; 
		nRet = 	ocmath_surviv_fn_comp(vTime, vTime.GetSize(), vCensor, vCensor.GetSize(), vGroup, vGroup.GetSize(), censor, censor.GetSize(), &stLogRank, 0);								;	
		if (nRet != STATS_NO_ERROR)
			XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
		pSFComp[0] = stLogRank;
		
		nRet = 	ocmath_surviv_fn_comp(vTime, vTime.GetSize(), vCensor, vCensor.GetSize(), vGroup, vGroup.GetSize(), censor, censor.GetSize(), &stBreslow, SA_SFCOMP_BRESLOW);								;
		if (nRet != STATS_NO_ERROR)
			XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
		pSFComp[1] = stBreslow;
		
		nRet = 	ocmath_surviv_fn_comp(vTime, vTime.GetSize(), vCensor, vCensor.GetSize(), vGroup, vGroup.GetSize(), censor, censor.GetSize(), &stTarone, SA_SFCOMP_TARONEWARE);								;
		if (nRet != STATS_NO_ERROR)
			XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
		pSFComp[2] = stTarone;
		
		km_add_overall_comp_report_tree(rt,logrank, breslow, tarone, pSFComp);
		
	}	
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int kaplanmeier_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return kaplanmeier_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	TreeNode trRange = trGetN.irng;
	TreeNode trCensor = trGetN.censor;
	/// YuI 08/19/09 QA70-14173 BRANCHED_RANGES_MAY_BE_INPROPERLY_INITIALIZED_IF_EMPTY_STRING
	// should not set censor list until we know that input data is good
	//	if (trRange && trCensor)
	//		set_censor_list(trRange, trCensor);
	/// end BRANCHED_RANGES_MAY_BE_INPROPERLY_INITIALIZED_IF_EMPTY_STRING
	
	trGetN.irng.SetAttribute(STR_ATTRIB_BRANCH, GETNBRANCH_OPEN);
	trGetN.conf.Enable = trGetN.quartile.nVal || trGetN.mean.nVal;
		
	///Echo 9/22/06 The setting is not reasonable when play with theme. So error messages are used to treat such case insteadly
	/*
	if (nEventID >= 0)
	{
		//Branch "Test Equality of SA Functions" only avaiable if data is selected in Group Range
		Range rData;
		okxf_resolve_tree_construct_range(&trRange, &rData);
		bool bGroup;
		if( rData )
		{
			vector vGroup;
			rData.GetData(vGroup, 2);
			//Test Equality branch only enable if Group Range is set
			bGroup = trGetN.trComp.Enable = (vGroup.GetSize() == 0) ? false : true;	
		}
			
		if ( bGroup )//if Group Range is set
		{
			//Plot in one check box only enables if one of plots type is selected
			trGetN.plotinone.Enable = bPlot;
				
		}else
		{
			//if no Group Range, Plot in one check box is diabled
			trGetN.plotinone.nVal = trGetN.plotinone.Enable = false;
		}
	}
	*/
	
	//Plot in one check box and Confidence interval check box can not be selected together
	//trGetN.sfci.Enable = 1 - trGetN.plotinone.nVal;
	
	///------ Folger 08/26/2010 ORG-920-P2 KAPLAN_MEIER_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	/*
	///------ Folger 02/20/09 OUTPUT_NODES_SHOULD_BE_DISABLED_IN_CAHNGE_PARAM
	//bool bEnabled = (0 != get_plot_number(trGetN));
	int		nEnabled = ENABLE;
	bool	bIsChangeParam = trGetN.AutoUpdate.GetAttribute(STR_ENABLE_ATTRIB, nEnabled) && nEnabled == DISABLE;
	bool	bEnabled = !bIsChangeParam && (0 != get_plot_number(trGetN));
	///------ End OUTPUT_NODES_SHOULD_BE_DISABLED_IN_CAHNGE_PARAM
	
	/// Max 3/7/08 SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION
	//rd_set_optional(nEventID, bOKEnable, lpcszNodeName, trGetN.rd, bEnabled, _L("SurvFunc1"));
	/// Max 4/8/08 move to event_utils.h
	//string strLabel = "[<input>]<new>";
	string strLabel = STR_DEFAULT_TEXT_FOR_REPORT_DATA_NODE;
	//------
	okutil_convert_localized_PDS(&strLabel); 
	///Kyle 03/02/2009 SHOULD_NOT_CHANGE_OUTPUT_ON_GUI_ON_CHANGE_PARAMETERS
	//tr_set_optional(nEventID, lpcszNodeName, trGetN.rd, bEnabled, strLabel);
	if(!bIsChangeParam)
		tr_set_optional(nEventID, lpcszNodeName, trGetN.rd, bEnabled, strLabel);
	///End SHOULD_NOT_CHANGE_OUTPUT_ON_GUI_ON_CHANGE_PARAMETERS
	/// END SHOULD_PASS_WHOLE_STRING_OF_LPCSZRDLABEL_FOR_LOCALIZATION
	*/
	tr_set_optional_ex(nEventID, lpcszNodeName, trGetN.rd, xf_event_is_change_param(trGetN), 0 != get_plot_number(trGetN));
	///------ End KAPLAN_MEIER_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	
	int nErr = km_check_input(trGetN);
	///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
	if (nErr == CER_NO_ERROR && is_same_sheet(trGetN.rd, trGetN.rt))
		nErr = XFERR_REPORT_SHEET_CONFLICT;
	///End REPORT_SHEET_CHECK_CONFLICT
	
	/// YuI 08/19/09 QA70-14173 BRANCHED_RANGES_MAY_BE_INPROPERLY_INITIALIZED_IF_EMPTY_STRING
	// should not set censor list until we know that input data is good
	if( nErr != CER_NOT_SA_DATA && trRange && trCensor )
		set_censor_list(trRange, trCensor);
	/// end BRANCHED_RANGES_MAY_BE_INPROPERLY_INITIALIZED_IF_EMPTY_STRING
	
	if (CER_NO_ERROR != nErr)
	{
		strErrMsg = nErr;
		if (nErr == CER_COL_NUM_NOT_ONE_EX)
			strErrMsg += ":" + _L("for Grouping Range");
		bOKEnable = false;
	}
	
	return true;
	

}

int kaplanmeier_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	
	return false;	
	
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void kaplanmeier_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	//------ fisher 11/16/07 ADD_MAP_ID_TO_CHM
	if(is_use_origin_chm())
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_kaplanmeier);
	
	/// Max 3/19/08 SHOULD_NOT_RESET_VARIABLE_VALUE_IN_LT
	// It is the responsibility of users to specify each variable value (<auto> ones are exception) when run from LT
	/*
	///handle case that user select plot but not specify rd, when run from command
	if (nGetNDialog <= 0)
	{
		/// Max 3/7/08 LOCALIZE_PREDEFINED_STRING
		//if (!lstrcmp(trGetN.rd.strVal, "<optional>") && get_plot_number(trGetN))
		//{
			//trGetN.rd.strVal = "[<input>]<new name:=SurvFunc1>";
		//}
		if (compare_string_localization(trGetN.rd.strVal, STR_OPTIONAL) && get_plot_number(trGetN))
		{
			string strRDvalue = "[<input>]<new>";
			okutil_convert_localized_PDS(&strRDvalue);
			trGetN.rd.strVal = strRDvalue;
		}
		/// END LOCALIZE_PREDEFINED_STRING
	}
	*/
	/// END SHOULD_NOT_RESET_VARIABLE_VALUE_IN_LT
	
	///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
	//if ( (dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0 )
	if (nGetNDialog <= 0 )
	{
		//if ( CER_NO_ERROR != km_check_input(trGetN) )
		int nErr = km_check_input(trGetN);
		if(CER_NO_ERROR == nErr && is_same_sheet(trGetN.rd, trGetN.rt))
			nErr = XFERR_REPORT_SHEET_CONFLICT;
		if(CER_NO_ERROR != nErr)
		{
			if((dwCntrl&LTXF_THEME_USED))
				nRet = XFEVT_PROCEED_WITH_DLG;
			else
			{
				warning_msg_box(nErr, false, 'E');
				nRet = XFEVT_ABORT;
			}
		}
	}
	///End REPORT_SHEET_CHECK_CONFLICT
	
	///Kyle 03/02/2009 SHOULD_NOT_CHANGE_OUTPUT_ON_GUI_ON_CHANGE_PARAMETERS
	if( nGetNDialog == 0 && (dwCntrl & LTXF_EXECUTE) && 0 == get_plot_number(trGetN) )
		trGetN.rd.strVal = STR_OPTIONAL;
	///End SHOULD_NOT_CHANGE_OUTPUT_ON_GUI_ON_CHANGE_PARAMETERS	
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int kaplanmeier_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
