From 99f04ac848bfbee4181b2f81a05b28cfe6854f7a Mon Sep 17 00:00:00 2001
From: Aleksandra <aleks.dimitrova.21@gmail.com>
Date: Tue, 6 Jun 2023 17:10:18 +0200
Subject: [PATCH] backend

---
 backend/__pycache__/agent.cpython-311.pyc     | Bin 2465 -> 2874 bytes
 .../__pycache__/environment.cpython-311.pyc   | Bin 6200 -> 10311 bytes
 backend/__pycache__/eventlog.cpython-311.pyc  | Bin 0 -> 7786 bytes
 .../simplesimmodel.cpython-311.pyc            | Bin 31186 -> 28897 bytes
 backend/agent.py                              |  63 +++-
 backend/environment.py                        |  83 ++++-
 backend/eventlog.py                           | 155 +++++++-
 backend/input.py                              |   2 +
 backend/main.py                               |  91 +++++
 backend/simplesimmodel.py                     | 352 ++++++++++--------
 simpy_tutorial/eventlog.py                    |   7 +-
 11 files changed, 562 insertions(+), 191 deletions(-)
 create mode 100644 backend/__pycache__/eventlog.cpython-311.pyc
 create mode 100644 backend/input.py
 create mode 100644 backend/main.py

diff --git a/backend/__pycache__/agent.cpython-311.pyc b/backend/__pycache__/agent.cpython-311.pyc
index 87f701a04a31d900d91fd18b6bc837516be90163..51f4f916a98f67a7704f896ffc5c1d4ef0b81626 100644
GIT binary patch
delta 1690
zcmZ1|yi1I4IWI340|NsCyGDJAHt$5fN^Wij1_ovZ28PdJEE6ZqtLJ1W0f~UrFfcHr
zu%@srV`5-f%>)%-sAcA4sA0-tgYmOiV60m95`Gw)fgy_n#;#$mVNYW!5rXj<7}l_(
znaPpDQOlXaQOlKL&QZ&q!dc6c!dc6k!d1&xB8t#f!?%o)fnhZxOvHs@0%L4*Eq@Ku
z0`AEZnS>|vGD$J=fLYc|B97d(LN!cTyfD>Sd~g=rnYF?-Ld7Rb;4%yhSpqOs3j{$X
zX)~m7rZA#9w}v|#tf)u|IUp7Yfz(gtW#XUwfr(WdZU+NHmM~a30|P@1$7CL6c}5Yi
zN_%Emt`x=^&MGdjL>#k(N);;uLk(w*SPd6SP{PBYhNDJwG9R<V<aNxPj2x5Wm?b7(
zVCJpos1cBaS;0^vVgs^CpjNy_v{rzVp+;!^NkZXJBMfpxtwaq^jYJhM14AuO4R4JY
zn8jPepTbkc#=wxmn+;9`MH)4{DLhpY3=FlrH9R0zJxD`|F5CqSDSS2jDZC&fXEUVm
z*YM9~ND-*vnaz+QSi?J;VJ-)1G%_-PR6`ACs^P7btl>`)g7PJ6cx$C<q-rEVrqxQL
z*dkmbJ)2=J(=thvRKdtFfw8Bxh9j6kQ)F@ii%k7Xkh5Qc;#iaM7HdjLWkG8CteGIN
z)4m8Km-&L3fx+#i2m=GdOHfo*akv&_7U!p=Dpc_(l;kU<!gzdE3c0C?c?u<&xv2`a
z3RV0%5Pnf=d16tDl|troW(I~T;UF+qAv3q2D8DR~Jw+j@QbALE@=g{zALfGm@>@KK
z$t9WjdGW;siOH$AnDPp4u~wxP<rm*#&de*h#afh@m!5iywJ5bXwd9smT25j~Nornv
zeo}F2QCT8bV@ZB|W?so;OIBwwnOm$7W4J(umSvV?rWO}TPoBhTG5IX35f3-Wz3~wD
zP5#H~ZONIRlM-KCl30>@iv{G3TRg=jiA5z)CAYXz^HN}JZm0)xQ}arSWhMu(Nl#8^
zv*B`JU|;|hA;t41uVwSA|G>h+%JG$pK}d8$;Dn-yl2arbygsmSv2uKnU=S9&BBXRh
zNTtF1D+dE7cMrz|tr^)D1huw0U*NE~$YF7X!=l0Q0~-UcK!fWI9{vW`8+?Kd?hgb6
z8$53a2{(9uU}F%GXz;l!EHOjoqOjT(VYLqoMy%!^K|}}p4PmkAmKKvNCt6Rj?&RoT
z?I^q<Abedw?~;JtiqeY$rdI?^J6Lb<i*&Hu5D=ciJ%#^@fN}@x4I!})3=*6IlaH~d
z)+;J4P+iErLU4uY8i@^RS2Qgz%3JPmJrH&x^=eqem9Ur#v2hpTGq1#ET@1^<5|(|@
zFZ-fv_JzFs3k9WD^2#oh*Ivo1yXabX(Wd^Qe0_&wM{1A9gs_V|G9Ne?B;`6hZ-~fs
zxPD+^<rVm#&LAufw)cY>gMe^Pbx-{jex=D%IRxu(a0pK*yT~Ei!3_!tkqJqiJ~Nyy
z@yK1^k-NboKEvoDk8Fqc4Ia@MLY@8{o_Bc!F9;RS2wxC1GwOm+@dcsc4dD>_geQc)
zkX8s`T;wUa!c%gAr{n>*(1fHe+YZ|s(rO((A2=9zgeN3-*>%|6kW}f=@VX(TvY_Uo
zlyQeQ*l^Po+!usQF9?}l<T1O#V|IbZ?B@e+o(7M}H#y|lKqXNT-{gNBvZ|nTu#%z3
wk%57s$ew|L;TMNZZhlH>PO4pzI|Bm)sFW^_o9w{ps+h#c$oqi-I|<eg0ArB5SO5S3

delta 1223
zcmdlbwosUFIWI340|NuYY0=`8RE~*!mE4>R3=GT+3=E%7F;AQ{ufB%Gg&~%`mc53#
zhP_INfuWYUhogoSix_ha8$`Z_DT@_kBnW4*fJhLo<tX6=(GZ-)4xt$sYM5&{(wItk
zV0;FKEDjiZ4eK&hCI*JpOfZ33&J?y<t`zoK?i99Ko)nH+-W1MSz7pZd2N>nqjcfU9
zm=<tN-o>QE6T`&7P%BU?Si`h{d$I_VIzLyfPz_TS+?L4>Od>J0!Zkw02T-i$huO41
z0LDV5Q#eu>m!Y_*h9?`WphybY+Y1CI?_yGyME0-{SQ!HYLk(w*z~nw=3AS318m0xp
zlO>o9m})pDZ(x>?tKq5<tKmioClQ3U$vw=<j39-o>YOzKk}wH|8W9_iv7)sCHA3qT
zp!?FJM!1TLfuUBshPOt%ikE?*mY0*EL>sP~A%(k!e>Ou3PmTC&hPf=u7#SE=Gs0vU
z8746Hn5HlUGidToe#0VTtI2qaHKnAoAT@o~Oc2;<pT5rhVU@_b_x44gSbCYlz`)>E
z#o=0zS)8Aes!+vgrBITYo2p=|peZ)FkJWDSMOH~o*37&TL$h0~MTvRoskc~*Qj1ed
zZV9L5B$kw<=EdhH6{i-JC6;97=S`Mia~6}h#adjDn4EfxD>1nwvn;bDGqt!#d~zY1
z1ruZD<P~hjlV7lTaj}4`DVAVhV3=IUE-|@_-Ga-4fq?;(xQjI>pJDf_f50nsfkpcQ
zi*^U&46hZ6GyP|H&G5RxD}I4R;{uCD2jdK>1%)%^XGqPEy1~LXLHi<$Y=hSWA<-*B
zN>_wb8oZx!aP@FZ(3+8bK~QU}(iV*i9M%^(tgmobH#mM^W8f8NaJ|6;BKQOw+#d)C
zHh6wuV-OK<@VP52F+=8}u$s>mVYLqo@~p-mK|}}p4PmkAmXj<eT2Ha=<mh1SD7+yc
zd|g2Ol7RXO){6pqR|NDrSa0x)bg<kI5T3$4h5w3xatG@TA+Zk({G9TWFLI<NC@3xv
zol~)b?TWnq2Gt#A2VBoOopHMm9C9Hv{z`DdMW4hgK8Y7y5-(aOUPwv3kd}QVCFeqJ
z@s*U4i`FF<jY==dmv%UIr1p4B2)oE5^MQ>)RKCOYgFJ(<IM|90N|RS}N*jM*Vd3QY
z%EQ3PcY)7vhWG_O!wY<dD@-8tMGm7Y97Y#7j4pB*eXy5jHU0qd+vHp>c@IGb28JST
z1_p*(Lg|&cd5OiDrMY_LMTrFksYS&_paP}{6hA8&iY!4Y%^4UNesS33=BJeAq}mnP
aGcYiKQekoA<SSgRGS-a79~dwRuvP$>kv8lA

diff --git a/backend/__pycache__/environment.cpython-311.pyc b/backend/__pycache__/environment.cpython-311.pyc
index 51daa198751b4836531ffe9cc564ed462aed29b8..4b3cb87be7554aa6bcb531d2a1fd6d299d80c0a5 100644
GIT binary patch
delta 4771
zcmdmCa6Eu-IWI340|Ntt1Xq2^7Kw>`5{wlS)&2BYS{R}@Q@K)Dvzb7$MLbLlshrCg
z7#LQAxM0l4kir-Y#+qyst7I76CQet<<mzBZV@zRf;f!KS;Z9+1VT@u=;b>uq;z;2H
znb^Tl!5GCA%%I7$@y;I>MxM<#S&f+(H7E0O1aq@8FfcGPFfe@n#=JS3V+kWu(WlA6
zTze*ma%xOA=N4uZoP3c}baDc>kU2{Ya}^f@LoHhha}67q#a_cu!I&ikb{7K!Lk)Ws
zF9Sm|Q#@RxM4f?QawDhc<W1ZXyetq;70bd!KX8cq!2QaU!kEXH!dA;s!&<|DWGF`p
zLmEpk1FBUitmszNFf0H$Rbg^IkDv)oQ#9HALW)2kpDCcu!0-~}`65tIyJ?C{zQWU}
zE|r#(SW=Rj7oVS0oLW?tSdy8a7hjSepP5%uq{P6$P$bE~z@W)FxrW!stt2xy6)bp*
zB_%&EwV0EEfk6QVic~?WEg2XXs>Gd2i!<|5i;Dw_@{?1Gi(T`|^omPT3yc^T7>ch<
ze$Km;`2&OG<bJ+T)(;#EQgV~|_+@o0E=gMKkh&=8az)am!|Q>t_zcyFHXSZEM5Shg
zOpNJpyTK#S;oajs!|WoD;$(0B2pPkRJTf4W8<MiuCBeEyu2_0sl=QhG>9cu1|4Swz
z1CWbAp3r0|QU<Y|C+`wcV|1PTP)L?BZu5U3Uq;4~&AuXbjH0)Mv4q3q38ET|m6Lah
z)=v)R5UY1%Wnh@jkiuBYRKrxmn8E}K8AwVfVT8~iGKD#XWf>C#!)j0{g9I3=SQ!{V
zkq6bsiqMzBhG3(a!Hi)>JuX9-NiYOv28#1*nQNF+7$J$ZNCoUUc7&NJj1YD`$TMiJ
z<iKzx)Pf02c|0}DDQq|m#qD!kX4W%JV9a}z!dAna%v8aY4RQ@b5nBppHaPH$(({-Y
z8S+vvT#q|+uvk>Xn1bwcPKeJzR+TV<{SRU?Fr+Z2aAEN|s6;?DfE(EWh+Ytx!kof`
zT|Xq9Okm8*OW{QGXgvqir|w{%x?uQ}7pG-}eaeATFWjS0|ASLAD3|jxFw}ygL@I>?
z&80k0ho*rYnvCI4E}WL(b120A6ds(K;VuOQF#{yqVMYlbPW^bJByV|r3J;n;`3d-w
z1*cW`{0Vk_3O|NksQ-ygdIA^*Kny03^zuwn_|d#62=Qipks3HYl`-NIT0nrzC$@aZ
zW8`G0VG3r@6!HUCN8l>zC8)@J3977$Kvhc-8>r0YU|?W)31Y>+1l8Iv*+G035CM`Y
z(gm?Vs$X)0SUezt4^(9_-eNAuFNc-<fgq!_K?KP7Vvv3X1qB62rDX+5&bpH)iK^8@
ztG-51O~ua4z|g>OLqM>D^#%v;1nC*!R|Hj;Ca+Lj;j}PwN#;dC{fiv>FuAZRf+`CF
zuL!EIWnSU9B5@_h8jg#C1{XODh*2OQJ;VKqfJz5z{S9t`365P>9acAZ1Sdo<kh~(Q
zy~6Q|sNUM*4Tc*6S5~a4xF~9Vk;lBlwbS(muh4|VuBeVEqSW$D5bcQVi0z8)h@Bw_
zB0;>4SX90Bs21(uKHz!9!tX@k6^p>DL7^AI!Y@QbUJQ!55)^gOBI=@O)P?A@3+V+{
zq6;q+6<>)ixmsFrp|a{ib<M@n+AF2C7o%%0iq>A_sfD<f2p80&dzGLIF7iYnOpoh`
z>x%1$o1q9IJK{hP)qjM%S5L10I$Uq?g8UcX5#JTx5kEr-M0Ui3Ad(B5u88VyW!~Vp
zA#o$e7LJRe7CWR5L|(D<zYq{~#WMJ6NI1y;3sKP*Lt?Ik#9XwDxhNWQAvWVeX3>?{
z;tM5ZS7OVrR#ac8sl8BF|B->AlF^ar3xxW}z!1mi$n=qcK@3dtIx=;*f*i#^LG=Q!
z>;+!gOJH(_5rl?_UEq~Pa-HK9QGL_^0w=T%*9SZT5BNnoc#70P8H>r!Pm{683&iA}
z>?)@3X$i_!t{}n>M1+C}P?oyI8y}yXlUQ7woSKspAFs(+<O#}Fpz7KIlJP*<un0te
zGv(aLJH+((HCfF+Fu;k3$zR1Bg9XG{ML#g$Bfw4r8<h+yhF}<EHmKD2+{FxPyQMSK
zg4%D4H4F<TU*r^#VyIzU#>l|18ssFf7Dk2?rdlSb^yC~)K~6@76y{oHn8+FtVfGZ}
zS{4}p4TR4M<HvDBb+AE2q!?=0FsxvyWk*P}V@R{sav-ERFr=AkIT6yF7}Bh@TnK3{
z3~9DnZiF;97HJ-YG!GVOUZ}JULk%ywbUH&VUkNC<!C}e3kb>qn7lv5zTK*b7aNvWw
zbm#{3NYpUY@TD`=3Z!t<3YLI6D^R0q1Zo6PTTHb=H9}c%%W8#dgch)XdT#c@sHWD6
zlz?gmm^mV-vWyJK4z3Z(Vw?P&L!sV<Ay%+f6h)&by2c)%6oz01O-?^ZJq4<WilRVi
zKO98FfQVR7ZNv{E1VGt^qbPuZf#DWwQDR<tDmbwgNrRMuGYe}$5vb243Q|$en5QXL
z1ghU|vF4TL#uwjW15x=Uw>Us_aYlS1oRtJ;CEsEP$>zo<!Wc;qMgdHuARaD~4AGWS
z3^OXFI38+LN^yOBGNc9$202d!M1bnlB2y3xT#E*QoXJ|2m{XcsEQZ_-1l6i=49?}Z
zSaK6H^NOk&7#L=O^8a;4aJ9-O(BOW9hquA?1`Bt)Uz6Vi(~B&US6C!3ut?sh=jCf~
zgNd76WRbeUB6Wd9>IT0+g9l95;v$R86&9HbEHWet^YJ&h!wfOM$Rd4(Mfw7Z^bKU;
zdK}_p3zO*ZdaV9@z|Gs>a+g<Vf>CE=Pvi#%Mpkh!(ZP6wgQuUni+h4&CtnX=2VV!@
z1748{DINX|t~UgQ8@!%!$;=2{;B}Ep{|c9WgYyj@{wqAP4X!r?gs%(eT@uh+QF>9p
z^ooFKgXdiq&JN9sEIuMvSVS(ch};zvn^1g3T>Xl;=0!oRD}q`e`$WM+2kTu9-j38x
zo*teKo(`T5%#5rM32;e#iz7ZB6zlQvn%t8^#T|7)v0nr#nu~luX$Vx2fD^|r4x8Nk
zl+v73yCP7V3sevnFPOYj+&Y)TkBL$A0|Rz)hVUHmk6^hkU=pe>fkhLf2TnvVGO+M;
iR9#}0yud7ZgN38PrO~a$tpN-_Ff*`7U0{|3yB7drKvuc{

delta 975
zcmX>eu)~0FIWI340|NsCqiAu;MgEC=5{!Nm)%}zhgBdhgUV<e2l0hU4Gea4l9VQ-B
zQs(SnNMlT4ZQ+b!OW{gkZ()pLPvK}`h~nsAs9=oZ3}(>e-ps@JhlP=MGbfud6QkB-
zTaI9Eb_NCpkU5`qST@h*Si;CMfw72ZvLn|XhZ1F|@eB+MDa<ttS#WL^6O1{VA%&%e
zaW+E=>s;1lj0_B`8DTPv43qzISu+Yv4pdapt7WZWs9?+zhDp}2)G$|ZF)(m5RPiz}
zBs0asWlA&|7$$Gz6rH?=TY{S{8*EXrY>DRN^W6I0>=1qtQwn1qV+uztTMcUs1Cpt1
zDGX^W!3?N&rEsF#QNyr6Xfh+0!sJXI!4RCLXma_56oF!+ir+CkHLpY=B{M}KIk7lZ
zp^8f(F}WnOEVHCi;TNOcOI8L3h9Zzl-7@F=|Nmc8bn-f$Ms?PLqRhOKTf%8Mi6tee
zdGYy4#i>PQi6xo&c|}Sf9g++T44Ukd!+4FvQ}Xjti$O7=00Bj+AO%*F*YL`)88a|2
z6u+H(j&~{ZM+Wi9WqhGpPk96{2>C8>S>kg=#o~gH?*$>>18xxdf{^b;9=|I*eiwNB
z9!SbgzQ8A|V0cN=aD&!GN!u%uwjEv%cmz7Ud%S0aEO4C}GsFHOkJe;K{s<Y9i#+lm
z@f(t|*CoL^RIV7gT$FUZBI&xhm;WV`kRixTAeU>h6oHaPk;~)`AvH#~$?Jt=8Dlq}
z74l_dEZ!_FV#ml{WW&I~P^C6`Bd_q}W>I0ripkSO>v=Vq{QNW-i@ZVp=9=s;ukT_7
zGSUr1_=5<Lu3NnE@yR)f#l^{~IXUt1nv6wWpa1}+D+frhuz-|;2yT!>-{j-+di?6F
z<{uc~M95?o1xI-XHde_Gs6>%EOs^*AWJ7gFM&HS`>JnUWpezS6tbFo(b!!){Vn#;E
W4-DAJ8NzeKKZ51HfJsbsU`qfmZ{H07

diff --git a/backend/__pycache__/eventlog.cpython-311.pyc b/backend/__pycache__/eventlog.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5c000c77be103887b9d6c9671a5555bb455cc198
GIT binary patch
literal 7786
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

literal 0
HcmV?d00001

diff --git a/backend/__pycache__/simplesimmodel.cpython-311.pyc b/backend/__pycache__/simplesimmodel.cpython-311.pyc
index 7f8f062a2173a3f3440055bc14475b66274869c3..def6d5e7c495421b42862ead8fe246f98d50bf31 100644
GIT binary patch
literal 28897
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

literal 31186
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
STLTz=U}j*Ey1*<6ju8M8O;XeV

diff --git a/backend/agent.py b/backend/agent.py
index 111df06..e75453c 100644
--- a/backend/agent.py
+++ b/backend/agent.py
@@ -18,26 +18,44 @@ def q_learning(space, activities):
     case_space = env.observation_space['case'].nvec 
     event_space = env.observation_space['event'].n
     
-    for i in process_space: num_states *= i
-    for i in case_space: num_states *= i
-    num_states *= event_space
+    """
+    for i in process_space: num_states *= (i+1)
+    for i in case_space: num_states *= (i+1)
+    num_states *= event_space + 1
+    """
+    num_states = pow(2,14)
+
+    """
+    process_space = env.observation_space['process'] 
+    case_space = env.observation_space['case'] 
+    event_space = env.observation_space['event'] 
+
+    state_shape = []
+    for i in process_space: state_shape.append(i.n + 1)
+    for j in case_space: state_shape.append(j.n + 1)
+    state_shape.append(event_space.n)
+    state_shape = tuple(state_shape)
+    """
     
     num_actions = env.action_space.n
 
-    Q = np.zeros((num_states, num_actions), dtype=np.int16)
+
+    # Q = np.zeros(state_shape + (num_actions,), dtype=np.int8)
+    Q = np.zeros((num_states, num_actions), dtype = int)
 
     # Set the hyperparameters
     alpha = 0.1   # learning rate
-    gamma = 0.99  # discount factor
+    gamma = 0.1  # discount factor
     epsilon = 0.1 # exploration rate
 
     mean_time = 0
+    mean_reward = 0
 
     # Train the agent using Q-learning
-    num_episodes = 100
+    num_episodes = 1000
     for episode in range(num_episodes):
         state, _ = env.reset()
-        state = env.flatten_observation(state)
+        state = env.flatten_observation_to_int(state)
         done = False
         start = env.process.env.now
         while not done:
@@ -52,18 +70,39 @@ def q_learning(space, activities):
             next_state, reward, done, _ = env.step(action)
 
             # Update the Q-value for the current state-action pair
-            Q[state][action] = Q[state][action] + alpha * (reward + gamma * np.max(Q[next_state]) - Q[state][action])
+            Q[state][action] = (1-alpha)*Q[state][action] + alpha * (reward + gamma * np.max(Q[next_state]) - Q[state][action])
+            #Q[state][action] = (1-alpha)*Q[state][action] + alpha*reward 
             
             # Transition to the next state
+            old_state = state
             state = next_state
+            
+            """
+            if old_state != state: 
+                print(state)
+                print(action)
+                print(Q[state][action])
+            """
+            
 
         time = env.process.env.now - start 
         mean_time += time
+        mean_reward += reward
+
 
-        """
         if (episode % 20 == 19):
+            mean_reward /= 20
             mean_time /= 20 
-            print(f"Episode {episode-19} to episode {episode}: mean time = {mean_time}")
-        """
+            print(f"Episode {episode-19} to episode {episode}: mean time = {mean_time}, mean reward: {mean_reward}")
+        
+        if episode == 19:
+            start_reward = mean_reward
+
+        # print(f"Episode {episode}: time = {time}, reward = {reward}")
+        
+        if episode == 999:
+            end_reward = mean_reward
+            improvement = end_reward - start_reward
+            print(f"Reward improved by {improvement}")
 
-        print(f"Episode {episode}: time = {time}")
\ No newline at end of file
+    return Q
diff --git a/backend/environment.py b/backend/environment.py
index b96b642..1ee254b 100644
--- a/backend/environment.py
+++ b/backend/environment.py
@@ -7,7 +7,6 @@ import simplesimmodel as model
 Environment for the RL agent
 """
 
-
 class BusinessProcessEnv(gym.Env):
 
     def __init__(self, space, activities):
@@ -73,19 +72,21 @@ class BusinessProcessEnv(gym.Env):
 
             case_obj = self.process.case_objects[self.process.case_id]
 
-            print(f"Agent did case {self.process.case_id} activity {action}.")
+            # print(f"Agent did case {self.process.case_id} activity {action}.")
 
             next_state = self.get_current_state(case_obj)
             self.current_state = next_state
-            next_state = self.flatten_observation(next_state)
+            next_state = self.flatten_observation_to_int(next_state)
 
-            self.reward += -(stop - start)
+            time = stop - start
+            reward = 10000 - time
+            self.reward += reward
             done = True if (len(self.process.done_cases) == 5 or len(self.process.active_cases) == 0) else False
             return next_state, self.reward, done, None
         
         else: 
-            self.reward += -100
-            next_state = self.flatten_observation(self.current_state)
+            self.reward += 0
+            next_state = self.flatten_observation_to_int(self.current_state)
             done = False
             return next_state, self.reward, done, None
     
@@ -125,4 +126,74 @@ class BusinessProcessEnv(gym.Env):
 
         return flattened
 
+    def flatten_observation_to_int(self, observation):
+        state = 0
+        state += observation['event']*pow(2,10)
+        state += observation['case'][1]*pow(2,2)
+        state += observation['case'][2]*pow(2,2)
+        event = observation['event']
+        if event == 0:
+            state += observation['process'][0]*pow(2,6)
+        elif event == 1:
+            state += observation['process'][1]*pow(2,6)
+        elif 1 < event <=3:
+            state += observation['process'][2]*pow(2,6)+observation['process'][3]*pow(2,7)+observation['process'][4]*pow(2,8)
+        elif 3 < event <=6:
+            state += observation['process'][5]*pow(2,6)+observation['process'][6]*pow(2,7)
+        elif 6 < event <= 8:
+            state += observation['process'][7]*pow(2,6)+observation['process'][8]*pow(2,7)+observation['process'][9]*pow(2,8)
+        elif 8 < event <= 11:
+            state += observation['process'][10]*pow(2,6)+observation['process'][11]*pow(2,7)+observation['process'][12]*pow(2,8)
+        elif 11 < event <= 14:
+            state += observation['process'][0]*pow(2,6)
+        else:
+            pass
+        
+        return state
+
+def main():
+    process = [] 
+    num_s = 1
+    process.append(num_s)
+    num_ot = 5
+    process.append(num_ot)
+    num_sh_a = 3
+    process.append(num_sh_a)
+    num_sh_b = 3
+    process.append(num_sh_b)
+    num_sh_c = 3
+    process.append(num_sh_c)
+    num_m_a = 3
+    process.append(num_m_a)
+    num_m_b = 2
+    process.append(num_m_b)
+    num_p_a = 4
+    process.append(num_p_a)
+    num_p_b = 5
+    process.append(num_p_b)
+    num_p_c = 4
+    process.append(num_p_c)
+    num_ds_a = 8
+    process.append(num_ds_a)
+    num_ds_b = 8
+    process.append(num_ds_b)
+    num_ds_c = 8
+    process.append(num_ds_c)
+
+    case = []
+    for i in range(15):
+        case.append(1)
+        
+    space = [process, case]
+    activities = 16
+
+    env = BusinessProcessEnv(space, activities)
+    state = env.current_state
+    flattened = env.flatten_observation_to_int(state)
+    print(flattened)
+    for value in range(env.action_space.n):
+        print(value)
+
 
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/backend/eventlog.py b/backend/eventlog.py
index 36848b5..7a3625e 100644
--- a/backend/eventlog.py
+++ b/backend/eventlog.py
@@ -1,33 +1,172 @@
 import pandas as pd
 import simplesimmodel as model
+import numpy as np
 
 """
 Event log generator for our simulation model:
 - generate an event log
 - update an event log (adding new events)
+- export event log
+- get current state of an event log
 """
 
 def add_start_event(process, event_id, case_id, activity, start_timestamp):
+    process.event_log.append(event_id)
     process.event_log[event_id] = {
         'CaseID': case_id,
         'Activity': activity,
         'StartTimestamp': float(start_timestamp),
         'EndTimestamp': None
     }
+    process.event_counter += 1
 
 def add_end_event(process, event_id, end_timestamp):
-    # if event_id in process.event_log:
     event = process.event_log[event_id]
     event['EndTimestamp'] = end_timestamp
-    # process.event_log.append(event)
-    # del process.event_log[event_id]
 
-# add functions for adding events with their attributes to the log
 
-def export_to_csv(env, file_path):
-    event_log_df = pd.DataFrame.from_dict(env.bigeventlog)
-    event_log_df.to_csv(file_path)
+def export_to_csv(process, file_path):
+    event_log_df = pd.DataFrame.from_dict(process.event_log)
+    event_log_df.to_csv(file_path, index=False)
 
 def export_to_xes(process, file_path):
     # Use appropriate code to export to XES format
-    pass
\ No newline at end of file
+    pass
+
+def get_active_cases():
+    event_log = pd.read_csv(r'D:\test\optis.csv')
+    active_cases = event_log.groupby('CaseID').filter(lambda x: 'order completed' not in x['Activity'].values)['CaseID'].unique().tolist()
+    return active_cases
+
+
+def get_state(case_id):
+
+    process = [] 
+    num_s = 1
+    process.append(num_s)
+    num_ot = 5
+    process.append(num_ot)
+    num_sh_a = 3
+    process.append(num_sh_a)
+    num_sh_b = 3
+    process.append(num_sh_b)
+    num_sh_c = 3
+    process.append(num_sh_c)
+    num_m_a = 3
+    process.append(num_m_a)
+    num_m_b = 2
+    process.append(num_m_b)
+    num_p_a = 4
+    process.append(num_p_a)
+    num_p_b = 5
+    process.append(num_p_b)
+    num_p_c = 4
+    process.append(num_p_c)
+    num_ds_a = 8
+    process.append(num_ds_a)
+    num_ds_b = 8
+    process.append(num_ds_b)
+    num_ds_c = 8
+    process.append(num_ds_c)
+
+    case = []
+    for i in range(15):
+        case.append(0)
+
+    activity_mapping = {
+        'place order': 1,
+        'arrange standard order': 2,
+        'arrange custom order': 3,
+        'pick from stock A': 4, 
+        'pick from stock B': 5, 
+        'pick from stock C': 6, 
+        'manufacture A': 7, 
+        'manufacture B': 8, 
+        'pack A': 9,
+        'pack B': 10,
+        'pack C': 11,
+        'attempt delivery A': 12,
+        'attempt delivery B': 13,
+        'attempt delivery C': 14,
+        'order completed': 15,
+    }
+
+    event_log = pd.read_csv(r'D:\test\optis.csv')
+    # Sort the event log by case ID and start timestamp
+    event_log.sort_values(by=['CaseID', 'StartTimestamp'], inplace=True)
+
+    # Group the event log by case ID and get the last activity for each case
+    last_activities = event_log.groupby('CaseID').tail(1).reset_index()
+   
+    # Remap the activity names to numbers using the mapping dictionary
+    last_activities['Activity'] = last_activities['Activity'].map(activity_mapping)
+
+    # Filter the cases where the end timestamp of the last activity is None or empty
+    unfinished_cases = last_activities[last_activities['EndTimestamp'].isnull()]['CaseID'].tolist()
+
+    # Update the state of the ressources given all unfinished cases
+    for i in unfinished_cases:
+        activity = last_activities[last_activities['CaseID'] == i]['Activity'].values[0]
+        if activity == 1 or activity == 15:
+            process[0] -= 1
+        elif activity == 2 or activity == 3:
+            process[1] -= 1
+        else:
+            process[activity-2] -= 1
+
+    # Get the state of the case for the given Case ID
+    filtered_log = event_log[event_log['CaseID'] == case_id]
+    activities = filtered_log['Activity'].map(activity_mapping).tolist()
+    for i in activities:
+        case[i-1] += 1
+
+    # Get the last event for the given Case ID
+    event = last_activities[last_activities['CaseID'] == case_id]['Activity'].values[0]
+
+    state = {
+        'process': process,
+        'case': case,
+        'event': event
+    }
+
+    print(state)
+
+    """
+    flattened = []
+    for i in state['process']: flattened.append(i)
+    for j in state['case']: flattened.append(j)
+    flattened.append(state['event'])
+    
+
+    flattened = 0
+    flattened += state['event']
+    for i in state['case']: flattened += i
+    for j in state['process']: flattened += j*process[j]
+
+    print(flattened)
+    """
+    flat_state = 0
+    flat_state += state['event']*pow(2,10)
+    print(flat_state)
+    flat_state += state['case'][1]*pow(2,1)
+    flat_state += state['case'][2]*pow(2,2)
+    event = state['event']
+    if event == 0:
+        flat_state += state['process'][0]*pow(2,6)
+    elif event == 1:
+        flat_state += state['process'][1]*pow(2,6)
+    elif 1 < event <=3:
+        flat_state += state['process'][2]*pow(2,6)+state['process'][3]*pow(2,7)+state['process'][4]*pow(2,8)
+    elif 3 < event <=6:
+        flat_state += state['process'][5]*pow(2,6)+state['process'][6]*pow(2,7)
+    elif 6 < event <= 8:
+        flat_state += state['process'][7]*pow(2,6)+state['process'][8]*pow(2,7)+state['process'][9]*pow(2,8)
+    elif 8 < event <= 11:
+        flat_state += state['process'][10]*pow(2,6)+state['process'][11]*pow(2,7)+state['process'][12]*pow(2,8)
+    elif 11 < event <= 14:
+        flat_state += state['process'][0]*pow(2,6)
+    else:
+        pass
+    
+    print(flat_state)
+    return flat_state
diff --git a/backend/input.py b/backend/input.py
new file mode 100644
index 0000000..e8c6f1e
--- /dev/null
+++ b/backend/input.py
@@ -0,0 +1,2 @@
+import pandas as pd
+
diff --git a/backend/main.py b/backend/main.py
new file mode 100644
index 0000000..fdee31d
--- /dev/null
+++ b/backend/main.py
@@ -0,0 +1,91 @@
+import simpy
+import random
+import numpy as np
+import simplesimmodel as model
+import environment 
+import agent
+import eventlog as log
+import pandas as pd
+
+def main():
+    # Setup
+    # we can use a random seed if we want to generate the same results every time (maybe useful later for the training)
+    # random.seed(42)
+    # initialize the number of resources
+
+    process = [] 
+    num_s = 1
+    process.append(num_s)
+    num_ot = 5
+    process.append(num_ot)
+    num_sh_a = 3
+    process.append(num_sh_a)
+    num_sh_b = 3
+    process.append(num_sh_b)
+    num_sh_c = 3
+    process.append(num_sh_c)
+    num_m_a = 3
+    process.append(num_m_a)
+    num_m_b = 2
+    process.append(num_m_b)
+    num_p_a = 4
+    process.append(num_p_a)
+    num_p_b = 5
+    process.append(num_p_b)
+    num_p_c = 4
+    process.append(num_p_c)
+    num_ds_a = 7
+    process.append(num_ds_a)
+    num_ds_b = 7
+    process.append(num_ds_b)
+    num_ds_c = 7
+    process.append(num_ds_c)
+
+    case = []
+    for i in range(15):
+        case.append(1)
+        
+    space = [process, case]
+    activities = 16
+
+    # q learning
+    Q = agent.q_learning(space, activities)
+    # print(Q)
+
+    # generate event log
+    env = simpy.Environment()
+    business_process = model.BusinessProcess(env, process)
+    business_process.event_log_flag = True
+    env.process(model.run_process(env, business_process))
+    env.run(until = 10000)
+    log.export_to_csv(business_process, r'D:\test\optis.csv')
+
+    # extract active cases from event log
+    active_cases = log.get_active_cases()
+    print(active_cases)
+
+    # test agent 
+    for i in range(20):
+        caseid = random.choice(active_cases)
+        state = log.get_state(caseid)
+
+        action = np.argmax(Q[state])
+        print(action)
+        #print(Q)
+        print(Q[state])
+
+    state = Q[0]
+    action = np.argmax(state)
+    print(action)
+    print(state)
+
+    state = Q[64]
+    action = np.argmax(state)
+    print(action)
+    print(state)
+    
+
+
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/backend/simplesimmodel.py b/backend/simplesimmodel.py
index fe23eb4..18cb952 100644
--- a/backend/simplesimmodel.py
+++ b/backend/simplesimmodel.py
@@ -3,6 +3,7 @@ import random
 import numpy as np
 import environment 
 import agent
+import eventlog as log
 
 """
 Simulation model for a simpler business process, including:
@@ -56,7 +57,11 @@ class BusinessProcess(object):
 
         self.done_cases = set([])
 
-        random.seed(1)
+        self.event_log_flag = False
+        self.event_log = []
+        self.event_counter = 0
+
+        # random.seed(1)
 
     def place_order(self, case):
         yield self.env.timeout(0)
@@ -162,20 +167,25 @@ def execute_case(env, case, process):
         case_obj.agent = True
 
     # place order
+    case_obj.state[0] += 1
+    case_obj.current = 1
     with process.system.request() as request:
         yield request
-        case_obj.state[0] += 1
-        case_obj.current = 1
+        if process.event_log_flag:
+            event_counter = process.event_counter
+            log.add_start_event(process, event_counter, case, "place order", env.now)
         yield env.process(process.place_order(case))
-        if case_obj.agent: print(f"Case {case}: 'placed order' at {env.now:.2f}")
+        if process.event_log_flag: 
+            log.add_end_event(process, event_counter, env.now)
+        # if case_obj.agent: print(f"Case {case}: 'placed order' at {env.now:.2f}")
 
 
     # if the last action was made from the agent set the process flag to be able to return to the environment's step function
     if case_obj.agent: 
         process.flag = False
 
-        with process.system.request() as request:
-            yield request
+    with process.system.request() as request:
+        yield request
 
     # before a new action is executed check if the agent is controlling the case and set the flag to true if yes
     if process.case_id == case: case_obj.agent = True 
@@ -184,32 +194,40 @@ def execute_case(env, case, process):
     choice = random.randint(2,3) if not case_obj.agent else process.next 
     if choice == 2:
         case_obj.standard_order = True
+        case_obj.state[1] += 1
+        case_obj.current = 2
         with process.order_taker.request() as request:
             yield request
-            case_obj.state[1] += 1
-            case_obj.current = 2
-            if case_obj.agent: print(f"Case {case}: started 'arrange standard order' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'arrange standard order' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "arrange standard order", env.now)
             yield env.process(process.arrange_standard_order(case))
-            if case_obj.agent: print(f"Case {case}: finished 'arrange standard order' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            # if case_obj.agent: print(f"Case {case}: finished 'arrange standard order' at {env.now:.2f}")
             if case_obj.agent: 
                 process.flag = False
-
-                with process.system.request() as request:
-                        yield request
+            with process.system.request() as request:
+                    yield request
     else:
+        case_obj.state[2] += 1
+        case_obj.current = 3
         case_obj.standard_order = False
         with process.order_taker.request() as request:
             yield request
-            case_obj.state[2] += 1
-            case_obj.current = 3
-            if case_obj.agent: print(f"Case {case}: started 'arrange custom order' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'arrange custom order' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "arrange custom order", env.now)
             yield env.process(process.arrange_custom_order(case))
-            if case_obj.agent: print(f"Case {case}: finished 'arrange custom order' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            # if case_obj.agent: print(f"Case {case}: finished 'arrange custom order' at {env.now:.2f}")
             if case_obj.agent: 
                 process.flag = False
-
-                with process.system.request() as request:
-                        yield request
+            with process.system.request() as request:
+                    yield request
 
 
     if process.case_id == case: case_obj.agent = True 
@@ -223,70 +241,92 @@ def execute_case(env, case, process):
      
     # choose stock or manufacturer
     if choice == 4:
+        case_obj.state[3] += 1
+        case_obj.current = 4
         with process.stock_handler_a.request() as request:
             yield request
-            case_obj.state[3] += 1
-            case_obj.current = 4
-            if case_obj.agent: print(f"Case {case}: started 'pick from stock A' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'pick from stock A' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "pick from stock A", env.now)
             yield env.process(process.pick_from_stock_a(case))
-            if case_obj.agent: print(f"Case {case}: finished 'pick from stock A' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            # if case_obj.agent: print(f"Case {case}: finished 'pick from stock A' at {env.now:.2f}")
             if case_obj.agent: 
                 process.flag = False
-
-                with process.system.request() as request:
-                    yield request
+            with process.system.request() as request:
+                yield request
     elif choice == 5:
+        case_obj.state[4] += 1
+        case_obj.current = 5
         with process.stock_handler_b.request() as request:
             yield request
-            case_obj.state[4] += 1
-            case_obj.current = 5
-            if case_obj.agent: print(f"Case {case}: started 'pick from stock B' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'pick from stock B' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "pick from stock B", env.now)
             yield env.process(process.pick_from_stock_b(case))
-            if case_obj.agent: print(f"Case {case}: finished 'pick from stock B' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'pick from stock B' at {env.now:.2f}")
             if case_obj.agent: 
                 process.flag = False
-
-                with process.system.request() as request:
-                    yield request
+            with process.system.request() as request:
+                yield request
     elif choice == 6:
+        case_obj.state[5] += 1
+        case_obj.current = 6
         with process.stock_handler_c.request() as request:
             yield request
-            case_obj.state[5] += 1
-            case_obj.current = 6
-            if case_obj.agent: print(f"Case {case}: started 'pick from stock C' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'pick from stock C' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "pick from stock C", env.now)
             yield env.process(process.pick_from_stock_c(case))
-            if case_obj.agent: print(f"Case {case}: finished 'pick from stock C' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            # if case_obj.agent: print(f"Case {case}: finished 'pick from stock C' at {env.now:.2f}")
             if case_obj.agent: 
                 process.flag = False
-
-                with process.system.request() as request:
-                    yield request
+            with process.system.request() as request:
+                yield request
     elif choice == 7:
+        case_obj.state[6] += 1
+        case_obj.current = 7
         with process.manufacturer_a.request() as request:
             yield request
-            case_obj.state[6] += 1
-            case_obj.current = 7
-            if case_obj.agent: print(f"Case {case}: started 'manufacture A' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'manufacture A' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "manufacture A", env.now)
             yield env.process(process.manufacture_a(case))
-            if case_obj.agent: print(f"Case {case}: finished 'manufacture A' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'manufacture A' at {env.now:.2f}")
             if case_obj.agent: 
                 process.flag = False
-
-                with process.system.request() as request:
-                    yield request
+            with process.system.request() as request:
+                yield request
     else:
+        case_obj.state[7] += 1
+        case_obj.current = 8
         with process.manufacturer_b.request() as request:
             yield request
-            case_obj.state[7] += 1
-            case_obj.current = 8
-            if case_obj.agent: print(f"Case {case}: started 'manufacture B' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'manufacture B' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "manufacture B", env.now)
             yield env.process(process.manufacture_b(case))
-            if case_obj.agent: print(f"Case {case}: finished 'manufacture B' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            # if case_obj.agent: print(f"Case {case}: finished 'manufacture B' at {env.now:.2f}")
             if case_obj.agent: 
                 process.flag = False
-
-                with process.system.request() as request:
-                    yield request
+            with process.system.request() as request:
+                yield request
 
 
     if process.case_id == case: case_obj.agent = True 
@@ -294,99 +334,135 @@ def execute_case(env, case, process):
     choice = random.randint(9,11) if not case_obj.agent else process.next
 
     if choice == 9:
+        case_obj.state[8] += 1
+        case_obj.current = 9
         with process.packer_a.request() as request:
             yield request
-            case_obj.state[8] += 1
-            case_obj.current = 9
-            if case_obj.agent: print(f"Case {case}: started 'pack A' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'pack A' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "pack A", env.now)
             yield env.process(process.pack_a(case))
-            if case_obj.agent: print(f"Case {case}: finished 'pack A' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'pack A' at {env.now:.2f}")
             if case_obj.agent: 
-                    process.flag = False
-
-                    with process.system.request() as request:
-                        yield request
+                process.flag = False
+            with process.system.request() as request:
+                yield request
     elif choice == 10:
+        case_obj.state[9] += 1
+        case_obj.current = 10
         with process.packer_b.request() as request:
             yield request
-            case_obj.state[9] += 1
-            case_obj.current = 10
-            if case_obj.agent: print(f"Case {case}: started 'pack B' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'pack B' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "pack B", env.now)
             yield env.process(process.pack_b(case))
-            if case_obj.agent: print(f"Case {case}: finished 'pack B' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'pack B' at {env.now:.2f}")
             if case_obj.agent: 
-                    process.flag = False
+                process.flag = False
 
-                    with process.system.request() as request:
-                        yield request
+            with process.system.request() as request:
+                yield request
     else:
+        case_obj.state[10] += 1
+        case_obj.current = 11
         with process.packer_c.request() as request:
             yield request
-            case_obj.state[10] += 1
-            case_obj.current = 11
-            if case_obj.agent: print(f"Case {case}: started 'pack C' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'pack C' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "pack C", env.now)
             yield env.process(process.pack_c(case))
-            if case_obj.agent: print(f"Case {case}: finished 'pack C' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'pack C' at {env.now:.2f}")
             if case_obj.agent: 
-                    process.flag = False
-
-                    with process.system.request() as request:
-                        yield request
+                process.flag = False
+            with process.system.request() as request:
+                yield request
 
     if process.case_id == case: case_obj.agent = True 
 
     # choose delivery
     choice = random.randint(12,14) if not case_obj.agent else process.next
     if choice == 12:
+        case_obj.state[11] += 1
+        case_obj.current = 12
         with process.delivery_service_a.request() as request:
             yield request
-            case_obj.state[11] += 1
-            case_obj.current = 12
-            if case_obj.agent: print(f"Case {case}: started 'attempt delivery A' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'attempt delivery A' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "attempt delivery A", env.now)
             yield env.process(process.attempt_delivery_a(case))
-            if case_obj.agent: print(f"Case {case}: finished 'attempt delivery A' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'attempt delivery A' at {env.now:.2f}")
             if case_obj.agent: 
-                    process.flag = False
-
-                    with process.system.request() as request:
-                        yield request
+                process.flag = False
+            with process.system.request() as request:
+                yield request
     elif choice == 13:
+        case_obj.state[12] += 1
+        case_obj.current = 13
         with process.delivery_service_b.request() as request:
             yield request
-            case_obj.state[12] += 1
-            case_obj.current = 13
-            if case_obj.agent: print(f"Case {case}: started 'attempt delivery B' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'attempt delivery B' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "attempt delivery B", env.now)
             yield env.process(process.attempt_delivery_b(case))
-            if case_obj.agent: print(f"Case {case}: finished 'attempt delivery B' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'attempt delivery B' at {env.now:.2f}")
             if case_obj.agent: 
-                    process.flag = False
-
-                    with process.system.request() as request:
-                        yield request
+                process.flag = False
+            with process.system.request() as request:
+                yield request
     else: 
+        case_obj.state[13] += 1
+        case_obj.current = 14
         with process.delivery_service_c.request() as request:
             yield request
-            case_obj.state[13] += 1
-            case_obj.current = 14
-            if case_obj.agent: print(f"Case {case}: started 'attempt delivery C' at {env.now:.2f}")
+            # if case_obj.agent: print(f"Case {case}: started 'attempt delivery C' at {env.now:.2f}")
+            if process.event_log_flag:
+                event_counter = process.event_counter
+                log.add_start_event(process, event_counter, case, "attempt delivery C", env.now)
             yield env.process(process.attempt_delivery_c(case))
-            if case_obj.agent: print(f"Case {case}: finished 'attempt delivery C' at {env.now:.2f}")
+            if process.event_log_flag: 
+                log.add_end_event(process, event_counter, env.now)
+            
+            # if case_obj.agent: print(f"Case {case}: finished 'attempt delivery C' at {env.now:.2f}")
             if case_obj.agent: 
-                    process.flag = False
-
-                    with process.system.request() as request:
-                        yield request
+                process.flag = False
+            with process.system.request() as request:
+                yield request
     
 
     if process.case_id == case: case_obj.agent = True 
 
     # case completed
+    case_obj.state[14] += 1
+    case_obj.current = 15
     with process.system.request() as request:
         yield request
-        case_obj.state[14] += 1
-        case_obj.current = 15
+        if process.event_log_flag:
+            event_counter = process.event_counter
+            log.add_start_event(process, event_counter, case, "order completed", env.now)
         yield env.process(process.order_completed(case))
-        if case_obj.agent: print(f"Case {case}: 'completed' at {env.now:.2f}")
+        if process.event_log_flag: 
+            log.add_end_event(process, event_counter, env.now)
+        # if case_obj.agent: print(f"Case {case}: 'completed' at {env.now:.2f}")
 
 
     if case in process.active_cases:
@@ -399,6 +475,13 @@ def execute_case(env, case, process):
         process.done_cases.add(process.case_id)
         process.flag = False 
     
+
+"""
+Get the cureent state of the process and a specific case
+- available ressouces
+- events which already happened in the case
+- current event of the case
+"""
 def get_current_state(process, case):
     process_state = []
 
@@ -447,6 +530,9 @@ def get_current_state(process, case):
 
     return process_state, cur_case, event
 
+"""
+Defines how often new orders (cases) come in and starts executing them
+"""
 def run_process(env, process):
     # process = Process(env, num_ot, num_m, num_sh_a, num_sh_b, num_sh_c, num_m_a, num_m_b, num_ds_a, num_ds_b, num_ds_c)
     
@@ -457,63 +543,11 @@ def run_process(env, process):
     # the new incoming orders
     while case < 1000:
         waittime = random.randint(10,15)
+        if case % 20 == 0:
+            waittime = 100
         yield env.timeout(waittime)  # Wait a bit before generating a new case
 
         case += 1
         # process.active_cases.append(case)
         env.process(execute_case(env, case, process))
 
-def main():
-    # Setup
-    # we can use a random seed if we want to generate the same results every time (maybe useful later for the training)
-    # random.seed(42)
-    # initialize the number of resources
-
-    process = [] 
-    num_s = 1
-    process.append(num_s)
-    num_ot = 5
-    process.append(num_ot)
-    num_sh_a = 3
-    process.append(num_sh_a)
-    num_sh_b = 3
-    process.append(num_sh_b)
-    num_sh_c = 3
-    process.append(num_sh_c)
-    num_m_a = 3
-    process.append(num_m_a)
-    num_m_b = 2
-    process.append(num_m_b)
-    num_p_a = 4
-    process.append(num_p_a)
-    num_p_b = 5
-    process.append(num_p_b)
-    num_p_c = 4
-    process.append(num_p_c)
-    num_ds_a = 8
-    process.append(num_ds_a)
-    num_ds_b = 8
-    process.append(num_ds_b)
-    num_ds_c = 8
-    process.append(num_ds_c)
-
-    case = []
-    for i in range(15):
-        case.append(1)
-        
-    space = [process, case]
-    activities = 16
- 
-    business_env = environment.BusinessProcessEnv(space, activities)
-    print(business_env.observation_space.shape)
-    print(business_env.observation_space.sample())
-
-    state, _ = business_env.reset()
-    print(state)
-    print(business_env.current_state)
-    print(state['event'])
-    print(business_env.flatten_observation(state))
-    agent.q_learning(space, activities)
-
-if __name__ == "__main__":
-    main()
diff --git a/simpy_tutorial/eventlog.py b/simpy_tutorial/eventlog.py
index 8a31eaf..e7f2df2 100644
--- a/simpy_tutorial/eventlog.py
+++ b/simpy_tutorial/eventlog.py
@@ -24,15 +24,10 @@ def add_end_event(process, event_id, end_timestamp):
 
 # add functions for adding events with their attributes to the log
 
-<<<<<<<< HEAD:simpy_tutorial/eventlog.py
-def export_to_csv(env, file_path):
-    event_log_df = pd.DataFrame.from_dict(env.bigeventlog)
-    event_log_df.to_csv(file_path)
-========
+
 def export_to_csv(process, file_path):
     event_log_df = pd.DataFrame.from_dict(process.event_log)
     event_log_df.to_csv(file_path, index=False)
->>>>>>>> 575b59827b5f928da4165070a4a1d51a85eed774:Simpy_Tutorial/eventlog.py
 
 def export_to_xes(process, file_path):
     # Use appropriate code to export to XES format
-- 
GitLab