diff --git a/backend/__pycache__/agent.cpython-311.pyc b/backend/__pycache__/agent.cpython-311.pyc
index 87f701a04a31d900d91fd18b6bc837516be90163..51f4f916a98f67a7704f896ffc5c1d4ef0b81626 100644
Binary files a/backend/__pycache__/agent.cpython-311.pyc and b/backend/__pycache__/agent.cpython-311.pyc differ
diff --git a/backend/__pycache__/environment.cpython-311.pyc b/backend/__pycache__/environment.cpython-311.pyc
index 51daa198751b4836531ffe9cc564ed462aed29b8..4b3cb87be7554aa6bcb531d2a1fd6d299d80c0a5 100644
Binary files a/backend/__pycache__/environment.cpython-311.pyc and b/backend/__pycache__/environment.cpython-311.pyc differ
diff --git a/backend/__pycache__/eventlog.cpython-311.pyc b/backend/__pycache__/eventlog.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5c000c77be103887b9d6c9671a5555bb455cc198
Binary files /dev/null and b/backend/__pycache__/eventlog.cpython-311.pyc differ
diff --git a/backend/__pycache__/simplesimmodel.cpython-311.pyc b/backend/__pycache__/simplesimmodel.cpython-311.pyc
index 7f8f062a2173a3f3440055bc14475b66274869c3..def6d5e7c495421b42862ead8fe246f98d50bf31 100644
Binary files a/backend/__pycache__/simplesimmodel.cpython-311.pyc and b/backend/__pycache__/simplesimmodel.cpython-311.pyc differ
diff --git a/backend/agent.py b/backend/agent.py
index 111df067c5097be66021c5d64734dcc9f66f6117..e75453c055229586c9597b39b5e9cc52d4327e28 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 b96b6425d7216e12269ab8b8a50577c25a72ae05..1ee254b01386f500a7728900d07f3ff8855ee4af 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 36848b5a3dd9d5e01f478cce5539b5d7175c10e8..7a3625ef7aca88f1debea601923e4acfb86ad3a5 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 0000000000000000000000000000000000000000..e8c6f1e805443c6f965ca5c3909457684b3d5063
--- /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 0000000000000000000000000000000000000000..fdee31d6eb3e8d2bf65037450ec61528c9b21529
--- /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 fe23eb4b077fbfcf15c62daa4a7e844ac1e875e0..18cb95273cd687ac419a8d7c8cf3fce44011e738 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 8a31eaf99ca99fbcee7db494ea8598148373147e..e7f2df2928a2f0eed752a42715a78b00eac001b1 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