| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  | __filename__ = "fitnessFunctions.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2022-02-03 13:58:20 +00:00
										 |  |  | __version__ = "1.3.0" | 
					
						
							| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@libreserver.org" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							|  |  |  | __module_group__ = "Core" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | from webapp_utils import html_header_with_external_style | 
					
						
							|  |  |  | from webapp_utils import html_footer | 
					
						
							| 
									
										
										
										
											2021-12-26 14:08:58 +00:00
										 |  |  | from utils import get_config_param | 
					
						
							| 
									
										
										
										
											2021-12-26 14:47:21 +00:00
										 |  |  | from utils import save_json | 
					
						
							| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  | def fitness_performance(startTime, fitness_state: {}, | 
					
						
							|  |  |  |                         fitness_id: str, watch_point: str, | 
					
						
							|  |  |  |                         debug: bool) -> None: | 
					
						
							| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  |     """Log a performance watchpoint
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |     if 'performance' not in fitness_state: | 
					
						
							|  |  |  |         fitness_state['performance'] = {} | 
					
						
							|  |  |  |     if fitness_id not in fitness_state['performance']: | 
					
						
							|  |  |  |         fitness_state['performance'][fitness_id] = {} | 
					
						
							|  |  |  |     if watch_point not in fitness_state['performance'][fitness_id]: | 
					
						
							|  |  |  |         fitness_state['performance'][fitness_id][watch_point] = { | 
					
						
							| 
									
										
										
										
											2021-10-19 18:12:48 +00:00
										 |  |  |             "total": float(0), | 
					
						
							|  |  |  |             "ctr": int(0) | 
					
						
							| 
									
										
										
										
											2021-10-19 18:08:18 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     time_diff = float(time.time() - startTime) | 
					
						
							| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |     fitness_state['performance'][fitness_id][watch_point]['total'] += time_diff | 
					
						
							|  |  |  |     fitness_state['performance'][fitness_id][watch_point]['ctr'] += 1 | 
					
						
							|  |  |  |     if fitness_state['performance'][fitness_id][watch_point]['ctr'] >= 1024: | 
					
						
							|  |  |  |         fitness_state['performance'][fitness_id][watch_point]['total'] /= 2 | 
					
						
							|  |  |  |         fitness_state['performance'][fitness_id][watch_point]['ctr'] = \ | 
					
						
							|  |  |  |             int(fitness_state['performance'][fitness_id][watch_point]['ctr'] / | 
					
						
							|  |  |  |                 2) | 
					
						
							| 
									
										
										
										
											2021-10-19 13:41:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if debug: | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |         ctr = fitness_state['performance'][fitness_id][watch_point]['ctr'] | 
					
						
							|  |  |  |         total = fitness_state['performance'][fitness_id][watch_point]['total'] | 
					
						
							|  |  |  |         print('FITNESS: performance/' + fitness_id + '/' + | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |               watch_point + '/' + str(total * 1000 / ctr)) | 
					
						
							| 
									
										
										
										
											2021-10-19 17:35:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  | def sorted_watch_points(fitness: {}, fitness_id: str) -> []: | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |     """Returns a sorted list of watchpoints
 | 
					
						
							| 
									
										
										
										
											2021-10-19 20:58:59 +00:00
										 |  |  |     times are in mS | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-10-19 20:46:29 +00:00
										 |  |  |     if not fitness.get('performance'): | 
					
						
							|  |  |  |         return [] | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |     if not fitness['performance'].get(fitness_id): | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |         return [] | 
					
						
							|  |  |  |     result = [] | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |     for watch_point, item in fitness['performance'][fitness_id].items(): | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |         if not item.get('total'): | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2022-04-23 19:47:40 +00:00
										 |  |  |         average_time = int(item['total'] * 1000 / item['ctr']) | 
					
						
							|  |  |  |         average_time_str = str(average_time).zfill(16) | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |         result.append(average_time_str + ' ' + watch_point) | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |     result.sort(reverse=True) | 
					
						
							|  |  |  |     return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  | def html_watch_points_graph(base_dir: str, fitness: {}, fitness_id: str, | 
					
						
							|  |  |  |                             max_entries: int) -> str: | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |     """Returns the html for a graph of watchpoints
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |     watch_points_list = sorted_watch_points(fitness, fitness_id) | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     css_filename = base_dir + '/epicyon-graph.css' | 
					
						
							| 
									
										
										
										
											2021-12-25 16:17:53 +00:00
										 |  |  |     if os.path.isfile(base_dir + '/graph.css'): | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |         css_filename = base_dir + '/graph.css' | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     instance_title = \ | 
					
						
							| 
									
										
										
										
											2021-12-26 14:08:58 +00:00
										 |  |  |         get_config_param(base_dir, 'instanceTitle') | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     html_str = \ | 
					
						
							|  |  |  |         html_header_with_external_style(css_filename, instance_title, None) | 
					
						
							|  |  |  |     html_str += \ | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |         '<table class="graph">\n' + \ | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |         '<caption>Watchpoints for ' + fitness_id + '</caption>\n' + \ | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |         '<thead>\n' + \ | 
					
						
							|  |  |  |         '  <tr>\n' + \ | 
					
						
							|  |  |  |         '    <th scope="col">Item</th>\n' + \ | 
					
						
							|  |  |  |         '    <th scope="col">Percent</th>\n' + \ | 
					
						
							|  |  |  |         '  </tr>\n' + \ | 
					
						
							|  |  |  |         '</thead><tbody>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # get the maximum time | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     max_average_time = float(1) | 
					
						
							|  |  |  |     if len(watch_points_list) > 0: | 
					
						
							|  |  |  |         max_average_time = float(watch_points_list[0].split(' ')[0]) | 
					
						
							|  |  |  |     for watch_point in watch_points_list: | 
					
						
							|  |  |  |         average_time = float(watch_point.split(' ')[0]) | 
					
						
							|  |  |  |         if average_time > max_average_time: | 
					
						
							|  |  |  |             max_average_time = average_time | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ctr = 0 | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     for watch_point in watch_points_list: | 
					
						
							|  |  |  |         name = watch_point.split(' ', 1)[1] | 
					
						
							|  |  |  |         average_time = float(watch_point.split(' ')[0]) | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |         height_percent = int(average_time * 100 / max_average_time) | 
					
						
							|  |  |  |         time_ms = int(average_time) | 
					
						
							|  |  |  |         if height_percent == 0: | 
					
						
							| 
									
										
										
										
											2021-10-19 21:12:06 +00:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |         html_str += \ | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |             '<tr style="height:' + str(height_percent) + '%">\n' + \ | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |             '  <th scope="row">' + name + '</th>\n' + \ | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |             '  <td><span>' + str(time_ms) + '</span></td>\n' + \ | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |             '</tr>\n' | 
					
						
							|  |  |  |         ctr += 1 | 
					
						
							| 
									
										
										
										
											2022-01-02 13:18:11 +00:00
										 |  |  |         if ctr >= max_entries: | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  |             break | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-31 21:18:12 +00:00
										 |  |  |     html_str += '</tbody></table>\n' + html_footer() | 
					
						
							|  |  |  |     return html_str | 
					
						
							| 
									
										
										
										
											2021-10-19 20:08:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def fitness_thread(base_dir: str, fitness: {}): | 
					
						
							| 
									
										
										
										
											2021-10-19 17:35:52 +00:00
										 |  |  |     """Thread used to save fitness function scores
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-25 21:45:06 +00:00
										 |  |  |     fitness_filename = base_dir + '/accounts/fitness.json' | 
					
						
							| 
									
										
										
										
											2021-10-19 17:35:52 +00:00
										 |  |  |     while True: | 
					
						
							|  |  |  |         # every 10 mins | 
					
						
							|  |  |  |         time.sleep(60 * 10) | 
					
						
							| 
									
										
										
										
											2021-12-26 14:47:21 +00:00
										 |  |  |         save_json(fitness, fitness_filename) |