#include "CivProjInpDbHelper.h"
#include "CivConnection.h"
#include "CivTableFields.h"
#include <algorithm>

CivProjInpDbHelper::CivProjInpDbHelper(const std::string& uri)
	:CivInpHelperAbs(uri)
{
	
}

CivProjInpDbHelper::~CivProjInpDbHelper()
{

}

void CivProjInpDbHelper::setProjCode(const std::string& projCode)
{
	mPorjCode = projCode;
}

void CivProjInpDbHelper::handlePump()
{
	// 处理水泵连接的管段
}

bool CivProjInpDbHelper::getNode(CivNode& node)
{
	// 查找，节点表数据
	JunctionTable nodeTableFields;

	std::string sql = "select  \"code\",  \"本点号\", \"高程\", \"基本需水量\", \"需水量模式\", \"横坐标\",\"纵坐标\" \
							from  \"节点\"   where\
							\"code\" not in(select det.\"code\" from \"方案详情表\" as det where det.\"方案编码\" = '" + mPorjCode + "' and \"图层\" = '节点' and \"操作类型\"=0)\
							union   select   \"code\",  \"本点号\", \"高程\", \"基本需水量\", \"需水量模式\", \"横坐标\",\"纵坐标\" \
							from   \"方案节点\"  where    \"方案编码\" = '" + mPorjCode + "' ";

	if (!mDbConn->execSql(sql))
		return false;

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->queryResult(resultVector);

	// 找出节点图层修改的值
	std::vector<std::map<std::string, std::string>> nodeDetailVec;
	auto iter = mDetailMap.find(PIPENODE);
	if (iter != mDetailMap.end())
		nodeDetailVec = iter->second;

	// 编辑包装结果
	size_t total = resultVector.size();
	for (int i = 0; i < total; i++)
	{
		std::map<std::string, std::string> map = resultVector[i];
		CivNode::NodeTable nodeTable;

		std::string code = map.find(nodeTableFields.code)->second;
		std::string elev = map.find(nodeTableFields.elev)->second;
		std::string patternID = map.find(nodeTableFields.demandPattern)->second;
		std::string demand = map.find(nodeTableFields.baseDemand)->second;

		// 根据code匹配
		for (int i = 0; i < nodeDetailVec.size(); i++)
		{
			auto detailMap = nodeDetailVec[i];

			//code 不匹配，继续下一次循环查找
			auto codeIter = detailMap.find(nodeTableFields.code);
			if (codeIter == detailMap.end())
				continue;

			// 详情表code 与原管网code不想等, 不符合条件
			if (codeIter->second == code)
				continue;

			// 根据属性修改对应的值
			std::string attri = detailMap.find("属性")->second;
			std::string newValue = detailMap.find("属性新值")->second;
			if (attri == nodeTableFields.elev)
			{
				elev = newValue;
			}
			else if (attri == nodeTableFields.demandPattern)
			{
				patternID = newValue;
			}
			else if (attri == nodeTableFields.baseDemand)
			{
				demand = newValue;
			}

		}

		nodeTable.ID = map.find("本点号")->second;
		nodeTable.Elev = elev;
		handleDelayPattern(demand, patternID, nodeTable.Demand, nodeTable.PatternId);

		node.addItem(nodeTable);
	}

	// 添加处理的阀门产生的节点
	size_t size = mNodeVec.size();
	for (int i = 0; i < size; i++)
	{
		node.addItem(mNodeVec[i]);
	}
}

void CivProjInpDbHelper::sortProjDeatil()
{
	// 查找方案详情表修改的属性
	std::string detailSql = "select detail.\"code\",detail.\"图层\",detail.\"属性\",detail.\"属性原值\",detail.\"属性新值\"\
		 from \"方案详情表\" as detail where \"方案编码\"='" + mPorjCode +"' and \"操作类型\"=1";

	if (!mDbConn->execSql(detailSql))
		return;

	std::vector<std::map<std::string, std::string>> detailVec;
	mDbConn->queryResult(detailVec);

	size_t detailVecSize = detailVec.size();

	// 将方案详情表查出来的数据
	for (int i = 0; i < detailVecSize; i++)
	{
		std::map<std::string, std::string> tempMap = detailVec[i];
		std::string layerName = tempMap.find("图层")->second;

		mDetailMap[layerName].push_back(tempMap);
	}
}

std::string CivProjInpDbHelper::splicingConditions(const std::string& layer)
{
	std::string condition = "\"code\" not in(select  \"code\" from \"方案详情表\" \
				where \"方案编码\" = '" + mPorjCode + "' and \"图层\" = '"+ layer +"' and \"操作类型\"=0)";

	return condition;
}

void CivProjInpDbHelper::handleValve()
{
	sortProjDeatil();
	handleValves2();
	return ;
}

bool CivProjInpDbHelper::getPipe(CivPipe& pipes)
{
	// 加上处理阀门和水泵产生的虚拟管段
	for (int i = 0; i < mPipesVec.size(); i++)
	{
		pipes.addItem(mPipesVec[i]);
	}

	PipeTable pipeTable;

	std::string sql = "select  \"code\",\"编号\",\"起始节点\",\"终止节点\",\"管长\",\"管径\",\"摩阻系数\",\"局损系数\",\"初始状态\"\
							 from \"管段\" \
							where \"from_layer\" not in('阀门','方案阀门','水泵','方案水泵') \
							and \"to_layer\" not in('阀门','方案阀门','水泵','方案水泵') \
							and \"code\" not in(select det.\"code\" from \"方案详情表\" as det where det.\"方案编码\" = '"+mPorjCode+"' and \"图层\"='管段')\
							union select \
							\"code\",\"编号\",\"起始节点\",\"终止节点\",\"管长\",\"管径\",\"摩阻系数\",\"局损系数\",\"初始状态\" from \"方案管段\" where \
							\"方案编码\" = '"+mPorjCode+"'";

	if (!mDbConn->execSql(sql))
		return false;

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->queryResult(resultVector);

	// 找出管段图层修改的值
	std::vector<std::map<std::string, std::string>> lineDetailVec;
	auto iter = mDetailMap.find(PIPELINE);
	if (iter != mDetailMap.end())
		lineDetailVec = iter->second;

	size_t total = resultVector.size();
	for (int i = 0; i < total; i++)
	{
		CivPipe::PipesTable pipe;

		std::map<std::string, std::string> map = resultVector[i];

		std::string code = map.find("code")->second;
		pipe.ID = map.find(pipeTable.snNo)->second;
		pipe.Node1 = map.find(pipeTable.startPoint)->second;
		pipe.Node2 = map.find(pipeTable.endPoint)->second;
		pipe.Status = map.find(pipeTable.status)->second;

		std::string Length = map.find(pipeTable.length)->second;
		std::string Diameter = map.find(pipeTable.diameter)->second;
		std::string Roughness = map.find(pipeTable.friction)->second;
		std::string MinorLoss = map.find(pipeTable.localLoss)->second;

		for (int i = 0; i < lineDetailVec.size(); i++)
		{
			std::map<std::string, std::string>  detailMap = lineDetailVec[i];

			//code 不匹配，继续下一次循环查找
			auto codeIter = detailMap.find("code");
			if (codeIter == detailMap.end())
				continue;

			// 详情表code 与原管网code不想等, 不符合条件
			if (codeIter->second != code)
				continue;

			// 根据属性修改对应的值
			std::string attri = detailMap.find("属性")->second;
			if (attri == pipeTable.length)
			{
				Length = detailMap.find("属性新值")->second;
			}
			else if (attri == pipeTable.diameter)
			{
				Diameter = detailMap.find("属性新值")->second;
			}
			else if (attri == pipeTable.friction)
			{
				Roughness = detailMap.find("属性新值")->second;
			}
			else if (attri == pipeTable.localLoss)
			{
				MinorLoss = detailMap.find("属性新值")->second;
			}
		}

		pipe.Length = Length;
		pipe.Diameter = Diameter;
		pipe.Roughness = Roughness;
		pipe.MinorLoss = MinorLoss;
		
		pipes.addItem(pipe);
	}
	
	return true;
}

bool CivProjInpDbHelper::getTank(CivTank& tanks)
{
	TankTable tankTable;
	std::string sql = "select \"code\",\"本点号\",\"高程\",\"初始水位\",\"最低水位\",\"最高水位\",\"直径\",\
		\"最小容积\",\"容积曲线\" from \"水池\"\
		where \"code\" not in(select det.\"code\" from \"方案详情表\" as det\
		 where det.\"方案编码\" = '"+mPorjCode+"' and det.\"图层\" = '水池') \
		union select  \"code\",\"本点号\",\"高程\",\"初始水位\",\"最低水位\",\
			\"最高水位\",\"直径\", \"最小容积\",\"容积曲线\" from \"方案水池\"\
		where \"方案编码\"='"+mPorjCode+"'";

	if (!mDbConn->execSql(sql))
		return false;

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->queryResult(resultVector);

	// 找出节点图层修改的值
	std::vector<std::map<std::string, std::string>> tankDetailVec;
	auto iter = mDetailMap.find(PIPENODE);
	if (iter != mDetailMap.end())
		tankDetailVec = iter->second;

	size_t total = resultVector.size();
	for (int i = 0; i < total; i++)
	{
		CivTank::TankTable tank;
		std::map<std::string, std::string>map = resultVector[i];

		std::string code = map.find("code")->second;

		tank.ID = map.find(tankTable.sn)->second;
		std::string Elev = map.find(tankTable.elev)->second;
		std::string InitLevel = map.find(tankTable.initLevel)->second;
		std::string MinLevel = map.find(tankTable.minLevel)->second;
		std::string MaxLevel = map.find(tankTable.maxLevel)->second;
		std::string Diameter = map.find(tankTable.diametor)->second;
		std::string MinVol = map.find(tankTable.minVolume)->second;
		std::string VolCurve = map.find(tankTable.volumeCurve)->second;

		// 根据code匹配
		for (int i = 0; i < tankDetailVec.size(); i++)
		{
			auto detailMap = tankDetailVec[i];

			//code 不匹配，继续下一次循环查找
			auto codeIter = detailMap.find("code");
			if (codeIter == detailMap.end())
				continue;

			// 详情表code 与原管网code不想等, 不符合条件
			if (codeIter->second == code)
				continue;

			// 根据属性修改对应的值
			std::string attri = detailMap.find("属性")->second;
			std::string newValue = detailMap.find("属性新值")->second;

			if (attri == tankTable.elev)
			{
				Elev = newValue;
			}
			else if (attri == tankTable.initLevel)
			{
				InitLevel = newValue;
			}
			else if (attri == tankTable.minLevel)
			{
				MinLevel = newValue;
			}
			else if (attri == tankTable.maxLevel)
			{
				MaxLevel = newValue;
			}
			else if (attri == tankTable.diametor)
			{
				Diameter = newValue;
			}
			else if (attri == tankTable.minVolume)
			{
				MinVol = newValue;
			}
			else if (attri == tankTable.volumeCurve)
			{
				VolCurve = newValue;
			}
		}

		tank.Elev = Elev;
		tank.InitLevel = InitLevel;
		tank.MinLevel = MinLevel;
		tank.MaxLevel = MaxLevel;
		tank.Diameter = Diameter;
		tank.MinVol = MinVol;
		tank.VolCurve = VolCurve;

		tanks.addItem(tank);
	}

	return true;
}

bool CivProjInpDbHelper::getValve(CivValve& valves)
{
	/*ValveTable vaveTable;
	std::vector<std::string> fields;

	fields.push_back(vaveTable.sn);
	fields.push_back(vaveTable.startPoint);
	fields.push_back(vaveTable.endPoint);
	fields.push_back(vaveTable.length);
	fields.push_back(vaveTable.type);
	fields.push_back(vaveTable.setting);
	fields.push_back(vaveTable.lossCoeff);

	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(VALVE, fields, resultVector);
	mDbConn->query(PROJ_VALVE, fields, resultVector, mCondition);

	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivValve::ValveTable vave;
		std::map<std::string, std::string> map = resultVector[i];

		vave.ID = map.find(vaveTable.sn)->second;
		vave.Node1 = map.find(vaveTable.startPoint)->second;
		vave.Node2 = map.find(vaveTable.endPoint)->second;
		vave.Diameter = map.find(vaveTable.length)->second;
		vave.Type = map.find(vaveTable.type)->second;
		vave.Setting = map.find(vaveTable.setting)->second;
		vave.MinorLoss = map.find(vaveTable.lossCoeff)->second;

		valves.addItem(vave);
	}*/
	for (int i = 0; i < mValuvesVec.size(); i++)
	{
		valves.addItem(mValuvesVec[i]);
	}
	return true;
}

bool CivProjInpDbHelper::getPumps(CivPumps& pumps)
{
	PumpTable pmTable;

	std::vector<std::string> fields;	
	fields.push_back(pmTable.sn);
	fields.push_back(pmTable.startPoint);
	fields.push_back(pmTable.endPoint);
	fields.push_back(pmTable.headCurve);
	fields.push_back(pmTable.power);
	
	std::vector<std::map<std::string, std::string>> resultVector;
	std::string condition1 = splicingConditions(PUMP);
	mDbConn->query(PUMP, fields, resultVector, condition1);

	std::string condition2 = " \"方案编码\" = '" + mPorjCode + "'";
	mDbConn->query(PROJ_PUMP, fields, resultVector, condition2);

	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivPumps::PumpTable pump;
		std::map<std::string, std::string> map = resultVector[i];

		pump.ID = map.find(pmTable.sn)->second;
		pump.Node1 = map.find(pmTable.startPoint)->second;
		pump.Node2 = map.find(pmTable.endPoint)->second;
		std::string param = "Head 1";

		std::string curve = map.find(pmTable.headCurve)->second;
		if (curve != "")
			param = "head " + curve;

		std::string power = map.find(pmTable.power)->second;
		if (power != "")
			param.append(" power " + power);

		pump.Parameters = param;
		pumps.addItem(pump);
	}
	return true;
}

bool CivProjInpDbHelper::getReservoirs(CivReservoirs& reservoirs)
{
	ResourcesTable restemTable;

	std::string sql = "select \"code\",\"本点号\",\"总水头\",\"水头模式\" from \"水库\" \
							where code not in(select \"code\" from \"方案详情表\" \
							where \"方案编码\"='"+mPorjCode+"' and \"图层\"='水库' and \"操作类型\" =0) \
							union select  \"code\",\"本点号\",\"总水头\",\"水头模式\" from \"方案水库\" where \"方案编码\" = '"+mPorjCode+"'";

	std::vector<std::map<std::string, std::string>> resultVector;

	if (!mDbConn->execSql(sql))
		return false;

	mDbConn->queryResult(resultVector);

	// 找出节点图层修改的值
	std::vector<std::map<std::string, std::string>> resourceDetailVec;
	auto iter = mDetailMap.find(RESIVOIR);
	if (iter != mDetailMap.end())
		resourceDetailVec = iter->second;

	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivReservoirs::ReservoirsTable resTable;
		std::map<std::string, std::string> map = resultVector[i];

		std::string code = map.find("code")->second;
		std::string totalHead = map.find(restemTable.totalHead)->second;
		std::string Pattern = map.find(restemTable.headPattern)->second;

		for (int i = 0; i < resourceDetailVec.size(); i++)
		{
			std::map<std::string, std::string> detailMap = resourceDetailVec[i];


			//code 不匹配，继续下一次循环查找
			auto codeIter = detailMap.find("code");
			if (codeIter == detailMap.end())
				continue;

			// 详情表code 与原管网code不想等, 不符合条件
			if (codeIter->second != code)
				continue;

			// 根据属性修改对应的值
			std::string attri = detailMap.find("属性")->second;
			std::string newValue = detailMap.find("属性新值")->second;
			if (attri == restemTable.totalHead)
			{
				totalHead = newValue;
			}
			else if (attri == restemTable.headPattern)
			{
				Pattern = newValue;
			}
		}
		resTable.ID = map.find(restemTable.sn)->second;
		resTable.Head = totalHead;
		resTable.Pattern = Pattern;

		reservoirs.addItem(resTable);
	}
	return true;
}

bool CivProjInpDbHelper::getCoordinates(CivCoordinates& coord)
{
	JunctionTable nodeTable;

	std::vector<std::string> fields;

	fields.push_back(nodeTable.sn);
	fields.push_back(nodeTable.xCoord);
	fields.push_back(nodeTable.yCoord);

	std::vector<std::map<std::string, std::string>> resultVector;


	std::string condition1 = splicingConditions(PIPENODE);
	mDbConn->query(PIPENODE, fields, resultVector, condition1);

	std::string condition2 = splicingConditions(TANK);
	mDbConn->query(TANK, fields, resultVector,condition2);

	std::string condition3 = splicingConditions(RESIVOIR);
	mDbConn->query(RESIVOIR, fields, resultVector, condition3);

	std::string condition = " \"方案编码\" = '"+mPorjCode+"'";
	mDbConn->query(PROJ_PIPENODE, fields, resultVector, condition);
	mDbConn->query(PROJ_TANK, fields, resultVector, condition);
	mDbConn->query(PROJ_RESIVOIR, fields, resultVector, condition);
	
	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivCoordinates::CoordTable coordTable;
		std::map<std::string, std::string> map = resultVector[i];

		coordTable.ID = map.find(fields[0])->second;
		coordTable.XCoord = map.find(fields[1])->second;
		coordTable.YCoord = map.find(fields[2])->second;

		coord.addItem(coordTable);
	}

	// 虚拟点坐标
	for (int i = 0; i < mCoords.size(); i++)
	{
		coord.addItem(mCoords[i]);
	}
	return true;
}

bool CivProjInpDbHelper::getQuality(CivQuality& quality)
{
	JunctionTable nodeTable;

	std::vector<std::string> fields; 

	fields.push_back(nodeTable.sn);
	fields.push_back(nodeTable.initQuality);
	
	std::vector<std::map<std::string, std::string>> resultVector;
	mDbConn->query(PIPENODE, fields, resultVector);
	mDbConn->query(RESIVOIR, fields, resultVector);
	mDbConn->query(PROJ_PIPENODE, fields, resultVector, mCondition);
	mDbConn->query(PROJ_RESIVOIR, fields, resultVector, mCondition);
	
	size_t totals = resultVector.size();
	for (int i = 0; i < totals; i++)
	{
		CivQuality::QualityTable quliTable;

		std::map<std::string, std::string> map = resultVector[i];
		quliTable.ID = map.find(fields[0])->second;
		quliTable.InitQuality = map.find(fields[1])->second;;

		quality.addItem(quliTable);
	}

	return true;
}

bool CivProjInpDbHelper::getStatus(CivStatus& status)
{
	// 阀门状态
	for (int i = 0; i < mStatusVec.size(); i++)
	{
		status.addItem(mStatusVec[i]);
	}
	return true;
}

std::string CivProjInpDbHelper::genSql(const std::string& table)
{
	return "";
}

std::string CivProjInpDbHelper::genSqlView(
	const std::string& table,
	const std::string& projTable,
	const std::vector<std::string>& fieldsVec,
	const std::string& projCode)
{
	int total = fieldsVec.size();
	if (total <= 0)
		return "";

	std::string fields1;
	std::string fileds2;
	for (int i = 0; i < total; i++)
	{
		fields1.append("\""+fieldsVec[i]+"\"");
		fields1.append(",");

		fileds2.append("node.\""+ fieldsVec[i] +"\"");
		fileds2.append(",");
	}
	fields1 = fields1.substr(0, fields1.length() - 1);	
	fileds2 = fileds2.substr(0, fileds2.length() - 1);

	std::string sql = " SELECT  "+ fields1 +"  FROM \""+table+"\" EXCEPT SELECT "+fileds2+" FROM \""+ table +"\" as node,\"方案详情表\" as  detail where  detail.\"图层\" = '" + table + "' and detail.\"方案编码\" = '"+ projCode +"' and  detail.\"操作类型\"=0 and node.code =detail.\"code\"";
	
	std::string sql2 = " SELECT " + fields1 + " FROM \""+projTable+"\" as tb WHERE tb.\"方案编码\"='"+ projCode +"'";


	return sql +" UNION "+ sql2;
}

std::string CivProjInpDbHelper::splicingSql(const std::string& rightTable, const std::string& demandName, const std::string& demandPattern)
{
	// 阀门sqlview视图
	std::vector<std::string> valveFiledVec;
	valveFiledVec.push_back("code");
	valveFiledVec.push_back("本点号");
	valveFiledVec.push_back("横坐标");
	valveFiledVec.push_back("纵坐标");
	valveFiledVec.push_back("固定状态");
	valveFiledVec.push_back("类型");
	valveFiledVec.push_back("设置");
	valveFiledVec.push_back("水损系数");
	valveFiledVec.push_back("起始节点");
	valveFiledVec.push_back("终止节点");

	std::string valveView = genSqlView(TABLE_VALVE, PROJ_TABLE_VALVE, valveFiledVec, mPorjCode);

	// 管段sqlview视图
	std::vector<std::string> pipeFiledVec;
	pipeFiledVec.push_back("编号");
	pipeFiledVec.push_back("管长");
	pipeFiledVec.push_back("管径");
	pipeFiledVec.push_back("摩阻系数");
	pipeFiledVec.push_back("from_code");
	pipeFiledVec.push_back("to_code");
	pipeFiledVec.push_back("code");

	std::string pipeView = genSqlView(TABLE_PIPE, PROJ_TABLE_PIPE, pipeFiledVec, mPorjCode);

	std::string upcondition;
	std::string downcondition;

		// 节点的sqlview视图
	std::vector<std::string> nodeFiledVec;
	nodeFiledVec.push_back("本点号");
	nodeFiledVec.push_back("code");
	nodeFiledVec.push_back("高程");
	nodeFiledVec.push_back("需水量模式");
	nodeFiledVec.push_back("基本需水量");
	nodeFiledVec.push_back("横坐标");
	nodeFiledVec.push_back("纵坐标");
	nodeFiledVec.push_back("初始水质");
	std::string nodeView = genSqlView(TABLE_NODE, PROJ_TABLE_NODE, nodeFiledVec, mPorjCode);
	
	
	std::string otherView;
	if (rightTable == "节点")
	{
		upcondition = "pipe.\"from_code\" = node.\"code\"  AND pipe.\"to_code\" = junc.\"code\"";
		downcondition = "pipe.\"to_code\" = node.\"code\" AND pipe.\"from_code\" = junc.\"code\"";

		otherView = nodeView;	 
	}
	else
	{
		upcondition = "(pipe.\"to_code\" = node.\"code\"\
				AND pipe.\"from_code\" = junc.\"code\") or\
			(pipe.\"from_code\" = node.\"code\"\
				AND pipe.\"to_code\" = junc.\"code\")";

		downcondition = "(pipe.\"to_code\" = node.\"code\"\
				AND pipe.\"from_code\" = junc.\"code\") or\
			(pipe.\"from_code\" = node.\"code\"\
				AND pipe.\"to_code\" = junc.\"code\")";

		std::vector<std::string> otherFiledVec;
		otherFiledVec.push_back("本点号");
		otherFiledVec.push_back("code");
		otherFiledVec.push_back("高程");
		otherFiledVec.push_back("横坐标");
		otherFiledVec.push_back("纵坐标");
		otherFiledVec.push_back("初始水质");
		otherView = genSqlView(rightTable, "方案" + rightTable, otherFiledVec, mPorjCode);
	}
	

	std::string sql2 = "SELECT  A.*, B.*  FROM (SELECT\
			node.\"本点号\",\
			node.\"横坐标\" AS 阀门横坐标,\
			node.\"纵坐标\" AS 阀门纵坐标,\
			node.\"固定状态\" AS 阀门固定状态,\
			node.\"类型\" AS 阀门类型,\
			node.\"设置\" AS 阀门设置,\
			node.\"水损系数\" AS 阀门水损系数,\
			pipe.编号 AS 上游管段编号,\
			pipe.\"管长\" AS 上游管长,\
			pipe.\"管径\" AS 上游管径,\
			pipe.\"摩阻系数\" AS 上游管段摩阻系数,\
			junc.\"本点号\" AS 上游节点,\
			junc.\"code\" AS \"上游节点code\",\
			junc.\"高程\" AS 上游节点高程,\
			" + demandPattern + " AS 上游节点蓄水量模式,\
			" + demandName + "  AS 上游节点基本需水量,\
			junc.\"横坐标\" AS 上游节点横坐标,\
			junc.\"纵坐标\" AS 上游节点纵坐标,\
			junc.\"初始水质\" AS 上游节点初始水质\
			FROM  ("+ valveView + ")node, ("+pipeView+") pipe,( " + otherView + ") junc\
			WHERE " + upcondition + ") A,\
		(\
			SELECT\
			pipe.编号 AS 下游管段编号,\
			pipe.\"管长\" AS 下游管段管长,\
			pipe.\"管径\" AS 下游管段管径,\
			pipe.\"摩阻系数\" AS 下游管段摩阻系数,\
			node.\"本点号\",\
			junc.\"本点号\" AS 下游节点,\
			junc.\"code\" AS \"上游节点code\",\
			junc.\"高程\" AS 下游节点高程,\
			junc.\"需水量模式\" AS 下游节点蓄水量模式,\
			junc.\"基本需水量\" AS 下游节点基本需水量,\
			junc.\"横坐标\" AS 下游节点横坐标,\
			junc.\"纵坐标\" AS 下游节点纵坐标,\
			junc.\"初始水质\" AS 下游节点初始水质\
			FROM  (" + valveView + ")node, (" + pipeView + ") pipe,(" + nodeView + ") junc\
			WHERE " + downcondition + ") B\
		WHERE\
		A.\"本点号\" = b.\"本点号\"";

	return sql2;
}

bool CivProjInpDbHelper::handleValves2()
{
	std::string sql = splicingSql("节点");

	if (!mDbConn->execSql(sql))
	{
		std::string error = mDbConn->getLastError();
		return false;
	}

	// 查询与阀门关联的管段，和节点
	std::vector<std::map<std::string, std::string>> valvesPipes;
	mDbConn->queryResult(valvesPipes);

	// 非
	std::string sql2 = splicingSql("水库", "0", "1");
	if (!mDbConn->execSql(sql2))
	{
		std::string error = mDbConn->getLastError();
		return false;
	}

	mDbConn->queryResult(valvesPipes);

	// 找出节点图层修改的值
	std::vector<std::map<std::string, std::string>> valvesDetailVec;
	auto iter = mDetailMap.find("阀门");
	if (iter != mDetailMap.end())
		valvesDetailVec = iter->second;

	// 总个数
	size_t total = valvesPipes.size();
	for (int i = 0; i < total; i++)
	{
		std::map<std::string, std::string> valvePipe = valvesPipes[i];

		std::string vaSzNo = valvePipe.find("本点号")->second;
		std::string vaXcoord = valvePipe.find("阀门横坐标")->second;
		std::string vaYcoord = valvePipe.find("阀门纵坐标")->second;
		std::string vaStatus = valvePipe.find("阀门固定状态")->second;
		std::string vaType = valvePipe.find("阀门类型")->second;
		std::string vaSetting = valvePipe.find("阀门设置")->second;
		std::string vaLoss = valvePipe.find("阀门水损系数")->second;
		std::string upperPipeSzNo = valvePipe.find("上游管段编号")->second;
		std::string upperPipeCode = valvePipe.find("上游管段code")->second;
		std::string upperPipeLength = valvePipe.find("上游管长")->second;
		std::string upperPipeDiametor = valvePipe.find("上游管径")->second;
		std::string upperPipeFriction = valvePipe.find("下游管段摩阻系数")->second;
		std::string upperNodeSz = valvePipe.find("上游节点")->second;
		std::string upperNodeHeight = valvePipe.find("上游节点高程")->second;
		std::string upperNodePattern = valvePipe.find("上游节点蓄水量模式")->second;
		std::string upperNodeDemand = valvePipe.find("上游节点基本需水量")->second;
		std::string upperNodeXcoord = valvePipe.find("上游节点横坐标")->second;
		std::string upperNodeYcoord = valvePipe.find("上游节点纵坐标")->second;
		std::string upperNodeQuality = valvePipe.find("上游节点初始水质")->second;
		std::string donwPipeSz = valvePipe.find("下游管段编号")->second;
		std::string donwPipeCode = valvePipe.find("下游管段code")->second;
		std::string donwPipeLength = valvePipe.find("下游管段管长")->second;
		std::string donwPipeDiametor = valvePipe.find("下游管段管径")->second;
		std::string downPipeFraction = valvePipe.find("下游管段摩阻系数")->second;
		std::string donwNodeSz = valvePipe.find("下游节点")->second;
		std::string donwNodeHeight = valvePipe.find("下游节点高程")->second;
		std::string donwNodePattern = valvePipe.find("下游节点蓄水量模式")->second;
		std::string donwNodeDemand = valvePipe.find("下游节点基本需水量")->second;
		std::string donwNodeXcoord = valvePipe.find("下游节点横坐标")->second;
		std::string donwNodeYcoord = valvePipe.find("下游节点纵坐标")->second;
		std::string donwNodeQuality = valvePipe.find("下游节点初始水质")->second;

		// 判断阀门类型
		std::string upperVaType = vaType;
		std::transform(vaType.begin(), vaType.begin(), vaType.end(), ::toupper);

		// 阀门需要构造两个虚拟节点，两个节点尽可能接近
		CivNode::NodeTable startNodeTable;
		CivCoordinates::CoordTable startNodeCoord; // 节点坐标

		// 节点信息
		startNodeTable.ID = "VUP" + vaSzNo;
		startNodeTable.Elev = upperNodeHeight;
		startNodeTable.Demand = "0";

		// 两点之间直线
		double vupperXcoord = (atof(upperNodeXcoord.c_str()) - atof(vaXcoord.c_str())) / 5 + atof(vaXcoord.c_str());
		double vupperYcoord = (atof(upperNodeYcoord.c_str()) - atof(vaYcoord.c_str())) / 5 + atof(vaYcoord.c_str());

		// 节点坐标
		startNodeCoord.ID = "VUP" + vaSzNo;
		startNodeCoord.XCoord = std::to_string(vupperXcoord);
		startNodeCoord.YCoord = std::to_string(vupperYcoord);

		// 终止节点构造
		CivNode::NodeTable endNodeTable; // 终止节点
		CivCoordinates::CoordTable endNodeCoord; // 终止节点坐标

		// 终止节点信息
		endNodeTable.ID = "VDW" + vaSzNo;
		endNodeTable.Elev = upperNodeHeight;
		endNodeTable.Demand = "0";

		mNodeVec.push_back(startNodeTable);
		mCoords.push_back(startNodeCoord);

		// 两点之间直线
		double vdownXcoord = (atof(donwNodeXcoord.c_str()) - atof(vaXcoord.c_str())) / 5 + atof(vaXcoord.c_str());
		double vdownYcoord = (atof(donwNodeYcoord.c_str()) - atof(vaYcoord.c_str())) / 5 + atof(vaYcoord.c_str());

		// 终止节点坐标信息
		endNodeCoord.ID = "VDW" + vaSzNo;
		endNodeCoord.XCoord = std::to_string(vdownXcoord);
		endNodeCoord.YCoord = std::to_string(vdownYcoord);

		mNodeVec.push_back(endNodeTable);
		mCoords.push_back(endNodeCoord);

		// 构造上游管段的
		CivPipe::PipesTable upperPipeTable;
		CivPipe::PipesTable downPipeTable;

		// 上游管段属性
		upperPipeTable.code = upperPipeCode;
		upperPipeTable.ID = upperPipeSzNo;
		upperPipeTable.Node1 = upperNodeSz;
		upperPipeTable.Node2 = startNodeTable.ID;
		upperPipeTable.Length = upperPipeLength;
		upperPipeTable.Diameter = upperPipeDiametor;
		upperPipeTable.Roughness = upperPipeFriction;
		upperPipeTable.Status = "Open";
		upperPipeTable.MinorLoss = vaLoss;

		// 下游管段属性
		downPipeTable.code = donwPipeCode;
		downPipeTable.ID = donwPipeSz;
		downPipeTable.Node1 = endNodeTable.ID;
		downPipeTable.Node2 = donwNodeSz;
		downPipeTable.Length = donwPipeLength;
		downPipeTable.Diameter = donwPipeDiametor;
		downPipeTable.Roughness = upperPipeFriction;
		downPipeTable.Status = "Open";
		downPipeTable.MinorLoss = vaLoss;

		mPipesVec.push_back(downPipeTable);
		mPipesVec.push_back(upperPipeTable);

		// 普通阀门等效于管段
		if (upperVaType == "BV")
		{
			// 构造一条虚拟管段
			CivPipe::PipesTable vPipeTable;
			vPipeTable.ID = "VG" + vaSzNo;
			vPipeTable.Node1 = startNodeTable.ID;
			vPipeTable.Node2 = endNodeTable.ID;
			vPipeTable.Length = donwPipeLength;
			vPipeTable.Diameter = donwPipeDiametor;
			vPipeTable.Roughness = upperPipeFriction;
			vPipeTable.Status = (vaStatus == "Close")?"CV":"Open";
			vPipeTable.MinorLoss = vaLoss;

			mPipesVec.push_back(vPipeTable);
		}
		else
		{
			// 阀门
			CivValve::ValveTable valveTable;
			valveTable.ID = vaSzNo;
			valveTable.Node1 = startNodeTable.ID;
			valveTable.Node2 = endNodeTable.ID;
			valveTable.Diameter = upperPipeDiametor;
			valveTable.Type = vaType;
			valveTable.Setting = vaSetting;
			valveTable.MinorLoss = vaLoss;

			mValuvesVec.push_back(valveTable);

			// 阀门状态组件
			CivStatus::StatusTable statusTable;
			statusTable.ID = vaSzNo;
			statusTable.Setting = vaStatus;

			mStatusVec.push_back(statusTable);
		}
	}
}