/**
 *
 * @author    seagle
 * @date      2025-3-21
 * @Description 
 *   Replace old OP
 */  
#include"TcPch.h"
#pragma hdrstop
#include"OP.h"
#include"errcode.h"
#include"EV.h"
#include"BoatModule.h"
#include"debug.h"
COP* OP;
//在alarmCheck之外的地方发生了alarm，是否使用alarmCallback回调
#define USE_NORMAL_ALARMCHECK FALSE
/**
* Do not use this function twice in one sentence!!!!!!
*/
static char* describeOperatorStatus(OperatorStatus status) {
	static char buffer[10];
	switch (status.value) {
	case OperatorStatusEnum::UNDEFINED:
		strcpy (buffer, "Undefined");
		break;
	case OperatorStatusEnum::INIT:
		strcpy (buffer, "Init");
		break;
	case OperatorStatusEnum::SUCCESS:
		strcpy (buffer, "Success");
		break;
	case OperatorStatusEnum::RUNNING:
		strcpy (buffer, "Running");
		break;
	case OperatorStatusEnum::ALARM:
		strcpy (buffer, "Alarm");
		break;
	default:
		sprintf(buffer, "%d", (int)status.value);
	}
	return buffer;
}
OperatorNode::OperatorNode()
{
	memset(&params, '\0', sizeof(params));
}

void OperatorNode::reset()
{
	
	elapsedDelayTime = elapsedStableTime = elapsedTriggerAlarmTime =elapsedTriggerWarningTime= elapsedTimeout=0;
	isInDelay = FALSE;
	isTimeout = FALSE;
	status = OperatorStatusEnum::INIT;
	subOpIndex = 0;
	confirm = 0;
	method = 0;
	paramsCount = 0;
	if (resetFunction != NULL) {
		resetFunction();
	}
	for (int i = 0; i < subOpCount;i++) {
		subOpList[i]->reset();		
	}
}

OperatorNode* OperatorNode::setTimes(long delayTime, long stableTime, long triggerAlarmTime, long timeout)
{
	if (delayTime >= 0) {
		this->setDelayTime = delayTime;
	}
	if (stableTime >= 0) {
		this->setStableTime = stableTime;
	}
	if (triggerAlarmTime >= 0) {
		this->setTriggerAlarmTime = triggerAlarmTime;
	}
	if (timeout >= 0) {
		this->setTimeout = timeout;
	}
	
	return this;
}
OperatorNode* OperatorNode::setParams(const char* paramString){
	if (paramString != NULL) {
		this->params.parse(paramString, ';');
	}
	
	return this;
}


void OperatorNode::subscribe(const char* name)
{
	strcpy (this->name , name);
}

void OperatorNode::subscribe(const char* name, OperatorFunctionPtr execFunction)
{
	strcpy (this->name , name);
	this->execFunction = execFunction;
}

void OperatorNode::subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction)
{
	strcpy (this->name , name);
	this->execFunction = execFunction;
	this->preCheckFunction = preCheckFunction;
}

void OperatorNode::subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction)
{
	strcpy (this->name , name);
	this->execFunction = execFunction;
	this->preCheckFunction = preCheckFunction;
	this->checkFunction = checkFunction;
}

void OperatorNode::subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction, OperatorCheckFunctionPtr alarmCheckFunction)
{
	strcpy (this->name , name);
	this->execFunction = execFunction;
	this->preCheckFunction = preCheckFunction;
	this->checkFunction = checkFunction;
	this->alarmCheckFunction = alarmCheckFunction;
}

void OperatorNode::subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction, OperatorCheckFunctionPtr alarmCheckFunction, OperatorCallbackFunctionPtr alarmCallbackFunction)
{
	strcpy (this->name , name);
	this->execFunction = execFunction;
	this->preCheckFunction = preCheckFunction;
	this->checkFunction = checkFunction;
	this->alarmCheckFunction = alarmCheckFunction;
	this->alarmCallbackFunction = alarmCallbackFunction;
}

void OperatorNode::addExec(OperatorFunctionPtr function)
{
	this->execFunction = function;	
	
	
}

void OperatorNode::addPreCheck(OperatorCheckFunctionPtr function)
{
	this->preCheckFunction = function;
	for (int i = 0; i < subOpCount; i++) {
		subOpList[i] = NULL;
	}
	subOpCount = 0;
}

void OperatorNode::addCheck(OperatorCheckFunctionPtr function)
{
	this->checkFunction = function;
	for (int i = 0; i < subOpCount; i++) {
		subOpList[i] = NULL;
	}
	subOpCount = 0;
}

void OperatorNode::addAlarmCheck(OperatorCheckFunctionPtr function)
{
	this->alarmCheckFunction = function;
	for (int i = 0; i < subOpCount; i++) {
		subOpList[i] = NULL;
	}
	subOpCount = 0;
}

void OperatorNode::addAlarmCallback(OperatorCallbackFunctionPtr function)
{
	this->alarmCallbackFunction = function;
}

void OperatorNode::addReset(OperatorCallbackFunctionPtr function)
{
	this->resetFunction = function;
}

OperatorNode* OperatorNode::addChild()
{
	//execFunction = NULL;
	preCheckFunction = checkFunction = alarmCallbackFunction = NULL;
	//alarmCallbackFunction = NULL;
	OperatorNode* node = &OP->subOpArray[OP->subOpLength++];
	*node = OperatorNode();//调用构造函数
	subOpList[subOpCount++] = node;
	return node;
}
OperatorNode* OperatorNode::addChild(const char* name) {
	auto node = addChild();
	strcpy(node->name, name);
	return node;
}


void OperatorNode::doSimpleOperation()
{
	if (OP->isAborted) {
		return;
	}
	OP->current = this;
	if (OP->currentRoot == NULL) {
		return;
	}
	if (status != OperatorStatusEnum::INIT) {
		char* err = EV->parseErrCode(ALARM_OP_STATUS, "name=%s;expect=Init;real=%s", name, describeOperatorStatus(status));
		strcpy (OP->alarmText ,err);
		status = OperatorStatusEnum::ALARM;
		//EV->postAlarmLog(alarmText); called by alarm deal method
		return;
	}
	logger->info("Do simple operation:[%s]", name);
	elapsedDelayTime = elapsedStableTime =elapsedTriggerAlarmTime=elapsedTriggerWarningTime=elapsedTimeout =0;
	isInDelay = FALSE;
	if (preCheckFunction != NULL) {
		OperatorStatusEnum preCheckStatus = preCheckFunction();
		if (preCheckStatus != OperatorStatusEnum::SUCCESS) {
			status = OperatorStatusEnum::ALARM;
			char *err= EV->parseErrCode(ALARM_OP_PRECHECK, "name=%s" , name );
			strcpy (OP->alarmText, err);
			//EV->postAlarmLog(alarmText);called by alarm deal method
			if (alarmCallbackFunction != NULL && USE_NORMAL_ALARMCHECK) {
				status=alarmCallbackFunction();
				if (status != OperatorStatusEnum::INIT && status != OperatorStatusEnum::SUCCESS&& status != OperatorStatusEnum::RUNNING) {
					return;
				}
			}
			else {
				OP->alarm();
				return;
			}
			
		}
	}
	if (execFunction == NULL) {
		status = OperatorStatusEnum::ALARM;
		char *err = EV->parseErrCode(ALARM_OP_NOT_EXIST, "name=%s" , name);
		strcpy (OP->alarmText, err);
		//EV->postAlarmLog(alarmText);called by alarm deal method
		if (alarmCallbackFunction != NULL && USE_NORMAL_ALARMCHECK) {
			status = alarmCallbackFunction();
			if (status != OperatorStatusEnum::INIT && status != OperatorStatusEnum::SUCCESS && status != OperatorStatusEnum::RUNNING) {
				return;
			}
		}
		else {
			OP->alarm();
			return;
		}
		
	}
	OperatorStatusEnum execStatus = execFunction();
	if (execStatus == OperatorStatusEnum::ALARM) {
		status = OperatorStatusEnum::ALARM;
		//alamText set in exec function
		//alarmText = EV->parseErrCode(ALARM_OP_NOT_EXIST, "name=" + name);
		//EV->postAlarmLog(alarmText);called by alarm deal method
		if (alarmCallbackFunction != NULL && USE_NORMAL_ALARMCHECK) {
			status = alarmCallbackFunction();
			if (status != OperatorStatusEnum::INIT && status != OperatorStatusEnum::SUCCESS && status != OperatorStatusEnum::RUNNING) {
				return;
			}
			else {
				if (execStatus == OperatorStatusEnum::SUCCESS || execStatus == OperatorStatusEnum::INIT) {
					//actual there can not be SUCCESS,only be INIT
					status = OperatorStatusEnum::INIT;
				}
			}
		}
		else {
			OP->alarm();
			return;
		}
		 
	}
	else if (execStatus == OperatorStatusEnum::SUCCESS||execStatus== OperatorStatusEnum::INIT) {
		//actual there can not be SUCCESS,only be INIT
		status = OperatorStatusEnum::INIT;
		return;
	}
	else if (execStatus == OperatorStatusEnum::RUNNING) {
		status = OperatorStatusEnum::RUNNING;
		isInDelay = TRUE;
	}
}

void OperatorNode::simpleMonitor()
{
	elapsedTimeout += TASK_TM;
	if (setTimeout > 0 && elapsedTimeout >= setTimeout) {
		isTimeout = TRUE;
	}
	
	if (OP->isAborted) {
		return;
	}
	OP->current = this;
	if (status != OperatorStatusEnum::SUCCESS && status != OperatorStatusEnum::RUNNING) {
		return;
	}
	if (isInDelay && setDelayTime == 0) {
		isInDelay = FALSE;
	}
	else if (isInDelay && setDelayTime > 0) {
		elapsedDelayTime += TASK_TM;
		if (elapsedDelayTime >= setDelayTime) {
			isInDelay = FALSE;
		}
		else {
			return;	//in delay time
		}
	}
	
	//from here, delay is over
	if (alarmCheckFunction != NULL) {
		OperatorStatusEnum alarmStatus = alarmCheckFunction();
		if (alarmStatus == OperatorStatusEnum::ALARM) {
			elapsedTriggerAlarmTime += TASK_TM;
			elapsedTriggerWarningTime += TASK_TM;
			if (elapsedTriggerAlarmTime > setTriggerAlarmTime) {
				elapsedTriggerAlarmTime = setTriggerAlarmTime;
				elapsedTriggerWarningTime = setTriggerAlarmTime;
				status = OperatorStatusEnum::ALARM;
				if (alarmCallbackFunction != NULL) {
					status = alarmCallbackFunction();
					if (status != OperatorStatusEnum::INIT && status != OperatorStatusEnum::SUCCESS && status != OperatorStatusEnum::RUNNING) {
						return;
					}
				}
				else {
					OP->alarm();
					return;
				}
			}
			else if (elapsedTriggerWarningTime > setTriggerAlarmTime) {
				elapsedTriggerWarningTime = setTriggerAlarmTime;
				if (alarmCallbackFunction != NULL) {
					alarmCallbackFunction();					
				}
				else {
					OP->warning();					
				}
			}
			
		}
		else if (alarmStatus == OperatorStatusEnum::WARNING) {
			elapsedTriggerAlarmTime = 0;
			elapsedTriggerWarningTime += TASK_TM;
			if (elapsedTriggerWarningTime > setTriggerAlarmTime) {
				if (alarmCallbackFunction != NULL) {
					alarmCallbackFunction();
				}
				else {
					OP->warning();
				}
			}
		}else{
			//alarm not trigger
			elapsedTriggerAlarmTime = 0;
			elapsedTriggerWarningTime = 0;
		}
	}
	if (checkFunction != NULL) {
		OperatorStatusEnum checkStatus =checkFunction();
		if (checkStatus == OperatorStatusEnum::RUNNING) {
			elapsedStableTime = 0;
			status = OperatorStatusEnum::RUNNING;
			return;
		}
		else if (checkStatus == OperatorStatusEnum::SUCCESS) {
			if (setStableTime == 0) {
				status = OperatorStatusEnum::SUCCESS;
				return;
			}
			else {
				elapsedStableTime += TASK_TM;
				if (elapsedStableTime > setStableTime) {
					elapsedStableTime = setStableTime;
					status = OperatorStatusEnum::SUCCESS;
					return;
				}
				else {
					status = OperatorStatusEnum::RUNNING;
				}
			}
		}
		else if (checkStatus == OperatorStatusEnum::ALARM) {
			status = OperatorStatusEnum::ALARM;
			if (alarmCallbackFunction != NULL && USE_NORMAL_ALARMCHECK) {
				status = alarmCallbackFunction();
				if (status != OperatorStatusEnum::INIT && status != OperatorStatusEnum::SUCCESS && status != OperatorStatusEnum::RUNNING) {
					return;
				}
			}
			else {
				OP->alarm();
				return;
			}
		}

	}

}

void OperatorNode::doOperation()
{
	if (OP->isAborted) {
		return;
	}
	if (subOpCount == 0 && execFunction != NULL) {
		//simple operate
		doSimpleOperation();
		return;
	}
	if (subOpCount == 0) {
		return;	//should not be here
	}
	if (status != OperatorStatusEnum::INIT) {
		char *err = EV->parseErrCode(ALARM_OP_STATUS, "name=%s;expect=Init;real=" ,name, describeOperatorStatus(status));
		strcpy (OP->alarmText, err);
		status = OperatorStatusEnum::ALARM;
		if (alarmCallbackFunction != NULL && USE_NORMAL_ALARMCHECK) {
			status = alarmCallbackFunction();
			if (status != OperatorStatusEnum::INIT && status != OperatorStatusEnum::SUCCESS && status != OperatorStatusEnum::RUNNING) {
				return;
			}
		}
		else {
			OP->alarm();
			return;
		}
	}
	if (execFunction != NULL) {
		//忽略exec的返回值，即组合动作的exec委托只允许处理简单的计算和数据准备，不能出错
		execFunction();
		
	}
	
	if (OP->isAborted) {
		return;
	}
	for (int index = 0; index < subOpCount;index++) {
		if (OP->isAborted) {
			return;
		}
		if (index == subOpIndex) {
			OperatorNode* subOp = subOpList[index];
			OperatorStatusEnum subExecStatus;
			subOp->doOperation();
			subExecStatus = subOp->status;
			
			if (subExecStatus == OperatorStatusEnum::ALARM) {
				status = OperatorStatusEnum::ALARM;
				subOp->status = OperatorStatusEnum::ALARM;
				break;
			}
			else if (subExecStatus == OperatorStatusEnum::INIT) {
				//continue;
			}
			else {
				status = OperatorStatusEnum::RUNNING;
				subOp->status = OperatorStatusEnum::RUNNING;
				break;
			}

			subOpIndex++;
		}
		
	}

}

void OperatorNode::Do()
{
	if (OP->isAborted) {
		return;
	}
	OP->currentRoot = this;
	doOperation();
}

void OperatorNode::monitor()
{
	if (OP->isAborted) {
		return;
	}
	if (subOpCount== 0 && execFunction != NULL) {
		//simple operate
		simpleMonitor();
		return;
	}
	if (subOpCount == 0) {
		return;	//should not be here
	}
	if (status != OperatorStatusEnum::RUNNING) {
		return;
	}
	
	for (int index = 0; index < subOpCount;index++) {
		if (index == subOpIndex) {
			OperatorNode* subOp = subOpList[index];
			OperatorStatusEnum subTestStatus;
			if (subOp->status == OperatorStatusEnum::INIT) {
				subOp->doOperation();
			}
			else {
				subOp->monitor();
			}
			if (OP->isAborted) {
				return;
			}
			subTestStatus = subOp->status;
			if (subTestStatus == OperatorStatusEnum::ALARM) {
				status = OperatorStatusEnum::ALARM;
				break;
			}
			else if (subTestStatus == OperatorStatusEnum::INIT) {

			}
			else if (subTestStatus == OperatorStatusEnum::SUCCESS) {
				if (subOpIndex == subOpCount - 1) {
					//last is success
					status = OperatorStatusEnum::SUCCESS;
					break;
				}
				else {
					status = OperatorStatusEnum::RUNNING;
					
				}
			}
			else {
				//sub op is running
				status = OperatorStatusEnum::RUNNING;
				break;
			}
			subOpIndex++;
		}
		
	}
}

void OperatorNode::retryAlarm()
{
	if (OP->isAborted) {
		return;
	}
	if (status != OperatorStatusEnum::ALARM) {
		return;
	}
	if (subOpCount == 0) {
		//简单动作
		this->reset();
		doSimpleOperation();
		return;
	}
	//复杂动作
	status = OperatorStatusEnum::INIT;
	for (int index = 0; index < subOpCount; index++) {
		if (OP->isAborted) {
			return;
		}
		if (index == subOpIndex) {
			OperatorNode* subOp = subOpList[index];
			OperatorStatusEnum subExecStatus;
			subOp->retryAlarm();
			subExecStatus = subOp->status;
			
			if (subExecStatus == OperatorStatusEnum::ALARM) {
				status = OperatorStatusEnum::ALARM;
				subOp->status = OperatorStatusEnum::ALARM;
				break;
			}
			else if (subExecStatus == OperatorStatusEnum::INIT) {
				//continue;
			}
			else {
				status = OperatorStatusEnum::RUNNING;
				subOp->status = OperatorStatusEnum::RUNNING;
				break;
			}

			subOpIndex++;
		}

	}
}
void OperatorNode::resetAlarm()
{
	if (OP->isAborted) {
		return;
	}
	if (status != OperatorStatusEnum::ALARM) {
		return;
	}
	this->reset();
	this->Do();
	
}
/*
* 
* 只有第一个被卡住的简单结点忽略错误，往后的要照常执行
*/
void OperatorNode::ignoreAlarm(PMCBOOL *first)
{
	if (OP->isAborted) {
		return;
	}
	if (status != OperatorStatusEnum::ALARM && *first) {
		return;
	}
	if (subOpCount == 0) {
		//简单动作
		this->reset();
		if (*first) {
			*first = FALSE;
			logger->info("Ignore ..%s", name);
		}
		else {
			doSimpleOperation();
		}
		
		return;
	}
	//复杂动作
	status = OperatorStatusEnum::INIT;
	BOOL findMatchedOp = FALSE;
	for (int index = 0; index < subOpCount; index++) {
		if (OP->isAborted) {
			return;
		}
		if (index == subOpIndex) {
			OperatorNode* subOp = subOpList[index];
			OperatorStatusEnum subExecStatus;
			subOp->ignoreAlarm(first);
			subExecStatus = subOp->status;

			if (subExecStatus == OperatorStatusEnum::ALARM) {
				status = OperatorStatusEnum::ALARM;
				subOp->status = OperatorStatusEnum::ALARM;
				break;
			}
			else if (subExecStatus == OperatorStatusEnum::INIT) {
				//continue;
			}
			else {
				status = OperatorStatusEnum::RUNNING;
				subOp->status = OperatorStatusEnum::RUNNING;
				break;
			}

			subOpIndex++;
		}

	}
}




OperatorNode* COP::subscribe(const char* name)
{
	static OperatorNode operatorNode;
	strcpy (operatorNode.name, name);
	opTree.set(name, operatorNode,__FILE__,__LINE__);
	OperatorNode* node = opTree.get(name);
	
	return node;
}

OperatorNode* COP::subscribe(const char* name, OperatorFunctionPtr execFunction)
{
	OperatorNode* node = subscribe(name);
	node->addExec(execFunction);
	return node;
}

OperatorNode* COP::subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction)
{
	OperatorNode* node = subscribe(name);
	node->addExec(execFunction);
	node->addPreCheck(preCheckFunction);
	return node;
}

OperatorNode* COP::subscribe(const char * name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction)
{
	OperatorNode* node = subscribe(name);
	node->addExec(execFunction);
	node->addPreCheck(preCheckFunction);
	node->addCheck(checkFunction);
	return node;
}

OperatorNode* COP::subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction, OperatorCheckFunctionPtr alarmCheckFunction)
{

	OperatorNode* node = subscribe(name);
	node->addExec(execFunction);
	node->addPreCheck(preCheckFunction);
	node->addCheck(checkFunction);
	node->addAlarmCheck(alarmCheckFunction);
	return node;
}

OperatorNode* COP::subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction, OperatorCheckFunctionPtr alarmCheckFunction, OperatorCallbackFunctionPtr alarmCallbackFunction)
{
	OperatorNode* node = subscribe(name);
	node->addExec(execFunction);
	node->addPreCheck(preCheckFunction);
	node->addCheck(checkFunction);
	node->addAlarmCheck(alarmCheckFunction);
	node->addAlarmCallback(alarmCallbackFunction);
	return node;
}

OperatorNode* COP::select(const char* name)
{
	
	OperatorNode* node = opTree.get(name);
	if (node == NULL) {
		node = opTree.get("default");
		if (node == NULL) {
			char* err = EV->parseErrCode(ALARM_OP_NOT_EXIST, "name=%s;", name);
			strcpy(alarmText, err);
			EV->postAlarmLog(alarmText);
			return NULL;
		}
		node->setParams(name);
	}
	return node;
}


OperatorStatus& COP::monitor() {
	static OperatorStatus returnStatus = OperatorStatusEnum::ALARM;
	return returnStatus = monitor_a();

}
OperatorStatusEnum COP::monitor_a()
{
	if (isAborted) {
		return OperatorStatusEnum::ABORT;
	}
	OperatorStatusEnum result = OperatorStatusEnum::SUCCESS;
	
	for (int index = 0; index < opTree.length;index++) {
		if (isAborted) {
			return OperatorStatusEnum::ABORT;
		}
		OperatorNode* op = opTree.getByIndex(index);
		if (op->status == OperatorStatusEnum::INIT) {
			continue;
		}
		OP->currentRoot = op;
		if (op->status == OperatorStatusEnum::SUCCESS || op->status == OperatorStatusEnum::RUNNING) {
			op->monitor();
			if (OP->isAborted) {
				return OperatorStatusEnum::ABORT;
			}
		}
		if (op->status == OperatorStatusEnum::INIT || op->status == OperatorStatusEnum::SUCCESS) {
			continue;
		}
		else if (op->status == OperatorStatusEnum::ALARM) {
			result = OperatorStatusEnum::ALARM;
			//abort停止所有动作，但alarm只停止当前动作，其他动作正常进行
			//break;
		}
		else {
			if (result == OperatorStatusEnum::SUCCESS) {
				result = OperatorStatusEnum::RUNNING;
			}
			
		}
	}
	return result;

}






void COP::abort()
{
	OP->isAborted = TRUE;

}

void COP::alarm()
{
	
	EV->postAlarmLog(OP->alarmText);
}
void COP::warning()
{

	EV->postWarningLog(OP->alarmText);
}

void COP::retryAlarm(const char *opName)
{
	OperatorNode* op = NULL;
	if (opName != NULL) {
		op= OP->opTree.get(opName);
	}
	if (op == NULL) {
		op = OP->currentRoot;
	}
	if (op == NULL) {
		return;
	}
	op->retryAlarm();
}
void COP::ignoreAlarm(const char* opName)
{
	OperatorNode* op = NULL;
	if (opName != NULL) {
		op = OP->opTree.get(opName);
	}
	if (op == NULL) {
		for (int id = 0; id < OP->opTree.length; id++) {
			auto errNode = OP->opTree.getByIndex(id);
			if (errNode->status == OperatorStatusEnum::ALARM) {
				op = errNode;
				break;
			}
		}
	}
	if (op == NULL) {
		return;
	}
	PMCBOOL first = TRUE;
	logger->info("Ignore %s", op->name);
	op->ignoreAlarm(&first);
}
void COP::resetAlarm(const char* opName)
{
	OperatorNode* op = NULL;
	if (opName != NULL) {
		op = OP->opTree.get(opName);
	}
	if (op == NULL) {
		for (int id = 0; id < OP->opTree.length; id++) {
			auto errNode = OP->opTree.getByIndex(id);
			if (errNode->status == OperatorStatusEnum::ALARM) {
				op = errNode;
				break;
			}
		}
	}
	if (op == NULL) {
		return;
	}
	
	logger->info("Reset %s", op->name);
	op->resetAlarm();
}

void COP::reset()
{
	
	for (int index = 0; index < opTree.length;index++) {
		opTree.getByIndex(index)->reset();
	}
	current = currentRoot = NULL;
	isAborted = FALSE;
	
}

