#ifndef __HCM4A_CalcFs4A_dtHcmIN_h_
#define __HCM4A_CalcFs4A_dtHcmIN_h_

#include <Core/Core.h>
#include <plugin/pcre/Pcre.h> // RegExp
#include <Xlnt/Xlnt.h>

#include "common.h"

using namespace Upp;

namespace HCMFS{

/// checking the string for mask compliance
inline bool CheckOnMask(const String& str, const String& mask){
	String p = "(\\b" + mask + "\\b)";
	RegExp r0(p);
	if(!r0.Match(TrimBoth(str))){
		return false;
	}
	return true;
}
//!---------------------------------------------------------------------------------------------

/*
/// parsing and checking coordinates
struct HcmLonLat{
	bool IsLonGrad(const String& lon)const{return IsStrToInt(lon, 0, 180);};
	bool IsLatGrad(const String& lat)const{return IsStrToInt(lat, 0, 90);};
	String GetLon()const{return _lon;}
	String GetLat()const{return _lat;}
	HcmLonLat():_lon(""), _lat(""){};
	HcmLonLat(const String& aLon, const String& aLat);
	HcmLonLat(const String& aCoord);
protected:
	void Clear(){_lon = ""; _lat = "";};
	String NormCoord(const String& aCoord);
	String NormLon(const String& aCoord);
	String NormLat(const String& aCoord);
	String _lon;
	String _lat;
};
/// 037e034704n2010 -> lon = 037e0347; lat = 04n2010
HcmLonLat::HcmLonLat(const String& aCoord){
	Clear();
	String tmpStr = NormCoord(aCoord);
	if(tmpStr.IsEmpty()) return;
	_lon = NormLon(tmpStr.Mid(0, 8));
	_lat = NormLat(tmpStr.Mid(8, 7));
}
HcmLonLat::HcmLonLat(const String& aLon, const String& aLat){
	Clear();
	String tmpLon = NormCoord(aLon);
	if(tmpLon.IsEmpty()) return;
	_lon = tmpLon;
	if(CheckOnMask(aLat, "[0-9]{2}[NnSs][0-9]{4}")) _lat = aLat;
}
String HcmLonLat::NormCoord(const String& aCoord){
	if(CheckOnMask(aCoord, "[0-9]{3}[EeWw][0-9]{6}[NnSs][0-9]{4}")){
		return aCoord;
	}
	if(CheckOnMask(aCoord, "[0-9]{2}[EeWw][0-9]{6}[NnSs][0-9]{4}")){
		return String() << "0" << aCoord;
	}
	if(CheckOnMask(aCoord, "[0-9]{3}[EeWw][0-9]{4}")){
		return aCoord;
	}
	if(CheckOnMask(aCoord, "[0-9]{2}[EeWw][0-9]{4}")){
		return String() << "0" << aCoord;
	}
	if(CheckOnMask(aCoord, "[0-9]{2}[NnSs][0-9]{4}")){
		return aCoord;
	}
	if(CheckOnMask(aCoord, "[0-9]{1}[NnSs][0-9]{4}")){
		return String() << "0" << aCoord;
	}
	return aCoord;
}
String HcmLonLat::NormLon(const String& aCoord){
	if(CheckOnMask(aCoord, "[0-9]{3}[EeWw][0-9]{6}[NnSs][0-9]{4}")){
		return aCoord;
	}
	if(CheckOnMask(aCoord, "[0-9]{2}[EeWw][0-9]{6}[NnSs][0-9]{4}")){
		return String() << "0" << aCoord;
	}
	return aCoord;
}
String HcmLonLat::NormLat(const String& aCoord){
	if(CheckOnMask(aCoord, "[0-9]{2}[NnSs][0-9]{4}")){
		return aCoord;
	}
	if(CheckOnMask(aCoord, "[0-9]{1}[NnSs][0-9]{4}")){
		return String() << "0" << aCoord;
	}
	return aCoord;
}
//!---------------------------------------------------------------------------------------------
*/


String StrToStrLon(const String& aLon){
	if(CheckOnMask(aLon, "[0-9]{3}[EeWw][0-9]{4}")){
		if(IsStrToInt(aLon, 0, 180)) return aLon;
	}
	if(CheckOnMask(aLon, "[0-9]{2}[EeWw][0-9]{4}")){
		String lon = String() << "0" << aLon;
		if(IsStrToInt(lon, 0, 180)) return lon;
	}
	return "";
}
String StrToStrLat(const String& aLat){
	if(CheckOnMask(aLat, "[0-9]{2}[NnSs][0-9]{4}")){
		if(IsStrToInt(aLat, 0, 180)) return aLat;
	}
	if(CheckOnMask(aLat, "[0-9]{1}[NnSs][0-9]{4}")){
		String lat = String() << "0" << aLat;
		if(IsStrToInt(lat, 0, 180)) return lat;
	}
	return "";
}
String StrToStrCoord(const String& aCoord, String& sLon, String& sLat){
	// 036e533004n1701 = 036e5330 04n1701
	if(CheckOnMask(aCoord, "[0-9]{3}[EeWw][0-9]{6}[NnSs][0-9]{4}")){
		sLon = StrToStrLon(aCoord.Mid(0, 8));
		sLat = StrToStrLat(aCoord.Mid(8, 7));
		if(!sLon.IsEmpty() && !sLat.IsEmpty()) return String() << sLon << sLat;
	}
	// 36e533004n1701 = 0 << 36e5330 04n1701
	if(CheckOnMask(aCoord, "[0-9]{2}[EeWw][0-9]{6}[NnSs][0-9]{4}")){
		sLon = StrToStrLon(aCoord.Mid(0, 7));
		sLat = StrToStrLat(aCoord.Mid(7, 7));
		if(!sLon.IsEmpty() && !sLat.IsEmpty()) return String() << sLon << sLat;
	}
	// 036e53304n1701 = 036e5330 << 0 << 4n1701
	if(CheckOnMask(aCoord, "[0-9]{3}[EeWw][0-9]{5}[NnSs][0-9]{4}")){
		sLon = StrToStrLon(aCoord.Mid(0, 8));
		sLat = StrToStrLat(aCoord.Mid(8, 6));
		if(!sLon.IsEmpty() && !sLat.IsEmpty()) return String() << sLon << sLat;
	}
	// 36e53304n1701 = 0 << 36e5330 << 0 << 4n1701
	if(CheckOnMask(aCoord, "[0-9]{2}[EeWw][0-9]{5}[NnSs][0-9]{4}")){
		sLon = StrToStrLon(aCoord.Mid(0, 7));
		sLat = StrToStrLat(aCoord.Mid(7, 6));
		if(!sLon.IsEmpty() && !sLat.IsEmpty()) return String() << sLon << sLat;
	}
	return "";
}
//!---------------------------------------------------------------------------------------------







/// Mandatory field types
enum class FldMandat {OFF = 0, ON, TX, RX, IF};
inline FldMandat IntToFldMandat(int z){
	if(z == static_cast<int>(FldMandat::OFF)) return FldMandat::OFF;
	if(z == static_cast<int>(FldMandat::ON))  return FldMandat::ON;
	if(z == static_cast<int>(FldMandat::TX))  return FldMandat::TX;
	if(z == static_cast<int>(FldMandat::RX))  return FldMandat::RX;
	if(z == static_cast<int>(FldMandat::IF))  return FldMandat::IF;
	return FldMandat::OFF;
}
inline int FldMandatToInt(FldMandat z){
	return static_cast<int>(z);
}
inline String FldMandatToStr(FldMandat z){
	String rStr = "OFF";
	switch(z){
		case FldMandat::OFF:
			rStr = "OFF";
			break;
		case FldMandat::ON:
			rStr = "ON";
			break;
		case FldMandat::TX:
			rStr = "TX";
			break;
		case FldMandat::RX:
			rStr = "RX";
			break;
		case FldMandat::IF:
			rStr = "IF";
			break;
	}
	return rStr;
}
inline FldMandat StrToFldMandat(const String& str){
	if(ToUpper(str) == "OFF")	return FldMandat::OFF;
	if(ToUpper(str) == "ON")	return FldMandat::ON;
	if(ToUpper(str) == "TX")	return FldMandat::TX;
	if(ToUpper(str) == "RX")	return FldMandat::RX;
	if(ToUpper(str) == "IF")	return FldMandat::IF;
	return FldMandat::OFF;
}
inline bool IsFldMandat(const String& str){
	return
		(StrToFldMandat(ToUpper(str)) == FldMandat::TX)||
		(StrToFldMandat(ToUpper(str)) == FldMandat::RX)||
		(StrToFldMandat(ToUpper(str)) == FldMandat::OFF)||
		(StrToFldMandat(ToUpper(str)) == FldMandat::IF)||
		(StrToFldMandat(ToUpper(str)) == FldMandat::ON);
}
//! --------------------------------------------------------------------------------------------

/// Entity types
enum class HcmEntity {None, HEADER, TX, PRX, PTX, RX};
inline HcmEntity IntToHcmEntity(int z){
	if(z == static_cast<int>(HcmEntity::TX))  return HcmEntity::TX;
	if(z == static_cast<int>(HcmEntity::RX))  return HcmEntity::RX;
	if(z == static_cast<int>(HcmEntity::PRX)) return HcmEntity::PRX;
	if(z == static_cast<int>(HcmEntity::PTX)) return HcmEntity::PTX;
	return HcmEntity::None;
}
inline int HcmEntityToInt(HcmEntity z){
	return static_cast<int>(z);
}
inline String HcmEntityToStr(HcmEntity z){
	String rStr = "None";
	switch(z){
		case HcmEntity::HEADER:
			rStr = "HEADER";
			break;
		case HcmEntity::TX:
			rStr = "TX";
			break;
		case HcmEntity::RX:
			rStr = "RX";
			break;
		case HcmEntity::PRX:
			rStr = "PRX";
			break;
		case HcmEntity::PTX:
			rStr = "PTX";
			break;
		case HcmEntity::None:
			rStr = "None";
			break;
	}
	return rStr;
}
inline HcmEntity StrToHcmEntity(const String& str){
	if(ToUpper(str) == "HEADER")return HcmEntity::HEADER;
	if(ToUpper(str) == "TX")	return HcmEntity::TX;
	if(ToUpper(str) == "RX")	return HcmEntity::RX;
	if(ToUpper(str) == "PRX")	return HcmEntity::PRX;
	if(ToUpper(str) == "PTX")	return HcmEntity::PTX;
	return HcmEntity::None;
}
inline bool IsHcmEntity(const String& str){
	return
		(StrToHcmEntity(ToUpper(str)) == HcmEntity::TX)||
		(StrToHcmEntity(ToUpper(str)) == HcmEntity::RX)||
		(StrToHcmEntity(ToUpper(str)) == HcmEntity::PRX)||
		(StrToHcmEntity(ToUpper(str)) == HcmEntity::PTX);
}
inline HcmEntity ToHcmEntity(bool isTx, bool isPassive){
	if(isTx && !isPassive)  return HcmEntity::TX;
	if(isTx && isPassive)   return HcmEntity::PTX;
	if(!isTx && isPassive)  return HcmEntity::PRX;
	if(!isTx && !isPassive) return HcmEntity::RX;
	return HcmEntity::None;
}
//! --------------------------------------------------------------------------------------------

/// Fields value types
enum class FldType {STR, INT, FLOAT, DATE, VEC};
inline FldType IntToFldType(int z){
	if(z == static_cast<int>(FldType::STR))   return FldType::STR;
	if(z == static_cast<int>(FldType::INT))   return FldType::INT;
	if(z == static_cast<int>(FldType::FLOAT)) return FldType::FLOAT;
	if(z == static_cast<int>(FldType::DATE))  return FldType::DATE;
	if(z == static_cast<int>(FldType::VEC))  return FldType::VEC;
	return FldType::STR;
}
inline int FldTypeToInt(FldType z){
	return static_cast<int>(z);
}
inline String FldTypeToStr(FldType z){
	String rStr = "STR";
	switch(z){
		case FldType::STR:
			rStr = "STR";
			break;
		case FldType::INT:
			rStr = "INT";
			break;
		case FldType::FLOAT:
			rStr = "FLOAT";
			break;
		case FldType::DATE:
			rStr = "DATE";
			break;
		case FldType::VEC:
			rStr = "VEC";
			break;
	}
	return rStr;
}
inline FldType StrToFldType(const String& str){
	if(ToUpper(str) == "STR")	return FldType::STR;
	if(ToUpper(str) == "INT")	return FldType::INT;
	if(ToUpper(str) == "FLOAT")	return FldType::FLOAT;
	if(ToUpper(str) == "DATE")	return FldType::DATE;
	if(ToUpper(str) == "VEC")	return FldType::VEC;
	return FldType::STR;
}
inline bool IsFldType(const String& str){
	return
		(StrToFldType(ToUpper(str)) == FldType::STR)||
		(StrToFldType(ToUpper(str)) == FldType::INT)||
		(StrToFldType(ToUpper(str)) == FldType::FLOAT)||
		(StrToFldType(ToUpper(str)) == FldType::DATE)||
		(StrToFldType(ToUpper(str)) == FldType::VEC);
}
//! --------------------------------------------------------------------------------------------

/// Fields edit ctrl types
enum class FldEditType {NONE, STR, INT, FLOAT, DATE, LIST, BTN};
inline FldEditType IntToFldEditType(int z){
	if(z == static_cast<int>(FldEditType::NONE))  return FldEditType::NONE;
	if(z == static_cast<int>(FldEditType::STR))   return FldEditType::STR;
	if(z == static_cast<int>(FldEditType::INT))   return FldEditType::INT;
	if(z == static_cast<int>(FldEditType::FLOAT)) return FldEditType::FLOAT;
	if(z == static_cast<int>(FldEditType::DATE))  return FldEditType::DATE;
	if(z == static_cast<int>(FldEditType::LIST))  return FldEditType::LIST;
	if(z == static_cast<int>(FldEditType::BTN))   return FldEditType::BTN;
	return FldEditType::STR;
}
inline int FldEditTypeToInt(FldEditType z){
	return static_cast<int>(z);
}
inline String FldEditTypeToStr(FldEditType z){
	String rStr = "STR";
	switch(z){
		case FldEditType::NONE:
			rStr = "NONE";
			break;
		case FldEditType::STR:
			rStr = "STR";
			break;
		case FldEditType::INT:
			rStr = "INT";
			break;
		case FldEditType::FLOAT:
			rStr = "FLOAT";
			break;
		case FldEditType::DATE:
			rStr = "DATE";
			break;
		case FldEditType::LIST:
			rStr = "LIST";
			break;
		case FldEditType::BTN:
			rStr = "BTN";
			break;
	}
	return rStr;
}
inline FldEditType StrToFldEditType(const String& str){
	if(ToUpper(str) == "NONE")	return FldEditType::NONE;
	if(ToUpper(str) == "STR")	return FldEditType::STR;
	if(ToUpper(str) == "INT")	return FldEditType::INT;
	if(ToUpper(str) == "FLOAT")	return FldEditType::FLOAT;
	if(ToUpper(str) == "DATE")	return FldEditType::DATE;
	if(ToUpper(str) == "LIST")	return FldEditType::LIST;
	if(ToUpper(str) == "BTN")	return FldEditType::BTN;
	return FldEditType::STR;
}
//! --------------------------------------------------------------------------------------------

/// struct for working with lists
struct HcmLstRec{
	void Clear(){lst.Clear();}
	String Name()const{return name;}
	const VectorMap<String, String>& Lst()const{return lst;}
	int LoadCSV(const String& file);
	int LoadFirstValueCSV(const String& file);

	void Fill(DropList& drList)const;
	void Fill_2(DropList& drList)const;
	void Fill(DropGrid & drGrid)const;
	String GetLstValue(const String& code)const;
	HcmLstRec():name(""){Clear();}
	HcmLstRec(const String& name):name(name){Clear();}
	HcmLstRec(const String& name, const Vector<String>& vec);
	HcmLstRec(const HcmLstRec& rec):name(rec.name), lst(clone(rec.lst)){}
	HcmLstRec(const String& name, const String& file):name(name){LoadCSV(file);};
protected:
	String name;
	VectorMap<String, String> lst;
};
HcmLstRec::HcmLstRec(const String& name, const Vector<String>& vec):name(name){
	for(auto v: vec){
		lst.FindAdd(v, v);
	}
}
String HcmLstRec::GetLstValue(const String& code)const{
	int idx = lst.Find(code);
	if(idx == -1) return "";
	return lst[idx];
}

int HcmLstRec::LoadCSV(const String& file){
	lst.Clear();
	if(!FileExists(file)){
		LOG(Format("Error: File %s, not found", file));
		return 0;
	}
	FileIn f_in(file);
	while(!f_in.IsEof()){
		Vector<String> tmpVec;
        String tmpS = f_in.GetLine();
        if(!TrimBoth(tmpS).IsEmpty()){
			StringStream strm = StringStream() << tmpS;
			tmpVec = GetCsvLine(strm, C_RAZDEL, CHARSET_DEFAULT);
			if(tmpVec.GetCount() > 1)
				lst.Add(tmpVec[0], tmpVec[1]);
			else if(tmpVec.GetCount() > 0)
				lst.Add(tmpVec[0], tmpVec[0]);
        }
    }
    return lst.GetCount();
}
int HcmLstRec::LoadFirstValueCSV(const String& file){
	lst.Clear();
	if(!FileExists(file)){
		LOG(Format("Error: File %s, not found", file));
		return 0;
	}
	FileIn f_in(file);
	while(!f_in.IsEof()){
		Vector<String> tmpVec;
        String tmpS = f_in.GetLine();
        if(!TrimBoth(tmpS).IsEmpty()){
			StringStream strm = StringStream() << tmpS;
			tmpVec = GetCsvLine(strm, C_RAZDEL, CHARSET_DEFAULT);
			if(tmpVec.GetCount() > 0)
				lst.Add(tmpVec[0], tmpVec[0]);
        }
    }
    return lst.GetCount();
}

void HcmLstRec::Fill(DropList& drList)const{
	for(int i=0; i<lst.GetCount(); i++){
		drList.Add(lst.GetKey(i), lst[i]);
		// drList.Add(AttrText(lst.GetKey(i)).Ink(Black()).Paper(White()));
	}
}
void HcmLstRec::Fill_2(DropList& drList)const{
	for(int i=0; i<lst.GetCount(); i++){
		drList.Add(lst.GetKey(i), String() << lst.GetKey(i) << " | "<< lst[i]);
		// drList.Add(AttrText(lst.GetKey(i)).Ink(Black()).Paper(White()));
	}
}
void HcmLstRec::Fill(DropGrid & drGrid)const{
	drGrid.Clear();
	drGrid.ClearButton();
	drGrid.AddColumn("Code");
	drGrid.AddColumn("Name");
	for(int i=0; i<lst.GetCount(); i++){
		drGrid.Add(lst.GetKey(i), lst[i]);
	}
}
//!---------------------------------------------------------------------------------------

/// struct for storing lists
struct HcmLstData{
	const HcmLstRec& GetLst(const String& nameLst)const{
		static HcmLstRec tmpLst(nameLst);
		int idx = lstMap.Find(nameLst);
		if(idx > -1){
			return lstMap[idx];
		}
		return tmpLst;
	}
	bool AddLst(const HcmLstRec& lst){
		return lstMap.FindAdd(lst.Name(), clone(lst));
	}
	bool AddLst(const String& name, const Vector<String>& vec){
		int idx = lstMap.Find(name);
		if(idx > -1){
			lstMap.Add(name, HcmLstRec(name, vec));
		}
		return false;
	}
	bool AddLst(const String& name, const String& file){
		int idx = lstMap.Find(name);
		if(idx > -1){
			lstMap.Add(name, HcmLstRec(name, file));
		}
		return false;
	}
	bool Find(const String& nameLst, const String& code){
		HcmLstRec lst = GetLst(nameLst);
		if(lst.Lst().Find(code) != -1)
			return true;
		else
			return false;
	}
	HcmLstData(){}
protected:
	ArrayMap<String, HcmLstRec> lstMap; // key: hcmCode
};
//!---------------------------------------------------------------------------------------


/// storing, parsing and checking Hcm Field 13X
struct HcmCoRefer{
	String GetCountry()const{return _country;}
	int GetYear()const{return _year;}
	String GetProcID()const{return _procID;}
	int GetChannelNo()const{return _channelNo;}
	int GetRecCount()const{return _recCount;}
	int GetRecNo()const{return _recNo;}
	bool IsValid()const{return isValid;}
	HcmCoRefer(){Clear();};
	bool SetCoRefer(const String& str);
protected:
	void Clear(){_country = ""; _year = 0; _procID = ""; _channelNo = 0; _recCount = 0; _recNo = 0; isValid = false;};
	bool isValid;
	String _country;
	int _year;
	String _procID;
	int _channelNo;
	int _recCount;
	int _recNo;
};
bool HcmCoRefer::SetCoRefer(const String& str){
	Clear();
	isValid = true;
	// 0-2: CCC		Country requesting co-ordination
	_country = TrimBoth(str.Mid(0, 3));
	if(!Single<HcmLstData>().Find("4B", _country)){
		return isValid = false;
	}
	// 3-6 YYYY	4 digits of the year of initial co-ordination, year (numerical; range: > 1900)
	_year = StrInt(TrimBoth(str.Mid(3, 4)));
	if(!IsNumber(_year) || int(_year) <= 1900){
		return isValid = false;
	}
	// 7-13 PPPPPPP	Process identification, alphanumeric
	_procID = TrimBoth(str.Mid(7, 7));
	if(_procID.IsEmpty() || _procID.GetLength() < 7){
		return isValid = false;
	}
	// 14-15 FF frequency order number or link order number (numeric)
	_channelNo = StrInt(TrimBoth(str.Mid(14, 2)));
	if(!IsNumber(_channelNo)){
		return isValid = false;
	}
	// 16-17 RR Number of the associated records (numeric)
	_recCount = StrInt(TrimBoth(str.Mid(16, 2)));
	if(!IsNumber(_recCount)){
		return isValid = false;
	}
	// 18-19 OO	Order number of the record in the assignment (numeric)
	_recNo = StrInt(TrimBoth(str.Mid(18, 2)));
	if(!IsNumber(_recNo)){
		return isValid = false;
	}
	return isValid;
}
//!---------------------------------------------------------------------------------------------


///  Empty data verification converter
struct EmptyConvert : public Convert{
	Value Scan(const Value& text) const{
		LOG("EmptyConvert: " << text);
		return text;
	}
};
///  Longitude data verification converter
struct CoLongConvert : public Convert{
	Value Scan(const Value& text) const{
		if(CheckOnMask(text, "[0-9]{3}[EeWw][0-9]{4}")){
			if(IsStrToInt(text.ToString().Mid(0, 3), 0, 180))
				return text;
			else
				return ErrorValue(t_("Please enter the valid Longitude"));
		}
		return ErrorValue(UPP::Format(t_("Please enter the Longitude in the format %s."), "9(3)X9(2)9(2)9(2)"));
	}
};
///  Latitude data verification converter
struct CoLatConvert : public Convert{
	Value Scan(const Value& text) const{
		if(CheckOnMask(text, "[0-9]{2}[NnSs][0-9]{4}")){
			if(IsStrToInt(text.ToString().Mid(0, 2), 0, 90))
				return text;
			else
				return ErrorValue(t_("Please enter the valid Latitude"));
		}
		return ErrorValue(UPP::Format(t_("Please enter the Latitude in the format %s."), "9(2)X9(2)9(2)9(2)"));
	}
};
///  Hcm Field 7A for RX(TX) data verification converter
struct RxTx7A_Convert : public Convert{
	Value Scan(const Value& text) const{
		// Designation of emission: 28M0G7W
		String design = TrimBoth(text);
		if(design.IsEmpty()){
			return ErrorValue(UPP::Format(t_("Designation of emission %s."), " is missing"));
		}
		if(!design.IsEmpty() && (design.GetLength() < 7 || design.GetLength() > 9)){
			return ErrorValue(UPP::Format(t_("Designation of emission %s."), " has incorrect number of characters"));
		}
		return text;
	}
};
///  Hcm Field 7A for PRX(PTX) data verification converter
struct PrxPtx7A_Convert : public Convert{
	Value Scan(const Value& text) const{
		// Designation of emission: 28M0G7W
		String design = TrimBoth(text);
		if(design.IsEmpty()) return text;
		if(!design.IsEmpty() && (design.GetLength() < 7 || design.GetLength() > 9)){
			return ErrorValue(UPP::Format(t_("Designation of emission %s."), " has incorrect number of characters"));
		}
		return text;
	}
};
///  Hcm Field 13X data verification converter
struct Fld_13X_Convert : public Convert{
	Value Scan(const Value& text) const{
		String inStr = TrimBoth(text);
		if(inStr.IsEmpty()){
			//return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " is missing"));
			return text;
		}
		// 0-2: CCC		Country requesting co-ordination
		String countryCode = TrimBoth(inStr.Mid(0, 3));
		if(!Single<HcmLstData>().Find("4B", countryCode)){
			return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " code country requesting co-ordination is unknown"));
		}
		// 3-6 YYYY	4 digits of the year of initial co-ordination, year (numerical; range: > 1900)
		Value year = StrInt(TrimBoth(inStr.Mid(3, 4)));
		// TODO the upper bound of the year of initial co-ordination = (GetSysDate().year+1) ?
		if(!IsNumber(year) || int(year) <= 1900 || int(year) > GetSysDate().year+1){
			return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " year of initial co-ordination is missing or is not a number"));
		}
		// 7-13 PPPPPPP	Process identification
		String process = TrimBoth(inStr.Mid(7, 7));
		if(process.IsEmpty() || process.GetLength() < 7){
			return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " process identification is incorrect"));
		}
		// 14-15 FF frequency order number or link order number (numeric)
		Value ff = StrInt(TrimBoth(inStr.Mid(14, 2)));
		if(!IsNumber(ff)){
			return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " frequency order number is not a number"));
		}
		// 16-17 RR Number of the associated records (numeric)
		Value rr = StrInt(TrimBoth(inStr.Mid(16, 2)));
		if(!IsNumber(rr)){
			return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " number of the associated records is not a number"));
		}
		// 18-19 OO	Order number of the record in the assignment (numeric)
		Value oo = StrInt(TrimBoth(inStr.Mid(18, 2)));
		if(!IsNumber(oo)){
			return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " order number of the record in the assignment is not a number"));
		}
		return text;
	}
};
//!---------------------------------------------------------------------------------------------


/// Hcm Field Description
struct FldDescr :Moveable<FldDescr>{
	void Clear(){
		type = FldType::STR;
		mandat = FldMandat::OFF;
		mask = "";
		lst = "";
		length = 0;
	}
	String ToString()const{
		return Format("%s, mandat: %s, length: %d, mask: %s", FldTypeToStr(type), FldMandatToStr(mandat), length, mask);
	}
	FldType GetType()const{return type;};
	FldMandat GetMandat()const{return mandat;};

	FldEditType GetFldEditType()const{return fldEditType;};
	bool IsMandat()const{return mandat == FldMandat::ON;};
	int GetLength()const{return length;};
	double GetMax()const{return max;};
	double GetMin()const{return min;};
	String GetMask()const{return mask;};
	String GetLst()const{return lst;};
	void Set(const FldDescr& desc){
		type = (desc.type);
		mandat = (desc.mandat);
		fldEditType = (desc.fldEditType);
		length = (desc.length);
		mask = (desc.mask);
		lst = desc.lst;
	}
	void Jsonize(JsonIO& json);
	FldDescr(){Clear();}
	// type, mandat, fldEditType, mask, lst, length
	FldDescr(FldType type, FldMandat mandat, FldEditType fldEditType, const String& mask, const String& lst, int length, double min, double max):
		type(type), mandat(mandat), fldEditType(fldEditType), mask(mask), lst(lst), length(length), min(min), max(max){}
	// type
	FldDescr(FldType type):
		type(type), mandat(FldMandat::OFF), fldEditType(FldEditType::STR), mask(""), lst(""), length(0), min(0), max(0){}
	// type, mandat
	FldDescr(FldType type, FldMandat mandat):
		type(type), mandat(mandat), fldEditType(FldEditType::STR), mask(""), lst(""), length(0), min(0), max(0){}
	// type, mandat, length
	FldDescr(FldType type, FldMandat mandat, int length):
		type(type), mandat(mandat), fldEditType(FldEditType::STR), mask(""), lst(""), length(length), min(0), max(0){}
	// type, mandat, mask
	FldDescr(FldType type, FldMandat mandat, const String& mask):
		type(type), mandat(mandat), fldEditType(FldEditType::STR), mask(mask), lst(""), length(0), min(0), max(0){}
	// type, mandat, fldEditType
	FldDescr(FldType type, FldMandat mandat, FldEditType fldEditType):
		type(type), mandat(mandat), fldEditType(fldEditType), mask(""), lst(""), length(0), min(0), max(0){}
	// type, mandat, fldEditType, length
	FldDescr(FldType type, FldMandat mandat, FldEditType fldEditType, int length):
		type(type), mandat(mandat), fldEditType(fldEditType), mask(""), lst(""), length(length), min(0), max(0){}
	// type, mandat, fldEditType, min, max
	FldDescr(FldType type, FldMandat mandat, FldEditType fldEditType, double min, double max):
		type(type), mandat(mandat), fldEditType(fldEditType), mask(""), lst(""), length(0), min(min), max(max){}
	// type, mandat, fldEditType, lst
	FldDescr(FldType type, FldMandat mandat, FldEditType fldEditType, const String& lst):
		type(type), mandat(mandat), fldEditType(fldEditType), mask(""), lst(lst), length(0), min(0), max(0){}
	FldDescr(const FldDescr& desc):
		type(desc.type), mandat(desc.mandat), fldEditType(desc.fldEditType), mask(desc.mask), lst(desc.lst), length(desc.length), min(desc.min), max(desc.max){}
protected:
	FldType type;
	FldMandat mandat;
	FldEditType fldEditType;
	String mask;
	String lst; // name of list
	int length;
	double max;
	double min;
};
void FldDescr::Jsonize(JsonIO& json){
	if(json.IsLoading()){
		String sType;
		String sMandat;
		String sIN;
		json
			("type", sType)
			("mandat", sMandat)
			("fldEditType", sIN)
			("mask", mask)
			("lst", lst)
			("length", length)
		;
		type = StrToFldType(sType);
		mandat = StrToFldMandat(sMandat);
		fldEditType = StrToFldEditType(sIN);
	}
	else{
		String sType = FldTypeToStr(type);
		String sMandat = FldMandatToStr(mandat);
		String sIN = FldEditTypeToStr(fldEditType);
		json
			("type", sType)
			("mandat", sMandat)
			("fldEditType", sIN)
			("mask", mask)
			("lst", lst)
			("length", length)
		;
	}
}
//!---------------------------------------------------------------------------------------
//!---------------------------------------------------------------------------------------





/// helper to select a part of the hcm field: code, name, value, description
struct NameVal :Moveable<NameVal>{
	String code;
	String name;
	String val;
	bool isEdit;
	FldDescr fDescr;
	String ToString()const{return Format("[%s] %s: %s", code, name, val);};
	void Set(const NameVal& nv){code = nv.code; name = nv.name; val = nv.val; fDescr.Set(nv.fDescr); isEdit = nv.isEdit;}
	void Set(const String& _code, const String& _name, const String& _val, const FldDescr& _fDescr)
		{code = _code; name = _name; val = _val; fDescr = clone(_fDescr); isEdit = true;}

	NameVal():code(""), name(""), val(""), isEdit(true){};
	NameVal(const bool isEdit):code(""), name(""), val(""), isEdit(isEdit){};

	NameVal(const String& code, const String& name, const String& val):
			code(code), name(name), val(val), isEdit(true){fDescr.Clear();};
	NameVal(const String& code, const String& name, const double val):
			code(code), name(name), val(DblStr(val)), isEdit(true){fDescr.Clear();};
	NameVal(const String& code, const String& name, const int val):
			code(code), name(name), val(IntStr(val)), isEdit(true){fDescr.Clear();};
	NameVal(const String& code, const String& name, const String& val, const FldDescr& fDescr):
			code(code), name(name), val(val), fDescr(clone(fDescr)), isEdit(true){};
	NameVal(const NameVal& nv): code(nv.code), name(nv.name), val(nv.val), fDescr(clone(nv.fDescr)), isEdit(nv.isEdit){};
};

/// helper to select a part of the two hcm field: code1, value1, code2, value2
struct TwoCodeVal :Moveable<TwoCodeVal>{
	String code_1;
	String val_1;
	String code_2;
	String val_2;
	String ToString()const{return Format("[%s] %s; [%s] %s", code_1, val_1, code_2, val_2);};
	void Set(const TwoCodeVal& tcv){code_1 = tcv.code_1; val_1 = tcv.val_1; code_2 = tcv.code_2; val_2 = tcv.val_2;}
	TwoCodeVal(){code_1= ""; val_1= ""; code_2= ""; val_2 = "";};
	TwoCodeVal(const String& code_1, const String& val_1, const String& code_2, const String& val_2):
			code_1(code_1), val_1(val_1), code_2(code_2), val_2(val_2){};
	TwoCodeVal(const String& code_1, const double val_1, const String& code_2, const double val_2):
			code_1(code_1), code_2(code_2), val_1(DblStr(val_1)), val_2(DblStr(val_2)){};
	TwoCodeVal(const String& code_1, const double val_1, const String& code_2, const int val_2):
			code_1(code_1), code_2(code_2), val_1(IntStr(val_1)), val_2(IntStr(val_2)){};
};
/// helper to select a part of the two hcm field: String value1, String value2
struct TwoStrVal: Moveable<TwoStrVal>{
	String val_1;
	String val_2;
	bool IsEmpty()const{return TrimBoth(val_1).IsEmpty() || TrimBoth(val_2).IsEmpty();}
	void Set(const TwoStrVal& tsv){val_1 = tsv.val_1; val_2 = tsv.val_2;}
	String ToString()const{return Format("%s; %s", val_1, val_2);};
	TwoStrVal(){val_1= ""; val_2 = "";};
	TwoStrVal(const String& val_1, const String& val_2): val_1(val_1), val_2(val_2){};
};
/// helper to select a part of the two hcm field: double value1, double value2
struct TwoDblVal: Moveable<TwoDblVal>{
	double val_1;
	double val_2;
	void Clear(){val_1= 0.0; val_2 = 0.0;}
	void Set(const TwoDblVal& tsv){val_1 = tsv.val_1; val_2 = tsv.val_2;}
	String ToString()const{return Format("%f; %f", val_1, val_2);};
	TwoDblVal(){Clear();};
	TwoDblVal(const double val_1, const double val_2): val_1(val_1), val_2(val_2){};
	TwoDblVal(const String& val_1, const String& val_2): val_1(StrDbl(TrimBoth(val_1))), val_2(StrDbl(TrimBoth(val_1))){};
};
//!---------------------------------------------------------------------------------------
/// helper to select a part of the hcm field: code, Vector values
struct CodeVec :Moveable<CodeVec>{
	String code;
	Vector<String> vec;
	String ToString()const{return Format("%s: %s", code, vec.ToString());};
	void Jsonize(JsonIO& json){json("code", code)("val", vec);};
	void Set(const CodeVec& nv){code = nv.code; vec = clone(nv.vec);}
	void Set(const String& _code, const Vector<String>& _vec)
		{code = _code; vec = clone(_vec);}
	CodeVec():code(""){vec.Clear();};
	CodeVec(const String& code, const Vector<String>& vec):	code(code), vec(clone(vec)){};
	CodeVec(const CodeVec& cv): code(cv.code), vec(clone(cv.vec)){};
};
//!---------------------------------------------------------------------------------------










///  Empty data verification converter
Function<Value (Value)> ConvEmpty = [](const Value& v) { return v; };
///  Longitude data verification converter
Function<Value (Value)> ConvScanCoLong = [](const Value& v){
	if(CheckOnMask(v, "[0-9]{3}[EeWw][0-9]{4}")){
		if(IsStrToInt(v.ToString().Mid(0, 3), 0, 180))
			return v;
		else
			return ErrorValue(t_("Please enter the valid Longitude"));
	}
	return ErrorValue(UPP::Format(t_("Please enter the Longitude in the format %s."), "9(3)X9(2)9(2)9(2)"));
};
///  Latitude data verification converter
Function<Value (Value)> ConvScanCoLat = [](const Value& v) {
	if(CheckOnMask(v, "[0-9]{2}[NnSs][0-9]{4}")){
		if(IsStrToInt(v.ToString().Mid(0, 2), 0, 90))
			return v;
		else
			return ErrorValue(t_("Please enter the valid Latitude"));
	}
		return ErrorValue(UPP::Format(t_("Please enter the Latitude in the format %s."), "9(2)X9(2)9(2)9(2)"));
};
///  Hcm Field 7A for RX(TX) data verification converter
Function<Value (Value)> ConvScanRxTx7A = [](const Value& v) {
	// Designation of emission: 28M0G7W
	String design = TrimBoth(v);
	if(design.IsEmpty()){
		return ErrorValue(UPP::Format(t_("Designation of emission %s."), " is missing"));
	}
	if(!design.IsEmpty() && (design.GetLength() < 7 || design.GetLength() > 9)){
		return ErrorValue(UPP::Format(t_("Designation of emission %s."), " has incorrect number of characters"));
	}
	return v;
};
///  Hcm Field 7A for PRX(PTX) data verification converter
Function<Value (Value)> ConvScanPrxPtx7A = [](const Value& v) {
	// Designation of emission: 28M0G7W
	String design = TrimBoth(v);
	if(design.IsEmpty()) return v;
	if(!design.IsEmpty() && (design.GetLength() < 7 || design.GetLength() > 9)){
		return ErrorValue(UPP::Format(t_("Designation of emission %s."), " has incorrect number of characters"));
	}
	return v;
};
///  Hcm Field 13X data verification converter
Function<Value (Value)> ConvScan13X = [](const Value& v) {
	String inStr = TrimBoth(v);
	if(inStr.IsEmpty()){
		//return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " is missing"));
		return v;
	}
	// 0-2: CCC		Country requesting co-ordination
	String countryCode = TrimBoth(inStr.Mid(0, 3));
	if(!Single<HcmLstData>().Find("4B", countryCode)){
		return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " code country requesting co-ordination is unknown"));
	}
	// 3-6 YYYY	4 digits of the year of initial co-ordination, year (numerical; range: > 1900)
	Value year = StrInt(TrimBoth(inStr.Mid(3, 4)));
	// TODO the upper bound of the year of initial co-ordination = (GetSysDate().year+1) ?
	if(!IsNumber(year) || int(year) <= 1900 || int(year) > GetSysDate().year+1){
		return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " year of initial co-ordination is missing or is not a number"));
	}
	// 7-13 PPPPPPP	Process identification
	String process = TrimBoth(inStr.Mid(7, 7));
	if(process.IsEmpty() || process.GetLength() < 7){
		return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " process identification is incorrect"));
	}
	// 14-15 FF frequency order number or link order number (numeric)
	Value ff = StrInt(TrimBoth(inStr.Mid(14, 2)));
	if(!IsNumber(ff)){
		return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " frequency order number is not a number"));
	}
	// 16-17 RR Number of the associated records (numeric)
	Value rr = StrInt(TrimBoth(inStr.Mid(16, 2)));
	if(!IsNumber(rr)){
		return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " number of the associated records is not a number"));
	}
	// 18-19 OO	Order number of the record in the assignment (numeric)
	Value oo = StrInt(TrimBoth(inStr.Mid(18, 2)));
	if(!IsNumber(oo)){
		return ErrorValue(UPP::Format(t_("[13X] Co-ordination  reference %s."), " order number of the record in the assignment is not a number"));
	}
	return v;
};

struct HcmFldConvert : public Convert{
	Value Scan(const Value& text)const;
	HcmFldConvert(const NameVal& nv, const bool isCheckMandat): nv(clone(nv)), isCheckMandat(isCheckMandat){}
protected:
	bool isCheckMandat;
	NameVal nv;
};
Value HcmFldConvert::Scan(const Value& text)const{
	if(nv.code == "4C1") return ConvScanCoLong(text);
	if(nv.code == "4C2") return ConvScanCoLat(text);
	if(nv.code == "13X") return ConvScan13X(text);
	if(nv.fDescr.GetLength() > 0 && text.ToString().GetLength() > nv.fDescr.GetLength()){
		return ErrorValue(UPP::Format(t_("Please enter a value that is no more than %d characters long."), nv.fDescr.GetLength()));
	}
	if(isCheckMandat && nv.fDescr.IsMandat() && text.ToString().IsEmpty()){
		return ErrorValue(t_("Please enter a value. The field must not be empty."));
	}
	return text;
}
//!---------------------------------------------------------------------------------------------

/// helper to select a part of the hcm field: CNV [code, name, value], description
struct FldCVE :Moveable<FldCVE>{
	String GetCode()const{return code;}
	String GetName()const{return name;}
	void SetName(const String& _name){name=_name;}
	Value GetValue()const{return val;}
	void SetValue(const Value& value){val=value;}
	FldDescr GetDescr()const{return descr;}
	void SetDescr(const FldDescr& fd){descr=clone(fd);}
	bool GetIsEdit()const{return isEdit;}
	String ToString()const{return Format("  [%s] %s: %s | (isEdit %d)\n", code, name, val.ToString(), isEdit);};
	FldCVE(): code(""), name(""), val(""), isEdit(true){};
	FldCVE(const String& code):	code(code), name(""), val(""), isEdit(true){};
	FldCVE(const String& code, const bool isEdit):code(code), name(""), val(""), isEdit(isEdit){};
	FldCVE(const String& code, const String& name):code(code), name(name), val(""), isEdit(true){};
	FldCVE(const String& code, const String& name, const String& val, const FldDescr& descr):code(code), name(name), val(val), descr(clone(descr)), isEdit(true){};
	FldCVE(const FldCVE& cv): code(cv.code), name(cv.name), val(cv.val), descr(clone(cv.descr)), isEdit(cv.isEdit){};
	FldCVE(FldCVE& cv): code(cv.code), name(cv.name), val(cv.val), descr(clone(cv.descr)), isEdit(cv.isEdit){};
protected:
	FldDescr descr;
	String code;
	String name;
	Value val;
	bool isEdit;
};
//!---------------------------------------------------------------------------------------------
//!---------------------------------------------------------------------------------------------



/// hcm field
struct HcmField :Moveable<HcmField>{
	String ToString()const{
		return Format("[%s]:\t\t%s:\t%s", code, name, vval.ToString());
	}
	const FldDescr& GetDesct()const{return fDescr;}
	String GetCode()const{return code;}
	String GetName()const{return name;}
	String GetTitle()const{return Format("[%s] %s", code, name);}
	bool IsHidden()const{return isHidden;}
	String GetErMsg()const{return erMsg;}
	void SetErMsg(const String& str){erMsg << str;}
	String GetStr()const{
		if(vval.GetCount() == 1)
			return vval[0];
		else if(vval.GetCount() > 1)
			return vval.ToString();
		return "";
	}
	double GetDbl()const{
		if(vval.GetCount() == 1)
			return StrDbl(vval[0]);
		return 0.0;
	}
	bool GetBool()const{
		if(vval.GetCount() == 1)
			if(StrInt(vval[0]) > 0) return true;
		return false;
	}

	NameVal ToNV()const{
		return NameVal(code, name, GetStr(), fDescr);
	}
	String ToCSV()const{
		String str = "";
		if(vval.GetCount() == 1){
			if(fDescr.GetType() == FldType::DATE){
				return HcmStrDateToStr(vval[0]);
			}
			else
				return vval[0];
		}
		for(int i=0; i< vval.GetCount(); i++){
			if(i==0)
				str << vval[i];
			else
				str << S_RAZDEL << vval[i];
		}
		return str;
	}
	Vector<String> ToVec()const{
		Vector<String> vec;
		for(int i=0; i< vval.GetCount(); i++)
			vec.Add(vval[i]);
		return vec;
	}
	const Vector<String>& GetVec()const{return vval;}

	void EditVal(const String& s){
		vval.Clear();
		if(fDescr.GetType() == FldType::DATE)
			vval << DateFormat(HcmStrToDate(s));
		else
			vval << s;
	}
	void EditVal(const Vector<String>& v){
		vval = clone(v);
	}
	void SetVal(const String& s){
		if(fDescr.GetType() == FldType::DATE)
			vval << DateFormat(HcmStrToDate(s));
		else
			vval << s;
	}
	void SetVal(const Vector<String>& v){
		vval = clone(v);
	}
	void Clear(){vval.Clear(); erMsg.Clear();}
	bool IsEmpty()const{
		if(vval.GetCount() == 1)
			return vval[0].IsEmpty();
		else if(vval.GetCount() > 1){
			for(auto v: vval)
				if(!v.IsEmpty()){
					return false;
				}
		}
		return true;
	}
	void Jsonize(JsonIO& json);
	String ToJsonStr();
	bool FromJsonStr(const String &s);
	bool Check();
	~HcmField(){vval.Clear();}
	HcmField(): code(""), name(""){fDescr.Clear(); Clear(); isHidden = false;}

	HcmField(const String& code, const String& name, const FldDescr& fDescr):
		 code(code), name(name), fDescr(clone(fDescr)){vval.Clear(); isHidden = false;}
	HcmField(const String& code, const String& name, const bool isHidden, const FldDescr& fDescr):
		 code(code), name(name), isHidden(isHidden), fDescr(clone(fDescr)){vval.Clear();}

	HcmField(const HcmField& fld):
		 code(fld.code), name(fld.name), isHidden(fld.isHidden), fDescr(clone(fld.fDescr)), vval(clone(fld.vval)){}
protected:
	bool isHidden;
	FldDescr fDescr;
	String code;
	String name;
	String erMsg;
	Vector<String> vval;
	bool CheckMandat();
	bool CheckOnType();
	bool CheckInLst();
	bool CheckOnLenghts();
	bool CheckOnMask();
};
void HcmField::Jsonize(JsonIO& json){
	json
		("code", code)
		("val", vval)
	;
}
String HcmField::ToJsonStr(){
	return StoreAsJson(*this, true);
}
bool HcmField::FromJsonStr(const String &s){
	return LoadFromJson(*this, s);
}
bool HcmField::Check(){
	if(!CheckMandat()) return false;
	if(!CheckOnType()) return false;
	if(!CheckInLst()) return false;
	if(!CheckOnLenghts()) return false;
	if(!CheckOnMask()) return false;
	return true;
}
bool HcmField::CheckMandat(){
	String str = TrimBoth(GetStr());
	//if(GetDesct().IsMandat() && str.IsEmpty()){
	FldMandat fmd = GetDesct().GetMandat();
	if(fmd == FldMandat::ON && str.IsEmpty()){
		erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " is missing");
		return false;
	}
	return true;
}
// checking the value for type compliance
bool HcmField::CheckOnType(){
	Value fValue = Null;
	switch(GetDesct().GetType()){
		case FldType::STR:
			fValue = GetStr();
			if(!IsString(fValue)){
				erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " is not a alphanumeric");
				return false;
			}
			return true;
		case FldType::INT:
			fValue = StrInt(GetStr());
			if(!IsNumber(fValue)){
				erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " is not a integer number");
				return false;
			}
			return true;
		case FldType::FLOAT:
			fValue = StrDbl(GetStr());
			if(!IsNumber(fValue)){
				erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " is not a float number");
				return false;
			}
			return true;
		case FldType::DATE:{
				String txt = GetStr();
				if(!IsNull(txt)){
					Date d;
					if(StrToDate(d, txt)) fValue = d;
					if(!IsDateTime(fValue)){
						erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " is not a date");
						return false;
					}
				}
			}
			return true;
		case FldType::VEC:
			return true;
	}
	erMsg = Format("%s %s", GetName(), " is unknown");
	return false;
}
// checking the value for matching the list
bool HcmField::CheckInLst(){
	if(fDescr.GetLst().IsEmpty()) return true;
	HcmLstRec lst = Single<HcmLstData>().GetLst(fDescr.GetLst());
	bool isFind = false;
	for(int i=0; i<lst.Lst().GetCount(); i++){
		if(ToUpper(lst.Lst().GetKey(i)) == ToUpper(GetStr())){
			isFind = true;
			break;
		}
	}
	if(!isFind){
		erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " is unknown");
		return false;
	}
	return true;
}
bool HcmField::CheckOnLenghts(){
	if(fDescr.GetLength()==0) return true;
	if(!fDescr.IsMandat()) return true;
	String str = TrimBoth(GetStr());
	if(str.GetLength() > fDescr.GetLength()){
		erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " has incorrect number of characters");
		return false;
	}
	return true;
}
bool HcmField::CheckOnMask(){
	if(fDescr.GetMask().IsEmpty()) return true;
	String p = "(\\b" + fDescr.GetMask() + "\\b)";
	RegExp r0(p);
	if(!r0.Match(TrimBoth(GetStr()))){
		erMsg = Format(" [%s] %s %s", GetCode(), GetName(), " is incorrect");
		return false;
	}
	return true;
}
//! --------------------------------------------------------------------------------------------
//! --------------------------------------------------------------------------------------------
//! --------------------------------------------------------------------------------------------

struct HcmData: Moveable<HcmData>{
	const VectorMap<int, HcmField>& GetMap()const{return map;}
	const HcmEntity GetEntity()const{return hcmEntity;};
	const HcmField GetField(const String& code)const;
	const HcmField GetField(const int id)const;
	HcmField& Field(const String& code);
	bool EditVal(const String& code, const String& val);
	bool EditVal(const String& code, const Vector<String>& vval);
	bool EditVal(const int id, const String& val);
	bool SetVal(const int id, const String& val);
	bool SetVal(const int id, const Vector<String>& v);
	void ClearVal(const int id);
	String ToString()const;
	String ToCSV()const{return "";};
	void FromCSV(const String& hcmString){};
	//virtual void FromCSV(const String& hcmString) = 0;
	const Vector<NameVal> ToNV()const;
	void Clear();
	unsigned GetHash()const;
	void Set(const HcmData& hcmData){map = clone(hcmData.map);};
	HcmData(): hcmEntity(HcmEntity::None){};
	HcmData(const HcmData& hcmData){map = clone(hcmData.map); hcmEntity = hcmData.GetEntity();};
	~HcmData(){map.Clear();};
protected:
	HcmEntity hcmEntity;
	VectorMap<int, HcmField> map; // key HcmField npp
};
void HcmData::Clear(){
	for(int i=0; i<map.GetCount(); i++)
		map[i].Clear();
}
const Vector<NameVal> HcmData::ToNV()const{
	Vector<NameVal> nameValList;
	for(int i=0; i < map.GetCount(); i++)
		nameValList.Add(map[i].ToNV());
	return nameValList;
}
const HcmField HcmData::GetField(const int id)const{
	int idx = map.Find(id);
	if(idx != -1)
		return clone(map[idx]);
	else
		return HcmField();
}
const HcmField HcmData::GetField(const String& code)const{
	for(int i=0; i < map.GetCount(); i++){
		if(map[i].GetCode() == code)
			return clone(map[i]);
	}
	return HcmField();
}
HcmField& HcmData::Field(const String& code){
	static HcmField hcmField;
	for(int i=0; i < map.GetCount(); i++){
		if(map[i].GetCode() == code){
			return map[i];
		}
	}
	return hcmField;
}
bool HcmData::EditVal(const int id, const String& val){
	int idx = map.Find(id);
	if(idx != -1){
		map[idx].EditVal(val);
		return true;
	}
	return false;
}
bool HcmData::EditVal(const String& code, const String& val){
	for(int i=0; i < map.GetCount(); i++){
		if(map[i].GetCode() == code){
			map[i].EditVal(val);
			return true;
		}
	}
	return false;
}
bool HcmData::EditVal(const String& code, const Vector<String>& vval){
	for(int i=0; i < map.GetCount(); i++){
		if(map[i].GetCode() == code){
			map[i].SetVal(vval);
			return true;
		}
	}
	return false;
}
bool HcmData::SetVal(const int id, const String& val){
	int idx = map.Find(id);
	if(idx != -1){
		map[idx].SetVal(val);
		return true;
	}
	return false;
}
bool HcmData::SetVal(const int id, const Vector<String>& v){
	int idx = map.Find(id);
	if(idx != -1){
		map[idx].SetVal(v);
		return true;
	}
	return false;
}
void HcmData::ClearVal(const int id){
	int idx = map.Find(id);
	if(idx != -1){
		map[idx].Clear();
	}
}
String HcmData::ToString()const{
	String str = "HcmData:\n";
	for(int i=0; i < map.GetCount(); i++){
		str << Format("%d:\t%s\n", map.GetKey(i), map[i].ToString());
	}
	return str;
}
unsigned HcmData::GetHash()const{
	bool isTx = (hcmEntity == HcmEntity::TX) ? true : false;
	bool isPassive = (hcmEntity == HcmEntity::PTX || hcmEntity == HcmEntity::PRX) ? true : false;
	String upStr = ToUpper(GetField("1A1").GetStr());
	double freq = GetField("1A").GetDbl();
	if(upStr == "K")
		freq = freq / 1E6;
	else if(upStr == "M")
		freq = freq / 1000;
	String name_of_station = GetField("4A").GetStr();
	String country = GetField("4B").GetStr();
	String sLong = GetField("4C1").GetStr();
	String sLat = GetField("4C2").GetStr();
	return CombineHash() << isTx << isPassive << freq << name_of_station << country << sLong << sLat;
}

//! --------------------------------------------------------------------------------------------

struct HcmHeader: HcmData, Moveable<HcmHeader>{
	void FromCSV(const String& hcmString);
	String ToCSV()const;
	void FromVecXLS(const Vector<Vector<String>>& head);
	Vector<Vector<String>> ToVecXLS();
	void FromNV(const Vector<NameVal>& vecNV);
	void Clear();
	void Jsonize(JsonIO& json);
	void Set(const Vector<CodeVec>& cvLst);
	void Set(const HcmHeader& header){map = clone(header.map);  hcmEntity = header.GetEntity();};
	void Check(String& vlog);
	HcmHeader();
	HcmHeader(const HcmHeader& header){ map = clone(header.map);  hcmEntity = header.GetEntity(); };
	~HcmHeader(){map.Clear();};
};

HcmHeader::HcmHeader(){
	hcmEntity = HcmEntity::HEADER;
	map.Add(0, HcmField("H01",  t_("File number"), FldDescr(FldType::INT, FldMandat::ON, FldEditType::INT, 1, 99)));
	map.Add(1, HcmField("H02",  t_("File contents"), FldDescr(FldType::STR, FldMandat::ON, 80)));
	map.Add(2, HcmField("H03",  t_("File contents code"), FldDescr(FldType::STR, FldMandat::ON, 1)));
	map.Add(3, HcmField("H04",  t_("Country"), FldDescr(FldType::STR, FldMandat::ON, FldEditType::LIST, "4B")));
	map.Add(4, HcmField("H05",  t_("Name of the responsible person"), FldDescr(FldType::STR, FldMandat::OFF, 40)));
	map.Add(5, HcmField("H06",  t_("Phone"), FldDescr(FldType::STR, FldMandat::OFF, 20)));
	map.Add(6, HcmField("H07",  t_("Telefax"), FldDescr(FldType::STR, FldMandat::OFF, 20)));
	map.Add(7, HcmField("H08",  t_("E-mail"), FldDescr(FldType::STR, FldMandat::OFF, 40)));
	map.Add(8, HcmField("H09",  t_("Number of records"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::INT, 1, 999999)));
	map.Add(9, HcmField("H10", t_("Writing date"), FldDescr(FldType::DATE, FldMandat::ON, FldEditType::DATE)));
}
void HcmHeader::Clear(){
	for(int i=0; i<map.GetCount(); i++)
		map[i].Clear();
}
void HcmHeader::FromVecXLS(const Vector<Vector<String>>& head){
	for(int i=0; i < head.GetCount(); i++){
		if(i < map.GetCount()){
			// The header lines consist of 3x columns
			if(head[i].GetCount() >= 3){
				// [0] - code
				// [1] - value
				// [2] - caption
				EditVal(head[i][0], head[i][1]);
			}
		}
		else
			break;
	}
}
Vector<Vector<String>> HcmHeader::ToVecXLS(){
	Vector<Vector<String>> head;
	for(int i=0; i<map.GetCount(); i++){
		Vector<String> row;
		row.Add(map[i].GetCode());	// [0] - code
		row.Add(map[i].GetStr());	// [1] - value
		row.Add(map[i].GetTitle());	// [2] - caption
		head.Add(pick(row));
	}
	return head;
}
void HcmHeader::FromNV(const Vector<NameVal>& vecNV){
	for(int i=0; i < vecNV.GetCount(); i++){
		EditVal(vecNV[i].code, vecNV[i].val);
	}
}
void HcmHeader::FromCSV(const String& hcmString){
	Clear();
	Vector<String> vhcm;
	StringStream strm = StringStream() << hcmString;
	auto v = GetCsvLine(strm, C_RAZDEL, CHARSET_DEFAULT);
	for(auto e : v){
		vhcm.Add(e);
	}
	for(int i=0; i < vhcm.GetCount(); i++){
		EditVal(i, TrimBoth(vhcm[i]));
	}
}
String HcmHeader::ToCSV()const{
	String str = "";
	for(int i=0; i < map.GetCount(); i++){
		if(i==0){
			str << map[i].ToCSV();
			continue;
		}
		str  << S_RAZDEL << map[i].ToCSV();
	}
	return str << S_RAZDEL;
}
void HcmHeader::Jsonize(JsonIO& json){
	Vector<CodeVec> cvLst;
	if(json.IsStoring()){
		for(int i=0; i<map.GetCount(); i++){
			cvLst.Add(CodeVec(map[i].GetCode(), map[i].GetVec()));
		}
	}
	json
		("Data", cvLst)
	;
	if(json.IsLoading()){
		Set(cvLst);
	}
}
void HcmHeader::Set(const Vector<CodeVec>& cvLst){
	for(auto cv: cvLst){
		for(auto m: map){
			if(m.GetCode() == cv.code){
				m.EditVal(cv.vec);
				break;
			}
		}
	}
}
void HcmHeader::Check(String& vlog){
	for(int i=0; i< map.GetCount(); i++){
		if(!map[i].Check())
			vlog << (map[i].GetErMsg()) << "\n";
	}
}
//! --------------------------------------------------------------------------------------------
//! --------------------------------------------------------------------------------------------

struct HcmIN: HcmData, Moveable<HcmIN>{
	typedef HcmIN CLASSNAME;
	void FromCSV(const String& hcmString);
	String ToCSV()const;
	void FromVecXLS(const Vector<String>& vxls);
	Vector<String> ToVecXLS(Vector<String>& columns)const;
	void Jsonize(JsonIO& json);
	void Set(const Vector<CodeVec>& cvLst);
	void Check(String& vlog);
	int mask_node_id;
	HcmIN();
	HcmIN(const HcmIN& hcmIN){mask_node_id = 0; map = clone(hcmIN.map); hcmEntity = hcmIN.GetEntity();};
	~HcmIN(){map.Clear();};
protected:
	HcmCoRefer сoRefer13X;
	// bool Check_4C(HcmField& fld);
	bool CheckIfMandat(HcmField& fld);
	bool Check_7A(HcmField& fld);
	bool Check_7G(HcmField& fld);
	bool Check_7G3(HcmField& fld);
	bool Check_8B(HcmField& fld);
	bool Check_9A(HcmField& fld);
	bool Check_13Y(HcmField& fld);
	bool Check_13X(HcmField& fld);
	bool Check_9X(HcmField& fld);
};
HcmIN::HcmIN(){
	mask_node_id = 0;
	hcmEntity = HcmEntity::None;
	map.Add(0,  HcmField("0A",	 t_("Type of entry"), FldDescr(FldType::STR, FldMandat::ON, FldEditType::LIST, "")));
	map.Add(1,  HcmField("1A",	 t_("Frequency"), FldDescr(FldType::FLOAT, FldMandat::ON, FldEditType::FLOAT, 0, 99999)));
	map.Add(2,  HcmField("1A1",	 t_("Frequency unit"), FldDescr(FldType::STR, FldMandat::ON, FldEditType::LIST, "")));
	map.Add(3,  HcmField("1Z",	 t_("Frequency category"), FldDescr(FldType::STR, FldMandat::ON, FldEditType::LIST)));
	map.Add(4,  HcmField("6A",	 t_("Class of station"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::LIST)));
	map.Add(5,  HcmField("6B",	 t_("Nature of service"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::LIST)));
	map.Add(6,  HcmField("6Z",	 t_("Category of use"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::LIST)));
	map.Add(7,  HcmField("2C",	 t_("Date of bringing into use"), FldDescr(FldType::DATE, FldMandat::OFF, FldEditType::DATE)));
	map.Add(8,  HcmField("4A",	 t_("Name of station"), FldDescr(FldType::STR, FldMandat::OFF, 40)));
	map.Add(9,  HcmField("4B",	 t_("Country"), FldDescr(FldType::STR, FldMandat::ON, FldEditType::LIST, "")));
	map.Add(10, HcmField("4C",	 t_("Geographical co-ordinates"), true, FldDescr(FldType::STR, FldMandat::OFF, "[0-9]{3}[EeWw][0-9]{6}[NnSs][0-9]{4}")));
	map.Add(11, HcmField("4Z",	 t_("Height of the station site above sea level"), FldDescr(FldType::INT, FldMandat::ON, FldEditType::INT, -9999, 9999)));
	map.Add(12, HcmField("7A",	 t_("Designation of emission"), FldDescr(FldType::STR, FldMandat::OFF, 9)));
	map.Add(13, HcmField("7H",	 t_("Equipment manufacturer name"), FldDescr(FldType::STR, FldMandat::OFF, 20)));
	map.Add(14, HcmField("7I",	 t_("Equipment type"), FldDescr(FldType::STR, FldMandat::OFF, 20)));
	map.Add(15, HcmField("7K",	 t_("Max. capacity of the link"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::LIST, "")));
	map.Add(16, HcmField("7Gf1", t_("Tx/Rx mask. Point 1: frequency, MHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999999)));
	map.Add(17, HcmField("7Ga1", t_("Tx/Rx mask. Point 1: attenuation, dBW"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99)));
	map.Add(18, HcmField("7Gf2", t_("Tx/Rx mask. Point 2: frequency, MHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999999)));
	map.Add(19, HcmField("7Ga2", t_("Tx/Rx mask. Point 2: attenuation, dBW"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99)));
	map.Add(20, HcmField("7Gf3", t_("Tx/Rx mask. Point 3: frequency, MHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999999)));
	map.Add(21, HcmField("7Ga3", t_("Tx/Rx mask. Point 3: attenuation, dBW"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99)));
	map.Add(22, HcmField("7Gf4", t_("Tx/Rx mask. Point 4: frequency, MHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999999)));
	map.Add(23, HcmField("7Ga4", t_("Tx/Rx mask. Point 4: attenuation, dBW"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99)));
	map.Add(24, HcmField("7Gf5", t_("Tx/Rx mask. Point 5: frequency, MHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999999)));
	map.Add(25, HcmField("7Ga5", t_("Tx/Rx mask. Point 5: attenuation, dBW"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99)));
	map.Add(26, HcmField("7Gf6", t_("Tx/Rx mask. Point 6: frequency, MHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999999)));
	map.Add(27, HcmField("7Ga6", t_("Tx/Rx mask. Point 6: attenuation, dBW"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99)));
	map.Add(28, HcmField("7G1",	 t_("Equipment class"), FldDescr(FldType::STR, FldMandat::OFF, 3)));
	map.Add(29, HcmField("7G2",	 t_("NFD 2"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT)));
	map.Add(30, HcmField("7G3",	 t_("Channel spacing, MHz"), FldDescr(FldType::FLOAT, FldMandat::ON, FldEditType::FLOAT, 0, 9999)));
	map.Add(31, HcmField("8B",	 t_("Maximum permitted transmitter power, dBW"), FldDescr(FldType::FLOAT, FldMandat::TX, FldEditType::FLOAT, -999.9, 999.9)));
	map.Add(32, HcmField("8B3",	 t_("ATPC, dB"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99)));
	map.Add(33, HcmField("9A",	 t_("Azimuth"), FldDescr(FldType::FLOAT, FldMandat::ON, FldEditType::FLOAT, 0, 360.0)));
	map.Add(34, HcmField("9B",	 t_("Elevation"), FldDescr(FldType::FLOAT, FldMandat::ON, FldEditType::FLOAT, -360.0, 360.0)));
	map.Add(35, HcmField("9D",	 t_("Polarization"), FldDescr(FldType::STR, FldMandat::ON, FldEditType::LIST, "")));
	map.Add(36, HcmField("9H",	 t_("Receiver noise power level, dBW"), FldDescr(FldType::FLOAT, FldMandat::RX, FldEditType::FLOAT, -999, 999)));
	map.Add(37, HcmField("9L",	 t_("Branches and line losses, dB"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 99.9)));
	map.Add(38, HcmField("9Y",	 t_("Height of antenna above ground, m"), FldDescr(FldType::INT, FldMandat::ON, FldEditType::INT, -999, 9999)));
	map.Add(39, HcmField("13Z",	 t_("Remarks"), FldDescr(FldType::STR, FldMandat::OFF, 50)));
	map.Add(40, HcmField("13Y",	 t_("Status of co-ordination"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::LIST)));
	map.Add(41, HcmField("2W",	 t_("Date of co-ordination request"), FldDescr(FldType::DATE, FldMandat::OFF, FldEditType::DATE)));
	map.Add(42, HcmField("2Z",	 t_("Final date of achieving co-ordination"), FldDescr(FldType::DATE, FldMandat::OFF, FldEditType::DATE)));
	map.Add(43, HcmField("13X",	 t_("Co-ordination reference"), FldDescr(FldType::STR, FldMandat::OFF, 20))); // TODO MASK
	map.Add(44, HcmField("9XM",	 t_("Antenna manufacturer name"), FldDescr(FldType::STR, FldMandat::IF, 20)));
	map.Add(45, HcmField("9XT",	 t_("Antenna type"), FldDescr(FldType::STR, FldMandat::IF, 20)));
	map.Add(46, HcmField("9XFL", t_("Lower antenna frequency, GHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999.9)));
	map.Add(47, HcmField("9XFU", t_("Upper antenna frequency, GHz"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999.9)));
	map.Add(48, HcmField("9X1",	 t_("Antenna gain, dB"), FldDescr(FldType::FLOAT, FldMandat::ON, FldEditType::FLOAT, 0, 99.9)));
	map.Add(49, HcmField("9Xptcp",	 t_("Copolar radiation pattern"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::LIST, "")));
	map.Add(50, HcmField("9Xcpsize", t_("Number of CP antenna mask data"), FldDescr(FldType::INT, FldMandat::OFF, FldEditType::INT, 0, 999)));
	map.Add(51, HcmField("9XCPan",	 t_("Antenna CP angle"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999.9)));
	map.Add(52, HcmField("9XCPat",	 t_("Antenna CP attenuation"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::FLOAT, 0, 999.9)));
	map.Add(53, HcmField("9Xptxp",	 t_("Cross-polar radiation pattern"), FldDescr(FldType::STR, FldMandat::OFF, FldEditType::LIST, "")));
	map.Add(54, HcmField("9Xxpsize", t_("Number of XP antenna mask data"), FldDescr(FldType::INT, FldMandat::OFF, FldEditType::INT, 0, 999)));
	map.Add(55, HcmField("9XXPan",	 t_("Antenna XP angle"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::BTN)));
	map.Add(56, HcmField("9XXPat",	 t_("Antenna XP attenuation"), FldDescr(FldType::FLOAT, FldMandat::OFF, FldEditType::BTN)));
	// additional fields
	map.Add(1110, HcmField("4C1",	 t_("Longitude"), FldDescr(FldType::STR, FldMandat::ON, "[0-9]{3}[EeWw][0-9]{4}"))); // 037e0347
	map.Add(1111, HcmField("4C2",	 t_("Latitude"),  FldDescr(FldType::STR, FldMandat::ON, "[0-9]{2}[NnSs][0-9]{4}"))); // 04n2010
}
void HcmIN::FromVecXLS(const Vector<String>& vxls){
	Vector<String> vhcm = clone(vxls);
	// In the xls format, instead of one coordinate field, two fields are used: longitude and latitude.
	if(vhcm.GetCount() > 11 && CheckOnMask(vhcm[10], "[0-9]{3}[EeWw][0-9]{4}") && CheckOnMask(vhcm[11], "[0-9]{2}[NnSs][0-9]{4}")){
		vhcm[10] = vhcm[10] << vhcm[11];
		vhcm.Remove(11);
	}
	for(int i=0; i < vhcm.GetCount(); i++){
		if(i <= 48){
			if(i == 10){
				String sLon, sLat;
				String sCoord = StrToStrCoord(TrimBoth(vhcm[i]), sLon, sLat);
				EditVal("4C1", sLon);
				EditVal("4C2", sLat);
				SetVal(i, sCoord);
			}else if(i==43){
				сoRefer13X.SetCoRefer(vhcm[i]);
				SetVal(i, TrimBoth(vhcm[i]));
			}
			else{
				SetVal(i, TrimBoth(vhcm[i]));
			}
		}
		else
			break;
	}
	hcmEntity = StrToHcmEntity(map[0].GetStr());
	//------------------------------------------

	if(vhcm.GetCount() > 49){
		//--- ANTENNA COPOLAR RADIATION PATTERN
		SetVal(49, vhcm[49]);
	}
	int cpMaskCount = 0;
	if(vhcm.GetCount() > 50){
		//--- Number of CP antenna mask data
		Value tmp = StrInt(TrimBoth(vhcm[50]));
		if(!tmp.IsNull()){
			cpMaskCount = tmp;
			SetVal(50, tmp.ToString());
		}
	}
	Vector<String> cpAngle;
	Vector<String> cpAttenuation;
	int cpMaskIdxMax = 51+cpMaskCount*2;
	if(cpMaskCount > 0 && vhcm.GetCount() > cpMaskIdxMax){
		for(int i = 51; i < cpMaskIdxMax; i++){
			if(i%2 != 0)
				cpAngle << vhcm[i];
			else
				cpAttenuation << vhcm[i];
		}
	}
	if(!cpAngle.IsEmpty()) SetVal(51, cpAngle);
	if(!cpAttenuation.IsEmpty()) SetVal(52, cpAttenuation);
	//------------------------------------------

	int xpStartIdx = cpMaskIdxMax;
	if(vhcm.GetCount() > xpStartIdx){
		//--- ANTENNA  Cross-polar radiation pattern
		SetVal(53, vhcm[xpStartIdx]);
	}
	int xpMaskCount = 0;
	if(vhcm.GetCount() > xpStartIdx+1){
		//--- Number of CP antenna mask data
		Value tmp = StrInt(TrimBoth(vhcm[xpStartIdx+1]));
		if(!tmp.IsNull()){
			xpMaskCount = tmp;
			SetVal(54, tmp.ToString());
		}
	}
	Vector<String> xpAngle;
	Vector<String> xpAttenuation;
	int xpMaskIdxMax = (xpStartIdx+2)+xpMaskCount*2;
	if(xpMaskCount > 0 && vhcm.GetCount() >= xpMaskIdxMax){
		for(int i = (xpStartIdx+2); i < xpMaskIdxMax; i++){
			if(i%2 != 0)
				xpAngle << vhcm[i];
			else
				xpAttenuation << vhcm[i];
		}
	}
	if(!xpAngle.IsEmpty()) SetVal(55, xpAngle);
	if(!xpAttenuation.IsEmpty()) SetVal(56, xpAttenuation);
}
Vector<String> HcmIN::ToVecXLS(Vector<String>& columns)const{
	Vector<String> vec;
	bool isFillCols = false;
	if(columns.IsEmpty()) isFillCols = true;
	for(int i=0; i < map.GetCount(); i++){
		if(i<=50){
			if(i == 10){
				if(isFillCols) columns.Add("4C1");
				if(isFillCols) columns.Add("4C2");
				vec.Add(GetField("4C1").GetStr());
				vec.Add(GetField("4C2").GetStr());
			}
			else{
				for(auto v: map[i].ToVec()){
					vec.Add(v);
					if(isFillCols) columns.Add(map[i].GetCode());
				}
			}
		}
		if(i==51 && map.GetCount() >=52){
			Vector<String> cpAngles = clone(map[i].GetVec());
			Vector<String> cpAttens = clone(map[i+1].GetVec());
			int idx=0;
			while(idx<cpAngles.GetCount() && idx<cpAttens.GetCount()){
				if(isFillCols) columns.Add(map[i].GetCode()+"(" + IntStr(idx) + ")");
				vec.Add(cpAngles[idx]);
				if(isFillCols) columns.Add(map[i+1].GetCode()+"(" + IntStr(idx) + ")");
				vec.Add(cpAttens[idx]);
				idx++;
			}
		}
		if(i==53 || i==54){
			for(auto v: map[i].ToVec()){
				vec.Add(v);
				if(isFillCols) columns.Add(map[i].GetCode());
			}
		}
		if(i==55 && map.GetCount() >=56){
			Vector<String> xpAngles = clone(map[i].GetVec());
			Vector<String> xpAttens = clone(map[i+1].GetVec());
			int idx=0;
			String xpStr = "";
			while(idx<xpAngles.GetCount() && idx<xpAttens.GetCount()){
				if(isFillCols) columns.Add(map[i].GetCode()+"(" + IntStr(idx) + ")");
				vec.Add(xpAngles[idx]);
				if(isFillCols) columns.Add(map[i+1].GetCode()+"(" + IntStr(idx) + ")");
				vec.Add(xpAttens[idx]);
				idx++;
			}
		}
	}
	return vec;
}
void HcmIN::FromCSV(const String& hcmString){
	Clear();
	Vector<String> vhcm;
	StringStream strm = StringStream() << hcmString;
	auto v = GetCsvLine(strm, C_RAZDEL, CHARSET_DEFAULT);
	for(auto e : v){
		vhcm.Add(e);
	}
	for(int i=0; i < vhcm.GetCount(); i++){
		if(i <= 48){
			if(i == 10){
				String sLon, sLat;
				String sCoord = StrToStrCoord(TrimBoth(vhcm[i]), sLon, sLat);
				EditVal("4C1", sLon);
				EditVal("4C2", sLat);
				SetVal(i, sCoord);
			}
			else if(i==43){
				SetVal(i, TrimBoth(vhcm[i]));
				сoRefer13X.SetCoRefer(vhcm[i]);
			}
			else{
				SetVal(i, TrimBoth(vhcm[i]));
			}
		}
		else
			break;
	}
	hcmEntity = StrToHcmEntity(map[0].GetStr());
	//------------------------------------------

	if(vhcm.GetCount() > 49){
		//--- ANTENNA COPOLAR RADIATION PATTERN
		SetVal(49, vhcm[49]);
	}
	int cpMaskCount = 0;
	if(vhcm.GetCount() > 50){
		//--- Number of CP antenna mask data
		Value tmp = StrInt(TrimBoth(vhcm[50]));
		if(!tmp.IsNull()){
			cpMaskCount = tmp;
			SetVal(50, tmp.ToString());
		}
	}
	Vector<String> cpAngle;
	Vector<String> cpAttenuation;
	int cpMaskIdxMax = 51+cpMaskCount*2;
	if(cpMaskCount > 0 && vhcm.GetCount() > cpMaskIdxMax){
		for(int i = 51; i < cpMaskIdxMax; i++){
			if(i%2 != 0)
				cpAngle << vhcm[i];
			else
				cpAttenuation << vhcm[i];
		}
	}
	if(!cpAngle.IsEmpty()) SetVal(51, cpAngle);
	if(!cpAttenuation.IsEmpty()) SetVal(52, cpAttenuation);
	//------------------------------------------

	int xpStartIdx = cpMaskIdxMax;
	if(vhcm.GetCount() > xpStartIdx){
		//--- ANTENNA  Cross-polar radiation pattern
		SetVal(53, vhcm[xpStartIdx]);
	}
	int xpMaskCount = 0;
	if(vhcm.GetCount() > xpStartIdx+1){
		//--- Number of CP antenna mask data
		Value tmp = StrInt(TrimBoth(vhcm[xpStartIdx+1]));
		if(!tmp.IsNull()){
			xpMaskCount = tmp;
			SetVal(54, tmp.ToString());
		}
	}
	Vector<String> xpAngle;
	Vector<String> xpAttenuation;
	int xpMaskIdxMax = (xpStartIdx+2)+xpMaskCount*2;
	if(xpMaskCount > 0 && vhcm.GetCount() >= xpMaskIdxMax){
		for(int i = (xpStartIdx+2); i < xpMaskIdxMax; i++){
			if(i%2 != 0)
				xpAngle << vhcm[i];
			else
				xpAttenuation << vhcm[i];
		}
	}
	if(!xpAngle.IsEmpty()) SetVal(55, xpAngle);
	if(!xpAttenuation.IsEmpty()) SetVal(56, xpAttenuation);
}

String HcmIN::ToCSV()const{
	String str = "";
	for(int i=0; i < map.GetCount(); i++){
		if(i==0){
			str << map[i].ToCSV();
			continue;
		}
		if(i<49){
			if(i==10){
				str  << S_RAZDEL << GetField("4C1").ToCSV() << GetField("4C2").ToCSV();
			}else
				str  << S_RAZDEL << map[i].ToCSV();
		}
		if(i==49 || i==50){
			str  << S_RAZDEL << map[i].ToCSV();
		}
		if(i==51 && map.GetCount() >=52){
			Vector<String> cpAngles = clone(map[i].GetVec());
			Vector<String> cpAttens = clone(map[i+1].GetVec());
			int idx=0;
			String cpStr = "";
			while(idx<cpAngles.GetCount() && idx<cpAttens.GetCount()){
				cpStr << S_RAZDEL << cpAngles[idx] << S_RAZDEL << cpAttens[idx];
				idx++;
			}
			str << cpStr;
		}
		if(i==53 || i==54){
			str  << S_RAZDEL << map[i].ToCSV();
		}
		if(i==55 && map.GetCount() >=56){
			Vector<String> xpAngles = clone(map[i].GetVec());
			Vector<String> xpAttens = clone(map[i+1].GetVec());
			int idx=0;
			String xpStr = "";
			while(idx<xpAngles.GetCount() && idx<xpAttens.GetCount()){
				xpStr << S_RAZDEL << xpAngles[idx] << S_RAZDEL << xpAttens[idx];
				idx++;
			}
			str << xpStr;
		}
	}
	return str << S_RAZDEL;
}
void HcmIN::Jsonize(JsonIO& json){
	Vector<CodeVec> cvLst;
	if(json.IsStoring()){
		for(int i=0; i<map.GetCount(); i++){
			cvLst.Add(CodeVec(map[i].GetCode(), map[i].GetVec()));
		}
		json
			("Data", cvLst)
		;
	}
	else{
		// IsLoading()
		json
			("Data", cvLst)
		;
		Set(cvLst);
		hcmEntity = StrToHcmEntity(map[0].GetStr());
		String sLon, sLat;
		String sCoord = StrToStrCoord(GetField(10).GetStr(), sLon, sLat);
		EditVal("4C1", sLon);
		EditVal("4C2", sLat);
		EditVal("4C", sCoord);
		сoRefer13X.SetCoRefer(GetField(43).GetStr());
	}
}
void HcmIN::Set(const Vector<CodeVec>& cvLst){
	for(auto cv: cvLst){
		for(int i=0; i< map.GetCount(); i++){
			if(map[i].GetCode() == cv.code){
				map[i].EditVal(cv.vec);
				break;
			}
		}
	}
	String sLon, sLat;
	String sCoord = StrToStrCoord(GetField(10).GetStr(), sLon, sLat);
	EditVal("4C1", sLon);
	EditVal("4C2", sLat);
	EditVal("4C", sCoord);
	сoRefer13X.SetCoRefer(GetField(43).GetStr());
}
//-------------------------------------------------------------------
bool HcmIN::CheckIfMandat(HcmField& fld){
	FldMandat fmd = fld.GetDesct().GetMandat();
	if(fmd == FldMandat::OFF || fmd == FldMandat::ON) return true;
	if(fmd == FldMandat::RX && hcmEntity == HcmEntity::RX && fld.IsEmpty()){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " is missing"));
		return false;
	}
	if(fmd == FldMandat::TX && hcmEntity == HcmEntity::TX && fld.IsEmpty()){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " is missing"));
		return false;
	}
	return true;
}
bool HcmIN::Check_7A(HcmField& fld){
	if(fld.GetCode() != "7A") return true;
	// Designation of emission: 28M0G7W
	HcmEntity entity = StrToHcmEntity(map[0].GetStr());
	String design = TrimBoth(fld.GetStr());
	if(design.IsEmpty() && (entity == HcmEntity::PRX || entity == HcmEntity::PTX))
		return true;
	else if(design.IsEmpty() && fld.GetDesct().IsMandat()){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " is missing"));
		return false;
	}
	if(!design.IsEmpty() && (design.GetLength() < 7 || design.GetLength() > 9)){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " has incorrect number of characters"));
		return false;
	}
	return true;
}
bool HcmIN::Check_7G(HcmField& fld){
	String code = fld.GetCode().Mid(0, 3);
	if(code != "7Ga" && code != "7Gf" ) return true;
	if(code == "7Gf"){
		
	}
	else{
		
	}
	return true;
}
bool HcmIN::Check_7G3(HcmField& fld){
	if(fld.GetCode() != "7G3") return true;
	LOG("Check_7G3: " << fld.GetStr());
	return true;
}
bool HcmIN::Check_8B(HcmField& fld){
	if(fld.GetCode() != "8B") return true;
	LOG("Check_8B: " << fld.GetStr());
	return true;
}
bool HcmIN::Check_9A(HcmField& fld){
	if(fld.GetCode() != "9A") return true;
	LOG("Check_9A: " << fld.GetStr());
	return true;
}
bool HcmIN::Check_13Y(HcmField& fld){
	if(fld.GetCode() != "13Y") return true;
	LOG("Check_13Y: " << fld.GetStr());
	return true;
}
bool HcmIN::Check_13X(HcmField& fld){
	if(fld.GetCode() != "13X") return true;
	if(fld.IsEmpty() && !fld.GetDesct().IsMandat()) return true;

	// 0-2: CCC		Country requesting co-ordination
	String countryCode = TrimBoth(fld.GetStr().Mid(0, 3));
	if(!Single<HcmLstData>().Find("4B", countryCode)){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " code country requesting co-ordination is unknown"));
		return false;
	}
	// 3-6 YYYY	4 digits of the year of initial co-ordination, year (numerical; range: > 1900)
	Value year = StrInt(TrimBoth(fld.GetStr().Mid(3, 4)));
	// TODO the upper bound of the year of initial co-ordination = (GetSysDate().year+1) ?
	if(!IsNumber(year) || int(year) <= 1900 || int(year) > GetSysDate().year+1){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " year of initial co-ordination is missing or is not a number"));
		return false;
	}
	// 7-13 PPPPPPP	Process identification
	String process = TrimBoth(fld.GetStr().Mid(7, 7));
	if(process.IsEmpty() || process.GetLength() < 7){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " process identification is incorrect"));
		return false;
	}
	// 14-15 FF frequency order number or link order number (numeric)
	Value ff = StrInt(TrimBoth(fld.GetStr().Mid(14, 2)));
	if(!IsNumber(ff)){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " frequency order number is not a number"));
		return false;
	}
	// 16-17 RR Number of the associated records (numeric)
	Value rr = StrInt(TrimBoth(fld.GetStr().Mid(16, 2)));
	if(!IsNumber(rr)){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " number of the associated records is not a number"));
		return false;
	}
	// 18-19 OO	Order number of the record in the assignment (numeric)
	Value oo = StrInt(TrimBoth(fld.GetStr().Mid(18, 2)));
	if(!IsNumber(oo)){
		fld.SetErMsg(Format(" [%s] %s %s", fld.GetCode(), fld.GetName(), " order number of the record in the assignment is not a number"));
		return false;
	}
	return true;
}
bool HcmIN::Check_9X(HcmField& fld){
	if(fld.GetCode() != "9X") return true;
	LOG("Check_9X: " << fld.GetStr());
	return true;
}
void HcmIN::Check(String& vlog){
	for(int i=0; i< map.GetCount(); i++){
		if(!map[i].Check()){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!CheckIfMandat(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_7A(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_7G(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_7G3(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_8B(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_9A(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_13Y(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_13X(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
		if(!Check_9X(map[i])){
			vlog << (map[i].GetErMsg()) << "\n";
			continue;
		}
	}
}
//!---------------------------------------------------------------------------------------------

struct HcmConvert : public Convert{
	Value Scan(const Value& text)const;
	HcmConvert(const FldCVE& fcve, const HcmEntity hcmEntity, const bool isCheckMandat): fcve(clone(fcve)), hcmEntity(hcmEntity), isCheckMandat(isCheckMandat){}
protected:
	bool isCheckMandat;
	HcmEntity hcmEntity;
	FldCVE fcve;
};
Value HcmConvert::Scan(const Value& text)const{
	if(fcve.GetCode() == "4C1") return ConvScanCoLong(text);
	if(fcve.GetCode() == "4C2") return ConvScanCoLat(text);
	if(fcve.GetCode() == "13X") return ConvScan13X(text);
	if(fcve.GetCode() == "7A"){
		if(hcmEntity == HcmEntity::RX || hcmEntity == HcmEntity::TX)
			return ConvScanRxTx7A(text);
		if(hcmEntity == HcmEntity::PRX || hcmEntity == HcmEntity::PTX)
			return ConvScanPrxPtx7A(text);
	}
	if(fcve.GetDescr().GetLength() > 0 && text.ToString().GetLength() > fcve.GetDescr().GetLength()){
		return ErrorValue(UPP::Format(t_("Please enter a value that is no more than %d characters long."), fcve.GetDescr().GetLength()));
	}
	if(isCheckMandat && fcve.GetDescr().IsMandat() && text.ToString().IsEmpty()){
		return ErrorValue(t_("Please enter a value. The field must not be empty."));
	}
	return text;
}
//!---------------------------------------------------------------------------------------------

struct OneCveList :Moveable<OneCveList>{
	void ClearValue();
	const Vector<FldCVE>& Get()const{return cvList;}
	//Vector<FldCVE> GetList(){return clone(cvList);}
	Vector<FldCVE>& GetList(){return cvList;}
	FldCVE& GetFld(const String& code);
	void Set(const Vector<FldCVE>& vec){cvList = clone(vec);};
	void Fill(const HcmData& hcmIN);
	String ToString()const;
	OneCveList(){ClearValue();};
	OneCveList(const Vector<FldCVE>& cvList): cvList(clone(cvList)){};
	OneCveList(const OneCveList& one): cvList(clone(one.cvList)){};
protected:
	Vector<FldCVE> cvList;
};
FldCVE& OneCveList::GetFld(const String& code){
	static FldCVE fld;
	for(int i=0; i<cvList.GetCount();i++){
		if(cvList[i].GetCode() == code)	return cvList[i];
	}
	return fld;
}
void OneCveList::Fill(const HcmData& hcmData){
	if(cvList.GetCount()){
		for(int i=0; i<cvList.GetCount();i++){
			HcmField hField = hcmData.GetField(cvList[i].GetCode());
			cvList[i].SetName(hField.GetName());
			cvList[i].SetValue(hField.GetStr());
			cvList[i].SetDescr(hField.GetDesct());
		}
	}
	else{
		for(int i=0; i < hcmData.GetMap().GetCount(); i++){
			cvList.Add(FldCVE(hcmData.GetField(i).GetCode(), hcmData.GetField(i).GetName(), hcmData.GetField(i).GetStr(), hcmData.GetField(i).GetDesct()));
		}
	}
}
void OneCveList::ClearValue(){
	for(int i=0; i<cvList.GetCount();i++)
		cvList[i].SetValue("");
}
String OneCveList::ToString()const{
	String rStr = "OneCveList: ";
	for(int i=0; i<cvList.GetCount();i++)
		rStr << cvList[i].ToString() << "\n";
	return rStr;
}
//!---------------------------------------------------------------------------------------------

struct TwoCveList :Moveable<TwoCveList>{
	void ClearValue();
	const Vector<Tuple<FldCVE, FldCVE>>& Get()const{return tcvList;}
	FldCVE& GetFld(const String& code);
	void Set(const Vector<Tuple<FldCVE, FldCVE>>& vec){tcvList = clone(vec);};
	void Fill(const HcmData& hcmIN);
	String ToString()const;
	TwoCveList(){ClearValue();};
	TwoCveList(const Tuple<FldCVE, FldCVE>& cvList): tcvList(clone(tcvList)){};
	TwoCveList(const TwoCveList& twoCveList): tcvList(clone(twoCveList.Get())){};
protected:
	Vector<Tuple<FldCVE, FldCVE>> tcvList;
};
FldCVE& TwoCveList::GetFld(const String& code){
	static FldCVE fld;
	for(int i=0; i<tcvList.GetCount();i++){
		if(tcvList[i].a.GetCode() == code) return tcvList[i].a;
		if(tcvList[i].b.GetCode() == code) return tcvList[i].b;
	}
	return fld;
}
void TwoCveList::Fill(const HcmData& hcmIN){
	for(int i=0; i<tcvList.GetCount();i++){
		HcmField aField = hcmIN.GetField(tcvList[i].a.GetCode());
		HcmField bField = hcmIN.GetField(tcvList[i].b.GetCode());
		tcvList[i].a.SetValue(aField.GetStr());
		tcvList[i].a.SetName(aField.GetName());
		tcvList[i].b.SetValue(bField.GetStr());
		tcvList[i].b.SetName(bField.GetName());
	}
}
void TwoCveList::ClearValue(){
	for(int i=0; i<tcvList.GetCount();i++){
		tcvList[i].a.SetValue("");
		tcvList[i].b.SetValue("");
	}
}
String TwoCveList::ToString()const{
	String str = "\n";
	for(int i=0; i<tcvList.GetCount();i++){
		str << Format("%s\n", tcvList[i].a.ToString());
		str << Format("%s\n\n", tcvList[i].b.ToString());
	}
	return str;
}

//!---------------------------------------------------------------------------------------

struct CpXpVecList :Moveable<CpXpVecList>{
	void Clear();
	const Vector<Tuple<double, double>>& Get()const{return tvList;}
	void Set(const Tuple<String, String>& code){fcode = clone(code);};
	void Fill(const HcmData& hcmIN);
	void Save(HcmData& hcmIN);
	void Add(const Tuple<double, double>& v);
	void Edit(const double& a, const Tuple<double, double>& v);
	void Del(const double& a);
	CpXpVecList(){Clear();};
	CpXpVecList(const Tuple<String, String>& fcode): fcode(clone(fcode)){};
protected:
	Tuple<String, String> fcode; // Tuple<String, String> cpCode = MakeTuple("9XCPan", "9XCPat"); | MakeTuple("9XXPan", "9XXPat");
	Vector<Tuple<double, double>> tvList;
};
void CpXpVecList::Fill(const HcmData& hcmIN){
	Vector<String> vec_a = clone(hcmIN.GetField(fcode.a).GetVec());
	Vector<String> vec_b  = clone(hcmIN.GetField(fcode.b).GetVec());
	int i=0;
	while(i<vec_a.GetCount() && i<vec_b.GetCount()){
		tvList.Add(MakeTuple(StrDbl(vec_a[i]), StrDbl(vec_b[i])));
		i++;
	}
}
void CpXpVecList::Save(HcmData& hcmIN){
	Vector<String> vec_a;
	Vector<String> vec_b;
	for(int i=0; i< tvList.GetCount(); i++){
		vec_a.Add(DblStr(tvList[i].a));
		vec_b.Add(DblStr(tvList[i].b));
	}
	hcmIN.EditVal(fcode.a, vec_a);
	hcmIN.EditVal(fcode.b, vec_b);
}
void CpXpVecList::Add(const Tuple<double, double>& v){
	for(int i=0; i< tvList.GetCount(); i++){
		if(tvList[i].a == v.a){
			tvList[i].b = v.b;
			return;
		}
	}
	tvList.Add(clone(v));
}
void CpXpVecList::Edit(const double& a, const Tuple<double, double>& v){
	for(int i=0; i< tvList.GetCount(); i++){
		if(tvList[i].a == a){
			tvList[i].a = v.a;
			tvList[i].b = v.b;
			return;
		}
	}
}
void CpXpVecList::Del(const double& a){
	for(int i=0; i< tvList.GetCount(); i++){
		if(tvList[i].a == a){
			tvList.Remove(i);
			return;
		}
	}
}
void CpXpVecList::Clear(){
	tvList.Clear();
}
//!---------------------------------------------------------------------------------------

struct CveHeaderList: OneCveList{
CveHeaderList(){
	cvList.Add(FldCVE("H01"));
	cvList.Add(FldCVE("H02"));
	cvList.Add(FldCVE("H03"));
	cvList.Add(FldCVE("H04"));
	cvList.Add(FldCVE("H05"));
	cvList.Add(FldCVE("H06"));
	cvList.Add(FldCVE("H07"));
	cvList.Add(FldCVE("H08"));
	cvList.Add(FldCVE("H09"));
	cvList.Add(FldCVE("H10"));
	Fill(HcmHeader());}
};

struct CveCoHeaderList: OneCveList{
CveCoHeaderList(){
	cvList.Add(FldCVE("H03", false));
	cvList.Add(FldCVE("H04"));
	cvList.Add(FldCVE("H05"));
	cvList.Add(FldCVE("H06"));
	cvList.Add(FldCVE("H07"));
	cvList.Add(FldCVE("H08"));
	cvList.Add(FldCVE("H10"));
	Fill(HcmHeader());}
};

struct CveCoEntryList: OneCveList{
CveCoEntryList(){
	cvList.Add(FldCVE("13Y"));
	cvList.Add(FldCVE("13Z"));
	cvList.Add(FldCVE("2Z"));
	Fill(HcmIN());}
};

struct CveEntryList: OneCveList{
CveEntryList(){
	cvList.Add(FldCVE("0A"));
	cvList.Add(FldCVE("1A"));
	cvList.Add(FldCVE("1A1"));
	cvList.Add(FldCVE("1Z"));

	cvList.Add(FldCVE("6A"));
	cvList.Add(FldCVE("6B"));
	cvList.Add(FldCVE("6Z"));

	cvList.Add(FldCVE("2C"));

	cvList.Add(FldCVE("4A"));
	cvList.Add(FldCVE("4B"));
	cvList.Add(FldCVE("4C1"));
	cvList.Add(FldCVE("4C2"));

	cvList.Add(FldCVE("4Z"));

	cvList.Add(FldCVE("7A"));
	cvList.Add(FldCVE("7H"));
	cvList.Add(FldCVE("7I"));
	cvList.Add(FldCVE("7K"));

	cvList.Add(FldCVE("7Gf1"));
	cvList.Add(FldCVE("7Ga1"));
	cvList.Add(FldCVE("7Gf2"));
	cvList.Add(FldCVE("7Ga2"));
	cvList.Add(FldCVE("7Gf3"));
	cvList.Add(FldCVE("7Ga3"));
	cvList.Add(FldCVE("7Gf4"));
	cvList.Add(FldCVE("7Ga4"));
	cvList.Add(FldCVE("7Gf5"));
	cvList.Add(FldCVE("7Ga5"));
	cvList.Add(FldCVE("7Gf6"));
	cvList.Add(FldCVE("7Ga6"));

    cvList.Add(FldCVE("7G1"));
    cvList.Add(FldCVE("7G2"));
    cvList.Add(FldCVE("7G3"));

    cvList.Add(FldCVE("8B"));
    cvList.Add(FldCVE("8B3"));

	cvList.Add(FldCVE("9A"));
	cvList.Add(FldCVE("9B"));
	cvList.Add(FldCVE("9D"));
	cvList.Add(FldCVE("9H"));
	cvList.Add(FldCVE("9L"));
	cvList.Add(FldCVE("9Y"));

	cvList.Add(FldCVE("13Z"));
	cvList.Add(FldCVE("13Y"));

	cvList.Add(FldCVE("2W"));
	cvList.Add(FldCVE("2Z"));

	cvList.Add(FldCVE("13X"));
		
    cvList.Add(FldCVE("9XM"));
    cvList.Add(FldCVE("9XT"));
    cvList.Add(FldCVE("9XFL"));
    cvList.Add(FldCVE("9XFU"));
    cvList.Add(FldCVE("9X1"));
    cvList.Add(FldCVE("9Xptcp"));
    cvList.Add(FldCVE("9Xcpsize"));

    cvList.Add(FldCVE("9XCPan"));
    cvList.Add(FldCVE("9XCPat"));
    cvList.Add(FldCVE("9Xptxp"));
    cvList.Add(FldCVE("9Xxpsize"));
    cvList.Add(FldCVE("9XXPan"));
    cvList.Add(FldCVE("9XXPat"));
	Fill(HcmIN());}
};
//!---------------------------------------------------------------------------------------


} // namespace HCMFS

#endif
