/*------------------------------------------------------------------------------*
 * File Name: FFWFunctionOrganizer.cpp											*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Jasmine 06/21/10 ORG-343 QUICK_CHECK_FUNCTION_BODY							*
 *	Jasmine 06/22/10 ORG-2-S2 WANT_DESTINATION_PATH								*
 *	Jasmine 06/23/10 ORG-2-S4 FUNCTION_WIZARD_ALLOW_USER_DEFINED_FUNC_CHANGE_FORM*
 *	Jasmine 06/23/10 ORG-2-P4 AUTO_INIT_VALUE_MAYBE_STRING_OR_NUMBER			*
 *	Folger 06/24/10 ORG-390-S1 USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED			*
 *	Folger 06/24/10 ORG-390-S2 BETTER_SPACE_TO_SEPARATE_PARAMETERS				*
 *	Folger 06/24/10 ORG-390-P4 SHOW_CONSTANTS_IN_EVALUATION_PAGE				*
 *	Folger 06/24/10 ORG-390-P3 FDF_FILE_NAME_SHOULD_UPDATE_AFTER_FUNCTION_NAME_CHANGED
 *	Folger 06/25/10 ORG-390-P2 SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF*
 *	Folger 07/05/10 ORG-478-S1 ERROR_CHECKING_FOR_EXPRESSION_MULTIPLE_DEPENDENTS*
 *  Jacky 07/19/10 ORG-591-P2 INIT_CONSTANTS_VALUES_WHEN_CREATE_USER_DEF_FUNCTION
 *  Jacky 07/20/10 ORG-591-P2 CHOOSE_EDIT_USERDEFINED_ALSO_INIT_CONSTANTS_VALUES
 *	Folger 08/16/10 ORG-762-P4 DERIVED_PARAMS_FAILED_TO_BE_LOADED_FROM_FUNCTION_EDITING
 *	Jasmine 08/17/10 ORG-745-P5 SHARE_FO_NAME_CHECKING_CODE						*
 *	Jasmine 08/17/10 ORG-745-P7 ONLY_CONVERT_DERIVED_PARAM_ONCE					*
 *	Folger 08/31/2010 ORG-958-P1 CONSTANTS_VALUE_FAILED_TO_IDENTIFY_COMMA_IN_G	*
 *	Folger 09/02/2010 ORG-958-P4 FFW_RUNTIME_ERROR_WHEN_SWITCH_FROM_FO_WITH_MULTIPLE_PARAMETERS
 *	Folger 09/06/2010 ORG-958-P5 FAIED_TO_SAVE_FDF_NAME_NEW_FUNCION_IN_FFW_OPEN_FROM_FO
 *------------------------------------------------------------------------------*/

#include "FFWFunctionOrganizer.h"

#define		VALUE_DELIMITER							";"

///------ Folger 09/06/2010 ORG-958-P5 FAIED_TO_SAVE_FDF_NAME_NEW_FUNCION_IN_FFW_OPEN_FROM_FO
FFWFunctionOrganizer::FFWFunctionOrganizer(NumFunctionOrganizer* pNFO/* = NULL*/)
{
	m_pNFO = pNFO;
	if ( NULL == m_pNFO )
	{
		m_pNFO = new NumFunctionOrganizer;
		m_bOwner = TRUE;
	}
	else
	{
		m_bOwner = FALSE;
	}
}
FFWFunctionOrganizer::~FFWFunctionOrganizer()
{
	if ( m_bOwner )
		NICE_SAFE_REMOVAL(m_pNFO);
}
///------ End FAIED_TO_SAVE_FDF_NAME_NEW_FUNCION_IN_FFW_OPEN_FROM_FO

void FFWFunctionOrganizer::GetCategoryList(TreeNode & trCategory)
{
	m_pNFO->GetCategoryList(trCategory);
}

bool FFWFunctionOrganizer::NewCategory(const string & strCategoryName)
{
	Tree trTemp;

	m_pNFO->GetCategoryList(trTemp);

	return m_pNFO->NewCategory(trTemp, strCategoryName);
}


int FFWFunctionOrganizer::GetFunctionList(const string & strCategoryName, vector<string> & vsFunctions)
{
	vector<string> vsDummyFileNames;
	vector<bool> vbDummyShared;

	return m_pNFO->GetFunctionList(vsFunctions, vsDummyFileNames, vbDummyShared, strCategoryName);
}

bool FFWFunctionOrganizer::NewFunction(TreeNode & trNewFunction, string strFunctionName)
{
	/// Bill 07/06/2010 ORG-478-S3 DO_NOT_AUTO_FILL_FUNCTION_BODY
	//return m_pNFO->New(trNewFunction, strFunctionName);
	bool bSuccess = m_pNFO->New(trNewFunction, strFunctionName);
	if ( bSuccess )
	{
		string strFormula("");
		SetFormula(strFormula, trNewFunction);
	}
	return bSuccess;
	/// End DO_NOT_AUTO_FILL_FUNCTION_BODY
}

string FFWFunctionOrganizer::GetCategoryDefaultFunction(const string & strCategoryName)
{
	string strFunction;
	int nDefault;

	vector<string> vsFunctions;
	vector<string> vsDummyFileNames;
	vector<bool> vbDummyShared;

	m_pNFO->GetFunctionList(vsFunctions, vsDummyFileNames, vbDummyShared, strCategoryName, &nDefault);

	return vsFunctions[nDefault];
}

bool FFWFunctionOrganizer::IsCategoryExist(const string & strCategoryName)
{
	vector<string> vExistedCategory;

	m_pNFO->GetCategoryList(vExistedCategory);

	return (vExistedCategory.Find(strCategoryName) != -1);
}

bool FFWFunctionOrganizer::LoadFunction(const string & strCategoryName, const string & strFunctionName, TreeNode & trFunction)
{
	return m_pNFO->LoadEx(trFunction, strFunctionName, strCategoryName);
}

///Sophy 7/5/2010 ORG-432-P4 INIT_PARAMS_VALUES_WHEN_CREATE_USER_DEF_FUNCTION
bool FFWFunctionOrganizer::IsFunctionExist(const TreeNode& trFunction)
{
	string strFunctionName = GetFunctionName(trFunction);
	if ( strFunctionName.IsEmpty() )
		return false;
	
	string strCategory = FindFunctionCategory(strFunctionName);
	if ( strCategory.IsEmpty() )
		return false;
	return true;
}
///end INIT_PARAMS_VALUES_WHEN_CREATE_USER_DEF_FUNCTION

string FFWFunctionOrganizer::CreateNewFunctionName(string strAttribute, string strPrefix, string strPostfix)
{
	if ( !m_trCategoryFunction.FirstNode)
		GetCategoryList(m_trCategoryFunction);
	
	return m_pNFO->CreateNewFunctionName(m_trCategoryFunction, strAttribute, strPrefix, strPostfix);
}

bool FFWFunctionOrganizer::CheckFuncName(string& strFuncName, TreeNode trParent, bool bCorrect, string *pStrError)
{
	return m_pNFO->CheckFuncName(strFuncName, trParent, pStrError,
								NULL, false, bCorrect? 0 : FO_NAME_CHECKING_RETURN_ON_INVALID);
}
///Jasmine 06/22/10 ORG-2-S2 WANT_DESTINATION_PATH
bool FFWFunctionOrganizer::SaveFunction(TreeNode & trFunction, string* pstrErr /* = NULL */, string* pstrDestinationFile/* = NULL*/)
{
	return m_pNFO->Save(trFunction, NULL, pstrErr, pstrDestinationFile);
}
///End WANT_DESTINATION_PATH
string FFWFunctionOrganizer::FindFunctionCategory(const string & strFunctionName)
{
	/*vector<string> vExistedCategory;

	m_pNFO->GetCategoryList(vExistedCategory);
	///Sophy 6/29/2010 ORG-432-S5 CHECK_EXIST_IN_USER_DEFINED_FUNCTION_CATEGORY
	string	strUserDefFunction = m_pNFO->GetFunctionNameStr(strFunctionName, USER_FOLDER);
	///end CHECK_EXIST_IN_USER_DEFINED_FUNCTION_CATEGORY
	for (int ii = 0 ; ii < vExistedCategory.GetSize() ; ++ii)
	{
		vector<string> vFunctions;

		GetFunctionList(vExistedCategory[ii], vFunctions);

		for (int jj = 0 ; jj < vFunctions.GetSize() ; ++jj)
			if ( vFunctions[jj].CompareNoCase(strFunctionName) == 0 
					|| strUserDefFunction.CompareNoCase(vFunctions[jj]) == 0	///Sophy 6/29/2010 ORG-432-S5 CHECK_EXIST_IN_USER_DEFINED_FUNCTION_CATEGORY
				)
			{
				return vExistedCategory[ii];
			}
	}

	return "";*/
	
	if ( !m_trCategoryFunction.FirstNode)
		GetCategoryList(m_trCategoryFunction);
	
	string strCategory;
	TreeNode trFind = m_trCategoryFunction.FindNodeByAttribute(STR_LABEL_ATTRIB, strFunctionName);
	///Sophy 6/29/2010 ORG-432-S5 CHECK_EXIST_IN_USER_DEFINED_FUNCTION_CATEGORY
	if ( !trFind )
	{
		string	strUserDefFunction = m_pNFO->GetFunctionNameStr(strFunctionName, USER_FOLDER);
		trFind = m_trCategoryFunction.FindNodeByAttribute(STR_LABEL_ATTRIB, strUserDefFunction);	
	}
	///end CHECK_EXIST_IN_USER_DEFINED_FUNCTION_CATEGORY
	if(trFind)
	{
		trFind.Parent().GetAttribute(STR_LABEL_ATTRIB, strCategory);
	}
	
	return strCategory;
}

string FFWFunctionOrganizer::GetFunctionName(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetGeneralInfo(trFunction, false, STR_FUNC_NAME);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetFunctionName(const string & strName, TreeNode & trFunction)
{
	m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNC_NAME, strName);
}

string FFWFunctionOrganizer::GetDescription(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetGeneralInfo(trFunction, false, STR_FUNC_DESCRIPTION);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetDescription(const string & strDescription, TreeNode & trFunction)
{
	m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNC_DESCRIPTION, strDescription);
}

int FFWFunctionOrganizer::EquationParse(const string strEquations, char chDelimiter, vector<string> & vVariables, vector<string> & vExpressions)
{
	vector<string> vLines;
	string strVariable;
	string strExpression;
		
	strEquations.GetTokens(vLines, chDelimiter);

	for (int ii = 0 ; ii < vLines.GetSize() ; ++ii)
	{
		string & strLine = vLines[ii];
		int nEqIndex, nStart;

		strLine.TrimLeft();
		strLine.TrimRight();
		
		///------ Folger 06/24/10 ORG-390-P4 SHOW_CONSTANTS_IN_EVALUATION_PAGE
		if ( strLine.IsEmpty() )
			continue;
		///------ End SHOW_CONSTANTS_IN_EVALUATION_PAGE

		nEqIndex = strLine.Find('=', 0);

		if ( nEqIndex != -1 )
		{
			strVariable = strLine.Left(nEqIndex);
			strVariable.TrimRight();

			strExpression = strLine.Mid(nEqIndex + 1, strLine.GetLength() - nEqIndex);
			strExpression.TrimLeft();

			vVariables.Add(strVariable);
			vExpressions.Add(strExpression);
		}
	}

	return vVariables.GetSize();
}

string FFWFunctionOrganizer::GetFittingPara(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetFittingPara(trFunction, false, STR_FUNC_NAMES);

	return GetTreeNodeString(trSubNode);
}

///------ Folger 09/02/2010 ORG-958-P4 FFW_RUNTIME_ERROR_WHEN_SWITCH_FROM_FO_WITH_MULTIPLE_PARAMETERS
#define	CHECK_SET_SIZE(_vv, _nn, _small) \
		if ( _small && _vv.GetSize() < _nn || !_small && _vv.GetSize() > _nn ) \
			_vv.SetSize(_nn)
///------ End FFW_RUNTIME_ERROR_WHEN_SWITCH_FROM_FO_WITH_MULTIPLE_PARAMETERS
		

void FFWFunctionOrganizer::SetFittingPara(const string & strNames, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetFittingPara(trFunction, true, STR_FUNC_NAMES);
	if ( trSubNode )
	{
		///Sophy 7/30/2010 ORG-591-P8 PROPER_INIT_PARAMETER_VALUES
		string strOldNames = trSubNode.strVal;
		///end PROPER_INIT_PARAMETER_VALUES
		trSubNode.strVal = strNames;

		string strNumber;
		int nNumber = strNames.Count(',') + 1;
		strNumber.Format("%d", nNumber);
		
		///Sophy 7/5/2010 ORG-432-P4 INIT_PARAMS_VALUES_WHEN_CREATE_USER_DEF_FUNCTION
		if ( !IsFunctionExist(trFunction) )
		{
			vector vValues;
			vector<bool> vbFixed;
			string strValues;
			strValues = GetParaValues(trFunction);
			nlf_set_param_values_vector(strValues, vValues, 0, true);
			nlf_set_param_fixed_vector(strValues, vbFixed, 0, true);
			
			///Sophy 7/30/2010 ORG-591-P8 PROPER_INIT_PARAMETER_VALUES
			vector<string> vsMeanings;
			string strMeanings = GetParaMeanings(trFunction);
			strMeanings.GetTokens(vsMeanings, ',');
			
			vector<string> vsNames, vsOldNames;;
			strNames.GetTokens(vsNames, ',');
			strOldNames.GetTokens(vsOldNames, ',');
			
			///------ Folger 09/02/2010 ORG-958-P4 FFW_RUNTIME_ERROR_WHEN_SWITCH_FROM_FO_WITH_MULTIPLE_PARAMETERS
			//if ( vsOldNames.GetSize() < nNumber )
			//{
				//vsMeanings.SetSize(nNumber);
				//vbFixed.SetSize(nNumber);
				//vValues.SetSize(nNumber);
			//}
			CHECK_SET_SIZE(vsMeanings, nNumber, TRUE);
			CHECK_SET_SIZE(vbFixed, nNumber, TRUE);
			CHECK_SET_SIZE(vValues, nNumber, TRUE);
			///------ End FFW_RUNTIME_ERROR_WHEN_SWITCH_FROM_FO_WITH_MULTIPLE_PARAMETERS
			for ( int ii = 0; ii < nNumber; ii++ )
			{
				int nIndex = vsOldNames.Find(vsNames[ii]);
				if ( nIndex >= 0 )
				{
					vValues[ii] = vValues[nIndex] != NANUM ? vValues[nIndex] : 1;
					vbFixed[ii] = vbFixed[nIndex];
					vsMeanings[ii] = vsMeanings[nIndex];
				}
				else
				{
					vValues[ii] = 1;
					vbFixed[ii] = false;
					vsMeanings[ii] = "?";
				}
				
			}
			///------ Folger 09/02/2010 ORG-958-P4 FFW_RUNTIME_ERROR_WHEN_SWITCH_FROM_FO_WITH_MULTIPLE_PARAMETERS
			//if ( vsOldNames.GetSize() > nNumber )
			//{
				//vsMeanings.SetSize(nNumber);
				//vValues.SetSize(nNumber);
				//vbFixed.SetSize(nNumber);
			//}
			CHECK_SET_SIZE(vsMeanings, nNumber, FALSE);
			CHECK_SET_SIZE(vbFixed, nNumber, FALSE);
			CHECK_SET_SIZE(vValues, nNumber, FALSE);
			///------ End FFW_RUNTIME_ERROR_WHEN_SWITCH_FROM_FO_WITH_MULTIPLE_PARAMETERS
			///end PROPER_INIT_PARAMETER_VALUES

			SetParaValues(nlf_get_param_value_list(vValues, vbFixed), trFunction);

			SetParaMeanings(nlf_get_param_meaning_list(vsMeanings), trFunction);
		}
		///end INIT_PARAMS_VALUES_WHEN_CREATE_USER_DEF_FUNCTION
		
		m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNC_NUM_PARAMS, strNumber);
	}
}

///------ Folger 06/24/10 ORG-390-S1 USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
#define		INIT_VALUE_OVER_NANUM			1
///------ End USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED

///Jasmine 06/21/10 ORG-343 QUICK_CHECK_FUNCTION_BODY
string FFWFunctionOrganizer::GetFittingParamWithValue(TreeNode & trFunction, char chDelimiter)
{
	string strTemp = GetFittingPara(trFunction);
	vector<string> vsParams;
	int nParams = strTemp.GetTokens(vsParams, chDelimiter);
	
	TreeNode trSubNode = m_pNFO->GetFittingPara(trFunction, false, STR_FDF_SETTING_INIT_VAL);
	strTemp = GetTreeNodeString(trSubNode);
	vector vParamValues;
	///------ Folger 06/24/10 ORG-390-S1 USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
	//nlf_set_param_values_vector(strTemp, vParamValues, nParams);
	nlf_set_param_values_vector(strTemp, vParamValues, nParams, false, INIT_VALUE_OVER_NANUM);
	///------ End USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED

	///------ Folger 06/25/10 ORG-390-P2 SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF
	SubstituteValuesWithQuickCheck(vParamValues, vsParams, trFunction);
	///------ End SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF

	strTemp = _combine_name_value_str(vsParams, vParamValues);
	return strTemp;
}

int _parse_name_value_str(vector& vIndepValue, LPCSTR lpcszNames, LPCSTR lpcszNameVals, char chDelimiter)
{
	string strNameDelimiter(chDelimiter);
	vector<string> vsParams;
	int nParams = str_separate(lpcszNames, strNameDelimiter, vsParams);
	
	vector<string> vsNames, vsValues;
	int nCount = str_separate(lpcszNameVals, VALUE_DELIMITER, vsValues);
	vsNames.SetSize(nCount);
	for(int ii = 0; ii < nCount; ii++)
	{
		string strTemp = vsValues[ii];
		strTemp = strTemp.GetToken(0,'='); strTemp.TrimRight(); strTemp.TrimLeft();
		vsNames[ii] = strTemp;
		
		strTemp = vsValues[ii];
		strTemp = strTemp.GetToken(1,'='); strTemp.TrimRight(); strTemp.TrimLeft();
		vsValues[ii] = strTemp;
	}
	
	vIndepValue.SetSize(nParams);
	for(ii = 0; ii < nParams; ii++)
	{
		string strTemp = vsParams[ii]; strTemp.TrimRight(); strTemp.TrimLeft();
		int nFind = vsNames.Find(strTemp, 0, true);
		vIndepValue[ii] = (nFind > -1 && nFind < nCount)? atof( vsValues[nFind] ) : NANUM;
	}
	
	return nParams;
}

int FFWFunctionOrganizer::ParseFittingParamValue(vector& vParamValue, const TreeNode& trFunction, LPCSTR lpcszParamVal, char chDelimiter)
{
	string strTemp = GetFittingPara(trFunction);
	return _parse_name_value_str(vParamValue, strTemp, lpcszParamVal, chDelimiter);
}
///End QUICK_CHECK_FUNCTION_BODY
int FFWFunctionOrganizer::GetConstants(TreeNode & trFunction, vector<string> & vsVariables, vector<string> & vsValues)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetConstants(trFunction, false, STR_FUNC_SCRIPT);

	if ( trSubNode )
		///------ Folger 06/24/10 ORG-390-P4 SHOW_CONSTANTS_IN_EVALUATION_PAGE
		//return EquationParse(trSubNode.strVal, ';', vsVariables, vsValues);
		///------ Folger 08/31/2010 ORG-958-P1 CONSTANTS_VALUE_FAILED_TO_IDENTIFY_COMMA_IN_G
		//return ParseScriptItems(trSubNode.strVal, vsVariables, vsValues);
		{
			int		nReturn = ParseScriptItems(trSubNode.strVal, vsVariables, vsValues);
			vector	vv;
			/// This is a tricky solution, we cannot save decimal point as comma into FDF since comma is one of the constant eqaution separators(, ; \n).
			/// So dot is always saved for constants as decimal point, when for display, need to convert all the values according to number format.
			convert_str_vector_to_num_vector(vsValues, vv);
			convert_double_vector_to_string_vector(vv, vsValues, vv.GetSize());
			return nReturn;
		}
		///------ End CONSTANTS_VALUE_FAILED_TO_IDENTIFY_COMMA_IN_G
		///------ End SHOW_CONSTANTS_IN_EVALUATION_PAGE
	else
		return 0;
}

void FFWFunctionOrganizer::SetConstants(vector<string> & vsVariables, vector<string> & vsValues, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetConstants(trFunction, true, STR_FUNC_SCRIPT);

	if ( trSubNode )
	{
		///------ Folger 06/25/10 ORG-390-P4 SHOW_CONSTANTS_IN_EVALUATION_PAGE
		//vector<string> vsExpression;
		//string strConstants;

		//for (int ii = 0 ; ii < vsVariables.GetSize() ; ++ii)
			//vsExpression.Add(vsVariables[ii] + "=" + vsValues[ii]);

		//strConstants = str_combine(vsExpression, "\r\n");

		//trSubNode.strVal = strConstants;
		//--- Jacky 07/19/10 ORG-591-P2 INIT_CONSTANTS_VALUES_WHEN_CREATE_USER_DEF_FUNCTION
		//--- Jacky 07/20/10 ORG-591-P2 CHOOSE_EDIT_USERDEFINED_ALSO_INIT_CONSTANTS_VALUES
	//	if ( !IsFunctionExist(trFunction) )
	//	{
	//--- end CHOOSE_EDIT_USERDEFINED_ALSO_INIT_CONSTANTS_VALUES
			int nSize = vsValues.GetSize();
			for ( int ii = 0; ii < nSize; ii++ )
			{
				///------ Folger 08/31/2010 ORG-958-P1 CONSTANTS_VALUE_FAILED_TO_IDENTIFY_COMMA_IN_G
				//if ( is_missing_value(atof(vsValues[ii])) )
					//vsValues[ii] = 1;
				double		rr = atof(vsValues[ii]);
				if ( is_missing_value(rr) )
					vsValues[ii] = 1;
				else
					/// use full precision here same as parameter values
					vsValues[ii].Format("%.15g", rr);
				///------ End CONSTANTS_VALUE_FAILED_TO_IDENTIFY_COMMA_IN_G
			}
		//}
		//--- end INIT_CONSTANTS_VALUES_WHEN_CREATE_USER_DEF_FUNCTION
		trSubNode.strVal = CombineScriptItems(vsVariables, vsValues);
		///------ End SHOW_CONSTANTS_IN_EVALUATION_PAGE

	}
}

///------ Folger 06/24/10 ORG-390-P4 SHOW_CONSTANTS_IN_EVALUATION_PAGE
string	FFWFunctionOrganizer::GetConstantsWithValues(TreeNode & trFunction)
{
	TreeNode trSubNode;
	string strConstant;
	
	vector<string> vsVariables;
	vector<string> vsValues;
	
	int nCount = GetConstants(trFunction, vsVariables, vsValues);
	vector		vValues;
	convert_str_vector_to_num_vector(vsValues, vValues);
	return _combine_name_value_str(vsVariables, vValues);
}
///------ End SHOW_CONSTANTS_IN_EVALUATION_PAGE

string FFWFunctionOrganizer::GetFormula(TreeNode & trFunction)
{
	TreeNode trSubNode =	m_pNFO->GetFormula(trFunction, false, STR_FUNC_SCRIPT);

	return GetTreeNodeString(trSubNode);
}

bool FFWFunctionOrganizer::SetFormula(const string &  strFormula, TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetFormula(trFunction, true, STR_FUNC_SCRIPT);

	if ( trSubNode )
	{
		trSubNode.strVal = strFormula;
		return true;
	}
	else
	{
		return error_report("SetFormula: No tree node \n");
	}
}

string FFWFunctionOrganizer::GetIndependVars(TreeNode & trFunction, char chDelimiter)
{
	return m_pNFO->GetSubNodeNameList(trFunction, STR_FUNC_INDEPENDENT_VARS, chDelimiter);
}

void FFWFunctionOrganizer::SetIndependVars(vector<string> & vsIndependVars, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetNodeCheckAdd(trFunction, STR_FUNC_INDEPENDENT_VARS, true);
	if ( trSubNode )
	{
		trSubNode.Reset(true);
		for (int ii = 0 ; ii < vsIndependVars.GetSize() ; ++ii)
			trSubNode.AddTextNode("", vsIndependVars[ii]);

		string strNumber;
		strNumber.Format("%d", vsIndependVars.GetSize());
		m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNC_NUM_IND_VARS, strNumber);
	}
}
///Jasmine 06/21/10 ORG-343 QUICK_CHECK_FUNCTION_BODY
string _combine_name_value_str(const vector<string>& vsNames, const vector& vValue)
{
	int nParams = vsNames.GetSize();
	int nSize = vValue.GetSize();
	
	string strTemp;
	for(int ii = 0; ii < nParams; ii++)
	{
		///------ Folger 06/24/10 ORG-390-S1 USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
		//double dd = ii < nSize? vValue[ii] : NANUM;
		double dd = ii < nSize? vValue[ii] : INIT_VALUE_OVER_NANUM;
		///------ End USE_ONE_IF_NO_PARAM_INIT_VALUE_SPECIFIED
		///------ Folger 06/24/10 ORG-390-S2 BETTER_SPACE_TO_SEPARATE_PARAMETERS
		//strTemp += vsNames[ii] + "=" + ftoa(dd) + VALUE_DELIMITER + " ";
		string	str;
		str.Format("%s = %s %s ", vsNames[ii], ftoa(dd), VALUE_DELIMITER);
		strTemp += str;
		///------ End BETTER_SPACE_TO_SEPARATE_PARAMETERS
	}
	
	strTemp.TrimRight();
	strTemp.TrimRight(VALUE_DELIMITER);
	return strTemp;
}

string FFWFunctionOrganizer::GetIndependVarsWithValue(TreeNode & trFunction, char chDelimiter)
{
	string strTemp = GetIndependVars(trFunction, chDelimiter);
	vector<string> vsParams;
	int nParams = strTemp.GetTokens(vsParams, chDelimiter);
	
	vector vEmpty;
	///------ Folger 06/25/10 ORG-390-P2 SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF
	SubstituteValuesWithQuickCheck(vEmpty, vsParams, trFunction);
	///------ End SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF
	strTemp = _combine_name_value_str(vsParams, vEmpty);
	return strTemp;
}

int FFWFunctionOrganizer::ParseIndependVarsValue(vector& vIndepValue, const TreeNode& trFunction, LPCSTR lpcszIndepVal, char chDelimiter)
{
	string strTemp = GetIndependVars(trFunction, chDelimiter);
	return _parse_name_value_str(vIndepValue, strTemp, lpcszIndepVal, chDelimiter);
}
///End QUICK_CHECK_FUNCTION_BODY
string FFWFunctionOrganizer::GetDependVars(TreeNode & trFunction, char chDelimiter)
{
	return m_pNFO->GetSubNodeNameList(trFunction, STR_FUNC_DEPENDENT_VARS, chDelimiter);
}

void FFWFunctionOrganizer::SetDependVars(vector<string> & vsDependVars, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetNodeCheckAdd(trFunction, STR_FUNC_DEPENDENT_VARS, true);
	if ( trSubNode )
	{
		trSubNode.Reset(true);
		for (int ii = 0 ; ii < vsDependVars.GetSize() ; ++ii)
			trSubNode.AddTextNode("", vsDependVars[ii]);

		string strNumber;
		strNumber.Format("%d", vsDependVars.GetSize());
		m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNC_NUM_DEP_VARS, strNumber);
	}
	
}
///Jasmine 06/21/10 ORG-343 QUICK_CHECK_FUNCTION_BODY
string FFWFunctionOrganizer::CombineDependVarsWithValue(const vector& vDepValue, const TreeNode& trFunction, char chDelimiter)
{
	string strTemp = GetDependVars(trFunction, chDelimiter);
	vector<string> vsParams;
	int nParams = strTemp.GetTokens(vsParams, chDelimiter);
	
	strTemp = _combine_name_value_str(vsParams, vDepValue);
	return strTemp;
}
///End QUICK_CHECK_FUNCTION_BODY
string FFWFunctionOrganizer::GetType(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetGeneralInfo(trFunction, false, STR_FUNC_TYPE);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetType(const string & strType, TreeNode & trFunction)
{
	m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNC_TYPE, strType);
}

string FFWFunctionOrganizer::GetForm(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetGeneralInfo(trFunction, false, STR_FUNC_FORM);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetForm(const string & strForm, TreeNode & trFunction)
{
	m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNC_FORM, strForm);
}

string FFWFunctionOrganizer::GetSource(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetGeneralInfo(trFunction, false, STR_FUNCTION_SOURCE);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetSource(const string & strSource, TreeNode & trFunction)
{
	m_pNFO->SetGeneralInfo(trFunction, true, STR_FUNCTION_SOURCE, strSource);
}

void FFWFunctionOrganizer::UpdateCompileState(TreeNode& trFunction)
{
	m_pNFO->UpdateCompileByFunctionForm(trFunction);
}

string FFWFunctionOrganizer::GetInitialCode(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetParaInit(trFunction);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetInitialCode(const string & strCode, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetParaInit(trFunction, true);
	if ( trSubNode )
		trSubNode.strVal = strCode;
}

bool FFWFunctionOrganizer::IsDerivative(TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetGeneralInfo(trFunction, false, STR_FUNC_ANALYTICAL_DERIVATIVES);
	if ( trSubNode )
		return ( !trSubNode.strVal.CompareNoCase("on") || !trSubNode.strVal.CompareNoCase("1") );
	else
		return false;
}

void FFWFunctionOrganizer::SetDerivative(bool bDerivative, TreeNode & trFunction)
{
	TreeNode trSubNode;
	string str = bDerivative ? "1" : "0";

	trSubNode = m_pNFO->GetGeneralInfo(trFunction, true, STR_FUNC_ANALYTICAL_DERIVATIVES);
	if ( trSubNode )
	{
		trSubNode.strVal = str;
		trSubNode.SetAttribute(STR_ID_ATTRIB, IDS_OPTION_USERDEF_ANALYT_DERIV);
	}
}

bool FFWFunctionOrganizer::IsAutoInitial(TreeNode & trFunction)
{
	///Jasmine 06/23/10 ORG-2-P4 AUTO_INIT_VALUE_MAYBE_STRING_OR_NUMBER
	/*
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetControls(trFunction, false, STR_FUNC_ENABLE_PARAMETERS_INIT);

	if ( trSubNode )
		return trSubNode.nVal;
	else
		return false;
	*/	
	bool bAutoInit = false;
	nlf_is_auto_init_params(trFunction, bAutoInit);
	return bAutoInit;
	///End AUTO_INIT_VALUE_MAYBE_STRING_OR_NUMBER
}

void FFWFunctionOrganizer::SetAutoInitial(bool bAutoInitial, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetControls(trFunction, true, STR_FUNC_ENABLE_PARAMETERS_INIT);

	if ( trSubNode )
		trSubNode.nVal = bAutoInitial;
}

bool FFWFunctionOrganizer::IsUseOC(TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetCompile(trFunction, false, STR_FUNC_PARAM_INIT_COMPILE);

	if ( trSubNode )
		return trSubNode.nVal;
	else
		return false;
}

void FFWFunctionOrganizer::SetUseOC(bool bUseOC, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetCompile(trFunction, true, STR_FUNC_PARAM_INIT_COMPILE);

	if ( trSubNode )
		trSubNode.nVal = bUseOC;
}
///Jasmine 08/17/10 ORG-745-P7 COPY_DERIVED_PARAM_SETTINGS_FROM_EQUATION_FOR_OLD_FDF
bool FFWFunctionOrganizer::CvtDerivedParameterNames(const TreeNode& trFunction)
{
	///Jasmine 08/17/10 ORG-745-P7 ONLY_CONVERT_DERIVED_PARAM_ONCE
	string strAttribute = "Converted";
	int bConvert;
	if( trFunction.GetAttribute(strAttribute, bConvert) )
		return false;
	
	trFunction.SetAttribute(strAttribute, true);
	//End ONLY_CONVERT_DERIVED_PARAM_ONCE
	
	string strTemp = GetDerivedParameterNames(trFunction);
	
	if( strTemp.IsEmpty() )
	{
		string strEquation = GetDerivedParameterEquation(trFunction);
		///------ Folger 08/16/10 ORG-762-P4 DERIVED_PARAMS_FAILED_TO_BE_LOADED_FROM_FUNCTION_EDITING
		//check_convert_CR_str_to_CRLF(strEquation);
		///------ End DERIVED_PARAMS_FAILED_TO_BE_LOADED_FROM_FUNCTION_EDITING
		
		vector<string> vsName, vsDummyValues;
		///------ Folger 08/16/10 ORG-762-P4 DERIVED_PARAMS_FAILED_TO_BE_LOADED_FROM_FUNCTION_EDITING
		//EquationParse(strEquation, '\r\n', vsName, vsDummyValues);
		int nRet = EquationParse(strEquation, '\n', vsName, vsDummyValues);
		///------ End DERIVED_PARAMS_FAILED_TO_BE_LOADED_FROM_FUNCTION_EDITING

		if(nRet > 0)
		{
			SetDerivedParameterSetting(trFunction, vsName);
			return true;
		}
	}

	return false;
}
///End COPY_DERIVED_PARAM_SETTINGS_FROM_EQUATION_FOR_OLD_FDF
///Jasmine 08/17/10 ORG-745-P7 DERIVED_PARAM_SETTINGS_ARE_INDEPENDENT_WITH_EQUATION
string FFWFunctionOrganizer::GetDerivedParameterNames(const TreeNode& trFunction)
{
	string strTemp;
	
	TreeNode trSubNode = m_pNFO->GetDeriParaSettings(trFunction, false, STR_FUNC_NAMES);
	if ( trSubNode )
		strTemp = trSubNode.strVal;
	
	strTemp.TrimLeft();
	strTemp.TrimRight();

	return strTemp;
}
///End DERIVED_PARAM_SETTINGS_ARE_INDEPENDENT_WITH_EQUATION

///Jasmine 08/18/10 ORG-820-S1 NOT_ALLOW_FINISH_UNTIL_DERIVED_PARAM_CHECK_OK
bool FFWFunctionOrganizer::HasDerivedParameters(const TreeNode& trFunction)
{
	string strDerivedParams = GetDerivedParameterNames(trFunction);	
	string strEquation = GetDerivedParameterEquation(trFunction);
	
	return !strDerivedParams.IsEmpty() || !strEquation.IsEmpty();
}
///End NOT_ALLOW_FINISH_UNTIL_DERIVED_PARAM_CHECK_OK

string FFWFunctionOrganizer::GetDerivedParameterEquation(TreeNode & trFunction)
{
	TreeNode trSubNode;
	string str;

	trSubNode = m_pNFO->GetDerivedParams(trFunction,  false);
	if ( trSubNode )
	{
		if ( !octree_branch_to_key_value_pairs_str(&trSubNode, &str) )
			return "";
		else
			return str;
	}
	else
		return "";
}

void FFWFunctionOrganizer::SetDerivedParameterEquation(const string & strEquation, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetDerivedParams(trFunction, true);
	if ( trSubNode )
	{
		tree_key_value_pairs_str_to_branch(trSubNode, strEquation);
	}
}

int FFWFunctionOrganizer::GetDerivedParameterSetting(TreeNode & trFunction, vector<string> & vsNames/* = NULL*/, vector<string> & vsMeanings/* = NULL*/, vector<string> & vsUnit/* = NULL*/)
{
	TreeNode trSubNode;
	int nCounts = 0;
	string strTemp;

	trSubNode = m_pNFO->GetDeriParaSettings(trFunction, false, STR_FUNC_NAMES);
	if (vsNames)
	{
		vsNames.SetSize(0);
		if(trSubNode)
		{
			strTemp = trSubNode.strVal;
			nCounts = strTemp.GetTokens(vsNames, ',');
		}
	}

	trSubNode = m_pNFO->GetDeriParaSettings(trFunction, false, STR_PARAM_SETTING_MEANINGS);
	if (vsMeanings)
	{
		vsMeanings.SetSize(0);
		if(trSubNode)
		{
			strTemp = trSubNode.strVal;
			strTemp.GetTokens(vsMeanings, ',');
		}
	}

	trSubNode = m_pNFO->GetDeriParaSettings(trFunction, false, STR_PARAM_UNIT);
	if (vsUnit)
	{
		vsUnit.SetSize(0);
		if(trSubNode)
		{
			strTemp = trSubNode.strVal;
			strTemp.GetTokens(vsUnit, ',');
		}
	}

	return nCounts;
}

void FFWFunctionOrganizer::SetDerivedParameterSetting(TreeNode & trFunction, vector<string> & vsNames/* = NULL*/, vector<string> & vsMeanings/* = NULL*/, vector<string> & vsUnit/* = NULL*/)
{
	TreeNode trSubNode;
	int nCounts = 0;
	string strTemp;

	trSubNode = m_pNFO->GetDeriParaSettings(trFunction, true, STR_FUNC_NAMES);
	if (vsNames && trSubNode)
	{
		strTemp.SetTokens(vsNames, ',');
		trSubNode.strVal = strTemp;
	}

	trSubNode = m_pNFO->GetDeriParaSettings(trFunction, true, STR_PARAM_SETTING_MEANINGS);
	if (vsMeanings && trSubNode)
	{
		strTemp.SetTokens(vsMeanings, ',');
		trSubNode.strVal = strTemp;
	}

	trSubNode = m_pNFO->GetDeriParaSettings(trFunction, true, STR_PARAM_UNIT);
	if (vsUnit && trSubNode)
	{
		strTemp.SetTokens(vsUnit, ',');
		trSubNode.strVal = strTemp;
	}
}

string FFWFunctionOrganizer::GetConstraints(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetConstraints(trFunction, false, STR_FUNC_SCRIPT);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetConstraints(const string & strConstraints, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetConstraints(trFunction, true, STR_FUNC_SCRIPT);
	if ( trSubNode )
		trSubNode.strVal = strConstraints;
}

bool FFWFunctionOrganizer::IsEnableConstraint(TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetControls(trFunction, false, STR_FUNC_GENERAL_CONSTRAINTS);
	if ( trSubNode )
		return trSubNode.nVal;
	else
		return false;

}

void FFWFunctionOrganizer::EnableConstraint(bool bEnableConstraint, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetControls(trFunction, true, STR_FUNC_GENERAL_CONSTRAINTS);
	if ( trSubNode )
		trSubNode.nVal = bEnableConstraint;
}

string FFWFunctionOrganizer::GetBeforeFittingScript(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetScripts(trFunction, STR_INIT_SCRIPT, false);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetBeforeFittingScript(const string & strScript, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetScripts(trFunction, STR_INIT_SCRIPT, true);

	trSubNode.strVal = strScript;
}

string FFWFunctionOrganizer::GetAfterFittingScript(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetScripts(trFunction, STR_SCRIPT_AFTER_FITTING, false);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetAfterFittingScript(const string & strScript, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetScripts(trFunction, STR_SCRIPT_AFTER_FITTING, true);

	trSubNode.strVal = strScript;
}

bool FFWFunctionOrganizer::IsPeak(TreeNode & trFunction)
{
	return nlf_get_duplicate_offset(trFunction) > 1;
}

void FFWFunctionOrganizer::SetPeak(bool bPeek, TreeNode & trFunction)
{
	set_duplicate_unit_for_peak_fit(trFunction, !bPeek);
}

bool FFWFunctionOrganizer::CheckCopyPeakAttributeNodes(bool bPeakFunction, const TreeNode& trSource, TreeNode& trTarget)
{
	return m_pNFO->CheckCopyPeakAttributeNodes(bPeakFunction, trSource, trTarget);
}

TreeNode FFWFunctionOrganizer::GetControls(const TreeNode& trFunction, bool bAddWhenNoExist, string strSubNode)
{
	return m_pNFO->GetControls(trFunction, bAddWhenNoExist, strSubNode);
}

string FFWFunctionOrganizer::GetParaUnits(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetFittingPara(trFunction, false, STR_FDF_SETTING_UNIT);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetParaUnits(const string & strUnits, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetFittingPara(trFunction, true, STR_FDF_SETTING_UNIT);
	if ( trSubNode )
		trSubNode.strVal = strUnits;
}

string FFWFunctionOrganizer::GetParaMeanings(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetFittingPara(trFunction, true, STR_FDF_SETTING_MEANINGS);

	return GetTreeNodeString(trSubNode);	
}

void FFWFunctionOrganizer::SetParaMeanings(const string & strMeanings, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetFittingPara(trFunction, true, STR_FDF_SETTING_MEANINGS);
	if ( trSubNode )
		trSubNode.strVal = strMeanings;
}

string FFWFunctionOrganizer::GetParaValues(TreeNode & trFunction)
{
	TreeNode trSubNode = m_pNFO->GetFittingPara(trFunction, true, STR_FDF_SETTING_INIT_VAL);

	return GetTreeNodeString(trSubNode);
}

void FFWFunctionOrganizer::SetParaValues(const string & strValues, TreeNode & trFunction)
{
	TreeNode trSubNode;

	trSubNode = m_pNFO->GetFittingPara(trFunction, true, STR_FDF_SETTING_INIT_VAL);
	if ( trSubNode )
		trSubNode.strVal = strValues;
}

string FFWFunctionOrganizer::GetTreeNodeString(TreeNode & trNode)
{
	if ( trNode )
		return trNode.strVal;
	else
		return "";
}

///Jasmine 06/23/10 ORG-2-S4 FUNCTION_WIZARD_ALLOW_USER_DEFINED_FUNC_CHANGE_FORM
bool FFWFunctionOrganizer::IsSysFunc(const TreeNode& trFunction)
{
	return m_pNFO->IsSysFunc(trFunction);
}

bool FFWFunctionOrganizer::IsSharedFunc(const TreeNode& trFunction)
{
	bool bSharedFunction;
	m_pNFO->IsCurrentUserShared(trFunction, bSharedFunction);
	return bSharedFunction;
}
///End FUNCTION_WIZARD_ALLOW_USER_DEFINED_FUNC_CHANGE_FORM

///------ Folger 06/25/10 ORG-390-P2 SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF
#define STR_FUNC_QUICKCHECK				_LE("QuickCheck")
int		FFWFunctionOrganizer::GetQuickCheckItems(vector<string>& vsNames, vector<string>& vsValues, TreeNode& trFunction)
{
	vsNames.RemoveAll();
	vsValues.RemoveAll();

	TreeNode	trQuickCheck = m_pNFO->GetNodeCheckAdd(trFunction, STR_FUNC_QUICKCHECK, false, STR_FUNC_SCRIPT);
	if ( !trQuickCheck )
		return 0;

	return ParseScriptItems(trQuickCheck.strVal, vsNames, vsValues);
}
int		FFWFunctionOrganizer::SetQuickCheckItems(TreeNode& trFunction, const vector<string>& vsNames, const vector<string>& vsValues)
{
	TreeNode	trQuickCheck = m_pNFO->GetNodeCheckAdd(trFunction, STR_FUNC_QUICKCHECK, true, STR_FUNC_SCRIPT);
	if ( !trQuickCheck )
	{
		ASSERT(FALSE);
		return -1;
	}

	trQuickCheck.strVal = CombineScriptItems(vsNames, vsValues);
	return 0;
}

BOOL	FFWFunctionOrganizer::ClearQuickCheck(TreeNode& trFunction)
{
	TreeNode	trQuickCheck = m_pNFO->GetNodeCheckAdd(trFunction, STR_FUNC_QUICKCHECK, false);
	return trQuickCheck && trQuickCheck.Remove();
}

int		FFWFunctionOrganizer::SetQuickCheck(TreeNode& trFunction, LPCSTR lpcsz)
{
	vector<string>	vsNames;
	vector<string>	vsValues;
	GetQuickCheckItems(vsNames, vsValues, trFunction);
	
	vector<string>	vsNamesEx;
	vector<string>	vsValuesEx;
	LPCSTR			lpcszDelimiter = VALUE_DELIMITER;
	EquationParse(lpcsz, *lpcszDelimiter, vsNamesEx, vsValuesEx);

	for ( int ii=0; ii<vsNamesEx.GetSize(); ii++ )
	{
		int			nIndex = -1;
		if ( (nIndex = vsNames.Find(vsNamesEx[ii])) >= 0 )
		{
			vsValues[nIndex] = vsValuesEx[ii];
		}
		else
		{
			vsNames.Add(vsNamesEx[ii]);
			vsValues.Add(vsValuesEx[ii]);
		}
	}

	return SetQuickCheckItems(trFunction, vsNames, vsValues);
}
///------ End SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF

///------ Folger 06/24/10 ORG-390-P3 FDF_FILE_NAME_SHOULD_UPDATE_AFTER_FUNCTION_NAME_CHANGED
///Jasmine 08/17/10 ORG-745-P5 SHARE_FO_NAME_CHECKING_CODE
bool 	FFWFunctionOrganizer::CheckUpdateFuncName(	string& strName, TreeNode &trFunction, 
												string *pStrError/*=NULL*/, string* pstrFile/* = NULL*/,
												bool bUpdate/* = true*/)//only check name if false
{
	string strCategoryNodePrefix = STR_NODE_CATEGORY;
	string strCategoryNode = tree_get_enum_node_name(m_trCategoryFunction, strCategoryNodePrefix);
	TreeNode trParentTemp =  m_trCategoryFunction.AddNode(strCategoryNode);
	
	TreeNode trFuncTemp = trParentTemp.AddNode(STR_NODE_FUNCTION);
	trFuncTemp.Replace(trFunction, TRUE, TRUE, FALSE);
	
	TreeNode trNameTemp = trFuncTemp.AddTextNode(strName, cvt_str_to_tag_name(STR_FUNC_NAME));
	
	string strFile;
	trFuncTemp.GetAttribute(STR_FILENAME_ATTRIB, strFile);
	TreeNode trFileTemp = trFuncTemp.AddTextNode(strFile, cvt_str_to_tag_name(STR_FUNC_FILE_NAME));
	trFileTemp.SetAttribute(STR_DATAID_ATTRIB, FUNC_TREE_FILE_NAME_ID);
	
	bool		bRet = m_pNFO->UpdateFuncName(trNameTemp, trFuncTemp, pStrError, pstrFile);
	if(bUpdate && bRet)
	{
		trNameTemp.Remove();
		trFileTemp.Remove();
		
		trFunction.Replace(trFuncTemp, TRUE, TRUE, FALSE);
	}
	
	trParentTemp.Remove();
	
	return bRet;
}
///End SHARE_FO_NAME_CHECKING_CODE
///------ End FDF_FILE_NAME_SHOULD_UPDATE_AFTER_FUNCTION_NAME_CHANGED

///------ Folger 06/24/10 ORG-390-P4 SHOW_CONSTANTS_IN_EVALUATION_PAGE
int		FFWFunctionOrganizer::ParseScriptItems(string str, vector<string> & vVariables, vector<string> & vExpressions)
{
	str.Replace(';', '\n');
	str.Replace(',', '\n');
	return EquationParse(str, '\n', vVariables, vExpressions);
}

string	FFWFunctionOrganizer::CombineScriptItems(const vector<string> & vVariables, const vector<string> & vExpressions)
{
	vector<string>	vs;
	
	for (int ii = 0 ; ii < vVariables.GetSize() ; ++ii)
		vs.Add(vVariables[ii] + "=" + vExpressions[ii]);
	
	return str_combine(vs, "\r\n");
}
///------ End SHOW_CONSTANTS_IN_EVALUATION_PAGE

///------ Folger 06/25/10 ORG-390-P2 SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF
int		FFWFunctionOrganizer::SubstituteValuesWithQuickCheck(vector& vValues, const vector<string>& vsNames, TreeNode& trFunction)
{
	vector<string>	vsNamesEx;
	vector<string>	vsValuesEx;

	GetQuickCheckItems(vsNamesEx, vsValuesEx, trFunction);

	int		nCount = 0;
	for ( int ii=vsNamesEx.GetSize()-1; ii>=0; --ii )
	{
		int			nIndex = -1;
		if ( (nIndex = vsNames.Find(vsNamesEx[ii])) >= 0 )
		{
			vValues.SetAtGrow(nIndex, atof(vsValuesEx[ii]));
			++nCount;
		}
	}

	return nCount;
}
///------ End SAVE_USER_CHANGED_IN_FIT_FUNCTION_WIZARD_INTO_FDF

///------ Folger 07/05/10 ORG-478-S1 ERROR_CHECKING_FOR_EXPRESSION_MULTIPLE_DEPENDENTS
BOOL	FFWFunctionOrganizer::IsAllowMultipleDeps(TreeNode& trFunction)
{
	string	strType = GetType(trFunction);
	if ( strType.Compare(STR_FUNCTION_TYPE_USER_DEFINE) != 0 )
		return TRUE;

	string	strForm = GetForm(trFunction);
	return strForm.Compare(STR_FUNCTION_FORM_EXPRESSION) != 0;
}
///------ End ERROR_CHECKING_FOR_EXPRESSION_MULTIPLE_DEPENDENTS
