#include "cprocess_scan.h"
#include "logic.h"
CProcess_Scan::CProcess_Scan(const QString& name, int32_t id)
	:CMProcess(name, id)
{
	m_Variants.add_Variant(Var_Cass_Slot_Step,
		QObject::trUtf8("Slot_Step"), double(0), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_CheckBox_EnableCheck,
		QObject::trUtf8("Enable_Check_Wafer"), false, false,
		Variant::TOXML);

	m_Variants.add_Variant(Var_Rail_Scan_Pos_ID,
		QObject::trUtf8("ScanRailPos"), double(0), false,
		Variant::TOXML);

	m_Variants.add_Variant(Var_Cass_FirstClawPos_ID,
		QObject::trUtf8("FirstClawPos"), double(4), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_Cass_FirstScanPos_ID,
		QObject::trUtf8("FirstScanPos"), double(-27.5), false,
		Variant::TOXML);
	//检查料盒取料位
	m_Variants.add_Variant(Var_ClawPos_CheckBox_ID,
		QObject::trUtf8("CheckClawPos"), double(19.6), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_Cass_UnloadOffset_ID,
		QObject::trUtf8("UnloadOffset"), double(2), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_Cass_CassUpPos_ID,
		QObject::trUtf8("CassUpPos"), double(-62), false,
		Variant::TOXML);

	//扫片点位
	m_Variants.add_Variant(Var_Cass_ScanPosStart,
		QObject::trUtf8("ScanStart"), double(17), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_Cass_ScanPosEnd,
		QObject::trUtf8("ScanEnd"), double(174.5), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_Cass_ScanSensorOffset,
		QObject::trUtf8("ScanSensorOffset"), double(-0.2), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_Cass_WaferThickness,
		QObject::trUtf8("WaferThickness"), double(2), false,
		Variant::TOXML);

	m_Variants.add_Variant(Var_Process_WaferCheckType,
		QObject::trUtf8("WaferCheckType"), uint(0), false,
		Variant::TOXML, QStringList() << "Not Use" << "1'St" << "Every");

	m_Variants.add_Variant(Var_Process_UserTwoSensor,
		QObject::trUtf8("UseTwoSensor"), true, false,
		Variant::TOXML);
	//扫片速度
	m_Variants.add_Variant(Var_Process_ScanSpeed,
		QObject::trUtf8("ScanSpeed"), double(40), false,
		Variant::TOXML);
	//叠片判定最小阈值，通过厚度进行判定
	m_Variants.add_Variant(Var_Process_WPOverrlapped_ThickLimit1,
		QObject::trUtf8("OverrlappedLimitLeft"), double(3), false,
		Variant::TOXML);
	m_Variants.add_Variant(Var_Process_WPOverrlapped_ThickLimit2,
		QObject::trUtf8("OverrlappedLimitRight"), double(3.4), false,
		Variant::TOXML);
	//错位判定最小阈值，两个传感器的差值
	m_Variants.add_Variant(Var_Process_WPMalposed_ThickLimit,
		QObject::trUtf8("MalposedLimit"), double(0.5), false,
		Variant::TOXML);

	m_Variants.add_Variant(Var_Process_DelayCompensation,
		QObject::trUtf8("DelayCompensation"), double(-0.4), false,
		Variant::TOXML);

	m_Variants.add_Variant(Var_Process_WaferExistsRange,
		QObject::trUtf8("WaferExistsRange"), double(1), false,
		Variant::TOXML);
}

void CProcess_Scan::do_msg(int iID, QVariantList& vlInput, V_MsgOutput* pvlOutput)
{
	UNUSED(pvlOutput);

	int32_t isize = vlInput.size();
	switch (iID)
	{
	case CASSSCAN:
		if (isize >= 2)
		{
			CassScan(vlInput[0].toInt(), vlInput[1].toInt());
		}
		break;
	case CASSUP:
		if (isize >= 1)
		{
			CassUp(vlInput[0].toInt());
		}
		break;
	case MOVESLOTSCANPOS:
		if (isize >= 2)
		{
			MoveSlotScanPos(vlInput[0].toInt(), vlInput[1].toInt());
		}
		break;
	case MOVESLOTLOADPOS:
		if (isize >= 3)
		{
			MoveSlotLoadPos(vlInput[0].toInt(), vlInput[1].toInt(), vlInput[2].toBool());
		}
		break;
	case MOVESLOTUNLOADPOS:
		if (isize >= 2)
		{
			MoveSlotUnLoadPos(vlInput[0].toInt(), vlInput[1].toInt(), vlInput[2].toBool());
		}
		break;
	default:
		break;
	}
	CMProcess::do_msg(iID, vlInput, pvlOutput);
}

bool CProcess_Scan::CassScan(int32_t cassid, int iStep)
{
	if (m_gSystem.IsSimulator())
	{
		return SimulatorScan(cassid, iStep);
	}

	//料盒是否存在
	if (!CCassExist(cassid))
	{
		MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("No Cassette"));
	}

	//料盒运动前安全检查
	ScanMoveCheck();

	CCassette* pCass = GET_CHDIRECT(cassid, CCassette);
	Q_ASSERT(pCass);
	int iSlotCountMax = pCass->m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
	if (iStep == 0)
	{
		FUNC_START("");
		g_SecsManager.SendEvent(EVENT_MappingStarted);
		//如果是第一片，重置所有
		pCass->ResetSlots();

#ifdef __LOWK_SOLUTION__
		//轨道移动到扫描位置
		CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
		double dPos = m_Variants.get_VData(Var_Rail_Scan_Pos_ID)->toDouble();
		pMotorDriver->absmove(MOTORB1_LOCK, dPos);
#endif
	}
	else if (iStep >= 1 && iStep <= iSlotCountMax)
	{
		m_gSystem.m_bScanTwoSensor = m_Variants.get_VData(Var_Process_UserTwoSensor)->toBool();
		//步进扫片
		//1~25
		//扫描完后，这里用于处理首片检测
		if (false == m_gSystem.m_bScanTwoSensor)
			ScanStep(cassid, iStep - 1);
		return true;
	}
	else if (iStep == iSlotCountMax + 1)
	{
		if (m_gSystem.m_bScanTwoSensor)
			ScanTwoSensor(cassid);
		return true;
	}
	else if (iStep == iSlotCountMax + 2)
	{
		AfterScan(cassid);
		return true;
	}
	else if (iStep == iSlotCountMax + 3)
	{
		FUNC_END("");
		g_SecsManager.SendEvent(EVENT_MappingComplete);
	}

	return true;
}

void CProcess_Scan::CassUp(int32_t cassid)
{
	UNUSED(cassid);
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pDriver);
	pDriver->absmove(MOTORC_CASS, m_Variants.get_VData(Var_Cass_CassUpPos_ID)->toDouble());

}

//移动到扫描准备位
int CProcess_Scan::MoveCassScanReady()
{
	double firstScanPos = m_Variants.get_VData(Var_Cass_FirstScanPos_ID)->toDouble();
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);

	Q_ASSERT(pDriver);
	pDriver->absmove(MOTORC_CASS, firstScanPos, true);

	return RTN_SUCCESS1;
}


void CProcess_Scan::RecordToFile(const QList<double>& list, QString fileName)
{
	QString strPath = CMakePath::make_data_path(fileName);
	QFile file(strPath);
	if (!file.open(QIODevice::WriteOnly))
	{
		MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
			.arg(strPath));
	}
	QTextStream stream(&file);
	for (int i = 0; i < list.size(); i++)
	{
		stream << list[i] << endl;
	}
}


void CProcess_Scan::RecordToFile(const QList<int>& list, QString fileName)
{
	QString strPath = CMakePath::make_data_path(fileName);
	QFile file(strPath);
	if (!file.open(QIODevice::WriteOnly))
	{
		MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
			.arg(strPath));
	}
	QTextStream stream(&file);
	for (int i = 0; i < list.size(); i++)
	{
		stream << list[i] << endl;
	}
}

void CProcess_Scan::ScanStep(int cassid, int iStep)
{
	MoveSlotScanPos(cassid, iStep);
	CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pMotorDriver);
	CCassette* pCass = GET_CHDIRECT(cassid, CCassette);
	Q_ASSERT(pCass);
	bool bExist = pMotorDriver->get_iodata(IO_INPUT, IN_SCAN_LEFT, true);
	if (bExist)
	{
		pCass->vslots[iStep].WPstatus = WPUNCUT;
	}
	else
	{
		pCass->vslots[iStep].WPstatus = NOWP;
	}
}

void CProcess_Scan::ScanTwoSensor(int cassid)
{
	CCassette* pCass = GET_CHDIRECT(cassid, CCassette);
	Q_ASSERT(pCass);
	int iSlotCountMax = pCass->m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
	double firstScanPos = m_Variants.get_VData(Var_Cass_FirstScanPos_ID)->toDouble();
	double dSlotStep = m_Variants.get_VData(Var_Cass_Slot_Step)->toDouble();

	double dScanPosBottom = m_Variants.get_VData(Var_Cass_ScanPosStart)->toDouble();
	double dScanPosTop = m_Variants.get_VData(Var_Cass_ScanPosEnd)->toDouble();
	double dSensorOffset = m_Variants.get_VData(Var_Cass_ScanSensorOffset)->toDouble();
	double dWaferThickness = m_Variants.get_VData(Var_Cass_WaferThickness)->toDouble();
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pDriver);

	QList<double> scanExistList1;
	QList<double> scanExistList2;
	QList<double> scanEmptyList1;
	QList<double> scanEmptyList2;


	std::vector<int> firstWaferSlotStatus;//!第一次扫描结果
	std::vector<int> secondWaferSlotStatus;//!第二次扫描结果
	firstWaferSlotStatus.assign(iSlotCountMax, NOWP);
	secondWaferSlotStatus.assign(iSlotCountMax, NOWP);
	//moveIndex = 0 从上往下移动，moveIndex = 1 从下往上移动
	int moveIndex = 0;
	//for(int moveIndex = 0;  moveIndex < 1; moveIndex++) {
	scanExistList1.clear();
	scanExistList2.clear();
	scanEmptyList1.clear();
	scanEmptyList2.clear();

	if (m_gSystem.IsSimulator())
	{
		FileToRecord(scanEmptyList1, QString("D:/scandata/%1scanEmptyList1.txt").arg(moveIndex));
		FileToRecord(scanExistList1, QString("D:/scandata/%1scanExistList1.txt").arg(moveIndex));
		FileToRecord(scanEmptyList2, QString("D:/scandata/%1scanEmptyList2.txt").arg(moveIndex));
		FileToRecord(scanExistList2, QString("D:/scandata/%1scanExistList2.txt").arg(moveIndex));
	}
	else
	{
		if (moveIndex == 0)
		{
			GetSensorData(scanExistList1, scanExistList2, scanEmptyList1, scanEmptyList2, pDriver, dScanPosBottom, dScanPosTop);
		}
		else if (moveIndex == 1)
		{
			GetSensorData(scanExistList1, scanExistList2, scanEmptyList1, scanEmptyList2, pDriver, dScanPosTop, dScanPosBottom);
		}

		RecordToFile(scanEmptyList1, QString("%1scanEmptyList1.txt").arg(moveIndex));
		RecordToFile(scanExistList1, QString("%1scanExistList1.txt").arg(moveIndex));
		RecordToFile(scanEmptyList2, QString("%1scanEmptyList2.txt").arg(moveIndex));
		RecordToFile(scanExistList2, QString("%1scanExistList2.txt").arg(moveIndex));
	}

	//两个传感器扫描数据不一致
	if (scanExistList1.size() != scanExistList2.size()
		|| scanExistList2.size() != scanEmptyList2.size()
		|| scanExistList1.size() != scanEmptyList1.size())
	{
		MQT_THROW_CODESTR(ALARM_SCAN_WAFER_DATAERROR, QObject::trUtf8("Two sensor scan data inconsistency"));
	}

	QList<double> scanCenterList;
	double sensorOffset = dSensorOffset;
	double waferThickness = dWaferThickness;
	QList<int> scanResultList;
	double dOffset = m_Variants.get_VData(Var_Process_DelayCompensation)->toDouble();;
	if (moveIndex > 0)
		dOffset = 0.4;
	ComputeWaferCenter(scanExistList1, scanExistList2,
		scanEmptyList1, scanEmptyList2,
		sensorOffset, waferThickness,
		scanCenterList, scanResultList, dOffset);

	if (1 == moveIndex)
	{
		std::reverse(scanCenterList.begin(), scanCenterList.end());
		std::reverse(scanResultList.begin(), scanResultList.end());
	}
	RecordToFile(scanCenterList, QString("%1scanCenterList.txt").arg(moveIndex));
	RecordToFile(scanResultList, QString("%1scanResultList.txt").arg(moveIndex));

	//检查是否有叠片或斜片
	bool isError = false;
	QString errInfo;
	QString wpMalposed = QObject::tr("Malposed:");
	QString wpOverlapped = QObject::tr("Overlapped:");
	bool bMalposed = false;
	bool bOverlapped = false;
	for (int i = 0; i < scanResultList.size(); ++i)
	{
		if (scanResultList[i] == WPMALPOSED)
		{  //斜片
			wpMalposed += QString("%1,").arg(i + 1);
			bMalposed = true;
		}
		else if (scanResultList[i] == WPOVERLAPPED)
		{ //叠片
			wpOverlapped += QString("%1,").arg(i + 1);
			bOverlapped = true;
		}
	}
	isError = bOverlapped || bMalposed;
	if (isError)
	{
		if (!bMalposed)wpMalposed = "";
		if (!bOverlapped)wpOverlapped = "";
		errInfo = QObject::tr("Scan Err %1 %2").arg(wpMalposed).arg(wpOverlapped);
		MQT_THROW_CODESTR(ALARM_SCAN_WAFER_WPERROR, errInfo);
	}
	//计算槽是否存在晶圆

	double dWaferExistsRange = m_Variants.get_VData(Var_Process_WaferExistsRange)->toDouble();
	int curj = 0;
	for (size_t i = 0; i < firstWaferSlotStatus.size(); i++)
	{
		//! note: 向上为正 区别是firstScanPos - dSlotStep*i
		//! note: 向下为正 区别是firstScanPos + dSlotStep*i
		//! 当前轴向上为正
		double dPosLower = firstScanPos - dSlotStep * i - dWaferExistsRange;
		double dPosUpper = firstScanPos - dSlotStep * i + dWaferExistsRange;

		firstWaferSlotStatus[i] = UNSCANED;

		bool bFind = false;
		//从小到大
		for (int j = curj; j < scanCenterList.size(); j++)
		{
			double curPos = scanCenterList[j];
			if (curPos >= dPosLower && curPos < dPosUpper)
			{
				firstWaferSlotStatus[i] = scanResultList[j];
				curj = j + 1;
				bFind = true;
				break;
			}
		}

		if (!bFind)
			firstWaferSlotStatus[i] = NOWP;
	}

	//更新每一层最终的扫描数据
	QString strMismatch = "";
	bool bErr = false;
	for (size_t i = 0; i < firstWaferSlotStatus.size(); i++)
	{
		pCass->vslots[i].WPstatus = firstWaferSlotStatus[i];
	}

	pDriver->setdefaultspeed(MOTORC_CASS);
	//CassUp(CASSETTE);

	//TODO:两次扫描验证
	if (bErr)
	{
		pDriver->absmove(MOTORC_CASS, dScanPosBottom, true);
		MQT_THROW_CODESTR(ALARM_SCAN_WAFER_WPERROR, QObject::trUtf8("Twice scan mismatch at(%1), please rescan!").arg(strMismatch));
	}
	else
	{
		pDriver->absmove(MOTORC_CASS, dScanPosBottom, true);
	}

	return;
}

void CProcess_Scan::AfterScan(int cassid)
{
	CCassette* pCass = GET_CHDIRECT(cassid, CCassette);
	Q_ASSERT(pCass);
	//设置首片检测
	uint checkType = m_Variants.get_VData(Var_Process_WaferCheckType)->toUInt();
	int iSlotCountMax = pCass->m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
	bool bFirst = false;
	pCass->SetFirstCheckFinished(true);
	for (int i = 0; i < iSlotCountMax - 1; i++)
	{
		pCass->vslots[i].bNeedCheckCoat = false;
		pCass->vslots[i].bNeedCheckCut = false;
		pCass->vslots[i].CheckStatus = NONEEDCHECK;
		if (checkType == 0)
			continue;
		if (pCass->vslots[i].WPstatus == WPUNCUT && pCass->vslots[i].bEnableCut)
		{
			if (bFirst == false)
			{
				bFirst = true;
				if (checkType >= 1)
				{
					pCass->vslots[i].bNeedCheckCoat = true;
					pCass->vslots[i].bNeedCheckCut = true;
					pCass->vslots[i].CheckStatus = CHECKBEGIN;
					pCass->SetFirstCheckFinished(false);
				}
			}
			else
			{
				if (checkType == 2)
				{
					pCass->vslots[i].bNeedCheckCoat = true;
					pCass->vslots[i].bNeedCheckCut = true;
					pCass->vslots[i].CheckStatus = CHECKBEGIN;
					pCass->SetFirstCheckFinished(false);
				}
			}
		}
	}

	////结束后移动到Open位置

#ifdef __LOWK_SOLUTION__
	//轨道移动到扫描位置
	CProcess_Trans* pTrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS, CProcess_Trans);
	pTrans->MoveRailNearOpen(true);
#endif

}

void CProcess_Scan::FileToRecord(QList<double>& list, QString fileName)
{
	QString strPath = CMakePath::make_data_path(fileName);
	QFile file(strPath);
	if (!file.open(QIODevice::ReadOnly))
	{
		MQT_THROW_STR(QObject::trUtf8("open path %1 failed")
			.arg(strPath));
	}

	list.clear();

	QTextStream stream(&file);
	double x;
	while (!stream.atEnd())
	{
		x = stream.readLine().toDouble();
		list.push_back(x);
	}
}

//移动到某片料的，料盒扫描位置
int CProcess_Scan::MoveSlotScanPos(int32_t cassid, int32_t slotindex)
{
	UNUSED(cassid);
	UNUSED(slotindex);
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pDriver);
	double firstScanPos = m_Variants.get_VData(Var_Cass_FirstScanPos_ID)->toDouble();
	double dSlotStep = m_Variants.get_VData(Var_Cass_Slot_Step)->toDouble();
	double dScanPos = firstScanPos - dSlotStep * slotindex;

	pDriver->absmove(MOTORC_CASS, dScanPos, true);
	return 0;
}

/*!
 * \brief CProcess_Scan::CCassExist
 * 判断料盒是否存在， 12inch和8inch使用不一样的传感器
 * \param cassid
 * \return
 */
BOOL CProcess_Scan::CCassExist(int32_t cassid)
{
	UNUSED(cassid);
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pDriver);
	CMProduct* pProduct = GET_CHDIRECT(PRODUCT, CMProduct);

	int iWaferSize = pProduct->m_Variants.get_VData(Var_MProduct_SizeType_ID)
		->toUInt();
	if (iWaferSize == 0)
	{
		return pDriver->get_iodata(IO_INPUT, IN_CASSEXISTCHECK8Inch_Right, true);
	}
	return pDriver->get_iodata(IO_INPUT, IN_CASSEXISTCHECK8Inch_Left, true);
}

/*!
 * \brief CProcess_Scan::ScanMoveCheck
 * 扫描前检测
 * \return
 */
int CProcess_Scan::ScanMoveCheck()
{
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pDriver);
	if (pDriver->get_iodata(IO_INPUT, IN_WaferOutCass_Front_Cassete, true))
	{
		MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cassette Front Sensor On"));
	}
	if (pDriver->get_iodata(IO_INPUT, IN_WaferOutCass_Wafer_OutSide, true))
	{
		MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Wafer Outside"));
	}
	if (pDriver->get_iodata(IO_INPUT, IN_CHECKBOX_DOOR_OPENED, true))
	{
		MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Cupboard Opened."));
	}
	//需要检测轨道上是否有料
	bool_t bLockHasWafer =
		pDriver->get_iodata(IO_INPUT, IN_Rail_NearCass_HasWafer, true);
	if (bLockHasWafer)
	{
		MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Rail(near) has wafer.Please remove and retry."));
	}
	bLockHasWafer = pDriver->get_iodata(IO_INPUT, IN_Rail_NearLoc_HasWafer, true);
	if (bLockHasWafer)
	{
		MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Rail(near) has wafer.Please remove and retry."));
	}
	return 0;
}

BOOL CProcess_Scan::IsCheckCellExist()
{
	return FALSE;
}

int CProcess_Scan::MoveSlotLoadPos(int32_t cassid, int32_t slotindex, bool bWait/*=true*/, bool bAuto/* = true*/)
{
	UNUSED(cassid);
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pDriver);
	double dPos = slotLoadPos(cassid, slotindex, bAuto);
	pDriver->absmove(MOTORC_CASS, dPos, bWait);
	return RTN_SUCCESS1;
}

int CProcess_Scan::MoveSlotUnLoadPos(int32_t cassid, int32_t slotindex, bool bWait/*=true*/, bool bAuto/* = true*/)
{
	UNUSED(cassid);
	CMotorDriver* pDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
	Q_ASSERT(pDriver);
	pDriver->absmove(MOTORC_CASS, slotunLoadPos(cassid, slotindex, bAuto), bWait);
	return RTN_SUCCESS1;
}

float64_t CProcess_Scan::slotLoadPos(int32_t cassid, int32_t slotindex, bool bAuto/* = true*/)
{
	CCassette* pCass = GET_CHDIRECT(cassid, CCassette);
	Q_ASSERT(pCass);
	if (slotindex < 0)
	{
		//CheckBox取料位置
		return m_Variants.get_VData(Var_ClawPos_CheckBox_ID)->toDouble();
	}

	if (bAuto && pCass->vslots[slotindex].WPstatus == NOWP)
	{
		MQT_THROW_CODESTR(ALARM_TRANS_SAFE_PROTECT, QObject::trUtf8("Slot do not have wafer."));
	}

	double dSlotStep = m_Variants.get_VData(Var_Cass_Slot_Step)->toDouble();
	double firstClawPos = m_Variants.get_VData(Var_Cass_FirstClawPos_ID)->toDouble();
	double distance = dSlotStep * slotindex;
	double dLoadPos = firstClawPos - distance;
	return dLoadPos;
}

float64_t CProcess_Scan::slotunLoadPos(int32_t cassid, int32_t slotindex, bool bAuto/* = true*/)
{
	double offset = m_Variants.get_VData(Var_Cass_UnloadOffset_ID)->toDouble();
	return slotLoadPos(cassid, slotindex, bAuto) + offset;
}



void CProcess_Scan::GetSensorData(QList<double>& scanExistList1,
	QList<double>& scanExistList2,
	QList<double>& scanEmptyList1,
	QList<double>& scanEmptyList2,
	CMotorDriver* pDriver,
	double posStart,
	double posEnd)
{
	//首先移动扫描开始位
	pDriver->setdefaultspeed(MOTORC_CASS);
	pDriver->absmove(MOTORC_CASS, posStart, true);

	//移动到开始位置，开始位置传感器应该没信号
	bool bScanStatus1 = pDriver->get_iodata(IO_INPUT, IN_SCAN_LEFT, true);
	bool bScanStatus2 = pDriver->get_iodata(IO_INPUT, IN_SCAN_RIGHT, true);
	if (bScanStatus1 || bScanStatus2)
	{
		MQT_THROW_CODESTR(ALARM_SCAN_WAFER_DATAERROR, QObject::trUtf8("Scan position start sensor check failed"));
	}

	CMotor* pMotor = GET_CHDIRECT(MOTORC_CASS, CMotor);
	double dDefaultSpd = m_Variants.get_VData(Var_Process_ScanSpeed)
		->toDouble();
	pDriver->setspeed(MOTORC_CASS, dDefaultSpd, 0, 0, 0, 0);
	//移动到结束点
	pDriver->absmove(MOTORC_CASS, posEnd, false);

	bool bExist1 = bScanStatus1;
	bool bExist2 = bScanStatus2;
	bool bFinished = false;
	while (!bFinished)
	{
		bExist1 = pDriver->get_iodata(IO_INPUT, IN_SCAN_LEFT, true);
		bExist2 = pDriver->get_iodata(IO_INPUT, IN_SCAN_RIGHT, true);

		if (bScanStatus1 != bExist1)
		{
			double dPos = pDriver->get_posdata(MOTORC_CASS, true);
			bScanStatus1 = bExist1;
			if (bExist1)
			{
				scanExistList1.push_back(dPos);
				/*QString info = QString("Scan Left Exists: Pos:%1").arg(dPos);
				m_gSystem.SendLogMessage(info, 0);*/
			}
			else
			{
				double dLastExistPos = scanExistList1.last();
				if (fabs(dLastExistPos - dPos) < 1.2)
				{
					scanExistList1.removeLast();
					MqDebug() << "Remove Exception scan data";
				}
				else
				{
					QString info = QString("Scan Left Exists: Pos:%1").arg(dPos);
					m_gSystem.SendLogMessage(info, 0);
					scanEmptyList1.push_back(dPos);
				}
			}
		}

		if (bScanStatus2 != bExist2)
		{
			double dPos = pDriver->get_posdata(MOTORC_CASS, true);
			bScanStatus2 = bExist2;
			if (bExist2)
			{
				QString info = QString("Scan Right Exists: Pos:%1").arg(dPos);
				m_gSystem.SendLogMessage(info, 0);
				scanExistList2.push_back(dPos);
			}
			else
				scanEmptyList2.push_back(dPos);
		}

		bFinished = pDriver->is_move_finished(MOTORC_CASS);
	}

	pDriver->setdefaultspeed(MOTORC_CASS);
	bScanStatus1 = pDriver->get_iodata(IO_INPUT, IN_SCAN_LEFT, true);
	bScanStatus2 = pDriver->get_iodata(IO_INPUT, IN_SCAN_RIGHT, true);
	if (bScanStatus1 || bScanStatus2)
	{
		MQT_THROW_CODESTR(ALARM_SCAN_WAFER_DATAERROR, QObject::trUtf8("Scan position finish sensor check failed"));
	}
}

void CProcess_Scan::ComputeWaferCenter(QList<double>& scanExistList1,
	QList<double>& scanExistList2,
	QList<double>& scanEmptyList1,
	QList<double>& scanEmptyList2,
	double sensorOffset,
	double waferThickness,
	QList<double>& scanCenterList,
	QList<int>& scanResultList,
	double dOffset)
{
	bool bErr = false;
	double sumThick1 = 0;
	double sumThick2 = 0;
	double minThick = 100;
	double maxThick = 0;
	double minThick2 = 100;
	double maxThick2 = 0;
	double dWpOverlappedThickness1 = m_Variants.get_VData(Var_Process_WPOverrlapped_ThickLimit1)->toDouble();
	double dWpOverlappedThickness2 = m_Variants.get_VData(Var_Process_WPOverrlapped_ThickLimit2)->toDouble();
	for (int i = 0; i < scanExistList1.size(); i++)
	{
		double dThickness1 = abs(scanEmptyList1[i] - scanExistList1[i]);
		double dThickness2 = abs(scanEmptyList2[i] - scanExistList2[i]);
		sumThick1 += dThickness1;
		sumThick2 += dThickness2;
		minThick = min(minThick, dThickness1);
		maxThick = max(maxThick, dThickness1);
		minThick2 = min(minThick2, dThickness2);
		maxThick2 = max(maxThick2, dThickness2);
		MqDebug() << i << "Thickness: Left:" << dThickness1 << " Right:" << dThickness2;
		m_gSystem.SendLogMessage(QString("%1 Thickness: Left: %2 Right:%3").arg(i).arg(dThickness1).arg(dThickness2), 0);
		bErr = false;
		//判断是否叠片
		//片厚超过阈值，则是叠片
		if (dThickness1 > dWpOverlappedThickness1 || dThickness2 > dWpOverlappedThickness2)
		{
			MqDebug() << i << "WPOVERLAPPED: Left:" << dWpOverlappedThickness1 << " Right:" << dWpOverlappedThickness2;
			scanResultList.push_back(WPOVERLAPPED);
			bErr = true;
		}

		double sensorCenterLeft = (scanEmptyList1[i] + scanExistList1[i]) / 2.0 + dOffset;
		double sensorCenterRight = (scanEmptyList2[i] + scanExistList2[i]) / 2.0 + sensorOffset + dOffset;

		{
			std::ostringstream stream;
			stream << i << "Center: Left:" << sensorCenterLeft << " Right:" << sensorCenterRight << " Right Src:" << sensorCenterRight - sensorOffset;
			m_gSystem.SendLogMessage(stream.str().c_str(), 0);
			MqDebug() << stream.str().c_str();
		}

		//判断晶圆是否错位
		//左右两个传感器扫描数据超过阈值，则是错位
		double dMalposed = m_Variants.get_VData(Var_Process_WPMalposed_ThickLimit)->toDouble();
		if (abs(sensorCenterRight - sensorCenterLeft) > dMalposed)
		{
			scanResultList.push_back(WPMALPOSED);
			bErr = true;
		}

		scanCenterList.push_back((sensorCenterLeft + sensorCenterRight) / 2);
		if (!bErr)
		{
			scanResultList.push_back(WPUNCUT);
		}
	}
	//LOG(INFO) << "Aver:" << sumThick1 / scanExistList1.size() << "," << sumThick2 / scanExistList1.size();
	//LOG(INFO) << "Max:" << maxThick << "Min:" << minThick;
	//LOG(INFO) << "Max:" << maxThick2 << "Min:" << minThick2;

	{
		std::ostringstream stream;
		stream << "Aver:" << sumThick1 / scanExistList1.size() << "," << sumThick2 / scanExistList1.size() << endl;
		stream << "Max:" << maxThick << "Min:" << minThick << endl;
		stream << "Max:" << maxThick2 << "Min:" << minThick2 << endl;
        m_gSystem.SendLogMessage(stream.str().c_str(), 0);
		MqDebug() << stream.str().c_str();
	}
}

bool CProcess_Scan::SimulatorScan(int cassid, int iStep)
{
	CCassette* pCass = GET_CHDIRECT(cassid, CCassette);
	Q_ASSERT(pCass);

	int iSlotCountMax = pCass->m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
	//模拟所有都有片
	if (iStep == 0)
	{
		//如果是第一片，重置所有
		pCass->ResetSlots();

		//轨道移动到扫描位置
		/*CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
		double dPos = m_Variants.get_VData(Var_Rail_Scan_Pos_ID)->toDouble();
		pMotorDriver->absmove(MOTORB1_LOCK, dPos);*/

	}
	else if (iStep == 1)
	{
		//1~iSlotCountMax
		for (int i = 0; i < iSlotCountMax; i++)
		{
			pCass->vslots[i].WPstatus = WPUNCUT;
		}
	}
	else if (iStep == iSlotCountMax + 2)
	{
		AfterScan(cassid);
		return true;
	}

	return true;
}

