medicafe 0.240419.2__py3-none-any.whl → 0.240517.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of medicafe might be problematic. Click here for more details.

MediBot/MediBot.bat CHANGED
@@ -8,63 +8,191 @@ set "config_file=F:\Medibot\json\config.json"
8
8
  set "python_script=C:\Python34\Lib\site-packages\MediBot\update_json.py"
9
9
  set "python_script2=C:\Python34\Lib\site-packages\MediBot\Medibot.py"
10
10
  set "medicafe_package=medicafe"
11
- set "upgrade_medicafe=F:\Medibot\upgrade_medicafe.py"
12
-
13
- :: Set PYTHONWARNINGS environment variable to ignore deprecation warnings
11
+ set "upgrade_medicafe=F:\Medibot\update_medicafe.py"
12
+ set "temp_file=F:\Medibot\last_update_timestamp.txt"
13
+ set "firefox_path=C:\Program Files\Mozilla Firefox\firefox.exe"
14
+ set "package_version="
14
15
  set PYTHONWARNINGS=ignore
15
16
 
16
- :: Upgrade Medicafe package
17
- py "%upgrade_medicafe%"
17
+ :: Check if Python is installed and the path is correctly set
18
+ python --version >nul 2>&1
19
+ if %errorlevel% neq 0 (
20
+ echo Python is not installed or not added to PATH.
21
+ exit /b
22
+ )
18
23
 
19
- :: Check for the latest CSV file in source folder
20
- set "latest_csv="
21
- for /f "delims=" %%a in ('dir /b /a-d /o-d "%source_folder%\*.csv" 2^>nul') do (
22
- set "latest_csv=%%a"
23
- goto :found_latest_csv
24
+ :: Check if the MediCafe package is installed and retrieve its version
25
+ echo Checking for installed MediCafe package version...
26
+ python -c "import pkg_resources; print('MediCafe=='+pkg_resources.get_distribution('medicafe').version)" > temp.txt 2>nul
27
+ set /p package_version=<temp.txt
28
+ del temp.txt
29
+
30
+ if not defined package_version (
31
+ echo MediCafe package version not detected or MediCafe not installed. Consider manual re-install.
32
+ exit /b
24
33
  )
25
34
 
26
- :: If no CSV found in source folder, check target folder
27
- echo No CSV file found in "%source_folder%".
28
- for /f "delims=" %%a in ('dir /b /a-d /o-d "%target_folder%\*.csv" 2^>nul') do (
29
- set "latest_csv=%%a"
30
- echo Using latest processed file in CSV folder: !latest_csv!
31
- goto :found_latest_csv
35
+ :: Extract version number and display it
36
+ for /f "tokens=2 delims==" %%a in ("%package_version%") do (
37
+ set "medicafe_version=%%a"
38
+ )
39
+
40
+ if not defined medicafe_version (
41
+ echo Failed to detect MediCafe version.
42
+ ) else (
43
+ echo Detected MediCafe version: %medicafe_version%
44
+ )
45
+
46
+ :: Check for internet connectivity
47
+ ping -n 1 google.com > nul 2>&1
48
+ if %ERRORLEVEL% neq 0 (
49
+ set "internet_available=0"
50
+ echo No internet connection detected.
51
+ ) else (
52
+ set "internet_available=1"
53
+ echo Internet connection detected.
54
+ )
55
+
56
+ :: Common pre-menu setup
57
+ echo Setting up the environment...
58
+ if not exist "%config_file%" (
59
+ echo Configuration file missing.
60
+ goto end_script
32
61
  )
33
62
 
34
- :found_latest_csv
63
+ :: Check if the file exists and attempt to move it
64
+ :: Implementing a check with copy as a fallback if move fails
65
+ echo Checking for the upgrade script...
66
+ if exist "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" (
67
+ echo Found upgrade_medicafe.py. Attempting to move...
68
+ move "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" "F:\Medibot\upgrade_medicafe.py" >nul 2>&1
69
+ if %errorlevel% neq 0 (
70
+ echo Move failed. Attempting copy and delete as fallback...
71
+ copy "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" "F:\Medibot\upgrade_medicafe.py" >nul 2>&1
72
+ if %errorlevel% neq 0 (
73
+ echo Copy failed. Error Level: %errorlevel%
74
+ ) else (
75
+ del "C:\Python34\Lib\site-packages\MediBot\upgrade_medicafe.py" >nul 2>&1
76
+ if %errorlevel% neq 0 (
77
+ echo Delete failed. Manual cleanup may be required.
78
+ ) else (
79
+ echo File copied and original deleted successfully.
80
+ )
81
+ )
82
+ ) else (
83
+ echo File moved successfully.
84
+ )
85
+ ) else (
86
+ echo upgrade_medicafe.py not detected. Check path and filename.
87
+ )
35
88
 
36
- :: If no CSV found in either folder, end the script
37
- if not defined latest_csv (
38
- echo No CSV file found in either folder.
39
- goto :end_script
89
+ :: Main menu
90
+ :main_menu
91
+ cls
92
+ echo version: %medicafe_version%
93
+ echo --------------------------------------------------------------
94
+ echo .//* Welcome to MediCafe *\\.
95
+ echo --------------------------------------------------------------
96
+ echo.
97
+ echo Please select an option:
98
+ if "!internet_available!"=="1" (
99
+ echo 1. Check for MediCafe Package Updates
100
+ echo 2. Download Email de Carol
101
+ echo 3. MediLink Claims
40
102
  )
103
+ echo 4. Run MediBot
104
+ echo 5. Exit
105
+ echo.
106
+ set /p choice=Enter your choice:
41
107
 
42
- :: Display the name of the found CSV file to the user
43
- echo Found CSV file: !latest_csv!
108
+ if "!choice!"=="5" goto end_script
109
+ if "!choice!"=="4" goto medibot_flow
110
+ if "!choice!"=="3" goto medilink_flow
111
+ if "!choice!"=="2" goto download_emails
112
+ if "!choice!"=="1" goto check_updates
44
113
 
45
- :: Get the current date in MMDDYY format
46
- for /f "tokens=1-3 delims=/" %%a in ("%date%") do (
47
- set "month=%%a"
48
- set "day=%%b"
49
- set "year=%%c"
114
+ :: Medicafe Update
115
+ :check_updates
116
+ if "!internet_available!"=="0" (
117
+ echo No internet connection available.
118
+ goto main_menu
119
+ )
120
+ echo Checking for MediCafe package updates. Please wait...
121
+ start cmd /c py "%upgrade_medicafe%" > upgrade_log.txt 2>&1 && (
122
+ echo %DATE% %TIME% Upgrade initiated. >> "%temp_file%"
123
+ echo Exiting batch to complete the upgrade.
124
+ ) || (
125
+ echo %DATE% %TIME% Update failed. Check logs. >> upgrade_log.txt
50
126
  )
51
- set "datestamp=!month!!day!!year:~2,2!"
127
+ exit /b
52
128
 
53
- :: Move and rename the CSV file only if found in source folder
54
- if exist "%source_folder%\!latest_csv!" (
55
- move "%source_folder%\!latest_csv!" "%target_folder%\SX_CSV_!datestamp!.csv"
56
- set "new_csv_path=%target_folder%\SX_CSV_!datestamp!.csv"
129
+ :: Download Carol's Emails
130
+ :download_emails
131
+ if "!internet_available!"=="0" (
132
+ echo No internet connection available.
133
+ goto main_menu
134
+ )
135
+ echo Downloading emails...
136
+ py "../MediLink/MediLink_Gmail.py" "%firefox_path%"
137
+ if errorlevel 1 (
138
+ echo Failed to download emails.
139
+ pause
57
140
  ) else (
58
- set "new_csv_path=%target_folder%\!latest_csv!"
141
+ echo Calling CSV Processor...
142
+ call :process_csvs
59
143
  )
144
+ goto main_menu
60
145
 
146
+ :: Run MediBot Flow
147
+ :medibot_flow
148
+ call :process_csvs
149
+ cls
61
150
  echo Please wait...
151
+ py "%python_script2%" "%config_file%"
152
+ if errorlevel 1 echo Failed to run MediBot.
153
+ pause
154
+ goto main_menu
62
155
 
63
- :: Call Python script to update the JSON file
64
- py "%python_script%" "%config_file%" "!new_csv_path!"
156
+ :: Continue to MediLink
157
+ :medilink_flow
158
+ if "!internet_available!"=="0" (
159
+ echo No internet connection available.
160
+ goto main_menu
161
+ )
162
+ call :process_csvs
163
+ cls
164
+ py "C:\Python34\Lib\site-packages\MediLink\MediLink.py"
165
+ if errorlevel 1 echo MediLink failed to execute.
166
+ pause
167
+ goto main_menu
65
168
 
66
- :: Execute the second Python script
67
- py "%python_script2%" "%config_file%"
169
+ :: Process CSV Files
170
+ :process_csvs
171
+ for /f "tokens=1-5 delims=/: " %%a in ('echo %time%') do (
172
+ set "hour=%%a"
173
+ set "minute=%%b"
174
+ set "second=%%c"
175
+ )
176
+ set "timestamp=%DATE:~-4%%DATE:~3,2%%DATE:~0,2%_%hour%%minute%"
177
+ set "latest_csv="
178
+ for /f "delims=" %%a in ('dir /b /a-d /o-d "%source_folder%\*.csv" 2^>nul') do (
179
+ set "latest_csv=%%a"
180
+ echo Found New CSV Files...
181
+ goto process_found_csv
182
+ )
183
+ ::echo CSV Check Complete.
184
+ goto :eof
185
+
186
+ :process_found_csv
187
+ echo Processing CSVs...
188
+ move "%source_folder%\!latest_csv!" "%target_folder%\SX_CSV_!timestamp!.csv"
189
+ set "new_csv_path=%target_folder%\SX_CSV_!timestamp!.csv"
190
+ py "%python_script%" "%config_file%" "!new_csv_path!"
191
+ echo CSV Processor Complete...
192
+ goto :eof
68
193
 
194
+ :: Exit Script
69
195
  :end_script
196
+ echo Exiting MediCafe.
70
197
  pause
198
+ exit /b
MediBot/MediBot.py CHANGED
@@ -4,10 +4,10 @@ import tempfile
4
4
  import traceback
5
5
  import re #for addresses
6
6
  from collections import OrderedDict
7
- import MediBot_UI
8
7
  import MediBot_dataformat_library
9
8
  import MediBot_Preprocessor
10
- from MediBot_Preprocessor import initialize, AHK_EXECUTABLE, CSV_FILE_PATH, field_mapping
9
+ from MediBot_Preprocessor_lib import initialize, AHK_EXECUTABLE, CSV_FILE_PATH, field_mapping, load_csv_data
10
+ from MediBot_UI import app_control, manage_script_pause, user_interaction
11
11
 
12
12
  # Add parent directory of the project to the Python path
13
13
  import sys
@@ -16,10 +16,17 @@ sys.path.append(project_dir)
16
16
 
17
17
  from MediLink import MediLink_ConfigLoader
18
18
 
19
+ try:
20
+ from MediBot_Crosswalk_Library import crosswalk_update
21
+ except ImportError:
22
+ from MediBot import MediBot_Crosswalk_Library
23
+ crosswalk_update = MediBot_Crosswalk_Library.crosswalk_update
24
+
19
25
  """
20
26
  # Development Task List for MediBot
21
27
 
22
28
  Error Handling Improvements
29
+ - [ ] Its really difficult to get out of the main menu if you go open MediBot by accident
23
30
  - [ ] Develop a centralized error handling and logging mechanism for improved troubleshooting.
24
31
  - [ ] Implement validation checks during patient data entry to prevent submission of incomplete or incorrect records.
25
32
 
@@ -102,6 +109,8 @@ def process_field(medisoft_field, csv_row, parsed_address_components, reverse_ma
102
109
  elif medisoft_field in fixed_values:
103
110
  value = fixed_values[medisoft_field][0] # Use the fixed value
104
111
  elif medisoft_field in reverse_mapping:
112
+ if medisoft_field == "Ins1 Insurance ID" or reverse_mapping[medisoft_field] == "Primary Insurance Company":
113
+ MediLink_ConfigLoader.log("Detected {} or {}: {}".format(medisoft_field, reverse_mapping[medisoft_field], value))
105
114
  csv_header = reverse_mapping[medisoft_field]
106
115
  value = csv_row.get(csv_header, '')
107
116
 
@@ -114,10 +123,11 @@ def process_field(medisoft_field, csv_row, parsed_address_components, reverse_ma
114
123
  return handle_error(e, medisoft_field, last_processed_entry, csv_data)
115
124
 
116
125
  def handle_error(error, medisoft_field, last_processed_entry, csv_data):
126
+ MediLink_ConfigLoader.log("Error in process_field: ", e)
117
127
  print("An error occurred while processing {0}: {1}".format(medisoft_field, error))
118
128
  # Assuming the interaction mode is 'error' in this case
119
129
  interaction_mode = 'error'
120
- response = MediBot_UI.user_interaction(csv_data, interaction_mode, error, reverse_mapping)
130
+ response = user_interaction(csv_data, interaction_mode, error, reverse_mapping)
121
131
  return response, last_processed_entry
122
132
 
123
133
  # iterating through each field defined in the field_mapping.
@@ -125,7 +135,7 @@ def iterate_fields(csv_row, field_mapping, parsed_address_components, reverse_ma
125
135
  global last_processed_entry
126
136
  # Check for user action at the start of each field processing
127
137
  for medisoft_field in field_mapping.keys():
128
- action = MediBot_UI.manage_script_pause(csv_data,'',reverse_mapping) # per-field pause availability. Necessary to provide frequent opportunities for the user to pause the script.
138
+ action = manage_script_pause(csv_data,'',reverse_mapping) # per-field pause availability. Necessary to provide frequent opportunities for the user to pause the script.
129
139
  if action != 0: # If action is either 'Retry' (-1) or 'Skip' (1)
130
140
  return action # Break out and pass the action up
131
141
 
@@ -135,8 +145,8 @@ def iterate_fields(csv_row, field_mapping, parsed_address_components, reverse_ma
135
145
  return 0 # Default action to continue
136
146
 
137
147
  def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
138
- global last_processed_entry, parsed_address_components, script_paused
139
- script_paused = False
148
+ global last_processed_entry, parsed_address_components
149
+ # last_processed_entry, parsed_address_components = None, {} // BUG should this just be this line rather than the global line above?
140
150
  error_message = '' # Initialize error_message once
141
151
  current_row_index = 0
142
152
 
@@ -144,10 +154,10 @@ def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
144
154
  row = csv_data[current_row_index]
145
155
 
146
156
  # Handle script pause at the start of each row (patient record).
147
- MediBot_UI.manage_script_pause(csv_data, error_message, reverse_mapping)
157
+ manage_script_pause(csv_data, error_message, reverse_mapping)
148
158
  error_message = '' # Clear error message for the next iteration
149
159
 
150
- if script_paused:
160
+ if app_control.get_pause_status():
151
161
  continue # Skip processing this row if the script is paused
152
162
 
153
163
  # I feel like this is overwriting what would have already been idenfitied in the mapping.
@@ -157,12 +167,13 @@ def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
157
167
 
158
168
  # Process each field in the row
159
169
  action = iterate_fields(row, field_mapping, parsed_address_components, reverse_mapping, csv_data, fixed_values)
160
- # TODO add a feature here where if you accidentally started overwriting a patient that you could go back 2 patients.
170
+ # TODO (Low) add a feature here where if you accidentally started overwriting a patient that you could go back 2 patients.
161
171
  # Need to tell the user which patient we're talking about because it won't be obvious anymore.
162
172
  if action == -1: # Retry
163
173
  continue # Remain on the current row.
164
174
  elif action == 1: # Skip
165
175
  if current_row_index == len(csv_data) - 1: # If it's the last row
176
+ MediLink_ConfigLoader.log("Reached the end of the patient list.")
166
177
  print("Reached the end of the patient list. Looping back to the beginning.")
167
178
  current_row_index = 0 # Reset to the first row
168
179
  else:
@@ -173,9 +184,8 @@ def data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values):
173
184
  continue
174
185
 
175
186
  # Code to handle the end of a patient record
176
- # print("\nA patient record was completed.")
177
- script_paused = True
178
- # Handle script pause at the end of each row (patient record).
187
+ # TODO One day this can just not pause...
188
+ app_control.set_pause_status(True) # Pause at the end of processing each patient record
179
189
  current_row_index += 1 # Move to the next row by default
180
190
 
181
191
  def open_medisoft(shortcut_path):
@@ -198,14 +208,24 @@ def cleanup():
198
208
  pass
199
209
 
200
210
  class ExecutionState:
201
- def __init__(self) -> None:
202
-
203
- #print("Loading Configuration...")
204
- config, _ = MediLink_ConfigLoader.load_configuration(config_path, crosswalk_path)
205
-
206
- self.verify_config_type(config)
207
- #print("Initializing Constants...")
208
- initialize(config)
211
+ def __init__(self, config_path, crosswalk_path) -> None:
212
+ try:
213
+ config, crosswalk = MediLink_ConfigLoader.load_configuration(config_path, crosswalk_path)
214
+ self.verify_config_type(config)
215
+ self.crosswalk = crosswalk
216
+ self.config = config
217
+ MediLink_ConfigLoader.log("Config loaded successfully...")
218
+
219
+ crosswalk_update(config, crosswalk)
220
+ MediLink_ConfigLoader.log("Crosswalk update complete...")
221
+
222
+ initialize(config)
223
+ MediLink_ConfigLoader.log("Constants initialized...")
224
+
225
+ except Exception as e:
226
+ print("Failed to load or update configuration: {}".format(e))
227
+ raise # Re-throwing the exception or using a more sophisticated error handling mechanism might be needed
228
+ # Handle the exception somehow (e.g., retry, halt, log)??
209
229
 
210
230
  def verify_config_type(self, config):
211
231
  if not isinstance(config, (dict, OrderedDict)):
@@ -215,7 +235,8 @@ class ExecutionState:
215
235
  if __name__ == "__main__":
216
236
  e_state = None
217
237
  try:
218
- # Default paths
238
+ print("Please wait...")
239
+ # Default paths
219
240
  default_config_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'config.json')
220
241
  default_crosswalk_path = os.path.join(os.path.dirname(__file__), '..', 'json', 'crosswalk.json')
221
242
 
@@ -229,36 +250,50 @@ if __name__ == "__main__":
229
250
  config_path = default_config_path
230
251
  crosswalk_path = default_crosswalk_path
231
252
 
232
- e_state = ExecutionState()
253
+ e_state = ExecutionState(config_path, crosswalk_path)
233
254
 
234
- #print("Loading CSV Data...")
235
- csv_data = MediBot_Preprocessor.load_csv_data(CSV_FILE_PATH)
255
+ print("Loading CSV Data...")
256
+ MediLink_ConfigLoader.log("Loading CSV Data...", level="INFO")
257
+ csv_data = load_csv_data(CSV_FILE_PATH)
236
258
 
237
- #print("Pre-processing CSV Data...")
238
- MediBot_Preprocessor.preprocess_csv_data(csv_data) # Pre-process CSV data to add combined fields
239
- headers = csv_data[0].keys() # Including Patient Name and Patient Address
259
+ # Pre-process CSV data to add combined fields & crosswalk values.
260
+ print("Pre-Processing CSV...")
261
+ MediLink_ConfigLoader.log("Pre-processing CSV Data...", level="INFO")
262
+ MediBot_Preprocessor.preprocess_csv_data(csv_data, e_state.crosswalk)
263
+ headers = csv_data[0].keys() # Make sure all the headers are in place
240
264
 
241
- #print("Performing Intake Scan...")
265
+ print("Performing Intake Scan...")
266
+ MediLink_ConfigLoader.log("Performing Intake Scan...", level="INFO")
242
267
  # identified_fields is an OrderedDict
243
268
  identified_fields = MediBot_Preprocessor.intake_scan(headers, field_mapping)
244
269
 
245
270
  # Reverse the identified_fields mapping for lookup
246
271
  reverse_mapping = {v: k for k, v in identified_fields.items()}
272
+ # MediLink_ConfigLoader.log("Reverse Mapping: {}".format(reverse_mapping))
247
273
 
248
274
  # CSV Patient Triage
249
275
  interaction_mode = 'triage' # Start in triage mode
250
276
  error_message = "" # This will be filled if an error has occurred
251
277
  #print("Debug - Identified fields mapping (main): {}".format(identified_fields)) # Debug Line
252
278
 
253
- proceed, selected_patient_ids, selected_indices, fixed_values = MediBot_UI.user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
279
+ print("Load Complete...")
280
+ _ = os.system('cls')
281
+
282
+ proceed, selected_patient_ids, selected_indices, fixed_values = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
254
283
 
255
284
  if proceed:
256
285
  # Filter csv_data for selected patients from Triage mode.
257
286
  csv_data = [row for index, row in enumerate(csv_data) if index in selected_indices]
258
- existing_patients, patients_to_process = MediBot_Preprocessor.check_existing_patients(selected_patient_ids, MediBot_UI.MAPAT_MED_PATH)
287
+
288
+ # Check if MAPAT_MED_PATH is missing or blank
289
+ if not app_control.get_mapat_med_path() or not os.path.exists(app_control.get_mapat_med_path()):
290
+ print("Warning: MAPAT.MED PATH is missing or invalid. Please check the path configuration.")
291
+
292
+ # Perform the existing patients check
293
+ existing_patients, patients_to_process = MediBot_Preprocessor.check_existing_patients(selected_patient_ids, app_control.get_mapat_med_path())
259
294
 
260
295
  if existing_patients:
261
- print("\nNOTE: The following patient(s) already EXIST in the system and \nwill be excluded from processing:")
296
+ print("\nNOTE: The following patient(s) already EXIST in the system and \n will be excluded from processing:")
262
297
  for patient_id, patient_name in existing_patients:
263
298
  print("(ID: {0}) {1}".format(patient_id, patient_name))
264
299
  # Update csv_data to exclude existing patients
@@ -290,27 +325,22 @@ if __name__ == "__main__":
290
325
  print(" Press 'F12' to begin data entry.")
291
326
  print(" Press 'F11' at any time to Pause.")
292
327
  input("\n*** Press [Enter] when ready to begin! ***\n")
293
- open_medisoft(MediBot_UI.MEDISOFT_SHORTCUT)
294
- script_paused = True
295
- _ = MediBot_UI.manage_script_pause(csv_data, error_message, reverse_mapping)
328
+ MediLink_ConfigLoader.log("Opening Medisoft...")
329
+ open_medisoft(app_control.get_medisoft_shortcut())
330
+ app_control.set_pause_status(True)
331
+ _ = manage_script_pause(csv_data, error_message, reverse_mapping)
296
332
  data_entry_loop(csv_data, field_mapping, reverse_mapping, fixed_values)
297
333
  cleanup()
298
334
  else:
299
- print("Data entry canceled by user.")
335
+ print("Data entry canceled by user. Exiting MediBot.")
300
336
  except Exception as e:
301
337
  if e_state:
302
338
  interaction_mode = 'error' # Switch to error mode
303
339
  error_message = str(e) # Capture the error message
304
- print("An error occurred: {0}".format(e))
340
+ print("An error occurred while running MediBot: {0}".format(e))
305
341
  # Handle the error by calling user interaction with the error information
306
342
  # Ensure that identified_fields is defined before using it in user interaction
307
343
  if 'identified_fields' in locals():
308
- _ = MediBot_UI.user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
344
+ _ = user_interaction(csv_data, interaction_mode, error_message, reverse_mapping)
309
345
  else:
310
- print("Please ensure CSV headers match expected field names in config file, then re-run Medibot.")
311
-
312
- # Performance: Process flow (25px - 13 min)
313
- # 2:00 Internet connect & Email
314
- # 6:00 6 px medicare
315
- # 1:00 menu handling for privado
316
- # 4:00 5 px privado
346
+ print("Please ensure CSV headers match expected field names in config file, then re-run Medibot.")