diff --git a/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java b/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java index 952105b8..59373e6c 100644 --- a/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java +++ b/src/main/java/com/interplug/qcast/biz/estimate/EstimateService.java @@ -469,7 +469,7 @@ public class EstimateService { break; } } - + itemRequest.setNorthModuleYn(itemRequest.getNorthModuleYn()); // 아이템 BOM Header인 경우 컴포넌트 등록 처리 if ("ERLA".equals(itemRequest.getItemCtgGr())) { List itemBomList = @@ -507,6 +507,7 @@ public class EstimateService { } } + System.out.print("itemRequest"); // BOM 컴포넌트 추가 itemList.addAll(estimateBomList); @@ -687,13 +688,15 @@ public class EstimateService { itemRequest.setRoofSurfaceId(roofRequest.getRoofSurfaceId()); itemRequest.setObjectNo(estimateRequest.getObjectNo()); itemRequest.setPlanNo(estimateRequest.getPlanNo()); - // 선택한 PCS 아이템이 다른 경우 for (ItemRequest itemObj : itemList) { - if(itemObj.getQcastCustPrdId() != null && itemObj.getQcastCustPrdId().equals(itemRequest.getPcItemId())) { itemRequest.setQcastCustPrdId(itemObj.getItemId()); } + if(itemObj.getItemId().equals(itemRequest.getItemId())) { + itemRequest.setNorthModuleYn(itemObj.getNorthModuleYn()); + } + } estimateMapper.insertEstimateRoofItem(itemRequest); } diff --git a/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemRequest.java b/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemRequest.java index 3770a0b3..8497725a 100644 --- a/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemRequest.java +++ b/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemRequest.java @@ -115,4 +115,7 @@ public class ItemRequest { @Schema(description = "Q.CAST 고객 제품 ID") public String qcastCustPrdId; + + @Schema(description = "모듈의 북면지원여부") + public String northModuleYn; } diff --git a/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemResponse.java b/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemResponse.java index 6d5d7f81..209f4c3d 100644 --- a/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemResponse.java +++ b/src/main/java/com/interplug/qcast/biz/estimate/dto/ItemResponse.java @@ -97,4 +97,7 @@ public class ItemResponse { @Schema(description = "Q.CAST 고객 제품 ID") public String qcastCustPrdId; + + @Schema(description = "모듈의 북면지원여부") + public String northModuleYn; } diff --git a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java index ee3e8378..81449b44 100644 --- a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java +++ b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/PwrGnrSimService.java @@ -1,5 +1,6 @@ package com.interplug.qcast.biz.pwrGnrSimulation; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.interplug.qcast.biz.estimate.dto.*; @@ -25,6 +26,7 @@ import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; @@ -177,6 +179,7 @@ public class PwrGnrSimService { // 견적서 정보 기준으로 발전시뮬레이션 계산을 진행한다. PwrGnrSimRequest pwrGnrSimReq = new PwrGnrSimRequest(); pwrGnrSimReq.setSimulationPointNumber(planInfo.getAreaId() - 1); + pwrGnrSimReq.setSimulationPointCode(planInfo.getSimulationCode()); double[] dKoubai = new double[roofLength]; double[] dHoui = new double[roofLength]; @@ -217,18 +220,21 @@ public class PwrGnrSimService { pwrGnrSimReq.setModuleSpecification1(m.getSpecification()); pwrGnrSimReq.setModuleTempCoeff1(m.getTempCoeff()); pwrGnrSimReq.setModuleTempLoss1(m.getTempLoss()); + pwrGnrSimReq.setNorthModuleYn1(m.getNorthModuleYn()); //모듈 북면지원여부 } else if (k == 1) { pwrGnrSimReq.setModule2(m.getItemId()); pwrGnrSimReq.setModuleAmp2(m.getAmp()); pwrGnrSimReq.setModuleSpecification2(m.getSpecification()); pwrGnrSimReq.setModuleTempCoeff2(m.getTempCoeff()); pwrGnrSimReq.setModuleTempLoss2(m.getTempLoss()); + pwrGnrSimReq.setNorthModuleYn2(m.getNorthModuleYn()); //모듈 북면지원여부 } else { pwrGnrSimReq.setModule3(m.getItemId()); pwrGnrSimReq.setModuleAmp3(m.getAmp()); pwrGnrSimReq.setModuleSpecification3(m.getSpecification()); pwrGnrSimReq.setModuleTempCoeff3(m.getTempCoeff()); pwrGnrSimReq.setModuleTempLoss3(m.getTempLoss()); + pwrGnrSimReq.setNorthModuleYn3(m.getNorthModuleYn()); //모듈 북면지원여부 } k++; } @@ -265,7 +271,6 @@ public class PwrGnrSimService { j++; } } - i++; } @@ -278,7 +283,8 @@ public class PwrGnrSimService { // 발전시뮬레이션 결과와 견적서 정보를 return 한다. PwrGnrSimResponse pwrGnrSimRes = new PwrGnrSimResponse(); try { - pwrGnrSimRes = this.calcResults(pwrGnrSimReq, roofLength); + //pwrGnrSimRes = this.calcResults(pwrGnrSimReq, roofLength); + pwrGnrSimRes = this.calcResults2(pwrGnrSimReq, roofLength); } catch (Exception e) { log.error(e.toString()); //e.printStackTrace(); @@ -305,7 +311,300 @@ public class PwrGnrSimService { return pwrGnrSimRes; } - /** + private PwrGnrSimResponse calcResults2(PwrGnrSimRequest pwrGnrSimReq, int roofLength) throws IOException { + + int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + // Load snow data + List snow = loadJsonArray( + "template/pwrGnrSimulation/snow_db/" + pwrGnrSimReq.getSimulationPointCode() + ".json", + new TypeReference>() {} + ); + + String module_name = null; + double module_system_loss = pwrGnrSimReq.getModuleTempLoss1(); + double ondo_Keisu = pwrGnrSimReq.getModuleTempCoeff1(); // 모듈 온도 계수 + double module_amp = pwrGnrSimReq.getModuleAmp1(); + + if(Double.isNaN(module_system_loss)){ + module_system_loss = pwrGnrSimReq.getModuleTempLoss2(); + } + if(Double.isNaN(ondo_Keisu)){ + ondo_Keisu = pwrGnrSimReq.getModuleTempCoeff2(); + } + if(Double.isNaN(module_amp)){ + module_amp = pwrGnrSimReq.getModuleAmp2(); + } + if(Double.isNaN(module_system_loss)){ + module_system_loss = pwrGnrSimReq.getModuleTempLoss3(); + } + if(Double.isNaN(ondo_Keisu)){ + ondo_Keisu = pwrGnrSimReq.getModuleTempCoeff3(); + } + if(Double.isNaN(module_amp)){ + module_amp = pwrGnrSimReq.getModuleAmp3(); + } + + if(Double.isNaN(module_system_loss) || Double.isNaN(ondo_Keisu) || Double.isNaN(module_amp)){ + log.error("Module system loss, module amp, or module angle is NaN"); + return null; + } + + double module1_watt = pwrGnrSimReq.getModuleSpecification1(); + double module2_watt = pwrGnrSimReq.getModuleSpecification2(); + double module3_watt = pwrGnrSimReq.getModuleSpecification3(); + double module1_watt_flash = module1_watt + 1; + double module2_watt_flash = module2_watt + 1; + double module3_watt_flash = module3_watt + 1; + String northModuleYn1 = pwrGnrSimReq.getNorthModuleYn1(); + boolean module1_north_reduction = (northModuleYn1 != null && northModuleYn1.equals("Y")); + String northModuleYn2 = pwrGnrSimReq.getNorthModuleYn2(); + boolean module2_north_reduction = (northModuleYn2 != null && northModuleYn2.equals("Y")); + String northModuleYn3 = pwrGnrSimReq.getNorthModuleYn3(); + boolean module3_north_reduction = (northModuleYn3 != null && northModuleYn3.equals("Y")); + + //モジュール枚数積算 + int module1_number_total = 0; + int module2_number_total = 0; + int module3_number_total = 0; + + for (int i = 0; i < roofLength; i++) { + if (!Double.isNaN(pwrGnrSimReq.getKoubai()[i]) && !Double.isNaN(pwrGnrSimReq.getHoui()[i])) { + // 설치면 기울기와 방위가 입력되어 있으면 모듈의 매수를 취득 + module1_number_total += pwrGnrSimReq.getModuleInput1()[i]; // amount + module2_number_total += pwrGnrSimReq.getModuleInput2()[i]; + module3_number_total += pwrGnrSimReq.getModuleInput3()[i]; + } + } + + // 모듈 1, 2, 3 총 용량 계산 + double module1_youryou_total = module1_watt * module1_number_total; + double module2_youryou_total = module2_watt * module2_number_total; + double module3_youryou_total = module3_watt * module3_number_total; + + // 모듈 총 용량 계산 + double module_youryou_total = module1_youryou_total + module2_youryou_total + module3_youryou_total; + + if(module1_youryou_total==0){ + log.error("Noting valid roof,you shuld set 'module number','direction' and 'angle' correctly"); + return null; + } + + // 각 월별 온도 손실 계산 + double ondo_keisu = pwrGnrSimReq.getModuleTempCoeff1(); // 모듈 온도 계수 + double[] ondo_sonshitsu = new double[12]; + ondo_sonshitsu[0] = 1 - 0.1 * ondo_keisu / 0.5; + ondo_sonshitsu[1] = 1 - 0.1 * ondo_keisu / 0.5; + ondo_sonshitsu[2] = 1 - 0.1 * ondo_keisu / 0.5; + ondo_sonshitsu[3] = 1 - 0.15 * ondo_keisu / 0.5; + ondo_sonshitsu[4] = 1 - 0.15 * ondo_keisu / 0.5; + ondo_sonshitsu[5] = 1 - 0.2 * ondo_keisu / 0.5; + ondo_sonshitsu[6] = 1 - 0.2 * ondo_keisu / 0.5; + ondo_sonshitsu[7] = 1 - 0.2 * ondo_keisu / 0.5; + ondo_sonshitsu[8] = 1 - 0.2 * ondo_keisu / 0.5; + ondo_sonshitsu[9] = 1 - 0.15 * ondo_keisu / 0.5; + ondo_sonshitsu[10] = 1 - 0.15 * ondo_keisu / 0.5; + ondo_sonshitsu[11] = 1 - 0.1 * ondo_keisu / 0.5; + + // PCS1, pcs2, pcs3 선택 정보 + double pcs1_henkankouritsu = pwrGnrSimReq.getPcsCnvEff1() / 100; // 변환 효율 + double pcs1_youryou = pwrGnrSimReq.getPcsSpecification1(); // 용량 (예시 4.4) + double pcs2_henkankouritsu = pwrGnrSimReq.getPcsCnvEff2() / 100; + double pcs2_youryou = pwrGnrSimReq.getPcsSpecification2(); + double pcs3_henkankouritsu = pwrGnrSimReq.getPcsCnvEff3() / 100; + double pcs3_youryou = pwrGnrSimReq.getPcsSpecification3(); + + double pcs_amp1 = pwrGnrSimReq.getPcsAmp1(); + double pcs_amp2 = pwrGnrSimReq.getPcsAmp2(); + double pcs_amp3 = pwrGnrSimReq.getPcsAmp3(); + + + int pcs1_number = pwrGnrSimReq.getPcsInput1(); + int pcs2_number = pwrGnrSimReq.getPcsInput2(); + int pcs3_number = pwrGnrSimReq.getPcsInput3(); + + // pcs1과 pcs2, pcs3의 실효 변환 효율 중 낮은 값을 사용 + double[] values = {pcs1_henkankouritsu, pcs2_henkankouritsu, pcs3_henkankouritsu}; + double pcs_henkankouritsu = + Arrays.stream(values) + .filter(value -> value > 0.0) // 0.0 제외 + .min() + .orElse(0.0); // 모두 0.0인 경우 기본값 반환 + + // pcs 총 용량 계산 + double pcs_youryou_total = (pcs1_youryou * pcs1_number) + + (pcs2_youryou * pcs2_number) + + (pcs3_youryou * pcs3_number); + + // 적재율 [실수] 계산 + double sekisairitsu = module_youryou_total / (pcs_youryou_total * 1000); + + //過積載率によるスクリーニング + if(sekisairitsu > 3){ + log.error("Too many PV_modules or too few pcs capacity"); + return null; + } + +// double pcs_sekisairitsu = 0; //new +// if(sekisairitsu >= pcs_sekisairitsu/100){ +// log.error("Too many PV_modules or too few pcs capacity"); +// return null; +// } + + if(pcs_youryou_total < 4 && sekisairitsu > 2){ + log.error("Too many PV_modules or too few pcs capacity"); + return null; + } +// boolean pcs_daidenryu = false; //new +// //大電流モジュール対応可否判定 +// if(module_amp > 12.5 && pcs_daidenryu){ +// log.error("This PV module is a high current model and cannot be combined with this PCS") +// return null; +// } + + // 피크 컷 및 발전량 배열 선언 + //double[] hatsudenryou_all = new double[13]; // 피크 컷 없음 발전량(적설 고려 없음) + // double[] hatsudenryou_all_snow = new double[13]; // 피크 컷 없음 발전량(적설 고려 있음) + double[] hatsudenryou_peakcut_all = new double[13]; // 피크 컷 있음 발전량(적설 고려 없음) + double[] hatsudenryou_peakcut_all_snow = new double[13]; // 피크 컷 있음 발전량(적설 고려 있음) + +// 설치면 피크 컷 및 발전량 배열 선언 + double[][] hatsudenryou_peakcutShow = new double[roofLength][12]; + double[][] hatsudenryou_peakcut = new double[roofLength][12]; // 전체 설치면의 피크 컷 있음 발전량 + double[] peakcutParam = new double[3]; + Arrays.fill(peakcutParam, 1.0); + + int simulationPointCode = pwrGnrSimReq.getSimulationPointCode(); + int m = 0; + + for (int i = 0; i < roofLength; i++) { + double angle = pwrGnrSimReq.getKoubai()[i]; + double direction = pwrGnrSimReq.getHoui()[i]; + + // 설치면 발전량 계산 + if (!Double.isNaN(angle) && angle > 0 && angle <= (Math.PI / 2) ) { + if(!Double.isNaN(direction) && direction >= (-Math.PI) && direction <= (Math.PI)){ + // 설치면의 사면 일사량 계산 + double[] shamen_nissha = this.shamenNissharyou2(angle, direction, simulationPointCode); + double[] peakcut_param = this.peakcut2(simulationPointCode,angle,direction,sekisairitsu,module_amp, pcs_amp1, pcs_henkankouritsu); + Map northReductionParam = this.mathNorthReduction(angle, direction); + double northReduction; + if (northReductionParam.get("direction") == 1.0) { + northReduction = 1.0; + } else { + northReduction = northReductionParam.get("direction") * northReductionParam.get("angle"); + } + + hatsudenryou_peakcut[m] = new double[12]; + hatsudenryou_peakcutShow[m] = new double[12]; + + for(int k = 0 ; k < 12 ; k++){ + +// Calculate the power generation for the current month + double monthlyPower = shamen_nissha[k] * days[k] * ondo_sonshitsu[k] * pcs_henkankouritsu * + ((module1_watt_flash * pwrGnrSimReq.getModuleInput1()[i]) * (module1_north_reduction ? northReduction : 1.0) + + (module2_watt_flash * pwrGnrSimReq.getModuleInput2()[i]) * (module2_north_reduction ? northReduction : 1.0) + + (module3_watt_flash * pwrGnrSimReq.getModuleInput3()[i]) * (module3_north_reduction ? northReduction : 1.0)) / 1000.0 * + module_system_loss * peakcut_param[2]; + +// Store the result in the arrays + + hatsudenryou_peakcut[m][k] = monthlyPower; // Monthly power without snow + hatsudenryou_peakcutShow[m][k] = monthlyPower * (1.0 - snow.get(k)); // Monthly power with snow + hatsudenryou_peakcut_all[k] += hatsudenryou_peakcut[m][k]; + hatsudenryou_peakcut_all_snow[k] += hatsudenryou_peakcutShow[m][k]; + + // 계산 후 반올림 처리 + hatsudenryou_peakcut_all[k] = (int) Math.round(hatsudenryou_peakcut_all[k]); + hatsudenryou_peakcut_all_snow[k] =(int) Math.round(hatsudenryou_peakcut_all_snow[k]); + + } + m++; + } + } + } + // 마지막에 총합계 추가 + hatsudenryou_peakcut_all[12] = Arrays.stream(hatsudenryou_peakcut_all).sum(); + hatsudenryou_peakcut_all_snow[12] = Arrays.stream(hatsudenryou_peakcut_all_snow).sum(); + + PwrGnrSimResponse pwrGnrSimRes = new PwrGnrSimResponse(); + pwrGnrSimRes.setHatsudenryouPeakcutAll(formatAndPrintArray(hatsudenryou_peakcut_all)); + pwrGnrSimRes.setHatsudenryouPeakcutAllSnow(formatAndPrintArray(hatsudenryou_peakcut_all_snow)); + return pwrGnrSimRes; +} + + + + private Map mathNorthReduction(double angle, double direction) { + + // 각도 감소값 배열 [angle, reduction] 쌍 + double[][] northReductionAngle = { + {0, 1.0}, {1, 0.9994}, {2, 0.9988}, {3, 0.9982}, {4, 0.9976}, {5, 0.997}, + {6, 0.9964}, {7, 0.9958}, {8, 0.9952}, {9, 0.9946}, {10, 0.994}, {11, 0.9934}, + {12, 0.9928}, {13, 0.9922}, {14, 0.9916}, {15, 0.991}, {16, 0.9904}, {17, 0.9898}, + {18, 0.9892}, {19, 0.9886}, {20, 0.988}, {21, 0.9874}, {22, 0.9868}, {23, 0.9862}, + {24, 0.9856}, {25, 0.985}, {26, 0.9844}, {27, 0.9838}, {28, 0.9832}, {29, 0.9826}, + {30, 0.982}, {31, 0.9814}, {32, 0.9808}, {33, 0.9802}, {34, 0.9796}, {35, 0.979}, + {36, 0.9784}, {37, 0.9778}, {38, 0.9772}, {39, 0.9766}, {40, 0.976}, {41, 0.9754}, + {42, 0.9748}, {43, 0.9742}, {44, 0.9736}, {45, 0.973} + }; + // 방향 감소값 배열 [direction, reduction] 쌍 + double[][] northReductionDirection = { + {135, 0.99}, {136, 0.989511407046165}, {137, 0.989023409367582}, {138, 0.988536601514253}, + {139, 0.988051576586559}, {140, 0.987568925512663}, {141, 0.987089236328551}, {142, 0.986613093461605}, + {143, 0.986141077018562}, {144, 0.985673762078751}, {145, 0.985211717993441}, {146, 0.984755507692177}, + {147, 0.984305686996939}, {148, 0.983862803944953}, {149, 0.983427398120998}, {150, 0.983}, + {151, 0.982581130300735}, {152, 0.98217129935141}, {153, 0.981771006467905}, {154, 0.981380739345441}, + {155, 0.981000973464388}, {156, 0.980632171510976}, {157, 0.980274782813574}, {158, 0.979929242795259}, + {159, 0.979595972443316}, {160, 0.979275377796334}, {161, 0.978967849449506}, {162, 0.978673762078751}, + {163, 0.978393473984229}, {164, 0.97812732665381}, {165, 0.977875644347018}, {166, 0.977638733699975}, + {167, 0.977416883351812}, {168, 0.977210363593004}, {169, 0.977019426036065}, {170, 0.976844303308997}, + {171, 0.976685208771868}, {172, 0.976542336256863}, {173, 0.976415859832136}, {174, 0.976305933589727}, + {175, 0.976212691457829}, {176, 0.976136247037618}, {177, 0.976076693464844}, {178, 0.976034103296362}, + {179, 0.976008528421733}, {180, 0.976} + }; + + // 각도 계산 (라디안 → 도) + double angleDeg = Math.toDegrees(angle); + angleDeg = Math.abs(angleDeg); + angleDeg = Math.ceil(angleDeg); + +// 방향 계산 (라디안 → 도) + double directionDeg = Math.toDegrees(direction); + directionDeg = Math.abs(directionDeg); + directionDeg = Math.round(directionDeg); + + // 각도 감소값 찾기 + double angleReduction = 1.0; + for (double[] entry : northReductionAngle) { + if (angleDeg == entry[0]) { + angleReduction = entry[1]; + break; + } + } + + // 방향 감소값 찾기 + double directionReduction = 1.0; + for (double[] entry : northReductionDirection) { + if (directionDeg == entry[0]) { + directionReduction = entry[1]; + break; + } + } + Map result = new HashMap<>(); + result.put("angle", angleReduction); + result.put("direction", directionReduction); + return result; + } + + private T loadJsonArray(String path, TypeReference typeReference) throws IOException { + ClassPathResource resource = new ClassPathResource(path); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), typeReference); + } + + + /** * 실제 계산로직 * * @param pwrGnrSimReq @@ -622,7 +921,487 @@ public class PwrGnrSimService { return peakcutResult; } - /** 0도 방위 전력 피크 컷을 계산하는 방법 */ + public double[] peakcut2( int simulationPointCode,double koubai, double houi,double sekisairitsu, double moduleAmp1, double pcsAmp1, double pcsHenkankouritsu) throws IOException { + List> peakcut_by_pcs_data = loadJsonArray("template/pwrGnrSimulation/peakcut_db/peakcut_by_pcs_data.json", new TypeReference>>() {} ); + + // koubai[rad]을 [도]로 변환 _아래 계산식도 변경된 값으로 계산됨. + koubai = (koubai / (2 * Math.PI)) * 360; + + // 방위각 0도 설치각에서의 전력 피크 컷 + double watt_peakcut_about_deg0 = tashounenDataDeg0(simulationPointCode, sekisairitsu, koubai); + double watt_peakcut_about_deg90 = tashounenDataDeg90(simulationPointCode, sekisairitsu, koubai); + + double matrix_multiply1 = (1 * watt_peakcut_about_deg0)+(-1 * watt_peakcut_about_deg90); + double matrix_multiply2 = (-1 * watt_peakcut_about_deg0)+(2 * watt_peakcut_about_deg90); + + // houi[rad]을 [도]로 변환 + houi = (houi / (2 * Math.PI)) * 360; + + //電力ピークカット + double watt_peakcut_result = ((matrix_multiply1 * (Math.cos(houi * Math.PI/180) + 1) + matrix_multiply2) < 0.1) ? + 0.1:(matrix_multiply1 * (Math.cos(houi * Math.PI / 180) + 1) + matrix_multiply2); + + //////////// + // pcs1과 모듈 1의 전류차 구하기 용도 + boolean pcsAmpFound = true; // pcs_ampr 값은 항상있을거라 true + + // pcs1과 모듈 1의 전류차(pcs의 입력 전류 데이터가 없는 경우는 0) + double amp_peakcut_result = 1; // 디폴트 : pcs1이 없거나 pcs1과모듈1dml wjsfbckrk 0 보다 작은경우 + if (pcsAmpFound) { + + // pcs1과 모듈 1의 전류차(pcs의 입력 전류 데이터가 없는 경우는 0) + double amp_delta = moduleAmp1 - pcsAmp1; + if (amp_delta >= 0) { + + double amp_peakcut_about_deg0 = ampPeakcutDataDeg0(simulationPointCode, koubai, amp_delta); + + double amp_peakcut_about_deg90 = ampPeakcutDataDeg90(simulationPointCode, koubai, amp_delta); + + matrix_multiply1 = (1 * amp_peakcut_about_deg0) + (-1 * amp_peakcut_about_deg90); + matrix_multiply2 = (-1 * amp_peakcut_about_deg0) + (2 * amp_peakcut_about_deg90); + //電流ピークカット + amp_peakcut_result = 1-(((matrix_multiply1 * (Math.cos(houi * Math.PI / 180) + 1) + matrix_multiply2) < 0.001) ? + 0:(matrix_multiply1 * (Math.cos(houi*Math.PI/180) + 1) + matrix_multiply2)); + } + } + + // 전력 피크 컷과 전류 피크 컷의 최소값 계산 + if (sekisairitsu >= 1.25) { + sekisairitsu *= 100; + int sekisairitsu_ceil = (int) Math.ceil(sekisairitsu / 5.0) * 5; + double pcs_henkankouritsu = (pcsHenkankouritsu * 1000 <= 985) ? Math.ceil(pcsHenkankouritsu * 1000 / 5) * 5 : 985; + + int a = 1, b = 1; + + for(int i = 1 ; i < 37 ; i++){ + a++;//pcs効率によるピークカットデータベースから積載率の一致する行番号取得 + if(sekisairitsu_ceil == peakcut_by_pcs_data.get(i).get(0)){ + break; + }; + }; + + for(int j = 1 ; j < 15 ; j++){ + b++;//pcs効率によるピークカットデータベースから積載率の一致する列番号取得 + if(pcs_henkankouritsu == peakcut_by_pcs_data.get(0).get(j)){ + break; + }; + }; + + double peakcut_by_pcs = peakcut_by_pcs_data.get(a).get(b); //ピークカット率を代入 + double peakcut_by_pcs_kijun = peakcut_by_pcs_data.get(a).get(10); //基準ピークカット率(変換効率0.965)を代入 + double peakcut_by_pcs_result = peakcut_by_pcs_kijun - peakcut_by_pcs; //ピークカット率と基準ピークカット率の差分を代入 + + + if(((100 - watt_peakcut_result + peakcut_by_pcs_result) /100) < 1){ + + watt_peakcut_result = ((100 - watt_peakcut_result+peakcut_by_pcs_result)/100); + + }else{ + watt_peakcut_result = 1; + } + + } else { + watt_peakcut_result = 1.0; + } + + // 피크컷이 없는 경우, 발전량에 곱하는 피크컷 계수 + double[] peakcut_result = new double[3]; + peakcut_result[0] = amp_peakcut_result; //ピークカットなしの場合、発電量に乗算するピークカット係数 + peakcut_result[1] = watt_peakcut_result; //ピークカットなしの場合、発電量に乗算するピークカット係数 + peakcut_result[2] = Math.min(watt_peakcut_result,amp_peakcut_result); //ピークカットありの場合、発電量に乗算するピークカット係数 + + log.debug("peakcutResult ::: {}", peakcut_result); + return peakcut_result; + } + + private double ampPeakcutDataDeg90(int simulationPointCode, double koubai, double amp_delta) throws IOException { + + List amp_peakcut_data_deg90 = loadJsonArray("template/pwrGnrSimulation/peakcut_db/amp_peakcut_data_deg90/" + simulationPointCode + ".json", new TypeReference>() {} ); + + // 초기 설정 + double[] x = {5, 15, 20, 30, 40, 50}; + double[] z2 = new double[6]; + double[] y = new double[6]; + + // 데이터 초기화 - y 값 계산 (amp_delta의 다항식 계산) + for (int i = 0; i < 6; i++) { + int idx = i * 5; + y[i] = amp_peakcut_data_deg90.get(idx) * Math.pow(amp_delta, 4) + + amp_peakcut_data_deg90.get(idx + 1) * Math.pow(amp_delta, 3) + + amp_peakcut_data_deg90.get(idx + 2) * Math.pow(amp_delta, 2) + + amp_peakcut_data_deg90.get(idx + 3) * amp_delta + + amp_peakcut_data_deg90.get(idx + 4); + } + + // 최소 제곱법을 위한 행렬 A와 w 초기화 + double[][] w = new double[6][7]; + double[][] A = new double[6][6]; + + // A 행렬 설정 (x 값을 사용하여 다항식 계수 생성) + for (int i1 = 0; i1 < 6; i1++) { + A[i1][4] = x[i1]; + A[i1][5] = 1.0; + double x1 = A[i1][4]; + double x2 = x1; + for (int i2 = 3; i2 >= 0; i2--) { + x2 *= x1; + A[i1][i2] = x2; + } + } + + // w 행렬 초기화 + for (int i1 = 0; i1 < 6; i1++) { + for (int i2 = 0; i2 < 6; i2++) { + w[i1][i2] = 0.0; + for (int i3 = 0; i3 < 6; i3++) { + w[i1][i2] += A[i3][i1] * A[i3][i2]; + } + } + } + + // w의 마지막 열 값 설정 + for (int i1 = 0; i1 < 6; i1++) { + w[i1][6] = 0.0; + for (int i2 = 0; i2 < 6; i2++) { + w[i1][6] += A[i2][i1] * y[i2]; + } + } + + // 가우스 소거법을 통해 연립방정식 해 구하기 + for (int i1 = 0; i1 < 6; i1++) { + double y1 = 0.0; + int m1 = i1 + 1; + int m2 = 0; + + for (int i2 = i1; i2 < 6; i2++) { + double y2 = Math.abs(w[i2][i1]); + if (y1 < y2) { + y1 = y2; + m2 = i2; + } + } + + for (int i2 = i1; i2 < 7; i2++) { + y1 = w[i1][i2]; + w[i1][i2] = w[m2][i2]; + w[m2][i2] = y1; + } + + y1 = 1.0 / w[i1][i1]; + for (int i2 = m1; i2 < 7; i2++) { + w[i1][i2] *= y1; + } + + for (int i2 = 0; i2 < 6; i2++) { + if (i2 != i1) { + for (int i3 = m1; i3 < 7; i3++) { + w[i2][i3] -= w[i2][i1] * w[i1][i3]; + } + } + } + } + + // z2에 계수 저장 + for (int i1 = 0; i1 < 6; i1++) { + z2[i1] = w[i1][6]; + } + + return z2[0] * Math.pow(koubai, 5) + + z2[1] * Math.pow(koubai, 4) + + z2[2] * Math.pow(koubai, 3) + + z2[3] * Math.pow(koubai, 2) + + z2[4] * koubai + + z2[5]; + } + + private double ampPeakcutDataDeg0(int simulationPointCode, double koubai, double amp_delta) throws IOException { + + List amp_peakcut_data_deg0 = loadJsonArray("template/pwrGnrSimulation/peakcut_db/amp_peakcut_data_deg0/" + simulationPointCode + ".json", new TypeReference>() {} ); + + + double[] x = {5, 15, 20, 30, 40, 50}; + double[] z2 = new double[6]; + + double[] y = new double[6]; + for (int i = 0; i < 6; i++) { + int idx = i * 5; + y[i] = amp_peakcut_data_deg0.get(idx) * Math.pow(amp_delta, 4) + + amp_peakcut_data_deg0.get(idx + 1) * Math.pow(amp_delta, 3) + + amp_peakcut_data_deg0.get(idx + 2) * Math.pow(amp_delta, 2) + + amp_peakcut_data_deg0.get(idx + 3) * amp_delta + + amp_peakcut_data_deg0.get(idx + 4); + } + + double[][] w = new double[6][7]; + double[][] A = new double[6][6]; + + for (int i1 = 0; i1 < 6; i1++) { + A[i1][4] = x[i1]; + A[i1][5] = 1.0; + double x1 = A[i1][4]; + double x2 = x1; + for (int i2 = 3; i2 >= 0; i2--) { + x2 *= x1; + A[i1][i2] = x2; + } + } + + for (int i1 = 0; i1 < 6; i1++) { + for (int i2 = 0; i2 < 6; i2++) { + w[i1][i2] = 0.0; + for (int i3 = 0; i3 < 6; i3++) { + w[i1][i2] += A[i3][i1] * A[i3][i2]; + } + } + } + + for (int i1 = 0; i1 < 6; i1++) { + w[i1][6] = 0.0; + for (int i2 = 0; i2 < 6; i2++) { + w[i1][6] += A[i2][i1] * y[i2]; + } + } + + for (int i1 = 0; i1 < 6; i1++) { + double y1 = 0.0; + int m1 = i1 + 1; + int m2 = 0; + for (int i2 = i1; i2 < 6; i2++) { + double y2 = Math.abs(w[i2][i1]); + if (y1 < y2) { + y1 = y2; + m2 = i2; + } + } + + for (int i2 = i1; i2 < 7; i2++) { + y1 = w[i1][i2]; + w[i1][i2] = w[m2][i2]; + w[m2][i2] = y1; + } + + y1 = 1.0 / w[i1][i1]; + for (int i2 = m1; i2 < 7; i2++) { + w[i1][i2] *= y1; + } + + for (int i2 = 0; i2 < 6; i2++) { + if (i2 != i1) { + for (int i3 = m1; i3 < 7; i3++) { + w[i2][i3] -= w[i2][i1] * w[i1][i3]; + } + } + } + } + + for (int i1 = 0; i1 < 6; i1++) { + z2[i1] = w[i1][6]; + } + + return z2[0] * Math.pow(koubai, 5) + + z2[1] * Math.pow(koubai, 4) + + z2[2] * Math.pow(koubai, 3) + + z2[3] * Math.pow(koubai, 2) + + z2[4] * koubai + + z2[5]; + } + + private double tashounenDataDeg90(int simulationPointCode, double sekisairitsu, double koubai) throws IOException { + + List tashounen_data_deg90 = loadJsonArray("template/pwrGnrSimulation/peakcut_db/tashounen_data_deg90/" + simulationPointCode + ".json", new TypeReference>() {} ); + + double[] x = {1, 5, 15, 20, 30, 40}; + + // y 배열 초기화 및 값 할당 + double[] y = new double[6]; + for (int i = 0; i < 6; i++) { + int idx = i * 6; + y[i] = tashounen_data_deg90.get(idx) * Math.pow(sekisairitsu, 5) + + tashounen_data_deg90.get(idx + 1) * Math.pow(sekisairitsu, 4) + + tashounen_data_deg90.get(idx + 2) * Math.pow(sekisairitsu, 3) + + tashounen_data_deg90.get(idx + 3) * Math.pow(sekisairitsu, 2) + + tashounen_data_deg90.get(idx + 4) * sekisairitsu + + tashounen_data_deg90.get(idx + 5); + } + + // w 행렬 초기화 + double[][] w = new double[4][5]; + + // A 행렬 초기화 + double[][] A = new double[6][4]; + for (int i = 0; i < 6; i++) { + A[i][2] = x[i]; + A[i][3] = 1.0; + double x1 = A[i][2]; + double x2 = x1; + for (int j = 1; j >= 0; j--) { + x2 *= x1; + A[i][j] = x2; + } + } + + // w[i1][i2] 계산 + for (int i1 = 0; i1 < 4; i1++) { + for (int i2 = 0; i2 < 4; i2++) { + w[i1][i2] = 0.0; + for (int i3 = 0; i3 < 6; i3++) { + w[i1][i2] += A[i3][i1] * A[i3][i2]; + } + } + } + + // w[i1][4] 계산 + for (int i1 = 0; i1 < 4; i1++) { + w[i1][4] = 0.0; + for (int i2 = 0; i2 < 6; i2++) { + w[i1][4] += A[i2][i1] * y[i2]; + } + } + + // 가우스 소거법 적용 + for (int i1 = 0; i1 < 4; i1++) { + double y1 = 0.0; + int m1 = i1 + 1; + int m2 = 0; + for (int i2 = i1; i2 < 4; i2++) { + double y2 = Math.abs(w[i2][i1]); + if (y1 < y2) { + y1 = y2; + m2 = i2; + } + } + + for (int i2 = i1; i2 < 5; i2++) { + y1 = w[i1][i2]; + w[i1][i2] = w[m2][i2]; + w[m2][i2] = y1; + } + + y1 = 1.0 / w[i1][i1]; + for (int i2 = m1; i2 < 5; i2++) { + w[i1][i2] *= y1; + } + + for (int i2 = 0; i2 < 4; i2++) { + if (i2 != i1) { + for (int i3 = m1; i3 < 5; i3++) { + w[i2][i3] -= w[i2][i1] * w[i1][i3]; + } + } + } + } + + // 결과 z1 배열에 저장 + double[] z1 = new double[4]; + for (int i1 = 0; i1 < 4; i1++) { + z1[i1] = w[i1][4]; + } + + // 출력 결과 확인 + // System.out.println("Fitted coefficients:"); + // for (double coef : z1) { + // System.out.println(coef); + // } + + return (z1[0] * Math.pow(koubai, 3)) + (z1[1] * Math.pow(koubai, 2)) + (z1[2] * koubai) + z1[3]; + } + + private double tashounenDataDeg0(int simulationPointCode, double sekisairitsu, double koubai) throws IOException { + List tashounen_data_deg0 = loadJsonArray("template/pwrGnrSimulation/peakcut_db/tashounen_data_deg0/" + simulationPointCode + ".json", new TypeReference>() {} ); + // 0度近似曲線係数 + double[] x = {1, 5, 15, 20, 30, 40}; + double[] y = new double[6]; + double x1, x2, y1, y2; + int m1; + double[] z1 = new double[4]; + + // 적재율과 다조년 데이터(방위 0도)에서 y를 대입 + for (int i = 0; i < 6; i++) { + int idx = i * 6; + y[i] = tashounen_data_deg0.get(idx) * Math.pow(sekisairitsu, 5) + + tashounen_data_deg0.get(idx + 1) * Math.pow(sekisairitsu, 4) + + tashounen_data_deg0.get(idx + 2) * Math.pow(sekisairitsu, 3) + + tashounen_data_deg0.get(idx + 3) * Math.pow(sekisairitsu, 2) + + tashounen_data_deg0.get(idx + 4) * sekisairitsu + + tashounen_data_deg0.get(idx + 5); + } + + // 3차 최소 제곱법 + double[][] w = new double[4][5]; + double[][] A = new double[6][4]; + + for (int i = 0; i < 6; i++) { + A[i][2] = x[i]; + A[i][3] = 1.0; + x1 = A[i][2]; + x2 = x1; + for (int j = 1; j >= 0; j--) { + x2 *= x1; + A[i][j] = x2; + } + } + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + w[i][j] = 0.0; + for (int k = 0; k < 6; k++) { + w[i][j] += A[k][i] * A[k][j]; + } + } + } + + for (int i = 0; i < 4; i++) { + w[i][4] = 0.0; + for (int j = 0; j < 6; j++) { + w[i][4] += A[j][i] * y[j]; + } + } + + for (int i = 0; i < 4; i++) { + y1 = 0.0; + m1 = i + 1; + int m2Index = 0; + for (int j = i; j < 4; j++) { + y2 = Math.abs(w[j][i]); + if (y1 < y2) { + y1 = y2; + m2Index = j; + } + } + + for (int j = i; j < 5; j++) { + double temp = w[i][j]; + w[i][j] = w[m2Index][j]; + w[m2Index][j] = temp; + } + + y1 = 1.0 / w[i][i]; + + for (int j = m1; j < 5; j++) { + w[i][j] *= y1; + } + + for (int j = 0; j < 4; j++) { + if (j != i) { + for (int k = m1; k < 5; k++) { + w[j][k] -= w[j][i] * w[i][k]; + } + } + } + } + + // z1에 3차, 2차, 1차 계수와 절편을 대입 + for (int i = 0; i < 4; i++) { + z1[i] = w[i][4]; + } + + // 방위각 90도 설치각에서의 전력 피크 컷 + return (z1[0] * Math.pow(koubai, 3)) + (z1[1] * Math.pow(koubai, 2)) + (z1[2] * koubai) + z1[3]; +//電力ピークカット(3次) + + } + + /** 0도 방위 전력 피크 컷을 계산하는 방법 */ private double computePowerPeakCutDeg0( int simulationPointNumber, double sekisairitsu, double koubai) { // 0度近似曲線係数 @@ -1196,6 +1975,185 @@ public class PwrGnrSimService { return shamenNissha; } + public double[] shamenNissharyou2(double koubai, double houi, int simulationPointCode) throws IOException { + + + + List> cosThetaZ = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/cosθz/" + simulationPointCode + ".json", new TypeReference>>() {} ); + List> hinode_nichibotsu = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/hinode_nichibotsu/" + simulationPointCode + ".json", new TypeReference>>() {} ); + List> jikakudo = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/jikakudo/" + simulationPointCode + ".json", new TypeReference>>() {} ); + List jimenhansharitsu = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/jimenhansharitsu/" + simulationPointCode + ".json", new TypeReference>() {} ); + List latlng = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/latlng/" + simulationPointCode + ".json", new TypeReference>() {} ); + List> rd = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/rd/" + simulationPointCode + ".json", new TypeReference>>() {} ); + List> rdx = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/rdx/" + simulationPointCode + ".json", new TypeReference>>() {} ); + List> rtx = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/rtx/" + simulationPointCode + ".json", new TypeReference>>() {} ); + List sanrannissha = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/sanrannissha/" + simulationPointCode + ".json", new TypeReference>() {} ); + List suiheimennissha = loadJsonArray("template/pwrGnrSimulation/shamen_nissha_db/suiheimennissha/" + simulationPointCode + ".json", new TypeReference>() {} ); + + + double[] taiyousekii = new double[]{-0.364097062,-0.223037136,-0.03680526,0.168291101,0.327203218,0.399562561,0.371583056,0.247059216,0.059440186,-0.146278793,-0.316089477,-0.396166795}; + double[] ion = new double[]{1.426094061,1.414593394,1.396093029,1.372838185,1.351972937,1.339772275,1.337619965,1.348593875,1.368280812,1.391546004,1.412321395,1.424077899}; + + + double[] shamen_nissha = new double[12]; // 경사면 일사량 대입을 위한 빈 배열 변수 생성 + + int i = simulationPointCode * 12; // 일사량 관측 지점의 행 번호로부터 데이터베이스의 일치하는 행을 산출 + // (例:波照間は836行目→データベースでは836×12=10032行目から10044行目までが1月~12月) + + if (koubai == 0) { // 경사가 0이면 경사 일사량 = 수평면 일사 + shamen_nissha = suiheimennissha.stream() + .mapToDouble(Double::doubleValue) + .toArray(); + } else { // 기울기가 0이 아니면 경사 일사량 계산 + + // 경사면 일사량 (직접, 산란, 지면 반사)의 도출을위한 빈 배열 변수 생성 + double[][] cosTheta = new double[12][26]; + double[][] rb = new double[12][26]; + double[][] io = new double[12][26]; + double[][] I = new double[12][26]; + double[][] id = new double[12][26]; + double[][] Isby = new double[12][26]; + double[][] Ibby = new double[12][26]; + double[][] Irby = new double[12][26]; + + // 시간 + double[] time_param = { + 100, 100, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, + 15.5, 16.5, 17.5, 18.5, 19.5, 20.5, 21.5, 22.5, 23.5 + }; + + double Isby_math = 0; + double[] Isby_total = new double[12]; + + double Ibby_math = 0; + double[] Ibby_total = new double[12]; + + double Irby_math = 0; + double[] Irby_total = new double[12]; + + // 매월 각 시간의 각 파라미터 계산 + for (int m = 0; m < 12; m++) { + + for (int j = 0; j < 26; j++) { + + cosTheta[m][j] = + Math.max( + 0, + (Math.sin(latlng.get(0)) * Math.cos(koubai) + - Math.cos(latlng.get(0)) * Math.sin(koubai) * Math.cos(houi)) + * Math.sin(taiyousekii[m]) + + (Math.cos(latlng.get(0)) * Math.cos(koubai) + + Math.sin(latlng.get(0)) * Math.sin(koubai) * Math.cos(houi)) + * Math.cos(taiyousekii[m]) + * Math.cos(jikakudo.get(m).get(j)) + + Math.cos(taiyousekii[m]) + * Math.sin(koubai) + * Math.sin(houi) + * Math.sin(jikakudo.get(m).get(j))); + rb[m][j] = (cosThetaZ.get(m).get(j) == 0) ? 0 : cosTheta[m][j] / cosThetaZ.get(m).get(j); + io[m][j] = ion[m] * cosThetaZ.get(m).get(j); + I[m][j] = suiheimennissha.get(m) * rtx.get(m).get(j); + id[m][j] = Math.min(sanrannissha.get(m) * rdx.get(m).get(j), I[m][j]); + Isby[m][j] = + Math.max( + 0, + (io[m][j] == 0) + ? 0 + : id[m][j] + * (((I[m][j] - id[m][j]) / io[m][j]) * rb[m][j] + + (1 - (I[m][j] - id[m][j]) / io[m][j]) + * (1 + Math.cos(koubai)) + / 2)); + Ibby[m][j] = Math.max(0, (I[m][j] - id[m][j]) * rb[m][j]); + Irby[m][j] = I[m][j] * jimenhansharitsu.get(m) * ((1 - Math.cos(koubai)) / 2); + } + } + + // 直達、散乱の計算 Direct, scattering calculation + for (int m = 0; m < 12; m++) { + for (int j = 0; j < 26; j++) { + if (time_param[j] > (Math.ceil(hinode_nichibotsu.get(m).get(0) * 2) / 2) + && time_param[j] < (Math.floor(hinode_nichibotsu.get(m).get(1) * 2) / 2)) { + Isby_math += Isby[m][j]; + Ibby_math += Ibby[m][j]; + } + ; + } + ; + + Isby_math = + Isby_math + + (((Math.ceil(hinode_nichibotsu.get(m).get(0)) - 0.5) + < hinode_nichibotsu.get(m).get(0)) + ? 0 + : Isby[m][0]) + + (((Math.floor(hinode_nichibotsu.get(m).get(1)) + 0.5) + > hinode_nichibotsu.get(m).get(1)) + ? 0 + : Isby[m][1]); + Isby_total[m] = Isby_math; + Ibby_math = + Ibby_math + + (((Math.ceil(hinode_nichibotsu.get(m).get(0)) - 0.5) + < hinode_nichibotsu.get(m).get(0)) + ? 0 + : Ibby[m][0]) + + (((Math.floor(hinode_nichibotsu.get(m).get(1)) + 0.5) + > hinode_nichibotsu.get(m).get(1)) + ? 0 + : Ibby[m][1]); + Ibby_total[m] = Ibby_math; + Isby_math = 0; + Ibby_math = 0; + } + ; + + // 地面反射の計算 Calculating ground reflection + for (int m = 0; m < 12; m++) { + for (int j = 0; j < 26; j++) { + if (j + 2 < rd.get(m).size()) { //추가 java에러 + if ((rd.get(m).get(j + 2) //java에러 + > ((jikakudo.get(m).get(0) >= 0) + ? (Math.ceil(jikakudo.get(m).get(0) * 2) / 2) + : (Math.floor(jikakudo.get(m).get(0) * 2) / 2))) + && (rd.get(m).get(j + 2) + < ((jikakudo.get(m).get(1) >= 0) + ? (Math.floor(jikakudo.get(m).get(1) * 2) / 2) + : (Math.ceil(jikakudo.get(m).get(1) * 2) / 2)))) { + Irby_math += Irby[m][j + 2]; + } + } + ; + } + ; + Irby_math = + Irby_math + + ((((jikakudo.get(m).get(0) >= 0) + ? (Math.ceil(jikakudo.get(m).get(0)) - 0.5) + : (Math.floor(jikakudo.get(m).get(0)) - 0.5)) + < jikakudo.get(m).get(0)) + ? 0 + : Irby[m][0]) + + ((((jikakudo.get(m).get(1) >= 0) + ? (Math.floor(jikakudo.get(m).get(1)) + 0.5) + : (Math.ceil(jikakudo.get(m).get(1)) + 0.5)) + > jikakudo.get(m).get(1)) + ? 0 + : Irby[m][1]); + Irby_total[m] = Irby_math; + Irby_math = 0; + } + ; + + // 直達、散乱、地面反射を各月ごとに合計 //Total direct, scattering, and ground reflections for each month + for (int m = 0; m < 12; m++) { + shamen_nissha[m] = Isby_total[m] + Ibby_total[m] + Irby_total[m]; + } + } + log.debug("shamen_nissha ::: {}", shamen_nissha); + return shamen_nissha; + } + public double[] readValuesFromFile(String fileName) { List values = new ArrayList<>(); @@ -1625,4 +2583,5 @@ public class PwrGnrSimService { throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR); } } + } diff --git a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimPlanResponse.java b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimPlanResponse.java index 61dc1eef..c09e8a9b 100644 --- a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimPlanResponse.java +++ b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimPlanResponse.java @@ -42,4 +42,9 @@ public class PwrGnrSimPlanResponse { @Schema(description = "경칭") private String objectNameOmit; + @Schema(description = "관측지점 코드") + private int simulationCode; + + + } diff --git a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRequest.java b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRequest.java index 0776f6fb..972e5a02 100644 --- a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRequest.java +++ b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRequest.java @@ -125,4 +125,19 @@ public class PwrGnrSimRequest { @Schema(description = "PCS 3 용량") private double pcsSpecification3; + + @Schema(description = "지붕면 갯수") + private int roofLength; + + @Schema(description = "관측지점 코드") + private int simulationPointCode; + + @Schema(description = "북면 모듈 여부1") + private String northModuleYn1; + + @Schema(description = "북면 모듈 여부2") + private String northModuleYn2; + + @Schema(description = "북면 모듈 여부3") + private String northModuleYn3; } diff --git a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRoofResponse.java b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRoofResponse.java index 5fa61895..0a7183dd 100644 --- a/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRoofResponse.java +++ b/src/main/java/com/interplug/qcast/biz/pwrGnrSimulation/dto/PwrGnrSimRoofResponse.java @@ -56,4 +56,8 @@ public class PwrGnrSimRoofResponse { @Schema(description = "온도계수") private double tempCoeff; + + @Schema(description = "북면 모듈 여부") + private String northModuleYn; + } diff --git a/src/main/resources/mappers/estimate/estimateMapper.xml b/src/main/resources/mappers/estimate/estimateMapper.xml index c83fb112..1551f5bc 100644 --- a/src/main/resources/mappers/estimate/estimateMapper.xml +++ b/src/main/resources/mappers/estimate/estimateMapper.xml @@ -1056,6 +1056,7 @@ , AMOUNT , PC_ITEM_ID , QCAST_CUST_PRD_ID + , NORTH_MODULE_YN ) SELECT #{roofItemNo} AS ROOF_ITEM_NO @@ -1069,6 +1070,7 @@ , #{amount} , #{pcItemId} , #{qcastCustPrdId} + , #{northModuleYn} FROM M_ITEM I WITH (NOLOCK) WHERE I.ITEM_ID = #{itemId} @@ -1325,6 +1327,7 @@ , SPECIFICATION , AMOUNT , PC_ITEM_ID + , NORTH_MODULE_YN ) SELECT PRIE.ROOF_ITEM_NO @@ -1337,6 +1340,7 @@ , PRIE.SPECIFICATION , PRIE.AMOUNT , PRIE.PC_ITEM_ID + , PRIE.NORTH_MODULE_YN FROM T_PART_ROOF_ITEM_ESTIMATE PRIE WITH (NOLOCK) WHERE PRIE.OBJECT_NO = #{objectNo} AND PRIE.PLAN_NO = #{planNo} diff --git a/src/main/resources/mappers/pwrGnrSimulation/pwrGnrSimMapper.xml b/src/main/resources/mappers/pwrGnrSimulation/pwrGnrSimMapper.xml index e12fed3b..579a2df2 100644 --- a/src/main/resources/mappers/pwrGnrSimulation/pwrGnrSimMapper.xml +++ b/src/main/resources/mappers/pwrGnrSimulation/pwrGnrSimMapper.xml @@ -19,6 +19,7 @@ , (SELECT AREA_NAME FROM T_SIMULATION_AREA WHERE AREA_ID = B1.AREA_ID ) AS AREA_NAME , B.OBJECT_NAME /* 물건명 */ , B.OBJECT_NAME_OMIT /* 물건명(영문) */ + , (SELECT SIMULATION_CODE FROM T_SIMULATION_AREA WHERE AREA_ID = B1.AREA_ID) AS SIMULATION_CODE FROM T_PLAN A WITH (NOLOCK) INNER JOIN T_PLAN_INFO A1 WITH (NOLOCK) ON A.OBJECT_NO = A1.OBJECT_NO @@ -98,6 +99,7 @@ , A.ROOF_SURFACE AS ROOF_SURFACE , A.CLASS_TYPE AS CLASS_TYPE , A.AZIMUTH AS AZIMUTH + , ISNULL(B.NORTH_MODULE_YN, 'N') AS NORTH_MODULE_YN , (CASE WHEN A.CLASS_TYPE = 0 THEN A.SLOPE ELSE A.ANGLE END) AS SLOPE_ANGLE @@ -116,7 +118,7 @@ WHERE A.OBJECT_NO = #{objectNo} AND A.PLAN_NO = #{planNo} AND C.ITEM_GROUP = #{itemGroup} - GROUP BY A.ROOF_SURFACE_ID, A.ROOF_SURFACE, A.CLASS_TYPE, A.AZIMUTH, A.ANGLE, A.SLOPE, B.ITEM_ID, B.ITEM_NO + GROUP BY A.ROOF_SURFACE_ID, A.ROOF_SURFACE, A.CLASS_TYPE, A.AZIMUTH, A.ANGLE, A.SLOPE, B.ITEM_ID, B.ITEM_NO, B.NORTH_MODULE_YN ) T ORDER BY T.ROOF_SURFACE_ID ASC, T.ITEM_ID ASC