package com.steering.pss.plan.lenthCal;

import java.util.List;

/*
 * 长度计算方法类
 * @author 杨天海
 * @version v1.1
 * @date 2015.05.22
 */
public class CoreLenCalculate{
	/*
	 * 圆周率
	 */
	private static double Pi = 3.1415926;		//圆周率
	
	/*
	 * 计算过程
	 */
	public static LenCalculateOutObject comput(LenCalculateInObject param){
		LenCalculateOutObject paramOut = new LenCalculateOutObject();
		
		double outdiameter = param.getOutdiameter();		//外径
		double wallthick = param.getWallthick();		//壁厚
		double wallLower = param.getWallLower();		//壁厚公差下限(mm)
		double wallUpper = param.getWallUpper();		//壁厚公差上限(mm)
		boolean shrt_stove = param.getShrtstove();		//短尺随炉
		double sigl_len = param.getSigllen();		//单倍尺长
		double burning = param.getBurning()/100;			//烧损(%)
		List<Double> Diameter = param.getDiameter();	//断面(管坯直径)集合
		double lengthmax = param.getLengthmax();		//最大长度
		double lengthmin = param.getLengthmin();		//最小长度
		double Cuthead_tail = param.getCutheadtail();	//切头尾
		double Billetmax = param.getBilletmax();		//环形炉最长(mm)
		double Sizing = param.getSizing();		//定径后max(m)
		double Footmin = param.getFootmin();		//短尺最短(m)
		
		double aimwallthick = 0; 	//控制壁厚
		double aimlength = 0;		//目标长度
		int Cutnum = 0;
		double lengthZz = 0;
		double lossprcent = 0;
		double lengthLimit = 0;		//管极限长度(m)
		double Billet = 0;			//坯料长度
		boolean isOutput = true;	//是否能够生产
		String reason = "";			//不可生产的原因
		double BestDiame = 0;		//最佳断面（mm）
		
		//#start 判断数据是否正常
		//外径、壁厚必须大于零
		if(outdiameter<=0 || wallthick<=0){
			isOutput = false;
			reason = "外径、壁厚必须大于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//烧损率必须小于100%
		if(burning >=1 || burning <0){
			isOutput = false;
			reason = "烧损率必须在0-99%之间！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//最大长度必须大于零
		if(lengthmax <= 0){
			isOutput = false;
			reason = "最大长度必须大于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//最小长度必须大于等于零
		if(lengthmin < 0){
			isOutput = false;
			reason = "最小长度必须大于等于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//切头尾必须大于等于零
		if(Cuthead_tail < 0){
			isOutput = false;
			reason = "切头尾必须大于等于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//环形炉最长必须大于零
		if(Billetmax <= 0){
			isOutput = false;
			reason = "环形炉最长必须大于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//冷床长度必须大于零
		if(Sizing <= 0){
			isOutput = false;
			reason = "冷床长度必须大于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//短尺最短必须大于等于零
		if(Footmin < 0){
			isOutput = false;
			reason = "短尺最短必须大于等于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		//#end
		
		//壁厚公差标准（内控）
		aimwallthick = ((wallthick - wallLower) + (wallthick + wallUpper)) / 2;
		if(aimwallthick <= 0){
			isOutput = false;
			reason = "控制壁厚必须大于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		//管单重
		double weight_one = 0.02466 * aimwallthick * (outdiameter - aimwallthick);
		
		//坯料米单重
		double weight_m = 0;
		
		//坯料重量
		double Billet_weight = 0;
		
		//有无比冷床长度小的管极限长度。
		boolean isSmallerSize = false;

		///循环断面集合，找出最佳断面
		for(int i=0;i<Diameter.size();i++){
			double diame = Diameter.get(i);
			
			//坯料米单重
			double weightofm = (7.8*Pi/4*diame*diame)/1000/1000;
			
			//坯料重量
			double billetweight = weightofm * Billetmax/1000;
			
			//轧制后管长max
			double lengthZzmax = billetweight*(1-burning)*1000/weight_one;
			
			///与冷床长度比较
			if(lengthZzmax > 0 && Sizing > lengthZzmax){
				isSmallerSize = true;
				
				//比冷床长度小的，最长的作为管极限长度。
				if(lengthLimit < lengthZzmax){
					lengthLimit = lengthZzmax;
					BestDiame = diame;
					weight_m = weightofm;
					Billet_weight = billetweight;
				}
			}
		}
		
		///如果没有比冷床长度小的管极限长度。
		if(!isSmallerSize){
			lengthLimit = Sizing;
			Billet_weight = Sizing*weight_one/1000/(1-burning);
			
			//坯料米单重
			for(int i=0;i<Diameter.size();i++){
				double diame = Diameter.get(i);
				if(diame > 0){
					if(BestDiame == 0 || BestDiame > diame){
						BestDiame = diame;
					}
				}
			}
			
			///坯料断面必须大于零
			if(BestDiame <= 0){
				isOutput = false;
				reason = "坯料断面必须大于零！";
				paramOut.setisOutput(isOutput);
				paramOut.setReason(reason);
				return paramOut;
			}
			
			weight_m = (7.8*Pi/4*BestDiame*BestDiame)/1000/1000;
			Billetmax = Billet_weight*1000/weight_m;
		}
		
		if(lengthLimit > 0){
			///分切过程
			//1.无短尺随炉and无使用单倍长度
			if(!shrt_stove && sigl_len <= 0){
				int x = (int)((lengthLimit-Cuthead_tail)/lengthmax);
				int y = (int)((lengthLimit-Cuthead_tail)/lengthmin);
				if(y > 0){
					int z = y - x;
					if(z>=1){
						Cutnum = x + 1;
						lengthZz = lengthLimit;
						aimlength = (lengthZz-Cuthead_tail)/Cutnum;//成品长度
					}
					else{
						Cutnum = x;
						lengthZz = x*lengthmax + Cuthead_tail;
						aimlength = lengthmax;		//成品长度
					}
				}
				else{
					isOutput = false;
					reason = "管长度太短，无法分切！";
					paramOut.setisOutput(isOutput);
					paramOut.setReason(reason);
					return paramOut;
				}
			}
			//2.短尺随炉
			if(shrt_stove && sigl_len <= 0){
				int x = (int)((lengthLimit-Cuthead_tail)/lengthmax);
				int y = (int)((lengthLimit-Cuthead_tail)/lengthmin);
				if(y > 0){
					int z = y - x;
					if(z>1){
						Cutnum = x + 1;
						lengthZz = lengthLimit;
						aimlength = (lengthZz-Cuthead_tail)/Cutnum;		//成品长度
					}
					else{
						if(((((lengthLimit-Cuthead_tail)/lengthmin)-y)*lengthmin) >= 6.5){
							Cutnum = y + 1;
							lengthZz = lengthLimit;
							aimlength = lengthmin;
						}
						else{
							Cutnum = x;
							lengthZz = x * lengthmax + Cuthead_tail;
							aimlength = lengthmax;		//成品长度
						}
					}
				}
				else{
					isOutput = false;
					reason = "管长度太短，无法分切！";
					paramOut.setisOutput(isOutput);
					paramOut.setReason(reason);
					return paramOut;
				}
			}
			//3.单倍尺长
			if(sigl_len > 0){
				int a = 0;						//最小倍尺数
				int b = 0;						//最大倍尺数
				int w = 0;						//有多少种分切方案
				double min = lengthmin;			//短尺最短与长度下限比较取小者
				if(Footmin > 0 && Footmin < lengthmin){
					min = Footmin;
				}
				a = (int)(min/sigl_len);			//最小倍尺数
				b = (int)(lengthmax/sigl_len);		//最大倍尺数
				if((a*sigl_len)<min){
					a = a + 1;
				}
				w = b - a + 1;						//有多少种分切方案
				for(int i = 0; i < w; i++){
					double result = (int)(lengthLimit/((b-i)*sigl_len))
					*((b-i)*sigl_len);
					if(lengthZz < result){
						lengthZz = result;
						Cutnum = (int)(lengthLimit/((b-i)*sigl_len));
						aimlength = (b-i)*sigl_len;		//成品长度
					}
				}
				lengthZz = lengthZz + Cuthead_tail;
			}
			
			//管长度太短，无法分切
			if(Cutnum <= 0){
				isOutput = false;
				reason = "管长度太短，无法分切！";
				paramOut.setisOutput(isOutput);
				paramOut.setReason(reason);
				return paramOut;
			}

			///损失率
			lossprcent = (lengthLimit-lengthZz)/lengthLimit*100;

			//铸坯
			Billet_weight = (weight_one*((Cutnum*aimlength)
					+Cuthead_tail))/(1-burning)/1000;
			Billet = Billet_weight*1000/weight_m;
		}
		else{
			isOutput = false;
			reason = "管长度必须大于零！";
			paramOut.setisOutput(isOutput);
			paramOut.setReason(reason);
			return paramOut;
		}
		
		paramOut.setAimwallthick(aimwallthick);
		paramOut.setAimlength(aimlength);
		paramOut.setCutnum(Cutnum);
		paramOut.setLengthZz(lengthZz);
		paramOut.setLossprcent(lossprcent);
		paramOut.setLengthLimit(lengthLimit);
		paramOut.setBillet(Billet);
		paramOut.setBestDiame(BestDiame);
		paramOut.setisOutput(isOutput);
		paramOut.setReason(reason);
		return paramOut;
	}

}