//---------------------------------------------------------------------------
// For SELMA200, 20180227, moon, 완료
//---------------------------------------------------------------------------

#include <inifiles.hpp>
#include <registry.hpp>
#include <Classes.hpp>
#include <math.h>
#include "MultiLanguage.h"
#include "StudySpeedControl_Form.h"

#pragma hdrstop

#include "Common_PC.h"
#include "CameraSetting3D_Form.h"
#pragma package(smart_init)

#define MOTOR_ROUND_PER_VALUE	10
#define MECH_MOVE_PER_VALUE		140
//#define MOTOR_SPEED_STEP_COUNT			10

#define CURRENT_PRODUCT_DATA_MAJOR_VERSION		2
#define CURRENT_PRODUCT_DATA_MINOR_VERSION		0

#define min(x, y) (x < y ? x : y)


bool GlobalEnabledCameraStatus[SYSTEM_TOTAL_CAMERA_COUNT];
int  SystemImageOffsetSWCal[SYSTEM_TOTAL_CAMERA_COUNT];
unsigned char SystemOffsetImage[SYSTEM_TOTAL_CAMERA_COUNT][SYSTEM_CAMERA_WIDTH / 2 * SYSTEM_CAMERA_HEIGHT / 2];
int Table_Interval_PixelAndMeter[1000]; //10um단위
//---------------------------------------------------------------------------
void __fastcall SetGrayPalette(Graphics::TBitmap *theBitmap)
{
	struct
	{
		WORD        palVersion;
		WORD        palNumEntries;
		PALETTEENTRY        palPalEntry[256];
	} grayPalette;

	grayPalette.palVersion = 0x300;
	grayPalette.palNumEntries = 256;
	for (int i = 0; i < 256; i++)
	{
		grayPalette.palPalEntry[i].peRed = i;
		grayPalette.palPalEntry[i].peGreen = i;
		grayPalette.palPalEntry[i].peBlue = i;
		grayPalette.palPalEntry[i].peFlags = 0;
	}
	PLOGPALETTE pLogPal = (PLOGPALETTE)&grayPalette;

	theBitmap->Palette = CreatePalette(pLogPal);
}
//---------------------------------------------------------------------------
void __fastcall Set3DPalette(Graphics::TBitmap *theBitmap)
{
	struct
	{
		WORD        palVersion;
		WORD        palNumEntries;
		PALETTEENTRY        palPalEntry[256];
	} grayPalette;

	grayPalette.palVersion = 0x300;
	grayPalette.palNumEntries = 256;
	for (int i = 0; i < 64; i++)
	{
		grayPalette.palPalEntry[i].peRed = 0;
		grayPalette.palPalEntry[i].peGreen = 0;
		grayPalette.palPalEntry[i].peBlue = i * 4 + 3;   // 0 7 12 15 19
		grayPalette.palPalEntry[i].peFlags = 0;
	}
	for (int i = 64; i < 128; i++)
	{
		grayPalette.palPalEntry[i].peRed = 0;
		grayPalette.palPalEntry[i].peGreen = i * 4 + 3;
		grayPalette.palPalEntry[i].peBlue = (127 - i) * 4 + 3;
		grayPalette.palPalEntry[i].peFlags = 0;
	}
	for (int i = 128; i < 192; i++)
	{
		grayPalette.palPalEntry[i].peRed = i * 4 + 3;
		grayPalette.palPalEntry[i].peGreen = 255;
		grayPalette.palPalEntry[i].peBlue = 0;
		grayPalette.palPalEntry[i].peFlags = 0;
	}
	for (int i = 192; i < 256; i++)
	{
		grayPalette.palPalEntry[i].peRed = 255;
		grayPalette.palPalEntry[i].peGreen = (255 - i) * 4 + 3;
		grayPalette.palPalEntry[i].peBlue = 0;
		grayPalette.palPalEntry[i].peFlags = 0;
	}
	PLOGPALETTE pLogPal = (PLOGPALETTE)&grayPalette;

	theBitmap->Palette = CreatePalette(pLogPal);
}
//---------------------------------------------------------------------------
double __fastcall Motor_RPM_To_MMPS(int rpm)
{
	return rpm * MECH_MOVE_PER_VALUE / MOTOR_ROUND_PER_VALUE / 10.0 / 60.0;
}
//---------------------------------------------------------------------------

bool __fastcall ReadMachineSetupData(AnsiString fileName, TMachineSetupData &machineSetupData)
{
	bool returnValue = true;
	memset(&machineSetupData, 0, sizeof(TMachineSetupData));
	TIniFile *iniFile = new TIniFile(fileName);

	if (iniFile)
	{
		machineSetupData.MachineMode = iniFile->ReadInteger("Machine Info", "Machine Mode", MACHINE_MODE_TEST);
		machineSetupData.MachineType = iniFile->ReadInteger("Machine Info", "Machine Type", MACHINE_TYPE_SELMA_BASIC);
		machineSetupData.PC_Power_Mode = iniFile->ReadInteger("Power Info", "PC PowerMode", PC_POWER_MODE_AUTO);

    //한국콜마
		machineSetupData.EjectorInfo.DistributorGoodTabletCount1 = iniFile->ReadInteger("Ejector Info", "DistributorGoodTabletCount1", 50000);
		machineSetupData.EjectorInfo.DistributorGoodTabletCount2 = iniFile->ReadInteger("Ejector Info", "DistributorGoodTabletCount2", 50000);
		machineSetupData.EjectorInfo.DistributorGoodTabletCount3 = iniFile->ReadInteger("Ejector Info", "DistributorGoodTabletCount3", 50000);

		machineSetupData.LasercomplexerInfo.Machine_type=  iniFile->ReadInteger("LasercomplexerInfo", "Machine_Type", MACHINE_TYPE_SELMA_BASIC);
		machineSetupData.LasercomplexerInfo.Laser_complexer_Enable =  iniFile->ReadInteger("LasercomplexerInfo", "Laser_complexer_Enable", 0);
		machineSetupData.LasercomplexerInfo.Laser_deley_time =  iniFile->ReadInteger("LasercomplexerInfo", "Laser_deley_time", 0);
		machineSetupData.LasercomplexerInfo.Laser_Trig_mode = iniFile->ReadInteger("LasercomplexerInfo", "Laser_Trig_mode", 0);

    machineSetupData.EjectorInfo.DefectEjectorDelay = iniFile->ReadInteger("Ejector Info", "Defect Ejector Delay", 20);
    machineSetupData.EjectorInfo.UnInsEjectorDelay = iniFile->ReadInteger("Ejector Info", "UnIns Ejector Delay", 20);
    machineSetupData.EjectorInfo.GoodEjectorDelay = iniFile->ReadInteger("Ejector Info", "Good Ejector Delay",20);

    machineSetupData.EjectorInfo.DefectEjectorLength= iniFile->ReadInteger("Ejector Info", "Defect Ejector Length", 1);
    machineSetupData.EjectorInfo.UnInsEjectorLength= iniFile->ReadInteger("Ejector Info", "UnIns Ejector Length", 1);
    machineSetupData.EjectorInfo.GoodEjectorLength= iniFile->ReadInteger("Ejector Info", "Good Ejector Length",1);
    machineSetupData.SensorIntervalA = iniFile->ReadInteger("Sensor Info", "Sensor Interval A", 0);
    machineSetupData.SensorIntervalB = iniFile->ReadInteger("Sensor Info", "Sensor Interval B", 0);

    for (int captureIndex = 0; captureIndex < SYSTEM_MACHINE_CAPTURE_COUNT; captureIndex++)
    {
      machineSetupData.MachineCaptureInfo.CaptureDelay[captureIndex] = iniFile->ReadInteger("Machine Capture Info", "Capture Delay " + IntToStr(captureIndex), 0);
      machineSetupData.MachineCaptureInfo.IlluminatorMask[captureIndex] = iniFile->ReadInteger("Machine Capture Info", "Illuminator Mask " + IntToStr(captureIndex), 0);
      machineSetupData.MachineCaptureInfo.IlluminatorDelay[captureIndex] = iniFile->ReadInteger("Machine Capture Info", "Illuminator Delay " + IntToStr(captureIndex), 0);
      machineSetupData.MachineCaptureInfo.IlluminatorTime[captureIndex] = iniFile->ReadInteger("Machine Capture Info", "Illuminator Time " + IntToStr(captureIndex), 0);
      machineSetupData.MachineCaptureInfo.CamMask[captureIndex] = iniFile->ReadInteger("Machine Capture Info", "Camera Map " + IntToStr(captureIndex), 0);
    }

		//        machineSetupData.MachineCaptureInfo.CaptureStableDelay = iniFile->ReadInteger("Machine Capture Info", "Capture Stable Delay", 0);

		for (int sensorIndex = 0; sensorIndex < 2; sensorIndex++)
		{
			machineSetupData.MachineCaptureInfo.SensorSPBMask[sensorIndex] = iniFile->ReadInteger("Machine Capture Info", "Sensor SPB Mask " + IntToStr(sensorIndex), 0);
		}

		machineSetupData.EjectorInfo.MisejectActive = iniFile->ReadInteger("Ejector Info", "Miseject Active", 1);
		machineSetupData.EjectorInfo.MisejectActiveDelay = iniFile->ReadInteger("Ejector Info", "Miseject Active Delay", 0);
		//sjm
		machineSetupData.EjectorInfo.Special_InspectionActive = iniFile->ReadInteger("Ejector Info", "Special Inspection Active", 1);
		machineSetupData.EjectorInfo.Blowinterval = iniFile->ReadInteger("Ejector Info", "Blow Interval", 60);
		machineSetupData.EjectorInfo.Blowstart = iniFile->ReadInteger("Ejector Info", "Blow Start", 0);
		machineSetupData.EjectorInfo.Blowlength = iniFile->ReadInteger("Ejector Info", "Blow Length", 0);
		machineSetupData.EjectorInfo.UninsBlowCheck = iniFile->ReadInteger("Ejector Info", "Uninspection Active", 0);

		//cik add
		machineSetupData.EjectorInfo.EjectorWindStrength = iniFile->ReadInteger("Ejector Info", "Ejector Wind Strength", 100);

		machineSetupData.EjectorInfo.EjectorDefaultMode = iniFile->ReadInteger("Ejector Info", "Ejector Default Mode", 0);
		machineSetupData.EjectorInfo.SpModeGoodTabletCollectCount1 = iniFile->ReadInteger("Ejector Info", "SpMode Good Tablet Collect Count 1", 50000);
		machineSetupData.EjectorInfo.SpModeGoodTabletCollectCount2 = iniFile->ReadInteger("Ejector Info", "SpMode Good Tablet Collect Count 2", 50000);

		//TPB Miseject
		machineSetupData.EjectorInfo.TPB_MisejectActive 				= iniFile->ReadInteger("Ejector Info", "TPB_MisejectActive", 0);
		machineSetupData.EjectorInfo.TPB_MisejectOpenDelay 			= iniFile->ReadInteger("Ejector Info", "TPB_MisejectOpenDelay", 0);
		machineSetupData.EjectorInfo.TPB_MisejectOpenRunTime 		= iniFile->ReadInteger("Ejector Info", "TPB_MisejectOpenRunTime", 2000);    
		machineSetupData.EjectorInfo.TPB_MisCmdValidCnt 				= iniFile->ReadInteger("Ejector Info", "TPB_MisCmdValidCnt", 3);
		machineSetupData.EjectorInfo.IgnoreMultiMisejectAction	= iniFile->ReadInteger("Ejector Info", "IgnoreMultiMisejectAction", 0);   
		machineSetupData.EjectorInfo.TPB_MisejectOperationMode	= iniFile->ReadInteger("Ejector Info", "TPB_MisejectOperationMode", TPB_MISEJECT_NO_INSPECTION_MODE); 

		// machineSetupData.VFInfo.EmptySensorIndex = iniFile->ReadInteger("Vibration Feeder Info", "Empty Sensor Index", 0);
// machineSetupData.VFInfo.FullSensorIndex = iniFile->ReadInteger("Vibration Feeder Info", "Full Sensor Index", 1);

		machineSetupData.VFInfo.MaxSpeedTrainingMode = iniFile->ReadInteger("Vibration Feeder Info", "Max Speed Training Mode", MAX_SPEED_TRAINING_MODE_AUTO);
		machineSetupData.VFInfo.StartSpeed = iniFile->ReadInteger("Vibration Feeder Info", "Start Speed", 40);
		machineSetupData.VFInfo.EmptySensorActiveRatio = iniFile->ReadInteger("Vibration Feeder Info", "Empty Sensor Active Ratio", 80);
		machineSetupData.VFInfo.FullSensorActiveRatio = iniFile->ReadInteger("Vibration Feeder Info", "Full Sensor Active Ratio", 80);

		machineSetupData.VFInfo.ManualMaxSpeed = iniFile->ReadInteger("Vibration Feeder Info", "Manual Max Speed", 100);
		machineSetupData.VFInfo.ManualLimitSpeed = iniFile->ReadInteger("Vibration Feeder Info", "Manual Limit Speed", 60);
		machineSetupData.VFInfo.ManualModeSensorIndex = iniFile->ReadInteger("Vibration Feeder Info", "Manual Mode Sensor Index", 0);
		machineSetupData.VFInfo.ManualModeLimitSensorIndex = iniFile->ReadInteger("Vibration Feeder Info", "Manual Mode Limit Sensor Index", 1);
		machineSetupData.VFInfo.ManualModeSensorActiveRatio = iniFile->ReadInteger("Vibration Feeder Info", "Manual Mode Sensor Active Ratio", 80);
		machineSetupData.VFInfo.ManualModeLimitSensorActiveRatio = iniFile->ReadInteger("Vibration Feeder Info", "Manual Mode Limit Sensor Active Ratio", 30);

		machineSetupData.VFInfo.MechanicalMinSpeed = iniFile->ReadInteger("Vibration Feeder Info", "Mechanical Min Speed", 100);
		machineSetupData.VFInfo.MechanicalMaxSpeed = iniFile->ReadInteger("Vibration Feeder Info", "Mechanical Max Speed", 100);

    machineSetupData.VFInfo.FeederEmptyAlarmDelayTime = iniFile->ReadInteger("Vibration Feeder Info", "Feeder Alarm Delay Time", 5);

		machineSetupData.InterlockInfo.DoorInterlockEnabled = iniFile->ReadInteger("Interlock Info", "Door Enabled", 0);
		machineSetupData.InterlockInfo.NCInterlockAValue = iniFile->ReadInteger("Interlock Info", "NC Interlock A Value", 0);

    machineSetupData.InterlockInfo.ACdomesticMode = iniFile->ReadInteger("Interlock Info", "ACdomesticMode", 0);

		for (int stepMotorIndex = 0; stepMotorIndex < MAX_STEP_MOTOR_COUNT; stepMotorIndex++)
		{
			machineSetupData.ZeroPositionValue[stepMotorIndex] = iniFile->ReadFloat("NC Info", "NC Zero Pos " + IntToStr(stepMotorIndex + 1), 0);
		}

		machineSetupData.LEDControlInfo.EyeProtectionModeEnabled = iniFile->ReadInteger("LED Control Info", "Eye Protection Mode Enabled", 0);
		machineSetupData.LEDControlInfo.LEDOnTime = iniFile->ReadInteger("LED Control Info", "Eye Protection LED On Time", 3);
		machineSetupData.LEDControlInfo.LEDOffDelay = iniFile->ReadInteger("LED Control Info", "Eye Protection LED Off Delay", 17);

		machineSetupData.BuzzerInfo.BuzzerContinuousOn = iniFile->ReadBool("Buzzer Info", "Buzzer Continuous On", true) ? 1 : 0;
		machineSetupData.BuzzerInfo.BuzzerOnTime = iniFile->ReadInteger("Buzzer Info", "Buzzer On Time", 10);

		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			machineSetupData.ServoMotorData[motorIndex].BaseSpeed = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Base Speed", 100);
			machineSetupData.ServoMotorData[motorIndex].AccTime = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Acc Time", 1000);
			machineSetupData.ServoMotorData[motorIndex].DecTime = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Dec Time", 1000);
			machineSetupData.ServoMotorData[motorIndex].Dir = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Direction", 1);
		}

		machineSetupData.AlarmSetupInfo.PressureAlarmLevel = iniFile->ReadInteger("Alarm Level", "Pressure Alarm Level", 400);
		machineSetupData.AlarmSetupInfo.VacuumAlarmLevel1 = iniFile->ReadInteger("Alarm Level", "Vacuum Alarm Level 1", 0);
		machineSetupData.AlarmSetupInfo.VacuumAlarmLevel2 = iniFile->ReadInteger("Alarm Level", "Vacuum Alarm Level 2", 0);
		machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel1 = iniFile->ReadInteger("Alarm Level", "Temperature Alarm Level 1", 50);
		machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel2 = iniFile->ReadInteger("Alarm Level", "Temperature Alarm Level 2", 50);
		machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel3 = iniFile->ReadInteger("Alarm Level", "Temperature Alarm Level 3", 50);

		machineSetupData.HopperEmptyEnable = iniFile->ReadInteger("Hopper Empty", "Enabled", 0);
		// khd1994 HCB IP주소 및 Port처리
		strcpy(machineSetupData.szHCB_IpAddr, iniFile->ReadString("HCB", "ServerIpAddr", "192.168.0.10").c_str());
		machineSetupData.nHCB_TcpPort = iniFile->ReadInteger("HCB", "ServerPort", 7000);

    machineSetupData.CompanyID = iniFile->ReadInteger("HCB", "CompanyID", 0);
    machineSetupData.BowlFeederSensorOption = iniFile->ReadInteger("HCB", "BowlFeederSensorOption", 1);
    machineSetupData.SafetyCircuitMode = iniFile->ReadInteger("Safety", "SafetyCircuitMode", 1);
    machineSetupData.DiskStartDelay = iniFile->ReadInteger("Disk", "StartDelay", 0);
    machineSetupData.SuctionDiskGearRatio = iniFile->ReadInteger("Disk", "SucktionDisk Gear Ratio", 10);
    machineSetupData.Qualis_Machine1_CutomOption = iniFile->ReadInteger("Acrocia", "Machine1Special", 0);
    machineSetupData.SimpleSpeedControlOption = iniFile->ReadInteger("Simple Servo Speed", "Enabled", 0);
    machineSetupData.IPB_BoardCount = iniFile->ReadInteger("IPB Count", "IPB_BoardCount", 6);

    machineSetupData.AutoDemper = iniFile->ReadInteger("Auto Demper", "Activated", 1);

    machineSetupData.DistributorCtrl.InSigOffTimeLength = iniFile->ReadInteger("Distributor", "In_SW_Time", 10);
	  machineSetupData.DistributorCtrl.OutSigOnTimeLength = iniFile->ReadInteger("Distributor", "Out_SW_Time", 2);
	  machineSetupData.DistributorCtrl.OutSigDelayTime = iniFile->ReadInteger("Distributor", "Out_Signal_Start_Delay", 30);
      machineSetupData.DistributorCtrl.WaitChangeBarrelTime = iniFile->ReadInteger("Distributor", "Wait Change Barrel Time", 120);
	  machineSetupData.InverterType = iniFile->ReadInteger("Inverter", "Type", 0);

		delete iniFile;
	}
	else
	{
		machineSetupData.MachineMode = MACHINE_MODE_TEST;
		machineSetupData.MachineType = MACHINE_TYPE_SELMA_BASIC;
		machineSetupData.PC_Power_Mode = PC_POWER_MODE_AUTO;

		for (int captureIndex = 0; captureIndex < SYSTEM_MACHINE_CAPTURE_COUNT; captureIndex++)
		{
			machineSetupData.MachineCaptureInfo.CaptureDelay[captureIndex] = 0;
			machineSetupData.MachineCaptureInfo.IlluminatorMask[captureIndex] = 0;
			machineSetupData.MachineCaptureInfo.IlluminatorDelay[captureIndex] = 0;
			machineSetupData.MachineCaptureInfo.IlluminatorTime[captureIndex] = 0;
			machineSetupData.MachineCaptureInfo.CamMask[captureIndex] = 0;
		}
		//        machineSetupData.MachineCaptureInfo.CaptureStableDelay = 0;

		for (int sensorIndex = 0; sensorIndex < 2; sensorIndex++)
		{
			machineSetupData.MachineCaptureInfo.SensorSPBMask[sensorIndex] = 0;
		}

		machineSetupData.EjectorInfo.DefectEjectorDelay = 20;
		machineSetupData.EjectorInfo.UnInsEjectorDelay = 20;
		machineSetupData.EjectorInfo.GoodEjectorDelay = 20;
		machineSetupData.EjectorInfo.DefectEjectorLength= 1;
		machineSetupData.EjectorInfo.UnInsEjectorLength = 1;
		machineSetupData.EjectorInfo.GoodEjectorLength = 1;

		machineSetupData.EjectorInfo.MisejectActive = 1;
		machineSetupData.EjectorInfo.MisejectActiveDelay = 0;

		//sjm
		machineSetupData.EjectorInfo.Special_InspectionActive = 1;
		machineSetupData.EjectorInfo.Blowinterval = 60;
		machineSetupData.EjectorInfo.Blowstart = 0;
		machineSetupData.EjectorInfo.Blowlength = 0;
		machineSetupData.EjectorInfo.UninsBlowCheck = 0;

		//cik add
		machineSetupData.EjectorInfo.EjectorWindStrength = 100;
		//한국콜마
		machineSetupData.EjectorInfo.DistributorGoodTabletCount1 = 50000;
		machineSetupData.EjectorInfo.DistributorGoodTabletCount2 = 50000;
		machineSetupData.EjectorInfo.DistributorGoodTabletCount3 = 50000;

		machineSetupData.EjectorInfo.EjectorDefaultMode = 0;
		machineSetupData.EjectorInfo.SpModeGoodTabletCollectCount1 = 50000;
		machineSetupData.EjectorInfo.SpModeGoodTabletCollectCount2 = 50000;

		machineSetupData.VFInfo.ManualModeSensorIndex = 0;
		machineSetupData.VFInfo.ManualModeLimitSensorIndex = 1;
		machineSetupData.VFInfo.ManualModeSensorActiveRatio = 80;
		machineSetupData.VFInfo.ManualModeLimitSensorActiveRatio = 30;

		machineSetupData.VFInfo.FullSensorActiveRatio = 80;
		machineSetupData.VFInfo.EmptySensorActiveRatio = 80;

		machineSetupData.VFInfo.StartSpeed = 40;
		machineSetupData.VFInfo.MechanicalMinSpeed = 20;
		machineSetupData.VFInfo.MechanicalMaxSpeed = 255;
		//		machineSetupData.VFInfo.FullSensorIndex = 1;
		//		machineSetupData.VFInfo.EmptySensorIndex = 0;
		machineSetupData.VFInfo.FeederEmptyAlarmDelayTime = 5;
		machineSetupData.SensorIntervalA = 0;
		machineSetupData.SensorIntervalB = 0;

		machineSetupData.InterlockInfo.DoorInterlockEnabled = 0;
		machineSetupData.InterlockInfo.NCInterlockAValue = 0;
		machineSetupData.InterlockInfo.ACdomesticMode = 0;

		machineSetupData.BuzzerInfo.BuzzerContinuousOn = true;
		machineSetupData.BuzzerInfo.BuzzerOnTime = 10;

		machineSetupData.LEDControlInfo.EyeProtectionModeEnabled = 0;
		machineSetupData.LEDControlInfo.LEDOnTime = 3;
		machineSetupData.LEDControlInfo.LEDOffDelay = 17;

		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			machineSetupData.ServoMotorData[motorIndex].BaseSpeed = 100;
			machineSetupData.ServoMotorData[motorIndex].AccTime = 1000;
			machineSetupData.ServoMotorData[motorIndex].DecTime = 1000;
			machineSetupData.ServoMotorData[motorIndex].Dir = 1;
		}

		machineSetupData.AlarmSetupInfo.PressureAlarmLevel = 400;
		machineSetupData.AlarmSetupInfo.VacuumAlarmLevel1 = 0;
		machineSetupData.AlarmSetupInfo.VacuumAlarmLevel2 = 0;
		machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel1 = 50;
		machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel2 = 50;
		machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel3 = 50;

		machineSetupData.HopperEmptyEnable = 0;
		machineSetupData.CompanyID = 0;
		machineSetupData.BowlFeederSensorOption=1;
		machineSetupData.SafetyCircuitMode = 1;
		machineSetupData.DiskStartDelay = 0 ;
		machineSetupData.Qualis_Machine1_CutomOption = 0;
		machineSetupData.SimpleSpeedControlOption = 0;
		machineSetupData.LasercomplexerInfo.Machine_type =  MACHINE_TYPE_SELMA_BASIC;    
		machineSetupData.LasercomplexerInfo.Laser_complexer_Enable = 0;
		machineSetupData.LasercomplexerInfo.Laser_deley_time = 10;
		machineSetupData.LasercomplexerInfo.Laser_Trig_mode = 0;
		machineSetupData.IPB_BoardCount = 6;
		machineSetupData.SuctionDiskGearRatio = 10;

		machineSetupData.AutoDemper = 1;
    	machineSetupData.DistributorCtrl.InSigOffTimeLength = 10;
	  	machineSetupData.DistributorCtrl.OutSigOnTimeLength = 2;
	  	machineSetupData.DistributorCtrl.OutSigDelayTime = 30;
        machineSetupData.DistributorCtrl.WaitChangeBarrelTime = 120;
		machineSetupData.EjectorInfo.IgnoreMultiMisejectAction	= 0;     

		machineSetupData.InverterType = 0; 

	 returnValue = false;
	}
	return returnValue;
}
//---------------------------------------------------------------------------
void __fastcall WriteMachineSetupData(AnsiString fileName, TMachineSetupData &machineSetupData,bool ChangeLaserComplexValue)
{
	bool PrevLaserComplexStatus = false;
  
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		iniFile->WriteInteger("Machine Info", "Machine Mode", machineSetupData.MachineMode);
		iniFile->WriteInteger("Machine Info", "Machine Type", machineSetupData.MachineType);
		iniFile->WriteInteger("Power Info", "PC PowerMode", machineSetupData.PC_Power_Mode);

		iniFile->WriteInteger("LasercomplexerInfo", "Machine_Type",machineSetupData.LasercomplexerInfo.Machine_type);
		iniFile->WriteInteger("LasercomplexerInfo", "Laser_complexer_Enable",machineSetupData.LasercomplexerInfo.Laser_complexer_Enable);
		iniFile->WriteInteger("LasercomplexerInfo", "Laser_deley_time",machineSetupData.LasercomplexerInfo.Laser_deley_time);
		iniFile->WriteInteger("LasercomplexerInfo", "Laser_Trig_mode",machineSetupData.LasercomplexerInfo.Laser_Trig_mode);	

		if(ChangeLaserComplexValue)
		{
			PrevLaserComplexStatus = !machineSetupData.LasercomplexerInfo.Laser_complexer_Enable;
		}
		else
		{
			PrevLaserComplexStatus = machineSetupData.LasercomplexerInfo.Laser_complexer_Enable;
		}

		iniFile->WriteInteger("Ejector Info", "Defect Ejector Delay", machineSetupData.EjectorInfo.DefectEjectorDelay);
		iniFile->WriteInteger("Ejector Info", "UnIns Ejector Delay", machineSetupData.EjectorInfo.UnInsEjectorDelay);
		iniFile->WriteInteger("Ejector Info", "Good Ejector Delay", machineSetupData.EjectorInfo.GoodEjectorDelay);
		iniFile->WriteInteger("Ejector Info", "Defect Ejector Length", machineSetupData.EjectorInfo.DefectEjectorLength);
		iniFile->WriteInteger("Ejector Info", "UnIns Ejector Length", machineSetupData.EjectorInfo.UnInsEjectorLength);
		iniFile->WriteInteger("Ejector Info", "Good Ejector Length", machineSetupData.EjectorInfo.GoodEjectorLength);
		
		iniFile->WriteInteger("Sensor Info", "Sensor Interval A", machineSetupData.SensorIntervalA);
		iniFile->WriteInteger("Sensor Info", "Sensor Interval B", machineSetupData.SensorIntervalB);

		for (int captureIndex = 0; captureIndex < SYSTEM_MACHINE_CAPTURE_COUNT; captureIndex++)
		{
			iniFile->WriteInteger("Machine Capture Info", "Capture Delay " + IntToStr(captureIndex), machineSetupData.MachineCaptureInfo.CaptureDelay[captureIndex]);
			iniFile->WriteInteger("Machine Capture Info", "Illuminator Mask " + IntToStr(captureIndex), machineSetupData.MachineCaptureInfo.IlluminatorMask[captureIndex]);
			iniFile->WriteInteger("Machine Capture Info", "Illuminator Delay " + IntToStr(captureIndex), machineSetupData.MachineCaptureInfo.IlluminatorDelay[captureIndex]);
			iniFile->WriteInteger("Machine Capture Info", "Illuminator Time " + IntToStr(captureIndex), machineSetupData.MachineCaptureInfo.IlluminatorTime[captureIndex]);
			iniFile->WriteInteger("Machine Capture Info", "Camera Map " + IntToStr(captureIndex), machineSetupData.MachineCaptureInfo.CamMask[captureIndex]);
		}
		//        iniFile->WriteInteger("Machine Capture Info", "Capture Stable Delay", machineSetupData.MachineCaptureInfo.CaptureStableDelay);

		for (int sensorIndex = 0; sensorIndex < 2; sensorIndex++)
		{
			iniFile->WriteInteger("Machine Capture Info", "Sensor SPB Mask " + IntToStr(sensorIndex), machineSetupData.MachineCaptureInfo.SensorSPBMask[sensorIndex]);
		}



		iniFile->WriteInteger("Ejector Info", "Miseject Active", machineSetupData.EjectorInfo.MisejectActive);
		iniFile->WriteInteger("Ejector Info", "Miseject Active Delay", machineSetupData.EjectorInfo.MisejectActiveDelay);

		//sjm
		iniFile->WriteInteger("Ejector Info", "Special Inspection Active", machineSetupData.EjectorInfo.Special_InspectionActive);
		iniFile->WriteInteger("Ejector Info", "Blow Interval", machineSetupData.EjectorInfo.Blowinterval);
		iniFile->WriteInteger("Ejector Info", "Blow Start", machineSetupData.EjectorInfo.Blowstart);
		iniFile->WriteInteger("Ejector Info", "Blow Length", machineSetupData.EjectorInfo.Blowlength);
		iniFile->WriteInteger("Ejector Info", "Uninspection Active", machineSetupData.EjectorInfo.UninsBlowCheck);
		//cik add
		iniFile->WriteInteger("Ejector Info", "Ejector Wind Strength", machineSetupData.EjectorInfo.EjectorWindStrength);
		iniFile->WriteInteger("Ejector Info", "Ejector Default Mode", machineSetupData.EjectorInfo.EjectorDefaultMode);
		iniFile->WriteInteger("Ejector Info", "SpMode Good Tablet Collect Count 1", machineSetupData.EjectorInfo.SpModeGoodTabletCollectCount1);
		iniFile->WriteInteger("Ejector Info", "SpMode Good Tablet Collect Count 2", machineSetupData.EjectorInfo.SpModeGoodTabletCollectCount2);
		//한국콜마
		iniFile->WriteInteger("Ejector Info", "DistributorGoodTabletCount1", machineSetupData.EjectorInfo.DistributorGoodTabletCount1);
		iniFile->WriteInteger("Ejector Info", "DistributorGoodTabletCount2", machineSetupData.EjectorInfo.DistributorGoodTabletCount2);
		iniFile->WriteInteger("Ejector Info", "DistributorGoodTabletCount3", machineSetupData.EjectorInfo.DistributorGoodTabletCount3);

		//TPB Miseject
		iniFile->WriteInteger("Ejector Info", "TPB_MisejectActive", machineSetupData.EjectorInfo.TPB_MisejectActive);
		iniFile->WriteInteger("Ejector Info", "TPB_MisejectOpenDelay", machineSetupData.EjectorInfo.TPB_MisejectOpenDelay);
		iniFile->WriteInteger("Ejector Info", "TPB_MisejectOpenRunTime", machineSetupData.EjectorInfo.TPB_MisejectOpenRunTime);
		iniFile->WriteInteger("Ejector Info", "TPB_MisCmdValidCnt", machineSetupData.EjectorInfo.TPB_MisCmdValidCnt);
		iniFile->WriteInteger("Ejector Info", "IgnoreMultiMisejectAction", machineSetupData.EjectorInfo.IgnoreMultiMisejectAction);
		iniFile->WriteInteger("Ejector Info", "TPB_MisejectOperationMode", machineSetupData.EjectorInfo.TPB_MisejectOperationMode);


		iniFile->WriteInteger("Vibration Feeder Info", "Manual Mode Sensor Index", machineSetupData.VFInfo.ManualModeSensorIndex);
		iniFile->WriteInteger("Vibration Feeder Info", "Manual Mode Sensor Active Ratio", machineSetupData.VFInfo.ManualModeSensorActiveRatio);
		iniFile->WriteInteger("Vibration Feeder Info", "Empty Sensor Active Ratio", machineSetupData.VFInfo.EmptySensorActiveRatio);
		iniFile->WriteInteger("Vibration Feeder Info", "Full Sensor Active Ratio", machineSetupData.VFInfo.FullSensorActiveRatio);
		iniFile->WriteInteger("Vibration Feeder Info", "Start Speed", machineSetupData.VFInfo.StartSpeed);
		iniFile->WriteInteger("Vibration Feeder Info", "Max Speed Training Mode", machineSetupData.VFInfo.MaxSpeedTrainingMode);
		iniFile->WriteInteger("Vibration Feeder Info", "Manual Max Speed", machineSetupData.VFInfo.ManualMaxSpeed);
		iniFile->WriteInteger("Vibration Feeder Info", "Mechanical Min Speed", machineSetupData.VFInfo.MechanicalMinSpeed);
		iniFile->WriteInteger("Vibration Feeder Info", "Mechanical Max Speed", machineSetupData.VFInfo.MechanicalMaxSpeed);

		iniFile->WriteInteger("Vibration Feeder Info", "Feeder Alarm Delay Time", machineSetupData.VFInfo.FeederEmptyAlarmDelayTime);

		iniFile->WriteInteger("Interlock Info", "Door Enabled", machineSetupData.InterlockInfo.DoorInterlockEnabled);
		iniFile->WriteInteger("Interlock Info", "NC Interlock A Value", machineSetupData.InterlockInfo.NCInterlockAValue);

		iniFile->WriteInteger("Interlock Info", "ACdomesticMode", machineSetupData.InterlockInfo.ACdomesticMode);

		iniFile->WriteBool("Buzzer Info", "Buzzer Continuous On", (machineSetupData.BuzzerInfo.BuzzerContinuousOn != 0));
		iniFile->WriteInteger("Buzzer Info", "Buzzer On Time", machineSetupData.BuzzerInfo.BuzzerOnTime);

		for (int stepMotorIndex = 0; stepMotorIndex < MAX_STEP_MOTOR_COUNT; stepMotorIndex++)
		{
			iniFile->WriteFloat("NC Info", "NC Zero Pos " + IntToStr(stepMotorIndex + 1), machineSetupData.ZeroPositionValue[stepMotorIndex]);
		}

		iniFile->WriteInteger("LED Control Info", "Eye Protection Mode Enabled", machineSetupData.LEDControlInfo.EyeProtectionModeEnabled);
		iniFile->WriteInteger("LED Control Info", "Eye Protection LED On Time", machineSetupData.LEDControlInfo.LEDOnTime);
		iniFile->WriteInteger("LED Control Info", "Eye Protection LED Off Delay", machineSetupData.LEDControlInfo.LEDOffDelay);

		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			iniFile->WriteInteger("Servo " + IntToStr(motorIndex), "Base Speed", machineSetupData.ServoMotorData[motorIndex].BaseSpeed);
			iniFile->WriteInteger("Servo " + IntToStr(motorIndex), "Acc Time", machineSetupData.ServoMotorData[motorIndex].AccTime);
			iniFile->WriteInteger("Servo " + IntToStr(motorIndex), "Dec Time", machineSetupData.ServoMotorData[motorIndex].DecTime);
			iniFile->WriteBool("Servo " + IntToStr(motorIndex), "Direction", machineSetupData.ServoMotorData[motorIndex].Dir);
		}

		iniFile->WriteInteger("Alarm Level", "Pressure Alarm Level", machineSetupData.AlarmSetupInfo.PressureAlarmLevel);
		iniFile->WriteInteger("Alarm Level", "Vacuum Alarm Level 1", machineSetupData.AlarmSetupInfo.VacuumAlarmLevel1);
		iniFile->WriteInteger("Alarm Level", "Vacuum Alarm Level 2", machineSetupData.AlarmSetupInfo.VacuumAlarmLevel2);
		iniFile->WriteInteger("Alarm Level", "Temperature Alarm Level 1", machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel1);
		iniFile->WriteInteger("Alarm Level", "Temperature Alarm Level 2", machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel2);
		iniFile->WriteInteger("Alarm Level", "Temperature Alarm Level 3", machineSetupData.AlarmSetupInfo.TemperatureAlarmLevel3);

		iniFile->WriteInteger("Hopper Empty", "Enabled", machineSetupData.HopperEmptyEnable);

		// khd1994 HCB IP주소 및 Port처리
		iniFile->WriteString("HCB", "ServerIpAddr", machineSetupData.szHCB_IpAddr);
		iniFile->WriteInteger("HCB", "ServerPort", machineSetupData.nHCB_TcpPort);

		iniFile->WriteInteger("HCB", "CompanyID", machineSetupData.CompanyID);
		iniFile->WriteInteger("HCB", "BowlFeederSensorOption", machineSetupData.BowlFeederSensorOption);
		iniFile->WriteInteger("Safety", "SafetyCircuitMode", machineSetupData.SafetyCircuitMode);
		iniFile->WriteInteger("Disk", "StartDelay", machineSetupData.DiskStartDelay);
		iniFile->WriteInteger("Disk", "SucktionDisk Gear Ratio", machineSetupData.SuctionDiskGearRatio);
		iniFile->WriteInteger("Acrocia", "Machine1Special", machineSetupData.Qualis_Machine1_CutomOption);
		iniFile->WriteInteger("Simple Servo Speed", "Enabled", machineSetupData.SimpleSpeedControlOption);
		iniFile->WriteInteger("IPB Count", "IPB_BoardCount",machineSetupData.IPB_BoardCount); 
		iniFile->WriteInteger("Auto Demper", "Activated", machineSetupData.AutoDemper);
		iniFile->WriteInteger("Distributor", "In_SW_Time",machineSetupData.DistributorCtrl.InSigOffTimeLength);
		iniFile->WriteInteger("Distributor", "Out_SW_Time",machineSetupData.DistributorCtrl.OutSigOnTimeLength);
		iniFile->WriteInteger("Distributor", "Out_Signal_Start_Delay",machineSetupData.DistributorCtrl.OutSigDelayTime);
        iniFile->WriteInteger("Distributor", "Wait Change Barrel Time", machineSetupData.DistributorCtrl.WaitChangeBarrelTime);
		iniFile->WriteInteger("Inverter", "Type",machineSetupData.InverterType);

		delete iniFile;
	}
}
//---------------------------------------------------------------------------
bool __fastcall ReadCameraMapData(AnsiString fileName, TCameraMapInfo *cameraMapInfo)
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		for (int globalCamIndex = 0; globalCamIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCamIndex++)
		{
			cameraMapInfo[globalCamIndex].SPBIndex = iniFile->ReadInteger("Camera Map " + IntToStr(globalCamIndex + 1), "SPB Index", 0);
			cameraMapInfo[globalCamIndex].CamIndex = iniFile->ReadInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Cam Index", 0);
			cameraMapInfo[globalCamIndex].CameraInspectPosition = iniFile->ReadInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Inspect Position", 0);
		}
		delete iniFile;
	}
	else
	{
		for (int globalCamIndex = 0; globalCamIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCamIndex++)
		{
			cameraMapInfo[globalCamIndex].SPBIndex = 0;
			cameraMapInfo[globalCamIndex].CamIndex = 0;
			cameraMapInfo[globalCamIndex].CameraInspectPosition = 0;
		}
		returnValue = false;
	}


	return returnValue;



}
//---------------------------------------------------------------------------
bool __fastcall WriteCameraMapData(AnsiString fileName, TCameraMapInfo *cameraMapInfo)
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		for (int globalCamIndex = 0; globalCamIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCamIndex++)
		{
			iniFile->WriteInteger("Camera Map " + IntToStr(globalCamIndex + 1), "SPB Index", cameraMapInfo[globalCamIndex].SPBIndex);
			iniFile->WriteInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Cam Index", cameraMapInfo[globalCamIndex].CamIndex);
			iniFile->WriteInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Inspect Position", cameraMapInfo[globalCamIndex].CameraInspectPosition);
		}
		delete iniFile;
	}
	else
	{
		returnValue = false;
	}
	return returnValue;
}
//---------------------------------------------------------------------------
bool __fastcall ReadSPBSystemSetupData(AnsiString fileName, TSPBSystemSetupData *spbSystemSetupData,
	TCameraMapInfo *cameraMapInfo)
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
	AnsiString  sIpAddr;
	if (iniFile)
	{
		for (int spbIndex = 0; spbIndex < SYSTEM_SPB_MAX_COUNT; spbIndex++)
		{
			memset(&spbSystemSetupData[spbIndex], 0, sizeof(TSPBSystemSetupData));
			memcpy(spbSystemSetupData[spbIndex].CameraMapInfo, cameraMapInfo, SYSTEM_TOTAL_CAMERA_COUNT * sizeof(TCameraMapInfo));

			spbSystemSetupData[spbIndex].DefaultCPBProgramID = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
				"Default CPB Program ID", PID_CPB | ('0' << 8) | '0');

			for (int cpbIndex = 0; cpbIndex < SYSTEM_CPB_MAX_COUNT; cpbIndex++)
			{
				spbSystemSetupData[spbIndex].CPBEnabled[cpbIndex] = (iniFile->ReadBool("SPB " + IntToStr(spbIndex + 1),
					"CPB Enable " + IntToStr(cpbIndex + 1), false) ? 1 : 0);
				spbSystemSetupData[spbIndex].CPBSDRSizeType[cpbIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB SDR Size Type " + IntToStr(cpbIndex + 1), 0);
				spbSystemSetupData[spbIndex].CPBClockKind[cpbIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB Clock Kind " + IntToStr(cpbIndex + 1), 0);
				spbSystemSetupData[spbIndex].CameraDistributionIndex[cpbIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"Camera Distribution " + IntToStr(cpbIndex + 1), 0);
			}
			spbSystemSetupData[spbIndex].CamMask = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
				"Camera Mask", 0);			

      for (int camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
      {
        spbSystemSetupData[spbIndex].CameraKind[camIndex] = CAMERA_KIND_NONE;
        spbSystemSetupData[spbIndex].GlobalCameraIndex[camIndex] = 0;
        spbSystemSetupData[spbIndex].InspectPosition[camIndex] = CAMERA_POSITION_DISCONNECT;
      }

			for (int camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
			{
				spbSystemSetupData[spbIndex].CameraHardwarePosition[camIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"Camera Hardware Position " + IntToStr(camIndex + 1), 0);
				spbSystemSetupData[spbIndex].GlobalCameraIndex[camIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"Global Camera Index " + IntToStr(camIndex + 1), 0);

        if(spbSystemSetupData[spbIndex].CamMask & (0x1<<camIndex))
        {
          spbSystemSetupData[spbIndex].InspectPosition[camIndex] =
            cameraMapInfo[spbSystemSetupData[spbIndex].GlobalCameraIndex[camIndex]].CameraInspectPosition;

          if (spbSystemSetupData[spbIndex].InspectPosition[camIndex] != CAMERA_POSITION_3D)
          {
            spbSystemSetupData[spbIndex].CameraKind[camIndex] = CAMERA_KIND_NFA_2D;
          }
          else		// 3D camera
          {
            spbSystemSetupData[spbIndex].CameraKind[camIndex] = CAMERA_KIND_NFA_3D;
          }
        }
			}


			spbSystemSetupData[spbIndex].ImageTransferMethod = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1), "Image Transfer Method", SPB_IMAGE_TRANSFER_METHOD_CHECKSUM);
			spbSystemSetupData[spbIndex].CPBVersion = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1), "CPB Version", CPB_VERSION_04);
			spbSystemSetupData[spbIndex].MaxProcessingCoreCount = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1), "Max CPU Core Count", 32);
			// khd1994- TCP서버 주소 및 통신포트 정보읽어오기
			sIpAddr = "192.168.0." + IntToStr(11 + spbIndex);
			strcpy(spbSystemSetupData[spbIndex].szIpAddr, iniFile->ReadString("SPB " + IntToStr(spbIndex + 1), "ServerIpAddr", sIpAddr).c_str());
			spbSystemSetupData[spbIndex].nTcpPort = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1), "ServerPort", 7000);
			spbSystemSetupData[spbIndex].ThreeDCaptureMethod = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1), "ThreeD Capture Method", THREED_CAPTURE_DEFAULT_MODE);
			spbSystemSetupData[spbIndex].Laser_complexer_Enable = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1), "Laser_complexer_Enable", 0);
			spbSystemSetupData[spbIndex].CamBootEnabled = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1), "Boot_Enabled", 0);
			spbSystemSetupData[spbIndex].LaserPositionCalData[0] = iniFile->ReadFloat("SPB " + IntToStr(spbIndex + 1), "Laser X Pos : X CalData", 1);
			spbSystemSetupData[spbIndex].LaserPositionCalData[1] = iniFile->ReadFloat("SPB " + IntToStr(spbIndex + 1), "Laser X Pos : Y CalData", 0);
			spbSystemSetupData[spbIndex].LaserPositionCalData[2] = iniFile->ReadFloat("SPB " + IntToStr(spbIndex + 1), "Laser Y Pos : X CalData", 0);
			spbSystemSetupData[spbIndex].LaserPositionCalData[3] = iniFile->ReadFloat("SPB " + IntToStr(spbIndex + 1), "Laser Y Pos : Y CalData", 1);	
		}
		delete iniFile;
	}
	else
	{
		for (int spbIndex = 0; spbIndex < SYSTEM_SPB_MAX_COUNT; spbIndex++)
		{
			memset(&spbSystemSetupData[spbIndex], 0, sizeof(TSPBSystemSetupData));
			memcpy(spbSystemSetupData[spbIndex].CameraMapInfo, cameraMapInfo, SYSTEM_TOTAL_CAMERA_COUNT * sizeof(TCameraMapInfo));

			spbSystemSetupData[spbIndex].DefaultCPBProgramID = (PID_CPB | ('0' << 8) | '0');

			for (int cpbIndex = 0; cpbIndex < SYSTEM_CPB_MAX_COUNT; cpbIndex++)
			{
				spbSystemSetupData[spbIndex].CPBEnabled[cpbIndex] = 0;
				spbSystemSetupData[spbIndex].CPBSDRSizeType[cpbIndex] = 0;
				spbSystemSetupData[spbIndex].CPBClockKind[cpbIndex] = 0;
				spbSystemSetupData[spbIndex].CameraDistributionIndex[cpbIndex] = 0;
			}
			for (int camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
			{
				spbSystemSetupData[spbIndex].CameraHardwarePosition[camIndex] = 0;
				spbSystemSetupData[spbIndex].GlobalCameraIndex[camIndex] = 0;
				spbSystemSetupData[spbIndex].InspectPosition[camIndex] = 0;
				spbSystemSetupData[spbIndex].CameraKind[camIndex] = CAMERA_KIND_NFA_2D;
			}
			spbSystemSetupData[spbIndex].CamMask = 0;
			spbSystemSetupData[spbIndex].ImageTransferMethod = SPB_IMAGE_TRANSFER_METHOD_CHECKSUM;
			spbSystemSetupData[spbIndex].CPBVersion = CPB_VERSION_04;
			spbSystemSetupData[spbIndex].MaxProcessingCoreCount = 32;
			// khd1994- TCP서버 주소 및 통신포트 정보읽어오기
			sIpAddr = "192.168.0." + IntToStr(11 + spbIndex);
			strcpy(spbSystemSetupData[spbIndex].szIpAddr, sIpAddr.c_str());
			spbSystemSetupData[spbIndex].nTcpPort = 7000;
			spbSystemSetupData[spbIndex].ThreeDCaptureMethod = THREED_CAPTURE_DEFAULT_MODE;
			spbSystemSetupData[spbIndex].Laser_complexer_Enable  =0;
			spbSystemSetupData[spbIndex].CamBootEnabled = 0;
			spbSystemSetupData[spbIndex].LaserPositionCalData[0] = 1;
			spbSystemSetupData[spbIndex].LaserPositionCalData[1] = 0;
			spbSystemSetupData[spbIndex].LaserPositionCalData[2] = 0;
			spbSystemSetupData[spbIndex].LaserPositionCalData[3] = 1;
			

		}
		returnValue = false;
	}

	return returnValue;
}

//---------------------------------------------------------------------------
bool __fastcall WriteSPBSystemSetupData(AnsiString fileName, TSPBSystemSetupData *spbSystemSetupData)
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		for (int spbIndex = 0; spbIndex < SYSTEM_SPB_MAX_COUNT; spbIndex++)
		{
			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
				"Default CPB Program ID", spbSystemSetupData[spbIndex].DefaultCPBProgramID);

			for (int cpbIndex = 0; cpbIndex < SYSTEM_CPB_MAX_COUNT; cpbIndex++)
			{
				iniFile->WriteBool("SPB " + IntToStr(spbIndex + 1),
					"CPB Enable " + IntToStr(cpbIndex + 1), spbSystemSetupData[spbIndex].CPBEnabled[cpbIndex]);

				iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB SDR Size Type " + IntToStr(cpbIndex + 1), spbSystemSetupData[spbIndex].CPBSDRSizeType[cpbIndex]);

				iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB Clock Kind " + IntToStr(cpbIndex + 1), spbSystemSetupData[spbIndex].CPBClockKind[cpbIndex]);

				iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"Camera Distribution " + IntToStr(cpbIndex + 1), spbSystemSetupData[spbIndex].CameraDistributionIndex[cpbIndex]);
			}
			for (int camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
			{
				iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"Camera Hardware Position " + IntToStr(camIndex + 1), spbSystemSetupData[spbIndex].CameraHardwarePosition[camIndex]);

				iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"Global Camera Index " + IntToStr(camIndex + 1), spbSystemSetupData[spbIndex].GlobalCameraIndex[camIndex]);
			}
			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1), "Camera Mask", spbSystemSetupData[spbIndex].CamMask);
			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1), "Image Transfer Method", spbSystemSetupData[spbIndex].ImageTransferMethod);
			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1), "CPB Version", spbSystemSetupData[spbIndex].CPBVersion);

			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1), "Max CPU Core Count", spbSystemSetupData[spbIndex].MaxProcessingCoreCount);

			// khd1994 - IP주소 및 Port
			iniFile->WriteString("SPB " + IntToStr(spbIndex + 1), "ServerIpAddr", spbSystemSetupData[spbIndex].szIpAddr);
			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1), "ServerPort", spbSystemSetupData[spbIndex].nTcpPort);
			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1), "ThreeD Capture Method", spbSystemSetupData[spbIndex].ThreeDCaptureMethod);
			iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1), "Laser_complexer_Enable", spbSystemSetupData[spbIndex].Laser_complexer_Enable);
			iniFile->WriteInteger("SPB "  + IntToStr(spbIndex + 1), "Boot_Enabled", spbSystemSetupData[spbIndex].CamBootEnabled);
			iniFile->WriteFloat("SPB "  + IntToStr(spbIndex + 1), "Laser X Pos : X CalData", spbSystemSetupData[spbIndex].LaserPositionCalData[0]);
			iniFile->WriteFloat("SPB "  + IntToStr(spbIndex + 1), "Laser X Pos : Y CalData", spbSystemSetupData[spbIndex].LaserPositionCalData[1]);
			iniFile->WriteFloat("SPB "  + IntToStr(spbIndex + 1), "Laser Y Pos : X CalData", spbSystemSetupData[spbIndex].LaserPositionCalData[2]);
			iniFile->WriteFloat("SPB "  + IntToStr(spbIndex + 1), "Laser Y Pos : Y CalData", spbSystemSetupData[spbIndex].LaserPositionCalData[3]);
		}
		delete iniFile;
	}
	else
	{
		returnValue = false;
	}
	return returnValue;
}

//---------------------------------------------------------------------------
bool __fastcall ReadLightProductData(AnsiString fileName, TProductData &productData)
{
   if (!FileExists(fileName))
    {
		return false;
    }
    else
    {
		TIniFile *iniFile = new TIniFile(fileName);
		if (iniFile)
		{
			int majorVersion = iniFile->ReadInteger("Product Data Verion", "Major Version", 0);
			int minorVersion = iniFile->ReadInteger("Product Data Verion", "Minor Version", 0);
			// compare with current version
			if (majorVersion != CURRENT_PRODUCT_DATA_MAJOR_VERSION || minorVersion != CURRENT_PRODUCT_DATA_MINOR_VERSION)
			{
				return false;
			}

			productData.ProductName = iniFile->ReadString("Product Info", "Product Name", "");
			productData.TabletType = iniFile->ReadInteger("Tablet Info", "Tablet Type", 0);
			productData.TabletShape = iniFile->ReadInteger("Tablet Info", "Tablet Shape", 0);
			productData.TabletLength = iniFile->ReadFloat("Tablet Info", "Tablet Length", 0);
      productData.LastInspectionTime.Val = iniFile->ReadFloat("Tablet Info", "Last Inspection Time", 0);
      productData.SubSamplingMode =iniFile->ReadInteger("SubSamplingMode", "Mode", 0);

			delete iniFile;
		}
		else
		{
			return false;
    }
	}
    return true;
}

bool __fastcall ReadProductData(AnsiString fileName, TProductData &productData,
	TMachineParams &machineParams, TMachineSetupData &machineSetupData)
{
	if (!FileExists(fileName))
	{
		return false;
	}
	else
	{
		TIniFile *iniFile = new TIniFile(fileName);
		if (iniFile)
		{
			int majorVersion = iniFile->ReadInteger("Product Data Verion", "Major Version", 0);
			int minorVersion = iniFile->ReadInteger("Product Data Verion", "Minor Version", 0);
			// compare with current version
			if (majorVersion != CURRENT_PRODUCT_DATA_MAJOR_VERSION || minorVersion != CURRENT_PRODUCT_DATA_MINOR_VERSION)
			{
				return false;
			}

			productData.ProductCode = iniFile->ReadString("Product Info", "Product Code", "");
			productData.ProductName = iniFile->ReadString("Product Info", "Product Name", "");
			productData.TabletType = iniFile->ReadInteger("Tablet Info", "Tablet Type", 0);
			productData.TabletShape = iniFile->ReadInteger("Tablet Info", "Tablet Shape", 0);
			productData.TabletLength = iniFile->ReadFloat("Tablet Info", "Tablet Length", 0);
			productData.TabletWidth = iniFile->ReadFloat("Tablet Info", "Tablet Width", 0);
			productData.TabletThick = iniFile->ReadFloat("Tablet Info", "Tablet Thick", 0);
			productData.TabletSideThick = iniFile->ReadFloat("Tablet Info", "Tablet Side Thick", 0);
			productData.EngraveType = iniFile->ReadInteger("Engrave Info", "Engrave Type", 0);
			productData.EngravePos = iniFile->ReadInteger("Engrave Info", "Engrave Pos", 0);
			productData.PlateTablet = iniFile->ReadBool("Tablet Info", "Plate Tablet", false);
      productData.PrintBrightness = iniFile->ReadInteger("Tablet Info", "Print Brightness", 0);
			productData.Arrange = iniFile->ReadBool("Tablet Info", "Arrange", true);
			productData.SymmetricLineCount = iniFile->ReadInteger("Tablet Info", "Symmetric Line Count", 1);
			productData.StudiedSensor1Length = iniFile->ReadInteger("Machine Parameter", "Studied Sensor 1 Length", 1000);
			productData.StudiedSensor2Length = iniFile->ReadInteger("Machine Parameter", "Studied Sensor 2 Length", 1000);
			//sjm add 깨진정제
			productData.StudiedSensor3Length = iniFile->ReadInteger("Machine Parameter", "Studied Sensor 3 Length", 1000);

			productData.StudiedSensorIntervalA = iniFile->ReadInteger("Machine Parameter", "Studied Sensor Interval A", machineSetupData.SensorIntervalA);
			productData.StudiedSensorIntervalB = iniFile->ReadInteger("Machine Parameter", "Studied Sensor Interval B", machineSetupData.SensorIntervalB);

			productData.MachineRunOption.applyEjectorDelay = iniFile->ReadInteger("Machine Parameter", "Apply Ejector Delay", 0);
			productData.MachineRunOption.adjustUnInsDelay = iniFile->ReadInteger("Machine Parameter", "UnInspect Ejector Delay", machineSetupData.EjectorInfo.UnInsEjectorDelay);
			productData.MachineRunOption.adjustDefectDelay = iniFile->ReadInteger("Machine Parameter", "Defect Ejector Delay", machineSetupData.EjectorInfo.DefectEjectorDelay);
            //Q사
            productData.MachineRunOption.adjustGoodDelay = iniFile->ReadInteger("Machine Parameter", "Good Ejector Delay", machineSetupData.EjectorInfo.GoodEjectorDelay);
			productData.MachineRunOption.adjustEjectorWindStrength = iniFile->ReadInteger("Machine Parameter", "Ejector Wind Strength", machineSetupData.EjectorInfo.EjectorWindStrength);

			productData.LastInspectionTime.Val = iniFile->ReadFloat("Tablet Info", "Last Inspection Time", 0);
			productData.TabletLayerCount = iniFile->ReadInteger("Tablet Info", "Tablet Layer Count", 1);

      productData.DivisionLineInfo = iniFile->ReadInteger("Tablet Info", "Tablet Division Line Info", DIVISION_LINE_NONE);

			for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
			{
				productData.BoundaryLeft[globalCameraIndex] = iniFile->ReadInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Left", 0);
				productData.BoundaryTop[globalCameraIndex] = iniFile->ReadInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Top", 0);
				productData.BoundaryRight[globalCameraIndex] = iniFile->ReadInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Right", SYSTEM_CAMERA_WIDTH);
				productData.BoundaryBottom[globalCameraIndex] = iniFile->ReadInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Bottom", SYSTEM_CAMERA_HEIGHT);
				productData.ShutterSpeed[globalCameraIndex] = iniFile->ReadInteger("Shutter Speed", IntToStr(globalCameraIndex + 1), 10);
				productData.ThresholdFor3D[globalCameraIndex] = iniFile->ReadInteger("Threshold For 3D", IntToStr(globalCameraIndex + 1), 10);
        productData.DigitalGainV[globalCameraIndex] = iniFile->ReadInteger("Digital Gain", IntToStr(globalCameraIndex + 1), 1);

        productData.StudyShutterSpeed[globalCameraIndex] = iniFile->ReadInteger("Study Camera Shutter Speed", IntToStr(globalCameraIndex + 1), 0);
				productData.StudyGainV[globalCameraIndex] = iniFile->ReadInteger("Study Camera Gain", IntToStr(globalCameraIndex + 1), 0);
			}

			productData.ProcessingStep = iniFile->ReadInteger("Processing Info", "Processing Step", TABLET_PROCESSING_STEP_CALIBRATION_REQUIRED);
			productData.TabletColorCode = iniFile->ReadString("Tablet Info", "Tablet Color Code", "");
			productData.PrintColorCode = iniFile->ReadString("Tablet Info", "Print Color Code", "");

			// read motor params
			int msTabletTypeIndex = 0, msTabletShapeIndex = 0;

			msTabletTypeIndex = GetMSTabletTypeIndex(productData.TabletType);
			msTabletShapeIndex = GetMSTabletShapeIndex(productData.TabletShape);

			for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
			{
				for (int speedIndex = 0; speedIndex < MOTOR_SPEED_STEP_COUNT_FOR_PRODUCT; speedIndex++)
				{
					productData.MotorSpeedList[motorIndex][speedIndex] = iniFile->ReadInteger("Motor " + IntToStr(motorIndex + 1) + " Speed", IntToStr(speedIndex + 1),
						machineParams.MotorSpeedList[msTabletTypeIndex][msTabletShapeIndex][motorIndex][speedIndex]);
            
          if(motorIndex == 0 || motorIndex == 1)
          {
            productData.SimpleMotorSpeedList[motorIndex][speedIndex] = iniFile->ReadInteger("Motor " + IntToStr(motorIndex + 1) + " Speed", "SimpleSpeed"+IntToStr(speedIndex + 1),3);
          }
				}
			}

			/// add khs studyspeed
			int StdSpeedIndex = 0;
			int StdMSIndex = 7;
			int motorIndex;
			for (motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
			{
				productData.StudyMotorSpeedList[motorIndex][StdSpeedIndex] = iniFile->ReadInteger("Motor " + IntToStr(motorIndex + 1) + " Study Speed", IntToStr(StdSpeedIndex + 1),
        machineParams.MotorSpeedList[StdMSIndex][_STUDY_MS_SHAPE_INDEX][motorIndex][StdSpeedIndex]);

				if (MachineSetupData.ServoMotorData[motorIndex].BaseSpeed * 100 / productData.StudyMotorSpeedList[motorIndex][StdSpeedIndex] < 10)
				{
					if (motorIndex == SD1_MOTOR_INDEX || motorIndex == SD2_MOTOR_INDEX || motorIndex == BF_ID_MOTOR_INDEX)
					{
						productData.StudyMotorSpeedList[motorIndex][StdSpeedIndex] = MachineSetupData.ServoMotorData[motorIndex].BaseSpeed * 100 / 100;
					}
					else
					{
						productData.StudyMotorSpeedList[motorIndex][StdSpeedIndex] = MachineSetupData.ServoMotorData[motorIndex].BaseSpeed * 100 / 50;
					}
				}

        if(motorIndex == 0 || motorIndex == 1)
        {
          productData.SimpleStudyMotorSpeedList[motorIndex][StdSpeedIndex] = iniFile->ReadInteger("Motor " + IntToStr(motorIndex + 1) + "Study Speed", "SimpleSpeed"+IntToStr(StdSpeedIndex + 1),3);
        }
			}

			for (int layerIndex = 0; layerIndex < MAX_TABLET_LAYER_COUNT; layerIndex++)
			{
				productData.MultiLayeredTabletColor[layerIndex] = iniFile->ReadInteger("Tablet Color", IntToStr(layerIndex + 1), clWhite);
			}

			productData.ProductionCount = iniFile->ReadInteger("Production Info", "Production Count", 0);

			//productData.MachineRunOption.FullSensorIndex = iniFile->ReadInteger("Machine Parameter", "Full Sensor Index", 1);
			//productData.MachineRunOption.EmptySensorIndex = iniFile->ReadInteger("Machine Parameter", "Empty Sensor Index",  0);
			productData.MachineRunOption.MaxSpeedTrainingMode = iniFile->ReadInteger("Machine Parameter", "Max Speed Training Mode", MAX_SPEED_TRAINING_MODE_AUTO);
			productData.MachineRunOption.ManualMaxSpeed = iniFile->ReadInteger("Machine Parameter", "Manual Max Speed", 100);
			productData.MachineRunOption.ManualModeSensorIndex = iniFile->ReadInteger("Machine Parameter", "Manual Mode Index", machineSetupData.VFInfo.ManualModeSensorIndex);
			productData.MachineRunOption.ManualModeSensorActiveRatio = iniFile->ReadInteger("Machine Parameter", "Manual Mode Sensor Active Ratio", machineSetupData.VFInfo.ManualModeSensorActiveRatio);
			productData.MachineRunOption.ManualLimitSpeed = iniFile->ReadInteger("Machine Parameter", "Manual Limit Speed", 60);
			productData.MachineRunOption.ManualModeLimitSensorIndex = iniFile->ReadInteger("Machine Parameter", "Manual Mode Limit Index", machineSetupData.VFInfo.ManualModeLimitSensorIndex);
			productData.MachineRunOption.ManualModeLimitSensorActiveRatio = iniFile->ReadInteger("Machine Parameter", "Manual Mode Limit Sensor Active Ratio", machineSetupData.VFInfo.ManualModeLimitSensorActiveRatio);
			productData.MachineRunOption.EmptySensorActiveRatio = iniFile->ReadInteger("Machine Parameter", "Empty Sensor Active Ratio", 50);
			productData.MachineRunOption.FullSensorActiveRatio = iniFile->ReadInteger("Machine Parameter", "Full Sensor Active Ratio", 50);
			productData.MachineRunOption.StartSpeed = iniFile->ReadInteger("Machine Parameter", "Start Speed", 40);
			productData.MachineRunOption.SuctionDisk1InverterSpeed = iniFile->ReadInteger("Machine Parameter", "Suction Disk 1 Inverter Speed", 255);
			productData.MachineRunOption.SuctionDisk2InverterSpeed = iniFile->ReadInteger("Machine Parameter", "Suction Disk 2 Inverter Speed", 255);
			productData.MachineRunOption.AirKnifeSpeed = iniFile->ReadInteger("Machine Parameter", "Air Knife Speed", 2);

			productData.RotatingGuideKind = iniFile->ReadInteger("Change Part", "Rotating Guide Kind", GetDefaultGuideKind(0, productData.TabletWidth));
			productData.FixedGuideKind = iniFile->ReadInteger("Change Part", "Fixed Guide Kind", GetDefaultGuideKind(1, productData.TabletWidth));
			productData.VerticalGate2Kind = iniFile->ReadInteger("Change Part", "Vertical Gate 2 Kind", GetDefaultVGateKind(1, productData.TabletWidth));
			GetDefaultNCPosition(productData, productData.NCMotorPos, machineSetupData.InterlockInfo.NCInterlockAValue / 100.0 -
				machineSetupData.ZeroPositionValue[3] + machineSetupData.ZeroPositionValue[0]);
			productData.NCMotorPos[0] = iniFile->ReadFloat("NC Encoder Position", "Motor 1 Pos", productData.NCMotorPos[0]);
			productData.NCMotorPos[1] = iniFile->ReadFloat("NC Encoder Position", "Motor 2 Pos", productData.NCMotorPos[1]);
			productData.NCMotorPos[2] = iniFile->ReadFloat("NC Encoder Position", "Motor 3 Pos", productData.NCMotorPos[2]);
			productData.NCMotorPos[3] = iniFile->ReadFloat("NC Encoder Position", "Motor 4 Pos", productData.NCMotorPos[3]);
			productData.NCMotorPos[4] = iniFile->ReadFloat("NC Encoder Position", "Motor 5 Pos", productData.NCMotorPos[4]);
 
			productData.LampKind = iniFile->ReadInteger("Tablet Info", "Lamp Kind", MACHINE_LAMP_KIND_NORMAL_TABLET);

			productData.MachineRunOption.EnabledSensorType = iniFile->ReadInteger("Enabled Sensor Type", "Sensor Index", 0); // 0 -> Sensor out A, 1 -> Sensor out B

			productData.MarvelingTabletSW = iniFile->ReadInteger("Special Tablet", "Marveling Tablet", 0); // 0 -> none, 1 -> ok
      		productData.FatTabletCapture = iniFile->ReadInteger("Special Tablet", "Fat Tablet Capture", 0); // 0 -> none, 1 -> ok
      		productData.CurvedSurfaceTabletSW = iniFile->ReadInteger("Special Tablet", "Curved Surface Tablet", 0); // 0 -> none, 1 -> ok

			for (int i = 0; i < 6; i++)
			{
				productData.SpecialInsCount[i] = iniFile->ReadInteger("Special Tablet", "DaeHwa SpecialCount" + IntToStr(i + 1), productData.SpecialInsCount[i]);
			}

      productData.SubSamplingMode = iniFile->ReadInteger("SubSamplingMode", "Mode", 0);

      productData.ExposureTime3D[0] =  iniFile->ReadInteger("CameraParam3D_1", "ExposureTime" , -1);
      productData.AnalogGain3D[0] =iniFile->ReadInteger("CameraParam3D_1", "AnalogGain" , -1);

      productData.ExposureTime3D[1] =iniFile->ReadInteger("CameraParam3D_2", "ExposureTime" , -1);
      productData.AnalogGain3D[1] =iniFile->ReadInteger("CameraParam3D_2", "AnalogGain" ,-1);

      productData.DischargeCountSetValue = iniFile->ReadInteger("DischargeCountSetValue", "DischargeCountSetValue" , 50000);
	    productData.RecipeName = iniFile->ReadString("Product Info", "Laser Recipe Name", "");
      productData.LastDischargeCountSetValue = iniFile->ReadInteger("DischargeCountSetValue", "LastDischargeCountSetValue" , 50000);
      productData.DischargeCount = iniFile->ReadInteger("DischargeCount", "DischargeCount" ,0);
      productData.MisejectActiveLimitCount = iniFile->ReadInteger("MisejectActive", "MisejectActiveLimitCount" ,10);

      productData.Disk1ThreeDImageCenterXForLaser = iniFile->ReadInteger("ThreeD Image X Position Information", "Disk1", 0);
      productData.Disk1ThreeDImageCenterYForLaser = iniFile->ReadInteger("ThreeD Image Y Position Information", "Disk1", 0);
      productData.Disk2ThreeDImageCenterXForLaser = iniFile->ReadInteger("ThreeD Image X Position Information", "Disk2", 0);
      productData.Disk2ThreeDImageCenterYForLaser = iniFile->ReadInteger("ThreeD Image Y Position Information", "Disk2", 0);

      productData.Disk1ThreeDImageLengthForLaser = iniFile->ReadInteger("ThreeD Image Length Information", "Disk1", 0);
      productData.Disk2ThreeDImageLengthForLaser = iniFile->ReadInteger("ThreeD Image Length Information", "Disk2", 0);

      productData.SpecialInsCount[0] = iniFile->ReadInteger("Distributor Setup", "Distributor Good Tablet Count", 0);
      productData.SpecialInsCount[1] = iniFile->ReadInteger("Distributor Setup", "Distributor Barrel", 0);
      productData.SpecialInsCount[2] = iniFile->ReadInteger("Distributor Setup", "Distributor Continue Inspection", 0);
                
			delete iniFile;
		}
		else
		{
			return false;
		}
	}
	return true;
}
//---------------------------------------------------------------------------
bool __fastcall WriteProductData(AnsiString fileName, TProductData &productData)
{
	TIniFile *iniFile = new TIniFile(fileName);

	if (iniFile)
	{
		// check revision
		iniFile->WriteInteger("Product Data Verion", "Major Version", CURRENT_PRODUCT_DATA_MAJOR_VERSION);
		iniFile->WriteInteger("Product Data Verion", "Minor Version", CURRENT_PRODUCT_DATA_MINOR_VERSION);

		iniFile->WriteString("Product Info", "Product Code", productData.ProductCode);
		iniFile->WriteString("Product Info", "Product Name", productData.ProductName);
		iniFile->WriteInteger("Tablet Info", "Tablet Type", productData.TabletType);
		iniFile->WriteInteger("Tablet Info", "Tablet Shape", productData.TabletShape);
		iniFile->WriteFloat("Tablet Info", "Tablet Length", productData.TabletLength);
		iniFile->WriteFloat("Tablet Info", "Tablet Width", productData.TabletWidth);
		iniFile->WriteFloat("Tablet Info", "Tablet Thick", productData.TabletThick);
		iniFile->WriteFloat("Tablet Info", "Tablet Side Thick", productData.TabletSideThick);
		iniFile->WriteInteger("Engrave Info", "Engrave Type", productData.EngraveType);
		iniFile->WriteInteger("Engrave Info", "Engrave Pos", productData.EngravePos);
		iniFile->WriteBool("Tablet Info", "Plate Tablet", productData.PlateTablet);
		iniFile->WriteBool("Tablet Info", "Arrange", productData.Arrange);
		iniFile->WriteInteger("Tablet Info", "Symmetric Line Count", productData.SymmetricLineCount);

		iniFile->WriteInteger("Processing Info", "Processing Step", productData.ProcessingStep);
		iniFile->WriteString("Tablet Info", "Tablet Color Code", productData.TabletColorCode);
		iniFile->WriteString("Tablet Info", "Print Color Code", productData.PrintColorCode);
    iniFile->WriteInteger("Tablet Info", "Print Brightness", productData.PrintBrightness);

		//		iniFile->WriteInteger("Tablet Info", "Tablet Size", productData.TabletSize);
		iniFile->WriteFloat("Tablet Info", "Last Inspection Time", productData.LastInspectionTime.Val);

		iniFile->WriteInteger("Tablet Info", "Tablet Layer Count", productData.TabletLayerCount);

    iniFile->WriteInteger("Tablet Info", "Tablet Division Line Info", productData.DivisionLineInfo);

		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			iniFile->WriteInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Left", productData.BoundaryLeft[globalCameraIndex]);
			iniFile->WriteInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Top", productData.BoundaryTop[globalCameraIndex]);
			iniFile->WriteInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Right", productData.BoundaryRight[globalCameraIndex]);
			iniFile->WriteInteger("Boundary of Camera " + IntToStr(globalCameraIndex + 1), "Bottom", productData.BoundaryBottom[globalCameraIndex]);
			iniFile->WriteInteger("Shutter Speed", IntToStr(globalCameraIndex + 1), productData.ShutterSpeed[globalCameraIndex]);
			iniFile->WriteInteger("Threshold For 3D", IntToStr(globalCameraIndex + 1), productData.ThresholdFor3D[globalCameraIndex]);
      iniFile->WriteInteger("Digital Gain", IntToStr(globalCameraIndex + 1), productData.DigitalGainV[globalCameraIndex]);

      iniFile->WriteInteger("Study Camera Shutter Speed", IntToStr(globalCameraIndex + 1), productData.StudyShutterSpeed[globalCameraIndex]);
      iniFile->WriteInteger("Study Camera Gain", IntToStr(globalCameraIndex + 1), productData.StudyGainV[globalCameraIndex]);
		}


		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			for (int speedIndex = 0; speedIndex < MOTOR_SPEED_STEP_COUNT_FOR_PRODUCT; speedIndex++)
			{
				iniFile->WriteInteger("Motor " + IntToStr(motorIndex + 1) + " Speed", IntToStr(speedIndex + 1), productData.MotorSpeedList[motorIndex][speedIndex]);
        if(motorIndex == 0 || motorIndex == 1)
        {
          iniFile->WriteInteger("Motor " + IntToStr(motorIndex + 1) + " Speed", "SimpleSpeed"+IntToStr(speedIndex + 1) , productData.SimpleMotorSpeedList[motorIndex][speedIndex]);
        }
			}

		}

		/// add khs studyspeed
		int StdSpeedIndex = 0;
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			iniFile->WriteInteger("Motor " + IntToStr(motorIndex + 1) + " Study Speed", IntToStr(StdSpeedIndex + 1), productData.StudyMotorSpeedList[motorIndex][StdSpeedIndex]);
      if(motorIndex == 0 || motorIndex == 1)
      {
        iniFile->WriteInteger("Motor " + IntToStr(motorIndex + 1) + " Study Speed", "SimpleSpeed"+IntToStr(StdSpeedIndex + 1) , productData.SimpleStudyMotorSpeedList[motorIndex][StdSpeedIndex]);
      }
		}

		for (int layerIndex = 0; layerIndex < MAX_TABLET_LAYER_COUNT; layerIndex++)
		{
			iniFile->WriteInteger("Tablet Color", IntToStr(layerIndex + 1), productData.MultiLayeredTabletColor[layerIndex]);
		}

		iniFile->WriteInteger("Production Info", "Production Count", productData.ProductionCount);

		iniFile->WriteInteger("Machine Parameter", "Max Speed Training Mode", productData.MachineRunOption.MaxSpeedTrainingMode);
		iniFile->WriteInteger("Machine Parameter", "Manual Max Speed", productData.MachineRunOption.ManualMaxSpeed);
		iniFile->WriteInteger("Machine Parameter", "Manual Mode Index", productData.MachineRunOption.ManualModeSensorIndex);
		iniFile->WriteInteger("Machine Parameter", "Manual Mode Sensor Active Ratio", productData.MachineRunOption.ManualModeSensorActiveRatio);
		iniFile->WriteInteger("Machine Parameter", "Manual Limit Speed", productData.MachineRunOption.ManualLimitSpeed);
		iniFile->WriteInteger("Machine Parameter", "Manual Mode Limit Index", productData.MachineRunOption.ManualModeLimitSensorIndex);
		iniFile->WriteInteger("Machine Parameter", "Manual Mode Limit Sensor Active Ratio", productData.MachineRunOption.ManualModeLimitSensorActiveRatio);

		//		iniFile->WriteInteger("Machine Parameter", "Empty Sensor Index", productData.MachineRunOption.EmptySensorIndex);
		iniFile->WriteInteger("Machine Parameter", "Empty Sensor Active Ratio", productData.MachineRunOption.EmptySensorActiveRatio);
		//		iniFile->WriteInteger("Machine Parameter", "Full Sensor Index", productData.MachineRunOption.FullSensorIndex);
		iniFile->WriteInteger("Machine Parameter", "Full Sensor Active Ratio", productData.MachineRunOption.FullSensorActiveRatio);
		iniFile->WriteInteger("Machine Parameter", "Start Speed", productData.MachineRunOption.StartSpeed);
		iniFile->WriteInteger("Machine Parameter", "Suction Disk 1 Inverter Speed", productData.MachineRunOption.SuctionDisk1InverterSpeed);
		iniFile->WriteInteger("Machine Parameter", "Suction Disk 2 Inverter Speed", productData.MachineRunOption.SuctionDisk2InverterSpeed);
		iniFile->WriteInteger("Machine Parameter", "Air Knife Speed", productData.MachineRunOption.AirKnifeSpeed);

		iniFile->WriteInteger("Machine Parameter", "Studied Sensor 1 Length", productData.StudiedSensor1Length);
		iniFile->WriteInteger("Machine Parameter", "Studied Sensor 2 Length", productData.StudiedSensor2Length);
		//sjm add 깨진정제
		iniFile->WriteInteger("Machine Parameter", "Studied Sensor 3 Length", productData.StudiedSensor3Length);
		//ShowMessage("WriteProductData");
	//ShowMessage(productData.StudiedSensor3Length);

		iniFile->WriteInteger("Machine Parameter", "Studied Sensor Interval A", productData.StudiedSensorIntervalA);
		iniFile->WriteInteger("Machine Parameter", "Studied Sensor Interval B", productData.StudiedSensorIntervalB);

		iniFile->WriteInteger("Machine Parameter", "Apply Ejector Delay", productData.MachineRunOption.applyEjectorDelay);
		iniFile->WriteInteger("Machine Parameter", "UnInspect Ejector Delay", productData.MachineRunOption.adjustUnInsDelay);
		iniFile->WriteInteger("Machine Parameter", "Defect Ejector Delay", productData.MachineRunOption.adjustDefectDelay);
		iniFile->WriteInteger("Machine Parameter", "Ejector Wind Strength", productData.MachineRunOption.adjustEjectorWindStrength);

		iniFile->WriteInteger("Change Part", "Rotating Guide Kind", productData.RotatingGuideKind);
		iniFile->WriteInteger("Change Part", "Fixed Guide Kind", productData.FixedGuideKind);
		iniFile->WriteInteger("Change Part", "Vertical Gate 2 Kind", productData.VerticalGate2Kind);
		iniFile->WriteFloat("NC Encoder Position", "Motor 1 Pos", productData.NCMotorPos[0]);
		iniFile->WriteFloat("NC Encoder Position", "Motor 2 Pos", productData.NCMotorPos[1]);
		iniFile->WriteFloat("NC Encoder Position", "Motor 3 Pos", productData.NCMotorPos[2]);
		iniFile->WriteFloat("NC Encoder Position", "Motor 4 Pos", productData.NCMotorPos[3]);
		iniFile->WriteFloat("NC Encoder Position", "Motor 5 Pos", productData.NCMotorPos[4]);

		iniFile->WriteInteger("Tablet Info", "Lamp Kind", productData.LampKind);

		iniFile->WriteInteger("Enabled Sensor Type", "Sensor Index", productData.MachineRunOption.EnabledSensorType); // 0 -> Sensor out A, 1 -> Sensor out B

		iniFile->WriteInteger("Special Tablet", "Marveling Tablet", productData.MarvelingTabletSW); // 0 -> none, 1 -> ok
        iniFile->WriteInteger("Special Tablet", "Fat Tablet Capture", productData.FatTabletCapture); // 0 -> none, 1 -> ok
        iniFile->WriteInteger("Special Tablet", "Curved Surface Tablet", productData.CurvedSurfaceTabletSW); // 0 -> none, 1 -> ok

		//#ifdef DAEHWAPROGRAM
		for (int i = 0; i < 6; i++)
		{
			iniFile->WriteInteger("Special Tablet", "DaeHwa SpecialCount" + IntToStr(i + 1), productData.SpecialInsCount[i]);
		}
		//#endif
    iniFile->WriteInteger("SubSamplingMode", "Mode" , productData.SubSamplingMode);

    iniFile->WriteInteger("CameraParam3D_1", "ExposureTime" , productData.ExposureTime3D[0]);
    iniFile->WriteInteger("CameraParam3D_1", "AnalogGain" , productData.AnalogGain3D[0]);

    iniFile->WriteInteger("CameraParam3D_2", "ExposureTime" , productData.ExposureTime3D[1]);
    iniFile->WriteInteger("CameraParam3D_2", "AnalogGain" , productData.AnalogGain3D[1]);
    iniFile->WriteInteger("DischargeCountSetValue", "DischargeCountSetValue" , productData.DischargeCountSetValue);
    iniFile->WriteString("Product Info", "Laser Recipe Name", productData.RecipeName);
    iniFile->WriteInteger("DischargeCountSetValue", "LastDischargeCountSetValue" , productData.LastDischargeCountSetValue);
    iniFile->WriteInteger("DischargeCount", "DischargeCount" ,productData.DischargeCount);
    iniFile->WriteInteger("MisejectActive", "MisejectActiveLimitCount" ,productData.MisejectActiveLimitCount);

    iniFile->WriteInteger("ThreeD Image X Position Information", "Disk1", productData.Disk1ThreeDImageCenterXForLaser);
    iniFile->WriteInteger("ThreeD Image Y Position Information", "Disk1", productData.Disk1ThreeDImageCenterYForLaser);
    iniFile->WriteInteger("ThreeD Image X Position Information", "Disk2", productData.Disk2ThreeDImageCenterXForLaser);
    iniFile->WriteInteger("ThreeD Image Y Position Information", "Disk2", productData.Disk2ThreeDImageCenterYForLaser); 

    iniFile->WriteInteger("ThreeD Image Length Information", "Disk1", productData.Disk1ThreeDImageLengthForLaser);
    iniFile->WriteInteger("ThreeD Image Length Information", "Disk2", productData.Disk2ThreeDImageLengthForLaser);

    iniFile->WriteInteger("Distributor Setup", "Distributor Good Tablet Count", productData.SpecialInsCount[0]);
    iniFile->WriteInteger("Distributor Setup", "Distributor Barrel", productData.SpecialInsCount[1]); 
    iniFile->WriteInteger("Distributor Setup", "Distributor Continue Inspection", productData.SpecialInsCount[2]); 

		delete iniFile;
		return true;
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
/*
__fastcall TSystemInfor::TSystemInfor()
{
	SpeedIndex = 0;
}
//---------------------------------------------------------------------------
bool __fastcall TSystemInfor::LoadData(AnsiString fileName)
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
		if (iniFile)
		{
				for (int spbIndex = 0; spbIndex < SYSTEM_SPB_MAX_COUNT; spbIndex++)
				{
					SPBInfo[spbIndex].DefaultCPBProgramID = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
						"Default CPB Program ID", PID_CPB | ('0' << 8) | '0');

					for (int cpbIndex = 0; cpbIndex < SYSTEM_CPB_MAX_COUNT; cpbIndex++)
						{
								SPBInfo[spbIndex].CPBEnabled[cpbIndex] = iniFile->ReadBool("SPB " + IntToStr(spbIndex + 1),
									"CPB Enable " + IntToStr(cpbIndex + 1), false);
								SPBInfo[spbIndex].CPBSDRSizeType[cpbIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB SDR Size Type " + IntToStr(cpbIndex + 1), 0);
				SPBInfo[spbIndex].CPBClockKind[cpbIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB Clock Kind " + IntToStr(cpbIndex + 1), 0);
				SPBInfo[spbIndex].CameraDistribution[cpbIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
									"Camera Distribution " + IntToStr(cpbIndex + 1), 0);
						}
					for (int camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
					{
						SPBInfo[spbIndex].CameraHardwarePosition[camIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
									"Camera Hardware Position " + IntToStr(camIndex + 1), 0);
						SPBInfo[spbIndex].ShutterSpeed[camIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
					"Shutter Speed " + IntToStr(camIndex + 1), 100);
						SPBInfo[spbIndex].GlobalCameraIndex[camIndex] = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
									"Global Camera Index " + IntToStr(camIndex + 1), 0);
					}
						SPBInfo[spbIndex].CamMask = iniFile->ReadInteger("SPB " + IntToStr(spbIndex + 1),
							"Camera Mask", 0);
				}

				for (int globalCamIndex = 0; globalCamIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCamIndex++)
				{
			CameraMapInfo[globalCamIndex].SPBIndex = iniFile->ReadInteger("Camera Map " + IntToStr(globalCamIndex + 1), "SPB Index", 0);
						CameraMapInfo[globalCamIndex].CamIndex = iniFile->ReadInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Cam Index", 0);
						CameraMapInfo[globalCamIndex].CameraInspectPosition = iniFile->ReadInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Inspect Position", 0);

//            ShutterSpeed[globalCamIndex] = iniFile->ReadInteger("Calibration", "Shutter Speed " + IntToStr(globalCamIndex + 1), 100);
//            Resolution[globalCamIndex] = iniFile->ReadFloat("Calibration", "Resolution " + IntToStr(globalCamIndex + 1), 0);
//            LEDOnMask[globalCamIndex] = iniFile->ReadInteger("Calibration", "LED On Mask " + IntToStr(globalCamIndex + 1), 0);
				}

			delete iniFile;
		}
		else
		{
				for (int spbIndex = 0; spbIndex < SYSTEM_SPB_MAX_COUNT; spbIndex++)
				{
					SPBInfo[spbIndex].DefaultCPBProgramID = PID_CPB | ('0' << 8) | '0';

					for (int cpbIndex = 0; cpbIndex < SYSTEM_CPB_MAX_COUNT; cpbIndex++)
						{
							SPBInfo[spbIndex].CPBEnabled[cpbIndex] = false;
						}
					for (int camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
					{
						SPBInfo[spbIndex].CameraHardwarePosition[camIndex] = 0;
						}
				}

				for (int globalCamIndex = 0; globalCamIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCamIndex++)
		{
			CameraMapInfo[globalCamIndex].SPBIndex = 0;
			CameraMapInfo[globalCamIndex].CamIndex = 0;
//			ShutterSpeed[globalCamIndex] = 100;
//			LEDOnMask[globalCamIndex] = 0;
		}
		returnValue = false;
	}
	return returnValue;
}
//---------------------------------------------------------------------------
bool __fastcall TSystemInfor::SaveData(AnsiString fileName)
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
		if (iniFile)
		{
				for (int spbIndex = 0; spbIndex < SYSTEM_SPB_MAX_COUNT; spbIndex++)
				{
					iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
						"Default CPB Program ID", SPBInfo[spbIndex].DefaultCPBProgramID);

					for (int cpbIndex = 0; cpbIndex < SYSTEM_CPB_MAX_COUNT; cpbIndex++)
						{
							iniFile->WriteBool("SPB " + IntToStr(spbIndex + 1),
									"CPB Enable " + IntToStr(cpbIndex + 1), SPBInfo[spbIndex].CPBEnabled[cpbIndex]);
				iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB SDR Size Type " + IntToStr(cpbIndex + 1), SPBInfo[spbIndex].CPBSDRSizeType[cpbIndex]);
				iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"CPB Clock Kind " + IntToStr(cpbIndex + 1), SPBInfo[spbIndex].CPBClockKind[cpbIndex]);
								iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
									"Camera Distribution " + IntToStr(cpbIndex + 1), SPBInfo[spbIndex].CameraDistribution[cpbIndex]);
						}
					for (int camIndex = 0; camIndex < SYSTEM_SPB_CAMERA_MAX_COUNT; camIndex++)
					{
							iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
									"Camera Hardware Position " + IntToStr(camIndex + 1), SPBInfo[spbIndex].CameraHardwarePosition[camIndex]);
						iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
					"Shutter Speed " + IntToStr(camIndex + 1), SPBInfo[spbIndex].ShutterSpeed[camIndex]);
						iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
									"Global Camera Index " + IntToStr(camIndex + 1), SPBInfo[spbIndex].GlobalCameraIndex[camIndex]);
					}
						iniFile->WriteInteger("SPB " + IntToStr(spbIndex + 1),
							"Camera Mask", SPBInfo[spbIndex].CamMask);
				}

				for (int globalCamIndex = 0; globalCamIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCamIndex++)
				{
					iniFile->WriteInteger("Camera Map " + IntToStr(globalCamIndex + 1), "SPB Index", CameraMapInfo[globalCamIndex].SPBIndex);
						iniFile->WriteInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Cam Index", CameraMapInfo[globalCamIndex].CamIndex);
			iniFile->WriteInteger("Camera Map " + IntToStr(globalCamIndex + 1), "Inspect Position", CameraMapInfo[globalCamIndex].CameraInspectPosition);

//            iniFile->WriteInteger("Calibration", "Shutter Speed " + IntToStr(globalCamIndex + 1), ShutterSpeed[globalCamIndex]);
//			iniFile->WriteFloat("Calibration", "Resolution " + IntToStr(globalCamIndex + 1), Resolution[globalCamIndex]);
//            iniFile->WriteInteger("Calibration", "LED On Mask " + IntToStr(globalCamIndex + 1), LEDOnMask[globalCamIndex]);
				}
			delete iniFile;
	}
		else
		{
			returnValue = false;
	}
	return returnValue;
}
//---------------------------------------------------------------------------
*/
bool __fastcall SetProgramPath(TProgramPath &path)
{
	TRegIniFile *regIniFile = new TRegIniFile("Application");
	bool returnValue = true;
	if (regIniFile)
	{
		regIniFile->RootKey = HKEY_LOCAL_MACHINE;
		regIniFile->OpenKey(PROGRAM_REGISTRY_KEY, true);

		path.Root = regIniFile->ReadString("Folder", "Root_Tablet", "");

		if (!DirectoryExists(path.Root))
		{
			returnValue = false;
		}
		else
		{
			path.Env = path.Root + "\\Env";
			path.Hex = path.Root + "\\Hex";
			path.Image = path.Root + "\\Image";
			path.Product = path.Root + "\\Product";
			path.Log = path.Root + "\\Log";
			path.Defect = path.Root + "\\Defect";
		}
		delete regIniFile;
	}
	TCHAR tempPath[256];
	GetTempPath(256, tempPath);
	path.Temp = AnsiString(tempPath) + "\\tvm_pc_dir";
	if (!DirectoryExists(path.Temp))
	{
		ForceDirectories(path.Temp);
	}
	return returnValue;
}
//---------------------------------------------------------------------------
bool __fastcall ReadMachineParams(AnsiString fileName, TMachineParams &machineParams)		// pc saved params
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		for (int tabletType = 0; tabletType < MS_TABLET_TYPE_COUNT; tabletType++)
		{
			for (int tabletShape = 0; tabletShape < MS_TABLET_SHAPE_COUNT; tabletShape++)
			{
				for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
				{
					for (int speedIndex = 0; speedIndex < MS_MOTOR_SPEED_STEP_COUNT; speedIndex++)
					{
						machineParams.MotorSpeedList[tabletType][tabletShape][motorIndex][speedIndex] =
							iniFile->ReadInteger("Step " + IntToStr(tabletType * 100 + tabletShape * 10 + motorIndex), "Speed Modifier " + IntToStr(speedIndex), 500000);
					}
				}
			}
		}
		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			machineParams.DiscCenterPos[globalCameraIndex] =
				iniFile->ReadInteger("Disc Center Pos", IntToStr(globalCameraIndex + 1), 0);
			machineParams.CameraResolution[globalCameraIndex] =
				iniFile->ReadFloat("Camera Resolution", IntToStr(globalCameraIndex + 1), 30);
		}

		for (int camTestIndex = 0; camTestIndex < 4; camTestIndex++)
		{
			machineParams.CameraBrightnessEvalValue[camTestIndex] =
				iniFile->ReadInteger("Camera Brightness Eval Value", IntToStr(camTestIndex + 1), 100);
		}

    machineParams.MotorSimpleSpeedList[0] = iniFile->ReadInteger("Default Simple Motor Speed", "1", 13242);
    machineParams.MotorSimpleSpeedList[1] = iniFile->ReadInteger("Default Simple Motor Speed", "2", 11587);
    machineParams.MotorSimpleSpeedList[2] = iniFile->ReadInteger("Default Simple Motor Speed", "3", 10360);
    machineParams.MotorSimpleSpeedList[3] = iniFile->ReadInteger("Default Simple Motor Speed", "4", 9270);
    machineParams.MotorSimpleSpeedList[4] = iniFile->ReadInteger("Default Simple Motor Speed", "5", 8427);
    machineParams.MotorSimpleSpeedList[5] = iniFile->ReadInteger("Default Simple Motor Speed", "6", 7725);
    machineParams.MotorSimpleSpeedList[6] = iniFile->ReadInteger("Default Simple Motor Speed", "7", 7130);
    machineParams.MotorSimpleSpeedList[7] = iniFile->ReadInteger("Default Simple Motor Speed", "8", 6621);
    machineParams.MotorSimpleSpeedList[8] = iniFile->ReadInteger("Default Simple Motor Speed", "9", 6180);
    machineParams.MotorSimpleSpeedList[9] = iniFile->ReadInteger("Default Simple Motor Speed", "10", 13242);
    machineParams.MotorSimpleSpeedList[10] = iniFile->ReadInteger("Default Simple Motor Speed", "11", 11587);
    machineParams.MotorSimpleSpeedList[11] = iniFile->ReadInteger("Default Simple Motor Speed", "12", 10360);
    machineParams.MotorSimpleSpeedList[12] = iniFile->ReadInteger("Default Simple Motor Speed", "13", 9270);
    machineParams.MotorSimpleSpeedList[13] = iniFile->ReadInteger("Default Simple Motor Speed", "14", 8427);
    machineParams.MotorSimpleSpeedList[14] = iniFile->ReadInteger("Default Simple Motor Speed", "15", 7725);
    machineParams.MotorSimpleSpeedList[15] = iniFile->ReadInteger("Default Simple Motor Speed", "16", 7130);
    machineParams.MotorSimpleSpeedList[16] = iniFile->ReadInteger("Default Simple Motor Speed", "17", 6621);
    machineParams.MotorSimpleSpeedList[17] = iniFile->ReadInteger("Default Simple Motor Speed", "18", 6180);
	}
	else
	{
		for (int tabletType = 0; tabletType < MS_TABLET_TYPE_COUNT; tabletType++)
		{
			for (int tabletShape = 0; tabletShape < MS_TABLET_SHAPE_COUNT; tabletShape++)
			{
				for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
				{
					for (int speedIndex = 0; speedIndex < MS_MOTOR_SPEED_STEP_COUNT; speedIndex++)
					{
						machineParams.MotorSpeedList[tabletType][tabletShape][motorIndex][speedIndex] = 500000;
					}
				}
			}
		}
		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			machineParams.DiscCenterPos[globalCameraIndex] = 0;
			machineParams.CameraResolution[globalCameraIndex] = 30;
		}
		for (int camTestIndex = 0; camTestIndex < 4; camTestIndex++)
		{
			machineParams.CameraBrightnessEvalValue[camTestIndex] = 100;
		}

  	machineParams.MotorSimpleSpeedList[0] = 13242;
    machineParams.MotorSimpleSpeedList[1] = 11587;
    machineParams.MotorSimpleSpeedList[2] = 10360;
    machineParams.MotorSimpleSpeedList[3] = 9270;
    machineParams.MotorSimpleSpeedList[4] = 8427;
    machineParams.MotorSimpleSpeedList[5] = 7725;
    machineParams.MotorSimpleSpeedList[6] = 7130;
    machineParams.MotorSimpleSpeedList[7] = 6621;
    machineParams.MotorSimpleSpeedList[8] = 6180;
    machineParams.MotorSimpleSpeedList[9] = 13242;
    machineParams.MotorSimpleSpeedList[10] = 11587;
    machineParams.MotorSimpleSpeedList[11] = 10360;
    machineParams.MotorSimpleSpeedList[12] = 9270;
    machineParams.MotorSimpleSpeedList[13] = 8427;
    machineParams.MotorSimpleSpeedList[14] = 7725;
    machineParams.MotorSimpleSpeedList[15] = 7130;
    machineParams.MotorSimpleSpeedList[16] = 6621;
    machineParams.MotorSimpleSpeedList[17] = 6180;

		returnValue = false;
	}


	return returnValue;
}
//---------------------------------------------------------------------------
bool __fastcall WriteMachineParams(AnsiString fileName, TMachineParams &machineParams)		// pc saved params
{
	bool returnValue = true;
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		for (int tabletType = 0; tabletType < MS_TABLET_TYPE_COUNT; tabletType++)
		{
			for (int tabletShape = 0; tabletShape < MS_TABLET_SHAPE_COUNT; tabletShape++)
			{
				for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
				{
					for (int speedIndex = 0; speedIndex < MS_MOTOR_SPEED_STEP_COUNT; speedIndex++)
					{
						iniFile->WriteInteger("Step " + IntToStr(tabletType * 100 + tabletShape * 10 + motorIndex), "Speed Modifier " + IntToStr(speedIndex),
							machineParams.MotorSpeedList[tabletType][tabletShape][motorIndex][speedIndex]);
					}
				}
			}
		}

		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			iniFile->WriteInteger("Disc Center Pos", IntToStr(globalCameraIndex + 1), machineParams.DiscCenterPos[globalCameraIndex]);
			iniFile->WriteInteger("Camera Resolution", IntToStr(globalCameraIndex + 1), machineParams.CameraResolution[globalCameraIndex]);
		}

		for (int camTestIndex = 0; camTestIndex < 4; camTestIndex++)
		{
			iniFile->WriteInteger("Camera Brightness Eval Value", IntToStr(camTestIndex + 1), machineParams.CameraBrightnessEvalValue[camTestIndex]);
		}

    for (int motorSpeedIndex = 0; motorSpeedIndex < 18; motorSpeedIndex++)
		{
  		iniFile->WriteInteger("Default Simple Motor Speed", IntToStr(motorSpeedIndex + 1),machineParams.MotorSimpleSpeedList[motorSpeedIndex]);
		}
	}
	else
	{
		returnValue = false;
	}
	return returnValue;
}
//---------------------------------------------------------------------------
/*
bool __fastcall ReadServoMotorInfo(AnsiString fileName, TServoMotorInfo *servoMotorInfo)
{
	if (!FileExists(fileName)) return false;
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			servoMotorInfo[motorIndex].BaseSpeed = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Base Speed", 100);
			servoMotorInfo[motorIndex].AccTime = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Acc Time", 1000);
			servoMotorInfo[motorIndex].DecTime = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Dec Time", 1000);
			servoMotorInfo[motorIndex].IsPositiveDirection = iniFile->ReadBool("Servo " + IntToStr(motorIndex), "Positive Direction", true);
		}
		delete iniFile;
		return true;
	}
	else
	{
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			servoMotorInfo[motorIndex].BaseSpeed = 100;
			servoMotorInfo[motorIndex].AccTime = 1000;
			servoMotorInfo[motorIndex].DecTime = 1000;
			servoMotorInfo[motorIndex].IsPositiveDirection = true;
		}
		return false;
	}
}
//---------------------------------------------------------------------------
void __fastcall WriteServoMotorInfo(AnsiString fileName, TServoMotorInfo *servoMotorInfo)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			iniFile->WriteInteger("Servo " + IntToStr(motorIndex), "Base Speed", servoMotorInfo[motorIndex].BaseSpeed);
			iniFile->WriteInteger("Servo " + IntToStr(motorIndex), "Acc Time", servoMotorInfo[motorIndex].AccTime);
			iniFile->WriteInteger("Servo " + IntToStr(motorIndex), "Dec Time", servoMotorInfo[motorIndex].DecTime);
			iniFile->WriteBool("Servo " + IntToStr(motorIndex), "Positive Direction", servoMotorInfo[motorIndex].IsPositiveDirection);
		}

		delete iniFile;
	}
}
*/
//---------------------------------------------------------------------------
bool __fastcall ReadMachineOperationInfo(AnsiString fileName, TMachineOperationInfo &machineOperationInfo, TMachineSetupData &machineSetupData)		// read recent operation info
{
	if (!FileExists(fileName))
	{
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			machineOperationInfo.ServoMotorSpeed[motorIndex] = machineSetupData.ServoMotorData[motorIndex].BaseSpeed * 2;
		}
		return false;
	}
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		machineOperationInfo.Disk1InverterSpeed = iniFile->ReadInteger("Inverter Speed", "Suction Disk 1 Inverter Speed", 255);
		machineOperationInfo.Disk2InverterSpeed = iniFile->ReadInteger("Inverter Speed", "Suction Disk 2 Inverter Speed", 255);
    machineOperationInfo.Disk3InverterSpeed = iniFile->ReadInteger("Inverter Speed", "Suction Disk 3 Inverter Speed", 255);
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			machineOperationInfo.ServoMotorSpeed[motorIndex] = iniFile->ReadInteger("Servo " + IntToStr(motorIndex), "Target Speed", machineSetupData.ServoMotorData[motorIndex].BaseSpeed * 2);
		}

		machineOperationInfo.SpeedIndex = iniFile->ReadInteger("Control Option", "Speed Index", 0);
		delete iniFile;
		return true;
	}
	else
	{
		machineOperationInfo.Disk1InverterSpeed = 255;
		machineOperationInfo.Disk2InverterSpeed = 255;
    machineOperationInfo.Disk3InverterSpeed = 255;
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			machineOperationInfo.ServoMotorSpeed[motorIndex] = machineSetupData.ServoMotorData[motorIndex].BaseSpeed * 2;
		}
		machineOperationInfo.SpeedIndex = 0;
		return false;
	}
}
//---------------------------------------------------------------------------
void __fastcall WriteMachineOperationInfo(AnsiString fileName, TMachineOperationInfo &machineOperationInfo)		// write recent operation info
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		iniFile->WriteInteger("Inverter Speed", "Suction Disk 1 Inverter Speed", machineOperationInfo.Disk1InverterSpeed);
		iniFile->WriteInteger("Inverter Speed", "Suction Disk 2 Inverter Speed", machineOperationInfo.Disk2InverterSpeed);
    iniFile->WriteInteger("Inverter Speed", "Suction Disk 3 Inverter Speed", machineOperationInfo.Disk3InverterSpeed);
		for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
		{
			iniFile->WriteInteger("Servo " + IntToStr(motorIndex), "Target Speed", machineOperationInfo.ServoMotorSpeed[motorIndex]);
		}
		iniFile->WriteInteger("Control Option", "Speed Index", machineOperationInfo.SpeedIndex);
		delete iniFile;
	}
}
//---------------------------------------------------------------------------
bool __fastcall SaveGradeData(AnsiString gradeFileName, TTabletGradeData &GradeData)
{
	TFileStream *fileStream = new TFileStream(gradeFileName, fmCreate);
	if (fileStream)
	{
		fileStream->Write(&GradeData, sizeof(TTabletGradeData));
		delete fileStream;
		return true;
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
bool __fastcall LoadGradeData(AnsiString gradeFileName, TTabletGradeData &GradeData)
{
	if (FileExists(gradeFileName))
	{
		TFileStream *fileStream = new TFileStream(gradeFileName, fmOpenRead);
		if (fileStream)
		{
			fileStream->Read(&GradeData, sizeof(TTabletGradeData));
			delete fileStream;
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
bool __fastcall LoadStudyData(AnsiString studyFileName, TTabletStudyResultData &StudyData)
{
	if (FileExists(studyFileName))
	{
		TFileStream *fileStream = new TFileStream(studyFileName, fmOpenRead);
		if (fileStream)
		{
			fileStream->Read(&StudyData, sizeof(TTabletStudyData));
			delete fileStream;
			return true;
		}
		else
		{
			return false;
		}
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
bool __fastcall SaveStudyData(AnsiString studyFileName, TTabletStudyResultData &StudyData)
{
	TFileStream *fileStream = new TFileStream(studyFileName, fmCreate);
	if (fileStream)
	{
		fileStream->Write(&StudyData, sizeof(TTabletStudyData));
		delete fileStream;
		return true;
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
float __fastcall ConvertDiscTimeToLength(int discIndex, int motorBaseSpeed, int discSpeedModifier, float time)
{
	int discDiameter[2];
	float discSpeed;
	discDiameter[0] = 102;
	discDiameter[1] = 202;

	discSpeed = motorBaseSpeed / 500.0 * 3 / 10;		// motor base speed / step count * gear ratio 

	float length = time / 1000 * discSpeed * discSpeedModifier / 100 * discDiameter[discIndex] * 3.141592;
	return length;
}
//---------------------------------------------------------------------------
float __fastcall ConvertDiscLengthToTime(int discIndex, int motorBaseSpeed, int discSpeedModifier, float length)
{
	int discDiameter[2];
	float discSpeed;
	discDiameter[0] = 102;
	discDiameter[1] = 202;

	discSpeed = motorBaseSpeed / 500.0 * 3 / 10;

	float time = length / (discDiameter[discIndex] * 3.141592) / (discSpeed * discSpeedModifier / 100) * 1000;
	return time;
}
//---------------------------------------------------------------------------

void __fastcall MakeTabletCharacterData(TProductData *productData,
	TTabletCharacter *tabletCharacter, TMachineParams *machineParams)
{
	switch (productData->TabletType)
	{
	case TABLET_TYPE_UNCOATED:
		tabletCharacter->kind = UNCOATING;
		break;
	case TABLET_TYPE_FILM_COATED:
		tabletCharacter->kind = FILMCOATING;
		break;
	case TABLET_TYPE_SUGAR_COATED:
		tabletCharacter->kind = SUGARCOATING;
		break;
	default:
		tabletCharacter->kind = UNCOATING;
		break;
	}

	switch (productData->TabletShape)
	{
	case TABLET_SHAPE_CIRCLE:
		tabletCharacter->shape = ROUND;
		break;
	case TABLET_SHAPE_OBLONG:
		tabletCharacter->shape = OBLONG;
		break;
	case TABLET_SHAPE_OVAL:
		tabletCharacter->shape = OVAL;
		break;
	case TABLET_SHAPE_HEXAGON:
		tabletCharacter->shape = HEXA;
		break;
	case TABLET_SHAPE_TRIANGLE:
		tabletCharacter->shape = TRIANGLE;
		break;
	case TABLET_SHAPE_SQUARE:
		tabletCharacter->shape = SQUARE;
		break;
	case TABLET_SHAPE_OCTAGON:
		tabletCharacter->shape = ETC;
		break;
	case TABLET_SHAPE_ETC:
		tabletCharacter->shape = ETC;
		break;
	default:
		tabletCharacter->shape = ROUND;
		break;
	}

	switch (productData->EngraveType)
	{
	case ENGRAVE_TYPE_RELIEF:
		tabletCharacter->discriminationDisplay_kind = STAMP;
		break;
	case ENGRAVE_TYPE_INTAGLIO:
		tabletCharacter->discriminationDisplay_kind = STAMP;
		break;
	case ENGRAVE_TYPE_PRINT:
		tabletCharacter->discriminationDisplay_kind = PRINT;
		break;
	default:
		tabletCharacter->discriminationDisplay_kind = NONE;
		break;
	}

	switch (productData->EngravePos)
	{
	case ENGRAVE_POS_ONESIDE:
		tabletCharacter->discriminationDisplay_num = ONE_FACE;
		break;
	case ENGRAVE_POS_SAME:
		tabletCharacter->discriminationDisplay_num = TWO_FACE_SAME;
		break;
	default:
		tabletCharacter->discriminationDisplay_num = TWO_FACE_DIFF;
		break;
	}

	if (productData->PlateTablet)
	{
		tabletCharacter->plateInformation = 1;
	}
	else
	{
		tabletCharacter->plateInformation = 0;
	}

	if (productData->Arrange)
	{
		tabletCharacter->arrangeInfo = ARRANGE;
	}
	else
	{
		tabletCharacter->arrangeInfo = NOT_ARRANGE;
	}

  tabletCharacter->tabletDivisionLineInfo = productData->DivisionLineInfo;

	tabletCharacter->symmetric_line_count = productData->SymmetricLineCount;
	tabletCharacter->length = productData->TabletLength * 10000 / machineParams->CameraResolution[0];
	tabletCharacter->width = productData->TabletWidth * 10000 / machineParams->CameraResolution[0];
	tabletCharacter->middle_height = productData->TabletSideThick * 10000 / machineParams->CameraResolution[0];
	tabletCharacter->height = productData->TabletThick * 10000 / machineParams->CameraResolution[0];

	if (productData->TabletType != TABLET_TYPE_MULTI_LAYERED)
	{
		tabletCharacter->tabletLayerCount = 1;
		tabletCharacter->tabletColorN = ONECOLOR;
	}
	else
	{
		tabletCharacter->tabletLayerCount = productData->TabletLayerCount;
		if (productData->MultiLayeredTabletColor[0] != productData->MultiLayeredTabletColor[productData->TabletLayerCount - 1])
		{
			tabletCharacter->tabletColorN = TWOCOLOR;
		}
		else
		{
			tabletCharacter->tabletColorN = ONECOLOR;
		}
	}

	tabletCharacter->MarvelingTablet = productData->MarvelingTabletSW;
	tabletCharacter->CurvedSurfaceTablet = productData->CurvedSurfaceTabletSW;
	
  tabletCharacter->HighResolutionImage = productData->SubSamplingMode;

  tabletCharacter->Disk1ThreeDImageCenterXForLaser = productData->Disk1ThreeDImageCenterXForLaser;
  tabletCharacter->Disk1ThreeDImageCenterYForLaser = productData->Disk1ThreeDImageCenterYForLaser;
  tabletCharacter->Disk2ThreeDImageCenterXForLaser = productData->Disk2ThreeDImageCenterXForLaser;
  tabletCharacter->Disk2ThreeDImageCenterYForLaser = productData->Disk2ThreeDImageCenterYForLaser;

  tabletCharacter->Disk1ThreeDImageLengthForLaser = productData->Disk1ThreeDImageLengthForLaser;
  tabletCharacter->Disk2ThreeDImageLengthForLaser = productData->Disk2ThreeDImageLengthForLaser;

}
//---------------------------------------------------------------------------
WideString __fastcall GetDefectSeriesStr(int series)
{
	WideString returnStr;
	switch (series)
	{
	case DEFECT_COLOR_R:
		returnStr = COMMONPC_RETURNSTR_17;
		break;
	case DEFECT_COLOR_G:
		returnStr = COMMONPC_RETURNSTR_16;
		break;
	case DEFECT_COLOR_B:
		returnStr = COMMONPC_RETURNSTR_15;
		break;
	case DEFECT_FRONT_DIRTY:
		returnStr = COMMONPC_RETURNSTR_40;
		break;
	case DEFECT_FRONT_STAIN:
		returnStr = COMMONPC_RETURNSTR_46;
		break;
	case DEFECT_SIDE_DIRTY:
		returnStr = COMMONPC_RETURNSTR_41;
		break;
	case DEFECT_SIDE_STAIN:
		returnStr = COMMONPC_RETURNSTR_42;
		break;
	case DEFECT_SIDE_EDGE_NEIGHBOR:
		returnStr = NEW_ADD_STRING_17;
		break;
	case DEFECT_FRONT_EDGE_STAIN: //모서리 흐린 얼룩
		returnStr = COMMONPC_RETURNSTR_10;
		break;
	case DEFECT_TABLET_SIZE:
		returnStr = COMMONPC_RETURNSTR_38;
		break;
	case DEFECT_PRINT_ERASE:
		returnStr = COMMONPC_RETURNSTR_31;
		break;
	case DEFECT_PRINT_SPREAD:
		returnStr = COMMONPC_RETURNSTR_30;
		break;
	case DEFECT_3D_BREAKING_FOR_NORMAL_AREA:
		returnStr = COMMONPC_RETURNSTR_37;
		break;
  case DEFECT_3D_SUGAR_SHAPE_DEFORMATION:
		returnStr = COMMONPC_RETURNSTR_63;
		break;
	case DEFECT_3D_PRINT_ERASE:
		returnStr = COMMONPC_RETURNSTR_36;
		break;
	case DEFECT_FRONT_COLOR_DIRTY:
    returnStr = COMMONPC_RETURNSTR_19;
		break;
	case DEFECT_SIDE_COLOR_DIRTY:
		returnStr = COMMONPC_RETURNSTR_18;
		break;
	case DEFECT_3D_BREAKING_FOR_EDGE_AREA:
		returnStr = COMMONPC_RETURNSTR_11;
		break;
  case DEFECT_3D_BREAKING_FOR_EDGE_NEIGHBOR:
		returnStr = COMMONPC_RETURNSTR_59;
		break;
	case DEFECT_FRONT_EDGE_DIRTY:	//정면 모서리 짙은 이물
		returnStr = COMMONPC_RETURNSTR_09;
		break;
	case UNINS_CLOSED:
		returnStr = COMMONPC_RETURNSTR_14;
		break;
	case UNINS_TABLET_POSITION:
		returnStr = COMMONPC_RETURNSTR_32;
		break;
	case UNINS_BRIGHTNESS_DROPPED:
		returnStr = COMMONPC_RETURNSTR_12;
		break;
	case UNINS_BRIGHTNESS_CHASE:
		returnStr = COMMONPC_RETURNSTR_13;
		break;
	case THIN_TALBET:
		returnStr = COMMONPC_RETURNSTR_21;
		break;
	case FAT_TALBET:
		returnStr = COMMONPC_RETURNSTR_08;
		break;
  case DEFECT_FRONT_COLOR_LARGE_DIRTY:
		returnStr = COMMONPC_RETURNSTR_26;
		break;
	case DEFECT_SIDE_COLOR_LARGE_DIRTY:
		returnStr = NEW_ADD_STRING_55;
		break;
	case DEFECT_2D_AND_3D_PRINT_NOT_MATCHING:
		returnStr = COMMONPC_RETURNSTR_49;
		break;
	case DEFECT_2D_DARK_SPOT_MARVELING:
		returnStr = COMMONPC_RETURNSTR_53;
		break;
	case DEFECT_2D_BRIGHT_SPOT_MARVELING:
		returnStr = COMMONPC_RETURNSTR_54;
		break;
	case DEFECT_2D_DARK_STAIN_MARVELING:
		returnStr = COMMONPC_RETURNSTR_55;
		break;
	case DEFECT_2D_BRIGHT_STAIN_MARVELING:
		returnStr = COMMONPC_RETURNSTR_56;
		break;
  case DEFECT_SIDE_EDGE_DARK:
		returnStr = NEW_ADD_STRING_79;
		break;
  case DEFECT_SIDE_EDGE_BRIGHT:
		returnStr = NEW_ADD_STRING_80;
		break;
  case DEFECT_SIDE_EDGE_NEIGHBOR_BREAK:
		returnStr = NEW_ADD_STRING_85;
		break;
  case DEFECT_FRONT_WHITE_ENGRAVE:
		returnStr = NEW_ADD_STRING_86;
		break;
  case DEFECT_FRONT_ENGRAVE_WHITE_SPOT:
		returnStr = NEW_ADD_STRING_87;
		break;
  case DEFECT_FRONT_BRIGHT_STAIN_LABEL:
		returnStr = COMMONPC_RETURNSTR_57;
		break;
  case DEFECT_FRONT_BRIGHT_STAIN_ALL:
		returnStr = COMMONPC_RETURNSTR_58;
		break;
  case DEFECT_PRINT_POSITION_ERROR:
		returnStr = COMMONPC_RETURNSTR_60;
		break;
  case DEFECT_PRINT_ROTATION_ERROR:
		returnStr = COMMONPC_RETURNSTR_61;
		break;
  case DEFECT_UNPRINT:
		returnStr = COMMONPC_RETURNSTR_62;
		break;
  case DEFECT_3D_PRINT_ERASE_PARTIAL:
		returnStr = COMMONPC_RETURNSTR_36 + "(Opt)";
		break;
  case DEFECT_SIDE_EDGE_DIRTY_OPTION:
		returnStr = COMMONPC_RETURNSTR_41 + "(Opt)";
		break;
	default:
		returnStr = COMMONPC_RETURNSTR_04;
		break;
	}

	return returnStr;
}
//---------------------------------------------------------------------------
bool __fastcall SaveShutterSpeedInfo(AnsiString fileName, AnsiString colorCodeName, TColor bgrColor, int *shutterSpeedList, unsigned int validCameraMask,int*Gain)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		// does same color table exists?
		TStringList *colorTableList = new TStringList;
		iniFile->ReadSections(colorTableList);
		for (int tableIndex = 0; tableIndex < colorTableList->Count; tableIndex++)
		{
			AnsiString existColorCodeName = colorTableList->Strings[tableIndex];
			TColor existColor = iniFile->ReadInteger(existColorCodeName, "BGR Value", 0);
			if (existColor == bgrColor)
			{
				iniFile->EraseSection(existColorCodeName);
			}
		}
		delete colorTableList;

		iniFile->WriteInteger(colorCodeName, "BGR Value", bgrColor);

		for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
		{
			if (validCameraMask & (0x0001 << globalCameraIndex))
			{
				iniFile->WriteInteger(colorCodeName, "Shutter Speed" + IntToStr(globalCameraIndex + 1), shutterSpeedList[globalCameraIndex]);
        iniFile->WriteInteger(colorCodeName, "Digital Gain" + IntToStr(globalCameraIndex + 1),  Gain[globalCameraIndex]);
			}
		}

		delete iniFile;
		return true;
	}
	else
	{
		return false;
	}
}
//---------------------------------------------------------------------------
AnsiString __fastcall LoadShutterSpeedInfo(AnsiString fileName, AnsiString colorCodeName, TColor bgrColor, int *shutterSpeedList, unsigned int validCameraMask,int*Gain)
{
	TIniFile *iniFile = new TIniFile(fileName);
	AnsiString returnCodeName = "";
	if (iniFile)
	{
		bool bColorCodeNameExist = false;
		TColor similarColor = 0xFFFFFF;
		AnsiString similarColorCodeName = "";
		int minColorSimilarity;
		// does same color table exists?
		TStringList *colorTableList = new TStringList;
		iniFile->ReadSections(colorTableList);
		for (int tableIndex = 0; tableIndex < colorTableList->Count; tableIndex++)
		{
			AnsiString existColorCodeName = colorTableList->Strings[tableIndex];
			if (existColorCodeName == colorCodeName)
			{
				bColorCodeNameExist = true;
				break;
			}
			else
			{
				TColor existColor = iniFile->ReadInteger(existColorCodeName, "BGR Value", 0);
				int bgrColorR = (bgrColor >> 0) & 0xFF;
				int bgrColorG = (bgrColor >> 8) & 0xFF;
				int bgrColorB = (bgrColor >> 16) & 0xFF;
				int existColorR = (existColor >> 0) & 0xFF;
				int existColorG = (existColor >> 8) & 0xFF;
				int existColorB = (existColor >> 16) & 0xFF;
				int similarity = sqrt(((bgrColorR - existColorR) * (bgrColorR - existColorR) + (bgrColorG - existColorG) * (bgrColorG - existColorG) +
					(bgrColorB - existColorB) * (bgrColorB - existColorB)) / 3) +
					abs(bgrColorR + bgrColorG + bgrColorB - existColorR - existColorG - existColorB) / 3;
				if (similarColorCodeName == "")
				{
					similarColorCodeName = existColorCodeName;
					minColorSimilarity = similarity;
				}
				else if (minColorSimilarity > similarity)
				{
					similarColorCodeName = existColorCodeName;
					minColorSimilarity = similarity;
				}
			}
		}

		if (colorTableList->Count == 0)
		{
			returnCodeName = "";
		}
		else if (bColorCodeNameExist)
		{
			returnCodeName = colorCodeName;
			for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
			{
				if (validCameraMask & (0x0001 << globalCameraIndex))
				{
					shutterSpeedList[globalCameraIndex] = iniFile->ReadInteger(colorCodeName, "Shutter Speed" + IntToStr(globalCameraIndex + 1), 10);
          Gain[globalCameraIndex] = iniFile->ReadInteger(colorCodeName, "Digital Gain" + IntToStr(globalCameraIndex + 1), 1);
				}
			}
		}
		else
		{
			returnCodeName = similarColorCodeName;
			for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
			{
				if (validCameraMask & (0x0001 << globalCameraIndex))
				{
					shutterSpeedList[globalCameraIndex] = iniFile->ReadInteger(similarColorCodeName, "Shutter Speed" + IntToStr(globalCameraIndex + 1), 10);
          Gain[globalCameraIndex] = iniFile->ReadInteger(similarColorCodeName, "Digital Gain" + IntToStr(globalCameraIndex + 1), 1);
				}
			}
		}

		delete colorTableList;
		delete iniFile;
	}
	else
	{
	}
	return returnCodeName;
}
//---------------------------------------------------------------------------
AnsiString __fastcall Load3DParameterInfo(AnsiString fileName, AnsiString colorCodeName, TColor bgrColor, int *exposureTimeList, int *thresholdList, unsigned int validCameraMask)
{
	int colorGradeValue = (((bgrColor & 0xFF) * 8 + ((bgrColor >> 8) & 0xFF) + ((bgrColor >> 16) & 0xFF)) + 128) / 256;		// 11 grades

	int exposureTimePerGrade[11] = { 20, 20, 20, 20, 20, 10, 10, 10, 10, 10, 10 };
	int thresholdPerGrade[11] = { 20, 20, 25, 25, 25, 20, 20, 25, 30, 35, 40 };

	for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
	{
		if (validCameraMask & (0x0001 << globalCameraIndex))
		{
			exposureTimeList[globalCameraIndex] = exposureTimePerGrade[colorGradeValue];
			thresholdList[globalCameraIndex] = thresholdPerGrade[colorGradeValue];
		}
	}
	/*
		TIniFile *iniFile = new TIniFile(fileName);
			AnsiString returnCodeName = "";
		if (iniFile)
			{
			bool bColorCodeNameExist = false;
					TColor similarColor = 0xFFFFFF;
					AnsiString similarColorCodeName = "";
					int minColorSimilarity;
				// does same color table exists?
					TStringList *colorTableList = new TStringList;
				iniFile->ReadSections(colorTableList);
					for (int tableIndex = 0; tableIndex < colorTableList->Count; tableIndex++)
					{
						AnsiString existColorCodeName = colorTableList->Strings[tableIndex];
				if (existColorCodeName == colorCodeName)
							{
					bColorCodeNameExist = true;
									break;
							}
							else
							{
								TColor existColor = iniFile->ReadInteger(existColorCodeName, "BGR Value", 0);
									int bgrColorR = (bgrColor >>  0) & 0xFF;
					int existColorR = (existColor >>  0) & 0xFF;
					int similarity = abs(bgrColorR - existColorR);
					if (similarColorCodeName == "")
									{
						similarColorCodeName = existColorCodeName;
											minColorSimilarity = similarity;
									}
									else if (minColorSimilarity > similarity)
									{
						similarColorCodeName = existColorCodeName;
											minColorSimilarity = similarity;
									}
							}
					}

					if (colorTableList->Count == 0)
					{
				returnCodeName = "";
					}
					else if (bColorCodeNameExist)
					{
				returnCodeName = colorCodeName;
				for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
				{
					if (validCameraMask & (0x0001 << globalCameraIndex))
					{
						exposureTimeList[globalCameraIndex] = iniFile->ReadInteger(colorCodeName, "Exposure Time" + IntToStr(globalCameraIndex + 1), 10);
						thresholdList[globalCameraIndex] = iniFile->ReadInteger(colorCodeName, "Threshold" + IntToStr(globalCameraIndex + 1), 30);
					}
				}
			}
			else
			{
				returnCodeName = similarColorCodeName;
				for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
				{
					if (validCameraMask & (0x0001 << globalCameraIndex))
					{
						exposureTimeList[globalCameraIndex] = iniFile->ReadInteger(similarColorCodeName, "Shutter Speed" + IntToStr(globalCameraIndex + 1), 10);
						thresholdList[globalCameraIndex] = iniFile->ReadInteger(similarColorCodeName, "Threshold" + IntToStr(globalCameraIndex + 1), 30);
					}
						}
					}

					delete colorTableList;
				delete iniFile;
			}
			else
		{
		}
		return returnCodeName;
	*/
	return "";
}
//---------------------------------------------------------------------------
bool __fastcall IsLargeTablet(TProductData &productData)
{
	bool bLargeTablet = false;
	if (productData.TabletThick >= LARGE_TABLET_CIRCLE_THICK)
	{
		bLargeTablet = true;
	}
	if (productData.TabletShape == TABLET_SHAPE_CIRCLE)
	{
		if (productData.TabletLength >= LARGE_TABLET_CIRCLE_LENGTH)
		{
			bLargeTablet = true;
		}
	}
	else
	{
		if (productData.TabletLength >= LARGE_TABLET_OBLONG_LENGTH)
		{
			bLargeTablet = true;
		}
	}

	return bLargeTablet;
}
//---------------------------------------------------------------------------
WideString __fastcall TabletKindStr(int tabletKind)
{
	switch (tabletKind)
	{
	case TABLET_TYPE_UNCOATED:
		return COMMONPC_RETURNSTR_05;
		break;
	case TABLET_TYPE_FILM_COATED:
		return COMMONPC_RETURNSTR_44;
		break;
	case TABLET_TYPE_SUGAR_COATED:
		return COMMONPC_RETURNSTR_01;
		break;
	case TABLET_TYPE_MULTI_LAYERED:
		return COMMONPC_RETURNSTR_06;
		break;
	case TABLET_TYPE_UNKNOWN:
	default:
		return COMMONPC_RETURNSTR_02;
		break;
	}
}
//---------------------------------------------------------------------------
WideString __fastcall TabletShapeStr(int tabletShape)
{
	switch (tabletShape)
	{
	case TABLET_SHAPE_CIRCLE:
		return COMMONPC_RETURNSTR_27;
		break;
	case TABLET_SHAPE_OBLONG:
		return COMMONPC_RETURNSTR_33;
		break;
	case TABLET_SHAPE_OVAL:
		return COMMONPC_RETURNSTR_43;
		break;
	case TABLET_SHAPE_HEXAGON:
		return COMMONPC_RETURNSTR_35;
		break;
	case TABLET_SHAPE_TRIANGLE:
		return COMMONPC_RETURNSTR_34;
		break;
	case TABLET_SHAPE_SQUARE:
		return PRODUCTINPUTFORM_PANEL_CAPTION_21;
		break;
	case TABLET_SHAPE_OCTAGON:
		return COMMONPC_RETURNSTR_39;
		break;
	case TABLET_SHAPE_ETC:
		return COMMONPC_RETURNSTR_04;
		break;
	case TABLET_SHAPE_UNKNOWN:
	default:
		return COMMONPC_RETURNSTR_20;
		break;
	}

}
//---------------------------------------------------------------------------
WideString __fastcall TabletEngraveKindStr(int engraveKind)
{
	switch (engraveKind)
	{
	case ENGRAVE_TYPE_UNKNOWN:
		return COMMONPC_RETURNSTR_20;
	case ENGRAVE_TYPE_RELIEF:
		return COMMONPC_RETURNSTR_22;
	case ENGRAVE_TYPE_INTAGLIO:
		return COMMONPC_RETURNSTR_28;
	case ENGRAVE_TYPE_PRINT:
		return COMMONPC_RETURNSTR_29;
	case ENGRAVE_TYPE_EMPTY:
		return COMMONPC_RETURNSTR_25;
	default:
		return COMMONPC_RETURNSTR_20;
	}
}
//---------------------------------------------------------------------------
WideString __fastcall TabletEngravePosStr(int engravePos)
{
	switch (engravePos)
	{
	case ENGRAVE_POS_UNKNOWN:
		return COMMONPC_RETURNSTR_20;
	case ENGRAVE_POS_ONESIDE:
		return COMMONPC_RETURNSTR_45;
	case ENGRAVE_POS_SAME:
		return COMMONPC_RETURNSTR_23;
	case ENGRAVE_POS_DIFF:
		return COMMONPC_RETURNSTR_24;
	default:
		return COMMONPC_RETURNSTR_20;
	}
}
//---------------------------------------------------------------------------
WideString __fastcall LampKindStr(int lampKind)
{
	switch (lampKind)
	{
	case MACHINE_LAMP_KIND_NORMAL_TABLET:
		return COMMONPC_RETURNSTR_03;
	case MACHINE_LAMP_KIND_NORMAL_CAPSULE:
		return NEW_ADD_STRING_07;
	case MACHINE_LAMP_KIND_SUGAR_COATED_TABLET:
		return COMMONPC_RETURNSTR_01;
	default:
		return COMMONPC_RETURNSTR_02;
	}
}
//---------------------------------------------------------------------------
bool __fastcall ReadUserMachineEnvData(AnsiString fileName, TUserMachineEnv &userMachineEnv)
{
	memset(&userMachineEnv, 0, sizeof(TUserMachineEnv));
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		userMachineEnv.Enabled = iniFile->ReadInteger("Dust Blower Sol", "Global Enabled", 1);
		userMachineEnv.DustBlower1Interval = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 1 Interval", 60000);
		userMachineEnv.DustBlower2Interval = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 2 Interval", 60000);
		userMachineEnv.DustBlower3Interval = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 3 Interval", 60000);
		userMachineEnv.DustBlower4Interval = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 4 Interval", 60000);
		userMachineEnv.DustBlower5Interval = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 5 Interval", 60000);
		userMachineEnv.DustBlower1Delay = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 1 Delay", 0);
		userMachineEnv.DustBlower2Delay = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 2 Delay", 12000);
		userMachineEnv.DustBlower3Delay = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 3 Delay", 24000);
		userMachineEnv.DustBlower4Delay = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 4 Delay", 36000);
		userMachineEnv.DustBlower5Delay = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 5 Delay", 48000);
		userMachineEnv.DustBlower1BlowTime = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 1 Blow Time", 1000);
		userMachineEnv.DustBlower2BlowTime = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 2 Blow Time", 1000);
		userMachineEnv.DustBlower3BlowTime = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 3 Blow Time", 1000);
		userMachineEnv.DustBlower4BlowTime = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 4 Blow Time", 1000);
		userMachineEnv.DustBlower5BlowTime = iniFile->ReadInteger("Dust Blower Sol", "Dust Blower 5 Blow Time", 1000);
		delete iniFile;
	}
	else
	{
		return false;
	}
	return true;
}
//---------------------------------------------------------------------------
bool __fastcall WriteUserMachineEnvData(AnsiString fileName, TUserMachineEnv &userMachineEnv)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		iniFile->WriteInteger("Dust Blower Sol", "Global Enabled", userMachineEnv.Enabled);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 1 Interval", userMachineEnv.DustBlower1Interval);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 2 Interval", userMachineEnv.DustBlower2Interval);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 3 Interval", userMachineEnv.DustBlower3Interval);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 4 Interval", userMachineEnv.DustBlower4Interval);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 5 Interval", userMachineEnv.DustBlower5Interval);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 1 Delay", userMachineEnv.DustBlower1Delay);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 2 Delay", userMachineEnv.DustBlower2Delay);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 3 Delay", userMachineEnv.DustBlower3Delay);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 4 Delay", userMachineEnv.DustBlower4Delay);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 5 Delay", userMachineEnv.DustBlower5Delay);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 1 Blow Time", userMachineEnv.DustBlower1BlowTime);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 2 Blow Time", userMachineEnv.DustBlower2BlowTime);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 3 Blow Time", userMachineEnv.DustBlower3BlowTime);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 4 Blow Time", userMachineEnv.DustBlower4BlowTime);
		iniFile->WriteInteger("Dust Blower Sol", "Dust Blower 5 Blow Time", userMachineEnv.DustBlower5BlowTime);
		delete iniFile;
	}
	else
	{
		return false;
	}
	return true;
}
//---------------------------------------------------------------------------
void __fastcall InitCommon_PC(void)
{
	for (int m = 4; m < 1000; m++)
	{
		Table_Interval_PixelAndMeter[m - 4] = (int)(5.73 * (float)(m* m) / 100.0);
	}
}
//---------------------------------------------------------------------------
int  __fastcall DefectSizePixelToMili(int pixel)
{
	int closeMili = 0;
	int min = 10000000;
	for (int m = 0; m < 1000; m++)
	{
		if (abs(pixel - Table_Interval_PixelAndMeter[m]) < min)
		{
			min = abs(pixel - Table_Interval_PixelAndMeter[m]);
			closeMili = m;
		}
	}
	return(closeMili);
}
//---------------------------------------------------------------------------
int  __fastcall GetDefaultGuideKind(int guideIndex, double tabletWidth)
{
	if (tabletWidth <= 6.3)
	{
		return 6;
	}
	else if (tabletWidth <= 7.3)
	{
		return 7;
	}
	else if (tabletWidth <= 8.3)
	{
		return 8;
	}
	else if (tabletWidth <= 9.3)
	{
		return 9;
	}
	else if (tabletWidth <= 10.3)
	{
		return 10;
	}
	else
	{
		return 11;
	}
}
//---------------------------------------------------------------------------
int  __fastcall GetDefaultVGateKind(int gateIndex, double tabletWidth)
{
	if (tabletWidth <= 6.3)
	{
		return 6;
	}
	else if (tabletWidth <= 7.3)
	{
		return 7;
	}
	else if (tabletWidth <= 8.3)
	{
		return 8;
	}
	else if (tabletWidth <= 9.3)
	{
		return 9;
	}
	else if (tabletWidth <= 10.3)
	{
		return 10;
	}
	else
	{
		return 11;
	}
}
//---------------------------------------------------------------------------
int __fastcall GetDefaultAirKnifeSpeed(void)
{
	return 2;
}
//---------------------------------------------------------------------------
int __fastcall GetDefaultSuctionSpeed(TProductData &productData, int &suctionSpeed1, int &suctionSpeed2)
{
	if (productData.TabletLength <= 7) // 7mm
	{
		suctionSpeed1 = 160;
		suctionSpeed2 = 160;
	}
	else if (productData.TabletLength > 7 && productData.TabletLength <= 12)
	{
		suctionSpeed1 = 170;
		suctionSpeed2 = 170;
	}
	else if (productData.TabletLength > 12 && productData.TabletLength <= 17)
	{
		suctionSpeed1 = 180;
		suctionSpeed2 = 180;
	}
	else if (productData.TabletLength > 17)
	{
		suctionSpeed1 = 190;
		suctionSpeed2 = 190;
	}
	else
	{
		suctionSpeed1 = 255;
		suctionSpeed2 = 255;
	}
	suctionSpeed1 = 255;
	suctionSpeed2 = 255;
}
//---------------------------------------------------------------------------
bool __fastcall ReadDSMInfo(AnsiString fileName, TDSMInfo &dsmInfo)
{
	bool dataExists = false;
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		dataExists = iniFile->ReadBool("Information", "Data Exists", false);
		dsmInfo.DSMEnabled = iniFile->ReadBool("Information", "Enabled", dataExists);
		//		dsmInfo.OldDataCompress = iniFile->ReadBool("Information", "Old Data Compress", false);
		//		dsmInfo.BMPMaintainTime = iniFile->ReadFloat("Information", "BMP Maintain Time", 10.0);
		dsmInfo.ReduceTime[0] = iniFile->ReadFloat("Information", "Reduce Time 1", 0);
		dsmInfo.ReduceTime[1] = iniFile->ReadFloat("Information", "Reduce Time 2", 90);
		dsmInfo.ReduceTime[2] = iniFile->ReadFloat("Information", "Reduce Time 3", 365);
		dsmInfo.PrimeLotCount[0] = iniFile->ReadInteger("Information", "Prime Lot Count 1", 2);
		dsmInfo.PrimeLotCount[1] = iniFile->ReadInteger("Information", "Prime Lot Count 2", 2);
		dsmInfo.PrimeLotCount[2] = iniFile->ReadInteger("Information", "Prime Lot Count 3", 2);
		dsmInfo.PrimeLotMaxDefectCount[0] = iniFile->ReadInteger("Information", "Prime Lot Max Defect Count 1", -1);
		dsmInfo.PrimeLotMaxDefectCount[1] = iniFile->ReadInteger("Information", "Prime Lot Max Defect Count 2", 1000);
		dsmInfo.PrimeLotMaxDefectCount[2] = iniFile->ReadInteger("Information", "Prime Lot Max Defect Count 3", 100);
		dsmInfo.TrivialLotMaxDefectCount[0] = iniFile->ReadInteger("Information", "Trivial Lot Max Defect Count 1", 1000);
		dsmInfo.TrivialLotMaxDefectCount[1] = iniFile->ReadInteger("Information", "Trivial Lot Max Defect Count 2", 100);
		dsmInfo.TrivialLotMaxDefectCount[2] = iniFile->ReadInteger("Information", "Trivial Lot Max Defect Count 3", 0);
		dsmInfo.MinDiskSpaceRatio = iniFile->ReadInteger("Information", "Min Disk Space Ratio", 10);
		dsmInfo.DSMAlwaysOn = iniFile->ReadBool("Information", "DSM Always On", true);
		dsmInfo.MainformDiskSpaceEnabled = iniFile->ReadBool("Information", "Mainform DiskspaceEnabled", false);
		dsmInfo.DSMStartTime.Val = iniFile->ReadFloat("Information", "DSM Start Time", 0.5);
		dsmInfo.DSMEndTime.Val = iniFile->ReadFloat("Information", "DSM End Time", 0.6);
		delete iniFile;
		return dsmInfo.DSMEnabled;
	}
	else
	{
		return false;
	}
	return true;
}
//---------------------------------------------------------------------------
void __fastcall WriteDSMInfo(AnsiString fileName, TDSMInfo &dsmInfo)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		iniFile->WriteBool("Information", "Data Exists", true);
		iniFile->WriteBool("Information", "Enabled", dsmInfo.DSMEnabled);
		//		iniFile->WriteBool("Information", "Old Data Compress", dsmInfo.OldDataCompress);
		//		iniFile->WriteFloat("Information", "BMP Maintain Time", dsmInfo.BMPMaintainTime);
		iniFile->WriteFloat("Information", "Reduce Time 1", dsmInfo.ReduceTime[0]);
		iniFile->WriteFloat("Information", "Reduce Time 2", dsmInfo.ReduceTime[1]);
		iniFile->WriteFloat("Information", "Reduce Time 3", dsmInfo.ReduceTime[2]);
		iniFile->WriteInteger("Information", "Prime Lot Count 1", dsmInfo.PrimeLotCount[0]);
		iniFile->WriteInteger("Information", "Prime Lot Count 2", dsmInfo.PrimeLotCount[1]);
		iniFile->WriteInteger("Information", "Prime Lot Count 3", dsmInfo.PrimeLotCount[2]);
		iniFile->WriteInteger("Information", "Prime Lot Max Defect Count 1", dsmInfo.PrimeLotMaxDefectCount[0]);
		iniFile->WriteInteger("Information", "Prime Lot Max Defect Count 2", dsmInfo.PrimeLotMaxDefectCount[1]);
		iniFile->WriteInteger("Information", "Prime Lot Max Defect Count 3", dsmInfo.PrimeLotMaxDefectCount[2]);
		iniFile->WriteInteger("Information", "Trivial Lot Max Defect Count 1", dsmInfo.TrivialLotMaxDefectCount[0]);
		iniFile->WriteInteger("Information", "Trivial Lot Max Defect Count 2", dsmInfo.TrivialLotMaxDefectCount[1]);
		iniFile->WriteInteger("Information", "Trivial Lot Max Defect Count 3", dsmInfo.TrivialLotMaxDefectCount[2]);
		iniFile->WriteInteger("Information", "Min Disk Space Ratio", dsmInfo.MinDiskSpaceRatio);
		iniFile->WriteBool("Information", "DSM Always On", dsmInfo.DSMAlwaysOn);
		iniFile->WriteBool("Information", "Mainform DiskspaceEnabled", dsmInfo.MainformDiskSpaceEnabled); 
		iniFile->WriteFloat("Information", "DSM Start Time", dsmInfo.DSMStartTime.Val);
		iniFile->WriteFloat("Information", "DSM End Time", dsmInfo.DSMEndTime.Val);
		delete iniFile;
	}
}
//---------------------------------------------------------------------------
void __fastcall ImageConversion_3D(Graphics::TBitmap *DestBitmap, int destWidth, int destHeight,
	byte *srcBitmap, int srcWidth, int srcHeight)
{
	 unsigned char ConversionImage[SYSTEM_CAMERA_WIDTH_3D * SYSTEM_CAMERA_HEIGHT_3D];
  memset(ConversionImage, 0, SYSTEM_CAMERA_WIDTH_3D * SYSTEM_CAMERA_HEIGHT_3D);

  float value;
  float subval;
  int k;
  int tempAddress;

  try
  {
    for (int y = 0; y < srcHeight / 2; y++)
    {
      for (int x = 0; x < srcWidth * 2; x+=2)
      {
        //value = srcBitmap[y * srcWidth * 2 + x + 1] * 256;
        value = (srcBitmap[y * srcWidth * 2 + x + 1]) << 8;
        subval = srcBitmap[y * srcWidth * 2 + x + 0];

        k = min(255, (int)((value + subval) * 255 / 65535));

        //k = min(255, srcBitmap[y * srcWidth * 2 + x + 1]);

        tempAddress = srcWidth * y + x / 2;

        if(k)
          ConversionImage[tempAddress] = (unsigned char)(255-k);//(255 - k);
        else
          ConversionImage[tempAddress] = 0;
      }
    }
  }
  catch(...)
  {

  }

	for (int y = 0; y < destHeight; y++)
	{
		byte *pBitmap = (byte *)DestBitmap->ScanLine[y];
		for (int x = 0; x < destWidth; x++)
		{
			pBitmap[x] = ConversionImage[x * srcWidth + y];
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall ImageConversion_3D_Reverse(Graphics::TBitmap *DestBitmap, int destWidth, int destHeight,
	byte *srcBitmap, int srcWidth, int srcHeight)
{
  // ImageConversion_3D의 반대의 역할을 한다.
  // ImageConversion_3D가 BayerImage를 TBitmap으로 바꿔준다면 ImageConversion_3D_Reverse를 BayerImage로 바꿔준다.
  // 그런데 TBitmap를 처리하는 과정에서 width를 2배로 해주는 처리 등이 맞물려 있어서 두 함수가 완전히 똑같지는 않다.
  unsigned char ConversionImage[SYSTEM_CAMERA_WIDTH_3D * SYSTEM_CAMERA_HEIGHT_3D];
  memset(ConversionImage, 0, SYSTEM_CAMERA_WIDTH_3D * SYSTEM_CAMERA_HEIGHT_3D);

  for (int y = 0; y < destHeight; y++)
  {
    byte *pBitmap = (byte *)DestBitmap->ScanLine[y];
    for (int x = 0; x < destWidth; x++)
    {
      ConversionImage[x * srcWidth + y] = pBitmap[x * 3]; // from 24bit
    }
  }

  float value;
  float subval;
  int k, c;
  int tempAddress;

  try
  {
    for (int y = 0; y < srcHeight / 2; y++)
    {
      for (int x = 0; x < srcWidth * 2; x+=2)
      {
        tempAddress = srcWidth * y * 2 + x / 2;

        c = (unsigned char)ConversionImage[tempAddress];

        if (c)
        {
          k = 255 - c;
        }
        else
        {
          k = 0;
        }

        srcBitmap[y * 2 * srcWidth + x + 1] = k;
        srcBitmap[y * 2 * srcWidth + x + 0] = 0;
        srcBitmap[(y * 2 + 1) * srcWidth + x + 1] = k;
        srcBitmap[(y * 2 + 1) * srcWidth + x + 0] = 0;
      }
    }
  }
  catch(...)
  {

  }

}
//---------------------------------------------------------------------------
int __fastcall GetMSTabletTypeIndex(int tabletType)
{
	int returnValue = 0;
	if (tabletType == TABLET_TYPE_UNCOATED)
	{
		returnValue = 0;
	}
	else if (tabletType == TABLET_TYPE_FILM_COATED)
	{
		returnValue = 1;
	}
	else if (tabletType == TABLET_TYPE_SUGAR_COATED)
	{
		returnValue = 2;
	}
	else if (tabletType == TABLET_TYPE_MULTI_LAYERED)
	{
		returnValue = 0; // treat as uncoated
	}
	return returnValue;
}
//---------------------------------------------------------------------------
int __fastcall GetMSTabletShapeIndex(int tabletShape)
{
	int returnValue = 0;
	if (tabletShape == TABLET_SHAPE_CIRCLE)
	{
		returnValue = 0;
	}
	else if (tabletShape == TABLET_SHAPE_OBLONG)
	{
		returnValue = 1;
	}
	else if (tabletShape == TABLET_SHAPE_OVAL)
	{
		returnValue = 2;
	}
	else
	{
		returnValue = 3;
	}
	return returnValue;
}
//---------------------------------------------------------------------------
unsigned short Generate_CRC16(unsigned char *data, int len)
{
	const unsigned char abCrcHi[] =
	{
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
		0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
	};

	const unsigned char abCrcLo[] =
	{
		0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04,
		0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8,
		0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
		0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10,
		0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
		0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,	0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
		0x28, 0xE8, 0xE9, 0x29,	0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,	0xEC, 0x2C,
		0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,	0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0,
		0xA0, 0x60,	0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,	0xA5, 0x65, 0x64, 0x44,
		0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,	0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
		0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C,
		0xB4, 0x74, 0x75, 0xB5,	0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,	0x70, 0xB0,
		0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,	0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54,
		0x9C, 0x5C,	0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,	0x99, 0x59, 0x58, 0x98,
		0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,	0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
		0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,	0x43, 0x83, 0x41, 0x81, 0x80, 0x40
	};

	unsigned char bCrcHi = 0xFF;
	unsigned char bCrcLo = 0xFF;
	unsigned short index;
	unsigned char *pData = data;

	int length = len;
	while (length--)
	{
		index = bCrcHi ^ *pData++;
		bCrcHi = bCrcLo ^ abCrcHi[index];
		bCrcLo = abCrcLo[index];
	}
	return (bCrcHi << 8 | bCrcLo);
}
//---------------------------------------------------------------------------
void __fastcall GetDefaultNCPosition(TProductData &productData, double *ncMotorPos, double interlockAValue)
{
	double N = productData.RotatingGuideKind;
	double R = productData.TabletWidth;
	double W = productData.TabletWidth;
	double L = productData.TabletLength;
	double H = productData.TabletThick;
	double Hc = (productData.TabletThick - productData.TabletSideThick) / 2;
	double Dsd = 0;

	if (productData.TabletType == TABLET_TYPE_SUGAR_COATED)
	{
		Hc = productData.TabletThick / 6;
	}

	if (productData.TabletShape == TABLET_SHAPE_OBLONG)
	{
		if (!productData.PlateTablet)
		{
			ncMotorPos[VG1_UP_DOWN_MOTOR_INDEX] = H - 0.1 + (W - H - 1) / 10;
			//sjm VG2
			ncMotorPos[VG2_UP_DOWN_MOTOR_INDEX] = H - 0.1 + (W - H - 1) / 10;
			ncMotorPos[BF_UP_DOWN_MOTOR_INDEX] = H - 0.2;
		}
		else
		{
			ncMotorPos[VG1_UP_DOWN_MOTOR_INDEX] = H + 0.1;
			//sjm VG2
			ncMotorPos[VG2_UP_DOWN_MOTOR_INDEX] = H + 0.1;
			ncMotorPos[BF_UP_DOWN_MOTOR_INDEX] = H;
		}

		if (W > 0)
		{
			Dsd = H - (1.5 / sqrt(W) + Hc / 2);
		}
		else
		{
			Dsd = H;
		}
		ncMotorPos[BF_IN_OUT_MOTOR_INDEX] = (N - 6) / 2 + (N - W) / 2 + H * 0.1 + L / 2 * 0.1;
	}
	else if (productData.TabletShape == TABLET_SHAPE_OVAL)
	{
		if (!productData.PlateTablet)
		{
			ncMotorPos[VG1_UP_DOWN_MOTOR_INDEX] = H - 0.1;
			//sjm VG2
			ncMotorPos[VG2_UP_DOWN_MOTOR_INDEX] = H - 0.1;
			ncMotorPos[BF_UP_DOWN_MOTOR_INDEX] = H - 0.3;
		}
		else
		{
			ncMotorPos[VG1_UP_DOWN_MOTOR_INDEX] = H;
			//sjm VG2
			ncMotorPos[VG2_UP_DOWN_MOTOR_INDEX] = H;
			ncMotorPos[BF_UP_DOWN_MOTOR_INDEX] = H;
		}

		if (W > 0)
		{
			Dsd = H - (1.6 / sqrt(W) + 5 * Hc / W);
		}
		else
		{
			Dsd = H;
		}
		ncMotorPos[BF_IN_OUT_MOTOR_INDEX] = (N - 6) / 2 + (N - W) / 2 + H * 0.1 + 0.1;
	}
	else // cirle or other shape
	{
		if (!productData.PlateTablet)
		{
			ncMotorPos[VG1_UP_DOWN_MOTOR_INDEX] = H;
			//sjm VG2
			ncMotorPos[VG2_UP_DOWN_MOTOR_INDEX] = H;
			ncMotorPos[BF_UP_DOWN_MOTOR_INDEX] = H - 0.2;
		}
		else
		{
			ncMotorPos[VG1_UP_DOWN_MOTOR_INDEX] = H + 0.2;
			//sjm VG2
			ncMotorPos[VG2_UP_DOWN_MOTOR_INDEX] = H + 0.2;
			ncMotorPos[BF_UP_DOWN_MOTOR_INDEX] = H;
		}

		if (R > 0)
		{
			Dsd = H - (1.6 / sqrt(R) + 6 * Hc / R);
		}
		else
		{
			Dsd = H;
		}
		ncMotorPos[BF_IN_OUT_MOTOR_INDEX] = (N - 6) / 2 + (N - R) / 2 + H * 0.1 + (R - 6) * 0.1;
	}

	double suctionDisk2Position = sqrt((SUCTION_DISK_DIAMETER + Dsd) * (SUCTION_DISK_DIAMETER + Dsd) - SUCTION_DISK_DISTANCE_Y * SUCTION_DISK_DISTANCE_Y) - SUCTION_DISK_DISTANCE_BASE_X;
	ncMotorPos[SD2_LEFT_RIGHT_MOTOR_INDEX] = suctionDisk2Position;

  //sjm VG2
	//ncMotorPos[VG2_UP_DOWN_MOTOR_INDEX] = interlockAValue + ncMotorPos[BF_UP_DOWN_MOTOR_INDEX] - 0.1;
}
//---------------------------------------------------------------------------
void __fastcall CopyProductData(TProductData &dest, TProductData &src)
{
	dest.ProductCode = src.ProductCode;
	dest.ProductName = src.ProductName;
	dest.LOTName = src.LOTName;
	dest.TabletType = src.TabletType;
	dest.TabletShape = src.TabletShape;
	dest.StudyStep = src.StudyStep;
	dest.TabletLength = src.TabletLength;
	dest.TabletWidth = src.TabletWidth;
	dest.TabletThick = src.TabletThick;
	dest.TabletSideThick = src.TabletSideThick;
	dest.EngraveType = src.EngraveType;
	dest.EngravePos = src.EngravePos;
	dest.PrintBrightness = src.PrintBrightness;
	for (int globalCameraIndex = 0; globalCameraIndex < SYSTEM_TOTAL_CAMERA_COUNT; globalCameraIndex++)
	{
		dest.BoundaryLeft[globalCameraIndex] = src.BoundaryLeft[globalCameraIndex];
		dest.BoundaryTop[globalCameraIndex] = src.BoundaryTop[globalCameraIndex];
		dest.BoundaryRight[globalCameraIndex] = src.BoundaryRight[globalCameraIndex];
		dest.BoundaryBottom[globalCameraIndex] = src.BoundaryBottom[globalCameraIndex];
		dest.ShutterSpeed[globalCameraIndex] = src.ShutterSpeed[globalCameraIndex];
		dest.ThresholdFor3D[globalCameraIndex] = src.ThresholdFor3D[globalCameraIndex];
    dest.DigitalGainV[globalCameraIndex] = src.DigitalGainV[globalCameraIndex];

    dest.StudyShutterSpeed[globalCameraIndex] = src.StudyShutterSpeed[globalCameraIndex];
    dest.StudyGainV[globalCameraIndex] = src.StudyGainV[globalCameraIndex];
	}
	dest.ProcessingStep = src.ProcessingStep;
	dest.TabletColorCode = src.TabletColorCode;
	dest.PrintColorCode = src.PrintColorCode;
	for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
	{
		for (int speedIndex = 0; speedIndex < MOTOR_SPEED_STEP_COUNT_FOR_PRODUCT; speedIndex++)
		{
			dest.MotorSpeedList[motorIndex][speedIndex] = src.MotorSpeedList[motorIndex][speedIndex];
      if(motorIndex == 0|| motorIndex == 1)
      {
        dest.SimpleMotorSpeedList[motorIndex][speedIndex] = src.SimpleMotorSpeedList[motorIndex][speedIndex];
      }
		}

	}
	int StudySpeedIndex = 0;
	for (int motorIndex = 0; motorIndex < MAX_SERVO_MOTOR_COUNT; motorIndex++)
  {
		dest.StudyMotorSpeedList[motorIndex][StudySpeedIndex] = src.StudyMotorSpeedList[motorIndex][StudySpeedIndex];
    if(motorIndex == 0|| motorIndex == 1)
    {
      dest.SimpleStudyMotorSpeedList[motorIndex][StudySpeedIndex] = src.SimpleStudyMotorSpeedList[motorIndex][StudySpeedIndex];
    }
  }

	dest.ProductionCount = src.ProductionCount;
	dest.LastInspectionTime = src.LastInspectionTime;
	dest.PlateTablet = src.PlateTablet;
	dest.Arrange = src.Arrange;
	dest.SymmetricLineCount = src.SymmetricLineCount;

	dest.TabletLayerCount = src.TabletLayerCount;

  dest.DivisionLineInfo = src.DivisionLineInfo;

	for (int layerIndex = 0; layerIndex < MAX_TABLET_LAYER_COUNT; layerIndex++)
	{
		dest.MultiLayeredTabletColor[layerIndex] = src.MultiLayeredTabletColor[layerIndex];
	}
	dest.MachineRunOption = src.MachineRunOption;
	dest.StudiedSensor1Length = src.StudiedSensor1Length;
	dest.StudiedSensor2Length = src.StudiedSensor2Length;
	//sjm add 깨진정제
	dest.StudiedSensor3Length = src.StudiedSensor3Length;
	dest.StudiedSensorIntervalA = src.StudiedSensorIntervalA;
	dest.StudiedSensorIntervalB = src.StudiedSensorIntervalB;

	dest.MachineRunOption.applyEjectorDelay = src.MachineRunOption.applyEjectorDelay;
	dest.MachineRunOption.adjustUnInsDelay = src.MachineRunOption.adjustUnInsDelay;
	dest.MachineRunOption.adjustDefectDelay = src.MachineRunOption.adjustDefectDelay;
	dest.MachineRunOption.adjustEjectorWindStrength = src.MachineRunOption.adjustEjectorWindStrength;

	for (int motorIndex = 0; motorIndex < MAX_STEP_MOTOR_COUNT; motorIndex++)
	{
		dest.NCMotorPos[motorIndex] = src.NCMotorPos[motorIndex];
	}

	dest.RotatingGuideKind = src.RotatingGuideKind;
	dest.FixedGuideKind = src.FixedGuideKind;
	dest.VerticalGate2Kind = src.VerticalGate2Kind;
	dest.LampKind = src.LampKind;

	dest.MachineRunOption.EnabledSensorType = src.MachineRunOption.EnabledSensorType;
	dest.MarvelingTabletSW = src.MarvelingTabletSW;
    dest.FatTabletCapture = src.FatTabletCapture;
    dest.CurvedSurfaceTabletSW = src.CurvedSurfaceTabletSW;
  dest.SubSamplingMode = src.SubSamplingMode;

  for(int i = 0; i < 2; ++i)
  {
     dest.ExposureTime3D[i] = src.ExposureTime3D[i];
     dest.AnalogGain3D[i] = src.AnalogGain3D[i];
  }
  dest.RecipeName = src.RecipeName;
  dest.LastDischargeCountSetValue = src.LastDischargeCountSetValue;
	dest.DischargeCountSetValue = src.DischargeCountSetValue;
	
	dest.DischargeCount = src.DischargeCount;
  dest.MisejectActiveLimitCount = src.MisejectActiveLimitCount;

  dest.Disk1ThreeDImageCenterXForLaser = src.Disk1ThreeDImageCenterXForLaser;
  dest.Disk1ThreeDImageCenterYForLaser = src.Disk1ThreeDImageCenterYForLaser;
  dest.Disk2ThreeDImageCenterXForLaser = src.Disk2ThreeDImageCenterXForLaser;
  dest.Disk2ThreeDImageCenterYForLaser = src.Disk2ThreeDImageCenterYForLaser;	 

  dest.Disk1ThreeDImageLengthForLaser = src.Disk1ThreeDImageLengthForLaser;
  dest.Disk2ThreeDImageLengthForLaser = src.Disk2ThreeDImageLengthForLaser;
}



//ThreeDCamera 작업
//Camera 정보 Write 하는 지점 확인 -> Common에 정의한 함수를 활용하여 변경
//기존에 카메라 정보 write 하는것 제거
//SPB 쪽작업........ ??
// - DMA
// - ThreeD Data writing



//---------------------------------------------------------------------------
void __fastcall ReadCameraWhiteBalanceColorInfo(AnsiString fileName, int cameraIndex)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
    WhiteBalanceInfo[cameraIndex].BColorInfo = iniFile->ReadInteger("White Balance Info " + IntToStr(cameraIndex + 1), "B Color Infomation", 1051);
    WhiteBalanceInfo[cameraIndex].GColorInfo = iniFile->ReadInteger("White Balance Info " + IntToStr(cameraIndex + 1), "G Color Infomation", 926);
    WhiteBalanceInfo[cameraIndex].RColorInfo = iniFile->ReadInteger("White Balance Info " + IntToStr(cameraIndex + 1), "R Color Infomation", 1321);
	}
	else
	{
		WhiteBalanceInfo[cameraIndex].BColorInfo = 1051;
    WhiteBalanceInfo[cameraIndex].GColorInfo = 962;
    WhiteBalanceInfo[cameraIndex].RColorInfo = 1321;
	}

  delete iniFile;
}
//---------------------------------------------------------------------------
void __fastcall WriteCameraWhiteBalanceColorInfo(AnsiString fileName, int cameraIndex, int rgbIndex)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
    if(rgbIndex == 0)
      iniFile->WriteInteger("White Balance Info " + IntToStr(cameraIndex + 1), "B Color Infomation",          WhiteBalanceInfo[cameraIndex].BColorInfo);
    else if(rgbIndex == 1)
      iniFile->WriteInteger("White Balance Info " + IntToStr(cameraIndex + 1), "G Color Infomation",          WhiteBalanceInfo[cameraIndex].GColorInfo);
    else if(rgbIndex == 2)
      iniFile->WriteInteger("White Balance Info " + IntToStr(cameraIndex + 1), "R Color Infomation",          WhiteBalanceInfo[cameraIndex].RColorInfo);
	}
  delete iniFile;
}
//---------------------------------------------------------------------------
void __fastcall ReadDiskLineScanFrequency(AnsiString fileName)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
    RANGER_3D_BASE_SHUTTER_SPEED = iniFile->ReadInteger("Disk Line Scen Frequency", "Value", 1000);
    RANGER_3D_BASE_SHUTTER_SPEED2 = iniFile->ReadInteger("Disk Line Scen Frequency2", "Value", 1000);
 	}
	else
	{
		RANGER_3D_BASE_SHUTTER_SPEED = 1000;
    RANGER_3D_BASE_SHUTTER_SPEED2 = 1000;
	}

  delete iniFile;
}
//---------------------------------------------------------------------------
void __fastcall WriteDiskLineScanFrequency(AnsiString fileName)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
    iniFile->WriteInteger("Disk Line Scen Frequency", "Value",  RANGER_3D_BASE_SHUTTER_SPEED);
    iniFile->WriteInteger("Disk Line Scen Frequency2", "Value",  RANGER_3D_BASE_SHUTTER_SPEED2);
	}
  delete iniFile;
}
//---------------------------------------------------------------------------
void __fastcall ReadSystem2DCamAnalogGain(AnsiString fileName)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		SYSTEM_DEFAULT_ANLOG_GAIN = iniFile->ReadInteger("Camera Analog Gain", "Value", 3);
	}
	else
	{
		SYSTEM_DEFAULT_ANLOG_GAIN = 3;
	}

	delete iniFile;
}
//---------------------------------------------------------------------------
void __fastcall WriteSystem2DCamAnalogGain(AnsiString fileName)
{
	TIniFile *iniFile = new TIniFile(fileName);
	if (iniFile)
	{
		iniFile->WriteInteger("Camera Analog Gain", "Value", SYSTEM_DEFAULT_ANLOG_GAIN);
	}
	delete iniFile;
}
//---------------------------------------------------------------------------

void __fastcall ApplyWhiteBalance(int cameraIndex, Graphics::TBitmap *srcImage, Graphics::TBitmap *dstImage)
{
  int x, y;
  int Limitx, Limity;
  int tempAddress;
  int tempBuff[3];
  int normalized[3];

  Byte *ptr1, *ptr2;

  int maxB = min((WhiteBalanceInfo[cameraIndex].BColorInfo * 255) / 1000, 255);
  int maxG = min((WhiteBalanceInfo[cameraIndex].GColorInfo * 255) / 1000, 255);
  int maxR = min((WhiteBalanceInfo[cameraIndex].RColorInfo * 255) / 1000, 255);


  for(y = 0; y < srcImage->Height; y++)
  {
    ptr1 = (Byte*) srcImage->ScanLine[y];
    ptr2 = (Byte*) dstImage->ScanLine[y];
    for(x = 0; x < srcImage->Width; x++)
    {
      tempBuff[0] = ptr1[3*x + 0];
      tempBuff[1] = ptr1[3*x + 1];
      tempBuff[2] = ptr1[3*x + 2];

      tempBuff[0] = min((WhiteBalanceInfo[cameraIndex].BColorInfo * tempBuff[0]) / 1000, 255);
      tempBuff[1] = min((WhiteBalanceInfo[cameraIndex].GColorInfo * tempBuff[1]) / 1000, 255);
      tempBuff[2] = min((WhiteBalanceInfo[cameraIndex].RColorInfo * tempBuff[2]) / 1000, 255);
      
        if(maxB)
          normalized[0] = min((tempBuff[0] * 255) / maxB, 255);
        else
        normalized[0] = 0;

      if(maxG)
        normalized[1] = min((tempBuff[1] * 255) / maxG, 255);
      else
        normalized[1] = 0;

      if(maxR)
        normalized[2] = min((tempBuff[2] * 255) / maxR, 255);
      else
        normalized[2] = 0;

      ptr2[3*x + 0] = normalized[0];
      ptr2[3*x + 1] = normalized[1];
      ptr2[3*x + 2] = normalized[2];
    }
  }

  /*
  // 임시
  for(y = 0; y < 480; y++)
  {
    ptr2 = (Byte*) dstImage->ScanLine[y];
    for(x = 0; x < 640; x++)
    {
      if(y < 90 || y > 390)
      {
        ptr2[3 * x + 0] = 0;
        ptr2[3 * x + 1] = 0;
        ptr2[3 * x + 2] = 0;
      }
    }
  }
  */
}
//---------------------------------------------------------------------------

void __fastcall SetCameraGain(int cameraIndex, int AnalogGain, int DigitalGain1, int DigitalGain2)
{
  // cameraIndex
  // Input : (T)1 - 10 , (C)1 - 16

  // AnalogGain
  // Input : x1 - x4(dB)

  // DigitalGain1
  // Input : 0 - 31

  // DigitalGain2
  // Input : 0 - 9

  if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX || cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX) return;
  
  const int MAX_COMM_DATA_LENGTH = 20;
  int SendPacketLength;
  int ReceivePacketLength;

  char TxData[MAX_COMM_DATA_LENGTH];
  char RxData[MAX_COMM_DATA_LENGTH];

  int spbCamIndex = CameraMapInfo[cameraIndex - 1].CamIndex;

  memset(TxData, 0, MAX_COMM_DATA_LENGTH);
  memset(RxData, 0, MAX_COMM_DATA_LENGTH);

  // Analog Gain
  TxData[0] = 0xA1;
  TxData[1] = 0x01;
  TxData[2] = 0x00;
  TxData[3] = ((spbCamIndex + 1) << 4) & 0xF0;
  TxData[4] = 0x6C;
  TxData[5] = 0xCC;

  TxData[6] = (AnalogGain & 0xFF); // 1 ~ 4

  TxData[7] = 0xAE;
  TxData[8] = 0x00;

  SendPacketLength = 9;
  ReceivePacketLength = 9;

  RequestCameraCommand(cameraIndex, TxData, RxData, SendPacketLength, ReceivePacketLength);

  if(RxData[0] == 'T' && RxData[1] == 'O')
  {
    GlobalEnabledCameraStatus[cameraIndex - 1] = false;
    
    ShowMessage("Camera information write failed [#" + IntToStr(cameraIndex) + "]");
  }
  else
  {
    memset(TxData, 0, MAX_COMM_DATA_LENGTH);
    memset(RxData, 0, MAX_COMM_DATA_LENGTH);

    // Analog Gain
    TxData[0] = 0xA1;
    TxData[1] = 0x02;
    TxData[2] = 0x00;
    TxData[3] = ((spbCamIndex + 1) << 4) & 0xF0;
    TxData[4] = 0x6C;
    TxData[5] = 0xC2;

    TxData[6] = (DigitalGain1 & 0xFF); // 0 ~ 31
    TxData[7] = (DigitalGain2 & 0xFF); // 0 ~ 9

    TxData[8] = 0xAE;
    TxData[9] = 0x00;

    SendPacketLength = 10;
    ReceivePacketLength = 9;

    RequestCameraCommand(cameraIndex, TxData, RxData, SendPacketLength, ReceivePacketLength);

    if(RxData[0] == 'T' && RxData[1] == 'O')
    {
      GlobalEnabledCameraStatus[cameraIndex - 1] = false;

      ShowMessage("Camera information write failed [#" + IntToStr(cameraIndex) + "]");
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall Set3DCamera_CaptureParameter(int cameraIndex, int AnalogGain,int ExposureTime)
{ 
  if (cameraIndex == SD1_3D_FRONT_FACE_CAMERA_INDEX-1 || cameraIndex == SD2_3D_FRONT_FACE_CAMERA_INDEX-1)
  {
    const int MAX_COMM_DATA_LENGTH = 20;
    char TxData[MAX_COMM_DATA_LENGTH];
    char RxData[MAX_COMM_DATA_LENGTH];
    bool bRead = false;
    bool bBreakSW = false;
    bool bErrorData = false;

    TCommDataLength CommDataLength;
    int Data[MAX_3D_CAMERA_DATA_INDEX];
    Data[ECAMERA_PARAM_3D_SHUTTER_TIME] = ExposureTime;
    Data[ECAMERA_PARAM_3D_ANALOG_GAIN] = AnalogGain;
    if(AnalogGain != -1)
    {
      memset(TxData, 0, sizeof(char) * MAX_COMM_DATA_LENGTH);
      memset(RxData, 0, sizeof(char) * MAX_COMM_DATA_LENGTH);

      CommDataLength = gMakeCameraWriteDataPacket(TxData, cameraIndex, Data, ECAMERA_PARAM_3D_ANALOG_GAIN);

      if(!gRequestCameraCommand(TxData, RxData, CommDataLength.SendDataLength, CommDataLength.ReceivedDataLength, cameraIndex, 0))
      {
        bBreakSW = true;
      }
      else
      {
      }

      memset(TxData, 0, sizeof(char) * MAX_COMM_DATA_LENGTH);
      memset(RxData, 0, sizeof(char) * MAX_COMM_DATA_LENGTH);

      CommDataLength = gMakeCameraWriteDataPacket(TxData, cameraIndex, Data, ECAMERA_PARAM_3D_SHUTTER_TIME);

      if(!gRequestCameraCommand(TxData, RxData, CommDataLength.SendDataLength, CommDataLength.ReceivedDataLength, cameraIndex, 1))
      {
        bBreakSW = true;
      }
      else
      {
      }
    }
  }

  /*const int MAX_COMM_DATA_LENGTH = 20;
  char TxData[MAX_COMM_DATA_LENGTH];
  char RxData[MAX_COMM_DATA_LENGTH];
  bool bRead = false;
  bool bBreakSW = false;
  bool bErrorData = false;
  int Data[MAX_3D_CAMERA_DATA_INDEX]={0};
  Data[7] = AnalogGain;
  TCommDataLength CommDataLength;

  if(AnalogGain != -1)
  {
      memset(TxData, 0, sizeof(char) * MAX_COMM_DATA_LENGTH);
      memset(RxData, 0, sizeof(char) * MAX_COMM_DATA_LENGTH);

      CommDataLength = gMakeCameraWriteDataPacket(TxData, cameraIndex, Data, ECAMERA_PARAM_3D_ANALOG_GAIN);
      if(!RequestCameraCommand(TxData, RxData, CommDataLength.SendDataLength, CommDataLength.ReceivedDataLength, cameraIndex))
      {
        bBreakSW = true;
      }
  }*/
}
//---------------------------------------------------------------------------

bool __fastcall RequestCameraCommand(int cameraIndex, char *sendData, char *receivedData, unsigned int txDataLength, unsigned int rxDataLength)
{
	int spbIndex = CameraMapInfo[cameraIndex - 1].SPBIndex;

  const int MAX_COMM_DATA_LENGTH = 20;
  char tempSendData[MAX_COMM_DATA_LENGTH];
  memcpy(tempSendData + 2, sendData, sizeof(char) * txDataLength);
  *(tempSendData + 0) = txDataLength;
  *(tempSendData + 1) = rxDataLength;
  txDataLength += 2;

  Comm_SetMaxWaitingTime(COMM_SPB + spbIndex, 30000);
  if (!Comm_Request(COMM_SPB + spbIndex, CMD_CAMERA_CONTROL_NORMAL_MODE, tempSendData, txDataLength, receivedData, rxDataLength))
  {
//    ShowMessage("Communication Error #" + IntToStr(spbIndex + 1) + " IPB");
   Comm_SetDefaultMaxWaitingTime(COMM_SPB + spbIndex);
    return false;
  }
  else
  {
    Comm_SetDefaultMaxWaitingTime(COMM_SPB + spbIndex);
    return true;
  }
  Comm_SetDefaultMaxWaitingTime(COMM_SPB + spbIndex);
}
//-----------------------------------------------------------------------------

bool __fastcall ReadSystemUserAuthorityInformation(AnsiString fileName)
{
  if(!FileExists(fileName))
  {
    MakeSystemUserAuthorityInitInformation();
    WriteSystemUserAuthorityInformation(fileName);

    return false;
  }
  else
  {
    TIniFile *iniFile = new TIniFile(fileName);

    bool bUserAuthoritySetting = false;

    WideString EventDescription[MAX_UI_ACCESS_EVENT];
    EventDescription[ACCESS_PGM_EVT_MAINFORM_LOG_IN] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_01;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_PRODUCT_INFO] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_02;
    EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_NEW_PRODUCT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_03;
    EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_SEARCH_PRODUCT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_04;
    EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_NAME] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_05;
    EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_CLONE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_06;
    EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_DATA_INFO] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_07;
    EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_DELETE_DATA_INFO] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_08;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_MACHINE_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_09;
    EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_NEW_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_10;
    EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_EXIST_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_11;
    EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_ADJUST_VALUE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_12;
    EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_TEST] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_13;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_CAPTURE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_14;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_START] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_15;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_STOP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_16;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_BRIGHTNESS_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_17;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_SPEED_CONTROL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_18;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_AREA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_19;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_RESOLUTION_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_20;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_3D_CAMERA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_21;
    EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_CAMERA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_22;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_FEATURE_EXTRACTION] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_23;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_FIRST_STUDY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_24;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_SECOND_STUDY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_25;
    EventDescription[ACCESS_PGM_EVT_SEC_STUDY_FORM_ADJUST_VALUE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_26;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_INSPECTION] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_27;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_INSPECTION_HISTORY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_28;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_LOG_OUT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_29;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_CLEANING_STANDBY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_30;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_DEVICE_CONTROL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_31;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_USER_ADMINISTRATION] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_32;
    EventDescription[ACCESS_PGM_EVT_USERRESISTERFORM_REGIST] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_33;
    EventDescription[ACCESS_PGM_EVT_USERRESISTERFORM_DELETE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_34;
    EventDescription[ACCESS_PGM_EVT_USERRESISTERFORM_CHANGE_PW] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_35;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_ENV_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_36;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_COM_SYS_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_37;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_PGM_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_38;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_SECURITY_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_39;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_AUTHORITY_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_40;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_COMM_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_41;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_STORAGE_SPACE_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_42;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_RUN_DMU] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_43;
    EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_AIR_CONTROL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_44;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_SYSTEM_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_45;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_AUDIT_TRAIL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_46;
    EventDescription[ACCESS_PGM_EVT_MAINFORM_EXIT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_47;
    EventDescription[ACCESS_PGM_EVT_INSPECTIONFORM_GRADESETTING] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_48;
    EventDescription[ACCESS_PGM_EVT_INSPECTIONFORM_CAMERA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_49;

    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_LOG_IN] = "1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_PRODUCT_INFO] = "2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_NEW_PRODUCT] = "2.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_SEARCH_PRODUCT] = "2.2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_NAME] = "2.2.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_CLONE] = "2.2.2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_DATA_INFO] = "2.2.3.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_DELETE_DATA_INFO] = "2.2.4.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_MACHINE_SETUP] = "3.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_NEW_SETUP] = "3.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_EXIST_SETUP] = "3.2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_ADJUST_VALUE] = "3.3.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_TEST] = "3.4.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_CAPTURE] = "4.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_START] = "4.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_STOP] = "4.2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_BRIGHTNESS_SETUP] = "4.3.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_SPEED_CONTROL] = "4.4.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_AREA_SETUP] = "4.5.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_RESOLUTION_SETUP] = "4.6.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_3D_CAMERA_SETUP] = "4.7.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_CAMERA_SETUP] = "4.8.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_FEATURE_EXTRACTION] = "5.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_FIRST_STUDY] = "6.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_SECOND_STUDY] = "7.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_SEC_STUDY_FORM_ADJUST_VALUE] = "7.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_INSPECTION] = "8.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_INSPECTION_HISTORY] = "9.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_LOG_OUT] = "10.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_CLEANING_STANDBY] = "11.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_DEVICE_CONTROL] = "12.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_USER_ADMINISTRATION] = "13.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_USERRESISTERFORM_REGIST] = "13.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_USERRESISTERFORM_DELETE] = "13.2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_USERRESISTERFORM_CHANGE_PW] = "13.3.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_ENV_SETUP] = "14.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_COM_SYS_SETUP] = "14.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_PGM_SETUP] = "14.1.1.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_SECURITY_SETUP] = "14.1.2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_AUTHORITY_SETUP] = "14.1.3.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_COMM_SETUP] = "14.2.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_STORAGE_SPACE_SETUP] = "14.3.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_RUN_DMU] = "14.4.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_AIR_CONTROL] = "14.5.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_SYSTEM_SETUP] = "15.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_AUDIT_TRAIL] = "16.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_EXIT] = "17.";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_INSPECTIONFORM_GRADESETTING] = "8.1";
    ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_INSPECTIONFORM_CAMERA_SETUP] = "8.2";

		if (iniFile)
    {
      ProgramAccessAuthorityData.SystemAuthorityCount = iniFile->ReadInteger("Authority Level", "System Authority Count", 4);

      if(DefaultLCID == 1028)
      {
  		ProgramAccessAuthorityData.ProgramAccessAuthorityName[0] = ENVIRONMENT_RETURNSTR_07;
  		ProgramAccessAuthorityData.ProgramAccessAuthorityName[1] = ENVIRONMENT_RETURNSTR_01; //"ADMINISTRATOR";
  		ProgramAccessAuthorityData.ProgramAccessAuthorityName[2] = ENVIRONMENT_RETURNSTR_05; //"MANAGER";
  		ProgramAccessAuthorityData.ProgramAccessAuthorityName[3] = ENVIRONMENT_RETURNSTR_06; //"OPERATOR";
      }
      else
      {
      	for(int AuthorityID = 0; AuthorityID < ProgramAccessAuthorityData.SystemAuthorityCount; AuthorityID++)
      	{
        	ProgramAccessAuthorityData.ProgramAccessAuthorityName[AuthorityID] = iniFile->ReadString("Authority Name", "Authority Name " + IntToStr(AuthorityID + 1), "");
      	}
      }

      /*
      // ini에서 읽어오는 방식이 아닌 PC실행 시 다국어 ID에서 삽입하는 방식으로 변경
      for(int EventID = 0; EventID < MAX_UI_ACCESS_EVENT; EventID++)
      {
        ProgramAccessAuthorityData.ProgramAccessEventDescription[EventID] = iniFile->ReadString("Event Description", "Event Description " + IntToStr(EventID + 1), "");
      }
      */
      for(int EventID = 0; EventID < MAX_UI_ACCESS_EVENT; EventID++)
      {
        ProgramAccessAuthorityData.ProgramAccessEventDescription[EventID] = EventDescription[EventID];
      }

      for(int AuthorityID = 0; AuthorityID < ProgramAccessAuthorityData.SystemAuthorityCount; AuthorityID++)
      {
        for(int EventID = 0; EventID < MAX_UI_ACCESS_EVENT; EventID++)
        {
          ProgramAccessAuthorityData.ProgramAccessAuthorityTable[AuthorityID][EventID] = iniFile->ReadBool("Event Access Authority", "Authority ID[" + IntToStr(AuthorityID + 1) + "] Event[" + IntToStr(EventID + 1) + "] Enabled", true);
        }
      }

      bUserAuthoritySetting = iniFile->ReadBool("Initial Authority Complete", "State", false);
    }

    delete iniFile;

    return bUserAuthoritySetting;
  }
}

//---------------------------------------------------------------------------
bool __fastcall WriteSystemUserAuthorityInformation(AnsiString fileName)
{
  TIniFile *iniFile = new TIniFile(fileName);

  if (iniFile)
  {
    iniFile->WriteInteger("Authority Level", "System Authority Count", ProgramAccessAuthorityData.SystemAuthorityCount);

    for(int AuthorityID = 0; AuthorityID < ProgramAccessAuthorityData.SystemAuthorityCount; AuthorityID++)
    {
      iniFile->WriteString("Authority Name", "Authority Name " + IntToStr(AuthorityID + 1), ProgramAccessAuthorityData.ProgramAccessAuthorityName[AuthorityID]);
    }

    /*
    // ini에서 읽어오는 방식이 아닌 PC실행 시 다국어 ID에서 삽입하는 방식으로 변경
    for(int EventID = 0; EventID < MAX_UI_ACCESS_EVENT; EventID++)
    {
      iniFile->WriteString("Event Description", "Event Description " + IntToStr(EventID + 1), ProgramAccessAuthorityData.ProgramAccessEventDescription[EventID]);
    }
    */

    for(int AuthorityID = 0; AuthorityID < ProgramAccessAuthorityData.SystemAuthorityCount; AuthorityID++)
    {
      for(int EventID = 0; EventID < MAX_UI_ACCESS_EVENT; EventID++)
      {
        iniFile->WriteBool("Event Access Authority", "Authority ID[" + IntToStr(AuthorityID + 1) + "] Event[" + IntToStr(EventID + 1) + "] Enabled", ProgramAccessAuthorityData.ProgramAccessAuthorityTable[AuthorityID][EventID]);
      }
    }
  }

  delete iniFile;
}

//---------------------------------------------------------------------------
void __fastcall MakeSystemUserAuthorityInitInformation()
{
  memset(&ProgramAccessAuthorityData, 0, sizeof(TProgramAccessAuthorityData));

  WideString EventDescription[MAX_UI_ACCESS_EVENT];
  EventDescription[ACCESS_PGM_EVT_MAINFORM_LOG_IN] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_01;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_PRODUCT_INFO] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_02;
  EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_NEW_PRODUCT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_03;
  EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_SEARCH_PRODUCT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_04;
  EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_NAME] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_05;
  EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_CLONE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_06;
  EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_DATA_INFO] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_07;
  EventDescription[ACCESS_PGM_EVT_PRODUCTINPUTFORM_DELETE_DATA_INFO] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_08;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_MACHINE_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_09;
  EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_NEW_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_10;
  EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_EXIST_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_11;
  EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_ADJUST_VALUE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_12;
  EventDescription[ACCESS_PGM_EVT_MACHINESETUPFORM_TEST] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_13;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_CAPTURE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_14;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_START] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_15;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_STOP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_16;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_BRIGHTNESS_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_17;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_SPEED_CONTROL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_18;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_AREA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_19;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_RESOLUTION_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_20;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_3D_CAMERA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_21;
  EventDescription[ACCESS_PGM_EVT_CALIBRATIONFORM_CAMERA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_22;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_FEATURE_EXTRACTION] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_23;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_FIRST_STUDY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_24;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_SECOND_STUDY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_25;
  EventDescription[ACCESS_PGM_EVT_SEC_STUDY_FORM_ADJUST_VALUE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_26;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_INSPECTION] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_27;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_INSPECTION_HISTORY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_28;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_LOG_OUT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_29;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_CLEANING_STANDBY] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_30;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_DEVICE_CONTROL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_31;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_USER_ADMINISTRATION] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_32;
  EventDescription[ACCESS_PGM_EVT_USERRESISTERFORM_REGIST] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_33;
  EventDescription[ACCESS_PGM_EVT_USERRESISTERFORM_DELETE] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_34;
  EventDescription[ACCESS_PGM_EVT_USERRESISTERFORM_CHANGE_PW] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_35;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_ENV_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_36;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_COM_SYS_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_37;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_PGM_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_38;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_SECURITY_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_39;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_AUTHORITY_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_40;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_COMM_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_41;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_STORAGE_SPACE_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_42;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_RUN_DMU] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_43;
  EventDescription[ACCESS_PGM_EVT_ENVSETUPFORM_AIR_CONTROL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_44;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_SYSTEM_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_45;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_AUDIT_TRAIL] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_46;
  EventDescription[ACCESS_PGM_EVT_MAINFORM_EXIT] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_47;
  EventDescription[ACCESS_PGM_EVT_INSPECTIONFORM_GRADESETTING] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_48;
  EventDescription[ACCESS_PGM_EVT_INSPECTIONFORM_CAMERA_SETUP] = SYSTEM_AUTHORITY_EVENT_DESCRIPTION_49;

  ProgramAccessAuthorityData.SystemAuthorityCount = 4;

  ProgramAccessAuthorityData.ProgramAccessAuthorityName[0] = "SYSTEM";
  ProgramAccessAuthorityData.ProgramAccessAuthorityName[1] = "ADMINISTRATOR";
  ProgramAccessAuthorityData.ProgramAccessAuthorityName[2] = "MANAGER";
  ProgramAccessAuthorityData.ProgramAccessAuthorityName[3] = "OPERATOR";
  //ProgramAccessAuthorityData.ProgramAccessAuthorityName[1] = ENVIRONMENT_RETURNSTR_01; //"ADMINISTRATOR";
  //ProgramAccessAuthorityData.ProgramAccessAuthorityName[2] = ENVIRONMENT_RETURNSTR_05; //"MANAGER";
  //ProgramAccessAuthorityData.ProgramAccessAuthorityName[3] = ENVIRONMENT_RETURNSTR_06; //"OPERATOR";

  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_LOG_IN] = "1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_PRODUCT_INFO] = "2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_NEW_PRODUCT] = "2.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_SEARCH_PRODUCT] = "2.2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_NAME] = "2.2.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_CLONE] = "2.2.2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_DATA_INFO] = "2.2.3.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_PRODUCTINPUTFORM_DELETE_DATA_INFO] = "2.2.4.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_MACHINE_SETUP] = "3.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_NEW_SETUP] = "3.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_EXIST_SETUP] = "3.2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_ADJUST_VALUE] = "3.3.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MACHINESETUPFORM_TEST] = "3.4.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_CAPTURE] = "4.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_START] = "4.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_CAPTURE_STOP] = "4.2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_BRIGHTNESS_SETUP] = "4.3.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_SPEED_CONTROL] = "4.4.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_AREA_SETUP] = "4.5.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_RESOLUTION_SETUP] = "4.6.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_3D_CAMERA_SETUP] = "4.7.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_CALIBRATIONFORM_CAMERA_SETUP] = "4.8.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_FEATURE_EXTRACTION] = "5.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_FIRST_STUDY] = "6.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_SECOND_STUDY] = "7.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_SEC_STUDY_FORM_ADJUST_VALUE] = "7.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_INSPECTION] = "8.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_INSPECTION_HISTORY] = "9.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_LOG_OUT] = "10.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_CLEANING_STANDBY] = "11.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_DEVICE_CONTROL] = "12.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_USER_ADMINISTRATION] = "13.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_USERRESISTERFORM_REGIST] = "13.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_USERRESISTERFORM_DELETE] = "13.2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_USERRESISTERFORM_CHANGE_PW] = "13.3.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_ENV_SETUP] = "14.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_COM_SYS_SETUP] = "14.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_PGM_SETUP] = "14.1.1.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_SECURITY_SETUP] = "14.1.2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_AUTHORITY_SETUP] = "14.1.3.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_COMM_SETUP] = "14.2.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_STORAGE_SPACE_SETUP] = "14.3.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_RUN_DMU] = "14.4.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_ENVSETUPFORM_AIR_CONTROL] = "14.5.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_SYSTEM_SETUP] = "15.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_AUDIT_TRAIL] = "16.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_MAINFORM_EXIT] = "17.";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_INSPECTIONFORM_GRADESETTING] = "8.1";
  ProgramAccessAuthorityData.ProgramAccessEventSerialNumber[ACCESS_PGM_EVT_INSPECTIONFORM_CAMERA_SETUP] = "8.2";

  for(int EventID = 0; EventID < MAX_UI_ACCESS_EVENT; EventID++)
  {
    ProgramAccessAuthorityData.ProgramAccessEventDescription[EventID] = EventDescription[EventID];
  }

  for(int AuthorityID = 0; AuthorityID < ProgramAccessAuthorityData.SystemAuthorityCount; AuthorityID++)
  {
    for(int EventID = 0; EventID < MAX_UI_ACCESS_EVENT; EventID++)
    {
      ProgramAccessAuthorityData.ProgramAccessAuthorityTable[AuthorityID][EventID] = true;
    }
  }

  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[1][ACCESS_PGM_EVT_MAINFORM_DEVICE_CONTROL] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[1][ACCESS_PGM_EVT_MAINFORM_SYSTEM_SETUP] = false;

  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_MAINFORM_DEVICE_CONTROL] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_MAINFORM_SYSTEM_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_NAME] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_PRODUCTINPUTFORM_DELETE_DATA_INFO] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_USERRESISTERFORM_REGIST] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_USERRESISTERFORM_DELETE] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_COM_SYS_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_PGM_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_SECURITY_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_AUTHORITY_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_COMM_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_STORAGE_SPACE_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_RUN_DMU] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_ENVSETUPFORM_AIR_CONTROL] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[2][ACCESS_PGM_EVT_MAINFORM_AUDIT_TRAIL] = false;
  
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_MAINFORM_DEVICE_CONTROL] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_MAINFORM_SYSTEM_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_NAME] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_PRODUCTINPUTFORM_DELETE_DATA_INFO] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_PRODUCTINPUTFORM_MAKE_CLONE] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_PRODUCTINPUTFORM_CHANGE_DATA_INFO] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_MACHINESETUPFORM_ADJUST_VALUE] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_USERRESISTERFORM_REGIST] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_USERRESISTERFORM_DELETE] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_COM_SYS_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_PGM_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_SECURITY_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_AUTHORITY_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_COMM_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_STORAGE_SPACE_SETUP] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_RUN_DMU] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_ENVSETUPFORM_AIR_CONTROL] = false;
  ProgramAccessAuthorityData.ProgramAccessAuthorityTable[3][ACCESS_PGM_EVT_MAINFORM_AUDIT_TRAIL] = false;
}
//-------------------------------------------------------------------------------------------------------
bool Read_InspectionReportData(AnsiString inspectionReportFileName , NFA_INSPECTION_REPORT_STRUCT & Report)
{
  // Version 0 Data size
  /*
    NFA_DATA_REPORT Data;  - 1040
    NFA_DATA_REPORT_GRADE GradeData; - 256_v0  -> 561_v1
    NFA_DATA_REPORT_DEFECT_SERIES_COUNT DefectSeriesCount; - 200_v0 -> 400_v1
    NFA_DATA_REPORT_SUB SubData; - 48_v0 -> 168_v1
  */
  memset(&Report,0,sizeof(NFA_INSPECTION_REPORT_STRUCT));

	TFileStream *fileStream = NULL;
  try
	{
    fileStream = new TFileStream(inspectionReportFileName, fmOpenRead);

    fileStream->Read(&Report.Fmt,sizeof(NFA_DATA_FMT));

    if(strncmp(Report.Fmt.ChunkID,"INSR",4)==0)
    {
      if(Report.Fmt.Version == INSPECTION_REPORT_DATA_VER) // 버전이 같으면 한번에
      {
        fileStream->Seek(0,soFromBeginning);
        fileStream->Read(&Report,sizeof(NFA_INSPECTION_REPORT_STRUCT));
      }
      else
      {
        // 데이터가 있는데 버전이 다른경우 . ex ) 현재 v1 -> 추후 v2 변경 시 수정 필요
        // 상황에 따라서 데이터가 바뀔 수 있다고 알려줘야하나?
        // 대처 방안은 ? 일단은 데이터가 다 온전하다는 조건하에 진행

        // 1. DATA
        fileStream->Read(&Report.Data,sizeof(char)*8);
        if(strcpy(Report.Data.ChunkID,"RD  "))
        {
          int ReadSize = sizeof(NFA_DATA_REPORT) - 8 ;
          if(sizeof(NFA_DATA_REPORT) > Report.Data.ChunkSize)
          {
            ReadSize = sizeof(NFA_DATA_REPORT);
            ReadSize = Report.Data.ChunkSize; // 버전이 다른 문서에 저장 된 구조체 사이즈가 작을 경우 작은 사이즈로 읽는다.
          }
          fileStream->Read(((char*)&Report.Data+8),ReadSize);
        }
        else
        {
          // ERROR
        }

        // 2. GRADE
        fileStream->Read(&Report.GradeData,sizeof(char)*8);
        if(strcpy(Report.GradeData.ChunkID,"RGD "))
        {
          int ReadSize = sizeof(NFA_DATA_REPORT_GRADE) - 8 ;
          if(sizeof(NFA_DATA_REPORT_GRADE) > Report.GradeData.ChunkSize)
          {
            ReadSize = sizeof(NFA_DATA_REPORT_GRADE);
            ReadSize = Report.GradeData.ChunkSize; // 버전이 다른 문서에 저장 된 구조체 사이즈가 작을 경우 작은 사이즈로 읽는다.
          }
          fileStream->Read(((char*)&Report.GradeData+8),ReadSize);
        }
        else
        {
          // ERROR
        }

        // 3. DEFECT SERIES
        fileStream->Read(&Report.DefectSeriesCount,sizeof(char)*8);
        if(strcpy(Report.DefectSeriesCount.ChunkID,"RDDS"))
        {
          int ReadSize = sizeof(NFA_DATA_REPORT_DEFECT_SERIES_COUNT) - 8 ;
          if(sizeof(NFA_DATA_REPORT_DEFECT_SERIES_COUNT) > Report.DefectSeriesCount.ChunkSize)
          {
            ReadSize = sizeof(NFA_DATA_REPORT_DEFECT_SERIES_COUNT);
            ReadSize = Report.DefectSeriesCount.ChunkSize; // 버전이 다른 문서에 저장 된 구조체 사이즈가 작을 경우 작은 사이즈로 읽는다.
          }
          fileStream->Read(((char*)&Report.DefectSeriesCount+8),ReadSize);
        }
        else
        {
          // ERROR
        }

        // 4. SUB DATA
        fileStream->Read(&Report.SubData,sizeof(char)*8);
        if(strcpy(Report.SubData.ChunkID,"RDS "))
        {
          int ReadSize = sizeof(NFA_DATA_REPORT_SUB) - 8 ;
          if(sizeof(NFA_DATA_REPORT_SUB) > Report.SubData.ChunkSize)
          {
            ReadSize = sizeof(NFA_DATA_REPORT_SUB);
            ReadSize = Report.SubData.ChunkSize; // 버전이 다른 문서에 저장 된 구조체 사이즈가 작을 경우 작은 사이즈로 읽는다.
          }
          fileStream->Read(((char*)&Report.SubData+8),ReadSize);
        }
        else
        {
          // ERROR
        }

        if (FileExists(inspectionReportFileName))
        {
          DeleteFile(inspectionReportFileName.c_str());
        }

        Create_Report_Data(Report,inspectionReportFileName);

      }
      delete fileStream;
    }
    else
    {
      // Version 0 만 해당
      int V0RerportGradeDataSize = 256;
      int V0RerportDefDataSize = 200;
      int V0RerportSubDataSize = 48;

      memset(&Report,0,sizeof(Report));
      // FMT SET
      strcpy(Report.Fmt.ChunkID,"INSR");
      Report.Fmt.ChunkSize = 16; // 16 fix
      Report.Fmt.Version = INSPECTION_REPORT_DATA_VER;

      // 이전 데이터 Load
      // 이전 구조체 사이즈를 사용해서 v1 과 비교
      int NewChunkSize = 8;
      fileStream->Seek(0,soFromBeginning);

      // 1.DATA
      strcpy(Report.Data.ChunkID,"RD  ");
      Report.Data.ChunkSize = sizeof(Report.Data)-8;
      fileStream->Read(((char*)&Report.Data)+NewChunkSize,sizeof(NFA_DATA_REPORT)-NewChunkSize);
      // 2.GRADE
      strcpy(Report.GradeData.ChunkID,"RGD ");
      Report.GradeData.ChunkSize = sizeof(Report.GradeData)-8;
      fileStream->Read(((char*)&Report.GradeData)+NewChunkSize,V0RerportGradeDataSize);
      // 3.DEFECT SERIES
      strcpy(Report.DefectSeriesCount.ChunkID,"RDDS");
      Report.DefectSeriesCount.ChunkSize = sizeof(Report.DefectSeriesCount)-8;
      fileStream->Read(Report.DefectSeriesCount.DefectSeriesCount,V0RerportDefDataSize);
      // 4.SUB DATA
      strcpy(Report.SubData.ChunkID,"RDS ");
      Report.SubData.ChunkSize = sizeof(Report.SubData)-8;
      fileStream->Read(((char*)&Report.SubData)+NewChunkSize,V0RerportSubDataSize);
      delete fileStream;

      AnsiString NewFileName = inspectionReportFileName+"_old";
      if (FileExists(inspectionReportFileName))
      {
        RenameFile(inspectionReportFileName, inspectionReportFileName.SubString(0,inspectionReportFileName.Length()-4)+".Conv_old");
        Create_Report_Data(Report,inspectionReportFileName);
      }
    }

  }
  catch(...)
  {
    if (fileStream) delete fileStream;
    return false;
  }
  return true;
}

void Create_Report_Data(NFA_INSPECTION_REPORT_STRUCT Report,AnsiString FileName)
{
  TFileStream*fileStream = NULL;
  try
  {
    int NewChunkSize = 8;
    
    // FMT SET
    strcpy(Report.Fmt.ChunkID,"INSR");
    Report.Fmt.ChunkSize = 16; // 16 fix
    Report.Fmt.Version = INSPECTION_REPORT_DATA_VER;

    // 1.DATA
    strcpy(Report.Data.ChunkID,"RD  ");
    Report.Data.ChunkSize = sizeof(Report.Data)-8;
    // 2.GRADE
    strcpy(Report.GradeData.ChunkID,"RGD ");
    Report.GradeData.ChunkSize = sizeof(Report.GradeData)-8;
    // 3.DEFECT SERIES
    strcpy(Report.DefectSeriesCount.ChunkID,"RDDS");
    Report.DefectSeriesCount.ChunkSize = sizeof(Report.DefectSeriesCount)-8;
    // 4.SUB DATA
    strcpy(Report.SubData.ChunkID,"RDS ");
    Report.SubData.ChunkSize = sizeof(Report.SubData)-8;

    // FILE CREATE
    fileStream = new TFileStream(FileName, fmCreate);
    fileStream->Write(&Report, sizeof(NFA_INSPECTION_REPORT_STRUCT));
    delete fileStream;
  }
  catch(...)
  {
    if (fileStream) delete fileStream;
  }
}

/*
int ConvertCameraIndex(int globalCameraIndex, const char* ConvertString)
{

  ConvertString = "SD2";

  switch(globalCameraIndex)
  {
    case 0 :
    ConvertString = "SD1";
    break;


  }

  return ConvertString;
}
*/

AnsiString ConvertCameraIndex(int globalCameraIndex)
{
  AnsiString ConvertString;
  ConvertString = SystemCameraID[globalCameraIndex];

  return ConvertString;
}

int ComponentReposition(int type, int Left1, int Left2, int Width)
{
  int MoveD;
  switch(type)
  {
    case 1 :
    MoveD = Width / 2;
    return MoveD;
    break;
    case 2 :
    MoveD = ((Left2 + Width)-Left1)/2;
    return MoveD;
    break;
    case 3 :
    MoveD = Left2 - Left1;
    return MoveD;
    break;
    case 4 :
    MoveD = Width;
    return MoveD;
    break;
  }

}
//-----------------------------------------------------------------------
void __fastcall ReadSystemCameraOffsetImage(int *gainlist)
{
  bool globalOffsetSW = false;
  memset(SystemOffsetImage, 0, SYSTEM_TOTAL_CAMERA_COUNT * (SYSTEM_CAMERA_WIDTH / 2) * (SYSTEM_CAMERA_HEIGHT / 2));
  memset(SystemImageOffsetSWCal,0,sizeof(int)*SYSTEM_TOTAL_CAMERA_COUNT);
  bool bExistAllImage = true;

  AnsiString imageDir, fileName;
  AnsiString RootPath;
  RootPath = ProgramPath.Env;

  for (int cameraIndex = 1; cameraIndex <= SYSTEM_TOTAL_CAMERA_COUNT; cameraIndex++)
  {
    if(cameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX  && cameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX)
    {
      if (CameraMapInfo[cameraIndex - 1].CameraInspectPosition < CAMERA_POSITION_DISCONNECT)
      {
        imageDir = RootPath + "\\OFFSETIMAGE\\GAIN" + IntToStr(gainlist[cameraIndex-1]);
        fileName = imageDir + "\\Camera" + IntToStr(cameraIndex) + "_OffSet.bmp";

        if (!FileExists(fileName))
        {
          bExistAllImage = false;
          break;
        }
        else
        {
          SystemImageOffsetSWCal[cameraIndex - 1] = 1;
        }
      }
    }
  }

  if (bExistAllImage)
  {
    globalOffsetSW = true;
  }

  if (globalOffsetSW)
  {
    int halfImageWidth = SYSTEM_CAMERA_WIDTH / 2;

    Graphics::TBitmap *img2;
    img2 = new Graphics::TBitmap();

    img2->Width = SYSTEM_CAMERA_WIDTH;
    img2->Height = SYSTEM_CAMERA_HEIGHT;
    img2->PixelFormat = pf24bit;

    Byte *ptr;

    int x, y;
    int tempAddress;
    int tempAddress2;

    unsigned char tempOffsetImage[SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT];

    for (int cameraIndex = 1; cameraIndex <= SYSTEM_TOTAL_CAMERA_COUNT; cameraIndex++)
    {
      if(cameraIndex != SD1_3D_FRONT_FACE_CAMERA_INDEX  && cameraIndex != SD2_3D_FRONT_FACE_CAMERA_INDEX)
      {
        if (CameraMapInfo[cameraIndex - 1].CameraInspectPosition < CAMERA_POSITION_DISCONNECT)
        {
          memset(tempOffsetImage, 0, SYSTEM_CAMERA_WIDTH * SYSTEM_CAMERA_HEIGHT);

          imageDir = RootPath + "\\OFFSETIMAGE\\GAIN" + IntToStr(gainlist[cameraIndex-1]);
          fileName = imageDir + "\\Camera" + IntToStr(cameraIndex) + "_OffSet.bmp";

          img2->LoadFromFile(fileName);

          for (y = 0; y < MAX_IMAGE_HEIGHT; y++)
          {
            ptr = (Byte*)img2->ScanLine[y];
            for (x = 0; x < MAX_IMAGE_WIDTH; x++)
            {
              tempAddress = MAX_IMAGE_WIDTH * y + x;
              tempOffsetImage[tempAddress] = ptr[3 * x + 1];
            }
          }

          int value;
          for (y = 2; y < MAX_IMAGE_HEIGHT - 2; y += 2)
          {
            for (x = 2; x < MAX_IMAGE_WIDTH - 2; x += 2)
            {
              tempAddress = halfImageWidth * (y / 2) + (x / 2);
              tempAddress2 = MAX_IMAGE_WIDTH * y + x;

              value = tempOffsetImage[tempAddress2] +
                tempOffsetImage[tempAddress2 - 1] +
                tempOffsetImage[tempAddress2 + 1] +
                tempOffsetImage[tempAddress2 - MAX_IMAGE_WIDTH] +
                tempOffsetImage[tempAddress2 + MAX_IMAGE_WIDTH];

              SystemOffsetImage[cameraIndex - 1][tempAddress] = value / 5;
            }
          }
        }
      }
    }

    delete img2;
  }
}
//-----------------------------------------------------------------------
void __fastcall SetScreenPosition(TTntForm *tempForm)
{
  const int DesignedWidth = 1080;
  const int DesignedHeight = 1920;

  tempForm->Align = alCustom;
  if (Screen->MonitorCount >= 2)
  {
    unsigned int minDiff = 0xFFFFFFFF;
    unsigned int maxSize = 0;
    int mindst = 0;
    int maxdst = 0;
    for(int scnIdx = 0; scnIdx < Screen->MonitorCount; scnIdx++)
    {
      int width = abs(DesignedWidth - Screen->Monitors[scnIdx]->Width) + 1;
      int height = abs(DesignedHeight - Screen->Monitors[scnIdx]->Height) + 1;

      if(minDiff > width * height)
      {
        minDiff = width * height;
        mindst = scnIdx;
      }

      if(maxSize < Screen->Monitors[scnIdx]->Width * Screen->Monitors[scnIdx]->Height)
      {
        maxSize = Screen->Monitors[scnIdx]->Width * Screen->Monitors[scnIdx]->Height;
        maxdst = scnIdx;
      }
    }

    if(minDiff < 10)
    {
      // exist 1080*1920 screen
      tempForm->Top = Screen->Monitors[mindst]->Top;
      tempForm->Left = Screen->Monitors[mindst]->Left;
      tempForm->Width = Screen->Monitors[mindst]->Width;
      tempForm->Height = Screen->Monitors[mindst]->Height;
    }
    else
    {
      // max size screen
      tempForm->Top = Screen->Monitors[maxdst]->Top;
      tempForm->Left = Screen->Monitors[maxdst]->Left;
      tempForm->Width = Screen->Monitors[maxdst]->Width;
      tempForm->Height = Screen->Monitors[maxdst]->Height;
    }
  }
  else
  {
    tempForm->Top = 0;
    tempForm->Left = 0;
  }
}

//---------------------------------------------------------------------------
void __fastcall ReadTPB_BoardExistInfo()
{
	TIniFile *iniFile;
	iniFile = new TIniFile(ProgramPath.Env + "\\SystemInfor.ini");

	if(iniFile)
	{
		TPBSystemInfo.boardExist	= iniFile->ReadInteger("TPB System", "Board Exist", 0);
	}

  delete iniFile;
}
