#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "calc_gate.h"

#define WISFARM_DEBUG
#define LOG_TAG             "gate.calc"
#include <wisfarm_log.h>


typedef enum {
	gate_full_open_with_free_flow = 0,    					/*A 闸门全开自由流*/
	gate_full_open_with_submerged_flow,						/*B 闸门全开淹没流*/
	gate_control_with_free_flow,							/*C 闸门控制自由流*/
	gate_control_with_submerged_flow,						/*D 闸门控制淹没流*/
	gate_full_open_with_free_flow_drop_step,				/*E 闸门全开自由流 有跌槛*/
	gate_full_open_with_submerged_flow_drop_step,			/*F 闸门全开淹没流 有跌槛*/
	gate_control_with_free_flow_drop_step,					/*G 闸门控制自由流 有跌槛*/
	gate_control_with_submerged_flow_drop_step				/*H 闸门控制淹没流 有跌槛*/
}patterns_of_water;

enum {
	NOTHINGNESS	=	0,
	EXIST
};
enum{
	warped_wingwall=1, 	/*弯曲墙面*/
	flat_wingwall,		/*平整墙面*/
	eight_c_wingwall,	/*八字墙面*/
	parallel_wingwall	/*平行墙面*/
};

struct warped_wingwall_para{
	double m_warped_wingwall;
	double m_warped_wingwall_ds;
	double m_flat_wingwall;
	double m_flat_wingwall_ds;
	double m_eight_c_wingwall;
	double m_eight_c_wingwall_ds;
	double m_parallel_wingwall;
	double m_parallel_wingwall_ds;
};

struct flat_wingwall_para{
	double fai_warped_wingwall;		//float m_warped_wingwall_ds;
	double fai_flat_wingwall;		//float m_flat_wingwall_ds;
	double fai_eight_c_wingwall;	//float m_eight_c_wingwall_ds;
	double fai_parallel_wingwall;	//float m_parallel_wingwall_ds;
};


struct eight_c_wingwall_para{
	double miu_warped_wingwall;
	double miu_warped_wingwall_ds;
	double miu_flat_wingwall;
	double miu_flat_wingwall_ds;
	double miu_eight_c_wingwall;
	double miu_eight_c_wingwall_ds;
	double miu_parallel_wingwall;
	double miu_parallel_wingwall_ds;
};
typedef struct total{
	struct warped_wingwall_para 	A;
	struct flat_wingwall_para 		B;
	struct eight_c_wingwall_para 	C;
	struct eight_c_wingwall_para 	D;
}coefficient_infor;

/*
 *几种墙面分别对应的系数
 *
*/
const coefficient_infor coefficient={
	{0.325,	0.380,	0.310,	0.365,	0.330,	0.390,	0.295,	0.355},
	{0.85,	0.825,	0.860,	0.795},
	{0.6,	0.625,	0.58,	0.60,	0.62,	0.64,	0.61,	0.65},
	{0.6,	0.625,	0.6,	0.6,	0.64,	0.64,	0.63,	0.65}
};
/*
 *函数名：	data_validity_check()
 *参数：	*param
 *功能：	检查传入的参数是否是有效参数
 *返回值：	0表示参数是合法的，非0表示不合法
 *
*/
int data_validity_check(struct param_gate *param)
{
	if(param->wingwall < warped_wingwall || param->wingwall>parallel_wingwall){
		return -1;
	}
	if(!(param->drop_step == 0 || param->drop_step == 1)){
		return -1;
	}
	if(param->openning_height_of_gate <-0.0000001){
		return -1;
	}
	if(param->water_depth_front_of_gate <-0.0000001){
		return -1;
	}
	if(param->water_depth_behind_of_gate <-0.0000001){
		return -1;
	}
	if(param->gate_width <-0.0000001){
		return -1;
	}
	return 0;
}

/*
 *函数名：	discrimination_of_flow_pattern()
 *参数：		openning_height_of_gate  		开闸高度
 *			water_depth_front_of_gate	闸前水位
 *			water_depth_behind_of_gate	闸后水位
 *			drop_step					跌槛
 *功能：	根据以上参数，判断出是那个水流模型
 *返回值：	水流模型
 *
*/

patterns_of_water discrimination_of_flow_pattern(double openning_height_of_gate,double water_depth_front_of_gate,double water_depth_behind_of_gate,int drop_step)
{
	if((openning_height_of_gate/water_depth_front_of_gate > 0.65) && (water_depth_behind_of_gate/water_depth_front_of_gate < 0.7)){
		if(drop_step == EXIST)
			return gate_full_open_with_free_flow_drop_step;
		else
			return gate_full_open_with_free_flow;
	}else if((openning_height_of_gate/water_depth_front_of_gate > 0.65) && (water_depth_behind_of_gate/water_depth_front_of_gate > 0.7)){
		if(drop_step == EXIST)
			return gate_full_open_with_submerged_flow_drop_step;
		else
			return gate_full_open_with_submerged_flow;
	}else if((openning_height_of_gate/water_depth_front_of_gate <= 0.65) && (water_depth_behind_of_gate < openning_height_of_gate)){
		if(drop_step == EXIST)
			return gate_control_with_free_flow_drop_step;
		else
			return gate_control_with_free_flow;
	}else if((water_depth_behind_of_gate > openning_height_of_gate)&& (water_depth_front_of_gate>openning_height_of_gate)){
		if(drop_step == EXIST)
			return gate_control_with_submerged_flow_drop_step;
		else
			return gate_control_with_submerged_flow;
	}
}


struct datas{
    double original_data_front;
    double original_data_after;
    double value;
};
const struct datas table[46]={
	{0.00,0.05,1.00},
	{0.05,0.15,0.990},
	{0.15,0.25,0.980},
	{0.25,0.35,0.970},
	{0.35,0.45,0.956},
	{0.45,0.475,0.947},
	{0.475,0.525,0.937},
	{0.525,0.575,0.925},
	{0.575,0.625,0.907},
	{0.625,0.675,0.885},
	{0.675,0.710,0.856},
	{0.710,0.730,0.843},
	{0.730,0.750,0.828},
	{0.750,0.770,0.813},
	{0.770,0.790,0.800},
	{0.790,0.805,0.778},
	{0.805,0.815,0.767},
	{0.815,0.825,0.755},
	{0.825,0.835,0.742},
	{0.835,0.845,0.728},
	{0.845,0.855,0.713},
	{0.855,0.865,0.698},
	{0.865,0.875,0.681},
	{0.875,0.885,0.662},
	{0.885,0.895,0.642},
	{0.895,0.9025,0.621},
	{0.9025,0.9075,0.608},
	{0.9075,0.9125,0.595},
	{0.9125,0.9175,0.580},
	{0.9175,0.9225,0.565},
	{0.9225,0.9275,0.549},
	{0.9275,0.9325,0.532},
	{0.9325,0.9375,0.514},
	{0.9375,0.9425,0.484},
	{0.9425,0.9475,0.473},
	{0.9475,0.9525,0.450},
	{0.9525,0.9575,0.427},
	{0.9575,0.9625,0.403},
	{0.9625,0.9675,0.375},
	{0.9675,0.9725,0.344},
	{0.9725,0.9775,0.318},
	{0.9775,0.9825,0.267},
	{0.9825,0.9875,0.225},
	{0.9875,0.9925,0.175},
	{0.9925,0.9975,0.115},
	{0.9975,1.0000,0.000}
};
double find(double target)
{
     int i=0;
     for(i=0;i<46;i++)
     {
         if(target>=table[i].original_data_front && target<table[i].original_data_after)
            return table[i].value;
     }
     return 0;
}

/*
 *函数名：	get_coefficient_rou()
 *参数：	water_depth_front_of_gate
 *			water_depth_behind_of_gate
 *功能：	根据闸前闸后水位，获取ρ
 *返回值：	ρ的值
 *
*/
double get_coefficient_rou(double water_depth_front_of_gate,double water_depth_behind_of_gate)
{
	double s;
	s=water_depth_behind_of_gate/water_depth_front_of_gate;
	return find(s);
}

/*
 *函数名：		cal_gate_full_open_with_free_flow()
 *参数：		water_depth_front_of_gate		闸前水深
 *			water_depth_behind_of_gate		闸后水深
 *			gate_width						闸门宽度
 *			wingwall						翼墙类型
 *			ds								跌槛
 *功能：	根据参数，计算出闸门全开自由流模型下的瞬时流量
 *返回值：	瞬时流量
 *
*/
double cal_gate_full_open_with_free_flow(double water_depth_front_of_gate,double gate_width,int wingwall,int ds)
{
	double instantaneousFlow;

	LOG_I("gate full open with free flow.");

	switch(wingwall){
		case warped_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.A.m_warped_wingwall_ds*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
			else
				instantaneousFlow=coefficient.A.m_warped_wingwall*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
		break;
		case flat_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.A.m_flat_wingwall_ds*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
			else
				instantaneousFlow=coefficient.A.m_flat_wingwall*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
		break;
		case eight_c_wingwall:
			 if(ds == EXIST)
				instantaneousFlow=coefficient.A.m_eight_c_wingwall_ds*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
			else
				instantaneousFlow=coefficient.A.m_eight_c_wingwall*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
		break;
		case parallel_wingwall:
			 if(ds == EXIST)
				instantaneousFlow=coefficient.A.m_parallel_wingwall_ds*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
			else
				instantaneousFlow=coefficient.A.m_parallel_wingwall*gate_width*water_depth_front_of_gate*sqrt(2*g*water_depth_front_of_gate);
		break;
	}
	return instantaneousFlow;
}

/*
 *函数名：		cal_gate_full_open_with_submerged_flow()
 *参数：		water_depth_front_of_gate		闸前水深
 *			water_depth_behind_of_gate		闸后水深
 *			gate_width						闸门宽度
 *			wingwall						翼墙类型
 *			ds								跌槛
 *功能：	根据参数，计算出闸门全开淹没流模型下的瞬时流量
 *返回值：	瞬时流量
 *
*/
double cal_gate_full_open_with_submerged_flow(double water_depth_front_of_gate,double water_depth_behind_of_gate,double gate_width,int wingwall,int ds)
{
	double instantaneousFlow;

	LOG_I("gate full open with submerged flow.");

	switch(wingwall){
		case warped_wingwall:
		    if(ds == EXIST)
        		instantaneousFlow=coefficient.B.fai_warped_wingwall*gate_width*get_coefficient_rou(water_depth_front_of_gate,water_depth_behind_of_gate)\
				*water_depth_behind_of_gate*sqrt(2*g*water_depth_front_of_gate);
            else
                instantaneousFlow=coefficient.B.fai_warped_wingwall*gate_width*water_depth_behind_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
		case flat_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.B.fai_flat_wingwall*gate_width*get_coefficient_rou(water_depth_front_of_gate,water_depth_behind_of_gate)*water_depth_behind_of_gate\
				*sqrt(2*g*water_depth_front_of_gate);
            else
                instantaneousFlow=coefficient.B.fai_flat_wingwall*gate_width*water_depth_behind_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
		case eight_c_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.B.fai_eight_c_wingwall*gate_width*get_coefficient_rou(water_depth_front_of_gate,water_depth_behind_of_gate)*water_depth_behind_of_gate\
				*sqrt(2*g*water_depth_front_of_gate);
            else
                instantaneousFlow=coefficient.B.fai_eight_c_wingwall*gate_width*water_depth_behind_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
		case parallel_wingwall:
			 if(ds == EXIST)
				instantaneousFlow=coefficient.B.fai_parallel_wingwall*gate_width*get_coefficient_rou(water_depth_front_of_gate,water_depth_behind_of_gate)*water_depth_behind_of_gate\
				*sqrt(2*g*water_depth_front_of_gate);
            else
                instantaneousFlow=coefficient.B.fai_parallel_wingwall*gate_width*water_depth_behind_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
	}
	return instantaneousFlow;
}

/*
 *函数名：		cal_gate_control_with_free_flow()
 *参数：		water_depth_front_of_gate		闸前水深
 *			water_depth_behind_of_gate		闸后水深
 *			height_of_gate					闸门开启高度
 *			gate_width						闸门宽度
 *			wingwall						翼墙类型
 *			ds								跌槛
 *功能：	根据参数，计算出闸门控制自由流模型下的瞬时流量
 *返回值：	瞬时流量
 *
*/
double cal_gate_control_with_free_flow(double water_depth_front_of_gate,double water_depth_behind_of_gate,double height_of_gate,double gate_width,int wingwall,int ds)
{
	double instantaneousFlow;

	LOG_I("gate control with free flow.");

	switch(wingwall){
		case warped_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.C.miu_warped_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.5*height_of_gate));
			else
				instantaneousFlow=coefficient.C.miu_warped_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.65*height_of_gate));
		break;
		case flat_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.C.miu_flat_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.5*height_of_gate));
			else
				instantaneousFlow=coefficient.C.miu_flat_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.65*height_of_gate));
		break;
		case eight_c_wingwall:
			 if(ds == EXIST)
				instantaneousFlow=coefficient.C.miu_eight_c_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.5*height_of_gate));
			else
				instantaneousFlow=coefficient.C.miu_eight_c_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.65*height_of_gate));
		break;
		case parallel_wingwall:
			 if(ds == EXIST)
				instantaneousFlow=coefficient.C.miu_parallel_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.5*height_of_gate));
			else
				instantaneousFlow=coefficient.C.miu_parallel_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-0.65*height_of_gate));
		break;
	}
	return instantaneousFlow;
}

/*
 *函数名：		cal_gate_control_with_submerged_flow()
 *参数：		water_depth_front_of_gate		闸前水深
 *			water_depth_behind_of_gate		闸后水深
 *			height_of_gate					闸门开启高度
 *			gate_width						闸门宽度
 *			wingwall						翼墙类型
 *			ds								跌槛
 *功能：		根据参数，计算出闸门控制淹没流模型下的瞬时流量
 *返回值：		瞬时流量
 *
*/
double cal_gate_control_with_submerged_flow(double water_depth_front_of_gate,double water_depth_behind_of_gate,double height_of_gate,double gate_width,int wingwall,int ds)
{
	double instantaneousFlow;

	LOG_I("gate control with submerged flow.");

	switch(wingwall){
		case warped_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.D.miu_warped_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
			else
				instantaneousFlow=coefficient.D.miu_warped_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
		case flat_wingwall:
			if(ds == EXIST)
				instantaneousFlow=coefficient.D.miu_flat_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
			else
				instantaneousFlow=coefficient.D.miu_flat_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
		case eight_c_wingwall:
			 if(ds == EXIST)
				instantaneousFlow=coefficient.D.miu_eight_c_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
			else
				instantaneousFlow=coefficient.D.miu_eight_c_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
		case parallel_wingwall:
			 if(ds == EXIST)
				instantaneousFlow=coefficient.D.miu_parallel_wingwall_ds*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
			else
				instantaneousFlow=coefficient.D.miu_parallel_wingwall*gate_width*height_of_gate*sqrt(2*g*(water_depth_front_of_gate-water_depth_behind_of_gate));
		break;
	}
	return instantaneousFlow;
}

/*
 *函数名：	Calculation_of_InstantaneousFlow()
 *参数：	*param		指向struct param_gate的指针
 *
 *功能：	根据参数，计算出瞬时流量
 *返回值：	瞬时流量
 *
*/
int Calculation_of_InstantaneousFlow(double *value,struct param_gate *param)
{
	patterns_of_water get_pattern;

	if(data_validity_check(param)!=0)
		return -1;

	get_pattern = discrimination_of_flow_pattern(param->openning_height_of_gate,param->water_depth_front_of_gate,param->water_depth_behind_of_gate,param->drop_step);
	switch(get_pattern){
		case gate_full_open_with_free_flow:
				*value = cal_gate_full_open_with_free_flow(param->water_depth_front_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		case gate_full_open_with_submerged_flow:
				*value = cal_gate_full_open_with_submerged_flow(param->water_depth_front_of_gate,param->water_depth_behind_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		case gate_control_with_free_flow:
				*value = cal_gate_control_with_free_flow(param->water_depth_front_of_gate,param->water_depth_behind_of_gate,\
				param->openning_height_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		case gate_control_with_submerged_flow:
				*value = cal_gate_control_with_submerged_flow(param->water_depth_front_of_gate,param->water_depth_behind_of_gate,\
				param->openning_height_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		case gate_full_open_with_free_flow_drop_step:
				*value = cal_gate_full_open_with_free_flow(param->water_depth_front_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		case gate_full_open_with_submerged_flow_drop_step:
				*value = cal_gate_full_open_with_submerged_flow(param->water_depth_front_of_gate,param->water_depth_behind_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		case gate_control_with_free_flow_drop_step:
				*value = cal_gate_control_with_free_flow(param->water_depth_front_of_gate,param->water_depth_behind_of_gate,\
				param->openning_height_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		case gate_control_with_submerged_flow_drop_step:
				*value = cal_gate_control_with_submerged_flow(param->water_depth_front_of_gate,param->water_depth_behind_of_gate,\
				param->openning_height_of_gate,param->gate_width,param->wingwall,param->drop_step);
		break;
		default:
				*value=0;
				return -1;
			break;
	}
	return 0;
}


















