1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547 |
- package de.tu_darmstadt.tk.SmartHomeNetworkSim.core;
- import java.beans.PropertyChangeListener;
- import java.beans.PropertyChangeSupport;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.math.BigDecimal;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Calendar;
- import java.util.Date;
- import java.util.LinkedHashMap;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Scanner;
- import java.util.concurrent.ThreadLocalRandom;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.Controller;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.NetworkController;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.devices.SWaTDevice;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.distributionHandler.SWaTDatasetDistributionHandler;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.protocols.SWaTSimplifiedModbusProtocol;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.util.SWaTDeviceTypes;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.util.SWaTUtilities;
- /**
- * The functions of the SWaT physical data simulation.</br>
- * The simulation methods may contain a lot of copied and slightly changed code.
- * This was done on purpose to make it easier to fine-adjust the parameters.
- *
- * @author Fabian Kaiser
- */
- public class SWaTSimulationManagerPhysical {
-
- /**
- * Network controller for the simulation.
- */
- private NetworkController networkController;
-
- /**
- * The duration of the simulation in seconds.
- */
- private int durationInSeconds;
-
- /**
- * The path of the directory where the output files are saved.
- */
- private String outputDirectoryPath;
-
- /**
- * The path of the last output file;
- */
- private static String lastOutputFilePath = "";
-
- /**
- * The start time of the simulation.
- */
- private Calendar startTime;
-
- /**
- * The start time of the simulation.
- */
- private Calendar currentTime;
-
- /**
- * Offset of the start of the backup interval. Is 600 for the tests in the main method and 0 for general use.
- */
- private static int backupIntervalTestOffset = 0;
-
- /**
- * Pass-by-reference value to stop the simulation.
- */
- private boolean[] passByReferenceValue_KeepSimulationRunning;
-
- /**
- * Variable needed as Observable.
- */
- private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
-
- /**
- * The list with the output line by line.
- */
- private LinkedList<String> outputList = new LinkedList<String>();
-
- /**
- * The first line of the output with the description of the columns.
- */
- private String outputColumnDescription = "";
-
- /**
- * A HashMap with the time in seconds as key and a String array of double representations as value.</br>
- * String[]: [0] = LIT-101, [1] = AIT-201, [2] = FIT-201, [3] = LIT-301, [4] = LIT-401, [5] = 0 for normal, 1 for attack
- */
- private LinkedHashMap<Integer, String[]> resultsMap = new LinkedHashMap<Integer, String[]>();
- ///////////////////////// Lists for the status values (start)
- /**
- * The list for the timestamps.
- */
- private LinkedList<String> listTimestamp;
-
- /**
- * The list for the attack status.
- */
- private LinkedList<String> listNormalAttack;
-
- /**
- * The list for FIT-101 values.
- */
- private LinkedList<Double> listFIT101;
-
- /**
- * The list for LIT-101 values.
- */
- private LinkedList<Double> listLIT101;
- /**
- * The list for LIT-101 values without jittering.
- */
- private LinkedList<Double> listLIT101WithoutJittering;
-
- /**
- * The list for MV-101 values.
- */
- private LinkedList<Integer> listMV101;
-
- /**
- * The list for P-101 values.
- */
- private LinkedList<Integer> listP101;
-
- /**
- * The list for P-102 values.
- */
- private LinkedList<Integer> listP102;
-
- /**
- * The list for MV-201 values.
- */
- private LinkedList<Integer> listMV201;
-
- /**
- * The list for AIT-201 values.
- */
- private LinkedList<Double> listAIT201;
-
- /**
- * The list for AIT-202 values.
- */
- private LinkedList<Double> listAIT202;
-
- /**
- * The list for AIT-203 values.
- */
- private LinkedList<Double> listAIT203;
-
- /**
- * The list for FIT-201 values.
- */
- private LinkedList<Double> listFIT201;
-
- /**
- * The list for P-201 values.
- */
- private LinkedList<Integer> listP201;
-
- /**
- * The list for P-202 values.
- */
- private LinkedList<Integer> listP202;
-
- /**
- * The list for P-203 values.
- */
- private LinkedList<Integer> listP203;
-
- /**
- * The list for P-204 values.
- */
- private LinkedList<Integer> listP204;
-
- /**
- * The list for P-205 values.
- */
- private LinkedList<Integer> listP205;
-
- /**
- * The list for P-206 values.
- */
- private LinkedList<Integer> listP206;
-
-
- /**
- * The list of backwash intervals from the training data for MV-301.
- */
- private LinkedList<Integer> backwashIntervalList;
-
- /**
- * The list for DPIT-301 values.
- */
- private LinkedList<Double> listDPIT301;
-
- /**
- * The list for FIT-301 values.
- */
- private LinkedList<Double> listFIT301;
-
- /**
- * The list for LIT-301 values.
- */
- private LinkedList<Double> listLIT301;
-
- /**
- * The list for LIT-301 values without jittering.
- */
- private LinkedList<Double> listLIT301WithoutJittering;
-
- /**
- * The list for MV-301 values.
- */
- private LinkedList<Integer> listMV301;
-
- /**
- * The list for MV-302 values.
- */
- private LinkedList<Integer> listMV302;
-
- /**
- * The list for MV-303 values.
- */
- private LinkedList<Integer> listMV303;
-
- /**
- * The list for MV-304 values.
- */
- private LinkedList<Integer> listMV304;
-
- /**
- * The list for P-301 values.
- */
- private LinkedList<Integer> listP301;
-
- /**
- * The list for P-302 values.
- */
- private LinkedList<Integer> listP302;
-
- /**
- * The list for AIT-401 values.
- */
- private LinkedList<Double> listAIT401;
- /**
- * The list for AIT-402 values.
- */
- private LinkedList<Double> listAIT402;
-
- /**
- * The list for FIT-401 values.
- */
- private LinkedList<Double> listFIT401;
-
- /**
- * The list for LIT-401 values.
- */
- private LinkedList<Double> listLIT401;
-
- /**
- * The list for P-401 values.
- */
- private LinkedList<Integer> listP401;
-
- /**
- * The list for P-402 values.
- */
- private LinkedList<Integer> listP402;
-
- /**
- * The list for P-403 values.
- */
- private LinkedList<Integer> listP403;
-
- /**
- * The list for P-404 values.
- */
- private LinkedList<Integer> listP404;
-
- /**
- * The list for UV-401 values.
- */
- private LinkedList<Integer> listUV401;
-
- /**
- * The list for AIT-501 values.
- */
- private LinkedList<Double> listAIT501;
-
- /**
- * The list for AIT-502 values.
- */
- private LinkedList<Double> listAIT502;
-
- /**
- * The list for AIT-503 values.
- */
- private LinkedList<Double> listAIT503;
-
- /**
- * The list for AIT-504 values.
- */
- private LinkedList<Double> listAIT504;
-
- /**
- * The list for FIT-501 values.
- */
- private LinkedList<Double> listFIT501;
- /**
- * The list for FIT-502 values.
- */
- private LinkedList<Double> listFIT502;
-
- /**
- * The list for FIT-503 values.
- */
- private LinkedList<Double> listFIT503;
-
- /**
- * The list for FIT-504 values.
- */
- private LinkedList<Double> listFIT504;
-
- /**
- * The list for P-501 values.
- */
- private LinkedList<Integer> listP501;
-
- /**
- * The list for P-502 values.
- */
- private LinkedList<Integer> listP502;
-
- /**
- * The list for PIT-501 values.
- */
- private LinkedList<Double> listPIT501;
-
- /**
- * The list for PIT-502 values.
- */
- private LinkedList<Double> listPIT502;
-
- /**
- * The list for PIT-503 values.
- */
- private LinkedList<Double> listPIT503;
-
- /**
- * The list for FIT-601 values.
- */
- private LinkedList<Double> listFIT601;
-
- /**
- * The list for P-601 values.
- */
- private LinkedList<Integer> listP601;
-
- /**
- * The list for P-602 values.
- */
- private LinkedList<Integer> listP602;
-
- /**
- * The list for P-603 values.
- */
- private LinkedList<Integer> listP603;
- ///////////////////////// Lists for the status values (end)
-
- /**
- * The distribution handlers for the physical data.
- */
- private LinkedHashMap<String, SWaTDatasetDistributionHandler> distributionHandlers = new LinkedHashMap<String, SWaTDatasetDistributionHandler>();
-
- /**
- * A Hashmap of transition information with key sensor name and value array of length 5 with [0] = {0, 1} for {false, true}, [1] = total transition time, [2] = remaining transition time, [3] = goal status {1, 2}, [4] = remaining time offset before transition starts.
- */
- private LinkedHashMap<String, int[]> transitionInformation = new LinkedHashMap<String, int[]>();
-
- /**
- * A Hashmap of extreme values with key sensor name and value extreme values list.
- */
- private LinkedHashMap<String, LinkedList<Double>> extremeValues = new LinkedHashMap<String, LinkedList<Double>>();
-
- /**
- * A Hashmap of extreme value informations with key sensor name and value {-1, 0, 1} for {none, minimum, maximum}.
- */
- private LinkedHashMap<String, Integer> extremeValueInformation = new LinkedHashMap<String, Integer>();
-
- /**
- * A Hashmap of plateaus values with key sensor name and value plateau values list.
- */
- private LinkedHashMap<String, LinkedList<Double>> plateauValues = new LinkedHashMap<String, LinkedList<Double>>();
-
- /**
- * Maps the device names of sensors to their lists.
- */
- private LinkedHashMap<String, LinkedList<Double>> deviceNamesToDeviceListsSensors = new LinkedHashMap<String, LinkedList<Double>>();
- /**
- * Maps the device names of sensors to their lists.
- */
- private LinkedHashMap<String, LinkedList<Integer>> deviceNamesToDeviceListsActuators = new LinkedHashMap<String, LinkedList<Integer>>();
-
- /**
- * The constructor.
- * @param controller The controller of the scenario.
- */
- public SWaTSimulationManagerPhysical(Controller controller) {
- this.networkController = controller.getNetworkController();
- }
-
- /**
- * Starts the physical simulation.
- * @param duration The duration of the simulation in seconds.
- * @param outputFileTime A calendar object for the timestamp in the file name of the output file
- * @param outputDirectoryPath The path of the directory for the output files.
- * @param startStatus The status at which the simulation is to be started. Has the format of a line of the network traffic data.
- * @param passByReferenceValue_KeepSimulationRunning The PropertyChangeListener to observe this class.
- * @param propertyChangeListener The PropertyChangeListener to observe this class.
- * @param attackData The attack data as a two-dimensional array. Each row is an attack with [0] = start time, [1] = end time, [2] = device name, [3] = value/status to change to
- */
- public void startSimulation(String duration, Calendar outputFileTime, String outputDirectoryPath, String startStatus,
- boolean[] passByReferenceValue_KeepSimulationRunning, PropertyChangeListener propertyChangeListener,
- Object[][] attackData) {
- // Reset lists
- outputList = new LinkedList<String>();
- listTimestamp = new LinkedList<String>();
- listNormalAttack = new LinkedList<String>();
- listFIT101 = new LinkedList<Double>();
- listLIT101 = new LinkedList<Double>();
- listLIT101WithoutJittering = new LinkedList<Double>();
- listMV101 = new LinkedList<Integer>();
- listP101 = new LinkedList<Integer>();
- listP102 = new LinkedList<Integer>();
- listMV201 = new LinkedList<Integer>();
-
- listAIT201 = new LinkedList<Double>();
- listAIT202 = new LinkedList<Double>();
- listAIT203 = new LinkedList<Double>();
- listFIT201 = new LinkedList<Double>();
- listP201 = new LinkedList<Integer>();
- listP202 = new LinkedList<Integer>();
- listP203 = new LinkedList<Integer>();
- listP204 = new LinkedList<Integer>();
- listP205 = new LinkedList<Integer>();
- listP206 = new LinkedList<Integer>();
-
- backwashIntervalList = new LinkedList<Integer>();
- setUpBackwashIntervalList();
- listDPIT301 = new LinkedList<Double>();
- listFIT301 = new LinkedList<Double>();
- listLIT301 = new LinkedList<Double>();
- listLIT301WithoutJittering = new LinkedList<Double>();
- listMV301 = new LinkedList<Integer>();
- listMV302 = new LinkedList<Integer>();
- listMV303 = new LinkedList<Integer>();
- listMV304 = new LinkedList<Integer>();
- listP301 = new LinkedList<Integer>();
- listP302 = new LinkedList<Integer>();
-
- listAIT401 = new LinkedList<Double>();
- listAIT402 = new LinkedList<Double>();
- listFIT401 = new LinkedList<Double>();
- listLIT401 = new LinkedList<Double>();
- listP401 = new LinkedList<Integer>();
- listP402 = new LinkedList<Integer>();
- listP403 = new LinkedList<Integer>();
- listP404 = new LinkedList<Integer>();
- listUV401 = new LinkedList<Integer>();
-
- listAIT501 = new LinkedList<Double>();
- listAIT502 = new LinkedList<Double>();
- listAIT503 = new LinkedList<Double>();
- listAIT504 = new LinkedList<Double>();
- listFIT501 = new LinkedList<Double>();
- listFIT502 = new LinkedList<Double>();
- listFIT503 = new LinkedList<Double>();
- listFIT504 = new LinkedList<Double>();
- listP501 = new LinkedList<Integer>();
- listP502 = new LinkedList<Integer>();
- listPIT501 = new LinkedList<Double>();
- listPIT502 = new LinkedList<Double>();
- listPIT503 = new LinkedList<Double>();
-
- listFIT601 = new LinkedList<Double>();
- listP601 = new LinkedList<Integer>();
- listP602 = new LinkedList<Integer>();
- listP603 = new LinkedList<Integer>();
-
- deviceNamesToDeviceListsSensors = new LinkedHashMap<String, LinkedList<Double>>();
- deviceNamesToDeviceListsSensors.put("FIT-101", listFIT101);
- deviceNamesToDeviceListsSensors.put("LIT-101", listLIT101);
- deviceNamesToDeviceListsSensors.put("AIT-201", listAIT201);
- deviceNamesToDeviceListsSensors.put("AIT-202", listAIT202);
- deviceNamesToDeviceListsSensors.put("AIT-203", listAIT203);
- deviceNamesToDeviceListsSensors.put("FIT-201", listFIT201);
- deviceNamesToDeviceListsSensors.put("DPIT-301", listDPIT301);
- deviceNamesToDeviceListsSensors.put("FIT-301", listFIT301);
- deviceNamesToDeviceListsSensors.put("LIT-301", listLIT301);
- deviceNamesToDeviceListsSensors.put("AIT-401", listAIT401);
- deviceNamesToDeviceListsSensors.put("AIT-402", listAIT402);
- deviceNamesToDeviceListsSensors.put("FIT-401", listFIT401);
- deviceNamesToDeviceListsSensors.put("LIT-401", listLIT401);
- deviceNamesToDeviceListsSensors.put("AIT-501", listAIT501);
- deviceNamesToDeviceListsSensors.put("AIT-502", listAIT502);
- deviceNamesToDeviceListsSensors.put("AIT-503", listAIT503);
- deviceNamesToDeviceListsSensors.put("AIT-504", listAIT504);
- deviceNamesToDeviceListsSensors.put("FIT-501", listFIT501);
- deviceNamesToDeviceListsSensors.put("FIT-502", listFIT502);
- deviceNamesToDeviceListsSensors.put("FIT-503", listFIT503);
- deviceNamesToDeviceListsSensors.put("FIT-504", listFIT504);
- deviceNamesToDeviceListsSensors.put("PIT-501", listPIT501);
- deviceNamesToDeviceListsSensors.put("PIT-502", listPIT502);
- deviceNamesToDeviceListsSensors.put("PIT-503", listPIT503);
- deviceNamesToDeviceListsSensors.put("FIT-601", listFIT601);
- deviceNamesToDeviceListsActuators = new LinkedHashMap<String, LinkedList<Integer>>();
- deviceNamesToDeviceListsActuators.put("MV-101", listMV101);
- deviceNamesToDeviceListsActuators.put("P-101", listP101);
- deviceNamesToDeviceListsActuators.put("P-102", listP102);
- deviceNamesToDeviceListsActuators.put("MV-201", listMV201);
- deviceNamesToDeviceListsActuators.put("P-201", listP201);
- deviceNamesToDeviceListsActuators.put("P-202", listP202);
- deviceNamesToDeviceListsActuators.put("P-203", listP203);
- deviceNamesToDeviceListsActuators.put("P-204", listP204);
- deviceNamesToDeviceListsActuators.put("P-205", listP205);
- deviceNamesToDeviceListsActuators.put("P-206", listP206);
- deviceNamesToDeviceListsActuators.put("MV-301", listMV301);
- deviceNamesToDeviceListsActuators.put("MV-302", listMV302);
- deviceNamesToDeviceListsActuators.put("MV-303", listMV303);
- deviceNamesToDeviceListsActuators.put("MV-304", listMV304);
- deviceNamesToDeviceListsActuators.put("P-301", listP301);
- deviceNamesToDeviceListsActuators.put("P-302", listP302);
- deviceNamesToDeviceListsActuators.put("P-401", listP401);
- deviceNamesToDeviceListsActuators.put("P-402", listP402);
- deviceNamesToDeviceListsActuators.put("P-403", listP403);
- deviceNamesToDeviceListsActuators.put("P-404", listP404);
- deviceNamesToDeviceListsActuators.put("UV-401", listUV401);
- deviceNamesToDeviceListsActuators.put("P-501", listP501);
- deviceNamesToDeviceListsActuators.put("P-502", listP502);
- deviceNamesToDeviceListsActuators.put("P-601", listP601);
- deviceNamesToDeviceListsActuators.put("P-602", listP602);
- deviceNamesToDeviceListsActuators.put("P-603", listP603);
-
- // Reset additional variables
- transitionInformation = new LinkedHashMap<String, int[]>();
- transitionInformation.put("MV-101", new int[]{0,0,0,0,0});
- transitionInformation.put("MV-201", new int[]{0,0,0,0,3});
- transitionInformation.put("P-203", new int[]{0,0,0,0,0});
- transitionInformation.put("P-205", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-201", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-202", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-203", new int[]{0,0,0,0,0});
- transitionInformation.put("FIT-201", new int[]{0,0,0,0,0});
- transitionInformation.put("MV-301", new int[]{0,0,0,0,0});
- transitionInformation.put("MV-302", new int[]{0,0,0,0,0});
- transitionInformation.put("MV-303", new int[]{0,0,0,0,0});
- transitionInformation.put("MV-304", new int[]{0,0,0,0,0});
- transitionInformation.put("P-302", new int[]{0,0,0,0,0});
- transitionInformation.put("LIT-301", new int[]{0,0,0,0,0});
- transitionInformation.put("LIT-401", new int[]{0,0,0,0,0});
- transitionInformation.put("FIT-401", new int[]{0,0,0,0,0});
- transitionInformation.put("P-402", new int[]{0,0,0,0,0});
- transitionInformation.put("UV-401", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-402", new int[]{0,0,0,0,0});
- transitionInformation.put("LIT-401", new int[]{0,0,0,0,0});
- transitionInformation.put("P-501", new int[]{0,0,0,0,0});
- transitionInformation.put("FIT-501", new int[]{0,0,0,0,0});
- transitionInformation.put("FIT-502", new int[]{0,0,0,0,0});
- transitionInformation.put("FIT-503", new int[]{0,0,0,0,0});
- transitionInformation.put("FIT-504", new int[]{0,0,0,0,0});
- transitionInformation.put("PIT-501", new int[]{0,0,0,0,0});
- transitionInformation.put("PIT-502", new int[]{0,0,0,0,0});
- transitionInformation.put("PIT-503", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-501", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-502", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-503", new int[]{0,0,0,0,0});
- transitionInformation.put("AIT-504", new int[]{0,0,0,0,0});
- transitionInformation.put("P-602", new int[]{0,0,-1,0,0});
-
- extremeValues = new LinkedHashMap<String, LinkedList<Double>>();
- LinkedList<Double> extremeValueListTemp = new LinkedList<Double>();
- extremeValueListTemp.add(0.0);
- extremeValues.put("FIT-101", extremeValueListTemp);
- extremeValues.put("LIT-101", new LinkedList<Double>());
- LinkedList<Double> extremeValueListTemp2 = new LinkedList<Double>();
- extremeValueListTemp2.add(0.0);
- extremeValues.put("FIT-201", new LinkedList<Double>());
- extremeValues.put("AIT-203", new LinkedList<Double>());
- extremeValues.put("AIT-202", new LinkedList<Double>());
- extremeValues.put("FIT-301", new LinkedList<Double>());
- extremeValueInformation = new LinkedHashMap<String, Integer>();
- extremeValueInformation.put("FIT-101", 0);
- extremeValueInformation.put("LIT-101", -1);
- extremeValueInformation.put("FIT-201", 0);
- extremeValueInformation.put("AIT-201", -1);
- extremeValueInformation.put("AIT-202", -1);
- extremeValueInformation.put("AIT-203", -1);
- extremeValueInformation.put("LIT-301", -1);
- extremeValueInformation.put("FIT-301", 1);
- extremeValueInformation.put("LIT-401", -1);
- extremeValueInformation.put("FIT-501", -1);
- extremeValueInformation.put("FIT-502", -1);
- extremeValueInformation.put("FIT-503", -1);
- extremeValueInformation.put("FIT-504", -1);
- extremeValueInformation.put("PIT-501", -1);
- extremeValueInformation.put("PIT-502", -1);
- extremeValueInformation.put("PIT-503", -1);
- extremeValueInformation.put("AIT-501", -1);
- extremeValueInformation.put("AIT-502", 1);
- extremeValueInformation.put("AIT-503", -1);
- extremeValueInformation.put("AIT-504", -1);
- extremeValueInformation.put("FIT-601", -1);
-
- plateauValues = new LinkedHashMap<String, LinkedList<Double>>();
- plateauValues.put("FIT-201", new LinkedList<Double>());
- plateauValues.put("DPIT-301", null);
-
- // Set parameters
- distributionHandlers = new LinkedHashMap<String, SWaTDatasetDistributionHandler>();
- setDatasetDistributionHandlers();
- durationInSeconds = Integer.parseInt(duration);
- this.outputDirectoryPath = outputDirectoryPath;
- startTime = (Calendar) outputFileTime.clone();
- currentTime = (Calendar) startTime.clone();
- setUpStatus(startStatus);
- this.passByReferenceValue_KeepSimulationRunning = passByReferenceValue_KeepSimulationRunning;
- if(listLIT301.getFirst() > 780) extremeValueInformation.put("LIT-301", 2);
- else transitionInformation.get("LIT-301")[4] = 4;
- this.propertyChangeSupport.addPropertyChangeListener(propertyChangeListener);
- resultsMap = new LinkedHashMap<Integer, String[]>();
- resultsMap.put(0, new String[] {listLIT101.getLast().toString(), listAIT201.getLast().toString(), listFIT201.getLast().toString(), listLIT301.getLast().toString(), listLIT401.getLast().toString(), "0"});
-
- // Simulate each second
- int durationInSecondsPercent = durationInSeconds/100;
- for(int s = 0; s < durationInSeconds; s++) {
- if(passByReferenceValue_KeepSimulationRunning[0] == false) break;
- if(s % durationInSecondsPercent == 0) propertyChangeSupport.firePropertyChange("statusPercentagePhysicalSimulation", 0, (int)(s/durationInSecondsPercent));
-
- increaseTimeByOneSecond();
- listTimestamp.add(getCurrentTimeString());
-
- simulateStage1(s);
- simulateStage2(s);
- simulateStage3(s);
- simulateStage4(s);
- simulateStage5(s);
- simulateStage6(s);
-
- // Attacks here
- boolean attackHappened = false;
- for(Object[] attacks:attackData) {
- if(s >= Integer.parseInt((String) attacks[0]) && s <= Integer.parseInt((String) attacks[1])) { // the current second is between start time and end time of the attack
- String attackedDeviceName = (String) attacks[2];
- if(deviceNamesToDeviceListsSensors.containsKey(attackedDeviceName)) {
- LinkedList<Double> attackedSensorList = deviceNamesToDeviceListsSensors.get(attackedDeviceName);
- attackedSensorList.removeLast();
- String attackType = (String) attacks[3];
- Double attackValue = Double.parseDouble((String) attacks[4]);
- switch(attackType) {
- case "Increase by":
- attackedSensorList.add(attackedSensorList.getLast() + attackValue);
- break;
- case "Decrease by":
- attackedSensorList.add(attackedSensorList.getLast() - attackValue);
- break;
- default: // "Set to"
- attackedSensorList.add(attackValue);
- }
- attackHappened = true;
- }
- else if(deviceNamesToDeviceListsActuators.containsKey(attackedDeviceName)) {
- LinkedList<Integer> attackedActuatorList = deviceNamesToDeviceListsActuators.get(attackedDeviceName);
- int attackStatus = attackedActuatorList.removeLast();
- switch((String) attacks[4]) {
- case "On":
- attackStatus = 2;
- break;
- case "Off":
- attackStatus = 1;
- break;
- case "Transition":
- attackStatus = 0;
- break;
- }
- attackedActuatorList.add(attackStatus);
- attackHappened = true;
- }
- }
- }
-
- if(attackHappened)
- listNormalAttack.add("Attack");
- else
- listNormalAttack.add("Normal");
- resultsMap.put(s+1, new String[] {listLIT101.getLast().toString(), listAIT201.getLast().toString(), listFIT201.getLast().toString(), listLIT301.getLast().toString(), listLIT401.getLast().toString(), (attackHappened ? "1" : "0")});
- }
-
- // Create and save output
- if(passByReferenceValue_KeepSimulationRunning[0] == true) {
- createOutput();
- saveCSVOutput();
- }
- }
-
- /**
- * Simulates stage one for one second.
- *
- * @param seconds The current simulation time in seconds.
- */
- private void simulateStage1(int seconds) {
- // MV-101
- double lit101LastStatus = listLIT101.getLast();
- int mv101LastStatus = listMV101.getLast();
- simulateMV("MV-101", listMV101, listLIT101, 500, 800, 0, 0, true, true);
- int[] mv101TransitionInformation = transitionInformation.get("MV-101");
-
- // FIT-101
- double fit101LastValue = listFIT101.getLast();
- LinkedList<Double> extremeValueListFIT = extremeValues.get("FIT-101");
- if(mv101LastStatus == 0) { // Start or stop flow
- int totalTransitionTime = mv101TransitionInformation[1];
- if(mv101TransitionInformation[3] == 1) { // Transition to closed: decrease value immediately
- double fit101step = distributionHandlers.get("FIT-101 Flank Distribution Sharply Decreasing").sampleNextValueExactly();
- double fit101New = BigDecimal.valueOf(fit101LastValue).subtract(BigDecimal.valueOf(fit101step)).doubleValue();
- if(fit101New < 0) fit101New = 0.0;
- listFIT101.add(fit101New);
- }
- else if(mv101TransitionInformation[3] == 2) { // Transition to open: increase value at half of transition time
- if(totalTransitionTime%2 == 1) totalTransitionTime++;
- if(totalTransitionTime/2 > mv101TransitionInformation[2]) {
- double fit101step = distributionHandlers.get("FIT-101 Flank Distribution Sharply Increasing").sampleNextValueExactly();
- listFIT101.add(BigDecimal.valueOf(fit101LastValue).add(BigDecimal.valueOf(fit101step)).doubleValue());
- }
- else
- listFIT101.add(0.0);
- }
- double minimum = distributionHandlers.get("FIT-101 Minima Distribution").sampleNextValueExactly();
- extremeValueInformation.put("FIT-101", 0);
- extremeValueListFIT.set(0, minimum);
- }
- else if(mv101LastStatus == 1) { // Valve is closed
- if(fit101LastValue > 0) { // Continue to decrease until 0
- double fit101step = distributionHandlers.get("FIT-101 Flank Distribution Sharply Decreasing").sampleNextValueExactly();
- double fit101New = BigDecimal.valueOf(fit101LastValue).subtract(BigDecimal.valueOf(fit101step)).doubleValue();
- if(fit101New < 0) fit101New = 0.0;
- listFIT101.add(fit101New);
- }
- else
- listFIT101.add(0.0);
-
- }
- else if(mv101LastStatus == 2) { // Valve is open
- double extremeValue = extremeValueListFIT.get(0);
- if(extremeValueInformation.get("FIT-101") == 0) { // Decreasing
- double fit101step = distributionHandlers.get("FIT-101 Flank Distribution Decreasing").sampleNextValueExactly();
- double fit101New = BigDecimal.valueOf(fit101LastValue).subtract(BigDecimal.valueOf(fit101step)).doubleValue();
- if(fit101New < extremeValue) {
- fit101New = extremeValue;
- // Maximum after minimum
- double maximum = distributionHandlers.get("FIT-101 Maxima Distribution").sampleNextValueExactly();
- extremeValueInformation.put("FIT-101", 1);
- extremeValueListFIT.set(0, maximum);
- }
- listFIT101.add(fit101New);
- }
- else { // Increasing
- double fit101step = distributionHandlers.get("FIT-101 Flank Distribution Increasing").sampleNextValueExactly();
- double fit101New = BigDecimal.valueOf(fit101LastValue).add(BigDecimal.valueOf(fit101step)).doubleValue();
- if(fit101New > extremeValue) {
- fit101New = extremeValue;
- // Minimum after maximum
- double minimum = distributionHandlers.get("FIT-101 Minima Distribution").sampleNextValueExactly();
- extremeValueInformation.put("FIT-101", 0);
- extremeValueListFIT.set(0, minimum);
- }
- listFIT101.add(fit101New);
- }
- }
- // P-101 and P-102
- int p101102LastStatus = 1;
- int p101LastStatus = listP101.getLast();
- int p102LastStatus = listP102.getLast();
- if(p101LastStatus == 2 || p102LastStatus == 2)
- p101102LastStatus = 2;
- listP102.add(1); // Still off or again off
-
- // P-101
- int mv201LastStatus = listMV201.getLast();
- if(lit101LastStatus >= 250 && mv201LastStatus == 2) { // Turn on
- listP101.add(2);
- }
- else // Turn off
- listP101.add(1);
-
-
- // LIT-101
- double litstep = 0.0;
- double lit101New = 0.0;
- String litName = "LIT-101";
- int extremeValueInformationLIT101 = extremeValueInformation.get("LIT-101");
-
- if(mv101LastStatus != 2 && fit101LastValue == 0 && p101102LastStatus == 1) // Neither inflow nor outflow
- litstep = 0;
- // Inflow and outflow at the same time
- else if(mv101LastStatus == 2 && p101102LastStatus == 2) {
- litstep = 0.0115193476;//0.01014685;
- }
- // Only outflow
- else if((mv101LastStatus == 1 || mv101LastStatus == 0) && p101102LastStatus == 2) { // listFIT101.getLast() < listFIT201.getLast()
- litstep = -0.4870658842;
- }
- // Only inflow
- else {
- litstep = 0.4842940878;
- }
- listLIT101WithoutJittering.add(BigDecimal.valueOf(listLIT101WithoutJittering.getLast()).add(BigDecimal.valueOf(litstep)).doubleValue());
-
- LinkedList<Double> extremeValueList = extremeValues.get(litName);
- if(extremeValueList.size() > 0) {
- litstep = extremeValueList.pop();
- if(mv101LastStatus == 2 && p101102LastStatus == 2) litstep*=3;
- }
- else {
- int secondsToZero = (int) distributionHandlers.get("LIT-101 Seconds Between Zeros Distribution").sampleNextValueExactly();
- if(extremeValueInformationLIT101 == -1) {
- double firstJitterValue = distributionHandlers.get("LIT-101 Jitter").sampleNextValueExactlyAlsoNegative();
- extremeValueList.add(firstJitterValue);
- if(secondsToZero > 1) {
- if(firstJitterValue > 1) { // Positive Jitter
- extremeValueInformationLIT101 = 1;
- for(int i = 2; i <= secondsToZero; i++) {
- extremeValueList.add(distributionHandlers.get("LIT-101 Jitter Positive").sampleNextValueExactly());
- }
- }
- else { // Negative Jitter
- extremeValueInformationLIT101 = 0;
- for(int i = 2; i <= secondsToZero; i++) {
- extremeValueList.add(-distributionHandlers.get("LIT-101 Jitter Negative").sampleNextValueExactly());
- }
- }
- }
- }
- else if(extremeValueInformationLIT101 == 1) { // Negative Jitter
- extremeValueInformationLIT101 = 0;
- for(int i = 1; i <= secondsToZero; i++) {
- extremeValueList.add(-distributionHandlers.get("LIT-101 Jitter Negative").sampleNextValueExactly());
- }
- }
- else { // Positive Jitter
- extremeValueInformationLIT101 = 1;
- for(int i = 1; i <= secondsToZero; i++) {
- extremeValueList.add(distributionHandlers.get("LIT-101 Jitter Positive").sampleNextValueExactly());
- }
- }
- }
- extremeValueInformation.put("LIT-101", extremeValueInformationLIT101);
- extremeValues.put(litName, extremeValueList);
- lit101New = BigDecimal.valueOf(listLIT101WithoutJittering.getLast()).add(BigDecimal.valueOf(litstep)).doubleValue();
- if(lit101New < 0) lit101New = 0;// Tank cannot be less full than empty
- listLIT101.add(lit101New);
- }
-
- /**
- * Simulates stage two for one second.
- *
- * @param seconds The current simulation time in seconds.
- */
- private void simulateStage2(int seconds) {
- // MV-201
- int mv201LastStatus = listMV201.getLast();
- int[] mv201TransitionInformation = transitionInformation.get("MV-201");
- simulateMV("MV-201", listMV201, listLIT301, 800, 1000, 3, 3, true, true);
-
- // FIT-201
- String fitName = "FIT-201";
- int[] fitTransitionInformation = transitionInformation.get(fitName);
- double fit201LastValue = listFIT201.getLast();
-
- LinkedList<Double> extremeValueListFIT = extremeValues.get(fitName);
- double lit101LastValue = listLIT101.getLast();
-
- if(fitTransitionInformation[0] == 0 && mv201LastStatus == 0) { // New transition
- fitTransitionInformation[0] = 1;
- if(mv201TransitionInformation[3] == 1) { // Transition to closed
- fitTransitionInformation[3] = 1;
- fitTransitionInformation[4] = ThreadLocalRandom.current().nextInt(0, 2);
- }
- else { // Transition to open
- fitTransitionInformation[3] = 2;
- fitTransitionInformation[4] = mv201TransitionInformation[2] + ThreadLocalRandom.current().nextInt(3, 5);
- }
- listFIT201.add(fit201LastValue);
- }
- else if(lit101LastValue <= 250) {
- listFIT201.add(fit201LastValue);
- }
- else if(fitTransitionInformation[0] == 1) {
- if(fitTransitionInformation[4] <= 0) { // Flow changes
- plateauValues.put(fitName, new LinkedList<Double>());
- if(fitTransitionInformation[3] == 1) { // Transition to closed: sharply decreasing flow
- double fitStep = distributionHandlers.get(fitName+" Flank Distribution Sharply Decreasing").sampleNextValueExactly();
- double fitNew = BigDecimal.valueOf(fit201LastValue).subtract(BigDecimal.valueOf(fitStep)).doubleValue();
- if(fitNew < 0) {
- fitNew = 0.0;
- fitTransitionInformation[0] = 0;
- }
- listFIT201.add(fitNew);
- }
- else if(fitTransitionInformation[3] == 2) { // Transition to open: sharply increasing flow
- double fit101step = distributionHandlers.get(fitName+" Flank Distribution Sharply Increasing").sampleNextValueExactly();
- double fitNew = BigDecimal.valueOf(fit201LastValue).add(BigDecimal.valueOf(fit101step)).doubleValue();
- if(fitNew > 2.488) {
- while(true) {
- fitNew -= 0.01;
- if(fitNew <= 2.488) break;
- }
- fitTransitionInformation[0] = 0;
- }
- listFIT201.add(fitNew);
- }
- }
- else { // Count down
- fitTransitionInformation[4]--;
- listFIT201.add(listFIT201.getLast());
- }
- }
- else if(mv201LastStatus == 1) { // Valve is closed
- if(fit201LastValue > 0) { // Continue to decrease until 0
- double fitStep = distributionHandlers.get(fitName+" Flank Distribution Sharply Decreasing").sampleNextValueExactly();
- double fitNew = BigDecimal.valueOf(fit201LastValue).subtract(BigDecimal.valueOf(fitStep)).doubleValue();
- if(fitNew < 0) fitNew = 0.0;
- listFIT201.add(fitNew);
- }
- else
- listFIT201.add(0.0);
- }
- else if(mv201LastStatus == 2) { // Valve is open
- if(extremeValueListFIT.size() == 0) { // Initial value
- double minimum = distributionHandlers.get(fitName+" Minima Distribution").sampleNextValueExactly();
- if(fit201LastValue - minimum >= 0.005)
- while(true) {
- minimum += 0.001;
- if(fit201LastValue - minimum < 0.005) break;
- }
- extremeValueInformation.put(fitName, 0);
- extremeValueListFIT.add(minimum);
- }
-
- // Handle plateaus
- if(plateauValues.get(fitName).size() > 1) {
- listFIT201.add(plateauValues.get(fitName).pop());
- }
- else if(plateauValues.get(fitName).size() == 1) {
- listFIT201.add(plateauValues.get(fitName).pop());
- plateauValues.put(fitName, new LinkedList<Double>());
- }
- else {
- double extremeValue = extremeValueListFIT.get(0);
- double fitNew = fit201LastValue;
- if(extremeValueInformation.get(fitName) == 0) { // Decreasing
- double fitStep = distributionHandlers.get(fitName+" Flank Distribution Decreasing").sampleNextValueExactly();
- if(fitStep >= 0.005) fitStep = 0.005;
- fitNew = BigDecimal.valueOf(fit201LastValue).subtract(BigDecimal.valueOf(fitStep)).doubleValue();
- if(fitNew < extremeValue) {
- // Maximum after minimum
- double maximum = distributionHandlers.get(fitName+" Maxima Distribution").sampleNextValueExactly();
- if(maximum - fit201LastValue >= 0.005)
- while(true) {
- maximum -= 0.001;
- if(maximum - fit201LastValue < 0.005) break;
- }
- extremeValueInformation.put(fitName, 1);
- extremeValueListFIT.set(0, maximum);
- }
- }
- else { // Increasing
- double fitStep = distributionHandlers.get(fitName+" Flank Distribution Increasing").sampleNextValueExactly();
- if(fitStep >= 0.005) fitStep = 0.005;
- fitNew = BigDecimal.valueOf(fit201LastValue).add(BigDecimal.valueOf(fitStep)).doubleValue();
-
- if(fitNew > extremeValue) {
- double minimum = distributionHandlers.get(fitName+" Minima Distribution").sampleNextValueExactly();
- if(fit201LastValue - minimum >= 0.005)
- while(true) {
- minimum += 0.001;
- if(fit201LastValue - minimum < 0.005) break;
- }
- extremeValueInformation.put(fitName, 0);
- extremeValueListFIT.set(0, minimum);
- }
- }
- int plateauLength = (int) distributionHandlers.get(fitName+" Flank Plateaus Distribution").sampleNextValueExactly();
- LinkedList<Double> plateauList = new LinkedList<Double>();
- for(int i = 0; i < plateauLength; i++) {
- plateauList.add(fitNew);
- }
- plateauValues.put(fitName, plateauList);
- listFIT201.add(fitNew);
- }
- }
-
- // AIT-201
- String ait201Name = "AIT-201";
- double ait201LastValue = listAIT201.getLast();
- double ait201FirstValue = listAIT201.getFirst();
- double ait201Next = ait201LastValue;
- double ait201Maximum = 272.5263;
- double ait201Minimum = 244.3284;
- double ait201Middle = (ait201Maximum - ait201Minimum)/2;
- double ait201MiddlePosition = ait201Minimum + ait201Middle;
- int ait201ExtremeValueInformation = extremeValueInformation.get(ait201Name);
- if(ait201ExtremeValueInformation == -1) { // Wait for first water
- if(listFIT201.getLast() != 0)
- extremeValueInformation.put(ait201Name, 0);
- if(seconds % 25 == 0) {
- double randomStep = ThreadLocalRandom.current().nextDouble(-0.3, 0.031);
- if(ait201LastValue + randomStep < ait201FirstValue)
- ait201Next = ait201LastValue - randomStep;
- else
- ait201Next = ait201LastValue + randomStep;
- }
- else
- ait201Next = ait201LastValue;
- }
- else if(ait201ExtremeValueInformation == 0) { // Move to middle position
- if(ait201LastValue < ait201MiddlePosition) {
- double ait201Step = ThreadLocalRandom.current().nextDouble(-0.05, 0.15);
- ait201Next = ait201LastValue + ait201Step;
- if(ait201Next > ait201MiddlePosition) {
- ait201Next = ait201LastValue;
- extremeValueInformation.put(ait201Name, 1);
- }
- }
- else {
- extremeValueInformation.put(ait201Name, 1);
- }
- }
- else {
- if(seconds > 2 && mv201LastStatus == 2 && listMV201.get(listMV201.size()-3) == 0) { // Add spike
- ait201Next = ait201LastValue+ThreadLocalRandom.current().nextDouble(0.5, 1.5);
- }
- else {
- // Follow a sin curve
- double ait201SinPosition = Math.sin(2*Math.PI/200000*(seconds % 200000));
- ait201Next = ait201MiddlePosition+ait201Middle*ait201SinPosition;
- }
- }
- if(ait201ExtremeValueInformation != -1 && seconds % (200 + ThreadLocalRandom.current().nextInt(-20,21)) == 0) // Add jitter from time to time
- ait201Next = ait201Next + ThreadLocalRandom.current().nextDouble(-0.3, 0.31);
- if(ait201Next < ait201MiddlePosition-ait201Middle && ait201ExtremeValueInformation == 1)
- ait201Next = ait201MiddlePosition-ait201Middle;
- listAIT201.add(ait201Next);
-
- // AIT-202
- String ait202Name = "AIT-202";
- double ait202LastStatus = listAIT202.getLast();
- double ait202Next = ait202LastStatus;
- double ait202Maximum = 8.988273;
- double ait202Minimum = 8.19008;
- double ait202Middle = (ait202Maximum - ait202Minimum)/2;
- double ait202MiddlePosition = ait202Minimum + ait202Middle;
- int[] transitionInformationAIT202 = transitionInformation.get(ait202Name);
-
- int ait202ExtremeValueInformation = extremeValueInformation.get(ait202Name);
- if(ait202ExtremeValueInformation == -1) { // Wait for first water
- if(listFIT201.getLast() != 0)
- extremeValueInformation.put(ait202Name, 0);
- ait202Next = ait202LastStatus;
- }
- else if(ait202ExtremeValueInformation == 0) { // Move to middle position
- if(ait202LastStatus < ait202MiddlePosition) {
- double ait202Step = ThreadLocalRandom.current().nextDouble(-0.05, 0.15);
- ait202Next = ait202LastStatus + ait202Step;
- if(ait202Next > ait202MiddlePosition) {
- ait202Next = ait202MiddlePosition;
- extremeValueInformation.put(ait202Name, 1);
- }
- }
- else {
- extremeValueInformation.put(ait202Name, 1);
- }
- }
- else {
- if(seconds > 2) {
- if(mv201LastStatus == 1 && listMV201.get(listMV201.size()-3) == 0) { // Start spike
- transitionInformationAIT202[0] = ThreadLocalRandom.current().nextInt(68, 75);
- ait202Next = ait202LastStatus+transitionInformationAIT202[0]/1000.0;
- }
- else if(mv201LastStatus == 2 && listMV201.get(listMV201.size()-3) == 0) { // End spike
- ait202Next = ait202LastStatus-transitionInformationAIT202[0]/1000.0;
- }
- }
- }
- listAIT202.add(ait202Next + ThreadLocalRandom.current().nextGaussian()*0.00005);
-
- // AIT-203
- String ait203Name = "AIT-203";
- double ait203LastStatus = listAIT203.getLast();
- double ait203Next = ait203LastStatus;
- double ait203MiddlePosition = 335.0;
- int[] transitionInformationAIT203 = transitionInformation.get(ait203Name);
-
- int ait203ExtremeValueInformation = extremeValueInformation.get(ait203Name);
- if(ait203ExtremeValueInformation == -1) { // Wait for first water
- if(listFIT201.getLast() != 0)
- extremeValueInformation.put(ait203Name, 0);
- ait203Next = ait203LastStatus;
- }
- else if(ait203ExtremeValueInformation == 0) { // Move to middle position
- if(ait203LastStatus < ait203MiddlePosition) {
- double ait203Step = ThreadLocalRandom.current().nextDouble(-0.05, 0.15);
- ait203Next = ait203LastStatus + ait203Step;
- if(ait203Next > ait203MiddlePosition) {
- ait203Next = ait203MiddlePosition;
- extremeValueInformation.put(ait203Name, 1);
- }
- }
- else {
- extremeValueInformation.put(ait203Name, 1);
- }
- }
- else {
- if(seconds > 2) {
- if(mv201LastStatus == 1 && listMV201.get(listMV201.size()-3) == 0) { // Start spike
- transitionInformationAIT203[0] = ThreadLocalRandom.current().nextInt(1400, 1600);
- ait203Next = ait203LastStatus - transitionInformationAIT203[0]/100.0;
- }
- else if(mv201LastStatus == 2 && listMV201.get(listMV201.size()-3) == 0) { // End spike
- ait203Next = ait203LastStatus + transitionInformationAIT203[0]/100.0;
- }
- else if(mv201LastStatus == 2) {
- ait203Next = ait203LastStatus - 0.001;
- }
- else {
- ait203Next = ait203LastStatus + 0.0035;
- }
- }
- }
- listAIT203.add(ait203Next + ThreadLocalRandom.current().nextGaussian()*0.05);
-
- // P-201 and P-202
- listP202.add(1); // Still off or again off
- if(mv201LastStatus == 1 || (mv201LastStatus == 0 & transitionInformation.get("MV-201")[3] == 1)) {
- listP201.add(1);
- }
- else {
- listP201.add(1);
- }
-
- // P-203 and P-204
- listP204.add(1); // Still off or again off
- if(mv201LastStatus == 1 || (mv201LastStatus == 0 & transitionInformation.get("MV-201")[3] == 1)) {
- listP203.add(1);
- }
- else{
- if(transitionInformation.get("P-203")[0] == 0 && fit201LastValue > 0 && ait202LastStatus >= 6.94999980927) { // Start offset countdown
- transitionInformation.get("P-203")[0] = 1;
- transitionInformation.get("P-203")[4] = ThreadLocalRandom.current().nextInt(6, 10);
- }
- if(transitionInformation.get("P-203")[0] == 1) {
- if(transitionInformation.get("P-203")[4] > 0 && (fit201LastValue <= 0 || ait202LastStatus < 6.94999980927)) { // Stop offset countdown
- listP203.add(1);
- transitionInformation.get("P-203")[0] = 0;
- }
- else {
- transitionInformation.get("P-203")[4]--;
- if(transitionInformation.get("P-203")[4] <= 0) { // Finish offset countdown
- transitionInformation.get("P-203")[0] = 0;
- listP203.add(2);
- }
- else {
- listP203.add(listP203.getLast());
- }
- }
- }
- else {
- listP203.add(listP203.getLast());
- }
- }
-
- // P-205 and P-206
- listP206.add(1); // Still off or again off
- if(ait203LastStatus >= 500 || mv201LastStatus == 1 || (mv201LastStatus == 0 & transitionInformation.get("MV-201")[3] == 1)) {
- listP205.add(1);
- }
- else{
- if(transitionInformation.get("P-205")[0] == 0 && fit201LastValue > 0 && ait203LastStatus <= 436) { // Start offset countdown
- transitionInformation.get("P-205")[0] = 1;
- transitionInformation.get("P-205")[4] = ThreadLocalRandom.current().nextInt(2, 8);
- }
- if(transitionInformation.get("P-205")[0] == 1) {
- if(transitionInformation.get("P-205")[4] > 0 && (fit201LastValue <= 0 || ait203LastStatus > 436 && ait203LastStatus < 500)) { // Stop offset countdown
- listP205.add(1);
- transitionInformation.get("P-205")[0] = 0;
- }
- else {
- transitionInformation.get("P-205")[4]--;
- if(transitionInformation.get("P-205")[4] <= 0) { // Finish offset countdown
- transitionInformation.get("P-205")[0] = 0;
- listP205.add(2);
- }
- else {
- listP205.add(listP205.getLast());
- }
- }
- }
- else {
- listP205.add(listP205.getLast());
- }
- }
- }
-
- /**
- * Simulates stage three for one second.
- * @param seconds The current simulation time in seconds.
- */
- private void simulateStage3(int seconds){
- // P-301 and P-302
- int p301302LastStatus = 1;
- int p301LastStatus = listP301.getLast();
- int p302LastStatus = listP302.getLast();
- if(p301LastStatus == 2 || p302LastStatus == 2)
- p301302LastStatus = 2;
-
- listP301.add(1); // Still off or again off
-
- double lit401LastStatus = listLIT401.getLast();
- int[] mv301TransitionInformation = transitionInformation.get("MV-301");
- int[] p302TransitionInformation = transitionInformation.get("P-302");
- int[] mv304TransitionInformation = transitionInformation.get("MV-304");
- int mv301LastStatus = listMV301.getLast();
- double lit301LastStatus = listLIT301.getLast();
-
- int p302New = 0;
- if(p302TransitionInformation[0] == 1) {
- if(p302TransitionInformation[4] > 0) { // Wait for offset to end
- p302TransitionInformation[4]--;
- p302New = p301302LastStatus;
- }
- else {
- if(p302TransitionInformation[2] > 0) {
- p302TransitionInformation[2]--;
- p302New = 1;
- }
- else if(p302TransitionInformation[2] == 0) {
- p302TransitionInformation[0] = 0;
- if(p302TransitionInformation[3] == 2)
- p302New = 2;
- else
- p302New = 1;
- }
- }
- }
- else if(seconds == backwashIntervalList.getFirst()-14) { // Backwash: Transition to off
- int transitionTime = 10 + ThreadLocalRandom.current().nextInt(1, 4);
- p302TransitionInformation[0] = 1;
- p302TransitionInformation[1] = transitionTime;
- p302TransitionInformation[2] = transitionTime;
- p302TransitionInformation[3] = 1;
- p302TransitionInformation[4] = 14 - transitionTime;
- p302New = p301302LastStatus;
- }
- else if(mv301TransitionInformation[0] == 1 && mv301TransitionInformation[3] == 1 && p302TransitionInformation[0] == 0) { // Backwash: Transition to on
- int transitionTime = ThreadLocalRandom.current().nextInt(60, 65);
- p302TransitionInformation[0] = 1;
- p302TransitionInformation[1] = transitionTime;
- p302TransitionInformation[2] = transitionTime;
- p302TransitionInformation[3] = 2;
- p302TransitionInformation[4] = 0;
- p302New = 1;
- }
- else if(p301302LastStatus != 2 && p302TransitionInformation[0] == 0 && mv301LastStatus == 1 && lit401LastStatus < 800 && lit301LastStatus > 250) { // Normal operation only: Turn on
- p302TransitionInformation[0] = 1;
- p302TransitionInformation[1] = 10;
- p302TransitionInformation[2] = 10;
- p302TransitionInformation[3] = 2;
- p302TransitionInformation[4] = 0;
- p302New = 1;
- }
- else if(mv301LastStatus == 1 && (lit401LastStatus >= 1000 || lit301LastStatus < 250)){ // Normal operation only: Turn off
- p302New = 1;
- p302TransitionInformation[0] = 0;
- }
- else {
- p302New = p301302LastStatus;
- }
- listP302.add(p302New);
-
- // LIT-301
- double fit201LastValue = listFIT201.getLast();
- double fit301LastValue = listFIT301.getLast();
- double litstep = 0.0;
- double lit301New = 0.0;
-
- int lit301ExtremeValueInformation = extremeValueInformation.get("LIT-301");
- int[] lit301TransitionInformation = transitionInformation.get("LIT-301");
-
- int p101102LastStatus = 1;
- int p101LastStatus = listP101.getLast();
- int p102LastStatus = listP102.getLast();
- if(p101LastStatus == 2 || p102LastStatus == 2)
- p101102LastStatus = 2;
- int mv201LastStatus = listMV201.getLast();
-
- // Outflow until typical minimum
- if(lit301ExtremeValueInformation == 2 && lit301LastStatus <= 800 && lit301LastStatus >= 787) {
- litstep = -0.156944897959183;
- }
- // Only inflow
- else if(p101102LastStatus == 2 && mv201LastStatus == 2 && p301302LastStatus == 1) {
- litstep = 0.4930476987;
- }
- // Inflow and outflow at the same time
- else if(p101102LastStatus == 2 && mv201LastStatus == 2 && p301302LastStatus == 2 && fit201LastValue > 2.43) {
- litstep = 0.0531137471; // Intial climb to 1000
- if(lit301TransitionInformation[4] <= 0) {
- litstep = 0.04611385; // Second climb from 800 to 1000
- }
- else if(lit301ExtremeValueInformation == 0)
- litstep = 0.0735018503; // First climb from 800 to 1000
-
- }
- // Only outflow
- else if((p101102LastStatus == 1 || mv201LastStatus == 1) && p301302LastStatus == 2) {
- litstep = -0.4181877264;
- }
- else {// Neither inflow nor outflow
- litstep = 0;
- }
- listLIT301WithoutJittering.add(BigDecimal.valueOf(listLIT301WithoutJittering.getLast()).add(BigDecimal.valueOf(litstep)).doubleValue());
- lit301New = BigDecimal.valueOf(listLIT301WithoutJittering.getLast()).add(BigDecimal.valueOf(litstep)).doubleValue();
- if(lit301New < 0) lit301New = 0;// Tank cannot be less full than empty
- listLIT301.add(lit301New);
- if(lit301ExtremeValueInformation == -1 && lit301New >= 1000) extremeValueInformation.put("LIT-301", 1);
- else if(lit301ExtremeValueInformation == 1 && lit301New <= 800) extremeValueInformation.put("LIT-301", 0);
- else if(lit301ExtremeValueInformation == 0 && lit301New >= 1000) extremeValueInformation.put("LIT-301", 2);
- else if(lit301ExtremeValueInformation == 2 && lit301New <= 788) extremeValueInformation.put("LIT-301", 3);
- else if(lit301ExtremeValueInformation == 3 && lit301New >= 1000) extremeValueInformation.put("LIT-301", 2);
- if(lit301LastStatus < 1000 && lit301New >= 1000) lit301TransitionInformation[4]--;
-
- // FIT-301
- String fitName = "FIT-301";
- LinkedList<Double> extremeValueListFIT = extremeValues.get(fitName);
- double fit301New = fit301LastValue;
- int mv302LastStatus = listMV302.getLast();
- int mv303LastStatus = listMV303.getLast();
- int mv304LastStatus = listMV304.getLast();
- if(p301302LastStatus == 1) { // Decrease
- double fit301step = distributionHandlers.get(fitName+" Flank Distribution Sharply Decreasing").sampleNextValueExactly();
- fit301New = BigDecimal.valueOf(fit301LastValue).subtract(BigDecimal.valueOf(fit301step)).doubleValue();
- if(fit301New < 0.0002562214) {
- fit301New = 0.0002562214;
- }
- if(fit301New == 0.0002562214 && ThreadLocalRandom.current().nextInt(1, 100) < 5 &&
- mv301LastStatus == 2 && mv302LastStatus == 1 && mv303LastStatus == 2 && mv304LastStatus == 1) {
- fit301New = fit301New + ThreadLocalRandom.current().nextDouble(0.1, 0.31);
- }
- else if(mv301LastStatus == 1 && mv302LastStatus == 1 && (mv303LastStatus == 2 || mv303LastStatus == 0) && mv304LastStatus == 2) {
- fit301New = 0.37 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- }
- // Add new maximum
- double maximum = ThreadLocalRandom.current().nextDouble(2.3, 2.358);
- if(extremeValueListFIT.size() > 0)
- extremeValueListFIT.set(0, maximum);
- else
- extremeValueListFIT.add(maximum);
- extremeValueInformation.put(fitName, 1);
- }
- else if(p301302LastStatus == 2 && extremeValueInformation.get(fitName) == 1) { // Increase
- if(extremeValueListFIT.size() == 0) { // New maximum
- extremeValueListFIT.add(ThreadLocalRandom.current().nextDouble(2.3, 2.351));
- }
-
- double fit301step = distributionHandlers.get(fitName+" Flank Distribution Sharply Increasing").sampleNextValueExactly();
- fit301New = BigDecimal.valueOf(fit301LastValue).add(BigDecimal.valueOf(fit301step)).doubleValue();
- double extremeValue = extremeValueListFIT.getFirst();
- if(fit301New >= extremeValue) {
- fit301New = extremeValue;
- // Small Minimum afterwards
- extremeValueListFIT.set(0, 2.21 + ThreadLocalRandom.current().nextGaussian()*0.0015);
- extremeValueInformation.put(fitName, 0);
- }
- }
- else if(p301302LastStatus == 2 && extremeValueInformation.get(fitName) == 0) { // Small decrease after maximum
- double fit301step = distributionHandlers.get(fitName+" Flank Distribution Sharply Decreasing").sampleNextValueExactly();
- fit301New = BigDecimal.valueOf(fit301LastValue).subtract(BigDecimal.valueOf(fit301step)).doubleValue();
- double extremeValue = extremeValueListFIT.getFirst();
- if(fit301New < extremeValue) {
- fit301New = extremeValue;
- extremeValueInformation.put(fitName, -1);
- }
- }
- else if(extremeValueInformation.get(fitName) == -1) { // Jitter slightly below maximum
- fit301New = 2.21 + ThreadLocalRandom.current().nextGaussian()*0.0015;
- }
- listFIT301.add(fit301New);
- // MV-303
- // Must be before MV-301 in the code
- String mv303Name = "MV-303";
- LinkedList<Integer> mv303List = listMV303;
- int[] mv303TransitionInformation = transitionInformation.get("MV-303");
-
- if(mv303TransitionInformation[0] == 1) {
- if(mv303TransitionInformation[4] > 0) {
- mv303TransitionInformation[4]--;
- mv303List.add(mv303LastStatus);
- }
- else {
- int remainingTransistionTime = mv303TransitionInformation[2];
- if(remainingTransistionTime == 0) { // Stop
- mv303TransitionInformation[0] = 0;
- if(mv303TransitionInformation[3] == 2)
- mv303List.add(2);
- else
- mv303List.add(1);
- }
- else { // Continue
- mv303TransitionInformation[2] = remainingTransistionTime-1;
- mv303List.add(0);
- }
- }
- }
- else if(mv303LastStatus == 1) {
- // Take interval times from the training set
- if(seconds == backwashIntervalList.getFirst()) {
- // Start new transition to opened
- int transitionTime = (int) distributionHandlers.get(mv303Name+" Transition Distribution 1 to 2").sampleNextValueExactly();
- mv303TransitionInformation[0] = 1;
- mv303TransitionInformation[1] = transitionTime;
- mv303TransitionInformation[2] = transitionTime-1;
- mv303TransitionInformation[3] = 2;
- mv303TransitionInformation[4] = 0;
- mv303List.add(0);
- }
- else
- mv303List.add(1);
- }
- else if(mv303LastStatus == 2 && mv301TransitionInformation[0] == 1 && mv301TransitionInformation[3] == 1) { // Backwash: Transition to on
- int transitionTime = (int) distributionHandlers.get(mv303Name+" Transition Distribution 2 to 1").sampleNextValueExactly();
- mv303TransitionInformation[0] = 1;
- mv303TransitionInformation[1] = transitionTime;
- mv303TransitionInformation[2] = transitionTime;
- mv303TransitionInformation[3] = 1;
- mv303TransitionInformation[4] = ThreadLocalRandom.current().nextInt(60, 65);
- mv303List.add(2);
- }
- else {
- mv303List.add(mv303LastStatus);
- }
-
-
- // MV-301
- LinkedList<Integer> mv301List = listMV301;
- String mv301Name = "MV-301";
-
- if(mv301LastStatus == 1 && mv301TransitionInformation[0] == 0) {
- // Take interval times from the training set
- if(seconds == backwashIntervalList.getFirst()) {
- backwashIntervalList.pop();
- // Generate new time if all fixed times are used
- // Use an interval of 70 + (1 to 3) minutes
- if(backwashIntervalList.size() == 0) {
- backwashIntervalList.add(seconds + (70 + ThreadLocalRandom.current().nextInt(1, 4)) * 60);
- }
- // Start new transition to opened
- int transitionTime = (int) distributionHandlers.get(mv301Name+" Transition Distribution 1 to 2").sampleNextValueExactly();
- mv301TransitionInformation[0] = 1;
- mv301TransitionInformation[1] = transitionTime;
- mv301TransitionInformation[2] = transitionTime-1;
- mv301TransitionInformation[3] = 2;
- mv301TransitionInformation[4] = ThreadLocalRandom.current().nextInt(30, 34);
- mv301List.add(0);
- }
- else
- mv301List.add(1);
- }
- else if(mv301LastStatus == 0) {
- int remainingTransistionTime = mv301TransitionInformation[2];
- if(remainingTransistionTime == 0) { // Stop
- mv301TransitionInformation[0] = 0;
- mv301List.add(mv301TransitionInformation[3]);
- mv301TransitionInformation[4]--;
- }
- else { // Continue
- mv301TransitionInformation[2] = remainingTransistionTime-1;
- mv301List.add(0);
- }
- }
- else if(mv301TransitionInformation[4] >= 0){
- if(mv301TransitionInformation[4] == 0) {
- // Start new transition to closed
- int transitionTime = (int) distributionHandlers.get(mv301Name+" Transition Distribution 2 to 1").sampleNextValueExactly();
- mv301TransitionInformation[0] = 1;
- mv301TransitionInformation[1] = transitionTime;
- mv301TransitionInformation[2] = transitionTime-1;
- mv301TransitionInformation[3] = 1;
- mv301List.add(0);
- }
- else {
- mv301List.add(2);
- }
- mv301TransitionInformation[4]--;
- }
- else {
- mv301List.add(1);
- }
-
-
- // MV-302
- String mv302Name = "MV-302";
- LinkedList<Integer> mv302List = listMV302;
- int[] mv302TransitionInformation = transitionInformation.get(mv302Name);
-
- if(mv302TransitionInformation[0] == 1 && mv302TransitionInformation[4] > 1) { // Wait for offset to end
- mv302TransitionInformation[4]--;
- mv302List.add(mv302List.getLast());
- }
- else if(mv302TransitionInformation[0] == 1 && mv302LastStatus != 0 && mv302TransitionInformation[4] == 1) {
- mv302TransitionInformation[4]--;
- mv302List.add(0); // Start transition in next second
- }
- else if(mv302LastStatus == 0) { // Transition
- int remainingTransistionTime = mv302TransitionInformation[2];
- if(remainingTransistionTime == 0) { // Stop
- mv302TransitionInformation[0] = 0;
- mv302List.add(mv302TransitionInformation[3]);
- }
- else { // Continue
- mv302TransitionInformation[2] = remainingTransistionTime-1;
- mv302List.add(0);
- }
- }
- else if(mv302TransitionInformation[0] == 0 && mv302LastStatus == 1 && p301302LastStatus == 2) { // Start offset count down to opening transition
- int transitionTime = (int) distributionHandlers.get(mv302Name+" Transition Distribution 1 to 2").sampleNextValueExactly();
- mv302TransitionInformation[0] = 1;
- mv302TransitionInformation[1] = transitionTime;
- mv302TransitionInformation[2] = transitionTime;
- mv302TransitionInformation[3] = 2;
- mv302TransitionInformation[4] = ThreadLocalRandom.current().nextInt(30, 41)-1;
- mv302List.add(1);
- }
- else if(mv302TransitionInformation[0] == 0 && mv302LastStatus == 2 && p301302LastStatus == 1) { // Start offset count down to closing transition
- int transitionTime = (int) distributionHandlers.get(mv302Name+" Transition Distribution 2 to 1").sampleNextValueExactly();
- mv302TransitionInformation[0] = 1;
- mv302TransitionInformation[1] = transitionTime;
- mv302TransitionInformation[2] = transitionTime;
- mv302TransitionInformation[3] = 1;
- mv302TransitionInformation[4] = 2-1;
- mv302List.add(2);
- }
- else {
- mv302List.add(mv302List.getLast());
- }
-
- // MV-304
- String mv304Name = "MV-304";
- int mv304New = mv304LastStatus;
-
- if(mv304TransitionInformation[0] == 1 && mv304TransitionInformation[4] > 1) { // Wait for offset to end
- mv304TransitionInformation[4]--;
- mv304New = mv304LastStatus;
- }
- else if(mv304TransitionInformation[0] == 1 && mv304LastStatus != 0 && mv304TransitionInformation[4] == 1) {
- if((mv301LastStatus != 1 || backwashIntervalList.getFirst()-seconds < 10)
- && mv304TransitionInformation[3] == 2) {//System.out.println("aa "+seconds);
- mv304TransitionInformation[0] = 0;
- mv304New = mv304LastStatus;
- }
- else {
- mv304TransitionInformation[4]--;
- mv304New = 0; // Start transition in next second
- }
- }
- else if(mv304LastStatus == 0) { // Transition
- int remainingTransistionTime = mv304TransitionInformation[2];
- if(remainingTransistionTime == 0) { // Stop
- mv304TransitionInformation[0] = 0;
- mv304New = mv304TransitionInformation[3];
- }
- else { // Continue
- mv304TransitionInformation[2] = remainingTransistionTime-1;
- mv304New = 0;
- }
- }
- else if(mv304LastStatus != 2 && lit301LastStatus >= 250 && mv301LastStatus == 1 && mv302LastStatus == 1 && (mv303LastStatus == 2 || lit401LastStatus < 800)) { // Start offset count down to opening transition
- int transitionTime = (int) distributionHandlers.get(mv304Name+" Transition Distribution 1 to 2").sampleNextValueExactly();
- mv304TransitionInformation[0] = 1;
- mv304TransitionInformation[1] = transitionTime;
- mv304TransitionInformation[2] = transitionTime;
- mv304TransitionInformation[3] = 2;
- mv304TransitionInformation[4] = ThreadLocalRandom.current().nextInt(1, 4);
- mv304New = 1;
- }
- else if(mv304LastStatus == 2 && listMV302.size() >= 3) {
- int mv302SecondLastStatus = mv302List.get(mv302List.size()-3);
- if(mv302SecondLastStatus == 0 && mv302LastStatus == 2) { // Start offset count down to closing transition
- int transitionTime = (int) distributionHandlers.get(mv304Name+" Transition Distribution 2 to 1").sampleNextValueExactly();
- mv304TransitionInformation[0] = 1;
- mv304TransitionInformation[1] = transitionTime;
- mv304TransitionInformation[2] = transitionTime;
- mv304TransitionInformation[3] = 1;
- mv304TransitionInformation[4] = ThreadLocalRandom.current().nextInt(1, 4);
- mv304New = 2;
- }
- else
- mv304New = mv304LastStatus;
- }
- else {
- mv304New = mv304LastStatus;
- }
- if(mv301LastStatus != 1) {
- if(mv304New == 0) { // Correct too early started transitions
- for(int i = listMV304.size()-1; i >= 0; i--) {
- if(listMV304.get(i) == 0)
- listMV304.set(i, 1);
- else
- break;
- }
- }
- mv304TransitionInformation[0] = 0;
- mv304New = 1;
- }
- listMV304.add(mv304New);
- // DPIT-301
- double dpit301LastValue = listDPIT301.getLast();
- double dpit301Step = 0.0;
- double dpit301New = 0.0;
- if(p301302LastStatus == 2) { // Increase
- if(dpit301LastValue >= 8.5 && dpit301LastValue <= 11.5) {
- dpit301Step = 0.3 + ThreadLocalRandom.current().nextDouble(-0.5, 0.51);}
- else
- if(dpit301LastValue >= 1.5 && dpit301LastValue <= 2.38) {
- dpit301Step = ThreadLocalRandom.current().nextDouble(-0.2, 0.31);
- }
- else
- dpit301Step = 1 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
-
- double maximum = 19.5 + ThreadLocalRandom.current().nextDouble(-0.15, 0.151);
- dpit301New = BigDecimal.valueOf(dpit301LastValue).add(BigDecimal.valueOf(dpit301Step)).doubleValue();
- if(dpit301New > maximum)
- dpit301New = maximum;
- }
- else {
- if(mv301LastStatus == 1 && mv302LastStatus == 1 && mv303LastStatus == 1) { // Plateau if nothing happens
- dpit301Step = 1.8 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- double minimum = 2.4 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- dpit301New = BigDecimal.valueOf(dpit301LastValue).subtract(BigDecimal.valueOf(dpit301Step)).doubleValue();
- if(dpit301New < minimum)
- dpit301New = minimum;
- }
- else if(mv301LastStatus == 0 && mv302LastStatus == 1 && mv303LastStatus == 0 && mv304LastStatus == 1) { // Backwash: small plateau during decrease
- int dpit301ListSize = listDPIT301.size();
- if(dpit301ListSize >= 2) {
- double dpit301SecondLastValue = listDPIT301.get(dpit301ListSize-2);
- if(dpit301LastValue >= dpit301SecondLastValue) { // If already on the plateau for one second, start small increase
- dpit301New = dpit301LastValue + 0.02 + ThreadLocalRandom.current().nextDouble(-0.0051, 0.0051);
- }
- else
- dpit301New = dpit301LastValue;
- }
- else {
- dpit301New = dpit301LastValue;
- }
- }
- else if(mv301LastStatus == 2 && mv302LastStatus == 1 && mv303LastStatus == 2 && mv304LastStatus == 1) { // Backwash: lowest plateau
- dpit301Step = 1.8 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- double minimum = 0.03201229;
- dpit301New = BigDecimal.valueOf(dpit301LastValue).subtract(BigDecimal.valueOf(dpit301Step)).doubleValue();
- if(dpit301New < minimum)
- dpit301New = minimum;
- }
- else {
-
-
- // No backwash
- dpit301Step = 0.9769087778 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- double minimum = 2.4 + ThreadLocalRandom.current().nextDouble(-0.05, 0.051);
- dpit301New = BigDecimal.valueOf(dpit301LastValue).subtract(BigDecimal.valueOf(dpit301Step)).doubleValue();
- if(dpit301New < minimum)
- dpit301New = minimum;
- }
- }
- listDPIT301.add(dpit301New);
- }
-
- /**
- * Simulates stage four for one second.
- * @param seconds The current simulation time in seconds.
- */
- private void simulateStage4(int seconds){
- // LIT-401
- double lit401LastStatus = listLIT401.getLast();
- int lit401ExtremeValueInformation = extremeValueInformation.get("LIT-401");
- int[] lit401TransitionInformation = transitionInformation.get("LIT-401");
- int mv302LastStatus = listMV302.getLast();
- double lit401Step = 0.0;
- if(mv302LastStatus == 2) {
- lit401TransitionInformation[4] = 1;
- if(lit401TransitionInformation[3] == 0) { // Highest slope for initial climb to 250
- lit401Step = 0.391;
- }
- else if(lit401TransitionInformation[0] == 0) { // Higher slope for initial climb to 800
- lit401Step = 0.08335;
- }
- else if(lit401TransitionInformation[1] == 0) { // Higher slope for initial climb to 1000
- lit401Step = 0.066;
- }
- else if(lit401TransitionInformation[2] == 0) { // Lower slope after climb from local minimum until 800
- lit401Step = 0.048;
- }
- else { // Higher slope for the second half of the increase until 1000
- lit401Step = 0.082;
- }
- extremeValueInformation.put("LIT-401", 0);
- }
- else {
- if(lit401ExtremeValueInformation == 0) {
- lit401TransitionInformation[4] = -1;
- lit401Step = -0.32;
- }
- else
- lit401Step = 0;
- }
- double lit401New = lit401LastStatus + lit401Step;
- if(lit401New < 0)
- lit401New = 0;
- listLIT401.add(lit401New);
- if(lit401New >= 250) lit401TransitionInformation[3] = 1;
- if(lit401New >= 800) lit401TransitionInformation[0] = 1;
- if(lit401New <= 800) lit401TransitionInformation[2] = 0;
- else lit401TransitionInformation[2] = 1;
- if(lit401New >= 1000) lit401TransitionInformation[1] = 1;
-
- // P-401 and P-402
- int p401402LastStatus = 1;
- int p401LastStatus = listP401.getLast();
- int p402LastStatus = listP402.getLast();
- if(p401LastStatus == 2 || p402LastStatus == 2)
- p401402LastStatus = 2;
-
- listP401.add(1); // Still off or again off
-
- int[] p402TransitionInformation = transitionInformation.get("P-402");
-
- int p402New = p401402LastStatus;
- if(p402TransitionInformation[0] == 1) {
- if(p402TransitionInformation[4] > 0) { // Wait for offset to end
- p402TransitionInformation[4]--;
- p402New = p401402LastStatus;
- }
- else {
- p402TransitionInformation[0] = 0;
- if(p402TransitionInformation[3] == 2)
- p402New = 2;
- else
- p402New = 1;
- }
- }
- else if(p401402LastStatus == 1 && lit401LastStatus > 250) { // Turn on
- p402TransitionInformation[0] = 1;
- p402TransitionInformation[3] = 2;
- p402TransitionInformation[4] = 3;
- p402New = 1;
- }
- else if(p401402LastStatus == 2 && lit401LastStatus < 250){ // Turn off
- p402New = 2;
- p402TransitionInformation[0] = 0;
- }
- listP402.add(p402New);
-
- // P-403 and P-404
- listP403.add(1);
- listP404.add(1);
-
- // FIT-401
- double fit401LastValue = listFIT401.getLast();
- int[] fit401TransitionInformation = transitionInformation.get("FIT-401");
- double fit401New = fit401LastValue;
- double fit401NewMaximum = 1.7 + ThreadLocalRandom.current().nextDouble(-0.005, 0.0051);
- if(fit401TransitionInformation[0] == 1) {
- if(fit401TransitionInformation[4] > 0) { // Wait for offset to end
- fit401TransitionInformation[4]--;
- }
- else {
- fit401TransitionInformation[0] = -1; // Block decrease until increase
- }
- }
- else if(lit401LastStatus >= 250) {
- if(p401402LastStatus == 1) {// Decrease or initiate offset to decrease
- if(fit401TransitionInformation[0] == 0) { // Decrease only possible after increase
- fit401TransitionInformation[0] = 1;
- fit401TransitionInformation[4] = 2;
- }
- else {
- fit401New = fit401LastValue - (0.100139294117647 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011));
- }
- }
- else { // Increase
- fit401New = fit401LastValue + 0.013694855932203 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- if(fit401New > fit401NewMaximum)
- fit401New = fit401NewMaximum;
- fit401TransitionInformation[0] = 0;
- }
- }
- if(fit401New < 0)
- fit401New = 0;
- listFIT401.add(fit401New);
-
- // UV-401
- int uv401LastStatus = listUV401.getLast();
- int[] uv401TransitionInformation = transitionInformation.get("UV-401");
- int uv401New = uv401LastStatus;
- if(uv401TransitionInformation[0] == 1) {
- if(uv401TransitionInformation[4] > 0) { // Wait for offset to end
- uv401TransitionInformation[4]--;
- uv401New = uv401LastStatus;
- }
- else {
- uv401TransitionInformation[0] = 0;
- if(uv401TransitionInformation[3] == 2)
- uv401New = 2;
- else
- uv401New = 1;
- }
- }
- else if(uv401LastStatus == 1 && p401402LastStatus == 2) { // Turn on
- uv401TransitionInformation[0] = 1;
- uv401TransitionInformation[3] = 2;
- uv401TransitionInformation[4] = 3;
- uv401New = 1;
- }
- else if(uv401LastStatus == 2 && p401402LastStatus == 1){ // Turn off
- uv401New = 1;
- uv401TransitionInformation[0] = 0;
- }
- listUV401.add(uv401New);
-
- // AIT-401
- // Stays constant as a simplification
- listAIT401.add(listAIT401.getLast());
-
- // AIT-402
- double ait402LastValue = listAIT402.getLast();
- double ait402New = 0.0;
- int[] ait402TransitionInformation = transitionInformation.get("AIT-402");
- if(fit401LastValue <= 1) {
- ait402New = ait402LastValue + ThreadLocalRandom.current().nextDouble(-0.08, 0.091);
- }
- else if(ait402TransitionInformation[0] == 0){ // Increase until ~235
- ait402New = ait402LastValue + 0.063792395833333 + ThreadLocalRandom.current().nextDouble(-0.04, 0.041);
- if(ait402New >= 235)
- ait402TransitionInformation[0] = 1;
- }
- else {
- ait402New = ait402LastValue - ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- if(lit401TransitionInformation[4] == -1)
- ait402New -= ThreadLocalRandom.current().nextDouble(0.001, 0.0011);
- else if(lit401TransitionInformation[4] == 1)
- ait402New += ThreadLocalRandom.current().nextDouble(0.00059, 0.000591);
- }
- if(ait402New < 0)
- ait402New = 0;
- listAIT402.add(ait402New);
- }
-
- /**
- * Simulates stage five for one second.
- * @param seconds The current simulation time in seconds.
- */
- private void simulateStage5(int seconds){
- // P-501 and P-502
- int p401402LastStatus = 1;
- int p401LastStatus = listP401.getLast();
- int p402LastStatus = listP402.getLast();
- if(p401LastStatus == 2 || p402LastStatus == 2)
- p401402LastStatus = 2;
- int uv401LastStatus = listUV401.getLast();
-
- int p501502LastStatus = 1;
- int p501LastStatus = listP501.getLast();
- int p502LastStatus = listP502.getLast();
- if(p501LastStatus == 2 || p502LastStatus == 2)
- p501502LastStatus = 2;
-
- listP502.add(1); // Still off or again off
-
- int[] p501TransitionInformation = transitionInformation.get("P-501");
- int p501New = p501502LastStatus;
- if(p501TransitionInformation[0] == 1) {
- if(p501TransitionInformation[4] > 0) { // Wait for offset to end
- p501TransitionInformation[4]--;
- p501New = p501502LastStatus;
- }
- else {
- p501TransitionInformation[0] = 0;
- if(p501TransitionInformation[3] == 2)
- p501New = 2;
- else
- p501New = 1;
- }
- }
- else if(p501502LastStatus == 1 && p401402LastStatus == 2) { // Turn on
- p501TransitionInformation[0] = 1;
- p501TransitionInformation[3] = 2;
- p501TransitionInformation[4] = 78;
- p501New = 1;
- }
- else if(p501502LastStatus == 2 && (p401402LastStatus == 1 || uv401LastStatus == 1)){ // Turn off
- p501New = 2;
- p501TransitionInformation[0] = 0;
- }
- listP501.add(p501New);
-
- // AIT-501
- String ait501Name = "AIT-501";
- double ait501LastValue = listAIT501.getLast();
- int ait501ExtremeValueInformation = extremeValueInformation.get(ait501Name);
- int[] ait501TransitionInformation = transitionInformation.get(ait501Name);
- double ait501New = ait501LastValue;
-
- if(ait501LastValue >= 8)
- ait501ExtremeValueInformation = 0; // No need to further increase
-
- if(ait501TransitionInformation[0] == 1) {
- if(ait501TransitionInformation[4] > 0) { // Wait for offset to end
- ait501TransitionInformation[4]--;
- }
- else {
- ait501TransitionInformation[0] = -1;
- }
- ait501TransitionInformation[1] = 0;
- ait501New = ait501LastValue - 0.0000224865497076031;
- }
- else if(p401402LastStatus == 2) {
- if(ait501ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(ait501Name, 1);
- if(ait501TransitionInformation[0] == 0) {
- ait501TransitionInformation[0] = 1;
- ait501TransitionInformation[4] = 19;
- }
- else {
- if(ait501New <= 7.5) {
- ait501New = ait501LastValue + 0.000256540785498;
- }
- else if(ait501New >= 7.5 && ait501New < 7.6) {
- ait501New = ait501LastValue + 0.000112060335196;
- }
- else if(ait501New >= 7.6 && ait501New < 7.7) {
- ait501New = ait501LastValue + 0.0000510995429151855;
- }
- else if(ait501New >= 7.7 && ait501New < 7.8) {
- ait501New = ait501LastValue + 0.0000259445320715034;
- }
- else if(ait501New >= 7.8 && ait501New < 7.85) {
- ait501New = ait501LastValue + 0.0000236707706338351;
- }
- else if(ait501New >= 7.85) {
- extremeValueInformation.put(ait501Name, 0);
- }
- }
- ait501TransitionInformation[1] = 0;
- }
- else {
- // Follow a sin curve
- if(ait501TransitionInformation[1] == 0) {
- ait501TransitionInformation[2] = seconds; // Sine start
- ait501TransitionInformation[1] = -1;
- }
- double ait501SinPosition = Math.sin(2*Math.PI/200000*((seconds-ait501TransitionInformation[2]) % 200000));
- ait501New = 7.85+ait501SinPosition/10;
- }
- }
- else { // Decrease
- ait501New = ait501LastValue - 0.0000224865497076031;
- if(ait501New < 0)
- ait501New = 0;
- ait501TransitionInformation[0] = 0;
- }
- if(seconds % ThreadLocalRandom.current().nextInt(10, 20) == 0) // Jitter from time to time
- ait501New = ait501New + ThreadLocalRandom.current().nextDouble(-0.003, 0.0031);
- if(ait501New < 0)
- ait501New = 0;
- listAIT501.add(ait501New);
-
- // AIT-502
- double ait502LastValue = listAIT502.getLast();
- double ait502New = ait502LastValue;
- int[] ait502TransitionInformation = transitionInformation.get("AIT-502");
- int ait502ExtremeValueInformation = extremeValueInformation.get("AIT-502");
- double fit401LastValue = listFIT401.getLast();
- int[] lit401TransitionInformation = transitionInformation.get("LIT-401");
- if(fit401LastValue <= 0.2) {
- ait502New = ait502LastValue + 0.002892280285036 + ThreadLocalRandom.current().nextDouble(-0.01, 0.01);
- }
- else if(ait502TransitionInformation[0] == 0) { // Generate spikes
- if(ait502ExtremeValueInformation == 1) {// Small positive spike
- ait502New = ait502LastValue + 0.095903846153846 + ThreadLocalRandom.current().nextDouble(-0.08, 0.081);
- if(ait502New >= 181.77)
- extremeValueInformation.put("AIT-502", 0);
- }
- else if(ait502ExtremeValueInformation == 0) { // Larger negative spike
- ait502New = ait502LastValue - 0.051939215686275 + ThreadLocalRandom.current().nextDouble(-0.08, 0.081);
- if(ait502New <= 173.8273) {
- extremeValueInformation.put("AIT-502", -1);
- ait502TransitionInformation[0] = -1;
- }
- }
- else
- ait502TransitionInformation[0] = -1;
- }
- else if(ait502TransitionInformation[0] == -1){ // Increase until ~218
- ait502New = ait502LastValue + 0.063792395833333 + ThreadLocalRandom.current().nextDouble(-0.08, 0.081);
- if(ait502New >= 218)
- ait502TransitionInformation[0] = 1;
- ait502ExtremeValueInformation = 0;
- }
- else {
- ait502New = ait502LastValue - ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- if(lit401TransitionInformation[4] == -1)
- ait502New -= ThreadLocalRandom.current().nextDouble(0.001, 0.0011);
- else if(lit401TransitionInformation[4] == 1)
- ait502New += ThreadLocalRandom.current().nextDouble(0.00059, 0.000591);
- ait502ExtremeValueInformation = 0;
- }
- if(ait502New < 0)
- ait502New = 0;
- listAIT502.add(ait502New);
-
- // AIT-503
- String ait503Name = "AIT-503";
- double ait503LastValue = listAIT503.getLast();
- int ait503ExtremeValueInformation = extremeValueInformation.get(ait503Name);
- int[] ait503TransitionInformation = transitionInformation.get(ait503Name);
- double ait503New = ait503LastValue;
- int mv301LastValue = listMV301.getLast();
- int mv301SecondLastValue = -1;
- if(seconds >= 3)
- mv301SecondLastValue = listMV301.get(listMV301.size()-3);
-
- if(mv301SecondLastValue == 0 && mv301LastValue == 2)
- ait503ExtremeValueInformation = 0;
-
- if(ait503TransitionInformation[0] == 1) {
- if(ait503TransitionInformation[4] > 0) { // Wait for offset to end
- ait503TransitionInformation[4]--;
- }
- else {
- ait503TransitionInformation[0] = -1;
- extremeValueInformation.put(ait503Name, 1);
- ait503TransitionInformation[1] = 0;
- }
- }
- else if(ait503ExtremeValueInformation == 1) { // Fast increase of spike for 52 seconds
- if(ait503TransitionInformation[1] == 0)
- ait503TransitionInformation[2] = 52 + ThreadLocalRandom.current().nextInt(-5, 6);
- ait503New = ait503LastValue + 0.184248076923077;
- ait503TransitionInformation[1]++;
- if(ait503TransitionInformation[1] == ait503TransitionInformation[2]) {
- extremeValueInformation.put(ait503Name, 2);
- ait503TransitionInformation[1] = 0;
- }
- }
- else if(ait503ExtremeValueInformation == 2) { // Short fast decrease of spike for 105 seconds
- if(ait503TransitionInformation[1] == 0)
- ait503TransitionInformation[2] = 105 + ThreadLocalRandom.current().nextInt(-10, 11);
- ait503New = ait503LastValue - 0.048827619047619;
- ait503TransitionInformation[1]++;
- if(ait503TransitionInformation[1] == ait503TransitionInformation[2]) {
- extremeValueInformation.put(ait503Name, 3);
- ait503TransitionInformation[1] = 0;
- }
- }
- else if(ait503ExtremeValueInformation == 3) { // First long slow decrease of spike for 1323 seconds
- if(ait503TransitionInformation[1] == 0)
- ait503TransitionInformation[2] = 1323 + ThreadLocalRandom.current().nextInt(-130, 131);
- ait503New = ait503LastValue - 0.003126701966717;
- ait503TransitionInformation[1]++;
- if(ait503TransitionInformation[1] == ait503TransitionInformation[2]) {
- extremeValueInformation.put(ait503Name, 4);
- ait503TransitionInformation[1] = 0;
- }
- }
- else if(ait503ExtremeValueInformation == 4) { // Plateau during decrease of spike for 842 seconds
- if(ait503TransitionInformation[1] == 0)
- ait503TransitionInformation[2] = 842 + ThreadLocalRandom.current().nextInt(-84, 85);
- ait503New = ait503LastValue;
- ait503TransitionInformation[1]++;
- if(ait503TransitionInformation[1] == 842) {
- extremeValueInformation.put(ait503Name, 5);
- ait503TransitionInformation[1] = 0;
- }
- }
- else if(ait503ExtremeValueInformation == 5) { // Second long slow decrease of spike
- ait503New = ait503LastValue - 0.001363149171271;
- }
- else if(mv301SecondLastValue == 0 && mv301LastValue == 2) {
- ait503TransitionInformation[0] = 1;
- ait503TransitionInformation[4] = 220 + ThreadLocalRandom.current().nextInt(-3, 3);
- }
- else
- ait503New = ait503LastValue + 0.0025;
- ait503New = ait503New + ThreadLocalRandom.current().nextDouble(-0.0119999999999999, 0.012);
-
- if(ait503New < 0)
- ait503New = 0;
- listAIT503.add(ait503New);
-
- // AIT-504
- String ait504Name = "AIT-504";
- double ait504LastValue = listAIT504.getLast();
- int ait504ExtremeValueInformation = extremeValueInformation.get(ait504Name);
- int[] ait504TransitionInformation = transitionInformation.get(ait504Name);
- double ait504New = ait504LastValue;
- double p401402SecondLastStatus = -1;
- if(seconds >= 3) {
- p401402SecondLastStatus = 1;
- int p401SecondLastStatus = listP401.get(seconds-3);
- int p402SecondLastStatus = listP402.get(seconds-3);
- if(p401SecondLastStatus == 2 || p402SecondLastStatus == 2)
- p401402SecondLastStatus = 2;
- }
-
- if(ait504TransitionInformation[0] == 1 && ait504TransitionInformation[4] > 0) { // Wait for offset to end
- ait504TransitionInformation[4]--;
- extremeValueInformation.put(ait504Name, 0); // Start with negative spike
- }
- else if(p401402LastStatus == 2) {
- if(p401402SecondLastStatus == 1 && ait504ExtremeValueInformation == -1) { // Start new offset count down
- ait504TransitionInformation[0] = 1;
- ait504TransitionInformation[4] = 4;
- }
- else if(ait504ExtremeValueInformation == 0) { // Negative spike
- ait504New = ait504LastValue - 2.1648 + ThreadLocalRandom.current().nextDouble(-0.1, 0.11);
- if(ait504New < 102)
- extremeValueInformation.put(ait504Name, 1); // Continue with positive spike
- }
- else if(ait504ExtremeValueInformation == 1) { // Positive spike
- ait504New = ait504LastValue + 5.00793846153846 + ThreadLocalRandom.current().nextDouble(-0.1, 0.11);
- if(ait504New >= 227) {
- extremeValueInformation.put(ait504Name, 2); // Second negative spike
- }
- }
- else if(ait504ExtremeValueInformation == 2) { // Second negative spike
- ait504New = ait504LastValue - 2.10118023469388 + ThreadLocalRandom.current().nextDouble(-0.1, 0.11);
- if(ait504New < 12){
- ait504New = ait504LastValue - 0.1 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- }
- if(ait504New < 7.421174){
- extremeValueInformation.put(ait504Name, 3); // Increase until normal level
- }
- }
- else if(ait504ExtremeValueInformation == 3) { // Increase until normal level
- ait504New = ait504LastValue + 0.006898988372093 + ThreadLocalRandom.current().nextDouble(-0.001, 0.0011);
- if(ait504New >= 10){
- extremeValueInformation.put(ait504Name, 4); // Stay constant
- }
- }
- else if(ait504ExtremeValueInformation == 4) { // Increase until normal level
- ait504New = ait504LastValue + 0.001298988372093 + ThreadLocalRandom.current().nextDouble(-0.001, 0.0011);
- if(ait504New >= 12){
- extremeValueInformation.put(ait504Name, 5); // Stay constant
- }
- }
- }
- else if(p401402LastStatus == 2) {
- extremeValueInformation.put(ait504Name, -1);
- }
- if(seconds % ThreadLocalRandom.current().nextInt(30, 50) == 0 && ait504ExtremeValueInformation == 5) { // Jitter from time to time
- ait504New = 12 + ThreadLocalRandom.current().nextDouble(-0.3, 0.31);
- }
- if(ait504New < 0)
- ait504New = 0;
- listAIT504.add(ait504New);
-
-
-
- // FIT-501
- String fit501Name = "FIT-501";
- double fit501LastValue = listFIT501.getLast();
- int fit501ExtremeValueInformation = extremeValueInformation.get(fit501Name);
- int[] fit501TransitionInformation = transitionInformation.get(fit501Name);
- double fit501New = fit501LastValue;
-
- if(fit501TransitionInformation[0] == 1) {
- if(fit501TransitionInformation[4] > 0) { // Wait for offset to end
- fit501TransitionInformation[4]--;
- }
- else {
- fit501TransitionInformation[0] = -1;
- }
- }
- else if(p401402LastStatus == 2 && fit501ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(fit501Name, 1);
- if(fit501TransitionInformation[0] == 0) {
- fit501TransitionInformation[0] = 1;
- fit501TransitionInformation[4] = 3;
- }
- else {
- fit501New = fit501LastValue + 0.028255744740741;
- if(fit501New >= 1.64) {
- fit501New = fit501LastValue + 0.00007;
- }
- if(fit501New >= 1.71) {
- extremeValueInformation.put(fit501Name, 0);
- }
- }
- }
- else if(p401402LastStatus == 1 && fit501ExtremeValueInformation != -1) { // Decrease
- if(fit501TransitionInformation[0] == 0) {
- fit501TransitionInformation[0] = 1;
- fit501TransitionInformation[4] = 2;
- }
- else {
- fit501New = fit501LastValue - 0.106816575833333;
- if(fit501New < 0)
- fit501New = 0;
- fit501TransitionInformation[0] = 0;
- if(fit501LastValue <= 1.7096)
- extremeValueInformation.put(fit501Name, 1);
- }
- }
- else if(fit501ExtremeValueInformation == 0){ // Stay in range
- if(fit501New <= 1.7096 || fit501New >= 1.714)
- fit501New = 1.71;
- }
- if(fit501New != 0.001538067 && seconds % ThreadLocalRandom.current().nextInt(5, 10) == 0) // Jitter from time to time
- fit501New = fit501New + ThreadLocalRandom.current().nextDouble(-0.002, 0.0021);
- if(fit501New < 0.001538067)
- fit501New = 0.001538067;
- listFIT501.add(fit501New);
-
- // FIT-502
- String fit502Name = "FIT-502";
- double fit502LastValue = listFIT502.getLast();
- int fit502ExtremeValueInformation = extremeValueInformation.get(fit502Name);
- int[] fit502TransitionInformation = transitionInformation.get(fit502Name);
- double fit502New = fit502LastValue;
-
- if(fit502TransitionInformation[0] == 1) {
- if(fit502TransitionInformation[4] > 0) { // Wait for offset to end
- fit502TransitionInformation[4]--;
- }
- else {
- fit502TransitionInformation[0] = -1;
- }
- }
- else if(p401402LastStatus == 2 && fit502ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(fit502Name, 1);
- if(fit502TransitionInformation[0] == 0) {
- fit502TransitionInformation[0] = 1;
- fit502TransitionInformation[4] = 1;
- }
- else {
- fit502New = fit502LastValue + 0.028255744740741;
- if(fit502LastValue >= 1.27) {
- extremeValueInformation.put(fit502Name, 0);
- fit502New = 1.27;
- }
- }
- }
- else if(p401402LastStatus == 1 && fit502ExtremeValueInformation != -1) { // Decrease
- if(fit502TransitionInformation[0] == 0) {
- fit502TransitionInformation[0] = 1;
- fit502TransitionInformation[4] = 1;
- }
- else {
- fit502New = fit502LastValue - 0.106816575833333;
- if(fit502New < 0)
- fit502New = 0;
- fit502TransitionInformation[0] = 0;
- if(fit502LastValue <= 1.235)
- extremeValueInformation.put(fit502Name, 1);
- }
- }
- else if(fit502ExtremeValueInformation == 0){ // Stay in range
- if(fit502New <= 1.235 || fit502New >= 1.3)
- fit502New = 1.27;
- }
- if(fit502New != 0.001408992 ) // Jitter
- fit502New = fit502New + ThreadLocalRandom.current().nextDouble(-0.018, 0.0181);
- if(fit502New < 0.001408992)
- fit502New = 0.001408992;
- listFIT502.add(fit502New);
-
- // FIT-503
- String fit503Name = "FIT-503";
- double fit503LastValue = listFIT503.getLast();
- int fit503ExtremeValueInformation = extremeValueInformation.get(fit503Name);
- int[] fit503TransitionInformation = transitionInformation.get(fit503Name);
- double fit503New = fit503LastValue;
-
- if(fit503TransitionInformation[0] == 1) {
- if(fit503TransitionInformation[4] > 0) { // Wait for offset to end
- fit503TransitionInformation[4]--;
- }
- else {
- fit503TransitionInformation[0] = -1;
- }
- }
- else if(p401402LastStatus == 2 && fit503ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(fit503Name, 1);
- if(fit503TransitionInformation[0] == 0) {
- fit503TransitionInformation[0] = 1;
- fit503TransitionInformation[4] = 4;
- }
- else {
- fit503New = fit503LastValue + 0.006381567474138;
- if(fit503LastValue >= 0.75)
- extremeValueInformation.put(fit503Name, 0);
- }
- }
- else if(p401402LastStatus == 1 && fit503ExtremeValueInformation != -1) { // Decrease
- if(fit503TransitionInformation[0] == 0) {
- fit503TransitionInformation[0] = 1;
- fit503TransitionInformation[4] = 2;
- }
- else {
- fit503New = fit503LastValue - 0.056470497769231;
- if(fit503New < 0)
- fit503New = 0;
- fit503TransitionInformation[0] = 0;
- if(fit503LastValue <= 0.743)
- extremeValueInformation.put(fit503Name, 1);
- }
- }
- else if(fit503ExtremeValueInformation == 0){ // Stay in range
- if(fit503LastValue >= 1.45) {
- fit503New = fit503LastValue - 0.001;
- }
- else if(fit503New <= 0.743 || fit503New >= 0.747)
- fit503New = 0.745;
- }
- if(fit503New != 0.001664373 && seconds % ThreadLocalRandom.current().nextInt(5, 11) == 0) // Jitter from time to time
- fit503New = fit503New + ThreadLocalRandom.current().nextDouble(-0.0015, 0.00151);
- if(fit503New < 0.001664373)
- fit503New = 0.001664373;
- listFIT503.add(fit503New);
-
- // FIT-504
- String fit504Name = "FIT-504";
- double fit504LastValue = listFIT504.getLast();
- int fit504ExtremeValueInformation = extremeValueInformation.get(fit504Name);
- int[] fit504TransitionInformation = transitionInformation.get(fit504Name);
- double fit504New = fit504LastValue;
-
- if(fit504TransitionInformation[0] == 1) {
- if(fit504TransitionInformation[4] > 0) { // Wait for offset to end
- fit504TransitionInformation[4]--;
- }
- else {
- fit504TransitionInformation[0] = -1;
- }
- }
- else if(p501502LastStatus == 2 && fit504ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(fit504Name, 1);
- if(fit504TransitionInformation[0] == 0) {
- fit504TransitionInformation[0] = 1;
- fit504TransitionInformation[4] = 20;
- }
- else {
- fit504New = fit504LastValue + 0.005026830540541;
- if(fit504LastValue >= 0.15)
- extremeValueInformation.put(fit504Name, 0);
- }
- }
- else if(p501502LastStatus == 1 && fit504ExtremeValueInformation != -1) { // Decrease
- if(fit504TransitionInformation[0] == 0) {
- fit504TransitionInformation[0] = 1;
- fit504TransitionInformation[4] = 2;
- }
- else {
- fit504New = fit504LastValue - 0.028201818181818;
- if(fit504New < 0)
- fit504New = 0;
- fit504TransitionInformation[0] = 0;
- if(fit504LastValue <= 0.308)
- extremeValueInformation.put(fit504Name, 1);
- }
- }
- else if(fit504ExtremeValueInformation == 0){ // Stay in range
- if(fit504LastValue >= 1.45) {
- fit504New = fit504LastValue - 0.001;
- }
- else if(fit504New <= 0.308 || fit504New >= 0.31)
- fit504New = 0.309;
- }
- if(fit504New != 0 && seconds % ThreadLocalRandom.current().nextInt(5, 11) == 0) // Jitter from time to time
- fit504New = fit504New + ThreadLocalRandom.current().nextDouble(-0.0015, 0.00151);
- if(fit504New < 0)
- fit504New = 0;
- listFIT504.add(fit504New);
-
-
-
- // PIT-501
- String pit501Name = "PIT-501";
- double pit501LastValue = listPIT501.getLast();
- int pit501ExtremeValueInformation = extremeValueInformation.get(pit501Name);
- int[] pit501TransitionInformation = transitionInformation.get(pit501Name);
- double pit501New = pit501LastValue;
-
- if(pit501TransitionInformation[0] == 1) {
- if(pit501TransitionInformation[4] > 0) { // Wait for offset to end
- pit501TransitionInformation[4]--;
- }
- else {
- pit501TransitionInformation[0] = -1;
- }
- }
- else if(p401402LastStatus == 2 && pit501ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(pit501Name, 1);
- if(pit501TransitionInformation[0] == 0) {
- pit501TransitionInformation[0] = 1;
- pit501TransitionInformation[3] = 2;
- pit501TransitionInformation[4] = 0;
- }
- else {
- pit501New = pit501LastValue + 2.00231330708661;
- if(pit501LastValue >= 254)
- extremeValueInformation.put(pit501Name, 0);
- }
- }
- else if(p401402LastStatus == 1 && pit501ExtremeValueInformation != -1) { // Decrease
- pit501New = pit501LastValue - 10.2795569565217;
- if(pit501New < 10)
- pit501New = 10 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- pit501TransitionInformation[0] = 0;
- if(pit501LastValue <= 252)
- extremeValueInformation.put(pit501Name, 1);
- }
- else if(pit501ExtremeValueInformation == 0){ // Stay in range
- if(pit501New <= 252.5 || pit501New >= 253.5)
- pit501New = 253;
- }
- if(seconds % ThreadLocalRandom.current().nextInt(10, 20) == 0) // Jitter from time to time
- pit501New = pit501New + ThreadLocalRandom.current().nextDouble(-0.3, 0.31);
- if(pit501New < 0)
- pit501New = 0;
- listPIT501.add(pit501New);
- // PIT-502
- String pit502Name = "PIT-502";
- double pit502LastValue = listPIT502.getLast();
- int pit502ExtremeValueInformation = extremeValueInformation.get(pit502Name);
- int[] pit502TransitionInformation = transitionInformation.get(pit502Name);
- double pit502New = pit502LastValue;
-
- if(pit502TransitionInformation[0] == 1) {
- if(pit502TransitionInformation[4] > 0) { // Wait for offset to end
- pit502TransitionInformation[4]--;
- }
- else {
- pit502TransitionInformation[0] = -1;
- }
- }
- else if(p401402LastStatus == 2 && pit502ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(pit502Name, 1);
- if(pit502TransitionInformation[0] == 0) {
- pit502TransitionInformation[0] = 1;
- pit502TransitionInformation[3] = 2;
- pit502TransitionInformation[4] = 4;
- }
- else {
- pit502New = pit502LastValue + 0.2979528;
- if(pit502LastValue >= 3)
- extremeValueInformation.put(pit502Name, 0);
- }
- }
- else if(p401402LastStatus == 1 && pit502ExtremeValueInformation != -1) { // Decrease
- pit502New = pit502LastValue - 0.5 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- if(pit502New < 0)
- pit502New = 0;
- pit502TransitionInformation[0] = 0;
- if(pit502LastValue <= 0.95)
- extremeValueInformation.put(pit502Name, 1);
- }
- else if(pit502ExtremeValueInformation == 0){ // Stay in range
- if(pit502LastValue >= 1.45) {
- pit502New = pit502LastValue - 0.0123529 + ThreadLocalRandom.current().nextDouble(-0.001, 0.0011);
- }
- else if(pit502New <= 0.95 || pit502New >= 1.2)
- pit502New = 1.1;
- }
- if(pit502New != 0 && seconds % ThreadLocalRandom.current().nextInt(5, 11) == 0) // Jitter from time to time
- pit502New = pit502New + ThreadLocalRandom.current().nextDouble(-0.09, 0.091);
- if(pit502New < 0)
- pit502New = 0;
- listPIT502.add(pit502New);
-
- // PIT-503
- String pit503Name = "PIT-503";
- double pit503LastValue = listPIT503.getLast();
- int pit503ExtremeValueInformation = extremeValueInformation.get(pit503Name);
- int[] pit503TransitionInformation = transitionInformation.get(pit503Name);
- double pit503New = pit503LastValue;
-
- if(pit503TransitionInformation[0] == 1) {
- if(pit503TransitionInformation[4] > 0) { // Wait for offset to end
- pit503TransitionInformation[4]--;
- }
- else {
- pit503TransitionInformation[0] = -1;
- }
- }
- else if(p401402LastStatus == 2 && pit503ExtremeValueInformation != 0) { // Increase
- extremeValueInformation.put(pit503Name, 1);
- if(pit503TransitionInformation[0] == 0) {
- pit503TransitionInformation[0] = 1;
- pit503TransitionInformation[3] = 2;
- pit503TransitionInformation[4] = 0;
- }
- else {
- pit503New = pit503LastValue + 2.00231330708661;
- if(pit503LastValue >= 193)
- extremeValueInformation.put(pit503Name, 0);
- }
- }
- else if(p401402LastStatus == 1 && pit503ExtremeValueInformation != -1) { // Decrease
- pit503New = pit503LastValue - 10.2795569565217;
- if(pit503New < 4.6)
- pit503New = 4.6 + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- pit503TransitionInformation[0] = 0;
- if(pit503LastValue <= 192)
- extremeValueInformation.put(pit503Name, 1);
- }
- else if(pit503ExtremeValueInformation == 0){ // Stay in range
- if(pit503New <= 192 || pit503New >= 193)
- pit503New = 192.5;
- }
- if(seconds % ThreadLocalRandom.current().nextInt(5, 11) == 0) // Jitter from time to time
- pit503New = pit503New + ThreadLocalRandom.current().nextDouble(-0.3, 0.31);
- if(pit503New < 0)
- pit503New = 0;
- listPIT503.add(pit503New);
- }
-
- /**
- * Simulates stage six for one second.
- * @param seconds The current simulation time in seconds.
- */
- private void simulateStage6(int seconds){
- // P-601
- listP601.add(1);
-
- //P-602
- String p602Name = "P-602";
- int p602LastStatus = listP602.getLast();
- int p602NewStatus = p602LastStatus;
- int[] p602TransitionInformation = transitionInformation.get(p602Name);
- int mv301LastStatus = listMV301.getLast();
-
- if(p602TransitionInformation[0] == 1) {
- if(p602TransitionInformation[4] > 0) { // Wait for offset to end
- p602TransitionInformation[4]--;
- }
- else {
- p602TransitionInformation[0] = -1;
- p602NewStatus = 2;
- }
- }
- else {
- int mv301SecondLastStatus = -1;
- if(seconds > 3)
- mv301SecondLastStatus = listMV301.get(listMV301.size()-3);
-
- if(mv301SecondLastStatus == 0 && mv301LastStatus == 2 ) { // Increase
- p602TransitionInformation[0] = 1;
- p602TransitionInformation[4] = ThreadLocalRandom.current().nextInt(1, 3) - 1; // Offset to turning on
- p602TransitionInformation[2] = ThreadLocalRandom.current().nextInt(29, 31); // Count down to turn off again
- }
- if(mv301SecondLastStatus == 0 && mv301LastStatus == 1 && p602LastStatus == 2) {
- p602NewStatus = 1;
- p602TransitionInformation[0] = -1;
- p602TransitionInformation[2] = -1;
- }
- else {
- if(p602TransitionInformation[2] == 0)
- p602NewStatus = 1;
- p602TransitionInformation[2]--;
- }
- }
- listP602.add(p602NewStatus);
-
- // P-603
- listP603.add(1);
-
- // FIT-601
- String fit601Name = "FIT-601";
- double fit601LastValue = listFIT601.getLast();
- double fit601New = fit601LastValue;
- int fit601ExtremeValueInformation = extremeValueInformation.get(fit601Name);
- int[] mv301TransitionInformation = transitionInformation.get("MV-301");
-
- if(fit601ExtremeValueInformation == -1) {
- if(mv301TransitionInformation[0] == 1 && mv301TransitionInformation[2] == 1 && mv301TransitionInformation[3] == 2) {
- extremeValueInformation.put(fit601Name, 1);
- }
- else {
- fit601New = fit601LastValue - 0.086726684825;
- }
- }
- else if(fit601ExtremeValueInformation == 1) {
- if(p602LastStatus == 1) {
- extremeValueInformation.put(fit601Name, 2);
- }
- if(fit601LastValue <= 1.675) {
- fit601New = fit601LastValue + 0.0867203;
- }
- }
- else if(fit601ExtremeValueInformation == 2) {
- if(p602LastStatus == 2) {
- extremeValueInformation.put(fit601Name, 3);
- fit601New = fit601LastValue - 0.086726684825;
- }
- else if(fit601LastValue <= 1.675) {
- fit601New = fit601LastValue + 0.0867203;
- }
- }
- else if(fit601ExtremeValueInformation == 3) {
- if(p602LastStatus == 1) {
- extremeValueInformation.put(fit601Name, -1);
- fit601New = fit601LastValue - 0.086726684825;
- }
- else if(fit601LastValue <= 1.675) {
- fit601New = fit601LastValue + 0.0867203;
- }
- }
- fit601New = fit601New + ThreadLocalRandom.current().nextDouble(-0.01, 0.011);
- if(fit601New < 0.0002563035)
- fit601New = 0.0002563035;
- listFIT601.add(fit601New);
- }
-
- /**
- * Simulates a motorized valve.
- * @param mvName The name of the motorized valve.
- * @param mvList The list of the motorized valve
- * @param relatedLITList The list of the LIT related to the of the motorized valve.
- * @param minimumValueRelatedLIT The minimum value for the motorized valve to start its transition to open.
- * @param maximumValueRelatedLIT The maximum value for the motorized valve to start its transition to closed.
- * @param mvOpeningOffset Offset in seconds before transition to open starts after conditions are met.
- * @param mvClosingOffset Offset in seconds before transition to closed starts after conditions are met.
- * @param additionalStartOpeningConditionMet Additional conditions that have to be met before the transition to open can start. True if none.
- * @param additionalStartClosingConditionMet Additional conditions that have to be met before the transition to closed can start. True if none.
- */
- private void simulateMV(String mvName, LinkedList<Integer> mvList, LinkedList<Double> relatedLITList, int minimumValueRelatedLIT, int maximumValueRelatedLIT, int mvOpeningOffset, int mvClosingOffset, boolean additionalStartOpeningConditionMet, boolean additionalStartClosingConditionMet) {
- int mvLastStatus = mvList.getLast();
- int[] mvTransitionInformation = transitionInformation.get(mvName);
- double litLastStatus = relatedLITList.getLast();
-
- if(mvTransitionInformation[0] == 1 && mvTransitionInformation[4] > 1) { // Wait for offset to end
- mvTransitionInformation[4]--;
- mvList.add(mvList.getLast());
- }
- else if(mvTransitionInformation[0] == 1 && mvLastStatus != 0 && mvTransitionInformation[4] == 1) {
- mvTransitionInformation[4]--;
- mvList.add(0); // Start transition in next second
- }
- else if(mvLastStatus == 1) { // Closed
- if(litLastStatus >= minimumValueRelatedLIT) // Do nothing
- mvList.add(1);
- else { // Start transition
- if(additionalStartOpeningConditionMet) {
- int transitionTime = (int) distributionHandlers.get(mvName+" Transition Distribution 1 to 2").sampleNextValueExactly();
- mvTransitionInformation[0] = 1;
- mvTransitionInformation[1] = transitionTime;
- mvTransitionInformation[2] = transitionTime-1;
- mvTransitionInformation[3] = 2;
- mvTransitionInformation[4] = mvOpeningOffset-1;
- if(mvTransitionInformation[4] <= 0)
- mvList.add(0);
- else
- mvList.add(1);
- }
- else
- mvList.add(1);
- }
- }
- else if(mvLastStatus == 2) { // Open
- if(litLastStatus <= maximumValueRelatedLIT) // Do nothing
- mvList.add(2);
- else { // Start transition
- if(additionalStartClosingConditionMet) {
- int transitionTime = (int) distributionHandlers.get(mvName+" Transition Distribution 2 to 1").sampleNextValueExactly();
- mvTransitionInformation[0] = 1;
- mvTransitionInformation[1] = transitionTime;
- mvTransitionInformation[2] = transitionTime-1;
- mvTransitionInformation[3] = 1;
- mvTransitionInformation[4] = mvClosingOffset-1;
- if(mvTransitionInformation[4] <= 0)
- mvList.add(0);
- else
- mvList.add(2);
- }
- else
- mvList.add(2);
- }
- }
- else if(mvLastStatus == 0) {
- int remainingTransistionTime = mvTransitionInformation[2];
- if(remainingTransistionTime == 0) { // Stop
- mvTransitionInformation[0] = 0;
- mvList.add(mvTransitionInformation[3]);
- }
- else { // Continue
- mvTransitionInformation[2] = remainingTransistionTime-1;
- mvList.add(0);
- }
- }
- }
-
- /**
- * Sets the status.
- * @param startStatus The line of physical data to set the status from or "" for the standard status.
- */
- private void setUpStatus(String startStatus) {
- if(startStatus.equals("")) setUpStandardStatus();
- else setUpCustomStatus(startStatus);
- }
-
- /**
- * Sets up the variables for the standard statuses.
- */
- private void setUpStandardStatus() {
- listTimestamp.add(getCurrentTimeString());
- listFIT101.add(0.0);
- listLIT101.add(0.0);
- listLIT101WithoutJittering.add(0.0);
- listMV101.add(1);
- listP101.add(1);
- listP102.add(1);
-
- listAIT201.add(244.3284);
- listAIT202.add(8.19008);
- listAIT203.add(300.8459);
- listFIT201.add(0.0);
- listMV201.add(1);
- listP201.add(1);
- listP202.add(1);
- listP203.add(1);
- listP204.add(1);
- listP205.add(1);
- listP206.add(1);
- listLIT301.add(0.0);
- listLIT301WithoutJittering.add(0.0);
- listDPIT301.add(2.560983);
- listFIT301.add(0.0);
- listMV301.add(1);
- listMV302.add(1);
- listMV303.add(1);
- listMV304.add(1);
- listP301.add(1);
- listP302.add(1);
-
- listAIT401.add(0.0);
- listAIT402.add(171.3407);
- listFIT401.add(0.0);
- listLIT401.add(0.0);
- listP401.add(1);
- listP402.add(1);
- listP403.add(1);
- listP404.add(1);
- listUV401.add(1);
-
- listAIT501.add(7.430659);
- listAIT502.add(177.1597);
- listAIT503.add(260.7665);
- listAIT504.add(123.3914);
- listFIT501.add(0.001538067);
- listFIT502.add(0.001408992);
- listFIT503.add(0.001664373);
- listFIT504.add(0.0);
- listP501.add(1);
- listP502.add(1);
- listPIT501.add(10.2698);
- listPIT502.add(0.0);
- listPIT503.add(4.6183);
-
- listFIT601.add(0.0002563035);
- listP601.add(1);
- listP602.add(1);
- listP603.add(1);
- }
-
-
- /**
- * Sets up the variables for the custom statuses.
- * @param startStatus The line of physical data to set the status from.
- */
- private void setUpCustomStatus(String startStatus) {
- startStatus = startStatus.trim();
- startStatus = startStatus.replace(",", ".");
- String[] values = startStatus.split("\t");
-
- String timestamp = values[0];
- listTimestamp.add(timestamp);
- setCurrentTimeString(timestamp);
-
- listFIT101.add(Double.parseDouble(values[1]));
- listLIT101.add(Double.parseDouble(values[2]));
- listLIT101WithoutJittering.add(listLIT101.getFirst());
- listMV101.add(Integer.parseInt(values[3]));
- listP101.add(Integer.parseInt(values[4]));
- listP102.add(Integer.parseInt(values[5]));
-
- listAIT201.add(Double.parseDouble(values[6]));
- listAIT202.add(Double.parseDouble(values[7]));
- listAIT203.add(Double.parseDouble(values[8]));
- listFIT201.add(Double.parseDouble(values[9]));
- listMV201.add(Integer.parseInt(values[10]));
- listP201.add(Integer.parseInt(values[11]));
- listP202.add(Integer.parseInt(values[12]));
- listP203.add(Integer.parseInt(values[13]));
- listP204.add(Integer.parseInt(values[14]));
- listP205.add(Integer.parseInt(values[15]));
- listP206.add(Integer.parseInt(values[16]));
-
- listDPIT301.add(Double.parseDouble(values[17]));
- listFIT301.add(Double.parseDouble(values[18]));
- listLIT301.add(Double.parseDouble(values[19]));
- listLIT301WithoutJittering.add(listLIT301.getFirst());
- listMV301.add(Integer.parseInt(values[20]));
- listMV302.add(Integer.parseInt(values[21]));
- listMV303.add(Integer.parseInt(values[22]));
- listMV304.add(Integer.parseInt(values[23]));
- listP301.add(Integer.parseInt(values[24]));
- listP302.add(Integer.parseInt(values[25]));
-
- listAIT401.add(Double.parseDouble(values[26]));
- listAIT402.add(Double.parseDouble(values[27]));
- listFIT401.add(Double.parseDouble(values[28]));
- listLIT401.add(Double.parseDouble(values[29]));
- listP401.add(Integer.parseInt(values[30]));
- listP402.add(Integer.parseInt(values[31]));
- listP403.add(Integer.parseInt(values[32]));
- listP404.add(Integer.parseInt(values[33]));
- listUV401.add(Integer.parseInt(values[34]));
-
- listAIT501.add(Double.parseDouble(values[35]));
- listAIT502.add(Double.parseDouble(values[36]));
- listAIT503.add(Double.parseDouble(values[37]));
- listAIT504.add(Double.parseDouble(values[38]));
- listFIT501.add(Double.parseDouble(values[39]));
- listFIT502.add(Double.parseDouble(values[40]));
- listFIT503.add(Double.parseDouble(values[41]));
- listFIT504.add(Double.parseDouble(values[42]));
- listP501.add(Integer.parseInt(values[43]));
- listP502.add(Integer.parseInt(values[44]));
- listPIT501.add(Double.parseDouble(values[45]));
- listPIT502.add(Double.parseDouble(values[46]));
- listPIT503.add(Double.parseDouble(values[47]));
-
- listFIT601.add(Double.parseDouble(values[48]));
- listP601.add(Integer.parseInt(values[49]));
- listP602.add(Integer.parseInt(values[50]));
- listP603.add(Integer.parseInt(values[51]));
- }
-
- /**
- * The current time as a string in the format of the physical data.
- * @return The time string.
- */
- private String getCurrentTimeString() {
- return new SimpleDateFormat("dd/MM/yyyy h:mm:ss a").format(currentTime.getTime());
- }
-
- /**
- * Sets the current time from a string in the format of the physical data.
- * @param timeString The time string.
- */
- private void setCurrentTimeString(String timeString) {
- try {
- Date date = new SimpleDateFormat("dd/MM/yyyy h:mm:ss a").parse(timeString);
- currentTime.setTime(date);
- } catch (ParseException e) {
- System.out.println("Could not set current time.");
- }
- }
-
- /**
- * Increases the run time by one second.
- */
- private void increaseTimeByOneSecond() {
- currentTime.set(Calendar.SECOND, currentTime.get(Calendar.SECOND)+1);
- }
-
- /**
- * Sets the distribution handlers.
- */
- private void setDatasetDistributionHandlers() {
- distributionHandlers.put("FIT-101 Flank Distribution Decreasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-101 Flank Distribution Decreasing.txt"));
- distributionHandlers.put("FIT-101 Flank Distribution Increasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-101 Flank Distribution Increasing.txt"));
- distributionHandlers.put("FIT-101 Flank Distribution Sharply Decreasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-101 Flank Distribution Sharply Decreasing.txt"));
- distributionHandlers.put("FIT-101 Flank Distribution Sharply Increasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-101 Flank Distribution Sharply Increasing.txt"));
- distributionHandlers.put("FIT-101 Maxima Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-101 Maxima Distribution.txt"));
- distributionHandlers.put("FIT-101 Minima Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-101 Minima Distribution.txt"));
- distributionHandlers.put("MV-101 Transition Distribution 1 to 2", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-101 Transition Distribution 1 to 2.txt"));
- distributionHandlers.put("MV-101 Transition Distribution 2 to 1", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-101 Transition Distribution 2 to 1.txt"));
- distributionHandlers.put("LIT-101 Ventil Closed Pumps Off Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Ventil Closed Pumps Off Distribution.txt"));
- // distributionHandlers.put("LIT-101 Ventil Closed Pumps On Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Ventil Closed Pumps On Distribution.txt"));
- // distributionHandlers.put("LIT-101 Ventil Open Pumps Off Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Ventil Open Pumps Off Distribution.txt"));
- // distributionHandlers.put("LIT-101 Ventil Open Pumps On Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Ventil Open Pumps On Distribution.txt"));
- // distributionHandlers.put("LIT-101 Random Jitter", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Random Jitter.txt"));
- distributionHandlers.put("LIT-101 Flank Distribution Increasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Flank Distribution Increasing.txt"));
- distributionHandlers.put("LIT-101 Flank Distribution Decreasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Flank Distribution Decreasing.txt"));
- distributionHandlers.put("LIT-101 Maxima Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Maxima Distribution.txt"));
- distributionHandlers.put("LIT-101 Minima Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Minima Distribution.txt"));
- distributionHandlers.put("LIT-101 Jitter", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Jitter.txt"));
- distributionHandlers.put("LIT-101 Seconds Between Zeros Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Seconds Between Zeros Distribution.txt"));
- distributionHandlers.put("LIT-101 Jitter Negative", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Jitter Negative.txt"));
- distributionHandlers.put("LIT-101 Jitter Positive", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_LIT-101 Jitter Positive.txt"));
- distributionHandlers.put("MV-201 Transition Distribution 1 to 2", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-201 Transition Distribution 1 to 2.txt"));
- distributionHandlers.put("MV-201 Transition Distribution 2 to 1", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-201 Transition Distribution 2 to 1.txt"));
- distributionHandlers.put("AIT-201 Distribution of Durations of Unchanged Values", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_AIT-201 Distribution of Durations of Unchanged Values.txt"));
- distributionHandlers.put("AIT-201 Value Change Slopes Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_AIT-201 Value Change Slopes Distribution.txt"));
- distributionHandlers.put("AIT-202 Distribution of Durations of Unchanged Values", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_AIT-202 Distribution of Durations of Unchanged Values.txt"));
- distributionHandlers.put("AIT-202 Value Change Slopes Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_AIT-202 Value Change Slopes Distribution.txt"));
- distributionHandlers.put("AIT-203 Distribution of Durations of Unchanged Values", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_AIT-203 Distribution of Durations of Unchanged Values.txt"));
- distributionHandlers.put("AIT-203 Value Change Slopes Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_AIT-203 Value Change Slopes Distribution.txt"));
- distributionHandlers.put("FIT-201 Flank Distribution Decreasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-201 Flank Distribution Decreasing.txt"));
- distributionHandlers.put("FIT-201 Flank Distribution Increasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-201 Flank Distribution Increasing.txt"));
- distributionHandlers.put("FIT-201 Flank Distribution Sharply Decreasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-201 Flank Distribution Sharply Decreasing.txt"));
- distributionHandlers.put("FIT-201 Flank Distribution Sharply Increasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-201 Flank Distribution Sharply Increasing.txt"));
- distributionHandlers.put("FIT-201 Maxima Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-201 Maxima Distribution.txt"));
- distributionHandlers.put("FIT-201 Minima Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-201 Minima Distribution.txt"));
- distributionHandlers.put("FIT-201 Flank Plateaus Distribution", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-201 Flank Plateaus Distribution.txt"));
- distributionHandlers.put("MV-301 Transition Distribution 1 to 2", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-301 Transition Distribution 1 to 2.txt"));
- distributionHandlers.put("MV-301 Transition Distribution 2 to 1", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-301 Transition Distribution 2 to 1.txt"));
- distributionHandlers.put("MV-302 Transition Distribution 1 to 2", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-302 Transition Distribution 1 to 2.txt"));
- distributionHandlers.put("MV-302 Transition Distribution 2 to 1", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-302 Transition Distribution 2 to 1.txt"));
- distributionHandlers.put("MV-303 Transition Distribution 1 to 2", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-303 Transition Distribution 1 to 2.txt"));
- distributionHandlers.put("MV-303 Transition Distribution 2 to 1", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-303 Transition Distribution 2 to 1.txt"));
- distributionHandlers.put("MV-304 Transition Distribution 1 to 2", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-304 Transition Distribution 1 to 2.txt"));
- distributionHandlers.put("MV-304 Transition Distribution 2 to 1", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_MV-304 Transition Distribution 2 to 1.txt"));
- distributionHandlers.put("FIT-301 Flank Distribution Sharply Increasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-301 Flank Distribution Sharply Increasing.txt"));
- distributionHandlers.put("FIT-301 Flank Distribution Sharply Decreasing", SWaTUtilities.readDatasetDistributionData("PhysicalDataA1_FIT-301 Flank Distribution Sharply Decreasing.txt"));
-
-
- // distributionHandlers.put("", SWaTUtilities.readDatasetDistributionData(""));
- }
- /**
- * Creates the output as list of lines from the variables.
- */
- private void createOutput() {
- List<String> deviceNames = SWaTUtilities.getSortedDeviceNames(networkController);
- outputList = new LinkedList<String>();
- outputColumnDescription = "";
- outputColumnDescription += " Timestamp";
- if(deviceNames.contains("PLC 1"))
- outputColumnDescription += ",FIT101,LIT101,MV101,P101,P102";
- if(deviceNames.contains("PLC 2"))
- outputColumnDescription += ",AIT201,AIT202,AIT203,FIT201,MV201,P201,P202,P203,P204,P205,P206";
- if(deviceNames.contains("PLC 3"))
- outputColumnDescription += ",DPIT301,FIT301,LIT301,MV301,MV302,MV303,MV304,P301,P302";
- if(deviceNames.contains("PLC 4"))
- outputColumnDescription += ",AIT401,AIT402,FIT401,LIT401,P401,P402,P403,P404,UV401";
- if(deviceNames.contains("PLC 5"))
- outputColumnDescription += ",AIT501,AIT502,AIT503,AIT504,FIT501,FIT502,FIT503,FIT504,P501,P502,PIT501,PIT502,PIT503";
- if(deviceNames.contains("PLC 6"))
- outputColumnDescription += ",FIT601,P601,P602,P603";
- outputColumnDescription += ",Normal/Attack";
-
- StringBuilder outputStringBuilder = new StringBuilder(300); // 388+290*durationInSeconds
- for(int i = 0; i < durationInSeconds; i++) {
- outputStringBuilder = new StringBuilder(300);
- outputStringBuilder.append(" "+listTimestamp.pop());
- if(deviceNames.contains("PLC 1")) {
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT101.pop(), 10));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listLIT101.pop(), 4));
- outputStringBuilder.append(","+listMV101.pop());
- outputStringBuilder.append(","+listP101.pop());
- outputStringBuilder.append(","+listP102.pop());
- }
- if(deviceNames.contains("PLC 2")) {
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT201.pop(), 4));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT202.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT203.pop(), 4));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT201.pop(), 6));
- outputStringBuilder.append(","+listMV201.pop());
- outputStringBuilder.append(","+listP201.pop());
- outputStringBuilder.append(","+listP202.pop());
- outputStringBuilder.append(","+listP203.pop());
- outputStringBuilder.append(","+listP204.pop());
- outputStringBuilder.append(","+listP205.pop());
- outputStringBuilder.append(","+listP206.pop());
- }
- if(deviceNames.contains("PLC 3")) {
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listDPIT301.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT301.pop(), 10));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listLIT301.pop(), 4));
- outputStringBuilder.append(","+listMV301.pop());
- outputStringBuilder.append(","+listMV302.pop());
- outputStringBuilder.append(","+listMV303.pop());
- outputStringBuilder.append(","+listMV304.pop());
- outputStringBuilder.append(","+listP301.pop());
- outputStringBuilder.append(","+listP302.pop());
- }
- if(deviceNames.contains("PLC 4")) {
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT401.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT402.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT401.pop(), 10));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listLIT401.pop(), 4));
- outputStringBuilder.append(","+listP401.pop());
- outputStringBuilder.append(","+listP402.pop());
- outputStringBuilder.append(","+listP403.pop());
- outputStringBuilder.append(","+listP404.pop());
- outputStringBuilder.append(","+listUV401.pop());
- }
- if(deviceNames.contains("PLC 5")) {
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT501.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT502.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT503.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listAIT504.pop(), 6));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT501.pop(), 10));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT502.pop(), 10));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT503.pop(), 10));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT504.pop(), 10));
- outputStringBuilder.append(","+listP501.pop());
- outputStringBuilder.append(","+listP502.pop());
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listPIT501.pop(), 4));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listPIT502.pop(), 4));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listPIT503.pop(), 4));
- }
- if(deviceNames.contains("PLC 6")) {
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listFIT601.pop(), 10));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listP601.pop(), 4));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listP602.pop(), 4));
- outputStringBuilder.append(","+formatDoubleRoundMathematically(listP603.pop(), 4));
- }
- outputStringBuilder.append(","+listNormalAttack.pop());
- outputList.add(outputStringBuilder.toString());
- }
- }
-
- /**
- * Saves the CSV output.
- */
- private void saveCSVOutput() {
- String filePathName = outputDirectoryPath+"/IoTDGF_SWaT Simulation";
- String fileNameAddition = "_"+new SimpleDateFormat("yyyy-MM-dd HH.mm.ss").format(startTime.getTime())+"_Physical";
-
- // Write file
- FileWriter outputWriter;
- try {
- double rowsPerFile = 500000;
- double rowsPerFileCurrent = rowsPerFile;
- double numberOfTimes = outputList.size();
- int numberOfFiles = (int) Math.ceil(numberOfTimes/rowsPerFile);
- int rowsInLastFile = (int) (numberOfTimes-rowsPerFile*(numberOfFiles-1));
- int num = 0;
- int numberOfTimesTenth = (int) numberOfTimes/100;
- if(numberOfTimesTenth == 0) numberOfTimesTenth = 1;
- for(int j = 0; j < numberOfFiles; j++) {
- if(passByReferenceValue_KeepSimulationRunning[0] == false) break;
- if(j == numberOfFiles-1) // Last File
- rowsPerFileCurrent = rowsInLastFile;
- StringBuilder outputStringBuilder = new StringBuilder(300*((int) rowsPerFileCurrent));
- outputStringBuilder.append(outputColumnDescription+"\n");
- for(int i = 0; i < rowsPerFileCurrent; i++) {
- if(passByReferenceValue_KeepSimulationRunning[0] == false) break;
- num++;
- outputStringBuilder.append(outputList.pop()); //outputList.get((int)(j*rowsPerFile+i)));
- if(i < rowsPerFileCurrent-1)
- outputStringBuilder.append("\n");
- if(num % numberOfTimesTenth == 0) {
- propertyChangeSupport.firePropertyChange("statusPercentagePhysicalOutput", 0, (int)(num/numberOfTimesTenth));
- }
- }
- if(passByReferenceValue_KeepSimulationRunning[0] == true) {
- String outputFileName = filePathName+fileNameAddition;
- if(numberOfFiles > 1)
- outputFileName += "_"+String.valueOf(j+1)+" of "+numberOfFiles;
-
- // Try file name combinations until one does not yet exist
- File outputFile;
- int fileNameAdditionExtra = 0;
- while(true) {
- String fileNameCandidate = outputFileName;
- if(fileNameAdditionExtra > 0) fileNameCandidate += "_"+fileNameAdditionExtra;
- outputFile = new File(fileNameCandidate+".csv");
-
- if(outputFile.exists())
- fileNameAdditionExtra++;
- else
- break;
- }
- if(fileNameAdditionExtra > 0) outputFileName += "_"+fileNameAdditionExtra;
- outputFileName += ".csv";
- lastOutputFilePath = outputFileName;
- outputWriter = new FileWriter(outputFileName);
- outputWriter.write(outputStringBuilder.toString());
- outputWriter.close();
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- System.out.println("Could not write physical simulation output to file");
- }
-
- }
-
- /**
- * Formats a double as a string by cutting off after the number of given floating point numbers.</br>
- * Trailing zeros are removed.
- * </br>
- * Speed comparison:</br>
- * 20-30 times faster than DecimalFormat.</br></br>
- * double dbl = 123.123456789181112131415;
- * long startTime = System.nanoTime();
- * DecimalFormat decimalFormatMax10 = new DecimalFormat("0.##########", new DecimalFormatSymbols(Locale.ROOT));
- * decimalFormatMax10.format(dbl);
- * long durationDF = System.nanoTime()-startTime;
- * System.out.println("DecimalFormat: "+durationDF);
- * startTime = System.nanoTime();
- * formatDoubleCutOff(dbl, 10);
- * long durationFDCO = System.nanoTime()-startTime;
- * System.out.println("formatDoubleCutOff: "+durationFDCO);
- * System.out.println("formatDoubleCutOff is " + durationDF/durationFDCO + " faster than DecimalFormat");
- *
- * @param doubleToFormat The double to format.
- * @param numberOfFloatingPointNumbers The number of positions after the floating point at which to cut off. Must be >= 0;
- * @return The formatted double as a string.
- */
- @SuppressWarnings("unused")
- private String formatDoubleCutOff(double doubleToFormat, int numberOfFloatingPointNumbers) {
- if(numberOfFloatingPointNumbers < 0)
- return "Error";
-
- String doubleAsString = String.valueOf(doubleToFormat);
- String[] strArray = doubleAsString.split("\\.");
- int floatingPointNumbers = strArray[1].length();
- if(numberOfFloatingPointNumbers > floatingPointNumbers)
- numberOfFloatingPointNumbers = floatingPointNumbers;
- doubleAsString = strArray[0]+"."+strArray[1].substring(0, numberOfFloatingPointNumbers);
- return doubleAsString;
- }
-
- /**
- * Formats a double as a string by rounding mathematically according to the number of given floating point numbers.</br>
- * Trailing zeros are removed.
- * </br>
- * Speed comparison:</br>
- * 150-400 times faster than DecimalFormat.</br></br>
- * double dbl = 123.123456789181112131415;
- * long startTime = System.nanoTime();
- * DecimalFormat decimalFormatMax10 = new DecimalFormat("0.##########", new DecimalFormatSymbols(Locale.ROOT));
- * decimalFormatMax10.format(dbl);
- * long durationDF = System.nanoTime()-startTime;
- * System.out.println("DecimalFormat: "+durationDF);
- * startTime = System.nanoTime();
- * formatDoubleRoundMathematically(dbl, 10);
- * long durationFDRM = System.nanoTime()-startTime;
- * System.out.println("formatDoubleRoundMathematically: "+durationFDRM);
- * System.out.println("formatDoubleRoundMathematically is " + durationDF/durationFDRM + " faster than DecimalFormat");
- * @param doubleToFormat The double to format.
- * @param numberOfFloatingPointNumbers The number of positions after the floating point at which to cut off. Must be >= 0;
- * @return The formatted double as a string.
- */
- private String formatDoubleRoundMathematically(double doubleToFormat, int numberOfFloatingPointNumbers) {
- if(numberOfFloatingPointNumbers < 0)
- return "Error";
-
- // Round double mathematically
- double multiplier = 1.0;
- for(int i = 0; i < numberOfFloatingPointNumbers; i++) {
- multiplier *= 10;
- }
- double roundedDouble = Math.round(doubleToFormat*multiplier)/multiplier;
- long doubleRoundedToLong = Math.round(roundedDouble);
- if(doubleRoundedToLong == roundedDouble) // Remove trailing zero after decimal point, e.g., 124.0 becomes 124
- return String.valueOf(doubleRoundedToLong);
- else
- return String.valueOf(roundedDouble);
- }
-
- /**
- * Sets the interval times for the backwash from the training set.
- */
- private void setUpBackwashIntervalList(){
- int offset = backupIntervalTestOffset;
- backwashIntervalList.add(2980 - offset);
- backwashIntervalList.add(4901 - offset);
- backwashIntervalList.add(6821 - offset);
- backwashIntervalList.add(8742 - offset);
- backwashIntervalList.add(10661 - offset);
- backwashIntervalList.add(12582 - offset);
- backwashIntervalList.add(14501 - offset);
- backwashIntervalList.add(16421 - offset);
- backwashIntervalList.add(19902 - offset);
- backwashIntervalList.add(24103 - offset);
- backwashIntervalList.add(28302 - offset);
- backwashIntervalList.add(32503 - offset);
- backwashIntervalList.add(34423 - offset);
- backwashIntervalList.add(37843 - offset);
- backwashIntervalList.add(42044 - offset);
- backwashIntervalList.add(46244 - offset);
- backwashIntervalList.add(50445 - offset);
- backwashIntervalList.add(54645 - offset);
- backwashIntervalList.add(58726 - offset);
- backwashIntervalList.add(62865 - offset);
- backwashIntervalList.add(67067 - offset);
- backwashIntervalList.add(68986 - offset);
- backwashIntervalList.add(73007 - offset);
- backwashIntervalList.add(77147 - offset);
- backwashIntervalList.add(81408 - offset);
- backwashIntervalList.add(85728 - offset);
- backwashIntervalList.add(89928 - offset);
- backwashIntervalList.add(94129 - offset);
- backwashIntervalList.add(98329 - offset);
- backwashIntervalList.add(102529 - offset);
- backwashIntervalList.add(106730 - offset);
- backwashIntervalList.add(110930 - offset);
- backwashIntervalList.add(115131 - offset);
- backwashIntervalList.add(119271 - offset);
- backwashIntervalList.add(123411 - offset);
- backwashIntervalList.add(127551 - offset);
- backwashIntervalList.add(131692 - offset);
- backwashIntervalList.add(135832 - offset);
- backwashIntervalList.add(139972 - offset);
- backwashIntervalList.add(144112 - offset);
- backwashIntervalList.add(148194 - offset);
- backwashIntervalList.add(152333 - offset);
- backwashIntervalList.add(156475 - offset);
- backwashIntervalList.add(160615 - offset);
- backwashIntervalList.add(164754 - offset);
- backwashIntervalList.add(168835 - offset);
- backwashIntervalList.add(172855 - offset);
- backwashIntervalList.add(176875 - offset);
- backwashIntervalList.add(181016 - offset);
- backwashIntervalList.add(185156 - offset);
- backwashIntervalList.add(189296 - offset);
- backwashIntervalList.add(193437 - offset);
- backwashIntervalList.add(197638 - offset);
- backwashIntervalList.add(201778 - offset);
- backwashIntervalList.add(205918 - offset);
- backwashIntervalList.add(209999 - offset);
- backwashIntervalList.add(214139 - offset);
- backwashIntervalList.add(218339 - offset);
- backwashIntervalList.add(222480 - offset);
- backwashIntervalList.add(226620 - offset);
- backwashIntervalList.add(230760 - offset);
- backwashIntervalList.add(234840 - offset);
- backwashIntervalList.add(238982 - offset);
- backwashIntervalList.add(243121 - offset);
- backwashIntervalList.add(247262 - offset);
- backwashIntervalList.add(251462 - offset);
- backwashIntervalList.add(255723 - offset);
- backwashIntervalList.add(260043 - offset);
- backwashIntervalList.add(264364 - offset);
- backwashIntervalList.add(268684 - offset);
- backwashIntervalList.add(272944 - offset);
- backwashIntervalList.add(277205 - offset);
- backwashIntervalList.add(281524 - offset);
- backwashIntervalList.add(285726 - offset);
- backwashIntervalList.add(289925 - offset);
- backwashIntervalList.add(294125 - offset);
- backwashIntervalList.add(298386 - offset);
- backwashIntervalList.add(302586 - offset);
- backwashIntervalList.add(306788 - offset);
- backwashIntervalList.add(310987 - offset);
- backwashIntervalList.add(315188 - offset);
- backwashIntervalList.add(319388 - offset);
- backwashIntervalList.add(323648 - offset);
- backwashIntervalList.add(327849 - offset);
- backwashIntervalList.add(332109 - offset);
- backwashIntervalList.add(336430 - offset);
- backwashIntervalList.add(338350 - offset);
- backwashIntervalList.add(341650 - offset);
- backwashIntervalList.add(346030 - offset);
- backwashIntervalList.add(347950 - offset);
- backwashIntervalList.add(351310 - offset);
- backwashIntervalList.add(353231 - offset);
- backwashIntervalList.add(356591 - offset);
- backwashIntervalList.add(358512 - offset);
- backwashIntervalList.add(361811 - offset);
- backwashIntervalList.add(363732 - offset);
- backwashIntervalList.add(367033 - offset);
- backwashIntervalList.add(371292 - offset);
- backwashIntervalList.add(375613 - offset);
- backwashIntervalList.add(379933 - offset);
- backwashIntervalList.add(384253 - offset);
- backwashIntervalList.add(388574 - offset);
- backwashIntervalList.add(392834 - offset);
- backwashIntervalList.add(397095 - offset);
- backwashIntervalList.add(401415 - offset);
- backwashIntervalList.add(405675 - offset);
- backwashIntervalList.add(409936 - offset);
- backwashIntervalList.add(414196 - offset);
- backwashIntervalList.add(418456 - offset);
- backwashIntervalList.add(422777 - offset);
- backwashIntervalList.add(427158 - offset);
- backwashIntervalList.add(431538 - offset);
- backwashIntervalList.add(433458 - offset);
- backwashIntervalList.add(436758 - offset);
- backwashIntervalList.add(438678 - offset);
- backwashIntervalList.add(441978 - offset);
- backwashIntervalList.add(446359 - offset);
- backwashIntervalList.add(450680 - offset);
- backwashIntervalList.add(455000 - offset);
- backwashIntervalList.add(459320 - offset);
- backwashIntervalList.add(463641 - offset);
- backwashIntervalList.add(468021 - offset);
- backwashIntervalList.add(472341 - offset);
- backwashIntervalList.add(476722 - offset);
- backwashIntervalList.add(480983 - offset);
- backwashIntervalList.add(485303 - offset);
- backwashIntervalList.add(489564 - offset);
- backwashIntervalList.add(493824 - offset);
- }
-
- /**
- * Returns the results of the simulation as a HashMap with the time in seconds as key and a String array of double representations as value.</br>
- * Empty, if simulation has not been started before.</br>
- * Does only return the elements necessary for the physical simulation.</br>
- * String[]: [0] = LIT-101, [1] = AIT-201, [2] = FIT-201, [3] = LIT-301, [4] = LIT-401, [5] = 0 for normal, 1 for attack
- * @return The results of the simulation as a HashMap with the time in seconds as key and a double array as value
- */
- public LinkedHashMap<Integer, String[]> getSimulationResults(){
- return resultsMap;
- }
-
- /**
- * The main methods creates plots to compare the generated data with the original data from the training set.</br>
- * The path to the needed files has to be set correctly.
- * @see #generatePythonPlotScript(int, String)
- * @param args Not used.
- */
- public static void main(String[] args){
- String pathToCSVDirectory = "C:/Users/user/master"; // Set the path correctly.
-
- Model testmodel = new Model();
- Controller testController = new Controller(testmodel);
- NetworkController testNetworkController = testController.getNetworkController();
- Link ethernetLink = new PrecisionLink("Ethernet");
- Connection SWaTConnection = new ConnectionPrecision();
-
- testNetworkController.addLink(ethernetLink);
- SWaTConnection.setName("SWaT");
- testNetworkController.addConnectionToLink(SWaTConnection, ethernetLink);
- SWaTSimplifiedModbusProtocol SWaTProtocol = new SWaTSimplifiedModbusProtocol();
- SWaTConnection.setProtocol(SWaTProtocol);
- testNetworkController.addConnection(SWaTConnection);
- SmartDevice PLC1 = new SWaTDevice("PLC 1", SWaTDeviceTypes.PLC, 0.6);
- testNetworkController.addSmartDevice(PLC1);
- testNetworkController.addLinkToDevice(ethernetLink, PLC1);
- Port portPLC1 = new Port(PLC1, (short)1);
- portPLC1.setStatus(Port.SENDING);
- testNetworkController.addDeviceToConnectionAndProtocol(portPLC1, SWaTConnection, SWaTProtocol.roleSenderAndReceiver);
- SmartDevice PLC2 = new SWaTDevice("PLC 2", SWaTDeviceTypes.PLC, 0.6);
- testNetworkController.addSmartDevice(PLC2);
- testNetworkController.addLinkToDevice(ethernetLink, PLC2);
- Port portPLC2 = new Port(PLC2, (short)1);
- portPLC2.setStatus(Port.SENDING);
- testNetworkController.addDeviceToConnectionAndProtocol(portPLC2, SWaTConnection, SWaTProtocol.roleSenderAndReceiver);
-
- SmartDevice PLC3 = new SWaTDevice("PLC 3", SWaTDeviceTypes.PLC, 0.6);
- testNetworkController.addSmartDevice(PLC3);
- testNetworkController.addLinkToDevice(ethernetLink, PLC3);
- Port portPLC3 = new Port(PLC3, (short)1);
- portPLC3.setStatus(Port.SENDING);
- testNetworkController.addDeviceToConnectionAndProtocol(portPLC3, SWaTConnection, SWaTProtocol.roleSenderAndReceiver);
-
- SmartDevice PLC4 = new SWaTDevice("PLC 4", SWaTDeviceTypes.PLC, 0.6);
- testNetworkController.addSmartDevice(PLC4);
- testNetworkController.addLinkToDevice(ethernetLink, PLC4);
- Port portPLC4 = new Port(PLC4, (short)1);
- portPLC3.setStatus(Port.SENDING);
- testNetworkController.addDeviceToConnectionAndProtocol(portPLC4, SWaTConnection, SWaTProtocol.roleSenderAndReceiver);
-
- SmartDevice PLC5 = new SWaTDevice("PLC 5", SWaTDeviceTypes.PLC, 0.6);
- testNetworkController.addSmartDevice(PLC5);
- testNetworkController.addLinkToDevice(ethernetLink, PLC5);
- Port portPLC5 = new Port(PLC5, (short)1);
- portPLC3.setStatus(Port.SENDING);
- testNetworkController.addDeviceToConnectionAndProtocol(portPLC5, SWaTConnection, SWaTProtocol.roleSenderAndReceiver);
-
- SmartDevice PLC6 = new SWaTDevice("PLC 6", SWaTDeviceTypes.PLC, 0.6);
- testNetworkController.addSmartDevice(PLC6);
- testNetworkController.addLinkToDevice(ethernetLink, PLC6);
- Port portPLC6 = new Port(PLC6, (short)1);
- portPLC3.setStatus(Port.SENDING);
- testNetworkController.addDeviceToConnectionAndProtocol(portPLC6, SWaTConnection, SWaTProtocol.roleSenderAndReceiver);
-
- backupIntervalTestOffset = 600;
- boolean[] passByReferenceValue_KeepSimulationRunning = {true};
- SWaTSimulationManagerPhysical testObject = new SWaTSimulationManagerPhysical(testController);
- String startStatus = " 22/12/2015 4:40:00 PM 0 121,4088 1 1 1 251,7944 8,307358 315,7652 0 1 1 1 1 1 1 1 2,560983 0,0002562214 136,1029 1 1 1 1 1 1 0 171,0843 0 132,8121 1 1 1 1 1 7,430659 177,1597 260,7665 123,3914 0,001538067 0,001408992 0,001664373 0 1 1 8,891951 0 3,108177 0,0002563035 1 1 1 Normal";
- startStatus = "25/12/2015 12:00:00 AM 2.649649 742.5052 2 1 1 267.0469 8.416304 324.2758 0 1 1 1 1 1 1 1 2.29208 0 1012.12 1 1 1 1 1 1 148.8032 171.0587 1.701855 841.3997 1 2 1 1 2 7.877019 162.3686 268.617 11.11254 1.710972 1.272064 0.7435906 0.3104122 2 1 255.6716 1.121328 194.3092 6.41E-05 1 1 1 Normal";
- long startTimeInNanoSeconds = System.nanoTime();
- testObject.startSimulation("30000", Calendar.getInstance(), pathToCSVDirectory, startStatus, passByReferenceValue_KeepSimulationRunning, null, new Object[0][0]);
- System.out.println("Physical simulation run time in nano seconds: "+ (System.nanoTime()-startTimeInNanoSeconds));
- System.out.print("Creating plots");
- for(int i = 1; i <= 51; i++) {
- System.out.print(".");
- generatePythonPlotScript(i, pathToCSVDirectory);
- }
- System.out.println("\nFinished");
- }
- /**
- * Creates Python plot scripts for one IoT device. </br>
- * Make sure the needed files exist. </br> </br>
- * SWaT_Dataset_Normal_v1_stripped 10 Min_30k.csv </br>
- * The file consists of data from SWaT_Dataset_Normal_v1.xlsx for 22/12/2015 4:40:00 PM to 23/12/2015 12:59:59 AM </br>
- * The file's first line are the column description. It has 30001 lines in total. </br>
- * Creation of the file: </br>
- * 1) Convert SWaT_Dataset_Normal_v1.xlsx to a CSV file </br>
- * 2) Remove the first row with the stage descriptions </br>
- * 3) Remove all rows after the row with the timestamp 23/12/2015 12:59:59 AM </br>
- * @param column The column of the device data in the CSV files.
- * @param pathToCSVDirectory The path to the directory of the CSV files (without trailing "/").
- */
- private static void generatePythonPlotScript(int column, String pathToCSVDirectory){
- // Hashmap for the column names
- LinkedHashMap<Integer, String> columnNames = new LinkedHashMap<Integer, String>();
- columnNames.put(0,"Timestamp");
- columnNames.put(1,"FIT-101");
- columnNames.put(2,"LIT-101");
- columnNames.put(3,"MV-101");
- columnNames.put(4,"P-101");
- columnNames.put(5,"P-102");
- columnNames.put(6,"AIT-201");
- columnNames.put(7,"AIT-202");
- columnNames.put(8,"AIT-203");
- columnNames.put(9,"FIT-201");
- columnNames.put(10,"MV-201");
- columnNames.put(11,"P-201");
- columnNames.put(12,"P-202");
- columnNames.put(13,"P-203");
- columnNames.put(14,"P-204");
- columnNames.put(15,"P-205");
- columnNames.put(16,"P-206");
- columnNames.put(17,"DPIT-301");
- columnNames.put(18,"FIT-301");
- columnNames.put(19,"LIT-301");
- columnNames.put(20,"MV-301");
- columnNames.put(21,"MV-302");
- columnNames.put(22,"MV-303");
- columnNames.put(23,"MV-304");
- columnNames.put(24,"P-301");
- columnNames.put(25,"P-302");
- columnNames.put(26,"AIT-401");
- columnNames.put(27,"AIT-402");
- columnNames.put(28,"FIT-401");
- columnNames.put(29,"LIT-401");
- columnNames.put(30,"P-401");
- columnNames.put(31,"P-402");
- columnNames.put(32,"P-403");
- columnNames.put(33,"P-404");
- columnNames.put(34,"UV-401");
- columnNames.put(35,"AIT-501");
- columnNames.put(36,"AIT-502");
- columnNames.put(37,"AIT-503");
- columnNames.put(38,"AIT-504");
- columnNames.put(39,"FIT-501");
- columnNames.put(40,"FIT-502");
- columnNames.put(41,"FIT-503");
- columnNames.put(42,"FIT-504");
- columnNames.put(43,"P-501");
- columnNames.put(44,"P-502");
- columnNames.put(45,"PIT-501");
- columnNames.put(46,"PIT-502");
- columnNames.put(47,"PIT-503");
- columnNames.put(48,"FIT-601");
- columnNames.put(49,"P-601");
- columnNames.put(50,"P-602");
- columnNames.put(51,"P-603");
-
- List<String> generatedDataList = new ArrayList<String>();
- List<String> trainingSetDataList = new ArrayList<String>();
-
- // Process files
- try {
- File csvFile = new File(lastOutputFilePath);
- Scanner csvFileReader = new Scanner(csvFile);
- while (csvFileReader.hasNextLine() == true) {
- String csvLine = csvFileReader.nextLine();
- String[] entries = csvLine.split(",");
-
- generatedDataList.add(entries[column]);
- }
- csvFileReader.close();
- File csvFile2 = new File(pathToCSVDirectory+"/"+"SWaT_Dataset_Normal_v1_stripped 10 Min_30k.csv");
- Scanner csvFileReader2 = new Scanner(csvFile2);
- boolean firstLine = true;
- while (csvFileReader2.hasNextLine() == true) {
- String csvLine = csvFileReader2.nextLine();
- String[] entries = csvLine.split(",");
-
- if(firstLine == false)
- trainingSetDataList.add(entries[column]);
- else
- firstLine = false;
- }
- csvFileReader2.close();
-
- FileWriter rFWriter = new FileWriter(pathToCSVDirectory+"/"+"Combo plot_"+column+"_"+columnNames.get(column)+".py");
- generatedDataList.remove(0);
- rFWriter.write("import matplotlib.pyplot as plt\n");
- rFWriter.write("plt.plot("+trainingSetDataList.toString()+", label='original')");
- rFWriter.write("\nplt.plot("+generatedDataList.toString()+", label='generated')");
- rFWriter.write("\nplt.grid()");
- rFWriter.write("\nplt.legend()");
- rFWriter.write("\nplt.title(label=\""+columnNames.get(column)+"\")");
- rFWriter.write("\nplt.show()");
- rFWriter.close();
- } catch (FileNotFoundException e) {
- System.out.println("Input files for the SWaT Physical Simulation test plots not found. Check if the path is set correctly and the files exist.");
- } catch (IOException e) {
- System.out.println("Cannot write SWaT Physical Simulation test plots to files.");
- }
- }
- }
|