package com.ordobill.webapp.common;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.ordobill.webapp.beans.AvailableFields;
import com.ordobill.webapp.beans.Figures;
import com.ordobill.webapp.beans.Modeling;
import com.ordobill.webapp.beans.Project;
import com.ordobill.webapp.beans.SimulationFields;
import com.ordobill.webapp.engine.SimulationEngine;
/**
* SimulationEngine클래스를 구현하고 Engine을 완성합니다.
*
* @author Choi Jin Wook(A.K.A Brian Choi @ Ordobill Office) / choijinwook84@gmail.com
*
*/
public class SimulationEngineImpl extends SimulationEngine{
private Log log = LogFactory.getFactory().getInstance(this.getClass().getName());
/**
* SimualtionEngineImpl 의 생성자를 정의합니다.
* Project 객체를 받아 SimulationEngine의 기본 변수들을
* 초기화 합니다.
* @param project
*/
public SimulationEngineImpl(Project project){
super(project);
}
/**
* SimulationEngineImpl의 기본생성자입니다.
*/
public SimulationEngineImpl(){}
/**
* {@inheritDoc}
* @deprecated for packing Figures per Equipment and probably doing Thread programing replaced by {@link #simulationBody(Vector)}
*/
@Override
@Deprecated public SimulationFields[] simulationBody(ArrayList<Figures> figList) throws Exception{
/**
* Initialization return object Arrays
*/
SimulationFields[] simFieldsArr = new SimulationFields[getSimTime()];
/**
* View for simulation start time (Only View on command line)
*/
long start = System.currentTimeMillis();
/**
* 각 수치값에서 나오는 결과를 저장하는 String Array 입니다.
*/
String[] equipInform = new String[figList.size()];
/**
* Running Simulation Times
*/
for(int strtSim = 0; strtSim < getSimTime(); strtSim++){
/**
* Initialize Simulation Fields Object
*/
SimulationFields simFields = new SimulationFields();
/**
* Initialize present
*/
float present = getStrTime();
/**
* Initialize repair time
*/
float repairTime = 0f;
ArrayList<Float> presentList = new ArrayList<Float>();
/**
* Testing gear in Life Times
*/
//Start while syntax
while(present < getLifeTime()){
/**
* Setting Present to parent instance
*/
super.setPresent(present);
/**
* Initialize MTTR ArrayList<Float>
*/
ArrayList<Float> mttr = new ArrayList<Float>(figList.size());
/**
* Initialize System State
*/
int systemState = 1;
/**
* Initialize figIndex
*/
int figIndx = 0;
//Start For syntax
for(Figures fig : figList){
float MTTR = 0f;
float hazardRate = selectFailType(fig);
float ran = (float)Math.random();
equipInform[figIndx] = fig.getFigUid()+","+hazardRate+","+ran;
/**
* 장비가 해당하는 FM모드에서 고장났는지를
* 분별하는 구문입니다. Monte Carlo 공식이 적용되는 부분입니다.
* Hazard Rate가 난수보다 작으면 정상이고, 난수보다 크면 장비는 고장나게 됩니다.
*/
if(ran > hazardRate){
systemState = 1;
MTTR = 0f;
}else{
systemState = 0;
// if(fig.getFigConnect() == 1){
/**
* 수리시간을 얻어 옵니다.
*/
MTTR = fig.getFigMttr().floatValue();
/**
* 고장 시점을 Fail Mode에 기록합니다.
*/
fig.setFigBreakPoint(present+(MTTR/8760f));
/**
* 고장 시점에 작용될 Reduction Factor를 기록합니다.
*/
fig.setFigRecovFactor(fig.getFigImpRecov());
// }else{
MTTR = 0f;
// }
}
mttr.add(MTTR);
systemState *= systemState;
figIndx++;
//End of For syntax
}
/**
* Max MTTR divided by 8760(Hour multiplied by 365(A year)
*/
float maxMTTR = (Collections.max(mttr)/8760f);
//Initialize ArrayList Object for memory
mttr = null;
repairTime += maxMTTR;
//if systems is available then
if(systemState == 1){
present += (1f/getTimeDiv());
//or else
}else{
present += maxMTTR;
}
//End of While syntax
}
/**
* 부모 클래스에 각 장비의 FM마다 생성되는
* Hazard Rate와 난수를 저장합니다.
*/
super.returnHazardRandom(equipInform);
presentList.add(present);
float availability = (1f-(repairTime/present))*100;
Float[] timeSim = new Float[presentList.size()];
//Converting ArrayList with Arrays
presentList.toArray(timeSim);
//Initialize ArrayList Object for memory
presentList = null;
simFields.setIterationStep(strtSim);
simFields.setRepairTime(repairTime);
simFields.setAvailabilityValue(availability);
simFields.setTimeOfSimulation(timeSim);
simFieldsArr[strtSim] = simFields;
//Initialize Object for memory
simFields = null;
for(Figures fig : figList){
fig.setFigBreakPoint(0f);
fig.setFigRecovFactorIniti();
}
//End of for syntax
}
long end = System.currentTimeMillis();
log.debug( "실행 시간 : " + ( end - start )/1000.0 + "초" );
//System.out.println( "실행 시간 : " + ( end - start )/1000.0 + "초" );
return simFieldsArr;
}
/**
* {@inheritDoc}
*/
@Override
public SimulationFields[] simulationBody(Vector<Modeling> modelingVector) throws Exception{
//Initialization return object Arrays
SimulationFields[] simFieldsArr = new SimulationFields[getSimTime()];
// View for simulation start time (Only View on command line)
long start = System.currentTimeMillis();
int figuresCount = 0;
for(Modeling mod : modelingVector){
for(Figures fig : mod.getFiguresVector()){
figuresCount++;
}
}
//각 수치값에서 나오는 결과를 저장하는 String Array 입니다.
String[] equipInform = new String[figuresCount];
//
ArrayList<BigDecimal> availableAverageList = new ArrayList<BigDecimal>();
//Running Simulation Times
for(int strtSim = 0; strtSim < getSimTime(); strtSim++){
//Initialize Simulation Fields Object
SimulationFields simFields = new SimulationFields();
//Initialize present
float present = getStrTime();
//Initialize repair time
float repairTime = 0f;
//Initialize present list
ArrayList<Float> presentList = new ArrayList<Float>();
//Initialize available per equipment list
ArrayList<AvailableFields> availableEquipmentList = new ArrayList<AvailableFields>();
//Start while syntax
while(present < getLifeTime()){
//Setting Present to parent instance
super.setPresent(present);
//Initialize MTTR ArrayList<Float>
ArrayList<Float> mttr = new ArrayList<Float>();
//Initialize System State
int systemState = 1;
//Initialize figIndex
int figIndx = 0;
//Initialize Equipment for Available per a 1/timeDiv
BigDecimal equipmentAvailable = new BigDecimal(1f);
//Start equipment's for syntax
for(Modeling mod : modelingVector){
//Start calculator for modeling type 'eq'
if(mod.getMoType().equals("eq")){
//get modeling's figures
Vector<Figures> figVector = mod.getFiguresVector();
//Initialize Figures for Available per a 1/timeDiv
BigDecimal figuresAvailable = new BigDecimal(0);
//Start For syntax
for(Figures fig : figVector){
//Check it figure's state. true : normality, false : failure
if(fig.isFigStates()){
//Mean Time To Repair
float MTTR = 0f;
//Getting Harzard Rate
float hazardRate = selectFailType(fig);
//Setting Random Number
float ran = (float)Math.random();
//Collecting for Simulation Display
equipInform[figIndx] = fig.getFigUid()+","+hazardRate+","+ran;
/*
* 장비가 해당하는 FM모드에서 고장났는지를
* 분별하는 구문입니다. Monte Carlo 공식이 적용되는 부분입니다.
* Hazard Rate가 난수보다 작으면 정상이고, 난수보다 크면 장비는 고장나게 됩니다.
*/
if(ran > hazardRate){
figuresAvailable = new BigDecimal(1f);
systemState = 1;
MTTR = 0f;
//End of if syntax
}else{
//To Set system state when break down
systemState = 0;
//if modeling's pu connecting one
if(mod.getMoPuConnect() == 1){
//To Set Figure's state
fig.setFigStates(false);
//입력되어있는 1년 평균 수리시간을 년단위 비율로 환산합니다.
MTTR = (fig.getFigMttr().floatValue()/8760f);
//수리가 끝나는 시점을 구합니다.
float finishedTime = present + MTTR;
/*
* 복구되는 시점이 1/TimeDivision 보다 클경우
* 나머지를 구합니다.
*/
float pieceTime = finishedTime%(1f/getTimeDiv());
//Check next finish time over the life time
if(finishedTime < getLifeTime()){
//수리가 끝나는 시점을 저장합니다.
fig.setFigFinishRepairTime(new BigDecimal(finishedTime));
/*
* (1/timeDiv)만큼 시간이 갈 때, 남게 되는 시간을 저장합니다.
* 예를 들어 (1/timeDiv)가 0.002739 일 때, 수리 시점이 0.019178 이라고 가정하면
* (1/timeDiv)가 7번 후에는 수리가 완료 된다. 하지만 수리시점이 0.020131 라고 하면
* (1/timeDiv)가 7.35 후에야 수리가 완료 된다. 여기에서 0.35만큼은 따로 계산 해야 함으로
* 나머지 값을 저장하여 계산을 돕습니다.
*/
fig.setFigPieceRepairTime(new BigDecimal(pieceTime));
//배달 시점을 저장합니다.
fig.setFigFinishDeliveryTime(new BigDecimal(present+(fig.getFigDelivery().floatValue()/getTimeDiv())));
}
//고장 시점을 Fail Mode에 기록합니다.
fig.setFigBreakPoint(present);
//고장 시점에 작용될 Reduction Factor를 기록합니다.
fig.setFigRecovFactor(fig.getFigImpRecov());
//고장난 시점에도 가용성을 측정하여야 함으로 아래 코드를 추가하였습니다.
//고장난 현재 시점을 부품조달 시간과 비교합니다.
// if(present < fig.getFigFinishDeliveryTime().floatValue()){
//
// //부품조달 중에는 1-MTTF impact(참고자료 1-2 2번 케이스)를 합니다.
// figuresAvailable = new BigDecimal(1f-fig.getFigImpFailure().floatValue());
//
// //고장난 현재 시점이 부품조달 시간보다 크거나 같다면 즉 배달시간이 없거나 배달을 했다면
// }else if(present >= fig.getFigFinishDeliveryTime().floatValue()){
//
// //부품조달이 없거나 부품 조달이 끝났을 때에는 1-MTTR impact(참고자료 1-2 3번 케이스)를 합니다.
// figuresAvailable = new BigDecimal(1f-fig.getFigImpRepair().floatValue());
// //부품조달 시점을 초기화 합니다.
// fig.setFigFinishDeliveryTime(new BigDecimal(0f));
//
// }
//End of else syntax at Connect
}else{
MTTR = 0f;
}
//End of else syntax at compare random number with hazard rate
}
mttr.add(MTTR);
// End if syntax at isFigStates
}else{
//현재시점이 수리가 끝나는 시점보다 작다면(아직 수리중이라면)
if(present < fig.getFigFinishRepairTime().floatValue()){
//고장난 현재 시점을 부품조달 시간과 비교합니다.
if(present < fig.getFigFinishDeliveryTime().floatValue()){
//부품조달 중에는 1-MTTF impact(참고자료 1-2 2번 케이스)를 합니다.
figuresAvailable = new BigDecimal(1f-fig.getFigImpFailure().floatValue());
//고장난 현재 시점이 부품조달 시간보다 크거나 같다면 즉 배달시간이 없거나 배달을 했다면
}else if(present >= fig.getFigFinishDeliveryTime().floatValue()){
//부품조달이 없거나 부품 조달이 끝났을 때에는 1-MTTR impact(참고자료 1-2 3번 케이스)를 합니다.
figuresAvailable = new BigDecimal(1f-fig.getFigImpRepair().floatValue());
//부품조달 시점을 초기화 합니다.
fig.setFigFinishDeliveryTime(new BigDecimal(0f));
}
//현재시점이 수리가 끝나는 시점보다 크다면(즉 수리가 끝났다면)
}else if(present >= fig.getFigFinishRepairTime().floatValue()){
//수리종료 시점을 초기화 합니다.
fig.setFigFinishRepairTime(new BigDecimal(0));
//부품조달 시점을 초기화 합니다.
fig.setFigFinishDeliveryTime(new BigDecimal(0));
//Fail Mode의 상태를 정상으로 변환합니다.
fig.setFigStates(true);
/*
* 고장 시점에 저장한 자투리 시간이 존재한다면
* 자투리 시간을 1루의 생산량에 미치는 영향 대한 계산을 합니다.
*/
if(fig.getFigPieceRepairTime().floatValue() > 0f){
/*
* 자투리 시간이 Time Division 차지하는 백분율을 계산하고(자투리시간/Time Division)
* 정상적인 Time Division 의 백분율을 계산하여(1/Time Division)
* 이 두 값의 비율(자투리 비율/정상의 비율)을 다시 구한 다음 1에서 뺴면 자투리 시간에 대한 가용율이 나옵니다.
*/
figuresAvailable = new BigDecimal((1f-(fig.getFigPieceRepairTime().floatValue()/getTimeDiv())/(1/getTimeDiv())));
//자투리 시간을 초기화 합니다.
fig.setFigPieceRepairTime(new BigDecimal(0));
//자투리 시간이 존재하지 않는다면
}else if(fig.getFigPieceRepairTime().floatValue() <= 0f){
//자투리 시간이 없거나, 작다면 bd를 초기화 합니다.
figuresAvailable = new BigDecimal(1f);
//자투리 시간을 초기화 합니다.
fig.setFigPieceRepairTime(new BigDecimal(0));
//End of if syntax at pieceRepairTime
}
//End of if syntax at capre psresent with finishRepairTime
}
// End else syntax at isFigStates
}
systemState *= systemState;
figIndx++;
equipmentAvailable = equipmentAvailable.multiply(figuresAvailable);
//End of For syntax at Figures
}
/*
* 장비당 가용율을 저장하는 부분입니다.
*
* 만약에 Reporting을 위해서 구해야 할 것이 있다면
* 이부분에서나 이 부분 이전에 Code에서 찾아서 변경하거나 추가 하면 됩니다.
*/
availableEquipmentList.add(new AvailableFields(mod.getMoTagId(), equipmentAvailable, new BigDecimal(1f-equipmentAvailable.floatValue())));
//계산된 Figure의 데이터(breakPoint, isFigStates, finishDeliveryTime and finishRepairTiem)를 다시 입력합니다.
mod.setFiguresVector(figVector);
//End of if syntax at modeling type 'eq'
}
//End of For syntax at Equipments
}
//Initialize ArrayList Object for memory
mttr = null;
//모든 시간은 1/time division한 것 만큼 증가합니다.
present += (1f/getTimeDiv());
//End of While syntax
}
float aver = 0f;
for(AvailableFields av : availableEquipmentList){
aver = av.getAvailable().floatValue()+aver;
}
//log.debug("Available Average is "+((aver/(float)availableEquipmentList.size())*100f));
availableAverageList.add(new BigDecimal(((aver/(float)availableEquipmentList.size())*100f)));
/*
* 부모 클래스에 각 장비의 FM마다 생성되는
* Hazard Rate와 난수를 저장합니다.
* 시뮬레이션 실행 화면에서 필요한 부분입니다.
*/
super.returnHazardRandom(equipInform);
//각각의 Operating Time을 저장합니다.
presentList.add(present);
//저장된 Operating Time의 회수만큼 Float Arrays를 선언합니다.
Float[] timeSim = new Float[presentList.size()];
//Converting ArrayList with Arrays
presentList.toArray(timeSim);
//Initialize ArrayList Object for memory
presentList = null;
//시뮬레이션 횟수를 저장합니다.
simFields.setIterationStep(strtSim);
//수리시간을 저장합니다. - 가용성 로직을 변경하면서 수정이 필요하게 되었습니다.
simFields.setRepairTime(0);
//가용성을 측정하여 저장합니다.
simFields.setAvailabilityValue((aver/(float)availableEquipmentList.size())*100f);
//Operating Time의 Arrays를 저장합니다.
simFields.setTimeOfSimulation(timeSim);
//SimFields를 SimFields Arrays에 저장합니다.
simFieldsArr[strtSim] = simFields;
//Initialize Object for memory
simFields = null;
//Initiate figures break point, recover factor per Equipment
for(Modeling modeling : modelingVector){
Vector<Figures> figVector = modeling.getFiguresVector();
for(Figures fig : figVector){
fig.setFigBreakPoint(0f);
fig.setFigRecovFactorIniti();
}
modeling.setFiguresVector(figVector);
//End of for syntax at initiate
}
//End of for syntax
}
BigDecimal aveAvailable = new BigDecimal(0f);
for(BigDecimal aveList : availableAverageList){
aveAvailable = aveAvailable.add(aveList);
}
//log.debug("Ave Availability : "+(aveAvailable.floatValue()/(float)availableAverageList.size()));
//시뮬레이션이 끝나는 시점의 시간을 구합니다.
long end = System.currentTimeMillis();
//시뮬레이션 시작과 끝시점의 차이고 시뮬레이션이 몇초가 걸렸는지 표현합니다.
log.debug( "실행 시간 : " + ( end - start )/1000.0 + "초" );
//SimFields Arrays를 반환합니다.
//log.debug(simFieldsArr[0].getFigureList());
return simFieldsArr;
}
}