/// <summary> /// 시운전 그래프를 기준으로 ballast와 scanlt 사이의 각 draft 별 power, speed 계수를 구하여 Json으로 리턴 /// </summary> /// <param name="shipParticular">선박제원정보</param> /// <param name="seaTrialPowerToSpeedAtBallast">Power Speed 변환계수(ballast)</param> /// <param name="seaTrialPowerToSpeedAtScant">Power Speed 변환계수(scant)</param> /// <returns>각 10cm 별 power speed 계수를 Json 형식으로 변환</returns> public JObject speedPowerTableJson(SHIP_PARTICULAR_DETAIL shipParticularDetail, SHIP_PARTICULAR_DETAIL standardData) { JObject result = new JObject(); double seatrialdraftScantling = (standardData.DRAFT_FORE_SCANTLING + standardData.DRAFT_AFT_SCANTLING) * 0.5; //Draft (Scantling) Fore , Draft (Scantling) Aft double seaTrialdraftBallast = (standardData.DRAFT_FORE_BALLAST + standardData.DRAFT_AFT_BALLAST) * 0.5; //Draft (Ballast) Fore, Draft (Ballast) Aft List <double[]> draftTable = new List <double[]> { }; double startDraft = Math.Truncate((seaTrialdraftBallast - 3) * 10); // ref draft -2 부터 시작 (-2는 여유분) int numerOfDraft = (int)((Math.Truncate((seatrialdraftScantling + 3) * 10)) - (Math.Truncate((seaTrialdraftBallast - 3) * 10))); // 스캔틀링까지 소수점 한자리 까지 검색, 기준 draft보다 -2 +2 만큼 큼 int numberOfPwer = (int)(shipParticularDetail.ME_POWER_MCR / 200); //ME_POWER_MCr double[] powerTable = new double[numberOfPwer]; // 확인 완 200 씩 파워 간격을 띄움 --> 커브피팅 알고리즘으로 x 축 배열 double[] speedTable = new double[numberOfPwer]; // 확인 완 파워 간격 만큼 스피드를 계산 --> 커브피팅 알고리즘으로 y 축 배열 var curveFitting = new CurveFitting(); for (int i = 0; i < numerOfDraft; i++) // 드라프트 간격 0.1 만큼 해상도의 커프피팅 테이블을 만듦 { for (int j = 0; j < numberOfPwer; j++) { powerTable[j] = (j + 1) * 200; speedTable[j] = ((standardData.B_SPEED_TO_POWER_SCANTLING * Math.Pow(powerTable[j], standardData.A_SPEED_TO_POWER_SCANTLING) - standardData.B_SPEED_TO_POWER_BALLAST * Math.Pow(powerTable[j], standardData.A_SPEED_TO_POWER_BALLAST)) / // Seatrial PowerToSpeed(Scant') (seatrialdraftScantling - seaTrialdraftBallast) * ((i + startDraft) * 0.1 - seaTrialdraftBallast) + (standardData.B_SPEED_TO_POWER_BALLAST * Math.Pow(powerTable[j], standardData.A_SPEED_TO_POWER_BALLAST))); // Seatrial PowerToSpeed(Ballast') } var curve = curveFitting.powerRegression(speedTable, powerTable); result.Add(((startDraft + i) / 10).ToString(), new JArray(curve[1], curve[2])); } return(result); }
static public List <SAILING_DATA_FOR_19030> Convert(List <SAILING_DATA> sailingData, SHIP_PARTICULAR_DETAIL shipParticularDetail) { List <SAILING_DATA_FOR_19030TEMP> rawShipdata = new List <SAILING_DATA_FOR_19030TEMP>(); foreach (var item in sailingData) { SAILING_DATA_FOR_19030TEMP temp = new SAILING_DATA_FOR_19030TEMP(); temp.CALLSIGN = item.CALLSIGN; temp.TIME_STAMP = item.TIME_STAMP; temp.SPEED_VG = item.SPEED_VG; temp.SPEED_LW = item.SPEED_LW; temp.SPEED_LW_VIRTUAL = item.SPEED_LW_VIRTUAL; temp.REL_WIND_DIR = item.REL_WIND_DIR; temp.REL_WIND_SPEED = item.REL_WIND_SPEED; temp.WIND_SPEED_HEADING_TO_TAIL = item.WIND_SPEED_HEADING_TO_TAIL; temp.COURSE_OVER_GROUND = item.COURSE_OVER_GROUND; temp.SHIP_HEADING = item.SHIP_HEADING; temp.WATER_DEPTH = item.WATER_DEPTH; temp.RUDDER_ANGLE = item.RUDDER_ANGLE; temp.SW_TEMP = item.SW_TEMP; temp.AIR_TEMP = item.AIR_TEMP; temp.AIR_DENSITY = item.AIR_DENSITY; temp.AIR_PRESSURE = item.AIR_PRESSURE; temp.DRAFT_FORE = item.DRAFT_FORE; temp.DRAFT_AFT = item.DRAFT_AFT; temp.ROLL = item.ROLL; temp.PITCH = item.PITCH; temp.ABS_WIND_DIR = item.ABS_WIND_DIR; temp.ABS_WIND_SPEED = item.ABS_WIND_SPEED; temp.BHP_BY_FOC = item.BHP_BY_FOC; temp.ME_FOC_HOUR = item.ME_FOC_HOUR; temp.SLIP = item.SLIP; temp.SHAFT_REV = item.SHAFT_REV; temp.SHAFT_POWER = item.SHAFT_POWER; temp.SHAFT_THRUST = item.SHAFT_THRUST; temp.SHAFT_TORQUE = item.SHAFT_TORQUE; temp.SSS = item.SSS; temp.SST = item.SST; temp.CURRENT_UV = item.CURRENT_UV; temp.CURRENT_VV = item.CURRENT_VV; temp.CURRENT_VEL = item.CURRENT_VEL; temp.CURRENT_DIR = item.CURRENT_DIR; temp.CURRENT_VEL_TAIL_TO_HEADING_NOWCAST = item.CURRENT_VEL_TAIL_TO_HEADING_NOWCAST; temp.SWDIR_SEQ1 = item.SWDIR_SEQ1; temp.SWDIR_SEQ2 = item.SWDIR_SEQ2; temp.WVDIR = item.WVDIR; temp.MWSPER = item.MWSPER; temp.MWSDIR = item.MWSDIR; temp.SWPER_SEQ1 = item.SWPER_SEQ1; temp.SWPER_SEQ2 = item.SWPER_SEQ2; temp.WVPER = item.WVPER; temp.DIRPW = item.DIRPW; temp.PERPW = item.PERPW; temp.HTSGW = item.HTSGW; temp.SWELL_SEQ1 = item.SWELL_SEQ1; temp.SWELL_SEQ2 = item.SWELL_SEQ2; temp.WVHGT = item.WVHGT; temp.UGRD = item.UGRD; temp.VGRD = item.VGRD; temp.WDIR = item.WDIR; temp.WIND = item.WIND; temp.WIND_SPEED_HEADING_TO_TAIL_NOWCAST = item.WIND_SPEED_HEADING_TO_TAIL_NOWCAST; temp.VALID_CHAUVENT = true; temp.VALID_VALIDATION = true; temp.VALID_REFCONDITION = true; rawShipdata.Add(temp); } List <SAILING_DATA_FOR_19030TEMP> afterChauvent_shipdata = new List <SAILING_DATA_FOR_19030TEMP> { }; //인수로 넣은 List 와 동일한 자료형으로 만들 것 List <SAILING_DATA_FOR_19030TEMP> afterValID_shipdata = new List <SAILING_DATA_FOR_19030TEMP> { }; List <SAILING_DATA_FOR_19030TEMP> afterRef_shipdata = new List <SAILING_DATA_FOR_19030TEMP> { }; var callSign = shipParticularDetail.CALLSIGN; int FILTER_TOTAL_COUNT = 0; int VALID_COUNT = 0; int REF_CONDITION_COUNT = 0; int count_rawShipdata = 0; foreach (var item in rawShipdata) { item.ID = count_rawShipdata; count_rawShipdata++; } IEnumerable <List <SAILING_DATA_FOR_19030TEMP> > tenMinBlock_shipdata = from s in rawShipdata group s by new { s.TIME_STAMP.Year, s.TIME_STAMP.Month, s.TIME_STAMP.Day, s.TIME_STAMP.Hour, Minute = s.TIME_STAMP.Minute / 10 } into groupShipdata orderby groupShipdata.Key.Year, groupShipdata.Key.Month, groupShipdata.Key.Day, groupShipdata.Key.Hour, groupShipdata.Key.Minute ascending select groupShipdata.ToList(); foreach (var item in tenMinBlock_shipdata) { var BHP_BY_FOC = Chauvent(item.Select(d => d.BHP_BY_FOC)); var REL_WIND_DIR = Chauvent_angle(item.Select(d => d.REL_WIND_DIR)); var REL_WIND_SPEED = Chauvent(item.Select(d => d.REL_WIND_SPEED)); var SPEED_VG = Chauvent(item.Select(d => d.SPEED_VG)); var SHAFT_REV = Chauvent(item.Select(d => d.SHAFT_REV)); var SHIP_HEADING = Chauvent_angle(item.Select(d => d.SHIP_HEADING)); var DRAFT_FORE = Chauvent(item.Select(d => d.DRAFT_FORE)); var DRAFT_AFT = Chauvent(item.Select(d => d.DRAFT_AFT)); var WATER_DEPTH = Chauvent(item.Select(d => d.WATER_DEPTH)); var RUDDER_ANGLE = Chauvent_angle(item.Select(d => d.RUDDER_ANGLE)); var SW_TEMP = Chauvent(item.Select(d => d.SST)); var AIR_TEMP = Chauvent(item.Select(d => d.AIR_TEMP)); var SHAFT_POWER = Chauvent(item.Select(d => d.SHAFT_POWER)); int count_chauvent = 0; foreach (var item2 in item) { item2.VALID_CHAUVENT = BHP_BY_FOC[count_chauvent] && REL_WIND_DIR[count_chauvent] && REL_WIND_SPEED[count_chauvent] && SPEED_VG[count_chauvent] && SHAFT_REV[count_chauvent] && SHIP_HEADING[count_chauvent] && DRAFT_FORE[count_chauvent] && DRAFT_AFT[count_chauvent] && WATER_DEPTH[count_chauvent] && RUDDER_ANGLE[count_chauvent] && SW_TEMP[count_chauvent] && AIR_TEMP[count_chauvent] && SHAFT_POWER[count_chauvent]; if (item2.VALID_CHAUVENT == true) { afterChauvent_shipdata.Add(item2); } else { rawShipdata[FILTER_TOTAL_COUNT].VALID_CHAUVENT = false; rawShipdata[FILTER_TOTAL_COUNT].VALID_VALIDATION = false; rawShipdata[FILTER_TOTAL_COUNT].VALID_REFCONDITION = false; } FILTER_TOTAL_COUNT++; count_chauvent++; } } IEnumerable <List <SAILING_DATA_FOR_19030TEMP> > afterChauvent_tenMinBlock_shipdata = from s in afterChauvent_shipdata group s by new { s.TIME_STAMP.Year, s.TIME_STAMP.Month, s.TIME_STAMP.Day, s.TIME_STAMP.Hour, Minute = s.TIME_STAMP.Minute / 10 } into groupShipdata orderby groupShipdata.Key.Year, groupShipdata.Key.Month, groupShipdata.Key.Day, groupShipdata.Key.Hour, groupShipdata.Key.Minute ascending select groupShipdata.ToList(); foreach (var item in afterChauvent_tenMinBlock_shipdata) { var RUDDER_ANGLE_VALID = standardError_angle(item.Select(d => d.RUDDER_ANGLE), 1); var SHAFT_REV_VALID = standardError(item.Select(d => d.SHAFT_REV), 3); var SPEED_VG_VALID = standardError(item.Select(d => d.SPEED_VG), 0.5f); int temp_i = 0; foreach (var item2 in item) { int index = (int)item2.ID; item2.VALID_VALIDATION = SHAFT_REV_VALID[temp_i] && SPEED_VG_VALID[temp_i] && RUDDER_ANGLE_VALID[temp_i]; if (item2.VALID_VALIDATION == true) { afterValID_shipdata.Add(item2); } else { rawShipdata.ElementAt((int)item2.ID).VALID_VALIDATION = false; rawShipdata.ElementAt((int)item2.ID).VALID_REFCONDITION = false; VALID_COUNT++; } } } foreach (var item in afterValID_shipdata) { var speedVg = item.SPEED_VG * 0.5144f; var waterDepth1 = 3 * Math.Sqrt(shipParticularDetail.BREADTH * ((item.DRAFT_FORE + item.DRAFT_AFT) / 2)); var waterDepth2 = 2.75 * (speedVg * speedVg) / 9.80665; if (waterDepth1 < waterDepth2) { waterDepth1 = waterDepth2; } int index = (int)item.ID; if (item.SST <= 2 || item.SST > 50 || item.WATER_DEPTH <= waterDepth1 || Math.Abs(item.RUDDER_ANGLE) >= 5) { rawShipdata.ElementAt(index).VALID_REFCONDITION = false; REF_CONDITION_COUNT++; } else { afterRef_shipdata.Add(item); rawShipdata.ElementAt(index).VALID_REFCONDITION = true; } } List <SAILING_DATA_FOR_19030> result = new List <SAILING_DATA_FOR_19030>(); foreach (var item in rawShipdata) { if (item.VALID_CHAUVENT == false || item.VALID_CHAUVENT == false || item.VALID_REFCONDITION == false) { SAILING_DATA_FOR_19030 temp = new SAILING_DATA_FOR_19030(); temp.CALLSIGN = item.CALLSIGN; temp.TIME_STAMP = item.TIME_STAMP; temp.SPEED_VG = item.SPEED_VG; temp.SPEED_LW = item.SPEED_LW; temp.SPEED_LW_VIRTUAL = item.SPEED_LW_VIRTUAL; temp.REL_WIND_DIR = item.REL_WIND_DIR; temp.REL_WIND_SPEED = item.REL_WIND_SPEED; temp.WIND_SPEED_HEADING_TO_TAIL = item.WIND_SPEED_HEADING_TO_TAIL; temp.COURSE_OVER_GROUND = item.COURSE_OVER_GROUND; temp.SHIP_HEADING = item.SHIP_HEADING; temp.WATER_DEPTH = item.WATER_DEPTH; temp.RUDDER_ANGLE = item.RUDDER_ANGLE; temp.SW_TEMP = item.SW_TEMP; temp.AIR_TEMP = item.AIR_TEMP; temp.AIR_DENSITY = item.AIR_DENSITY; temp.AIR_PRESSURE = item.AIR_PRESSURE; temp.DRAFT_FORE = item.DRAFT_FORE; temp.DRAFT_AFT = item.DRAFT_AFT; temp.ROLL = item.ROLL; temp.PITCH = item.PITCH; temp.ABS_WIND_DIR = item.ABS_WIND_DIR; temp.ABS_WIND_SPEED = item.ABS_WIND_SPEED; temp.BHP_BY_FOC = item.BHP_BY_FOC; temp.ME_FOC_HOUR = item.ME_FOC_HOUR; temp.SLIP = item.SLIP; temp.SHAFT_REV = item.SHAFT_REV; temp.SHAFT_POWER = item.SHAFT_POWER; temp.SHAFT_TORQUE = item.SHAFT_TORQUE; temp.SHAFT_THRUST = item.SHAFT_THRUST; temp.SSS = item.SSS; temp.SST = item.SST; temp.CURRENT_UV = item.CURRENT_UV; temp.CURRENT_VV = item.CURRENT_VV; temp.CURRENT_VEL = item.CURRENT_VEL; temp.CURRENT_DIR = item.CURRENT_DIR; temp.CURRENT_VEL_TAIL_TO_HEADING_NOWCAST = item.CURRENT_VEL_TAIL_TO_HEADING_NOWCAST; temp.SWDIR_SEQ1 = item.SWDIR_SEQ1; temp.SWDIR_SEQ2 = item.SWDIR_SEQ2; temp.WVDIR = item.WVDIR; temp.MWSPER = item.MWSPER; temp.MWSDIR = item.MWSDIR; temp.SWPER_SEQ1 = item.SWPER_SEQ1; temp.SWPER_SEQ2 = item.SWPER_SEQ2; temp.WVPER = item.WVPER; temp.DIRPW = item.DIRPW; temp.PERPW = item.PERPW; temp.HTSGW = item.HTSGW; temp.SWELL_SEQ1 = item.SWELL_SEQ1; temp.SWELL_SEQ2 = item.SWELL_SEQ2; temp.WVHGT = item.WVHGT; temp.UGRD = item.UGRD; temp.VGRD = item.VGRD; temp.WDIR = item.WDIR; temp.WIND = item.WIND; temp.WIND_SPEED_HEADING_TO_TAIL_NOWCAST = item.WIND_SPEED_HEADING_TO_TAIL_NOWCAST; result.Add(temp); } } return(result); }